Merge pull request #4150 from Pringo/master

Externals: Update libusb to version 1.0.20
This commit is contained in:
shuffle2 2016-10-03 14:32:26 -07:00 committed by GitHub
commit be6aeaad33
56 changed files with 46036 additions and 1287 deletions

View File

@ -8,20 +8,22 @@ Copyright © 2010-2012 Michael Plante <michael.plante@gmail.com>
Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com> Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com>
Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org> Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org>
Copyright © 2012-2013 Toby Gray <toby.gray@realvnc.com> Copyright © 2012-2013 Toby Gray <toby.gray@realvnc.com>
Copyright © 2013-2015 Chris Dickens <christopher.a.dickens@gmail.com>
Other contributors: Other contributors:
Akshay Jaggi
Alan Ott Alan Ott
Alan Stern Alan Stern
Alex Vatchenko Alex Vatchenko
Andrew Fernandes Andrew Fernandes
Anthony Clay Anthony Clay
Antonio Ospite
Artem Egorkine Artem Egorkine
Aurelien Jarno Aurelien Jarno
Bastien Nocera Bastien Nocera
Bei Zhang Bei Zhang
Benjamin Dobell Benjamin Dobell
Carl Karsten Carl Karsten
Chris Dickens
Colin Walters Colin Walters
Dave Camarillo Dave Camarillo
David Engraf David Engraf
@ -32,6 +34,7 @@ Felipe Balbi
Florian Albrechtskirchinger Florian Albrechtskirchinger
Francesco Montorsi Francesco Montorsi
Francisco Facioni Francisco Facioni
Gaurav Gupta
Graeme Gill Graeme Gill
Gustavo Zacarias Gustavo Zacarias
Hans Ulrich Niedermann Hans Ulrich Niedermann
@ -48,7 +51,9 @@ Kuangye Guo
Lars Kanis Lars Kanis
Lars Wirzenius Lars Wirzenius
Luca Longinotti Luca Longinotti
Marcus Meissner
Markus Heidelberg Markus Heidelberg
Martin Ettl
Martin Koegler Martin Koegler
Matthias Bolte Matthias Bolte
Mike Frysinger Mike Frysinger
@ -64,15 +69,21 @@ Rob Walker
Sean McBride Sean McBride
Sebastian Pipping Sebastian Pipping
Simon Haggett Simon Haggett
Simon Newton
Thomas Röfer Thomas Röfer
Tim Hutt
Tim Roberts Tim Roberts
Tobias Klauser
Toby Peterson Toby Peterson
Tormod Volden
Trygve Laugstøl Trygve Laugstøl
Uri Lublin Uri Lublin
Vasily Khoruzhick Vasily Khoruzhick
Vegard Storheil Eriksen Vegard Storheil Eriksen
Venkatesh Shukla
Vitali Lovich Vitali Lovich
Xiaofan Chen Xiaofan Chen
Zoltán Kovács Zoltán Kovács
Роман Донченко Роман Донченко
parafin
xantares xantares

View File

@ -1,14 +1,30 @@
For detailed information about the changes below, please see the git log or For detailed information about the changes below, please see the git log or
visit: http://log.libusb.info visit: http://log.libusb.info
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 2014-05-30: v1.0.19
* Add support for USB bulk streams on Linux and Mac OS X (#11) * 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: Add AMD and Intel USB-3.0 root hub support
* Windows: Fix USB 3.0 speed detection on Windows 8 or later (#10) * Windows: Fix USB 3.0 speed detection on Windows 8 or later (#10)
* Added Russian translation for libusb_strerror strings * Added Russian translation for libusb_strerror strings
* All: Various small fixes and cleanups * All: Various small fixes and cleanups
The (#xx) numbers are libusb issue numbers, see ie:
https://github.com/libusb/libusb/issues/11
2014-01-25: v1.0.18 2014-01-25: v1.0.18
* Fix multiple memory leaks * Fix multiple memory leaks

View File

@ -1,4 +1,4 @@
Dolphin-specific changes (as of 2015-02-12) Dolphin-specific changes (as of 2016-08-25)
------------------------------------------- -------------------------------------------
- removed all toplevel directories save msvc/ & libusb/ - removed all toplevel directories save msvc/ & libusb/

View File

@ -2,9 +2,10 @@ libusb
====== ======
libusb is a library for USB device access from Linux, Mac OS X, libusb is a library for USB device access from Linux, Mac OS X,
Windows and OpenBSD/NetBSD userspace. Windows, OpenBSD/NetBSD and Haiku userspace.
It is written in C and licensed under the GNU Lesser General Public It is written in C (Haiku backend in C++) and licensed under the GNU
License version 2.1 or, at your option, any later version (see COPYING). Lesser General Public License version 2.1 or, at your option, any later
version (see COPYING).
libusb is abstracted internally in such a way that it can hopefully libusb is abstracted internally in such a way that it can hopefully
be ported to other operating systems. Please see the PORTING file be ported to other operating systems. Please see the PORTING file
@ -24,4 +25,5 @@ http://mailing-list.libusb.info
- Xiaofan Chen <xiaofanc@gmail.com> - Xiaofan Chen <xiaofanc@gmail.com>
- Ludovic Rousseau <ludovic.rousseau@gmail.com> - Ludovic Rousseau <ludovic.rousseau@gmail.com>
- Nathan Hjelm <hjelmn@users.sourceforge.net> - Nathan Hjelm <hjelmn@users.sourceforge.net>
- Chris Dickens <christopher.a.dickens@gmail.com>
(Please use the mailing list rather than mailing developers directly) (Please use the mailing list rather than mailing developers directly)

View File

@ -12,12 +12,18 @@ NETBSD_USB_SRC = os/netbsd_usb.c
WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc libusb-1.0.def WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc libusb-1.0.def
WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h
DIST_SUBDIRS =
EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \ EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
$(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \ $(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
$(POSIX_POLL_SRC) \ $(POSIX_POLL_SRC) \
os/threads_posix.c os/threads_windows.c \ os/threads_posix.c os/threads_windows.c \
os/linux_udev.c os/linux_netlink.c os/linux_udev.c os/linux_netlink.c
dist-hook:
cp -r os/haiku $(distdir)/os/haiku
rm -rf $(distdir)/os/haiku/autom4te.cache
if OS_LINUX if OS_LINUX
if USE_UDEV if USE_UDEV
@ -43,6 +49,11 @@ if OS_NETBSD
OS_SRC = $(NETBSD_USB_SRC) $(POSIX_POLL_SRC) OS_SRC = $(NETBSD_USB_SRC) $(POSIX_POLL_SRC)
endif endif
if OS_HAIKU
OS_SRC = $(POSIX_POLL_SRC)
SUBDIRS = os/haiku
endif
if OS_WINDOWS if OS_WINDOWS
OS_SRC = $(WINDOWS_USB_SRC) OS_SRC = $(WINDOWS_USB_SRC)
@ -71,5 +82,9 @@ libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c strerror.c sync.c \
hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \ hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \
os/poll_posix.h os/poll_windows.h os/poll_posix.h os/poll_windows.h
if OS_HAIKU
libusb_1_0_la_LIBADD = os/haiku/libhaikuusb.la
endif
hdrdir = $(includedir)/libusb-1.0 hdrdir = $(includedir)/libusb-1.0
hdr_HEADERS = libusb.h hdr_HEADERS = libusb.h

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am. # Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc. # Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -16,7 +16,17 @@
VPATH = @srcdir@ VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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 = \ am__make_running_with_option = \
case $${target_option-} in \ case $${target_option-} in \
?) ;; \ ?) ;; \
@ -80,8 +90,6 @@ POST_UNINSTALL = :
build_triplet = @build@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
subdir = libusb subdir = libusb
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp $(hdr_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@ -89,6 +97,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/libusb/version.h $(top_srcdir)/configure.ac $(top_srcdir)/libusb/version.h $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(hdr_HEADERS) $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = CONFIG_CLEAN_FILES =
@ -122,7 +131,7 @@ am__uninstall_files_from_dir = { \
} }
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(hdrdir)" am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(hdrdir)"
LTLIBRARIES = $(lib_LTLIBRARIES) LTLIBRARIES = $(lib_LTLIBRARIES)
libusb_1_0_la_LIBADD = @OS_HAIKU_TRUE@libusb_1_0_la_DEPENDENCIES = os/haiku/libhaikuusb.la
am__libusb_1_0_la_SOURCES_DIST = libusbi.h core.c descriptor.c io.c \ am__libusb_1_0_la_SOURCES_DIST = libusbi.h core.c descriptor.c io.c \
strerror.c sync.c os/linux_usbfs.h os/darwin_usb.h \ strerror.c sync.c os/linux_usbfs.h os/darwin_usb.h \
os/windows_usb.h os/windows_common.h hotplug.h hotplug.c \ os/windows_usb.h os/windows_common.h hotplug.h hotplug.c \
@ -143,17 +152,18 @@ am__objects_5 = os/libusb_1_0_la-netbsd_usb.lo
am__objects_6 = os/libusb_1_0_la-openbsd_usb.lo am__objects_6 = os/libusb_1_0_la-openbsd_usb.lo
am__objects_7 = os/libusb_1_0_la-poll_windows.lo \ am__objects_7 = os/libusb_1_0_la-poll_windows.lo \
os/libusb_1_0_la-windows_usb.lo libusb-1.0.lo os/libusb_1_0_la-windows_usb.lo libusb-1.0.lo
@OS_DARWIN_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_FALSE@@OS_OPENBSD_FALSE@@OS_WINDOWS_TRUE@am__objects_8 = $(am__objects_7) @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_FALSE@@OS_OPENBSD_FALSE@@OS_WINDOWS_TRUE@am__objects_8 = $(am__objects_7)
@OS_DARWIN_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_FALSE@@OS_OPENBSD_TRUE@am__objects_8 = $(am__objects_6) \ @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_FALSE@@OS_OPENBSD_TRUE@am__objects_8 = $(am__objects_6) \
@OS_DARWIN_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_FALSE@@OS_OPENBSD_TRUE@ $(am__objects_3) @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_FALSE@@OS_OPENBSD_TRUE@ $(am__objects_3)
@OS_DARWIN_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_TRUE@am__objects_8 = $(am__objects_5) \ @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_TRUE@am__objects_8 = $(am__objects_5) \
@OS_DARWIN_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_TRUE@ $(am__objects_3) @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_FALSE@@OS_NETBSD_TRUE@ $(am__objects_3)
@OS_DARWIN_FALSE@@OS_LINUX_TRUE@@USE_UDEV_FALSE@am__objects_8 = $(am__objects_4) \ @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_TRUE@@USE_UDEV_FALSE@am__objects_8 = $(am__objects_4) \
@OS_DARWIN_FALSE@@OS_LINUX_TRUE@@USE_UDEV_FALSE@ $(am__objects_3) \ @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_TRUE@@USE_UDEV_FALSE@ $(am__objects_3) \
@OS_DARWIN_FALSE@@OS_LINUX_TRUE@@USE_UDEV_FALSE@ os/libusb_1_0_la-linux_netlink.lo @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_TRUE@@USE_UDEV_FALSE@ os/libusb_1_0_la-linux_netlink.lo
@OS_DARWIN_FALSE@@OS_LINUX_TRUE@@USE_UDEV_TRUE@am__objects_8 = $(am__objects_4) \ @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_TRUE@@USE_UDEV_TRUE@am__objects_8 = $(am__objects_4) \
@OS_DARWIN_FALSE@@OS_LINUX_TRUE@@USE_UDEV_TRUE@ $(am__objects_3) \ @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_TRUE@@USE_UDEV_TRUE@ $(am__objects_3) \
@OS_DARWIN_FALSE@@OS_LINUX_TRUE@@USE_UDEV_TRUE@ os/libusb_1_0_la-linux_udev.lo @OS_DARWIN_FALSE@@OS_HAIKU_FALSE@@OS_LINUX_TRUE@@USE_UDEV_TRUE@ os/libusb_1_0_la-linux_udev.lo
@OS_DARWIN_FALSE@@OS_HAIKU_TRUE@am__objects_8 = $(am__objects_3)
@OS_DARWIN_TRUE@am__objects_8 = $(am__objects_2) $(am__objects_3) @OS_DARWIN_TRUE@am__objects_8 = $(am__objects_2) $(am__objects_3)
am_libusb_1_0_la_OBJECTS = libusb_1_0_la-core.lo \ am_libusb_1_0_la_OBJECTS = libusb_1_0_la-core.lo \
libusb_1_0_la-descriptor.lo libusb_1_0_la-io.lo \ libusb_1_0_la-descriptor.lo libusb_1_0_la-io.lo \
@ -203,12 +213,28 @@ am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 = am__v_CCLD_1 =
SOURCES = $(libusb_1_0_la_SOURCES) SOURCES = $(libusb_1_0_la_SOURCES)
DIST_SOURCES = $(am__libusb_1_0_la_SOURCES_DIST) DIST_SOURCES = $(am__libusb_1_0_la_SOURCES_DIST)
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \ am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \ case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \ n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \ *) (install-info --version) >/dev/null 2>&1;; \
esac esac
HEADERS = $(hdr_HEADERS) HEADERS = $(hdr_HEADERS)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input, # Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is # and print each of them once, without duplicates. Input order is
@ -228,7 +254,33 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags ETAGS = etags
CTAGS = ctags CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@ ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@ AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@ AM_CFLAGS = @AM_CFLAGS@
@ -279,6 +331,7 @@ NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@ OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@ OBJEXT = @OBJEXT@
OS_DARWIN = @OS_DARWIN@ OS_DARWIN = @OS_DARWIN@
OS_HAIKU = @OS_HAIKU@
OS_LINUX = @OS_LINUX@ OS_LINUX = @OS_LINUX@
OS_NETBSD = @OS_NETBSD@ OS_NETBSD = @OS_NETBSD@
OS_OPENBSD = @OS_OPENBSD@ OS_OPENBSD = @OS_OPENBSD@
@ -348,6 +401,7 @@ psdir = @psdir@
sbindir = @sbindir@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@ srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@ sysconfdir = @sysconfdir@
target_alias = @target_alias@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@ top_build_prefix = @top_build_prefix@
@ -362,6 +416,7 @@ OPENBSD_USB_SRC = os/openbsd_usb.c
NETBSD_USB_SRC = os/netbsd_usb.c NETBSD_USB_SRC = os/netbsd_usb.c
WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc libusb-1.0.def WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc libusb-1.0.def
WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h
DIST_SUBDIRS =
EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \ EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
$(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \ $(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
$(POSIX_POLL_SRC) \ $(POSIX_POLL_SRC) \
@ -369,6 +424,7 @@ EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
os/linux_udev.c os/linux_netlink.c os/linux_udev.c os/linux_netlink.c
@OS_DARWIN_TRUE@OS_SRC = $(DARWIN_USB_SRC) $(POSIX_POLL_SRC) @OS_DARWIN_TRUE@OS_SRC = $(DARWIN_USB_SRC) $(POSIX_POLL_SRC)
@OS_HAIKU_TRUE@OS_SRC = $(POSIX_POLL_SRC)
@OS_LINUX_TRUE@@USE_UDEV_FALSE@OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \ @OS_LINUX_TRUE@@USE_UDEV_FALSE@OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \
@OS_LINUX_TRUE@@USE_UDEV_FALSE@ os/linux_netlink.c @OS_LINUX_TRUE@@USE_UDEV_FALSE@ os/linux_netlink.c
@ -379,6 +435,7 @@ EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
@OS_OPENBSD_TRUE@OS_SRC = $(OPENBSD_USB_SRC) $(POSIX_POLL_SRC) @OS_OPENBSD_TRUE@OS_SRC = $(OPENBSD_USB_SRC) $(POSIX_POLL_SRC)
@OS_WINDOWS_TRUE@OS_SRC = $(WINDOWS_USB_SRC) @OS_WINDOWS_TRUE@OS_SRC = $(WINDOWS_USB_SRC)
@OS_DARWIN_TRUE@AM_CFLAGS_EXT = -no-cpp-precomp @OS_DARWIN_TRUE@AM_CFLAGS_EXT = -no-cpp-precomp
@OS_HAIKU_TRUE@SUBDIRS = os/haiku
@THREADS_POSIX_FALSE@THREADS_SRC = os/threads_windows.h os/threads_windows.c @THREADS_POSIX_FALSE@THREADS_SRC = os/threads_windows.h os/threads_windows.c
@THREADS_POSIX_TRUE@THREADS_SRC = os/threads_posix.h os/threads_posix.c @THREADS_POSIX_TRUE@THREADS_SRC = os/threads_posix.h os/threads_posix.c
libusb_1_0_la_CFLAGS = $(AM_CFLAGS) libusb_1_0_la_CFLAGS = $(AM_CFLAGS)
@ -388,9 +445,10 @@ libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c strerror.c sync.c \
hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \ hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \
os/poll_posix.h os/poll_windows.h os/poll_posix.h os/poll_windows.h
@OS_HAIKU_TRUE@libusb_1_0_la_LIBADD = os/haiku/libhaikuusb.la
hdrdir = $(includedir)/libusb-1.0 hdrdir = $(includedir)/libusb-1.0
hdr_HEADERS = libusb.h hdr_HEADERS = libusb.h
all: all-am all: all-recursive
.SUFFIXES: .SUFFIXES:
.SUFFIXES: .c .lo .o .obj .rc .SUFFIXES: .c .lo .o .obj .rc
@ -406,7 +464,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libusb/Makefile'; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libusb/Makefile'; \
$(am__cd) $(top_srcdir) && \ $(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu libusb/Makefile $(AUTOMAKE) --gnu libusb/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \ @case '$?' in \
*config.status*) \ *config.status*) \
@ -688,14 +745,61 @@ uninstall-hdrHEADERS:
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(hdrdir)'; $(am__uninstall_files_from_dir) dir='$(DESTDIR)$(hdrdir)'; $(am__uninstall_files_from_dir)
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files) ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique $(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am tags: tags-recursive
TAGS: tags TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \ set x; \
here=`pwd`; \ here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \ $(am__define_uniq_tagged_files); \
shift; \ shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
@ -708,7 +812,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$$unique; \ $$unique; \
fi; \ fi; \
fi fi
ctags: ctags-am ctags: ctags-recursive
CTAGS: ctags CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
@ -721,7 +825,7 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \ here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \ && $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here" && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files) cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \ list='$(am__tagged_files)'; \
@ -770,22 +874,51 @@ distdir: $(DISTFILES)
|| exit 1; \ || exit 1; \
fi; \ fi; \
done done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$(top_distdir)" distdir="$(distdir)" \
dist-hook
check-am: all-am check-am: all-am
check: check-am check: check-recursive
all-am: Makefile $(LTLIBRARIES) $(HEADERS) all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs: installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(hdrdir)"; do \ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(hdrdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done done
install: install-am install: install-recursive
install-exec: install-exec-am install-exec: install-exec-recursive
install-data: install-data-am install-data: install-data-recursive
uninstall: uninstall-am uninstall: uninstall-recursive
install-am: all-am install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am installcheck: installcheck-recursive
install-strip: install-strip:
if test -z '$(STRIP)'; then \ if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
@ -809,97 +942,103 @@ distclean-generic:
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild." @echo "it deletes files that may require special tools to rebuild."
clean: clean-am clean: clean-recursive
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-am mostlyclean-am
distclean: distclean-am distclean: distclean-recursive
-rm -rf ./$(DEPDIR) os/$(DEPDIR) -rm -rf ./$(DEPDIR) os/$(DEPDIR)
-rm -f Makefile -rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \ distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags distclean-tags
dvi: dvi-am dvi: dvi-recursive
dvi-am: dvi-am:
html: html-am html: html-recursive
html-am: html-am:
info: info-am info: info-recursive
info-am: info-am:
install-data-am: install-hdrHEADERS install-data-am: install-hdrHEADERS
install-dvi: install-dvi-am install-dvi: install-dvi-recursive
install-dvi-am: install-dvi-am:
install-exec-am: install-libLTLIBRARIES install-exec-am: install-libLTLIBRARIES
install-html: install-html-am install-html: install-html-recursive
install-html-am: install-html-am:
install-info: install-info-am install-info: install-info-recursive
install-info-am: install-info-am:
install-man: install-man:
install-pdf: install-pdf-am install-pdf: install-pdf-recursive
install-pdf-am: install-pdf-am:
install-ps: install-ps-am install-ps: install-ps-recursive
install-ps-am: install-ps-am:
installcheck-am: installcheck-am:
maintainer-clean: maintainer-clean-am maintainer-clean: maintainer-clean-recursive
-rm -rf ./$(DEPDIR) os/$(DEPDIR) -rm -rf ./$(DEPDIR) os/$(DEPDIR)
-rm -f Makefile -rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool mostlyclean-libtool
pdf: pdf-am pdf: pdf-recursive
pdf-am: pdf-am:
ps: ps-am ps: ps-recursive
ps-am: ps-am:
uninstall-am: uninstall-hdrHEADERS uninstall-libLTLIBRARIES uninstall-am: uninstall-hdrHEADERS uninstall-libLTLIBRARIES
.MAKE: install-am install-strip .MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ check-am clean clean-generic clean-libLTLIBRARIES \
ctags-am distclean distclean-compile distclean-generic \ clean-libtool cscopelist-am ctags ctags-am dist-hook distclean \
distclean-libtool distclean-tags distdir dvi dvi-am html \ distclean-compile distclean-generic distclean-libtool \
html-am info info-am install install-am install-data \ distclean-tags distdir dvi dvi-am html html-am info info-am \
install-data-am install-dvi install-dvi-am install-exec \ install install-am install-data install-data-am install-dvi \
install-exec-am install-hdrHEADERS install-html \ install-dvi-am install-exec install-exec-am install-hdrHEADERS \
install-html-am install-info install-info-am \ install-html install-html-am install-info install-info-am \
install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \ install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \ installcheck-am installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \ maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am uninstall-hdrHEADERS \ tags tags-am uninstall uninstall-am uninstall-hdrHEADERS \
uninstall-libLTLIBRARIES uninstall-libLTLIBRARIES
.PRECIOUS: Makefile
all: libusb-1.0.la libusb-1.0.dll all: libusb-1.0.la libusb-1.0.dll
dist-hook:
cp -r os/haiku $(distdir)/os/haiku
rm -rf $(distdir)/os/haiku/autom4te.cache
@OS_WINDOWS_TRUE@.rc.lo: @OS_WINDOWS_TRUE@.rc.lo:
@OS_WINDOWS_TRUE@ $(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@ @OS_WINDOWS_TRUE@ $(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@

View File

@ -56,6 +56,8 @@ const struct usbi_os_backend * const usbi_backend = &netbsd_backend;
const struct usbi_os_backend * const usbi_backend = &windows_backend; const struct usbi_os_backend * const usbi_backend = &windows_backend;
#elif defined(OS_WINCE) #elif defined(OS_WINCE)
const struct usbi_os_backend * const usbi_backend = &wince_backend; const struct usbi_os_backend * const usbi_backend = &wince_backend;
#elif defined(OS_HAIKU)
const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend;
#else #else
#error "Unsupported OS" #error "Unsupported OS"
#endif #endif
@ -92,6 +94,10 @@ struct list_head active_contexts_list;
* Specification</a> which is available for free download. You can probably * Specification</a> which is available for free download. You can probably
* find less verbose introductions by searching the web. * find less verbose introductions by searching the web.
* *
* \section API Application Programming Interface (API)
*
* See the \ref api page for a complete list of the libusb functions.
*
* \section features Library features * \section features Library features
* *
* - All transfer types supported (control/bulk/interrupt/isochronous) * - All transfer types supported (control/bulk/interrupt/isochronous)
@ -217,9 +223,6 @@ struct list_head active_contexts_list;
* -# If the device is already in the desired configuration, calling * -# If the device is already in the desired configuration, calling
* libusb_set_configuration() using the same configuration value will cause * libusb_set_configuration() using the same configuration value will cause
* a lightweight device reset. This may not be desirable behaviour. * a lightweight device reset. This may not be desirable behaviour.
* -# libusb will be unable to change configuration if the device is in
* another configuration and other programs or drivers have claimed
* interfaces under that configuration.
* -# In the case where the desired configuration is already active, libusb * -# In the case where the desired configuration is already active, libusb
* may not even be able to perform a lightweight device reset. For example, * may not even be able to perform a lightweight device reset. For example,
* take my USB keyboard with fingerprint reader: I'm interested in driving * take my USB keyboard with fingerprint reader: I'm interested in driving
@ -228,12 +231,17 @@ struct list_head active_contexts_list;
* Because the kernel has claimed an interface, it is not even possible to * Because the kernel has claimed an interface, it is not even possible to
* perform the lightweight device reset, so libusb_set_configuration() will * perform the lightweight device reset, so libusb_set_configuration() will
* fail. (Luckily the device in question only has a single configuration.) * fail. (Luckily the device in question only has a single configuration.)
* -# libusb will be unable to set a configuration if other programs or
* drivers have claimed interfaces. In particular, this means that kernel
* drivers must be detached from all the interfaces before
* libusb_set_configuration() may succeed.
* *
* One solution to some of the above problems is to consider the currently * One solution to some of the above problems is to consider the currently
* active configuration. If the configuration we want is already active, then * active configuration. If the configuration we want is already active, then
* we don't have to select any configuration: * we don't have to select any configuration:
\code \code
cfg = libusb_get_configuration(dev); cfg = -1;
libusb_get_configuration(dev, &cfg);
if (cfg != desired) if (cfg != desired)
libusb_set_configuration(dev, desired); libusb_set_configuration(dev, desired);
\endcode \endcode
@ -323,6 +331,151 @@ if (cfg != desired)
* can infer the context from those objects. * can infer the context from those objects.
*/ */
/**
* \page api Application Programming Interface
*
* This is the complete list of libusb functions, structures and
* enumerations in alphabetical order.
*
* \section Functions
* - libusb_alloc_streams()
* - libusb_alloc_transfer()
* - libusb_attach_kernel_driver()
* - libusb_bulk_transfer()
* - libusb_cancel_transfer()
* - libusb_claim_interface()
* - libusb_clear_halt()
* - libusb_close()
* - libusb_control_transfer()
* - libusb_control_transfer_get_data()
* - libusb_control_transfer_get_setup()
* - libusb_cpu_to_le16()
* - libusb_detach_kernel_driver()
* - libusb_error_name()
* - libusb_event_handler_active()
* - libusb_event_handling_ok()
* - libusb_exit()
* - libusb_fill_bulk_stream_transfer()
* - libusb_fill_bulk_transfer()
* - libusb_fill_control_setup()
* - libusb_fill_control_transfer()
* - libusb_fill_interrupt_transfer()
* - libusb_fill_iso_transfer()
* - libusb_free_bos_descriptor()
* - libusb_free_config_descriptor()
* - libusb_free_container_id_descriptor()
* - libusb_free_device_list()
* - libusb_free_ss_endpoint_companion_descriptor()
* - libusb_free_ss_usb_device_capability_descriptor()
* - libusb_free_streams()
* - libusb_free_transfer()
* - libusb_free_usb_2_0_extension_descriptor()
* - libusb_get_active_config_descriptor()
* - libusb_get_bos_descriptor()
* - libusb_get_bus_number()
* - libusb_get_config_descriptor()
* - libusb_get_config_descriptor_by_value()
* - libusb_get_configuration()
* - libusb_get_container_id_descriptor()
* - libusb_get_descriptor()
* - libusb_get_device()
* - libusb_get_device_address()
* - libusb_get_device_descriptor()
* - libusb_get_device_list()
* - libusb_get_device_speed()
* - libusb_get_iso_packet_buffer()
* - libusb_get_iso_packet_buffer_simple()
* - libusb_get_max_iso_packet_size()
* - libusb_get_max_packet_size()
* - libusb_get_next_timeout()
* - libusb_get_parent()
* - libusb_get_port_number()
* - libusb_get_port_numbers()
* - libusb_get_ss_endpoint_companion_descriptor()
* - libusb_get_ss_usb_device_capability_descriptor()
* - libusb_get_string_descriptor()
* - libusb_get_string_descriptor_ascii()
* - libusb_get_usb_2_0_extension_descriptor()
* - libusb_get_version()
* - libusb_handle_events()
* - libusb_handle_events_completed()
* - libusb_handle_events_locked()
* - libusb_handle_events_timeout()
* - libusb_handle_events_timeout_completed()
* - libusb_has_capability()
* - libusb_hotplug_deregister_callback()
* - libusb_hotplug_register_callback()
* - libusb_init()
* - libusb_interrupt_transfer()
* - libusb_kernel_driver_active()
* - libusb_lock_events()
* - libusb_lock_event_waiters()
* - libusb_open()
* - libusb_open_device_with_vid_pid()
* - libusb_pollfds_handle_timeouts()
* - libusb_ref_device()
* - libusb_release_interface()
* - libusb_reset_device()
* - libusb_set_auto_detach_kernel_driver()
* - libusb_set_configuration()
* - libusb_set_debug()
* - libusb_set_interface_alt_setting()
* - libusb_set_iso_packet_lengths()
* - libusb_setlocale()
* - libusb_set_pollfd_notifiers()
* - libusb_strerror()
* - libusb_submit_transfer()
* - libusb_transfer_get_stream_id()
* - libusb_transfer_set_stream_id()
* - libusb_try_lock_events()
* - libusb_unlock_events()
* - libusb_unlock_event_waiters()
* - libusb_unref_device()
* - libusb_wait_for_event()
*
* \section Structures
* - libusb_bos_descriptor
* - libusb_bos_dev_capability_descriptor
* - libusb_config_descriptor
* - libusb_container_id_descriptor
* - \ref libusb_context
* - libusb_control_setup
* - \ref libusb_device
* - libusb_device_descriptor
* - \ref libusb_device_handle
* - libusb_endpoint_descriptor
* - libusb_interface
* - libusb_interface_descriptor
* - libusb_iso_packet_descriptor
* - libusb_pollfd
* - libusb_ss_endpoint_companion_descriptor
* - libusb_ss_usb_device_capability_descriptor
* - libusb_transfer
* - libusb_usb_2_0_extension_descriptor
* - libusb_version
*
* \section Enums
* - \ref libusb_bos_type
* - \ref libusb_capability
* - \ref libusb_class_code
* - \ref libusb_descriptor_type
* - \ref libusb_endpoint_direction
* - \ref libusb_error
* - \ref libusb_iso_sync_type
* - \ref libusb_iso_usage_type
* - \ref libusb_log_level
* - \ref libusb_request_recipient
* - \ref libusb_request_type
* - \ref libusb_speed
* - \ref libusb_ss_usb_device_capability_attributes
* - \ref libusb_standard_request
* - \ref libusb_supported_speed
* - \ref libusb_transfer_flags
* - \ref libusb_transfer_status
* - \ref libusb_transfer_type
* - \ref libusb_usb_2_0_extension_attributes
*/
/** /**
* @defgroup lib Library initialization/deinitialization * @defgroup lib Library initialization/deinitialization
* This page details how to initialize and deinitialize libusb. Initialization * This page details how to initialize and deinitialize libusb. Initialization
@ -533,12 +686,8 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
void usbi_connect_device(struct libusb_device *dev) void usbi_connect_device(struct libusb_device *dev)
{ {
libusb_hotplug_message message; struct libusb_context *ctx = DEVICE_CTX(dev);
ssize_t ret;
memset(&message, 0, sizeof(message));
message.event = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED;
message.device = dev;
dev->attached = 1; dev->attached = 1;
usbi_mutex_lock(&dev->ctx->usb_devs_lock); usbi_mutex_lock(&dev->ctx->usb_devs_lock);
@ -546,25 +695,17 @@ void usbi_connect_device(struct libusb_device *dev)
usbi_mutex_unlock(&dev->ctx->usb_devs_lock); usbi_mutex_unlock(&dev->ctx->usb_devs_lock);
/* Signal that an event has occurred for this device if we support hotplug AND /* Signal that an event has occurred for this device if we support hotplug AND
* the hotplug pipe is ready. This prevents an event from getting raised during * the hotplug message list is ready. This prevents an event from getting raised
* initial enumeration. */ * during initial enumeration. */
if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_pipe[1] > 0) { if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) {
ret = usbi_write(dev->ctx->hotplug_pipe[1], &message, sizeof(message)); usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
if (sizeof (message) != ret) {
usbi_err(DEVICE_CTX(dev), "error writing hotplug message");
}
} }
} }
void usbi_disconnect_device(struct libusb_device *dev) void usbi_disconnect_device(struct libusb_device *dev)
{ {
libusb_hotplug_message message; struct libusb_context *ctx = DEVICE_CTX(dev);
struct libusb_context *ctx = dev->ctx;
ssize_t ret;
memset(&message, 0, sizeof(message));
message.event = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT;
message.device = dev;
usbi_mutex_lock(&dev->lock); usbi_mutex_lock(&dev->lock);
dev->attached = 0; dev->attached = 0;
usbi_mutex_unlock(&dev->lock); usbi_mutex_unlock(&dev->lock);
@ -574,14 +715,11 @@ void usbi_disconnect_device(struct libusb_device *dev)
usbi_mutex_unlock(&ctx->usb_devs_lock); usbi_mutex_unlock(&ctx->usb_devs_lock);
/* Signal that an event has occurred for this device if we support hotplug AND /* Signal that an event has occurred for this device if we support hotplug AND
* the hotplug pipe is ready. This prevents an event from getting raised during * the hotplug message list is ready. This prevents an event from getting raised
* initial enumeration. libusb_handle_events will take care of dereferencing the * during initial enumeration. libusb_handle_events will take care of dereferencing
* device. */ * the device. */
if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_pipe[1] > 0) { if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) {
ret = usbi_write(dev->ctx->hotplug_pipe[1], &message, sizeof(message)); usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);
if (sizeof(message) != ret) {
usbi_err(DEVICE_CTX(dev), "error writing hotplug message");
}
} }
} }
@ -1021,47 +1159,41 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev)
} }
/* /*
* Interrupt the iteration of the event handling thread, so that it picks * Signal the event pipe so that the event handling thread will be
* up the new fd. * interrupted to process an internal event.
*/ */
void usbi_fd_notification(struct libusb_context *ctx) int usbi_signal_event(struct libusb_context *ctx)
{ {
unsigned char dummy = 1; unsigned char dummy = 1;
ssize_t r; ssize_t r;
if (ctx == NULL) /* write some data on event pipe to interrupt event handlers */
return; r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy));
if (r != sizeof(dummy)) {
/* record that we are messing with poll fds */
usbi_mutex_lock(&ctx->pollfd_modify_lock);
ctx->pollfd_modify++;
usbi_mutex_unlock(&ctx->pollfd_modify_lock);
/* write some data on control pipe to interrupt event handlers */
r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
if (r <= 0) {
usbi_warn(ctx, "internal signalling write failed"); usbi_warn(ctx, "internal signalling write failed");
usbi_mutex_lock(&ctx->pollfd_modify_lock); return LIBUSB_ERROR_IO;
ctx->pollfd_modify--;
usbi_mutex_unlock(&ctx->pollfd_modify_lock);
return;
} }
/* take event handling lock */ return 0;
libusb_lock_events(ctx); }
/* read the dummy data */ /*
r = usbi_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); * Clear the event pipe so that the event handling will no longer be
if (r <= 0) * interrupted.
*/
int usbi_clear_event(struct libusb_context *ctx)
{
unsigned char dummy;
ssize_t r;
/* read some data on event pipe to clear it */
r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
if (r != sizeof(dummy)) {
usbi_warn(ctx, "internal signalling read failed"); usbi_warn(ctx, "internal signalling read failed");
return LIBUSB_ERROR_IO;
}
/* we're done with modifying poll fds */ return 0;
usbi_mutex_lock(&ctx->pollfd_modify_lock);
ctx->pollfd_modify--;
usbi_mutex_unlock(&ctx->pollfd_modify_lock);
/* Release event handling lock and wake up event waiters */
libusb_unlock_events(ctx);
} }
/** \ingroup dev /** \ingroup dev
@ -1125,14 +1257,6 @@ int API_EXPORTED libusb_open(libusb_device *dev,
usbi_mutex_unlock(&ctx->open_devs_lock); usbi_mutex_unlock(&ctx->open_devs_lock);
*handle = _handle; *handle = _handle;
/* At this point, we want to interrupt any existing event handlers so
* that they realise the addition of the new device's poll fd. One
* example when this is desirable is if the user is running a separate
* dedicated libusb events handling thread, which is running with a long
* or infinite timeout. We want to interrupt that iteration of the loop,
* so that it picks up the new fd, and then continues. */
usbi_fd_notification(ctx);
return 0; return 0;
} }
@ -1260,8 +1384,7 @@ static void do_close(struct libusb_context *ctx,
void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
{ {
struct libusb_context *ctx; struct libusb_context *ctx;
unsigned char dummy = 1; int pending_events;
ssize_t r;
if (!dev_handle) if (!dev_handle)
return; return;
@ -1275,37 +1398,29 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
* thread from doing event handling) because we will be removing a file * thread from doing event handling) because we will be removing a file
* descriptor from the polling loop. */ * descriptor from the polling loop. */
/* record that we are messing with poll fds */ /* Record that we are closing a device.
usbi_mutex_lock(&ctx->pollfd_modify_lock); * Only signal an event if there are no prior pending events. */
ctx->pollfd_modify++; usbi_mutex_lock(&ctx->event_data_lock);
usbi_mutex_unlock(&ctx->pollfd_modify_lock); pending_events = usbi_pending_events(ctx);
ctx->device_close++;
/* write some data on control pipe to interrupt event handlers */ if (!pending_events)
r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); usbi_signal_event(ctx);
if (r <= 0) { usbi_mutex_unlock(&ctx->event_data_lock);
usbi_warn(ctx, "internal signalling write failed, closing anyway");
do_close(ctx, dev_handle);
usbi_mutex_lock(&ctx->pollfd_modify_lock);
ctx->pollfd_modify--;
usbi_mutex_unlock(&ctx->pollfd_modify_lock);
return;
}
/* take event handling lock */ /* take event handling lock */
libusb_lock_events(ctx); libusb_lock_events(ctx);
/* read the dummy data */
r = usbi_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy));
if (r <= 0)
usbi_warn(ctx, "internal signalling read failed, closing anyway");
/* Close the device */ /* Close the device */
do_close(ctx, dev_handle); do_close(ctx, dev_handle);
/* we're done with modifying poll fds */ /* We're done with closing this device.
usbi_mutex_lock(&ctx->pollfd_modify_lock); * Clear the event pipe if there are no further pending events. */
ctx->pollfd_modify--; usbi_mutex_lock(&ctx->event_data_lock);
usbi_mutex_unlock(&ctx->pollfd_modify_lock); ctx->device_close--;
pending_events = usbi_pending_events(ctx);
if (!pending_events)
usbi_clear_event(ctx);
usbi_mutex_unlock(&ctx->event_data_lock);
/* Release event handling lock and wake up event waiters */ /* Release event handling lock and wake up event waiters */
libusb_unlock_events(ctx); libusb_unlock_events(ctx);
@ -1413,7 +1528,8 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev,
* *
* \param dev a device handle * \param dev a device handle
* \param configuration the bConfigurationValue of the configuration you * \param configuration the bConfigurationValue of the configuration you
* wish to activate, or -1 if you wish to put the device in unconfigured state * wish to activate, or -1 if you wish to put the device in an unconfigured
* state
* \returns 0 on success * \returns 0 on success
* \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist * \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist
* \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed * \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed
@ -1907,8 +2023,8 @@ int API_EXPORTED libusb_init(libusb_context **context)
usbi_dbg("created default context"); usbi_dbg("created default context");
} }
usbi_dbg("libusb v%d.%d.%d.%d", libusb_version_internal.major, libusb_version_internal.minor, usbi_dbg("libusb v%u.%u.%u.%u%s", libusb_version_internal.major, libusb_version_internal.minor,
libusb_version_internal.micro, libusb_version_internal.nano); libusb_version_internal.micro, libusb_version_internal.nano, libusb_version_internal.rc);
usbi_mutex_init(&ctx->usb_devs_lock, NULL); usbi_mutex_init(&ctx->usb_devs_lock, NULL);
usbi_mutex_init(&ctx->open_devs_lock, NULL); usbi_mutex_init(&ctx->open_devs_lock, NULL);
@ -1946,8 +2062,10 @@ err_backend_exit:
if (usbi_backend->exit) if (usbi_backend->exit)
usbi_backend->exit(); usbi_backend->exit();
err_free_ctx: err_free_ctx:
if (ctx == usbi_default_context) if (ctx == usbi_default_context) {
usbi_default_context = NULL; usbi_default_context = NULL;
default_context_refcnt--;
}
usbi_mutex_static_lock(&active_contexts_lock); usbi_mutex_static_lock(&active_contexts_lock);
list_del (&ctx->list); list_del (&ctx->list);
@ -2191,8 +2309,8 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
usbi_gettimeofday(&now, NULL); usbi_gettimeofday(&now, NULL);
if ((global_debug) && (!has_debug_header_been_displayed)) { if ((global_debug) && (!has_debug_header_been_displayed)) {
has_debug_header_been_displayed = 1; has_debug_header_been_displayed = 1;
usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] <message>\n"); usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] <message>" USBI_LOG_LINE_END);
usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------\n"); usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END);
} }
if (now.tv_usec < timestamp_origin.tv_usec) { if (now.tv_usec < timestamp_origin.tv_usec) {
now.tv_sec--; now.tv_sec--;

View File

@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <config.h>
#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@ -453,7 +455,7 @@ static int parse_configuration(struct libusb_context *ctx,
(header.bDescriptorType == LIBUSB_DT_DEVICE)) (header.bDescriptorType == LIBUSB_DT_DEVICE))
break; break;
usbi_dbg("skipping descriptor 0x%x\n", header.bDescriptorType); usbi_dbg("skipping descriptor 0x%x", header.bDescriptorType);
buffer += header.bLength; buffer += header.bLength;
size -= header.bLength; size -= header.bLength;
} }

View File

@ -43,7 +43,7 @@
* *
* \page hotplug Device hotplug event notification * \page hotplug Device hotplug event notification
* *
* \section intro Introduction * \section hotplug_intro Introduction
* *
* Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support * 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 * for hotplug events on <b>some</b> platforms (you should test if your platform
@ -203,6 +203,30 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
/* the backend is expected to call the callback for each active transfer */ /* the backend is expected to call the callback for each active transfer */
} }
void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event)
{
int pending_events;
libusb_hotplug_message *message = calloc(1, sizeof(*message));
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, int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
libusb_hotplug_event events, libusb_hotplug_flag flags, libusb_hotplug_event events, libusb_hotplug_flag flags,
int vendor_id, int product_id, int dev_class, int vendor_id, int product_id, int dev_class,
@ -285,8 +309,6 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx
libusb_hotplug_callback_handle handle) libusb_hotplug_callback_handle handle)
{ {
struct libusb_hotplug_callback *hotplug_cb; struct libusb_hotplug_callback *hotplug_cb;
libusb_hotplug_message message;
ssize_t ret;
/* check for hotplug support */ /* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
@ -305,12 +327,7 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx
} }
usbi_mutex_unlock(&ctx->hotplug_cbs_lock); usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
/* wakeup handle_events to do the actual free */ usbi_hotplug_notification(ctx, NULL, 0);
memset(&message, 0, sizeof(message));
ret = usbi_write(ctx->hotplug_pipe[1], &message, sizeof(message));
if (sizeof(message) != ret) {
usbi_err(ctx, "error writing hotplug message");
}
} }
void usbi_hotplug_deregister_all(struct libusb_context *ctx) { void usbi_hotplug_deregister_all(struct libusb_context *ctx) {

View File

@ -69,8 +69,14 @@ struct libusb_hotplug_callback {
typedef struct libusb_hotplug_callback libusb_hotplug_callback; typedef struct libusb_hotplug_callback libusb_hotplug_callback;
struct libusb_hotplug_message { struct libusb_hotplug_message {
/** The hotplug event that occurred */
libusb_hotplug_event event; libusb_hotplug_event event;
/** The device for which this hotplug event occurred */
struct libusb_device *device; struct libusb_device *device;
/** List this message is contained in (ctx->hotplug_msgs) */
struct list_head list;
}; };
typedef struct libusb_hotplug_message libusb_hotplug_message; typedef struct libusb_hotplug_message libusb_hotplug_message;
@ -78,5 +84,7 @@ typedef struct libusb_hotplug_message libusb_hotplug_message;
void usbi_hotplug_deregister_all(struct libusb_context *ctx); void usbi_hotplug_deregister_all(struct libusb_context *ctx);
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event); libusb_hotplug_event event);
void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -80,6 +80,8 @@ EXPORTS
libusb_get_parent@4 = libusb_get_parent libusb_get_parent@4 = libusb_get_parent
libusb_get_pollfds libusb_get_pollfds
libusb_get_pollfds@4 = libusb_get_pollfds libusb_get_pollfds@4 = libusb_get_pollfds
libusb_free_pollfds
libusb_free_pollfds@4 = libusb_free_pollfds
libusb_get_port_number libusb_get_port_number
libusb_get_port_number@4 = libusb_get_port_number libusb_get_port_number@4 = libusb_get_port_number
libusb_get_port_numbers libusb_get_port_numbers

View File

@ -54,7 +54,7 @@ typedef unsigned __int32 uint32_t;
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) #if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
#include <sys/time.h> #include <sys/time.h>
#endif #endif
@ -90,7 +90,7 @@ typedef unsigned __int32 uint32_t;
* Under Windows, the selection of available compilers and configurations * Under Windows, the selection of available compilers and configurations
* means that, unlike other platforms, there is not <em>one true calling * means that, unlike other platforms, there is not <em>one true calling
* convention</em> (calling convention: the manner in which parameters are * convention</em> (calling convention: the manner in which parameters are
* passed to funcions in the generated assembly code). * passed to functions in the generated assembly code).
* *
* Matching the Windows API itself, libusb uses the WINAPI convention (which * Matching the Windows API itself, libusb uses the WINAPI convention (which
* translates to the <tt>stdcall</tt> convention) and guarantees that the * translates to the <tt>stdcall</tt> convention) and guarantees that the
@ -138,13 +138,10 @@ typedef unsigned __int32 uint32_t;
* #endif * #endif
* \endcode * \endcode
* *
* Another feature of LIBUSB_API_VERSION is that it can be used to detect
* whether you are compiling against the libusb or the libusb library.
*
* Internally, LIBUSB_API_VERSION is defined as follows: * Internally, LIBUSB_API_VERSION is defined as follows:
* (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
*/ */
#define LIBUSB_API_VERSION 0x01000103 #define LIBUSB_API_VERSION 0x01000104
/* The following is kept for compatibility, but will be deprecated in the future */ /* The following is kept for compatibility, but will be deprecated in the future */
#define LIBUSBX_API_VERSION LIBUSB_API_VERSION #define LIBUSBX_API_VERSION LIBUSB_API_VERSION
@ -668,8 +665,9 @@ struct libusb_config_descriptor {
uint8_t bmAttributes; uint8_t bmAttributes;
/** Maximum power consumption of the USB device from this bus in this /** Maximum power consumption of the USB device from this bus in this
* configuration when the device is fully opreation. Expressed in units * configuration when the device is fully operation. Expressed in units
* of 2 mA. */ * of 2 mA when the device is operating in high-speed mode and in units
* of 8 mA when the device is operating in super-speed mode. */
uint8_t MaxPower; uint8_t MaxPower;
/** Array of interfaces supported by this configuration. The length of /** Array of interfaces supported by this configuration. The length of
@ -900,7 +898,6 @@ struct libusb_control_setup {
struct libusb_context; struct libusb_context;
struct libusb_device; struct libusb_device;
struct libusb_device_handle; struct libusb_device_handle;
struct libusb_hotplug_callback;
/** \ingroup lib /** \ingroup lib
* Structure providing the version of the libusb runtime * Structure providing the version of the libusb runtime
@ -1860,6 +1857,7 @@ typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data);
const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
libusb_context *ctx); libusb_context *ctx);
void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds);
void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx,
libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
void *user_data); void *user_data);
@ -1884,8 +1882,11 @@ typedef int libusb_hotplug_callback_handle;
* *
* Flags for hotplug events */ * Flags for hotplug events */
typedef enum { typedef enum {
/** Default value when not using any flags. */
LIBUSB_HOTPLUG_NO_FLAGS = 0,
/** Arm the callback and fire it for all matching currently attached devices. */ /** Arm the callback and fire it for all matching currently attached devices. */
LIBUSB_HOTPLUG_ENUMERATE = 1, LIBUSB_HOTPLUG_ENUMERATE = 1<<0,
} libusb_hotplug_flag; } libusb_hotplug_flag;
/** \ingroup hotplug /** \ingroup hotplug

View File

@ -21,7 +21,7 @@
#ifndef LIBUSBI_H #ifndef LIBUSBI_H
#define LIBUSBI_H #define LIBUSBI_H
#include "config.h" #include <config.h>
#include <stdlib.h> #include <stdlib.h>
@ -32,10 +32,10 @@
#ifdef HAVE_POLL_H #ifdef HAVE_POLL_H
#include <poll.h> #include <poll.h>
#endif #endif
#ifdef HAVE_MISSING_H #ifdef HAVE_MISSING_H
#include "missing.h" #include <missing.h>
#endif #endif
#include "libusb.h" #include "libusb.h"
#include "version.h" #include "version.h"
@ -48,6 +48,10 @@
*/ */
#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY #define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY
#ifdef __cplusplus
extern "C" {
#endif
#define DEVICE_DESC_LENGTH 18 #define DEVICE_DESC_LENGTH 18
#define USB_MAXENDPOINTS 32 #define USB_MAXENDPOINTS 32
@ -82,6 +86,9 @@ struct list_head {
#define list_entry(ptr, type, member) \ #define list_entry(ptr, type, member) \
((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member))) ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/* Get each entry from a list /* Get each entry from a list
* pos - A structure pointer has a "member" element * pos - A structure pointer has a "member" element
* head - list head * head - list head
@ -144,8 +151,12 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
const typeof( ((type *)0)->member ) *mptr = (ptr); \ const typeof( ((type *)0)->member ) *mptr = (ptr); \
(type *)( (char *)mptr - offsetof(type,member) );}) (type *)( (char *)mptr - offsetof(type,member) );})
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0) #define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0)
@ -228,13 +239,15 @@ static inline void usbi_dbg(const char *format, ...)
extern struct libusb_context *usbi_default_context; extern struct libusb_context *usbi_default_context;
/* Forward declaration for use in context (fully defined inside poll abstraction) */
struct pollfd;
struct libusb_context { struct libusb_context {
int debug; int debug;
int debug_fixed; int debug_fixed;
/* internal control pipe, used for interrupting event handling when /* internal event pipe, used for signalling occurrence of an internal event. */
* something needs to modify poll fds. */ int event_pipe[2];
int ctrl_pipe[2];
struct list_head usb_devs; struct list_head usb_devs;
usbi_mutex_t usb_devs_lock; usbi_mutex_t usb_devs_lock;
@ -247,7 +260,6 @@ struct libusb_context {
/* A list of registered hotplug callbacks */ /* A list of registered hotplug callbacks */
struct list_head hotplug_cbs; struct list_head hotplug_cbs;
usbi_mutex_t hotplug_cbs_lock; usbi_mutex_t hotplug_cbs_lock;
int hotplug_pipe[2];
/* this is a list of in-flight transfer handles, sorted by timeout /* this is a list of in-flight transfer handles, sorted by timeout
* expiration. URBs to timeout the soonest are placed at the beginning of * expiration. URBs to timeout the soonest are placed at the beginning of
@ -256,15 +268,6 @@ struct libusb_context {
struct list_head flying_transfers; struct list_head flying_transfers;
usbi_mutex_t flying_transfers_lock; usbi_mutex_t flying_transfers_lock;
/* list of poll fds */
struct list_head pollfds;
usbi_mutex_t pollfds_lock;
/* a counter that is set when we want to interrupt event handling, in order
* to modify the poll fd set. and a lock to protect it. */
unsigned int pollfd_modify;
usbi_mutex_t pollfd_modify_lock;
/* user callbacks for pollfd changes */ /* user callbacks for pollfd changes */
libusb_pollfd_added_cb fd_added_cb; libusb_pollfd_added_cb fd_added_cb;
libusb_pollfd_removed_cb fd_removed_cb; libusb_pollfd_removed_cb fd_removed_cb;
@ -281,6 +284,28 @@ struct libusb_context {
usbi_mutex_t event_waiters_lock; usbi_mutex_t event_waiters_lock;
usbi_cond_t event_waiters_cond; usbi_cond_t event_waiters_cond;
/* A lock to protect internal context event data. */
usbi_mutex_t event_data_lock;
/* A counter that is set when we want to interrupt and prevent event handling,
* in order to safely close a device. Protected by event_data_lock. */
unsigned int device_close;
/* list and count of poll fds and an array of poll fd structures that is
* (re)allocated as necessary prior to polling, and a flag to indicate
* when the list of poll fds has changed since the last poll.
* Protected by event_data_lock. */
struct list_head ipollfds;
struct pollfd *pollfds;
POLL_NFDS_TYPE pollfds_cnt;
unsigned int pollfds_modified;
/* A list of pending hotplug messages. Protected by event_data_lock. */
struct list_head hotplug_msgs;
/* A list of pending completed transfers. Protected by event_data_lock. */
struct list_head completed_transfers;
#ifdef USBI_TIMERFD_AVAILABLE #ifdef USBI_TIMERFD_AVAILABLE
/* used for timeout handling, if supported by OS. /* used for timeout handling, if supported by OS.
* this timerfd is maintained to trigger on the next pending timeout */ * this timerfd is maintained to trigger on the next pending timeout */
@ -290,6 +315,11 @@ struct libusb_context {
struct list_head list; struct list_head list;
}; };
/* Update the following macro if new event sources are added */
#define usbi_pending_events(ctx) \
((ctx)->device_close || (ctx)->pollfds_modified \
|| !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers))
#ifdef USBI_TIMERFD_AVAILABLE #ifdef USBI_TIMERFD_AVAILABLE
#define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0) #define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0)
#else #else
@ -364,6 +394,7 @@ enum {
struct usbi_transfer { struct usbi_transfer {
int num_iso_packets; int num_iso_packets;
struct list_head list; struct list_head list;
struct list_head completed_list;
struct timeval timeout; struct timeval timeout;
int transferred; int transferred;
uint32_t stream_id; uint32_t stream_id;
@ -377,6 +408,10 @@ struct usbi_transfer {
* its completion (presumably there would be races within your OS backend * its completion (presumably there would be races within your OS backend
* if this were possible). */ * if this were possible). */
usbi_mutex_t lock; usbi_mutex_t lock;
/* this lock should be held whenever viewing or modifying flags
* relating to the transfer state */
usbi_mutex_t flags_lock;
}; };
enum usbi_transfer_flags { enum usbi_transfer_flags {
@ -392,8 +427,17 @@ enum usbi_transfer_flags {
/* Operation on the transfer failed because the device disappeared */ /* Operation on the transfer failed because the device disappeared */
USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 3, USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 3,
/* Set by backend submit_transfer() if the fds in use have been updated */ /* Transfer is currently being submitted */
USBI_TRANSFER_UPDATED_FDS = 1 << 4, USBI_TRANSFER_SUBMITTING = 1 << 4,
/* Transfer successfully submitted by backend */
USBI_TRANSFER_IN_FLIGHT = 1 << 5,
/* Completion handler has run */
USBI_TRANSFER_COMPLETED = 1 << 6,
/* The transfer timeout has been handled */
USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 7,
}; };
#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ #define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \
@ -434,6 +478,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle);
int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
enum libusb_transfer_status status); enum libusb_transfer_status status);
int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer); int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer);
void usbi_signal_transfer_completion(struct usbi_transfer *transfer);
int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
void *dest, int host_endian); void *dest, int host_endian);
@ -444,8 +489,11 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
void usbi_connect_device (struct libusb_device *dev); void usbi_connect_device (struct libusb_device *dev);
void usbi_disconnect_device (struct libusb_device *dev); void usbi_disconnect_device (struct libusb_device *dev);
int usbi_signal_event(struct libusb_context *ctx);
int usbi_clear_event(struct libusb_context *ctx);
/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */ /* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) #if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU)
#include <unistd.h> #include <unistd.h>
#include "os/poll_posix.h" #include "os/poll_posix.h"
#elif defined(OS_WINDOWS) || defined(OS_WINCE) #elif defined(OS_WINDOWS) || defined(OS_WINCE)
@ -474,7 +522,6 @@ struct usbi_pollfd {
int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events); int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events);
void usbi_remove_pollfd(struct libusb_context *ctx, int fd); void usbi_remove_pollfd(struct libusb_context *ctx, int fd);
void usbi_fd_notification(struct libusb_context *ctx);
/* device discovery */ /* device discovery */
@ -765,7 +812,7 @@ struct usbi_os_backend {
* This function should not generate any bus I/O and should not block. * This function should not generate any bus I/O and should not block.
* Interface claiming is a logical operation that simply ensures that * Interface claiming is a logical operation that simply ensures that
* no other drivers/applications are using the interface, and after * no other drivers/applications are using the interface, and after
* claiming, no other drivers/applicatiosn can use the interface because * claiming, no other drivers/applications can use the interface because
* we now "own" it. * we now "own" it.
* *
* Return: * Return:
@ -943,8 +990,14 @@ struct usbi_os_backend {
*/ */
void (*clear_transfer_priv)(struct usbi_transfer *itransfer); void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
/* Handle any pending events. This involves monitoring any active /* Handle any pending events on file descriptors. Optional.
* transfers and processing their completion or cancellation. *
* Provide this function when file descriptors directly indicate device
* or transfer activity. If your backend does not have such file descriptors,
* implement the handle_transfer_completion function below.
*
* This involves monitoring any active transfers and processing their
* completion or cancellation.
* *
* The function is passed an array of pollfd structures (size nfds) * The function is passed an array of pollfd structures (size nfds)
* as a result of the poll() system call. The num_ready parameter * as a result of the poll() system call. The num_ready parameter
@ -972,6 +1025,31 @@ struct usbi_os_backend {
int (*handle_events)(struct libusb_context *ctx, int (*handle_events)(struct libusb_context *ctx,
struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
/* Handle transfer completion. Optional.
*
* Provide this function when there are no file descriptors available
* that directly indicate device or transfer activity. If your backend does
* have such file descriptors, implement the handle_events function above.
*
* Your backend must tell the library when a transfer has completed by
* calling usbi_signal_transfer_completion(). You should store any private
* information about the transfer and its completion status in the transfer's
* private backend data.
*
* During event handling, this function will be called on each transfer for
* which usbi_signal_transfer_completion() was called.
*
* For any cancelled transfers, call usbi_handle_transfer_cancellation().
* For completed transfers, call usbi_handle_transfer_completion().
* For control/bulk/interrupt transfers, populate the "transferred"
* element of the appropriate usbi_transfer structure before calling the
* above functions. For isochronous transfers, populate the status and
* transferred fields of the iso packet descriptors of the transfer.
*
* Return 0 on success, or a LIBUSB_ERROR code on failure.
*/
int (*handle_transfer_completion)(struct usbi_transfer *itransfer);
/* Get time from specified clock. At least two clocks must be implemented /* Get time from specified clock. At least two clocks must be implemented
by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC.
@ -1002,12 +1080,6 @@ struct usbi_os_backend {
* usbi_transfer_get_os_priv() on the appropriate usbi_transfer instance. * usbi_transfer_get_os_priv() on the appropriate usbi_transfer instance.
*/ */
size_t transfer_priv_size; size_t transfer_priv_size;
/* Mumber of additional bytes for os_priv for each iso packet.
* Can your backend use this? */
/* FIXME: linux can't use this any more. if other OS's cannot either,
* then remove this */
size_t add_iso_packet_size;
}; };
extern const struct usbi_os_backend * const usbi_backend; extern const struct usbi_os_backend * const usbi_backend;
@ -1018,8 +1090,13 @@ extern const struct usbi_os_backend openbsd_backend;
extern const struct usbi_os_backend netbsd_backend; extern const struct usbi_os_backend netbsd_backend;
extern const struct usbi_os_backend windows_backend; extern const struct usbi_os_backend windows_backend;
extern const struct usbi_os_backend wince_backend; extern const struct usbi_os_backend wince_backend;
extern const struct usbi_os_backend haiku_usb_raw_backend;
extern struct list_head active_contexts_list; extern struct list_head active_contexts_list;
extern usbi_mutex_static_t active_contexts_lock; extern usbi_mutex_static_t active_contexts_lock;
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -246,7 +246,7 @@ static usb_device_t **darwin_device_from_service (io_service_t service)
&score); &score);
if (kIOReturnSuccess != result || !plugInInterface) { if (kIOReturnSuccess != result || !plugInInterface) {
usbi_dbg ("could not set up plugin for service: %s\n", darwin_error_str (result)); usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (result));
return NULL; return NULL;
} }
@ -279,6 +279,7 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
struct libusb_device *dev = NULL; struct libusb_device *dev = NULL;
struct libusb_context *ctx; struct libusb_context *ctx;
struct darwin_cached_device *old_device;
io_service_t device; io_service_t device;
UInt64 session; UInt64 session;
@ -293,6 +294,17 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
if (!ret) if (!ret)
continue; continue;
/* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function
otherwise no cached device will ever get freed */
usbi_mutex_lock(&darwin_cached_devices_lock);
list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
if (old_device->session == session) {
darwin_deref_cached_device (old_device);
break;
}
}
usbi_mutex_unlock(&darwin_cached_devices_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
usbi_dbg ("notifying context %p of device disconnect", ctx); usbi_dbg ("notifying context %p of device disconnect", ctx);
@ -973,14 +985,6 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
/* device opened successfully */ /* device opened successfully */
dpriv->open_count++; dpriv->open_count++;
/* create a file descriptor for notifications */
pipe (priv->fds);
/* set the pipe to be non-blocking */
fcntl (priv->fds[1], F_SETFD, O_NONBLOCK);
usbi_add_pollfd(HANDLE_CTX(dev_handle), priv->fds[0], POLLIN);
usbi_dbg ("device open for access"); usbi_dbg ("device open for access");
return 0; return 0;
@ -994,7 +998,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
if (dpriv->open_count == 0) { if (dpriv->open_count == 0) {
/* something is probably very wrong if this is the case */ /* something is probably very wrong if this is the case */
usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!\n"); usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!");
return; return;
} }
@ -1024,13 +1028,6 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
} }
} }
} }
/* file descriptors are maintained per-instance */
usbi_remove_pollfd (HANDLE_CTX (dev_handle), priv->fds[0]);
close (priv->fds[1]);
close (priv->fds[0]);
priv->fds[0] = priv->fds[1] = -1;
} }
static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) { static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) {
@ -1761,9 +1758,7 @@ static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) {
static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) { static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) {
struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon; struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon;
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
struct darwin_msg_async_io_complete message = {.itransfer = itransfer, .result = result,
.size = (UInt32) (uintptr_t) arg0};
usbi_dbg ("an async io operation has completed"); usbi_dbg ("an async io operation has completed");
@ -1777,8 +1772,11 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
(*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0); (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0);
} }
/* send a completion message to the device's file descriptor */ tpriv->result = result;
write (priv->fds[1], &message, sizeof (message)); tpriv->size = (UInt32) (uintptr_t) arg0;
/* signal the core that this transfer is complete */
usbi_signal_transfer_completion(itransfer);
} }
static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) { static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
@ -1807,7 +1805,7 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
} }
} }
static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type; int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
@ -1818,13 +1816,13 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return
if (!isIsoc && !isBulk && !isControl && !isInterrupt) { if (!isIsoc && !isBulk && !isControl && !isInterrupt) {
usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
return; return LIBUSB_ERROR_INVALID_PARAM;
} }
usbi_dbg ("handling %s completion with kernel status %d", usbi_dbg ("handling %s completion with kernel status %d",
isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", result); isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result);
if (kIOReturnSuccess == result || kIOReturnUnderrun == result) { if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) {
if (isIsoc && tpriv->isoc_framelist) { if (isIsoc && tpriv->isoc_framelist) {
/* copy isochronous results back */ /* copy isochronous results back */
@ -1834,48 +1832,11 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return
lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount; lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
} }
} else if (!isIsoc) } else if (!isIsoc)
itransfer->transferred += io_size; itransfer->transferred += tpriv->size;
} }
/* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */ /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */
usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, result)); return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result));
}
static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) {
struct darwin_msg_async_io_complete message;
POLL_NFDS_TYPE i = 0;
ssize_t ret;
usbi_mutex_lock(&ctx->open_devs_lock);
for (i = 0; i < nfds && num_ready > 0; i++) {
struct pollfd *pollfd = &fds[i];
usbi_dbg ("checking fd %i with revents = %x", pollfd->fd, pollfd->revents);
if (!pollfd->revents)
continue;
num_ready--;
if (pollfd->revents & POLLERR) {
/* this probably will never happen so ignore the error an move on. */
continue;
}
/* there is only one type of message */
ret = read (pollfd->fd, &message, sizeof (message));
if (ret < (ssize_t) sizeof (message)) {
usbi_dbg ("WARNING: short read on async io completion pipe\n");
continue;
}
darwin_handle_callback (message.itransfer, message.result, message.size);
}
usbi_mutex_unlock(&ctx->open_devs_lock);
return 0;
} }
static int darwin_clock_gettime(int clk_id, struct timespec *tp) { static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
@ -1998,12 +1959,11 @@ const struct usbi_os_backend darwin_backend = {
.cancel_transfer = darwin_cancel_transfer, .cancel_transfer = darwin_cancel_transfer,
.clear_transfer_priv = darwin_clear_transfer_priv, .clear_transfer_priv = darwin_clear_transfer_priv,
.handle_events = op_handle_events, .handle_transfer_completion = darwin_handle_transfer_completion,
.clock_gettime = darwin_clock_gettime, .clock_gettime = darwin_clock_gettime,
.device_priv_size = sizeof(struct darwin_device_priv), .device_priv_size = sizeof(struct darwin_device_priv),
.device_handle_priv_size = sizeof(struct darwin_device_handle_priv), .device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
.transfer_priv_size = sizeof(struct darwin_transfer_priv), .transfer_priv_size = sizeof(struct darwin_transfer_priv),
.add_iso_packet_size = 0,
}; };

View File

@ -28,7 +28,7 @@
#include <IOKit/IOCFPlugIn.h> #include <IOKit/IOCFPlugIn.h>
/* IOUSBInterfaceInferface */ /* IOUSBInterfaceInferface */
#if defined (kIOUSBInterfaceInterfaceID550) #if defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
#define usb_interface_t IOUSBInterfaceInterface550 #define usb_interface_t IOUSBInterfaceInterface550
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550
@ -65,7 +65,7 @@
#endif #endif
/* IOUSBDeviceInterface */ /* IOUSBDeviceInterface */
#if defined (kIOUSBDeviceInterfaceID500) #if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
#define usb_device_t IOUSBDeviceInterface500 #define usb_device_t IOUSBDeviceInterface500
#define DeviceInterfaceID kIOUSBDeviceInterfaceID500 #define DeviceInterfaceID kIOUSBDeviceInterfaceID500
@ -130,7 +130,6 @@ struct darwin_device_priv {
struct darwin_device_handle_priv { struct darwin_device_handle_priv {
int is_open; int is_open;
CFRunLoopSourceRef cfSource; CFRunLoopSourceRef cfSource;
int fds[2];
struct darwin_interface { struct darwin_interface {
usb_interface_t **interface; usb_interface_t **interface;
@ -150,11 +149,8 @@ struct darwin_transfer_priv {
IOUSBDevRequestTO req; IOUSBDevRequestTO req;
/* Bulk */ /* Bulk */
};
/* structure for signaling io completion */ /* Completion status */
struct darwin_msg_async_io_complete {
struct usbi_transfer *itransfer;
IOReturn result; IOReturn result;
UInt32 size; UInt32 size;
}; };

View File

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

View File

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

347
Externals/libusb/libusb/os/haiku/compile vendored Normal file
View File

@ -0,0 +1,347 @@
#! /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

17579
Externals/libusb/libusb/os/haiku/configure vendored Normal file

File diff suppressed because it is too large Load Diff

View File

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

791
Externals/libusb/libusb/os/haiku/depcomp vendored Normal file
View File

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

View File

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

View File

@ -0,0 +1,112 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <List.h>
#include <Locker.h>
#include <Autolock.h>
#include <USBKit.h>
#include <map>
#include "libusbi.h"
#include "haiku_usb_raw.h"
using namespace std;
class USBDevice;
class USBDeviceHandle;
class USBTransfer;
class USBDevice {
public:
USBDevice(const char *);
virtual ~USBDevice();
const char* Location() const;
uint8 CountConfigurations() const;
const usb_device_descriptor* Descriptor() const;
const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const;
const usb_configuration_descriptor* ActiveConfiguration() const;
uint8 EndpointToIndex(uint8) const;
uint8 EndpointToInterface(uint8) const;
int ClaimInterface(int);
int ReleaseInterface(int);
int CheckInterfacesFree(int);
int SetActiveConfiguration(int);
int ActiveConfigurationIndex() const;
bool InitCheck();
private:
int Initialise();
unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask
usb_device_descriptor fDeviceDescriptor;
unsigned char** fConfigurationDescriptors;
int fActiveConfiguration;
char* fPath;
map<uint8,uint8> fConfigToIndex;
map<uint8,uint8>* fEndpointToIndex;
map<uint8,uint8>* fEndpointToInterface;
bool fInitCheck;
};
class USBDeviceHandle {
public:
USBDeviceHandle(USBDevice* dev);
virtual ~USBDeviceHandle();
int ClaimInterface(int);
int ReleaseInterface(int);
int SetConfiguration(int);
int SetAltSetting(int,int);
status_t SubmitTransfer(struct usbi_transfer*);
status_t CancelTransfer(USBTransfer*);
bool InitCheck();
private:
int fRawFD;
static status_t TransfersThread(void *);
void TransfersWorker();
USBDevice* fUSBDevice;
unsigned int fClaimedInterfaces;
BList fTransfers;
BLocker fTransfersLock;
sem_id fTransfersSem;
thread_id fTransfersThread;
bool fInitCheck;
};
class USBTransfer {
public:
USBTransfer(struct usbi_transfer*,USBDevice*);
virtual ~USBTransfer();
void Do(int);
struct usbi_transfer* UsbiTransfer();
void SetCancelled();
bool IsCancelled();
private:
struct usbi_transfer* fUsbiTransfer;
struct libusb_transfer* fLibusbTransfer;
USBDevice* fUSBDevice;
BLocker fStatusLock;
bool fCancelled;
};
class USBRoster {
public:
USBRoster();
virtual ~USBRoster();
int Start();
void Stop();
private:
void* fLooper;
};

View File

@ -0,0 +1,550 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#include "haiku_usb.h"
int _errno_to_libusb(int status)
{
return status;
}
USBTransfer::USBTransfer(struct usbi_transfer* itransfer, USBDevice* device)
{
fUsbiTransfer=itransfer;
fLibusbTransfer=USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
fUSBDevice=device;
fCancelled=false;
}
USBTransfer::~USBTransfer()
{
}
struct usbi_transfer*
USBTransfer::UsbiTransfer()
{
return fUsbiTransfer;
}
void
USBTransfer::SetCancelled()
{
fCancelled=true;
}
bool
USBTransfer::IsCancelled()
{
return fCancelled;
}
void
USBTransfer::Do(int fRawFD)
{
switch(fLibusbTransfer->type)
{
case LIBUSB_TRANSFER_TYPE_CONTROL:
{
struct libusb_control_setup* setup=(struct libusb_control_setup*)fLibusbTransfer->buffer;
usb_raw_command command;
command.control.request_type=setup->bmRequestType;
command.control.request=setup->bRequest;
command.control.value=setup->wValue;
command.control.index=setup->wIndex;
command.control.length=setup->wLength;
command.control.data=fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
if(fCancelled)
{
break;
}
if(ioctl(fRawFD,B_USB_RAW_COMMAND_CONTROL_TRANSFER,&command,
sizeof(command)) || command.control.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed control transfer");
break;
}
fUsbiTransfer->transferred=command.control.length;
}
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
{
usb_raw_command command;
command.transfer.interface=fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
command.transfer.endpoint=fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
command.transfer.data=fLibusbTransfer->buffer;
command.transfer.length=fLibusbTransfer->length;
if(fCancelled)
{
break;
}
if(fLibusbTransfer->type==LIBUSB_TRANSFER_TYPE_BULK)
{
if(ioctl(fRawFD,B_USB_RAW_COMMAND_BULK_TRANSFER,&command,
sizeof(command)) || command.transfer.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed bulk transfer");
break;
}
}
else
{
if(ioctl(fRawFD,B_USB_RAW_COMMAND_INTERRUPT_TRANSFER,&command,
sizeof(command)) || command.transfer.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed interrupt transfer");
break;
}
}
fUsbiTransfer->transferred=command.transfer.length;
}
break;
// IsochronousTransfers not tested
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
{
usb_raw_command command;
command.isochronous.interface=fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint);
command.isochronous.endpoint=fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint);
command.isochronous.data=fLibusbTransfer->buffer;
command.isochronous.length=fLibusbTransfer->length;
command.isochronous.packet_count=fLibusbTransfer->num_iso_packets;
int i=0;
usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets];
for (i=0; i<fLibusbTransfer->num_iso_packets; i++)
{
if((int16)(fLibusbTransfer->iso_packet_desc[i]).length!=(fLibusbTransfer->iso_packet_desc[i]).length)
{
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed isochronous transfer");
break;
}
packetDescriptors[i].request_length=(int16)(fLibusbTransfer->iso_packet_desc[i]).length;
}
if(i<fLibusbTransfer->num_iso_packets)
{
break; // TODO Handle this error
}
command.isochronous.packet_descriptors=packetDescriptors;
if(fCancelled)
{
break;
}
if(ioctl(fRawFD,B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER,&command,
sizeof(command)) || command.isochronous.status!=B_USB_RAW_STATUS_SUCCESS) {
fUsbiTransfer->transferred=-1;
usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed isochronous transfer");
break;
}
for (i=0; i<fLibusbTransfer->num_iso_packets; i++)
{
(fLibusbTransfer->iso_packet_desc[i]).actual_length=packetDescriptors[i].actual_length;
switch(packetDescriptors[i].status)
{
case B_OK: (fLibusbTransfer->iso_packet_desc[i]).status=LIBUSB_TRANSFER_COMPLETED;
break;
default: (fLibusbTransfer->iso_packet_desc[i]).status=LIBUSB_TRANSFER_ERROR;
break;
}
}
delete[] packetDescriptors;
// Do we put the length of transfer here, for isochronous transfers?
fUsbiTransfer->transferred=command.transfer.length;
}
break;
default:
usbi_err(TRANSFER_CTX(fLibusbTransfer),"Unknown type of transfer");
}
}
bool
USBDeviceHandle::InitCheck()
{
return fInitCheck;
}
status_t
USBDeviceHandle::TransfersThread(void* self)
{
USBDeviceHandle* handle = (USBDeviceHandle*)self;
handle->TransfersWorker();
return B_OK;
}
void
USBDeviceHandle::TransfersWorker()
{
while(true)
{
status_t status = acquire_sem(fTransfersSem);
if(status== B_BAD_SEM_ID)
break;
if(status == B_INTERRUPTED)
continue;
fTransfersLock.Lock();
USBTransfer* fPendingTransfer= (USBTransfer*) fTransfers.RemoveItem((int32)0);
fTransfersLock.Unlock();
fPendingTransfer->Do(fRawFD);
usbi_signal_transfer_completion(fPendingTransfer->UsbiTransfer());
}
}
status_t
USBDeviceHandle::SubmitTransfer(struct usbi_transfer* itransfer)
{
USBTransfer* transfer = new USBTransfer(itransfer,fUSBDevice);
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=transfer;
BAutolock locker(fTransfersLock);
fTransfers.AddItem(transfer);
release_sem(fTransfersSem);
return LIBUSB_SUCCESS;
}
status_t
USBDeviceHandle::CancelTransfer(USBTransfer* transfer)
{
transfer->SetCancelled();
fTransfersLock.Lock();
bool removed = fTransfers.RemoveItem(transfer);
fTransfersLock.Unlock();
if(removed)
{
usbi_signal_transfer_completion(transfer->UsbiTransfer());
}
return LIBUSB_SUCCESS;
}
USBDeviceHandle::USBDeviceHandle(USBDevice* dev)
:
fTransfersThread(-1),
fUSBDevice(dev),
fClaimedInterfaces(0),
fInitCheck(false)
{
fRawFD=open(dev->Location(), O_RDWR | O_CLOEXEC);
if(fRawFD < 0)
{
usbi_err(NULL,"failed to open device");
return;
}
fTransfersSem = create_sem(0, "Transfers Queue Sem");
fTransfersThread = spawn_thread(TransfersThread,"Transfer Worker",B_NORMAL_PRIORITY, this);
resume_thread(fTransfersThread);
fInitCheck = true;
}
USBDeviceHandle::~USBDeviceHandle()
{
if(fRawFD>0)
close(fRawFD);
for(int i=0; i<32; i++)
{
if(fClaimedInterfaces&(1<<i))
ReleaseInterface(i);
}
delete_sem(fTransfersSem);
if(fTransfersThread>0)
wait_for_thread(fTransfersThread, NULL);
}
int
USBDeviceHandle::ClaimInterface(int inumber)
{
int status=fUSBDevice->ClaimInterface(inumber);
if(status==LIBUSB_SUCCESS)
{
fClaimedInterfaces|=(1<<inumber);
}
return status;
}
int
USBDeviceHandle::ReleaseInterface(int inumber)
{
fUSBDevice->ReleaseInterface(inumber);
fClaimedInterfaces&=(!(1<<inumber));
return LIBUSB_SUCCESS;
}
int
USBDeviceHandle::SetConfiguration(int config)
{
int config_index=fUSBDevice->CheckInterfacesFree(config);
if(config_index==LIBUSB_ERROR_BUSY || config_index==LIBUSB_ERROR_NOT_FOUND)
return config_index;
usb_raw_command command;
command.config.config_index=config_index;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_SET_CONFIGURATION,&command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
return _errno_to_libusb(command.config.status);
}
fUSBDevice->SetActiveConfiguration(config_index);
return LIBUSB_SUCCESS;
}
int
USBDeviceHandle::SetAltSetting(int inumber, int alt)
{
usb_raw_command command;
command.alternate.config_index=fUSBDevice->ActiveConfigurationIndex();
command.alternate.interface_index=inumber;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX,&command,
sizeof(command)) || command.alternate.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"Error retrieving active alternate interface");
return _errno_to_libusb(command.alternate.status);
}
if(command.alternate.alternate_info == alt)
{
usbi_dbg("Setting alternate interface successful");
return LIBUSB_SUCCESS;
}
command.alternate.alternate_info = alt;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_SET_ALT_INTERFACE,&command, //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY
sizeof(command)) || command.alternate.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"Error setting alternate interface");
return _errno_to_libusb(command.alternate.status);
}
usbi_dbg("Setting alternate interface successful");
return LIBUSB_SUCCESS;
}
USBDevice::USBDevice(const char * path)
:
fPath(NULL),
fActiveConfiguration(0), //0?
fConfigurationDescriptors(NULL),
fClaimedInterfaces(0),
fEndpointToIndex(NULL),
fEndpointToInterface(NULL),
fInitCheck(false)
{
fPath=strdup(path);
Initialise();
}
USBDevice::~USBDevice()
{
free(fPath);
if (fConfigurationDescriptors)
{
for(int i=0;i<fDeviceDescriptor.num_configurations;i++)
{
if (fConfigurationDescriptors[i])
delete fConfigurationDescriptors[i];
}
delete[] fConfigurationDescriptors;
}
if (fEndpointToIndex)
delete[] fEndpointToIndex;
if (fEndpointToInterface)
delete[] fEndpointToInterface;
}
bool
USBDevice::InitCheck()
{
return fInitCheck;
}
const char*
USBDevice::Location() const
{
return fPath;
}
uint8
USBDevice::CountConfigurations() const
{
return fDeviceDescriptor.num_configurations;
}
const usb_device_descriptor*
USBDevice::Descriptor() const
{
return &fDeviceDescriptor;
}
const usb_configuration_descriptor*
USBDevice::ConfigurationDescriptor(uint32 index) const
{
if(index>CountConfigurations())
return NULL;
return (usb_configuration_descriptor*) fConfigurationDescriptors[index];
}
const usb_configuration_descriptor*
USBDevice::ActiveConfiguration() const
{
return (usb_configuration_descriptor*) fConfigurationDescriptors[fActiveConfiguration];
}
int
USBDevice::ActiveConfigurationIndex() const
{
return fActiveConfiguration;
}
int USBDevice::ClaimInterface(int interface)
{
if(interface>ActiveConfiguration()->number_interfaces)
{
return LIBUSB_ERROR_NOT_FOUND;
}
if((fClaimedInterfaces & (1<<interface)) !=0 )
return LIBUSB_ERROR_BUSY;
fClaimedInterfaces|=(1<<interface);
return LIBUSB_SUCCESS;
}
int USBDevice::ReleaseInterface(int interface)
{
fClaimedInterfaces&=(!(1<<interface));
return LIBUSB_SUCCESS;
}
int
USBDevice::CheckInterfacesFree(int config)
{
if(fConfigToIndex.count(config)==0)
return LIBUSB_ERROR_NOT_FOUND;
if(fClaimedInterfaces==0)
return fConfigToIndex[(uint8)config];
return LIBUSB_ERROR_BUSY;
}
int
USBDevice::SetActiveConfiguration(int config_index)
{
fActiveConfiguration=config_index;
return LIBUSB_SUCCESS;
}
uint8
USBDevice::EndpointToIndex(uint8 address) const
{
return fEndpointToIndex[fActiveConfiguration][address];
}
uint8
USBDevice::EndpointToInterface(uint8 address) const
{
return fEndpointToInterface[fActiveConfiguration][address];
}
int
USBDevice::Initialise() //Do we need more error checking, etc? How to report?
{
int fRawFD=open(fPath, O_RDWR | O_CLOEXEC);
if(fRawFD < 0)
return B_ERROR;
usb_raw_command command;
command.device.descriptor = &fDeviceDescriptor;
if(ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command,
sizeof(command)) || command.device.status != B_USB_RAW_STATUS_SUCCESS) {
close(fRawFD);
return B_ERROR;
}
size_t size;
fConfigurationDescriptors = new(std::nothrow) unsigned char*[fDeviceDescriptor.num_configurations];
fEndpointToIndex = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
fEndpointToInterface = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
for( int i=0; i<fDeviceDescriptor.num_configurations; i++)
{
size=0;
usb_configuration_descriptor tmp_config;
command.config.descriptor = &tmp_config;
command.config.config_index = i;
if(ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving configuration descriptor");
close(fRawFD);
return B_ERROR;
}
fConfigToIndex[tmp_config.configuration_value]=i;
fConfigurationDescriptors[i]=new(std::nothrow) unsigned char[tmp_config.total_length];
command.control.request_type=128;
command.control.request=6;
command.control.value=(2<<8)|i;
command.control.index=0;
command.control.length=tmp_config.total_length;
command.control.data=fConfigurationDescriptors[i];
if(ioctl(fRawFD,B_USB_RAW_COMMAND_CONTROL_TRANSFER,&command,
sizeof(command)) || command.control.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving full configuration descriptor");
close(fRawFD);
return B_ERROR;
}
for( int j=0;j<tmp_config.number_interfaces;j++)
{
command.alternate.config_index=i;
command.alternate.interface_index=j;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving number of alternate interfaces");
close(fRawFD);
return B_ERROR;
}
int num_alternate=command.alternate.alternate_info;
for( int k=0;k<num_alternate;k++)
{
usb_interface_descriptor tmp_interface;
command.interface_etc.config_index=i;
command.interface_etc.interface_index=j;
command.interface_etc.alternate_index=k;
command.interface_etc.descriptor=&tmp_interface;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving interface descriptor");
close(fRawFD);
return B_ERROR;
}
for( int l=0;l<tmp_interface.num_endpoints;l++)
{
usb_endpoint_descriptor tmp_endpoint;
command.endpoint_etc.config_index=i;
command.endpoint_etc.interface_index=j;
command.endpoint_etc.alternate_index=k;
command.endpoint_etc.endpoint_index=l;
command.endpoint_etc.descriptor=&tmp_endpoint;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving endpoint descriptor");
close(fRawFD);
return B_ERROR;
}
fEndpointToIndex[i][tmp_endpoint.endpoint_address]=l;
fEndpointToInterface[i][tmp_endpoint.endpoint_address]=j;
}
}
}
}
close(fRawFD);
fInitCheck = true;
return B_OK;
}

View File

@ -0,0 +1,255 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#include "haiku_usb.h"
USBRoster gUsbRoster;
int32 gInitCount = 0;
static int
haiku_init(struct libusb_context* ctx)
{
if (atomic_add(&gInitCount, 1) == 0)
{
return gUsbRoster.Start();
}
return LIBUSB_SUCCESS;
}
static void
haiku_exit(void)
{
if (atomic_add(&gInitCount, -1) == 1)
gUsbRoster.Stop();
}
static int
haiku_open(struct libusb_device_handle *dev_handle)
{
USBDevice* dev=*((USBDevice**)dev_handle->dev->os_priv);
USBDeviceHandle *handle=new(std::nothrow) USBDeviceHandle(dev);
if (handle == NULL)
return LIBUSB_ERROR_NO_MEM;
if (handle->InitCheck() == false)
{
delete handle;
return LIBUSB_ERROR_NO_DEVICE;
}
*((USBDeviceHandle**)dev_handle->os_priv)=handle;
return LIBUSB_SUCCESS;
}
static void
haiku_close(struct libusb_device_handle *dev_handle)
{
USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv);
if(handle==NULL)
return;
delete handle;
*((USBDeviceHandle**)dev_handle->os_priv)=NULL;
}
static int
haiku_get_device_descriptor(struct libusb_device *device, unsigned char* buffer, int *host_endian)
{
USBDevice *dev = *((USBDevice**)(device->os_priv));
memcpy(buffer,dev->Descriptor(),DEVICE_DESC_LENGTH);
*host_endian=0;
return LIBUSB_SUCCESS;
}
static int
haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
{
USBDevice *dev = *((USBDevice**)(device->os_priv));
const usb_configuration_descriptor* act_config = dev->ActiveConfiguration();
if(len>act_config->total_length)
{
return LIBUSB_ERROR_OVERFLOW;
}
memcpy(buffer,act_config,len);
*host_endian=0;
return LIBUSB_SUCCESS;
}
static int
haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
{
USBDevice *dev = *((USBDevice**)(device->os_priv));
const usb_configuration_descriptor* config = dev->ConfigurationDescriptor(config_index);
if(config==NULL)
{
usbi_err(DEVICE_CTX(device),"failed getting configuration descriptor");
return LIBUSB_ERROR_INVALID_PARAM;
}
if(len>config->total_length)
len=config->total_length;
memcpy(buffer,(unsigned char*)config,len);
*host_endian=0;
return len;
}
static int
haiku_set_configuration(struct libusb_device_handle *dev_handle, int config)
{
USBDeviceHandle * handle= *((USBDeviceHandle**)dev_handle->os_priv);
return handle->SetConfiguration(config);
}
static int
haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
{
USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv);
return handle->ClaimInterface(interface_number);
}
static int
haiku_set_altsetting(struct libusb_device_handle* dev_handle, int interface_number, int altsetting)
{
USBDeviceHandle* handle = *((USBDeviceHandle**)dev_handle->os_priv);
return handle->SetAltSetting(interface_number, altsetting);
}
static int
haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
{
USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv);
haiku_set_altsetting(dev_handle,interface_number,0);
return handle->ReleaseInterface(interface_number);
}
static int
haiku_submit_transfer(struct usbi_transfer * itransfer)
{
struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv);
return fDeviceHandle->SubmitTransfer(itransfer);
}
static int
haiku_cancel_transfer(struct usbi_transfer * itransfer)
{
struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv);
return fDeviceHandle->CancelTransfer(*((USBTransfer**)usbi_transfer_get_os_priv(itransfer)));
}
static void
haiku_clear_transfer_priv(struct usbi_transfer * itransfer)
{
USBTransfer* transfer=*((USBTransfer**)usbi_transfer_get_os_priv(itransfer));
delete transfer;
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL;
}
static int
haiku_handle_transfer_completion(struct usbi_transfer * itransfer)
{
USBTransfer* transfer=*((USBTransfer**)usbi_transfer_get_os_priv(itransfer));
usbi_mutex_lock(&itransfer->lock);
if(transfer->IsCancelled())
{
delete transfer;
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL;
usbi_mutex_unlock(&itransfer->lock);
if (itransfer->transferred < 0)
itransfer->transferred = 0;
return usbi_handle_transfer_cancellation(itransfer);
}
libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
if(itransfer->transferred < 0)
{
usbi_err(ITRANSFER_CTX(itransfer), "error in transfer");
status = LIBUSB_TRANSFER_ERROR;
itransfer->transferred=0;
}
delete transfer;
*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL;
usbi_mutex_unlock(&itransfer->lock);
return usbi_handle_transfer_completion(itransfer, status);
}
static int
haiku_clock_gettime(int clkid, struct timespec *tp)
{
if(clkid == USBI_CLOCK_REALTIME)
return clock_gettime(CLOCK_REALTIME, tp);
if(clkid == USBI_CLOCK_MONOTONIC)
return clock_gettime(CLOCK_MONOTONIC, tp);
return LIBUSB_ERROR_INVALID_PARAM;
}
const struct usbi_os_backend haiku_usb_raw_backend = {
/*.name =*/ "Haiku usbfs",
/*.caps =*/ 0,
/*.init =*/ haiku_init,
/*.exit =*/ haiku_exit,
/*.get_device_list =*/ NULL,
/*.hotplug_poll =*/ NULL,
/*.open =*/ haiku_open,
/*.close =*/ haiku_close,
/*.get_device_descriptor =*/ haiku_get_device_descriptor,
/*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor,
/*.get_config_descriptor =*/ haiku_get_config_descriptor,
/*.get_config_descriptor_by_value =*/ NULL,
/*.get_configuration =*/ NULL,
/*.set_configuration =*/ haiku_set_configuration,
/*.claim_interface =*/ haiku_claim_interface,
/*.release_interface =*/ haiku_release_interface,
/*.set_interface_altsetting =*/ haiku_set_altsetting,
/*.clear_halt =*/ NULL,
/*.reset_device =*/ NULL,
/*.alloc_streams =*/ NULL,
/*.free_streams =*/ NULL,
/*.kernel_driver_active =*/ NULL,
/*.detach_kernel_driver =*/ NULL,
/*.attach_kernel_driver =*/ NULL,
/*.destroy_device =*/ NULL,
/*.submit_transfer =*/ haiku_submit_transfer,
/*.cancel_transfer =*/ haiku_cancel_transfer,
/*.clear_transfer_priv =*/ haiku_clear_transfer_priv,
/*.handle_events =*/ NULL,
/*.handle_transfer_completion =*/ haiku_handle_transfer_completion,
/*.clock_gettime =*/ haiku_clock_gettime,
#ifdef USBI_TIMERFD_AVAILABLE
/*.get_timerfd_clockid =*/ NULL,
#endif
/*.device_priv_size =*/ sizeof(USBDevice*),
/*.device_handle_priv_size =*/ sizeof(USBDeviceHandle*),
/*.transfer_priv_size =*/ sizeof(USBTransfer*),
};

View File

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

View File

@ -0,0 +1,501 @@
#!/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:

9655
Externals/libusb/libusb/os/haiku/ltmain.sh vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -0,0 +1,98 @@
# 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])])

215
Externals/libusb/libusb/os/haiku/missing vendored Normal file
View File

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

View File

@ -20,10 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "config.h" #include <config.h>
#include "libusb.h"
#include "libusbi.h"
#include "linux_usbfs.h"
#include <ctype.h> #include <ctype.h>
#include <dirent.h> #include <dirent.h>
@ -53,6 +50,9 @@
#include <linux/filter.h> #include <linux/filter.h>
#endif #endif
#include "libusbi.h"
#include "linux_usbfs.h"
#define KERNEL 1 #define KERNEL 1
static int linux_netlink_socket = -1; static int linux_netlink_socket = -1;

View File

@ -20,7 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "config.h" #include <config.h>
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
@ -39,7 +39,6 @@
#include <unistd.h> #include <unistd.h>
#include <libudev.h> #include <libudev.h>
#include "libusb.h"
#include "libusbi.h" #include "libusbi.h"
#include "linux_usbfs.h" #include "linux_usbfs.h"

View File

@ -38,7 +38,6 @@
#include <sys/utsname.h> #include <sys/utsname.h>
#include <unistd.h> #include <unistd.h>
#include "libusb.h"
#include "libusbi.h" #include "libusbi.h"
#include "linux_usbfs.h" #include "linux_usbfs.h"
@ -199,7 +198,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
if (errno == ENOENT) { if (errno == ENOENT) {
if (!silent) if (!silent)
usbi_err(ctx, "File doesn't exist, wait %d ms and try again\n", delay/1000); usbi_err(ctx, "File doesn't exist, wait %d ms and try again", delay/1000);
/* Wait 10ms for USB device path creation.*/ /* Wait 10ms for USB device path creation.*/
usleep(delay); usleep(delay);
@ -308,6 +307,14 @@ static const char *find_usbfs_path(void)
} }
} }
/* On udev based systems without any usb-devices /dev/bus/usb will not
* exist. So if we've not found anything and we're using udev for hotplug
* simply assume /dev/bus/usb rather then making libusb_init fail. */
#if defined(USE_UDEV)
if (ret == NULL)
ret = "/dev/bus/usb";
#endif
if (ret != NULL) if (ret != NULL)
usbi_dbg("found usbfs at %s", ret); usbi_dbg("found usbfs at %s", ret);
@ -632,9 +639,9 @@ int linux_get_device_address (struct libusb_context *ctx, int detached,
/* will this work with all supported kernel versions? */ /* will this work with all supported kernel versions? */
if (!strncmp(dev_node, "/dev/bus/usb", 12)) { if (!strncmp(dev_node, "/dev/bus/usb", 12)) {
sscanf (dev_node, "/dev/bus/usb/%hhd/%hhd", busnum, devaddr); sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
} else if (!strncmp(dev_node, "/proc/bus/usb", 13)) { } else if (!strncmp(dev_node, "/proc/bus/usb", 13)) {
sscanf (dev_node, "/proc/bus/usb/%hhd/%hhd", busnum, devaddr); sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr);
} }
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
@ -998,6 +1005,9 @@ static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_di
} }
parent_sysfs_dir = strdup(sysfs_dir); parent_sysfs_dir = strdup(sysfs_dir);
if (NULL == parent_sysfs_dir) {
return LIBUSB_ERROR_NO_MEM;
}
if (NULL != (tmp = strrchr(parent_sysfs_dir, '.')) || if (NULL != (tmp = strrchr(parent_sysfs_dir, '.')) ||
NULL != (tmp = strrchr(parent_sysfs_dir, '-'))) { NULL != (tmp = strrchr(parent_sysfs_dir, '-'))) {
dev->port_number = atoi(tmp + 1); dev->port_number = atoi(tmp + 1);
@ -1765,10 +1775,6 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
int bulk_buffer_len, use_bulk_continuation; int bulk_buffer_len, use_bulk_continuation;
int r; int r;
int i; int i;
size_t alloc_size;
if (tpriv->urbs)
return LIBUSB_ERROR_BUSY;
if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) && if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) &&
!(dpriv->caps & USBFS_CAP_ZERO_PACKET)) !(dpriv->caps & USBFS_CAP_ZERO_PACKET))
@ -1827,8 +1833,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
} }
usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, usbi_dbg("need %d urbs for new transfer with length %d", num_urbs,
transfer->length); transfer->length);
alloc_size = num_urbs * sizeof(struct usbfs_urb); urbs = calloc(num_urbs, sizeof(struct usbfs_urb));
urbs = calloc(1, alloc_size);
if (!urbs) if (!urbs)
return LIBUSB_ERROR_NO_MEM; return LIBUSB_ERROR_NO_MEM;
tpriv->urbs = urbs; tpriv->urbs = urbs;
@ -1946,18 +1951,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
unsigned int packet_len; unsigned int packet_len;
unsigned char *urb_buffer = transfer->buffer; unsigned char *urb_buffer = transfer->buffer;
if (tpriv->iso_urbs) /* usbfs places arbitrary limits on iso URBs. this limit has changed
return LIBUSB_ERROR_BUSY; * at least three times, and it's difficult to accurately detect which
* limit this running kernel might impose. so we attempt to submit
/* usbfs places a 32kb limit on iso URBs. we divide up larger requests * whatever the user has provided. if the kernel rejects the request
* into smaller units to meet such restriction, then fire off all the * due to its size, we return an error indicating such to the user.
* units at once. it would be simpler if we just fired one unit at a time,
* but there is a big performance gain through doing it this way.
*
* Newer kernels lift the 32k limit (USBFS_CAP_NO_PACKET_SIZE_LIM),
* using arbritary large transfers is still be a bad idea though, as
* the kernel needs to allocate physical contiguous memory for this,
* which may fail for large buffers.
*/ */
/* calculate how many URBs we need */ /* calculate how many URBs we need */
@ -1968,14 +1966,16 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
if (packet_len > space_remaining) { if (packet_len > space_remaining) {
num_urbs++; num_urbs++;
this_urb_len = packet_len; this_urb_len = packet_len;
/* check that we can actually support this packet length */
if (this_urb_len > MAX_ISO_BUFFER_LENGTH)
return LIBUSB_ERROR_INVALID_PARAM;
} else { } else {
this_urb_len += packet_len; this_urb_len += packet_len;
} }
} }
usbi_dbg("need %d 32k URBs for transfer", num_urbs); usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024);
alloc_size = num_urbs * sizeof(*urbs); urbs = calloc(num_urbs, sizeof(*urbs));
urbs = calloc(1, alloc_size);
if (!urbs) if (!urbs)
return LIBUSB_ERROR_NO_MEM; return LIBUSB_ERROR_NO_MEM;
@ -2040,6 +2040,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
if (r < 0) { if (r < 0) {
if (errno == ENODEV) { if (errno == ENODEV) {
r = LIBUSB_ERROR_NO_DEVICE; r = LIBUSB_ERROR_NO_DEVICE;
} else if (errno == EINVAL) {
usbi_warn(TRANSFER_CTX(transfer),
"submiturb failed, transfer too large");
r = LIBUSB_ERROR_INVALID_PARAM;
} else { } else {
usbi_err(TRANSFER_CTX(transfer), usbi_err(TRANSFER_CTX(transfer),
"submiturb failed error %d errno=%d", r, errno); "submiturb failed error %d errno=%d", r, errno);
@ -2093,9 +2097,6 @@ static int submit_control_transfer(struct usbi_transfer *itransfer)
struct usbfs_urb *urb; struct usbfs_urb *urb;
int r; int r;
if (tpriv->urbs)
return LIBUSB_ERROR_BUSY;
if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH) if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH)
return LIBUSB_ERROR_INVALID_PARAM; return LIBUSB_ERROR_INVALID_PARAM;
@ -2153,6 +2154,14 @@ static int op_cancel_transfer(struct usbi_transfer *itransfer)
struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
struct libusb_transfer *transfer = struct libusb_transfer *transfer =
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
int r;
if (!tpriv->urbs)
return LIBUSB_ERROR_NOT_FOUND;
r = discard_urbs(itransfer, 0, tpriv->num_urbs);
if (r != 0)
return r;
switch (transfer->type) { switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_BULK:
@ -2160,21 +2169,11 @@ static int op_cancel_transfer(struct usbi_transfer *itransfer)
if (tpriv->reap_action == ERROR) if (tpriv->reap_action == ERROR)
break; break;
/* else, fall through */ /* else, fall through */
case LIBUSB_TRANSFER_TYPE_CONTROL:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
tpriv->reap_action = CANCELLED;
break;
default: default:
usbi_err(TRANSFER_CTX(transfer), tpriv->reap_action = CANCELLED;
"unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
} }
if (!tpriv->urbs) return 0;
return LIBUSB_ERROR_NOT_FOUND;
return discard_urbs(itransfer, 0, tpriv->num_urbs);
} }
static void op_clear_transfer_priv(struct usbi_transfer *itransfer) static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
@ -2189,17 +2188,16 @@ static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_BULK_STREAM: case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_INTERRUPT:
usbi_mutex_lock(&itransfer->lock); if (tpriv->urbs) {
if (tpriv->urbs)
free(tpriv->urbs); free(tpriv->urbs);
tpriv->urbs = NULL; tpriv->urbs = NULL;
usbi_mutex_unlock(&itransfer->lock); }
break; break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
usbi_mutex_lock(&itransfer->lock); if (tpriv->iso_urbs) {
if (tpriv->iso_urbs)
free_iso_urbs(tpriv); free_iso_urbs(tpriv);
usbi_mutex_unlock(&itransfer->lock); tpriv->iso_urbs = NULL;
}
break; break;
default: default:
usbi_err(TRANSFER_CTX(transfer), usbi_err(TRANSFER_CTX(transfer),
@ -2591,7 +2589,7 @@ static int op_handle_events(struct libusb_context *ctx,
} }
if (!hpriv || hpriv->fd != pollfd->fd) { if (!hpriv || hpriv->fd != pollfd->fd) {
usbi_err(ctx, "cannot find handle for fd %d\n", usbi_err(ctx, "cannot find handle for fd %d",
pollfd->fd); pollfd->fd);
continue; continue;
} }
@ -2691,5 +2689,4 @@ const struct usbi_os_backend linux_usbfs_backend = {
.device_priv_size = sizeof(struct linux_device_priv), .device_priv_size = sizeof(struct linux_device_priv),
.device_handle_priv_size = sizeof(struct linux_device_handle_priv), .device_handle_priv_size = sizeof(struct linux_device_handle_priv),
.transfer_priv_size = sizeof(struct linux_transfer_priv), .transfer_priv_size = sizeof(struct linux_transfer_priv),
.add_iso_packet_size = 0,
}; };

