update to libusb v1.0.26
moves libusb from vendored to submodule
This commit is contained in:
parent
3ed9d5a3c7
commit
70507c2237
|
@ -13,3 +13,6 @@
|
||||||
url = https://github.com/dolphin-emu/ext-win-ffmpeg.git
|
url = https://github.com/dolphin-emu/ext-win-ffmpeg.git
|
||||||
branch = master
|
branch = master
|
||||||
shallow = true
|
shallow = true
|
||||||
|
[submodule "libusb"]
|
||||||
|
path = Externals/libusb/libusb
|
||||||
|
url = https://github.com/libusb/libusb.git
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -1,4 +0,0 @@
|
||||||
brew 'automake'
|
|
||||||
brew 'libtool'
|
|
||||||
brew 'autoconf'
|
|
||||||
brew 'm4'
|
|
|
@ -1,79 +1,74 @@
|
||||||
add_library(usb STATIC EXCLUDE_FROM_ALL
|
add_library(usb STATIC EXCLUDE_FROM_ALL
|
||||||
libusb/core.c
|
libusb/libusb/core.c
|
||||||
libusb/core.c
|
libusb/libusb/descriptor.c
|
||||||
libusb/descriptor.c
|
libusb/libusb/hotplug.c
|
||||||
libusb/hotplug.c
|
libusb/libusb/io.c
|
||||||
libusb/io.c
|
libusb/libusb/strerror.c
|
||||||
libusb/strerror.c
|
libusb/libusb/sync.c
|
||||||
libusb/sync.c
|
|
||||||
)
|
)
|
||||||
set_target_properties(usb PROPERTIES VERSION 1.0.19)
|
set_target_properties(usb PROPERTIES VERSION 1.0.26)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_include_directories(usb BEFORE PUBLIC libusb PRIVATE msvc)
|
target_include_directories(usb BEFORE PUBLIC libusb/libusb PRIVATE libusb/msvc)
|
||||||
else()
|
else()
|
||||||
target_include_directories(usb
|
target_include_directories(usb
|
||||||
# turns out other projects also have "config.h", so make sure the
|
# turns out other projects also have "config.h", so make sure the
|
||||||
# LibUSB one comes first
|
# LibUSB one comes first
|
||||||
BEFORE
|
BEFORE
|
||||||
|
|
||||||
PUBLIC libusb
|
PUBLIC libusb/libusb
|
||||||
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}"
|
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32 OR CYGWIN)
|
if(WIN32 OR CYGWIN)
|
||||||
target_sources(usb PRIVATE
|
target_sources(usb PRIVATE
|
||||||
libusb/os/threads_windows.c
|
libusb/libusb/os/threads_windows.c
|
||||||
libusb/os/windows_winusb.c
|
libusb/libusb/os/windows_common.c
|
||||||
libusb/os/windows_usbdk.c
|
libusb/libusb/os/windows_usbdk.c
|
||||||
libusb/os/windows_nt_common.c
|
libusb/libusb/os/windows_winusb.c
|
||||||
)
|
)
|
||||||
set(OS_WINDOWS TRUE)
|
set(PLATFORM_WINDOWS TRUE)
|
||||||
elseif(APPLE)
|
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(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||||
find_library(IOKIT_LIBRARY IOKit)
|
find_library(IOKIT_LIBRARY IOKit)
|
||||||
find_library(OBJC_LIBRARY objc)
|
find_library(OBJC_LIBRARY objc)
|
||||||
|
find_library(SECURITY_LIBRARY Security)
|
||||||
target_link_libraries(usb PRIVATE
|
target_link_libraries(usb PRIVATE
|
||||||
${COREFOUNDATION_LIBRARY}
|
${COREFOUNDATION_LIBRARY}
|
||||||
${IOKIT_LIBRARY}
|
${IOKIT_LIBRARY}
|
||||||
${OBJC_LIBRARY}
|
${OBJC_LIBRARY}
|
||||||
|
${SECURITY_LIBRARY}
|
||||||
)
|
)
|
||||||
set(OS_DARWIN TRUE)
|
|
||||||
# # Dolphin on Android doesn't use libusb.
|
# # Dolphin on Android doesn't use libusb.
|
||||||
#elseif(ANDROID)
|
#elseif(ANDROID)
|
||||||
# target_sources(usb PRIVATE
|
# target_sources(usb PRIVATE
|
||||||
# libusb/os/linux_usbfs.c
|
# libusb/libusb/os/linux_usbfs.c
|
||||||
# libusb/os/linux_netlink.c
|
# libusb/libusb/os/linux_netlink.c
|
||||||
# )
|
# )
|
||||||
# find_library(LOG_LIBRARY log)
|
# find_library(LOG_LIBRARY log)
|
||||||
# target_link_libraries(usb PRIVATE ${LOG_LIBRARY})
|
# target_link_libraries(usb PRIVATE ${LOG_LIBRARY})
|
||||||
# set(OS_LINUX TRUE)
|
|
||||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
target_sources(usb PRIVATE libusb/os/linux_usbfs.c)
|
target_sources(usb PRIVATE libusb/libusb/os/linux_usbfs.c)
|
||||||
find_package(Libudev)
|
find_package(LIBUDEV)
|
||||||
if(LIBUDEV_FOUND)
|
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_link_libraries(usb PRIVATE "${LIBUDEV_LIBRARIES}")
|
||||||
target_include_directories(usb PRIVATE "${LIBUDEV_INCLUDE_DIR}")
|
target_include_directories(usb PRIVATE "${LIBUDEV_INCLUDE_DIR}")
|
||||||
set(HAVE_LIBUDEV TRUE)
|
set(HAVE_LIBUDEV TRUE)
|
||||||
set(USE_UDEV TRUE)
|
|
||||||
else()
|
else()
|
||||||
target_sources(usb PRIVATE libusb/os/linux_netlink.c)
|
target_sources(usb PRIVATE libusb/libusb/os/linux_netlink.c)
|
||||||
endif()
|
endif()
|
||||||
set(OS_LINUX TRUE)
|
|
||||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
|
elseif(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
|
||||||
target_sources(usb PRIVATE libusb/os/netbsd_usb.c)
|
target_sources(usb PRIVATE libusb/libusb/os/netbsd_usb.c)
|
||||||
set(OS_NETBSD TRUE)
|
|
||||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
|
elseif(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
|
||||||
target_sources(usb PRIVATE libusb/os/openbsd_usb.c)
|
target_sources(usb PRIVATE libusb/libusb/os/openbsd_usb.c)
|
||||||
set(OS_OPENBSD TRUE)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
target_sources(usb PRIVATE
|
target_sources(usb PRIVATE
|
||||||
libusb/os/poll_posix.c
|
libusb/libusb/os/events_posix.c
|
||||||
libusb/os/threads_posix.c
|
libusb/libusb/os/threads_posix.c
|
||||||
)
|
)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
if(THREADS_HAVE_PTHREAD_ARG)
|
if(THREADS_HAVE_PTHREAD_ARG)
|
||||||
|
@ -82,41 +77,48 @@ if(UNIX)
|
||||||
if(CMAKE_THREAD_LIBS_INIT)
|
if(CMAKE_THREAD_LIBS_INIT)
|
||||||
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
|
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
endif()
|
endif()
|
||||||
set(THREADS_POSIX TRUE)
|
set(PLATFORM_POSIX TRUE)
|
||||||
elseif(WIN32)
|
|
||||||
target_sources(usb PRIVATE
|
|
||||||
libusb/os/poll_windows.c
|
|
||||||
libusb/os/threads_windows.c
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Create config.h
|
||||||
|
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
|
#include(CheckLibraryExists)
|
||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
|
||||||
check_include_files(asm/types.h HAVE_ASM_TYPES_H)
|
check_include_files(asm/types.h HAVE_ASM_TYPES_H)
|
||||||
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
|
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
|
||||||
check_include_files(linux/filter.h HAVE_LINUX_FILTER_H)
|
check_symbol_exists(EFD_CLOEXEC "sys/eventfd.h" HAVE_DECL_EFD_CLOEXEC)
|
||||||
check_include_files(linux/netlink.h HAVE_LINUX_NETLINK_H)
|
check_symbol_exists(EFD_NONBLOCK "sys/eventfd.h" HAVE_DECL_EFD_NONBLOCK)
|
||||||
check_include_files(poll.h HAVE_POLL_H)
|
check_symbol_exists(TFD_CLOEXEC "sys/timerfd.h" HAVE_DECL_TFD_CLOEXEC)
|
||||||
check_include_files(signal.h HAVE_SIGNAL_H)
|
check_symbol_exists(TFD_NONBLOCK "sys/timerfd.h" HAVE_DECL_TFD_NONBLOCK)
|
||||||
check_include_files(strings.h HAVE_STRINGS_H)
|
check_include_files(dlfcn.h HAVE_DLFCN_H)
|
||||||
check_type_size("struct timespec" STRUCT_TIMESPEC)
|
check_include_files(sys/eventfd.h HAVE_EVENTFD)
|
||||||
check_function_exists(syslog HAVE_SYSLOG_FUNC)
|
check_include_files(inttypes.h HAVE_INTTYPES_H)
|
||||||
check_include_files(syslog.h HAVE_SYSLOG_H)
|
check_include_files(IOKit/usb/IOUSBHostFamilyDefinitions.h HAVE_IOKIT_USB_IOUSBHOSTFAMILYDEFINITIONS_H)
|
||||||
check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
|
#check_library_exists(udev HAVE_LIBUDEV)
|
||||||
check_include_files(sys/time.h HAVE_SYS_TIME_H)
|
check_include_files(memory.h HAVE_MEMORY_H)
|
||||||
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
|
|
||||||
|
|
||||||
set(CMAKE_EXTRA_INCLUDE_FILES poll.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)
|
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)
|
configure_file(config.h.in config.h)
|
||||||
|
|
|
@ -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!
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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.
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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)
|
|
|
@ -1,2 +0,0 @@
|
||||||
For the latest libusb news, please refer to the ChangeLog file, or visit:
|
|
||||||
http://libusb.info
|
|
|
@ -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.
|
|
|
@ -1 +0,0 @@
|
||||||
README.md
|
|
|
@ -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.
|
|
|
@ -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)
|
|
|
@ -1,2 +0,0 @@
|
||||||
Please see the libusb roadmap by visiting:
|
|
||||||
https://github.com/libusb/libusb/milestones?direction=asc&sort=due_date&state=open
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
./bootstrap.sh
|
|
||||||
if test -z "$NOCONFIGURE"; then
|
|
||||||
exec ./configure --enable-examples-build --enable-tests-build "$@"
|
|
||||||
fi
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if ! test -d m4 ; then
|
|
||||||
mkdir m4
|
|
||||||
fi
|
|
||||||
autoreconf -ivf || exit 1
|
|
|
@ -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")))
|
#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
|
#undef ENABLE_DEBUG_LOGGING
|
||||||
|
|
||||||
/* Message logging */
|
/* Define to 1 to enable message logging. */
|
||||||
#undef ENABLE_LOGGING
|
#undef ENABLE_LOGGING
|
||||||
|
|
||||||
/* Define to 1 if you have the <asm/types.h> header file. */
|
/* Define to 1 if you have the <asm/types.h> header file. */
|
||||||
#cmakedefine HAVE_ASM_TYPES_H 1
|
#cmakedefine HAVE_ASM_TYPES_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
/* Define to 1 if you have the `clock_gettime' function. */
|
||||||
#cmakedefine HAVE_GETTIMEOFDAY 1
|
#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). */
|
/* Define to 1 if you have the `udev' library (-ludev). */
|
||||||
#cmakedefine HAVE_LIBUDEV 1
|
#cmakedefine HAVE_LIBUDEV 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <linux/filter.h> header file. */
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
#cmakedefine HAVE_LINUX_FILTER_H 1
|
#cmakedefine HAVE_MEMORY_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <linux/netlink.h> header file. */
|
/* Define to 1 if the system has the type `nfds_t'. */
|
||||||
#cmakedefine HAVE_LINUX_NETLINK_H 1
|
#cmakedefine HAVE_NFDS_T 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <poll.h> header file. */
|
/* Define to 1 if you have the `pipe2' function. */
|
||||||
#cmakedefine HAVE_POLL_H 1
|
#cmakedefine HAVE_PIPE2 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <signal.h> header file. */
|
/* Define to 1 if you have the `pthread_condattr_setclock' function. */
|
||||||
#cmakedefine HAVE_SIGNAL_H 1
|
#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. */
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
#cmakedefine HAVE_STRINGS_H 1
|
#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'. */
|
/* Define to 1 if the system has the type `struct timespec'. */
|
||||||
#cmakedefine HAVE_STRUCT_TIMESPEC 1
|
#cmakedefine HAVE_STRUCT_TIMESPEC 1
|
||||||
|
|
||||||
/* syslog() function available */
|
/* Define to 1 if you have the `syslog' function. */
|
||||||
#cmakedefine HAVE_SYSLOG_FUNC 1
|
#cmakedefine HAVE_SYSLOG 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <syslog.h> header file. */
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
#cmakedefine HAVE_SYSLOG_H 1
|
#cmakedefine HAVE_SYS_STAT_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/time.h> header file. */
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
#cmakedefine HAVE_SYS_TIME_H 1
|
#cmakedefine HAVE_SYS_TIME_H 1
|
||||||
|
@ -49,38 +93,66 @@
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
#cmakedefine HAVE_SYS_TYPES_H 1
|
#cmakedefine HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
/* Darwin backend */
|
/* Define to 1 if the system has timerfd functionality. */
|
||||||
#cmakedefine OS_DARWIN 1
|
#cmakedefine HAVE_TIMERFD 1
|
||||||
|
|
||||||
/* Linux backend */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#cmakedefine OS_LINUX 1
|
#cmakedefine HAVE_UNISTD_H 1
|
||||||
|
|
||||||
/* NetBSD backend */
|
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||||
#cmakedefine OS_NETBSD 1
|
#undef LT_OBJDIR
|
||||||
|
|
||||||
/* OpenBSD backend */
|
/* Name of package */
|
||||||
#cmakedefine OS_OPENBSD 1
|
#undef PACKAGE
|
||||||
|
|
||||||
/* Windows backend */
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
#cmakedefine OS_WINDOWS 1
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
/* type of second poll() argument */
|
/* Define to the full name of this package. */
|
||||||
#define POLL_NFDS_TYPE @POLL_NFDS_TYPE@
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
/* Use POSIX Threads */
|
/* Define to the full name and version of this package. */
|
||||||
#cmakedefine THREADS_POSIX
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
/* timerfd headers available */
|
/* Define to the one symbol short name of this package. */
|
||||||
#cmakedefine USBI_TIMERFD_AVAILABLE 1
|
#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
|
#define USE_SYSTEM_LOGGING_FACILITY 1
|
||||||
|
|
||||||
/* Use udev for device enumeration/hotplug */
|
/* Version number of package */
|
||||||
#cmakedefine USE_UDEV 1
|
#undef VERSION
|
||||||
|
|
||||||
/* Use GNU extensions */
|
/* Enable GNU extensions. */
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
/* Oldest Windows version supported */
|
/* Define to the oldest supported Windows version. */
|
||||||
#define WINVER 0x0501
|
//#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
|
||||||
|
|
|
@ -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
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 4239bc3a50014b8e6a5a2a59df1fff3b7469543b
|
|
@ -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
|
|
|
@ -18,36 +18,35 @@
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<!-- Ensure libusb sees it's own config.h first... -->
|
<!-- Ensure libusb sees it's own config.h first... -->
|
||||||
<AdditionalIncludeDirectories>.\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>.\libusb\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="libusb\core.c" />
|
<ClCompile Include="libusb\libusb\core.c" />
|
||||||
<ClCompile Include="libusb\descriptor.c" />
|
<ClCompile Include="libusb\libusb\descriptor.c" />
|
||||||
<ClCompile Include="libusb\hotplug.c" />
|
<ClCompile Include="libusb\libusb\hotplug.c" />
|
||||||
<ClCompile Include="libusb\io.c" />
|
<ClCompile Include="libusb\libusb\io.c" />
|
||||||
<ClCompile Include="libusb\os\poll_windows.c" />
|
<ClCompile Include="libusb\libusb\os\events_windows.c" />
|
||||||
<ClCompile Include="libusb\strerror.c" />
|
<ClCompile Include="libusb\libusb\os\threads_windows.c" />
|
||||||
<ClCompile Include="libusb\sync.c" />
|
<ClCompile Include="libusb\libusb\os\windows_common.c" />
|
||||||
<ClCompile Include="libusb\os\threads_windows.c" />
|
<ClCompile Include="libusb\libusb\os\windows_usbdk.c" />
|
||||||
<ClCompile Include="libusb\os\windows_nt_common.c" />
|
<ClCompile Include="libusb\libusb\os\windows_winusb.c" />
|
||||||
<ClCompile Include="libusb\os\windows_usbdk.c" />
|
<ClCompile Include="libusb\libusb\strerror.c" />
|
||||||
<ClCompile Include="libusb\os\windows_winusb.c" />
|
<ClCompile Include="libusb\libusb\sync.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="msvc\config.h" />
|
<ClInclude Include="libusb\libusb\hotplug.h" />
|
||||||
<ClInclude Include="libusb\hotplug.h" />
|
<ClInclude Include="libusb\libusb\libusb.h" />
|
||||||
<ClInclude Include="libusb\libusb.h" />
|
<ClInclude Include="libusb\libusb\libusbi.h" />
|
||||||
<ClInclude Include="libusb\libusbi.h" />
|
<ClInclude Include="libusb\libusb\os\events_windows.h" />
|
||||||
<ClInclude Include="libusb\os\poll_windows.h" />
|
<ClInclude Include="libusb\libusb\os\threads_windows.h" />
|
||||||
<ClInclude Include="libusb\os\threads_windows.h" />
|
<ClInclude Include="libusb\libusb\os\windows_common.h" />
|
||||||
<ClInclude Include="libusb\version.h" />
|
<ClInclude Include="libusb\libusb\os\windows_nt_common.h" />
|
||||||
<ClInclude Include="libusb\version_nano.h" />
|
<ClInclude Include="libusb\libusb\os\windows_usbdk.h" />
|
||||||
<ClInclude Include="libusb\os\windows_common.h" />
|
<ClInclude Include="libusb\libusb\os\windows_winusb.h" />
|
||||||
<ClInclude Include="libusb\os\windows_nt_common.h" />
|
<ClInclude Include="libusb\libusb\version_nano.h" />
|
||||||
<ClInclude Include="libusb\os\windows_nt_shared_types.h" />
|
<ClInclude Include="libusb\libusb\version.h" />
|
||||||
<ClInclude Include="libusb\os\windows_usbdk.h" />
|
<ClInclude Include="libusb\msvc\config.h" />
|
||||||
<ClInclude Include="libusb\os\windows_winusb.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -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
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
@ -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
|
|
|
@ -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
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
@ -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
|
@ -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
|
|
|
@ -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:
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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*),
|
|
||||||
};
|
|
|
@ -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_
|
|
|
@ -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
|
@ -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])])
|
|
|
@ -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
|
|
||||||
])
|
|
|
@ -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)
|
|
||||||
])
|
|
|
@ -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])])
|
|
|
@ -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:
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 *),
|
|
||||||
};
|
|
|
@ -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_
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
@ -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
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 */
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
@ -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 */
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 */
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 */
|
|
|
@ -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),
|
|
||||||
};
|
|
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
|
@ -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
|
@ -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
|
|
|
@ -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
|
@ -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));
|
|
|
@ -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,
|
|
||||||
};
|
|
|
@ -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
|
@ -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));
|
|
|
@ -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 d’un 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];
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
#define LIBUSB_NANO 11367
|
|
|
@ -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
|
|
|
@ -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 "$@"
|
|
|
@ -33,7 +33,7 @@
|
||||||
<AdditionalIncludeDirectories>$(ExternalsDir)imgui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ExternalsDir)imgui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(ExternalsDir)liblzma\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ExternalsDir)liblzma\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(ExternalsDir)libpng;%(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)LZO;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(ExternalsDir)mGBA\mgba\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ExternalsDir)mGBA\mgba\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(ExternalsDir)miniupnpc\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ExternalsDir)miniupnpc\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<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-->
|
<!--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>_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>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions>USE_ANALYTICS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>USE_ANALYTICS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions>USE_DISCORD_PRESENCE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>USE_DISCORD_PRESENCE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
|
Loading…
Reference in New Issue