update to libusb v1.0.26

moves libusb from vendored to submodule
This commit is contained in:
Shawn Hoffman 2022-04-11 06:04:20 -07:00
parent 3ed9d5a3c7
commit 70507c2237
98 changed files with 204 additions and 85165 deletions

3
.gitmodules vendored
View File

@ -13,3 +13,6 @@
url = https://github.com/dolphin-emu/ext-win-ffmpeg.git
branch = master
shallow = true
[submodule "libusb"]
path = Externals/libusb/libusb
url = https://github.com/libusb/libusb.git

View File

@ -1,49 +0,0 @@
language: c
matrix:
include:
- os: linux
dist: trusty
sudo: required
compiler: gcc
- os: linux
dist: trusty
sudo: required
compiler: clang
- os: osx
osx_image: xcode8
compiler: gcc
- os: osx
osx_image: xcode8
compiler: clang
- os: osx
osx_image: xcode7.1
compiler: gcc
- os: osx
osx_image: xcode7.1
compiler: clang
- os: osx
osx_image: beta-xcode6.2
compiler: gcc
- os: osx
osx_image: beta-xcode6.2
compiler: clang
addons:
homebrew:
update: true
brewfile: true
apt:
packages:
- autoconf
- automake
- libtool
- m4
- libudev-dev
sources:
- ubuntu-toolchain-r-test
script:
- ./autogen.sh && make clean && make
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./travis-autogen.sh --disable-udev && make clean && make ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cd Xcode && xcodebuild -project libusb.xcodeproj ; fi

View File

@ -1,119 +0,0 @@
Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
Copyright © 2010-2012 Peter Stuge <peter@stuge.se>
Copyright © 2008-2016 Nathan Hjelm <hjelmn@users.sourceforge.net>
Copyright © 2009-2013 Pete Batard <pete@akeo.ie>
Copyright © 2009-2013 Ludovic Rousseau <ludovic.rousseau@gmail.com>
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-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
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
Francesco Montorsi
Francisco Facioni
Gaurav Gupta
Graeme Gill
Gustavo Zacarias
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
Omri Iluz
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
Tobias Klauser
Toby Peterson
Tormod Volden
Trygve Laugstøl
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

View File

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

View File

@ -1,79 +1,74 @@
add_library(usb STATIC EXCLUDE_FROM_ALL
libusb/core.c
libusb/core.c
libusb/descriptor.c
libusb/hotplug.c
libusb/io.c
libusb/strerror.c
libusb/sync.c
libusb/libusb/core.c
libusb/libusb/descriptor.c
libusb/libusb/hotplug.c
libusb/libusb/io.c
libusb/libusb/strerror.c
libusb/libusb/sync.c
)
set_target_properties(usb PROPERTIES VERSION 1.0.19)
set_target_properties(usb PROPERTIES VERSION 1.0.26)
if(WIN32)
target_include_directories(usb BEFORE PUBLIC libusb PRIVATE msvc)
target_include_directories(usb BEFORE PUBLIC libusb/libusb PRIVATE libusb/msvc)
else()
target_include_directories(usb
# turns out other projects also have "config.h", so make sure the
# LibUSB one comes first
BEFORE
PUBLIC libusb
PUBLIC libusb/libusb
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}"
)
endif()
if(WIN32 OR CYGWIN)
target_sources(usb PRIVATE
libusb/os/threads_windows.c
libusb/os/windows_winusb.c
libusb/os/windows_usbdk.c
libusb/os/windows_nt_common.c
libusb/libusb/os/threads_windows.c
libusb/libusb/os/windows_common.c
libusb/libusb/os/windows_usbdk.c
libusb/libusb/os/windows_winusb.c
)
set(OS_WINDOWS TRUE)
set(PLATFORM_WINDOWS TRUE)
elseif(APPLE)
target_sources(usb PRIVATE libusb/os/darwin_usb.c)
target_sources(usb PRIVATE libusb/libusb/os/darwin_usb.c)
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
find_library(IOKIT_LIBRARY IOKit)
find_library(OBJC_LIBRARY objc)
find_library(SECURITY_LIBRARY Security)
target_link_libraries(usb PRIVATE
${COREFOUNDATION_LIBRARY}
${IOKIT_LIBRARY}
${OBJC_LIBRARY}
${SECURITY_LIBRARY}
)
set(OS_DARWIN TRUE)
# # Dolphin on Android doesn't use libusb.
#elseif(ANDROID)
# target_sources(usb PRIVATE
# libusb/os/linux_usbfs.c
# libusb/os/linux_netlink.c
# libusb/libusb/os/linux_usbfs.c
# libusb/libusb/os/linux_netlink.c
# )
# find_library(LOG_LIBRARY log)
# target_link_libraries(usb PRIVATE ${LOG_LIBRARY})
# set(OS_LINUX TRUE)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
target_sources(usb PRIVATE libusb/os/linux_usbfs.c)
find_package(Libudev)
target_sources(usb PRIVATE libusb/libusb/os/linux_usbfs.c)
find_package(LIBUDEV)
if(LIBUDEV_FOUND)
target_sources(usb PRIVATE libusb/os/linux_udev.c)
target_sources(usb PRIVATE libusb/libusb/os/linux_udev.c)
target_link_libraries(usb PRIVATE "${LIBUDEV_LIBRARIES}")
target_include_directories(usb PRIVATE "${LIBUDEV_INCLUDE_DIR}")
set(HAVE_LIBUDEV TRUE)
set(USE_UDEV TRUE)
else()
target_sources(usb PRIVATE libusb/os/linux_netlink.c)
target_sources(usb PRIVATE libusb/libusb/os/linux_netlink.c)
endif()
set(OS_LINUX TRUE)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
target_sources(usb PRIVATE libusb/os/netbsd_usb.c)
set(OS_NETBSD TRUE)
target_sources(usb PRIVATE libusb/libusb/os/netbsd_usb.c)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
target_sources(usb PRIVATE libusb/os/openbsd_usb.c)
set(OS_OPENBSD TRUE)
target_sources(usb PRIVATE libusb/libusb/os/openbsd_usb.c)
endif()
if(UNIX)
target_sources(usb PRIVATE
libusb/os/poll_posix.c
libusb/os/threads_posix.c
libusb/libusb/os/events_posix.c
libusb/libusb/os/threads_posix.c
)
find_package(Threads REQUIRED)
if(THREADS_HAVE_PTHREAD_ARG)
@ -82,41 +77,48 @@ if(UNIX)
if(CMAKE_THREAD_LIBS_INIT)
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
endif()
set(THREADS_POSIX TRUE)
elseif(WIN32)
target_sources(usb PRIVATE
libusb/os/poll_windows.c
libusb/os/threads_windows.c
)
set(PLATFORM_POSIX TRUE)
endif()
# Create config.h
include(CheckFunctionExists)
include(CheckIncludeFiles)
#include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckSymbolExists)
check_include_files(asm/types.h HAVE_ASM_TYPES_H)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
check_include_files(linux/filter.h HAVE_LINUX_FILTER_H)
check_include_files(linux/netlink.h HAVE_LINUX_NETLINK_H)
check_include_files(poll.h HAVE_POLL_H)
check_include_files(signal.h HAVE_SIGNAL_H)
check_include_files(strings.h HAVE_STRINGS_H)
check_type_size("struct timespec" STRUCT_TIMESPEC)
check_function_exists(syslog HAVE_SYSLOG_FUNC)
check_include_files(syslog.h HAVE_SYSLOG_H)
check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
check_symbol_exists(EFD_CLOEXEC "sys/eventfd.h" HAVE_DECL_EFD_CLOEXEC)
check_symbol_exists(EFD_NONBLOCK "sys/eventfd.h" HAVE_DECL_EFD_NONBLOCK)
check_symbol_exists(TFD_CLOEXEC "sys/timerfd.h" HAVE_DECL_TFD_CLOEXEC)
check_symbol_exists(TFD_NONBLOCK "sys/timerfd.h" HAVE_DECL_TFD_NONBLOCK)
check_include_files(dlfcn.h HAVE_DLFCN_H)
check_include_files(sys/eventfd.h HAVE_EVENTFD)
check_include_files(inttypes.h HAVE_INTTYPES_H)
check_include_files(IOKit/usb/IOUSBHostFamilyDefinitions.h HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H)
#check_library_exists(udev HAVE_LIBUDEV)
check_include_files(memory.h HAVE_MEMORY_H)
set(CMAKE_EXTRA_INCLUDE_FILES poll.h)
check_type_size("nfds_t" nfds_t)
check_type_size("nfds_t" NFDS_T)
unset(CMAKE_EXTRA_INCLUDE_FILES)
if(HAVE_NFDS_T)
set(POLL_NFDS_TYPE "nfds_t")
else()
set(POLL_NFDS_TYPE "unsigned int")
endif()
check_include_files(sys/timerfd.h USBI_TIMERFD_AVAILABLE)
check_function_exists(pipe2 HAVE_PIPE2)
check_function_exists(pthread_condattr_setclock HAVE_PTHREAD_CONDATTR_SETCLOCK)
check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP)
check_function_exists(pthread_threadid_np HAVE_PTHREAD_THREADID_NP)
check_include_files(stdint.h HAVE_STDINT_H)
check_include_files(stdlib.h HAVE_STDLIB_H)
check_include_files(strings.h HAVE_STRINGS_H)
check_include_files(string.h HAVE_STRING_H)
check_type_size("struct timespec" STRUCT_TIMESPEC)
check_function_exists(syslog HAVE_SYSLOG)
check_include_files(sys/stat.h HAVE_SYS_STAT_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
check_include_files(sys/timerfd.h HAVE_TIMERFD)
check_include_files(unistd.h HAVE_UNISTD_H)
configure_file(config.h.in config.h)

View File

@ -1,504 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -1,279 +0,0 @@
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
* Darwin: Improved support for OS X El Capitan
* Darwin: Work around devices with buggy endpoint descriptors
* Darwin: Do not use objc_registerThreadWithCollector after its deprecation
* Darwin: Use C11 atomics on 10.12+ as the OS atomics are now deprecated
* Linux: Support preallocating kernel memory for zerocopy USB
* Linux: Deal with receiving POLLERR before all transfers have completed
* Solaris: Add solaris backend
* Windows: Add Visual Studio 2015 support
* Windows: Add usbdk backend
* Prevent attempts to recursively handle events
* Fix race condition in handle_timeout()
* Allow transferred argument to be optional in bulk APIs
* Various other bug fixes and improvements
2015-09-13: v1.0.20
* Add Haiku support
* Fix multiple memory and resource leaks (#16, #52, #76, #81)
* Fix possible deadlock when executing transfer callback
* New libusb_free_pollfds() API
* Darwin: Fix devices not being detected on OS X 10.8 (#48)
* Linux: Allow larger isochronous transfer submission (#23)
* Windows: Fix broken builds Cygwin/MinGW builds and compiler warnings
* Windows: Fix broken bus number lookup
* Windows: Improve submission of control requests for composite devices
* Examples: Add two-stage load support to fxload (#12)
* Correctly report cancellations due to timeouts
* Improve efficiency of event handling
* Improve speed of transfer submission in multi-threaded environments
* Various other bug fixes and improvements
The (#xx) numbers are libusb issue numbers, see ie:
https://github.com/libusb/libusb/issues/16
2014-05-30: v1.0.19
* Add support for USB bulk streams on Linux and Mac OS X (#11)
* Windows: Add AMD and Intel USB-3.0 root hub support
* Windows: Fix USB 3.0 speed detection on Windows 8 or later (#10)
* Added Russian translation for libusb_strerror strings
* All: Various small fixes and cleanups
2014-01-25: v1.0.18
* Fix multiple memory leaks
* Fix a crash when HID transfers return no data on Windows
* Ensure all pending events are consumed
* Improve Android and ucLinux support
* Multiple Windows improvements (error logging, VS2013, VIA xHCI support)
* Multiple OS X improvements (broken compilation, SIGFPE, 64bit support)
2013-09-06: v1.0.17
* Hotplug callbacks now always get passed a libusb_context, even if it is
the default context. Previously NULL would be passed for the default context,
but since the first context created is the default context, and most apps
use only 1 context, this meant that apps explicitly creating a context would
still get passed NULL
* Android: Add .mk files to build with the Android NDK
* Darwin: Add Xcode project
* Darwin: Fix crash on unplug (#121)
* Linux: Fix hang (deadlock) on libusb_exit
* Linux: Fix libusb build failure with --disable-udev (#124)
* Linux: Fix libusb_get_device_list() hang with --disable-udev (#130)
* OpenBSD: Update OpenBSD backend with support for control transfers to
non-ugen(4) devices and make get_configuration() no longer generate I/O.
Note that using this libusb version on OpenBSD requires using
OpenBSD 5.3-current or later. Users of older OpenBSD versions are advised
to stay with the libusb shipped with OpenBSD (mpi)
* Windows: fix libusb_dll_2010.vcxproj link errors (#129)
* Various other bug fixes and improvements
2013-07-11: v1.0.16
* Add hotplug support for Darwin and Linux (#9)
* Add superspeed endpoint companion descriptor support (#15)
* Add BOS descriptor support (#15)
* Make descriptor parsing code more robust
* New libusb_get_port_numbers API, this is libusb_get_port_path without
the unnecessary context parameter, libusb_get_port_path is now deprecated
* New libusb_strerror API (#14)
* New libusb_set_auto_detach_kernel_driver API (#17)
* Improve topology API docs (#95)
* Logging now use a single write call per log-message, avoiding log-message
"interlacing" when using multiple threads.
* Android: use Android logging when building on Android (#101)
* Darwin: make libusb_reset reenumerate device on descriptors change (#89)
* Darwin: add support for the LIBUSB_TRANSFER_ADD_ZERO_PACKET flag (#91)
* Darwin: add a device cache (#112, #114)
* Examples: Add sam3u_benchmark isochronous example by Harald Welte (#109)
* Many other bug fixes and improvements
The (#xx) numbers are libusbx issue numbers, see ie:
https://github.com/libusbx/libusbx/issues/9
2013-04-15: v1.0.15
* Improve transfer cancellation and avoid short read failures on broken descriptors
* Filter out 8-bit characters in libusb_get_string_descriptor_ascii()
* Add WinCE support
* Add library stress tests
* Add Cypress FX3 firmware upload support for fxload sample
* Add HID and kernel driver detach support capabilities detection
* Add SuperSpeed detection on OS X
* Fix bInterval value interpretation on OS X
* Fix issues with autoclaim, composite HID devices, interface autoclaim and
early abort in libusb_close() on Windows. Also add VS2012 solution files.
* Improve fd event handling on Linux
* Other bug fixes and improvements
2012-09-26: v1.0.14
* Reverts the previous API change with regards to bMaxPower.
If this doesn't matter to you, you are encouraged to keep using v1.0.13,
as it will use the same attribute as v2.0, to be released soon.
* Note that LIBUSB_API_VERSION is *decreased* to 0x010000FF and the previous
guidelines with regards to concurrent use of MaxPower/bMaxPower still apply.
2012-09-20: v1.0.13
* [MAJOR] Fix a typo in the API with struct libusb_config_descriptor where
MaxPower was used instead of bMaxPower, as defined in the specs. If your
application was accessing the MaxPower attribute, and you need to maintain
compatibility with libusb or older versions, see APPENDIX A below.
* Fix broken support for the 0.1 -> 1.0 libusb-compat layer
* Fix unwanted cancellation of pending timeouts as well as major timeout related bugs
* Fix handling of HID and composite devices on Windows
* Introduce LIBUSB_API_VERSION macro
* Add Cypress FX/FX2 firmware upload sample, based on fxload from
http://linux-hotplug.sourceforge.net
* Add libusb0 (libusb-win32) and libusbK driver support on Windows. Note that while
the drivers allow it, isochronous transfers are not supported yet in libusb. Also
not supported yet is the use of libusb-win32 filter drivers on composite interfaces
* Add support for the new get_capabilities ioctl on Linux and avoid unnecessary
splitting of bulk transfers
* Improve support for newer Intel and Renesas USB 3.0 controllers on Windows
* Harmonize the device number for root hubs across platforms
* Other bug fixes and improvements
2012-06-15: v1.0.12
* Fix a potential major regression with pthread on Linux
* Fix missing thread ID from debug log output on cygwin
* Fix possible crash when using longjmp and MinGW's gcc 4.6
* Add topology calls: libusb_get_port_number(), libusb_get_parent() & libusb_get_port_path()
* Add toggleable debug, using libusb_set_debug() or the LIBUSB_DEBUG environment variable
* Define log levels in libusb.h and set timestamp origin to first libusb_init() call
* All logging is now sent to to stderr (info was sent to stdout previously)
* Update log messages severity and avoid polluting log output on OS-X
* Add HID driver support on Windows
* Enable interchangeability of MSVC and MinGW DLLs
* Additional bug fixes and improvements
2012-05-08: v1.0.11
* Revert removal of critical Windows event handling that was introduced in 1.0.10
* Fix a possible deadlock in Windows when submitting transfers
* Add timestamped logging
* Add NetBSD support (experimental) and BSD libusb_get_device_speed() data
* Add bootstrap.sh alongside autogen.sh (bootstrap.sh doesn't invoke configure)
* Search for device nodes in /dev for Android support
* Other bug fixes
2012-04-17: v1.0.10
* Public release
* Add libusb_get_version
* Add Visual Studio 2010 project files
* Some Windows code cleanup
* Fix xusb sample warnings
2012-04-02: v1.0.9
* First libusbx release
* Add libusb_get_device_speed (all, except BSD) and libusb_error_name
* Add Windows support (WinUSB driver only)
* Add OpenBSD support
* Add xusb sample
* Tons of bug fixes
2010-05-07: v1.0.8
* Bug fixes
2010-04-19: v1.0.7
* Bug fixes and documentation tweaks
* Add more interface class definitions
2009-11-22: v1.0.6
* Bug fixes
* Increase libusb_handle_events() timeout to 60s for powersaving
2009-11-15: v1.0.5
* Use timerfd when available for timer management
* Small fixes/updates
2009-11-06: v1.0.4 release
* Bug fixes including transfer locking to fix some potential threading races
* More flexibility with clock types on Linux
* Use new bulk continuation tracking in Linux 2.6.32 for improved handling
of short/failed transfers
2009-08-27: v1.0.3 release
* Bug fixes
* Add libusb_get_max_iso_packet_size()
2009-06-13: v1.0.2 release
* Bug fixes
2009-05-12: v1.0.1 release
* Bug fixes
* Darwin backend
2008-12-13: v1.0.0 release
* Bug fixes
2008-11-21: v0.9.4 release
* Bug fixes
* Add libusb_attach_kernel_driver()
2008-08-23: v0.9.3 release
* Bug fixes
2008-07-19: v0.9.2 release
* Bug fixes
2008-06-28: v0.9.1 release
* Bug fixes
* Introduce contexts to the API
* Compatibility with new Linux kernel features
2008-05-25: v0.9.0 release
* First libusb-1.0 beta release
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
APPENDIX A - How to maintain code compatibility with versions of libusb and
libusb that use MaxPower:
If you must to maintain compatibility with versions of the library that aren't
using the bMaxPower attribute in struct libusb_config_descriptor, the
recommended way is to use the new LIBUSB_API_VERSION macro with an #ifdef.
For instance, if your code was written as follows:
if (dev->config[0].MaxPower < 250)
Then you should modify it to have:
#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000100)
if (dev->config[0].bMaxPower < 250)
#else
if (dev->config[0].MaxPower < 250)
#endif

View File

@ -1,370 +0,0 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@ -1,73 +0,0 @@
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

View File

@ -1,28 +0,0 @@
AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip
ACLOCAL_AMFLAGS = -I m4
DISTCLEANFILES = libusb-1.0.pc
EXTRA_DIST = TODO PORTING msvc libusb/libusb-1.0.def libusb/version_nano.h \
examples/getopt/getopt.c examples/getopt/getopt1.c examples/getopt/getopt.h \
android Xcode
SUBDIRS = libusb doc
if BUILD_EXAMPLES
SUBDIRS += examples
endif
if BUILD_TESTS
SUBDIRS += tests
endif
pkgconfigdir=$(libdir)/pkgconfig
pkgconfig_DATA=libusb-1.0.pc
.PHONY: dist-up
reldir = .release/$(distdir)
dist-up: dist
rm -rf $(reldir)
mkdir -p $(reldir)
cp $(distdir).tar.bz2 $(reldir)
rsync -rv $(reldir) frs.sourceforge.net:/home/frs/project/l/li/libusb/libusb-1.0/
rm -rf $(reldir)

View File

@ -1,2 +0,0 @@
For the latest libusb news, please refer to the ChangeLog file, or visit:
http://libusb.info

View File

@ -1,94 +0,0 @@
PORTING LIBUSB TO OTHER PLATFORMS
Introduction
============
This document is aimed at developers wishing to port libusb to unsupported
platforms. I believe the libusb API is OS-independent, so by supporting
multiple operating systems we pave the way for cross-platform USB device
drivers.
Implementation-wise, the basic idea is that you provide an interface to
libusb's internal "backend" API, which performs the appropriate operations on
your target platform.
In terms of USB I/O, your backend provides functionality to submit
asynchronous transfers (synchronous transfers are implemented in the higher
layers, based on the async interface). Your backend must also provide
functionality to cancel those transfers.
Your backend must also provide an event handling function to "reap" ongoing
transfers and process their results.
The backend must also provide standard functions for other USB operations,
e.g. setting configuration, obtaining descriptors, etc.
File descriptors for I/O polling
================================
For libusb to work, your event handling function obviously needs to be called
at various points in time. Your backend must provide a set of file descriptors
which libusb and its users can pass to poll() or select() to determine when
it is time to call the event handling function.
On Linux, this is easy: the usbfs kernel interface exposes a file descriptor
which can be passed to poll(). If something similar is not true for your
platform, you can emulate this using an internal library thread to reap I/O as
necessary, and a pipe() with the main library to raise events. The file
descriptor of the pipe can then be provided to libusb as an event source.
Interface semantics and documentation
=====================================
Documentation of the backend interface can be found in libusbi.h inside the
usbi_os_backend structure definition.
Your implementations of these functions will need to call various internal
libusb functions, prefixed with "usbi_". Documentation for these functions
can be found in the .c files where they are implemented.
You probably want to skim over *all* the documentation before starting your
implementation. For example, you probably need to allocate and store private
OS-specific data for device handles, but the documentation for the mechanism
for doing so is probably not the first thing you will see.
The Linux backend acts as a good example - view it as a reference
implementation which you should try to match the behaviour of.
Getting started
===============
1. Modify configure.ac to detect your platform appropriately (see the OS_LINUX
stuff for an example).
2. Implement your backend in the libusb/os/ directory, modifying
libusb/os/Makefile.am appropriately.
3. Add preprocessor logic to the top of libusb/core.c to statically assign the
right usbi_backend for your platform.
4. Produce and test your implementation.
5. Send your implementation to libusb-devel mailing list.
Implementation difficulties? Questions?
=======================================
If you encounter difficulties porting libusb to your platform, please raise
these issues on the libusb-devel mailing list. Where possible and sensible, I
am interested in solving problems preventing libusb from operating on other
platforms.
The libusb-devel mailing list is also a good place to ask questions and
make suggestions about the internal API. Hopefully we can produce some
better documentation based on your questions and other input.
You are encouraged to get involved in the process; if the library needs
some infrastructure additions/modifications to better support your platform,
you are encouraged to make such changes (in cleanly distinct patch
submissions). Even if you do not make such changes yourself, please do raise
the issues on the mailing list at the very minimum.

View File

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

View File

@ -1,41 +0,0 @@
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.

View File

@ -1,32 +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, 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)

View File

@ -1,2 +0,0 @@
Please see the libusb roadmap by visiting:
https://github.com/libusb/libusb/milestones?direction=asc&sort=due_date&state=open

View File

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

View File

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

View File

@ -1,47 +1,91 @@
/* Default visibility */
/* from libusb v1.0.26 release. modified for cmake for dolphin */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to the attribute for default visibility. */
#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
/* Start with debug message logging enabled */
/* Define to 1 to start with debug message logging enabled. */
#undef ENABLE_DEBUG_LOGGING
/* Message logging */
/* Define to 1 to enable message logging. */
#undef ENABLE_LOGGING
/* Define to 1 if you have the <asm/types.h> header file. */
#cmakedefine HAVE_ASM_TYPES_H 1
/* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the `clock_gettime' function. */
#cmakedefine HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the declaration of `EFD_CLOEXEC', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_EFD_CLOEXEC 1
/* Define to 1 if you have the declaration of `EFD_NONBLOCK', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_EFD_NONBLOCK 1
/* Define to 1 if you have the declaration of `TFD_CLOEXEC', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_TFD_CLOEXEC 1
/* Define to 1 if you have the declaration of `TFD_NONBLOCK', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_TFD_NONBLOCK 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
/* Define to 1 if the system has eventfd functionality. */
#cmakedefine HAVE_EVENTFD 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the <IOKit/usb/IOUSBHostFamilyDefinitions.h> header
file. */
#cmakedefine HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H 1
/* Define to 1 if you have the `udev' library (-ludev). */
#cmakedefine HAVE_LIBUDEV 1
/* Define to 1 if you have the <linux/filter.h> header file. */
#cmakedefine HAVE_LINUX_FILTER_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define to 1 if you have the <linux/netlink.h> header file. */
#cmakedefine HAVE_LINUX_NETLINK_H 1
/* Define to 1 if the system has the type `nfds_t'. */
#cmakedefine HAVE_NFDS_T 1
/* Define to 1 if you have the <poll.h> header file. */
#cmakedefine HAVE_POLL_H 1
/* Define to 1 if you have the `pipe2' function. */
#cmakedefine HAVE_PIPE2 1
/* Define to 1 if you have the <signal.h> header file. */
#cmakedefine HAVE_SIGNAL_H 1
/* Define to 1 if you have the `pthread_condattr_setclock' function. */
#cmakedefine HAVE_PTHREAD_CONDATTR_SETCLOCK 1
/* Define to 1 if you have the `pthread_setname_np' function. */
#cmakedefine HAVE_PTHREAD_SETNAME_NP 1
/* Define to 1 if you have the `pthread_threadid_np' function. */
#cmakedefine HAVE_PTHREAD_THREADID_NP 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
/* Define to 1 if the system has the type `struct timespec'. */
#cmakedefine HAVE_STRUCT_TIMESPEC 1
/* syslog() function available */
#cmakedefine HAVE_SYSLOG_FUNC 1
/* Define to 1 if you have the `syslog' function. */
#cmakedefine HAVE_SYSLOG 1
/* Define to 1 if you have the <syslog.h> header file. */
#cmakedefine HAVE_SYSLOG_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
@ -49,38 +93,66 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Darwin backend */
#cmakedefine OS_DARWIN 1
/* Define to 1 if the system has timerfd functionality. */
#cmakedefine HAVE_TIMERFD 1
/* Linux backend */
#cmakedefine OS_LINUX 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* NetBSD backend */
#cmakedefine OS_NETBSD 1
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#undef LT_OBJDIR
/* OpenBSD backend */
#cmakedefine OS_OPENBSD 1
/* Name of package */
#undef PACKAGE
/* Windows backend */
#cmakedefine OS_WINDOWS 1
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* type of second poll() argument */
#define POLL_NFDS_TYPE @POLL_NFDS_TYPE@
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Use POSIX Threads */
#cmakedefine THREADS_POSIX
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* timerfd headers available */
#cmakedefine USBI_TIMERFD_AVAILABLE 1
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Enable output to system log */
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if compiling for a POSIX platform. */
#cmakedefine PLATFORM_POSIX 1
/* Define to 1 if compiling for a Windows platform. */
#cmakedefine PLATFORM_WINDOWS 1
/* Define to the attribute for enabling parameter checks on printf-like
functions. */
#define PRINTF_FORMAT(a, b) __attribute__((format(printf, a, b)))
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* UMockdev hotplug code is not racy */
#undef UMOCKDEV_HOTPLUG
/* Define to 1 to output logging messages to the systemwide log. */
#define USE_SYSTEM_LOGGING_FACILITY 1
/* Use udev for device enumeration/hotplug */
#cmakedefine USE_UDEV 1
/* Version number of package */
#undef VERSION
/* Use GNU extensions */
/* Enable GNU extensions. */
#define _GNU_SOURCE
/* Oldest Windows version supported */
#define WINVER 0x0501
/* Define to the oldest supported Windows version. */
//#undef _WIN32_WINNT
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif

View File

@ -1,332 +0,0 @@
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

1
Externals/libusb/libusb vendored Submodule

@ -0,0 +1 @@
Subproject commit 4239bc3a50014b8e6a5a2a59df1fff3b7469543b

View File

@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libusb-1.0
Description: C API for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Solaris userspace
Version: @VERSION@
Libs: -L${libdir} -lusb-1.0
Libs.private: @LIBS@
Cflags: -I${includedir}/libusb-1.0

View File

@ -18,36 +18,35 @@
<ItemDefinitionGroup>
<ClCompile>
<!-- Ensure libusb sees it's own config.h first... -->
<AdditionalIncludeDirectories>.\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>.\libusb\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="libusb\core.c" />
<ClCompile Include="libusb\descriptor.c" />
<ClCompile Include="libusb\hotplug.c" />
<ClCompile Include="libusb\io.c" />
<ClCompile Include="libusb\os\poll_windows.c" />
<ClCompile Include="libusb\strerror.c" />
<ClCompile Include="libusb\sync.c" />
<ClCompile Include="libusb\os\threads_windows.c" />
<ClCompile Include="libusb\os\windows_nt_common.c" />
<ClCompile Include="libusb\os\windows_usbdk.c" />
<ClCompile Include="libusb\os\windows_winusb.c" />
<ClCompile Include="libusb\libusb\core.c" />
<ClCompile Include="libusb\libusb\descriptor.c" />
<ClCompile Include="libusb\libusb\hotplug.c" />
<ClCompile Include="libusb\libusb\io.c" />
<ClCompile Include="libusb\libusb\os\events_windows.c" />
<ClCompile Include="libusb\libusb\os\threads_windows.c" />
<ClCompile Include="libusb\libusb\os\windows_common.c" />
<ClCompile Include="libusb\libusb\os\windows_usbdk.c" />
<ClCompile Include="libusb\libusb\os\windows_winusb.c" />
<ClCompile Include="libusb\libusb\strerror.c" />
<ClCompile Include="libusb\libusb\sync.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="msvc\config.h" />
<ClInclude Include="libusb\hotplug.h" />
<ClInclude Include="libusb\libusb.h" />
<ClInclude Include="libusb\libusbi.h" />
<ClInclude Include="libusb\os\poll_windows.h" />
<ClInclude Include="libusb\os\threads_windows.h" />
<ClInclude Include="libusb\version.h" />
<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" />
<ClInclude Include="libusb\libusb\hotplug.h" />
<ClInclude Include="libusb\libusb\libusb.h" />
<ClInclude Include="libusb\libusb\libusbi.h" />
<ClInclude Include="libusb\libusb\os\events_windows.h" />
<ClInclude Include="libusb\libusb\os\threads_windows.h" />
<ClInclude Include="libusb\libusb\os\windows_common.h" />
<ClInclude Include="libusb\libusb\os\windows_nt_common.h" />
<ClInclude Include="libusb\libusb\os\windows_usbdk.h" />
<ClInclude Include="libusb\libusb\os\windows_winusb.h" />
<ClInclude Include="libusb\libusb\version_nano.h" />
<ClInclude Include="libusb\libusb\version.h" />
<ClInclude Include="libusb\msvc\config.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -1,101 +0,0 @@
all: libusb-1.0.la libusb-1.0.dll
AUTOMAKE_OPTIONS = subdir-objects
lib_LTLIBRARIES = libusb-1.0.la
POSIX_POLL_SRC = os/poll_posix.h os/poll_posix.c
POSIX_THREADS_SRC = os/threads_posix.h os/threads_posix.c
WINDOWS_POLL_SRC = os/poll_windows.h os/poll_windows.c
WINDOWS_THREADS_SRC = os/threads_windows.h os/threads_windows.c
LINUX_USBFS_SRC = os/linux_usbfs.h os/linux_usbfs.c
DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c
OPENBSD_USB_SRC = os/openbsd_usb.c
NETBSD_USB_SRC = os/netbsd_usb.c
SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h
WINDOWS_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
EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \
$(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \
$(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \
$(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \
$(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
$(HAIKU_USB_SRC) \
os/linux_udev.c os/linux_netlink.c
if OS_LINUX
if USE_UDEV
OS_SRC = $(LINUX_USBFS_SRC) os/linux_udev.c
else
OS_SRC = $(LINUX_USBFS_SRC) os/linux_netlink.c
endif
endif
if OS_DARWIN
OS_SRC = $(DARWIN_USB_SRC)
AM_CFLAGS_EXT = -no-cpp-precomp
endif
if OS_OPENBSD
OS_SRC = $(OPENBSD_USB_SRC)
endif
if OS_NETBSD
OS_SRC = $(NETBSD_USB_SRC)
endif
if OS_SUNOS
OS_SRC = $(SUNOS_USB_SRC)
endif
if OS_HAIKU
noinst_LTLIBRARIES = libusb_haiku.la
libusb_haiku_la_SOURCES = $(HAIKU_USB_SRC)
libusb_1_0_la_LIBADD = libusb_haiku.la
endif
if OS_WINDOWS
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 $@
libusb-1.0.rc: version.h version_nano.h
endif
libusb-1.0.dll: libusb-1.0.def libusb-1.0.la
if CREATE_IMPORT_LIB
# Rebuild the import lib from the .def so that MS and MinGW DLLs can be interchanged
$(AM_V_GEN)$(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def $(srcdir)/libusb-1.0.def --dllname $@ --output-lib .libs/$@.a
endif
if OS_WINDOWS
POLL_SRC = $(WINDOWS_POLL_SRC)
else
POLL_SRC = $(POSIX_POLL_SRC)
endif
if THREADS_POSIX
THREADS_SRC = $(POSIX_THREADS_SRC)
else
THREADS_SRC = $(WINDOWS_THREADS_SRC)
endif
libusb_1_0_la_CFLAGS = $(AM_CFLAGS)
libusb_1_0_la_LDFLAGS = $(LTLDFLAGS)
libusb_1_0_la_SOURCES = libusbi.h libusb.h version.h version_nano.h \
core.c descriptor.c hotplug.h hotplug.c io.c strerror.c sync.c \
$(POLL_SRC) $(THREADS_SRC) $(OS_SRC)
hdrdir = $(includedir)/libusb-1.0
hdr_HEADERS = libusb.h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,373 +0,0 @@
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
/*
* Hotplug functions for libusb
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
* Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
*
* 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 <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <assert.h>
#include "libusbi.h"
#include "hotplug.h"
/**
* @defgroup libusb_hotplug Device hotplug event notification
* This page details how to use the libusb hotplug interface, where available.
*
* Be mindful that not all platforms currently implement hotplug notification and
* that you should first call on \ref libusb_has_capability() with parameter
* \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
*
* \page libusb_hotplug Device hotplug event notification
*
* \section hotplug_intro Introduction
*
* Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support
* for hotplug events on <b>some</b> platforms (you should test if your platform
* supports hotplug notification by calling \ref libusb_has_capability() with
* parameter \ref LIBUSB_CAP_HAS_HOTPLUG).
*
* This interface allows you to request notification for the arrival and departure
* of matching USB devices.
*
* To receive hotplug notification you register a callback by calling
* \ref libusb_hotplug_register_callback(). This function will optionally return
* a callback handle that can be passed to \ref libusb_hotplug_deregister_callback().
*
* A callback function must return an int (0 or 1) indicating whether the callback is
* expecting additional events. Returning 0 will rearm the callback and 1 will cause
* the callback to be deregistered. Note that when callbacks are called from
* libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
* flag, the callback return value is ignored, iow you cannot cause a callback
* to be deregistered by returning 1 when it is called from
* libusb_hotplug_register_callback().
*
* Callbacks for a particular context are automatically deregistered by libusb_exit().
*
* As of 1.0.16 there are two supported hotplug events:
* - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
* - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
*
* A hotplug event can listen for either or both of these events.
*
* Note: If you receive notification that a device has left and you have any
* a libusb_device_handles for the device it is up to you to call libusb_close()
* on each device handle to free up any remaining resources associated with the device.
* Once a device has left any libusb_device_handle associated with the device
* are invalid and will remain so even if the device comes back.
*
* When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
* safe to call any libusb function that takes a libusb_device. It also safe to
* open a device and submit asynchronous transfers. However, most other functions
* that take a libusb_device_handle are <b>not</b> safe to call. Examples of such
* functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking
* functions that retrieve various \ref libusb_desc "USB descriptors". These functions must
* be used outside of the context of the hotplug callback.
*
* When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
* is libusb_get_device_descriptor().
*
* The following code provides an example of the usage of the hotplug interface:
\code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <libusb.h>
static int count = 0;
int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *user_data) {
static libusb_device_handle *dev_handle = NULL;
struct libusb_device_descriptor desc;
int rc;
(void)libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
rc = libusb_open(dev, &dev_handle);
if (LIBUSB_SUCCESS != rc) {
printf("Could not open USB device\n");
}
} else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
if (dev_handle) {
libusb_close(dev_handle);
dev_handle = NULL;
}
} else {
printf("Unhandled event %d\n", event);
}
count++;
return 0;
}
int main (void) {
libusb_hotplug_callback_handle callback_handle;
int rc;
libusb_init(NULL);
rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005,
LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
&callback_handle);
if (LIBUSB_SUCCESS != rc) {
printf("Error creating a hotplug callback\n");
libusb_exit(NULL);
return EXIT_FAILURE;
}
while (count < 2) {
libusb_handle_events_completed(NULL, NULL);
nanosleep(&(struct timespec){0, 10000000UL}, NULL);
}
libusb_hotplug_deregister_callback(NULL, callback_handle);
libusb_exit(NULL);
return 0;
}
\endcode
*/
static int usbi_hotplug_match_cb(struct libusb_context *ctx,
struct libusb_device *dev, libusb_hotplug_event event,
struct libusb_hotplug_callback *hotplug_cb)
{
if (!(hotplug_cb->flags & event)) {
return 0;
}
if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) &&
hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
return 0;
}
if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) &&
hotplug_cb->product_id != dev->device_descriptor.idProduct) {
return 0;
}
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);
}
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event)
{
struct libusb_hotplug_callback *hotplug_cb, *next;
int ret;
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);
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
if (ret) {
list_del(&hotplug_cb->list);
free(hotplug_cb);
}
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
}
void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event)
{
int pending_events;
struct libusb_hotplug_message *message = calloc(1, sizeof(*message));
if (!message) {
usbi_err(ctx, "error allocating hotplug message");
return;
}
message->event = event;
message->device = dev;
/* Take the event data lock and add this message to the list.
* Only signal an event if there are no prior pending events. */
usbi_mutex_lock(&ctx->event_data_lock);
pending_events = usbi_pending_events(ctx);
list_add_tail(&message->list, &ctx->hotplug_msgs);
if (!pending_events)
usbi_signal_event(ctx);
usbi_mutex_unlock(&ctx->event_data_lock);
}
int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
libusb_hotplug_event events, libusb_hotplug_flag flags,
int vendor_id, int product_id, int dev_class,
libusb_hotplug_callback_fn cb_fn, void *user_data,
libusb_hotplug_callback_handle *callback_handle)
{
struct libusb_hotplug_callback *new_callback;
/* check for sane values */
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 = calloc(1, sizeof(*new_callback));
if (!new_callback) {
return LIBUSB_ERROR_NO_MEM;
}
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;
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
/* 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) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) {
ssize_t i, len;
struct libusb_device **devs;
len = libusb_get_device_list(ctx, &devs);
if (len < 0) {
libusb_hotplug_deregister_callback(ctx,
new_callback->handle);
return (int)len;
}
for (i = 0; i < len; i++) {
usbi_hotplug_match_cb(ctx, devs[i],
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
new_callback);
}
libusb_free_device_list(devs, 1);
}
if (callback_handle)
*callback_handle = new_callback->handle;
return LIBUSB_SUCCESS;
}
void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx,
libusb_hotplug_callback_handle callback_handle)
{
struct libusb_hotplug_callback *hotplug_cb;
int deregistered = 0;
/* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
return;
}
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) {
if (callback_handle == hotplug_cb->handle) {
/* Mark this callback for deregistration */
hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE;
deregistered = 1;
}
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
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(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) {
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);
}

View File

@ -1,99 +0,0 @@
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
/*
* Hotplug support for libusb
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
* Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef USBI_HOTPLUG_H
#define USBI_HOTPLUG_H
#include "libusbi.h"
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
* libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback()
* to receive notification of hotplug events.
*/
struct libusb_hotplug_callback {
/** Flags that control how this callback behaves */
uint8_t flags;
/** Vendor ID to match (if flags says this is valid) */
uint16_t vendor_id;
/** Product ID to match (if flags says this is valid) */
uint16_t product_id;
/** 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;
/** Handle for this callback (used to match on deregister) */
libusb_hotplug_callback_handle handle;
/** User data that will be passed to the callback function */
void *user_data;
/** List this callback is registered in (ctx->hotplug_cbs) */
struct list_head list;
};
struct libusb_hotplug_message {
/** The hotplug event that occurred */
libusb_hotplug_event event;
/** The device for which this hotplug event occurred */
struct libusb_device *device;
/** List this message is contained in (ctx->hotplug_msgs) */
struct list_head list;
};
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,
libusb_hotplug_event event);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,178 +0,0 @@
LIBRARY "libusb-1.0.dll"
EXPORTS
libusb_alloc_streams
libusb_alloc_streams@16 = libusb_alloc_streams
libusb_alloc_transfer
libusb_alloc_transfer@4 = libusb_alloc_transfer
libusb_attach_kernel_driver
libusb_attach_kernel_driver@8 = libusb_attach_kernel_driver
libusb_bulk_transfer
libusb_bulk_transfer@24 = libusb_bulk_transfer
libusb_cancel_transfer
libusb_cancel_transfer@4 = libusb_cancel_transfer
libusb_claim_interface
libusb_claim_interface@8 = libusb_claim_interface
libusb_clear_halt
libusb_clear_halt@8 = libusb_clear_halt
libusb_close
libusb_close@4 = libusb_close
libusb_control_transfer
libusb_control_transfer@32 = libusb_control_transfer
libusb_detach_kernel_driver
libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver
libusb_dev_mem_alloc
libusb_dev_mem_alloc@8 = libusb_dev_mem_alloc
libusb_dev_mem_free
libusb_dev_mem_free@12 = libusb_dev_mem_free
libusb_error_name
libusb_error_name@4 = libusb_error_name
libusb_event_handler_active
libusb_event_handler_active@4 = libusb_event_handler_active
libusb_event_handling_ok
libusb_event_handling_ok@4 = libusb_event_handling_ok
libusb_exit
libusb_exit@4 = libusb_exit
libusb_free_bos_descriptor
libusb_free_bos_descriptor@4 = libusb_free_bos_descriptor
libusb_free_config_descriptor
libusb_free_config_descriptor@4 = libusb_free_config_descriptor
libusb_free_container_id_descriptor
libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor
libusb_free_device_list
libusb_free_device_list@8 = libusb_free_device_list
libusb_free_pollfds
libusb_free_pollfds@4 = libusb_free_pollfds
libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_usb_device_capability_descriptor
libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
libusb_free_streams
libusb_free_streams@12 = libusb_free_streams
libusb_free_transfer
libusb_free_transfer@4 = libusb_free_transfer
libusb_free_usb_2_0_extension_descriptor
libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor
libusb_get_active_config_descriptor
libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor
libusb_get_bos_descriptor
libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor
libusb_get_bus_number
libusb_get_bus_number@4 = libusb_get_bus_number
libusb_get_config_descriptor
libusb_get_config_descriptor@12 = libusb_get_config_descriptor
libusb_get_config_descriptor_by_value
libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
libusb_get_configuration
libusb_get_configuration@8 = libusb_get_configuration
libusb_get_container_id_descriptor
libusb_get_container_id_descriptor@12 = libusb_get_container_id_descriptor
libusb_get_device
libusb_get_device@4 = libusb_get_device
libusb_get_device_address
libusb_get_device_address@4 = libusb_get_device_address
libusb_get_device_descriptor
libusb_get_device_descriptor@8 = libusb_get_device_descriptor
libusb_get_device_list
libusb_get_device_list@8 = libusb_get_device_list
libusb_get_device_speed
libusb_get_device_speed@4 = libusb_get_device_speed
libusb_get_max_iso_packet_size
libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size
libusb_get_max_packet_size
libusb_get_max_packet_size@8 = libusb_get_max_packet_size
libusb_get_next_timeout
libusb_get_next_timeout@8 = libusb_get_next_timeout
libusb_get_parent
libusb_get_parent@4 = libusb_get_parent
libusb_get_pollfds
libusb_get_pollfds@4 = libusb_get_pollfds
libusb_get_port_number
libusb_get_port_number@4 = libusb_get_port_number
libusb_get_port_numbers
libusb_get_port_numbers@12 = libusb_get_port_numbers
libusb_get_port_path
libusb_get_port_path@16 = libusb_get_port_path
libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_usb_device_capability_descriptor
libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
libusb_get_string_descriptor_ascii
libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
libusb_get_usb_2_0_extension_descriptor
libusb_get_usb_2_0_extension_descriptor@12 = libusb_get_usb_2_0_extension_descriptor
libusb_get_version
libusb_get_version@0 = libusb_get_version
libusb_handle_events
libusb_handle_events@4 = libusb_handle_events
libusb_handle_events_completed
libusb_handle_events_completed@8 = libusb_handle_events_completed
libusb_handle_events_locked
libusb_handle_events_locked@8 = libusb_handle_events_locked
libusb_handle_events_timeout
libusb_handle_events_timeout@8 = libusb_handle_events_timeout
libusb_handle_events_timeout_completed
libusb_handle_events_timeout_completed@12 = libusb_handle_events_timeout_completed
libusb_has_capability
libusb_has_capability@4 = libusb_has_capability
libusb_hotplug_deregister_callback
libusb_hotplug_deregister_callback@8 = libusb_hotplug_deregister_callback
libusb_hotplug_register_callback
libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
libusb_init
libusb_init@4 = libusb_init
libusb_interrupt_event_handler
libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler
libusb_interrupt_transfer
libusb_interrupt_transfer@24 = libusb_interrupt_transfer
libusb_kernel_driver_active
libusb_kernel_driver_active@8 = libusb_kernel_driver_active
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
libusb_open_device_with_vid_pid@12 = libusb_open_device_with_vid_pid
libusb_pollfds_handle_timeouts
libusb_pollfds_handle_timeouts@4 = libusb_pollfds_handle_timeouts
libusb_ref_device
libusb_ref_device@4 = libusb_ref_device
libusb_release_interface
libusb_release_interface@8 = libusb_release_interface
libusb_reset_device
libusb_reset_device@4 = libusb_reset_device
libusb_set_auto_detach_kernel_driver
libusb_set_auto_detach_kernel_driver@8 = libusb_set_auto_detach_kernel_driver
libusb_set_configuration
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_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
libusb_submit_transfer@4 = libusb_submit_transfer
libusb_transfer_get_stream_id
libusb_transfer_get_stream_id@4 = libusb_transfer_get_stream_id
libusb_transfer_set_stream_id
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_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
libusb_wait_for_event@8 = libusb_wait_for_event

View File

@ -1,61 +0,0 @@
/*
* For Windows: input this file to the Resoure Compiler to produce a binary
* .res file. This is then embedded in the resultant library (like any other
* compilation object).
* The information can then be queried using standard APIs and can also be
* viewed with utilities such as Windows Explorer.
*/
#ifndef _WIN32_WCE
#include "winresrc.h"
#endif
#include "version.h"
#ifndef LIBUSB_VERSIONSTRING
#define LU_STR(s) #s
#define LU_XSTR(s) LU_STR(s)
#if LIBUSB_NANO > 0
#define LIBUSB_VERSIONSTRING \
LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \
LU_XSTR(LIBUSB_MICRO) "." LU_XSTR(LIBUSB_NANO) LIBUSB_RC "\0"
#else
#define LIBUSB_VERSIONSTRING \
LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \
LU_XSTR(LIBUSB_MICRO) LIBUSB_RC "\0"
#endif
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION LIBUSB_MAJOR,LIBUSB_MINOR,LIBUSB_MICRO,LIBUSB_NANO
PRODUCTVERSION LIBUSB_MAJOR,LIBUSB_MINOR,LIBUSB_MICRO,LIBUSB_NANO
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "libusb.info\0"
VALUE "FileDescription", "C library for writing portable USB drivers in userspace\0"
VALUE "FileVersion", LIBUSB_VERSIONSTRING
VALUE "InternalName", "libusb\0"
VALUE "LegalCopyright", "See individual source files, GNU LGPL v2.1 or later.\0"
VALUE "LegalTrademarks", "http://www.gnu.org/licenses/lgpl-2.1.html\0"
VALUE "OriginalFilename", "libusb-1.0.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "libusb-1.0\0"
VALUE "ProductVersion", LIBUSB_VERSIONSTRING
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,203 +0,0 @@
/*
* darwin backend for libusb 1.0
* 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
* 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
*/
#if !defined(LIBUSB_DARWIN_H)
#define LIBUSB_DARWIN_H
#include <stdbool.h>
#include "libusbi.h"
#include <IOKit/IOTypes.h>
#include <IOKit/IOCFBundle.h>
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
/* IOUSBInterfaceInferface */
/* 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
/* 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
/* 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
/* 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
/* 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
/* New in OS 10.4.0. */
#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040)
#define usb_interface_t IOUSBInterfaceInterface220
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
#define InterfaceVersion 220
#else
#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
#endif
/* IOUSBDeviceInterface */
/* 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
/* 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
/* 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
/* 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
/* 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 SDK and/or deployment target"
#endif
#if !defined(IO_OBJECT_NULL)
#define IO_OBJECT_NULL ((io_object_t) 0)
#endif
typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
typedef IONotificationPortRef io_notification_port_t;
/* private structures */
struct darwin_cached_device {
struct list_head list;
IOUSBDeviceDescriptor dev_descriptor;
UInt32 location;
UInt64 parent_session;
UInt64 session;
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 {
struct darwin_cached_device *dev;
};
struct darwin_device_handle_priv {
bool is_open;
CFRunLoopSourceRef cfSource;
struct darwin_interface {
usb_interface_t **interface;
uint8_t num_endpoints;
CFRunLoopSourceRef cfSource;
uint64_t frames[256];
uint8_t endpoint_addrs[USB_MAXENDPOINTS];
} interfaces[USB_MAXINTERFACES];
};
struct darwin_transfer_priv {
/* Isoc */
IOUSBIsocFrame *isoc_framelist;
int num_iso_packets;
/* Control */
IOUSBDevRequestTO req;
/* Bulk */
/* Completion status */
IOReturn result;
UInt32 size;
};
#endif

View File

@ -1,5 +0,0 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
noinst_LTLIBRARIES = libhaikuusb.la
libhaikuusb_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/.. -I$(srcdir)/../.. -I$(srcdir)/../../.. -I$(srcdir)/../../../..
libhaikuusb_la_SOURCES = haiku_usb_raw.cpp haiku_usb_backend.cpp haiku_pollfs.cpp haiku_usb_raw.h haiku_usb.h

View File

@ -1,810 +0,0 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
$(am__configure_deps) $(am__DIST_COMMON)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libhaikuusb_la_LIBADD =
am_libhaikuusb_la_OBJECTS = libhaikuusb_la-haiku_usb_raw.lo \
libhaikuusb_la-haiku_usb_backend.lo \
libhaikuusb_la-haiku_pollfs.lo
libhaikuusb_la_OBJECTS = $(am_libhaikuusb_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CXXFLAGS) $(CXXFLAGS)
AM_V_CXX = $(am__v_CXX_@AM_V@)
am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
am__v_CXX_0 = @echo " CXX " $@;
am__v_CXX_1 =
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
am__v_CXXLD_0 = @echo " CXXLD " $@;
am__v_CXXLD_1 =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libhaikuusb_la_SOURCES)
DIST_SOURCES = $(libhaikuusb_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
AM_RECURSIVE_TARGETS = cscope
am__DIST_COMMON = $(srcdir)/Makefile.in compile config.guess \
config.sub depcomp install-sh ltmain.sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
if test -d "$(distdir)"; then \
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
am__post_remove_distdir = $(am__remove_distdir)
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
noinst_LTLIBRARIES = libhaikuusb.la
libhaikuusb_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/.. -I$(srcdir)/../.. -I$(srcdir)/../../.. -I$(srcdir)/../../../..
libhaikuusb_la_SOURCES = haiku_usb_raw.cpp haiku_usb_backend.cpp haiku_pollfs.cpp haiku_usb_raw.h haiku_usb.h
all: all-am
.SUFFIXES:
.SUFFIXES: .cpp .lo .o .obj
am--refresh: Makefile
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
libhaikuusb.la: $(libhaikuusb_la_OBJECTS) $(libhaikuusb_la_DEPENDENCIES) $(EXTRA_libhaikuusb_la_DEPENDENCIES)
$(AM_V_CXXLD)$(CXXLINK) $(libhaikuusb_la_OBJECTS) $(libhaikuusb_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhaikuusb_la-haiku_pollfs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhaikuusb_la-haiku_usb_backend.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhaikuusb_la-haiku_usb_raw.Plo@am__quote@
.cpp.o:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
.cpp.obj:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.cpp.lo:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
libhaikuusb_la-haiku_usb_raw.lo: haiku_usb_raw.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhaikuusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libhaikuusb_la-haiku_usb_raw.lo -MD -MP -MF $(DEPDIR)/libhaikuusb_la-haiku_usb_raw.Tpo -c -o libhaikuusb_la-haiku_usb_raw.lo `test -f 'haiku_usb_raw.cpp' || echo '$(srcdir)/'`haiku_usb_raw.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhaikuusb_la-haiku_usb_raw.Tpo $(DEPDIR)/libhaikuusb_la-haiku_usb_raw.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='haiku_usb_raw.cpp' object='libhaikuusb_la-haiku_usb_raw.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhaikuusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libhaikuusb_la-haiku_usb_raw.lo `test -f 'haiku_usb_raw.cpp' || echo '$(srcdir)/'`haiku_usb_raw.cpp
libhaikuusb_la-haiku_usb_backend.lo: haiku_usb_backend.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhaikuusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libhaikuusb_la-haiku_usb_backend.lo -MD -MP -MF $(DEPDIR)/libhaikuusb_la-haiku_usb_backend.Tpo -c -o libhaikuusb_la-haiku_usb_backend.lo `test -f 'haiku_usb_backend.cpp' || echo '$(srcdir)/'`haiku_usb_backend.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhaikuusb_la-haiku_usb_backend.Tpo $(DEPDIR)/libhaikuusb_la-haiku_usb_backend.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='haiku_usb_backend.cpp' object='libhaikuusb_la-haiku_usb_backend.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhaikuusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libhaikuusb_la-haiku_usb_backend.lo `test -f 'haiku_usb_backend.cpp' || echo '$(srcdir)/'`haiku_usb_backend.cpp
libhaikuusb_la-haiku_pollfs.lo: haiku_pollfs.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhaikuusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libhaikuusb_la-haiku_pollfs.lo -MD -MP -MF $(DEPDIR)/libhaikuusb_la-haiku_pollfs.Tpo -c -o libhaikuusb_la-haiku_pollfs.lo `test -f 'haiku_pollfs.cpp' || echo '$(srcdir)/'`haiku_pollfs.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhaikuusb_la-haiku_pollfs.Tpo $(DEPDIR)/libhaikuusb_la-haiku_pollfs.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='haiku_pollfs.cpp' object='libhaikuusb_la-haiku_pollfs.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhaikuusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libhaikuusb_la-haiku_pollfs.lo `test -f 'haiku_pollfs.cpp' || echo '$(srcdir)/'`haiku_pollfs.cpp
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool config.lt
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscope: cscope.files
test ! -s cscope.files \
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
clean-cscope:
-rm -f cscope.files
cscope.files: clean-cscope cscopelist
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(DISTFILES)
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -755 \
-exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__post_remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
$(am__post_remove_distdir)
dist-lzip: distdir
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
$(am__post_remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__post_remove_distdir)
dist-shar: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__post_remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__post_remove_distdir)
dist dist-all:
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
$(am__post_remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lz*) \
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build/sub \
&& ../../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__post_remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@test -n '$(distuninstallcheck_dir)' || { \
echo 'ERROR: trying to run $@ with an empty' \
'$$(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
$(am__cd) '$(distuninstallcheck_dir)' || { \
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
clean-cscope clean-generic clean-libtool \
clean-noinstLTLIBRARIES cscope cscopelist-am ctags ctags-am \
dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \
dist-tarZ dist-xz dist-zip distcheck distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distcleancheck distdir distuninstallcheck dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

File diff suppressed because it is too large Load Diff

View File

@ -1,347 +0,0 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
AC_INIT([haikuusb], [1.0])
AM_INIT_AUTOMAKE([no-define foreign])
AM_MAINTAINER_MODE
LT_INIT
AC_PROG_CXX
AC_CONFIG_FILES([Makefile])
AC_CONFIG_MACRO_DIR([m4])
AC_OUTPUT

View File

@ -1,791 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,378 +0,0 @@
/*
* Copyright 2007-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "haiku_usb.h"
#include <cstdio>
#include <Directory.h>
#include <Entry.h>
#include <Looper.h>
#include <Messenger.h>
#include <Node.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <cstring>
class WatchedEntry {
public:
WatchedEntry(BMessenger*, entry_ref*);
~WatchedEntry();
bool EntryCreated(entry_ref* ref);
bool EntryRemoved(ino_t node);
bool InitCheck();
private:
BMessenger* fMessenger;
node_ref fNode;
bool fIsDirectory;
USBDevice* fDevice;
WatchedEntry* fEntries;
WatchedEntry* fLink;
bool fInitCheck;
};
class RosterLooper : public BLooper {
public:
RosterLooper(USBRoster*);
void Stop();
virtual void MessageReceived(BMessage*);
bool InitCheck();
private:
USBRoster* fRoster;
WatchedEntry* fRoot;
BMessenger* fMessenger;
bool fInitCheck;
};
WatchedEntry::WatchedEntry(BMessenger* messenger, entry_ref* ref)
: fMessenger(messenger),
fIsDirectory(false),
fDevice(NULL),
fEntries(NULL),
fLink(NULL),
fInitCheck(false)
{
BEntry entry(ref);
entry.GetNodeRef(&fNode);
BDirectory directory;
if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) {
fIsDirectory = true;
while (directory.GetNextEntry(&entry) >= B_OK) {
if (entry.GetRef(ref) < B_OK)
continue;
WatchedEntry* child = new(std::nothrow) WatchedEntry(fMessenger, ref);
if (child == NULL)
continue;
if (child->InitCheck() == false)
{
delete child;
continue;
}
child->fLink = fEntries;
fEntries = child;
}
watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger);
} else {
if (strncmp(ref->name, "raw", 3) == 0)
return;
BPath path, parent_path;
entry.GetPath(&path);
fDevice = new(std::nothrow) USBDevice(path.Path());
if (fDevice != NULL && fDevice->InitCheck() == true) {
// Add this new device to each active context's device list
struct libusb_context *ctx;
unsigned long session_id = (unsigned long)&fDevice;
usbi_mutex_lock(&active_contexts_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
struct libusb_device* dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev) {
usbi_dbg("using previously allocated device with location %lu", session_id);
libusb_unref_device(dev);
continue;
}
usbi_dbg("allocating new device with location %lu" ,session_id);
dev = usbi_alloc_device(ctx, session_id);
if (!dev) {
usbi_dbg("device allocation failed");
continue;
}
*((USBDevice**)dev->os_priv) = fDevice;
// Calculate pseudo-device-address
int addr,tmp;
if (strcmp(path.Leaf(), "hub") == 0)
{
tmp=100; //Random Number
}
else
{
sscanf(path.Leaf(), "%d", &tmp);
}
addr = tmp + 1;
path.GetParent(&parent_path);
while(strcmp(parent_path.Leaf(),"usb") != 0)
{
sscanf(parent_path.Leaf(), "%d", &tmp);
addr += tmp + 1;
parent_path.GetParent(&parent_path);
}
sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number);
(dev->device_address) = addr - (dev->bus_number + 1);
if(usbi_sanitize_device(dev) < 0)
{
usbi_dbg("device sanitization failed");
libusb_unref_device(dev);
continue;
}
usbi_connect_device(dev);
}
usbi_mutex_unlock(&active_contexts_lock);
} else if (fDevice) {
delete fDevice;
fDevice = NULL;
return;
}
}
fInitCheck = true;
}
WatchedEntry::~WatchedEntry()
{
if (fIsDirectory) {
watch_node(&fNode, B_STOP_WATCHING, *fMessenger);
WatchedEntry* child = fEntries;
while (child) {
WatchedEntry *next = child->fLink;
delete child;
child = next;
}
}
if (fDevice) {
// Remove this device from each active context's device list
struct libusb_context *ctx;
struct libusb_device *dev;
unsigned long session_id = (unsigned long)&fDevice;
usbi_mutex_lock(&active_contexts_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
dev = usbi_get_device_by_session_id (ctx, session_id);
if (dev != NULL) {
usbi_disconnect_device (dev);
libusb_unref_device(dev);
} else {
usbi_dbg("device with location %lu not found", session_id);
}
}
usbi_mutex_static_unlock(&active_contexts_lock);
delete fDevice;
}
}
bool
WatchedEntry::EntryCreated(entry_ref *ref)
{
if (!fIsDirectory)
return false;
if (ref->directory != fNode.node) {
WatchedEntry* child = fEntries;
while (child) {
if (child->EntryCreated(ref))
return true;
child = child->fLink;
}
return false;
}
WatchedEntry* child = new(std::nothrow) WatchedEntry(fMessenger, ref);
if (child == NULL)
return false;
child->fLink = fEntries;
fEntries = child;
return true;
}
bool
WatchedEntry::EntryRemoved(ino_t node)
{
if (!fIsDirectory)
return false;
WatchedEntry* child = fEntries;
WatchedEntry* lastChild = NULL;
while (child) {
if (child->fNode.node == node) {
if (lastChild)
lastChild->fLink = child->fLink;
else
fEntries = child->fLink;
delete child;
return true;
}
if (child->EntryRemoved(node))
return true;
lastChild = child;
child = child->fLink;
}
return false;
}
bool
WatchedEntry::InitCheck()
{
return fInitCheck;
}
RosterLooper::RosterLooper(USBRoster* roster)
: BLooper("LibusbRoster Looper"),
fRoster(roster),
fRoot(NULL),
fMessenger(NULL),
fInitCheck(false)
{
BEntry entry("/dev/bus/usb");
if (!entry.Exists()) {
usbi_err(NULL,"usb_raw not published");
return;
}
Run();
fMessenger = new(std::nothrow) BMessenger(this);
if (fMessenger == NULL)
{
usbi_err(NULL,"error creating BMessenger object");
return;
}
if(Lock()) {
entry_ref ref;
entry.GetRef(&ref);
fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref);
Unlock();
if (fRoot == NULL)
{
return;
}
if (fRoot->InitCheck() == false)
{
delete fRoot;
return;
}
}
fInitCheck = true;
}
void
RosterLooper::Stop()
{
Lock();
delete fRoot;
delete fMessenger;
Quit();
}
void
RosterLooper::MessageReceived(BMessage *message)
{
int32 opcode;
if (message->FindInt32("opcode", &opcode) < B_OK)
return;
switch (opcode) {
case B_ENTRY_CREATED: {
dev_t device;
ino_t directory;
const char* name;
if (message->FindInt32("device", &device) < B_OK
|| message->FindInt64("directory", &directory) < B_OK
|| message->FindString("name", &name) < B_OK)
break;
entry_ref ref(device, directory, name);
fRoot->EntryCreated(&ref);
break;
}
case B_ENTRY_REMOVED: {
ino_t node;
if (message->FindInt64("node", &node) < B_OK)
break;
fRoot->EntryRemoved(node);
break;
}
}
}
bool
RosterLooper::InitCheck()
{
return fInitCheck;
}
USBRoster::USBRoster()
: fLooper(NULL)
{
}
USBRoster::~USBRoster()
{
Stop();
}
int
USBRoster::Start()
{
if(fLooper)
return LIBUSB_SUCCESS;
fLooper = new(std::nothrow) RosterLooper(this);
if (fLooper == NULL || ((RosterLooper*)fLooper)->InitCheck() == false)
return LIBUSB_ERROR_OTHER;
return LIBUSB_SUCCESS;
}
void
USBRoster::Stop()
{
if(!fLooper)
return;
((RosterLooper *)fLooper)->Stop();
fLooper = NULL;
}

View File

@ -1,112 +0,0 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.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 <List.h>
#include <Locker.h>
#include <Autolock.h>
#include <USBKit.h>
#include <map>
#include "libusbi.h"
#include "haiku_usb_raw.h"
using namespace std;
class USBDevice;
class USBDeviceHandle;
class USBTransfer;
class USBDevice {
public:
USBDevice(const char *);
virtual ~USBDevice();
const char* Location() const;
uint8 CountConfigurations() const;
const usb_device_descriptor* Descriptor() const;
const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const;
const usb_configuration_descriptor* ActiveConfiguration() const;
uint8 EndpointToIndex(uint8) const;
uint8 EndpointToInterface(uint8) const;
int ClaimInterface(int);
int ReleaseInterface(int);
int CheckInterfacesFree(int);
int SetActiveConfiguration(int);
int ActiveConfigurationIndex() const;
bool InitCheck();
private:
int Initialise();
unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask
usb_device_descriptor fDeviceDescriptor;
unsigned char** fConfigurationDescriptors;
int fActiveConfiguration;
char* fPath;
map<uint8,uint8> fConfigToIndex;
map<uint8,uint8>* fEndpointToIndex;
map<uint8,uint8>* fEndpointToInterface;
bool fInitCheck;
};
class USBDeviceHandle {
public:
USBDeviceHandle(USBDevice* dev);
virtual ~USBDeviceHandle();
int ClaimInterface(int);
int ReleaseInterface(int);
int SetConfiguration(int);
int SetAltSetting(int,int);
status_t SubmitTransfer(struct usbi_transfer*);
status_t CancelTransfer(USBTransfer*);
bool InitCheck();
private:
int fRawFD;
static status_t TransfersThread(void *);
void TransfersWorker();
USBDevice* fUSBDevice;
unsigned int fClaimedInterfaces;
BList fTransfers;
BLocker fTransfersLock;
sem_id fTransfersSem;
thread_id fTransfersThread;
bool fInitCheck;
};
class USBTransfer {
public:
USBTransfer(struct usbi_transfer*,USBDevice*);
virtual ~USBTransfer();
void Do(int);
struct usbi_transfer* UsbiTransfer();
void SetCancelled();
bool IsCancelled();
private:
struct usbi_transfer* fUsbiTransfer;
struct libusb_transfer* fLibusbTransfer;
USBDevice* fUSBDevice;
BLocker fStatusLock;
bool fCancelled;
};
class USBRoster {
public:
USBRoster();
virtual ~USBRoster();
int Start();
void Stop();
private:
void* fLooper;
};

View File

@ -1,550 +0,0 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.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 <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#include "haiku_usb.h"
int _errno_to_libusb(int status)
{
return status;
}
USBTransfer::USBTransfer(struct usbi_transfer* itransfer, USBDevice* device)
{
fUsbiTransfer=itransfer;
fLibusbTransfer=USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
fUSBDevice=device;
fCancelled=false;
}
USBTransfer::~USBTransfer()
{
}
struct usbi_transfer*
USBTransfer::UsbiTransfer()
{
return fUsbiTransfer;
}
void
USBTransfer::SetCancelled()
{
fCancelled=true;
}
bool
USBTransfer::IsCancelled()
{
return fCancelled;
}
void
USBTransfer::Do(int fRawFD)
{
switch(fLibusbTransfer->type)
{
case LIBUSB_TRANSFER_TYPE_CONTROL:
{
struct libusb_control_setup* setup=(struct libusb_control_setup*)fLibusbTransfer->buffer;
usb_raw_command command;
command.control.request_type=setup->bmRequestType;
command.control.request=setup->bRequest;
command.control.value=setup->wValue;
command.control.index=setup->wIndex;
command.control.length=setup->wLength;
command.control.data=fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
if(fCancelled)
{
break;
}
if(ioctl(fRawFD,B_USB_RAW_COMMAND_CONTROL_TRANSFER,&command,
sizeof(command)) || command.control.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed control transfer");
break;
}
fUsbiTransfer->transferred=command.control.length;
}
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
{
usb_raw_command command;
command.transfer.interface=fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
command.transfer.endpoint=fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
command.transfer.data=fLibusbTransfer->buffer;
command.transfer.length=fLibusbTransfer->length;
if(fCancelled)
{
break;
}
if(fLibusbTransfer->type==LIBUSB_TRANSFER_TYPE_BULK)
{
if(ioctl(fRawFD,B_USB_RAW_COMMAND_BULK_TRANSFER,&command,
sizeof(command)) || command.transfer.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed bulk transfer");
break;
}
}
else
{
if(ioctl(fRawFD,B_USB_RAW_COMMAND_INTERRUPT_TRANSFER,&command,
sizeof(command)) || command.transfer.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed interrupt transfer");
break;
}
}
fUsbiTransfer->transferred=command.transfer.length;
}
break;
// IsochronousTransfers not tested
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
{
usb_raw_command command;
command.isochronous.interface=fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
command.isochronous.endpoint=fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
command.isochronous.data=fLibusbTransfer->buffer;
command.isochronous.length=fLibusbTransfer->length;
command.isochronous.packet_count=fLibusbTransfer->num_iso_packets;
int i=0;
usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets];
for (i=0; i<fLibusbTransfer->num_iso_packets; i++)
{
if((int16)(fLibusbTransfer->iso_packet_desc[i]).length!=(fLibusbTransfer->iso_packet_desc[i]).length)
{
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed isochronous transfer");
break;
}
packetDescriptors[i].request_length=(int16)(fLibusbTransfer->iso_packet_desc[i]).length;
}
if(i<fLibusbTransfer->num_iso_packets)
{
break; // TODO Handle this error
}
command.isochronous.packet_descriptors=packetDescriptors;
if(fCancelled)
{
break;
}
if(ioctl(fRawFD,B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER,&command,
sizeof(command)) || command.isochronous.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed isochronous transfer");
break;
}
for (i=0; i<fLibusbTransfer->num_iso_packets; i++)
{
(fLibusbTransfer->iso_packet_desc[i]).actual_length=packetDescriptors[i].actual_length;
switch(packetDescriptors[i].status)
{
case B_OK: (fLibusbTransfer->iso_packet_desc[i]).status=LIBUSB_TRANSFER_COMPLETED;
break;
default: (fLibusbTransfer->iso_packet_desc[i]).status=LIBUSB_TRANSFER_ERROR;
break;
}
}
delete[] packetDescriptors;
// Do we put the length of transfer here, for isochronous transfers?
fUsbiTransfer->transferred=command.transfer.length;
}
break;
default:
usbi_err(TRANSFER_CTX(fLibusbTransfer),"Unknown type of transfer");
}
}
bool
USBDeviceHandle::InitCheck()
{
return fInitCheck;
}
status_t
USBDeviceHandle::TransfersThread(void* self)
{
USBDeviceHandle* handle = (USBDeviceHandle*)self;
handle->TransfersWorker();
return B_OK;
}
void
USBDeviceHandle::TransfersWorker()
{
while(true)
{
status_t status = acquire_sem(fTransfersSem);
if(status== B_BAD_SEM_ID)
break;
if(status == B_INTERRUPTED)
continue;
fTransfersLock.Lock();
USBTransfer* fPendingTransfer= (USBTransfer*) fTransfers.RemoveItem((int32)0);
fTransfersLock.Unlock();
fPendingTransfer->Do(fRawFD);
usbi_signal_transfer_completion(fPendingTransfer->UsbiTransfer());
}
}
status_t
USBDeviceHandle::SubmitTransfer(struct usbi_transfer* itransfer)
{
USBTransfer* transfer = new USBTransfer(itransfer,fUSBDevice);
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=transfer;
BAutolock locker(fTransfersLock);
fTransfers.AddItem(transfer);
release_sem(fTransfersSem);
return LIBUSB_SUCCESS;
}
status_t
USBDeviceHandle::CancelTransfer(USBTransfer* transfer)
{
transfer->SetCancelled();
fTransfersLock.Lock();
bool removed = fTransfers.RemoveItem(transfer);
fTransfersLock.Unlock();
if(removed)
{
usbi_signal_transfer_completion(transfer->UsbiTransfer());
}
return LIBUSB_SUCCESS;
}
USBDeviceHandle::USBDeviceHandle(USBDevice* dev)
:
fTransfersThread(-1),
fUSBDevice(dev),
fClaimedInterfaces(0),
fInitCheck(false)
{
fRawFD=open(dev->Location(), O_RDWR | O_CLOEXEC);
if(fRawFD < 0)
{
usbi_err(NULL,"failed to open device");
return;
}
fTransfersSem = create_sem(0, "Transfers Queue Sem");
fTransfersThread = spawn_thread(TransfersThread,"Transfer Worker",B_NORMAL_PRIORITY, this);
resume_thread(fTransfersThread);
fInitCheck = true;
}
USBDeviceHandle::~USBDeviceHandle()
{
if(fRawFD>0)
close(fRawFD);
for(int i=0; i<32; i++)
{
if(fClaimedInterfaces&(1<<i))
ReleaseInterface(i);
}
delete_sem(fTransfersSem);
if(fTransfersThread>0)
wait_for_thread(fTransfersThread, NULL);
}
int
USBDeviceHandle::ClaimInterface(int inumber)
{
int status=fUSBDevice->ClaimInterface(inumber);
if(status==LIBUSB_SUCCESS)
{
fClaimedInterfaces|=(1<<inumber);
}
return status;
}
int
USBDeviceHandle::ReleaseInterface(int inumber)
{
fUSBDevice->ReleaseInterface(inumber);
fClaimedInterfaces&=(!(1<<inumber));
return LIBUSB_SUCCESS;
}
int
USBDeviceHandle::SetConfiguration(int config)
{
int config_index=fUSBDevice->CheckInterfacesFree(config);
if(config_index==LIBUSB_ERROR_BUSY || config_index==LIBUSB_ERROR_NOT_FOUND)
return config_index;
usb_raw_command command;
command.config.config_index=config_index;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_SET_CONFIGURATION,&command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
return _errno_to_libusb(command.config.status);
}
fUSBDevice->SetActiveConfiguration(config_index);
return LIBUSB_SUCCESS;
}
int
USBDeviceHandle::SetAltSetting(int inumber, int alt)
{
usb_raw_command command;
command.alternate.config_index=fUSBDevice->ActiveConfigurationIndex();
command.alternate.interface_index=inumber;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX,&command,
sizeof(command)) || command.alternate.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"Error retrieving active alternate interface");
return _errno_to_libusb(command.alternate.status);
}
if(command.alternate.alternate_info == alt)
{
usbi_dbg("Setting alternate interface successful");
return LIBUSB_SUCCESS;
}
command.alternate.alternate_info = alt;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_SET_ALT_INTERFACE,&command, //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY
sizeof(command)) || command.alternate.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"Error setting alternate interface");
return _errno_to_libusb(command.alternate.status);
}
usbi_dbg("Setting alternate interface successful");
return LIBUSB_SUCCESS;
}
USBDevice::USBDevice(const char * path)
:
fPath(NULL),
fActiveConfiguration(0), //0?
fConfigurationDescriptors(NULL),
fClaimedInterfaces(0),
fEndpointToIndex(NULL),
fEndpointToInterface(NULL),
fInitCheck(false)
{
fPath=strdup(path);
Initialise();
}
USBDevice::~USBDevice()
{
free(fPath);
if (fConfigurationDescriptors)
{
for(int i=0;i<fDeviceDescriptor.num_configurations;i++)
{
if (fConfigurationDescriptors[i])
delete fConfigurationDescriptors[i];
}
delete[] fConfigurationDescriptors;
}
if (fEndpointToIndex)
delete[] fEndpointToIndex;
if (fEndpointToInterface)
delete[] fEndpointToInterface;
}
bool
USBDevice::InitCheck()
{
return fInitCheck;
}
const char*
USBDevice::Location() const
{
return fPath;
}
uint8
USBDevice::CountConfigurations() const
{
return fDeviceDescriptor.num_configurations;
}
const usb_device_descriptor*
USBDevice::Descriptor() const
{
return &fDeviceDescriptor;
}
const usb_configuration_descriptor*
USBDevice::ConfigurationDescriptor(uint32 index) const
{
if(index>CountConfigurations())
return NULL;
return (usb_configuration_descriptor*) fConfigurationDescriptors[index];
}
const usb_configuration_descriptor*
USBDevice::ActiveConfiguration() const
{
return (usb_configuration_descriptor*) fConfigurationDescriptors[fActiveConfiguration];
}
int
USBDevice::ActiveConfigurationIndex() const
{
return fActiveConfiguration;
}
int USBDevice::ClaimInterface(int interface)
{
if(interface>ActiveConfiguration()->number_interfaces)
{
return LIBUSB_ERROR_NOT_FOUND;
}
if((fClaimedInterfaces & (1<<interface)) !=0 )
return LIBUSB_ERROR_BUSY;
fClaimedInterfaces|=(1<<interface);
return LIBUSB_SUCCESS;
}
int USBDevice::ReleaseInterface(int interface)
{
fClaimedInterfaces&=(!(1<<interface));
return LIBUSB_SUCCESS;
}
int
USBDevice::CheckInterfacesFree(int config)
{
if(fConfigToIndex.count(config)==0)
return LIBUSB_ERROR_NOT_FOUND;
if(fClaimedInterfaces==0)
return fConfigToIndex[(uint8)config];
return LIBUSB_ERROR_BUSY;
}
int
USBDevice::SetActiveConfiguration(int config_index)
{
fActiveConfiguration=config_index;
return LIBUSB_SUCCESS;
}
uint8
USBDevice::EndpointToIndex(uint8 address) const
{
return fEndpointToIndex[fActiveConfiguration][address];
}
uint8
USBDevice::EndpointToInterface(uint8 address) const
{
return fEndpointToInterface[fActiveConfiguration][address];
}
int
USBDevice::Initialise() //Do we need more error checking, etc? How to report?
{
int fRawFD=open(fPath, O_RDWR | O_CLOEXEC);
if(fRawFD < 0)
return B_ERROR;
usb_raw_command command;
command.device.descriptor = &fDeviceDescriptor;
if(ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command,
sizeof(command)) || command.device.status != B_USB_RAW_STATUS_SUCCESS) {
close(fRawFD);
return B_ERROR;
}
size_t size;
fConfigurationDescriptors = new(std::nothrow) unsigned char*[fDeviceDescriptor.num_configurations];
fEndpointToIndex = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
fEndpointToInterface = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
for( int i=0; i<fDeviceDescriptor.num_configurations; i++)
{
size=0;
usb_configuration_descriptor tmp_config;
command.config.descriptor = &tmp_config;
command.config.config_index = i;
if(ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving configuration descriptor");
close(fRawFD);
return B_ERROR;
}
fConfigToIndex[tmp_config.configuration_value]=i;
fConfigurationDescriptors[i]=new(std::nothrow) unsigned char[tmp_config.total_length];
command.control.request_type=128;
command.control.request=6;
command.control.value=(2<<8)|i;
command.control.index=0;
command.control.length=tmp_config.total_length;
command.control.data=fConfigurationDescriptors[i];
if(ioctl(fRawFD,B_USB_RAW_COMMAND_CONTROL_TRANSFER,&command,
sizeof(command)) || command.control.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving full configuration descriptor");
close(fRawFD);
return B_ERROR;
}
for( int j=0;j<tmp_config.number_interfaces;j++)
{
command.alternate.config_index=i;
command.alternate.interface_index=j;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving number of alternate interfaces");
close(fRawFD);
return B_ERROR;
}
int num_alternate=command.alternate.alternate_info;
for( int k=0;k<num_alternate;k++)
{
usb_interface_descriptor tmp_interface;
command.interface_etc.config_index=i;
command.interface_etc.interface_index=j;
command.interface_etc.alternate_index=k;
command.interface_etc.descriptor=&tmp_interface;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving interface descriptor");
close(fRawFD);
return B_ERROR;
}
for( int l=0;l<tmp_interface.num_endpoints;l++)
{
usb_endpoint_descriptor tmp_endpoint;
command.endpoint_etc.config_index=i;
command.endpoint_etc.interface_index=j;
command.endpoint_etc.alternate_index=k;
command.endpoint_etc.endpoint_index=l;
command.endpoint_etc.descriptor=&tmp_endpoint;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving endpoint descriptor");
close(fRawFD);
return B_ERROR;
}
fEndpointToIndex[i][tmp_endpoint.endpoint_address]=l;
fEndpointToInterface[i][tmp_endpoint.endpoint_address]=j;
}
}
}
}
close(fRawFD);
fInitCheck = true;
return B_OK;
}

View File

@ -1,255 +0,0 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.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 <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#include "haiku_usb.h"
USBRoster gUsbRoster;
int32 gInitCount = 0;
static int
haiku_init(struct libusb_context* ctx)
{
if (atomic_add(&gInitCount, 1) == 0)
{
return gUsbRoster.Start();
}
return LIBUSB_SUCCESS;
}
static void
haiku_exit(void)
{
if (atomic_add(&gInitCount, -1) == 1)
gUsbRoster.Stop();
}
static int
haiku_open(struct libusb_device_handle *dev_handle)
{
USBDevice* dev=*((USBDevice**)dev_handle->dev->os_priv);
USBDeviceHandle *handle=new(std::nothrow) USBDeviceHandle(dev);
if (handle == NULL)
return LIBUSB_ERROR_NO_MEM;
if (handle->InitCheck() == false)
{
delete handle;
return LIBUSB_ERROR_NO_DEVICE;
}
*((USBDeviceHandle**)dev_handle->os_priv)=handle;
return LIBUSB_SUCCESS;
}
static void
haiku_close(struct libusb_device_handle *dev_handle)
{
USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv);
if(handle==NULL)
return;
delete handle;
*((USBDeviceHandle**)dev_handle->os_priv)=NULL;
}
static int
haiku_get_device_descriptor(struct libusb_device *device, unsigned char* buffer, int *host_endian)
{
USBDevice *dev = *((USBDevice**)(device->os_priv));
memcpy(buffer,dev->Descriptor(),DEVICE_DESC_LENGTH);
*host_endian=0;
return LIBUSB_SUCCESS;
}
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;
}
static int
haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
{
USBDevice *dev = *((USBDevice**)(device->os_priv));
const usb_configuration_descriptor* config = dev->ConfigurationDescriptor(config_index);
if(config==NULL)
{
usbi_err(DEVICE_CTX(device),"failed getting configuration descriptor");
return LIBUSB_ERROR_INVALID_PARAM;
}
if(len>config->total_length)
len=config->total_length;
memcpy(buffer,(unsigned char*)config,len);
*host_endian=0;
return len;
}
static int
haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
{
USBDeviceHandle * handle= *((USBDeviceHandle**)dev_handle->os_priv);
return handle->SetConfiguration(config);
}
static int
haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
{
USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv);
return handle->ClaimInterface(interface_number);
}
static int
haiku_set_altsetting(struct libusb_device_handle* dev_handle, int interface_number, int altsetting)
{
USBDeviceHandle* handle = *((USBDeviceHandle**)dev_handle->os_priv);
return handle->SetAltSetting(interface_number, altsetting);
}
static int
haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
{
USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv);
haiku_set_altsetting(dev_handle,interface_number,0);
return handle->ReleaseInterface(interface_number);
}
static int
haiku_submit_transfer(struct usbi_transfer * itransfer)
{
struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv);
return fDeviceHandle->SubmitTransfer(itransfer);
}
static int
haiku_cancel_transfer(struct usbi_transfer * itransfer)
{
struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv);
return fDeviceHandle->CancelTransfer(*((USBTransfer**)usbi_transfer_get_os_priv(itransfer)));
}
static void
haiku_clear_transfer_priv(struct usbi_transfer * itransfer)
{
USBTransfer* transfer=*((USBTransfer**)usbi_transfer_get_os_priv(itransfer));
delete transfer;
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL;
}
static int
haiku_handle_transfer_completion(struct usbi_transfer * itransfer)
{
USBTransfer* transfer=*((USBTransfer**)usbi_transfer_get_os_priv(itransfer));
usbi_mutex_lock(&itransfer->lock);
if(transfer->IsCancelled())
{
delete transfer;
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL;
usbi_mutex_unlock(&itransfer->lock);
if (itransfer->transferred < 0)
itransfer->transferred = 0;
return usbi_handle_transfer_cancellation(itransfer);
}
libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
if(itransfer->transferred < 0)
{
usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
status = LIBUSB_TRANSFER_ERROR;
itransfer->transferred=0;
}
delete transfer;
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL;
usbi_mutex_unlock(&itransfer->lock);
return usbi_handle_transfer_completion(itransfer, status);
}
static int
haiku_clock_gettime(int clkid, struct timespec *tp)
{
if(clkid == USBI_CLOCK_REALTIME)
return clock_gettime(CLOCK_REALTIME, tp);
if(clkid == USBI_CLOCK_MONOTONIC)
return clock_gettime(CLOCK_MONOTONIC, tp);
return LIBUSB_ERROR_INVALID_PARAM;
}
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,
/*.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,
/*.alloc_streams =*/ NULL,
/*.free_streams =*/ NULL,
/*.kernel_driver_active =*/ NULL,
/*.detach_kernel_driver =*/ NULL,
/*.attach_kernel_driver =*/ NULL,
/*.destroy_device =*/ NULL,
/*.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,
/*.clock_gettime =*/ haiku_clock_gettime,
#ifdef USBI_TIMERFD_AVAILABLE
/*.get_timerfd_clockid =*/ NULL,
#endif
/*.device_priv_size =*/ sizeof(USBDevice*),
/*.device_handle_priv_size =*/ sizeof(USBDeviceHandle*),
/*.transfer_priv_size =*/ sizeof(USBTransfer*),
};

View File

@ -1,180 +0,0 @@
/*
* Copyright 2006-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _USB_RAW_H_
#define _USB_RAW_H_
#include <USB3.h>
#define B_USB_RAW_PROTOCOL_VERSION 0x0015
#define B_USB_RAW_ACTIVE_ALTERNATE 0xffffffff
typedef enum {
B_USB_RAW_COMMAND_GET_VERSION = 0x1000,
B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR = 0x2000,
B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT,
B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX,
B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000,
B_USB_RAW_COMMAND_SET_FEATURE,
B_USB_RAW_COMMAND_CLEAR_FEATURE,
B_USB_RAW_COMMAND_GET_STATUS,
B_USB_RAW_COMMAND_GET_DESCRIPTOR,
B_USB_RAW_COMMAND_SET_ALT_INTERFACE,
B_USB_RAW_COMMAND_CONTROL_TRANSFER = 0x4000,
B_USB_RAW_COMMAND_INTERRUPT_TRANSFER,
B_USB_RAW_COMMAND_BULK_TRANSFER,
B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER
} usb_raw_command_id;
typedef enum {
B_USB_RAW_STATUS_SUCCESS = 0,
B_USB_RAW_STATUS_FAILED,
B_USB_RAW_STATUS_ABORTED,
B_USB_RAW_STATUS_STALLED,
B_USB_RAW_STATUS_CRC_ERROR,
B_USB_RAW_STATUS_TIMEOUT,
B_USB_RAW_STATUS_INVALID_CONFIGURATION,
B_USB_RAW_STATUS_INVALID_INTERFACE,
B_USB_RAW_STATUS_INVALID_ENDPOINT,
B_USB_RAW_STATUS_INVALID_STRING,
B_USB_RAW_STATUS_NO_MEMORY
} usb_raw_command_status;
typedef union {
struct {
status_t status;
} version;
struct {
status_t status;
usb_device_descriptor *descriptor;
} device;
struct {
status_t status;
usb_configuration_descriptor *descriptor;
uint32 config_index;
} config;
struct {
status_t status;
uint32 alternate_info;
uint32 config_index;
uint32 interface_index;
} alternate;
struct {
status_t status;
usb_interface_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
} interface;
struct {
status_t status;
usb_interface_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 alternate_index;
} interface_etc;
struct {
status_t status;
usb_endpoint_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 endpoint_index;
} endpoint;
struct {
status_t status;
usb_endpoint_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 alternate_index;
uint32 endpoint_index;
} endpoint_etc;
struct {
status_t status;
usb_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 generic_index;
size_t length;
} generic;
struct {
status_t status;
usb_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 alternate_index;
uint32 generic_index;
size_t length;
} generic_etc;
struct {
status_t status;
usb_string_descriptor *descriptor;
uint32 string_index;
size_t length;
} string;
struct {
status_t status;
uint8 type;
uint8 index;
uint16 language_id;
void *data;
size_t length;
} descriptor;
struct {
status_t status;
uint8 request_type;
uint8 request;
uint16 value;
uint16 index;
uint16 length;
void *data;
} control;
struct {
status_t status;
uint32 interface;
uint32 endpoint;
void *data;
size_t length;
} transfer;
struct {
status_t status;
uint32 interface;
uint32 endpoint;
void *data;
size_t length;
usb_iso_packet_descriptor *packet_descriptors;
uint32 packet_count;
} isochronous;
} usb_raw_command;
#endif // _USB_RAW_H_

View File

@ -1,501 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2013-12-25.23; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,384 +0,0 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 7 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option `$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl `shared' nor `disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [1], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the `shared' and
# `disable-shared' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the `static' and
# `disable-static' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the `fast-install'
# and `disable-fast-install' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the `pic-only' and `no-pic'
# LT_INIT options.
# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for lt_pkg in $withval; do
IFS="$lt_save_ifs"
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[pic_mode=default])
test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])

View File

@ -1,123 +0,0 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])

View File

@ -1,23 +0,0 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# @configure_input@
# serial 3337 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.2])
m4_define([LT_PACKAGE_REVISION], [1.3337])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.2'
macro_revision='1.3337'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

View File

@ -1,98 +0,0 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])

View File

@ -1,215 +0,0 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,367 +0,0 @@
/*
* Copyright 2007-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "haiku_usb.h"
#include <cstdio>
#include <Directory.h>
#include <Entry.h>
#include <Looper.h>
#include <Messenger.h>
#include <Node.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <cstring>
class WatchedEntry {
public:
WatchedEntry(BMessenger *, entry_ref *);
~WatchedEntry();
bool EntryCreated(entry_ref *ref);
bool EntryRemoved(ino_t node);
bool InitCheck();
private:
BMessenger* fMessenger;
node_ref fNode;
bool fIsDirectory;
USBDevice* fDevice;
WatchedEntry* fEntries;
WatchedEntry* fLink;
bool fInitCheck;
};
class RosterLooper : public BLooper {
public:
RosterLooper(USBRoster *);
void Stop();
virtual void MessageReceived(BMessage *);
bool InitCheck();
private:
USBRoster* fRoster;
WatchedEntry* fRoot;
BMessenger* fMessenger;
bool fInitCheck;
};
WatchedEntry::WatchedEntry(BMessenger *messenger, entry_ref *ref)
: fMessenger(messenger),
fIsDirectory(false),
fDevice(NULL),
fEntries(NULL),
fLink(NULL),
fInitCheck(false)
{
BEntry entry(ref);
entry.GetNodeRef(&fNode);
BDirectory directory;
if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) {
fIsDirectory = true;
while (directory.GetNextEntry(&entry) >= B_OK) {
if (entry.GetRef(ref) < B_OK)
continue;
WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref);
if (child == NULL)
continue;
if (child->InitCheck() == false) {
delete child;
continue;
}
child->fLink = fEntries;
fEntries = child;
}
watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger);
}
else {
if (strncmp(ref->name, "raw", 3) == 0)
return;
BPath path, parent_path;
entry.GetPath(&path);
fDevice = new(std::nothrow) USBDevice(path.Path());
if (fDevice != NULL && fDevice->InitCheck() == true) {
// Add this new device to each active context's device list
struct libusb_context *ctx;
unsigned long session_id = (unsigned long)&fDevice;
usbi_mutex_lock(&active_contexts_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev) {
usbi_dbg("using previously allocated device with location %lu", session_id);
libusb_unref_device(dev);
continue;
}
usbi_dbg("allocating new device with location %lu", session_id);
dev = usbi_alloc_device(ctx, session_id);
if (!dev) {
usbi_dbg("device allocation failed");
continue;
}
*((USBDevice **)dev->os_priv) = fDevice;
// Calculate pseudo-device-address
int addr, tmp;
if (strcmp(path.Leaf(), "hub") == 0)
tmp = 100; //Random Number
else
sscanf(path.Leaf(), "%d", &tmp);
addr = tmp + 1;
path.GetParent(&parent_path);
while (strcmp(parent_path.Leaf(), "usb") != 0) {
sscanf(parent_path.Leaf(), "%d", &tmp);
addr += tmp + 1;
parent_path.GetParent(&parent_path);
}
sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number);
dev->device_address = addr - (dev->bus_number + 1);
if (usbi_sanitize_device(dev) < 0) {
usbi_dbg("device sanitization failed");
libusb_unref_device(dev);
continue;
}
usbi_connect_device(dev);
}
usbi_mutex_unlock(&active_contexts_lock);
}
else if (fDevice) {
delete fDevice;
fDevice = NULL;
return;
}
}
fInitCheck = true;
}
WatchedEntry::~WatchedEntry()
{
if (fIsDirectory) {
watch_node(&fNode, B_STOP_WATCHING, *fMessenger);
WatchedEntry *child = fEntries;
while (child) {
WatchedEntry *next = child->fLink;
delete child;
child = next;
}
}
if (fDevice) {
// Remove this device from each active context's device list
struct libusb_context *ctx;
struct libusb_device *dev;
unsigned long session_id = (unsigned long)&fDevice;
usbi_mutex_lock(&active_contexts_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev != NULL) {
usbi_disconnect_device(dev);
libusb_unref_device(dev);
} else {
usbi_dbg("device with location %lu not found", session_id);
}
}
usbi_mutex_static_unlock(&active_contexts_lock);
delete fDevice;
}
}
bool
WatchedEntry::EntryCreated(entry_ref *ref)
{
if (!fIsDirectory)
return false;
if (ref->directory != fNode.node) {
WatchedEntry *child = fEntries;
while (child) {
if (child->EntryCreated(ref))
return true;
child = child->fLink;
}
return false;
}
WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref);
if (child == NULL)
return false;
child->fLink = fEntries;
fEntries = child;
return true;
}
bool
WatchedEntry::EntryRemoved(ino_t node)
{
if (!fIsDirectory)
return false;
WatchedEntry *child = fEntries;
WatchedEntry *lastChild = NULL;
while (child) {
if (child->fNode.node == node) {
if (lastChild)
lastChild->fLink = child->fLink;
else
fEntries = child->fLink;
delete child;
return true;
}
if (child->EntryRemoved(node))
return true;
lastChild = child;
child = child->fLink;
}
return false;
}
bool
WatchedEntry::InitCheck()
{
return fInitCheck;
}
RosterLooper::RosterLooper(USBRoster *roster)
: BLooper("LibusbRoster Looper"),
fRoster(roster),
fRoot(NULL),
fMessenger(NULL),
fInitCheck(false)
{
BEntry entry("/dev/bus/usb");
if (!entry.Exists()) {
usbi_err(NULL, "usb_raw not published");
return;
}
Run();
fMessenger = new(std::nothrow) BMessenger(this);
if (fMessenger == NULL) {
usbi_err(NULL, "error creating BMessenger object");
return;
}
if (Lock()) {
entry_ref ref;
entry.GetRef(&ref);
fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref);
Unlock();
if (fRoot == NULL)
return;
if (fRoot->InitCheck() == false) {
delete fRoot;
fRoot = NULL;
return;
}
}
fInitCheck = true;
}
void
RosterLooper::Stop()
{
Lock();
delete fRoot;
delete fMessenger;
Quit();
}
void
RosterLooper::MessageReceived(BMessage *message)
{
int32 opcode;
if (message->FindInt32("opcode", &opcode) < B_OK)
return;
switch (opcode) {
case B_ENTRY_CREATED:
{
dev_t device;
ino_t directory;
const char *name;
if (message->FindInt32("device", &device) < B_OK ||
message->FindInt64("directory", &directory) < B_OK ||
message->FindString("name", &name) < B_OK)
break;
entry_ref ref(device, directory, name);
fRoot->EntryCreated(&ref);
break;
}
case B_ENTRY_REMOVED:
{
ino_t node;
if (message->FindInt64("node", &node) < B_OK)
break;
fRoot->EntryRemoved(node);
break;
}
}
}
bool
RosterLooper::InitCheck()
{
return fInitCheck;
}
USBRoster::USBRoster()
: fLooper(NULL)
{
}
USBRoster::~USBRoster()
{
Stop();
}
int
USBRoster::Start()
{
if (fLooper == NULL) {
fLooper = new(std::nothrow) RosterLooper(this);
if (fLooper == NULL || ((RosterLooper *)fLooper)->InitCheck() == false) {
if (fLooper)
fLooper = NULL;
return LIBUSB_ERROR_OTHER;
}
}
return LIBUSB_SUCCESS;
}
void
USBRoster::Stop()
{
if (fLooper) {
((RosterLooper *)fLooper)->Stop();
fLooper = NULL;
}
}

View File

@ -1,112 +0,0 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.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 <List.h>
#include <Locker.h>
#include <Autolock.h>
#include <USBKit.h>
#include <map>
#include "libusbi.h"
#include "haiku_usb_raw.h"
using namespace std;
class USBDevice;
class USBDeviceHandle;
class USBTransfer;
class USBDevice {
public:
USBDevice(const char *);
virtual ~USBDevice();
const char* Location() const;
uint8 CountConfigurations() const;
const usb_device_descriptor* Descriptor() const;
const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const;
const usb_configuration_descriptor* ActiveConfiguration() const;
uint8 EndpointToIndex(uint8) const;
uint8 EndpointToInterface(uint8) const;
int ClaimInterface(int);
int ReleaseInterface(int);
int CheckInterfacesFree(int);
int SetActiveConfiguration(int);
int ActiveConfigurationIndex() const;
bool InitCheck();
private:
int Initialise();
unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask
usb_device_descriptor fDeviceDescriptor;
unsigned char** fConfigurationDescriptors;
int fActiveConfiguration;
char* fPath;
map<uint8,uint8> fConfigToIndex;
map<uint8,uint8>* fEndpointToIndex;
map<uint8,uint8>* fEndpointToInterface;
bool fInitCheck;
};
class USBDeviceHandle {
public:
USBDeviceHandle(USBDevice *dev);
virtual ~USBDeviceHandle();
int ClaimInterface(int);
int ReleaseInterface(int);
int SetConfiguration(int);
int SetAltSetting(int, int);
status_t SubmitTransfer(struct usbi_transfer *);
status_t CancelTransfer(USBTransfer *);
bool InitCheck();
private:
int fRawFD;
static status_t TransfersThread(void *);
void TransfersWorker();
USBDevice* fUSBDevice;
unsigned int fClaimedInterfaces;
BList fTransfers;
BLocker fTransfersLock;
sem_id fTransfersSem;
thread_id fTransfersThread;
bool fInitCheck;
};
class USBTransfer {
public:
USBTransfer(struct usbi_transfer *, USBDevice *);
virtual ~USBTransfer();
void Do(int);
struct usbi_transfer* UsbiTransfer();
void SetCancelled();
bool IsCancelled();
private:
struct usbi_transfer* fUsbiTransfer;
struct libusb_transfer* fLibusbTransfer;
USBDevice* fUSBDevice;
BLocker fStatusLock;
bool fCancelled;
};
class USBRoster {
public:
USBRoster();
virtual ~USBRoster();
int Start();
void Stop();
private:
void* fLooper;
};

View File

@ -1,517 +0,0 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.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 <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#include "haiku_usb.h"
int _errno_to_libusb(int status)
{
return status;
}
USBTransfer::USBTransfer(struct usbi_transfer *itransfer, USBDevice *device)
{
fUsbiTransfer = itransfer;
fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
fUSBDevice = device;
fCancelled = false;
}
USBTransfer::~USBTransfer()
{
}
struct usbi_transfer *
USBTransfer::UsbiTransfer()
{
return fUsbiTransfer;
}
void
USBTransfer::SetCancelled()
{
fCancelled = true;
}
bool
USBTransfer::IsCancelled()
{
return fCancelled;
}
void
USBTransfer::Do(int fRawFD)
{
switch (fLibusbTransfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
{
struct libusb_control_setup *setup = (struct libusb_control_setup *)fLibusbTransfer->buffer;
usb_raw_command command;
command.control.request_type = setup->bmRequestType;
command.control.request = setup->bRequest;
command.control.value = setup->wValue;
command.control.index = setup->wIndex;
command.control.length = setup->wLength;
command.control.data = fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
if (fCancelled)
break;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) ||
command.control.status != B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred = -1;
usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed control transfer");
break;
}
fUsbiTransfer->transferred = command.control.length;
}
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
{
usb_raw_command command;
command.transfer.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
command.transfer.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
command.transfer.data = fLibusbTransfer->buffer;
command.transfer.length = fLibusbTransfer->length;
if (fCancelled)
break;
if (fLibusbTransfer->type == LIBUSB_TRANSFER_TYPE_BULK) {
if (ioctl(fRawFD, B_USB_RAW_COMMAND_BULK_TRANSFER, &command, sizeof(command)) ||
command.transfer.status != B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred = -1;
usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed bulk transfer");
break;
}
}
else {
if (ioctl(fRawFD, B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, &command, sizeof(command)) ||
command.transfer.status != B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred = -1;
usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed interrupt transfer");
break;
}
}
fUsbiTransfer->transferred = command.transfer.length;
}
break;
// IsochronousTransfers not tested
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
{
usb_raw_command command;
command.isochronous.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
command.isochronous.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
command.isochronous.data = fLibusbTransfer->buffer;
command.isochronous.length = fLibusbTransfer->length;
command.isochronous.packet_count = fLibusbTransfer->num_iso_packets;
int i;
usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets];
for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) {
if ((int16)(fLibusbTransfer->iso_packet_desc[i]).length != (fLibusbTransfer->iso_packet_desc[i]).length) {
fUsbiTransfer->transferred = -1;
usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer");
break;
}
packetDescriptors[i].request_length = (int16)(fLibusbTransfer->iso_packet_desc[i]).length;
}
if (i < fLibusbTransfer->num_iso_packets)
break; // TODO Handle this error
command.isochronous.packet_descriptors = packetDescriptors;
if (fCancelled)
break;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER, &command, sizeof(command)) ||
command.isochronous.status != B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred = -1;
usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer");
break;
}
for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) {
(fLibusbTransfer->iso_packet_desc[i]).actual_length = packetDescriptors[i].actual_length;
switch (packetDescriptors[i].status) {
case B_OK:
(fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_COMPLETED;
break;
default:
(fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_ERROR;
break;
}
}
delete[] packetDescriptors;
// Do we put the length of transfer here, for isochronous transfers?
fUsbiTransfer->transferred = command.transfer.length;
}
break;
default:
usbi_err(TRANSFER_CTX(fLibusbTransfer), "Unknown type of transfer");
}
}
bool
USBDeviceHandle::InitCheck()
{
return fInitCheck;
}
status_t
USBDeviceHandle::TransfersThread(void *self)
{
USBDeviceHandle *handle = (USBDeviceHandle *)self;
handle->TransfersWorker();
return B_OK;
}
void
USBDeviceHandle::TransfersWorker()
{
while (true) {
status_t status = acquire_sem(fTransfersSem);
if (status == B_BAD_SEM_ID)
break;
if (status == B_INTERRUPTED)
continue;
fTransfersLock.Lock();
USBTransfer *fPendingTransfer = (USBTransfer *) fTransfers.RemoveItem((int32)0);
fTransfersLock.Unlock();
fPendingTransfer->Do(fRawFD);
usbi_signal_transfer_completion(fPendingTransfer->UsbiTransfer());
}
}
status_t
USBDeviceHandle::SubmitTransfer(struct usbi_transfer *itransfer)
{
USBTransfer *transfer = new USBTransfer(itransfer, fUSBDevice);
*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = transfer;
BAutolock locker(fTransfersLock);
fTransfers.AddItem(transfer);
release_sem(fTransfersSem);
return LIBUSB_SUCCESS;
}
status_t
USBDeviceHandle::CancelTransfer(USBTransfer *transfer)
{
transfer->SetCancelled();
fTransfersLock.Lock();
bool removed = fTransfers.RemoveItem(transfer);
fTransfersLock.Unlock();
if(removed)
usbi_signal_transfer_completion(transfer->UsbiTransfer());
return LIBUSB_SUCCESS;
}
USBDeviceHandle::USBDeviceHandle(USBDevice *dev)
:
fTransfersThread(-1),
fUSBDevice(dev),
fClaimedInterfaces(0),
fInitCheck(false)
{
fRawFD = open(dev->Location(), O_RDWR | O_CLOEXEC);
if (fRawFD < 0) {
usbi_err(NULL,"failed to open device");
return;
}
fTransfersSem = create_sem(0, "Transfers Queue Sem");
fTransfersThread = spawn_thread(TransfersThread, "Transfer Worker", B_NORMAL_PRIORITY, this);
resume_thread(fTransfersThread);
fInitCheck = true;
}
USBDeviceHandle::~USBDeviceHandle()
{
if (fRawFD > 0)
close(fRawFD);
for(int i = 0; i < 32; i++) {
if (fClaimedInterfaces & (1U << i))
ReleaseInterface(i);
}
delete_sem(fTransfersSem);
if (fTransfersThread > 0)
wait_for_thread(fTransfersThread, NULL);
}
int
USBDeviceHandle::ClaimInterface(int inumber)
{
int status = fUSBDevice->ClaimInterface(inumber);
if (status == LIBUSB_SUCCESS)
fClaimedInterfaces |= (1U << inumber);
return status;
}
int
USBDeviceHandle::ReleaseInterface(int inumber)
{
fUSBDevice->ReleaseInterface(inumber);
fClaimedInterfaces &= ~(1U << inumber);
return LIBUSB_SUCCESS;
}
int
USBDeviceHandle::SetConfiguration(int config)
{
int config_index = fUSBDevice->CheckInterfacesFree(config);
if(config_index == LIBUSB_ERROR_BUSY || config_index == LIBUSB_ERROR_NOT_FOUND)
return config_index;
usb_raw_command command;
command.config.config_index = config_index;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command, sizeof(command)) ||
command.config.status != B_USB_RAW_STATUS_SUCCESS) {
return _errno_to_libusb(command.config.status);
}
fUSBDevice->SetActiveConfiguration(config_index);
return LIBUSB_SUCCESS;
}
int
USBDeviceHandle::SetAltSetting(int inumber, int alt)
{
usb_raw_command command;
command.alternate.config_index = fUSBDevice->ActiveConfigurationIndex();
command.alternate.interface_index = inumber;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, &command, sizeof(command)) ||
command.alternate.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL, "Error retrieving active alternate interface");
return _errno_to_libusb(command.alternate.status);
}
if (command.alternate.alternate_info == alt) {
usbi_dbg("Setting alternate interface successful");
return LIBUSB_SUCCESS;
}
command.alternate.alternate_info = alt;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command, sizeof(command)) ||
command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY
usbi_err(NULL, "Error setting alternate interface");
return _errno_to_libusb(command.alternate.status);
}
usbi_dbg("Setting alternate interface successful");
return LIBUSB_SUCCESS;
}
USBDevice::USBDevice(const char *path)
:
fPath(NULL),
fActiveConfiguration(0), //0?
fConfigurationDescriptors(NULL),
fClaimedInterfaces(0),
fEndpointToIndex(NULL),
fEndpointToInterface(NULL),
fInitCheck(false)
{
fPath=strdup(path);
Initialise();
}
USBDevice::~USBDevice()
{
free(fPath);
if (fConfigurationDescriptors) {
for(int i = 0; i < fDeviceDescriptor.num_configurations; i++) {
if (fConfigurationDescriptors[i])
delete fConfigurationDescriptors[i];
}
delete[] fConfigurationDescriptors;
}
if (fEndpointToIndex)
delete[] fEndpointToIndex;
if (fEndpointToInterface)
delete[] fEndpointToInterface;
}
bool
USBDevice::InitCheck()
{
return fInitCheck;
}
const char *
USBDevice::Location() const
{
return fPath;
}
uint8
USBDevice::CountConfigurations() const
{
return fDeviceDescriptor.num_configurations;
}
const usb_device_descriptor *
USBDevice::Descriptor() const
{
return &fDeviceDescriptor;
}
const usb_configuration_descriptor *
USBDevice::ConfigurationDescriptor(uint32 index) const
{
if (index > CountConfigurations())
return NULL;
return (usb_configuration_descriptor *) fConfigurationDescriptors[index];
}
const usb_configuration_descriptor *
USBDevice::ActiveConfiguration() const
{
return (usb_configuration_descriptor *) fConfigurationDescriptors[fActiveConfiguration];
}
int
USBDevice::ActiveConfigurationIndex() const
{
return fActiveConfiguration;
}
int USBDevice::ClaimInterface(int interface)
{
if (interface > ActiveConfiguration()->number_interfaces)
return LIBUSB_ERROR_NOT_FOUND;
if (fClaimedInterfaces & (1U << interface))
return LIBUSB_ERROR_BUSY;
fClaimedInterfaces |= (1U << interface);
return LIBUSB_SUCCESS;
}
int USBDevice::ReleaseInterface(int interface)
{
fClaimedInterfaces &= ~(1U << interface);
return LIBUSB_SUCCESS;
}
int
USBDevice::CheckInterfacesFree(int config)
{
if (fConfigToIndex.count(config) == 0)
return LIBUSB_ERROR_NOT_FOUND;
if (fClaimedInterfaces == 0)
return fConfigToIndex[(uint8)config];
return LIBUSB_ERROR_BUSY;
}
int
USBDevice::SetActiveConfiguration(int config_index)
{
fActiveConfiguration = config_index;
return LIBUSB_SUCCESS;
}
uint8
USBDevice::EndpointToIndex(uint8 address) const
{
return fEndpointToIndex[fActiveConfiguration][address];
}
uint8
USBDevice::EndpointToInterface(uint8 address) const
{
return fEndpointToInterface[fActiveConfiguration][address];
}
int
USBDevice::Initialise() //Do we need more error checking, etc? How to report?
{
int fRawFD = open(fPath, O_RDWR | O_CLOEXEC);
if (fRawFD < 0)
return B_ERROR;
usb_raw_command command;
command.device.descriptor = &fDeviceDescriptor;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command, sizeof(command)) ||
command.device.status != B_USB_RAW_STATUS_SUCCESS) {
close(fRawFD);
return B_ERROR;
}
fConfigurationDescriptors = new(std::nothrow) unsigned char *[fDeviceDescriptor.num_configurations];
fEndpointToIndex = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
fEndpointToInterface = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
for (int i = 0; i < fDeviceDescriptor.num_configurations; i++) {
usb_configuration_descriptor tmp_config;
command.config.descriptor = &tmp_config;
command.config.config_index = i;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command, sizeof(command)) ||
command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL, "failed retrieving configuration descriptor");
close(fRawFD);
return B_ERROR;
}
fConfigToIndex[tmp_config.configuration_value] = i;
fConfigurationDescriptors[i] = new(std::nothrow) unsigned char[tmp_config.total_length];
command.control.request_type = 128;
command.control.request = 6;
command.control.value = (2 << 8) | i;
command.control.index = 0;
command.control.length = tmp_config.total_length;
command.control.data = fConfigurationDescriptors[i];
if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) ||
command.control.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL, "failed retrieving full configuration descriptor");
close(fRawFD);
return B_ERROR;
}
for (int j = 0; j < tmp_config.number_interfaces; j++) {
command.alternate.config_index = i;
command.alternate.interface_index = j;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command, sizeof(command)) ||
command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL, "failed retrieving number of alternate interfaces");
close(fRawFD);
return B_ERROR;
}
int num_alternate = command.alternate.alternate_info;
for (int k = 0; k < num_alternate; k++) {
usb_interface_descriptor tmp_interface;
command.interface_etc.config_index = i;
command.interface_etc.interface_index = j;
command.interface_etc.alternate_index = k;
command.interface_etc.descriptor = &tmp_interface;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command, sizeof(command)) ||
command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL, "failed retrieving interface descriptor");
close(fRawFD);
return B_ERROR;
}
for (int l = 0; l < tmp_interface.num_endpoints; l++) {
usb_endpoint_descriptor tmp_endpoint;
command.endpoint_etc.config_index = i;
command.endpoint_etc.interface_index = j;
command.endpoint_etc.alternate_index = k;
command.endpoint_etc.endpoint_index = l;
command.endpoint_etc.descriptor = &tmp_endpoint;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command, sizeof(command)) ||
command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL, "failed retrieving endpoint descriptor");
close(fRawFD);
return B_ERROR;
}
fEndpointToIndex[i][tmp_endpoint.endpoint_address] = l;
fEndpointToInterface[i][tmp_endpoint.endpoint_address] = j;
}
}
}
}
close(fRawFD);
fInitCheck = true;
return B_OK;
}

View File

@ -1,253 +0,0 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.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 <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#include "haiku_usb.h"
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)
{
if (atomic_add(&gInitCount, 1) == 0)
return gUsbRoster.Start();
return LIBUSB_SUCCESS;
}
static void
haiku_exit(struct libusb_context *ctx)
{
UNUSED(ctx);
if (atomic_add(&gInitCount, -1) == 1)
gUsbRoster.Stop();
}
static int
haiku_open(struct libusb_device_handle *dev_handle)
{
USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv);
USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev);
if (handle == NULL)
return LIBUSB_ERROR_NO_MEM;
if (handle->InitCheck() == false) {
delete handle;
return LIBUSB_ERROR_NO_DEVICE;
}
*((USBDeviceHandle **)dev_handle->os_priv) = handle;
return LIBUSB_SUCCESS;
}
static void
haiku_close(struct libusb_device_handle *dev_handle)
{
USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
if (handle == NULL)
return;
delete handle;
*((USBDeviceHandle **)dev_handle->os_priv) = NULL;
}
static int
haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian)
{
USBDevice *dev = *((USBDevice **)device->os_priv);
memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH);
*host_endian = 0;
return LIBUSB_SUCCESS;
}
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);
return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len, host_endian);
}
static int
haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
{
USBDevice *dev = *((USBDevice **)device->os_priv);
const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
if (config == NULL) {
usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
return LIBUSB_ERROR_INVALID_PARAM;
}
if (len > config->total_length) {
len = config->total_length;
}
memcpy(buffer, config, len);
*host_endian = 0;
return len;
}
static int
haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
{
USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv);
return handle->SetConfiguration(config);
}
static int
haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
{
USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
return handle->ClaimInterface(interface_number);
}
static int
haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting)
{
USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
return handle->SetAltSetting(interface_number, altsetting);
}
static int
haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
{
USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv);
haiku_set_altsetting(dev_handle,interface_number, 0);
return handle->ReleaseInterface(interface_number);
}
static int
haiku_submit_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
return fDeviceHandle->SubmitTransfer(itransfer);
}
static int
haiku_cancel_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv);
return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)));
}
static void
haiku_clear_transfer_priv(struct usbi_transfer *itransfer)
{
USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
delete transfer;
*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
}
static int
haiku_handle_transfer_completion(struct usbi_transfer *itransfer)
{
USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer));
usbi_mutex_lock(&itransfer->lock);
if (transfer->IsCancelled()) {
delete transfer;
*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
usbi_mutex_unlock(&itransfer->lock);
if (itransfer->transferred < 0)
itransfer->transferred = 0;
return usbi_handle_transfer_cancellation(itransfer);
}
libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
if (itransfer->transferred < 0) {
usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
status = LIBUSB_TRANSFER_ERROR;
itransfer->transferred = 0;
}
delete transfer;
*((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL;
usbi_mutex_unlock(&itransfer->lock);
return usbi_handle_transfer_completion(itransfer, status);
}
static int
haiku_clock_gettime(int clkid, struct timespec *tp)
{
if (clkid == USBI_CLOCK_REALTIME)
return clock_gettime(CLOCK_REALTIME, tp);
if (clkid == USBI_CLOCK_MONOTONIC)
return clock_gettime(CLOCK_MONOTONIC, tp);
return LIBUSB_ERROR_INVALID_PARAM;
}
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,
.set_interface_altsetting = haiku_set_altsetting,
.clear_halt = NULL,
.reset_device = NULL,
.alloc_streams = NULL,
.free_streams = NULL,
.dev_mem_alloc = NULL,
.dev_mem_free = NULL,
.kernel_driver_active = NULL,
.detach_kernel_driver = NULL,
.attach_kernel_driver = NULL,
.destroy_device = NULL,
.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,
.clock_gettime = haiku_clock_gettime,
#ifdef USBI_TIMERFD_AVAILABLE
.get_timerfd_clockid = NULL,
#endif
.context_priv_size = 0,
.device_priv_size = sizeof(USBDevice *),
.device_handle_priv_size = sizeof(USBDeviceHandle *),
.transfer_priv_size = sizeof(USBTransfer *),
};

View File

@ -1,180 +0,0 @@
/*
* Copyright 2006-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _USB_RAW_H_
#define _USB_RAW_H_
#include <USB3.h>
#define B_USB_RAW_PROTOCOL_VERSION 0x0015
#define B_USB_RAW_ACTIVE_ALTERNATE 0xffffffff
typedef enum {
B_USB_RAW_COMMAND_GET_VERSION = 0x1000,
B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR = 0x2000,
B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT,
B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX,
B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000,
B_USB_RAW_COMMAND_SET_FEATURE,
B_USB_RAW_COMMAND_CLEAR_FEATURE,
B_USB_RAW_COMMAND_GET_STATUS,
B_USB_RAW_COMMAND_GET_DESCRIPTOR,
B_USB_RAW_COMMAND_SET_ALT_INTERFACE,
B_USB_RAW_COMMAND_CONTROL_TRANSFER = 0x4000,
B_USB_RAW_COMMAND_INTERRUPT_TRANSFER,
B_USB_RAW_COMMAND_BULK_TRANSFER,
B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER
} usb_raw_command_id;
typedef enum {
B_USB_RAW_STATUS_SUCCESS = 0,
B_USB_RAW_STATUS_FAILED,
B_USB_RAW_STATUS_ABORTED,
B_USB_RAW_STATUS_STALLED,
B_USB_RAW_STATUS_CRC_ERROR,
B_USB_RAW_STATUS_TIMEOUT,
B_USB_RAW_STATUS_INVALID_CONFIGURATION,
B_USB_RAW_STATUS_INVALID_INTERFACE,
B_USB_RAW_STATUS_INVALID_ENDPOINT,
B_USB_RAW_STATUS_INVALID_STRING,
B_USB_RAW_STATUS_NO_MEMORY
} usb_raw_command_status;
typedef union {
struct {
status_t status;
} version;
struct {
status_t status;
usb_device_descriptor *descriptor;
} device;
struct {
status_t status;
usb_configuration_descriptor *descriptor;
uint32 config_index;
} config;
struct {
status_t status;
uint32 alternate_info;
uint32 config_index;
uint32 interface_index;
} alternate;
struct {
status_t status;
usb_interface_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
} interface;
struct {
status_t status;
usb_interface_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 alternate_index;
} interface_etc;
struct {
status_t status;
usb_endpoint_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 endpoint_index;
} endpoint;
struct {
status_t status;
usb_endpoint_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 alternate_index;
uint32 endpoint_index;
} endpoint_etc;
struct {
status_t status;
usb_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 generic_index;
size_t length;
} generic;
struct {
status_t status;
usb_descriptor *descriptor;
uint32 config_index;
uint32 interface_index;
uint32 alternate_index;
uint32 generic_index;
size_t length;
} generic_etc;
struct {
status_t status;
usb_string_descriptor *descriptor;
uint32 string_index;
size_t length;
} string;
struct {
status_t status;
uint8 type;
uint8 index;
uint16 language_id;
void *data;
size_t length;
} descriptor;
struct {
status_t status;
uint8 request_type;
uint8 request;
uint16 value;
uint16 index;
uint16 length;
void *data;
} control;
struct {
status_t status;
uint32 interface;
uint32 endpoint;
void *data;
size_t length;
} transfer;
struct {
status_t status;
uint32 interface;
uint32 endpoint;
void *data;
size_t length;
usb_iso_packet_descriptor *packet_descriptors;
uint32 packet_count;
} isochronous;
} usb_raw_command;
#endif // _USB_RAW_H_

View File

@ -1,409 +0,0 @@
/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
/*
* Linux usbfs backend for libusb
* Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.com>
* Copyright (c) 2016 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
* 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 <config.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#ifdef HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif
#include <sys/socket.h>
#include <linux/netlink.h>
#include "libusbi.h"
#include "linux_usbfs.h"
#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, 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 (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
usbi_err(NULL, "failed to set netlink fd flags (%d)", errno);
return -1;
}
}
#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 (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno);
return -1;
}
}
return 0;
}
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 | SOCK_NONBLOCK | SOCK_CLOEXEC;
int opt = 1;
int ret;
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);
socktype = SOCK_RAW;
linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
}
if (linux_netlink_socket == -1) {
usbi_err(NULL, "failed to create netlink socket (%d)", errno);
goto err;
}
ret = set_fd_cloexec_nb(linux_netlink_socket, socktype);
if (ret == -1)
goto err_close_socket;
ret = bind(linux_netlink_socket, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
if (ret == -1) {
usbi_err(NULL, "failed to bind netlink socket (%d)", errno);
goto err_close_socket;
}
ret = setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
if (ret == -1) {
usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option (%d)", errno);
goto err_close_socket;
}
ret = usbi_pipe(netlink_control_pipe);
if (ret) {
usbi_err(NULL, "failed to create netlink control pipe");
goto err_close_socket;
}
ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL);
if (ret != 0) {
usbi_err(NULL, "failed to create netlink event thread (%d)", ret);
goto err_close_pipe;
}
return LIBUSB_SUCCESS;
err_close_pipe:
close(netlink_control_pipe[0]);
close(netlink_control_pipe[1]);
netlink_control_pipe[0] = -1;
netlink_control_pipe[1] = -1;
err_close_socket:
close(linux_netlink_socket);
linux_netlink_socket = -1;
err:
return LIBUSB_ERROR_OTHER;
}
int linux_netlink_stop_event_monitor(void)
{
char dummy = 1;
ssize_t r;
assert(linux_netlink_socket != -1);
/* Write some dummy data to the control pipe and
* wait for the thread to exit */
r = write(netlink_control_pipe[1], &dummy, sizeof(dummy));
if (r <= 0)
usbi_warn(NULL, "netlink control pipe signal failed");
pthread_join(libusb_linux_event_thread, NULL);
close(linux_netlink_socket);
linux_netlink_socket = -1;
/* close and reset control pipe */
close(netlink_control_pipe[0]);
close(netlink_control_pipe[1]);
netlink_control_pipe[0] = -1;
netlink_control_pipe[1] = -1;
return LIBUSB_SUCCESS;
}
static const char *netlink_message_parse(const char *buffer, size_t len, const char *key)
{
const char *end = buffer + len;
size_t keylen = strlen(key);
while (buffer < end && *buffer) {
if (strncmp(buffer, key, keylen) == 0 && buffer[keylen] == '=')
return buffer + keylen + 1;
buffer += strlen(buffer) + 1;
}
return NULL;
}
/* parse parts of netlink message common to both libudev and the kernel */
static int linux_netlink_parse(const char *buffer, size_t len, int *detached,
const char **sys_name, uint8_t *busnum, uint8_t *devaddr)
{
const char *tmp, *slash;
errno = 0;
*sys_name = NULL;
*detached = 0;
*busnum = 0;
*devaddr = 0;
tmp = netlink_message_parse(buffer, len, "ACTION");
if (!tmp) {
return -1;
} else if (strcmp(tmp, "remove") == 0) {
*detached = 1;
} else if (strcmp(tmp, "add") != 0) {
usbi_dbg("unknown device action %s", tmp);
return -1;
}
/* check that this is a usb message */
tmp = netlink_message_parse(buffer, len, "SUBSYSTEM");
if (!tmp || strcmp(tmp, "usb") != 0) {
/* not usb. ignore */
return -1;
}
/* check that this is an actual usb device */
tmp = netlink_message_parse(buffer, len, "DEVTYPE");
if (!tmp || strcmp(tmp, "usb_device") != 0) {
/* not usb. ignore */
return -1;
}
tmp = netlink_message_parse(buffer, len, "BUSNUM");
if (tmp) {
*busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
if (errno) {
errno = 0;
return -1;
}
tmp = netlink_message_parse(buffer, len, "DEVNUM");
if (NULL == tmp)
return -1;
*devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
if (errno) {
errno = 0;
return -1;
}
} else {
/* no bus number. try "DEVICE" */
tmp = netlink_message_parse(buffer, len, "DEVICE");
if (!tmp) {
/* not usb. ignore */
return -1;
}
/* Parse a device path such as /dev/bus/usb/003/004 */
slash = strrchr(tmp, '/');
if (!slash)
return -1;
*busnum = (uint8_t)(strtoul(slash - 3, NULL, 10) & 0xff);
if (errno) {
errno = 0;
return -1;
}
*devaddr = (uint8_t)(strtoul(slash + 1, NULL, 10) & 0xff);
if (errno) {
errno = 0;
return -1;
}
return 0;
}
tmp = netlink_message_parse(buffer, len, "DEVPATH");
if (!tmp)
return -1;
slash = strrchr(tmp, '/');
if (slash)
*sys_name = slash + 1;
/* found a usb device */
return 0;
}
static int linux_netlink_read_message(void)
{
char cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
char msg_buffer[2048];
const char *sys_name = NULL;
uint8_t busnum, devaddr;
int detached, r;
ssize_t len;
struct cmsghdr *cmsg;
struct ucred *cred;
struct sockaddr_nl sa_nl;
struct iovec iov = { .iov_base = msg_buffer, .iov_len = sizeof(msg_buffer) };
struct msghdr msg = {
.msg_iov = &iov, .msg_iovlen = 1,
.msg_control = cred_buffer, .msg_controllen = sizeof(cred_buffer),
.msg_name = &sa_nl, .msg_namelen = sizeof(sa_nl)
};
/* read netlink message */
len = recvmsg(linux_netlink_socket, &msg, 0);
if (len == -1) {
if (errno != EAGAIN && errno != EINTR)
usbi_err(NULL, "error receiving message from netlink (%d)", errno);
return -1;
}
if (len < 32 || (msg.msg_flags & MSG_TRUNC)) {
usbi_err(NULL, "invalid netlink message length");
return -1;
}
if (sa_nl.nl_groups != NL_GROUP_KERNEL || sa_nl.nl_pid != 0) {
usbi_dbg("ignoring netlink message from unknown group/PID (%u/%u)",
(unsigned int)sa_nl.nl_groups, (unsigned int)sa_nl.nl_pid);
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
usbi_dbg("ignoring netlink message with no sender credentials");
return -1;
}
cred = (struct ucred *)CMSG_DATA(cmsg);
if (cred->uid != 0) {
usbi_dbg("ignoring netlink message with non-zero sender UID %u", (unsigned int)cred->uid);
return -1;
}
r = linux_netlink_parse(msg_buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr);
if (r)
return r;
usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s",
busnum, devaddr, sys_name, detached ? "yes" : "no");
/* signal device is available (or not) to all contexts */
if (detached)
linux_device_disconnected(busnum, devaddr);
else
linux_hotplug_enumerate(busnum, devaddr, sys_name);
return 0;
}
static void *linux_netlink_event_thread_main(void *arg)
{
char dummy;
int r;
ssize_t nb;
struct pollfd fds[] = {
{ .fd = netlink_control_pipe[0],
.events = POLLIN },
{ .fd = linux_netlink_socket,
.events = POLLIN },
};
UNUSED(arg);
usbi_dbg("netlink event thread entering");
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 */
nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy));
if (nb <= 0)
usbi_warn(NULL, "netlink control pipe read failed");
break;
}
if (fds[1].revents & POLLIN) {
usbi_mutex_static_lock(&linux_hotplug_lock);
linux_netlink_read_message();
usbi_mutex_static_unlock(&linux_hotplug_lock);
}
}
usbi_dbg("netlink event thread exiting");
return NULL;
}
void linux_netlink_hotplug_poll(void)
{
int r;
usbi_mutex_static_lock(&linux_hotplug_lock);
do {
r = linux_netlink_read_message();
} while (r == 0);
usbi_mutex_static_unlock(&linux_hotplug_lock);
}

View File

@ -1,329 +0,0 @@
/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
/*
* Linux usbfs backend for libusb
* Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright (c) 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 <config.h>
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/socket.h>
#include <unistd.h>
#include <libudev.h>
#include "libusbi.h"
#include "linux_usbfs.h"
/* udev context */
static struct udev *udev_ctx = NULL;
static int udev_monitor_fd = -1;
static int udev_control_pipe[2] = {-1, -1};
static struct udev_monitor *udev_monitor = NULL;
static pthread_t linux_event_thread;
static void udev_hotplug_event(struct udev_device* udev_dev);
static void *linux_udev_event_thread_main(void *arg);
int linux_udev_start_event_monitor(void)
{
int r;
assert(udev_ctx == NULL);
udev_ctx = udev_new();
if (!udev_ctx) {
usbi_err(NULL, "could not create udev context");
goto err;
}
udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev");
if (!udev_monitor) {
usbi_err(NULL, "could not initialize udev monitor");
goto err_free_ctx;
}
r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device");
if (r) {
usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem");
goto err_free_monitor;
}
if (udev_monitor_enable_receiving(udev_monitor)) {
usbi_err(NULL, "failed to enable the udev monitor");
goto err_free_monitor;
}
udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
#if defined(FD_CLOEXEC)
/* Make sure the udev file descriptor is marked as CLOEXEC */
r = fcntl(udev_monitor_fd, F_GETFD);
if (r == -1) {
usbi_err(NULL, "geting udev monitor fd flags (%d)", errno);
goto err_free_monitor;
}
if (!(r & FD_CLOEXEC)) {
if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) {
usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
goto err_free_monitor;
}
}
#endif
/* Some older versions of udev are not non-blocking by default,
* so make sure this is set */
r = fcntl(udev_monitor_fd, F_GETFL);
if (r == -1) {
usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno);
goto err_free_monitor;
}
if (!(r & O_NONBLOCK)) {
if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) {
usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno);
goto err_free_monitor;
}
}
r = usbi_pipe(udev_control_pipe);
if (r) {
usbi_err(NULL, "could not create udev control pipe");
goto err_free_monitor;
}
r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL);
if (r) {
usbi_err(NULL, "creating hotplug event thread (%d)", r);
goto err_close_pipe;
}
return LIBUSB_SUCCESS;
err_close_pipe:
close(udev_control_pipe[0]);
close(udev_control_pipe[1]);
err_free_monitor:
udev_monitor_unref(udev_monitor);
udev_monitor = NULL;
udev_monitor_fd = -1;
err_free_ctx:
udev_unref(udev_ctx);
err:
udev_ctx = NULL;
return LIBUSB_ERROR_OTHER;
}
int linux_udev_stop_event_monitor(void)
{
char dummy = 1;
int r;
assert(udev_ctx != NULL);
assert(udev_monitor != NULL);
assert(udev_monitor_fd != -1);
/* Write some dummy data to the control pipe and
* wait for the thread to exit */
r = write(udev_control_pipe[1], &dummy, sizeof(dummy));
if (r <= 0) {
usbi_warn(NULL, "udev control pipe signal failed");
}
pthread_join(linux_event_thread, NULL);
/* Release the udev monitor */
udev_monitor_unref(udev_monitor);
udev_monitor = NULL;
udev_monitor_fd = -1;
/* Clean up the udev context */
udev_unref(udev_ctx);
udev_ctx = NULL;
/* close and reset control pipe */
close(udev_control_pipe[0]);
close(udev_control_pipe[1]);
udev_control_pipe[0] = -1;
udev_control_pipe[1] = -1;
return LIBUSB_SUCCESS;
}
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],
.events = POLLIN},
{.fd = udev_monitor_fd,
.events = POLLIN},
};
usbi_dbg("udev event thread entering.");
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 */
nb = read(udev_control_pipe[0], &dummy, sizeof(dummy));
if (nb <= 0) {
usbi_warn(NULL, "udev control pipe read failed");
}
break;
}
if (fds[1].revents & POLLIN) {
usbi_mutex_static_lock(&linux_hotplug_lock);
udev_dev = udev_monitor_receive_device(udev_monitor);
if (udev_dev)
udev_hotplug_event(udev_dev);
usbi_mutex_static_unlock(&linux_hotplug_lock);
}
}
usbi_dbg("udev event thread exiting");
return NULL;
}
static int udev_device_info(struct libusb_context *ctx, int detached,
struct udev_device *udev_dev, uint8_t *busnum,
uint8_t *devaddr, const char **sys_name) {
const char *dev_node;
dev_node = udev_device_get_devnode(udev_dev);
if (!dev_node) {
return LIBUSB_ERROR_OTHER;
}
*sys_name = udev_device_get_sysname(udev_dev);
if (!*sys_name) {
return LIBUSB_ERROR_OTHER;
}
return linux_get_device_address(ctx, detached, busnum, devaddr,
dev_node, *sys_name, -1);
}
static void udev_hotplug_event(struct udev_device* udev_dev)
{
const char* udev_action;
const char* sys_name = NULL;
uint8_t busnum = 0, devaddr = 0;
int detached;
int r;
do {
udev_action = udev_device_get_action(udev_dev);
if (!udev_action) {
break;
}
detached = !strncmp(udev_action, "remove", 6);
r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name);
if (LIBUSB_SUCCESS != r) {
break;
}
usbi_dbg("udev hotplug event. action: %s.", udev_action);
if (strncmp(udev_action, "add", 3) == 0) {
linux_hotplug_enumerate(busnum, devaddr, sys_name);
} else if (detached) {
linux_device_disconnected(busnum, devaddr);
} else {
usbi_err(NULL, "ignoring udev action %s", udev_action);
}
} while (0);
udev_device_unref(udev_dev);
}
int linux_udev_scan_devices(struct libusb_context *ctx)
{
struct udev_enumerate *enumerator;
struct udev_list_entry *devices, *entry;
struct udev_device *udev_dev;
const char *sys_name;
int r;
assert(udev_ctx != NULL);
enumerator = udev_enumerate_new(udev_ctx);
if (NULL == enumerator) {
usbi_err(ctx, "error creating udev enumerator");
return LIBUSB_ERROR_OTHER;
}
udev_enumerate_add_match_subsystem(enumerator, "usb");
udev_enumerate_add_match_property(enumerator, "DEVTYPE", "usb_device");
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;
udev_dev = udev_device_new_from_syspath(udev_ctx, path);
r = udev_device_info(ctx, 0, udev_dev, &busnum, &devaddr, &sys_name);
if (r) {
udev_device_unref(udev_dev);
continue;
}
linux_enumerate_device(ctx, busnum, devaddr, sys_name);
udev_device_unref(udev_dev);
}
udev_enumerate_unref(enumerator);
return LIBUSB_SUCCESS;
}
void linux_udev_hotplug_poll(void)
{
struct udev_device* udev_dev;
usbi_mutex_static_lock(&linux_hotplug_lock);
do {
udev_dev = udev_monitor_receive_device(udev_monitor);
if (udev_dev) {
usbi_dbg("Handling hotplug event from hotplug_poll");
udev_hotplug_event(udev_dev);
}
} while (udev_dev);
usbi_mutex_static_unlock(&linux_hotplug_lock);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,194 +0,0 @@
/*
* usbfs header structures
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
* Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.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
*/
#ifndef LIBUSB_USBFS_H
#define LIBUSB_USBFS_H
#include <linux/types.h>
#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices"
struct usbfs_ctrltransfer {
/* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint32_t timeout; /* in milliseconds */
/* pointer to data */
void *data;
};
struct usbfs_bulktransfer {
/* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */
unsigned int ep;
unsigned int len;
unsigned int timeout; /* in milliseconds */
/* pointer to data */
void *data;
};
struct usbfs_setinterface {
/* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */
unsigned int interface;
unsigned int altsetting;
};
#define USBFS_MAXDRIVERNAME 255
struct usbfs_getdriver {
unsigned int interface;
char driver[USBFS_MAXDRIVERNAME + 1];
};
#define USBFS_URB_SHORT_NOT_OK 0x01
#define USBFS_URB_ISO_ASAP 0x02
#define USBFS_URB_BULK_CONTINUATION 0x04
#define USBFS_URB_QUEUE_BULK 0x10
#define USBFS_URB_ZERO_PACKET 0x40
enum usbfs_urb_type {
USBFS_URB_TYPE_ISO = 0,
USBFS_URB_TYPE_INTERRUPT = 1,
USBFS_URB_TYPE_CONTROL = 2,
USBFS_URB_TYPE_BULK = 3,
};
struct usbfs_iso_packet_desc {
unsigned int length;
unsigned int actual_length;
unsigned int status;
};
#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;
int status;
unsigned int flags;
void *buffer;
int buffer_length;
int actual_length;
int start_frame;
union {
int number_of_packets; /* Only used for isoc urbs */
unsigned int stream_id; /* Only used with bulk streams */
};
int error_count;
unsigned int signr;
void *usercontext;
struct usbfs_iso_packet_desc iso_frame_desc[0];
};
struct usbfs_connectinfo {
unsigned int devnum;
unsigned char slow;
};
struct usbfs_ioctl {
int ifno; /* interface 0..N ; negative numbers reserved */
int ioctl_code; /* MUST encode size + direction of data so the
* macros in <asm/ioctl.h> give correct values */
void *data; /* param buffer (in, or out) */
};
struct usbfs_hub_portinfo {
unsigned char numports;
unsigned char port[127]; /* port to device num mapping */
};
#define USBFS_CAP_ZERO_PACKET 0x01
#define USBFS_CAP_BULK_CONTINUATION 0x02
#define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04
#define USBFS_CAP_BULK_SCATTER_GATHER 0x08
#define USBFS_CAP_REAP_AFTER_DISCONNECT 0x10
#define USBFS_DISCONNECT_CLAIM_IF_DRIVER 0x01
#define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02
struct usbfs_disconnect_claim {
unsigned int interface;
unsigned int flags;
char driver[USBFS_MAXDRIVERNAME + 1];
};
struct usbfs_streams {
unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */
unsigned int num_eps;
unsigned char eps[0];
};
#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer)
#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer)
#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int)
#define IOCTL_USBFS_SETINTF _IOR('U', 4, struct usbfs_setinterface)
#define IOCTL_USBFS_SETCONFIG _IOR('U', 5, unsigned int)
#define IOCTL_USBFS_GETDRIVER _IOW('U', 8, struct usbfs_getdriver)
#define IOCTL_USBFS_SUBMITURB _IOR('U', 10, struct usbfs_urb)
#define IOCTL_USBFS_DISCARDURB _IO('U', 11)
#define IOCTL_USBFS_REAPURB _IOW('U', 12, void *)
#define IOCTL_USBFS_REAPURBNDELAY _IOW('U', 13, void *)
#define IOCTL_USBFS_CLAIMINTF _IOR('U', 15, unsigned int)
#define IOCTL_USBFS_RELEASEINTF _IOR('U', 16, unsigned int)
#define IOCTL_USBFS_CONNECTINFO _IOW('U', 17, struct usbfs_connectinfo)
#define IOCTL_USBFS_IOCTL _IOWR('U', 18, struct usbfs_ioctl)
#define IOCTL_USBFS_HUB_PORTINFO _IOR('U', 19, struct usbfs_hub_portinfo)
#define IOCTL_USBFS_RESET _IO('U', 20)
#define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int)
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
#define IOCTL_USBFS_CONNECT _IO('U', 23)
#define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int)
#define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int)
#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32)
#define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim)
#define IOCTL_USBFS_ALLOC_STREAMS _IOR('U', 28, struct usbfs_streams)
#define IOCTL_USBFS_FREE_STREAMS _IOR('U', 29, struct usbfs_streams)
extern usbi_mutex_static_t linux_hotplug_lock;
#if defined(HAVE_LIBUDEV)
int linux_udev_start_event_monitor(void);
int linux_udev_stop_event_monitor(void);
int linux_udev_scan_devices(struct libusb_context *ctx);
void linux_udev_hotplug_poll(void);
#else
int linux_netlink_start_event_monitor(void);
int linux_netlink_stop_event_monitor(void);
void linux_netlink_hotplug_poll(void);
#endif
void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name);
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, int fd);
int linux_enumerate_device(struct libusb_context *ctx,
uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);
#endif

View File

@ -1,682 +0,0 @@
/*
* Copyright © 2011 Martin Pieuchot <mpi@openbsd.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 <config.h>
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dev/usb/usb.h>
#include "libusbi.h"
struct device_priv {
char devnode[16];
int fd;
unsigned char *cdesc; /* active config descriptor */
usb_device_descriptor_t ddesc; /* usb device descriptor */
};
struct handle_priv {
int endpoints[USB_MAX_ENDPOINTS];
};
/*
* Backend functions
*/
static int netbsd_get_device_list(struct libusb_context *,
struct discovered_devs **);
static int netbsd_open(struct libusb_device_handle *);
static void netbsd_close(struct libusb_device_handle *);
static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *,
int *);
static int netbsd_get_active_config_descriptor(struct libusb_device *,
unsigned char *, size_t, int *);
static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t,
unsigned char *, size_t, int *);
static int netbsd_get_configuration(struct libusb_device_handle *, int *);
static int netbsd_set_configuration(struct libusb_device_handle *, int);
static int netbsd_claim_interface(struct libusb_device_handle *, int);
static int netbsd_release_interface(struct libusb_device_handle *, int);
static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int,
int);
static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char);
static int netbsd_reset_device(struct libusb_device_handle *);
static void netbsd_destroy_device(struct libusb_device *);
static int netbsd_submit_transfer(struct usbi_transfer *);
static int netbsd_cancel_transfer(struct usbi_transfer *);
static void netbsd_clear_transfer_priv(struct usbi_transfer *);
static int netbsd_handle_transfer_completion(struct usbi_transfer *);
static int netbsd_clock_gettime(int, struct timespec *);
/*
* Private functions
*/
static int _errno_to_libusb(int);
static int _cache_active_config_descriptor(struct libusb_device *, int);
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 usbi_backend = {
"Synchronous NetBSD backend",
0,
NULL, /* init() */
NULL, /* exit() */
NULL, /* set_option() */
netbsd_get_device_list,
NULL, /* hotplug_poll */
netbsd_open,
netbsd_close,
netbsd_get_device_descriptor,
netbsd_get_active_config_descriptor,
netbsd_get_config_descriptor,
NULL, /* get_config_descriptor_by_value() */
netbsd_get_configuration,
netbsd_set_configuration,
netbsd_claim_interface,
netbsd_release_interface,
netbsd_set_interface_altsetting,
netbsd_clear_halt,
netbsd_reset_device,
NULL, /* alloc_streams */
NULL, /* free_streams */
NULL, /* dev_mem_alloc() */
NULL, /* dev_mem_free() */
NULL, /* kernel_driver_active() */
NULL, /* detach_kernel_driver() */
NULL, /* attach_kernel_driver() */
netbsd_destroy_device,
netbsd_submit_transfer,
netbsd_cancel_transfer,
netbsd_clear_transfer_priv,
NULL, /* handle_events() */
netbsd_handle_transfer_completion,
netbsd_clock_gettime,
0, /* context_priv_size */
sizeof(struct device_priv),
sizeof(struct handle_priv),
0, /* transfer_priv_size */
};
int
netbsd_get_device_list(struct libusb_context * ctx,
struct discovered_devs **discdevs)
{
struct libusb_device *dev;
struct device_priv *dpriv;
struct usb_device_info di;
unsigned long session_id;
char devnode[16];
int fd, err, i;
usbi_dbg("");
/* Only ugen(4) is supported */
for (i = 0; i < USB_MAX_DEVICES; i++) {
/* Control endpoint is always .00 */
snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
if ((fd = open(devnode, O_RDONLY)) < 0) {
if (errno != ENOENT && errno != ENXIO)
usbi_err(ctx, "could not open %s", devnode);
continue;
}
if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
continue;
session_id = (di.udi_bus << 8 | di.udi_addr);
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev == NULL) {
dev = usbi_alloc_device(ctx, session_id);
if (dev == NULL)
return (LIBUSB_ERROR_NO_MEM);
dev->bus_number = di.udi_bus;
dev->device_address = di.udi_addr;
dev->speed = di.udi_speed;
dpriv = (struct device_priv *)dev->os_priv;
strlcpy(dpriv->devnode, devnode, sizeof(devnode));
dpriv->fd = -1;
if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
err = errno;
goto error;
}
dpriv->cdesc = NULL;
if (_cache_active_config_descriptor(dev, fd)) {
err = errno;
goto error;
}
if ((err = usbi_sanitize_device(dev)))
goto error;
}
close(fd);
if (discovered_devs_append(*discdevs, dev) == NULL)
return (LIBUSB_ERROR_NO_MEM);
libusb_unref_device(dev);
}
return (LIBUSB_SUCCESS);
error:
close(fd);
libusb_unref_device(dev);
return _errno_to_libusb(err);
}
int
netbsd_open(struct libusb_device_handle *handle)
{
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) {
dpriv->fd = open(dpriv->devnode, O_RDONLY);
if (dpriv->fd < 0)
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);
}
void
netbsd_close(struct libusb_device_handle *handle)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("close: fd %d", dpriv->fd);
close(dpriv->fd);
dpriv->fd = -1;
}
int
netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usbi_dbg("");
memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
*host_endian = 0;
return (LIBUSB_SUCCESS);
}
int
netbsd_get_active_config_descriptor(struct libusb_device *dev,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usb_config_descriptor_t *ucd;
ucd = (usb_config_descriptor_t *) dpriv->cdesc;
len = MIN(len, UGETW(ucd->wTotalLength));
usbi_dbg("len %d", len);
memcpy(buf, dpriv->cdesc, len);
*host_endian = 0;
return len;
}
int
netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
struct usb_full_desc ufd;
int fd, err;
usbi_dbg("index %d, len %d", idx, len);
/* A config descriptor may be requested before opening the device */
if (dpriv->fd >= 0) {
fd = dpriv->fd;
} else {
fd = open(dpriv->devnode, O_RDONLY);
if (fd < 0)
return _errno_to_libusb(errno);
}
ufd.ufd_config_index = idx;
ufd.ufd_size = len;
ufd.ufd_data = buf;
if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
err = errno;
if (dpriv->fd < 0)
close(fd);
return _errno_to_libusb(err);
}
if (dpriv->fd < 0)
close(fd);
*host_endian = 0;
return len;
}
int
netbsd_get_configuration(struct libusb_device_handle *handle, int *config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("");
if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
return _errno_to_libusb(errno);
usbi_dbg("configuration %d", *config);
return (LIBUSB_SUCCESS);
}
int
netbsd_set_configuration(struct libusb_device_handle *handle, int config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("configuration %d", config);
if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
return _errno_to_libusb(errno);
return _cache_active_config_descriptor(handle->dev, dpriv->fd);
}
int
netbsd_claim_interface(struct libusb_device_handle *handle, int iface)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
int i;
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
hpriv->endpoints[i] = -1;
return (LIBUSB_SUCCESS);
}
int
netbsd_release_interface(struct libusb_device_handle *handle, int iface)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
int i;
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
if (hpriv->endpoints[i] >= 0)
close(hpriv->endpoints[i]);
return (LIBUSB_SUCCESS);
}
int
netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
int altsetting)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_alt_interface intf;
usbi_dbg("iface %d, setting %d", iface, altsetting);
memset(&intf, 0, sizeof(intf));
intf.uai_interface_index = iface;
intf.uai_alt_no = altsetting;
if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS);
}
int
netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_ctl_request req;
usbi_dbg("");
req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
req.ucr_request.bRequest = UR_CLEAR_FEATURE;
USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
USETW(req.ucr_request.wIndex, endpoint);
USETW(req.ucr_request.wLength, 0);
if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS);
}
int
netbsd_reset_device(struct libusb_device_handle *handle)
{
usbi_dbg("");
return (LIBUSB_ERROR_NOT_SUPPORTED);
}
void
netbsd_destroy_device(struct libusb_device *dev)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usbi_dbg("");
free(dpriv->cdesc);
}
int
netbsd_submit_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct handle_priv *hpriv;
int err = 0;
usbi_dbg("");
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
err = _sync_control_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
if (IS_XFEROUT(transfer)) {
/* Isochronous write is not supported */
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
err = _sync_gen_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
if (IS_XFEROUT(transfer) &&
transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
err = _sync_gen_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
if (err)
return (err);
usbi_signal_transfer_completion(itransfer);
return (LIBUSB_SUCCESS);
}
int
netbsd_cancel_transfer(struct usbi_transfer *itransfer)
{
usbi_dbg("");
return (LIBUSB_ERROR_NOT_SUPPORTED);
}
void
netbsd_clear_transfer_priv(struct usbi_transfer *itransfer)
{
usbi_dbg("");
/* Nothing to do */
}
int
netbsd_handle_transfer_completion(struct usbi_transfer *itransfer)
{
return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
}
int
netbsd_clock_gettime(int clkid, struct timespec *tp)
{
usbi_dbg("clock %d", clkid);
if (clkid == USBI_CLOCK_REALTIME)
return clock_gettime(CLOCK_REALTIME, tp);
if (clkid == USBI_CLOCK_MONOTONIC)
return clock_gettime(CLOCK_MONOTONIC, tp);
return (LIBUSB_ERROR_INVALID_PARAM);
}
int
_errno_to_libusb(int err)
{
switch (err) {
case EIO:
return (LIBUSB_ERROR_IO);
case EACCES:
return (LIBUSB_ERROR_ACCESS);
case ENOENT:
return (LIBUSB_ERROR_NO_DEVICE);
case ENOMEM:
return (LIBUSB_ERROR_NO_MEM);
}
usbi_dbg("error: %s", strerror(err));
return (LIBUSB_ERROR_OTHER);
}
int
_cache_active_config_descriptor(struct libusb_device *dev, int fd)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
struct usb_config_desc ucd;
struct usb_full_desc ufd;
unsigned char* buf;
int len;
usbi_dbg("fd %d", fd);
ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
return _errno_to_libusb(errno);
usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
len = UGETW(ucd.ucd_desc.wTotalLength);
buf = malloc(len);
if (buf == NULL)
return (LIBUSB_ERROR_NO_MEM);
ufd.ufd_config_index = ucd.ucd_config_index;
ufd.ufd_size = len;
ufd.ufd_data = buf;
usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
free(buf);
return _errno_to_libusb(errno);
}
if (dpriv->cdesc)
free(dpriv->cdesc);
dpriv->cdesc = buf;
return (0);
}
int
_sync_control_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct libusb_control_setup *setup;
struct device_priv *dpriv;
struct usb_ctl_request req;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
setup = (struct libusb_control_setup *)transfer->buffer;
usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
setup->bmRequestType, setup->bRequest,
libusb_le16_to_cpu(setup->wValue),
libusb_le16_to_cpu(setup->wIndex),
libusb_le16_to_cpu(setup->wLength), transfer->timeout);
req.ucr_request.bmRequestType = setup->bmRequestType;
req.ucr_request.bRequest = setup->bRequest;
/* Don't use USETW, libusb already deals with the endianness */
(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
req.ucr_flags = USBD_SHORT_XFER_OK;
if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
return _errno_to_libusb(errno);
itransfer->transferred = req.ucr_actlen;
usbi_dbg("transferred %d", itransfer->transferred);
return (0);
}
int
_access_endpoint(struct libusb_transfer *transfer)
{
struct handle_priv *hpriv;
struct device_priv *dpriv;
char *s, devnode[16];
int fd, endpt;
mode_t mode;
hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
endpt = UE_GET_ADDR(transfer->endpoint);
mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
usbi_dbg("endpoint %d mode %d", endpt, mode);
if (hpriv->endpoints[endpt] < 0) {
/* Pick the right node given the control one */
strlcpy(devnode, dpriv->devnode, sizeof(devnode));
s = strchr(devnode, '.');
snprintf(s, 4, ".%02d", endpt);
/* We may need to read/write to the same endpoint later. */
if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
if ((fd = open(devnode, mode)) < 0)
return (-1);
hpriv->endpoints[endpt] = fd;
}
return (hpriv->endpoints[endpt]);
}
int
_sync_gen_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
int fd, nr = 1;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
/*
* Bulk, Interrupt or Isochronous transfer depends on the
* endpoint and thus the node to open.
*/
if ((fd = _access_endpoint(transfer)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if (IS_XFERIN(transfer)) {
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
return _errno_to_libusb(errno);
nr = read(fd, transfer->buffer, transfer->length);
} else {
nr = write(fd, transfer->buffer, transfer->length);
}
if (nr < 0)
return _errno_to_libusb(errno);
itransfer->transferred = nr;
return (0);
}

View File

@ -1,771 +0,0 @@
/*
* Copyright © 2011-2013 Martin Pieuchot <mpi@openbsd.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 <config.h>
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dev/usb/usb.h>
#include "libusbi.h"
struct device_priv {
char *devname; /* name of the ugen(4) node */
int fd; /* device file descriptor */
unsigned char *cdesc; /* active config descriptor */
usb_device_descriptor_t ddesc; /* usb device descriptor */
};
struct handle_priv {
int endpoints[USB_MAX_ENDPOINTS];
};
/*
* Backend functions
*/
static int obsd_get_device_list(struct libusb_context *,
struct discovered_devs **);
static int obsd_open(struct libusb_device_handle *);
static void obsd_close(struct libusb_device_handle *);
static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *,
int *);
static int obsd_get_active_config_descriptor(struct libusb_device *,
unsigned char *, size_t, int *);
static int obsd_get_config_descriptor(struct libusb_device *, uint8_t,
unsigned char *, size_t, int *);
static int obsd_get_configuration(struct libusb_device_handle *, int *);
static int obsd_set_configuration(struct libusb_device_handle *, int);
static int obsd_claim_interface(struct libusb_device_handle *, int);
static int obsd_release_interface(struct libusb_device_handle *, int);
static int obsd_set_interface_altsetting(struct libusb_device_handle *, int,
int);
static int obsd_clear_halt(struct libusb_device_handle *, unsigned char);
static int obsd_reset_device(struct libusb_device_handle *);
static void obsd_destroy_device(struct libusb_device *);
static int obsd_submit_transfer(struct usbi_transfer *);
static int obsd_cancel_transfer(struct usbi_transfer *);
static void obsd_clear_transfer_priv(struct usbi_transfer *);
static int obsd_handle_transfer_completion(struct usbi_transfer *);
static int obsd_clock_gettime(int, struct timespec *);
/*
* Private functions
*/
static int _errno_to_libusb(int);
static int _cache_active_config_descriptor(struct libusb_device *);
static int _sync_control_transfer(struct usbi_transfer *);
static int _sync_gen_transfer(struct usbi_transfer *);
static int _access_endpoint(struct libusb_transfer *);
static int _bus_open(int);
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,
obsd_close,
obsd_get_device_descriptor,
obsd_get_active_config_descriptor,
obsd_get_config_descriptor,
NULL, /* get_config_descriptor_by_value() */
obsd_get_configuration,
obsd_set_configuration,
obsd_claim_interface,
obsd_release_interface,
obsd_set_interface_altsetting,
obsd_clear_halt,
obsd_reset_device,
NULL, /* alloc_streams */
NULL, /* free_streams */
NULL, /* dev_mem_alloc() */
NULL, /* dev_mem_free() */
NULL, /* kernel_driver_active() */
NULL, /* detach_kernel_driver() */
NULL, /* attach_kernel_driver() */
obsd_destroy_device,
obsd_submit_transfer,
obsd_cancel_transfer,
obsd_clear_transfer_priv,
NULL, /* handle_events() */
obsd_handle_transfer_completion,
obsd_clock_gettime,
0, /* context_priv_size */
sizeof(struct device_priv),
sizeof(struct handle_priv),
0, /* transfer_priv_size */
};
#define DEVPATH "/dev/"
#define USBDEV DEVPATH "usb"
int
obsd_get_device_list(struct libusb_context * ctx,
struct discovered_devs **discdevs)
{
struct discovered_devs *ddd;
struct libusb_device *dev;
struct device_priv *dpriv;
struct usb_device_info di;
struct usb_device_ddesc dd;
unsigned long session_id;
char devices[USB_MAX_DEVICES];
char busnode[16];
char *udevname;
int fd, addr, i, j;
usbi_dbg("");
for (i = 0; i < 8; i++) {
snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
if ((fd = open(busnode, O_RDWR)) < 0) {
if (errno != ENOENT && errno != ENXIO)
usbi_err(ctx, "could not open %s", busnode);
continue;
}
bzero(devices, sizeof(devices));
for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
if (devices[addr])
continue;
di.udi_addr = addr;
if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
continue;
/*
* XXX If ugen(4) is attached to the USB device
* it will be used.
*/
udevname = NULL;
for (j = 0; j < USB_MAX_DEVNAMES; j++)
if (!strncmp("ugen", di.udi_devnames[j], 4)) {
udevname = strdup(di.udi_devnames[j]);
break;
}
session_id = (di.udi_bus << 8 | di.udi_addr);
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev == NULL) {
dev = usbi_alloc_device(ctx, session_id);
if (dev == NULL) {
close(fd);
return (LIBUSB_ERROR_NO_MEM);
}
dev->bus_number = di.udi_bus;
dev->device_address = di.udi_addr;
dev->speed = di.udi_speed;
dpriv = (struct device_priv *)dev->os_priv;
dpriv->fd = -1;
dpriv->cdesc = NULL;
dpriv->devname = udevname;
dd.udd_bus = di.udi_bus;
dd.udd_addr = di.udi_addr;
if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) {
libusb_unref_device(dev);
continue;
}
dpriv->ddesc = dd.udd_desc;
if (_cache_active_config_descriptor(dev)) {
libusb_unref_device(dev);
continue;
}
if (usbi_sanitize_device(dev)) {
libusb_unref_device(dev);
continue;
}
}
ddd = discovered_devs_append(*discdevs, dev);
if (ddd == NULL) {
close(fd);
return (LIBUSB_ERROR_NO_MEM);
}
libusb_unref_device(dev);
*discdevs = ddd;
devices[addr] = 1;
}
close(fd);
}
return (LIBUSB_SUCCESS);
}
int
obsd_open(struct libusb_device_handle *handle)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
char devnode[16];
if (dpriv->devname) {
/*
* Only open ugen(4) attached devices read-write, all
* read-only operations are done through the bus node.
*/
snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
dpriv->devname);
dpriv->fd = open(devnode, O_RDWR);
if (dpriv->fd < 0)
return _errno_to_libusb(errno);
usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
}
return (LIBUSB_SUCCESS);
}
void
obsd_close(struct libusb_device_handle *handle)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
if (dpriv->devname) {
usbi_dbg("close: fd %d", dpriv->fd);
close(dpriv->fd);
dpriv->fd = -1;
}
}
int
obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usbi_dbg("");
memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
*host_endian = 0;
return (LIBUSB_SUCCESS);
}
int
obsd_get_active_config_descriptor(struct libusb_device *dev,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
len = MIN(len, UGETW(ucd->wTotalLength));
usbi_dbg("len %d", len);
memcpy(buf, dpriv->cdesc, len);
*host_endian = 0;
return (len);
}
int
obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
unsigned char *buf, size_t len, int *host_endian)
{
struct usb_device_fdesc udf;
int fd, err;
if ((fd = _bus_open(dev->bus_number)) < 0)
return _errno_to_libusb(errno);
udf.udf_bus = dev->bus_number;
udf.udf_addr = dev->device_address;
udf.udf_config_index = idx;
udf.udf_size = len;
udf.udf_data = buf;
usbi_dbg("index %d, len %d", udf.udf_config_index, len);
if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
err = errno;
close(fd);
return _errno_to_libusb(err);
}
close(fd);
*host_endian = 0;
return (len);
}
int
obsd_get_configuration(struct libusb_device_handle *handle, int *config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
*config = ucd->bConfigurationValue;
usbi_dbg("bConfigurationValue %d", *config);
return (LIBUSB_SUCCESS);
}
int
obsd_set_configuration(struct libusb_device_handle *handle, int config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
if (dpriv->devname == NULL)
return (LIBUSB_ERROR_NOT_SUPPORTED);
usbi_dbg("bConfigurationValue %d", config);
if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
return _errno_to_libusb(errno);
return _cache_active_config_descriptor(handle->dev);
}
int
obsd_claim_interface(struct libusb_device_handle *handle, int iface)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
int i;
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
hpriv->endpoints[i] = -1;
return (LIBUSB_SUCCESS);
}
int
obsd_release_interface(struct libusb_device_handle *handle, int iface)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
int i;
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
if (hpriv->endpoints[i] >= 0)
close(hpriv->endpoints[i]);
return (LIBUSB_SUCCESS);
}
int
obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
int altsetting)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_alt_interface intf;
if (dpriv->devname == NULL)
return (LIBUSB_ERROR_NOT_SUPPORTED);
usbi_dbg("iface %d, setting %d", iface, altsetting);
memset(&intf, 0, sizeof(intf));
intf.uai_interface_index = iface;
intf.uai_alt_no = altsetting;
if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS);
}
int
obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
{
struct usb_ctl_request req;
int fd, err;
if ((fd = _bus_open(handle->dev->bus_number)) < 0)
return _errno_to_libusb(errno);
usbi_dbg("");
req.ucr_addr = handle->dev->device_address;
req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
req.ucr_request.bRequest = UR_CLEAR_FEATURE;
USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
USETW(req.ucr_request.wIndex, endpoint);
USETW(req.ucr_request.wLength, 0);
if (ioctl(fd, USB_REQUEST, &req) < 0) {
err = errno;
close(fd);
return _errno_to_libusb(err);
}
close(fd);
return (LIBUSB_SUCCESS);
}
int
obsd_reset_device(struct libusb_device_handle *handle)
{
usbi_dbg("");
return (LIBUSB_ERROR_NOT_SUPPORTED);
}
void
obsd_destroy_device(struct libusb_device *dev)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usbi_dbg("");
free(dpriv->cdesc);
free(dpriv->devname);
}
int
obsd_submit_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct handle_priv *hpriv;
int err = 0;
usbi_dbg("");
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
err = _sync_control_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
if (IS_XFEROUT(transfer)) {
/* Isochronous write is not supported */
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
err = _sync_gen_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
if (IS_XFEROUT(transfer) &&
transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
err = _sync_gen_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
if (err)
return (err);
usbi_signal_transfer_completion(itransfer);
return (LIBUSB_SUCCESS);
}
int
obsd_cancel_transfer(struct usbi_transfer *itransfer)
{
usbi_dbg("");
return (LIBUSB_ERROR_NOT_SUPPORTED);
}
void
obsd_clear_transfer_priv(struct usbi_transfer *itransfer)
{
usbi_dbg("");
/* Nothing to do */
}
int
obsd_handle_transfer_completion(struct usbi_transfer *itransfer)
{
return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
}
int
obsd_clock_gettime(int clkid, struct timespec *tp)
{
usbi_dbg("clock %d", clkid);
if (clkid == USBI_CLOCK_REALTIME)
return clock_gettime(CLOCK_REALTIME, tp);
if (clkid == USBI_CLOCK_MONOTONIC)
return clock_gettime(CLOCK_MONOTONIC, tp);
return (LIBUSB_ERROR_INVALID_PARAM);
}
int
_errno_to_libusb(int err)
{
usbi_dbg("error: %s (%d)", strerror(err), err);
switch (err) {
case EIO:
return (LIBUSB_ERROR_IO);
case EACCES:
return (LIBUSB_ERROR_ACCESS);
case ENOENT:
return (LIBUSB_ERROR_NO_DEVICE);
case ENOMEM:
return (LIBUSB_ERROR_NO_MEM);
case ETIMEDOUT:
return (LIBUSB_ERROR_TIMEOUT);
}
return (LIBUSB_ERROR_OTHER);
}
int
_cache_active_config_descriptor(struct libusb_device *dev)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
struct usb_device_cdesc udc;
struct usb_device_fdesc udf;
unsigned char* buf;
int fd, len, err;
if ((fd = _bus_open(dev->bus_number)) < 0)
return _errno_to_libusb(errno);
usbi_dbg("fd %d, addr %d", fd, dev->device_address);
udc.udc_bus = dev->bus_number;
udc.udc_addr = dev->device_address;
udc.udc_config_index = USB_CURRENT_CONFIG_INDEX;
if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) {
err = errno;
close(fd);
return _errno_to_libusb(errno);
}
usbi_dbg("active bLength %d", udc.udc_desc.bLength);
len = UGETW(udc.udc_desc.wTotalLength);
buf = malloc(len);
if (buf == NULL)
return (LIBUSB_ERROR_NO_MEM);
udf.udf_bus = dev->bus_number;
udf.udf_addr = dev->device_address;
udf.udf_config_index = udc.udc_config_index;
udf.udf_size = len;
udf.udf_data = buf;
usbi_dbg("index %d, len %d", udf.udf_config_index, len);
if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
err = errno;
close(fd);
free(buf);
return _errno_to_libusb(err);
}
close(fd);
if (dpriv->cdesc)
free(dpriv->cdesc);
dpriv->cdesc = buf;
return (LIBUSB_SUCCESS);
}
int
_sync_control_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct libusb_control_setup *setup;
struct device_priv *dpriv;
struct usb_ctl_request req;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
setup = (struct libusb_control_setup *)transfer->buffer;
usbi_dbg("type %x request %x value %x index %d length %d timeout %d",
setup->bmRequestType, setup->bRequest,
libusb_le16_to_cpu(setup->wValue),
libusb_le16_to_cpu(setup->wIndex),
libusb_le16_to_cpu(setup->wLength), transfer->timeout);
req.ucr_addr = transfer->dev_handle->dev->device_address;
req.ucr_request.bmRequestType = setup->bmRequestType;
req.ucr_request.bRequest = setup->bRequest;
/* Don't use USETW, libusb already deals with the endianness */
(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
req.ucr_flags = USBD_SHORT_XFER_OK;
if (dpriv->devname == NULL) {
/*
* XXX If the device is not attached to ugen(4) it is
* XXX still possible to submit a control transfer but
* XXX with the default timeout only.
*/
int fd, err;
if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(fd, USB_REQUEST, &req)) < 0) {
err = errno;
close(fd);
return _errno_to_libusb(err);
}
close(fd);
} else {
if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
return _errno_to_libusb(errno);
}
itransfer->transferred = req.ucr_actlen;
usbi_dbg("transferred %d", itransfer->transferred);
return (0);
}
int
_access_endpoint(struct libusb_transfer *transfer)
{
struct handle_priv *hpriv;
struct device_priv *dpriv;
char devnode[16];
int fd, endpt;
mode_t mode;
hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
endpt = UE_GET_ADDR(transfer->endpoint);
mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
usbi_dbg("endpoint %d mode %d", endpt, mode);
if (hpriv->endpoints[endpt] < 0) {
/* Pick the right endpoint node */
snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
dpriv->devname, endpt);
/* We may need to read/write to the same endpoint later. */
if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
if ((fd = open(devnode, mode)) < 0)
return (-1);
hpriv->endpoints[endpt] = fd;
}
return (hpriv->endpoints[endpt]);
}
int
_sync_gen_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct device_priv *dpriv;
int fd, nr = 1;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
if (dpriv->devname == NULL)
return (LIBUSB_ERROR_NOT_SUPPORTED);
/*
* Bulk, Interrupt or Isochronous transfer depends on the
* endpoint and thus the node to open.
*/
if ((fd = _access_endpoint(transfer)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if (IS_XFERIN(transfer)) {
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
return _errno_to_libusb(errno);
nr = read(fd, transfer->buffer, transfer->length);
} else {
nr = write(fd, transfer->buffer, transfer->length);
}
if (nr < 0)
return _errno_to_libusb(errno);
itransfer->transferred = nr;
return (0);
}
int
_bus_open(int number)
{
char busnode[16];
snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
return open(busnode, O_RDWR);
}

View File

@ -1,84 +0,0 @@
/*
* poll_posix: poll compatibility wrapper for POSIX systems
* Copyright © 2013 RealVNC Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <config.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include "libusbi.h"
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_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 == -1) {
usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno);
goto err_close_pipe;
}
return 0;
err_close_pipe:
close(pipefd[0]);
close(pipefd[1]);
return ret;
}

View File

@ -1,14 +0,0 @@
#ifndef LIBUSB_POLL_POSIX_H
#define LIBUSB_POLL_POSIX_H
#define usbi_write write
#define usbi_read read
#define usbi_close close
#define usbi_poll poll
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 */

View File

@ -1,407 +0,0 @@
/*
* poll_windows: poll compatibility wrapper for Windows
* 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
* 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
*
*/
/*
* poll() and pipe() Windows compatibility layer for libusb 1.0
*
* The way this layer works is by using OVERLAPPED with async I/O transfers, as
* OVERLAPPED have an associated event which is flagged for I/O completion.
*
* For USB pollable async I/O, you would typically:
* - 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.
* - leave the core functions call the poll routine and flag POLLIN/POLLOUT
*
* The pipe pollable synchronous I/O works using the overlapped event associated
* with a fake pipe. The read/write functions are only meant to be used in that
* context.
*/
#include <config.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include "libusbi.h"
#include "windows_common.h"
// public fd data
const struct winfd INVALID_WINFD = { -1, NULL };
// private data
struct file_descriptor {
enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
OVERLAPPED overlapped;
int refcount;
};
static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
static struct file_descriptor *fd_table[MAX_FDS];
static struct file_descriptor *create_fd(enum fd_type type)
{
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;
}
fd->type = type;
fd->refcount = 1;
return fd;
}
static void free_fd(struct file_descriptor *fd)
{
CloseHandle(fd->overlapped.hEvent);
free(fd);
}
/*
* 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.
* 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(void)
{
struct file_descriptor *fd;
struct winfd wfd;
fd = create_fd(FD_TYPE_TRANSFER);
if (fd == NULL)
return INVALID_WINFD;
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;
}
usbi_mutex_static_unlock(&fd_table_lock);
if (wfd.fd == MAX_FDS) {
free_fd(fd);
return INVALID_WINFD;
}
wfd.overlapped = &fd->overlapped;
return wfd;
}
int usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds)
{
int n;
usbi_mutex_static_lock(&fd_table_lock);
for (n = 0; n < nfds; ++n) {
fd_table[fds[n].fd]->refcount++;
}
usbi_mutex_static_unlock(&fd_table_lock);
}
int usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds)
{
int n;
struct file_descriptor *fd;
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);
}
else {
free_fd(fd);
}
fd_table[fds[n].fd] = NULL;
}
}
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
* (but you can create multiple fds from the same handle for read and write)
*/
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
{
HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
DWORD nb_wait_handles = 0;
DWORD ret;
int nready;
nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles);
// If nothing was triggered, wait on all fds that require it
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;
}
}
return nready;
}
/*
* close a fake file descriptor
*/
int usbi_close(int _fd)
{
struct file_descriptor *fd;
if (_fd < 0 || _fd >= MAX_FDS)
goto err_badfd;
usbi_mutex_static_lock(&fd_table_lock);
fd = fd_table[_fd];
fd->refcount--;
if(fd->refcount==0)
{ fd_table[_fd] = NULL;
if (fd->type == FD_TYPE_PIPE) {
// InternalHigh is our reference count
fd->overlapped.InternalHigh--;
if (fd->overlapped.InternalHigh == 0)
free_fd(fd);
}
else {
free_fd(fd);
}
}
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;
}
/*
* synchronous write for fake "pipe" signaling
*/
ssize_t usbi_write(int fd, const void *buf, size_t count)
{
int error = EBADF;
UNUSED(buf);
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_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);
if (error)
goto err_out;
return sizeof(unsigned char);
err_out:
errno = error;
return -1;
}
/*
* synchronous read for fake "pipe" signaling
*/
ssize_t usbi_read(int fd, void *buf, size_t count)
{
int error = EBADF;
UNUSED(buf);
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;
}

View File

@ -1,100 +0,0 @@
/*
* 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.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#pragma once
#if defined(_MSC_VER)
// disable /W4 MSVC warnings that are benign
#pragma warning(disable:4127) // conditional expression is constant
#endif
// Handle synchronous completion through the overlapped structure
#if !defined(STATUS_REPARSE) // reuse the REPARSE status code
#define STATUS_REPARSE ((LONG)0x00000104L)
#endif
#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE
#if defined(_WIN32_WCE)
// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it
#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING)
#endif
#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY)
#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
#define MAX_FDS 256
#define POLLIN 0x0001 /* There is data to read */
#define POLLPRI 0x0002 /* There is urgent data to read */
#define POLLOUT 0x0004 /* Writing now will not block */
#define POLLERR 0x0008 /* Error condition */
#define POLLHUP 0x0010 /* Hung up */
#define POLLNVAL 0x0020 /* Invalid request: fd not open */
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
struct winfd {
int fd; // what's exposed to libusb core
OVERLAPPED *overlapped; // what will report our I/O status
};
extern const struct winfd INVALID_WINFD;
struct winfd usbi_create_fd(void);
int usbi_pipe(int pipefd[2]);
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout);
ssize_t usbi_write(int fd, const void *buf, size_t count);
ssize_t usbi_read(int fd, void *buf, size_t count);
int usbi_close(int fd);
int usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds);
int usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds);
/*
* Timeval operations
*/
#if defined(DDKBUILD)
#include <winsock.h> // defines timeval functions on DDK
#endif
#if !defined(TIMESPEC_TO_TIMEVAL)
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
(tv)->tv_sec = (long)(ts)->tv_sec; \
(tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \
}
#endif
#if !defined(timersub)
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,80 +0,0 @@
/*
*
* Copyright (c) 2016, Oracle and/or its affiliates.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LIBUSB_SUNOS_H
#define LIBUSB_SUNOS_H
#include <libdevinfo.h>
#include <pthread.h>
#include "libusbi.h"
#define READ 0
#define WRITE 1
typedef struct sunos_device_priv {
uint8_t cfgvalue; /* active config value */
uint8_t *raw_cfgdescr; /* active config descriptor */
struct libusb_device_descriptor dev_descr; /* usb device descriptor */
char *ugenpath; /* name of the ugen(4) node */
char *phypath; /* physical path */
} sunos_dev_priv_t;
typedef struct endpoint {
int datafd; /* data file */
int statfd; /* state file */
} sunos_ep_priv_t;
typedef struct sunos_device_handle_priv {
uint8_t altsetting[USB_MAXINTERFACES]; /* a interface's alt */
uint8_t config_index;
sunos_ep_priv_t eps[USB_MAXENDPOINTS];
sunos_dev_priv_t *dpriv; /* device private */
} sunos_dev_handle_priv_t;
typedef struct sunos_transfer_priv {
struct aiocb aiocb;
struct libusb_transfer *transfer;
} sunos_xfer_priv_t;
struct node_args {
struct libusb_context *ctx;
struct discovered_devs **discdevs;
const char *last_ugenpath;
di_devlink_handle_t dlink_hdl;
};
struct devlink_cbarg {
struct node_args *nargs; /* di node walk arguments */
di_node_t myself; /* the di node */
di_minor_t minor;
};
typedef struct walk_link {
char *path;
int len;
char **linkpp;
} walk_link_t;
/* AIO callback args */
struct aio_callback_args{
struct libusb_transfer *transfer;
struct aiocb aiocb;
};
#endif /* LIBUSB_SUNOS_H */

View File

@ -1,80 +0,0 @@
/*
* libusb synchronization using POSIX Threads
*
* Copyright © 2011 Vitali Lovich <vlovich@aliph.com>
* Copyright © 2011 Peter Stuge <peter@stuge.se>
*
* 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 <config.h>
#include <time.h>
#if defined(__linux__) || defined(__OpenBSD__)
# if defined(__OpenBSD__)
# define _BSD_SOURCE
# endif
# include <unistd.h>
# include <sys/syscall.h>
#elif defined(__APPLE__)
# include <pthread.h>
#elif defined(__CYGWIN__)
# include <windows.h>
#endif
#include "threads_posix.h"
#include "libusbi.h"
int usbi_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex, const struct timeval *tv)
{
struct timespec timeout;
int r;
r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout);
if (r < 0)
return r;
timeout.tv_sec += tv->tv_sec;
timeout.tv_nsec += tv->tv_usec * 1000;
while (timeout.tv_nsec >= 1000000000L) {
timeout.tv_nsec -= 1000000000L;
timeout.tv_sec++;
}
return pthread_cond_timedwait(cond, mutex, &timeout);
}
int usbi_get_tid(void)
{
int ret;
#if defined(__ANDROID__)
ret = gettid();
#elif defined(__linux__)
ret = syscall(SYS_gettid);
#elif defined(__OpenBSD__)
/* The following only works with OpenBSD > 5.1 as it requires
real thread support. For 5.1 and earlier, -1 is returned. */
ret = syscall(SYS_getthrid);
#elif defined(__APPLE__)
ret = (int)pthread_mach_thread_np(pthread_self());
#elif defined(__CYGWIN__)
ret = GetCurrentThreadId();
#else
ret = -1;
#endif
/* TODO: NetBSD thread ID support */
return ret;
}

View File

@ -1,102 +0,0 @@
/*
* libusb synchronization using POSIX Threads
*
* Copyright © 2010 Peter Stuge <peter@stuge.se>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LIBUSB_THREADS_POSIX_H
#define LIBUSB_THREADS_POSIX_H
#include <pthread.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t usbi_mutex_static_t;
static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
{
(void)pthread_mutex_lock(mutex);
}
static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
{
(void)pthread_mutex_unlock(mutex);
}
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);
}
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);
}
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);
#endif /* LIBUSB_THREADS_POSIX_H */

View File

@ -1,126 +0,0 @@
/*
* libusb synchronization on Microsoft Windows
*
* Copyright © 2010 Michael Plante <michael.plante@gmail.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 <config.h>
#include <errno.h>
#include "libusbi.h"
struct usbi_cond_perthread {
struct list_head list;
HANDLE event;
};
void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
{
while (InterlockedExchange(mutex, 1L) == 1L)
SleepEx(0, TRUE);
}
void usbi_cond_init(usbi_cond_t *cond)
{
list_init(&cond->waiters);
list_init(&cond->not_waiting);
}
static int usbi_cond_intwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, DWORD timeout_ms)
{
struct usbi_cond_perthread *pos;
DWORD r;
// 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->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
if (pos->event == NULL) {
free(pos);
return ENOMEM;
}
} 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_add(&pos->list, &cond->waiters);
LeaveCriticalSection(mutex);
r = WaitForSingleObject(pos->event, timeout_ms);
EnterCriticalSection(mutex);
list_del(&pos->list);
list_add(&pos->list, &cond->not_waiting);
if (r == WAIT_OBJECT_0)
return 0;
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)
{
return usbi_cond_intwait(cond, mutex, INFINITE);
}
int usbi_cond_timedwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, const struct timeval *tv)
{
DWORD millis;
millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
/* round up to next millisecond */
if (tv->tv_usec % 1000)
millis++;
return usbi_cond_intwait(cond, mutex, millis);
}
void 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!
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_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;
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);
}
}

View File

@ -1,111 +0,0 @@
/*
* libusb synchronization on Microsoft Windows
*
* Copyright © 2010 Michael Plante <michael.plante@gmail.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
*/
#ifndef LIBUSB_THREADS_WINDOWS_H
#define LIBUSB_THREADS_WINDOWS_H
#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);
}
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))
#define HAVE_STRUCT_TIMESPEC 1
#define _TIMESPEC_DEFINED 1
struct timespec {
long tv_sec;
long tv_nsec;
};
#endif /* HAVE_STRUCT_TIMESPEC | _TIMESPEC_DEFINED */
// We *were* getting ETIMEDOUT from pthread.h:
#ifndef ETIMEDOUT
#define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif
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;
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);
void usbi_cond_broadcast(usbi_cond_t *cond);
void usbi_cond_destroy(usbi_cond_t *cond);
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);
}
static inline int usbi_get_tid(void)
{
return (int)GetCurrentThreadId();
}
#endif /* LIBUSB_THREADS_WINDOWS_H */

View File

@ -1,888 +0,0 @@
/*
* Windows CE backend for libusb 1.0
* Copyright © 2011-2013 RealVNC Ltd.
* Large portions taken from Windows backend, which is
* Copyright © 2009-2010 Pete Batard <pbatard@gmail.com>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
*
* 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 <config.h>
#include <stdint.h>
#include <inttypes.h>
#include "libusbi.h"
#include "wince_usb.h"
// Global variables
int errno = 0;
static uint64_t hires_frequency, hires_ticks_to_ps;
static HANDLE driver_handle = INVALID_HANDLE_VALUE;
static int concurrent_usage = -1;
/*
* Converts a windows error to human readable string
* uses retval as errorcode, or, if 0, use GetLastError()
*/
#if defined(ENABLE_LOGGING)
static const char *windows_error_str(DWORD error_code)
{
static TCHAR wErr_string[ERR_BUFFER_SIZE];
static char err_string[ERR_BUFFER_SIZE];
DWORD size;
int len;
if (error_code == 0)
error_code = GetLastError();
len = sprintf(err_string, "[%u] ", (unsigned int)error_code);
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) {
DWORD format_error = GetLastError();
if (format_error)
snprintf(err_string, ERR_BUFFER_SIZE,
"Windows error code %u (FormatMessage error code %u)",
(unsigned int)error_code, (unsigned int)format_error);
else
snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code);
} else {
// 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[len], ERR_BUFFER_SIZE - len, NULL, NULL))
strcpy(err_string, "Unable to convert error string");
}
return err_string;
}
#endif
static struct wince_device_priv *_device_priv(struct libusb_device *dev)
{
return (struct wince_device_priv *)dev->os_priv;
}
// ceusbkwrapper to libusb error code mapping
static int translate_driver_error(DWORD error)
{
switch (error) {
case ERROR_INVALID_PARAMETER:
return LIBUSB_ERROR_INVALID_PARAM;
case ERROR_CALL_NOT_IMPLEMENTED:
case ERROR_NOT_SUPPORTED:
return LIBUSB_ERROR_NOT_SUPPORTED;
case ERROR_NOT_ENOUGH_MEMORY:
return LIBUSB_ERROR_NO_MEM;
case ERROR_INVALID_HANDLE:
return LIBUSB_ERROR_NO_DEVICE;
case ERROR_BUSY:
return LIBUSB_ERROR_BUSY;
// Error codes that are either unexpected, or have
// no suitable LIBUSB_ERROR equivalent.
case ERROR_CANCELLED:
case ERROR_INTERNAL_ERROR:
default:
return LIBUSB_ERROR_OTHER;
}
}
static BOOL init_dllimports(void)
{
DLL_GET_HANDLE(ceusbkwrapper);
DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceList, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseDeviceList, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceAddress, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceDescriptor, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfigDescriptor, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwCloseDriver, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwCancelTransfer, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueControlTransfer, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwClaimInterface, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseInterface, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwSetInterfaceAlternateSetting, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltHost, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltDevice, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfig, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwSetConfig, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwResetDevice, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwKernelDriverActive, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwAttachKernelDriver, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwDetachKernelDriver, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE);
return TRUE;
}
static void exit_dllimports(void)
{
DLL_FREE_HANDLE(ceusbkwrapper);
}
static int init_device(
struct libusb_device *dev, UKW_DEVICE drv_dev,
unsigned char bus_addr, unsigned char dev_addr)
{
struct wince_device_priv *priv = _device_priv(dev);
int r = LIBUSB_SUCCESS;
dev->bus_number = bus_addr;
dev->device_address = dev_addr;
priv->dev = drv_dev;
if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc)))
r = translate_driver_error(GetLastError());
return r;
}
// Internal API functions
static int wince_init(struct libusb_context *ctx)
{
int r = LIBUSB_ERROR_OTHER;
HANDLE semaphore;
LARGE_INTEGER li_frequency;
TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
_stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
semaphore = CreateSemaphore(NULL, 1, 1, sem_name);
if (semaphore == NULL) {
usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_MEM;
}
// A successful wait brings our semaphore count to 0 (unsignaled)
// => any concurent wait stalls until the semaphore's release
if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
CloseHandle(semaphore);
return LIBUSB_ERROR_NO_MEM;
}
// NB: concurrent usage supposes that init calls are equally balanced with
// exit calls. If init is called more than exit, we will not exit properly
if ( ++concurrent_usage == 0 ) { // First init?
// Load DLL imports
if (!init_dllimports()) {
usbi_err(ctx, "could not resolve DLL functions");
r = LIBUSB_ERROR_NOT_SUPPORTED;
goto init_exit;
}
// try to open a handle to the driver
driver_handle = UkwOpenDriver();
if (driver_handle == INVALID_HANDLE_VALUE) {
usbi_err(ctx, "could not connect to driver");
r = LIBUSB_ERROR_NOT_SUPPORTED;
goto init_exit;
}
// find out if we have access to a monotonic (hires) timer
if (QueryPerformanceFrequency(&li_frequency)) {
hires_frequency = li_frequency.QuadPart;
// The hires frequency can go as high as 4 GHz, so we'll use a conversion
// to picoseconds to compute the tv_nsecs part in clock_gettime
hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
} else {
usbi_dbg("no hires timer available on this platform");
hires_frequency = 0;
hires_ticks_to_ps = UINT64_C(0);
}
}
// At this stage, either we went through full init successfully, or didn't need to
r = LIBUSB_SUCCESS;
init_exit: // Holds semaphore here.
if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
exit_dllimports();
if (driver_handle != INVALID_HANDLE_VALUE) {
UkwCloseDriver(driver_handle);
driver_handle = INVALID_HANDLE_VALUE;
}
}
if (r != LIBUSB_SUCCESS)
--concurrent_usage; // Not expected to call libusb_exit if we failed.
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
CloseHandle(semaphore);
return r;
}
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);
if (semaphore == NULL)
return;
// A successful wait brings our semaphore count to 0 (unsignaled)
// => any concurent wait stalls until the semaphore release
if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
CloseHandle(semaphore);
return;
}
// Only works if exits and inits are balanced exactly
if (--concurrent_usage < 0) { // Last exit
exit_dllimports();
if (driver_handle != INVALID_HANDLE_VALUE) {
UkwCloseDriver(driver_handle);
driver_handle = INVALID_HANDLE_VALUE;
}
}
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
CloseHandle(semaphore);
}
static int wince_get_device_list(
struct libusb_context *ctx,
struct discovered_devs **discdevs)
{
UKW_DEVICE devices[MAX_DEVICE_COUNT];
struct discovered_devs *new_devices = *discdevs;
DWORD count = 0, i;
struct libusb_device *dev = NULL;
unsigned char bus_addr, dev_addr;
unsigned long session_id;
BOOL success;
DWORD release_list_offset = 0;
int r = LIBUSB_SUCCESS;
success = UkwGetDeviceList(driver_handle, devices, MAX_DEVICE_COUNT, &count);
if (!success) {
int libusbErr = translate_driver_error(GetLastError());
usbi_err(ctx, "could not get devices: %s", windows_error_str(0));
return libusbErr;
}
for (i = 0; i < count; ++i) {
release_list_offset = i;
success = UkwGetDeviceAddress(devices[i], &bus_addr, &dev_addr, &session_id);
if (!success) {
r = translate_driver_error(GetLastError());
usbi_err(ctx, "could not get device address for %u: %s", (unsigned int)i, windows_error_str(0));
goto err_out;
}
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev) {
usbi_dbg("using existing device for %u/%u (session %lu)",
bus_addr, dev_addr, session_id);
// Release just this element in the device list (as we already hold a
// reference to it).
UkwReleaseDeviceList(driver_handle, &devices[i], 1);
release_list_offset++;
} else {
usbi_dbg("allocating new device for %u/%u (session %lu)",
bus_addr, dev_addr, session_id);
dev = usbi_alloc_device(ctx, session_id);
if (!dev) {
r = LIBUSB_ERROR_NO_MEM;
goto err_out;
}
r = init_device(dev, devices[i], bus_addr, dev_addr);
if (r < 0)
goto err_out;
r = usbi_sanitize_device(dev);
if (r < 0)
goto err_out;
}
new_devices = discovered_devs_append(new_devices, dev);
if (!new_devices) {
r = LIBUSB_ERROR_NO_MEM;
goto err_out;
}
libusb_unref_device(dev);
}
*discdevs = new_devices;
return r;
err_out:
*discdevs = new_devices;
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.
UkwReleaseDeviceList(driver_handle, &devices[release_list_offset], count - release_list_offset);
return r;
}
static int wince_open(struct libusb_device_handle *handle)
{
// Nothing to do to open devices as a handle to it has
// been retrieved by wince_get_device_list
return LIBUSB_SUCCESS;
}
static void wince_close(struct libusb_device_handle *handle)
{
// Nothing to do as wince_open does nothing.
}
static int wince_get_device_descriptor(
struct libusb_device *device,
unsigned char *buffer, int *host_endian)
{
struct wince_device_priv *priv = _device_priv(device);
*host_endian = 1;
memcpy(buffer, &priv->desc, DEVICE_DESC_LENGTH);
return LIBUSB_SUCCESS;
}
static int wince_get_active_config_descriptor(
struct libusb_device *device,
unsigned char *buffer, size_t len, int *host_endian)
{
struct wince_device_priv *priv = _device_priv(device);
DWORD actualSize = len;
*host_endian = 0;
if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize))
return translate_driver_error(GetLastError());
return actualSize;
}
static int wince_get_config_descriptor(
struct libusb_device *device,
uint8_t config_index,
unsigned char *buffer, size_t len, int *host_endian)
{
struct wince_device_priv *priv = _device_priv(device);
DWORD actualSize = len;
*host_endian = 0;
if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize))
return translate_driver_error(GetLastError());
return actualSize;
}
static int wince_get_configuration(
struct libusb_device_handle *handle,
int *config)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
UCHAR cv = 0;
if (!UkwGetConfig(priv->dev, &cv))
return translate_driver_error(GetLastError());
(*config) = cv;
return LIBUSB_SUCCESS;
}
static int wince_set_configuration(
struct libusb_device_handle *handle,
int config)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
// Setting configuration 0 places the device in Address state.
// This should correspond to the "unconfigured state" required by
// libusb when the specified configuration is -1.
UCHAR cv = (config < 0) ? 0 : config;
if (!UkwSetConfig(priv->dev, cv))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_claim_interface(
struct libusb_device_handle *handle,
int interface_number)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
if (!UkwClaimInterface(priv->dev, interface_number))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_release_interface(
struct libusb_device_handle *handle,
int interface_number)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0))
return translate_driver_error(GetLastError());
if (!UkwReleaseInterface(priv->dev, interface_number))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_set_interface_altsetting(
struct libusb_device_handle *handle,
int interface_number, int altsetting)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_clear_halt(
struct libusb_device_handle *handle,
unsigned char endpoint)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
if (!UkwClearHaltHost(priv->dev, endpoint))
return translate_driver_error(GetLastError());
if (!UkwClearHaltDevice(priv->dev, endpoint))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_reset_device(
struct libusb_device_handle *handle)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
if (!UkwResetDevice(priv->dev))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_kernel_driver_active(
struct libusb_device_handle *handle,
int interface_number)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
BOOL result = FALSE;
if (!UkwKernelDriverActive(priv->dev, interface_number, &result))
return translate_driver_error(GetLastError());
return result ? 1 : 0;
}
static int wince_detach_kernel_driver(
struct libusb_device_handle *handle,
int interface_number)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
if (!UkwDetachKernelDriver(priv->dev, interface_number))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_attach_kernel_driver(
struct libusb_device_handle *handle,
int interface_number)
{
struct wince_device_priv *priv = _device_priv(handle->dev);
if (!UkwAttachKernelDriver(priv->dev, interface_number))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static void wince_destroy_device(struct libusb_device *dev)
{
struct wince_device_priv *priv = _device_priv(dev);
UkwReleaseDeviceList(driver_handle, &priv->dev, 1);
}
static void wince_clear_transfer_priv(struct usbi_transfer *itransfer)
{
struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
usbi_close(transfer_priv->pollable_fd.fd);
transfer_priv->pollable_fd = INVALID_WINFD;
}
static int wince_cancel_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT))
return translate_driver_error(GetLastError());
return LIBUSB_SUCCESS;
}
static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
BOOL direction_in, ret;
struct winfd wfd;
DWORD flags;
PUKW_CONTROL_HEADER setup = NULL;
const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL;
int r;
if (control_transfer) {
setup = (PUKW_CONTROL_HEADER) transfer->buffer;
direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN;
} else {
direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
}
flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER;
flags |= UKW_TF_SHORT_TRANSFER_OK;
wfd = usbi_create_fd();
if (wfd.fd < 0)
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);
PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)];
ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped);
} else {
ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer,
transfer->length, &transfer->actual_length, wfd.overlapped);
}
if (!ret) {
int libusbErr = translate_driver_error(GetLastError());
usbi_err(ctx, "UkwIssue%sTransfer failed: error %u",
control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError());
usbi_remove_pollfd(ctx, wfd.fd);
usbi_close(wfd.fd);
transfer_priv->pollable_fd = INVALID_WINFD;
return libusbErr;
}
return LIBUSB_SUCCESS;
}
static int wince_submit_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
return wince_submit_control_or_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
return LIBUSB_ERROR_NOT_SUPPORTED;
default:
usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
}
}
static void wince_transfer_callback(
struct usbi_transfer *itransfer,
uint32_t io_result, uint32_t io_size)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int status;
usbi_dbg("handling I/O completion with errcode %u", io_result);
if (io_result == ERROR_NOT_SUPPORTED &&
transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) {
/* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper
* Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the
* endpoint isn't actually stalled.
*
* One example of this is that some devices will occasionally fail to reply to an IN
* token. The WinCE USB layer carries on with the transaction until it is completed
* (or cancelled) but then completes it with USB_ERROR_STALL.
*
* This code therefore needs to confirm that there really is a stall error, by both
* checking the pipe status and requesting the endpoint status from the device.
*/
BOOL halted = FALSE;
usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall");
if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) {
/* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS
* control request to the device. This is done synchronously, which is a bit
* naughty, but this is a special corner case.
*/
WORD wStatus = 0;
DWORD written = 0;
UKW_CONTROL_HEADER ctrlHeader;
ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD |
LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT;
ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS;
ctrlHeader.wValue = 0;
ctrlHeader.wIndex = transfer->endpoint;
ctrlHeader.wLength = sizeof(wStatus);
if (UkwIssueControlTransfer(priv->dev,
UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT,
&ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) {
if (written == sizeof(wStatus) &&
(wStatus & STATUS_HALT_FLAG) == 0) {
if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) {
usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success");
io_result = ERROR_SUCCESS;
} else {
usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error");
io_result = ERROR_IO_DEVICE;
}
}
}
}
}
switch(io_result) {
case ERROR_SUCCESS:
itransfer->transferred += io_size;
status = LIBUSB_TRANSFER_COMPLETED;
break;
case ERROR_CANCELLED:
usbi_dbg("detected transfer cancel");
status = LIBUSB_TRANSFER_CANCELLED;
break;
case ERROR_NOT_SUPPORTED:
case ERROR_GEN_FAILURE:
usbi_dbg("detected endpoint stall");
status = LIBUSB_TRANSFER_STALL;
break;
case ERROR_SEM_TIMEOUT:
usbi_dbg("detected semaphore timeout");
status = LIBUSB_TRANSFER_TIMED_OUT;
break;
case ERROR_OPERATION_ABORTED:
usbi_dbg("detected operation aborted");
status = LIBUSB_TRANSFER_CANCELLED;
break;
default:
usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result));
status = LIBUSB_TRANSFER_ERROR;
break;
}
wince_clear_transfer_priv(itransfer);
if (status == LIBUSB_TRANSFER_CANCELLED)
usbi_handle_transfer_cancellation(itransfer);
else
usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
}
static void wince_handle_callback(
struct usbi_transfer *itransfer,
uint32_t io_result, uint32_t io_size)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
wince_transfer_callback (itransfer, io_result, io_size);
break;
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
break;
default:
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
}
}
static int wince_handle_events(
struct libusb_context *ctx,
struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
{
struct wince_transfer_priv* transfer_priv = NULL;
POLL_NFDS_TYPE i = 0;
BOOL found = FALSE;
struct usbi_transfer *itransfer;
DWORD io_size, io_result;
int r = LIBUSB_SUCCESS;
usbi_mutex_lock(&ctx->open_devs_lock);
for (i = 0; i < nfds && num_ready > 0; i++) {
usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
if (!fds[i].revents)
continue;
num_ready--;
// Because a Windows OVERLAPPED is used for poll emulation,
// a pollable fd is created and stored with each transfer
usbi_mutex_lock(&ctx->flying_transfers_lock);
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;
}
}
usbi_mutex_unlock(&ctx->flying_transfers_lock);
if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) {
io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal;
io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh;
usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
// let handle_callback free the event using the transfer wfd
// If you don't use the transfer wfd, you run a risk of trying to free a
// newly allocated wfd that took the place of the one from the transfer.
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;
break;
} else {
usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
r = LIBUSB_ERROR_NOT_FOUND;
break;
}
}
usbi_mutex_unlock(&ctx->open_devs_lock);
return r;
}
/*
* Monotonic and real time functions
*/
static int wince_clock_gettime(int clk_id, struct timespec *tp)
{
LARGE_INTEGER hires_counter;
ULARGE_INTEGER rtime;
FILETIME filetime;
SYSTEMTIME st;
switch(clk_id) {
case USBI_CLOCK_MONOTONIC:
if (hires_frequency != 0 && QueryPerformanceCounter(&hires_counter)) {
tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
return LIBUSB_SUCCESS;
}
// 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
// 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;
tp->tv_sec = (long)(rtime.QuadPart / 10000000);
tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
return LIBUSB_SUCCESS;
default:
return LIBUSB_ERROR_INVALID_PARAM;
}
}
const struct usbi_os_backend usbi_backend = {
"Windows CE",
0,
wince_init,
wince_exit,
NULL, /* set_option() */
wince_get_device_list,
NULL, /* hotplug_poll */
wince_open,
wince_close,
wince_get_device_descriptor,
wince_get_active_config_descriptor,
wince_get_config_descriptor,
NULL, /* get_config_descriptor_by_value() */
wince_get_configuration,
wince_set_configuration,
wince_claim_interface,
wince_release_interface,
wince_set_interface_altsetting,
wince_clear_halt,
wince_reset_device,
NULL, /* alloc_streams */
NULL, /* free_streams */
NULL, /* dev_mem_alloc() */
NULL, /* dev_mem_free() */
wince_kernel_driver_active,
wince_detach_kernel_driver,
wince_attach_kernel_driver,
wince_destroy_device,
wince_submit_transfer,
wince_cancel_transfer,
wince_clear_transfer_priv,
wince_handle_events,
NULL, /* handle_transfer_completion() */
wince_clock_gettime,
0,
sizeof(struct wince_device_priv),
0,
sizeof(struct wince_transfer_priv),
};

View File

@ -1,126 +0,0 @@
/*
* Windows CE backend for libusb 1.0
* Copyright © 2011-2013 RealVNC Ltd.
* Portions taken from Windows backend, which is
* Copyright © 2009-2010 Pete Batard <pbatard@gmail.com>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "windows_common.h"
#include <windows.h>
#include "poll_windows.h"
#define MAX_DEVICE_COUNT 256
// This is a modified dump of the types in the ceusbkwrapper.h library header
// with functions transformed into extern pointers.
//
// This backend dynamically loads ceusbkwrapper.dll and doesn't include
// ceusbkwrapper.h directly to simplify the build process. The kernel
// side wrapper driver is built using the platform image build tools,
// which makes it difficult to reference directly from the libusb build
// system.
struct UKW_DEVICE_PRIV;
typedef struct UKW_DEVICE_PRIV *UKW_DEVICE;
typedef UKW_DEVICE *PUKW_DEVICE, *LPUKW_DEVICE;
typedef struct {
UINT8 bLength;
UINT8 bDescriptorType;
UINT16 bcdUSB;
UINT8 bDeviceClass;
UINT8 bDeviceSubClass;
UINT8 bDeviceProtocol;
UINT8 bMaxPacketSize0;
UINT16 idVendor;
UINT16 idProduct;
UINT16 bcdDevice;
UINT8 iManufacturer;
UINT8 iProduct;
UINT8 iSerialNumber;
UINT8 bNumConfigurations;
} UKW_DEVICE_DESCRIPTOR, *PUKW_DEVICE_DESCRIPTOR, *LPUKW_DEVICE_DESCRIPTOR;
typedef struct {
UINT8 bmRequestType;
UINT8 bRequest;
UINT16 wValue;
UINT16 wIndex;
UINT16 wLength;
} UKW_CONTROL_HEADER, *PUKW_CONTROL_HEADER, *LPUKW_CONTROL_HEADER;
// Collection of flags which can be used when issuing transfer requests
/* Indicates that the transfer direction is 'in' */
#define UKW_TF_IN_TRANSFER 0x00000001
/* Indicates that the transfer direction is 'out' */
#define UKW_TF_OUT_TRANSFER 0x00000000
/* Specifies that the transfer should complete as soon as possible,
* even if no OVERLAPPED structure has been provided. */
#define UKW_TF_NO_WAIT 0x00000100
/* Indicates that transfers shorter than the buffer are ok */
#define UKW_TF_SHORT_TRANSFER_OK 0x00000200
#define UKW_TF_SEND_TO_DEVICE 0x00010000
#define UKW_TF_SEND_TO_INTERFACE 0x00020000
#define UKW_TF_SEND_TO_ENDPOINT 0x00040000
/* Don't block when waiting for memory allocations */
#define UKW_TF_DONT_BLOCK_FOR_MEM 0x00080000
/* Value to use when dealing with configuration values, such as UkwGetConfigDescriptor,
* to specify the currently active configuration for the device. */
#define UKW_ACTIVE_CONFIGURATION -1
DLL_DECLARE_HANDLE(ceusbkwrapper);
DLL_DECLARE_FUNC(WINAPI, HANDLE, UkwOpenDriver, ());
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD));
DLL_DECLARE_FUNC(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD));
DLL_DECLARE_FUNC(WINAPI, void, UkwCloseDriver, (HANDLE));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED));
DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL));
// Used to determine if an endpoint status really is halted on a failed transfer.
#define STATUS_HALT_FLAG 0x1
struct wince_device_priv {
UKW_DEVICE dev;
UKW_DEVICE_DESCRIPTOR desc;
};
struct wince_transfer_priv {
struct winfd pollable_fd;
uint8_t interface_number;
};

View File

@ -1,128 +0,0 @@
/*
* Windows backend common header for libusb 1.0
*
* This file brings together header code common between
* the desktop Windows and Windows CE backends.
* Copyright © 2012-2013 RealVNC Ltd.
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
// Windows API default is uppercase - ugh!
#if !defined(bool)
#define bool BOOL
#endif
#if !defined(true)
#define true TRUE
#endif
#if !defined(false)
#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 _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)
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#define ERR_BUFFER_SIZE 256
/*
* API macros - leveraged from libusb-win32 1.x
*/
#ifndef _WIN32_WCE
#define DLL_STRINGIFY(s) #s
#define DLL_LOAD_LIBRARY(name) LoadLibraryA(DLL_STRINGIFY(name))
#else
#define DLL_STRINGIFY(s) L#s
#define DLL_LOAD_LIBRARY(name) LoadLibrary(DLL_STRINGIFY(name))
#endif
/*
* Macros for handling DLL themselves
*/
#define DLL_HANDLE_NAME(name) __dll_##name##_handle
#define DLL_DECLARE_HANDLE(name) \
static HMODULE DLL_HANDLE_NAME(name) = NULL
#define DLL_GET_HANDLE(name) \
do { \
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_HANDLE_NAME(name)) { \
FreeLibrary(DLL_HANDLE_NAME(name)); \
DLL_HANDLE_NAME(name) = NULL; \
} \
} 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_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)
#define DLL_DECLARE_FUNC_PREFIXED(api, ret, prefix, name, args) \
DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefix##name, name, args)
#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
do { \
HMODULE h = DLL_HANDLE_NAME(dll); \
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name)); \
if (prefixname) \
break; \
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \
if (prefixname) \
break; \
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \
if (prefixname) \
break; \
if (ret_on_failure) \
return FALSE; \
} while (0)
#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \
DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure)
#define DLL_LOAD_FUNC_PREFIXED(dll, prefix, name, ret_on_failure) \
DLL_LOAD_FUNC_PREFIXNAME(dll, prefix##name, name, ret_on_failure)

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +0,0 @@
/*
* Windows backend common header for libusb 1.0
*
* This file brings together header code common between
* the desktop Windows backends.
* Copyright © 2012-2013 RealVNC Ltd.
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "windows_nt_shared_types.h"
/* 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
};
extern enum windows_version windows_version;
/* 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);
void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size);
#if defined(ENABLE_LOGGING)
const char *windows_error_str(DWORD error_code);
#endif

View File

@ -1,147 +0,0 @@
#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.
};

File diff suppressed because it is too large Load Diff

View File

@ -1,973 +0,0 @@
/*
* Windows backend for libusb 1.0
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "windows_common.h"
#if defined(_MSC_VER)
// disable /W4 MSVC warnings that are benign
#pragma warning(disable:4100) // unreferenced formal parameter
#pragma warning(disable:4127) // conditional expression is constant
#pragma warning(disable:4201) // nameless struct/union
#pragma warning(disable:4214) // bit field types other than int
#pragma warning(disable:4996) // deprecated API calls
#pragma warning(disable:28159) // more deprecated API calls
#endif
// Missing from MSVC6 setupapi.h
#if !defined(SPDRP_ADDRESS)
#define SPDRP_ADDRESS 28
#endif
#if !defined(SPDRP_INSTALL_STATE)
#define SPDRP_INSTALL_STATE 34
#endif
// Missing from MinGW
#if !defined(FACILITY_SETUPAPI)
#define FACILITY_SETUPAPI 15
#endif
#if defined(__CYGWIN__ )
#define _stricmp stricmp
#define _snprintf snprintf
#define _strdup strdup
// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, f)
#endif
#define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_DEVICES 256
#define MAX_USB_STRING_LENGTH 128
#define MAX_HID_REPORT_SIZE 1024
#define MAX_HID_DESCRIPTOR_SIZE 256
#define MAX_GUID_STRING_LENGTH 40
#define MAX_PATH_LENGTH 128
#define MAX_KEY_LENGTH 256
#define LIST_SEPARATOR ';'
#define HTAB_SIZE 1021
// Handle code for HID interface that have been claimed ("dibs")
#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5)
// Additional return code for HID operations that completed synchronously
#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1)
// http://msdn.microsoft.com/en-us/library/ff545978.aspx
// http://msdn.microsoft.com/en-us/library/ff545972.aspx
// http://msdn.microsoft.com/en-us/library/ff545982.aspx
#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} };
#endif
#if !defined(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} };
#endif
#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER)
const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} };
#endif
/*
* Multiple USB API backend support
*/
#define USB_API_UNSUPPORTED 0
#define USB_API_HUB 1
#define USB_API_COMPOSITE 2
#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
#define SUB_API_NOTSET -1
#define SUB_API_LIBUSBK 0
#define SUB_API_LIBUSB0 1
#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 uint8_t nb_driver_names;
int (*init)(int sub_api, struct libusb_context *ctx);
int (*exit)(int sub_api);
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);
int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
int (*clear_halt)(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
int (*reset_device)(int sub_api, struct libusb_device_handle *dev_handle);
int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*abort_control)(int sub_api, struct usbi_transfer *itransfer);
int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer);
int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
};
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;
/*
* private structures definition
* with inline pseudo constructors/destructors
*/
// TODO (v2+): move hid desc to libusb.h?
struct libusb_hid_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bClassDescriptorType;
uint16_t wClassDescriptorLength;
};
#define LIBUSB_DT_HID_SIZE 9
#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \
+ LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE)
#define HID_MAX_REPORT_SIZE 1024
#define HID_IN_EP 0x81
#define HID_OUT_EP 0x02
#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F)
#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5))
#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN)
#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type))
// The following are used for HID reports IOCTLs
#define HID_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
#define HID_BUFFER_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define HID_IN_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define HID_OUT_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100)
#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101)
enum libusb_hid_request_type {
HID_REQ_GET_REPORT = 0x01,
HID_REQ_GET_IDLE = 0x02,
HID_REQ_GET_PROTOCOL = 0x03,
HID_REQ_SET_REPORT = 0x09,
HID_REQ_SET_IDLE = 0x0A,
HID_REQ_SET_PROTOCOL = 0x0B
};
enum libusb_hid_report_type {
HID_REPORT_TYPE_INPUT = 0x01,
HID_REPORT_TYPE_OUTPUT = 0x02,
HID_REPORT_TYPE_FEATURE = 0x03
};
struct hid_device_priv {
uint16_t vid;
uint16_t pid;
uint8_t config;
uint8_t nb_interfaces;
bool uses_report_ids[3]; // input, ouptput, feature
uint16_t input_report_size;
uint16_t output_report_size;
uint16_t feature_report_size;
WCHAR string[3][MAX_USB_STRING_LENGTH];
uint8_t string_index[3]; // man, prod, ser
};
typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
struct windows_device_priv {
uint8_t depth; // distance to HCD
uint8_t port; // port number on the hub
uint8_t active_config;
struct libusb_device *parent_dev; // access to parent is required for usermode ops
struct windows_usb_api_backend const *apib;
char *path; // device interface path
int sub_api; // for WinUSB-like APIs
struct {
char *path; // each interface needs a device interface path,
struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support),
int sub_api;
int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
uint8_t *endpoint;
bool restricted_functionality; // indicates if the interface functionality is restricted
// by Windows (eg. HID keyboards or mice cannot do R/W)
} usb_interface[USB_MAXINTERFACES];
struct hid_device_priv *hid;
USB_DEVICE_DESCRIPTOR dev_descriptor;
unsigned char **config_descriptor; // list of pointers to the cached config descriptors
};
static inline struct windows_device_priv *_device_priv(struct libusb_device *dev) {
return (struct windows_device_priv *)dev->os_priv;
}
static inline void windows_device_priv_init(libusb_device* dev) {
struct windows_device_priv* p = _device_priv(dev);
int i;
p->depth = 0;
p->port = 0;
p->parent_dev = NULL;
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;
}
}
static inline void windows_device_priv_release(libusb_device* dev) {
struct windows_device_priv* p = _device_priv(dev);
int i;
safe_free(p->path);
if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
for (i=0; i < dev->num_configurations; i++)
safe_free(p->config_descriptor[i]);
}
safe_free(p->config_descriptor);
safe_free(p->hid);
for (i=0; i<USB_MAXINTERFACES; i++) {
safe_free(p->usb_interface[i].path);
safe_free(p->usb_interface[i].endpoint);
}
}
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(
struct libusb_device_handle *handle)
{
return (struct windows_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
const DWORD reg_prop; // SPDRP registry key to use to retreive list
const char* designation; // internal designation (for debug output)
};
#define WM_TIMER_REQUEST (WM_USER + 1)
#define WM_TIMER_EXIT (WM_USER + 2)
// used for monotonic clock_gettime()
struct timer_request {
struct timespec *tp;
HANDLE event;
};
/* OLE32 dependency */
DLL_DECLARE_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID));
/* This call is only available from XP SP2 */
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL));
/* SetupAPI dependencies */
DLL_DECLARE_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA,
const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA,
PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD));
DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
/* User32 dependencies */
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM));
/*
* Windows DDK API definitions. Most of it copied from MinGW's includes
*/
typedef DWORD DEVNODE, DEVINST;
typedef DEVNODE *PDEVNODE, *PDEVINST;
typedef DWORD RETURN_TYPE;
typedef RETURN_TYPE CONFIGRET;
#define CR_SUCCESS 0x00000000
#define CR_NO_SUCH_DEVNODE 0x0000000D
#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE
#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG
#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING
#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE
#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT
#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS
#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE
#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE
#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS
#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR
#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR
#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION
#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION
#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE
#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE
#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME
#define USB_GET_NODE_INFORMATION 258
#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
#define USB_GET_NODE_CONNECTION_NAME 261
#define USB_GET_HUB_CAPABILITIES 271
#if !defined(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)
#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
typedef enum USB_CONNECTION_STATUS {
NoDeviceConnected,
DeviceConnected,
DeviceFailedEnumeration,
DeviceGeneralFailure,
DeviceCausedOvercurrent,
DeviceNotEnoughPower,
DeviceNotEnoughBandwidth,
DeviceHubNestedTooDeeply,
DeviceInLegacyHub
} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS;
typedef enum USB_HUB_NODE {
UsbHub,
UsbMIParent
} USB_HUB_NODE;
/* Cfgmgr32.dll interface */
DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG));
DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG));
#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)
typedef struct USB_INTERFACE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
typedef struct USB_CONFIGURATION_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_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 {
ULONG ConnectionIndex;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
UCHAR CurrentConfigurationValue;
UCHAR Speed;
BOOLEAN DeviceIsHub;
USHORT DeviceAddress;
ULONG NumberOfOpenPipes;
USB_CONNECTION_STATUS ConnectionStatus;
// USB_PIPE_INFO PipeList[0];
} USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX;
typedef union _USB_PROTOCOLS {
ULONG ul;
struct {
ULONG Usb110:1;
ULONG Usb200:1;
ULONG Usb300:1;
ULONG ReservedMBZ:29;
};
} USB_PROTOCOLS, *PUSB_PROTOCOLS;
typedef union _USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS {
ULONG ul;
struct {
ULONG DeviceIsOperatingAtSuperSpeedOrHigher:1;
ULONG DeviceIsSuperSpeedCapableOrHigher:1;
ULONG ReservedMBZ:30;
};
} USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS;
typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 {
ULONG ConnectionIndex;
ULONG Length;
USB_PROTOCOLS SupportedUsbProtocols;
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)
/* winusb.dll interface */
#define SHORT_PACKET_TERMINATE 0x01
#define AUTO_CLEAR_STALL 0x02
#define PIPE_TRANSFER_TIMEOUT 0x03
#define IGNORE_SHORT_PACKETS 0x04
#define ALLOW_PARTIAL_READS 0x05
#define AUTO_FLUSH 0x06
#define RAW_IO 0x07
#define MAXIMUM_TRANSFER_SIZE 0x08
#define AUTO_SUSPEND 0x81
#define SUSPEND_DELAY 0x83
#define DEVICE_SPEED 0x01
#define LowSpeed 0x01
#define FullSpeed 0x02
#define HighSpeed 0x03
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;
#pragma pack(1)
typedef struct {
UCHAR request_type;
UCHAR request;
USHORT value;
USHORT index;
USHORT length;
} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
#pragma pack()
typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
typedef BOOL (WINAPI *WinUsb_AbortPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_ControlTransfer_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
WINUSB_SETUP_PACKET SetupPacket,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
typedef BOOL (WINAPI *WinUsb_FlushPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_Free_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
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,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
typedef BOOL (WINAPI *WinUsb_ResetPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_SetCurrentAlternateSetting_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR AlternateSetting
);
typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
ULONG PolicyType,
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,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle
);
/* /!\ These must match the ones from the official libusbk.h */
typedef enum _KUSB_FNID
{
KUSB_FNID_Init,
KUSB_FNID_Free,
KUSB_FNID_ClaimInterface,
KUSB_FNID_ReleaseInterface,
KUSB_FNID_SetAltInterface,
KUSB_FNID_GetAltInterface,
KUSB_FNID_GetDescriptor,
KUSB_FNID_ControlTransfer,
KUSB_FNID_SetPowerPolicy,
KUSB_FNID_GetPowerPolicy,
KUSB_FNID_SetConfiguration,
KUSB_FNID_GetConfiguration,
KUSB_FNID_ResetDevice,
KUSB_FNID_Initialize,
KUSB_FNID_SelectInterface,
KUSB_FNID_GetAssociatedInterface,
KUSB_FNID_Clone,
KUSB_FNID_QueryInterfaceSettings,
KUSB_FNID_QueryDeviceInformation,
KUSB_FNID_SetCurrentAlternateSetting,
KUSB_FNID_GetCurrentAlternateSetting,
KUSB_FNID_QueryPipe,
KUSB_FNID_SetPipePolicy,
KUSB_FNID_GetPipePolicy,
KUSB_FNID_ReadPipe,
KUSB_FNID_WritePipe,
KUSB_FNID_ResetPipe,
KUSB_FNID_AbortPipe,
KUSB_FNID_FlushPipe,
KUSB_FNID_IsoReadPipe,
KUSB_FNID_IsoWritePipe,
KUSB_FNID_GetCurrentFrameNumber,
KUSB_FNID_GetOverlappedResult,
KUSB_FNID_GetProperty,
KUSB_FNID_COUNT,
} KUSB_FNID;
typedef struct _KLIB_VERSION {
INT Major;
INT Minor;
INT Micro;
INT Nano;
} KLIB_VERSION;
typedef KLIB_VERSION* PKLIB_VERSION;
typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
PVOID* ProcAddress,
ULONG DriverID,
ULONG FunctionID
);
typedef VOID (WINAPI *LibK_GetVersion_t)(
PKLIB_VERSION Version
);
struct winusb_interface {
bool initialized;
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_ResetPipe_t ResetPipe;
WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting;
WinUsb_SetPipePolicy_t SetPipePolicy;
WinUsb_SetPowerPolicy_t SetPowerPolicy;
WinUsb_WritePipe_t WritePipe;
WinUsb_ResetDevice_t ResetDevice;
};
/* hid.dll interface */
#define HIDP_STATUS_SUCCESS 0x110000
typedef void* PHIDP_PREPARSED_DATA;
#pragma pack(1)
typedef struct {
ULONG Size;
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
#pragma pack()
typedef USHORT USAGE;
typedef struct {
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT NumberLinkCollectionNodes;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
} HIDP_CAPS, *PHIDP_CAPS;
typedef enum _HIDP_REPORT_TYPE {
HidP_Input,
HidP_Output,
HidP_Feature
} HIDP_REPORT_TYPE;
typedef struct _HIDP_VALUE_CAPS {
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USHORT BitField;
USHORT LinkCollection;
USAGE LinkUsage;
USAGE LinkUsagePage;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN HasNull;
UCHAR Reserved;
USHORT BitSize;
USHORT ReportCount;
USHORT Reserved2[5];
ULONG UnitsExp;
ULONG Units;
LONG LogicalMin, LogicalMax;
LONG PhysicalMin, PhysicalMax;
union {
struct {
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct {
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
} u;
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
DLL_DECLARE(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES));
DLL_DECLARE(WINAPI, VOID, HidD_GetHidGuid, (LPGUID));
DLL_DECLARE(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *));
DLL_DECLARE(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA));
DLL_DECLARE(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS));
DLL_DECLARE(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_FlushQueue, (HANDLE));
DLL_DECLARE(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA));

View File

@ -1,830 +0,0 @@
/*
* windows UsbDk backend for libusb 1.0
* Copyright © 2014 Red Hat, Inc.
* Authors:
* Dmitry Fleytman <dmitry@daynix.com>
* Pavel Gurvich <pavel@daynix.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 <config.h>
#include <windows.h>
#include <stdio.h>
#include "libusbi.h"
#include "windows_common.h"
#include "windows_nt_common.h"
#include "windows_usbdk.h"
#if !defined(STATUS_SUCCESS)
typedef LONG NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
#if !defined(STATUS_CANCELLED)
#define STATUS_CANCELLED ((NTSTATUS)0xC0000120L)
#endif
#if !defined(STATUS_REQUEST_CANCELED)
#define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L)
#endif
#if !defined(USBD_SUCCESS)
typedef 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)
#define USBD_STATUS_STALL_PID ((USBD_STATUS) 0xc0000004)
#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS) 0xc0000030)
#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS) 0xc0000a00)
#define USBD_STATUS_TIMEOUT ((USBD_STATUS) 0xc0006000)
#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000)
#endif
static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev)
{
return (struct usbdk_device_priv *)dev->os_priv;
}
static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer)
{
return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer);
}
static struct {
HMODULE module;
USBDK_GET_DEVICES_LIST GetDevicesList;
USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList;
USBDK_START_REDIRECT StartRedirect;
USBDK_STOP_REDIRECT StopRedirect;
USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor;
USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor;
USBDK_READ_PIPE ReadPipe;
USBDK_WRITE_PIPE WritePipe;
USBDK_ABORT_PIPE AbortPipe;
USBDK_RESET_PIPE ResetPipe;
USBDK_SET_ALTSETTING SetAltsetting;
USBDK_RESET_DEVICE ResetDevice;
USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle;
} usbdk_helper;
static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name)
{
FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
if (api_ptr == NULL)
usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0));
return api_ptr;
}
static void unload_usbdk_helper_dll(void)
{
if (usbdk_helper.module != NULL) {
FreeLibrary(usbdk_helper.module);
usbdk_helper.module = NULL;
}
}
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: %s", windows_error_str(0));
return LIBUSB_ERROR_NOT_FOUND;
}
usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList");
if (usbdk_helper.GetDevicesList == NULL)
goto error_unload;
usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList");
if (usbdk_helper.ReleaseDevicesList == NULL)
goto error_unload;
usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect");
if (usbdk_helper.StartRedirect == NULL)
goto error_unload;
usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect");
if (usbdk_helper.StopRedirect == NULL)
goto error_unload;
usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor");
if (usbdk_helper.GetConfigurationDescriptor == NULL)
goto error_unload;
usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor");
if (usbdk_helper.ReleaseConfigurationDescriptor == NULL)
goto error_unload;
usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe");
if (usbdk_helper.ReadPipe == NULL)
goto error_unload;
usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe");
if (usbdk_helper.WritePipe == NULL)
goto error_unload;
usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe");
if (usbdk_helper.AbortPipe == NULL)
goto error_unload;
usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe");
if (usbdk_helper.ResetPipe == NULL)
goto error_unload;
usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting");
if (usbdk_helper.SetAltsetting == NULL)
goto error_unload;
usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice");
if (usbdk_helper.ResetDevice == NULL)
goto error_unload;
usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle");
if (usbdk_helper.GetRedirectorSystemHandle == NULL)
goto error_unload;
return LIBUSB_SUCCESS;
error_unload:
FreeLibrary(usbdk_helper.module);
usbdk_helper.module = NULL;
return LIBUSB_ERROR_NOT_FOUND;
}
static int usbdk_init(struct libusb_context *ctx)
{
SC_HANDLE managerHandle;
SC_HANDLE serviceHandle;
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;
}
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();
}
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) + 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;
}
*session_id = htab_hash(dev_identity);
return LIBUSB_SUCCESS;
}
static void usbdk_release_config_descriptors(struct usbdk_device_priv *p, uint8_t count)
{
uint8_t i;
for (i = 0; i < count; i++)
usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]);
free(p->config_descriptors);
p->config_descriptors = NULL;
}
static int usbdk_cache_config_descriptors(struct libusb_context *ctx,
struct usbdk_device_priv *p, PUSB_DK_DEVICE_INFO info)
{
uint8_t i;
USB_DK_CONFIG_DESCRIPTOR_REQUEST Request;
Request.ID = info->ID;
p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
if (p->config_descriptors == NULL) {
usbi_err(ctx, "failed to allocate configuration descriptors holder");
return LIBUSB_ERROR_NO_MEM;
}
for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) {
ULONG Length;
Request.Index = i;
if (!usbdk_helper.GetConfigurationDescriptor(&Request, &p->config_descriptors[i], &Length)) {
usbi_err(ctx, "failed to retrieve configuration descriptors");
usbdk_release_config_descriptors(p, i);
return LIBUSB_ERROR_OTHER;
}
}
return LIBUSB_SUCCESS;
}
static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info)
{
struct usbdk_device_priv *p = _usbdk_device_priv(dev);
p->info = *info;
p->active_configuration = 0;
return usbdk_cache_config_descriptors(ctx, p, info);
}
static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info)
{
dev->bus_number = (uint8_t)info->FilterID;
dev->port_number = (uint8_t)info->Port;
dev->parent_dev = NULL;
// Addresses in libusb are 1-based
dev->device_address = (uint8_t)(info->Port + 1);
dev->num_configurations = info->DeviceDescriptor.bNumConfigurations;
memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
switch (info->Speed) {
case LowSpeed:
dev->speed = LIBUSB_SPEED_LOW;
break;
case FullSpeed:
dev->speed = LIBUSB_SPEED_FULL;
break;
case HighSpeed:
dev->speed = LIBUSB_SPEED_HIGH;
break;
case SuperSpeed:
dev->speed = LIBUSB_SPEED_SUPER;
break;
case NoSpeed:
default:
dev->speed = LIBUSB_SPEED_UNKNOWN;
break;
}
}
static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
{
int r = LIBUSB_SUCCESS;
ULONG i;
struct discovered_devs *discdevs = NULL;
ULONG dev_number;
PUSB_DK_DEVICE_INFO devices;
if (!usbdk_helper.GetDevicesList(&devices, &dev_number))
return LIBUSB_ERROR_OTHER;
for (i = 0; i < dev_number; i++) {
unsigned long session_id;
struct libusb_device *dev = NULL;
if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id))
continue;
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev == NULL) {
dev = usbi_alloc_device(ctx, session_id);
if (dev == NULL) {
usbi_err(ctx, "failed to allocate a new device structure");
continue;
}
usbdk_device_init(dev, &devices[i]);
if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) {
libusb_unref_device(dev);
continue;
}
}
discdevs = discovered_devs_append(*_discdevs, dev);
libusb_unref_device(dev);
if (!discdevs) {
usbi_err(ctx, "cannot append new device to list");
r = LIBUSB_ERROR_NO_MEM;
goto func_exit;
}
*_discdevs = discdevs;
}
func_exit:
usbdk_helper.ReleaseDevicesList(devices);
return r;
}
static 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);
return LIBUSB_SUCCESS;
}
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;
size_t size;
if (config_index >= dev->num_configurations)
return LIBUSB_ERROR_INVALID_PARAM;
config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index];
size = min(config_header->wTotalLength, len);
memcpy(buffer, config_header, size);
return (int)size;
}
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);
}
static int usbdk_open(struct libusb_device_handle *dev_handle)
{
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID);
if (priv->redirector_handle == INVALID_HANDLE_VALUE) {
usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed");
return LIBUSB_ERROR_OTHER;
}
priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
return LIBUSB_SUCCESS;
}
static void usbdk_close(struct libusb_device_handle *dev_handle)
{
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.StopRedirect(priv->redirector_handle))
usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed");
}
static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config)
{
*config = _usbdk_device_priv(dev_handle->dev)->active_configuration;
return LIBUSB_SUCCESS;
}
static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, int config)
{
UNUSED(dev_handle);
UNUSED(config);
return LIBUSB_SUCCESS;
}
static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int iface)
{
UNUSED(dev_handle);
UNUSED(iface);
return LIBUSB_SUCCESS;
}
static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
{
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) {
usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
return LIBUSB_SUCCESS;
}
static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int iface)
{
UNUSED(dev_handle);
UNUSED(iface);
return LIBUSB_SUCCESS;
}
static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) {
usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
return LIBUSB_SUCCESS;
}
static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
{
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.ResetDevice(priv->redirector_handle)) {
usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
return LIBUSB_SUCCESS;
}
static void usbdk_destroy_device(struct libusb_device *dev)
{
struct usbdk_device_priv* p = _usbdk_device_priv(dev);
if (p->config_descriptors != NULL)
usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations);
}
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_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);
safe_free(transfer_priv->IsochronousResultsArray);
}
}
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 = TRANSFER_CTX(transfer);
OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
TransferResult transResult;
transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
transfer_priv->request.BufferLength = transfer->length;
transfer_priv->request.TransferType = ControlTransferType;
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, overlapped);
switch (transResult) {
case TransferSuccess:
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));
return LIBUSB_ERROR_IO;
}
return LIBUSB_SUCCESS;
}
static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct libusb_context *ctx = TRANSFER_CTX(transfer);
OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
TransferResult transferRes;
transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
transfer_priv->request.BufferLength = transfer->length;
transfer_priv->request.EndpointAddress = transfer->endpoint;
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_BULK:
transfer_priv->request.TransferType = BulkTransferType;
break;
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
transfer_priv->request.TransferType = InterruptTransferType;
break;
default:
usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
}
if (IS_XFERIN(transfer))
transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
else
transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
switch (transferRes) {
case TransferSuccess:
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));
return LIBUSB_ERROR_IO;
}
return LIBUSB_SUCCESS;
}
static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct libusb_context *ctx = TRANSFER_CTX(transfer);
OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
TransferResult transferRes;
int i;
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)transfer_priv->IsochronousPacketsArray;
if (!transfer_priv->IsochronousPacketsArray) {
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)transfer_priv->IsochronousResultsArray;
if (!transfer_priv->IsochronousResultsArray) {
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;
if (IS_XFERIN(transfer))
transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
else
transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped);
switch (transferRes) {
case TransferSuccess:
windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
break;
case TransferSuccessAsync:
break;
case TransferFailure:
return LIBUSB_ERROR_IO;
}
return LIBUSB_SUCCESS;
}
static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer,
short events, int (*transfer_fn)(struct usbi_transfer *))
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct libusb_context *ctx = TRANSFER_CTX(transfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct winfd wfd;
int r;
wfd = usbi_create_fd();
if (wfd.fd < 0)
return LIBUSB_ERROR_NO_MEM;
r = usbi_add_pollfd(ctx, wfd.fd, events);
if (r) {
usbi_close(wfd.fd);
return r;
}
// Use transfer_priv to store data needed for async polling
transfer_priv->pollable_fd = wfd;
transfer_priv->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;
}
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:
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
events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
transfer_fn = usbdk_do_bulk_transfer;
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
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 = 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;
}
static int usbdk_cancel_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
// Control transfers cancelled by IoCancelXXX() API
// No special treatment needed
return LIBUSB_SUCCESS;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return usbdk_abort_transfers(itransfer);
default:
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
}
}
static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
{
itransfer->transferred += io_size;
return LIBUSB_TRANSFER_COMPLETED;
}
static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer)
{
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)
{
if (USBD_SUCCESS(UsbdStatus))
return NO_ERROR;
switch (UsbdStatus) {
case USBD_STATUS_TIMEOUT:
return ERROR_SEM_TIMEOUT;
case USBD_STATUS_CANCELED:
return ERROR_OPERATION_ABORTED;
default:
return ERROR_GEN_FAILURE;
}
}
static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size)
{
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct winfd *pollable_fd = &transfer_priv->pollable_fd;
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 = &transfer->iso_packet_desc[i];
switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
case STATUS_SUCCESS:
case STATUS_CANCELLED:
case STATUS_REQUEST_CANCELED:
lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
break;
default:
lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
break;
}
lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
}
}
*io_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred;
*io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
} else {
*io_result = GetLastError();
}
}
const struct windows_backend usbdk_backend = {
usbdk_init,
usbdk_exit,
usbdk_get_device_list,
usbdk_open,
usbdk_close,
usbdk_get_device_descriptor,
usbdk_get_active_config_descriptor,
usbdk_get_config_descriptor,
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,
usbdk_destroy_device,
usbdk_submit_transfer,
usbdk_cancel_transfer,
usbdk_clear_transfer_priv,
usbdk_copy_transfer_data,
usbdk_get_transfer_fd,
usbdk_get_overlapped_result,
};

View File

@ -1,103 +0,0 @@
/*
* windows UsbDk backend for libusb 1.0
* Copyright © 2014 Red Hat, Inc.
* Authors:
* Dmitry Fleytman <dmitry@daynix.com>
* Pavel Gurvich <pavel@daynix.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
*/
#pragma once
#include "windows_nt_common.h"
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 enum {
TransferFailure = 0,
TransferSuccess,
TransferSuccessAsync
} TransferResult;
typedef enum {
NoSpeed = 0,
LowSpeed,
FullSpeed,
HighSpeed,
SuperSpeed
} USB_DK_DEVICE_SPEED;
typedef enum {
ControlTransferType,
BulkTransferType,
InterruptTransferType,
IsochronousTransferType
} USB_DK_TRANSFER_TYPE;
typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST)(
PUSB_DK_DEVICE_INFO *DeviceInfo,
PULONG DeviceNumber
);
typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST)(
PUSB_DK_DEVICE_INFO DeviceInfo
);
typedef HANDLE (__cdecl *USBDK_START_REDIRECT)(
PUSB_DK_DEVICE_ID DeviceId
);
typedef BOOL (__cdecl *USBDK_STOP_REDIRECT)(
HANDLE DeviceHandle
);
typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR)(
PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request,
PUSB_CONFIGURATION_DESCRIPTOR *Descriptor,
PULONG Length
);
typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)(
PUSB_CONFIGURATION_DESCRIPTOR Descriptor
);
typedef TransferResult (__cdecl *USBDK_WRITE_PIPE)(
HANDLE DeviceHandle,
PUSB_DK_TRANSFER_REQUEST Request,
LPOVERLAPPED lpOverlapped
);
typedef TransferResult (__cdecl *USBDK_READ_PIPE)(
HANDLE DeviceHandle,
PUSB_DK_TRANSFER_REQUEST Request,
LPOVERLAPPED lpOverlapped
);
typedef BOOL (__cdecl *USBDK_ABORT_PIPE)(
HANDLE DeviceHandle,
ULONG64 PipeAddress
);
typedef BOOL (__cdecl *USBDK_RESET_PIPE)(
HANDLE DeviceHandle,
ULONG64 PipeAddress
);
typedef BOOL (__cdecl *USBDK_SET_ALTSETTING)(
HANDLE DeviceHandle,
ULONG64 InterfaceIdx,
ULONG64 AltSettingIdx
);
typedef BOOL (__cdecl *USBDK_RESET_DEVICE)(
HANDLE DeviceHandle
);
typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)(
HANDLE DeviceHandle
);

File diff suppressed because it is too large Load Diff

View File

@ -1,781 +0,0 @@
/*
* Windows backend for libusb 1.0
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "windows_common.h"
#include "windows_nt_common.h"
#if defined(_MSC_VER)
// disable /W4 MSVC warnings that are benign
#pragma warning(disable:4100) // unreferenced formal parameter
#pragma warning(disable:4127) // conditional expression is constant
#pragma warning(disable:4201) // nameless struct/union
#pragma warning(disable:4214) // bit field types other than int
#pragma warning(disable:4996) // deprecated API calls
#pragma warning(disable:28159) // more deprecated API calls
#endif
// Missing from MSVC6 setupapi.h
#ifndef SPDRP_ADDRESS
#define SPDRP_ADDRESS 28
#endif
#ifndef SPDRP_INSTALL_STATE
#define SPDRP_INSTALL_STATE 34
#endif
#define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_STRING_LENGTH 128
#define MAX_HID_REPORT_SIZE 1024
#define MAX_HID_DESCRIPTOR_SIZE 256
#define MAX_GUID_STRING_LENGTH 40
#define MAX_PATH_LENGTH 128
#define MAX_KEY_LENGTH 256
#define LIST_SEPARATOR ';'
// Handle code for HID interface that have been claimed ("dibs")
#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5)
// Additional return code for HID operations that completed synchronously
#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1)
// http://msdn.microsoft.com/en-us/library/ff545978.aspx
// http://msdn.microsoft.com/en-us/library/ff545972.aspx
// http://msdn.microsoft.com/en-us/library/ff545982.aspx
#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
#ifndef GUID_DEVINTERFACE_USB_DEVICE
const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
#endif
#ifndef GUID_DEVINTERFACE_USB_HUB
const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}};
#endif
#ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER
const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}};
#endif
/*
* Multiple USB API backend support
*/
#define USB_API_UNSUPPORTED 0
#define USB_API_HUB 1
#define USB_API_COMPOSITE 2
#define USB_API_WINUSBX 3
#define USB_API_HID 4
#define USB_API_MAX 5
// 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
#define SUB_API_NOTSET -1
#define SUB_API_LIBUSBK 0
#define SUB_API_LIBUSB0 1
#define SUB_API_WINUSB 2
#define SUB_API_MAX 3
struct windows_usb_api_backend {
const uint8_t id;
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)(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);
int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
int (*clear_halt)(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
int (*reset_device)(int sub_api, struct libusb_device_handle *dev_handle);
int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*abort_control)(int sub_api, struct usbi_transfer *itransfer);
int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer);
int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
};
extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
#define PRINT_UNSUPPORTED_API(fname) \
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
* with inline pseudo constructors/destructors
*/
// TODO (v2+): move hid desc to libusb.h?
struct libusb_hid_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bClassDescriptorType;
uint16_t wClassDescriptorLength;
};
#define LIBUSB_DT_HID_SIZE 9
#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \
+ LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE)
#define HID_MAX_REPORT_SIZE 1024
#define HID_IN_EP 0x81
#define HID_OUT_EP 0x02
#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F)
#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5))
#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN)
#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type))
#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_IN_CTL_CODE(id) \
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define HID_OUT_CTL_CODE(id) \
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100)
#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101)
enum libusb_hid_request_type {
HID_REQ_GET_REPORT = 0x01,
HID_REQ_GET_IDLE = 0x02,
HID_REQ_GET_PROTOCOL = 0x03,
HID_REQ_SET_REPORT = 0x09,
HID_REQ_SET_IDLE = 0x0A,
HID_REQ_SET_PROTOCOL = 0x0B
};
enum libusb_hid_report_type {
HID_REPORT_TYPE_INPUT = 0x01,
HID_REPORT_TYPE_OUTPUT = 0x02,
HID_REPORT_TYPE_FEATURE = 0x03
};
struct hid_device_priv {
uint16_t vid;
uint16_t pid;
uint8_t config;
uint8_t nb_interfaces;
bool uses_report_ids[3]; // input, ouptput, feature
uint16_t input_report_size;
uint16_t output_report_size;
uint16_t feature_report_size;
uint16_t usage;
uint16_t usagePage;
WCHAR string[3][MAX_USB_STRING_LENGTH];
uint8_t string_index[3]; // man, prod, ser
};
static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev)
{
return (struct winusb_device_priv *)dev->os_priv;
}
static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev)
{
struct winusb_device_priv *p = _device_priv(dev);
int i;
p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->sub_api = SUB_API_NOTSET;
for (i = 0; i < USB_MAXINTERFACES; i++) {
p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->usb_interface[i].sub_api = SUB_API_NOTSET;
}
return p;
}
static inline void winusb_device_priv_release(struct libusb_device *dev)
{
struct winusb_device_priv *p = _device_priv(dev);
int i;
free(p->dev_id);
free(p->path);
if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
for (i = 0; i < dev->num_configurations; i++)
free(p->config_descriptor[i]);
}
free(p->config_descriptor);
free(p->hid);
for (i = 0; i < USB_MAXINTERFACES; i++) {
free(p->usb_interface[i].path);
free(p->usb_interface[i].endpoint);
}
}
static inline struct winusb_device_handle_priv *_device_handle_priv(
struct libusb_device_handle *handle)
{
return (struct winusb_device_handle_priv *)handle->os_priv;
}
// used to match a device driver (including filter drivers) against a supported API
struct driver_lookup {
char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names
const DWORD reg_prop; // SPDRP registry key to use to retrieve list
const char* designation; // internal designation (for debug output)
};
/*
* Windows DDK API definitions. Most of it copied from MinGW's includes
*/
typedef DWORD DEVNODE, DEVINST;
typedef DEVNODE *PDEVNODE, *PDEVINST;
typedef DWORD RETURN_TYPE;
typedef RETURN_TYPE CONFIGRET;
#define CR_SUCCESS 0x00000000
/* 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));
/* 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));
/* OLE32 dependency */
DLL_DECLARE_HANDLE(OLE32);
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID));
/* SetupAPI dependencies */
DLL_DECLARE_HANDLE(SetupAPI);
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA,
LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA,
PCSTR, DWORD, PDWORD));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA,
PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD));
#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
#endif
#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX
#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274
#endif
#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX_V2
#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279
#endif
#ifndef FILE_DEVICE_USB
#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN
#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,
DeviceConnected,
DeviceFailedEnumeration,
DeviceGeneralFailure,
DeviceCausedOvercurrent,
DeviceNotEnoughPower,
DeviceNotEnoughBandwidth,
DeviceHubNestedTooDeeply,
DeviceInLegacyHub
} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS;
typedef enum USB_HUB_NODE {
UsbHub,
UsbMIParent
} USB_HUB_NODE;
// Most of the structures below need to be packed
#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;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
typedef struct _USB_NODE_CONNECTION_INFORMATION_EX {
ULONG ConnectionIndex;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
UCHAR CurrentConfigurationValue;
UCHAR Speed;
BOOLEAN DeviceIsHub;
USHORT DeviceAddress;
ULONG NumberOfOpenPipes;
USB_CONNECTION_STATUS ConnectionStatus;
// USB_PIPE_INFO PipeList[0];
} USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX;
typedef union _USB_PROTOCOLS {
ULONG ul;
struct {
ULONG Usb110:1;
ULONG Usb200:1;
ULONG Usb300:1;
ULONG ReservedMBZ:29;
};
} USB_PROTOCOLS, *PUSB_PROTOCOLS;
typedef union _USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS {
ULONG ul;
struct {
ULONG DeviceIsOperatingAtSuperSpeedOrHigher:1;
ULONG DeviceIsSuperSpeedCapableOrHigher:1;
ULONG ReservedMBZ:30;
};
} USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS;
typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 {
ULONG ConnectionIndex;
ULONG Length;
USB_PROTOCOLS SupportedUsbProtocols;
USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags;
} USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2;
#include <poppack.h>
/* winusb.dll interface */
/* pipe policies */
#define SHORT_PACKET_TERMINATE 0x01
#define AUTO_CLEAR_STALL 0x02
#define PIPE_TRANSFER_TIMEOUT 0x03
#define IGNORE_SHORT_PACKETS 0x04
#define ALLOW_PARTIAL_READS 0x05
#define AUTO_FLUSH 0x06
#define RAW_IO 0x07
#define MAXIMUM_TRANSFER_SIZE 0x08
/* libusbK */
#define ISO_ALWAYS_START_ASAP 0x21
typedef enum _USBD_PIPE_TYPE {
UsbdPipeTypeControl,
UsbdPipeTypeIsochronous,
UsbdPipeTypeBulk,
UsbdPipeTypeInterrupt
} USBD_PIPE_TYPE;
#include <pshpack1.h>
typedef struct _WINUSB_SETUP_PACKET {
UCHAR RequestType;
UCHAR Request;
USHORT Value;
USHORT Index;
USHORT Length;
} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
#include <poppack.h>
typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
typedef BOOL (WINAPI *WinUsb_AbortPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_ControlTransfer_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
WINUSB_SETUP_PACKET SetupPacket,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
typedef BOOL (WINAPI *WinUsb_FlushPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_Free_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR AssociatedInterfaceIndex,
PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_Initialize_t)(
HANDLE DeviceHandle,
PWINUSB_INTERFACE_HANDLE InterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
PUCHAR Buffer,
ULONG BufferLength,
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
);
typedef BOOL (WINAPI *WinUsb_SetCurrentAlternateSetting_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR AlternateSetting
);
typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
ULONG PolicyType,
ULONG ValueLength,
PVOID Value
);
typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
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 */
typedef enum _KUSB_FNID {
KUSB_FNID_Init,
KUSB_FNID_Free,
KUSB_FNID_ClaimInterface,
KUSB_FNID_ReleaseInterface,
KUSB_FNID_SetAltInterface,
KUSB_FNID_GetAltInterface,
KUSB_FNID_GetDescriptor,
KUSB_FNID_ControlTransfer,
KUSB_FNID_SetPowerPolicy,
KUSB_FNID_GetPowerPolicy,
KUSB_FNID_SetConfiguration,
KUSB_FNID_GetConfiguration,
KUSB_FNID_ResetDevice,
KUSB_FNID_Initialize,
KUSB_FNID_SelectInterface,
KUSB_FNID_GetAssociatedInterface,
KUSB_FNID_Clone,
KUSB_FNID_QueryInterfaceSettings,
KUSB_FNID_QueryDeviceInformation,
KUSB_FNID_SetCurrentAlternateSetting,
KUSB_FNID_GetCurrentAlternateSetting,
KUSB_FNID_QueryPipe,
KUSB_FNID_SetPipePolicy,
KUSB_FNID_GetPipePolicy,
KUSB_FNID_ReadPipe,
KUSB_FNID_WritePipe,
KUSB_FNID_ResetPipe,
KUSB_FNID_AbortPipe,
KUSB_FNID_FlushPipe,
KUSB_FNID_IsoReadPipe,
KUSB_FNID_IsoWritePipe,
KUSB_FNID_GetCurrentFrameNumber,
KUSB_FNID_GetOverlappedResult,
KUSB_FNID_GetProperty,
KUSB_FNID_COUNT,
} KUSB_FNID;
typedef struct _KLIB_VERSION {
INT Major;
INT Minor;
INT Micro;
INT Nano;
} KLIB_VERSION, *PKLIB_VERSION;
typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
PVOID *ProcAddress,
ULONG DriverID,
ULONG FunctionID
);
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_Initialize_t Initialize;
WinUsb_ReadPipe_t ReadPipe;
WinUsb_ResetDevice_t ResetDevice;
WinUsb_ResetPipe_t ResetPipe;
WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting;
WinUsb_SetPipePolicy_t SetPipePolicy;
WinUsb_WritePipe_t WritePipe;
// 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 */
#define HIDP_STATUS_SUCCESS 0x110000
typedef void * PHIDP_PREPARSED_DATA;
#include <pshpack1.h>
typedef struct _HIDD_ATTIRBUTES {
ULONG Size;
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
#include <poppack.h>
typedef USHORT USAGE;
typedef struct _HIDP_CAPS {
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT NumberLinkCollectionNodes;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
} HIDP_CAPS, *PHIDP_CAPS;
typedef enum _HIDP_REPORT_TYPE {
HidP_Input,
HidP_Output,
HidP_Feature
} HIDP_REPORT_TYPE;
typedef struct _HIDP_VALUE_CAPS {
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USHORT BitField;
USHORT LinkCollection;
USAGE LinkUsage;
USAGE LinkUsagePage;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN HasNull;
UCHAR Reserved;
USHORT BitSize;
USHORT ReportCount;
USHORT Reserved2[5];
ULONG UnitsExp;
ULONG Units;
LONG LogicalMin, LogicalMax;
LONG PhysicalMin, PhysicalMax;
union {
struct {
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct {
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
} u;
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
DLL_DECLARE_HANDLE(hid);
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_GetPhysicalDescriptor, (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));

View File

@ -1,233 +0,0 @@
/*
* libusb strerror code
* Copyright © 2013 Hans de Goede <hdegoede@redhat.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 <config.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#if defined(HAVE_STRINGS_H)
#include <strings.h>
#endif
#include "libusbi.h"
#if defined(_MSC_VER)
#define strncasecmp _strnicmp
#endif
static size_t usbi_locale = 0;
/** \ingroup libusb_misc
* 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/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>
* Eg. for Chinese, you would add "zh" so that:
* \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode
* becomes:
* \code... usbi_locale_supported[] = { "en", "nl", "fr", "zh" };\endcode </li>
* <li> Copy the <tt>{ / * English (en) * / ... }</tt> section and add it at the end of \c usbi_localized_errors<br>
* Eg. for Chinese, the last section of \c usbi_localized_errors could look like:
* \code
* }, { / * Chinese (zh) * /
* "Success",
* ...
* "Other error",
* }
* };\endcode </li>
* <li> Translate each of the English messages from the section you copied into your language </li>
* <li> Save the file (in UTF-8 format) and send it to \c libusb-devel\@lists.sourceforge.net </li>
* </ol>
*/
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",
"Input/Output Error",
"Invalid parameter",
"Access denied (insufficient permissions)",
"No such device (it may have been disconnected)",
"Entity not found",
"Resource busy",
"Operation timed out",
"Overflow",
"Pipe error",
"System call interrupted (perhaps due to signal)",
"Insufficient memory",
"Operation not supported or unimplemented on this platform",
"Other error",
}, { /* Dutch (nl) */
"Gelukt",
"Invoer-/uitvoerfout",
"Ongeldig argument",
"Toegang geweigerd (onvoldoende toegangsrechten)",
"Apparaat bestaat niet (verbinding met apparaat verbroken?)",
"Niet gevonden",
"Apparaat of hulpbron is bezig",
"Bewerking verlopen",
"Waarde is te groot",
"Gebroken pijp",
"Onderbroken systeemaanroep",
"Onvoldoende geheugen beschikbaar",
"Bewerking wordt niet ondersteund",
"Andere fout",
}, { /* French (fr) */
"Succès",
"Erreur d'entrée/sortie",
"Paramètre invalide",
"Accès refusé (permissions insuffisantes)",
"Périphérique introuvable (peut-être déconnecté)",
"Elément introuvable",
"Resource déjà occupée",
"Operation expirée",
"Débordement",
"Erreur de pipe",
"Appel système abandonné (peut-être à cause dun signal)",
"Mémoire insuffisante",
"Opération non supportée or non implémentée sur cette plateforme",
"Autre erreur",
}, { /* Russian (ru) */
"Успех",
"Ошибка ввода/вывода",
"Неверный параметр",
"Доступ запрещён (не хватает прав)",
"Устройство отсутствует (возможно, оно было отсоединено)",
"Элемент не найден",
"Ресурс занят",
"Истекло время ожидания операции",
"Переполнение",
"Ошибка канала",
"Системный вызов прерван (возможно, сигналом)",
"Память исчерпана",
"Операция не поддерживается данной платформой",
"Неизвестная ошибка"
}, { /* 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",
}
};
/** \ingroup libusb_misc
* Set the language, and only the language, not the encoding! used for
* translatable libusb messages.
*
* This takes a locale string in the default setlocale format: lang[-region]
* or lang[_country_region][.codeset]. Only the lang part of the string is
* used, and only 2 letter ISO 639-1 codes are accepted for it, such as "de".
* The optional region, country_region or codeset parts are ignored. This
* means that functions which return translatable strings will NOT honor the
* specified encoding.
* All strings returned are encoded as UTF-8 strings.
*
* If libusb_setlocale() is not called, all messages will be in English.
*
* The following functions return translatable strings: libusb_strerror().
* Note that the libusb log messages controlled through libusb_set_debug()
* are not translated, they are always in English.
*
* For POSIX UTF-8 environments if you want libusb to follow the standard
* locale settings, call libusb_setlocale(setlocale(LC_MESSAGES, NULL)),
* after your app has done its locale setup.
*
* \param locale locale-string in the form of lang[_country_region][.codeset]
* or lang[-region], where lang is a 2 letter ISO 639-1 code
* \returns LIBUSB_SUCCESS on success
* \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements
* \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported
* \returns a LIBUSB_ERROR code on other errors
*/
int API_EXPORTED libusb_setlocale(const char *locale)
{
size_t i;
if ( (locale == NULL) || (strlen(locale) < 2)
|| ((strlen(locale) > 2) && (locale[2] != '-') && (locale[2] != '_') && (locale[2] != '.')) )
return LIBUSB_ERROR_INVALID_PARAM;
for (i=0; i<ARRAYSIZE(usbi_locale_supported); i++) {
if (strncasecmp(usbi_locale_supported[i], locale, 2) == 0)
break;
}
if (i >= ARRAYSIZE(usbi_locale_supported)) {
return LIBUSB_ERROR_NOT_FOUND;
}
usbi_locale = i;
return LIBUSB_SUCCESS;
}
/** \ingroup libusb_misc
* Returns a constant string with a short description of the given error code,
* this description is intended for displaying to the end user and will be in
* the language set by libusb_setlocale().
*
* The returned string is encoded in UTF-8.
*
* The messages always start with a capital letter and end without any dot.
* The caller must not free() the returned string.
*
* \param errcode the error code whose description is desired
* \returns a short description of the error code in UTF-8 encoding
*/
DEFAULT_VISIBILITY const char* LIBUSB_CALL libusb_strerror(enum libusb_error errcode)
{
int errcode_index = -errcode;
if ((errcode_index < 0) || (errcode_index >= LIBUSB_ERROR_COUNT)) {
/* "Other Error", which should always be our last message, is returned */
errcode_index = LIBUSB_ERROR_COUNT - 1;
}
return usbi_localized_errors[usbi_locale][errcode_index];
}

View File

@ -1,327 +0,0 @@
/*
* Synchronous I/O functions for libusb
* Copyright © 2007-2008 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 <config.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "libusbi.h"
/**
* @defgroup libusb_syncio Synchronous device I/O
*
* This page documents libusb's synchronous (blocking) API for USB device I/O.
* This interface is easy to use but has some limitations. More advanced users
* may wish to consider using the \ref libusb_asyncio "asynchronous I/O API" instead.
*/
static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer)
{
int *completed = transfer->user_data;
*completed = 1;
usbi_dbg("actual_length=%d", transfer->actual_length);
/* caller interprets result and frees transfer */
}
static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer)
{
int r, *completed = transfer->user_data;
struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle);
while (!*completed) {
r = libusb_handle_events_completed(ctx, completed);
if (r < 0) {
if (r == LIBUSB_ERROR_INTERRUPTED)
continue;
usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying",
libusb_error_name(r));
libusb_cancel_transfer(transfer);
continue;
}
}
}
/** \ingroup libusb_syncio
* Perform a USB control transfer.
*
* The direction of the transfer is inferred from the bmRequestType field of
* the setup packet.
*
* The wValue, wIndex and wLength fields values should be given in host-endian
* byte order.
*
* \param dev_handle a handle for the device to communicate with
* \param bmRequestType the request type field for the setup packet
* \param bRequest the request field for the setup packet
* \param wValue the value field for the setup packet
* \param wIndex the index field for the setup packet
* \param data a suitably-sized data buffer for either input or output
* (depending on direction bits within bmRequestType)
* \param wLength the length field for the setup packet. The data buffer should
* be at least this size.
* \param timeout timeout (in millseconds) that this function should wait
* before giving up due to no response being received. For an unlimited
* timeout, use value 0.
* \returns on success, the number of bytes actually transferred
* \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out
* \returns LIBUSB_ERROR_PIPE if the control request was not supported by the
* device
* \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns LIBUSB_ERROR_BUSY if called from event handling context
* \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
* the operating system and/or hardware can support
* \returns another LIBUSB_ERROR code on other failures
*/
int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char *data, uint16_t wLength, unsigned int timeout)
{
struct libusb_transfer *transfer;
unsigned char *buffer;
int completed = 0;
int r;
if (usbi_handling_events(HANDLE_CTX(dev_handle)))
return LIBUSB_ERROR_BUSY;
transfer = libusb_alloc_transfer(0);
if (!transfer)
return LIBUSB_ERROR_NO_MEM;
buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
if (!buffer) {
libusb_free_transfer(transfer);
return LIBUSB_ERROR_NO_MEM;
}
libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex,
wLength);
if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
libusb_fill_control_transfer(transfer, dev_handle, buffer,
sync_transfer_cb, &completed, timeout);
transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER;
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
return r;
}
sync_transfer_wait_for_completion(transfer);
if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
memcpy(data, libusb_control_transfer_get_data(transfer),
transfer->actual_length);
switch (transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
r = transfer->actual_length;
break;
case LIBUSB_TRANSFER_TIMED_OUT:
r = LIBUSB_ERROR_TIMEOUT;
break;
case LIBUSB_TRANSFER_STALL:
r = LIBUSB_ERROR_PIPE;
break;
case LIBUSB_TRANSFER_NO_DEVICE:
r = LIBUSB_ERROR_NO_DEVICE;
break;
case LIBUSB_TRANSFER_OVERFLOW:
r = LIBUSB_ERROR_OVERFLOW;
break;
case LIBUSB_TRANSFER_ERROR:
case LIBUSB_TRANSFER_CANCELLED:
r = LIBUSB_ERROR_IO;
break;
default:
usbi_warn(HANDLE_CTX(dev_handle),
"unrecognised status code %d", transfer->status);
r = LIBUSB_ERROR_OTHER;
}
libusb_free_transfer(transfer);
return r;
}
static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *buffer, int length,
int *transferred, unsigned int timeout, unsigned char type)
{
struct libusb_transfer *transfer;
int completed = 0;
int r;
if (usbi_handling_events(HANDLE_CTX(dev_handle)))
return LIBUSB_ERROR_BUSY;
transfer = libusb_alloc_transfer(0);
if (!transfer)
return LIBUSB_ERROR_NO_MEM;
libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
sync_transfer_cb, &completed, timeout);
transfer->type = type;
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
return r;
}
sync_transfer_wait_for_completion(transfer);
if (transferred)
*transferred = transfer->actual_length;
switch (transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
r = 0;
break;
case LIBUSB_TRANSFER_TIMED_OUT:
r = LIBUSB_ERROR_TIMEOUT;
break;
case LIBUSB_TRANSFER_STALL:
r = LIBUSB_ERROR_PIPE;
break;
case LIBUSB_TRANSFER_OVERFLOW:
r = LIBUSB_ERROR_OVERFLOW;
break;
case LIBUSB_TRANSFER_NO_DEVICE:
r = LIBUSB_ERROR_NO_DEVICE;
break;
case LIBUSB_TRANSFER_ERROR:
case LIBUSB_TRANSFER_CANCELLED:
r = LIBUSB_ERROR_IO;
break;
default:
usbi_warn(HANDLE_CTX(dev_handle),
"unrecognised status code %d", transfer->status);
r = LIBUSB_ERROR_OTHER;
}
libusb_free_transfer(transfer);
return r;
}
/** \ingroup libusb_syncio
* Perform a USB bulk transfer. The direction of the transfer is inferred from
* the direction bits of the endpoint address.
*
* For bulk reads, the <tt>length</tt> field indicates the maximum length of
* data you are expecting to receive. If less data arrives than expected,
* this function will return that data, so be sure to check the
* <tt>transferred</tt> output parameter.
*
* You should also check the <tt>transferred</tt> parameter for bulk writes.
* Not all of the data may have been written.
*
* Also check <tt>transferred</tt> when dealing with a timeout error code.
* libusb may have to split your transfer into a number of chunks to satisfy
* underlying O/S requirements, meaning that the timeout may expire after
* the first few chunks have completed. libusb is careful not to lose any data
* that may have been transferred; do not assume that timeout conditions
* indicate a complete lack of I/O.
*
* \param dev_handle a handle for the device to communicate with
* \param endpoint the address of a valid endpoint to communicate with
* \param data a suitably-sized data buffer for either input or output
* (depending on endpoint)
* \param length for bulk writes, the number of bytes from data to be sent. for
* bulk reads, the maximum number of bytes to receive into the data buffer.
* \param transferred output location for the number of bytes actually
* transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
* it is legal to pass a NULL pointer if you do not wish to receive this
* information.
* \param timeout timeout (in millseconds) that this function should wait
* before giving up due to no response being received. For an unlimited
* timeout, use value 0.
*
* \returns 0 on success (and populates <tt>transferred</tt>)
* \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
* <tt>transferred</tt>)
* \returns LIBUSB_ERROR_PIPE if the endpoint halted
* \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
* \ref libusb_packetoverflow
* \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns LIBUSB_ERROR_BUSY if called from event handling context
* \returns another LIBUSB_ERROR code on other failures
*/
int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *data, int length, int *transferred,
unsigned int timeout)
{
return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK);
}
/** \ingroup libusb_syncio
* Perform a USB interrupt transfer. The direction of the transfer is inferred
* from the direction bits of the endpoint address.
*
* For interrupt reads, the <tt>length</tt> field indicates the maximum length
* of data you are expecting to receive. If less data arrives than expected,
* this function will return that data, so be sure to check the
* <tt>transferred</tt> output parameter.
*
* You should also check the <tt>transferred</tt> parameter for interrupt
* writes. Not all of the data may have been written.
*
* Also check <tt>transferred</tt> when dealing with a timeout error code.
* libusb may have to split your transfer into a number of chunks to satisfy
* underlying O/S requirements, meaning that the timeout may expire after
* the first few chunks have completed. libusb is careful not to lose any data
* that may have been transferred; do not assume that timeout conditions
* indicate a complete lack of I/O.
*
* The default endpoint bInterval value is used as the polling interval.
*
* \param dev_handle a handle for the device to communicate with
* \param endpoint the address of a valid endpoint to communicate with
* \param data a suitably-sized data buffer for either input or output
* (depending on endpoint)
* \param length for bulk writes, the number of bytes from data to be sent. for
* bulk reads, the maximum number of bytes to receive into the data buffer.
* \param transferred output location for the number of bytes actually
* transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
* it is legal to pass a NULL pointer if you do not wish to receive this
* information.
* \param timeout timeout (in millseconds) that this function should wait
* before giving up due to no response being received. For an unlimited
* timeout, use value 0.
*
* \returns 0 on success (and populates <tt>transferred</tt>)
* \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out
* \returns LIBUSB_ERROR_PIPE if the endpoint halted
* \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
* \ref libusb_packetoverflow
* \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns LIBUSB_ERROR_BUSY if called from event handling context
* \returns another LIBUSB_ERROR code on other error
*/
int API_EXPORTED libusb_interrupt_transfer(
struct libusb_device_handle *dev_handle, unsigned char endpoint,
unsigned char *data, int length, int *transferred, unsigned int timeout)
{
return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
}

View File

@ -1,18 +0,0 @@
/* This file is parsed by m4 and windres and RC.EXE so please keep it simple. */
#include "version_nano.h"
#ifndef LIBUSB_MAJOR
#define LIBUSB_MAJOR 1
#endif
#ifndef LIBUSB_MINOR
#define LIBUSB_MINOR 0
#endif
#ifndef LIBUSB_MICRO
#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 "-rc1"
#endif

View File

@ -1 +0,0 @@
#define LIBUSB_NANO 11367

View File

@ -1,51 +0,0 @@
/* config.h. Manual config for MSVC. */
#ifndef _MSC_VER
#warn "msvc/config.h shouldn't be included for your development environment."
#error "Please make sure the msvc/ directory is removed from your build path."
#endif
/* Visual Studio 2015 and later defines timespec */
#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)
/* Disable: warning C4996: 'GetVersionA': was declared deprecated */
#pragma warning(disable:4996)
#if defined(_PREFAST_)
/* Disable "Banned API" errors when using the MS's WDK OACR/Prefast */
#pragma warning(disable:28719)
/* Disable "The function 'InitializeCriticalSection' must be called from within a try/except block" */
#pragma warning(disable:28125)
#endif
/* Default visibility */
#define DEFAULT_VISIBILITY /**/
/* Enable global message logging */
#define ENABLE_LOGGING 1
/* Uncomment to start with debug message logging enabled */
// #define ENABLE_DEBUG_LOGGING 1
/* Uncomment to enabling logging to system log */
// #define USE_SYSTEM_LOGGING_FACILITY
/* type of second poll() argument */
#define POLL_NFDS_TYPE unsigned int
/* Windows/WinCE backend */
#if defined(_WIN32_WCE)
#define OS_WINCE 1
#define HAVE_MISSING_H
#else
#define OS_WINDOWS 1
#define HAVE_SYS_TYPES_H 1
#endif

View File

@ -1,39 +0,0 @@
#!/bin/bash
# Warnings enabled
CFLAGS="-Wall -Wextra"
CFLAGS+=" -Wbad-function-cast"
#CFLAGS+=" -Wcast-align"
CFLAGS+=" -Wchar-subscripts"
CFLAGS+=" -Wempty-body"
CFLAGS+=" -Wformat"
CFLAGS+=" -Wformat-security"
CFLAGS+=" -Winit-self"
CFLAGS+=" -Winline"
CFLAGS+=" -Wmissing-declarations"
CFLAGS+=" -Wmissing-include-dirs"
CFLAGS+=" -Wmissing-prototypes"
CFLAGS+=" -Wnested-externs"
CFLAGS+=" -Wold-style-definition"
CFLAGS+=" -Wpointer-arith"
CFLAGS+=" -Wredundant-decls"
CFLAGS+=" -Wshadow"
CFLAGS+=" -Wstrict-prototypes"
CFLAGS+=" -Wswitch-enum"
CFLAGS+=" -Wundef"
CFLAGS+=" -Wuninitialized"
CFLAGS+=" -Wunused"
CFLAGS+=" -Wwrite-strings"
# warnings disabled on purpose
CFLAGS+=" -Wno-unused-parameter"
CFLAGS+=" -Wno-unused-function"
CFLAGS+=" -Wno-deprecated-declarations"
# should be removed and the code fixed
CFLAGS+=" -Wno-incompatible-pointer-types-discards-qualifiers"
export CFLAGS
./autogen.sh "$@"

View File

@ -33,7 +33,7 @@
<AdditionalIncludeDirectories>$(ExternalsDir)imgui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)liblzma\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)libpng;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)libusb\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)libusb\libusb\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)LZO;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)mGBA\mgba\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)miniupnpc\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@ -67,7 +67,7 @@
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<!--The replacement for the old atomic shared_ptr functions was added in C++20, so we can't use it yet-->
<PreprocessorDefinitions>_SILENCE_CXX20_OLD_SHARED_PTR_ATOMIC_SUPPORT_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_UPNP;USE_USBDK;__LIBUSB__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_UPNP;__LIBUSB__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_ANALYTICS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_DISCORD_PRESENCE;%(PreprocessorDefinitions)</PreprocessorDefinitions>