View File

@ -81,7 +81,7 @@ struct usbfs_iso_packet_desc {
unsigned int status; unsigned int status;
}; };
#define MAX_ISO_BUFFER_LENGTH 32768 #define MAX_ISO_BUFFER_LENGTH 49152 * 128
#define MAX_BULK_BUFFER_LENGTH 16384 #define MAX_BULK_BUFFER_LENGTH 16384
#define MAX_CTRL_BUFFER_LENGTH 4096 #define MAX_CTRL_BUFFER_LENGTH 4096

View File

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <config.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
@ -28,7 +30,6 @@
#include <dev/usb/usb.h> #include <dev/usb/usb.h>
#include "libusb.h"
#include "libusbi.h" #include "libusbi.h"
struct device_priv { struct device_priv {
@ -40,7 +41,6 @@ struct device_priv {
}; };
struct handle_priv { struct handle_priv {
int pipe[2]; /* for event notification */
int endpoints[USB_MAX_ENDPOINTS]; int endpoints[USB_MAX_ENDPOINTS];
}; };
@ -74,8 +74,7 @@ static void netbsd_destroy_device(struct libusb_device *);
static int netbsd_submit_transfer(struct usbi_transfer *); static int netbsd_submit_transfer(struct usbi_transfer *);
static int netbsd_cancel_transfer(struct usbi_transfer *); static int netbsd_cancel_transfer(struct usbi_transfer *);
static void netbsd_clear_transfer_priv(struct usbi_transfer *); static void netbsd_clear_transfer_priv(struct usbi_transfer *);
static int netbsd_handle_events(struct libusb_context *ctx, struct pollfd *, static int netbsd_handle_transfer_completion(struct usbi_transfer *);
nfds_t, int);
static int netbsd_clock_gettime(int, struct timespec *); static int netbsd_clock_gettime(int, struct timespec *);
/* /*
@ -125,13 +124,13 @@ const struct usbi_os_backend netbsd_backend = {
netbsd_cancel_transfer, netbsd_cancel_transfer,
netbsd_clear_transfer_priv, netbsd_clear_transfer_priv,
netbsd_handle_events, NULL, /* handle_events() */
netbsd_handle_transfer_completion,
netbsd_clock_gettime, netbsd_clock_gettime,
sizeof(struct device_priv), sizeof(struct device_priv),
sizeof(struct handle_priv), sizeof(struct handle_priv),
0, /* transfer_priv_size */ 0, /* transfer_priv_size */
0, /* add_iso_packet_size */
}; };
int int
@ -222,10 +221,7 @@ netbsd_open(struct libusb_device_handle *handle)
usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
if (pipe(hpriv->pipe) < 0) return (LIBUSB_SUCCESS);
return _errno_to_libusb(errno);
return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN);
} }
void void
@ -238,11 +234,6 @@ netbsd_close(struct libusb_device_handle *handle)
close(dpriv->fd); close(dpriv->fd);
dpriv->fd = -1; dpriv->fd = -1;
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
close(hpriv->pipe[0]);
close(hpriv->pipe[1]);
} }
int int
@ -469,8 +460,7 @@ netbsd_submit_transfer(struct usbi_transfer *itransfer)
if (err) if (err)
return (err); return (err);
if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0) usbi_signal_transfer_completion(itransfer);
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS); return (LIBUSB_SUCCESS);
} }
@ -492,63 +482,9 @@ netbsd_clear_transfer_priv(struct usbi_transfer *itransfer)
} }
int int
netbsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, netbsd_handle_transfer_completion(struct usbi_transfer *itransfer)
int num_ready)
{ {
struct libusb_device_handle *handle; return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
struct handle_priv *hpriv = NULL;
struct usbi_transfer *itransfer;
struct pollfd *pollfd;
int i, err = 0;
usbi_dbg("");
pthread_mutex_lock(&ctx->open_devs_lock);
for (i = 0; i < nfds && num_ready > 0; i++) {
pollfd = &fds[i];
if (!pollfd->revents)
continue;
hpriv = NULL;
num_ready--;
list_for_each_entry(handle, &ctx->open_devs, list,
struct libusb_device_handle) {
hpriv = (struct handle_priv *)handle->os_priv;
if (hpriv->pipe[0] == pollfd->fd)
break;
hpriv = NULL;
}
if (NULL == hpriv) {
usbi_dbg("fd %d is not an event pipe!", pollfd->fd);
err = ENOENT;
break;
}
if (pollfd->revents & POLLERR) {
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
usbi_handle_disconnect(handle);
continue;
}
if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) {
err = errno;
break;
}
if ((err = usbi_handle_transfer_completion(itransfer,
LIBUSB_TRANSFER_COMPLETED)))
break;
}
pthread_mutex_unlock(&ctx->open_devs_lock);
if (err)
return _errno_to_libusb(err);
return (LIBUSB_SUCCESS);
} }
int int

View File

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <config.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
@ -28,7 +30,6 @@
#include <dev/usb/usb.h> #include <dev/usb/usb.h>
#include "libusb.h"
#include "libusbi.h" #include "libusbi.h"
struct device_priv { struct device_priv {
@ -40,7 +41,6 @@ struct device_priv {
}; };
struct handle_priv { struct handle_priv {
int pipe[2]; /* for event notification */
int endpoints[USB_MAX_ENDPOINTS]; int endpoints[USB_MAX_ENDPOINTS];
}; };
@ -74,8 +74,7 @@ static void obsd_destroy_device(struct libusb_device *);
static int obsd_submit_transfer(struct usbi_transfer *); static int obsd_submit_transfer(struct usbi_transfer *);
static int obsd_cancel_transfer(struct usbi_transfer *); static int obsd_cancel_transfer(struct usbi_transfer *);
static void obsd_clear_transfer_priv(struct usbi_transfer *); static void obsd_clear_transfer_priv(struct usbi_transfer *);
static int obsd_handle_events(struct libusb_context *ctx, struct pollfd *, static int obsd_handle_transfer_completion(struct usbi_transfer *);
nfds_t, int);
static int obsd_clock_gettime(int, struct timespec *); static int obsd_clock_gettime(int, struct timespec *);
/* /*
@ -128,13 +127,13 @@ const struct usbi_os_backend openbsd_backend = {
obsd_cancel_transfer, obsd_cancel_transfer,
obsd_clear_transfer_priv, obsd_clear_transfer_priv,
obsd_handle_events, NULL, /* handle_events() */
obsd_handle_transfer_completion,
obsd_clock_gettime, obsd_clock_gettime,
sizeof(struct device_priv), sizeof(struct device_priv),
sizeof(struct handle_priv), sizeof(struct handle_priv),
0, /* transfer_priv_size */ 0, /* transfer_priv_size */
0, /* add_iso_packet_size */
}; };
#define DEVPATH "/dev/" #define DEVPATH "/dev/"
@ -262,10 +261,7 @@ obsd_open(struct libusb_device_handle *handle)
usbi_dbg("open %s: fd %d", devnode, dpriv->fd); usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
} }
if (pipe(hpriv->pipe) < 0) return (LIBUSB_SUCCESS);
return _errno_to_libusb(errno);
return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN);
} }
void void
@ -280,11 +276,6 @@ obsd_close(struct libusb_device_handle *handle)
close(dpriv->fd); close(dpriv->fd);
dpriv->fd = -1; dpriv->fd = -1;
} }
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
close(hpriv->pipe[0]);
close(hpriv->pipe[1]);
} }
int int
@ -515,8 +506,7 @@ obsd_submit_transfer(struct usbi_transfer *itransfer)
if (err) if (err)
return (err); return (err);
if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0) usbi_signal_transfer_completion(itransfer);
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS); return (LIBUSB_SUCCESS);
} }
@ -538,63 +528,9 @@ obsd_clear_transfer_priv(struct usbi_transfer *itransfer)
} }
int int
obsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, obsd_handle_transfer_completion(struct usbi_transfer *itransfer)
int num_ready)
{ {
struct libusb_device_handle *handle; return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
struct handle_priv *hpriv = NULL;
struct usbi_transfer *itransfer;
struct pollfd *pollfd;
int i, err = 0;
usbi_dbg("");
pthread_mutex_lock(&ctx->open_devs_lock);
for (i = 0; i < nfds && num_ready > 0; i++) {
pollfd = &fds[i];
if (!pollfd->revents)
continue;
hpriv = NULL;
num_ready--;
list_for_each_entry(handle, &ctx->open_devs, list,
struct libusb_device_handle) {
hpriv = (struct handle_priv *)handle->os_priv;
if (hpriv->pipe[0] == pollfd->fd)
break;
hpriv = NULL;
}
if (NULL == hpriv) {
usbi_dbg("fd %d is not an event pipe!", pollfd->fd);
err = ENOENT;
break;
}
if (pollfd->revents & POLLERR) {
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
usbi_handle_disconnect(handle);
continue;
}
if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) {
err = errno;
break;
}
if ((err = usbi_handle_transfer_completion(itransfer,
LIBUSB_TRANSFER_COMPLETED)))
break;
}
pthread_mutex_unlock(&ctx->open_devs_lock);
if (err)
return _errno_to_libusb(err);
return (LIBUSB_SUCCESS);
} }
int int

View File

@ -18,6 +18,8 @@
* *
*/ */
#include <config.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>

View File

@ -40,6 +40,8 @@
* with a fake pipe. The read/write functions are only meant to be used in that * with a fake pipe. The read/write functions are only meant to be used in that
* context. * context.
*/ */
#include <config.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -331,7 +333,7 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer
wfd.cancel_fn = cancel_fn; wfd.cancel_fn = cancel_fn;
if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) { if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported.\n" usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. "
"If you want to poll for R/W simultaneously, create multiple fds from the same handle."); "If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
return INVALID_WINFD; return INVALID_WINFD;
} }

View File

@ -19,10 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <config.h>
#if defined(__linux__) || defined(__OpenBSD__) #if defined(__linux__) || defined(__OpenBSD__)
# if defined(__linux__) # if defined(__OpenBSD__)
# define _GNU_SOURCE
# else
# define _BSD_SOURCE # define _BSD_SOURCE
# endif # endif
# include <unistd.h> # include <unistd.h>

View File

@ -19,6 +19,7 @@
*/ */
#include <config.h> #include <config.h>
#include <objbase.h> #include <objbase.h>
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
@ -185,7 +186,8 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
// GetSystemTimeAsFileTime() is not available on CE // GetSystemTimeAsFileTime() is not available on CE
SYSTEMTIME st; SYSTEMTIME st;
GetSystemTime(&st); GetSystemTime(&st);
SystemTimeToFileTime(&st, &filetime); if (!SystemTimeToFileTime(&st, &filetime))
return 0;
rtime.LowPart = filetime.dwLowDateTime; rtime.LowPart = filetime.dwLowDateTime;
rtime.HighPart = filetime.dwHighDateTime; rtime.HighPart = filetime.dwHighDateTime;
rtime.QuadPart -= epoch_time; rtime.QuadPart -= epoch_time;

View File

@ -22,32 +22,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <libusbi.h> #include <config.h>
#include <stdint.h> #include <stdint.h>
#include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include "libusbi.h"
#include "wince_usb.h" #include "wince_usb.h"
// Forward declares
static int wince_clock_gettime(int clk_id, struct timespec *tp);
unsigned __stdcall wince_clock_gettime_threaded(void* param);
// Global variables // Global variables
uint64_t hires_frequency, hires_ticks_to_ps; uint64_t hires_frequency, hires_ticks_to_ps;
int errno; const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
int windows_version = WINDOWS_CE; int windows_version = WINDOWS_CE;
static int concurrent_usage = -1; static int concurrent_usage = -1;
// Timer thread
// NB: index 0 is for monotonic and 1 is for the thread exit event
HANDLE timer_thread = NULL;
HANDLE timer_mutex = NULL;
struct timespec timer_tp;
volatile LONG request_count[2] = {0, 1}; // last one must be > 0
HANDLE timer_request[2] = { NULL, NULL };
HANDLE timer_response = NULL;
HANDLE driver_handle = INVALID_HANDLE_VALUE; HANDLE driver_handle = INVALID_HANDLE_VALUE;
/* /*
@ -94,7 +81,7 @@ static char* windows_error_str(uint32_t retval)
static struct wince_device_priv *_device_priv(struct libusb_device *dev) static struct wince_device_priv *_device_priv(struct libusb_device *dev)
{ {
return (struct wince_device_priv *) dev->os_priv; return (struct wince_device_priv *) dev->os_priv;
} }
// ceusbkwrapper to libusb error code mapping // ceusbkwrapper to libusb error code mapping
@ -149,8 +136,9 @@ static int init_dllimports()
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
static int init_device(struct libusb_device *dev, UKW_DEVICE drv_dev, static int init_device(
unsigned char bus_addr, unsigned char dev_addr) struct libusb_device *dev, UKW_DEVICE drv_dev,
unsigned char bus_addr, unsigned char dev_addr)
{ {
struct wince_device_priv *priv = _device_priv(dev); struct wince_device_priv *priv = _device_priv(dev);
int r = LIBUSB_SUCCESS; int r = LIBUSB_SUCCESS;
@ -168,8 +156,9 @@ static int init_device(struct libusb_device *dev, UKW_DEVICE drv_dev,
// Internal API functions // Internal API functions
static int wince_init(struct libusb_context *ctx) static int wince_init(struct libusb_context *ctx)
{ {
int i, r = LIBUSB_ERROR_OTHER; int r = LIBUSB_ERROR_OTHER;
HANDLE semaphore; HANDLE semaphore;
LARGE_INTEGER li_frequency;
TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
_stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF); _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
@ -208,37 +197,17 @@ static int wince_init(struct libusb_context *ctx)
goto init_exit; goto init_exit;
} }
// Windows CE doesn't have a way of specifying thread affinity, so this code // find out if we have access to a monotonic (hires) timer
// just has to hope QueryPerformanceCounter doesn't report different values when if (QueryPerformanceFrequency(&li_frequency)) {
// running on different cores. hires_frequency = li_frequency.QuadPart;
r = LIBUSB_ERROR_NO_MEM; // The hires frequency can go as high as 4 GHz, so we'll use a conversion
for (i = 0; i < 2; i++) { // to picoseconds to compute the tv_nsecs part in clock_gettime
timer_request[i] = CreateEvent(NULL, TRUE, FALSE, NULL); hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
if (timer_request[i] == NULL) { usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
usbi_err(ctx, "could not create timer request event %d - aborting", i); } else {
goto init_exit; usbi_dbg("no hires timer available on this platform");
} hires_frequency = 0;
} hires_ticks_to_ps = UINT64_C(0);
timer_response = CreateSemaphore(NULL, 0, MAX_TIMER_SEMAPHORES, NULL);
if (timer_response == NULL) {
usbi_err(ctx, "could not create timer response semaphore - aborting");
goto init_exit;
}
timer_mutex = CreateMutex(NULL, FALSE, NULL);
if (timer_mutex == NULL) {
usbi_err(ctx, "could not create timer mutex - aborting");
goto init_exit;
}
timer_thread = CreateThread(NULL, 0, wince_clock_gettime_threaded, NULL, 0, NULL);
if (timer_thread == NULL) {
usbi_err(ctx, "Unable to create timer thread - aborting");
goto init_exit;
}
// Wait for timer thread to init before continuing.
if (WaitForSingleObject(timer_response, INFINITE) != WAIT_OBJECT_0) {
usbi_err(ctx, "Failed to wait for timer thread to become ready - aborting");
goto init_exit;
} }
} }
// At this stage, either we went through full init successfully, or didn't need to // At this stage, either we went through full init successfully, or didn't need to
@ -250,30 +219,6 @@ init_exit: // Holds semaphore here.
UkwCloseDriver(driver_handle); UkwCloseDriver(driver_handle);
driver_handle = INVALID_HANDLE_VALUE; driver_handle = INVALID_HANDLE_VALUE;
} }
if (timer_thread) {
SetEvent(timer_request[1]); // actually the signal to quit the thread.
if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) {
usbi_warn(ctx, "could not wait for timer thread to quit");
TerminateThread(timer_thread, 1); // shouldn't happen, but we're destroying
// all objects it might have held anyway.
}
CloseHandle(timer_thread);
timer_thread = NULL;
}
for (i = 0; i < 2; i++) {
if (timer_request[i]) {
CloseHandle(timer_request[i]);
timer_request[i] = NULL;
}
}
if (timer_response) {
CloseHandle(timer_response);
timer_response = NULL;
}
if (timer_mutex) {
CloseHandle(timer_mutex);
timer_mutex = NULL;
}
} }
if (r != LIBUSB_SUCCESS) if (r != LIBUSB_SUCCESS)
@ -286,7 +231,6 @@ init_exit: // Holds semaphore here.
static void wince_exit(void) static void wince_exit(void)
{ {
int i;
HANDLE semaphore; HANDLE semaphore;
TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
@ -307,29 +251,6 @@ static void wince_exit(void)
if (--concurrent_usage < 0) { // Last exit if (--concurrent_usage < 0) { // Last exit
exit_polling(); exit_polling();
if (timer_thread) {
SetEvent(timer_request[1]); // actually the signal to quit the thread.
if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) {
usbi_dbg("could not wait for timer thread to quit");
TerminateThread(timer_thread, 1);
}
CloseHandle(timer_thread);
timer_thread = NULL;
}
for (i = 0; i < 2; i++) {
if (timer_request[i]) {
CloseHandle(timer_request[i]);
timer_request[i] = NULL;
}
}
if (timer_response) {
CloseHandle(timer_response);
timer_response = NULL;
}
if (timer_mutex) {
CloseHandle(timer_mutex);
timer_mutex = NULL;
}
if (driver_handle != INVALID_HANDLE_VALUE) { if (driver_handle != INVALID_HANDLE_VALUE) {
UkwCloseDriver(driver_handle); UkwCloseDriver(driver_handle);
driver_handle = INVALID_HANDLE_VALUE; driver_handle = INVALID_HANDLE_VALUE;
@ -423,8 +344,8 @@ static void wince_close(struct libusb_device_handle *handle)
} }
static int wince_get_device_descriptor( static int wince_get_device_descriptor(
struct libusb_device *device, struct libusb_device *device,
unsigned char *buffer, int *host_endian) unsigned char *buffer, int *host_endian)
{ {
struct wince_device_priv *priv = _device_priv(device); struct wince_device_priv *priv = _device_priv(device);
@ -461,8 +382,8 @@ static int wince_get_config_descriptor(
} }
static int wince_get_configuration( static int wince_get_configuration(
struct libusb_device_handle *handle, struct libusb_device_handle *handle,
int *config) int *config)
{ {
struct wince_device_priv *priv = _device_priv(handle->dev); struct wince_device_priv *priv = _device_priv(handle->dev);
UCHAR cv = 0; UCHAR cv = 0;
@ -582,15 +503,13 @@ static int wince_attach_kernel_driver(
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
static void wince_destroy_device( static void wince_destroy_device(struct libusb_device *dev)
struct libusb_device *dev)
{ {
struct wince_device_priv *priv = _device_priv(dev); struct wince_device_priv *priv = _device_priv(dev);
UkwReleaseDeviceList(driver_handle, &priv->dev, 1); UkwReleaseDeviceList(driver_handle, &priv->dev, 1);
} }
static void wince_clear_transfer_priv( static void wince_clear_transfer_priv(struct usbi_transfer *itransfer)
struct usbi_transfer *itransfer)
{ {
struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd); struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd);
@ -600,8 +519,7 @@ static void wince_clear_transfer_priv(
usbi_free_fd(&transfer_priv->pollable_fd); usbi_free_fd(&transfer_priv->pollable_fd);
} }
static int wince_cancel_transfer( static int wince_cancel_transfer(struct usbi_transfer *itransfer)
struct usbi_transfer *itransfer)
{ {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
@ -667,7 +585,6 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer
return libusbErr; return libusbErr;
} }
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT); usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT);
itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
@ -677,8 +594,7 @@ static int wince_submit_iso_transfer(struct usbi_transfer *itransfer)
return LIBUSB_ERROR_NOT_SUPPORTED; return LIBUSB_ERROR_NOT_SUPPORTED;
} }
static int wince_submit_transfer( static int wince_submit_transfer(struct usbi_transfer *itransfer)
struct usbi_transfer *itransfer)
{ {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
@ -697,7 +613,9 @@ static int wince_submit_transfer(
} }
} }
static void wince_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) 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 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_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
@ -792,7 +710,9 @@ static void wince_transfer_callback(struct usbi_transfer *itransfer, uint32_t io
} }
} }
static void wince_handle_callback (struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) 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); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
@ -804,7 +724,7 @@ static void wince_handle_callback (struct usbi_transfer *itransfer, uint32_t io_
wince_transfer_callback (itransfer, io_result, io_size); wince_transfer_callback (itransfer, io_result, io_size);
break; break;
case LIBUSB_TRANSFER_TYPE_BULK_STREAM: case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
return LIBUSB_ERROR_NOT_SUPPORTED; break;
default: default:
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
} }
@ -853,9 +773,11 @@ static int wince_handle_events(
wince_handle_callback(transfer, io_result, io_size); wince_handle_callback(transfer, io_result, io_size);
} else if (found) { } else if (found) {
usbi_err(ctx, "matching transfer for fd %x has not completed", fds[i]); usbi_err(ctx, "matching transfer for fd %x has not completed", fds[i]);
usbi_mutex_unlock(&ctx->open_devs_lock);
return LIBUSB_ERROR_OTHER; return LIBUSB_ERROR_OTHER;
} else { } else {
usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]); usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]);
usbi_mutex_unlock(&ctx->open_devs_lock);
return LIBUSB_ERROR_NOT_FOUND; return LIBUSB_ERROR_NOT_FOUND;
} }
} }
@ -867,105 +789,20 @@ static int wince_handle_events(
/* /*
* Monotonic and real time functions * Monotonic and real time functions
*/ */
unsigned __stdcall wince_clock_gettime_threaded(void* param)
{
LARGE_INTEGER hires_counter, li_frequency;
LONG nb_responses;
int timer_index;
// Init - find out if we have access to a monotonic (hires) timer
if (!QueryPerformanceFrequency(&li_frequency)) {
usbi_dbg("no hires timer available on this platform");
hires_frequency = 0;
hires_ticks_to_ps = UINT64_C(0);
} else {
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);
}
// Signal wince_init() that we're ready to service requests
if (ReleaseSemaphore(timer_response, 1, NULL) == 0) {
usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
}
// Main loop - wait for requests
while (1) {
timer_index = WaitForMultipleObjects(2, timer_request, FALSE, INFINITE) - WAIT_OBJECT_0;
if ( (timer_index != 0) && (timer_index != 1) ) {
usbi_dbg("failure to wait on requests: %s", windows_error_str(0));
continue;
}
if (request_count[timer_index] == 0) {
// Request already handled
ResetEvent(timer_request[timer_index]);
// There's still a possiblity that a thread sends a request between the
// time we test request_count[] == 0 and we reset the event, in which case
// the request would be ignored. The simple solution to that is to test
// request_count again and process requests if non zero.
if (request_count[timer_index] == 0)
continue;
}
switch (timer_index) {
case 0:
WaitForSingleObject(timer_mutex, INFINITE);
// Requests to this thread are for hires always
if (QueryPerformanceCounter(&hires_counter) != 0) {
timer_tp.tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
timer_tp.tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency)/1000) * hires_ticks_to_ps);
} else {
// Fallback to real-time if we can't get monotonic value
// Note that real-time clock does not wait on the mutex or this thread.
wince_clock_gettime(USBI_CLOCK_REALTIME, &timer_tp);
}
ReleaseMutex(timer_mutex);
nb_responses = InterlockedExchange((LONG*)&request_count[0], 0);
if ( (nb_responses)
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) {
usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
}
continue;
case 1: // time to quit
usbi_dbg("timer thread quitting");
return 0;
}
}
usbi_dbg("ERROR: broken timer thread");
return 1;
}
static int wince_clock_gettime(int clk_id, struct timespec *tp) static int wince_clock_gettime(int clk_id, struct timespec *tp)
{ {
FILETIME filetime; LARGE_INTEGER hires_counter;
ULARGE_INTEGER rtime; ULARGE_INTEGER rtime;
DWORD r; FILETIME filetime;
SYSTEMTIME st; SYSTEMTIME st;
switch(clk_id) { switch(clk_id) {
case USBI_CLOCK_MONOTONIC: case USBI_CLOCK_MONOTONIC:
if (hires_frequency != 0) { if (hires_frequency != 0 && QueryPerformanceCounter(&hires_counter)) {
while (1) { tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
InterlockedIncrement((LONG*)&request_count[0]); tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
SetEvent(timer_request[0]); return LIBUSB_SUCCESS;
r = WaitForSingleObject(timer_response, TIMER_REQUEST_RETRY_MS);
switch(r) {
case WAIT_OBJECT_0:
WaitForSingleObject(timer_mutex, INFINITE);
*tp = timer_tp;
ReleaseMutex(timer_mutex);
return LIBUSB_SUCCESS;
case WAIT_TIMEOUT:
usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
break; // Retry until successful
default:
usbi_dbg("WaitForSingleObject failed: %s", windows_error_str(0));
return LIBUSB_ERROR_OTHER;
}
}
} }
// Fall through and return real-time if monotonic was not detected @ timer init // Fall through and return real-time if monotonic read failed or was not detected @ init
case USBI_CLOCK_REALTIME: case USBI_CLOCK_REALTIME:
// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00 // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
@ -985,48 +822,48 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp)
} }
const struct usbi_os_backend wince_backend = { const struct usbi_os_backend wince_backend = {
"Windows CE", "Windows CE",
0, 0,
wince_init, wince_init,
wince_exit, wince_exit,
wince_get_device_list, wince_get_device_list,
NULL, /* hotplug_poll */ NULL, /* hotplug_poll */
wince_open, wince_open,
wince_close, wince_close,
wince_get_device_descriptor, wince_get_device_descriptor,
wince_get_active_config_descriptor, wince_get_active_config_descriptor,
wince_get_config_descriptor, wince_get_config_descriptor,
NULL, /* get_config_descriptor_by_value() */ NULL, /* get_config_descriptor_by_value() */
wince_get_configuration, wince_get_configuration,
wince_set_configuration, wince_set_configuration,
wince_claim_interface, wince_claim_interface,
wince_release_interface, wince_release_interface,
wince_set_interface_altsetting, wince_set_interface_altsetting,
wince_clear_halt, wince_clear_halt,
wince_reset_device, wince_reset_device,
NULL, /* alloc_streams */ NULL, /* alloc_streams */
NULL, /* free_streams */ NULL, /* free_streams */
wince_kernel_driver_active, wince_kernel_driver_active,
wince_detach_kernel_driver, wince_detach_kernel_driver,
wince_attach_kernel_driver, wince_attach_kernel_driver,
wince_destroy_device, wince_destroy_device,
wince_submit_transfer, wince_submit_transfer,
wince_cancel_transfer, wince_cancel_transfer,
wince_clear_transfer_priv, wince_clear_transfer_priv,
wince_handle_events, wince_handle_events,
NULL, /* handle_transfer_completion() */
wince_clock_gettime, wince_clock_gettime,
sizeof(struct wince_device_priv), sizeof(struct wince_device_priv),
sizeof(struct wince_device_handle_priv), sizeof(struct wince_device_handle_priv),
sizeof(struct wince_transfer_priv), sizeof(struct wince_transfer_priv),
0,
}; };

View File

@ -39,7 +39,7 @@
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0) #define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0) #define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_min(a, b) min((size_t)(a), (size_t)(b)) #define safe_min(a, b) MIN((size_t)(a), (size_t)(b))
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \ #define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0) ((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1) #define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)

View File

@ -23,6 +23,7 @@
*/ */
#include <config.h> #include <config.h>
#include <windows.h> #include <windows.h>
#include <setupapi.h> #include <setupapi.h>
#include <ctype.h> #include <ctype.h>
@ -106,13 +107,8 @@ static char windows_version_str[128] = "Windows Undefined";
static int concurrent_usage = -1; static int concurrent_usage = -1;
usbi_mutex_t autoclaim_lock; usbi_mutex_t autoclaim_lock;
// Timer thread // Timer thread
// NB: index 0 is for monotonic and 1 is for the thread exit event
HANDLE timer_thread = NULL; HANDLE timer_thread = NULL;
HANDLE timer_mutex = NULL; DWORD timer_thread_id = 0;
struct timespec timer_tp;
volatile LONG request_count[2] = {0, 1}; // last one must be > 0
HANDLE timer_request[2] = { NULL, NULL };
HANDLE timer_response = NULL;
// API globals // API globals
#define CHECK_WINUSBX_AVAILABLE(sub_api) do { if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; \ #define CHECK_WINUSBX_AVAILABLE(sub_api) do { if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; \
if (!WinUSBX[sub_api].initialized) return LIBUSB_ERROR_ACCESS; } while(0) if (!WinUSBX[sub_api].initialized) return LIBUSB_ERROR_ACCESS; } while(0)
@ -257,6 +253,9 @@ static int init_dlls(void)
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegQueryValueExW, TRUE); DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegQueryValueExW, TRUE);
DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegCloseKey, TRUE); DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegCloseKey, TRUE);
DLL_LOAD_PREFIXED(User32.dll, p, GetMessageA, TRUE);
DLL_LOAD_PREFIXED(User32.dll, p, PeekMessageA, TRUE);
DLL_LOAD_PREFIXED(User32.dll, p, PostThreadMessageA, TRUE);
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
@ -661,6 +660,32 @@ static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
return session_id; return session_id;
} }
/*
* Determine which interface the given endpoint address belongs to
*/
static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep)
{
const struct libusb_interface *intf;
const struct libusb_interface_descriptor *intf_desc;
int i, j, k;
for (i = 0; i < conf_desc->bNumInterfaces; i++) {
intf = &conf_desc->interface[i];
for (j = 0; j < intf->num_altsetting; j++) {
intf_desc = &intf->altsetting[j];
for (k = 0; k < intf_desc->bNumEndpoints; k++) {
if (intf_desc->endpoint[k].bEndpointAddress == ep) {
usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber);
return intf_desc->bInterfaceNumber;
}
}
}
}
usbi_dbg("endpoint %02X not found on any interface", ep);
return LIBUSB_ERROR_NOT_FOUND;
}
/* /*
* Populate the endpoints addresses of the device_priv interface helper structs * Populate the endpoints addresses of the device_priv interface helper structs
*/ */
@ -672,7 +697,7 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int
const struct libusb_interface_descriptor *if_desc; const struct libusb_interface_descriptor *if_desc;
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
r = libusb_get_config_descriptor(dev_handle->dev, 0, &conf_desc); r = libusb_get_config_descriptor(dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc);
if (r != LIBUSB_SUCCESS) { if (r != LIBUSB_SUCCESS) {
usbi_warn(ctx, "could not read config descriptor: error %d", r); usbi_warn(ctx, "could not read config descriptor: error %d", r);
return r; return r;
@ -889,13 +914,13 @@ static void get_windows_version(void)
break; break;
case 0x63: w = (ws?"8.1":"2012_R2"); case 0x63: w = (ws?"8.1":"2012_R2");
break; break;
case 0x64: w = (ws?"8.2":"2012_R3"); case 0x64: w = (ws?"10":"2015");
break; break;
default: default:
if (windows_version < 0x50) if (windows_version < 0x50)
windows_version = WINDOWS_UNSUPPORTED; windows_version = WINDOWS_UNSUPPORTED;
else else
w = "9 or later"; w = "11 or later";
break; break;
} }
} }
@ -927,7 +952,10 @@ static void get_windows_version(void)
static int windows_init(struct libusb_context *ctx) static int windows_init(struct libusb_context *ctx)
{ {
int i, r = LIBUSB_ERROR_OTHER; int i, r = LIBUSB_ERROR_OTHER;
DWORD_PTR affinity, dummy;
HANDLE event = NULL;
HANDLE semaphore; HANDLE semaphore;
LARGE_INTEGER li_frequency;
char sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) char sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()&0xFFFFFFFF); sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
@ -965,7 +993,7 @@ static int windows_init(struct libusb_context *ctx)
// Load DLL imports // Load DLL imports
if (init_dlls() != LIBUSB_SUCCESS) { if (init_dlls() != LIBUSB_SUCCESS) {
usbi_err(ctx, "could not resolve DLL functions"); usbi_err(ctx, "could not resolve DLL functions");
return LIBUSB_ERROR_NOT_FOUND; goto init_exit;
} }
// Initialize the low level APIs (we don't care about errors at this stage) // Initialize the low level APIs (we don't care about errors at this stage)
@ -973,38 +1001,53 @@ static int windows_init(struct libusb_context *ctx)
usb_api_backend[i].init(SUB_API_NOTSET, ctx); usb_api_backend[i].init(SUB_API_NOTSET, ctx);
} }
// Because QueryPerformanceCounter might report different values when if (QueryPerformanceFrequency(&li_frequency)) {
// running on different cores, we create a separate thread for the timer // The hires frequency can go as high as 4 GHz, so we'll use a conversion
// calls, which we glue to the first core always to prevent timing discrepancies. // to picoseconds to compute the tv_nsecs part in clock_gettime
r = LIBUSB_ERROR_NO_MEM; hires_frequency = li_frequency.QuadPart;
for (i = 0; i < 2; i++) { hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
timer_request[i] = CreateEvent(NULL, TRUE, FALSE, NULL); usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
if (timer_request[i] == NULL) {
usbi_err(ctx, "could not create timer request event %d - aborting", i); // Because QueryPerformanceCounter might report different values when
// running on different cores, we create a separate thread for the timer
// calls, which we glue to the first available core always to prevent timing discrepancies.
if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) {
usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0));
goto init_exit;
}
// The process affinity mask is a bitmask where each set bit represents a core on
// which this process is allowed to run, so we find the first set bit
for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++);
affinity = (DWORD_PTR)(1 << i);
usbi_dbg("timer thread will run on core #%d", i);
r = LIBUSB_ERROR_NO_MEM;
event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (event == NULL) {
usbi_err(ctx, "could not create event: %s", windows_error_str(0));
goto init_exit;
}
timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event,
0, (unsigned int *)&timer_thread_id);
if (timer_thread == NULL) {
usbi_err(ctx, "unable to create timer thread - aborting");
goto init_exit;
}
if (!SetThreadAffinityMask(timer_thread, affinity)) {
usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise");
}
// Wait for timer thread to init before continuing.
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
usbi_err(ctx, "failed to wait for timer thread to become ready - aborting");
goto init_exit; goto init_exit;
} }
} }
timer_response = CreateSemaphore(NULL, 0, MAX_TIMER_SEMAPHORES, NULL); else {
if (timer_response == NULL) { usbi_dbg("no hires timer available on this platform");
usbi_err(ctx, "could not create timer response semaphore - aborting"); hires_frequency = 0;
goto init_exit; hires_ticks_to_ps = UINT64_C(0);
}
timer_mutex = CreateMutex(NULL, FALSE, NULL);
if (timer_mutex == NULL) {
usbi_err(ctx, "could not create timer mutex - aborting");
goto init_exit;
}
timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, NULL, 0, NULL);
if (timer_thread == NULL) {
usbi_err(ctx, "Unable to create timer thread - aborting");
goto init_exit;
}
SetThreadAffinityMask(timer_thread, 0);
// Wait for timer thread to init before continuing.
if (WaitForSingleObject(timer_response, INFINITE) != WAIT_OBJECT_0) {
usbi_err(ctx, "Failed to wait for timer thread to become ready - aborting");
goto init_exit;
} }
// Create a hash table to store session ids. Second parameter is better if prime // Create a hash table to store session ids. Second parameter is better if prime
@ -1016,35 +1059,27 @@ static int windows_init(struct libusb_context *ctx)
init_exit: // Holds semaphore here. init_exit: // Holds semaphore here.
if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
if (timer_thread) { if (timer_thread) {
SetEvent(timer_request[1]); // actually the signal to quit the thread. // actually the signal to quit the thread.
if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) { if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) ||
(WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
usbi_warn(ctx, "could not wait for timer thread to quit"); usbi_warn(ctx, "could not wait for timer thread to quit");
TerminateThread(timer_thread, 1); // shouldn't happen, but we're destroying TerminateThread(timer_thread, 1);
// all objects it might have held anyway. // shouldn't happen, but we're destroying
// all objects it might have held anyway.
} }
CloseHandle(timer_thread); CloseHandle(timer_thread);
timer_thread = NULL; timer_thread = NULL;
} timer_thread_id = 0;
for (i = 0; i < 2; i++) {
if (timer_request[i]) {
CloseHandle(timer_request[i]);
timer_request[i] = NULL;
}
}
if (timer_response) {
CloseHandle(timer_response);
timer_response = NULL;
}
if (timer_mutex) {
CloseHandle(timer_mutex);
timer_mutex = NULL;
} }
htab_destroy(); htab_destroy();
usbi_mutex_destroy(&autoclaim_lock);
} }
if (r != LIBUSB_SUCCESS) if (r != LIBUSB_SUCCESS)
--concurrent_usage; // Not expected to call libusb_exit if we failed. --concurrent_usage; // Not expected to call libusb_exit if we failed.
if (event)
CloseHandle(event);
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
CloseHandle(semaphore); CloseHandle(semaphore);
return r; return r;
@ -1124,7 +1159,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle
cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
cd_buf_short.req.SetupPacket.wIndex = i; cd_buf_short.req.SetupPacket.wIndex = 0;
cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
// Dummy call to get the required data size. Initial failures are reported as info rather // Dummy call to get the required data size. Initial failures are reported as info rather
@ -1153,7 +1188,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle
cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
cd_buf_actual->SetupPacket.wIndex = i; cd_buf_actual->SetupPacket.wIndex = 0;
cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size, if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size,
@ -1199,6 +1234,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
struct windows_device_priv *priv, *parent_priv; struct windows_device_priv *priv, *parent_priv;
struct libusb_context *ctx; struct libusb_context *ctx;
struct libusb_device* tmp_dev; struct libusb_device* tmp_dev;
unsigned long tmp_id;
unsigned i; unsigned i;
if ((dev == NULL) || (parent_dev == NULL)) { if ((dev == NULL) || (parent_dev == NULL)) {
@ -1216,8 +1252,10 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
// If that's the case, lookup the ancestors to set the bus number // If that's the case, lookup the ancestors to set the bus number
if (parent_dev->bus_number == 0) { if (parent_dev->bus_number == 0) {
for (i=2; ; i++) { for (i=2; ; i++) {
tmp_dev = usbi_get_device_by_session_id(ctx, get_ancestor_session_id(devinst, i)); tmp_id = get_ancestor_session_id(devinst, i);
if (tmp_dev == NULL) break; if (tmp_id == 0) break;
tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id);
if (tmp_dev == NULL) continue;
if (tmp_dev->bus_number != 0) { if (tmp_dev->bus_number != 0) {
usbi_dbg("got bus number from ancestor #%d", i); usbi_dbg("got bus number from ancestor #%d", i);
parent_dev->bus_number = tmp_dev->bus_number; parent_dev->bus_number = tmp_dev->bus_number;
@ -1525,7 +1563,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
//#define ENUM_DEBUG //#define ENUM_DEBUG
#ifdef ENUM_DEBUG #ifdef ENUM_DEBUG
const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" }; const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" };
usbi_dbg("\n#### PROCESSING %ss %s", passname[(pass<=HID_PASS)?pass:HID_PASS+1], usbi_dbg("#### PROCESSING %ss %s", passname[(pass<=HID_PASS)?pass:HID_PASS+1],
(pass!=GEN_PASS)?guid_to_string(guid[pass]):""); (pass!=GEN_PASS)?guid_to_string(guid[pass]):"");
#endif #endif
for (i = 0; ; i++) { for (i = 0; ; i++) {
@ -1627,6 +1665,10 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
LOOP_BREAK(LIBUSB_ERROR_OVERFLOW); LOOP_BREAK(LIBUSB_ERROR_OVERFLOW);
} }
if_guid = (GUID*) calloc(1, sizeof(GUID)); if_guid = (GUID*) calloc(1, sizeof(GUID));
if (if_guid == NULL) {
usbi_err(ctx, "could not calloc for if_guid: not enough memory");
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
}
pCLSIDFromString(guid_string_w, if_guid); pCLSIDFromString(guid_string_w, if_guid);
guid[nb_guids++] = if_guid; guid[nb_guids++] = if_guid;
usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
@ -1849,29 +1891,18 @@ static void windows_exit(void)
exit_polling(); exit_polling();
if (timer_thread) { if (timer_thread) {
SetEvent(timer_request[1]); // actually the signal to quit the thread. // actually the signal to quit the thread.
if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) { if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) ||
(WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
usbi_dbg("could not wait for timer thread to quit"); usbi_dbg("could not wait for timer thread to quit");
TerminateThread(timer_thread, 1); TerminateThread(timer_thread, 1);
} }
CloseHandle(timer_thread); CloseHandle(timer_thread);
timer_thread = NULL; timer_thread = NULL;
} timer_thread_id = 0;
for (i = 0; i < 2; i++) {
if (timer_request[i]) {
CloseHandle(timer_request[i]);
timer_request[i] = NULL;
}
}
if (timer_response) {
CloseHandle(timer_response);
timer_response = NULL;
}
if (timer_mutex) {
CloseHandle(timer_mutex);
timer_mutex = NULL;
} }
htab_destroy(); htab_destroy();
usbi_mutex_destroy(&autoclaim_lock);
} }
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
@ -1903,7 +1934,7 @@ static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t conf
config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index]; config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index];
size = min(config_header->wTotalLength, len); size = MIN(config_header->wTotalLength, len);
memcpy(buffer, priv->config_descriptor[config_index], size); memcpy(buffer, priv->config_descriptor[config_index], size);
*host_endian = 0; *host_endian = 0;
@ -1986,9 +2017,6 @@ static int windows_claim_interface(struct libusb_device_handle *dev_handle, int
int r = LIBUSB_SUCCESS; int r = LIBUSB_SUCCESS;
struct windows_device_priv *priv = _device_priv(dev_handle->dev); struct windows_device_priv *priv = _device_priv(dev_handle->dev);
if (iface >= USB_MAXINTERFACES)
return LIBUSB_ERROR_INVALID_PARAM;
safe_free(priv->usb_interface[iface].endpoint); safe_free(priv->usb_interface[iface].endpoint);
priv->usb_interface[iface].nb_endpoints= 0; priv->usb_interface[iface].nb_endpoints= 0;
@ -2084,7 +2112,6 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
@ -2104,7 +2131,6 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
@ -2123,7 +2149,6 @@ static int submit_control_transfer(struct usbi_transfer *itransfer)
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
@ -2251,7 +2276,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
{ {
struct windows_transfer_priv* transfer_priv = NULL; struct windows_transfer_priv* transfer_priv = NULL;
POLL_NFDS_TYPE i = 0; POLL_NFDS_TYPE i = 0;
bool found = false; bool found;
struct usbi_transfer *transfer; struct usbi_transfer *transfer;
DWORD io_size, io_result; DWORD io_size, io_result;
@ -2269,6 +2294,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
// Because a Windows OVERLAPPED is used for poll emulation, // Because a Windows OVERLAPPED is used for poll emulation,
// a pollable fd is created and stored with each transfer // a pollable fd is created and stored with each transfer
usbi_mutex_lock(&ctx->flying_transfers_lock); usbi_mutex_lock(&ctx->flying_transfers_lock);
found = false;
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
transfer_priv = usbi_transfer_get_os_priv(transfer); transfer_priv = usbi_transfer_get_os_priv(transfer);
if (transfer_priv->pollable_fd.fd == fds[i].fd) { if (transfer_priv->pollable_fd.fd == fds[i].fd) {
@ -2296,6 +2322,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
// newly allocated wfd that took the place of the one from the transfer. // newly allocated wfd that took the place of the one from the transfer.
windows_handle_callback(transfer, io_result, io_size); windows_handle_callback(transfer, io_result, io_size);
} else { } else {
usbi_mutex_unlock(&ctx->open_devs_lock);
usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]); usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]);
return LIBUSB_ERROR_NOT_FOUND; return LIBUSB_ERROR_NOT_FOUND;
} }
@ -2310,66 +2337,42 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
*/ */
unsigned __stdcall windows_clock_gettime_threaded(void* param) unsigned __stdcall windows_clock_gettime_threaded(void* param)
{ {
LARGE_INTEGER hires_counter, li_frequency; struct timer_request *request;
LONG nb_responses; LARGE_INTEGER hires_counter;
int timer_index; MSG msg;
// Init - find out if we have access to a monotonic (hires) timer // The following call will create this thread's message queue
if (!QueryPerformanceFrequency(&li_frequency)) { // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx
usbi_dbg("no hires timer available on this platform"); pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
hires_frequency = 0;
hires_ticks_to_ps = UINT64_C(0);
} else {
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);
}
// Signal windows_init() that we're ready to service requests // Signal windows_init() that we're ready to service requests
if (ReleaseSemaphore(timer_response, 1, NULL) == 0) { if (!SetEvent((HANDLE)param)) {
usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0)); usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0));
} }
param = NULL;
// Main loop - wait for requests // Main loop - wait for requests
while (1) { while (1) {
timer_index = WaitForMultipleObjects(2, timer_request, FALSE, INFINITE) - WAIT_OBJECT_0; if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) {
if ( (timer_index != 0) && (timer_index != 1) ) { usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0));
usbi_dbg("failure to wait on requests: %s", windows_error_str(0)); return 1;
continue;
} }
if (request_count[timer_index] == 0) {
// Request already handled
ResetEvent(timer_request[timer_index]);
// There's still a possiblity that a thread sends a request between the
// time we test request_count[] == 0 and we reset the event, in which case
// the request would be ignored. The simple solution to that is to test
// request_count again and process requests if non zero.
if (request_count[timer_index] == 0)
continue;
}
switch (timer_index) {
case 0:
WaitForSingleObject(timer_mutex, INFINITE);
// Requests to this thread are for hires always
if ((QueryPerformanceCounter(&hires_counter) != 0) && (hires_frequency != 0)) {
timer_tp.tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
timer_tp.tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency)/1000) * hires_ticks_to_ps);
} else {
// Fallback to real-time if we can't get monotonic value
// Note that real-time clock does not wait on the mutex or this thread.
windows_clock_gettime(USBI_CLOCK_REALTIME, &timer_tp);
}
ReleaseMutex(timer_mutex);
nb_responses = InterlockedExchange((LONG*)&request_count[0], 0); switch (msg.message) {
if ( (nb_responses) case WM_TIMER_REQUEST:
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) { // Requests to this thread are for hires always
usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0)); // Microsoft says that this function always succeeds on XP and later
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx
request = (struct timer_request *)msg.lParam;
QueryPerformanceCounter(&hires_counter);
request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
if (!SetEvent(request->event)) {
usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0));
} }
continue; break;
case 1: // time to quit
case WM_TIMER_EXIT:
usbi_dbg("timer thread quitting"); usbi_dbg("timer thread quitting");
return 0; return 0;
} }
@ -2378,29 +2381,41 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
static int windows_clock_gettime(int clk_id, struct timespec *tp) static int windows_clock_gettime(int clk_id, struct timespec *tp)
{ {
struct timer_request request;
FILETIME filetime; FILETIME filetime;
ULARGE_INTEGER rtime; ULARGE_INTEGER rtime;
DWORD r; DWORD r;
switch(clk_id) { switch(clk_id) {
case USBI_CLOCK_MONOTONIC: case USBI_CLOCK_MONOTONIC:
if (hires_frequency != 0) { if (timer_thread) {
while (1) { request.tp = tp;
InterlockedIncrement((LONG*)&request_count[0]); request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
SetEvent(timer_request[0]); if (request.event == NULL) {
r = WaitForSingleObject(timer_response, TIMER_REQUEST_RETRY_MS); return LIBUSB_ERROR_NO_MEM;
switch(r) { }
case WAIT_OBJECT_0:
WaitForSingleObject(timer_mutex, INFINITE); if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
*tp = timer_tp; usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
ReleaseMutex(timer_mutex); CloseHandle(request.event);
return LIBUSB_SUCCESS; return LIBUSB_ERROR_OTHER;
case WAIT_TIMEOUT: }
do {
r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
if (r == WAIT_TIMEOUT) {
usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?"); usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
break; // Retry until successful
default:
usbi_dbg("WaitForSingleObject failed: %s", windows_error_str(0));
return LIBUSB_ERROR_OTHER;
} }
else if (r == WAIT_FAILED) {
usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
}
} while (r == WAIT_TIMEOUT);
CloseHandle(request.event);
if (r == WAIT_OBJECT_0) {
return LIBUSB_SUCCESS;
}
else {
return LIBUSB_ERROR_OTHER;
} }
} }
// Fall through and return real-time if monotonic was not detected @ timer init // Fall through and return real-time if monotonic was not detected @ timer init
@ -2462,6 +2477,7 @@ const struct usbi_os_backend windows_backend = {
windows_clear_transfer_priv, windows_clear_transfer_priv,
windows_handle_events, windows_handle_events,
NULL, /* handle_transfer_completion() */
windows_clock_gettime, windows_clock_gettime,
#if defined(USBI_TIMERFD_AVAILABLE) #if defined(USBI_TIMERFD_AVAILABLE)
@ -2470,7 +2486,6 @@ const struct usbi_os_backend windows_backend = {
sizeof(struct windows_device_priv), sizeof(struct windows_device_priv),
sizeof(struct windows_device_handle_priv), sizeof(struct windows_device_handle_priv),
sizeof(struct windows_transfer_priv), sizeof(struct windows_transfer_priv),
0,
}; };
@ -2668,7 +2683,7 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx)
if (h == NULL) { if (h == NULL) {
h = LoadLibraryA("WinUSB"); h = LoadLibraryA("WinUSB");
} if (h == NULL) { } if (h == NULL) {
usbi_warn(ctx, "WinUSB DLL is not available either,\n" usbi_warn(ctx, "WinUSB DLL is not available either, "
"you will not be able to access devices outside of enumeration"); "you will not be able to access devices outside of enumeration");
return LIBUSB_ERROR_NOT_FOUND; return LIBUSB_ERROR_NOT_FOUND;
} }
@ -2769,7 +2784,7 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
{ {
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct windows_device_priv *priv = _device_priv(dev_handle->dev); struct windows_device_priv *priv = _device_priv(dev_handle->dev);
HANDLE file_handle; HANDLE handle;
int i; int i;
if (sub_api == SUB_API_NOTSET) if (sub_api == SUB_API_NOTSET)
@ -2777,14 +2792,40 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
if (!WinUSBX[sub_api].initialized) if (!WinUSBX[sub_api].initialized)
return; return;
for (i = 0; i < USB_MAXINTERFACES; i++) { if (priv->apib->id == USB_API_COMPOSITE) {
if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { // If this is a composite device, just free and close all WinUSB-like
file_handle = handle_priv->interface_handle[i].dev_handle; // interfaces directly (each is independent and not associated with another)
if ( (file_handle != 0) && (file_handle != INVALID_HANDLE_VALUE)) { for (i = 0; i < USB_MAXINTERFACES; i++) {
CloseHandle(file_handle); if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) {
handle = handle_priv->interface_handle[i].api_handle;
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
WinUSBX[sub_api].Free(handle);
}
handle = handle_priv->interface_handle[i].dev_handle;
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
CloseHandle(handle);
}
} }
} }
} }
else {
// If this is a WinUSB device, free all interfaces above interface 0,
// then free and close interface 0 last
for (i = 1; i < USB_MAXINTERFACES; i++) {
handle = handle_priv->interface_handle[i].api_handle;
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
WinUSBX[sub_api].Free(handle);
}
}
handle = handle_priv->interface_handle[0].api_handle;
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
WinUSBX[sub_api].Free(handle);
}
handle = handle_priv->interface_handle[0].dev_handle;
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
CloseHandle(handle);
}
}
} }
static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
@ -3579,7 +3620,7 @@ static int _hid_get_descriptor(struct hid_device_priv* dev, HANDLE hid_handle, i
return LIBUSB_ERROR_OTHER; return LIBUSB_ERROR_OTHER;
} }
usbi_dbg("unsupported"); usbi_dbg("unsupported");
return LIBUSB_ERROR_INVALID_PARAM; return LIBUSB_ERROR_NOT_SUPPORTED;
} }
static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data, static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data,
@ -4086,7 +4127,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
r = LIBUSB_COMPLETED; r = LIBUSB_COMPLETED;
} else { } else {
usbi_warn(ctx, "cannot set configuration other than the default one"); usbi_warn(ctx, "cannot set configuration other than the default one");
r = LIBUSB_ERROR_INVALID_PARAM; r = LIBUSB_ERROR_NOT_SUPPORTED;
} }
break; break;
case LIBUSB_REQUEST_GET_INTERFACE: case LIBUSB_REQUEST_GET_INTERFACE:
@ -4102,7 +4143,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
break; break;
default: default:
usbi_warn(ctx, "unsupported HID control request"); usbi_warn(ctx, "unsupported HID control request");
r = LIBUSB_ERROR_INVALID_PARAM; r = LIBUSB_ERROR_NOT_SUPPORTED;
break; break;
} }
break; break;
@ -4113,7 +4154,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
break; break;
default: default:
usbi_warn(ctx, "unsupported HID control request"); usbi_warn(ctx, "unsupported HID control request");
r = LIBUSB_ERROR_INVALID_PARAM; r = LIBUSB_ERROR_NOT_SUPPORTED;
break; break;
} }
@ -4387,24 +4428,31 @@ static void composite_close(int sub_api, struct libusb_device_handle *dev_handle
{ {
struct windows_device_priv *priv = _device_priv(dev_handle->dev); struct windows_device_priv *priv = _device_priv(dev_handle->dev);
uint8_t i; uint8_t i;
bool available[SUB_API_MAX]; // SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID
bool available[SUB_API_MAX+1] = {0};
for (i = 0; i<SUB_API_MAX; i++) {
available[i] = false;
}
for (i=0; i<USB_MAXINTERFACES; i++) { for (i=0; i<USB_MAXINTERFACES; i++) {
if ( (priv->usb_interface[i].apib->id == USB_API_WINUSBX) switch (priv->usb_interface[i].apib->id) {
&& (priv->usb_interface[i].sub_api != SUB_API_NOTSET) ) { case USB_API_WINUSBX:
available[priv->usb_interface[i].sub_api] = true; if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
available[priv->usb_interface[i].sub_api] = true;
break;
case USB_API_HID:
available[SUB_API_MAX] = true;
break;
default:
break;
} }
} }
for (i=0; i<SUB_API_MAX; i++) { for (i=0; i<SUB_API_MAX; i++) { // WinUSB-like drivers
if (available[i]) { if (available[i]) {
usb_api_backend[USB_API_WINUSBX].close(i, dev_handle); usb_api_backend[USB_API_WINUSBX].close(i, dev_handle);
} }
} }
if (available[SUB_API_MAX]) { // HID driver
hid_close(SUB_API_NOTSET, dev_handle);
}
} }
static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
@ -4433,19 +4481,57 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int i, pass; struct libusb_config_descriptor *conf_desc;
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer;
int iface, pass, r;
// Interface shouldn't matter for control, but it does in practice, with Windows' // Interface shouldn't matter for control, but it does in practice, with Windows'
// restrictions with regards to accessing HID keyboards and mice. Try a 2 pass approach // restrictions with regards to accessing HID keyboards and mice. Try to target
// a specific interface first, if possible.
switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) {
case LIBUSB_RECIPIENT_INTERFACE:
iface = setup->index & 0xFF;
break;
case LIBUSB_RECIPIENT_ENDPOINT:
r = libusb_get_config_descriptor(transfer->dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc);
if (r == LIBUSB_SUCCESS) {
iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF));
libusb_free_config_descriptor(conf_desc);
break;
}
// Fall through if not able to determine interface
default:
iface = -1;
break;
}
// Try and target a specific interface if the control setup indicates such
if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
usbi_dbg("attempting control transfer targeted to interface %d", iface);
if (priv->usb_interface[iface].path != NULL) {
r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
if (r == LIBUSB_SUCCESS) {
return r;
}
}
}
// Either not targeted to a specific interface or no luck in doing so.
// Try a 2 pass approach with all interfaces.
for (pass = 0; pass < 2; pass++) { for (pass = 0; pass < 2; pass++) {
for (i=0; i<USB_MAXINTERFACES; i++) { for (iface = 0; iface < USB_MAXINTERFACES; iface++) {
if (priv->usb_interface[i].path != NULL) { if (priv->usb_interface[iface].path != NULL) {
if ((pass == 0) && (priv->usb_interface[i].restricted_functionality)) { if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", i); usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
continue; continue;
} }
usbi_dbg("using interface %d", i); usbi_dbg("using interface %d", iface);
return priv->usb_interface[i].apib->submit_control_transfer(priv->usb_interface[i].sub_api, itransfer); r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
// If not supported on this API, it may be supported on another, so don't give up yet!!
if (r == LIBUSB_ERROR_NOT_SUPPORTED) {
continue;
}
return r;
} }
} }
} }

View File

@ -26,10 +26,12 @@
#if defined(_MSC_VER) #if defined(_MSC_VER)
// disable /W4 MSVC warnings that are benign // disable /W4 MSVC warnings that are benign
#pragma warning(disable:4127) // conditional expression is constant #pragma warning(disable:4100) // unreferenced formal parameter
#pragma warning(disable:4100) // unreferenced formal parameter #pragma warning(disable:4127) // conditional expression is constant
#pragma warning(disable:4214) // bit field types other than int #pragma warning(disable:4201) // nameless struct/union
#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 #endif
// Missing from MSVC6 setupapi.h // Missing from MSVC6 setupapi.h
@ -47,9 +49,8 @@
#if defined(__CYGWIN__ ) #if defined(__CYGWIN__ )
#define _stricmp stricmp #define _stricmp stricmp
// cygwin produces a warning unless these prototypes are defined #define _snprintf snprintf
extern int _snprintf(char *buffer, size_t count, const char *format, ...); #define _strdup strdup
extern char *_strdup(const char *strSource);
// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread // _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, f) #define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, f)
#endif #endif
@ -307,6 +308,15 @@ struct driver_lookup {
const char* designation; // internal designation (for debug output) 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 */ /* OLE32 dependency */
DLL_DECLARE_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID)); DLL_DECLARE_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID));
@ -328,6 +338,11 @@ DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINF
DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); 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 * Windows DDK API definitions. Most of it copied from MinGW's includes
*/ */

View File

@ -16,13 +16,16 @@
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "config.h"
#include <config.h>
#include <locale.h> #include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#if defined(HAVE_STRINGS_H)
#include <strings.h>
#endif
#include "libusb.h"
#include "libusbi.h" #include "libusbi.h"
#if defined(_MSC_VER) #if defined(_MSC_VER)

View File

@ -17,7 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "config.h" #include <config.h>
#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -7,7 +7,7 @@
#define LIBUSB_MINOR 0 #define LIBUSB_MINOR 0
#endif #endif
#ifndef LIBUSB_MICRO #ifndef LIBUSB_MICRO
#define LIBUSB_MICRO 19 #define LIBUSB_MICRO 20
#endif #endif
#ifndef LIBUSB_NANO #ifndef LIBUSB_NANO
#define LIBUSB_NANO 0 #define LIBUSB_NANO 0

View File

@ -1 +1 @@
#define LIBUSB_NANO 10903 #define LIBUSB_NANO 11004