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:
parent
42de5b9a10
commit
1b9617c85c
|
@ -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
|
|
@ -8,14 +8,19 @@ Copyright © 2010-2012 Michael Plante <michael.plante@gmail.com>
|
|||
Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com>
|
||||
Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org>
|
||||
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:
|
||||
Adrian Bunk
|
||||
Akshay Jaggi
|
||||
Alan Ott
|
||||
Alan Stern
|
||||
Alex Vatchenko
|
||||
Andrew Fernandes
|
||||
Andy Chunyu
|
||||
Andy McFadden
|
||||
Angus Gratton
|
||||
Anil Nair
|
||||
Anthony Clay
|
||||
Antonio Ospite
|
||||
Artem Egorkine
|
||||
|
@ -23,12 +28,17 @@ Aurelien Jarno
|
|||
Bastien Nocera
|
||||
Bei Zhang
|
||||
Benjamin Dobell
|
||||
Brent Rector
|
||||
Carl Karsten
|
||||
Christophe Zeitouny
|
||||
Colin Walters
|
||||
Dave Camarillo
|
||||
David Engraf
|
||||
David Moore
|
||||
Davidlohr Bueso
|
||||
Dmitry Fleytman
|
||||
Doug Johnston
|
||||
Evan Hunter
|
||||
Federico Manzan
|
||||
Felipe Balbi
|
||||
Florian Albrechtskirchinger
|
||||
|
@ -41,23 +51,34 @@ Hans Ulrich Niedermann
|
|||
Hector Martin
|
||||
Hoi-Ho Chan
|
||||
Ilya Konstantinov
|
||||
Jakub Klama
|
||||
James Hanko
|
||||
Jeffrey Nichols
|
||||
Johann Richard
|
||||
John Sheu
|
||||
Jonathon Jongsma
|
||||
Joost Muller
|
||||
Josh Gao
|
||||
Joshua Blake
|
||||
Justin Bischoff
|
||||
KIMURA Masaru
|
||||
Karsten Koenig
|
||||
Konrad Rzepecki
|
||||
Kuangye Guo
|
||||
Lars Kanis
|
||||
Lars Wirzenius
|
||||
Lei Chen
|
||||
Luca Longinotti
|
||||
Marcus Meissner
|
||||
Markus Heidelberg
|
||||
Martin Ettl
|
||||
Martin Koegler
|
||||
Matthew Stapleton
|
||||
Matthias Bolte
|
||||
Michel Zou
|
||||
Mike Frysinger
|
||||
Mikhail Gusarov
|
||||
Morgan Leborgne
|
||||
Moritz Fischer
|
||||
Ларионов Даниил
|
||||
Nicholas Corgan
|
||||
|
@ -66,10 +87,17 @@ Orin Eman
|
|||
Paul Fertser
|
||||
Pekka Nikander
|
||||
Rob Walker
|
||||
Romain Vimont
|
||||
Roman Kalashnikov
|
||||
Sameeh Jubran
|
||||
Sean McBride
|
||||
Sebastian Pipping
|
||||
Sergey Serb
|
||||
Simon Haggett
|
||||
Simon Newton
|
||||
Stefan Agner
|
||||
Stefan Tauner
|
||||
Steinar H. Gunderson
|
||||
Thomas Röfer
|
||||
Tim Hutt
|
||||
Tim Roberts
|
||||
|
@ -81,9 +109,11 @@ Uri Lublin
|
|||
Vasily Khoruzhick
|
||||
Vegard Storheil Eriksen
|
||||
Venkatesh Shukla
|
||||
Vianney le Clément de Saint-Marcq
|
||||
Victor Toso
|
||||
Vitali Lovich
|
||||
William Skellenger
|
||||
Xiaofan Chen
|
||||
Zoltán Kovács
|
||||
Роман Донченко
|
||||
parafin
|
||||
xantares
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
brew 'automake'
|
||||
brew 'libtool'
|
||||
brew 'autoconf'
|
||||
brew 'm4'
|
|
@ -1,6 +1,41 @@
|
|||
For detailed information about the changes below, please see the git log or
|
||||
visit: http://log.libusb.info
|
||||
|
||||
2019-04-05: v1.0.23 (in progress)
|
||||
* Add German translation (#446)
|
||||
* Add Hungarian translation (#493)
|
||||
* Android: Improved support for Android
|
||||
* configure.ac: Fix detection of clock_gettime library (#439)
|
||||
* Darwin(macOS): Switch from using ResetDevice to USBDeviceReEnumerate (#455)
|
||||
* Darwin(macOS): Remove code that changed the device class used (#428)
|
||||
* Darwin(macOS): Reduce hotplug timeout to 1ms (from 5s)
|
||||
* New API libusb_set_log_cb() to redirect global and per context log
|
||||
messages to the provided log handling function
|
||||
* New API libusb_wrap_sys_device to allow the user to specify the
|
||||
usb device to use.
|
||||
* Solaris: Break infinite recursion in backend clock_gettime
|
||||
* Solaris: Enable timerfd on sunos when available
|
||||
* Windows: Add support for isochronous transfers with WinUSB
|
||||
* Various other bug fixes and improvements
|
||||
|
||||
2018-03-24: v1.0.22:
|
||||
* New libusb_set_option() API
|
||||
* Fix transfer timeout not being cleared upon resubmission
|
||||
* Report super speed plus devices on modern Linux and macOS
|
||||
* Darwin: Improve support for macOS Sierra and High Sierra
|
||||
* Darwin: SDK fixes and improvements
|
||||
* Linux: Let initialization succeed when no devices are present
|
||||
* Linux: Mark internal file descriptors with CLOEXEC flag
|
||||
* Solaris: Add support for attach/detach kernel driver
|
||||
* Windows: Add dynamic UsbDk backend selection
|
||||
* Windows: Add isochronous transfer support via libusbK
|
||||
* Windows: Add Visual Studio 2017 support
|
||||
* Windows: Fix enumeration problems on Windows 8 and later
|
||||
* Windows: Major rework of poll() emulation
|
||||
* Windows: Numerous HID API fixes
|
||||
* Windows: Support cancelation of individual transfers (Vista and later)
|
||||
* Various other bug fixes and improvements
|
||||
|
||||
2016-10-01: v1.0.21:
|
||||
* Core: Refactor code related to transfer flags and timeout handling
|
||||
* Darwin: Ignore root hub simulation devices
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
|||
README.md
|
|
@ -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.
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 */;
|
||||
}
|
|
@ -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"
|
|
@ -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"
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
./bootstrap.sh
|
||||
if test -z "$NOCONFIGURE"; then
|
||||
exec ./configure --enable-examples-build --enable-tests-build "$@"
|
||||
fi
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
if ! test -d m4 ; then
|
||||
mkdir m4
|
||||
fi
|
||||
autoreconf -ivf || exit 1
|
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -13,10 +13,12 @@ DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c
|
|||
OPENBSD_USB_SRC = os/openbsd_usb.c
|
||||
NETBSD_USB_SRC = os/netbsd_usb.c
|
||||
SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h
|
||||
WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \
|
||||
os/windows_common.h libusb-1.0.rc libusb-1.0.def
|
||||
WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c os/windows_usbdk.h \
|
||||
os/windows_usbdk.c $(COMMON_WINDOWS_SRC)
|
||||
WINDOWS_USB_SRC = libusb-1.0.def libusb-1.0.rc \
|
||||
os/windows_common.h \
|
||||
os/windows_nt_common.h os/windows_nt_common.c \
|
||||
os/windows_nt_shared_types.h \
|
||||
os/windows_usbdk.h os/windows_usbdk.c \
|
||||
os/windows_winusb.h os/windows_winusb.c
|
||||
WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c
|
||||
HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \
|
||||
os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp
|
||||
|
@ -25,8 +27,8 @@ EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \
|
|||
$(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \
|
||||
$(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \
|
||||
$(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \
|
||||
$(WINDOWS_COMMON_SRC) $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \
|
||||
$(WINCE_USB_SRC) $(HAIKU_USB_SRC) \
|
||||
$(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
|
||||
$(HAIKU_USB_SRC) \
|
||||
os/linux_udev.c os/linux_netlink.c
|
||||
|
||||
if OS_LINUX
|
||||
|
@ -63,7 +65,7 @@ libusb_1_0_la_LIBADD = libusb_haiku.la
|
|||
endif
|
||||
|
||||
if OS_WINDOWS
|
||||
OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC)
|
||||
OS_SRC = $(WINDOWS_USB_SRC)
|
||||
|
||||
.rc.lo:
|
||||
$(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -62,7 +62,7 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
|
|||
if (host_endian) {
|
||||
memcpy(dp, sp, 2);
|
||||
} else {
|
||||
w = (sp[1] << 8) | sp[0];
|
||||
w = (uint16_t)((sp[1] << 8) | sp[0]);
|
||||
*((uint16_t *)dp) = w;
|
||||
}
|
||||
sp += 2;
|
||||
|
@ -74,8 +74,8 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
|
|||
if (host_endian) {
|
||||
memcpy(dp, sp, 4);
|
||||
} else {
|
||||
d = (sp[3] << 24) | (sp[2] << 16) |
|
||||
(sp[1] << 8) | sp[0];
|
||||
d = (uint32_t)((sp[3] << 24) | (sp[2] << 16) |
|
||||
(sp[1] << 8) | sp[0]);
|
||||
*((uint32_t *)dp) = d;
|
||||
}
|
||||
sp += 4;
|
||||
|
@ -168,13 +168,13 @@ static int parse_endpoint(struct libusb_context *ctx,
|
|||
/* Copy any unknown descriptors into a storage area for drivers */
|
||||
/* to later parse */
|
||||
len = (int)(buffer - begin);
|
||||
if (!len) {
|
||||
if (len <= 0) {
|
||||
endpoint->extra = NULL;
|
||||
endpoint->extra_length = 0;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
extra = malloc(len);
|
||||
extra = malloc((size_t)len);
|
||||
endpoint->extra = extra;
|
||||
if (!extra) {
|
||||
endpoint->extra_length = 0;
|
||||
|
@ -230,7 +230,7 @@ static int parse_interface(libusb_context *ctx,
|
|||
(struct libusb_interface_descriptor *) usb_interface->altsetting;
|
||||
altsetting = usbi_reallocf(altsetting,
|
||||
sizeof(struct libusb_interface_descriptor) *
|
||||
(usb_interface->num_altsetting + 1));
|
||||
((size_t)usb_interface->num_altsetting + 1));
|
||||
if (!altsetting) {
|
||||
r = LIBUSB_ERROR_NO_MEM;
|
||||
goto err;
|
||||
|
@ -307,8 +307,8 @@ static int parse_interface(libusb_context *ctx,
|
|||
/* Copy any unknown descriptors into a storage area for */
|
||||
/* drivers to later parse */
|
||||
len = (int)(buffer - begin);
|
||||
if (len) {
|
||||
ifp->extra = malloc(len);
|
||||
if (len > 0) {
|
||||
ifp->extra = malloc((size_t)len);
|
||||
if (!ifp->extra) {
|
||||
r = LIBUSB_ERROR_NO_MEM;
|
||||
goto err;
|
||||
|
@ -333,7 +333,7 @@ static int parse_interface(libusb_context *ctx,
|
|||
goto err;
|
||||
if (r == 0) {
|
||||
ifp->bNumEndpoints = (uint8_t)i;
|
||||
break;;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer += r;
|
||||
|
@ -453,10 +453,10 @@ static int parse_configuration(struct libusb_context *ctx,
|
|||
/* Copy any unknown descriptors into a storage area for */
|
||||
/* drivers to later parse */
|
||||
len = (int)(buffer - begin);
|
||||
if (len) {
|
||||
if (len > 0) {
|
||||
/* FIXME: We should realloc and append here */
|
||||
if (!config->extra_length) {
|
||||
config->extra = malloc(len);
|
||||
config->extra = malloc((size_t)len);
|
||||
if (!config->extra) {
|
||||
r = LIBUSB_ERROR_NO_MEM;
|
||||
goto err;
|
||||
|
@ -513,7 +513,7 @@ int usbi_device_cache_descriptor(libusb_device *dev)
|
|||
{
|
||||
int r, host_endian = 0;
|
||||
|
||||
r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
|
||||
r = usbi_backend.get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
|
||||
&host_endian);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -572,7 +572,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
|
|||
int host_endian = 0;
|
||||
int r;
|
||||
|
||||
r = usbi_backend->get_active_config_descriptor(dev, tmp,
|
||||
r = usbi_backend.get_active_config_descriptor(dev, tmp,
|
||||
LIBUSB_DT_CONFIG_SIZE, &host_endian);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -587,7 +587,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
|
|||
if (!buf)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
|
||||
r = usbi_backend->get_active_config_descriptor(dev, buf,
|
||||
r = usbi_backend.get_active_config_descriptor(dev, buf,
|
||||
_config.wTotalLength, &host_endian);
|
||||
if (r >= 0)
|
||||
r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
|
||||
|
@ -625,7 +625,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
|
|||
if (config_index >= dev->num_configurations)
|
||||
return LIBUSB_ERROR_NOT_FOUND;
|
||||
|
||||
r = usbi_backend->get_config_descriptor(dev, config_index, tmp,
|
||||
r = usbi_backend.get_config_descriptor(dev, config_index, tmp,
|
||||
LIBUSB_DT_CONFIG_SIZE, &host_endian);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -640,7 +640,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
|
|||
if (!buf)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
|
||||
r = usbi_backend->get_config_descriptor(dev, config_index, buf,
|
||||
r = usbi_backend.get_config_descriptor(dev, config_index, buf,
|
||||
_config.wTotalLength, &host_endian);
|
||||
if (r >= 0)
|
||||
r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
|
||||
|
@ -663,7 +663,7 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
|
|||
for (i = 0; i < dev->num_configurations; i++) {
|
||||
unsigned char tmp[6];
|
||||
int host_endian;
|
||||
int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp),
|
||||
int r = usbi_backend.get_config_descriptor(dev, i, tmp, sizeof(tmp),
|
||||
&host_endian);
|
||||
if (r < 0) {
|
||||
*idx = -1;
|
||||
|
@ -702,8 +702,8 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
|
|||
int r, idx, host_endian;
|
||||
unsigned char *buf = NULL;
|
||||
|
||||
if (usbi_backend->get_config_descriptor_by_value) {
|
||||
r = usbi_backend->get_config_descriptor_by_value(dev,
|
||||
if (usbi_backend.get_config_descriptor_by_value) {
|
||||
r = usbi_backend.get_config_descriptor_by_value(dev,
|
||||
bConfigurationValue, &buf, &host_endian);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1060,7 +1060,8 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
|
|||
* It is safe to call this function with a NULL ss_usb_device_cap
|
||||
* parameter, in which case the function simply returns.
|
||||
*
|
||||
* \param ss_usb_device_cap the USB 2.0 Extension descriptor to free
|
||||
* \param ss_usb_device_cap the SuperSpeed USB Device Capability descriptor
|
||||
* to free
|
||||
*/
|
||||
void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
|
||||
struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)
|
||||
|
@ -1117,7 +1118,7 @@ int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx,
|
|||
* It is safe to call this function with a NULL container_id parameter,
|
||||
* in which case the function simply returns.
|
||||
*
|
||||
* \param container_id the USB 2.0 Extension descriptor to free
|
||||
* \param container_id the Container ID descriptor to free
|
||||
*/
|
||||
void API_EXPORTED libusb_free_container_id_descriptor(
|
||||
struct libusb_container_id_descriptor *container_id)
|
||||
|
@ -1163,7 +1164,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha
|
|||
if (r < 4)
|
||||
return LIBUSB_ERROR_IO;
|
||||
|
||||
langid = tbuf[2] | (tbuf[3] << 8);
|
||||
langid = (uint16_t)(tbuf[2] | (tbuf[3] << 8));
|
||||
|
||||
r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf,
|
||||
sizeof(tbuf));
|
||||
|
@ -1176,7 +1177,8 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha
|
|||
if (tbuf[0] > r)
|
||||
return LIBUSB_ERROR_IO;
|
||||
|
||||
for (di = 0, si = 2; si < tbuf[0]; si += 2) {
|
||||
di = 0;
|
||||
for (si = 2; si < tbuf[0]; si += 2) {
|
||||
if (di >= (length - 1))
|
||||
break;
|
||||
|
||||
|
|
|
@ -154,36 +154,30 @@ int main (void) {
|
|||
\endcode
|
||||
*/
|
||||
|
||||
static int usbi_hotplug_match_cb (struct libusb_context *ctx,
|
||||
static int usbi_hotplug_match_cb(struct libusb_context *ctx,
|
||||
struct libusb_device *dev, libusb_hotplug_event event,
|
||||
struct libusb_hotplug_callback *hotplug_cb)
|
||||
{
|
||||
/* Handle lazy deregistration of callback */
|
||||
if (hotplug_cb->needs_free) {
|
||||
/* Free callback */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(hotplug_cb->events & event)) {
|
||||
if (!(hotplug_cb->flags & event)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
|
||||
if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) &&
|
||||
hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
|
||||
if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) &&
|
||||
hotplug_cb->product_id != dev->device_descriptor.idProduct) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
|
||||
if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) &&
|
||||
hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
|
||||
return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data);
|
||||
}
|
||||
|
||||
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
|
||||
|
@ -195,8 +189,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
|
|||
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
||||
|
||||
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
|
||||
if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) {
|
||||
/* process deregistration in usbi_hotplug_deregister() */
|
||||
continue;
|
||||
}
|
||||
|
||||
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
||||
ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
|
||||
ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb);
|
||||
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
||||
|
||||
if (ret) {
|
||||
|
@ -206,15 +205,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
|
|||
}
|
||||
|
||||
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
||||
|
||||
/* the backend is expected to call the callback for each active transfer */
|
||||
}
|
||||
|
||||
void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
|
||||
libusb_hotplug_event event)
|
||||
{
|
||||
int pending_events;
|
||||
libusb_hotplug_message *message = calloc(1, sizeof(*message));
|
||||
struct libusb_hotplug_message *message = calloc(1, sizeof(*message));
|
||||
|
||||
if (!message) {
|
||||
usbi_err(ctx, "error allocating hotplug message");
|
||||
|
@ -240,59 +237,70 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
|
|||
libusb_hotplug_callback_fn cb_fn, void *user_data,
|
||||
libusb_hotplug_callback_handle *callback_handle)
|
||||
{
|
||||
libusb_hotplug_callback *new_callback;
|
||||
static int handle_id = 1;
|
||||
|
||||
/* check for hotplug support */
|
||||
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
struct libusb_hotplug_callback *new_callback;
|
||||
|
||||
/* check for sane values */
|
||||
if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
|
||||
if ((!events || (~(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) & events)) ||
|
||||
(flags && (~LIBUSB_HOTPLUG_ENUMERATE & flags)) ||
|
||||
(LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
|
||||
(LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
|
||||
(LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
|
||||
!cb_fn) {
|
||||
return LIBUSB_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* check for hotplug support */
|
||||
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
USBI_GET_CONTEXT(ctx);
|
||||
|
||||
new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
|
||||
new_callback = calloc(1, sizeof(*new_callback));
|
||||
if (!new_callback) {
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
new_callback->ctx = ctx;
|
||||
new_callback->vendor_id = vendor_id;
|
||||
new_callback->product_id = product_id;
|
||||
new_callback->dev_class = dev_class;
|
||||
new_callback->flags = flags;
|
||||
new_callback->events = events;
|
||||
new_callback->flags = (uint8_t)events;
|
||||
if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) {
|
||||
new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID;
|
||||
new_callback->vendor_id = (uint16_t)vendor_id;
|
||||
}
|
||||
if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) {
|
||||
new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID;
|
||||
new_callback->product_id = (uint16_t)product_id;
|
||||
}
|
||||
if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) {
|
||||
new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID;
|
||||
new_callback->dev_class = (uint8_t)dev_class;
|
||||
}
|
||||
new_callback->cb = cb_fn;
|
||||
new_callback->user_data = user_data;
|
||||
new_callback->needs_free = 0;
|
||||
|
||||
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
||||
|
||||
/* protect the handle by the context hotplug lock. it doesn't matter if the same handle
|
||||
* is used for different contexts only that the handle is unique for this context */
|
||||
new_callback->handle = handle_id++;
|
||||
/* protect the handle by the context hotplug lock */
|
||||
new_callback->handle = ctx->next_hotplug_cb_handle++;
|
||||
|
||||
/* handle the unlikely case of overflow */
|
||||
if (ctx->next_hotplug_cb_handle < 0)
|
||||
ctx->next_hotplug_cb_handle = 1;
|
||||
|
||||
list_add(&new_callback->list, &ctx->hotplug_cbs);
|
||||
|
||||
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
||||
|
||||
usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle);
|
||||
|
||||
if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
|
||||
int i, len;
|
||||
if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) {
|
||||
ssize_t i, len;
|
||||
struct libusb_device **devs;
|
||||
|
||||
len = (int) libusb_get_device_list(ctx, &devs);
|
||||
len = libusb_get_device_list(ctx, &devs);
|
||||
if (len < 0) {
|
||||
libusb_hotplug_deregister_callback(ctx,
|
||||
new_callback->handle);
|
||||
return len;
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
@ -311,10 +319,11 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
|
||||
void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx,
|
||||
libusb_hotplug_callback_handle callback_handle)
|
||||
{
|
||||
struct libusb_hotplug_callback *hotplug_cb;
|
||||
int deregistered = 0;
|
||||
|
||||
/* check for hotplug support */
|
||||
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
|
||||
|
@ -323,28 +332,42 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx
|
|||
|
||||
USBI_GET_CONTEXT(ctx);
|
||||
|
||||
usbi_dbg("deregister hotplug cb %d", callback_handle);
|
||||
|
||||
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
||||
list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
|
||||
struct libusb_hotplug_callback) {
|
||||
list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
|
||||
if (callback_handle == hotplug_cb->handle) {
|
||||
/* Mark this callback for deregistration */
|
||||
hotplug_cb->needs_free = 1;
|
||||
hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE;
|
||||
deregistered = 1;
|
||||
}
|
||||
}
|
||||
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
||||
|
||||
usbi_hotplug_notification(ctx, NULL, 0);
|
||||
if (deregistered) {
|
||||
int pending_events;
|
||||
|
||||
usbi_mutex_lock(&ctx->event_data_lock);
|
||||
pending_events = usbi_pending_events(ctx);
|
||||
ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
|
||||
if (!pending_events)
|
||||
usbi_signal_event(ctx);
|
||||
usbi_mutex_unlock(&ctx->event_data_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
|
||||
void usbi_hotplug_deregister(struct libusb_context *ctx, int forced)
|
||||
{
|
||||
struct libusb_hotplug_callback *hotplug_cb, *next;
|
||||
|
||||
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
||||
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
|
||||
struct libusb_hotplug_callback) {
|
||||
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
|
||||
if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) {
|
||||
usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb,
|
||||
hotplug_cb->handle);
|
||||
list_del(&hotplug_cb->list);
|
||||
free(hotplug_cb);
|
||||
}
|
||||
|
||||
}
|
||||
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
||||
}
|
||||
|
|
|
@ -19,12 +19,34 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(USBI_HOTPLUG_H)
|
||||
#ifndef USBI_HOTPLUG_H
|
||||
#define USBI_HOTPLUG_H
|
||||
|
||||
#ifndef LIBUSBI_H
|
||||
#include "libusbi.h"
|
||||
#endif
|
||||
|
||||
enum usbi_hotplug_flags {
|
||||
/* This callback is interested in device arrivals */
|
||||
USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
|
||||
|
||||
/* This callback is interested in device removals */
|
||||
USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
|
||||
|
||||
/* IMPORTANT: The values for the below entries must start *after*
|
||||
* the highest value of the above entries!!!
|
||||
*/
|
||||
|
||||
/* The vendor_id field is valid for matching */
|
||||
USBI_HOTPLUG_VENDOR_ID_VALID = (1U << 3),
|
||||
|
||||
/* The product_id field is valid for matching */
|
||||
USBI_HOTPLUG_PRODUCT_ID_VALID = (1U << 4),
|
||||
|
||||
/* The dev_class field is valid for matching */
|
||||
USBI_HOTPLUG_DEV_CLASS_VALID = (1U << 5),
|
||||
|
||||
/* This callback has been unregistered and needs to be freed */
|
||||
USBI_HOTPLUG_NEEDS_FREE = (1U << 6),
|
||||
};
|
||||
|
||||
/** \ingroup hotplug
|
||||
* The hotplug callback structure. The user populates this structure with
|
||||
|
@ -32,23 +54,17 @@
|
|||
* to receive notification of hotplug events.
|
||||
*/
|
||||
struct libusb_hotplug_callback {
|
||||
/** Context this callback is associated with */
|
||||
struct libusb_context *ctx;
|
||||
/** Flags that control how this callback behaves */
|
||||
uint8_t flags;
|
||||
|
||||
/** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
|
||||
int vendor_id;
|
||||
/** Vendor ID to match (if flags says this is valid) */
|
||||
uint16_t vendor_id;
|
||||
|
||||
/** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
|
||||
int product_id;
|
||||
/** Product ID to match (if flags says this is valid) */
|
||||
uint16_t product_id;
|
||||
|
||||
/** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */
|
||||
int dev_class;
|
||||
|
||||
/** Hotplug callback flags */
|
||||
libusb_hotplug_flag flags;
|
||||
|
||||
/** Event(s) that will trigger this callback */
|
||||
libusb_hotplug_event events;
|
||||
/** Device class to match (if flags says this is valid) */
|
||||
uint8_t dev_class;
|
||||
|
||||
/** Callback function to invoke for matching event/device */
|
||||
libusb_hotplug_callback_fn cb;
|
||||
|
@ -59,15 +75,10 @@ struct libusb_hotplug_callback {
|
|||
/** User data that will be passed to the callback function */
|
||||
void *user_data;
|
||||
|
||||
/** Callback is marked for deletion */
|
||||
int needs_free;
|
||||
|
||||
/** List this callback is registered in (ctx->hotplug_cbs) */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
typedef struct libusb_hotplug_callback libusb_hotplug_callback;
|
||||
|
||||
struct libusb_hotplug_message {
|
||||
/** The hotplug event that occurred */
|
||||
libusb_hotplug_event event;
|
||||
|
@ -79,9 +90,7 @@ struct libusb_hotplug_message {
|
|||
struct list_head list;
|
||||
};
|
||||
|
||||
typedef struct libusb_hotplug_message libusb_hotplug_message;
|
||||
|
||||
void usbi_hotplug_deregister_all(struct libusb_context *ctx);
|
||||
void usbi_hotplug_deregister(struct libusb_context *ctx, int forced);
|
||||
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
|
||||
libusb_hotplug_event event);
|
||||
void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
@ -1147,8 +1144,8 @@ int usbi_io_init(struct libusb_context *ctx)
|
|||
goto err_close_pipe;
|
||||
|
||||
#ifdef USBI_TIMERFD_AVAILABLE
|
||||
ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(),
|
||||
TFD_NONBLOCK);
|
||||
ctx->timerfd = timerfd_create(usbi_backend.get_timerfd_clockid(),
|
||||
TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
if (ctx->timerfd >= 0) {
|
||||
usbi_dbg("using timerfd for timeouts");
|
||||
r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN);
|
||||
|
@ -1197,7 +1194,6 @@ void usbi_io_exit(struct libusb_context *ctx)
|
|||
usbi_cond_destroy(&ctx->event_waiters_cond);
|
||||
usbi_mutex_destroy(&ctx->event_data_lock);
|
||||
usbi_tls_key_delete(ctx->event_handling_key);
|
||||
if (ctx->pollfds)
|
||||
free(ctx->pollfds);
|
||||
}
|
||||
|
||||
|
@ -1208,10 +1204,12 @@ static int calculate_timeout(struct usbi_transfer *transfer)
|
|||
unsigned int timeout =
|
||||
USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout;
|
||||
|
||||
if (!timeout)
|
||||
if (!timeout) {
|
||||
timerclear(&transfer->timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time);
|
||||
r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time);
|
||||
if (r < 0) {
|
||||
usbi_err(ITRANSFER_CTX(transfer),
|
||||
"failed to read monotonic clock, errno=%d", errno);
|
||||
|
@ -1250,7 +1248,7 @@ static int calculate_timeout(struct usbi_transfer *transfer)
|
|||
* use it on a non-isochronous endpoint. If you do this, ensure that at time
|
||||
* of submission, num_iso_packets is 0 and that type is set appropriately.
|
||||
*
|
||||
* \param iso_packets number of isochronous packet descriptors to allocate
|
||||
* \param iso_packets number of isochronous packet descriptors to allocate. Must be non-negative.
|
||||
* \returns a newly allocated transfer, or NULL on error
|
||||
*/
|
||||
DEFAULT_VISIBILITY
|
||||
|
@ -1258,12 +1256,18 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
|
|||
int iso_packets)
|
||||
{
|
||||
struct libusb_transfer *transfer;
|
||||
size_t os_alloc_size = usbi_backend->transfer_priv_size;
|
||||
size_t alloc_size = sizeof(struct usbi_transfer)
|
||||
size_t os_alloc_size;
|
||||
size_t alloc_size;
|
||||
struct usbi_transfer *itransfer;
|
||||
|
||||
assert(iso_packets >= 0);
|
||||
|
||||
os_alloc_size = usbi_backend.transfer_priv_size;
|
||||
alloc_size = sizeof(struct usbi_transfer)
|
||||
+ sizeof(struct libusb_transfer)
|
||||
+ (sizeof(struct libusb_iso_packet_descriptor) * iso_packets)
|
||||
+ (sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets)
|
||||
+ os_alloc_size;
|
||||
struct usbi_transfer *itransfer = calloc(1, alloc_size);
|
||||
itransfer = calloc(1, alloc_size);
|
||||
if (!itransfer)
|
||||
return NULL;
|
||||
|
||||
|
@ -1298,7 +1302,7 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
|
|||
return;
|
||||
|
||||
usbi_dbg("transfer %p", transfer);
|
||||
if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer)
|
||||
if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
|
||||
free(transfer->buffer);
|
||||
|
||||
itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
|
||||
|
@ -1529,7 +1533,7 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
|
|||
*/
|
||||
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
||||
|
||||
r = usbi_backend->submit_transfer(itransfer);
|
||||
r = usbi_backend.submit_transfer(itransfer);
|
||||
if (r == LIBUSB_SUCCESS) {
|
||||
itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
|
||||
/* keep a reference to this device */
|
||||
|
@ -1570,7 +1574,7 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
|
|||
r = LIBUSB_ERROR_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
r = usbi_backend->cancel_transfer(itransfer);
|
||||
r = usbi_backend.cancel_transfer(itransfer);
|
||||
if (r < 0) {
|
||||
if (r != LIBUSB_ERROR_NOT_FOUND &&
|
||||
r != LIBUSB_ERROR_NO_DEVICE)
|
||||
|
@ -1707,7 +1711,10 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer)
|
|||
* function will be called the next time an event handler runs. */
|
||||
void usbi_signal_transfer_completion(struct usbi_transfer *transfer)
|
||||
{
|
||||
struct libusb_context *ctx = ITRANSFER_CTX(transfer);
|
||||
libusb_device_handle *dev_handle = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->dev_handle;
|
||||
|
||||
if (dev_handle) {
|
||||
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
||||
int pending_events;
|
||||
|
||||
usbi_mutex_lock(&ctx->event_data_lock);
|
||||
|
@ -1716,6 +1723,7 @@ void usbi_signal_transfer_completion(struct usbi_transfer *transfer)
|
|||
if (!pending_events)
|
||||
usbi_signal_event(ctx);
|
||||
usbi_mutex_unlock(&ctx->event_data_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/** \ingroup libusb_poll
|
||||
|
@ -1887,14 +1895,17 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
|
|||
*/
|
||||
void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
|
||||
{
|
||||
int pending_events;
|
||||
USBI_GET_CONTEXT(ctx);
|
||||
|
||||
usbi_dbg("");
|
||||
usbi_mutex_lock(&ctx->event_data_lock);
|
||||
if (!usbi_pending_events(ctx)) {
|
||||
|
||||
pending_events = usbi_pending_events(ctx);
|
||||
ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
|
||||
if (!pending_events)
|
||||
usbi_signal_event(ctx);
|
||||
}
|
||||
|
||||
usbi_mutex_unlock(&ctx->event_data_lock);
|
||||
}
|
||||
|
||||
|
@ -2004,7 +2015,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx)
|
|||
return 0;
|
||||
|
||||
/* get current time */
|
||||
r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts);
|
||||
r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -2077,13 +2088,19 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|||
struct pollfd *fds = NULL;
|
||||
int i = -1;
|
||||
int timeout_ms;
|
||||
int special_event;
|
||||
|
||||
/* prevent attempts to recursively handle events (e.g. calling into
|
||||
* libusb_handle_events() from within a hotplug or transfer callback) */
|
||||
usbi_mutex_lock(&ctx->event_data_lock);
|
||||
r = 0;
|
||||
if (usbi_handling_events(ctx))
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
r = LIBUSB_ERROR_BUSY;
|
||||
else
|
||||
usbi_start_event_handling(ctx);
|
||||
usbi_mutex_unlock(&ctx->event_data_lock);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* there are certain fds that libusb uses internally, currently:
|
||||
*
|
||||
|
@ -2105,10 +2122,8 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|||
if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) {
|
||||
usbi_dbg("poll fds modified, reallocating");
|
||||
|
||||
if (ctx->pollfds) {
|
||||
free(ctx->pollfds);
|
||||
ctx->pollfds = NULL;
|
||||
}
|
||||
|
||||
/* sanity check - it is invalid for a context to have fewer than the
|
||||
* required internal fds (memory corruption?) */
|
||||
|
@ -2138,6 +2153,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|||
}
|
||||
fds = ctx->pollfds;
|
||||
nfds = ctx->pollfds_cnt;
|
||||
usbi_inc_fds_ref(fds, nfds);
|
||||
usbi_mutex_unlock(&ctx->event_data_lock);
|
||||
|
||||
timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
|
||||
|
@ -2146,32 +2162,30 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|||
if (tv->tv_usec % 1000)
|
||||
timeout_ms++;
|
||||
|
||||
redo_poll:
|
||||
usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms);
|
||||
r = usbi_poll(fds, nfds, timeout_ms);
|
||||
usbi_dbg("poll() returned %d", r);
|
||||
if (r == 0) {
|
||||
r = handle_timeouts(ctx);
|
||||
goto done;
|
||||
}
|
||||
else if (r == -1 && errno == EINTR) {
|
||||
} else if (r == -1 && errno == EINTR) {
|
||||
r = LIBUSB_ERROR_INTERRUPTED;
|
||||
goto done;
|
||||
}
|
||||
else if (r < 0) {
|
||||
} else if (r < 0) {
|
||||
usbi_err(ctx, "poll failed %d err=%d", r, errno);
|
||||
r = LIBUSB_ERROR_IO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
special_event = 0;
|
||||
|
||||
/* fds[0] is always the event pipe */
|
||||
if (fds[0].revents) {
|
||||
libusb_hotplug_message *message = NULL;
|
||||
struct list_head hotplug_msgs;
|
||||
struct usbi_transfer *itransfer;
|
||||
int hotplug_cb_deregistered = 0;
|
||||
int ret = 0;
|
||||
|
||||
list_init(&hotplug_msgs);
|
||||
|
||||
usbi_dbg("caught a fish on the event pipe");
|
||||
|
||||
/* take the the event data lock while processing events */
|
||||
|
@ -2186,6 +2200,12 @@ redo_poll:
|
|||
ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT;
|
||||
}
|
||||
|
||||
if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) {
|
||||
usbi_dbg("someone unregistered a hotplug cb");
|
||||
ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
|
||||
hotplug_cb_deregistered = 1;
|
||||
}
|
||||
|
||||
/* check if someone is closing a device */
|
||||
if (ctx->device_close)
|
||||
usbi_dbg("someone is closing a device");
|
||||
|
@ -2193,9 +2213,7 @@ redo_poll:
|
|||
/* check for any pending hotplug messages */
|
||||
if (!list_empty(&ctx->hotplug_msgs)) {
|
||||
usbi_dbg("hotplug message received");
|
||||
special_event = 1;
|
||||
message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list);
|
||||
list_del(&message->list);
|
||||
list_cut(&hotplug_msgs, &ctx->hotplug_msgs);
|
||||
}
|
||||
|
||||
/* complete any pending transfers */
|
||||
|
@ -2203,7 +2221,7 @@ redo_poll:
|
|||
itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list);
|
||||
list_del(&itransfer->completed_list);
|
||||
usbi_mutex_unlock(&ctx->event_data_lock);
|
||||
ret = usbi_backend->handle_transfer_completion(itransfer);
|
||||
ret = usbi_backend.handle_transfer_completion(itransfer);
|
||||
if (ret)
|
||||
usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret);
|
||||
usbi_mutex_lock(&ctx->event_data_lock);
|
||||
|
@ -2215,14 +2233,21 @@ redo_poll:
|
|||
|
||||
usbi_mutex_unlock(&ctx->event_data_lock);
|
||||
|
||||
/* process the hotplug message, if any */
|
||||
if (message) {
|
||||
if (hotplug_cb_deregistered)
|
||||
usbi_hotplug_deregister(ctx, 0);
|
||||
|
||||
/* process the hotplug messages, if any */
|
||||
while (!list_empty(&hotplug_msgs)) {
|
||||
struct libusb_hotplug_message *message =
|
||||
list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list);
|
||||
|
||||
usbi_hotplug_match(ctx, message->device, message->event);
|
||||
|
||||
/* the device left, dereference the device */
|
||||
if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event)
|
||||
libusb_unref_device(message->device);
|
||||
|
||||
list_del(&message->list);
|
||||
free(message);
|
||||
}
|
||||
|
||||
|
@ -2233,7 +2258,7 @@ redo_poll:
|
|||
}
|
||||
|
||||
if (0 == --r)
|
||||
goto handled;
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifdef USBI_TIMERFD_AVAILABLE
|
||||
|
@ -2242,7 +2267,6 @@ redo_poll:
|
|||
/* timerfd indicates that a timeout has expired */
|
||||
int ret;
|
||||
usbi_dbg("timerfd triggered");
|
||||
special_event = 1;
|
||||
|
||||
ret = handle_timerfd_trigger(ctx);
|
||||
if (ret < 0) {
|
||||
|
@ -2252,22 +2276,17 @@ redo_poll:
|
|||
}
|
||||
|
||||
if (0 == --r)
|
||||
goto handled;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
r = usbi_backend->handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r);
|
||||
r = usbi_backend.handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r);
|
||||
if (r)
|
||||
usbi_err(ctx, "backend handle_events failed with error %d", r);
|
||||
|
||||
handled:
|
||||
if (r == 0 && special_event) {
|
||||
timeout_ms = 0;
|
||||
goto redo_poll;
|
||||
}
|
||||
|
||||
done:
|
||||
usbi_end_event_handling(ctx);
|
||||
usbi_dec_fds_ref(fds, nfds);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2583,7 +2602,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts);
|
||||
r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts);
|
||||
if (r < 0) {
|
||||
usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno);
|
||||
return 0;
|
||||
|
@ -2595,7 +2614,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
|
|||
timerclear(tv);
|
||||
} else {
|
||||
timersub(&next_timeout, &cur_tv, tv);
|
||||
usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec);
|
||||
usbi_dbg("next timeout in %ld.%06lds", (long)tv->tv_sec, (long)tv->tv_usec);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -2752,15 +2771,12 @@ out:
|
|||
* Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104
|
||||
*
|
||||
* It is legal to call this function with a NULL pollfd list. In this case,
|
||||
* the function will simply return safely.
|
||||
* the function will simply do nothing.
|
||||
*
|
||||
* \param pollfds the list of libusb_pollfd structures to free
|
||||
*/
|
||||
void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds)
|
||||
{
|
||||
if (!pollfds)
|
||||
return;
|
||||
|
||||
free((void *)pollfds);
|
||||
}
|
||||
|
||||
|
@ -2811,7 +2827,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
|
|||
USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
|
||||
|
||||
usbi_mutex_lock(&to_cancel->lock);
|
||||
usbi_backend->clear_transfer_priv(to_cancel);
|
||||
usbi_backend.clear_transfer_priv(to_cancel);
|
||||
usbi_mutex_unlock(&to_cancel->lock);
|
||||
usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
|
||||
}
|
||||
|
|
|
@ -126,10 +126,10 @@ EXPORTS
|
|||
libusb_interrupt_transfer@24 = libusb_interrupt_transfer
|
||||
libusb_kernel_driver_active
|
||||
libusb_kernel_driver_active@8 = libusb_kernel_driver_active
|
||||
libusb_lock_events
|
||||
libusb_lock_events@4 = libusb_lock_events
|
||||
libusb_lock_event_waiters
|
||||
libusb_lock_event_waiters@4 = libusb_lock_event_waiters
|
||||
libusb_lock_events
|
||||
libusb_lock_events@4 = libusb_lock_events
|
||||
libusb_open
|
||||
libusb_open@8 = libusb_open
|
||||
libusb_open_device_with_vid_pid
|
||||
|
@ -148,12 +148,16 @@ EXPORTS
|
|||
libusb_set_configuration@8 = libusb_set_configuration
|
||||
libusb_set_debug
|
||||
libusb_set_debug@8 = libusb_set_debug
|
||||
libusb_set_log_cb
|
||||
libusb_set_log_cb@12 = libusb_set_log_cb
|
||||
libusb_set_interface_alt_setting
|
||||
libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
|
||||
libusb_setlocale
|
||||
libusb_setlocale@4 = libusb_setlocale
|
||||
libusb_set_option
|
||||
_libusb_set_option = libusb_set_option
|
||||
libusb_set_pollfd_notifiers
|
||||
libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
|
||||
libusb_setlocale
|
||||
libusb_setlocale@4 = libusb_setlocale
|
||||
libusb_strerror
|
||||
libusb_strerror@4 = libusb_strerror
|
||||
libusb_submit_transfer
|
||||
|
@ -164,10 +168,10 @@ EXPORTS
|
|||
libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id
|
||||
libusb_try_lock_events
|
||||
libusb_try_lock_events@4 = libusb_try_lock_events
|
||||
libusb_unlock_events
|
||||
libusb_unlock_events@4 = libusb_unlock_events
|
||||
libusb_unlock_event_waiters
|
||||
libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters
|
||||
libusb_unlock_events
|
||||
libusb_unlock_events@4 = libusb_unlock_events
|
||||
libusb_unref_device
|
||||
libusb_unref_device@4 = libusb_unref_device
|
||||
libusb_wait_for_event
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
|
||||
* Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||
* 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
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -54,13 +54,19 @@ typedef unsigned __int32 uint32_t;
|
|||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <time.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
|
||||
* undefine it so as not to break the current libusb API, because
|
||||
* libusb_config_descriptor has an 'interface' member
|
||||
|
@ -79,6 +85,8 @@ typedef unsigned __int32 uint32_t;
|
|||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
#define LIBUSB_DEPRECATED_FOR(f) \
|
||||
__attribute__((deprecated("Use " #f " instead")))
|
||||
#elif __GNUC__ >= 3
|
||||
#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated))
|
||||
#else
|
||||
#define LIBUSB_DEPRECATED_FOR(f)
|
||||
#endif /* __GNUC__ */
|
||||
|
@ -141,7 +149,7 @@ typedef unsigned __int32 uint32_t;
|
|||
* Internally, LIBUSB_API_VERSION is defined as follows:
|
||||
* (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
|
||||
*/
|
||||
#define LIBUSB_API_VERSION 0x01000105
|
||||
#define LIBUSB_API_VERSION 0x01000107
|
||||
|
||||
/* The following is kept for compatibility, but will be deprecated in the future */
|
||||
#define LIBUSBX_API_VERSION LIBUSB_API_VERSION
|
||||
|
@ -569,7 +577,7 @@ struct libusb_endpoint_descriptor {
|
|||
* it will store them here, should you wish to parse them. */
|
||||
const unsigned char *extra;
|
||||
|
||||
/** Length of the extra descriptors, in bytes. */
|
||||
/** Length of the extra descriptors, in bytes. Must be non-negative. */
|
||||
int extra_length;
|
||||
};
|
||||
|
||||
|
@ -619,7 +627,7 @@ struct libusb_interface_descriptor {
|
|||
* it will store them here, should you wish to parse them. */
|
||||
const unsigned char *extra;
|
||||
|
||||
/** Length of the extra descriptors, in bytes. */
|
||||
/** Length of the extra descriptors, in bytes. Must be non-negative. */
|
||||
int extra_length;
|
||||
};
|
||||
|
||||
|
@ -631,7 +639,8 @@ struct libusb_interface {
|
|||
* by the num_altsetting field. */
|
||||
const struct libusb_interface_descriptor *altsetting;
|
||||
|
||||
/** The number of alternate settings that belong to this interface */
|
||||
/** The number of alternate settings that belong to this interface.
|
||||
* Must be non-negative. */
|
||||
int num_altsetting;
|
||||
};
|
||||
|
||||
|
@ -678,7 +687,7 @@ struct libusb_config_descriptor {
|
|||
* descriptors, it will store them here, should you wish to parse them. */
|
||||
const unsigned char *extra;
|
||||
|
||||
/** Length of the extra descriptors, in bytes. */
|
||||
/** Length of the extra descriptors, in bytes. Must be non-negative. */
|
||||
int extra_length;
|
||||
};
|
||||
|
||||
|
@ -729,13 +738,7 @@ struct libusb_bos_dev_capability_descriptor {
|
|||
/** Device Capability type */
|
||||
uint8_t bDevCapabilityType;
|
||||
/** Device Capability data (bLength - 3 bytes) */
|
||||
uint8_t dev_capability_data
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
[] /* valid C99 code */
|
||||
#else
|
||||
[0] /* non-standard, but usually working code */
|
||||
#endif
|
||||
;
|
||||
uint8_t dev_capability_data[ZERO_SIZED_ARRAY];
|
||||
};
|
||||
|
||||
/** \ingroup libusb_desc
|
||||
|
@ -760,13 +763,7 @@ struct libusb_bos_descriptor {
|
|||
uint8_t bNumDeviceCaps;
|
||||
|
||||
/** bNumDeviceCap Device Capability Descriptors */
|
||||
struct libusb_bos_dev_capability_descriptor *dev_capability
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
[] /* valid C99 code */
|
||||
#else
|
||||
[0] /* non-standard, but usually working code */
|
||||
#endif
|
||||
;
|
||||
struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY];
|
||||
};
|
||||
|
||||
/** \ingroup libusb_desc
|
||||
|
@ -927,7 +924,7 @@ struct libusb_version {
|
|||
* sessions allows for your program to use two libraries (or dynamically
|
||||
* load two modules) which both independently use libusb. This will prevent
|
||||
* interference between the individual libusb users - for example
|
||||
* libusb_set_debug() will not affect the other user of the library, and
|
||||
* libusb_set_option() will not affect the other user of the library, and
|
||||
* libusb_exit() will not destroy resources that the other user is still
|
||||
* using.
|
||||
*
|
||||
|
@ -987,6 +984,9 @@ enum libusb_speed {
|
|||
|
||||
/** The device is operating at super speed (5000MBit/s). */
|
||||
LIBUSB_SPEED_SUPER = 4,
|
||||
|
||||
/** The device is operating at super speed plus (10000MBit/s). */
|
||||
LIBUSB_SPEED_SUPER_PLUS = 5,
|
||||
};
|
||||
|
||||
/** \ingroup libusb_dev
|
||||
|
@ -1135,19 +1135,19 @@ enum libusb_transfer_status {
|
|||
* libusb_transfer.flags values */
|
||||
enum libusb_transfer_flags {
|
||||
/** Report short frames as errors */
|
||||
LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0,
|
||||
LIBUSB_TRANSFER_SHORT_NOT_OK = 1U << 0,
|
||||
|
||||
/** Automatically free() transfer buffer during libusb_free_transfer().
|
||||
* Note that buffers allocated with libusb_dev_mem_alloc() should not
|
||||
* be attempted freed in this way, since free() is not an appropriate
|
||||
* way to release such memory. */
|
||||
LIBUSB_TRANSFER_FREE_BUFFER = 1<<1,
|
||||
LIBUSB_TRANSFER_FREE_BUFFER = 1U << 1,
|
||||
|
||||
/** Automatically call libusb_free_transfer() after callback returns.
|
||||
* If this flag is set, it is illegal to call libusb_free_transfer()
|
||||
* from your transfer callback, as this will result in a double-free
|
||||
* when this flag is acted upon. */
|
||||
LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2,
|
||||
LIBUSB_TRANSFER_FREE_TRANSFER = 1U << 2,
|
||||
|
||||
/** Terminate transfers that are a multiple of the endpoint's
|
||||
* wMaxPacketSize with an extra zero length packet. This is useful
|
||||
|
@ -1172,7 +1172,7 @@ enum libusb_transfer_flags {
|
|||
*
|
||||
* Available since libusb-1.0.9.
|
||||
*/
|
||||
LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3,
|
||||
LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1U << 3,
|
||||
};
|
||||
|
||||
/** \ingroup libusb_asyncio
|
||||
|
@ -1220,7 +1220,7 @@ struct libusb_transfer {
|
|||
/** Type of the endpoint from \ref libusb_transfer_type */
|
||||
unsigned char type;
|
||||
|
||||
/** Timeout for this transfer in millseconds. A value of 0 indicates no
|
||||
/** Timeout for this transfer in milliseconds. A value of 0 indicates no
|
||||
* timeout. */
|
||||
unsigned int timeout;
|
||||
|
||||
|
@ -1233,7 +1233,7 @@ struct libusb_transfer {
|
|||
* to determine if errors occurred. */
|
||||
enum libusb_transfer_status status;
|
||||
|
||||
/** Length of the data buffer */
|
||||
/** Length of the data buffer. Must be non-negative. */
|
||||
int length;
|
||||
|
||||
/** Actual length of data that was transferred. Read-only, and only for
|
||||
|
@ -1252,17 +1252,11 @@ struct libusb_transfer {
|
|||
unsigned char *buffer;
|
||||
|
||||
/** Number of isochronous packets. Only used for I/O with isochronous
|
||||
* endpoints. */
|
||||
* endpoints. Must be non-negative. */
|
||||
int num_iso_packets;
|
||||
|
||||
/** Isochronous packet descriptors, for isochronous transfers only. */
|
||||
struct libusb_iso_packet_descriptor iso_packet_desc
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
[] /* valid C99 code */
|
||||
#else
|
||||
[0] /* non-standard, but usually working code */
|
||||
#endif
|
||||
;
|
||||
struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY];
|
||||
};
|
||||
|
||||
/** \ingroup libusb_misc
|
||||
|
@ -1290,22 +1284,46 @@ enum libusb_capability {
|
|||
* - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default)
|
||||
* - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr
|
||||
* - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr
|
||||
* - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning
|
||||
* and error messages are printed to stderr
|
||||
* - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout,
|
||||
* warnings and errors to stderr
|
||||
* - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr
|
||||
* - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr
|
||||
*/
|
||||
enum libusb_log_level {
|
||||
LIBUSB_LOG_LEVEL_NONE = 0,
|
||||
LIBUSB_LOG_LEVEL_ERROR,
|
||||
LIBUSB_LOG_LEVEL_WARNING,
|
||||
LIBUSB_LOG_LEVEL_INFO,
|
||||
LIBUSB_LOG_LEVEL_DEBUG,
|
||||
LIBUSB_LOG_LEVEL_ERROR = 1,
|
||||
LIBUSB_LOG_LEVEL_WARNING = 2,
|
||||
LIBUSB_LOG_LEVEL_INFO = 3,
|
||||
LIBUSB_LOG_LEVEL_DEBUG = 4,
|
||||
};
|
||||
|
||||
/** \ingroup libusb_lib
|
||||
* Log callback mode.
|
||||
* \see libusb_set_log_cb()
|
||||
*/
|
||||
enum libusb_log_cb_mode {
|
||||
|
||||
/** Callback function handling all log mesages. */
|
||||
LIBUSB_LOG_CB_GLOBAL = 1 << 0,
|
||||
|
||||
/** Callback function handling context related log mesages. */
|
||||
LIBUSB_LOG_CB_CONTEXT = 1 << 1
|
||||
};
|
||||
|
||||
/** \ingroup libusb_lib
|
||||
* Callback function for handling log messages.
|
||||
* \param ctx the context which is related to the log message, or NULL if it
|
||||
* is a global log message
|
||||
* \param level the log level, see \ref libusb_log_level for a description
|
||||
* \param str the log message
|
||||
* \see libusb_set_log_cb()
|
||||
*/
|
||||
typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx,
|
||||
enum libusb_log_level level, const char *str);
|
||||
|
||||
int LIBUSB_CALL libusb_init(libusb_context **ctx);
|
||||
void LIBUSB_CALL libusb_exit(libusb_context *ctx);
|
||||
LIBUSB_DEPRECATED_FOR(libusb_set_option)
|
||||
void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
|
||||
void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode);
|
||||
const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
|
||||
int LIBUSB_CALL libusb_has_capability(uint32_t capability);
|
||||
const char * LIBUSB_CALL libusb_error_name(int errcode);
|
||||
|
@ -1370,6 +1388,7 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev,
|
|||
int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
|
||||
unsigned char endpoint);
|
||||
|
||||
int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle);
|
||||
int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle);
|
||||
void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
|
||||
libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle);
|
||||
|
@ -1892,10 +1911,10 @@ typedef int libusb_hotplug_callback_handle;
|
|||
* Flags for hotplug events */
|
||||
typedef enum {
|
||||
/** Default value when not using any flags. */
|
||||
LIBUSB_HOTPLUG_NO_FLAGS = 0,
|
||||
LIBUSB_HOTPLUG_NO_FLAGS = 0U,
|
||||
|
||||
/** Arm the callback and fire it for all matching currently attached devices. */
|
||||
LIBUSB_HOTPLUG_ENUMERATE = 1<<0,
|
||||
LIBUSB_HOTPLUG_ENUMERATE = 1U << 0,
|
||||
} libusb_hotplug_flag;
|
||||
|
||||
/** \ingroup libusb_hotplug
|
||||
|
@ -1905,12 +1924,12 @@ typedef enum {
|
|||
* Hotplug events */
|
||||
typedef enum {
|
||||
/** A device has been plugged in and is ready to use */
|
||||
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01,
|
||||
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01U,
|
||||
|
||||
/** A device has left and is no longer available.
|
||||
* It is the user's responsibility to call libusb_close on any handle associated with a disconnected device.
|
||||
* It is safe to call libusb_get_device_descriptor on a device that has left */
|
||||
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02,
|
||||
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02U,
|
||||
} libusb_hotplug_event;
|
||||
|
||||
/** \ingroup libusb_hotplug
|
||||
|
@ -2001,6 +2020,45 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,
|
|||
void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx,
|
||||
libusb_hotplug_callback_handle callback_handle);
|
||||
|
||||
/** \ingroup libusb_lib
|
||||
* Available option values for libusb_set_option().
|
||||
*/
|
||||
enum libusb_option {
|
||||
/** Set the log message verbosity.
|
||||
*
|
||||
* The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever
|
||||
* printed. If you choose to increase the message verbosity level, ensure
|
||||
* that your application does not close the stderr file descriptor.
|
||||
*
|
||||
* You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative
|
||||
* with its message logging and most of the time, will only log messages that
|
||||
* explain error conditions and other oddities. This will help you debug
|
||||
* your software.
|
||||
*
|
||||
* If the LIBUSB_DEBUG environment variable was set when libusb was
|
||||
* initialized, this function does nothing: the message verbosity is fixed
|
||||
* to the value in the environment variable.
|
||||
*
|
||||
* If libusb was compiled without any message logging, this function does
|
||||
* nothing: you'll never get any messages.
|
||||
*
|
||||
* If libusb was compiled with verbose debug message logging, this function
|
||||
* does nothing: you'll always get messages from all levels.
|
||||
*/
|
||||
LIBUSB_OPTION_LOG_LEVEL,
|
||||
|
||||
/** Use the UsbDk backend for a specific context, if available.
|
||||
*
|
||||
* This option should be set immediately after calling libusb_init(), otherwise
|
||||
* unspecified behavior may occur.
|
||||
*
|
||||
* Only valid on Windows.
|
||||
*/
|
||||
LIBUSB_OPTION_USE_USBDK,
|
||||
};
|
||||
|
||||
int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
@ -39,6 +39,20 @@
|
|||
#include "libusb.h"
|
||||
#include "version.h"
|
||||
|
||||
/* Attribute to ensure that a structure member is aligned to a natural
|
||||
* pointer alignment. Used for os_priv member. */
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_WIN64)
|
||||
#define PTR_ALIGNED __declspec(align(8))
|
||||
#else
|
||||
#define PTR_ALIGNED __declspec(align(4))
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#define PTR_ALIGNED __attribute__((aligned(sizeof(void *))))
|
||||
#else
|
||||
#define PTR_ALIGNED
|
||||
#endif
|
||||
|
||||
/* Inside the libusb code, mark all public functions as follows:
|
||||
* return_type API_EXPORTED function_name(params) { ... }
|
||||
* But if the function returns a pointer, mark it as follows:
|
||||
|
@ -48,6 +62,16 @@
|
|||
*/
|
||||
#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY
|
||||
|
||||
/* Macro to decorate printf-like functions, in order to get
|
||||
* compiler warnings about format string mistakes.
|
||||
*/
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
|
||||
#define USBI_PRINTFLIKE(formatarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, formatarg, firstvararg)))
|
||||
#else
|
||||
#define USBI_PRINTFLIKE(formatarg, firstvararg)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -139,6 +163,19 @@ static inline void list_del(struct list_head *entry)
|
|||
entry->next = entry->prev = NULL;
|
||||
}
|
||||
|
||||
static inline void list_cut(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (list_empty(head))
|
||||
return;
|
||||
|
||||
list->next = head->next;
|
||||
list->next->prev = list;
|
||||
list->prev = head->prev;
|
||||
list->prev->next = list;
|
||||
|
||||
list_init(head);
|
||||
}
|
||||
|
||||
static inline void *usbi_reallocf(void *ptr, size_t size)
|
||||
{
|
||||
void *ret = realloc(ptr, size);
|
||||
|
@ -151,6 +188,9 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
|
|||
const typeof( ((type *)0)->member ) *mptr = (ptr); \
|
||||
(type *)( (char *)mptr - offsetof(type,member) );})
|
||||
|
||||
#ifndef CLAMP
|
||||
#define CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val)))
|
||||
#endif
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
@ -175,29 +215,33 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
#define snprintf usbi_snprintf
|
||||
#define vsnprintf usbi_vsnprintf
|
||||
int usbi_snprintf(char *dst, size_t size, const char *format, ...);
|
||||
int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap);
|
||||
#define LIBUSB_PRINTF_WIN32
|
||||
#endif /* defined(_MSC_VER) && (_MSC_VER < 1900) */
|
||||
|
||||
void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
|
||||
const char *function, const char *format, ...);
|
||||
const char *function, const char *format, ...) USBI_PRINTFLIKE(4, 5);
|
||||
|
||||
void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
|
||||
const char *function, const char *format, va_list args);
|
||||
const char *function, const char *format, va_list args) USBI_PRINTFLIKE(4, 0);
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1400
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1400)
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
#define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__)
|
||||
#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0)
|
||||
#define usbi_dbg(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__)
|
||||
#define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__)
|
||||
#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__)
|
||||
#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
|
||||
#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
|
||||
#else /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
#define LOG_BODY(ctxt, level) \
|
||||
{ \
|
||||
va_list args; \
|
||||
|
@ -205,24 +249,26 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
|
|||
usbi_log_v(ctxt, level, "", format, args); \
|
||||
va_end(args); \
|
||||
}
|
||||
#else
|
||||
#define LOG_BODY(ctxt, level) \
|
||||
{ \
|
||||
(void)(ctxt); \
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void usbi_info(struct libusb_context *ctx, const char *format, ...)
|
||||
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO)
|
||||
static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...)
|
||||
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING)
|
||||
static inline void usbi_err(struct libusb_context *ctx, const char *format, ...)
|
||||
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR)
|
||||
|
||||
static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...)
|
||||
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING)
|
||||
static inline void usbi_info(struct libusb_context *ctx, const char *format, ...)
|
||||
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO)
|
||||
static inline void usbi_dbg(const char *format, ...)
|
||||
LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG)
|
||||
|
||||
#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
|
||||
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */
|
||||
|
||||
#else /* ENABLE_LOGGING */
|
||||
|
||||
#define usbi_err(ctx, ...) do { (void)ctx; } while (0)
|
||||
#define usbi_warn(ctx, ...) do { (void)ctx; } while (0)
|
||||
#define usbi_info(ctx, ...) do { (void)ctx; } while (0)
|
||||
#define usbi_dbg(...) do {} while (0)
|
||||
|
||||
#endif /* ENABLE_LOGGING */
|
||||
|
||||
#define USBI_GET_CONTEXT(ctx) \
|
||||
do { \
|
||||
|
@ -254,8 +300,11 @@ extern struct libusb_context *usbi_default_context;
|
|||
struct pollfd;
|
||||
|
||||
struct libusb_context {
|
||||
int debug;
|
||||
#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
|
||||
enum libusb_log_level debug;
|
||||
int debug_fixed;
|
||||
libusb_log_cb log_handler;
|
||||
#endif
|
||||
|
||||
/* internal event pipe, used for signalling occurrence of an internal event. */
|
||||
int event_pipe[2];
|
||||
|
@ -270,6 +319,7 @@ struct libusb_context {
|
|||
|
||||
/* A list of registered hotplug callbacks */
|
||||
struct list_head hotplug_cbs;
|
||||
libusb_hotplug_callback_handle next_hotplug_cb_handle;
|
||||
usbi_mutex_t hotplug_cbs_lock;
|
||||
|
||||
/* this is a list of in-flight transfer handles, sorted by timeout
|
||||
|
@ -331,14 +381,19 @@ struct libusb_context {
|
|||
#endif
|
||||
|
||||
struct list_head list;
|
||||
|
||||
PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
|
||||
};
|
||||
|
||||
enum usbi_event_flags {
|
||||
/* The list of pollfds has been modified */
|
||||
USBI_EVENT_POLLFDS_MODIFIED = 1 << 0,
|
||||
USBI_EVENT_POLLFDS_MODIFIED = 1U << 0,
|
||||
|
||||
/* The user has interrupted the event handler */
|
||||
USBI_EVENT_USER_INTERRUPT = 1 << 1,
|
||||
USBI_EVENT_USER_INTERRUPT = 1U << 1,
|
||||
|
||||
/* A hotplug callback deregistration is pending */
|
||||
USBI_EVENT_HOTPLUG_CB_DEREGISTERED = 1U << 2,
|
||||
};
|
||||
|
||||
/* Macros for managing event handling state */
|
||||
|
@ -383,17 +438,7 @@ struct libusb_device {
|
|||
struct libusb_device_descriptor device_descriptor;
|
||||
int attached;
|
||||
|
||||
unsigned char os_priv
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
[] /* valid C99 code */
|
||||
#else
|
||||
[0] /* non-standard, but usually working code */
|
||||
#endif
|
||||
#if defined(OS_SUNOS)
|
||||
__attribute__ ((aligned (8)));
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
|
||||
};
|
||||
|
||||
struct libusb_device_handle {
|
||||
|
@ -404,17 +449,8 @@ struct libusb_device_handle {
|
|||
struct list_head list;
|
||||
struct libusb_device *dev;
|
||||
int auto_detach_kernel_driver;
|
||||
unsigned char os_priv
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
[] /* valid C99 code */
|
||||
#else
|
||||
[0] /* non-standard, but usually working code */
|
||||
#endif
|
||||
#if defined(OS_SUNOS)
|
||||
__attribute__ ((aligned (8)));
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -459,24 +495,24 @@ struct usbi_transfer {
|
|||
|
||||
enum usbi_transfer_state_flags {
|
||||
/* Transfer successfully submitted by backend */
|
||||
USBI_TRANSFER_IN_FLIGHT = 1 << 0,
|
||||
USBI_TRANSFER_IN_FLIGHT = 1U << 0,
|
||||
|
||||
/* Cancellation was requested via libusb_cancel_transfer() */
|
||||
USBI_TRANSFER_CANCELLING = 1 << 1,
|
||||
USBI_TRANSFER_CANCELLING = 1U << 1,
|
||||
|
||||
/* Operation on the transfer failed because the device disappeared */
|
||||
USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2,
|
||||
USBI_TRANSFER_DEVICE_DISAPPEARED = 1U << 2,
|
||||
};
|
||||
|
||||
enum usbi_transfer_timeout_flags {
|
||||
/* Set by backend submit_transfer() if the OS handles timeout */
|
||||
USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0,
|
||||
USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1U << 0,
|
||||
|
||||
/* The transfer timeout has been handled */
|
||||
USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1,
|
||||
USBI_TRANSFER_TIMEOUT_HANDLED = 1U << 1,
|
||||
|
||||
/* The transfer timeout was successfully processed */
|
||||
USBI_TRANSFER_TIMED_OUT = 1 << 2,
|
||||
USBI_TRANSFER_TIMED_OUT = 1U << 2,
|
||||
};
|
||||
|
||||
#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \
|
||||
|
@ -488,9 +524,10 @@ enum usbi_transfer_timeout_flags {
|
|||
|
||||
static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer)
|
||||
{
|
||||
assert(transfer->num_iso_packets >= 0);
|
||||
return ((unsigned char *)transfer) + sizeof(struct usbi_transfer)
|
||||
+ sizeof(struct libusb_transfer)
|
||||
+ (transfer->num_iso_packets
|
||||
+ ((size_t)transfer->num_iso_packets
|
||||
* sizeof(struct libusb_iso_packet_descriptor));
|
||||
}
|
||||
|
||||
|
@ -540,19 +577,6 @@ int usbi_clear_event(struct libusb_context *ctx);
|
|||
#include "os/poll_windows.h"
|
||||
#endif
|
||||
|
||||
#if (defined(OS_WINDOWS) || defined(OS_WINCE)) && !defined(__GNUC__)
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
int usbi_gettimeofday(struct timeval *tp, void *tzp);
|
||||
#define LIBUSB_GETTIMEOFDAY_WIN32
|
||||
#define HAVE_USBI_GETTIMEOFDAY
|
||||
#else
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
#define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz))
|
||||
#define HAVE_USBI_GETTIMEOFDAY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct usbi_pollfd {
|
||||
/* must come first */
|
||||
struct libusb_pollfd pollfd;
|
||||
|
@ -573,13 +597,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd);
|
|||
struct discovered_devs {
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
struct libusb_device *devices
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
[] /* valid C99 code */
|
||||
#else
|
||||
[0] /* non-standard, but usually working code */
|
||||
#endif
|
||||
;
|
||||
struct libusb_device *devices[ZERO_SIZED_ARRAY];
|
||||
};
|
||||
|
||||
struct discovered_devs *discovered_devs_append(
|
||||
|
@ -612,7 +630,17 @@ struct usbi_os_backend {
|
|||
*
|
||||
* This function is called when the user deinitializes the library.
|
||||
*/
|
||||
void (*exit)(void);
|
||||
void (*exit)(struct libusb_context *ctx);
|
||||
|
||||
/* Set a backend-specific option. Optional.
|
||||
*
|
||||
* This function is called when the user calls libusb_set_option() and
|
||||
* the option is not handled by the core library.
|
||||
*
|
||||
* Return 0 on success, or a LIBUSB_ERROR code on failure.
|
||||
*/
|
||||
int (*set_option)(struct libusb_context *ctx, enum libusb_option option,
|
||||
va_list args);
|
||||
|
||||
/* Enumerate all the USB devices on the system, returning them in a list
|
||||
* of discovered devices.
|
||||
|
@ -685,6 +713,34 @@ struct usbi_os_backend {
|
|||
*/
|
||||
void (*hotplug_poll)(void);
|
||||
|
||||
/* Wrap a platform-specific device handle for I/O and other USB
|
||||
* operations. The device handle is preallocated for you.
|
||||
*
|
||||
* Your backend should allocate any internal resources required for I/O
|
||||
* and other operations so that those operations can happen (hopefully)
|
||||
* without hiccup. This is also a good place to inform libusb that it
|
||||
* should monitor certain file descriptors related to this device -
|
||||
* see the usbi_add_pollfd() function.
|
||||
*
|
||||
* Your backend should also initialize the device structure
|
||||
* (dev_handle->dev), which is NULL at the beginning of the call.
|
||||
*
|
||||
* This function should not generate any bus I/O and should not block.
|
||||
*
|
||||
* This function is called when the user attempts to wrap an existing
|
||||
* platform-specific device handle for a device.
|
||||
*
|
||||
* Return:
|
||||
* - 0 on success
|
||||
* - LIBUSB_ERROR_ACCESS if the user has insufficient permissions
|
||||
* - another LIBUSB_ERROR code on other failure
|
||||
*
|
||||
* Do not worry about freeing the handle on failed open, the upper layers
|
||||
* do this for you.
|
||||
*/
|
||||
int (*wrap_sys_device)(struct libusb_context *ctx,
|
||||
struct libusb_device_handle *dev_handle, intptr_t sys_dev);
|
||||
|
||||
/* Open a device for I/O and other USB operations. The device handle
|
||||
* is preallocated for you, you can retrieve the device in question
|
||||
* through handle->dev.
|
||||
|
@ -1115,6 +1171,11 @@ struct usbi_os_backend {
|
|||
clockid_t (*get_timerfd_clockid)(void);
|
||||
#endif
|
||||
|
||||
/* Number of bytes to reserve for per-context private backend data.
|
||||
* This private data area is accessible through the "os_priv" field of
|
||||
* struct libusb_context. */
|
||||
size_t context_priv_size;
|
||||
|
||||
/* Number of bytes to reserve for per-device private backend data.
|
||||
* This private data area is accessible through the "os_priv" field of
|
||||
* struct libusb_device. */
|
||||
|
@ -1132,21 +1193,7 @@ struct usbi_os_backend {
|
|||
size_t transfer_priv_size;
|
||||
};
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
extern const struct usbi_os_backend * usbi_backend;
|
||||
#else
|
||||
extern const struct usbi_os_backend * const usbi_backend;
|
||||
#endif
|
||||
|
||||
extern const struct usbi_os_backend linux_usbfs_backend;
|
||||
extern const struct usbi_os_backend darwin_backend;
|
||||
extern const struct usbi_os_backend openbsd_backend;
|
||||
extern const struct usbi_os_backend netbsd_backend;
|
||||
extern const struct usbi_os_backend windows_backend;
|
||||
extern const struct usbi_os_backend usbdk_backend;
|
||||
extern const struct usbi_os_backend wince_backend;
|
||||
extern const struct usbi_os_backend haiku_usb_raw_backend;
|
||||
extern const struct usbi_os_backend sunos_backend;
|
||||
extern const struct usbi_os_backend usbi_backend;
|
||||
|
||||
extern struct list_head active_contexts_list;
|
||||
extern usbi_mutex_static_t active_contexts_lock;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* 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
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -20,6 +21,8 @@
|
|||
#if !defined(LIBUSB_DARWIN_H)
|
||||
#define LIBUSB_DARWIN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libusbi.h"
|
||||
|
||||
#include <IOKit/IOTypes.h>
|
||||
|
@ -28,37 +31,58 @@
|
|||
#include <IOKit/IOCFPlugIn.h>
|
||||
|
||||
/* IOUSBInterfaceInferface */
|
||||
#if defined (kIOUSBInterfaceInterfaceID700) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
|
||||
|
||||
/* New in OS 10.12.0. */
|
||||
#if defined (kIOUSBInterfaceInterfaceID800) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface800
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800
|
||||
#define InterfaceVersion 800
|
||||
|
||||
/* New in OS 10.10.0. */
|
||||
#elif defined (kIOUSBInterfaceInterfaceID700) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101000)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface700
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700
|
||||
#define InterfaceVersion 700
|
||||
|
||||
#elif defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
|
||||
/* New in OS 10.9.0. */
|
||||
#elif defined (kIOUSBInterfaceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface650
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID650
|
||||
#define InterfaceVersion 650
|
||||
|
||||
/* New in OS 10.8.2 but can't test deployment target to that granularity, so round up. */
|
||||
#elif defined (kIOUSBInterfaceInterfaceID550) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface550
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550
|
||||
#define InterfaceVersion 550
|
||||
|
||||
#elif defined (kIOUSBInterfaceInterfaceID500)
|
||||
/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */
|
||||
#elif defined (kIOUSBInterfaceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface500
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500
|
||||
#define InterfaceVersion 500
|
||||
|
||||
#elif defined (kIOUSBInterfaceInterfaceID300)
|
||||
/* New in OS 10.5.0. */
|
||||
#elif defined (kIOUSBInterfaceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface300
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300
|
||||
#define InterfaceVersion 300
|
||||
|
||||
#elif defined (kIOUSBInterfaceInterfaceID245)
|
||||
/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */
|
||||
#elif defined (kIOUSBInterfaceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface245
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245
|
||||
#define InterfaceVersion 245
|
||||
|
||||
#elif defined (kIOUSBInterfaceInterfaceID220)
|
||||
/* New in OS 10.4.0. */
|
||||
#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040)
|
||||
|
||||
#define usb_interface_t IOUSBInterfaceInterface220
|
||||
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
|
||||
|
@ -66,43 +90,57 @@
|
|||
|
||||
#else
|
||||
|
||||
#error "IOUSBFamily is too old. Please upgrade your OS"
|
||||
#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
|
||||
|
||||
#endif
|
||||
|
||||
/* IOUSBDeviceInterface */
|
||||
#if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
|
||||
|
||||
/* New in OS 10.9.0. */
|
||||
#if defined (kIOUSBDeviceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
|
||||
|
||||
#define usb_device_t IOUSBDeviceInterface650
|
||||
#define DeviceInterfaceID kIOUSBDeviceInterfaceID650
|
||||
#define DeviceVersion 650
|
||||
|
||||
/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */
|
||||
#elif defined (kIOUSBDeviceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
|
||||
|
||||
#define usb_device_t IOUSBDeviceInterface500
|
||||
#define DeviceInterfaceID kIOUSBDeviceInterfaceID500
|
||||
#define DeviceVersion 500
|
||||
|
||||
#elif defined (kIOUSBDeviceInterfaceID320)
|
||||
/* New in OS 10.5.4 but can't test deployment target to that granularity, so round up. */
|
||||
#elif defined (kIOUSBDeviceInterfaceID320) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
|
||||
|
||||
#define usb_device_t IOUSBDeviceInterface320
|
||||
#define DeviceInterfaceID kIOUSBDeviceInterfaceID320
|
||||
#define DeviceVersion 320
|
||||
|
||||
#elif defined (kIOUSBDeviceInterfaceID300)
|
||||
/* New in OS 10.5.0. */
|
||||
#elif defined (kIOUSBDeviceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
|
||||
|
||||
#define usb_device_t IOUSBDeviceInterface300
|
||||
#define DeviceInterfaceID kIOUSBDeviceInterfaceID300
|
||||
#define DeviceVersion 300
|
||||
|
||||
#elif defined (kIOUSBDeviceInterfaceID245)
|
||||
/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */
|
||||
#elif defined (kIOUSBDeviceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
|
||||
|
||||
#define usb_device_t IOUSBDeviceInterface245
|
||||
#define DeviceInterfaceID kIOUSBDeviceInterfaceID245
|
||||
#define DeviceVersion 245
|
||||
|
||||
#elif defined (kIOUSBDeviceInterfaceID220)
|
||||
/* New in OS 10.2.3 but can't test deployment target to that granularity, so round up. */
|
||||
#elif defined (kIOUSBDeviceInterfaceID197) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030)
|
||||
|
||||
#define usb_device_t IOUSBDeviceInterface197
|
||||
#define DeviceInterfaceID kIOUSBDeviceInterfaceID197
|
||||
#define DeviceVersion 197
|
||||
|
||||
#else
|
||||
|
||||
#error "IOUSBFamily is too old. Please upgrade your OS"
|
||||
#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -120,13 +158,14 @@ struct darwin_cached_device {
|
|||
UInt32 location;
|
||||
UInt64 parent_session;
|
||||
UInt64 session;
|
||||
UInt16 address;
|
||||
USBDeviceAddress address;
|
||||
char sys_path[21];
|
||||
usb_device_t **device;
|
||||
int open_count;
|
||||
UInt8 first_config, active_config, port;
|
||||
int can_enumerate;
|
||||
int refcount;
|
||||
bool in_reenumerate;
|
||||
};
|
||||
|
||||
struct darwin_device_priv {
|
||||
|
@ -134,7 +173,7 @@ struct darwin_device_priv {
|
|||
};
|
||||
|
||||
struct darwin_device_handle_priv {
|
||||
int is_open;
|
||||
bool is_open;
|
||||
CFRunLoopSourceRef cfSource;
|
||||
|
||||
struct darwin_interface {
|
||||
|
|
|
@ -243,7 +243,7 @@ USBDeviceHandle::~USBDeviceHandle()
|
|||
if (fRawFD > 0)
|
||||
close(fRawFD);
|
||||
for(int i = 0; i < 32; i++) {
|
||||
if (fClaimedInterfaces & (1 << i))
|
||||
if (fClaimedInterfaces & (1U << i))
|
||||
ReleaseInterface(i);
|
||||
}
|
||||
delete_sem(fTransfersSem);
|
||||
|
@ -256,7 +256,7 @@ USBDeviceHandle::ClaimInterface(int inumber)
|
|||
{
|
||||
int status = fUSBDevice->ClaimInterface(inumber);
|
||||
if (status == LIBUSB_SUCCESS)
|
||||
fClaimedInterfaces |= (1 << inumber);
|
||||
fClaimedInterfaces |= (1U << inumber);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@ int
|
|||
USBDeviceHandle::ReleaseInterface(int inumber)
|
||||
{
|
||||
fUSBDevice->ReleaseInterface(inumber);
|
||||
fClaimedInterfaces &= ~(1 << inumber);
|
||||
fClaimedInterfaces &= ~(1U << inumber);
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -388,15 +388,15 @@ int USBDevice::ClaimInterface(int interface)
|
|||
{
|
||||
if (interface > ActiveConfiguration()->number_interfaces)
|
||||
return LIBUSB_ERROR_NOT_FOUND;
|
||||
if (fClaimedInterfaces & (1 << interface))
|
||||
if (fClaimedInterfaces & (1U << interface))
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
fClaimedInterfaces |= (1 << interface);
|
||||
fClaimedInterfaces |= (1U << interface);
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
int USBDevice::ReleaseInterface(int interface)
|
||||
{
|
||||
fClaimedInterfaces &= ~(1 << interface);
|
||||
fClaimedInterfaces &= ~(1U << interface);
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
USBRoster gUsbRoster;
|
||||
int32 gInitCount = 0;
|
||||
|
||||
static int haiku_get_config_descriptor(struct libusb_device *, uint8_t,
|
||||
unsigned char *, size_t, int *);
|
||||
|
||||
static int
|
||||
haiku_init(struct libusb_context *ctx)
|
||||
{
|
||||
|
@ -38,8 +41,9 @@ haiku_init(struct libusb_context *ctx)
|
|||
}
|
||||
|
||||
static void
|
||||
haiku_exit(void)
|
||||
haiku_exit(struct libusb_context *ctx)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
if (atomic_add(&gInitCount, -1) == 1)
|
||||
gUsbRoster.Stop();
|
||||
}
|
||||
|
@ -82,12 +86,7 @@ static int
|
|||
haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
|
||||
{
|
||||
USBDevice *dev = *((USBDevice **)device->os_priv);
|
||||
const usb_configuration_descriptor *act_config = dev->ActiveConfiguration();
|
||||
if (len > act_config->total_length)
|
||||
return LIBUSB_ERROR_OVERFLOW;
|
||||
memcpy(buffer, act_config, len);
|
||||
*host_endian = 0;
|
||||
return LIBUSB_SUCCESS;
|
||||
return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len, host_endian);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -99,8 +98,9 @@ haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index,
|
|||
usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
|
||||
return LIBUSB_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (len > config->total_length)
|
||||
if (len > config->total_length) {
|
||||
len = config->total_length;
|
||||
}
|
||||
memcpy(buffer, config, len);
|
||||
*host_endian = 0;
|
||||
return len;
|
||||
|
@ -195,56 +195,59 @@ haiku_clock_gettime(int clkid, struct timespec *tp)
|
|||
return LIBUSB_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
const struct usbi_os_backend haiku_usb_raw_backend = {
|
||||
/*.name =*/ "Haiku usbfs",
|
||||
/*.caps =*/ 0,
|
||||
/*.init =*/ haiku_init,
|
||||
/*.exit =*/ haiku_exit,
|
||||
/*.get_device_list =*/ NULL,
|
||||
/*.hotplug_poll =*/ NULL,
|
||||
/*.open =*/ haiku_open,
|
||||
/*.close =*/ haiku_close,
|
||||
/*.get_device_descriptor =*/ haiku_get_device_descriptor,
|
||||
/*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor,
|
||||
/*.get_config_descriptor =*/ haiku_get_config_descriptor,
|
||||
/*.get_config_descriptor_by_value =*/ NULL,
|
||||
const struct usbi_os_backend usbi_backend = {
|
||||
.name = "Haiku usbfs",
|
||||
.caps = 0,
|
||||
.init = haiku_init,
|
||||
.exit = haiku_exit,
|
||||
.set_option = NULL,
|
||||
.get_device_list = NULL,
|
||||
.hotplug_poll = NULL,
|
||||
.wrap_sys_device = NULL,
|
||||
.open = haiku_open,
|
||||
.close = haiku_close,
|
||||
.get_device_descriptor = haiku_get_device_descriptor,
|
||||
.get_active_config_descriptor = haiku_get_active_config_descriptor,
|
||||
.get_config_descriptor = haiku_get_config_descriptor,
|
||||
.get_config_descriptor_by_value = NULL,
|
||||
|
||||
|
||||
/*.get_configuration =*/ NULL,
|
||||
/*.set_configuration =*/ haiku_set_configuration,
|
||||
/*.claim_interface =*/ haiku_claim_interface,
|
||||
/*.release_interface =*/ haiku_release_interface,
|
||||
.get_configuration = NULL,
|
||||
.set_configuration = haiku_set_configuration,
|
||||
.claim_interface = haiku_claim_interface,
|
||||
.release_interface = haiku_release_interface,
|
||||
|
||||
/*.set_interface_altsetting =*/ haiku_set_altsetting,
|
||||
/*.clear_halt =*/ NULL,
|
||||
/*.reset_device =*/ NULL,
|
||||
.set_interface_altsetting = haiku_set_altsetting,
|
||||
.clear_halt = NULL,
|
||||
.reset_device = NULL,
|
||||
|
||||
/*.alloc_streams =*/ NULL,
|
||||
/*.free_streams =*/ NULL,
|
||||
.alloc_streams = NULL,
|
||||
.free_streams = NULL,
|
||||
|
||||
/*.dev_mem_alloc =*/ NULL,
|
||||
/*.dev_mem_free =*/ NULL,
|
||||
.dev_mem_alloc = NULL,
|
||||
.dev_mem_free = NULL,
|
||||
|
||||
/*.kernel_driver_active =*/ NULL,
|
||||
/*.detach_kernel_driver =*/ NULL,
|
||||
/*.attach_kernel_driver =*/ NULL,
|
||||
.kernel_driver_active = NULL,
|
||||
.detach_kernel_driver = NULL,
|
||||
.attach_kernel_driver = NULL,
|
||||
|
||||
/*.destroy_device =*/ NULL,
|
||||
.destroy_device = NULL,
|
||||
|
||||
/*.submit_transfer =*/ haiku_submit_transfer,
|
||||
/*.cancel_transfer =*/ haiku_cancel_transfer,
|
||||
/*.clear_transfer_priv =*/ haiku_clear_transfer_priv,
|
||||
.submit_transfer = haiku_submit_transfer,
|
||||
.cancel_transfer = haiku_cancel_transfer,
|
||||
.clear_transfer_priv = haiku_clear_transfer_priv,
|
||||
|
||||
/*.handle_events =*/ NULL,
|
||||
/*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
|
||||
.handle_events = NULL,
|
||||
.handle_transfer_completion = haiku_handle_transfer_completion,
|
||||
|
||||
/*.clock_gettime =*/ haiku_clock_gettime,
|
||||
.clock_gettime = haiku_clock_gettime,
|
||||
|
||||
#ifdef USBI_TIMERFD_AVAILABLE
|
||||
/*.get_timerfd_clockid =*/ NULL,
|
||||
.get_timerfd_clockid = NULL,
|
||||
#endif
|
||||
|
||||
/*.device_priv_size =*/ sizeof(USBDevice *),
|
||||
/*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *),
|
||||
/*.transfer_priv_size =*/ sizeof(USBTransfer *),
|
||||
.context_priv_size = 0,
|
||||
.device_priv_size = sizeof(USBDevice *),
|
||||
.device_handle_priv_size = sizeof(USBDeviceHandle *),
|
||||
.transfer_priv_size = sizeof(USBTransfer *),
|
||||
};
|
||||
|
|
|
@ -45,24 +45,33 @@
|
|||
|
||||
#define NL_GROUP_KERNEL 1
|
||||
|
||||
#ifndef SOCK_CLOEXEC
|
||||
#define SOCK_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#ifndef SOCK_NONBLOCK
|
||||
#define SOCK_NONBLOCK 0
|
||||
#endif
|
||||
|
||||
static int linux_netlink_socket = -1;
|
||||
static int netlink_control_pipe[2] = { -1, -1 };
|
||||
static pthread_t libusb_linux_event_thread;
|
||||
|
||||
static void *linux_netlink_event_thread_main(void *arg);
|
||||
|
||||
static int set_fd_cloexec_nb(int fd)
|
||||
static int set_fd_cloexec_nb(int fd, int socktype)
|
||||
{
|
||||
int flags;
|
||||
|
||||
#if defined(FD_CLOEXEC)
|
||||
/* Make sure the netlink socket file descriptor is marked as CLOEXEC */
|
||||
if (!(socktype & SOCK_CLOEXEC)) {
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags == -1) {
|
||||
usbi_err(NULL, "failed to get netlink fd flags (%d)", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(flags & FD_CLOEXEC)) {
|
||||
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
|
||||
usbi_err(NULL, "failed to set netlink fd flags (%d)", errno);
|
||||
return -1;
|
||||
|
@ -70,13 +79,14 @@ static int set_fd_cloexec_nb(int fd)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Make sure the netlink socket is non-blocking */
|
||||
if (!(socktype & SOCK_NONBLOCK)) {
|
||||
flags = fcntl(fd, F_GETFL);
|
||||
if (flags == -1) {
|
||||
usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(flags & O_NONBLOCK)) {
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno);
|
||||
return -1;
|
||||
|
@ -89,21 +99,15 @@ static int set_fd_cloexec_nb(int fd)
|
|||
int linux_netlink_start_event_monitor(void)
|
||||
{
|
||||
struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL };
|
||||
int socktype = SOCK_RAW;
|
||||
int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC;
|
||||
int opt = 1;
|
||||
int ret;
|
||||
|
||||
#if defined(SOCK_CLOEXEC)
|
||||
socktype |= SOCK_CLOEXEC;
|
||||
#endif
|
||||
#if defined(SOCK_NONBLOCK)
|
||||
socktype |= SOCK_NONBLOCK;
|
||||
#endif
|
||||
|
||||
linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
|
||||
if (linux_netlink_socket == -1 && errno == EINVAL) {
|
||||
usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype);
|
||||
linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
|
||||
socktype = SOCK_RAW;
|
||||
linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
|
||||
}
|
||||
|
||||
if (linux_netlink_socket == -1) {
|
||||
|
@ -111,7 +115,7 @@ int linux_netlink_start_event_monitor(void)
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = set_fd_cloexec_nb(linux_netlink_socket);
|
||||
ret = set_fd_cloexec_nb(linux_netlink_socket, socktype);
|
||||
if (ret == -1)
|
||||
goto err_close_socket;
|
||||
|
||||
|
@ -162,7 +166,7 @@ int linux_netlink_stop_event_monitor(void)
|
|||
|
||||
/* Write some dummy data to the control pipe and
|
||||
* wait for the thread to exit */
|
||||
r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
|
||||
r = write(netlink_control_pipe[1], &dummy, sizeof(dummy));
|
||||
if (r <= 0)
|
||||
usbi_warn(NULL, "netlink control pipe signal failed");
|
||||
|
||||
|
@ -356,7 +360,8 @@ static int linux_netlink_read_message(void)
|
|||
static void *linux_netlink_event_thread_main(void *arg)
|
||||
{
|
||||
char dummy;
|
||||
ssize_t r;
|
||||
int r;
|
||||
ssize_t nb;
|
||||
struct pollfd fds[] = {
|
||||
{ .fd = netlink_control_pipe[0],
|
||||
.events = POLLIN },
|
||||
|
@ -368,11 +373,15 @@ static void *linux_netlink_event_thread_main(void *arg)
|
|||
|
||||
usbi_dbg("netlink event thread entering");
|
||||
|
||||
while (poll(fds, 2, -1) >= 0) {
|
||||
while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) {
|
||||
if (r < 0) {
|
||||
/* temporary failure */
|
||||
continue;
|
||||
}
|
||||
if (fds[0].revents & POLLIN) {
|
||||
/* activity on control pipe, read the byte and exit */
|
||||
r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
|
||||
if (r <= 0)
|
||||
nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy));
|
||||
if (nb <= 0)
|
||||
usbi_warn(NULL, "netlink control pipe read failed");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -82,18 +82,34 @@ int linux_udev_start_event_monitor(void)
|
|||
|
||||
udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
|
||||
|
||||
#if defined(FD_CLOEXEC)
|
||||
/* Make sure the udev file descriptor is marked as CLOEXEC */
|
||||
r = fcntl(udev_monitor_fd, F_GETFD);
|
||||
if (r == -1) {
|
||||
usbi_err(NULL, "geting udev monitor fd flags (%d)", errno);
|
||||
goto err_free_monitor;
|
||||
}
|
||||
if (!(r & FD_CLOEXEC)) {
|
||||
if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) {
|
||||
usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
|
||||
goto err_free_monitor;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some older versions of udev are not non-blocking by default,
|
||||
* so make sure this is set */
|
||||
r = fcntl(udev_monitor_fd, F_GETFL);
|
||||
if (r == -1) {
|
||||
usbi_err(NULL, "getting udev monitor fd flags (%d)", errno);
|
||||
usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno);
|
||||
goto err_free_monitor;
|
||||
}
|
||||
r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK);
|
||||
if (r) {
|
||||
usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
|
||||
if (!(r & O_NONBLOCK)) {
|
||||
if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) {
|
||||
usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno);
|
||||
goto err_free_monitor;
|
||||
}
|
||||
}
|
||||
|
||||
r = usbi_pipe(udev_control_pipe);
|
||||
if (r) {
|
||||
|
@ -134,7 +150,7 @@ int linux_udev_stop_event_monitor(void)
|
|||
|
||||
/* Write some dummy data to the control pipe and
|
||||
* wait for the thread to exit */
|
||||
r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy));
|
||||
r = write(udev_control_pipe[1], &dummy, sizeof(dummy));
|
||||
if (r <= 0) {
|
||||
usbi_warn(NULL, "udev control pipe signal failed");
|
||||
}
|
||||
|
@ -162,6 +178,7 @@ static void *linux_udev_event_thread_main(void *arg)
|
|||
{
|
||||
char dummy;
|
||||
int r;
|
||||
ssize_t nb;
|
||||
struct udev_device* udev_dev;
|
||||
struct pollfd fds[] = {
|
||||
{.fd = udev_control_pipe[0],
|
||||
|
@ -172,11 +189,15 @@ static void *linux_udev_event_thread_main(void *arg)
|
|||
|
||||
usbi_dbg("udev event thread entering.");
|
||||
|
||||
while (poll(fds, 2, -1) >= 0) {
|
||||
while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) {
|
||||
if (r < 0) {
|
||||
/* temporary failure */
|
||||
continue;
|
||||
}
|
||||
if (fds[0].revents & POLLIN) {
|
||||
/* activity on control pipe, read the byte and exit */
|
||||
r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy));
|
||||
if (r <= 0) {
|
||||
nb = read(udev_control_pipe[0], &dummy, sizeof(dummy));
|
||||
if (nb <= 0) {
|
||||
usbi_warn(NULL, "udev control pipe read failed");
|
||||
}
|
||||
break;
|
||||
|
@ -211,7 +232,7 @@ static int udev_device_info(struct libusb_context *ctx, int detached,
|
|||
}
|
||||
|
||||
return linux_get_device_address(ctx, detached, busnum, devaddr,
|
||||
dev_node, *sys_name);
|
||||
dev_node, *sys_name, -1);
|
||||
}
|
||||
|
||||
static void udev_hotplug_event(struct udev_device* udev_dev)
|
||||
|
@ -270,6 +291,7 @@ int linux_udev_scan_devices(struct libusb_context *ctx)
|
|||
udev_enumerate_scan_devices(enumerator);
|
||||
devices = udev_enumerate_get_list_entry(enumerator);
|
||||
|
||||
entry = NULL;
|
||||
udev_list_entry_foreach(entry, devices) {
|
||||
const char *path = udev_list_entry_get_name(entry);
|
||||
uint8_t busnum = 0, devaddr = 0;
|
||||
|
|
|
@ -81,6 +81,19 @@ static const char *usbfs_path = NULL;
|
|||
/* use usbdev*.* device names in /dev instead of the usbfs bus directories */
|
||||
static int usbdev_names = 0;
|
||||
|
||||
/* Linux has changed the maximum length of an individual isochronous packet
|
||||
* over time. Initially this limit was 1,023 bytes, but Linux 2.6.18
|
||||
* (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to
|
||||
* 8,192 bytes to support higher bandwidth devices. Linux 3.10
|
||||
* (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this
|
||||
* value to 49,152 bytes to support super speed devices.
|
||||
*/
|
||||
static unsigned int max_iso_packet_len = 0;
|
||||
|
||||
/* Linux 2.6.23 adds support for O_CLOEXEC when opening files, which marks the
|
||||
* close-on-exec flag in the underlying file descriptor. */
|
||||
static int supports_flag_cloexec = -1;
|
||||
|
||||
/* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically
|
||||
* allows us to mark URBs as being part of a specific logical transfer when
|
||||
* we submit them to the kernel. then, on any error except a cancellation, all
|
||||
|
@ -136,6 +149,12 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int);
|
|||
static int linux_default_scan_devices (struct libusb_context *ctx);
|
||||
#endif
|
||||
|
||||
struct kernel_version {
|
||||
int major;
|
||||
int minor;
|
||||
int sublevel;
|
||||
};
|
||||
|
||||
struct linux_device_priv {
|
||||
char *sysfs_dir;
|
||||
unsigned char *descriptors;
|
||||
|
@ -146,6 +165,7 @@ struct linux_device_priv {
|
|||
struct linux_device_handle_priv {
|
||||
int fd;
|
||||
int fd_removed;
|
||||
int fd_keep;
|
||||
uint32_t caps;
|
||||
};
|
||||
|
||||
|
@ -180,6 +200,16 @@ struct linux_transfer_priv {
|
|||
int iso_packet_offset;
|
||||
};
|
||||
|
||||
static int _open(const char *path, int flags)
|
||||
{
|
||||
#if defined(O_CLOEXEC)
|
||||
if (supports_flag_cloexec)
|
||||
return open(path, flags | O_CLOEXEC);
|
||||
else
|
||||
#endif
|
||||
return open(path, flags);
|
||||
}
|
||||
|
||||
static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
|
||||
{
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev);
|
||||
|
@ -194,7 +224,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
|
|||
snprintf(path, PATH_MAX, "%s/%03d/%03d",
|
||||
usbfs_path, dev->bus_number, dev->device_address);
|
||||
|
||||
fd = open(path, mode);
|
||||
fd = _open(path, mode);
|
||||
if (fd != -1)
|
||||
return fd; /* Success */
|
||||
|
||||
|
@ -205,7 +235,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
|
|||
/* Wait 10ms for USB device path creation.*/
|
||||
nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
|
||||
|
||||
fd = open(path, mode);
|
||||
fd = _open(path, mode);
|
||||
if (fd != -1)
|
||||
return fd; /* Success */
|
||||
}
|
||||
|
@ -311,8 +341,10 @@ static const char *find_usbfs_path(void)
|
|||
|
||||
/* On udev based systems without any usb-devices /dev/bus/usb will not
|
||||
* exist. So if we've not found anything and we're using udev for hotplug
|
||||
* simply assume /dev/bus/usb rather then making libusb_init fail. */
|
||||
#if defined(USE_UDEV)
|
||||
* simply assume /dev/bus/usb rather then making libusb_init fail.
|
||||
* Make the same assumption for Android where SELinux policies might block us
|
||||
* from reading /dev on newer devices. */
|
||||
#if defined(USE_UDEV) || defined(__ANDROID__)
|
||||
if (ret == NULL)
|
||||
ret = "/dev/bus/usb";
|
||||
#endif
|
||||
|
@ -342,39 +374,59 @@ static clockid_t find_monotonic_clock(void)
|
|||
return CLOCK_REALTIME;
|
||||
}
|
||||
|
||||
static int kernel_version_ge(int major, int minor, int sublevel)
|
||||
static int get_kernel_version(struct libusb_context *ctx,
|
||||
struct kernel_version *ver)
|
||||
{
|
||||
struct utsname uts;
|
||||
int atoms, kmajor, kminor, ksublevel;
|
||||
int atoms;
|
||||
|
||||
if (uname(&uts) < 0)
|
||||
return -1;
|
||||
atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel);
|
||||
if (atoms < 1)
|
||||
if (uname(&uts) < 0) {
|
||||
usbi_err(ctx, "uname failed, errno %d", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kmajor > major)
|
||||
atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel);
|
||||
if (atoms < 1) {
|
||||
usbi_err(ctx, "failed to parse uname release '%s'", uts.release);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (atoms < 2)
|
||||
ver->minor = -1;
|
||||
if (atoms < 3)
|
||||
ver->sublevel = -1;
|
||||
|
||||
usbi_dbg("reported kernel version is %s", uts.release);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kernel_version_ge(const struct kernel_version *ver,
|
||||
int major, int minor, int sublevel)
|
||||
{
|
||||
if (ver->major > major)
|
||||
return 1;
|
||||
if (kmajor < major)
|
||||
else if (ver->major < major)
|
||||
return 0;
|
||||
|
||||
/* kmajor == major */
|
||||
if (atoms < 2)
|
||||
if (ver->minor == -1 && ver->sublevel == -1)
|
||||
return 0 == minor && 0 == sublevel;
|
||||
if (kminor > minor)
|
||||
else if (ver->minor > minor)
|
||||
return 1;
|
||||
if (kminor < minor)
|
||||
else if (ver->minor < minor)
|
||||
return 0;
|
||||
|
||||
/* kminor == minor */
|
||||
if (atoms < 3)
|
||||
if (ver->sublevel == -1)
|
||||
return 0 == sublevel;
|
||||
|
||||
return ksublevel >= sublevel;
|
||||
return ver->sublevel >= sublevel;
|
||||
}
|
||||
|
||||
static int op_init(struct libusb_context *ctx)
|
||||
{
|
||||
struct kernel_version kversion;
|
||||
struct stat statbuf;
|
||||
int r;
|
||||
|
||||
|
@ -387,13 +439,17 @@ static int op_init(struct libusb_context *ctx)
|
|||
if (monotonic_clkid == -1)
|
||||
monotonic_clkid = find_monotonic_clock();
|
||||
|
||||
if (get_kernel_version(ctx, &kversion) < 0)
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
|
||||
if (supports_flag_cloexec == -1) {
|
||||
/* O_CLOEXEC flag available from Linux 2.6.23 */
|
||||
supports_flag_cloexec = kernel_version_ge(&kversion,2,6,23);
|
||||
}
|
||||
|
||||
if (supports_flag_bulk_continuation == -1) {
|
||||
/* bulk continuation URB flag available from Linux 2.6.32 */
|
||||
supports_flag_bulk_continuation = kernel_version_ge(2,6,32);
|
||||
if (supports_flag_bulk_continuation == -1) {
|
||||
usbi_err(ctx, "error checking for bulk continuation support");
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
supports_flag_bulk_continuation = kernel_version_ge(&kversion,2,6,32);
|
||||
}
|
||||
|
||||
if (supports_flag_bulk_continuation)
|
||||
|
@ -401,32 +457,31 @@ static int op_init(struct libusb_context *ctx)
|
|||
|
||||
if (-1 == supports_flag_zero_packet) {
|
||||
/* zero length packet URB flag fixed since Linux 2.6.31 */
|
||||
supports_flag_zero_packet = kernel_version_ge(2,6,31);
|
||||
if (-1 == supports_flag_zero_packet) {
|
||||
usbi_err(ctx, "error checking for zero length packet support");
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
supports_flag_zero_packet = kernel_version_ge(&kversion,2,6,31);
|
||||
}
|
||||
|
||||
if (supports_flag_zero_packet)
|
||||
usbi_dbg("zero length packet flag supported");
|
||||
|
||||
if (!max_iso_packet_len) {
|
||||
if (kernel_version_ge(&kversion,3,10,0))
|
||||
max_iso_packet_len = 49152;
|
||||
else if (kernel_version_ge(&kversion,2,6,18))
|
||||
max_iso_packet_len = 8192;
|
||||
else
|
||||
max_iso_packet_len = 1023;
|
||||
}
|
||||
|
||||
usbi_dbg("max iso packet length is (likely) %u bytes", max_iso_packet_len);
|
||||
|
||||
if (-1 == sysfs_has_descriptors) {
|
||||
/* sysfs descriptors has all descriptors since Linux 2.6.26 */
|
||||
sysfs_has_descriptors = kernel_version_ge(2,6,26);
|
||||
if (-1 == sysfs_has_descriptors) {
|
||||
usbi_err(ctx, "error checking for sysfs descriptors");
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
sysfs_has_descriptors = kernel_version_ge(&kversion,2,6,26);
|
||||
}
|
||||
|
||||
if (-1 == sysfs_can_relate_devices) {
|
||||
/* sysfs has busnum since Linux 2.6.22 */
|
||||
sysfs_can_relate_devices = kernel_version_ge(2,6,22);
|
||||
if (-1 == sysfs_can_relate_devices) {
|
||||
usbi_err(ctx, "error checking for sysfs busnum");
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
sysfs_can_relate_devices = kernel_version_ge(&kversion,2,6,22);
|
||||
}
|
||||
|
||||
if (sysfs_can_relate_devices || sysfs_has_descriptors) {
|
||||
|
@ -463,8 +518,9 @@ static int op_init(struct libusb_context *ctx)
|
|||
return r;
|
||||
}
|
||||
|
||||
static void op_exit(void)
|
||||
static void op_exit(struct libusb_context *ctx)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
|
||||
assert(init_count != 0);
|
||||
if (!--init_count) {
|
||||
|
@ -478,8 +534,10 @@ static int linux_start_event_monitor(void)
|
|||
{
|
||||
#if defined(USE_UDEV)
|
||||
return linux_udev_start_event_monitor();
|
||||
#else
|
||||
#elif !defined(__ANDROID__)
|
||||
return linux_netlink_start_event_monitor();
|
||||
#else
|
||||
return LIBUSB_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -487,20 +545,22 @@ static int linux_stop_event_monitor(void)
|
|||
{
|
||||
#if defined(USE_UDEV)
|
||||
return linux_udev_stop_event_monitor();
|
||||
#else
|
||||
#elif !defined(__ANDROID__)
|
||||
return linux_netlink_stop_event_monitor();
|
||||
#else
|
||||
return LIBUSB_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int linux_scan_devices(struct libusb_context *ctx)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
usbi_mutex_static_lock(&linux_hotplug_lock);
|
||||
|
||||
#if defined(USE_UDEV)
|
||||
ret = linux_udev_scan_devices(ctx);
|
||||
#else
|
||||
#elif !defined(__ANDROID__)
|
||||
ret = linux_default_scan_devices(ctx);
|
||||
#endif
|
||||
|
||||
|
@ -513,7 +573,7 @@ static void op_hotplug_poll(void)
|
|||
{
|
||||
#if defined(USE_UDEV)
|
||||
linux_udev_hotplug_poll();
|
||||
#else
|
||||
#elif !defined(__ANDROID__)
|
||||
linux_netlink_hotplug_poll();
|
||||
#endif
|
||||
}
|
||||
|
@ -526,7 +586,7 @@ static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
|
|||
|
||||
snprintf(filename, PATH_MAX, "%s/%s/%s",
|
||||
SYSFS_DEVICE_PATH, priv->sysfs_dir, attr);
|
||||
fd = open(filename, O_RDONLY);
|
||||
fd = _open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
usbi_err(DEVICE_CTX(dev),
|
||||
"open %s failed ret=%d errno=%d", filename, fd, errno);
|
||||
|
@ -542,12 +602,12 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
|
|||
{
|
||||
char filename[PATH_MAX];
|
||||
FILE *f;
|
||||
int r, value;
|
||||
int fd, r, value;
|
||||
|
||||
snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH,
|
||||
devname, attr);
|
||||
f = fopen(filename, "r");
|
||||
if (f == NULL) {
|
||||
fd = _open(filename, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
/* File doesn't exist. Assume the device has been
|
||||
disconnected (see trac ticket #70). */
|
||||
|
@ -557,6 +617,13 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
|
|||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
|
||||
f = fdopen(fd, "r");
|
||||
if (f == NULL) {
|
||||
usbi_err(ctx, "fdopen %s failed errno=%d", filename, errno);
|
||||
close(fd);
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
|
||||
r = fscanf(f, "%d", &value);
|
||||
fclose(f);
|
||||
if (r != 1) {
|
||||
|
@ -576,7 +643,7 @@ static int op_get_device_descriptor(struct libusb_device *dev,
|
|||
{
|
||||
struct linux_device_priv *priv = _device_priv(dev);
|
||||
|
||||
*host_endian = sysfs_has_descriptors ? 0 : 1;
|
||||
*host_endian = (priv->sysfs_dir && sysfs_has_descriptors) ? 0 : 1;
|
||||
memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH);
|
||||
|
||||
return 0;
|
||||
|
@ -627,14 +694,23 @@ static int sysfs_get_active_config(struct libusb_device *dev, int *config)
|
|||
|
||||
int linux_get_device_address (struct libusb_context *ctx, int detached,
|
||||
uint8_t *busnum, uint8_t *devaddr,const char *dev_node,
|
||||
const char *sys_name)
|
||||
const char *sys_name, int fd)
|
||||
{
|
||||
char proc_path[PATH_MAX], fd_path[PATH_MAX];
|
||||
int sysfs_attr;
|
||||
ssize_t r;
|
||||
|
||||
usbi_dbg("getting address for device: %s detached: %d", sys_name, detached);
|
||||
/* can't use sysfs to read the bus and device number if the
|
||||
* device has been detached */
|
||||
if (!sysfs_can_relate_devices || detached || NULL == sys_name) {
|
||||
if (NULL == dev_node && fd >= 0) {
|
||||
/* try to retrieve the device node from fd */
|
||||
snprintf(proc_path, PATH_MAX, "/proc/self/fd/%d", fd);
|
||||
r = readlink(proc_path, fd_path, PATH_MAX);
|
||||
if (r > 0)
|
||||
dev_node = fd_path;
|
||||
}
|
||||
if (NULL == dev_node) {
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
|
@ -644,6 +720,8 @@ int linux_get_device_address (struct libusb_context *ctx, int detached,
|
|||
sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
|
||||
} else if (!strncmp(dev_node, "/proc/bus/usb", 13)) {
|
||||
sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr);
|
||||
} else {
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
|
@ -696,9 +774,11 @@ static int seek_to_next_descriptor(struct libusb_context *ctx,
|
|||
}
|
||||
|
||||
/* Return offset to next config */
|
||||
static int seek_to_next_config(struct libusb_context *ctx,
|
||||
static int seek_to_next_config(struct libusb_device *dev,
|
||||
unsigned char *buffer, int size)
|
||||
{
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev);
|
||||
struct linux_device_priv *priv = _device_priv(dev);
|
||||
struct libusb_config_descriptor config;
|
||||
|
||||
if (size == 0)
|
||||
|
@ -725,7 +805,7 @@ static int seek_to_next_config(struct libusb_context *ctx,
|
|||
* config descriptor with verified bLength fields, with descriptors
|
||||
* with an invalid bLength removed.
|
||||
*/
|
||||
if (sysfs_has_descriptors) {
|
||||
if (priv->sysfs_dir && sysfs_has_descriptors) {
|
||||
int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG,
|
||||
buffer, size);
|
||||
if (next == LIBUSB_ERROR_NOT_FOUND)
|
||||
|
@ -754,7 +834,6 @@ static int seek_to_next_config(struct libusb_context *ctx,
|
|||
static int op_get_config_descriptor_by_value(struct libusb_device *dev,
|
||||
uint8_t value, unsigned char **buffer, int *host_endian)
|
||||
{
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev);
|
||||
struct linux_device_priv *priv = _device_priv(dev);
|
||||
unsigned char *descriptors = priv->descriptors;
|
||||
int size = priv->descriptors_len;
|
||||
|
@ -770,7 +849,7 @@ static int op_get_config_descriptor_by_value(struct libusb_device *dev,
|
|||
|
||||
/* Seek till the config is found, or till "EOF" */
|
||||
while (1) {
|
||||
int next = seek_to_next_config(ctx, descriptors, size);
|
||||
int next = seek_to_next_config(dev, descriptors, size);
|
||||
if (next < 0)
|
||||
return next;
|
||||
config = (struct libusb_config_descriptor *)descriptors;
|
||||
|
@ -786,16 +865,16 @@ static int op_get_config_descriptor_by_value(struct libusb_device *dev,
|
|||
static int op_get_active_config_descriptor(struct libusb_device *dev,
|
||||
unsigned char *buffer, size_t len, int *host_endian)
|
||||
{
|
||||
struct linux_device_priv *priv = _device_priv(dev);
|
||||
int r, config;
|
||||
unsigned char *config_desc;
|
||||
|
||||
if (sysfs_can_relate_devices) {
|
||||
if (priv->sysfs_dir && sysfs_can_relate_devices) {
|
||||
r = sysfs_get_active_config(dev, &config);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
/* Use cached bConfigurationValue */
|
||||
struct linux_device_priv *priv = _device_priv(dev);
|
||||
config = priv->active_config;
|
||||
}
|
||||
if (config == -1)
|
||||
|
@ -806,7 +885,7 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
len = MIN(len, r);
|
||||
len = MIN(len, (size_t)r);
|
||||
memcpy(buffer, config_desc, len);
|
||||
return len;
|
||||
}
|
||||
|
@ -827,7 +906,7 @@ static int op_get_config_descriptor(struct libusb_device *dev,
|
|||
|
||||
/* Seek till the config is found, or till "EOF" */
|
||||
for (i = 0; ; i++) {
|
||||
r = seek_to_next_config(DEVICE_CTX(dev), descriptors, size);
|
||||
r = seek_to_next_config(dev, descriptors, size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (i == config_index)
|
||||
|
@ -836,7 +915,7 @@ static int op_get_config_descriptor(struct libusb_device *dev,
|
|||
descriptors += r;
|
||||
}
|
||||
|
||||
len = MIN(len, r);
|
||||
len = MIN(len, (size_t)r);
|
||||
memcpy(buffer, descriptors, len);
|
||||
return len;
|
||||
}
|
||||
|
@ -886,7 +965,7 @@ static int usbfs_get_active_config(struct libusb_device *dev, int fd)
|
|||
}
|
||||
|
||||
static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
||||
uint8_t devaddr, const char *sysfs_dir)
|
||||
uint8_t devaddr, const char *sysfs_dir, int wrapped_fd)
|
||||
{
|
||||
struct linux_device_priv *priv = _device_priv(dev);
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev);
|
||||
|
@ -911,6 +990,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|||
case 12: dev->speed = LIBUSB_SPEED_FULL; break;
|
||||
case 480: dev->speed = LIBUSB_SPEED_HIGH; break;
|
||||
case 5000: dev->speed = LIBUSB_SPEED_SUPER; break;
|
||||
case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
|
||||
default:
|
||||
usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed);
|
||||
}
|
||||
|
@ -918,10 +998,18 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|||
}
|
||||
|
||||
/* cache descriptors in memory */
|
||||
if (sysfs_has_descriptors)
|
||||
if (sysfs_dir && sysfs_has_descriptors) {
|
||||
fd = _open_sysfs_attr(dev, "descriptors");
|
||||
else
|
||||
} else if (wrapped_fd < 0) {
|
||||
fd = _get_usbfs_fd(dev, O_RDONLY, 0);
|
||||
} else {
|
||||
fd = wrapped_fd;
|
||||
r = lseek(fd, 0, SEEK_SET);
|
||||
if (r < 0) {
|
||||
usbi_err(ctx, "seek failed ret=%d errno=%d", r, errno);
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
}
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
|
@ -930,11 +1018,12 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|||
priv->descriptors = usbi_reallocf(priv->descriptors,
|
||||
descriptors_size);
|
||||
if (!priv->descriptors) {
|
||||
if (fd != wrapped_fd)
|
||||
close(fd);
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
/* usbfs has holes in the file */
|
||||
if (!sysfs_has_descriptors) {
|
||||
if (!(sysfs_dir && sysfs_has_descriptors)) {
|
||||
memset(priv->descriptors + priv->descriptors_len,
|
||||
0, descriptors_size - priv->descriptors_len);
|
||||
}
|
||||
|
@ -943,12 +1032,14 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|||
if (r < 0) {
|
||||
usbi_err(ctx, "read descriptor failed ret=%d errno=%d",
|
||||
fd, errno);
|
||||
if (fd != wrapped_fd)
|
||||
close(fd);
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
priv->descriptors_len += r;
|
||||
} while (priv->descriptors_len == descriptors_size);
|
||||
|
||||
if (fd != wrapped_fd)
|
||||
close(fd);
|
||||
|
||||
if (priv->descriptors_len < DEVICE_DESC_LENGTH) {
|
||||
|
@ -957,11 +1048,14 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
|
||||
if (sysfs_can_relate_devices)
|
||||
if (sysfs_dir && sysfs_can_relate_devices)
|
||||
return LIBUSB_SUCCESS;
|
||||
|
||||
/* cache active config */
|
||||
if (wrapped_fd < 0)
|
||||
fd = _get_usbfs_fd(dev, O_RDWR, 1);
|
||||
else
|
||||
fd = wrapped_fd;
|
||||
if (fd < 0) {
|
||||
/* cannot send a control message to determine the active
|
||||
* config. just assume the first one is active. */
|
||||
|
@ -981,6 +1075,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|||
}
|
||||
|
||||
r = usbfs_get_active_config(dev, fd);
|
||||
if (wrapped_fd < 0)
|
||||
close(fd);
|
||||
|
||||
return r;
|
||||
|
@ -1029,11 +1124,13 @@ retry:
|
|||
usbi_mutex_lock(&ctx->usb_devs_lock);
|
||||
list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) {
|
||||
struct linux_device_priv *priv = _device_priv(it);
|
||||
if (priv->sysfs_dir) {
|
||||
if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) {
|
||||
dev->parent_dev = libusb_ref_device(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
usbi_mutex_unlock(&ctx->usb_devs_lock);
|
||||
|
||||
if (!dev->parent_dev && add_parent) {
|
||||
|
@ -1080,7 +1177,7 @@ int linux_enumerate_device(struct libusb_context *ctx,
|
|||
if (!dev)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
|
||||
r = initialize_device(dev, busnum, devaddr, sysfs_dir);
|
||||
r = initialize_device(dev, busnum, devaddr, sysfs_dir, -1);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
r = usbi_sanitize_device(dev);
|
||||
|
@ -1223,7 +1320,7 @@ static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
|
|||
uint8_t busnum, devaddr;
|
||||
int ret;
|
||||
|
||||
ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname);
|
||||
ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname, -1);
|
||||
if (LIBUSB_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1237,11 +1334,12 @@ static int sysfs_get_device_list(struct libusb_context *ctx)
|
|||
{
|
||||
DIR *devices = opendir(SYSFS_DEVICE_PATH);
|
||||
struct dirent *entry;
|
||||
int r = LIBUSB_ERROR_IO;
|
||||
int num_devices = 0;
|
||||
int num_enumerated = 0;
|
||||
|
||||
if (!devices) {
|
||||
usbi_err(ctx, "opendir devices failed errno=%d", errno);
|
||||
return r;
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
|
||||
while ((entry = readdir(devices))) {
|
||||
|
@ -1249,16 +1347,23 @@ static int sysfs_get_device_list(struct libusb_context *ctx)
|
|||
|| strchr(entry->d_name, ':'))
|
||||
continue;
|
||||
|
||||
num_devices++;
|
||||
|
||||
if (sysfs_scan_device(ctx, entry->d_name)) {
|
||||
usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
num_enumerated++;
|
||||
}
|
||||
|
||||
closedir(devices);
|
||||
return r;
|
||||
|
||||
/* successful if at least one device was enumerated or no devices were found */
|
||||
if (num_enumerated || !num_devices)
|
||||
return LIBUSB_SUCCESS;
|
||||
else
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
|
||||
static int linux_default_scan_devices (struct libusb_context *ctx)
|
||||
|
@ -1280,28 +1385,14 @@ static int linux_default_scan_devices (struct libusb_context *ctx)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int op_open(struct libusb_device_handle *handle)
|
||||
static int initialize_handle(struct libusb_device_handle *handle, int fd)
|
||||
{
|
||||
struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
|
||||
int r;
|
||||
|
||||
hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
|
||||
if (hpriv->fd < 0) {
|
||||
if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) {
|
||||
/* device will still be marked as attached if hotplug monitor thread
|
||||
* hasn't processed remove event yet */
|
||||
usbi_mutex_static_lock(&linux_hotplug_lock);
|
||||
if (handle->dev->attached) {
|
||||
usbi_dbg("open failed with no device, but device still attached");
|
||||
linux_device_disconnected(handle->dev->bus_number,
|
||||
handle->dev->device_address);
|
||||
}
|
||||
usbi_mutex_static_unlock(&linux_hotplug_lock);
|
||||
}
|
||||
return hpriv->fd;
|
||||
}
|
||||
hpriv->fd = fd;
|
||||
|
||||
r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
|
||||
r = ioctl(fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
|
||||
if (r < 0) {
|
||||
if (errno == ENOTTY)
|
||||
usbi_dbg("getcap not available");
|
||||
|
@ -1314,9 +1405,82 @@ static int op_open(struct libusb_device_handle *handle)
|
|||
hpriv->caps |= USBFS_CAP_BULK_CONTINUATION;
|
||||
}
|
||||
|
||||
r = usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
|
||||
return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
|
||||
}
|
||||
|
||||
static int op_wrap_sys_device(struct libusb_context *ctx,
|
||||
struct libusb_device_handle *handle, intptr_t sys_dev)
|
||||
{
|
||||
struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
|
||||
int fd = (int)sys_dev;
|
||||
uint8_t busnum, devaddr;
|
||||
struct usbfs_connectinfo ci;
|
||||
struct libusb_device *dev;
|
||||
int r;
|
||||
|
||||
r = linux_get_device_address(ctx, 1, &busnum, &devaddr, NULL, NULL, fd);
|
||||
if (r < 0) {
|
||||
r = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci);
|
||||
if (r < 0) {
|
||||
usbi_err(ctx, "connectinfo failed (%d)", errno);
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
/* There is no ioctl to get the bus number. We choose 0 here
|
||||
* as linux starts numbering buses from 1. */
|
||||
busnum = 0;
|
||||
devaddr = ci.devnum;
|
||||
}
|
||||
|
||||
/* Session id is unused as we do not add the device to the list of
|
||||
* connected devices. */
|
||||
usbi_dbg("allocating new device for fd %d", fd);
|
||||
dev = usbi_alloc_device(ctx, 0);
|
||||
if (!dev)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
|
||||
r = initialize_device(dev, busnum, devaddr, NULL, fd);
|
||||
if (r < 0)
|
||||
close(hpriv->fd);
|
||||
goto out;
|
||||
r = usbi_sanitize_device(dev);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
/* Consider the device as connected, but do not add it to the managed
|
||||
* device list. */
|
||||
dev->attached = 1;
|
||||
handle->dev = dev;
|
||||
|
||||
r = initialize_handle(handle, fd);
|
||||
hpriv->fd_keep = 1;
|
||||
|
||||
out:
|
||||
if (r < 0)
|
||||
libusb_unref_device(dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int op_open(struct libusb_device_handle *handle)
|
||||
{
|
||||
int fd, r;
|
||||
|
||||
fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
|
||||
if (fd < 0) {
|
||||
if (fd == LIBUSB_ERROR_NO_DEVICE) {
|
||||
/* device will still be marked as attached if hotplug monitor thread
|
||||
* hasn't processed remove event yet */
|
||||
usbi_mutex_static_lock(&linux_hotplug_lock);
|
||||
if (handle->dev->attached) {
|
||||
usbi_dbg("open failed with no device, but device still attached");
|
||||
linux_device_disconnected(handle->dev->bus_number,
|
||||
handle->dev->device_address);
|
||||
}
|
||||
usbi_mutex_static_unlock(&linux_hotplug_lock);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
r = initialize_handle(handle, fd);
|
||||
if (r < 0)
|
||||
close(fd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1327,21 +1491,23 @@ static void op_close(struct libusb_device_handle *dev_handle)
|
|||
/* fd may have already been removed by POLLERR condition in op_handle_events() */
|
||||
if (!hpriv->fd_removed)
|
||||
usbi_remove_pollfd(HANDLE_CTX(dev_handle), hpriv->fd);
|
||||
if (!hpriv->fd_keep)
|
||||
close(hpriv->fd);
|
||||
}
|
||||
|
||||
static int op_get_configuration(struct libusb_device_handle *handle,
|
||||
int *config)
|
||||
{
|
||||
struct linux_device_priv *priv = _device_priv(handle->dev);
|
||||
int r;
|
||||
|
||||
if (sysfs_can_relate_devices) {
|
||||
if (priv->sysfs_dir && sysfs_can_relate_devices) {
|
||||
r = sysfs_get_active_config(handle->dev, config);
|
||||
} else {
|
||||
r = usbfs_get_active_config(handle->dev,
|
||||
_device_handle_priv(handle)->fd);
|
||||
if (r == LIBUSB_SUCCESS)
|
||||
*config = _device_priv(handle->dev)->active_config;
|
||||
*config = priv->active_config;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1683,10 +1849,7 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
|
|||
strcpy(dc.driver, "usbfs");
|
||||
dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER;
|
||||
r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc);
|
||||
if (r == 0 || (r != 0 && errno != ENOTTY)) {
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (r != 0 && errno != ENOTTY) {
|
||||
switch (errno) {
|
||||
case EBUSY:
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
|
@ -1698,7 +1861,8 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
|
|||
usbi_err(HANDLE_CTX(handle),
|
||||
"disconnect-and-claim failed errno %d", errno);
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
} else if (r == 0)
|
||||
return 0;
|
||||
|
||||
/* Fallback code for kernels which don't support the
|
||||
disconnect-and-claim ioctl */
|
||||
|
@ -1971,38 +2135,43 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
|||
struct linux_device_handle_priv *dpriv =
|
||||
_device_handle_priv(transfer->dev_handle);
|
||||
struct usbfs_urb **urbs;
|
||||
size_t alloc_size;
|
||||
int num_packets = transfer->num_iso_packets;
|
||||
int i;
|
||||
int this_urb_len = 0;
|
||||
int num_urbs = 1;
|
||||
int packet_offset = 0;
|
||||
int num_packets_remaining;
|
||||
int i, j;
|
||||
int num_urbs;
|
||||
unsigned int packet_len;
|
||||
unsigned int total_len = 0;
|
||||
unsigned char *urb_buffer = transfer->buffer;
|
||||
|
||||
/* usbfs places arbitrary limits on iso URBs. this limit has changed
|
||||
* at least three times, and it's difficult to accurately detect which
|
||||
* limit this running kernel might impose. so we attempt to submit
|
||||
* whatever the user has provided. if the kernel rejects the request
|
||||
* due to its size, we return an error indicating such to the user.
|
||||
*/
|
||||
if (num_packets < 1)
|
||||
return LIBUSB_ERROR_INVALID_PARAM;
|
||||
|
||||
/* calculate how many URBs we need */
|
||||
/* usbfs places arbitrary limits on iso URBs. this limit has changed
|
||||
* at least three times, but we attempt to detect this limit during
|
||||
* init and check it here. if the kernel rejects the request due to
|
||||
* its size, we return an error indicating such to the user.
|
||||
*/
|
||||
for (i = 0; i < num_packets; i++) {
|
||||
unsigned int space_remaining = MAX_ISO_BUFFER_LENGTH - this_urb_len;
|
||||
packet_len = transfer->iso_packet_desc[i].length;
|
||||
|
||||
if (packet_len > space_remaining) {
|
||||
num_urbs++;
|
||||
this_urb_len = packet_len;
|
||||
/* check that we can actually support this packet length */
|
||||
if (this_urb_len > MAX_ISO_BUFFER_LENGTH)
|
||||
if (packet_len > max_iso_packet_len) {
|
||||
usbi_warn(TRANSFER_CTX(transfer),
|
||||
"iso packet length of %u bytes exceeds maximum of %u bytes",
|
||||
packet_len, max_iso_packet_len);
|
||||
return LIBUSB_ERROR_INVALID_PARAM;
|
||||
} 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));
|
||||
if (!urbs)
|
||||
|
@ -2015,31 +2184,15 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
|||
tpriv->iso_packet_offset = 0;
|
||||
|
||||
/* allocate + initialize each URB with the correct number of packets */
|
||||
for (i = 0; i < num_urbs; i++) {
|
||||
num_packets_remaining = num_packets;
|
||||
for (i = 0, j = 0; i < num_urbs; i++) {
|
||||
int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB);
|
||||
struct usbfs_urb *urb;
|
||||
unsigned int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH;
|
||||
int urb_packet_offset = 0;
|
||||
unsigned char *urb_buffer_orig = urb_buffer;
|
||||
int j;
|
||||
size_t alloc_size;
|
||||
int k;
|
||||
|
||||
/* swallow up all the packets we can fit into this URB */
|
||||
while (packet_offset < transfer->num_iso_packets) {
|
||||
packet_len = transfer->iso_packet_desc[packet_offset].length;
|
||||
if (packet_len <= space_remaining_in_urb) {
|
||||
/* throw it in */
|
||||
urb_packet_offset++;
|
||||
packet_offset++;
|
||||
space_remaining_in_urb -= packet_len;
|
||||
urb_buffer += packet_len;
|
||||
} else {
|
||||
/* it can't fit, save it for the next URB */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
alloc_size = sizeof(*urb)
|
||||
+ (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc));
|
||||
+ (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc));
|
||||
urb = calloc(1, alloc_size);
|
||||
if (!urb) {
|
||||
free_iso_urbs(tpriv);
|
||||
|
@ -2048,10 +2201,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
|||
urbs[i] = urb;
|
||||
|
||||
/* populate packet lengths */
|
||||
for (j = 0, k = packet_offset - urb_packet_offset;
|
||||
k < packet_offset; k++, j++) {
|
||||
packet_len = transfer->iso_packet_desc[k].length;
|
||||
urb->iso_frame_desc[j].length = packet_len;
|
||||
for (k = 0; k < num_packets_in_urb; j++, k++) {
|
||||
packet_len = transfer->iso_packet_desc[j].length;
|
||||
urb->buffer_length += packet_len;
|
||||
urb->iso_frame_desc[k].length = packet_len;
|
||||
}
|
||||
|
||||
urb->usercontext = itransfer;
|
||||
|
@ -2059,8 +2212,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
|||
/* FIXME: interface for non-ASAP data? */
|
||||
urb->flags = USBFS_URB_ISO_ASAP;
|
||||
urb->endpoint = transfer->endpoint;
|
||||
urb->number_of_packets = urb_packet_offset;
|
||||
urb->buffer = urb_buffer_orig;
|
||||
urb->number_of_packets = num_packets_in_urb;
|
||||
urb->buffer = urb_buffer;
|
||||
|
||||
urb_buffer += urb->buffer_length;
|
||||
num_packets_remaining -= num_packets_in_urb;
|
||||
}
|
||||
|
||||
/* submit URBs */
|
||||
|
@ -2073,6 +2229,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
|||
usbi_warn(TRANSFER_CTX(transfer),
|
||||
"submiturb failed, transfer too large");
|
||||
r = LIBUSB_ERROR_INVALID_PARAM;
|
||||
} else if (errno == EMSGSIZE) {
|
||||
usbi_warn(TRANSFER_CTX(transfer),
|
||||
"submiturb failed, iso packet length too large");
|
||||
r = LIBUSB_ERROR_INVALID_PARAM;
|
||||
} else {
|
||||
usbi_err(TRANSFER_CTX(transfer),
|
||||
"submiturb failed error %d errno=%d", r, errno);
|
||||
|
@ -2211,7 +2371,6 @@ static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
|
|||
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
|
||||
|
||||
/* urbs can be freed also in submit_transfer so lock mutex first */
|
||||
switch (transfer->type) {
|
||||
case LIBUSB_TRANSFER_TYPE_CONTROL:
|
||||
case LIBUSB_TRANSFER_TYPE_BULK:
|
||||
|
@ -2557,7 +2716,7 @@ static int reap_for_handle(struct libusb_device_handle *handle)
|
|||
{
|
||||
struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
|
||||
int r;
|
||||
struct usbfs_urb *urb;
|
||||
struct usbfs_urb *urb = NULL;
|
||||
struct usbi_transfer *itransfer;
|
||||
struct libusb_transfer *transfer;
|
||||
|
||||
|
@ -2683,7 +2842,7 @@ static clockid_t op_get_timerfd_clockid(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
const struct usbi_os_backend linux_usbfs_backend = {
|
||||
const struct usbi_os_backend usbi_backend = {
|
||||
.name = "Linux usbfs",
|
||||
.caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
|
||||
.init = op_init,
|
||||
|
@ -2695,6 +2854,7 @@ const struct usbi_os_backend linux_usbfs_backend = {
|
|||
.get_config_descriptor = op_get_config_descriptor,
|
||||
.get_config_descriptor_by_value = op_get_config_descriptor_by_value,
|
||||
|
||||
.wrap_sys_device = op_wrap_sys_device,
|
||||
.open = op_open,
|
||||
.close = op_close,
|
||||
.get_configuration = op_get_configuration,
|
||||
|
|
|
@ -81,10 +81,11 @@ struct usbfs_iso_packet_desc {
|
|||
unsigned int status;
|
||||
};
|
||||
|
||||
#define MAX_ISO_BUFFER_LENGTH 49152 * 128
|
||||
#define MAX_BULK_BUFFER_LENGTH 16384
|
||||
#define MAX_CTRL_BUFFER_LENGTH 4096
|
||||
|
||||
#define MAX_ISO_PACKETS_PER_URB 128
|
||||
|
||||
struct usbfs_urb {
|
||||
unsigned char type;
|
||||
unsigned char endpoint;
|
||||
|
@ -186,7 +187,7 @@ void linux_device_disconnected(uint8_t busnum, uint8_t devaddr);
|
|||
|
||||
int linux_get_device_address (struct libusb_context *ctx, int detached,
|
||||
uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
|
||||
const char *sys_name);
|
||||
const char *sys_name, int fd);
|
||||
int linux_enumerate_device(struct libusb_context *ctx,
|
||||
uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);
|
||||
|
||||
|
|
|
@ -86,11 +86,12 @@ static int _sync_control_transfer(struct usbi_transfer *);
|
|||
static int _sync_gen_transfer(struct usbi_transfer *);
|
||||
static int _access_endpoint(struct libusb_transfer *);
|
||||
|
||||
const struct usbi_os_backend netbsd_backend = {
|
||||
const struct usbi_os_backend usbi_backend = {
|
||||
"Synchronous NetBSD backend",
|
||||
0,
|
||||
NULL, /* init() */
|
||||
NULL, /* exit() */
|
||||
NULL, /* set_option() */
|
||||
netbsd_get_device_list,
|
||||
NULL, /* hotplug_poll */
|
||||
netbsd_open,
|
||||
|
@ -131,6 +132,7 @@ const struct usbi_os_backend netbsd_backend = {
|
|||
netbsd_handle_transfer_completion,
|
||||
|
||||
netbsd_clock_gettime,
|
||||
0, /* context_priv_size */
|
||||
sizeof(struct device_priv),
|
||||
sizeof(struct handle_priv),
|
||||
0, /* transfer_priv_size */
|
||||
|
@ -212,8 +214,9 @@ error:
|
|||
int
|
||||
netbsd_open(struct libusb_device_handle *handle)
|
||||
{
|
||||
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
|
||||
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
|
||||
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
|
||||
int i;
|
||||
|
||||
dpriv->fd = open(dpriv->devnode, O_RDWR);
|
||||
if (dpriv->fd < 0) {
|
||||
|
@ -222,6 +225,9 @@ netbsd_open(struct libusb_device_handle *handle)
|
|||
return _errno_to_libusb(errno);
|
||||
}
|
||||
|
||||
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
|
||||
hpriv->endpoints[i] = -1;
|
||||
|
||||
usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
|
||||
|
||||
return (LIBUSB_SUCCESS);
|
||||
|
@ -230,7 +236,6 @@ netbsd_open(struct libusb_device_handle *handle)
|
|||
void
|
||||
netbsd_close(struct libusb_device_handle *handle)
|
||||
{
|
||||
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
|
||||
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
|
||||
|
||||
usbi_dbg("close: fd %d", dpriv->fd);
|
||||
|
|
|
@ -89,11 +89,12 @@ static int _access_endpoint(struct libusb_transfer *);
|
|||
static int _bus_open(int);
|
||||
|
||||
|
||||
const struct usbi_os_backend openbsd_backend = {
|
||||
const struct usbi_os_backend usbi_backend = {
|
||||
"Synchronous OpenBSD backend",
|
||||
0,
|
||||
NULL, /* init() */
|
||||
NULL, /* exit() */
|
||||
NULL, /* set_option() */
|
||||
obsd_get_device_list,
|
||||
NULL, /* hotplug_poll */
|
||||
obsd_open,
|
||||
|
@ -134,6 +135,7 @@ const struct usbi_os_backend openbsd_backend = {
|
|||
obsd_handle_transfer_completion,
|
||||
|
||||
obsd_clock_gettime,
|
||||
0, /* context_priv_size */
|
||||
sizeof(struct device_priv),
|
||||
sizeof(struct handle_priv),
|
||||
0, /* transfer_priv_size */
|
||||
|
@ -246,7 +248,6 @@ obsd_get_device_list(struct libusb_context * ctx,
|
|||
int
|
||||
obsd_open(struct libusb_device_handle *handle)
|
||||
{
|
||||
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
|
||||
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
|
||||
char devnode[16];
|
||||
|
||||
|
@ -270,7 +271,6 @@ obsd_open(struct libusb_device_handle *handle)
|
|||
void
|
||||
obsd_close(struct libusb_device_handle *handle)
|
||||
{
|
||||
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
|
||||
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
|
||||
|
||||
if (dpriv->devname) {
|
||||
|
|
|
@ -29,25 +29,56 @@
|
|||
|
||||
int usbi_pipe(int pipefd[2])
|
||||
{
|
||||
#if defined(HAVE_PIPE2)
|
||||
int ret = pipe2(pipefd, O_CLOEXEC);
|
||||
#else
|
||||
int ret = pipe(pipefd);
|
||||
#endif
|
||||
|
||||
if (ret != 0) {
|
||||
usbi_err(NULL, "failed to create pipe (%d)", errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(HAVE_PIPE2) && defined(FD_CLOEXEC)
|
||||
ret = fcntl(pipefd[0], F_GETFD);
|
||||
if (ret == -1) {
|
||||
usbi_err(NULL, "failed to get pipe fd flags (%d)", errno);
|
||||
goto err_close_pipe;
|
||||
}
|
||||
ret = fcntl(pipefd[0], F_SETFD, ret | FD_CLOEXEC);
|
||||
if (ret == -1) {
|
||||
usbi_err(NULL, "failed to set pipe fd flags (%d)", errno);
|
||||
goto err_close_pipe;
|
||||
}
|
||||
|
||||
ret = fcntl(pipefd[1], F_GETFD);
|
||||
if (ret == -1) {
|
||||
usbi_err(NULL, "failed to get pipe fd flags (%d)", errno);
|
||||
goto err_close_pipe;
|
||||
}
|
||||
ret = fcntl(pipefd[1], F_SETFD, ret | FD_CLOEXEC);
|
||||
if (ret == -1) {
|
||||
usbi_err(NULL, "failed to set pipe fd flags (%d)", errno);
|
||||
goto err_close_pipe;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = fcntl(pipefd[1], F_GETFL);
|
||||
if (ret == -1) {
|
||||
usbi_dbg("Failed to get pipe fd flags: %d", errno);
|
||||
usbi_err(NULL, "failed to get pipe fd status flags (%d)", errno);
|
||||
goto err_close_pipe;
|
||||
}
|
||||
ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK);
|
||||
if (ret != 0) {
|
||||
usbi_dbg("Failed to set non-blocking on new pipe: %d", errno);
|
||||
if (ret == -1) {
|
||||
usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno);
|
||||
goto err_close_pipe;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_close_pipe:
|
||||
usbi_close(pipefd[0]);
|
||||
usbi_close(pipefd[1]);
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -8,4 +8,7 @@
|
|||
|
||||
int usbi_pipe(int pipefd[2]);
|
||||
|
||||
#define usbi_inc_fds_ref(x, y)
|
||||
#define usbi_dec_fds_ref(x, y)
|
||||
|
||||
#endif /* LIBUSB_POLL_POSIX_H */
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
/*
|
||||
* poll_windows: poll compatibility wrapper for Windows
|
||||
* Copyright © 2012-2013 RealVNC Ltd.
|
||||
* 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.
|
||||
* Copyright © 2017 Chris Dickens <christopher.a.dickens@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -31,9 +28,6 @@
|
|||
* - obtain a Windows HANDLE to a file or device that has been opened in
|
||||
* OVERLAPPED mode
|
||||
* - call usbi_create_fd with this handle to obtain a custom fd.
|
||||
* Note that if you need simultaneous R/W access, you need to call create_fd
|
||||
* twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate
|
||||
* pollable fds
|
||||
* - leave the core functions call the poll routine and flag POLLIN/POLLOUT
|
||||
*
|
||||
* The pipe pollable synchronous I/O works using the overlapped event associated
|
||||
|
@ -42,465 +36,176 @@
|
|||
*/
|
||||
#include <config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libusbi.h"
|
||||
|
||||
// Uncomment to debug the polling layer
|
||||
//#define DEBUG_POLL_WINDOWS
|
||||
#if defined(DEBUG_POLL_WINDOWS)
|
||||
#define poll_dbg usbi_dbg
|
||||
#else
|
||||
// MSVC++ < 2005 cannot use a variadic argument and non MSVC
|
||||
// compilers produce warnings if parenthesis are omitted.
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1400)
|
||||
#define poll_dbg
|
||||
#else
|
||||
#define poll_dbg(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_PREFAST_)
|
||||
#pragma warning(disable:28719)
|
||||
#endif
|
||||
|
||||
#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
|
||||
#include "windows_common.h"
|
||||
|
||||
// public fd data
|
||||
const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
|
||||
struct winfd poll_fd[MAX_FDS];
|
||||
// internal fd data
|
||||
struct {
|
||||
CRITICAL_SECTION mutex; // lock for fds
|
||||
// Additional variables for XP CancelIoEx partial emulation
|
||||
HANDLE original_handle;
|
||||
DWORD thread_id;
|
||||
} _poll_fd[MAX_FDS];
|
||||
const struct winfd INVALID_WINFD = { -1, NULL };
|
||||
|
||||
// globals
|
||||
BOOLEAN is_polling_set = FALSE;
|
||||
LONG pipe_number = 0;
|
||||
static volatile LONG compat_spinlock = 0;
|
||||
// private data
|
||||
struct file_descriptor {
|
||||
enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
|
||||
OVERLAPPED overlapped;
|
||||
int refcount;
|
||||
};
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
// CancelIoEx, available on Vista and later only, provides the ability to cancel
|
||||
// a single transfer (OVERLAPPED) when used. As it may not be part of any of the
|
||||
// platform headers, we hook into the Kernel32 system DLL directly to seek it.
|
||||
static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
|
||||
#define Use_Duplicate_Handles (pCancelIoEx == NULL)
|
||||
static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
|
||||
static struct file_descriptor *fd_table[MAX_FDS];
|
||||
|
||||
static inline void setup_cancel_io(void)
|
||||
static struct file_descriptor *create_fd(enum fd_type type)
|
||||
{
|
||||
HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
|
||||
if (hKernel32 != NULL) {
|
||||
pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
|
||||
GetProcAddress(hKernel32, "CancelIoEx");
|
||||
}
|
||||
usbi_dbg("Will use CancelIo%s for I/O cancellation",
|
||||
Use_Duplicate_Handles?"":"Ex");
|
||||
}
|
||||
|
||||
static inline BOOL cancel_io(int _index)
|
||||
{
|
||||
if ((_index < 0) || (_index >= MAX_FDS)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
|
||||
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
|
||||
return TRUE;
|
||||
}
|
||||
if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
|
||||
// Cancel outstanding transfer via the specific callback
|
||||
(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
|
||||
return TRUE;
|
||||
}
|
||||
if (pCancelIoEx != NULL) {
|
||||
return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
|
||||
}
|
||||
if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
|
||||
return CancelIo(poll_fd[_index].handle);
|
||||
}
|
||||
usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
#define Use_Duplicate_Handles FALSE
|
||||
|
||||
static __inline void setup_cancel_io()
|
||||
{
|
||||
// No setup needed on WinCE
|
||||
}
|
||||
|
||||
static __inline BOOL cancel_io(int _index)
|
||||
{
|
||||
if ((_index < 0) || (_index >= MAX_FDS)) {
|
||||
return FALSE;
|
||||
}
|
||||
if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
|
||||
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
|
||||
return TRUE;
|
||||
}
|
||||
if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
|
||||
// Cancel outstanding transfer via the specific callback
|
||||
(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Init
|
||||
void init_polling(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
|
||||
SleepEx(0, TRUE);
|
||||
}
|
||||
if (!is_polling_set) {
|
||||
setup_cancel_io();
|
||||
for (i=0; 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) {
|
||||
struct file_descriptor *fd = calloc(1, sizeof(*fd));
|
||||
if (fd == NULL)
|
||||
return NULL;
|
||||
fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (fd->overlapped.hEvent == NULL) {
|
||||
free(fd);
|
||||
return NULL;
|
||||
}
|
||||
overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if(overlapped->hEvent == NULL) {
|
||||
free (overlapped);
|
||||
return NULL;
|
||||
}
|
||||
return overlapped;
|
||||
fd->type = type;
|
||||
fd->refcount = 1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void free_overlapped(OVERLAPPED *overlapped)
|
||||
static void free_fd(struct file_descriptor *fd)
|
||||
{
|
||||
if (overlapped == NULL)
|
||||
return;
|
||||
|
||||
if ( (overlapped->hEvent != 0)
|
||||
&& (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
|
||||
CloseHandle(overlapped->hEvent);
|
||||
}
|
||||
free(overlapped);
|
||||
}
|
||||
|
||||
void exit_polling(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
|
||||
SleepEx(0, TRUE);
|
||||
}
|
||||
if (is_polling_set) {
|
||||
is_polling_set = FALSE;
|
||||
|
||||
for (i=0; 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);
|
||||
CloseHandle(fd->overlapped.hEvent);
|
||||
free(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a fake pipe.
|
||||
* As libusb only uses pipes for signaling, all we need from a pipe is an
|
||||
* event. To that extent, we create a single wfd and overlapped as a means
|
||||
* to access that event.
|
||||
*/
|
||||
int usbi_pipe(int filedes[2])
|
||||
{
|
||||
int i;
|
||||
OVERLAPPED* overlapped;
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
|
||||
overlapped = create_overlapped();
|
||||
|
||||
if (overlapped == NULL) {
|
||||
return -1;
|
||||
}
|
||||
// The overlapped must have status pending for signaling to work in poll
|
||||
overlapped->Internal = STATUS_PENDING;
|
||||
overlapped->InternalHigh = 0;
|
||||
|
||||
for (i=0; i<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
|
||||
* Create both an fd and an OVERLAPPED, so that it can be used with our
|
||||
* polling function
|
||||
* The handle MUST support overlapped transfers (usually requires CreateFile
|
||||
* with FILE_FLAG_OVERLAPPED)
|
||||
* Return a pollable file descriptor struct, or INVALID_WINFD on error
|
||||
*
|
||||
* Note that the fd returned by this function is a per-transfer fd, rather
|
||||
* than a per-session fd and cannot be used for anything else but our
|
||||
* custom functions (the fd itself points to the NUL: device)
|
||||
* custom functions.
|
||||
* if you plan to do R/W on the same handle, you MUST create 2 fds: one for
|
||||
* read and one for write. Using a single R/W fd is unsupported and will
|
||||
* produce unexpected results
|
||||
*/
|
||||
struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
|
||||
struct winfd usbi_create_fd(void)
|
||||
{
|
||||
int i;
|
||||
struct winfd wfd = INVALID_WINFD;
|
||||
OVERLAPPED* overlapped = NULL;
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
|
||||
if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
|
||||
return INVALID_WINFD;
|
||||
}
|
||||
|
||||
wfd.itransfer = itransfer;
|
||||
wfd.cancel_fn = cancel_fn;
|
||||
|
||||
if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
|
||||
usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. "
|
||||
"If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
|
||||
return INVALID_WINFD;
|
||||
}
|
||||
if (access_mode == RW_READ) {
|
||||
wfd.rw = RW_READ;
|
||||
} else {
|
||||
wfd.rw = RW_WRITE;
|
||||
}
|
||||
|
||||
overlapped = create_overlapped();
|
||||
if(overlapped == NULL) {
|
||||
return INVALID_WINFD;
|
||||
}
|
||||
|
||||
for (i=0; i<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 file_descriptor *fd;
|
||||
struct winfd wfd;
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
|
||||
if (fd < 0)
|
||||
fd = create_fd(FD_TYPE_TRANSFER);
|
||||
if (fd == NULL)
|
||||
return INVALID_WINFD;
|
||||
|
||||
for (i=0; i<MAX_FDS; i++) {
|
||||
if (poll_fd[i].fd == fd) {
|
||||
EnterCriticalSection(&_poll_fd[i].mutex);
|
||||
// fd might have been deleted before we got to critical
|
||||
if (poll_fd[i].fd != fd) {
|
||||
LeaveCriticalSection(&_poll_fd[i].mutex);
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) {
|
||||
if (fd_table[wfd.fd] != NULL)
|
||||
continue;
|
||||
fd_table[wfd.fd] = fd;
|
||||
break;
|
||||
}
|
||||
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
|
||||
LeaveCriticalSection(&_poll_fd[i].mutex);
|
||||
return wfd;
|
||||
}
|
||||
}
|
||||
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;
|
||||
struct winfd wfd;
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
|
||||
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;
|
||||
int n;
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
for (n = 0; n < nfds; ++n) {
|
||||
fd_table[fds[n].fd]->refcount++;
|
||||
}
|
||||
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;
|
||||
struct winfd wfd;
|
||||
int n;
|
||||
struct file_descriptor *fd;
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
|
||||
if (overlapped == NULL)
|
||||
return INVALID_WINFD;
|
||||
|
||||
for (i=0; i<MAX_FDS; i++) {
|
||||
if (poll_fd[i].overlapped == overlapped) {
|
||||
EnterCriticalSection(&_poll_fd[i].mutex);
|
||||
// fd might have been deleted before we got to critical
|
||||
if (poll_fd[i].overlapped != overlapped) {
|
||||
LeaveCriticalSection(&_poll_fd[i].mutex);
|
||||
continue;
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
for (n = 0; n < nfds; ++n) {
|
||||
fd = fd_table[fds[n].fd];
|
||||
fd->refcount--;
|
||||
if (fd->refcount == 0)
|
||||
{
|
||||
if (fd->type == FD_TYPE_PIPE) {
|
||||
// InternalHigh is our reference count
|
||||
fd->overlapped.InternalHigh--;
|
||||
if (fd->overlapped.InternalHigh == 0)
|
||||
free_fd(fd);
|
||||
}
|
||||
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
|
||||
LeaveCriticalSection(&_poll_fd[i].mutex);
|
||||
return wfd;
|
||||
else {
|
||||
free_fd(fd);
|
||||
}
|
||||
fd_table[fds[n].fd] = NULL;
|
||||
}
|
||||
}
|
||||
return INVALID_WINFD;
|
||||
usbi_mutex_static_unlock(&fd_table_lock);
|
||||
}
|
||||
|
||||
|
||||
static int check_pollfds(struct pollfd *fds, unsigned int nfds,
|
||||
HANDLE *wait_handles, DWORD *nb_wait_handles)
|
||||
{
|
||||
struct file_descriptor *fd;
|
||||
unsigned int n;
|
||||
int nready = 0;
|
||||
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
|
||||
for (n = 0; n < nfds; ++n) {
|
||||
fds[n].revents = 0;
|
||||
|
||||
// Keep it simple - only allow either POLLIN *or* POLLOUT
|
||||
assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT));
|
||||
if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) {
|
||||
fds[n].revents = POLLNVAL;
|
||||
nready++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS))
|
||||
fd = fd_table[fds[n].fd];
|
||||
else
|
||||
fd = NULL;
|
||||
|
||||
assert(fd != NULL);
|
||||
if (fd == NULL) {
|
||||
fds[n].revents = POLLNVAL;
|
||||
nready++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (HasOverlappedIoCompleted(&fd->overlapped)
|
||||
&& (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) {
|
||||
fds[n].revents = fds[n].events;
|
||||
nready++;
|
||||
} else if (wait_handles != NULL) {
|
||||
if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) {
|
||||
usbi_warn(NULL, "too many HANDLEs to wait on");
|
||||
continue;
|
||||
}
|
||||
wait_handles[*nb_wait_handles] = fd->overlapped.hEvent;
|
||||
(*nb_wait_handles)++;
|
||||
}
|
||||
}
|
||||
|
||||
usbi_mutex_static_unlock(&fd_table_lock);
|
||||
|
||||
return nready;
|
||||
}
|
||||
/*
|
||||
* POSIX poll equivalent, using Windows OVERLAPPED
|
||||
* Currently, this function only accepts one of POLLIN or POLLOUT per fd
|
||||
|
@ -508,143 +213,121 @@ struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
|
|||
*/
|
||||
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
|
||||
{
|
||||
unsigned i;
|
||||
int _index, object_index, triggered;
|
||||
HANDLE *handles_to_wait_on;
|
||||
int *handle_to_index;
|
||||
DWORD nb_handles_to_wait_on = 0;
|
||||
HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
|
||||
DWORD nb_wait_handles = 0;
|
||||
DWORD ret;
|
||||
int nready;
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
|
||||
triggered = 0;
|
||||
handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE)); // +1 for fd_update
|
||||
handle_to_index = (int*) calloc(nfds, sizeof(int));
|
||||
if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
|
||||
errno = ENOMEM;
|
||||
triggered = -1;
|
||||
goto poll_exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < nfds; ++i) {
|
||||
fds[i].revents = 0;
|
||||
|
||||
// Only one of POLLIN or POLLOUT can be selected with this version of poll (not both)
|
||||
if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
|
||||
fds[i].revents |= POLLERR;
|
||||
errno = EACCES;
|
||||
usbi_warn(NULL, "unsupported set of events");
|
||||
triggered = -1;
|
||||
goto poll_exit;
|
||||
}
|
||||
|
||||
_index = _fd_to_index_and_lock(fds[i].fd);
|
||||
poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);
|
||||
|
||||
if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
|
||||
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
|
||||
fds[i].revents |= POLLNVAL | POLLERR;
|
||||
errno = EBADF;
|
||||
if (_index >= 0) {
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
}
|
||||
usbi_warn(NULL, "invalid fd");
|
||||
triggered = -1;
|
||||
goto poll_exit;
|
||||
}
|
||||
|
||||
// IN or OUT must match our fd direction
|
||||
if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
|
||||
fds[i].revents |= POLLNVAL | POLLERR;
|
||||
errno = EBADF;
|
||||
usbi_warn(NULL, "attempted POLLIN on fd without READ access");
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
triggered = -1;
|
||||
goto poll_exit;
|
||||
}
|
||||
|
||||
if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
|
||||
fds[i].revents |= POLLNVAL | POLLERR;
|
||||
errno = EBADF;
|
||||
usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
triggered = -1;
|
||||
goto poll_exit;
|
||||
}
|
||||
|
||||
// The following macro only works if overlapped I/O was reported pending
|
||||
if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
|
||||
|| (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
|
||||
poll_dbg(" completed");
|
||||
// checks above should ensure this works:
|
||||
fds[i].revents = fds[i].events;
|
||||
triggered++;
|
||||
} else {
|
||||
handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
|
||||
handle_to_index[nb_handles_to_wait_on] = i;
|
||||
nb_handles_to_wait_on++;
|
||||
}
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
}
|
||||
nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles);
|
||||
|
||||
// If nothing was triggered, wait on all fds that require it
|
||||
if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
|
||||
if (timeout < 0) {
|
||||
poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on);
|
||||
} else {
|
||||
poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on);
|
||||
}
|
||||
ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
|
||||
FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
|
||||
object_index = ret-WAIT_OBJECT_0;
|
||||
if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
|
||||
poll_dbg(" completed after wait");
|
||||
i = handle_to_index[object_index];
|
||||
_index = _fd_to_index_and_lock(fds[i].fd);
|
||||
fds[i].revents = fds[i].events;
|
||||
triggered++;
|
||||
if (_index >= 0) {
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
}
|
||||
} else if (ret == WAIT_TIMEOUT) {
|
||||
poll_dbg(" timed out");
|
||||
triggered = 0; // 0 = timeout
|
||||
} else {
|
||||
errno = EIO;
|
||||
triggered = -1; // error
|
||||
if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) {
|
||||
ret = WaitForMultipleObjects(nb_wait_handles, wait_handles,
|
||||
FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout);
|
||||
if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) {
|
||||
nready = check_pollfds(fds, nfds, NULL, NULL);
|
||||
} else if (ret != WAIT_TIMEOUT) {
|
||||
if (ret == WAIT_FAILED)
|
||||
usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError());
|
||||
nready = -1;
|
||||
}
|
||||
}
|
||||
|
||||
poll_exit:
|
||||
if (handles_to_wait_on != NULL) {
|
||||
free(handles_to_wait_on);
|
||||
}
|
||||
if (handle_to_index != NULL) {
|
||||
free(handle_to_index);
|
||||
}
|
||||
return triggered;
|
||||
return nready;
|
||||
}
|
||||
|
||||
/*
|
||||
* close a fake pipe fd
|
||||
* close a fake file descriptor
|
||||
*/
|
||||
int usbi_close(int fd)
|
||||
int usbi_close(int _fd)
|
||||
{
|
||||
int _index;
|
||||
int r = -1;
|
||||
struct file_descriptor *fd;
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
if (_fd < 0 || _fd >= MAX_FDS)
|
||||
goto err_badfd;
|
||||
|
||||
_index = _fd_to_index_and_lock(fd);
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
fd = fd_table[_fd];
|
||||
fd->refcount--;
|
||||
if(fd->refcount==0)
|
||||
{ fd_table[_fd] = NULL;
|
||||
|
||||
if (_index < 0) {
|
||||
errno = EBADF;
|
||||
} else {
|
||||
free_overlapped(poll_fd[_index].overlapped);
|
||||
poll_fd[_index] = INVALID_WINFD;
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
if (fd->type == FD_TYPE_PIPE) {
|
||||
// InternalHigh is our reference count
|
||||
fd->overlapped.InternalHigh--;
|
||||
if (fd->overlapped.InternalHigh == 0)
|
||||
free_fd(fd);
|
||||
}
|
||||
return r;
|
||||
else {
|
||||
free_fd(fd);
|
||||
}
|
||||
}
|
||||
usbi_mutex_static_unlock(&fd_table_lock);
|
||||
|
||||
if (fd == NULL)
|
||||
goto err_badfd;
|
||||
|
||||
return 0;
|
||||
|
||||
err_badfd:
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a fake pipe.
|
||||
* As libusb only uses pipes for signaling, all we need from a pipe is an
|
||||
* event. To that extent, we create a single wfd and overlapped as a means
|
||||
* to access that event.
|
||||
*/
|
||||
int usbi_pipe(int filedes[2])
|
||||
{
|
||||
struct file_descriptor *fd;
|
||||
int r_fd = -1, w_fd = -1;
|
||||
int i;
|
||||
|
||||
fd = create_fd(FD_TYPE_PIPE);
|
||||
if (fd == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Use InternalHigh as a reference count
|
||||
fd->overlapped.Internal = STATUS_PENDING;
|
||||
fd->overlapped.InternalHigh = 2;
|
||||
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
do {
|
||||
for (i = 0; i < MAX_FDS; i++) {
|
||||
if (fd_table[i] != NULL)
|
||||
continue;
|
||||
if (r_fd == -1) {
|
||||
r_fd = i;
|
||||
} else if (w_fd == -1) {
|
||||
w_fd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAX_FDS)
|
||||
break;
|
||||
|
||||
fd_table[r_fd] = fd;
|
||||
fd_table[w_fd] = fd;
|
||||
|
||||
} while (0);
|
||||
usbi_mutex_static_unlock(&fd_table_lock);
|
||||
|
||||
if (i == MAX_FDS) {
|
||||
free_fd(fd);
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
filedes[0] = r_fd;
|
||||
filedes[1] = w_fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -652,35 +335,37 @@ int usbi_close(int fd)
|
|||
*/
|
||||
ssize_t usbi_write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
int _index;
|
||||
int error = EBADF;
|
||||
|
||||
UNUSED(buf);
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
if (fd < 0 || fd >= MAX_FDS)
|
||||
goto err_out;
|
||||
|
||||
if (count != sizeof(unsigned char)) {
|
||||
usbi_err(NULL, "this function should only used for signaling");
|
||||
return -1;
|
||||
error = EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
_index = _fd_to_index_and_lock(fd);
|
||||
|
||||
if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
|
||||
errno = EBADF;
|
||||
if (_index >= 0) {
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
}
|
||||
return -1;
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
|
||||
assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING);
|
||||
assert(fd_table[fd]->overlapped.InternalHigh == 2);
|
||||
fd_table[fd]->overlapped.Internal = STATUS_WAIT_0;
|
||||
SetEvent(fd_table[fd]->overlapped.hEvent);
|
||||
error = 0;
|
||||
}
|
||||
usbi_mutex_static_unlock(&fd_table_lock);
|
||||
|
||||
poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId());
|
||||
SetEvent(poll_fd[_index].overlapped->hEvent);
|
||||
poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
|
||||
// If two threads write on the pipe at the same time, we need to
|
||||
// process two separate reads => use the overlapped as a counter
|
||||
poll_fd[_index].overlapped->InternalHigh++;
|
||||
if (error)
|
||||
goto err_out;
|
||||
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
return sizeof(unsigned char);
|
||||
|
||||
err_out:
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -688,41 +373,35 @@ ssize_t usbi_write(int fd, const void *buf, size_t count)
|
|||
*/
|
||||
ssize_t usbi_read(int fd, void *buf, size_t count)
|
||||
{
|
||||
int _index;
|
||||
ssize_t r = -1;
|
||||
int error = EBADF;
|
||||
|
||||
UNUSED(buf);
|
||||
|
||||
CHECK_INIT_POLLING;
|
||||
if (fd < 0 || fd >= MAX_FDS)
|
||||
goto err_out;
|
||||
|
||||
if (count != sizeof(unsigned char)) {
|
||||
usbi_err(NULL, "this function should only used for signaling");
|
||||
error = EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
usbi_mutex_static_lock(&fd_table_lock);
|
||||
if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
|
||||
assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0);
|
||||
assert(fd_table[fd]->overlapped.InternalHigh == 2);
|
||||
fd_table[fd]->overlapped.Internal = STATUS_PENDING;
|
||||
ResetEvent(fd_table[fd]->overlapped.hEvent);
|
||||
error = 0;
|
||||
}
|
||||
usbi_mutex_static_unlock(&fd_table_lock);
|
||||
|
||||
if (error)
|
||||
goto err_out;
|
||||
|
||||
return sizeof(unsigned char);
|
||||
|
||||
err_out:
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_index = _fd_to_index_and_lock(fd);
|
||||
|
||||
if (_index < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
|
||||
usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError());
|
||||
errno = EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId());
|
||||
poll_fd[_index].overlapped->InternalHigh--;
|
||||
// Don't reset unless we don't have any more events to process
|
||||
if (poll_fd[_index].overlapped->InternalHigh <= 0) {
|
||||
ResetEvent(poll_fd[_index].overlapped->hEvent);
|
||||
poll_fd[_index].overlapped->Internal = STATUS_PENDING;
|
||||
}
|
||||
|
||||
r = sizeof(unsigned char);
|
||||
|
||||
out:
|
||||
LeaveCriticalSection(&_poll_fd[_index].mutex);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Windows compat: POSIX compatibility wrapper
|
||||
* Copyright © 2012-2013 RealVNC Ltd.
|
||||
* 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.
|
||||
* Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
|
||||
*
|
||||
|
@ -40,21 +41,6 @@
|
|||
|
||||
#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
|
||||
|
||||
/* Windows versions */
|
||||
enum windows_version {
|
||||
WINDOWS_CE = -2,
|
||||
WINDOWS_UNDEFINED = -1,
|
||||
WINDOWS_UNSUPPORTED = 0,
|
||||
WINDOWS_XP = 0x51,
|
||||
WINDOWS_2003 = 0x52, // Also XP x64
|
||||
WINDOWS_VISTA = 0x60,
|
||||
WINDOWS_7 = 0x61,
|
||||
WINDOWS_8 = 0x62,
|
||||
WINDOWS_8_1_OR_LATER = 0x63,
|
||||
WINDOWS_MAX
|
||||
};
|
||||
extern int windows_version;
|
||||
|
||||
#define MAX_FDS 256
|
||||
|
||||
#define POLLIN 0x0001 /* There is data to read */
|
||||
|
@ -70,40 +56,23 @@ struct pollfd {
|
|||
short revents; /* returned events */
|
||||
};
|
||||
|
||||
// access modes
|
||||
enum rw_type {
|
||||
RW_NONE,
|
||||
RW_READ,
|
||||
RW_WRITE,
|
||||
};
|
||||
|
||||
// fd struct that can be used for polling on Windows
|
||||
typedef int cancel_transfer(struct usbi_transfer *itransfer);
|
||||
|
||||
struct winfd {
|
||||
int fd; // what's exposed to libusb core
|
||||
HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it
|
||||
OVERLAPPED* overlapped; // what will report our I/O status
|
||||
struct usbi_transfer *itransfer; // Associated transfer, or NULL if completed
|
||||
cancel_transfer *cancel_fn; // Function pointer to cancel transfer API
|
||||
enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH)
|
||||
OVERLAPPED *overlapped; // what will report our I/O status
|
||||
};
|
||||
|
||||
extern const struct winfd INVALID_WINFD;
|
||||
|
||||
struct winfd usbi_create_fd(void);
|
||||
|
||||
int usbi_pipe(int pipefd[2]);
|
||||
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout);
|
||||
ssize_t usbi_write(int fd, const void *buf, size_t count);
|
||||
ssize_t usbi_read(int fd, void *buf, size_t count);
|
||||
int usbi_close(int fd);
|
||||
|
||||
void init_polling(void);
|
||||
void exit_polling(void);
|
||||
struct winfd usbi_create_fd(HANDLE handle, int access_mode,
|
||||
struct usbi_transfer *transfer, cancel_transfer *cancel_fn);
|
||||
void usbi_free_fd(struct winfd* winfd);
|
||||
struct winfd fd_to_winfd(int fd);
|
||||
struct winfd handle_to_winfd(HANDLE handle);
|
||||
struct winfd overlapped_to_winfd(OVERLAPPED* overlapped);
|
||||
int usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds);
|
||||
int usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds);
|
||||
|
||||
/*
|
||||
* Timeval operations
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/list.h>
|
||||
#include <sys/stat.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
@ -28,21 +29,34 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wait.h>
|
||||
#include <unistd.h>
|
||||
#include <aio.h>
|
||||
#include <libdevinfo.h>
|
||||
#include <sys/nvpair.h>
|
||||
#include <sys/devctl.h>
|
||||
#include <sys/usb/clients/ugen/usb_ugen.h>
|
||||
#include <errno.h>
|
||||
#include <sys/usb/usba.h>
|
||||
#include <sys/pci.h>
|
||||
|
||||
#include "libusbi.h"
|
||||
#include "sunos_usb.h"
|
||||
|
||||
#define UPDATEDRV_PATH "/usr/sbin/update_drv"
|
||||
#define UPDATEDRV "update_drv"
|
||||
|
||||
typedef list_t string_list_t;
|
||||
typedef struct string_node {
|
||||
char *string;
|
||||
list_node_t link;
|
||||
} string_node_t;
|
||||
|
||||
/*
|
||||
* Backend functions
|
||||
*/
|
||||
static int sunos_init(struct libusb_context *);
|
||||
static void sunos_exit(void);
|
||||
static void sunos_exit(struct libusb_context *);
|
||||
static int sunos_get_device_list(struct libusb_context *,
|
||||
struct discovered_devs **);
|
||||
static int sunos_open(struct libusb_device_handle *);
|
||||
|
@ -67,6 +81,162 @@ static int sunos_cancel_transfer(struct usbi_transfer *);
|
|||
static void sunos_clear_transfer_priv(struct usbi_transfer *);
|
||||
static int sunos_handle_transfer_completion(struct usbi_transfer *);
|
||||
static int sunos_clock_gettime(int, struct timespec *);
|
||||
static int sunos_kernel_driver_active(struct libusb_device_handle *, int interface);
|
||||
static int sunos_detach_kernel_driver (struct libusb_device_handle *dev, int interface_number);
|
||||
static int sunos_attach_kernel_driver (struct libusb_device_handle *dev, int interface_number);
|
||||
static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv);
|
||||
static int sunos_usb_ioctl(struct libusb_device *dev, int cmd);
|
||||
|
||||
static struct devctl_iocdata iocdata;
|
||||
static int sunos_get_link(di_devlink_t devlink, void *arg)
|
||||
{
|
||||
walk_link_t *larg = (walk_link_t *)arg;
|
||||
const char *p;
|
||||
const char *q;
|
||||
|
||||
if (larg->path) {
|
||||
char *content = (char *)di_devlink_content(devlink);
|
||||
char *start = strstr(content, "/devices/");
|
||||
start += strlen("/devices");
|
||||
usbi_dbg("%s", start);
|
||||
|
||||
/* line content must have minor node */
|
||||
if (start == NULL ||
|
||||
strncmp(start, larg->path, larg->len) != 0 ||
|
||||
start[larg->len] != ':')
|
||||
return (DI_WALK_CONTINUE);
|
||||
}
|
||||
|
||||
p = di_devlink_path(devlink);
|
||||
q = strrchr(p, '/');
|
||||
usbi_dbg("%s", q);
|
||||
|
||||
*(larg->linkpp) = strndup(p, strlen(p) - strlen(q));
|
||||
|
||||
return (DI_WALK_TERMINATE);
|
||||
}
|
||||
|
||||
|
||||
static int sunos_physpath_to_devlink(
|
||||
const char *node_path, const char *match, char **link_path)
|
||||
{
|
||||
walk_link_t larg;
|
||||
di_devlink_handle_t hdl;
|
||||
|
||||
*link_path = NULL;
|
||||
larg.linkpp = link_path;
|
||||
if ((hdl = di_devlink_init(NULL, 0)) == NULL) {
|
||||
usbi_dbg("di_devlink_init failure");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
larg.len = strlen(node_path);
|
||||
larg.path = (char *)node_path;
|
||||
|
||||
(void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK,
|
||||
(void *)&larg, sunos_get_link);
|
||||
|
||||
(void) di_devlink_fini(&hdl);
|
||||
|
||||
if (*link_path == NULL) {
|
||||
usbi_dbg("there is no devlink for this path");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunos_usb_ioctl(struct libusb_device *dev, int cmd)
|
||||
{
|
||||
int fd;
|
||||
nvlist_t *nvlist;
|
||||
char *end;
|
||||
char *phypath;
|
||||
char *hubpath;
|
||||
char path_arg[PATH_MAX];
|
||||
sunos_dev_priv_t *dpriv;
|
||||
devctl_ap_state_t devctl_ap_state;
|
||||
|
||||
dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
||||
phypath = dpriv->phypath;
|
||||
|
||||
end = strrchr(phypath, '/');
|
||||
if (end == NULL)
|
||||
return (-1);
|
||||
hubpath = strndup(phypath, end - phypath);
|
||||
if (hubpath == NULL)
|
||||
return (-1);
|
||||
|
||||
end = strrchr(hubpath, '@');
|
||||
if (end == NULL) {
|
||||
free(hubpath);
|
||||
return (-1);
|
||||
}
|
||||
end++;
|
||||
usbi_dbg("unitaddr: %s", end);
|
||||
|
||||
nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
|
||||
nvlist_add_int32(nvlist, "port", dev->port_number);
|
||||
//find the hub path
|
||||
snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath);
|
||||
usbi_dbg("ioctl hub path: %s", path_arg);
|
||||
|
||||
fd = open(path_arg, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
usbi_err(DEVICE_CTX(dev), "open failed: %d (%s)", errno, strerror(errno));
|
||||
nvlist_free(nvlist);
|
||||
free(hubpath);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset(&iocdata, 0, sizeof(iocdata));
|
||||
memset(&devctl_ap_state, 0, sizeof(devctl_ap_state));
|
||||
|
||||
nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0);
|
||||
|
||||
iocdata.cmd = DEVCTL_AP_GETSTATE;
|
||||
iocdata.flags = 0;
|
||||
iocdata.c_nodename = "hub";
|
||||
iocdata.c_unitaddr = end;
|
||||
iocdata.cpyout_buf = &devctl_ap_state;
|
||||
usbi_dbg("%p, %d", iocdata.nvl_user, iocdata.nvl_usersz);
|
||||
|
||||
errno = 0;
|
||||
if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) {
|
||||
usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
|
||||
fd, DEVCTL_AP_GETSTATE, errno, strerror(errno));
|
||||
} else {
|
||||
usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate);
|
||||
usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
iocdata.cmd = cmd;
|
||||
if (ioctl(fd, (int)cmd, &iocdata) != 0) {
|
||||
usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
|
||||
fd, cmd, errno, strerror(errno));
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
free(iocdata.nvl_user);
|
||||
nvlist_free(nvlist);
|
||||
free(hubpath);
|
||||
|
||||
return (-errno);
|
||||
}
|
||||
|
||||
static int
|
||||
sunos_kernel_driver_active(struct libusb_device_handle *dev, int interface)
|
||||
{
|
||||
sunos_dev_priv_t *dpriv;
|
||||
dpriv = (sunos_dev_priv_t *)dev->dev->os_priv;
|
||||
|
||||
usbi_dbg("%s", dpriv->ugenpath);
|
||||
|
||||
return (dpriv->ugenpath == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private functions
|
||||
|
@ -79,20 +249,239 @@ static int sunos_init(struct libusb_context *ctx)
|
|||
return (LIBUSB_SUCCESS);
|
||||
}
|
||||
|
||||
static void sunos_exit(void)
|
||||
static void sunos_exit(struct libusb_context *ctx)
|
||||
{
|
||||
usbi_dbg("");
|
||||
}
|
||||
|
||||
static string_list_t *
|
||||
sunos_new_string_list(void)
|
||||
{
|
||||
string_list_t *list;
|
||||
|
||||
list = calloc(1, sizeof(*list));
|
||||
if (list != NULL)
|
||||
list_create(list, sizeof(string_node_t),
|
||||
offsetof(string_node_t, link));
|
||||
|
||||
return (list);
|
||||
}
|
||||
|
||||
static int
|
||||
sunos_append_to_string_list(string_list_t *list, const char *arg)
|
||||
{
|
||||
string_node_t *np;
|
||||
|
||||
np = calloc(1, sizeof(*np));
|
||||
if (!np)
|
||||
return (-1);
|
||||
|
||||
np->string = strdup(arg);
|
||||
if (!np->string) {
|
||||
free(np);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
list_insert_tail(list, np);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
sunos_free_string_list(string_list_t *list)
|
||||
{
|
||||
string_node_t *np;
|
||||
|
||||
while ((np = list_remove_head(list)) != NULL) {
|
||||
free(np->string);
|
||||
free(np);
|
||||
}
|
||||
|
||||
free(list);
|
||||
}
|
||||
|
||||
static char **
|
||||
sunos_build_argv_list(string_list_t *list)
|
||||
{
|
||||
char **argv_list;
|
||||
string_node_t *np;
|
||||
int n;
|
||||
|
||||
n = 1; /* Start at 1 for NULL terminator */
|
||||
for (np = list_head(list); np != NULL; np = list_next(list, np))
|
||||
n++;
|
||||
|
||||
argv_list = calloc(n, sizeof(char *));
|
||||
if (argv_list == NULL)
|
||||
return NULL;
|
||||
|
||||
n = 0;
|
||||
for (np = list_head(list); np != NULL; np = list_next(list, np))
|
||||
argv_list[n++] = np->string;
|
||||
|
||||
return (argv_list);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sunos_exec_command(struct libusb_context *ctx, const char *path,
|
||||
string_list_t *list)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
int waitstat;
|
||||
int exit_status;
|
||||
char **argv_list;
|
||||
|
||||
argv_list = sunos_build_argv_list(list);
|
||||
if (argv_list == NULL)
|
||||
return (-1);
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
execv(path, argv_list);
|
||||
_exit(127);
|
||||
} else if (pid > 0) {
|
||||
/* parent */
|
||||
do {
|
||||
waitstat = waitpid(pid, &status, 0);
|
||||
} while ((waitstat == -1 && errno == EINTR) ||
|
||||
(waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status)));
|
||||
|
||||
if (waitstat == 0) {
|
||||
if (WIFEXITED(status))
|
||||
exit_status = WEXITSTATUS(status);
|
||||
else
|
||||
exit_status = WTERMSIG(status);
|
||||
} else {
|
||||
usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno));
|
||||
exit_status = -1;
|
||||
}
|
||||
} else {
|
||||
/* fork failed */
|
||||
usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno));
|
||||
exit_status = -1;
|
||||
}
|
||||
|
||||
free(argv_list);
|
||||
|
||||
return (exit_status);
|
||||
}
|
||||
|
||||
static int
|
||||
sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle,
|
||||
int interface_number)
|
||||
{
|
||||
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
||||
string_list_t *list;
|
||||
char path_arg[PATH_MAX];
|
||||
sunos_dev_priv_t *dpriv;
|
||||
int r;
|
||||
|
||||
dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv;
|
||||
snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
|
||||
usbi_dbg("%s", path_arg);
|
||||
|
||||
list = sunos_new_string_list();
|
||||
if (list == NULL)
|
||||
return (LIBUSB_ERROR_NO_MEM);
|
||||
|
||||
/* attach ugen driver */
|
||||
r = 0;
|
||||
r |= sunos_append_to_string_list(list, UPDATEDRV);
|
||||
r |= sunos_append_to_string_list(list, "-a"); /* add rule */
|
||||
r |= sunos_append_to_string_list(list, "-i"); /* specific device */
|
||||
r |= sunos_append_to_string_list(list, path_arg); /* physical path */
|
||||
r |= sunos_append_to_string_list(list, "ugen");
|
||||
if (r) {
|
||||
sunos_free_string_list(list);
|
||||
return (LIBUSB_ERROR_NO_MEM);
|
||||
}
|
||||
|
||||
r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
|
||||
sunos_free_string_list(list);
|
||||
if (r < 0)
|
||||
return (LIBUSB_ERROR_OTHER);
|
||||
|
||||
/* reconfigure the driver node */
|
||||
r = 0;
|
||||
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
|
||||
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
|
||||
if (r)
|
||||
usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
|
||||
|
||||
snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x", dpriv->dev_descr.idVendor,
|
||||
dpriv->dev_descr.idProduct);
|
||||
sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath);
|
||||
|
||||
if (access(dpriv->ugenpath, F_OK) == -1) {
|
||||
usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver");
|
||||
return (LIBUSB_ERROR_IO);
|
||||
}
|
||||
|
||||
return sunos_usb_open_ep0((sunos_dev_handle_priv_t *)dev_handle->os_priv, dpriv);
|
||||
}
|
||||
|
||||
static int
|
||||
sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle,
|
||||
int interface_number)
|
||||
{
|
||||
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
||||
string_list_t *list;
|
||||
char path_arg[PATH_MAX];
|
||||
sunos_dev_priv_t *dpriv;
|
||||
int r;
|
||||
|
||||
/* we open the dev in detach driver, so we need close it first. */
|
||||
sunos_close(dev_handle);
|
||||
|
||||
dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv;
|
||||
snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
|
||||
usbi_dbg("%s", path_arg);
|
||||
|
||||
list = sunos_new_string_list();
|
||||
if (list == NULL)
|
||||
return (LIBUSB_ERROR_NO_MEM);
|
||||
|
||||
/* detach ugen driver */
|
||||
r = 0;
|
||||
r |= sunos_append_to_string_list(list, UPDATEDRV);
|
||||
r |= sunos_append_to_string_list(list, "-d"); /* add rule */
|
||||
r |= sunos_append_to_string_list(list, "-i"); /* specific device */
|
||||
r |= sunos_append_to_string_list(list, path_arg); /* physical path */
|
||||
r |= sunos_append_to_string_list(list, "ugen");
|
||||
if (r) {
|
||||
sunos_free_string_list(list);
|
||||
return (LIBUSB_ERROR_NO_MEM);
|
||||
}
|
||||
|
||||
r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
|
||||
sunos_free_string_list(list);
|
||||
if (r < 0)
|
||||
return (LIBUSB_ERROR_OTHER);
|
||||
|
||||
/* reconfigure the driver node */
|
||||
r = 0;
|
||||
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
|
||||
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
|
||||
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
|
||||
if (r)
|
||||
usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
|
||||
{
|
||||
int proplen;
|
||||
int n, *addr, *port_prop;
|
||||
int *i, n, *addr, *port_prop;
|
||||
char *phypath;
|
||||
uint8_t *rdata;
|
||||
struct libusb_device_descriptor *descr;
|
||||
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
||||
char match_str[PATH_MAX];
|
||||
|
||||
/* Device descriptors */
|
||||
proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
|
||||
|
@ -137,7 +526,11 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
|
|||
phypath = di_devfs_path(node);
|
||||
if (phypath) {
|
||||
dpriv->phypath = strdup(phypath);
|
||||
snprintf(match_str, sizeof(match_str), "^usb/%x.%x", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct);
|
||||
usbi_dbg("match is %s", match_str);
|
||||
sunos_physpath_to_devlink(dpriv->phypath, match_str, &dpriv->ugenpath);
|
||||
di_devfs_path_free(phypath);
|
||||
|
||||
} else {
|
||||
free(dpriv->raw_cfgdescr);
|
||||
|
||||
|
@ -153,13 +546,13 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
|
|||
}
|
||||
|
||||
/* speed */
|
||||
if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) {
|
||||
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) {
|
||||
dev->speed = LIBUSB_SPEED_LOW;
|
||||
} else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) {
|
||||
} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) {
|
||||
dev->speed = LIBUSB_SPEED_HIGH;
|
||||
} else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) {
|
||||
} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "full-speed", &i) >= 0) {
|
||||
dev->speed = LIBUSB_SPEED_FULL;
|
||||
} else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) {
|
||||
} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "super-speed", &i) >= 0) {
|
||||
dev->speed = LIBUSB_SPEED_SUPER;
|
||||
}
|
||||
|
||||
|
@ -170,97 +563,88 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
|
|||
return (LIBUSB_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sunos_add_devices(di_devlink_t link, void *arg)
|
||||
{
|
||||
struct devlink_cbarg *largs = (struct devlink_cbarg *)arg;
|
||||
struct node_args *nargs;
|
||||
di_node_t myself, pnode;
|
||||
di_node_t myself, dn;
|
||||
uint64_t session_id = 0;
|
||||
uint16_t bdf = 0;
|
||||
uint64_t sid = 0;
|
||||
uint64_t bdf = 0;
|
||||
struct libusb_device *dev;
|
||||
sunos_dev_priv_t *devpriv;
|
||||
const char *path, *newpath;
|
||||
int n, i;
|
||||
int n, *j;
|
||||
int i = 0;
|
||||
int *addr_prop;
|
||||
uint8_t bus_number = 0;
|
||||
uint32_t * regbuf = NULL;
|
||||
uint32_t reg;
|
||||
|
||||
nargs = (struct node_args *)largs->nargs;
|
||||
myself = largs->myself;
|
||||
if (nargs->last_ugenpath) {
|
||||
/* the same node's links */
|
||||
return (DI_WALK_CONTINUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct session ID.
|
||||
* session ID = ...parent hub addr|hub addr|dev addr.
|
||||
* session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf
|
||||
* 8 bits 8bits 8 bits 16bits
|
||||
*/
|
||||
pnode = myself;
|
||||
i = 0;
|
||||
while (pnode != DI_NODE_NIL) {
|
||||
if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) {
|
||||
/* walk to root */
|
||||
uint32_t *regbuf = NULL;
|
||||
uint32_t reg;
|
||||
if (myself == DI_NODE_NIL)
|
||||
return (DI_WALK_CONTINUE);
|
||||
|
||||
n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg",
|
||||
(int **)®buf);
|
||||
reg = regbuf[0];
|
||||
bdf = (PCI_REG_BUS_G(reg) << 8) |
|
||||
(PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
|
||||
session_id |= (bdf << i * 8);
|
||||
|
||||
/* same as 'unit-address' property */
|
||||
bus_number =
|
||||
(PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
|
||||
|
||||
usbi_dbg("device bus address=%s:%x",
|
||||
di_bus_addr(pnode), bus_number);
|
||||
|
||||
break;
|
||||
dn = myself;
|
||||
/* find the root hub */
|
||||
while (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "root-hub", &j) != 0) {
|
||||
usbi_dbg("find_root_hub:%s", di_devfs_path(dn));
|
||||
n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
|
||||
"assigned-address", &addr_prop);
|
||||
session_id |= ((addr_prop[0] & 0xff) << i++ * 8);
|
||||
dn = di_parent_node(dn);
|
||||
}
|
||||
|
||||
/* dn is the root hub node */
|
||||
n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)®buf);
|
||||
reg = regbuf[0];
|
||||
bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
|
||||
/* bdf must larger than i*8 bits */
|
||||
session_id |= (bdf << i * 8);
|
||||
bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
|
||||
|
||||
usbi_dbg("device bus address=%s:%x, name:%s",
|
||||
di_bus_addr(myself), bus_number, di_node_name(dn));
|
||||
usbi_dbg("session id org:%lx", session_id);
|
||||
|
||||
/* dn is the usb device */
|
||||
for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) {
|
||||
usbi_dbg("device path:%s", di_devfs_path(dn));
|
||||
/* skip hub devices, because its driver can not been unload */
|
||||
if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1)
|
||||
continue;
|
||||
/* usb_addr */
|
||||
n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode,
|
||||
n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
|
||||
"assigned-address", &addr_prop);
|
||||
if ((n != 1) || (addr_prop[0] == 0)) {
|
||||
usbi_dbg("cannot get valid usb_addr");
|
||||
|
||||
return (DI_WALK_CONTINUE);
|
||||
continue;
|
||||
}
|
||||
|
||||
session_id |= ((addr_prop[0] & 0xff) << i * 8);
|
||||
if (++i > 7)
|
||||
break;
|
||||
sid = (session_id << 8) | (addr_prop[0] & 0xff) ;
|
||||
usbi_dbg("session id %lx", sid);
|
||||
|
||||
pnode = di_parent_node(pnode);
|
||||
}
|
||||
|
||||
path = di_devlink_path(link);
|
||||
dev = usbi_get_device_by_session_id(nargs->ctx, session_id);
|
||||
dev = usbi_get_device_by_session_id(nargs->ctx, sid);
|
||||
if (dev == NULL) {
|
||||
dev = usbi_alloc_device(nargs->ctx, session_id);
|
||||
dev = usbi_alloc_device(nargs->ctx, sid);
|
||||
if (dev == NULL) {
|
||||
usbi_dbg("can't alloc device");
|
||||
|
||||
return (DI_WALK_TERMINATE);
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) {
|
||||
libusb_unref_device(dev);
|
||||
|
||||
return (DI_WALK_TERMINATE);
|
||||
usbi_dbg("get infomation fail");
|
||||
continue;
|
||||
}
|
||||
if (usbi_sanitize_device(dev) < 0) {
|
||||
libusb_unref_device(dev);
|
||||
|
@ -268,13 +652,9 @@ sunos_add_devices(di_devlink_t link, void *arg)
|
|||
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;
|
||||
usbi_dbg("Dev %s exists", devpriv->ugenpath);
|
||||
}
|
||||
|
||||
if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) {
|
||||
usbi_dbg("cannot append device");
|
||||
|
@ -285,11 +665,11 @@ sunos_add_devices(di_devlink_t link, void *arg)
|
|||
* hereafter. Front end or app should take care of their ref.
|
||||
*/
|
||||
libusb_unref_device(dev);
|
||||
}
|
||||
|
||||
usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
|
||||
devpriv->ugenpath, path, (uint64_t)session_id,
|
||||
devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid,
|
||||
(*nargs->discdevs)->len, bdf);
|
||||
}
|
||||
|
||||
return (DI_WALK_CONTINUE);
|
||||
}
|
||||
|
@ -303,14 +683,14 @@ sunos_walk_minor_node_link(di_node_t node, void *args)
|
|||
struct node_args *nargs = (struct node_args *)args;
|
||||
di_devlink_handle_t devlink_hdl = nargs->dlink_hdl;
|
||||
|
||||
/* walk each minor to find ugen devices */
|
||||
/* walk each minor to find usb devices */
|
||||
while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
|
||||
minor_path = di_devfs_minor_path(minor);
|
||||
arg.nargs = args;
|
||||
arg.myself = node;
|
||||
arg.minor = minor;
|
||||
(void) di_devlink_walk(devlink_hdl,
|
||||
"^usb/[0-9a-f]+[.][0-9a-f]+", minor_path,
|
||||
"^usb/hub[0-9]+", minor_path,
|
||||
DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices);
|
||||
di_devfs_path_free(minor_path);
|
||||
}
|
||||
|
@ -496,7 +876,7 @@ sunos_check_device_and_status_open(struct libusb_device_handle *hdl,
|
|||
usbi_dbg("can't find interface for endpoint 0x%02x",
|
||||
ep_addr);
|
||||
|
||||
return (LIBUSB_ERROR_ACCESS);
|
||||
return (EACCES);
|
||||
}
|
||||
|
||||
/* create filename */
|
||||
|
@ -603,6 +983,11 @@ sunos_open(struct libusb_device_handle *handle)
|
|||
hpriv->eps[i].statfd = -1;
|
||||
}
|
||||
|
||||
if (sunos_kernel_driver_active(handle, 0)) {
|
||||
/* pretend we can open the device */
|
||||
return (LIBUSB_SUCCESS);
|
||||
}
|
||||
|
||||
if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) {
|
||||
usbi_dbg("fail: %d", ret);
|
||||
return (ret);
|
||||
|
@ -811,8 +1196,13 @@ sunos_async_callback(union sigval arg)
|
|||
int ret;
|
||||
sunos_dev_handle_priv_t *hpriv;
|
||||
uint8_t ep;
|
||||
libusb_device_handle *dev_handle;
|
||||
|
||||
hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv;
|
||||
dev_handle = xfer->dev_handle;
|
||||
|
||||
/* libusb can forcibly interrupt transfer in do_close() */
|
||||
if (dev_handle != NULL) {
|
||||
hpriv = (sunos_dev_handle_priv_t *)dev_handle->os_priv;
|
||||
ep = sunos_usb_ep_index(xfer->endpoint);
|
||||
|
||||
ret = aio_error(aiocb);
|
||||
|
@ -831,6 +1221,7 @@ sunos_async_callback(union sigval arg)
|
|||
|
||||
/* async notification */
|
||||
usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -975,9 +1366,15 @@ solaris_submit_ctrl_on_default(struct libusb_transfer *transfer)
|
|||
}
|
||||
usbi_dbg("Done: ctrl data bytes %d", ret);
|
||||
|
||||
/* sync transfer handling */
|
||||
/**
|
||||
* Sync transfer handling.
|
||||
* We should release transfer lock here and later get it back
|
||||
* as usbi_handle_transfer_completion() takes its own transfer lock.
|
||||
*/
|
||||
usbi_mutex_unlock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock);
|
||||
ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer),
|
||||
transfer->status);
|
||||
usbi_mutex_lock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
@ -1010,9 +1407,7 @@ void
|
|||
sunos_destroy_device(struct libusb_device *dev)
|
||||
{
|
||||
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
||||
|
||||
usbi_dbg("");
|
||||
|
||||
usbi_dbg("destroy everyting");
|
||||
free(dpriv->raw_cfgdescr);
|
||||
free(dpriv->ugenpath);
|
||||
free(dpriv->phypath);
|
||||
|
@ -1120,8 +1515,6 @@ sunos_handle_transfer_completion(struct usbi_transfer *itransfer)
|
|||
int
|
||||
sunos_clock_gettime(int clkid, struct timespec *tp)
|
||||
{
|
||||
usbi_dbg("clock %d", clkid);
|
||||
|
||||
if (clkid == USBI_CLOCK_REALTIME)
|
||||
return clock_gettime(CLOCK_REALTIME, tp);
|
||||
|
||||
|
@ -1254,7 +1647,14 @@ sunos_usb_get_status(int fd)
|
|||
return (status);
|
||||
}
|
||||
|
||||
const struct usbi_os_backend sunos_backend = {
|
||||
#ifdef USBI_TIMERFD_AVAILABLE
|
||||
static clockid_t op_get_timerfd_clockid(void)
|
||||
{
|
||||
return CLOCK_MONOTONIC;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct usbi_os_backend usbi_backend = {
|
||||
.name = "Solaris",
|
||||
.caps = 0,
|
||||
.init = sunos_init,
|
||||
|
@ -1276,9 +1676,9 @@ const struct usbi_os_backend sunos_backend = {
|
|||
.reset_device = sunos_reset_device, /* TODO */
|
||||
.alloc_streams = NULL,
|
||||
.free_streams = NULL,
|
||||
.kernel_driver_active = NULL,
|
||||
.detach_kernel_driver = NULL,
|
||||
.attach_kernel_driver = NULL,
|
||||
.kernel_driver_active = sunos_kernel_driver_active,
|
||||
.detach_kernel_driver = sunos_detach_kernel_driver,
|
||||
.attach_kernel_driver = sunos_attach_kernel_driver,
|
||||
.destroy_device = sunos_destroy_device,
|
||||
.submit_transfer = sunos_submit_transfer,
|
||||
.cancel_transfer = sunos_cancel_transfer,
|
||||
|
@ -1286,6 +1686,9 @@ const struct usbi_os_backend sunos_backend = {
|
|||
.clear_transfer_priv = sunos_clear_transfer_priv,
|
||||
.handle_transfer_completion = sunos_handle_transfer_completion,
|
||||
.clock_gettime = sunos_clock_gettime,
|
||||
#ifdef USBI_TIMERFD_AVAILABLE
|
||||
.get_timerfd_clockid = op_get_timerfd_clockid,
|
||||
#endif
|
||||
.device_priv_size = sizeof(sunos_dev_priv_t),
|
||||
.device_handle_priv_size = sizeof(sunos_dev_handle_priv_t),
|
||||
.transfer_priv_size = sizeof(sunos_xfer_priv_t),
|
||||
|
|
|
@ -65,6 +65,12 @@ struct devlink_cbarg {
|
|||
di_minor_t minor;
|
||||
};
|
||||
|
||||
typedef struct walk_link {
|
||||
char *path;
|
||||
int len;
|
||||
char **linkpp;
|
||||
} walk_link_t;
|
||||
|
||||
/* AIO callback args */
|
||||
struct aio_callback_args{
|
||||
struct libusb_transfer *transfer;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
# include <unistd.h>
|
||||
# include <sys/syscall.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <mach/mach.h>
|
||||
# include <pthread.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
|
|||
struct timespec timeout;
|
||||
int r;
|
||||
|
||||
r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout);
|
||||
r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -59,7 +59,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
|
|||
|
||||
int usbi_get_tid(void)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret;
|
||||
#if defined(__ANDROID__)
|
||||
ret = gettid();
|
||||
#elif defined(__linux__)
|
||||
|
@ -69,10 +69,11 @@ int usbi_get_tid(void)
|
|||
real thread support. For 5.1 and earlier, -1 is returned. */
|
||||
ret = syscall(SYS_getthrid);
|
||||
#elif defined(__APPLE__)
|
||||
ret = mach_thread_self();
|
||||
mach_port_deallocate(mach_task_self(), ret);
|
||||
ret = (int)pthread_mach_thread_np(pthread_self());
|
||||
#elif defined(__CYGWIN__)
|
||||
ret = GetCurrentThreadId();
|
||||
#else
|
||||
ret = -1;
|
||||
#endif
|
||||
/* TODO: NetBSD thread ID support */
|
||||
return ret;
|
||||
|
|
|
@ -26,32 +26,76 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#define usbi_mutex_static_t pthread_mutex_t
|
||||
#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
#define usbi_mutex_static_lock pthread_mutex_lock
|
||||
#define usbi_mutex_static_unlock pthread_mutex_unlock
|
||||
typedef pthread_mutex_t usbi_mutex_static_t;
|
||||
static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
|
||||
{
|
||||
(void)pthread_mutex_lock(mutex);
|
||||
}
|
||||
static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
|
||||
{
|
||||
(void)pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
#define usbi_mutex_t pthread_mutex_t
|
||||
#define usbi_mutex_init(mutex) pthread_mutex_init((mutex), NULL)
|
||||
#define usbi_mutex_lock pthread_mutex_lock
|
||||
#define usbi_mutex_unlock pthread_mutex_unlock
|
||||
#define usbi_mutex_trylock pthread_mutex_trylock
|
||||
#define usbi_mutex_destroy pthread_mutex_destroy
|
||||
typedef pthread_mutex_t usbi_mutex_t;
|
||||
static inline int usbi_mutex_init(usbi_mutex_t *mutex)
|
||||
{
|
||||
return pthread_mutex_init(mutex, NULL);
|
||||
}
|
||||
static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
|
||||
{
|
||||
(void)pthread_mutex_lock(mutex);
|
||||
}
|
||||
static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
|
||||
{
|
||||
(void)pthread_mutex_unlock(mutex);
|
||||
}
|
||||
static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
|
||||
{
|
||||
return pthread_mutex_trylock(mutex);
|
||||
}
|
||||
static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
|
||||
{
|
||||
(void)pthread_mutex_destroy(mutex);
|
||||
}
|
||||
|
||||
#define usbi_cond_t pthread_cond_t
|
||||
#define usbi_cond_init(cond) pthread_cond_init((cond), NULL)
|
||||
#define usbi_cond_wait pthread_cond_wait
|
||||
#define usbi_cond_broadcast pthread_cond_broadcast
|
||||
#define usbi_cond_destroy pthread_cond_destroy
|
||||
typedef pthread_cond_t usbi_cond_t;
|
||||
static inline void usbi_cond_init(pthread_cond_t *cond)
|
||||
{
|
||||
(void)pthread_cond_init(cond, NULL);
|
||||
}
|
||||
static inline int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
|
||||
{
|
||||
return pthread_cond_wait(cond, mutex);
|
||||
}
|
||||
int usbi_cond_timedwait(usbi_cond_t *cond,
|
||||
usbi_mutex_t *mutex, const struct timeval *tv);
|
||||
static inline void usbi_cond_broadcast(usbi_cond_t *cond)
|
||||
{
|
||||
(void)pthread_cond_broadcast(cond);
|
||||
}
|
||||
static inline void usbi_cond_destroy(usbi_cond_t *cond)
|
||||
{
|
||||
(void)pthread_cond_destroy(cond);
|
||||
}
|
||||
|
||||
#define usbi_tls_key_t pthread_key_t
|
||||
#define usbi_tls_key_create(key) pthread_key_create((key), NULL)
|
||||
#define usbi_tls_key_get pthread_getspecific
|
||||
#define usbi_tls_key_set pthread_setspecific
|
||||
#define usbi_tls_key_delete pthread_key_delete
|
||||
|
||||
int usbi_cond_timedwait(pthread_cond_t *cond,
|
||||
pthread_mutex_t *mutex, const struct timeval *tv);
|
||||
typedef pthread_key_t usbi_tls_key_t;
|
||||
static inline void usbi_tls_key_create(usbi_tls_key_t *key)
|
||||
{
|
||||
(void)pthread_key_create(key, NULL);
|
||||
}
|
||||
static inline void *usbi_tls_key_get(usbi_tls_key_t key)
|
||||
{
|
||||
return pthread_getspecific(key);
|
||||
}
|
||||
static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
|
||||
{
|
||||
(void)pthread_setspecific(key, ptr);
|
||||
}
|
||||
static inline void usbi_tls_key_delete(usbi_tls_key_t key)
|
||||
{
|
||||
(void)pthread_key_delete(key);
|
||||
}
|
||||
|
||||
int usbi_get_tid(void);
|
||||
|
||||
|
|
|
@ -20,189 +20,67 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
#include <objbase.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libusbi.h"
|
||||
|
||||
struct usbi_cond_perthread {
|
||||
struct list_head list;
|
||||
DWORD tid;
|
||||
HANDLE event;
|
||||
};
|
||||
|
||||
int usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
|
||||
void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
|
||||
{
|
||||
if (!mutex)
|
||||
return EINVAL;
|
||||
while (InterlockedExchange(mutex, 1) == 1)
|
||||
while (InterlockedExchange(mutex, 1L) == 1L)
|
||||
SleepEx(0, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
|
||||
void usbi_cond_init(usbi_cond_t *cond)
|
||||
{
|
||||
if (!mutex)
|
||||
return EINVAL;
|
||||
InterlockedExchange(mutex, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbi_mutex_init(usbi_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex)
|
||||
return EINVAL;
|
||||
*mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
if (!*mutex)
|
||||
return ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbi_mutex_lock(usbi_mutex_t *mutex)
|
||||
{
|
||||
DWORD result;
|
||||
|
||||
if (!mutex)
|
||||
return EINVAL;
|
||||
result = WaitForSingleObject(*mutex, INFINITE);
|
||||
if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
|
||||
return 0; // acquired (ToDo: check that abandoned is ok)
|
||||
else
|
||||
return EINVAL; // don't know how this would happen
|
||||
// so don't know proper errno
|
||||
}
|
||||
|
||||
int usbi_mutex_unlock(usbi_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex)
|
||||
return EINVAL;
|
||||
if (ReleaseMutex(*mutex))
|
||||
return 0;
|
||||
else
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
int usbi_mutex_trylock(usbi_mutex_t *mutex)
|
||||
{
|
||||
DWORD result;
|
||||
|
||||
if (!mutex)
|
||||
return EINVAL;
|
||||
result = WaitForSingleObject(*mutex, 0);
|
||||
if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
|
||||
return 0; // acquired (ToDo: check that abandoned is ok)
|
||||
else if (result == WAIT_TIMEOUT)
|
||||
return EBUSY;
|
||||
else
|
||||
return EINVAL; // don't know how this would happen
|
||||
// so don't know proper error
|
||||
}
|
||||
|
||||
int usbi_mutex_destroy(usbi_mutex_t *mutex)
|
||||
{
|
||||
// It is not clear if CloseHandle failure is due to failure to unlock.
|
||||
// If so, this should be errno=EBUSY.
|
||||
if (!mutex || !CloseHandle(*mutex))
|
||||
return EINVAL;
|
||||
*mutex = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbi_cond_init(usbi_cond_t *cond)
|
||||
{
|
||||
if (!cond)
|
||||
return EINVAL;
|
||||
list_init(&cond->waiters);
|
||||
list_init(&cond->not_waiting);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbi_cond_destroy(usbi_cond_t *cond)
|
||||
{
|
||||
// This assumes no one is using this anymore. The check MAY NOT BE safe.
|
||||
struct usbi_cond_perthread *pos, *next_pos;
|
||||
|
||||
if(!cond)
|
||||
return EINVAL;
|
||||
if (!list_empty(&cond->waiters))
|
||||
return EBUSY; // (!see above!)
|
||||
list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
|
||||
CloseHandle(pos->event);
|
||||
list_del(&pos->list);
|
||||
free(pos);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbi_cond_broadcast(usbi_cond_t *cond)
|
||||
{
|
||||
// Assumes mutex is locked; this is not in keeping with POSIX spec, but
|
||||
// libusb does this anyway, so we simplify by not adding more sync
|
||||
// primitives to the CV definition!
|
||||
int fail = 0;
|
||||
struct usbi_cond_perthread *pos;
|
||||
|
||||
if (!cond)
|
||||
return EINVAL;
|
||||
list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) {
|
||||
if (!SetEvent(pos->event))
|
||||
fail = 1;
|
||||
}
|
||||
// The wait function will remove its respective item from the list.
|
||||
return fail ? EINVAL : 0;
|
||||
}
|
||||
|
||||
__inline static int usbi_cond_intwait(usbi_cond_t *cond,
|
||||
static int usbi_cond_intwait(usbi_cond_t *cond,
|
||||
usbi_mutex_t *mutex, DWORD timeout_ms)
|
||||
{
|
||||
struct usbi_cond_perthread *pos;
|
||||
int r, found = 0;
|
||||
DWORD r2, tid = GetCurrentThreadId();
|
||||
DWORD r;
|
||||
|
||||
if (!cond || !mutex)
|
||||
return EINVAL;
|
||||
list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
|
||||
if(tid == pos->tid) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
pos = calloc(1, sizeof(struct usbi_cond_perthread));
|
||||
if (!pos)
|
||||
// Same assumption as usbi_cond_broadcast() holds
|
||||
if (list_empty(&cond->not_waiting)) {
|
||||
pos = malloc(sizeof(*pos));
|
||||
if (pos == NULL)
|
||||
return ENOMEM; // This errno is not POSIX-allowed.
|
||||
pos->tid = tid;
|
||||
pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
|
||||
if (!pos->event) {
|
||||
if (pos->event == NULL) {
|
||||
free(pos);
|
||||
return ENOMEM;
|
||||
}
|
||||
list_add(&pos->list, &cond->not_waiting);
|
||||
} else {
|
||||
pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list);
|
||||
list_del(&pos->list); // remove from not_waiting list.
|
||||
// Ensure the event is clear before waiting
|
||||
WaitForSingleObject(pos->event, 0);
|
||||
}
|
||||
|
||||
list_del(&pos->list); // remove from not_waiting list.
|
||||
list_add(&pos->list, &cond->waiters);
|
||||
|
||||
r = usbi_mutex_unlock(mutex);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r2 = WaitForSingleObject(pos->event, timeout_ms);
|
||||
r = usbi_mutex_lock(mutex);
|
||||
if (r)
|
||||
return r;
|
||||
LeaveCriticalSection(mutex);
|
||||
r = WaitForSingleObject(pos->event, timeout_ms);
|
||||
EnterCriticalSection(mutex);
|
||||
|
||||
list_del(&pos->list);
|
||||
list_add(&pos->list, &cond->not_waiting);
|
||||
|
||||
if (r2 == WAIT_OBJECT_0)
|
||||
if (r == WAIT_OBJECT_0)
|
||||
return 0;
|
||||
else if (r2 == WAIT_TIMEOUT)
|
||||
else if (r == WAIT_TIMEOUT)
|
||||
return ETIMEDOUT;
|
||||
else
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot!
|
||||
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
|
||||
{
|
||||
|
@ -221,39 +99,28 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
|
|||
return usbi_cond_intwait(cond, mutex, millis);
|
||||
}
|
||||
|
||||
int usbi_tls_key_create(usbi_tls_key_t *key)
|
||||
void usbi_cond_broadcast(usbi_cond_t *cond)
|
||||
{
|
||||
if (!key)
|
||||
return EINVAL;
|
||||
*key = TlsAlloc();
|
||||
if (*key == TLS_OUT_OF_INDEXES)
|
||||
return ENOMEM;
|
||||
else
|
||||
return 0;
|
||||
// Assumes mutex is locked; this is not in keeping with POSIX spec, but
|
||||
// libusb does this anyway, so we simplify by not adding more sync
|
||||
// primitives to the CV definition!
|
||||
struct usbi_cond_perthread *pos;
|
||||
|
||||
list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread)
|
||||
SetEvent(pos->event);
|
||||
// The wait function will remove its respective item from the list.
|
||||
}
|
||||
|
||||
void *usbi_tls_key_get(usbi_tls_key_t key)
|
||||
void usbi_cond_destroy(usbi_cond_t *cond)
|
||||
{
|
||||
return TlsGetValue(key);
|
||||
}
|
||||
// This assumes no one is using this anymore. The check MAY NOT BE safe.
|
||||
struct usbi_cond_perthread *pos, *next;
|
||||
|
||||
int usbi_tls_key_set(usbi_tls_key_t key, void *value)
|
||||
{
|
||||
if (TlsSetValue(key, value))
|
||||
return 0;
|
||||
else
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int usbi_tls_key_delete(usbi_tls_key_t key)
|
||||
{
|
||||
if (TlsFree(key))
|
||||
return 0;
|
||||
else
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int usbi_get_tid(void)
|
||||
{
|
||||
return (int)GetCurrentThreadId();
|
||||
if (!list_empty(&cond->waiters))
|
||||
return; // (!see above!)
|
||||
list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) {
|
||||
CloseHandle(pos->event);
|
||||
list_del(&pos->list);
|
||||
free(pos);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,17 +21,40 @@
|
|||
#ifndef LIBUSB_THREADS_WINDOWS_H
|
||||
#define LIBUSB_THREADS_WINDOWS_H
|
||||
|
||||
#define usbi_mutex_static_t volatile LONG
|
||||
#define USBI_MUTEX_INITIALIZER 0
|
||||
#define USBI_MUTEX_INITIALIZER 0L
|
||||
#ifdef _WIN32_WCE
|
||||
typedef LONG usbi_mutex_static_t;
|
||||
#else
|
||||
typedef volatile LONG usbi_mutex_static_t;
|
||||
#endif
|
||||
void usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
|
||||
static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
|
||||
{
|
||||
InterlockedExchange(mutex, 0L);
|
||||
}
|
||||
|
||||
#define usbi_mutex_t HANDLE
|
||||
|
||||
typedef struct usbi_cond {
|
||||
// Every time a thread touches the CV, it winds up in one of these lists.
|
||||
// It stays there until the CV is destroyed, even if the thread terminates.
|
||||
struct list_head waiters;
|
||||
struct list_head not_waiting;
|
||||
} usbi_cond_t;
|
||||
typedef CRITICAL_SECTION usbi_mutex_t;
|
||||
static inline int usbi_mutex_init(usbi_mutex_t *mutex)
|
||||
{
|
||||
InitializeCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
|
||||
{
|
||||
EnterCriticalSection(mutex);
|
||||
}
|
||||
static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
|
||||
{
|
||||
LeaveCriticalSection(mutex);
|
||||
}
|
||||
static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
|
||||
{
|
||||
return !TryEnterCriticalSection(mutex);
|
||||
}
|
||||
static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
|
||||
{
|
||||
DeleteCriticalSection(mutex);
|
||||
}
|
||||
|
||||
// We *were* getting timespec from pthread.h:
|
||||
#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED))
|
||||
|
@ -45,32 +68,44 @@ struct timespec {
|
|||
|
||||
// We *were* getting ETIMEDOUT from pthread.h:
|
||||
#ifndef ETIMEDOUT
|
||||
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
|
||||
#define ETIMEDOUT 10060 /* This is the value in winsock.h. */
|
||||
#endif
|
||||
|
||||
#define usbi_tls_key_t DWORD
|
||||
typedef struct usbi_cond {
|
||||
// Every time a thread touches the CV, it winds up in one of these lists.
|
||||
// It stays there until the CV is destroyed, even if the thread terminates.
|
||||
struct list_head waiters;
|
||||
struct list_head not_waiting;
|
||||
} usbi_cond_t;
|
||||
|
||||
int usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
|
||||
int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex);
|
||||
|
||||
int usbi_mutex_init(usbi_mutex_t *mutex);
|
||||
int usbi_mutex_lock(usbi_mutex_t *mutex);
|
||||
int usbi_mutex_unlock(usbi_mutex_t *mutex);
|
||||
int usbi_mutex_trylock(usbi_mutex_t *mutex);
|
||||
int usbi_mutex_destroy(usbi_mutex_t *mutex);
|
||||
|
||||
int usbi_cond_init(usbi_cond_t *cond);
|
||||
void usbi_cond_init(usbi_cond_t *cond);
|
||||
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex);
|
||||
int usbi_cond_timedwait(usbi_cond_t *cond,
|
||||
usbi_mutex_t *mutex, const struct timeval *tv);
|
||||
int usbi_cond_broadcast(usbi_cond_t *cond);
|
||||
int usbi_cond_destroy(usbi_cond_t *cond);
|
||||
void usbi_cond_broadcast(usbi_cond_t *cond);
|
||||
void usbi_cond_destroy(usbi_cond_t *cond);
|
||||
|
||||
int usbi_tls_key_create(usbi_tls_key_t *key);
|
||||
void *usbi_tls_key_get(usbi_tls_key_t key);
|
||||
int usbi_tls_key_set(usbi_tls_key_t key, void *value);
|
||||
int usbi_tls_key_delete(usbi_tls_key_t key);
|
||||
typedef DWORD usbi_tls_key_t;
|
||||
static inline void usbi_tls_key_create(usbi_tls_key_t *key)
|
||||
{
|
||||
*key = TlsAlloc();
|
||||
}
|
||||
static inline void *usbi_tls_key_get(usbi_tls_key_t key)
|
||||
{
|
||||
return TlsGetValue(key);
|
||||
}
|
||||
static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
|
||||
{
|
||||
(void)TlsSetValue(key, ptr);
|
||||
}
|
||||
static inline void usbi_tls_key_delete(usbi_tls_key_t key)
|
||||
{
|
||||
(void)TlsFree(key);
|
||||
}
|
||||
|
||||
int usbi_get_tid(void);
|
||||
static inline int usbi_get_tid(void)
|
||||
{
|
||||
return (int)GetCurrentThreadId();
|
||||
}
|
||||
|
||||
#endif /* LIBUSB_THREADS_WINDOWS_H */
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
#include "wince_usb.h"
|
||||
|
||||
// Global variables
|
||||
const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
|
||||
int windows_version = WINDOWS_CE;
|
||||
int errno = 0;
|
||||
static uint64_t hires_frequency, hires_ticks_to_ps;
|
||||
static HANDLE driver_handle = INVALID_HANDLE_VALUE;
|
||||
static int concurrent_usage = -1;
|
||||
|
@ -42,38 +41,39 @@ static int concurrent_usage = -1;
|
|||
* uses retval as errorcode, or, if 0, use GetLastError()
|
||||
*/
|
||||
#if defined(ENABLE_LOGGING)
|
||||
static const char *windows_error_str(DWORD retval)
|
||||
static const char *windows_error_str(DWORD error_code)
|
||||
{
|
||||
static TCHAR wErr_string[ERR_BUFFER_SIZE];
|
||||
static char err_string[ERR_BUFFER_SIZE];
|
||||
|
||||
DWORD error_code, format_error;
|
||||
DWORD size;
|
||||
size_t i;
|
||||
int len;
|
||||
|
||||
error_code = retval ? retval : GetLastError();
|
||||
if (error_code == 0)
|
||||
error_code = GetLastError();
|
||||
|
||||
safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("[%u] "), (unsigned int)error_code);
|
||||
len = sprintf(err_string, "[%u] ", (unsigned int)error_code);
|
||||
|
||||
size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wErr_string[safe_tcslen(wErr_string)],
|
||||
ERR_BUFFER_SIZE - (DWORD)safe_tcslen(wErr_string), NULL);
|
||||
size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
wErr_string, ERR_BUFFER_SIZE, NULL);
|
||||
if (size == 0) {
|
||||
format_error = GetLastError();
|
||||
DWORD format_error = GetLastError();
|
||||
if (format_error)
|
||||
safe_stprintf(wErr_string, ERR_BUFFER_SIZE,
|
||||
_T("Windows error code %u (FormatMessage error code %u)"),
|
||||
snprintf(err_string, ERR_BUFFER_SIZE,
|
||||
"Windows error code %u (FormatMessage error code %u)",
|
||||
(unsigned int)error_code, (unsigned int)format_error);
|
||||
else
|
||||
safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("Unknown error code %u"), (unsigned int)error_code);
|
||||
snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code);
|
||||
} else {
|
||||
// Remove CR/LF terminators
|
||||
for (i = safe_tcslen(wErr_string) - 1; ((wErr_string[i] == 0x0A) || (wErr_string[i] == 0x0D)); i--)
|
||||
wErr_string[i] = 0;
|
||||
}
|
||||
// Remove CR/LF terminators, if present
|
||||
size_t pos = size - 2;
|
||||
if (wErr_string[pos] == 0x0D)
|
||||
wErr_string[pos] = 0;
|
||||
|
||||
if (WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, err_string, ERR_BUFFER_SIZE, NULL, NULL) < 0)
|
||||
if (!WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, &err_string[len], ERR_BUFFER_SIZE - len, NULL, NULL))
|
||||
strcpy(err_string, "Unable to convert error string");
|
||||
}
|
||||
|
||||
return err_string;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ static int translate_driver_error(DWORD error)
|
|||
}
|
||||
}
|
||||
|
||||
static int init_dllimports(void)
|
||||
static BOOL init_dllimports(void)
|
||||
{
|
||||
DLL_GET_HANDLE(ceusbkwrapper);
|
||||
DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE);
|
||||
|
@ -135,7 +135,7 @@ static int init_dllimports(void)
|
|||
DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE);
|
||||
DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE);
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void exit_dllimports(void)
|
||||
|
@ -186,11 +186,8 @@ static int wince_init(struct libusb_context *ctx)
|
|||
// NB: concurrent usage supposes that init calls are equally balanced with
|
||||
// exit calls. If init is called more than exit, we will not exit properly
|
||||
if ( ++concurrent_usage == 0 ) { // First init?
|
||||
// Initialize pollable file descriptors
|
||||
init_polling();
|
||||
|
||||
// Load DLL imports
|
||||
if (init_dllimports() != LIBUSB_SUCCESS) {
|
||||
if (!init_dllimports()) {
|
||||
usbi_err(ctx, "could not resolve DLL functions");
|
||||
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
goto init_exit;
|
||||
|
@ -223,7 +220,6 @@ static int wince_init(struct libusb_context *ctx)
|
|||
init_exit: // Holds semaphore here.
|
||||
if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
|
||||
exit_dllimports();
|
||||
exit_polling();
|
||||
|
||||
if (driver_handle != INVALID_HANDLE_VALUE) {
|
||||
UkwCloseDriver(driver_handle);
|
||||
|
@ -239,10 +235,11 @@ init_exit: // Holds semaphore here.
|
|||
return r;
|
||||
}
|
||||
|
||||
static void wince_exit(void)
|
||||
static void wince_exit(struct libusb_context *ctx)
|
||||
{
|
||||
HANDLE semaphore;
|
||||
TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
|
||||
UNUSED(ctx);
|
||||
|
||||
_stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
|
||||
semaphore = CreateSemaphore(NULL, 1, 1, sem_name);
|
||||
|
@ -259,7 +256,6 @@ static void wince_exit(void)
|
|||
// Only works if exits and inits are balanced exactly
|
||||
if (--concurrent_usage < 0) { // Last exit
|
||||
exit_dllimports();
|
||||
exit_polling();
|
||||
|
||||
if (driver_handle != INVALID_HANDLE_VALUE) {
|
||||
UkwCloseDriver(driver_handle);
|
||||
|
@ -328,19 +324,19 @@ static int wince_get_device_list(
|
|||
}
|
||||
|
||||
new_devices = discovered_devs_append(new_devices, dev);
|
||||
if (!discdevs) {
|
||||
if (!new_devices) {
|
||||
r = LIBUSB_ERROR_NO_MEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
safe_unref_device(dev);
|
||||
libusb_unref_device(dev);
|
||||
}
|
||||
|
||||
*discdevs = new_devices;
|
||||
return r;
|
||||
err_out:
|
||||
*discdevs = new_devices;
|
||||
safe_unref_device(dev);
|
||||
libusb_unref_device(dev);
|
||||
// Release the remainder of the unprocessed device list.
|
||||
// The devices added to new_devices already will still be passed up to libusb,
|
||||
// which can dispose of them at its leisure.
|
||||
|
@ -541,12 +537,9 @@ static void wince_destroy_device(struct libusb_device *dev)
|
|||
static void wince_clear_transfer_priv(struct usbi_transfer *itransfer)
|
||||
{
|
||||
struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
|
||||
struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd);
|
||||
|
||||
// No need to cancel transfer as it is either complete or abandoned
|
||||
wfd.itransfer = NULL;
|
||||
CloseHandle(wfd.handle);
|
||||
usbi_free_fd(&transfer_priv->pollable_fd);
|
||||
usbi_close(transfer_priv->pollable_fd.fd);
|
||||
transfer_priv->pollable_fd = INVALID_WINFD;
|
||||
}
|
||||
|
||||
static int wince_cancel_transfer(struct usbi_transfer *itransfer)
|
||||
|
@ -570,11 +563,10 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer
|
|||
BOOL direction_in, ret;
|
||||
struct winfd wfd;
|
||||
DWORD flags;
|
||||
HANDLE eventHandle;
|
||||
PUKW_CONTROL_HEADER setup = NULL;
|
||||
const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL;
|
||||
int r;
|
||||
|
||||
transfer_priv->pollable_fd = INVALID_WINFD;
|
||||
if (control_transfer) {
|
||||
setup = (PUKW_CONTROL_HEADER) transfer->buffer;
|
||||
direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN;
|
||||
|
@ -584,19 +576,18 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer
|
|||
flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER;
|
||||
flags |= UKW_TF_SHORT_TRANSFER_OK;
|
||||
|
||||
eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (eventHandle == NULL) {
|
||||
usbi_err(ctx, "Failed to create event for async transfer");
|
||||
wfd = usbi_create_fd();
|
||||
if (wfd.fd < 0)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer);
|
||||
if (wfd.fd < 0) {
|
||||
CloseHandle(eventHandle);
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
r = usbi_add_pollfd(ctx, wfd.fd, direction_in ? POLLIN : POLLOUT);
|
||||
if (r) {
|
||||
usbi_close(wfd.fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
transfer_priv->pollable_fd = wfd;
|
||||
|
||||
if (control_transfer) {
|
||||
// Split out control setup header and data buffer
|
||||
DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER);
|
||||
|
@ -612,19 +603,16 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer
|
|||
int libusbErr = translate_driver_error(GetLastError());
|
||||
usbi_err(ctx, "UkwIssue%sTransfer failed: error %u",
|
||||
control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError());
|
||||
wince_clear_transfer_priv(itransfer);
|
||||
usbi_remove_pollfd(ctx, wfd.fd);
|
||||
usbi_close(wfd.fd);
|
||||
transfer_priv->pollable_fd = INVALID_WINFD;
|
||||
return libusbErr;
|
||||
}
|
||||
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT);
|
||||
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int wince_submit_iso_transfer(struct usbi_transfer *itransfer)
|
||||
{
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static int wince_submit_transfer(struct usbi_transfer *itransfer)
|
||||
{
|
||||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
|
@ -635,7 +623,6 @@ static int wince_submit_transfer(struct usbi_transfer *itransfer)
|
|||
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
||||
return wince_submit_control_or_bulk_transfer(itransfer);
|
||||
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
||||
return wince_submit_iso_transfer(itransfer);
|
||||
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
default:
|
||||
|
@ -763,7 +750,7 @@ static int wince_handle_events(
|
|||
struct wince_transfer_priv* transfer_priv = NULL;
|
||||
POLL_NFDS_TYPE i = 0;
|
||||
BOOL found = FALSE;
|
||||
struct usbi_transfer *transfer;
|
||||
struct usbi_transfer *itransfer;
|
||||
DWORD io_size, io_result;
|
||||
int r = LIBUSB_SUCCESS;
|
||||
|
||||
|
@ -780,8 +767,8 @@ static int wince_handle_events(
|
|||
// Because a Windows OVERLAPPED is used for poll emulation,
|
||||
// a pollable fd is created and stored with each transfer
|
||||
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
||||
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
|
||||
transfer_priv = usbi_transfer_get_os_priv(transfer);
|
||||
list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
|
||||
transfer_priv = usbi_transfer_get_os_priv(itransfer);
|
||||
if (transfer_priv->pollable_fd.fd == fds[i].fd) {
|
||||
found = TRUE;
|
||||
break;
|
||||
|
@ -796,7 +783,7 @@ static int wince_handle_events(
|
|||
// let handle_callback free the event using the transfer wfd
|
||||
// If you don't use the transfer wfd, you run a risk of trying to free a
|
||||
// newly allocated wfd that took the place of the one from the transfer.
|
||||
wince_handle_callback(transfer, io_result, io_size);
|
||||
wince_handle_callback(itransfer, io_result, io_size);
|
||||
} else if (found) {
|
||||
usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]);
|
||||
r = LIBUSB_ERROR_OTHER;
|
||||
|
@ -832,14 +819,14 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp)
|
|||
// Fall through and return real-time if monotonic read failed or was not detected @ init
|
||||
case USBI_CLOCK_REALTIME:
|
||||
// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
|
||||
// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
|
||||
// with a predef epoch time to have an epoch that starts at 1970.01.01 00:00
|
||||
// Note however that our resolution is bounded by the Windows system time
|
||||
// functions and is at best of the order of 1 ms (or, usually, worse)
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st, &filetime);
|
||||
rtime.LowPart = filetime.dwLowDateTime;
|
||||
rtime.HighPart = filetime.dwHighDateTime;
|
||||
rtime.QuadPart -= epoch_time;
|
||||
rtime.QuadPart -= EPOCH_TIME;
|
||||
tp->tv_sec = (long)(rtime.QuadPart / 10000000);
|
||||
tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
|
||||
return LIBUSB_SUCCESS;
|
||||
|
@ -848,11 +835,12 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp)
|
|||
}
|
||||
}
|
||||
|
||||
const struct usbi_os_backend wince_backend = {
|
||||
const struct usbi_os_backend usbi_backend = {
|
||||
"Windows CE",
|
||||
0,
|
||||
wince_init,
|
||||
wince_exit,
|
||||
NULL, /* set_option() */
|
||||
|
||||
wince_get_device_list,
|
||||
NULL, /* hotplug_poll */
|
||||
|
@ -893,6 +881,7 @@ const struct usbi_os_backend wince_backend = {
|
|||
NULL, /* handle_transfer_completion() */
|
||||
|
||||
wince_clock_gettime,
|
||||
0,
|
||||
sizeof(struct wince_device_priv),
|
||||
0,
|
||||
sizeof(struct wince_transfer_priv),
|
||||
|
|
|
@ -37,38 +37,23 @@
|
|||
#define false FALSE
|
||||
#endif
|
||||
|
||||
#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
|
||||
|
||||
#if defined(__CYGWIN__ )
|
||||
#define _stricmp strcasecmp
|
||||
#define _snprintf snprintf
|
||||
#define _strdup strdup
|
||||
// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
|
||||
#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f)
|
||||
#endif
|
||||
|
||||
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
|
||||
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
|
||||
#define safe_min(a, b) MIN((size_t)(a), (size_t)(b))
|
||||
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
|
||||
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
|
||||
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
|
||||
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
|
||||
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
|
||||
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<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)
|
||||
#define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0)
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
#define ERR_BUFFER_SIZE 256
|
||||
|
||||
|
||||
/*
|
||||
* API macros - leveraged from libusb-win32 1.x
|
||||
*/
|
||||
|
@ -83,31 +68,35 @@
|
|||
/*
|
||||
* Macros for handling DLL themselves
|
||||
*/
|
||||
#define DLL_HANDLE_NAME(name) __dll_##name##_handle
|
||||
|
||||
#define DLL_DECLARE_HANDLE(name) \
|
||||
static HMODULE __dll_##name##_handle = NULL
|
||||
static HMODULE DLL_HANDLE_NAME(name) = NULL
|
||||
|
||||
#define DLL_GET_HANDLE(name) \
|
||||
do { \
|
||||
__dll_##name##_handle = DLL_LOAD_LIBRARY(name); \
|
||||
if (!__dll_##name##_handle) \
|
||||
return LIBUSB_ERROR_OTHER; \
|
||||
DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \
|
||||
if (!DLL_HANDLE_NAME(name)) \
|
||||
return FALSE; \
|
||||
} while (0)
|
||||
|
||||
#define DLL_FREE_HANDLE(name) \
|
||||
do { \
|
||||
if (__dll_##name##_handle) { \
|
||||
FreeLibrary(__dll_##name##_handle); \
|
||||
__dll_##name##_handle = NULL; \
|
||||
if (DLL_HANDLE_NAME(name)) { \
|
||||
FreeLibrary(DLL_HANDLE_NAME(name)); \
|
||||
DLL_HANDLE_NAME(name) = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Macros for handling functions within a DLL
|
||||
*/
|
||||
#define DLL_FUNC_NAME(name) __dll_##name##_func_t
|
||||
|
||||
#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \
|
||||
typedef ret (api * __dll_##name##_func_t)args; \
|
||||
static __dll_##name##_func_t prefixname = NULL
|
||||
typedef ret (api * DLL_FUNC_NAME(name))args; \
|
||||
static DLL_FUNC_NAME(name) prefixname = NULL
|
||||
|
||||
#define DLL_DECLARE_FUNC(api, ret, name, args) \
|
||||
DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args)
|
||||
|
@ -116,22 +105,22 @@
|
|||
|
||||
#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
|
||||
do { \
|
||||
HMODULE h = __dll_##dll##_handle; \
|
||||
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \
|
||||
HMODULE h = DLL_HANDLE_NAME(dll); \
|
||||
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
|
||||
DLL_STRINGIFY(name)); \
|
||||
if (prefixname) \
|
||||
break; \
|
||||
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \
|
||||
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
|
||||
DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \
|
||||
if (prefixname) \
|
||||
break; \
|
||||
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \
|
||||
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
|
||||
DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \
|
||||
if (prefixname) \
|
||||
break; \
|
||||
if (ret_on_failure) \
|
||||
return LIBUSB_ERROR_NOT_FOUND; \
|
||||
} while(0)
|
||||
return FALSE; \
|
||||
} while (0)
|
||||
|
||||
#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \
|
||||
DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,48 +26,85 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// Missing from MinGW
|
||||
#if !defined(FACILITY_SETUPAPI)
|
||||
#define FACILITY_SETUPAPI 15
|
||||
#endif
|
||||
#include "windows_nt_shared_types.h"
|
||||
|
||||
typedef struct USB_CONFIGURATION_DESCRIPTOR {
|
||||
UCHAR bLength;
|
||||
UCHAR bDescriptorType;
|
||||
USHORT wTotalLength;
|
||||
UCHAR bNumInterfaces;
|
||||
UCHAR bConfigurationValue;
|
||||
UCHAR iConfiguration;
|
||||
UCHAR bmAttributes;
|
||||
UCHAR MaxPower;
|
||||
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
|
||||
/* Windows versions */
|
||||
enum windows_version {
|
||||
WINDOWS_UNDEFINED,
|
||||
WINDOWS_2000,
|
||||
WINDOWS_XP,
|
||||
WINDOWS_2003, // Also XP x64
|
||||
WINDOWS_VISTA,
|
||||
WINDOWS_7,
|
||||
WINDOWS_8,
|
||||
WINDOWS_8_1,
|
||||
WINDOWS_10,
|
||||
WINDOWS_11_OR_LATER
|
||||
};
|
||||
|
||||
typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
|
||||
extern enum windows_version windows_version;
|
||||
|
||||
int windows_common_init(struct libusb_context *ctx);
|
||||
void windows_common_exit(void);
|
||||
/* This call is only available from Vista */
|
||||
extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED);
|
||||
|
||||
struct windows_backend {
|
||||
int (*init)(struct libusb_context *ctx);
|
||||
void (*exit)(struct libusb_context *ctx);
|
||||
int (*get_device_list)(struct libusb_context *ctx,
|
||||
struct discovered_devs **discdevs);
|
||||
int (*open)(struct libusb_device_handle *dev_handle);
|
||||
void (*close)(struct libusb_device_handle *dev_handle);
|
||||
int (*get_device_descriptor)(struct libusb_device *device, unsigned char *buffer);
|
||||
int (*get_active_config_descriptor)(struct libusb_device *device,
|
||||
unsigned char *buffer, size_t len);
|
||||
int (*get_config_descriptor)(struct libusb_device *device,
|
||||
uint8_t config_index, unsigned char *buffer, size_t len);
|
||||
int (*get_config_descriptor_by_value)(struct libusb_device *device,
|
||||
uint8_t bConfigurationValue, unsigned char **buffer);
|
||||
int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config);
|
||||
int (*set_configuration)(struct libusb_device_handle *dev_handle, int config);
|
||||
int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number);
|
||||
int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number);
|
||||
int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
|
||||
int interface_number, int altsetting);
|
||||
int (*clear_halt)(struct libusb_device_handle *dev_handle,
|
||||
unsigned char endpoint);
|
||||
int (*reset_device)(struct libusb_device_handle *dev_handle);
|
||||
void (*destroy_device)(struct libusb_device *dev);
|
||||
int (*submit_transfer)(struct usbi_transfer *itransfer);
|
||||
int (*cancel_transfer)(struct usbi_transfer *itransfer);
|
||||
void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
|
||||
int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size);
|
||||
int (*get_transfer_fd)(struct usbi_transfer *itransfer);
|
||||
void (*get_overlapped_result)(struct usbi_transfer *itransfer,
|
||||
DWORD *io_result, DWORD *io_size);
|
||||
};
|
||||
|
||||
struct windows_context_priv {
|
||||
const struct windows_backend *backend;
|
||||
};
|
||||
|
||||
union windows_device_priv {
|
||||
struct usbdk_device_priv usbdk_priv;
|
||||
struct winusb_device_priv winusb_priv;
|
||||
};
|
||||
|
||||
union windows_device_handle_priv {
|
||||
struct usbdk_device_handle_priv usbdk_priv;
|
||||
struct winusb_device_handle_priv winusb_priv;
|
||||
};
|
||||
|
||||
union windows_transfer_priv {
|
||||
struct usbdk_transfer_priv usbdk_priv;
|
||||
struct winusb_transfer_priv winusb_priv;
|
||||
};
|
||||
|
||||
extern const struct windows_backend usbdk_backend;
|
||||
extern const struct windows_backend winusb_backend;
|
||||
|
||||
unsigned long htab_hash(const char *str);
|
||||
int windows_clock_gettime(int clk_id, struct timespec *tp);
|
||||
|
||||
typedef void(*CLEAR_TRANSFER_PRIV)(struct usbi_transfer *itransfer);
|
||||
typedef int(*COPY_TRANSFER_DATA)(struct usbi_transfer *itransfer, uint32_t io_size);
|
||||
typedef struct winfd *(*GET_FD)(struct usbi_transfer *transfer);
|
||||
typedef void(*GET_OVERLAPPED_RESULT)(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size);
|
||||
|
||||
typedef struct win_backend
|
||||
{
|
||||
CLEAR_TRANSFER_PRIV clear_transfer_priv;
|
||||
COPY_TRANSFER_DATA copy_transfer_data;
|
||||
GET_FD get_fd;
|
||||
GET_OVERLAPPED_RESULT get_overlapped_result;
|
||||
} win_backend;
|
||||
|
||||
void win_nt_init(win_backend *backend);
|
||||
|
||||
void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size);
|
||||
int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
|
||||
void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size);
|
||||
|
||||
#if defined(ENABLE_LOGGING)
|
||||
const char *windows_error_str(DWORD retval);
|
||||
const char *windows_error_str(DWORD error_code);
|
||||
#endif
|
||||
|
|
|
@ -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.
|
||||
};
|
|
@ -24,19 +24,11 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libusbi.h"
|
||||
#include "windows_common.h"
|
||||
#include "windows_nt_common.h"
|
||||
|
||||
#define ULONG64 uint64_t
|
||||
#define PVOID64 uint64_t
|
||||
|
||||
typedef CONST WCHAR *PCWCHAR;
|
||||
#define wcsncpy_s wcsncpy
|
||||
|
||||
#include "windows_usbdk.h"
|
||||
|
||||
#if !defined(STATUS_SUCCESS)
|
||||
|
@ -53,7 +45,7 @@ typedef LONG NTSTATUS;
|
|||
#endif
|
||||
|
||||
#if !defined(USBD_SUCCESS)
|
||||
typedef int32_t USBD_STATUS;
|
||||
typedef LONG USBD_STATUS;
|
||||
#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0)
|
||||
#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1)
|
||||
#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0)
|
||||
|
@ -64,24 +56,6 @@ typedef int32_t USBD_STATUS;
|
|||
#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000)
|
||||
#endif
|
||||
|
||||
static void backend_init(void);
|
||||
|
||||
static int concurrent_usage = -1;
|
||||
|
||||
struct usbdk_device_priv {
|
||||
USB_DK_DEVICE_INFO info;
|
||||
PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
|
||||
HANDLE redirector_handle;
|
||||
uint8_t active_configuration;
|
||||
};
|
||||
|
||||
struct usbdk_transfer_priv {
|
||||
USB_DK_TRANSFER_REQUEST request;
|
||||
struct winfd pollable_fd;
|
||||
PULONG64 IsochronousPacketsArray;
|
||||
PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray;
|
||||
};
|
||||
|
||||
static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev)
|
||||
{
|
||||
return (struct usbdk_device_priv *)dev->os_priv;
|
||||
|
@ -115,7 +89,7 @@ static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name)
|
|||
FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
|
||||
|
||||
if (api_ptr == NULL)
|
||||
usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError());
|
||||
usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0));
|
||||
|
||||
return api_ptr;
|
||||
}
|
||||
|
@ -132,7 +106,7 @@ static int load_usbdk_helper_dll(struct libusb_context *ctx)
|
|||
{
|
||||
usbdk_helper.module = LoadLibraryA("UsbDkHelper");
|
||||
if (usbdk_helper.module == NULL) {
|
||||
usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError());
|
||||
usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0));
|
||||
return LIBUSB_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
@ -198,44 +172,41 @@ error_unload:
|
|||
|
||||
static int usbdk_init(struct libusb_context *ctx)
|
||||
{
|
||||
int r;
|
||||
SC_HANDLE managerHandle;
|
||||
SC_HANDLE serviceHandle;
|
||||
|
||||
if (++concurrent_usage == 0) { // First init?
|
||||
|
||||
backend_init();
|
||||
|
||||
r = load_usbdk_helper_dll(ctx);
|
||||
if (r)
|
||||
goto init_exit;
|
||||
|
||||
init_polling();
|
||||
|
||||
r = windows_common_init(ctx);
|
||||
if (r)
|
||||
goto init_exit;
|
||||
managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||||
if (managerHandle == NULL) {
|
||||
usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0));
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
// 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();
|
||||
serviceHandle = OpenServiceA(managerHandle, "UsbDk", GENERIC_READ);
|
||||
CloseServiceHandle(managerHandle);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (r != LIBUSB_SUCCESS)
|
||||
--concurrent_usage; // Not expected to call libusb_exit if we failed.
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int usbdk_get_session_id_for_device(struct libusb_context *ctx,
|
||||
PUSB_DK_DEVICE_ID id, unsigned long *session_id)
|
||||
{
|
||||
char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)];
|
||||
char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1];
|
||||
|
||||
if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) {
|
||||
if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) {
|
||||
usbi_warn(ctx, "cannot form device identity", id->DeviceID);
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
@ -299,11 +270,11 @@ static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info)
|
|||
dev->port_number = (uint8_t)info->Port;
|
||||
dev->parent_dev = NULL;
|
||||
|
||||
//Addresses in libusb are 1-based
|
||||
// Addresses in libusb are 1-based
|
||||
dev->device_address = (uint8_t)(info->Port + 1);
|
||||
|
||||
dev->num_configurations = info->DeviceDescriptor.bNumConfigurations;
|
||||
dev->device_descriptor = info->DeviceDescriptor;
|
||||
memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
|
||||
|
||||
switch (info->Speed) {
|
||||
case LowSpeed:
|
||||
|
@ -333,7 +304,7 @@ static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_d
|
|||
ULONG dev_number;
|
||||
PUSB_DK_DEVICE_INFO devices;
|
||||
|
||||
if(!usbdk_helper.GetDevicesList(&devices, &dev_number))
|
||||
if (!usbdk_helper.GetDevicesList(&devices, &dev_number))
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
|
||||
for (i = 0; i < dev_number; i++) {
|
||||
|
@ -374,26 +345,16 @@ func_exit:
|
|||
return r;
|
||||
}
|
||||
|
||||
static void usbdk_exit(void)
|
||||
{
|
||||
if (--concurrent_usage < 0) {
|
||||
windows_common_exit();
|
||||
exit_polling();
|
||||
unload_usbdk_helper_dll();
|
||||
}
|
||||
}
|
||||
|
||||
static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian)
|
||||
static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer)
|
||||
{
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
|
||||
|
||||
memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH);
|
||||
*host_endian = 0;
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
|
||||
static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len)
|
||||
{
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
|
||||
PUSB_CONFIGURATION_DESCRIPTOR config_header;
|
||||
|
@ -406,15 +367,31 @@ static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config
|
|||
|
||||
size = min(config_header->wTotalLength, len);
|
||||
memcpy(buffer, config_header, size);
|
||||
*host_endian = 0;
|
||||
|
||||
return (int)size;
|
||||
}
|
||||
|
||||
static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
|
||||
static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
|
||||
unsigned char **buffer)
|
||||
{
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
|
||||
PUSB_CONFIGURATION_DESCRIPTOR config_header;
|
||||
uint8_t index;
|
||||
|
||||
for (index = 0; index < dev->num_configurations; index++) {
|
||||
config_header = priv->config_descriptors[index];
|
||||
if (config_header->bConfigurationValue == bConfigurationValue) {
|
||||
*buffer = (unsigned char *)priv->config_descriptors[index];
|
||||
return (int)config_header->wTotalLength;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBUSB_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
static int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len)
|
||||
{
|
||||
return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration,
|
||||
buffer, len, host_endian);
|
||||
buffer, len);
|
||||
}
|
||||
|
||||
static int usbdk_open(struct libusb_device_handle *dev_handle)
|
||||
|
@ -427,6 +404,8 @@ static int usbdk_open(struct libusb_device_handle *dev_handle)
|
|||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
|
||||
priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -434,10 +413,8 @@ static void usbdk_close(struct libusb_device_handle *dev_handle)
|
|||
{
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
|
||||
|
||||
if (!usbdk_helper.StopRedirect(priv->redirector_handle)) {
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
||||
usbi_err(ctx, "Redirector shutdown failed");
|
||||
}
|
||||
if (!usbdk_helper.StopRedirect(priv->redirector_handle))
|
||||
usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed");
|
||||
}
|
||||
|
||||
static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config)
|
||||
|
@ -463,7 +440,7 @@ static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int if
|
|||
|
||||
static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
|
||||
{
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
||||
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
|
||||
|
||||
if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) {
|
||||
|
@ -483,7 +460,7 @@ static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int
|
|||
|
||||
static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
|
||||
{
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
||||
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
|
||||
|
||||
if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) {
|
||||
|
@ -496,7 +473,7 @@ static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned ch
|
|||
|
||||
static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
|
||||
{
|
||||
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
||||
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
|
||||
|
||||
if (!usbdk_helper.ResetDevice(priv->redirector_handle)) {
|
||||
|
@ -507,27 +484,6 @@ static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface)
|
||||
{
|
||||
UNUSED(dev_handle);
|
||||
UNUSED(iface);
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
|
||||
{
|
||||
UNUSED(dev_handle);
|
||||
UNUSED(iface);
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static int usbdk_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
|
||||
{
|
||||
UNUSED(dev_handle);
|
||||
UNUSED(iface);
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static void usbdk_destroy_device(struct libusb_device *dev)
|
||||
{
|
||||
struct usbdk_device_priv* p = _usbdk_device_priv(dev);
|
||||
|
@ -536,12 +492,14 @@ static void usbdk_destroy_device(struct libusb_device *dev)
|
|||
usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations);
|
||||
}
|
||||
|
||||
static void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
|
||||
static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer)
|
||||
{
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
|
||||
usbi_free_fd(&transfer_priv->pollable_fd);
|
||||
usbi_close(transfer_priv->pollable_fd.fd);
|
||||
transfer_priv->pollable_fd = INVALID_WINFD;
|
||||
transfer_priv->system_handle = NULL;
|
||||
|
||||
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
|
||||
safe_free(transfer_priv->IsochronousPacketsArray);
|
||||
|
@ -554,47 +512,30 @@ static int usbdk_do_control_transfer(struct usbi_transfer *itransfer)
|
|||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
||||
struct winfd wfd;
|
||||
ULONG Length;
|
||||
struct libusb_context *ctx = TRANSFER_CTX(transfer);
|
||||
OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
|
||||
TransferResult transResult;
|
||||
HANDLE sysHandle;
|
||||
|
||||
sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
|
||||
|
||||
wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL);
|
||||
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
||||
if (wfd.fd < 0)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
|
||||
transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer;
|
||||
transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
|
||||
transfer_priv->request.BufferLength = transfer->length;
|
||||
transfer_priv->request.TransferType = ControlTransferType;
|
||||
transfer_priv->pollable_fd = INVALID_WINFD;
|
||||
Length = (ULONG)transfer->length;
|
||||
|
||||
if (IS_XFERIN(transfer))
|
||||
transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
|
||||
if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN)
|
||||
transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
|
||||
else
|
||||
transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
|
||||
transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
|
||||
|
||||
switch (transResult) {
|
||||
case TransferSuccess:
|
||||
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
||||
wfd.overlapped->InternalHigh = (DWORD)Length;
|
||||
windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
|
||||
break;
|
||||
case TransferSuccessAsync:
|
||||
break;
|
||||
case TransferFailure:
|
||||
usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0));
|
||||
usbi_free_fd(&wfd);
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
|
||||
// Use priv_transfer to store data needed for async polling
|
||||
transfer_priv->pollable_fd = wfd;
|
||||
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -603,12 +544,11 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
|
|||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
||||
struct winfd wfd;
|
||||
struct libusb_context *ctx = TRANSFER_CTX(transfer);
|
||||
OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
|
||||
TransferResult transferRes;
|
||||
HANDLE sysHandle;
|
||||
|
||||
transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer;
|
||||
transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
|
||||
transfer_priv->request.BufferLength = transfer->length;
|
||||
transfer_priv->request.EndpointAddress = transfer->endpoint;
|
||||
|
||||
|
@ -617,42 +557,29 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
|
|||
transfer_priv->request.TransferType = BulkTransferType;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
||||
transfer_priv->request.TransferType = IntertuptTransferType;
|
||||
transfer_priv->request.TransferType = InterruptTransferType;
|
||||
break;
|
||||
default:
|
||||
usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0));
|
||||
usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer", transfer->type);
|
||||
return LIBUSB_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
transfer_priv->pollable_fd = INVALID_WINFD;
|
||||
|
||||
sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
|
||||
|
||||
wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
|
||||
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
||||
if (wfd.fd < 0)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
|
||||
if (IS_XFERIN(transfer))
|
||||
transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
|
||||
transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
|
||||
else
|
||||
transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
|
||||
transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
|
||||
|
||||
switch (transferRes) {
|
||||
case TransferSuccess:
|
||||
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
||||
windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
|
||||
break;
|
||||
case TransferSuccessAsync:
|
||||
break;
|
||||
case TransferFailure:
|
||||
usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
|
||||
usbi_free_fd(&wfd);
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
|
||||
transfer_priv->pollable_fd = wfd;
|
||||
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT);
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -661,68 +588,81 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
|
|||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
||||
struct winfd wfd;
|
||||
struct libusb_context *ctx = TRANSFER_CTX(transfer);
|
||||
OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
|
||||
TransferResult transferRes;
|
||||
int i;
|
||||
HANDLE sysHandle;
|
||||
|
||||
transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer;
|
||||
transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
|
||||
transfer_priv->request.BufferLength = transfer->length;
|
||||
transfer_priv->request.EndpointAddress = transfer->endpoint;
|
||||
transfer_priv->request.TransferType = IsochronousTransferType;
|
||||
transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets;
|
||||
transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64));
|
||||
transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray;
|
||||
transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray;
|
||||
if (!transfer_priv->IsochronousPacketsArray) {
|
||||
usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0));
|
||||
return LIBUSB_ERROR_IO;
|
||||
usbi_err(ctx, "Allocation of IsochronousPacketsArray failed");
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT));
|
||||
transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray;
|
||||
transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray;
|
||||
if (!transfer_priv->IsochronousResultsArray) {
|
||||
usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0));
|
||||
free(transfer_priv->IsochronousPacketsArray);
|
||||
return LIBUSB_ERROR_IO;
|
||||
usbi_err(ctx, "Allocation of isochronousResultsArray failed");
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < transfer->num_iso_packets; i++)
|
||||
transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length;
|
||||
|
||||
transfer_priv->pollable_fd = INVALID_WINFD;
|
||||
|
||||
sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
|
||||
|
||||
wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
|
||||
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
||||
if (wfd.fd < 0) {
|
||||
free(transfer_priv->IsochronousPacketsArray);
|
||||
free(transfer_priv->IsochronousResultsArray);
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
if (IS_XFERIN(transfer))
|
||||
transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
|
||||
transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
|
||||
else
|
||||
transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped);
|
||||
transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
|
||||
|
||||
switch (transferRes) {
|
||||
case TransferSuccess:
|
||||
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
||||
windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
|
||||
break;
|
||||
case TransferSuccessAsync:
|
||||
break;
|
||||
case TransferFailure:
|
||||
usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
|
||||
usbi_free_fd(&wfd);
|
||||
free(transfer_priv->IsochronousPacketsArray);
|
||||
free(transfer_priv->IsochronousResultsArray);
|
||||
return LIBUSB_ERROR_IO;
|
||||
}
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer,
|
||||
short events, int (*transfer_fn)(struct usbi_transfer *))
|
||||
{
|
||||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
struct libusb_context *ctx = TRANSFER_CTX(transfer);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
struct winfd wfd;
|
||||
int r;
|
||||
|
||||
wfd = usbi_create_fd();
|
||||
if (wfd.fd < 0)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
|
||||
r = usbi_add_pollfd(ctx, wfd.fd, events);
|
||||
if (r) {
|
||||
usbi_close(wfd.fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Use transfer_priv to store data needed for async polling
|
||||
transfer_priv->pollable_fd = wfd;
|
||||
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT);
|
||||
transfer_priv->system_handle = priv->system_handle;
|
||||
|
||||
r = transfer_fn(itransfer);
|
||||
if (r != LIBUSB_SUCCESS) {
|
||||
usbi_remove_pollfd(ctx, wfd.fd);
|
||||
usbdk_clear_transfer_priv(itransfer);
|
||||
return r;
|
||||
}
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
@ -730,34 +670,53 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
|
|||
static int usbdk_submit_transfer(struct usbi_transfer *itransfer)
|
||||
{
|
||||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
int (*transfer_fn)(struct usbi_transfer *);
|
||||
short events;
|
||||
|
||||
switch (transfer->type) {
|
||||
case LIBUSB_TRANSFER_TYPE_CONTROL:
|
||||
return usbdk_do_control_transfer(itransfer);
|
||||
events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT;
|
||||
transfer_fn = usbdk_do_control_transfer;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_TYPE_BULK:
|
||||
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
||||
if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk
|
||||
else
|
||||
return usbdk_do_bulk_transfer(itransfer);
|
||||
events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
|
||||
transfer_fn = usbdk_do_bulk_transfer;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
||||
return usbdk_do_iso_transfer(itransfer);
|
||||
events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
|
||||
transfer_fn = usbdk_do_iso_transfer;
|
||||
break;
|
||||
default:
|
||||
usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
|
||||
return LIBUSB_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return usbdk_do_submit_transfer(itransfer, events, transfer_fn);
|
||||
}
|
||||
|
||||
static int usbdk_abort_transfers(struct usbi_transfer *itransfer)
|
||||
{
|
||||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
||||
struct libusb_context *ctx = TRANSFER_CTX(transfer);
|
||||
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
struct winfd *pollable_fd = &transfer_priv->pollable_fd;
|
||||
|
||||
if (pCancelIoEx != NULL) {
|
||||
// Use CancelIoEx if available to cancel just a single transfer
|
||||
if (!pCancelIoEx(priv->system_handle, pollable_fd->overlapped)) {
|
||||
usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0));
|
||||
return LIBUSB_ERROR_NO_DEVICE;
|
||||
}
|
||||
} else {
|
||||
if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) {
|
||||
usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
|
||||
return LIBUSB_ERROR_NO_DEVICE;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
@ -781,16 +740,16 @@ static int usbdk_cancel_transfer(struct usbi_transfer *itransfer)
|
|||
}
|
||||
}
|
||||
|
||||
static int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
|
||||
static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
|
||||
{
|
||||
itransfer->transferred += io_size;
|
||||
return LIBUSB_TRANSFER_COMPLETED;
|
||||
}
|
||||
|
||||
static struct winfd *windows_get_fd(struct usbi_transfer *transfer)
|
||||
static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer)
|
||||
{
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer);
|
||||
return &transfer_priv->pollable_fd;
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
return transfer_priv->pollable_fd.fd;
|
||||
}
|
||||
|
||||
static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus)
|
||||
|
@ -799,30 +758,28 @@ static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus)
|
|||
return NO_ERROR;
|
||||
|
||||
switch (UsbdStatus) {
|
||||
case USBD_STATUS_STALL_PID:
|
||||
case USBD_STATUS_ENDPOINT_HALTED:
|
||||
case USBD_STATUS_BAD_START_FRAME:
|
||||
return ERROR_GEN_FAILURE;
|
||||
case USBD_STATUS_TIMEOUT:
|
||||
return ERROR_SEM_TIMEOUT;
|
||||
case USBD_STATUS_CANCELED:
|
||||
return ERROR_OPERATION_ABORTED;
|
||||
default:
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
return ERROR_GEN_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
static void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size)
|
||||
static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size)
|
||||
{
|
||||
if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first
|
||||
|| GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped
|
||||
struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer);
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer);
|
||||
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|
||||
struct winfd *pollable_fd = &transfer_priv->pollable_fd;
|
||||
|
||||
if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
|
||||
int i;
|
||||
if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first
|
||||
|| GetOverlappedResult(transfer_priv->system_handle, pollable_fd->overlapped, io_size, FALSE)) { // Regular async overlapped
|
||||
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
|
||||
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
|
||||
ULONG64 i;
|
||||
for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
|
||||
struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i];
|
||||
struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
|
||||
|
||||
switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
|
||||
case STATUS_SUCCESS:
|
||||
|
@ -839,78 +796,35 @@ static void windows_get_overlapped_result(struct usbi_transfer *transfer, struct
|
|||
}
|
||||
}
|
||||
|
||||
*io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred;
|
||||
*io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus);
|
||||
}
|
||||
else {
|
||||
*io_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred;
|
||||
*io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
|
||||
} else {
|
||||
*io_result = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
static int usbdk_clock_gettime(int clk_id, struct timespec *tp)
|
||||
{
|
||||
return windows_clock_gettime(clk_id, tp);
|
||||
}
|
||||
|
||||
const struct usbi_os_backend usbdk_backend = {
|
||||
"Windows",
|
||||
USBI_CAP_HAS_HID_ACCESS,
|
||||
const struct windows_backend usbdk_backend = {
|
||||
usbdk_init,
|
||||
usbdk_exit,
|
||||
|
||||
usbdk_get_device_list,
|
||||
NULL,
|
||||
usbdk_open,
|
||||
usbdk_close,
|
||||
|
||||
usbdk_get_device_descriptor,
|
||||
usbdk_get_active_config_descriptor,
|
||||
usbdk_get_config_descriptor,
|
||||
NULL,
|
||||
|
||||
usbdk_get_config_descriptor_by_value,
|
||||
usbdk_get_configuration,
|
||||
usbdk_set_configuration,
|
||||
usbdk_claim_interface,
|
||||
usbdk_release_interface,
|
||||
|
||||
usbdk_set_interface_altsetting,
|
||||
usbdk_clear_halt,
|
||||
usbdk_reset_device,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL, // dev_mem_alloc()
|
||||
NULL, // dev_mem_free()
|
||||
|
||||
usbdk_kernel_driver_active,
|
||||
usbdk_detach_kernel_driver,
|
||||
usbdk_attach_kernel_driver,
|
||||
|
||||
usbdk_destroy_device,
|
||||
|
||||
usbdk_submit_transfer,
|
||||
usbdk_cancel_transfer,
|
||||
windows_clear_transfer_priv,
|
||||
|
||||
windows_handle_events,
|
||||
NULL,
|
||||
|
||||
usbdk_clock_gettime,
|
||||
#if defined(USBI_TIMERFD_AVAILABLE)
|
||||
NULL,
|
||||
#endif
|
||||
sizeof(struct usbdk_device_priv),
|
||||
0,
|
||||
sizeof(struct usbdk_transfer_priv),
|
||||
usbdk_clear_transfer_priv,
|
||||
usbdk_copy_transfer_data,
|
||||
usbdk_get_transfer_fd,
|
||||
usbdk_get_overlapped_result,
|
||||
};
|
||||
|
||||
static void backend_init(void)
|
||||
{
|
||||
win_backend backend;
|
||||
backend.clear_transfer_priv = windows_clear_transfer_priv;
|
||||
backend.copy_transfer_data = windows_copy_transfer_data;
|
||||
backend.get_fd = windows_get_fd;
|
||||
backend.get_overlapped_result = windows_get_overlapped_result;
|
||||
win_nt_init(&backend);
|
||||
}
|
||||
|
|
|
@ -23,56 +23,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
typedef struct tag_USB_DK_DEVICE_ID {
|
||||
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
|
||||
WCHAR InstanceID[MAX_DEVICE_ID_LEN];
|
||||
} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
|
||||
#include "windows_nt_common.h"
|
||||
|
||||
static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID)
|
||||
{
|
||||
wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN);
|
||||
wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN);
|
||||
}
|
||||
|
||||
typedef struct tag_USB_DK_DEVICE_INFO {
|
||||
USB_DK_DEVICE_ID ID;
|
||||
ULONG64 FilterID;
|
||||
ULONG64 Port;
|
||||
ULONG64 Speed;
|
||||
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||
} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;
|
||||
|
||||
typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST {
|
||||
typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST {
|
||||
USB_DK_DEVICE_ID ID;
|
||||
ULONG64 Index;
|
||||
} USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST;
|
||||
|
||||
typedef struct tag_USB_DK_ISO_TRANSFER_RESULT {
|
||||
ULONG64 ActualLength;
|
||||
ULONG64 TransferResult;
|
||||
} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;
|
||||
|
||||
typedef struct tag_USB_DK_GEN_TRANSFER_RESULT {
|
||||
ULONG64 BytesTransferred;
|
||||
ULONG64 UsbdStatus; // USBD_STATUS code
|
||||
} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;
|
||||
|
||||
typedef struct tag_USB_DK_TRANSFER_RESULT {
|
||||
USB_DK_GEN_TRANSFER_RESULT GenResult;
|
||||
PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
|
||||
} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;
|
||||
|
||||
typedef struct tag_USB_DK_TRANSFER_REQUEST {
|
||||
ULONG64 EndpointAddress;
|
||||
PVOID64 Buffer;
|
||||
ULONG64 BufferLength;
|
||||
ULONG64 TransferType;
|
||||
ULONG64 IsochronousPacketsArraySize;
|
||||
PVOID64 IsochronousPacketsArray;
|
||||
|
||||
USB_DK_TRANSFER_RESULT Result;
|
||||
} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;
|
||||
|
||||
typedef enum {
|
||||
TransferFailure = 0,
|
||||
TransferSuccess,
|
||||
|
@ -90,7 +47,7 @@ typedef enum {
|
|||
typedef enum {
|
||||
ControlTransferType,
|
||||
BulkTransferType,
|
||||
IntertuptTransferType,
|
||||
InterruptTransferType,
|
||||
IsochronousTransferType
|
||||
} USB_DK_TRANSFER_TYPE;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -36,15 +36,14 @@
|
|||
#endif
|
||||
|
||||
// Missing from MSVC6 setupapi.h
|
||||
#if !defined(SPDRP_ADDRESS)
|
||||
#ifndef SPDRP_ADDRESS
|
||||
#define SPDRP_ADDRESS 28
|
||||
#endif
|
||||
#if !defined(SPDRP_INSTALL_STATE)
|
||||
#ifndef SPDRP_INSTALL_STATE
|
||||
#define SPDRP_INSTALL_STATE 34
|
||||
#endif
|
||||
|
||||
#define MAX_CTRL_BUFFER_LENGTH 4096
|
||||
#define MAX_USB_DEVICES 256
|
||||
#define MAX_USB_STRING_LENGTH 128
|
||||
#define MAX_HID_REPORT_SIZE 1024
|
||||
#define MAX_HID_DESCRIPTOR_SIZE 256
|
||||
|
@ -61,17 +60,17 @@
|
|||
// http://msdn.microsoft.com/en-us/library/ff545978.aspx
|
||||
// http://msdn.microsoft.com/en-us/library/ff545972.aspx
|
||||
// http://msdn.microsoft.com/en-us/library/ff545982.aspx
|
||||
#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER)
|
||||
const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} };
|
||||
#ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER
|
||||
const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}};
|
||||
#endif
|
||||
#if !defined(GUID_DEVINTERFACE_USB_DEVICE)
|
||||
const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
|
||||
#ifndef GUID_DEVINTERFACE_USB_DEVICE
|
||||
const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
|
||||
#endif
|
||||
#if !defined(GUID_DEVINTERFACE_USB_HUB)
|
||||
const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} };
|
||||
#ifndef GUID_DEVINTERFACE_USB_HUB
|
||||
const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}};
|
||||
#endif
|
||||
#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER)
|
||||
const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} };
|
||||
#ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER
|
||||
const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}};
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -84,8 +83,6 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8
|
|||
#define USB_API_WINUSBX 3
|
||||
#define USB_API_HID 4
|
||||
#define USB_API_MAX 5
|
||||
// The following is used to indicate if the HID or composite extra props have already been set.
|
||||
#define USB_API_SET (1 << USB_API_MAX)
|
||||
|
||||
// Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL)
|
||||
// Must have the same values as the KUSB_DRVID enum from libusbk.h
|
||||
|
@ -95,15 +92,13 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8
|
|||
#define SUB_API_WINUSB 2
|
||||
#define SUB_API_MAX 3
|
||||
|
||||
#define WINUSBX_DRV_NAMES {"libusbK", "libusb0", "WinUSB"}
|
||||
|
||||
struct windows_usb_api_backend {
|
||||
const uint8_t id;
|
||||
const char *designation;
|
||||
const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
|
||||
const char * const designation;
|
||||
const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
|
||||
const uint8_t nb_driver_names;
|
||||
int (*init)(int sub_api, struct libusb_context *ctx);
|
||||
int (*exit)(int sub_api);
|
||||
int (*init)(struct libusb_context *ctx);
|
||||
void (*exit)(void);
|
||||
int (*open)(int sub_api, struct libusb_device_handle *dev_handle);
|
||||
void (*close)(int sub_api, struct libusb_device_handle *dev_handle);
|
||||
int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
||||
|
@ -123,9 +118,16 @@ struct windows_usb_api_backend {
|
|||
extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
|
||||
|
||||
#define PRINT_UNSUPPORTED_API(fname) \
|
||||
usbi_dbg("unsupported API call for '" \
|
||||
#fname "' (unrecognized device driver)"); \
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED;
|
||||
usbi_dbg("unsupported API call for '%s' " \
|
||||
"(unrecognized device driver)", #fname)
|
||||
|
||||
#define CHECK_SUPPORTED_API(apip, fname) \
|
||||
do { \
|
||||
if ((apip)->fname == NULL) { \
|
||||
PRINT_UNSUPPORTED_API(fname); \
|
||||
return LIBUSB_ERROR_NOT_SUPPORTED; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* private structures definition
|
||||
|
@ -154,15 +156,16 @@ struct libusb_hid_descriptor {
|
|||
#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN)
|
||||
#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type))
|
||||
|
||||
#ifndef CTL_CODE
|
||||
#define CTL_CODE(DeviceType, Function, Method, Access) \
|
||||
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
|
||||
#endif
|
||||
|
||||
// The following are used for HID reports IOCTLs
|
||||
#define HID_CTL_CODE(id) \
|
||||
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define HID_BUFFER_CTL_CODE(id) \
|
||||
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HID_IN_CTL_CODE(id) \
|
||||
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define HID_OUT_CTL_CODE(id) \
|
||||
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
|
||||
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
|
||||
|
@ -193,106 +196,57 @@ struct hid_device_priv {
|
|||
uint16_t input_report_size;
|
||||
uint16_t output_report_size;
|
||||
uint16_t feature_report_size;
|
||||
uint16_t usage;
|
||||
uint16_t usagePage;
|
||||
WCHAR string[3][MAX_USB_STRING_LENGTH];
|
||||
uint8_t string_index[3]; // man, prod, ser
|
||||
};
|
||||
|
||||
struct windows_device_priv {
|
||||
uint8_t depth; // distance to HCD
|
||||
uint8_t port; // port number on the hub
|
||||
uint8_t active_config;
|
||||
struct windows_usb_api_backend const *apib;
|
||||
char *path; // device interface path
|
||||
int sub_api; // for WinUSB-like APIs
|
||||
struct {
|
||||
char *path; // each interface needs a device interface path,
|
||||
struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support),
|
||||
int sub_api;
|
||||
int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
|
||||
uint8_t *endpoint;
|
||||
bool restricted_functionality; // indicates if the interface functionality is restricted
|
||||
// by Windows (eg. HID keyboards or mice cannot do R/W)
|
||||
} usb_interface[USB_MAXINTERFACES];
|
||||
struct hid_device_priv *hid;
|
||||
USB_DEVICE_DESCRIPTOR dev_descriptor;
|
||||
unsigned char **config_descriptor; // list of pointers to the cached config descriptors
|
||||
};
|
||||
|
||||
static inline struct windows_device_priv *_device_priv(struct libusb_device *dev)
|
||||
static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev)
|
||||
{
|
||||
return (struct windows_device_priv *)dev->os_priv;
|
||||
return (struct winusb_device_priv *)dev->os_priv;
|
||||
}
|
||||
|
||||
static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev)
|
||||
static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev)
|
||||
{
|
||||
struct windows_device_priv *p = _device_priv(dev);
|
||||
struct winusb_device_priv *p = _device_priv(dev);
|
||||
int i;
|
||||
|
||||
p->depth = 0;
|
||||
p->port = 0;
|
||||
p->path = NULL;
|
||||
p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
|
||||
p->sub_api = SUB_API_NOTSET;
|
||||
p->hid = NULL;
|
||||
p->active_config = 0;
|
||||
p->config_descriptor = NULL;
|
||||
memset(&p->dev_descriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
||||
p->usb_interface[i].path = NULL;
|
||||
p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED];
|
||||
p->usb_interface[i].sub_api = SUB_API_NOTSET;
|
||||
p->usb_interface[i].nb_endpoints = 0;
|
||||
p->usb_interface[i].endpoint = NULL;
|
||||
p->usb_interface[i].restricted_functionality = false;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void windows_device_priv_release(struct libusb_device *dev)
|
||||
static inline void winusb_device_priv_release(struct libusb_device *dev)
|
||||
{
|
||||
struct windows_device_priv *p = _device_priv(dev);
|
||||
struct winusb_device_priv *p = _device_priv(dev);
|
||||
int i;
|
||||
|
||||
safe_free(p->path);
|
||||
free(p->dev_id);
|
||||
free(p->path);
|
||||
if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
|
||||
for (i = 0; i < dev->num_configurations; i++)
|
||||
safe_free(p->config_descriptor[i]);
|
||||
free(p->config_descriptor[i]);
|
||||
}
|
||||
safe_free(p->config_descriptor);
|
||||
safe_free(p->hid);
|
||||
free(p->config_descriptor);
|
||||
free(p->hid);
|
||||
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
||||
safe_free(p->usb_interface[i].path);
|
||||
safe_free(p->usb_interface[i].endpoint);
|
||||
free(p->usb_interface[i].path);
|
||||
free(p->usb_interface[i].endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
struct interface_handle_t {
|
||||
HANDLE dev_handle; // WinUSB needs an extra handle for the file
|
||||
HANDLE api_handle; // used by the API to communicate with the device
|
||||
};
|
||||
|
||||
struct windows_device_handle_priv {
|
||||
int active_interface;
|
||||
struct interface_handle_t interface_handle[USB_MAXINTERFACES];
|
||||
int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
|
||||
};
|
||||
|
||||
static inline struct windows_device_handle_priv *_device_handle_priv(
|
||||
static inline struct winusb_device_handle_priv *_device_handle_priv(
|
||||
struct libusb_device_handle *handle)
|
||||
{
|
||||
return (struct windows_device_handle_priv *)handle->os_priv;
|
||||
return (struct winusb_device_handle_priv *)handle->os_priv;
|
||||
}
|
||||
|
||||
// used for async polling functions
|
||||
struct windows_transfer_priv {
|
||||
struct winfd pollable_fd;
|
||||
uint8_t interface_number;
|
||||
uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
|
||||
uint8_t *hid_dest; // transfer buffer destination, required for HID
|
||||
size_t hid_expected_size;
|
||||
};
|
||||
|
||||
// used to match a device driver (including filter drivers) against a supported API
|
||||
struct driver_lookup {
|
||||
char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names
|
||||
|
@ -300,34 +254,6 @@ struct driver_lookup {
|
|||
const char* designation; // internal designation (for debug output)
|
||||
};
|
||||
|
||||
/* OLE32 dependency */
|
||||
DLL_DECLARE_HANDLE(OLE32);
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID));
|
||||
|
||||
/* Kernel32 dependencies */
|
||||
DLL_DECLARE_HANDLE(Kernel32);
|
||||
/* This call is only available from XP SP2 */
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL));
|
||||
|
||||
/* SetupAPI dependencies */
|
||||
DLL_DECLARE_HANDLE(SetupAPI);
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA,
|
||||
const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA,
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
|
||||
PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD));
|
||||
|
||||
/* AdvAPI32 dependencies */
|
||||
DLL_DECLARE_HANDLE(AdvAPI32);
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
|
||||
|
||||
/*
|
||||
* Windows DDK API definitions. Most of it copied from MinGW's includes
|
||||
*/
|
||||
|
@ -337,57 +263,63 @@ typedef DWORD RETURN_TYPE;
|
|||
typedef RETURN_TYPE CONFIGRET;
|
||||
|
||||
#define CR_SUCCESS 0x00000000
|
||||
#define CR_NO_SUCH_DEVNODE 0x0000000D
|
||||
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG
|
||||
#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT
|
||||
/* Cfgmgr32 dependencies */
|
||||
DLL_DECLARE_HANDLE(Cfgmgr32);
|
||||
DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
|
||||
|
||||
#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS
|
||||
#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE
|
||||
#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE
|
||||
#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS
|
||||
#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR
|
||||
#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR
|
||||
#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION
|
||||
#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION
|
||||
#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE
|
||||
#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE
|
||||
#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME
|
||||
/* AdvAPI32 dependencies */
|
||||
DLL_DECLARE_HANDLE(AdvAPI32);
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
|
||||
|
||||
#define USB_GET_NODE_INFORMATION 258
|
||||
/* OLE32 dependency */
|
||||
DLL_DECLARE_HANDLE(OLE32);
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID));
|
||||
|
||||
/* SetupAPI dependencies */
|
||||
DLL_DECLARE_HANDLE(SetupAPI);
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA,
|
||||
LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA,
|
||||
PCSTR, DWORD, PDWORD));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA,
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
|
||||
PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
|
||||
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD));
|
||||
|
||||
|
||||
#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
|
||||
#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
|
||||
#define USB_GET_NODE_CONNECTION_NAME 261
|
||||
#define USB_GET_HUB_CAPABILITIES 271
|
||||
#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX)
|
||||
#endif
|
||||
#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX
|
||||
#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274
|
||||
#endif
|
||||
#if !defined(USB_GET_HUB_CAPABILITIES_EX)
|
||||
#define USB_GET_HUB_CAPABILITIES_EX 276
|
||||
#endif
|
||||
#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2)
|
||||
#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX_V2
|
||||
#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279
|
||||
#endif
|
||||
|
||||
#ifndef METHOD_BUFFERED
|
||||
#define METHOD_BUFFERED 0
|
||||
#endif
|
||||
#ifndef FILE_ANY_ACCESS
|
||||
#define FILE_ANY_ACCESS 0x00000000
|
||||
#endif
|
||||
#ifndef FILE_DEVICE_UNKNOWN
|
||||
#define FILE_DEVICE_UNKNOWN 0x00000022
|
||||
#endif
|
||||
#ifndef FILE_DEVICE_USB
|
||||
#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN
|
||||
#endif
|
||||
|
||||
#ifndef CTL_CODE
|
||||
#define CTL_CODE(DeviceType, Function, Method, Access) \
|
||||
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
|
||||
#endif
|
||||
#define USB_CTL_CODE(id) \
|
||||
CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \
|
||||
USB_CTL_CODE(USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION)
|
||||
|
||||
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \
|
||||
USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX)
|
||||
|
||||
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \
|
||||
USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2)
|
||||
|
||||
typedef enum USB_CONNECTION_STATUS {
|
||||
NoDeviceConnected,
|
||||
|
@ -406,42 +338,25 @@ typedef enum USB_HUB_NODE {
|
|||
UsbMIParent
|
||||
} USB_HUB_NODE;
|
||||
|
||||
/* Cfgmgr32.dll interface */
|
||||
DLL_DECLARE_HANDLE(Cfgmgr32);
|
||||
DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG));
|
||||
|
||||
#define IOCTL_USB_GET_HUB_CAPABILITIES_EX \
|
||||
CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_HUB_CAPABILITIES \
|
||||
CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \
|
||||
CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_ROOT_HUB_NAME \
|
||||
CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_NODE_INFORMATION \
|
||||
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \
|
||||
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \
|
||||
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \
|
||||
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_USB_GET_NODE_CONNECTION_NAME \
|
||||
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
// Most of the structures below need to be packed
|
||||
#pragma pack(push, 1)
|
||||
#include <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 {
|
||||
UCHAR bLength;
|
||||
|
@ -455,103 +370,7 @@ typedef struct USB_INTERFACE_DESCRIPTOR {
|
|||
UCHAR iInterface;
|
||||
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
|
||||
|
||||
typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT {
|
||||
struct {
|
||||
ULONG ConnectionIndex;
|
||||
struct {
|
||||
UCHAR bmRequest;
|
||||
UCHAR bRequest;
|
||||
USHORT wValue;
|
||||
USHORT wIndex;
|
||||
USHORT wLength;
|
||||
} SetupPacket;
|
||||
} req;
|
||||
USB_CONFIGURATION_DESCRIPTOR data;
|
||||
} USB_CONFIGURATION_DESCRIPTOR_SHORT;
|
||||
|
||||
typedef struct USB_ENDPOINT_DESCRIPTOR {
|
||||
UCHAR bLength;
|
||||
UCHAR bDescriptorType;
|
||||
UCHAR bEndpointAddress;
|
||||
UCHAR bmAttributes;
|
||||
USHORT wMaxPacketSize;
|
||||
UCHAR bInterval;
|
||||
} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
|
||||
|
||||
typedef struct USB_DESCRIPTOR_REQUEST {
|
||||
ULONG ConnectionIndex;
|
||||
struct {
|
||||
UCHAR bmRequest;
|
||||
UCHAR bRequest;
|
||||
USHORT wValue;
|
||||
USHORT wIndex;
|
||||
USHORT wLength;
|
||||
} SetupPacket;
|
||||
// UCHAR Data[0];
|
||||
} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST;
|
||||
|
||||
typedef struct USB_HUB_DESCRIPTOR {
|
||||
UCHAR bDescriptorLength;
|
||||
UCHAR bDescriptorType;
|
||||
UCHAR bNumberOfPorts;
|
||||
USHORT wHubCharacteristics;
|
||||
UCHAR bPowerOnToPowerGood;
|
||||
UCHAR bHubControlCurrent;
|
||||
UCHAR bRemoveAndPowerMask[64];
|
||||
} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
|
||||
|
||||
typedef struct USB_ROOT_HUB_NAME {
|
||||
ULONG ActualLength;
|
||||
WCHAR RootHubName[1];
|
||||
} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME;
|
||||
|
||||
typedef struct USB_ROOT_HUB_NAME_FIXED {
|
||||
ULONG ActualLength;
|
||||
WCHAR RootHubName[MAX_PATH_LENGTH];
|
||||
} USB_ROOT_HUB_NAME_FIXED;
|
||||
|
||||
typedef struct USB_NODE_CONNECTION_NAME {
|
||||
ULONG ConnectionIndex;
|
||||
ULONG ActualLength;
|
||||
WCHAR NodeName[1];
|
||||
} USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME;
|
||||
|
||||
typedef struct USB_NODE_CONNECTION_NAME_FIXED {
|
||||
ULONG ConnectionIndex;
|
||||
ULONG ActualLength;
|
||||
WCHAR NodeName[MAX_PATH_LENGTH];
|
||||
} USB_NODE_CONNECTION_NAME_FIXED;
|
||||
|
||||
typedef struct USB_HUB_NAME_FIXED {
|
||||
union {
|
||||
USB_ROOT_HUB_NAME_FIXED root;
|
||||
USB_NODE_CONNECTION_NAME_FIXED node;
|
||||
} u;
|
||||
} USB_HUB_NAME_FIXED;
|
||||
|
||||
typedef struct USB_HUB_INFORMATION {
|
||||
USB_HUB_DESCRIPTOR HubDescriptor;
|
||||
BOOLEAN HubIsBusPowered;
|
||||
} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION;
|
||||
|
||||
typedef struct USB_MI_PARENT_INFORMATION {
|
||||
ULONG NumberOfInterfaces;
|
||||
} USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION;
|
||||
|
||||
typedef struct USB_NODE_INFORMATION {
|
||||
USB_HUB_NODE NodeType;
|
||||
union {
|
||||
USB_HUB_INFORMATION HubInformation;
|
||||
USB_MI_PARENT_INFORMATION MiParentInformation;
|
||||
} u;
|
||||
} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION;
|
||||
|
||||
typedef struct USB_PIPE_INFO {
|
||||
USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||
ULONG ScheduleOffset;
|
||||
} USB_PIPE_INFO, *PUSB_PIPE_INFO;
|
||||
|
||||
typedef struct USB_NODE_CONNECTION_INFORMATION_EX {
|
||||
typedef struct _USB_NODE_CONNECTION_INFORMATION_EX {
|
||||
ULONG ConnectionIndex;
|
||||
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||
UCHAR CurrentConfigurationValue;
|
||||
|
@ -589,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, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2;
|
||||
|
||||
typedef struct USB_HUB_CAP_FLAGS {
|
||||
ULONG HubIsHighSpeedCapable:1;
|
||||
ULONG HubIsHighSpeed:1;
|
||||
ULONG HubIsMultiTtCapable:1;
|
||||
ULONG HubIsMultiTt:1;
|
||||
ULONG HubIsRoot:1;
|
||||
ULONG HubIsArmedWakeOnConnect:1;
|
||||
ULONG ReservedMBZ:26;
|
||||
} USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS;
|
||||
|
||||
typedef struct USB_HUB_CAPABILITIES {
|
||||
ULONG HubIs2xCapable:1;
|
||||
} USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES;
|
||||
|
||||
typedef struct USB_HUB_CAPABILITIES_EX {
|
||||
USB_HUB_CAP_FLAGS CapabilityFlags;
|
||||
} USB_HUB_CAPABILITIES_EX, *PUSB_HUB_CAPABILITIES_EX;
|
||||
|
||||
#pragma pack(pop)
|
||||
#include <poppack.h>
|
||||
|
||||
/* winusb.dll interface */
|
||||
|
||||
|
@ -619,36 +420,25 @@ typedef struct USB_HUB_CAPABILITIES_EX {
|
|||
#define AUTO_FLUSH 0x06
|
||||
#define RAW_IO 0x07
|
||||
#define MAXIMUM_TRANSFER_SIZE 0x08
|
||||
#define AUTO_SUSPEND 0x81
|
||||
#define SUSPEND_DELAY 0x83
|
||||
#define DEVICE_SPEED 0x01
|
||||
#define LowSpeed 0x01
|
||||
#define FullSpeed 0x02
|
||||
#define HighSpeed 0x03
|
||||
|
||||
typedef enum USBD_PIPE_TYPE {
|
||||
typedef enum _USBD_PIPE_TYPE {
|
||||
UsbdPipeTypeControl,
|
||||
UsbdPipeTypeIsochronous,
|
||||
UsbdPipeTypeBulk,
|
||||
UsbdPipeTypeInterrupt
|
||||
} USBD_PIPE_TYPE;
|
||||
|
||||
typedef struct {
|
||||
USBD_PIPE_TYPE PipeType;
|
||||
UCHAR PipeId;
|
||||
USHORT MaximumPacketSize;
|
||||
UCHAR Interval;
|
||||
} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION;
|
||||
#include <pshpack1.h>
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UCHAR request_type;
|
||||
UCHAR request;
|
||||
USHORT value;
|
||||
USHORT index;
|
||||
USHORT length;
|
||||
typedef struct _WINUSB_SETUP_PACKET {
|
||||
UCHAR RequestType;
|
||||
UCHAR Request;
|
||||
USHORT Value;
|
||||
USHORT Index;
|
||||
USHORT Length;
|
||||
} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
|
||||
#pragma pack()
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
|
||||
|
||||
|
@ -676,59 +466,10 @@ typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)(
|
|||
UCHAR AssociatedInterfaceIndex,
|
||||
PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_GetCurrentAlternateSetting_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
PUCHAR AlternateSetting
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_GetDescriptor_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR DescriptorType,
|
||||
UCHAR Index,
|
||||
USHORT LanguageID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
PULONG LengthTransferred
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_GetOverlappedResult_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
LPOVERLAPPED lpOverlapped,
|
||||
LPDWORD lpNumberOfBytesTransferred,
|
||||
BOOL bWait
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_GetPipePolicy_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
ULONG PolicyType,
|
||||
PULONG ValueLength,
|
||||
PVOID Value
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_GetPowerPolicy_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
ULONG PolicyType,
|
||||
PULONG ValueLength,
|
||||
PVOID Value
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_Initialize_t)(
|
||||
HANDLE DeviceHandle,
|
||||
PWINUSB_INTERFACE_HANDLE InterfaceHandle
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_QueryDeviceInformation_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
ULONG InformationType,
|
||||
PULONG BufferLength,
|
||||
PVOID Buffer
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_QueryInterfaceSettings_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR AlternateSettingNumber,
|
||||
PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_QueryPipe_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR AlternateInterfaceNumber,
|
||||
UCHAR PipeIndex,
|
||||
PWINUSB_PIPE_INFORMATION PipeInformation
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
|
@ -737,6 +478,9 @@ typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
|
|||
PULONG LengthTransferred,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_ResetPipe_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID
|
||||
|
@ -752,12 +496,6 @@ typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)(
|
|||
ULONG ValueLength,
|
||||
PVOID Value
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_SetPowerPolicy_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
ULONG PolicyType,
|
||||
ULONG ValueLength,
|
||||
PVOID Value
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
|
@ -766,8 +504,59 @@ typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
|
|||
PULONG LengthTransferred,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle
|
||||
|
||||
typedef PVOID WINUSB_ISOCH_BUFFER_HANDLE, *PWINUSB_ISOCH_BUFFER_HANDLE;
|
||||
|
||||
typedef BOOL (WINAPI *WinUsb_RegisterIsochBuffer_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
PVOID Buffer,
|
||||
ULONG BufferLength,
|
||||
PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *WinUsb_UnregisterIsochBuffer_t)(
|
||||
WINUSB_ISOCH_BUFFER_HANDLE BufferHandle
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *WinUsb_WriteIsochPipeAsap_t)(
|
||||
WINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
|
||||
ULONG Offset,
|
||||
ULONG Length,
|
||||
BOOL ContinueStream,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
|
||||
typedef LONG USBD_STATUS;
|
||||
typedef struct {
|
||||
ULONG Offset;
|
||||
ULONG Length;
|
||||
USBD_STATUS Status;
|
||||
} USBD_ISO_PACKET_DESCRIPTOR, *PUSBD_ISO_PACKET_DESCRIPTOR;
|
||||
|
||||
typedef BOOL (WINAPI *WinUsb_ReadIsochPipeAsap_t)(
|
||||
PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
|
||||
ULONG Offset,
|
||||
ULONG Length,
|
||||
BOOL ContinueStream,
|
||||
ULONG NumberOfPackets,
|
||||
PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors,
|
||||
LPOVERLAPPED Overlapped
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
USBD_PIPE_TYPE PipeType;
|
||||
UCHAR PipeId;
|
||||
USHORT MaximumPacketSize;
|
||||
UCHAR Interval;
|
||||
ULONG MaximumBytesPerInterval;
|
||||
} WINUSB_PIPE_INFORMATION_EX, *PWINUSB_PIPE_INFORMATION_EX;
|
||||
|
||||
typedef BOOL (WINAPI *WinUsb_QueryPipeEx_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR AlternateInterfaceHandle,
|
||||
UCHAR PipeIndex,
|
||||
PWINUSB_PIPE_INFORMATION_EX PipeInformationEx
|
||||
);
|
||||
|
||||
/* /!\ These must match the ones from the official libusbk.h */
|
||||
|
@ -814,8 +603,7 @@ typedef struct _KLIB_VERSION {
|
|||
INT Minor;
|
||||
INT Micro;
|
||||
INT Nano;
|
||||
} KLIB_VERSION;
|
||||
typedef KLIB_VERSION* PKLIB_VERSION;
|
||||
} KLIB_VERSION, *PKLIB_VERSION;
|
||||
|
||||
typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
|
||||
PVOID *ProcAddress,
|
||||
|
@ -827,29 +615,72 @@ typedef VOID (WINAPI *LibK_GetVersion_t)(
|
|||
PKLIB_VERSION Version
|
||||
);
|
||||
|
||||
//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths
|
||||
typedef struct _KISO_PACKET {
|
||||
UINT offset;
|
||||
USHORT actual_length; //changed from libusbk_shared.h "Length" for clarity
|
||||
USHORT status;
|
||||
} KISO_PACKET, *PKISO_PACKET;
|
||||
|
||||
typedef enum _KISO_FLAG {
|
||||
KISO_FLAG_NONE = 0,
|
||||
KISO_FLAG_SET_START_FRAME = 0x00000001,
|
||||
} KISO_FLAG;
|
||||
|
||||
//KISO_CONTEXT is the conceptual equivalent of libusb_transfer except is isochronous-specific and must match libusbk's version
|
||||
typedef struct _KISO_CONTEXT {
|
||||
KISO_FLAG Flags;
|
||||
UINT StartFrame;
|
||||
SHORT ErrorCount;
|
||||
SHORT NumberOfPackets;
|
||||
UINT UrbHdrStatus;
|
||||
KISO_PACKET IsoPackets[0];
|
||||
} KISO_CONTEXT, *PKISO_CONTEXT;
|
||||
|
||||
typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
LPOVERLAPPED Overlapped,
|
||||
PKISO_CONTEXT IsoContext
|
||||
);
|
||||
|
||||
typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)(
|
||||
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
||||
UCHAR PipeID,
|
||||
PUCHAR Buffer,
|
||||
ULONG BufferLength,
|
||||
LPOVERLAPPED Overlapped,
|
||||
PKISO_CONTEXT IsoContext
|
||||
);
|
||||
|
||||
struct winusb_interface {
|
||||
bool initialized;
|
||||
bool CancelIoEx_supported;
|
||||
WinUsb_AbortPipe_t AbortPipe;
|
||||
WinUsb_ControlTransfer_t ControlTransfer;
|
||||
WinUsb_FlushPipe_t FlushPipe;
|
||||
WinUsb_Free_t Free;
|
||||
WinUsb_GetAssociatedInterface_t GetAssociatedInterface;
|
||||
WinUsb_GetCurrentAlternateSetting_t GetCurrentAlternateSetting;
|
||||
WinUsb_GetDescriptor_t GetDescriptor;
|
||||
WinUsb_GetOverlappedResult_t GetOverlappedResult;
|
||||
WinUsb_GetPipePolicy_t GetPipePolicy;
|
||||
WinUsb_GetPowerPolicy_t GetPowerPolicy;
|
||||
WinUsb_Initialize_t Initialize;
|
||||
WinUsb_QueryDeviceInformation_t QueryDeviceInformation;
|
||||
WinUsb_QueryInterfaceSettings_t QueryInterfaceSettings;
|
||||
WinUsb_QueryPipe_t QueryPipe;
|
||||
WinUsb_ReadPipe_t ReadPipe;
|
||||
WinUsb_ResetDevice_t ResetDevice;
|
||||
WinUsb_ResetPipe_t ResetPipe;
|
||||
WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting;
|
||||
WinUsb_SetPipePolicy_t SetPipePolicy;
|
||||
WinUsb_SetPowerPolicy_t SetPowerPolicy;
|
||||
WinUsb_WritePipe_t WritePipe;
|
||||
WinUsb_ResetDevice_t ResetDevice;
|
||||
|
||||
// Isochoronous functions for LibUSBk sub api:
|
||||
WinUsb_IsoReadPipe_t IsoReadPipe;
|
||||
WinUsb_IsoWritePipe_t IsoWritePipe;
|
||||
|
||||
// Isochronous functions for Microsoft WinUSB sub api (native WinUSB):
|
||||
WinUsb_RegisterIsochBuffer_t RegisterIsochBuffer;
|
||||
WinUsb_UnregisterIsochBuffer_t UnregisterIsochBuffer;
|
||||
WinUsb_WriteIsochPipeAsap_t WriteIsochPipeAsap;
|
||||
WinUsb_ReadIsochPipeAsap_t ReadIsochPipeAsap;
|
||||
WinUsb_QueryPipeEx_t QueryPipeEx;
|
||||
};
|
||||
|
||||
/* hid.dll interface */
|
||||
|
@ -857,17 +688,19 @@ struct winusb_interface {
|
|||
#define HIDP_STATUS_SUCCESS 0x110000
|
||||
typedef void * PHIDP_PREPARSED_DATA;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
#include <pshpack1.h>
|
||||
|
||||
typedef struct _HIDD_ATTIRBUTES {
|
||||
ULONG Size;
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
|
||||
#pragma pack()
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
typedef USHORT USAGE;
|
||||
typedef struct {
|
||||
typedef struct _HIDP_CAPS {
|
||||
USAGE Usage;
|
||||
USAGE UsagePage;
|
||||
USHORT InputReportByteLength;
|
||||
|
@ -930,19 +763,16 @@ typedef struct _HIDP_VALUE_CAPS {
|
|||
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
|
||||
|
||||
DLL_DECLARE_HANDLE(hid);
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES));
|
||||
DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetIndexedString, (HANDLE, ULONG, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE));
|
||||
DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA));
|
|
@ -38,7 +38,7 @@ static size_t usbi_locale = 0;
|
|||
* How to add a new \ref libusb_strerror() translation:
|
||||
* <ol>
|
||||
* <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> 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>
|
||||
|
@ -60,7 +60,7 @@ static size_t usbi_locale = 0;
|
|||
* </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] = {
|
||||
{ /* English (en) */
|
||||
"Success",
|
||||
|
@ -122,6 +122,37 @@ static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUS
|
|||
"Память исчерпана",
|
||||
"Операция не поддерживается данной платформой",
|
||||
"Неизвестная ошибка"
|
||||
|
||||
}, { /* German (de) */
|
||||
"Erfolgreich",
|
||||
"Eingabe-/Ausgabefehler",
|
||||
"Ungültiger Parameter",
|
||||
"Keine Berechtigung (Zugriffsrechte fehlen)",
|
||||
"Kein passendes Gerät gefunden (es könnte entfernt worden sein)",
|
||||
"Entität nicht gefunden",
|
||||
"Die Ressource ist belegt",
|
||||
"Die Wartezeit für die Operation ist abgelaufen",
|
||||
"Mehr Daten empfangen als erwartet",
|
||||
"Datenübergabe unterbrochen (broken pipe)",
|
||||
"Unterbrechung während des Betriebssystemaufrufs",
|
||||
"Nicht genügend Hauptspeicher verfügbar",
|
||||
"Die Operation wird nicht unterstützt oder ist auf dieser Platform nicht implementiert",
|
||||
"Allgemeiner Fehler",
|
||||
}, { /* Hungarian (hu) */
|
||||
"Sikeres",
|
||||
"Be-/kimeneti hiba",
|
||||
"Érvénytelen paraméter",
|
||||
"Hozzáférés megtagadva",
|
||||
"Az eszköz nem található (eltávolították?)",
|
||||
"Nem található",
|
||||
"Az erőforrás foglalt",
|
||||
"Időtúllépés",
|
||||
"Túlcsordulás",
|
||||
"Törött adatcsatorna",
|
||||
"Rendszerhívás megszakítva",
|
||||
"Nincs elég memória",
|
||||
"A művelet nem támogatott ezen a rendszeren",
|
||||
"Általános hiba",
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
#define LIBUSB_MINOR 0
|
||||
#endif
|
||||
#ifndef LIBUSB_MICRO
|
||||
#define LIBUSB_MICRO 21
|
||||
#define LIBUSB_MICRO 23
|
||||
#endif
|
||||
#ifndef LIBUSB_NANO
|
||||
#define LIBUSB_NANO 0
|
||||
#endif
|
||||
/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */
|
||||
#ifndef LIBUSB_RC
|
||||
#define LIBUSB_RC ""
|
||||
#define LIBUSB_RC "-rc1"
|
||||
#endif
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define LIBUSB_NANO 11156
|
||||
#define LIBUSB_NANO 11367
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
<ClInclude Include="libusb\version_nano.h" />
|
||||
<ClInclude Include="libusb\os\windows_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_winusb.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -7,22 +7,21 @@ if [%Configuration%] NEQ [Release] goto debugx64
|
|||
:debugx64
|
||||
if [%Platform%] NEQ [x64] goto debugWin32
|
||||
if [%Configuration%] NEQ [Debug] exit 0
|
||||
call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Debug /x64
|
||||
msbuild %libusb_2010% /p:Configuration=Debug,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
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" || exit /B
|
||||
|
||||
:releasex64
|
||||
if [%Platform%] NEQ [x64] goto releaseWin32
|
||||
if [%Configuration%] NEQ [Release] exit 0
|
||||
call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /x64
|
||||
msbuild %libusb_2010% /p:Configuration=Release,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
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" || exit /B
|
||||
|
||||
:debugWin32
|
||||
if [%Platform%] NEQ [Win32] exit 0
|
||||
if [%Configuration%] NEQ [Debug] exit 0
|
||||
msbuild %libusb_2010% /p:Configuration=Debug,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
msbuild %libusb_2010% /p:Configuration=Debug,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || exit /B
|
||||
|
||||
:releaseWin32
|
||||
if [%Platform%] NEQ [Win32] exit 0
|
||||
if [%Configuration%] NEQ [Release] exit 0
|
||||
msbuild %libusb_2010% /p:Configuration=Release,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
msbuild %libusb_2010% /p:Configuration=Release,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || exit /B
|
||||
|
|
|
@ -6,16 +6,18 @@
|
|||
#endif
|
||||
|
||||
/* Visual Studio 2015 and later defines timespec */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
|
||||
#if (_MSC_VER >= 1900)
|
||||
#define _TIMESPEC_DEFINED 1
|
||||
#endif
|
||||
|
||||
/* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */
|
||||
#pragma warning(disable:4200)
|
||||
/* Disable: warning C4324: structure was padded due to __declspec(align()) */
|
||||
#pragma warning(disable:4324)
|
||||
/* Disable: warning C6258: Using TerminateThread does not allow proper thread clean up */
|
||||
#pragma warning(disable: 6258)
|
||||
#pragma warning(disable:6258)
|
||||
/* Disable: warning C4996: 'GetVersionA': was declared deprecated */
|
||||
#pragma warning(disable: 4996)
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
#if defined(_PREFAST_)
|
||||
/* Disable "Banned API" errors when using the MS's WDK OACR/Prefast */
|
||||
|
@ -45,6 +47,5 @@
|
|||
#define HAVE_MISSING_H
|
||||
#else
|
||||
#define OS_WINDOWS 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#endif
|
||||
|
|
|
@ -3,28 +3,20 @@
|
|||
::# you can pass the following arguments (case insensitive):
|
||||
::# - "DLL" to build a DLL instead of a static library
|
||||
::# - "/MT" to build a static library compatible with MSVC's /MT option (LIBCMT vs MSVCRT)
|
||||
::# - "USBDK" to build with UsbDk backend
|
||||
|
||||
if Test%BUILD_ALT_DIR%==Test goto usage
|
||||
|
||||
::# process commandline parameters
|
||||
set TARGET=LIBRARY
|
||||
set STATIC_LIBC=
|
||||
set WITH_USBDK=
|
||||
set version=1.0
|
||||
set PWD=%~dp0
|
||||
set BUILD_CMD=build -bcwgZ -M2
|
||||
|
||||
:more_args
|
||||
set BUILD_CMD=build /bcwgZ /M2
|
||||
|
||||
if "%1" == "" goto no_more_args
|
||||
::# /I for case insensitive
|
||||
if /I Test%1==TestDLL set TARGET=DYNLINK
|
||||
if /I Test%1==Test/MT set STATIC_LIBC=1
|
||||
if /I Test%1==TestUSBDK set WITH_USBDK=1
|
||||
|
||||
shift
|
||||
goto more_args
|
||||
|
||||
:no_more_args
|
||||
|
||||
|
@ -53,13 +45,13 @@ set dstPath=%destType%\Release
|
|||
:isDebug
|
||||
|
||||
if exist %destType% goto md2
|
||||
mkdir %destType%
|
||||
md %destType%
|
||||
:md2
|
||||
if exist %dstPath% goto md3
|
||||
mkdir %dstPath%
|
||||
md %dstPath%
|
||||
:md3
|
||||
if exist %dstPath%\dll goto md4
|
||||
mkdir %dstPath%\dll
|
||||
md %dstPath%\dll
|
||||
:md4
|
||||
if exist %dstPath%\lib goto md5
|
||||
md %dstPath%\lib
|
||||
|
@ -67,9 +59,12 @@ md %dstPath%\lib
|
|||
if exist %dstPath%\examples goto md6
|
||||
md %dstPath%\examples
|
||||
:md6
|
||||
if exist %dstPath%\tests goto md7
|
||||
md %dstPath%\tests
|
||||
:md7
|
||||
@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%.pdb %dstPath%\dll
|
||||
:copylib
|
||||
|
@ -77,49 +72,9 @@ copy %srcPath%\libusb-%version%.lib %dstPath%\lib
|
|||
|
||||
@echo off
|
||||
|
||||
if exist examples\listdevs_ddkbuild goto md7
|
||||
md examples\listdevs_ddkbuild
|
||||
:md7
|
||||
|
||||
cd examples\listdevs_ddkbuild
|
||||
copy ..\..\msvc\listdevs_sources sources >NUL 2>&1
|
||||
@echo on
|
||||
%BUILD_CMD%
|
||||
@echo off
|
||||
if errorlevel 1 goto builderror
|
||||
cd ..\..
|
||||
|
||||
set srcPath=examples\listdevs_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
|
||||
@echo on
|
||||
|
||||
copy %srcPath%\listdevs.exe %dstPath%\examples
|
||||
copy %srcPath%\listdevs.pdb %dstPath%\examples
|
||||
|
||||
@echo off
|
||||
|
||||
if exist examples\xusb_ddkbuild goto md8
|
||||
md examples\xusb_ddkbuild
|
||||
:md8
|
||||
|
||||
cd examples\xusb_ddkbuild
|
||||
copy ..\..\msvc\xusb_sources sources >NUL 2>&1
|
||||
@echo on
|
||||
%BUILD_CMD%
|
||||
@echo off
|
||||
if errorlevel 1 goto builderror
|
||||
cd ..\..
|
||||
|
||||
set srcPath=examples\xusb_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
|
||||
@echo on
|
||||
|
||||
copy %srcPath%\xusb.exe %dstPath%\examples
|
||||
copy %srcPath%\xusb.pdb %dstPath%\examples
|
||||
|
||||
@echo off
|
||||
|
||||
if exist examples\getopt\getopt_ddkbuild goto md9
|
||||
if exist examples\getopt\getopt_ddkbuild goto md8
|
||||
md examples\getopt\getopt_ddkbuild
|
||||
:md9
|
||||
:md8
|
||||
|
||||
cd examples\getopt\getopt_ddkbuild
|
||||
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
|
||||
cd ..\..\..
|
||||
|
||||
if exist examples\fxload_ddkbuild goto md10
|
||||
if exist examples\fxload_ddkbuild goto md9
|
||||
md examples\fxload_ddkbuild
|
||||
:md10
|
||||
:md9
|
||||
|
||||
cd examples\fxload_ddkbuild
|
||||
copy ..\..\msvc\fxload_sources sources >NUL 2>&1
|
||||
|
@ -149,9 +104,9 @@ copy %srcPath%\fxload.pdb %dstPath%\examples
|
|||
|
||||
@echo off
|
||||
|
||||
if exist examples\hotplugtest_ddkbuild goto md11
|
||||
if exist examples\hotplugtest_ddkbuild goto md10
|
||||
md examples\hotplugtest_ddkbuild
|
||||
:md11
|
||||
:md10
|
||||
|
||||
cd examples\hotplugtest_ddkbuild
|
||||
copy ..\..\msvc\hotplugtest_sources sources >NUL 2>&1
|
||||
|
@ -169,6 +124,86 @@ copy %srcPath%\hotplugtest.pdb %dstPath%\examples
|
|||
|
||||
@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
|
||||
goto done
|
||||
|
||||
|
|
|
@ -25,127 +25,45 @@
|
|||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" 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">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|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)'=='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">
|
||||
<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>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<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>
|
||||
<IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<BuildLog>
|
||||
<Path>$(IntDir)$(ProjectName).htm</Path>
|
||||
</BuildLog>
|
||||
<ItemDefinitionGroup>
|
||||
<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>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Release'">
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<Link Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
@ -153,16 +71,17 @@
|
|||
<ClCompile Include="..\examples\fxload.c" />
|
||||
</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">
|
||||
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="getopt_2010.vcxproj">
|
||||
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\examples\ezusb.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -25,131 +25,46 @@
|
|||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" 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">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|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)'=='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">
|
||||
<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>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<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>
|
||||
<IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<BuildLog>
|
||||
<Path>$(IntDir)$(ProjectName).htm</Path>
|
||||
</BuildLog>
|
||||
<ItemDefinitionGroup>
|
||||
<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>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Release'">
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<Link Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
@ -157,16 +72,17 @@
|
|||
<ClCompile Include="..\examples\fxload.c" />
|
||||
</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">
|
||||
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="getopt_2012.vcxproj">
|
||||
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\examples\ezusb.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -25,131 +25,46 @@
|
|||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" 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">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|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)'=='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">
|
||||
<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>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<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>
|
||||
<IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<BuildLog>
|
||||
<Path>$(IntDir)$(ProjectName).htm</Path>
|
||||
</BuildLog>
|
||||
<ItemDefinitionGroup>
|
||||
<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>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Release'">
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<Link Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
@ -157,16 +72,17 @@
|
|||
<ClCompile Include="..\examples\fxload.c" />
|
||||
</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">
|
||||
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="getopt_2013.vcxproj">
|
||||
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\examples\ezusb.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -25,131 +25,46 @@
|
|||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" 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">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|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)'=='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">
|
||||
<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>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<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>
|
||||
<IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<BuildLog>
|
||||
<Path>$(IntDir)$(ProjectName).htm</Path>
|
||||
</BuildLog>
|
||||
<ItemDefinitionGroup>
|
||||
<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>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ClCompile Condition="'$(Configuration)'=='Release'">
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<Link Condition="'$(Configuration)'=='Debug'">
|
||||
<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>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
@ -157,16 +72,17 @@
|
|||
<ClCompile Include="..\examples\fxload.c" />
|
||||
</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">
|
||||
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="getopt_2015.vcxproj">
|
||||
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\examples\ezusb.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue