Browse Source

Convert libusb-1.0.16-rc10 to libusbx-1.0.17

nfactor-troky
Con Kolivas 11 years ago
parent
commit
677e9816a5
  1. 46
      compat/libusb-1.0/AUTHORS
  2. 196
      compat/libusb-1.0/ChangeLog
  3. 22
      compat/libusb-1.0/Makefile.am
  4. 67
      compat/libusb-1.0/NEWS
  5. 27
      compat/libusb-1.0/PORTING
  6. 35
      compat/libusb-1.0/README
  7. 8
      compat/libusb-1.0/THANKS
  8. 11
      compat/libusb-1.0/TODO
  9. 108
      compat/libusb-1.0/configure.ac
  10. 3
      compat/libusb-1.0/doc/Makefile.am
  11. 38
      compat/libusb-1.0/doc/doxygen.cfg.in
  12. 6
      compat/libusb-1.0/examples/Makefile.am
  13. 9
      compat/libusb-1.0/examples/dpfp.c
  14. 9
      compat/libusb-1.0/examples/dpfp_threaded.c
  15. 118
      compat/libusb-1.0/examples/hotplugtest.c
  16. 21
      compat/libusb-1.0/examples/listdevs.c
  17. 2
      compat/libusb-1.0/examples/sam3u_benchmark.c
  18. 256
      compat/libusb-1.0/examples/testlibusb1.c
  19. 5
      compat/libusb-1.0/libusb-1.0.pc.in
  20. 46
      compat/libusb-1.0/libusb/Makefile.am
  21. 797
      compat/libusb-1.0/libusb/core.c
  22. 841
      compat/libusb-1.0/libusb/descriptor.c
  23. 306
      compat/libusb-1.0/libusb/hotplug.c
  24. 31
      compat/libusb-1.0/libusb/hotplug.h
  25. 652
      compat/libusb-1.0/libusb/io.c
  26. 40
      compat/libusb-1.0/libusb/libusb-1.0.def
  27. 13
      compat/libusb-1.0/libusb/libusb-1.0.rc
  28. 580
      compat/libusb-1.0/libusb/libusb.h
  29. 283
      compat/libusb-1.0/libusb/libusbi.h
  30. 550
      compat/libusb-1.0/libusb/os/darwin_usb.c
  31. 69
      compat/libusb-1.0/libusb/os/darwin_usb.h
  32. 198
      compat/libusb-1.0/libusb/os/linux_netlink.c
  33. 190
      compat/libusb-1.0/libusb/os/linux_udev.c
  34. 1144
      compat/libusb-1.0/libusb/os/linux_usbfs.c
  35. 27
      compat/libusb-1.0/libusb/os/linux_usbfs.h
  36. 734
      compat/libusb-1.0/libusb/os/netbsd_usb.c
  37. 334
      compat/libusb-1.0/libusb/os/openbsd_usb.c
  38. 51
      compat/libusb-1.0/libusb/os/poll_posix.c
  39. 3
      compat/libusb-1.0/libusb/os/poll_posix.h
  40. 203
      compat/libusb-1.0/libusb/os/poll_windows.c
  41. 20
      compat/libusb-1.0/libusb/os/poll_windows.h
  42. 47
      compat/libusb-1.0/libusb/os/threads_posix.c
  43. 6
      compat/libusb-1.0/libusb/os/threads_posix.h
  44. 28
      compat/libusb-1.0/libusb/os/threads_windows.c
  45. 9
      compat/libusb-1.0/libusb/os/threads_windows.h
  46. 1026
      compat/libusb-1.0/libusb/os/wince_usb.c
  47. 131
      compat/libusb-1.0/libusb/os/wince_usb.h
  48. 108
      compat/libusb-1.0/libusb/os/windows_common.h
  49. 2170
      compat/libusb-1.0/libusb/os/windows_usb.c
  50. 532
      compat/libusb-1.0/libusb/os/windows_usb.h
  51. 184
      compat/libusb-1.0/libusb/strerror.c
  52. 79
      compat/libusb-1.0/libusb/sync.c
  53. 6
      compat/libusb-1.0/libusb/version.h
  54. 1
      compat/libusb-1.0/libusb/version_nano.h

46
compat/libusb-1.0/AUTHORS

@ -1,46 +1,62 @@ @@ -1,46 +1,62 @@
Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
Copyright (C) 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
Copyright (C) 2009-2012 Pete Batard <pete@akeo.ie>
Copyright (C) 2010 Michael Plante <michael.plante@gmail.com>
Copyright (C) 2010-2012 Peter Stuge <peter@stuge.se>
Copyright (C) 2011-2012 Hans de Goede <hdegoede@redhat.com>
Copyright (C) 2012 Martin Pieuchot <mpi@openbsd.org>
Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
Copyright © 2010-2012 Peter Stuge <peter@stuge.se>
Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
Copyright © 2009-2013 Pete Batard <pete@akeo.ie>
Copyright © 2009-2013 Ludovic Rousseau <ludovic.rousseau@gmail.com>
Copyright © 2010-2012 Michael Plante <michael.plante@gmail.com>
Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com>
Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org>
Copyright © 2012-2013 Toby Gray <toby.gray@realvnc.com>
Other contributors:
Alan Ott
Alan Stern
Alex Vatchenko
Anthony Clay
Artem Egorkine
Aurelien Jarno
Bastien Nocera
Brian Shirley
Benjamin Dobell
Chris Dickens
Colin Walters
Dave Camarillo
David Engraf
David Moore
Davidlohr Bueso
Federico Manzan
Felipe Balbi
Florian Albrechtskirchinger
Francesco Montorsi
Graeme Gill
Hans de Goede
Hans Ulrich Niedermann
Hector Martin
Hoi-Ho Chan
Ilya Konstantinov
James Hanko
Konrad Rzepecki
Ludovic Rousseau
Lars Wirzenius
Luca Longinotti
Martin Koegler
Martin Pieuchot
Maya Erez
Matthias Bolte
Mike Frysinger
Mikhail Gusarov
Nicholas Corgan
Orin Eman
Paul Fertser
Pekka Nikander
Peter Stuge
Rob Walker
Sean McBride
Sebastian Pipping
Stephan Meyer
Simon Haggett
Thomas Röfer
Tim Roberts
Toby Peterson
Trygve Laugstøl
Uri Lublin
Vasily Khoruzhick
Vegard Storheil Eriksen
Vitali Lovich
Xiaofan Chen
Zoltán Kovács
Роман Донченко

196
compat/libusb-1.0/ChangeLog

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

22
compat/libusb-1.0/Makefile.am

@ -1,18 +1,23 @@ @@ -1,18 +1,23 @@
AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip
ACLOCAL_AMFLAGS = -I m4
DISTCLEANFILES = libusb-1.0.pc
MAINTAINERCLEANFILES = ChangeLog
EXTRA_DIST = TODO PORTING
SUBDIRS = libusb
EXTRA_DIST = TODO PORTING msvc libusb/libusb-1.0.def libusb/version_nano.h \
examples/getopt/getopt.c examples/getopt/getopt1.c examples/getopt/getopt.h \
android Xcode
SUBDIRS = libusb doc
if BUILD_EXAMPLES
SUBDIRS += examples
endif
if BUILD_TESTS
SUBDIRS += tests
endif
pkgconfigdir=$(libdir)/pkgconfig
pkgconfig_DATA=libusb-1.0.pc
.PHONY: ChangeLog dist-up
ChangeLog:
git --git-dir $(top_srcdir)/.git log > ChangeLog || touch ChangeLog
dist-hook: ChangeLog
.PHONY: dist-up
reldir = .release/$(distdir)
dist-up: dist
@ -21,4 +26,3 @@ dist-up: dist @@ -21,4 +26,3 @@ dist-up: dist
cp $(distdir).tar.bz2 $(reldir)
rsync -rv $(reldir) frs.sourceforge.net:/home/frs/project/l/li/libusb/libusb-1.0/
rm -rf $(reldir)

67
compat/libusb-1.0/NEWS

@ -1,65 +1,2 @@ @@ -1,65 +1,2 @@
This file lists notable changes in each release. For the full history of all
changes, see ChangeLog.
2012-04-20: 1.0.9
* Numerous bug fixes and improvements
* Backend for Windows, for devices using the WinUSB.sys driver
* Backend for OpenBSD and NetBSD, for devices using the ugen driver
* Add libusb_get_device_speed()
* Add libusb_has_capability()
* Add libusb_error_name()
* Add libusb_get_version()
2010-05-07: v1.0.8
* Bug fixes
2010-04-19: v1.0.7
* Bug fixes and documentation tweaks
* Add more interface class definitions
2009-11-22: v1.0.6
* Bug fixes
* Increase libusb_handle_events() timeout to 60s for powersaving
2009-11-15: v1.0.5
* Use timerfd when available for timer management
* Small fixes/updates
2009-11-06: v1.0.4 release
* Bug fixes including transfer locking to fix some potential threading races
* More flexibility with clock types on Linux
* Use new bulk continuation tracking in Linux 2.6.32 for improved handling
of short/failed transfers
2009-08-27: v1.0.3 release
* Bug fixes
* Add libusb_get_max_iso_packet_size()
2009-06-13: v1.0.2 release
* Bug fixes
2009-05-12: v1.0.1 release
* Bug fixes
* Darwin backend
2008-12-13: v1.0.0 release
* Bug fixes
2008-11-21: v0.9.4 release
* Bug fixes
* Add libusb_attach_kernel_driver()
2008-08-23: v0.9.3 release
* Bug fixes
2008-07-19: v0.9.2 release
* Bug fixes
2008-06-28: v0.9.1 release
* Bug fixes
* Introduce contexts to the API
* Compatibility with new Linux kernel features
2008-05-25: v0.9.0 release
* First libusb-1.0 beta release
For the latest libusbx news, please refer to the ChangeLog file, or visit:
http://libusbx.org

27
compat/libusb-1.0/PORTING

@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
PORTING LIBUSB TO OTHER PLATFORMS
PORTING LIBUSBX TO OTHER PLATFORMS
Introduction
============
This document is aimed at developers wishing to port libusb to unsupported
platforms. I believe the libusb API is OS-independent, so by supporting
This document is aimed at developers wishing to port libusbx to unsupported
platforms. I believe the libusbx API is OS-independent, so by supporting
multiple operating systems we pave the way for cross-platform USB device
drivers.
Implementation-wise, the basic idea is that you provide an interface to
libusb's internal "backend" API, which performs the appropriate operations on
libusbx's internal "backend" API, which performs the appropriate operations on
your target platform.
In terms of USB I/O, your backend provides functionality to submit
@ -27,16 +27,16 @@ e.g. setting configuration, obtaining descriptors, etc. @@ -27,16 +27,16 @@ e.g. setting configuration, obtaining descriptors, etc.
File descriptors for I/O polling
================================
For libusb to work, your event handling function obviously needs to be called
For libusbx to work, your event handling function obviously needs to be called
at various points in time. Your backend must provide a set of file descriptors
which libusb and its users can pass to poll() or select() to determine when
which libusbx and its users can pass to poll() or select() to determine when
it is time to call the event handling function.
On Linux, this is easy: the usbfs kernel interface exposes a file descriptor
which can be passed to poll(). If something similar is not true for your
platform, you can emulate this using an internal library thread to reap I/O as
necessary, and a pipe() with the main library to raise events. The file
descriptor of the pipe can then be provided to libusb as an event source.
descriptor of the pipe can then be provided to libusbx as an event source.
Interface semantics and documentation
@ -46,7 +46,7 @@ Documentation of the backend interface can be found in libusbi.h inside the @@ -46,7 +46,7 @@ Documentation of the backend interface can be found in libusbi.h inside the
usbi_os_backend structure definition.
Your implementations of these functions will need to call various internal
libusb functions, prefixed with "usbi_". Documentation for these functions
libusbx functions, prefixed with "usbi_". Documentation for these functions
can be found in the .c files where they are implemented.
You probably want to skim over *all* the documentation before starting your
@ -72,18 +72,18 @@ right usbi_backend for your platform. @@ -72,18 +72,18 @@ right usbi_backend for your platform.
4. Produce and test your implementation.
5. Send your implementation to libusb-devel mailing list.
5. Send your implementation to libusbx-devel mailing list.
Implementation difficulties? Questions?
=======================================
If you encounter difficulties porting libusb to your platform, please raise
these issues on the libusb-devel mailing list. Where possible and sensible, I
am interested in solving problems preventing libusb from operating on other
If you encounter difficulties porting libusbx to your platform, please raise
these issues on the libusbx-devel mailing list. Where possible and sensible, I
am interested in solving problems preventing libusbx from operating on other
platforms.
The libusb-devel mailing list is also a good place to ask questions and
The libusbx-devel mailing list is also a good place to ask questions and
make suggestions about the internal API. Hopefully we can produce some
better documentation based on your questions and other input.
@ -92,4 +92,3 @@ some infrastructure additions/modifications to better support your platform, @@ -92,4 +92,3 @@ some infrastructure additions/modifications to better support your platform,
you are encouraged to make such changes (in cleanly distinct patch
submissions). Even if you do not make such changes yourself, please do raise
the issues on the mailing list at the very minimum.

35
compat/libusb-1.0/README

@ -1,22 +1,29 @@ @@ -1,22 +1,29 @@
libusb
======
libusbx
=======
libusb is a library for USB device access from Linux, Mac OS X,
OpenBSD, NetBSD, and Windows userspace.
It is written in C and licensed under the LGPL-2.1 (see COPYING).
libusbx is a library for USB device access from Linux, Mac OS X,
Windows and OpenBSD/NetBSD userspace, with OpenBSD/NetBSD, and to a
lesser extent some of the newest features of Windows (such as libusbK
and libusb-win32 driver support) being EXPERIMENTAL.
It is written in C and licensed under the GNU 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
be ported to other operating systems. See the PORTING file for some
information, if you fancy a challenge. :)
libusbx is abstracted internally in such a way that it can hopefully
be ported to other operating systems. Please see the PORTING file
for more information.
libusb homepage:
http://libusb.org/
libusbx homepage:
http://libusbx.org/
Developers will wish to consult the API documentation:
http://libusb.sourceforge.net/api-1.0/
http://api.libusbx.org
Use the mailing list for questions, comments, etc:
http://libusb.org/wiki/MailingList
http://mailing-list.libusbx.org
- Peter Stuge <peter@stuge.se>
(use the mailing list rather than mailing developers directly)
- Pete Batard <pete@akeo.ie>
- Hans de Goede <hdegoede@redhat.com>
- Xiaofan Chen <xiaofanc@gmail.com>
- Ludovic Rousseau <ludovic.rousseau@gmail.com>
- Nathan Hjelm <hjelmn@users.sourceforge.net>
(Please use the mailing list rather than mailing developers directly)

8
compat/libusb-1.0/THANKS

@ -1,8 +0,0 @@ @@ -1,8 +0,0 @@
Development contributors are listed in the AUTHORS file. Other community
members who have made significant contributions in other areas are listed
in this file:
Alan Stern
Ludovic Rousseau
Tim Roberts
Xiaofan Chen

11
compat/libusb-1.0/TODO

@ -1,9 +1,2 @@ @@ -1,9 +1,2 @@
for 1.1 or future
==================
optional timerfd support (runtime detection)
notifications of hotplugged/unplugged devices
offer API to create/destroy handle_events thread
isochronous sync I/O?
exposing of parent-child device relationships
"usb primer" introduction docs
more examples
Please see the libusbx roadmap by visiting:
https://github.com/libusbx/libusbx/issues/milestones?direction=asc&sort=due_date

108
compat/libusb-1.0/configure.ac

@ -8,25 +8,25 @@ m4_define([LU_DEFINE_VERSION_RC_ATOM], @@ -8,25 +8,25 @@ m4_define([LU_DEFINE_VERSION_RC_ATOM],
[^#define\s*$1\s*"\(-rc[0-9]*\)".*], [\1]))])
dnl The m4_bregexp() returns (only) the numbers following the #define named
dnl in the first macro parameter. m4_define() then defines the name for use
dnl in AC_INIT().
dnl in AC_INIT.
LU_DEFINE_VERSION_ATOM([LIBUSB_MAJOR])
LU_DEFINE_VERSION_ATOM([LIBUSB_MINOR])
LU_DEFINE_VERSION_ATOM([LIBUSB_MICRO])
LU_DEFINE_VERSION_RC_ATOM([LIBUSB_RC])
AC_INIT([libusb], LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC, [libusb-devel@lists.sourceforge.net], [libusb], [http://www.libusb.org/])
AC_INIT([libusbx],[LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC],[libusbx-devel@lists.sourceforge.net],[libusbx],[http://libusbx.org])
# Library versioning
# These numbers should be tweaked on every release. Read carefully:
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
# http://sourceware.org/autobook/autobook/autobook_91.html
lt_current="2"
lt_current="1"
lt_revision="0"
lt_age="0"
lt_age="1"
LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}"
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_INIT_AUTOMAKE
AM_MAINTAINER_MODE
AC_CONFIG_SRCDIR([libusb/core.c])
@ -36,7 +36,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) @@ -36,7 +36,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_PREREQ([2.50])
AC_PROG_CC
AC_PROG_LIBTOOL
LT_INIT
LT_LANG([Windows Resource])
AC_C_INLINE
AM_PROG_CC_C_O
@ -45,26 +45,34 @@ AC_DEFINE([_GNU_SOURCE], 1, [Use GNU extensions]) @@ -45,26 +45,34 @@ AC_DEFINE([_GNU_SOURCE], 1, [Use GNU extensions])
LTLDFLAGS="${LTLDFLAGS} -no-undefined"
AC_MSG_CHECKING([operating system])
case $host in
*-linux*)
AC_MSG_RESULT([Linux])
backend="linux"
threads="posix"
;;
*-darwin*)
AC_MSG_RESULT([Darwin/Mac OS X])
backend="darwin"
threads="posix"
;;
*-openbsd*)
AC_MSG_RESULT([OpenBSD])
backend="openbsd"
threads="posix"
;;
*-netbsd*)
AC_MSG_RESULT([NetBSD (using OpenBSD backend)])
backend="openbsd"
AC_MSG_RESULT([NetBSD])
backend="netbsd"
threads="posix"
;;
*-mingw*)
AC_MSG_RESULT([Windows])
backend="windows"
threads="windows"
create_import_lib="yes"
AM_CFLAGS="${AM_CFLAGS} -fno-omit-frame-pointer"
;;
*-cygwin*)
AC_MSG_RESULT([Cygwin (using Windows backend)])
@ -74,24 +82,32 @@ case $host in @@ -74,24 +82,32 @@ case $host in
*)
AC_MSG_ERROR([unsupported operating system])
esac
case $backend in
linux)
AC_DEFINE(OS_LINUX, 1, [Linux backend])
AC_SUBST(OS_LINUX)
AC_CHECK_LIB(rt, clock_gettime, -pthread)
AC_SEARCH_LIBS(clock_gettime, rt, [], [], -pthread)
AC_ARG_ENABLE([udev],
[AC_HELP_STRING([--with-udev], [use udev for device enumeration and hotplug support (recommended, default: yes)])],
[], [enable_udev="yes"])
if test "x$enable_udev" = "xyes" ; then
# system has udev. use it or fail!
AC_CHECK_HEADERS([libudev.h],[],[AC_ERROR(["udev support requested but libudev not installed"])])
AC_CHECK_LIB([udev], [udev_new], [], [AC_ERROR(["udev support requested but libudev not installed"])])
AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug])
else
AC_CHECK_HEADERS([linux/netlink.h linux/filter.h], [], [AC_ERROR(["Linux netlink headers not found"])])
fi
AC_SUBST(USE_UDEV)
threads="posix"
[AC_HELP_STRING([--enable-udev], [use udev for device enumeration and hotplug support (recommended) [default=yes]])],
[], [enable_udev="yes"])
if test "x$enable_udev" = "xyes" ; then
# system has udev. use it or fail!
AC_CHECK_HEADERS([libudev.h],[],[AC_ERROR(["udev support requested but libudev not installed"])])
AC_CHECK_LIB([udev], [udev_new], [], [AC_ERROR(["udev support requested but libudev not installed"])])
AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug])
else
AC_CHECK_HEADERS([asm/types.h sys/socket.h], [], [])
AC_CHECK_HEADERS([linux/netlink.h linux/filter.h], [], [AC_ERROR(["Linux netlink headers not found"])], [
#ifdef HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
])
fi
AC_SUBST(USE_UDEV)
THREAD_CFLAGS="-pthread"
LIBS="${LIBS} -pthread"
AC_CHECK_HEADERS([poll.h])
@ -100,7 +116,6 @@ linux) @@ -100,7 +116,6 @@ linux)
darwin)
AC_DEFINE(OS_DARWIN, 1, [Darwin backend])
AC_SUBST(OS_DARWIN)
threads="posix"
LIBS="-lobjc -Wl,-framework,IOKit -Wl,-framework,CoreFoundation"
LTLDFLAGS="${LTLDFLAGS} -Wl,-prebind"
AC_CHECK_HEADERS([poll.h])
@ -112,7 +127,14 @@ darwin) @@ -112,7 +127,14 @@ darwin)
openbsd)
AC_DEFINE(OS_OPENBSD, 1, [OpenBSD backend])
AC_SUBST(OS_OPENBSD)
threads="posix"
THREAD_CFLAGS="-pthread"
LIBS="-pthread"
AC_CHECK_HEADERS([poll.h])
AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
;;
netbsd)
AC_DEFINE(OS_NETBSD, 1, [NetBSD backend])
AC_SUBST(OS_NETBSD)
THREAD_CFLAGS="-pthread"
LIBS="-pthread"
AC_CHECK_HEADERS([poll.h])
@ -126,13 +148,16 @@ windows) @@ -126,13 +148,16 @@ windows)
AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])
;;
esac
AC_SUBST(LIBS)
AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux)
AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin)
AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xopenbsd)
AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd)
AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows)
AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix)
AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes")
AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes)
if test "$threads" = posix; then
AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads])
@ -142,7 +167,7 @@ fi @@ -142,7 +167,7 @@ fi
AC_CHECK_HEADER([sys/timerfd.h], [timerfd_h=1], [timerfd_h=0])
AC_ARG_ENABLE([timerfd],
[AS_HELP_STRING([--enable-timerfd],
[use timerfd for timing (default auto)])],
[use timerfd for timing [default=auto]])],
[use_timerfd=$enableval], [use_timerfd='auto'])
if test "x$use_timerfd" = "xyes" -a "x$timerfd_h" = "x0"; then
@ -177,20 +202,42 @@ if test "x$log_enabled" != "xno"; then @@ -177,20 +202,42 @@ if test "x$log_enabled" != "xno"; then
fi
AC_ARG_ENABLE([debug-log], [AS_HELP_STRING([--enable-debug-log],
[enable debug logging (default n)])],
[start with debug message logging enabled [default=no]])],
[debug_log_enabled=$enableval],
[debug_log_enabled='no'])
if test "x$debug_log_enabled" != "xno"; then
AC_DEFINE([ENABLE_DEBUG_LOGGING], 1, [Debug message logging])
AC_DEFINE([ENABLE_DEBUG_LOGGING], 1, [Start with debug message logging enabled])
fi
AC_ARG_ENABLE([system-log], [AS_HELP_STRING([--enable-system-log],
[output logging messages to system wide log, if supported by the OS [default=no]])],
[system_log_enabled=$enableval],
[system_log_enabled='no'])
if test "x$system_log_enabled" != "xno"; then
AC_DEFINE([USE_SYSTEM_LOGGING_FACILITY], 1, [Enable output to system log])
fi
# Check if syslog is available in standard C library
AC_CHECK_HEADERS(syslog.h)
AC_CHECK_FUNC([syslog], [have_syslog=yes], [have_syslog=no])
if test "x$have_syslog" != "xno"; then
AC_DEFINE([HAVE_SYSLOG_FUNC], 1, [syslog() function available])
fi
# Examples build
AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build],
[build example applications (default n)])],
[build example applications [default=no]])],
[build_examples=$enableval],
[build_examples='no'])
AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"])
# Tests build
AC_ARG_ENABLE([tests-build], [AS_HELP_STRING([--enable-tests-build],
[build test applications [default=no]])],
[build_tests=$enableval],
[build_tests='no'])
AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != "xno"])
# check for -fvisibility=hidden compiler support (GCC >= 3.4)
saved_cflags="$CFLAGS"
# -Werror required for cygwin
@ -217,8 +264,9 @@ AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = "xyes"]) @@ -217,8 +264,9 @@ AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = "xyes"])
# headers not available on all platforms but required on others
AC_CHECK_HEADERS([sys/time.h])
AC_CHECK_FUNCS(gettimeofday)
AC_CHECK_HEADERS([signal.h])
AM_CFLAGS="-std=gnu99 -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_CFLAGS}"
AM_CFLAGS="${AM_CFLAGS} -std=gnu99 -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_CFLAGS}"
AC_SUBST(AM_CFLAGS)
AC_SUBST(LTLDFLAGS)
@ -226,4 +274,8 @@ AC_SUBST(LTLDFLAGS) @@ -226,4 +274,8 @@ AC_SUBST(LTLDFLAGS)
AC_CONFIG_FILES([libusb-1.0.pc])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([libusb/Makefile])
AC_CONFIG_FILES([examples/Makefile])
AC_CONFIG_FILES([tests/Makefile])
AC_CONFIG_FILES([doc/Makefile])
AC_CONFIG_FILES([doc/doxygen.cfg])
AC_OUTPUT

3
compat/libusb-1.0/doc/Makefile.am

@ -5,6 +5,5 @@ docs: doxygen.cfg @@ -5,6 +5,5 @@ docs: doxygen.cfg
docs-upload: docs
ln -s html api-1.0
rsync -av api-1.0/ web.sourceforge.net:htdocs/api-1.0/
scp -r api-1.0 pbatard@web.sourceforge.net:/home/project-web/libusbx/htdocs
rm -f api-1.0

38
compat/libusb-1.0/doc/doxygen.cfg.in

@ -25,13 +25,26 @@ DOXYFILE_ENCODING = UTF-8 @@ -25,13 +25,26 @@ DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = libusb
PROJECT_NAME =
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "eXpand your USB potential"
# With the PROJECT_LOGO tag one can specify an logo or icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will
# copy the logo to the output directory.
PROJECT_LOGO = libusbx.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
@ -154,13 +167,6 @@ QT_AUTOBRIEF = NO @@ -154,13 +167,6 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
# If the DETAILS_AT_TOP tag is set to YES then Doxygen
# will output the detailed description near the top, like JavaDoc.
# If set to NO, the detailed description appears after the member
# documentation.
DETAILS_AT_TOP = NO
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
@ -401,12 +407,6 @@ MAX_INITIALIZER_LINES = 30 @@ -401,12 +407,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
# in the documentation. The default is NO.
SHOW_DIRECTORIES = NO
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from the
# version control system). Doxygen will invoke the program by executing (via
@ -424,7 +424,7 @@ FILE_VERSION_FILTER = @@ -424,7 +424,7 @@ FILE_VERSION_FILTER =
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
@ -701,12 +701,6 @@ HTML_FOOTER = @@ -701,12 +701,6 @@ HTML_FOOTER =
HTML_STYLESHEET =
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)

6
compat/libusb-1.0/examples/Makefile.am

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
AM_CPPFLAGS = -I$(top_srcdir)/libusb
LDADD = ../libusb/libusb-1.0.la
noinst_PROGRAMS = listdevs hotplugtest testlibusb1
noinst_PROGRAMS = listdevs xusb fxload hotplugtest
if HAVE_SIGACTION
noinst_PROGRAMS += dpfp
@ -13,3 +14,6 @@ endif @@ -13,3 +14,6 @@ endif
sam3u_benchmark_SOURCES = sam3u_benchmark.c
noinst_PROGRAMS += sam3u_benchmark
endif
fxload_SOURCES = ezusb.c ezusb.h fxload.c
fxload_CFLAGS = $(THREAD_CFLAGS) $(AM_CFLAGS)

9
compat/libusb-1.0/examples/dpfp.c

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* libusb example program to manipulate U.are.U 4000B fingerprint scanner.
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
* libusbx example program to manipulate U.are.U 4000B fingerprint scanner.
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
*
* Basic image capture program only, does not consider the powerup quirks or
* the fact that image encryption may be enabled. Not expected to work
@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <libusb.h>
#include "libusb.h"
#define EP_INTR (1 | LIBUSB_ENDPOINT_IN)
#define EP_DATA (2 | LIBUSB_ENDPOINT_IN)
@ -164,7 +164,7 @@ static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer) @@ -164,7 +164,7 @@ static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer)
static int set_mode_async(unsigned char data)
{
unsigned char *buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
struct libusb_transfer *transfer;
if (!buf)
@ -504,4 +504,3 @@ out: @@ -504,4 +504,3 @@ out:
libusb_exit(NULL);
return r >= 0 ? r : -r;
}

9
compat/libusb-1.0/examples/dpfp_threaded.c

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* libusb example program to manipulate U.are.U 4000B fingerprint scanner.
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
* libusbx example program to manipulate U.are.U 4000B fingerprint scanner.
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
*
* Basic image capture program only, does not consider the powerup quirks or
* the fact that image encryption may be enabled. Not expected to work
@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <libusb.h>
#include "libusb.h"
#define EP_INTR (1 | LIBUSB_ENDPOINT_IN)
#define EP_DATA (2 | LIBUSB_ENDPOINT_IN)
@ -193,7 +193,7 @@ static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer) @@ -193,7 +193,7 @@ static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer)
static int set_mode_async(unsigned char data)
{
unsigned char *buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
struct libusb_transfer *transfer;
if (!buf)
@ -542,4 +542,3 @@ out: @@ -542,4 +542,3 @@ out:
libusb_exit(NULL);
return r >= 0 ? r : -r;
}

118
compat/libusb-1.0/examples/hotplugtest.c

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
/*
* libusb example program for hotplug API
* Copyright (C) 2012-2013 Nathan Hjelm <hjelmn@mac.ccom>
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.ccom>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -19,77 +20,78 @@ @@ -19,77 +20,78 @@
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
#include <unistd.h>
#include <libusb.h>
#include "libusb.h"
int done = 0;
libusb_device_handle *handle;
static int hotplug_callback (libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {
struct libusb_device_descriptor desc;
int rc;
static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
struct libusb_device_descriptor desc;
int rc;
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error getting device descriptor\n");
}
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error getting device descriptor\n");
}
printf ("Device attach: %04x:%04x\n", desc.idVendor, desc.idProduct);
printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
libusb_open (dev, &handle);
libusb_open (dev, &handle);
done++;
done++;
return 0;
return 0;
}
static int hotplug_callback_detach (libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {
printf ("Device detached\n");
static int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
printf ("Device detached\n");
libusb_close (handle);
libusb_close (handle);
done++;
return 0;
done++;
return 0;
}
int main (int argc, char *argv[]) {
libusb_hotplug_callback_handle hp[2];
int product_id, vendor_id, class_id;
int rc;
vendor_id = (argc > 1) ? strtol (argv[1], NULL, 0) : 0x045a;
product_id = (argc > 2) ? strtol (argv[2], NULL, 0) : 0x5005;
class_id = (argc > 3) ? strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY;
libusb_init (NULL);
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf ("Hotplug not supported by this build of libusb\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 0, vendor_id,
product_id, class_id, hotplug_callback, NULL, &hp[0]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 0\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, vendor_id,
product_id,class_id, hotplug_callback_detach, NULL, &hp[1]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 1\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
while (done < 2) {
libusb_handle_events (NULL);
}
libusb_exit (NULL);
int main(int argc, char *argv[])
{
libusb_hotplug_callback_handle hp[2];
int product_id, vendor_id, class_id;
int rc;
vendor_id = (argc > 1) ? strtol (argv[1], NULL, 0) : 0x045a;
product_id = (argc > 2) ? strtol (argv[2], NULL, 0) : 0x5005;
class_id = (argc > 3) ? strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY;
libusb_init (NULL);
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf ("Hotplug capabilites are not supported on this platform\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 0, vendor_id,
product_id, class_id, hotplug_callback, NULL, &hp[0]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 0\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, vendor_id,
product_id,class_id, hotplug_callback_detach, NULL, &hp[1]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 1\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
while (done < 2) {
libusb_handle_events (NULL);
}
libusb_exit (NULL);
}

21
compat/libusb-1.0/examples/listdevs.c

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* libusb example program to list devices on the bus
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
* libusbx example program to list devices on the bus
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -18,14 +18,14 @@ @@ -18,14 +18,14 @@
*/
#include <stdio.h>
#include <sys/types.h>
#include <libusb.h>
#include "libusb.h"
static void print_devs(libusb_device **devs)
{
libusb_device *dev;
int i = 0;
int i = 0, j = 0;
uint8_t path[8];
while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
@ -35,9 +35,17 @@ static void print_devs(libusb_device **devs) @@ -35,9 +35,17 @@ static void print_devs(libusb_device **devs)
return;
}
printf("%04x:%04x (bus %d, device %d)\n",
printf("%04x:%04x (bus %d, device %d)",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
r = libusb_get_port_numbers(dev, path, sizeof(path));
if (r > 0) {
printf(" path: %d", path[0]);
for (j = 1; j < r; j++)
printf(".%d", path[j]);
}
printf("\n");
}
}
@ -61,4 +69,3 @@ int main(void) @@ -61,4 +69,3 @@ int main(void)
libusb_exit(NULL);
return 0;
}

2
compat/libusb-1.0/examples/sam3u_benchmark.c

@ -40,7 +40,7 @@ static struct libusb_device_handle *devh = NULL; @@ -40,7 +40,7 @@ static struct libusb_device_handle *devh = NULL;
static unsigned long num_bytes = 0, num_xfer = 0;
static struct timeval tv_start;
static void cb_xfr(struct libusb_transfer *xfr)
static void LIBUSB_CALL cb_xfr(struct libusb_transfer *xfr)
{
unsigned int i;

256
compat/libusb-1.0/examples/testlibusb1.c

@ -1,256 +0,0 @@ @@ -1,256 +0,0 @@
/*
* Test suite program based of libusb-0.1-compat testlibusb
* Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.ccom>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <string.h>
#include <libusb.h>
int verbose = 0;
static void print_endpoint_comp(const struct libusb_ss_endpoint_companion_descriptor *ep_comp)
{
printf(" USB 3.0 Endpoint Companion:\n");
printf(" bMaxBurst: %d\n", ep_comp->bMaxBurst);
printf(" bmAttributes: 0x%02x\n", ep_comp->bmAttributes);
printf(" wBytesPerInterval: %d\n", ep_comp->wBytesPerInterval);
}
static void print_endpoint(const struct libusb_endpoint_descriptor *endpoint)
{
int i, ret;
printf(" Endpoint:\n");
printf(" bEndpointAddress: %02xh\n", endpoint->bEndpointAddress);
printf(" bmAttributes: %02xh\n", endpoint->bmAttributes);
printf(" wMaxPacketSize: %d\n", endpoint->wMaxPacketSize);
printf(" bInterval: %d\n", endpoint->bInterval);
printf(" bRefresh: %d\n", endpoint->bRefresh);
printf(" bSynchAddress: %d\n", endpoint->bSynchAddress);
for (i = 0 ; i < endpoint->extra_length ; ) {
if (LIBUSB_DT_SS_ENDPOINT_COMPANION == endpoint->extra[i+1]) {
struct libusb_ss_endpoint_companion_descriptor *ep_comp;
ret = libusb_parse_ss_endpoint_comp(endpoint->extra+i, endpoint->extra[0], &ep_comp);
if (LIBUSB_SUCCESS != ret) {
continue;
}
print_endpoint_comp(ep_comp);
libusb_free_ss_endpoint_comp(ep_comp);
}
i += endpoint->extra[i];
}
}
static void print_altsetting(const struct libusb_interface_descriptor *interface)
{
int i;
printf(" Interface:\n");
printf(" bInterfaceNumber: %d\n", interface->bInterfaceNumber);
printf(" bAlternateSetting: %d\n", interface->bAlternateSetting);
printf(" bNumEndpoints: %d\n", interface->bNumEndpoints);
printf(" bInterfaceClass: %d\n", interface->bInterfaceClass);
printf(" bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);
printf(" bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);
printf(" iInterface: %d\n", interface->iInterface);
for (i = 0; i < interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
static void print_2_0_ext_cap(struct libusb_usb_2_0_device_capability_descriptor *usb_2_0_ext_cap)
{
printf(" USB 2.0 Extension Capabilities:\n");
printf(" bDevCapabilityType: %d\n", usb_2_0_ext_cap->bDevCapabilityType);
printf(" bmAttributes: 0x%x\n", usb_2_0_ext_cap->bmAttributes);
}
static void print_ss_usb_cap(struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap)
{
printf(" USB 3.0 Capabilities:\n");
printf(" bDevCapabilityType: %d\n", ss_usb_cap->bDevCapabilityType);
printf(" bmAttributes: 0x%x\n", ss_usb_cap->bmAttributes);
printf(" wSpeedSupported: 0x%x\n", ss_usb_cap->wSpeedSupported);
printf(" bFunctionalitySupport: %d\n", ss_usb_cap->bFunctionalitySupport);
printf(" bU1devExitLat: %d\n", ss_usb_cap->bU1DevExitLat);
printf(" bU2devExitLat: %d\n", ss_usb_cap->bU2DevExitLat);
}
static void print_bos(libusb_device_handle *handle)
{
unsigned char buffer[128];
struct libusb_bos_descriptor *bos;
int ret;
ret = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, buffer, 128);
if (0 > ret) {
return;
}
ret = libusb_parse_bos_descriptor(buffer, 128, &bos);
if (0 > ret) {
return;
}
printf(" Binary Object Store (BOS):\n");
printf(" wTotalLength: %d\n", bos->wTotalLength);
printf(" bNumDeviceCaps: %d\n", bos->bNumDeviceCaps);
if (bos->usb_2_0_ext_cap) {
print_2_0_ext_cap(bos->usb_2_0_ext_cap);
}
if (bos->ss_usb_cap) {
print_ss_usb_cap(bos->ss_usb_cap);
}
}
static void print_interface(const struct libusb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
static void print_configuration(struct libusb_config_descriptor *config)
{
int i;
printf(" Configuration:\n");
printf(" wTotalLength: %d\n", config->wTotalLength);
printf(" bNumInterfaces: %d\n", config->bNumInterfaces);
printf(" bConfigurationValue: %d\n", config->bConfigurationValue);
printf(" iConfiguration: %d\n", config->iConfiguration);
printf(" bmAttributes: %02xh\n", config->bmAttributes);
printf(" MaxPower: %d\n", config->MaxPower);
for (i = 0; i < config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}
static int print_device(libusb_device *dev, int level)
{
struct libusb_device_descriptor desc;
libusb_device_handle *handle = NULL;
char description[256];
char string[256];
int ret, i;
ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0) {
fprintf(stderr, "failed to get device descriptor");
return -1;
}
ret = libusb_open(dev, &handle);
if (LIBUSB_SUCCESS == ret) {
if (desc.iManufacturer) {
ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string));
if (ret > 0)
snprintf(description, sizeof(description), "%s - ", string);
else
snprintf(description, sizeof(description), "%04X - ",
desc.idVendor);
} else
snprintf(description, sizeof(description), "%04X - ",
desc.idVendor);
if (desc.iProduct) {
ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string));
if (ret > 0)
snprintf(description + strlen(description), sizeof(description) -
strlen(description), "%s", string);
else
snprintf(description + strlen(description), sizeof(description) -
strlen(description), "%04X", desc.idProduct);
} else
snprintf(description + strlen(description), sizeof(description) -
strlen(description), "%04X", desc.idProduct);
} else {
snprintf(description, sizeof(description), "%04X - %04X",
desc.idVendor, desc.idProduct);
}
printf("%.*sDev (bus %d, device %d): %s\n", level * 2, " ",
libusb_get_bus_number(dev), libusb_get_device_address(dev), description);
if (handle && verbose) {
if (desc.iSerialNumber) {
ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string));
if (ret > 0)
printf("%.*s - Serial Number: %s\n", level * 2,
" ", string);
}
}
if (verbose) {
for (i = 0; i < desc.bNumConfigurations; i++) {
struct libusb_config_descriptor *config;
ret = libusb_get_config_descriptor(dev, i, &config);
if (LIBUSB_SUCCESS != ret) {
printf(" Couldn't retrieve descriptors\n");
continue;
}
print_configuration(config);
libusb_free_config_descriptor(config);
}
if (handle && desc.bcdUSB >= 0x0201) {
print_bos(handle);
}
}
if (handle)
libusb_close(handle);
return 0;
}
int main(int argc, char *argv[])
{
libusb_device **devs;
ssize_t cnt;
int r, i;
if (argc > 1 && !strcmp(argv[1], "-v"))
verbose = 1;
r = libusb_init(NULL);
if (r < 0)
return r;
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0)
return (int) cnt;
for (i = 0 ; devs[i] ; ++i) {
print_device(devs[i], 0);
}
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
return 0;
}

5
compat/libusb-1.0/libusb-1.0.pc.in

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

46
compat/libusb-1.0/libusb/Makefile.am

@ -1,32 +1,46 @@ @@ -1,32 +1,46 @@
all: libusb-1.0.la libusb-1.0.dll
AUTOMAKE_OPTIONS = subdir-objects
lib_LTLIBRARIES = libusb-1.0.la
POSIX_POLL_SRC = os/poll_posix.c
LINUX_USBFS_SRC = os/linux_usbfs.c
DARWIN_USB_SRC = os/darwin_usb.c
OPENBSD_USB_SRC = os/openbsd_usb.c
WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc \
libusb-1.0.def
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
WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h
EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
$(WINDOWS_USB_SRC) os/threads_posix.c os/threads_windows.c \
$(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
$(POSIX_POLL_SRC) \
os/threads_posix.c os/threads_windows.c \
os/linux_udev.c os/linux_netlink.c
if OS_LINUX
if USE_UDEV
OS_SRC = $(LINUX_USBFS_SRC) os/linux_udev.c
OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \
os/linux_udev.c
else
OS_SRC = $(LINUX_USBFS_SRC) os/linux_netlink.c
OS_SRC = $(LINUX_USBFS_SRC) $(POSIX_POLL_SRC) \
os/linux_netlink.c
endif
endif
if OS_DARWIN
OS_SRC = $(DARWIN_USB_SRC)
OS_SRC = $(DARWIN_USB_SRC) $(POSIX_POLL_SRC)
AM_CFLAGS_EXT = -no-cpp-precomp
endif
if OS_OPENBSD
OS_SRC = $(OPENBSD_USB_SRC)
OS_SRC = $(OPENBSD_USB_SRC) $(POSIX_POLL_SRC)
endif
if OS_NETBSD
OS_SRC = $(NETBSD_USB_SRC) $(POSIX_POLL_SRC)
endif
if OS_WINDOWS
@ -35,7 +49,13 @@ OS_SRC = $(WINDOWS_USB_SRC) @@ -35,7 +49,13 @@ OS_SRC = $(WINDOWS_USB_SRC)
.rc.lo:
$(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@
libusb-1.0.rc: version.h
libusb-1.0.rc: version.h version_nano.h
endif
libusb-1.0.dll: libusb-1.0.def
if CREATE_IMPORT_LIB
# Rebuild the import lib from the .def so that MS and MinGW DLLs can be interchanged
$(AM_V_GEN)$(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def $(srcdir)/libusb-1.0.def --dllname $@ --output-lib .libs/$@.a
endif
if THREADS_POSIX
@ -44,12 +64,12 @@ else @@ -44,12 +64,12 @@ else
THREADS_SRC = os/threads_windows.h os/threads_windows.c
endif
libusb_1_0_la_CFLAGS = $(AM_CFLAGS) \
-DLIBUSB_DESCRIBE=\"`git --git-dir "$(top_srcdir)/.git" describe --tags 2>/dev/null`\"
libusb_1_0_la_CFLAGS = $(AM_CFLAGS)
libusb_1_0_la_LDFLAGS = $(LTLDFLAGS)
libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c sync.c $(OS_SRC) \
hotplug.h hotplug.c os/linux_usbfs.h os/darwin_usb.h os/windows_usb.h \
$(THREADS_SRC) os/poll_posix.h os/poll_windows.h
libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c strerror.c sync.c \
os/linux_usbfs.h os/darwin_usb.h os/windows_usb.h os/windows_common.h \
hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \
os/poll_posix.h os/poll_windows.h
hdrdir = $(includedir)/libusb-1.0
hdr_HEADERS = libusb.h

797
compat/libusb-1.0/libusb/core.c

File diff suppressed because it is too large Load Diff

841
compat/libusb-1.0/libusb/descriptor.c

File diff suppressed because it is too large Load Diff

306
compat/libusb-1.0/libusb/hotplug.c

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
/* -*- Mode: C; indent-tabs-mode:nil ; c-basic-offset:8 -*- */
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
/*
* Hotplug functions for libusb
* Copyright (C) 2012-2013 Nathan Hjelm <hjelmn@mac.com>
* Copyright (C) 2012-2013 Peter Stuge <peter@stuge.se>
* Hotplug functions for libusbx
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
* Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -25,7 +25,9 @@ @@ -25,7 +25,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <assert.h>
#include "libusbi.h"
@ -33,27 +35,39 @@ @@ -33,27 +35,39 @@
/**
* @defgroup hotplug Device hotplug event notification
* This page details how to use the libusb hotplug interface.
* This page details how to use the libusb hotplug interface, where available.
*
* Be mindful that not all platforms currently implement hotplug notification and
* that you should first call on \ref libusb_has_capability() with parameter
* \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
*
* \page hotplug Device hotplug event notification
*
* \section intro Introduction
*
* Releases of libusb 1.0 newer than 1.X have added support for hotplug
* events. This interface allows you to request notification for the
* arrival and departure of matching USB devices.
* Version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, has added support
* for hotplug events on <b>some</b> platforms (you should test if your platform
* supports hotplug notification by calling \ref libusb_has_capability() with
* parameter \ref LIBUSB_CAP_HAS_HOTPLUG).
*
* This interface allows you to request notification for the arrival and departure
* of matching USB devices.
*
* To receive hotplug notification you register a callback by calling
* libusb_hotplug_register_callback(). This function will optionally return
* a handle that can be passed to libusb_hotplug_deregister_callback().
* \ref libusb_hotplug_register_callback(). This function will optionally return
* a handle that can be passed to \ref libusb_hotplug_deregister_callback().
*
* A callback function must return an int (0 or 1) indicating whether the callback is
* expecting additional events. Returning 0 will rearm the callback and 1 will cause
* the callback to be deregistered.
* the callback to be deregistered. Note that when callbacks are called from
* libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
* flag, the callback return value is ignored, iow you cannot cause a callback
* to be deregistered by returning 1 when it is called from
* libusb_hotplug_register_callback().
*
* Callbacks for a particulat context are automatically deregistered by libusb_exit().
* Callbacks for a particular context are automatically deregistered by libusb_exit().
*
* As of 1.X there are two supported hotplug events:
* As of 1.0.16 there are two supported hotplug events:
* - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
* - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
*
@ -66,7 +80,7 @@ @@ -66,7 +80,7 @@
* are invalid and will remain so even if the device comes back.
*
* When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
* safe to call any libusb function that takes a libusb_device. On the other hand,
* safe to call any libusbx function that takes a libusb_device. On the other hand,
* when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
* is libusb_get_device_descriptor().
*
@ -128,160 +142,170 @@ int main (void) { @@ -128,160 +142,170 @@ int main (void) {
\endcode
*/
static int usbi_hotplug_match_cb (struct libusb_device *dev, libusb_hotplug_event event,
struct libusb_hotplug_callback *hotplug_cb) {
struct libusb_context *ctx = dev->ctx;
/* Handle lazy deregistration of callback */
if (hotplug_cb->needs_free) {
/* Free callback */
return 1;
}
if (!(hotplug_cb->events & event)) {
return 0;
}
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
return 0;
}
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
hotplug_cb->product_id != dev->device_descriptor.idProduct) {
return 0;
}
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
return 0;
}
return hotplug_cb->cb (ctx == usbi_default_context ? NULL : ctx,
dev, event, hotplug_cb->user_data);
static int usbi_hotplug_match_cb (struct libusb_context *ctx,
struct libusb_device *dev, libusb_hotplug_event event,
struct libusb_hotplug_callback *hotplug_cb)
{
/* Handle lazy deregistration of callback */
if (hotplug_cb->needs_free) {
/* Free callback */
return 1;
}
if (!(hotplug_cb->events & event)) {
return 0;
}
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
return 0;
}
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
hotplug_cb->product_id != dev->device_descriptor.idProduct) {
return 0;
}
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
return 0;
}
return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
}
void usbi_hotplug_match(struct libusb_device *dev, libusb_hotplug_event event) {
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event)
{
struct libusb_hotplug_callback *hotplug_cb, *next;
struct libusb_context *ctx = dev->ctx;
int ret;
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
int ret = usbi_hotplug_match_cb (dev, event, hotplug_cb);
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
if (ret) {
list_del(&hotplug_cb->list);
free(hotplug_cb);
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
if (ret) {
list_del(&hotplug_cb->list);
free(hotplug_cb);
}
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
/* loop through and disconnect all open handles for this device */
if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
struct libusb_device_handle *handle;
usbi_mutex_lock(&ctx->open_devs_lock);
list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
if (dev == handle->dev) {
usbi_handle_disconnect (handle);
}
}
usbi_mutex_unlock(&ctx->open_devs_lock);
}
/* the backend is expected to call the callback for each active transfer */
}
int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
libusb_hotplug_event events,
libusb_hotplug_flag flags,
int vendor_id, int product_id,
int dev_class,
libusb_hotplug_callback_fn cb_fn,
void *user_data, libusb_hotplug_callback_handle *handle) {
libusb_hotplug_callback *new_callback;
static int handle_id = 1;
/* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
return LIBUSB_ERROR_NOT_SUPPORTED;
}
/* check for sane values */
if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
(LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
(LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
!cb_fn) {
return LIBUSB_ERROR_INVALID_PARAM;
}
USBI_GET_CONTEXT(ctx);
new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
if (!new_callback) {
return LIBUSB_ERROR_NO_MEM;
}
new_callback->ctx = ctx;
new_callback->vendor_id = vendor_id;
new_callback->product_id = product_id;
new_callback->dev_class = dev_class;
new_callback->flags = flags;
new_callback->events = events;
new_callback->cb = cb_fn;
new_callback->user_data = user_data;
new_callback->needs_free = 0;
libusb_hotplug_event events, libusb_hotplug_flag flags,
int vendor_id, int product_id, int dev_class,
libusb_hotplug_callback_fn cb_fn, void *user_data,
libusb_hotplug_callback_handle *handle)
{
libusb_hotplug_callback *new_callback;
static int handle_id = 1;
/* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
return LIBUSB_ERROR_NOT_SUPPORTED;
}
/* check for sane values */
if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
(LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
(LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
!cb_fn) {
return LIBUSB_ERROR_INVALID_PARAM;
}
USBI_GET_CONTEXT(ctx);
new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
if (!new_callback) {
return LIBUSB_ERROR_NO_MEM;
}
new_callback->ctx = ctx;
new_callback->vendor_id = vendor_id;
new_callback->product_id = product_id;
new_callback->dev_class = dev_class;
new_callback->flags = flags;
new_callback->events = events;
new_callback->cb = cb_fn;
new_callback->user_data = user_data;
new_callback->needs_free = 0;
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
/* protect the handle by the context hotplug lock. it doesn't matter if the same handle is used for different
contexts only that the handle is unique for this context */
new_callback->handle = handle_id++;
/* protect the handle by the context hotplug lock. it doesn't matter if the same handle
* is used for different contexts only that the handle is unique for this context */
new_callback->handle = handle_id++;
list_add(&new_callback->list, &ctx->hotplug_cbs);
if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
struct libusb_device *dev;
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
usbi_mutex_lock(&ctx->usb_devs_lock);
list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
(void) usbi_hotplug_match_cb (dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, new_callback);
}
if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
int i, len;
struct libusb_device **devs;
usbi_mutex_unlock(&ctx->usb_devs_lock);
}
len = (int) libusb_get_device_list(ctx, &devs);
if (len < 0) {
libusb_hotplug_deregister_callback(ctx,
new_callback->handle);
return len;
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
for (i = 0; i < len; i++) {
usbi_hotplug_match_cb(ctx, devs[i],
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
new_callback);
}
if (handle) {
*handle = new_callback->handle;
}
libusb_free_device_list(devs, 1);
}
return LIBUSB_SUCCESS;
if (handle) {
*handle = new_callback->handle;
}
return LIBUSB_SUCCESS;
}
void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, libusb_hotplug_callback_handle handle) {
struct libusb_hotplug_callback *hotplug_cb;
/* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
return;
}
USBI_GET_CONTEXT(ctx);
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
struct libusb_hotplug_callback) {
if (handle == hotplug_cb->handle) {
/* Mark this callback for deregistration */
hotplug_cb->needs_free = 1;
}
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
libusb_hotplug_callback_handle handle)
{
struct libusb_hotplug_callback *hotplug_cb;
libusb_hotplug_message message;
ssize_t ret;
/* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
return;
}
USBI_GET_CONTEXT(ctx);
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
struct libusb_hotplug_callback) {
if (handle == hotplug_cb->handle) {
/* Mark this callback for deregistration */
hotplug_cb->needs_free = 1;
}
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
/* wakeup handle_events to do the actual free */
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) {
@ -291,7 +315,7 @@ void usbi_hotplug_deregister_all(struct libusb_context *ctx) { @@ -291,7 +315,7 @@ void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
struct libusb_hotplug_callback) {
list_del(&hotplug_cb->list);
free(hotplug_cb);
free(hotplug_cb);
}
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);

31
compat/libusb-1.0/libusb/hotplug.h

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
/* -*- Mode: C; indent-tabs-mode:nil ; c-basic-offset:8 -*- */
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
/*
* Hotplug support for libusb 1.0
* Copyright (C) 2012 Nathan Hjelm <hjelmn@users.sourceforge.net>
* Copyright (C) 2012 Peter Stuge <peter@stuge.se>
* Hotplug support for libusbx
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
* Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -22,6 +22,10 @@ @@ -22,6 +22,10 @@
#if !defined(USBI_HOTPLUG_H)
#define USBI_HOTPLUG_H
#ifndef LIBUSBI_H
#include "libusbi.h"
#endif
/** \ingroup hotplug
* The hotplug callback structure. The user populates this structure with
* libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback()
@ -41,7 +45,7 @@ struct libusb_hotplug_callback { @@ -41,7 +45,7 @@ struct libusb_hotplug_callback {
int dev_class;
/** Hotplug callback flags */
libusb_hotplug_flag flags;
libusb_hotplug_flag flags;
/** Event(s) that will trigger this callback */
libusb_hotplug_event events;
@ -49,29 +53,30 @@ struct libusb_hotplug_callback { @@ -49,29 +53,30 @@ struct libusb_hotplug_callback {
/** Callback function to invoke for matching event/device */
libusb_hotplug_callback_fn cb;
/** Handle for this callback (used to match on deregister) */
libusb_hotplug_callback_handle handle;
/** Handle for this callback (used to match on deregister) */
libusb_hotplug_callback_handle handle;
/** User data that will be passed to the callback function */
void *user_data;
/** Callback is marked for deletion */
int needs_free;
/** Callback is marked for deletion */
int needs_free;
/** List this callback is registered in (ctx->hotplug_cbs) */
struct list_head list;
struct list_head list;
};
typedef struct libusb_hotplug_callback libusb_hotplug_callback;
struct libusb_hotplug_message {
libusb_hotplug_event event;
struct libusb_device *device;
libusb_hotplug_event event;
struct libusb_device *device;
};
typedef struct libusb_hotplug_message libusb_hotplug_message;
void usbi_hotplug_deregister_all(struct libusb_context *ctx);
void usbi_hotplug_match(struct libusb_device *dev, libusb_hotplug_event event);
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event);
#endif

652
compat/libusb-1.0/libusb/io.c

File diff suppressed because it is too large Load Diff

40
compat/libusb-1.0/libusb/libusb-1.0.def

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
LIBRARY
LIBRARY "libusb-1.0.dll"
EXPORTS
libusb_alloc_transfer
libusb_alloc_transfer@4 = libusb_alloc_transfer
@ -26,14 +26,26 @@ EXPORTS @@ -26,14 +26,26 @@ EXPORTS
libusb_event_handling_ok@4 = libusb_event_handling_ok
libusb_exit
libusb_exit@4 = libusb_exit
libusb_free_bos_descriptor
libusb_free_bos_descriptor@4 = libusb_free_bos_descriptor
libusb_free_config_descriptor
libusb_free_config_descriptor@4 = libusb_free_config_descriptor
libusb_free_container_id_descriptor
libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor
libusb_free_device_list
libusb_free_device_list@8 = libusb_free_device_list
libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
libusb_free_ss_usb_device_capability_descriptor
libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
libusb_free_transfer
libusb_free_transfer@4 = libusb_free_transfer
libusb_free_usb_2_0_extension_descriptor
libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor
libusb_get_active_config_descriptor
libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor
libusb_get_bos_descriptor
libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor
libusb_get_bus_number
libusb_get_bus_number@4 = libusb_get_bus_number
libusb_get_config_descriptor
@ -42,6 +54,8 @@ EXPORTS @@ -42,6 +54,8 @@ EXPORTS
libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
libusb_get_configuration
libusb_get_configuration@8 = libusb_get_configuration
libusb_get_container_id_descriptor
libusb_get_container_id_descriptor@12 = libusb_get_container_id_descriptor
libusb_get_device
libusb_get_device@4 = libusb_get_device
libusb_get_device_address
@ -58,10 +72,24 @@ EXPORTS @@ -58,10 +72,24 @@ EXPORTS
libusb_get_max_packet_size@8 = libusb_get_max_packet_size
libusb_get_next_timeout
libusb_get_next_timeout@8 = libusb_get_next_timeout
libusb_get_parent
libusb_get_parent@4 = libusb_get_parent
libusb_get_pollfds
libusb_get_pollfds@4 = libusb_get_pollfds
libusb_get_port_number
libusb_get_port_number@4 = libusb_get_port_number
libusb_get_port_numbers
libusb_get_port_numbers@12 = libusb_get_port_numbers
libusb_get_port_path
libusb_get_port_path@16 = libusb_get_port_path
libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
libusb_get_ss_usb_device_capability_descriptor
libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
libusb_get_string_descriptor_ascii
libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
libusb_get_usb_2_0_extension_descriptor
libusb_get_usb_2_0_extension_descriptor@12 = libusb_get_usb_2_0_extension_descriptor
libusb_get_version
libusb_get_version@0 = libusb_get_version
libusb_handle_events
@ -76,6 +104,10 @@ EXPORTS @@ -76,6 +104,10 @@ EXPORTS
libusb_handle_events_timeout_completed@12 = libusb_handle_events_timeout_completed
libusb_has_capability
libusb_has_capability@4 = libusb_has_capability
libusb_hotplug_deregister_callback
libusb_hotplug_deregister_callback@8 = libusb_hotplug_deregister_callback
libusb_hotplug_register_callback
libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
libusb_init
libusb_init@4 = libusb_init
libusb_interrupt_transfer
@ -98,6 +130,8 @@ EXPORTS @@ -98,6 +130,8 @@ EXPORTS
libusb_release_interface@8 = libusb_release_interface
libusb_reset_device
libusb_reset_device@4 = libusb_reset_device
libusb_set_auto_detach_kernel_driver
libusb_set_auto_detach_kernel_driver@8 = libusb_set_auto_detach_kernel_driver
libusb_set_configuration
libusb_set_configuration@8 = libusb_set_configuration
libusb_set_debug
@ -106,6 +140,10 @@ EXPORTS @@ -106,6 +140,10 @@ EXPORTS
libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
libusb_set_pollfd_notifiers
libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
libusb_setlocale
libusb_setlocale@4 = libusb_setlocale
libusb_strerror
libusb_strerror@4 = libusb_strerror
libusb_submit_transfer
libusb_submit_transfer@4 = libusb_submit_transfer
libusb_try_lock_events

13
compat/libusb-1.0/libusb/libusb-1.0.rc

@ -5,16 +5,22 @@ @@ -5,16 +5,22 @@
* The information can then be queried using standard APIs and can also be
* viewed with utilities such as Windows Explorer.
*/
#ifndef _WIN32_WCE
#include "winresrc.h"
#endif
#include "version.h"
#ifndef LIBUSB_VERSIONSTRING
#define LU_STR(s) #s
#define LU_XSTR(s) LU_STR(s)
#if LIBUSB_NANO > 0
#define LIBUSB_VERSIONSTRING LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." LU_XSTR(LIBUSB_MICRO) "." LU_XSTR(LIBUSB_NANO) LIBUSB_RC "\0"
#define LIBUSB_VERSIONSTRING \
LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \
LU_XSTR(LIBUSB_MICRO) "." LU_XSTR(LIBUSB_NANO) LIBUSB_RC "\0"
#else
#define LIBUSB_VERSIONSTRING LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." LU_XSTR(LIBUSB_MICRO) LIBUSB_RC "\0"
#define LIBUSB_VERSIONSTRING \
LU_XSTR(LIBUSB_MAJOR) "." LU_XSTR(LIBUSB_MINOR) "." \
LU_XSTR(LIBUSB_MICRO) LIBUSB_RC "\0"
#endif
#endif
@ -35,8 +41,7 @@ BEGIN @@ -35,8 +41,7 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "libusb.org\0"
VALUE "CompanyName", "libusbx.org\0"
VALUE "FileDescription", "C library for writing portable USB drivers in userspace\0"
VALUE "FileVersion", LIBUSB_VERSIONSTRING
VALUE "InternalName", "libusb\0"

580
compat/libusb-1.0/libusb/libusb.h

File diff suppressed because it is too large Load Diff

283
compat/libusb-1.0/libusb/libusbi.h

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/*
* Internal header for libusb
* Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
* Internal header for libusbx
* Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
* Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -21,7 +21,9 @@ @@ -21,7 +21,9 @@
#ifndef LIBUSBI_H
#define LIBUSBI_H
#include <config.h>
#include "config.h"
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
@ -31,14 +33,17 @@ @@ -31,14 +33,17 @@
#include <poll.h>
#endif
#include <libusb.h>
#include <version.h>
#ifdef HAVE_MISSING_H
#include "missing.h"
#endif
#include "libusb.h"
#include "version.h"
/* Inside the libusb code, mark all public functions as follows:
/* Inside the libusbx code, mark all public functions as follows:
* return_type API_EXPORTED function_name(params) { ... }
* But if the function returns a pointer, mark it as follows:
* DEFAULT_VISIBILITY return_type * LIBUSB_CALL function_name(params) { ... }
* In the libusb public header, mark all declarations as:
* In the libusbx public header, mark all declarations as:
* return_type LIBUSB_CALL function_name(params);
*/
#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY
@ -49,34 +54,50 @@ @@ -49,34 +54,50 @@
#define USB_MAXINTERFACES 32
#define USB_MAXCONFIG 8
/* Backend specific capabilities */
#define USBI_CAP_HAS_HID_ACCESS 0x00010000
#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000
/* Maximum number of bytes in a log line */
#define USBI_MAX_LOG_LEN 1024
/* Terminator for log lines */
#define USBI_LOG_LINE_END "\n"
/* The following is used to silence warnings for unused variables */
#define UNUSED(var) do { (void)(var); } while(0)
#if !defined(ARRAYSIZE)
#define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0]))
#endif
struct list_head {
struct list_head *prev, *next;
};
/* Get an entry from the list
* ptr - the address of this list_head element in "type"
* type - the data type that contains "member"
* member - the list_head element in "type"
* ptr - the address of this list_head element in "type"
* type - the data type that contains "member"
* member - the list_head element in "type"
*/
#define list_entry(ptr, type, member) \
((type *)((uintptr_t)(ptr) - (uintptr_t)(&((type *)0L)->member)))
((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
/* Get each entry from a list
* pos - A structure pointer has a "member" element
* head - list head
* member - the list_head element in "pos"
* type - the type of the first parameter
* pos - A structure pointer has a "member" element
* head - list head
* member - the list_head element in "pos"
* type - the type of the first parameter
*/
#define list_for_each_entry(pos, head, member, type) \
for (pos = list_entry((head)->next, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
for (pos = list_entry((head)->next, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member))
#define list_empty(entry) ((entry)->next == (entry))
@ -108,6 +129,15 @@ static inline void list_del(struct list_head *entry) @@ -108,6 +129,15 @@ static inline void list_del(struct list_head *entry)
{
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
entry->next = entry->prev = NULL;
}
static inline void *usbi_reallocf(void *ptr, size_t size)
{
void *ret = realloc(ptr, size);
if (!ret)
free(ptr);
return ret;
}
#define container_of(ptr, type, member) ({ \
@ -119,93 +149,52 @@ static inline void list_del(struct list_head *entry) @@ -119,93 +149,52 @@ static inline void list_del(struct list_head *entry)
#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0)
enum usbi_log_level {
LOG_LEVEL_DEBUG,
LOG_LEVEL_INFO,
LOG_LEVEL_WARNING,
LOG_LEVEL_ERROR,
};
void usbi_log(struct libusb_context *ctx, enum usbi_log_level level,
void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
const char *function, const char *format, ...);
void usbi_log_v(struct libusb_context *ctx, enum usbi_log_level level,
void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
const char *function, const char *format, va_list args);
#if !defined(_MSC_VER) || _MSC_VER >= 1400
#ifdef ENABLE_LOGGING
#define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__)
#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__)
#else
#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0)
#endif
#ifdef ENABLE_DEBUG_LOGGING
#define usbi_dbg(...) _usbi_log(NULL, LOG_LEVEL_DEBUG, __VA_ARGS__)
#else
#define usbi_dbg(...) do {} while(0)
#endif
#define usbi_info(ctx, ...) _usbi_log(ctx, LOG_LEVEL_INFO, __VA_ARGS__)
#define usbi_warn(ctx, ...) _usbi_log(ctx, LOG_LEVEL_WARNING, __VA_ARGS__)
#define usbi_err(ctx, ...) _usbi_log(ctx, LOG_LEVEL_ERROR, __VA_ARGS__)
#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__)
#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__)
#define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__)
#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
/* Old MS compilers don't support variadic macros. The code is simple, so we
* repeat it for each loglevel. Note that the debug case is special.
*
* Support for variadic macros was introduced in Visual C++ 2005.
* http://msdn.microsoft.com/en-us/library/ms177415%28v=VS.80%29.aspx
*/
static inline void usbi_info(struct libusb_context *ctx, const char *fmt, ...)
{
#ifdef ENABLE_LOGGING
va_list args;
va_start(args, fmt);
usbi_log_v(ctx, LOG_LEVEL_INFO, "", fmt, args);
va_end(args);
#else
(void)ctx;
#endif
#define LOG_BODY(ctxt, level) \
{ \
va_list args; \
va_start (args, format); \
usbi_log_v(ctxt, level, "", format, args); \
va_end(args); \
}
static inline void usbi_warn(struct libusb_context *ctx, const char *fmt, ...)
{
#ifdef ENABLE_LOGGING
va_list args;
va_start(args, fmt);
usbi_log_v(ctx, LOG_LEVEL_WARNING, "", fmt, args);
va_end(args);
#else
(void)ctx;
#define LOG_BODY(ctxt, level) do { (void)(ctxt); } while(0)
#endif
}
static inline void usbi_err(struct libusb_context *ctx, const char *fmt, ...)
{
#ifdef ENABLE_LOGGING
va_list args;
va_start(args, fmt);
usbi_log_v(ctx, LOG_LEVEL_ERROR, "", fmt, args);
va_end(args);
#else
(void)ctx;
#endif
}
static inline void usbi_info(struct libusb_context *ctx, const char *format,
...)
LOG_BODY(ctx,LIBUSB_LOG_LEVEL_INFO)
static inline void usbi_warn(struct libusb_context *ctx, const char *format,
...)
LOG_BODY(ctx,LIBUSB_LOG_LEVEL_WARNING)
static inline void usbi_err( struct libusb_context *ctx, const char *format,
...)
LOG_BODY(ctx,LIBUSB_LOG_LEVEL_ERROR)
static inline void usbi_dbg(const char *fmt, ...)
{
#ifdef ENABLE_DEBUG_LOGGING
va_list args;
va_start(args, fmt);
usbi_log_v(NULL, LOG_LEVEL_DEBUG, "", fmt, args);
va_end(args);
#else
(void)fmt;
#endif
}
static inline void usbi_dbg(const char *format, ...)
LOG_BODY(NULL,LIBUSB_LOG_LEVEL_DEBUG)
#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
@ -221,32 +210,13 @@ static inline void usbi_dbg(const char *fmt, ...) @@ -221,32 +210,13 @@ static inline void usbi_dbg(const char *fmt, ...)
#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN))
#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer))
/* Internal abstractions for thread synchronization and poll */
/* Internal abstraction for thread synchronization */
#if defined(THREADS_POSIX)
#include <os/threads_posix.h>
#elif defined(OS_WINDOWS)
#include "os/threads_posix.h"
#elif defined(OS_WINDOWS) || defined(OS_WINCE)
#include <os/threads_windows.h>
#endif
#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD)
#include <unistd.h>
#include <os/poll_posix.h>
#elif defined(OS_WINDOWS)
#include <os/poll_windows.h>
#endif
#if defined(OS_WINDOWS) && !defined(__GCC__)
#undef HAVE_GETTIMEOFDAY
int usbi_gettimeofday(struct timeval *tp, void *tzp);
#define LIBUSB_GETTIMEOFDAY_WIN32
#define HAVE_USBI_GETTIMEOFDAY
#else
#ifdef HAVE_GETTIMEOFDAY
#define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz))
#define HAVE_USBI_GETTIMEOFDAY
#endif
#endif
extern struct libusb_context *usbi_default_context;
struct libusb_context {
@ -268,7 +238,7 @@ struct libusb_context { @@ -268,7 +238,7 @@ struct libusb_context {
/* A list of registered hotplug callbacks */
struct list_head hotplug_cbs;
usbi_mutex_t hotplug_cbs_lock;
int hotplug_pipe[2];
int hotplug_pipe[2];
/* this is a list of in-flight transfer handles, sorted by timeout
* expiration. URBs to timeout the soonest are placed at the beginning of
@ -308,7 +278,7 @@ struct libusb_context { @@ -308,7 +278,7 @@ struct libusb_context {
int timerfd;
#endif
struct list_head list;
struct list_head list;
};
#ifdef USBI_TIMERFD_AVAILABLE
@ -326,6 +296,8 @@ struct libusb_device { @@ -326,6 +296,8 @@ struct libusb_device {
struct libusb_context *ctx;
uint8_t bus_number;
uint8_t port_number;
struct libusb_device* parent_dev;
uint8_t device_address;
uint8_t num_configurations;
enum libusb_speed speed;
@ -342,7 +314,7 @@ struct libusb_device { @@ -342,7 +314,7 @@ struct libusb_device {
#else
[0] /* non-standard, but usually working code */
#endif
;
;
};
struct libusb_device_handle {
@ -352,13 +324,14 @@ struct libusb_device_handle { @@ -352,13 +324,14 @@ struct libusb_device_handle {
struct list_head list;
struct libusb_device *dev;
int auto_detach_kernel_driver;
unsigned char os_priv
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
;
};
enum {
@ -409,7 +382,7 @@ enum usbi_transfer_flags { @@ -409,7 +382,7 @@ enum usbi_transfer_flags {
/* Operation on the transfer failed because the device disappeared */
USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 3,
/* Set by backend submit_transfer() if the fds in use were updated */
/* Set by backend submit_transfer() if the fds in use have been updated */
USBI_TRANSFER_UPDATED_FDS = 1 << 4,
};
@ -461,7 +434,26 @@ int usbi_get_config_index_by_value(struct libusb_device *dev, @@ -461,7 +434,26 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
void usbi_connect_device (struct libusb_device *dev);
void usbi_disconnect_device (struct libusb_device *dev);
/* polling */
/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD)
#include <unistd.h>
#include "os/poll_posix.h"
#elif defined(OS_WINDOWS) || defined(OS_WINCE)
#include "os/poll_windows.h"
#endif
#if (defined(OS_WINDOWS) || defined(OS_WINCE)) && !defined(__GNUC__)
#define snprintf _snprintf
#define vsnprintf _vsnprintf
int usbi_gettimeofday(struct timeval *tp, void *tzp);
#define LIBUSB_GETTIMEOFDAY_WIN32
#define HAVE_USBI_GETTIMEOFDAY
#else
#ifdef HAVE_GETTIMEOFDAY
#define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz))
#define HAVE_USBI_GETTIMEOFDAY
#endif
#endif
struct usbi_pollfd {
/* must come first */
@ -490,7 +482,7 @@ struct discovered_devs { @@ -490,7 +482,7 @@ struct discovered_devs {
#else
[0] /* non-standard, but usually working code */
#endif
;
;
};
struct discovered_devs *discovered_devs_append(
@ -504,11 +496,14 @@ struct usbi_os_backend { @@ -504,11 +496,14 @@ struct usbi_os_backend {
/* A human-readable name for your backend, e.g. "Linux usbfs" */
const char *name;
/* Binary mask for backend specific capabilities */
uint32_t caps;
/* Perform initialization of your backend. You might use this function
* to determine specific capabilities of the system, allocate required
* data structures for later, etc.
*
* This function is called when a libusb user initializes the library
* This function is called when a libusbx user initializes the library
* prior to use.
*
* Return 0 on success, or a LIBUSB_ERROR code on failure.
@ -538,7 +533,7 @@ struct usbi_os_backend { @@ -538,7 +533,7 @@ struct usbi_os_backend {
* but that is an unlikely case.
*
* After computing a session ID for a device, call
* usbi_get_device_by_session_id(). This function checks if libusb already
* usbi_get_device_by_session_id(). This function checks if libusbx already
* knows about the device, and if so, it provides you with a libusb_device
* structure for it.
*
@ -569,18 +564,37 @@ struct usbi_os_backend { @@ -569,18 +564,37 @@ struct usbi_os_backend {
* This function is executed when the user wishes to retrieve a list
* of USB devices connected to the system.
*
* If the backend has hotplug support, this function is not used!
*
* Return 0 on success, or a LIBUSB_ERROR code on failure.
*/
int (*get_device_list)(struct libusb_context *ctx,
struct discovered_devs **discdevs);
/* Apps which were written before hotplug support, may listen for
* hotplug events on their own and call libusb_get_device_list on
* device addition. In this case libusb_get_device_list will likely
* return a list without the new device in there, as the hotplug
* event thread will still be busy enumerating the device, which may
* take a while, or may not even have seen the event yet.
*
* To avoid this libusb_get_device_list will call this optional
* function for backends with hotplug support before copying
* ctx->usb_devs to the user. In this function the backend should
* ensure any pending hotplug events are fully processed before
* returning.
*
* Optional, should be implemented by backends with hotplug support.
*/
void (*hotplug_poll)(void);
/* Open a device for I/O and other USB operations. The device handle
* is preallocated for you, you can retrieve the device in question
* through handle->dev.
*
* Your backend should allocate any internal resources required for I/O
* and other operations so that those operations can happen (hopefully)
* without hiccup. This is also a good place to inform libusb that it
* without hiccup. This is also a good place to inform libusbx that it
* should monitor certain file descriptors related to this device -
* see the usbi_add_pollfd() function.
*
@ -604,7 +618,7 @@ struct usbi_os_backend { @@ -604,7 +618,7 @@ struct usbi_os_backend {
/* Close a device such that the handle cannot be used again. Your backend
* should destroy any resources that were allocated in the open path.
* This may also be a good place to call usbi_remove_pollfd() to inform
* libusb of any file descriptors associated with this device that should
* libusbx of any file descriptors associated with this device that should
* no longer be monitored.
*
* This function is called when the user closes a device handle.
@ -683,13 +697,29 @@ struct usbi_os_backend { @@ -683,13 +697,29 @@ struct usbi_os_backend {
uint8_t config_index, unsigned char *buffer, size_t len,
int *host_endian);
/* Like get_config_descriptor but then by bConfigurationValue instead
* of by index.
*
* Optional, if not present the core will call get_config_descriptor
* for all configs until it finds the desired bConfigurationValue.
*
* Returns a pointer to the raw-descriptor in *buffer, this memory
* is valid as long as device is valid.
*
* Returns the length of the returned raw-descriptor on success,
* or a LIBUSB_ERROR code on failure.
*/
int (*get_config_descriptor_by_value)(struct libusb_device *device,
uint8_t bConfigurationValue, unsigned char **buffer,
int *host_endian);
/* Get the bConfigurationValue for the active configuration for a device.
* Optional. This should only be implemented if you can retrieve it from
* cache (don't generate I/O).
*
* If you cannot retrieve this from cache, either do not implement this
* function, or return LIBUSB_ERROR_NOT_SUPPORTED. This will cause
* libusb to retrieve the information through a standard control transfer.
* libusbx to retrieve the information through a standard control transfer.
*
* This function must be non-blocking.
* Return:
@ -866,6 +896,8 @@ struct usbi_os_backend { @@ -866,6 +896,8 @@ struct usbi_os_backend {
*
* This function must not block.
*
* This function gets called with the flying_transfers_lock locked!
*
* Return:
* - 0 on success
* - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
@ -886,7 +918,7 @@ struct usbi_os_backend { @@ -886,7 +918,7 @@ struct usbi_os_backend {
* all private data from the transfer as if you were just about to report
* completion or cancellation.
*
* This function might seem a bit out of place. It is used when libusb
* This function might seem a bit out of place. It is used when libusbx
* detects a disconnected device - it calls this function for all pending
* transfers before reporting completion (with the disconnect code) to
* the user. Maybe we can improve upon this internal interface in future.
@ -965,10 +997,11 @@ extern const struct usbi_os_backend * const usbi_backend; @@ -965,10 +997,11 @@ extern const struct usbi_os_backend * const usbi_backend;
extern const struct usbi_os_backend linux_usbfs_backend;
extern const struct usbi_os_backend darwin_backend;
extern const struct usbi_os_backend openbsd_backend;
extern const struct usbi_os_backend netbsd_backend;
extern const struct usbi_os_backend windows_backend;
extern const struct usbi_os_backend wince_backend;
extern struct list_head active_contexts_list;
extern usbi_mutex_static_t active_contexts_lock;
#endif

550
compat/libusb-1.0/libusb/os/darwin_usb.c

File diff suppressed because it is too large Load Diff

69
compat/libusb-1.0/libusb/os/darwin_usb.h

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* darwin backend for libusb 1.0
* Copyright (C) 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
* darwin backend for libusbx 1.0
* Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,7 +28,19 @@ @@ -28,7 +28,19 @@
#include <IOKit/IOCFPlugIn.h>
/* IOUSBInterfaceInferface */
#if defined (kIOUSBInterfaceInterfaceID300)
#if defined (kIOUSBInterfaceInterfaceID550)
#define usb_interface_t IOUSBInterfaceInterface550
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550
#define InterfaceVersion 550
#elif defined (kIOUSBInterfaceInterfaceID500)
#define usb_interface_t IOUSBInterfaceInterface500
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500
#define InterfaceVersion 500
#elif defined (kIOUSBInterfaceInterfaceID300)
#define usb_interface_t IOUSBInterfaceInterface300
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300
@ -46,24 +58,6 @@ @@ -46,24 +58,6 @@
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
#define InterfaceVersion 220
#elif defined (kIOUSBInterfaceInterfaceID197)
#define usb_interface_t IOUSBInterfaceInterface197
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197
#define InterfaceVersion 197
#elif defined (kIOUSBInterfaceInterfaceID190)
#define usb_interface_t IOUSBInterfaceInterface190
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190
#define InterfaceVersion 190
#elif defined (kIOUSBInterfaceInterfaceID182)
#define usb_interface_t IOUSBInterfaceInterface182
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID182
#define InterfaceVersion 182
#else
#error "IOUSBFamily is too old. Please upgrade your OS"
@ -95,24 +89,11 @@ @@ -95,24 +89,11 @@
#define DeviceInterfaceID kIOUSBDeviceInterfaceID245
#define DeviceVersion 245
#elif defined (kIOUSBDeviceInterfaceID197)
#elif defined (kIOUSBDeviceInterfaceID220)
#define usb_device_t IOUSBDeviceInterface197
#define DeviceInterfaceID kIOUSBDeviceInterfaceID197
#define DeviceVersion 197
#elif defined (kIOUSBDeviceInterfaceID187)
#define usb_device_t IOUSBDeviceInterface187
#define DeviceInterfaceID kIOUSBDeviceInterfaceID187
#define DeviceVersion 187
#elif defined (kIOUSBDeviceInterfaceID182)
#define usb_device_t IOUSBDeviceInterface182
#define DeviceInterfaceID kIOUSBDeviceInterfaceID182
#define DeviceVersion 182
#else
#error "IOUSBFamily is too old. Please upgrade your OS"
@ -127,13 +108,23 @@ typedef IOCFPlugInInterface *io_cf_plugin_ref_t; @@ -127,13 +108,23 @@ typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
typedef IONotificationPortRef io_notification_port_t;
/* private structures */
struct darwin_device_priv {
struct darwin_cached_device {
struct list_head list;
IOUSBDeviceDescriptor dev_descriptor;
UInt32 location;
UInt64 parent_session;
UInt64 session;
UInt16 address;
char sys_path[21];
usb_device_t **device;
int open_count;
UInt8 first_config, active_config;
UInt8 first_config, active_config, port;
int can_enumerate;
int refcount;
};
struct darwin_device_priv {
struct darwin_cached_device *dev;
};
struct darwin_device_handle_priv {
@ -156,11 +147,7 @@ struct darwin_transfer_priv { @@ -156,11 +147,7 @@ struct darwin_transfer_priv {
int num_iso_packets;
/* Control */
#if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
IOUSBDevRequestTO req;
#else
IOUSBDevRequest req;
#endif
/* Bulk */
};

198
compat/libusb-1.0/libusb/os/linux_netlink.c

@ -21,6 +21,10 @@ @@ -21,6 +21,10 @@
*/
#include "config.h"
#include "libusb.h"
#include "libusbi.h"
#include "linux_usbfs.h"
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
@ -30,46 +34,113 @@ @@ -30,46 +34,113 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#include <arpa/inet.h>
#endif
#include "libusb.h"
#include "libusbi.h"
#include "linux_usbfs.h"
#include <arpa/inet.h>
#ifdef HAVE_LINUX_NETLINK_H
#include <linux/netlink.h>
#endif
#ifdef HAVE_LINUX_FILTER_H
#include <linux/filter.h>
#endif
#define KERNEL 1
static int linux_netlink_socket = -1;
static int netlink_control_pipe[2] = { -1, -1 };
static pthread_t libusb_linux_event_thread;
static void *linux_netlink_event_thread_main(void *arg);
struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL };
static int set_fd_cloexec_nb (int fd)
{
int flags;
#if defined(FD_CLOEXEC)
flags = fcntl (linux_netlink_socket, F_GETFD);
if (0 > flags) {
return -1;
}
if (!(flags & FD_CLOEXEC)) {
fcntl (linux_netlink_socket, F_SETFD, flags | FD_CLOEXEC);
}
#endif
flags = fcntl (linux_netlink_socket, F_GETFL);
if (0 > flags) {
return -1;
}
if (!(flags & O_NONBLOCK)) {
fcntl (linux_netlink_socket, F_SETFL, flags | O_NONBLOCK);
}
return 0;
}
int linux_netlink_start_event_monitor(void)
{
int socktype = SOCK_RAW;
int ret;
snl.nl_groups = KERNEL;
linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
#if defined(SOCK_CLOEXEC)
socktype |= SOCK_CLOEXEC;
#endif
#if defined(SOCK_NONBLOCK)
socktype |= SOCK_NONBLOCK;
#endif
linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
if (-1 == linux_netlink_socket && EINVAL == errno) {
linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
}
if (-1 == linux_netlink_socket) {
return LIBUSB_ERROR_OTHER;
}
ret = set_fd_cloexec_nb (linux_netlink_socket);
if (0 != ret) {
close (linux_netlink_socket);
linux_netlink_socket = -1;
return LIBUSB_ERROR_OTHER;
}
ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl));
if (0 != ret) {
close(linux_netlink_socket);
return LIBUSB_ERROR_OTHER;
}
/* TODO -- add authentication */
/* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */
ret = usbi_pipe(netlink_control_pipe);
if (ret) {
usbi_err(NULL, "could not create netlink control pipe");
close(linux_netlink_socket);
return LIBUSB_ERROR_OTHER;
}
ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL);
if (0 != ret) {
close(netlink_control_pipe[0]);
close(netlink_control_pipe[1]);
close(linux_netlink_socket);
return LIBUSB_ERROR_OTHER;
}
@ -79,22 +150,30 @@ int linux_netlink_start_event_monitor(void) @@ -79,22 +150,30 @@ int linux_netlink_start_event_monitor(void)
int linux_netlink_stop_event_monitor(void)
{
int r;
char dummy = 1;
if (-1 == linux_netlink_socket) {
/* already closed. nothing to do */
return LIBUSB_SUCCESS;
}
r = close(linux_netlink_socket);
if (0 > r) {
usbi_err(NULL, "error closing netlink socket. %s", strerror(errno));
return LIBUSB_ERROR_OTHER;
/* Write some dummy data to the control pipe and
* wait for the thread to exit */
r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
if (r <= 0) {
usbi_warn(NULL, "netlink control pipe signal failed");
}
pthread_join(libusb_linux_event_thread, NULL);
pthread_cancel(libusb_linux_event_thread);
close(linux_netlink_socket);
linux_netlink_socket = -1;
/* close and reset control pipe */
close(netlink_control_pipe[0]);
close(netlink_control_pipe[1]);
netlink_control_pipe[0] = -1;
netlink_control_pipe[1] = -1;
return LIBUSB_SUCCESS;
}
@ -127,10 +206,12 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch @@ -127,10 +206,12 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch
*devaddr = 0;
tmp = netlink_message_parse((const char *) buffer, len, "ACTION");
if (tmp == NULL)
return -1;
if (0 == strcmp(tmp, "remove")) {
*detached = 1;
} else if (0 != strcmp(tmp, "add")) {
usbi_dbg("unknown device action");
usbi_dbg("unknown device action %s", tmp);
return -1;
}
@ -180,52 +261,85 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch @@ -180,52 +261,85 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch
return 0;
}
static void *linux_netlink_event_thread_main(void *arg)
static int linux_netlink_read_message(void)
{
struct pollfd fds = {.fd = linux_netlink_socket,
.events = POLLIN};
unsigned char buffer[1024];
struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)};
struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1,
.msg_name=&snl, .msg_namelen=sizeof(snl) };
const char *sys_name = NULL;
uint8_t busnum, devaddr;
int detached, r;
size_t len;
/* silence compiler warning */
(void) arg;
/* read netlink message */
memset(buffer, 0, sizeof(buffer));
len = recvmsg(linux_netlink_socket, &meh, 0);
if (len < 32) {
if (errno != EAGAIN)
usbi_dbg("error recieving message from netlink");
return -1;
}
while (1 == poll(&fds, 1, -1)) {
const char *sys_name = NULL;
/* TODO -- authenticate this message is from the kernel or udevd */
if (POLLIN != fds.revents) {
break;
}
r = linux_netlink_parse(buffer, len, &detached, &sys_name,
&busnum, &devaddr);
if (r)
return r;
/* read netlink message */
memset(buffer, 0, sizeof(buffer));
len = recvmsg(linux_netlink_socket, &meh, 0);
if (len < 32) {
usbi_dbg("error recieving message from netlink");
continue;
}
usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s",
busnum, devaddr, sys_name, detached ? "yes" : "no");
/* TODO -- authenticate this message is from the kernel or udevd */
/* signal device is available (or not) to all contexts */
if (detached)
linux_device_disconnected(busnum, devaddr, sys_name);
else
linux_hotplug_enumerate(busnum, devaddr, sys_name);
r = linux_netlink_parse(buffer, len, &detached, &sys_name,
&busnum, &devaddr);
if (r)
continue;
return 0;
}
usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s",
busnum, devaddr, sys_name, detached ? "yes" : "no");
static void *linux_netlink_event_thread_main(void *arg)
{
char dummy;
int r;
struct pollfd fds[] = {
{ .fd = netlink_control_pipe[0],
.events = POLLIN },
{ .fd = linux_netlink_socket,
.events = POLLIN },
};
/* signal device is available (or not) to all contexts */
if (detached)
linux_hotplug_disconnected(busnum, devaddr, sys_name);
else
linux_hotplug_enumerate(busnum, devaddr, sys_name);
/* silence compiler warning */
(void) arg;
while (poll(fds, 2, -1) >= 0) {
if (fds[0].revents & POLLIN) {
/* activity on control pipe, read the byte and exit */
r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
if (r <= 0) {
usbi_warn(NULL, "netlink control pipe read failed");
}
break;
}
if (fds[1].revents & POLLIN) {
usbi_mutex_static_lock(&linux_hotplug_lock);
linux_netlink_read_message();
usbi_mutex_static_unlock(&linux_hotplug_lock);
}
}
return NULL;
return NULL;
}
void linux_netlink_hotplug_poll(void)
{
int r;
usbi_mutex_static_lock(&linux_hotplug_lock);
do {
r = linux_netlink_read_message();
} while (r == 0);
usbi_mutex_static_unlock(&linux_hotplug_lock);
}

190
compat/libusb-1.0/libusb/os/linux_udev.c

@ -20,7 +20,9 @@ @@ -20,7 +20,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include "config.h"
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
@ -44,84 +46,148 @@ @@ -44,84 +46,148 @@
/* udev context */
static struct udev *udev_ctx = NULL;
static int udev_monitor_fd = -1;
static int udev_control_pipe[2] = {-1, -1};
static struct udev_monitor *udev_monitor = NULL;
static pthread_t linux_event_thread;
static void udev_hotplug_event(void);
static void udev_hotplug_event(struct udev_device* udev_dev);
static void *linux_udev_event_thread_main(void *arg);
int linux_udev_start_event_monitor(void)
{
int r;
if (NULL == udev_ctx) {
udev_ctx = udev_new();
if (!udev_ctx) {
return LIBUSB_ERROR_OTHER;
}
assert(udev_ctx == NULL);
udev_ctx = udev_new();
if (!udev_ctx) {
usbi_err(NULL, "could not create udev context");
return LIBUSB_ERROR_OTHER;
}
udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev");
if (!udev_monitor) {
usbi_err(NULL, "could not initialize udev monitor");
goto err_free_ctx;
}
udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev");
if (!udev_monitor) {
usbi_err(NULL, "could not initialize udev monitor");
return LIBUSB_ERROR_OTHER;
}
r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", 0);
if (r) {
usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem");
goto err_free_monitor;
}
if (udev_monitor_enable_receiving(udev_monitor)) {
usbi_err(NULL, "failed to enable the udev monitor");
goto err_free_monitor;
}
r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", 0);
if (r) {
usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem");
return LIBUSB_ERROR_OTHER;
}
udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
/* Some older versions of udev are not non-blocking by default,
* so make sure this is set */
r = fcntl(udev_monitor_fd, F_GETFL);
if (r == -1) {
usbi_err(NULL, "getting udev monitor fd flags (%d)", errno);
goto err_free_monitor;
}
r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK);
if (r) {
usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
goto err_free_monitor;
}
if (udev_monitor_enable_receiving(udev_monitor)) {
usbi_err(NULL, "failed to enable the udev monitor");
return LIBUSB_ERROR_OTHER;
}
r = usbi_pipe(udev_control_pipe);
if (r) {
usbi_err(NULL, "could not create udev control pipe");
goto err_free_monitor;
}
udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL);
if (r) {
usbi_err(NULL, "creating hotplug event thread (%d)", r);
goto err_close_pipe;
}
pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL);
return LIBUSB_SUCCESS;
return LIBUSB_SUCCESS;
err_close_pipe:
close(udev_control_pipe[0]);
close(udev_control_pipe[1]);
err_free_monitor:
udev_monitor_unref(udev_monitor);
udev_monitor = NULL;
udev_monitor_fd = -1;
err_free_ctx:
udev_unref(udev_ctx);
udev_ctx = NULL;
return LIBUSB_ERROR_OTHER;
}
int linux_udev_stop_event_monitor(void)
{
if (-1 == udev_monitor_fd) {
/* this should never happen */
return LIBUSB_ERROR_OTHER;
}
char dummy = 1;
int r;
/* Cancel the event thread. This is the only way to garauntee the thread
exits since closing the monitor fd won't necessarily cause poll
to return. */
pthread_cancel(linux_event_thread);
assert(udev_ctx != NULL);
assert(udev_monitor != NULL);
assert(udev_monitor_fd != -1);
/* Write some dummy data to the control pipe and
* wait for the thread to exit */
r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy));
if (r <= 0) {
usbi_warn(NULL, "udev control pipe signal failed");
}
pthread_join(linux_event_thread, NULL);
/* Release the udev monitor */
udev_monitor_unref(udev_monitor);
udev_monitor_unref(udev_monitor);
udev_monitor = NULL;
udev_monitor_fd = -1;
udev_monitor_fd = -1;
/* Clean up the udev context */
udev_unref(udev_ctx);
udev_ctx = NULL;
return LIBUSB_SUCCESS;
/* close and reset control pipe */
close(udev_control_pipe[0]);
close(udev_control_pipe[1]);
udev_control_pipe[0] = -1;
udev_control_pipe[1] = -1;
return LIBUSB_SUCCESS;
}
static void *linux_udev_event_thread_main(void __attribute__((unused)) *arg)
static void *linux_udev_event_thread_main(void *arg)
{
struct pollfd fds = {.fd = udev_monitor_fd,
.events = POLLIN};
char dummy;
int r;
struct udev_device* udev_dev;
struct pollfd fds[] = {
{.fd = udev_control_pipe[0],
.events = POLLIN},
{.fd = udev_monitor_fd,
.events = POLLIN},
};
usbi_dbg("udev event thread entering.");
while (1 == poll(&fds, 1, -1)) {
if (NULL == udev_monitor || POLLIN != fds.revents) {
while (poll(fds, 2, -1) >= 0) {
if (fds[0].revents & POLLIN) {
/* activity on control pipe, read the byte and exit */
r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy));
if (r <= 0) {
usbi_warn(NULL, "udev control pipe read failed");
}
break;
}
udev_hotplug_event();
if (fds[1].revents & POLLIN) {
usbi_mutex_static_lock(&linux_hotplug_lock);
udev_dev = udev_monitor_receive_device(udev_monitor);
if (udev_dev)
udev_hotplug_event(udev_dev);
usbi_mutex_static_unlock(&linux_hotplug_lock);
}
}
usbi_dbg("udev event thread exiting");
@ -144,30 +210,19 @@ static int udev_device_info(struct libusb_context *ctx, int detached, @@ -144,30 +210,19 @@ static int udev_device_info(struct libusb_context *ctx, int detached,
return LIBUSB_ERROR_OTHER;
}
return linux_get_device_address(ctx, detached, busnum, devaddr,
return linux_get_device_address(ctx, detached, busnum, devaddr,
dev_node, *sys_name);
}
static void udev_hotplug_event(void)
static void udev_hotplug_event(struct udev_device* udev_dev)
{
struct udev_device* udev_dev;
const char* udev_action;
const char* sys_name = NULL;
uint8_t busnum = 0, devaddr = 0;
int detached;
int r;
if (NULL == udev_monitor) {
return;
}
do {
udev_dev = udev_monitor_receive_device(udev_monitor);
if (!udev_dev) {
usbi_err(NULL, "failed to read data from udev monitor socket.");
return;
}
udev_action = udev_device_get_action(udev_dev);
if (!udev_action) {
break;
@ -185,7 +240,7 @@ static void udev_hotplug_event(void) @@ -185,7 +240,7 @@ static void udev_hotplug_event(void)
if (strncmp(udev_action, "add", 3) == 0) {
linux_hotplug_enumerate(busnum, devaddr, sys_name);
} else if (detached) {
linux_hotplug_disconnected(busnum, devaddr, sys_name);
linux_device_disconnected(busnum, devaddr, sys_name);
} else {
usbi_err(NULL, "ignoring udev action %s", udev_action);
}
@ -202,12 +257,7 @@ int linux_udev_scan_devices(struct libusb_context *ctx) @@ -202,12 +257,7 @@ int linux_udev_scan_devices(struct libusb_context *ctx)
const char *sys_name;
int r;
if (NULL == udev_ctx) {
udev_ctx = udev_new();
if (!udev_ctx) {
return LIBUSB_ERROR_OTHER;
}
}
assert(udev_ctx != NULL);
enumerator = udev_enumerate_new(udev_ctx);
if (NULL == enumerator) {
@ -237,6 +287,20 @@ int linux_udev_scan_devices(struct libusb_context *ctx) @@ -237,6 +287,20 @@ int linux_udev_scan_devices(struct libusb_context *ctx)
udev_enumerate_unref(enumerator);
return LIBUSB_SUCCESS;
return LIBUSB_SUCCESS;
}
void linux_udev_hotplug_poll(void)
{
struct udev_device* udev_dev;
usbi_mutex_static_lock(&linux_hotplug_lock);
do {
udev_dev = udev_monitor_receive_device(udev_monitor);
if (udev_dev) {
usbi_dbg("Handling hotplug event from hotplug_poll");
udev_hotplug_event(udev_dev);
}
} while (udev_dev);
usbi_mutex_static_unlock(&linux_hotplug_lock);
}

1144
compat/libusb-1.0/libusb/os/linux_usbfs.c

File diff suppressed because it is too large Load Diff

27
compat/libusb-1.0/libusb/os/linux_usbfs.h

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/*
* usbfs header structures
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
* Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -123,6 +123,15 @@ struct usbfs_hub_portinfo { @@ -123,6 +123,15 @@ struct usbfs_hub_portinfo {
#define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04
#define USBFS_CAP_BULK_SCATTER_GATHER 0x08
#define USBFS_DISCONNECT_CLAIM_IF_DRIVER 0x01
#define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02
struct usbfs_disconnect_claim {
unsigned int interface;
unsigned int flags;
char driver[USBFS_MAXDRIVERNAME + 1];
};
#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer)
#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer)
#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int)
@ -145,24 +154,28 @@ struct usbfs_hub_portinfo { @@ -145,24 +154,28 @@ struct usbfs_hub_portinfo {
#define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int)
#define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int)
#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32)
#define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim)
extern usbi_mutex_static_t linux_hotplug_lock;
#if defined(HAVE_LIBUDEV)
int linux_udev_start_event_monitor(void);
int linux_udev_stop_event_monitor(void);
int linux_udev_scan_devices(struct libusb_context *ctx);
void linux_udev_hotplug_poll(void);
#else
int linux_netlink_start_event_monitor(void);
int linux_netlink_stop_event_monitor(void);
void linux_netlink_hotplug_poll(void);
#endif
void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name);
void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name);
void linux_device_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name);
int linux_get_device_address (struct libusb_context *ctx, int detached,
uint8_t *busnum, uint8_t *devaddr,
const char *dev_node, const char *sys_name);
uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
const char *sys_name);
int linux_enumerate_device(struct libusb_context *ctx,
uint8_t busnum, uint8_t devaddr,
const char *sysfs_dir);
uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);
#endif

734
compat/libusb-1.0/libusb/os/netbsd_usb.c

@ -0,0 +1,734 @@ @@ -0,0 +1,734 @@
/*
* Copyright © 2011 Martin Pieuchot <mpi@openbsd.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dev/usb/usb.h>
#include "libusb.h"
#include "libusbi.h"
struct device_priv {
char devnode[16];
int fd;
unsigned char *cdesc; /* active config descriptor */
usb_device_descriptor_t ddesc; /* usb device descriptor */
};
struct handle_priv {
int pipe[2]; /* for event notification */
int endpoints[USB_MAX_ENDPOINTS];
};
/*
* Backend functions
*/
static int netbsd_get_device_list(struct libusb_context *,
struct discovered_devs **);
static int netbsd_open(struct libusb_device_handle *);
static void netbsd_close(struct libusb_device_handle *);
static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *,
int *);
static int netbsd_get_active_config_descriptor(struct libusb_device *,
unsigned char *, size_t, int *);
static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t,
unsigned char *, size_t, int *);
static int netbsd_get_configuration(struct libusb_device_handle *, int *);
static int netbsd_set_configuration(struct libusb_device_handle *, int);
static int netbsd_claim_interface(struct libusb_device_handle *, int);
static int netbsd_release_interface(struct libusb_device_handle *, int);
static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int,
int);
static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char);
static int netbsd_reset_device(struct libusb_device_handle *);
static void netbsd_destroy_device(struct libusb_device *);
static int netbsd_submit_transfer(struct usbi_transfer *);
static int netbsd_cancel_transfer(struct usbi_transfer *);
static void netbsd_clear_transfer_priv(struct usbi_transfer *);
static int netbsd_handle_events(struct libusb_context *ctx, struct pollfd *,
nfds_t, int);
static int netbsd_clock_gettime(int, struct timespec *);
/*
* Private functions
*/
static int _errno_to_libusb(int);
static int _cache_active_config_descriptor(struct libusb_device *, int);
static int _sync_control_transfer(struct usbi_transfer *);
static int _sync_gen_transfer(struct usbi_transfer *);
static int _access_endpoint(struct libusb_transfer *);
const struct usbi_os_backend netbsd_backend = {
"Synchronous NetBSD backend",
0,
NULL, /* init() */
NULL, /* exit() */
netbsd_get_device_list,
NULL, /* hotplug_poll */
netbsd_open,
netbsd_close,
netbsd_get_device_descriptor,
netbsd_get_active_config_descriptor,
netbsd_get_config_descriptor,
NULL, /* get_config_descriptor_by_value() */
netbsd_get_configuration,
netbsd_set_configuration,
netbsd_claim_interface,
netbsd_release_interface,
netbsd_set_interface_altsetting,
netbsd_clear_halt,
netbsd_reset_device,
NULL, /* kernel_driver_active() */
NULL, /* detach_kernel_driver() */
NULL, /* attach_kernel_driver() */
netbsd_destroy_device,
netbsd_submit_transfer,
netbsd_cancel_transfer,
netbsd_clear_transfer_priv,
netbsd_handle_events,
netbsd_clock_gettime,
sizeof(struct device_priv),
sizeof(struct handle_priv),
0, /* transfer_priv_size */
0, /* add_iso_packet_size */
};
int
netbsd_get_device_list(struct libusb_context * ctx,
struct discovered_devs **discdevs)
{
struct libusb_device *dev;
struct device_priv *dpriv;
struct usb_device_info di;
unsigned long session_id;
char devnode[16];
int fd, err, i;
usbi_dbg("");
/* Only ugen(4) is supported */
for (i = 0; i < USB_MAX_DEVICES; i++) {
/* Control endpoint is always .00 */
snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
if ((fd = open(devnode, O_RDONLY)) < 0) {
if (errno != ENOENT && errno != ENXIO)
usbi_err(ctx, "could not open %s", devnode);
continue;
}
if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
continue;
session_id = (di.udi_bus << 8 | di.udi_addr);
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev) {
dev = libusb_ref_device(dev);
} else {
dev = usbi_alloc_device(ctx, session_id);
if (dev == NULL)
return (LIBUSB_ERROR_NO_MEM);
dev->bus_number = di.udi_bus;
dev->device_address = di.udi_addr;
dev->speed = di.udi_speed;
dpriv = (struct device_priv *)dev->os_priv;
strlcpy(dpriv->devnode, devnode, sizeof(devnode));
dpriv->fd = -1;
if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
err = errno;
goto error;
}
dpriv->cdesc = NULL;
if (_cache_active_config_descriptor(dev, fd)) {
err = errno;
goto error;
}
if ((err = usbi_sanitize_device(dev)))
goto error;
}
close(fd);
if (discovered_devs_append(*discdevs, dev) == NULL)
return (LIBUSB_ERROR_NO_MEM);
libusb_unref_device(dev);
}
return (LIBUSB_SUCCESS);
error:
close(fd);
libusb_unref_device(dev);
return _errno_to_libusb(err);
}
int
netbsd_open(struct libusb_device_handle *handle)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
dpriv->fd = open(dpriv->devnode, O_RDWR);
if (dpriv->fd < 0) {
dpriv->fd = open(dpriv->devnode, O_RDONLY);
if (dpriv->fd < 0)
return _errno_to_libusb(errno);
}
usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
if (pipe(hpriv->pipe) < 0)
return _errno_to_libusb(errno);
return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN);
}
void
netbsd_close(struct libusb_device_handle *handle)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("close: fd %d", dpriv->fd);
close(dpriv->fd);
dpriv->fd = -1;
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
close(hpriv->pipe[0]);
close(hpriv->pipe[1]);
}
int
netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usbi_dbg("");
memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
*host_endian = 0;
return (LIBUSB_SUCCESS);
}
int
netbsd_get_active_config_descriptor(struct libusb_device *dev,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usb_config_descriptor_t *ucd;
ucd = (usb_config_descriptor_t *) dpriv->cdesc;
len = MIN(len, UGETW(ucd->wTotalLength));
usbi_dbg("len %d", len);
memcpy(buf, dpriv->cdesc, len);
*host_endian = 0;
return len;
}
int
netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
struct usb_full_desc ufd;
int fd, err;
usbi_dbg("index %d, len %d", idx, len);
/* A config descriptor may be requested before opening the device */
if (dpriv->fd >= 0) {
fd = dpriv->fd;
} else {
fd = open(dpriv->devnode, O_RDONLY);
if (fd < 0)
return _errno_to_libusb(errno);
}
ufd.ufd_config_index = idx;
ufd.ufd_size = len;
ufd.ufd_data = buf;
if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
err = errno;
if (dpriv->fd < 0)
close(fd);
return _errno_to_libusb(err);
}
if (dpriv->fd < 0)
close(fd);
*host_endian = 0;
return len;
}
int
netbsd_get_configuration(struct libusb_device_handle *handle, int *config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("");
if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
return _errno_to_libusb(errno);
usbi_dbg("configuration %d", *config);
return (LIBUSB_SUCCESS);
}
int
netbsd_set_configuration(struct libusb_device_handle *handle, int config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("configuration %d", config);
if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
return _errno_to_libusb(errno);
return _cache_active_config_descriptor(handle->dev, dpriv->fd);
}
int
netbsd_claim_interface(struct libusb_device_handle *handle, int iface)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
int i;
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
hpriv->endpoints[i] = -1;
return (LIBUSB_SUCCESS);
}
int
netbsd_release_interface(struct libusb_device_handle *handle, int iface)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
int i;
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
if (hpriv->endpoints[i] >= 0)
close(hpriv->endpoints[i]);
return (LIBUSB_SUCCESS);
}
int
netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
int altsetting)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_alt_interface intf;
usbi_dbg("iface %d, setting %d", iface, altsetting);
memset(&intf, 0, sizeof(intf));
intf.uai_interface_index = iface;
intf.uai_alt_no = altsetting;
if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS);
}
int
netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_ctl_request req;
usbi_dbg("");
req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
req.ucr_request.bRequest = UR_CLEAR_FEATURE;
USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
USETW(req.ucr_request.wIndex, endpoint);
USETW(req.ucr_request.wLength, 0);
if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS);
}
int
netbsd_reset_device(struct libusb_device_handle *handle)
{
usbi_dbg("");
return (LIBUSB_ERROR_NOT_SUPPORTED);
}
void
netbsd_destroy_device(struct libusb_device *dev)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usbi_dbg("");
free(dpriv->cdesc);
}
int
netbsd_submit_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct handle_priv *hpriv;
int err = 0;
usbi_dbg("");
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
err = _sync_control_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
if (IS_XFEROUT(transfer)) {
/* Isochronous write is not supported */
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
err = _sync_gen_transfer(itransfer);
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
if (IS_XFEROUT(transfer) &&
transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
err = LIBUSB_ERROR_NOT_SUPPORTED;
break;
}
err = _sync_gen_transfer(itransfer);
break;
}
if (err)
return (err);
if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0)
return _errno_to_libusb(errno);
return (LIBUSB_SUCCESS);
}
int
netbsd_cancel_transfer(struct usbi_transfer *itransfer)
{
usbi_dbg("");
return (LIBUSB_ERROR_NOT_SUPPORTED);
}
void
netbsd_clear_transfer_priv(struct usbi_transfer *itransfer)
{
usbi_dbg("");
/* Nothing to do */
}
int
netbsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds,
int num_ready)
{
struct libusb_device_handle *handle;
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
netbsd_clock_gettime(int clkid, struct timespec *tp)
{
usbi_dbg("clock %d", clkid);
if (clkid == USBI_CLOCK_REALTIME)
return clock_gettime(CLOCK_REALTIME, tp);
if (clkid == USBI_CLOCK_MONOTONIC)
return clock_gettime(CLOCK_MONOTONIC, tp);
return (LIBUSB_ERROR_INVALID_PARAM);
}
int
_errno_to_libusb(int err)
{
switch (err) {
case EIO:
return (LIBUSB_ERROR_IO);
case EACCES:
return (LIBUSB_ERROR_ACCESS);
case ENOENT:
return (LIBUSB_ERROR_NO_DEVICE);
case ENOMEM:
return (LIBUSB_ERROR_NO_MEM);
}
usbi_dbg("error: %s", strerror(err));
return (LIBUSB_ERROR_OTHER);
}
int
_cache_active_config_descriptor(struct libusb_device *dev, int fd)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
struct usb_config_desc ucd;
struct usb_full_desc ufd;
unsigned char* buf;
int len;
usbi_dbg("fd %d", fd);
ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
return _errno_to_libusb(errno);
usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
len = UGETW(ucd.ucd_desc.wTotalLength);
buf = malloc(len);
if (buf == NULL)
return (LIBUSB_ERROR_NO_MEM);
ufd.ufd_config_index = ucd.ucd_config_index;
ufd.ufd_size = len;
ufd.ufd_data = buf;
usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
free(buf);
return _errno_to_libusb(errno);
}
if (dpriv->cdesc)
free(dpriv->cdesc);
dpriv->cdesc = buf;
return (0);
}
int
_sync_control_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct libusb_control_setup *setup;
struct device_priv *dpriv;
struct usb_ctl_request req;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
setup = (struct libusb_control_setup *)transfer->buffer;
usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
setup->bmRequestType, setup->bRequest,
libusb_le16_to_cpu(setup->wValue),
libusb_le16_to_cpu(setup->wIndex),
libusb_le16_to_cpu(setup->wLength), transfer->timeout);
req.ucr_request.bmRequestType = setup->bmRequestType;
req.ucr_request.bRequest = setup->bRequest;
/* Don't use USETW, libusbx already deals with the endianness */
(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
req.ucr_flags = USBD_SHORT_XFER_OK;
if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
return _errno_to_libusb(errno);
itransfer->transferred = req.ucr_actlen;
usbi_dbg("transferred %d", itransfer->transferred);
return (0);
}
int
_access_endpoint(struct libusb_transfer *transfer)
{
struct handle_priv *hpriv;
struct device_priv *dpriv;
char *s, devnode[16];
int fd, endpt;
mode_t mode;
hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
endpt = UE_GET_ADDR(transfer->endpoint);
mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
usbi_dbg("endpoint %d mode %d", endpt, mode);
if (hpriv->endpoints[endpt] < 0) {
/* Pick the right node given the control one */
strlcpy(devnode, dpriv->devnode, sizeof(devnode));
s = strchr(devnode, '.');
snprintf(s, 4, ".%02d", endpt);
/* We may need to read/write to the same endpoint later. */
if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
if ((fd = open(devnode, mode)) < 0)
return (-1);
hpriv->endpoints[endpt] = fd;
}
return (hpriv->endpoints[endpt]);
}
int
_sync_gen_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
int fd, nr = 1;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
/*
* Bulk, Interrupt or Isochronous transfer depends on the
* endpoint and thus the node to open.
*/
if ((fd = _access_endpoint(transfer)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if (IS_XFERIN(transfer)) {
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
return _errno_to_libusb(errno);
nr = read(fd, transfer->buffer, transfer->length);
} else {
nr = write(fd, transfer->buffer, transfer->length);
}
if (nr < 0)
return _errno_to_libusb(errno);
itransfer->transferred = nr;
return (0);
}

334
compat/libusb-1.0/libusb/os/openbsd_usb.c

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
* Copyright © 2011-2013 Martin Pieuchot <mpi@openbsd.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -32,8 +32,8 @@ @@ -32,8 +32,8 @@
#include "libusbi.h"
struct device_priv {
char devnode[16];
int fd;
char *devname; /* name of the ugen(4) node */
int fd; /* device file descriptor */
unsigned char *cdesc; /* active config descriptor */
usb_device_descriptor_t ddesc; /* usb device descriptor */
@ -82,22 +82,28 @@ static int obsd_clock_gettime(int, struct timespec *); @@ -82,22 +82,28 @@ static int obsd_clock_gettime(int, struct timespec *);
* Private functions
*/
static int _errno_to_libusb(int);
static int _cache_active_config_descriptor(struct libusb_device *, int);
static int _cache_active_config_descriptor(struct libusb_device *);
static int _sync_control_transfer(struct usbi_transfer *);
static int _sync_gen_transfer(struct usbi_transfer *);
static int _access_endpoint(struct libusb_transfer *);
static int _bus_open(int);
const struct usbi_os_backend openbsd_backend = {
"Synchronous OpenBSD backend",
0,
NULL, /* init() */
NULL, /* exit() */
obsd_get_device_list,
NULL, /* hotplug_poll */
obsd_open,
obsd_close,
obsd_get_device_descriptor,
obsd_get_active_config_descriptor,
obsd_get_config_descriptor,
NULL, /* get_config_descriptor_by_value() */
obsd_get_configuration,
obsd_set_configuration,
@ -128,75 +134,105 @@ const struct usbi_os_backend openbsd_backend = { @@ -128,75 +134,105 @@ const struct usbi_os_backend openbsd_backend = {
0, /* add_iso_packet_size */
};
#define DEVPATH "/dev/"
#define USBDEV DEVPATH "usb"
int
obsd_get_device_list(struct libusb_context * ctx,
struct discovered_devs **discdevs)
{
struct discovered_devs *ddd;
struct libusb_device *dev;
struct device_priv *dpriv;
struct usb_device_info di;
struct usb_device_ddesc dd;
unsigned long session_id;
char devnode[16];
int fd, err, i;
char devices[USB_MAX_DEVICES];
char busnode[16];
char *udevname;
int fd, addr, i, j;
usbi_dbg("");
/* Only ugen(4) is supported */
for (i = 0; i < USB_MAX_DEVICES; i++) {
/* Control endpoint is always .00 */
snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
for (i = 0; i < 8; i++) {
snprintf(busnode, sizeof(busnode), USBDEV "%d", i);
if ((fd = open(devnode, O_RDONLY)) < 0) {
if ((fd = open(busnode, O_RDWR)) < 0) {
if (errno != ENOENT && errno != ENXIO)
usbi_err(ctx, "could not open %s", devnode);
usbi_err(ctx, "could not open %s", busnode);
continue;
}
if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
continue;
session_id = (di.udi_bus << 8 | di.udi_addr);
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev == NULL) {
dev = usbi_alloc_device(ctx, session_id);
if (dev == NULL)
return (LIBUSB_ERROR_NO_MEM);
dev->bus_number = di.udi_bus;
dev->device_address = di.udi_addr;
dev->speed = di.udi_speed;
dpriv = (struct device_priv *)dev->os_priv;
strlcpy(dpriv->devnode, devnode, sizeof(devnode));
dpriv->fd = -1;
if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
err = errno;
goto error;
bzero(devices, sizeof(devices));
for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
if (devices[addr])
continue;
di.udi_addr = addr;
if (ioctl(fd, USB_DEVICEINFO, &di) < 0)
continue;
/*
* XXX If ugen(4) is attached to the USB device
* it will be used.
*/
udevname = NULL;
for (j = 0; j < USB_MAX_DEVNAMES; j++)
if (!strncmp("ugen", di.udi_devnames[j], 4)) {
udevname = strdup(di.udi_devnames[j]);
break;
}
session_id = (di.udi_bus << 8 | di.udi_addr);
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev == NULL) {
dev = usbi_alloc_device(ctx, session_id);
if (dev == NULL) {
close(fd);
return (LIBUSB_ERROR_NO_MEM);
}
dev->bus_number = di.udi_bus;
dev->device_address = di.udi_addr;
dev->speed = di.udi_speed;
dpriv = (struct device_priv *)dev->os_priv;
dpriv->fd = -1;
dpriv->cdesc = NULL;
dpriv->devname = udevname;
dd.udd_bus = di.udi_bus;
dd.udd_addr = di.udi_addr;
if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) {
libusb_unref_device(dev);
continue;
}
dpriv->ddesc = dd.udd_desc;
if (_cache_active_config_descriptor(dev)) {
libusb_unref_device(dev);
continue;
}
if (usbi_sanitize_device(dev))
libusb_unref_device(dev);
}
dpriv->cdesc = NULL;
if (_cache_active_config_descriptor(dev, fd)) {
err = errno;
goto error;
ddd = discovered_devs_append(*discdevs, dev);
if (ddd == NULL) {
close(fd);
return (LIBUSB_ERROR_NO_MEM);
}
if ((err = usbi_sanitize_device(dev)))
goto error;
*discdevs = ddd;
devices[addr] = 1;
}
close(fd);
if (discovered_devs_append(*discdevs, dev) == NULL)
return (LIBUSB_ERROR_NO_MEM);
close(fd);
}
return (LIBUSB_SUCCESS);
error:
close(fd);
libusb_unref_device(dev);
return _errno_to_libusb(err);
}
int
@ -204,15 +240,21 @@ obsd_open(struct libusb_device_handle *handle) @@ -204,15 +240,21 @@ obsd_open(struct libusb_device_handle *handle)
{
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
char devnode[16];
dpriv->fd = open(dpriv->devnode, O_RDWR);
if (dpriv->fd < 0) {
dpriv->fd = open(dpriv->devnode, O_RDONLY);
if (dpriv->devname) {
/*
* Only open ugen(4) attached devices read-write, all
* read-only operations are done through the bus node.
*/
snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
dpriv->devname);
dpriv->fd = open(devnode, O_RDWR);
if (dpriv->fd < 0)
return _errno_to_libusb(errno);
}
usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
}
if (pipe(hpriv->pipe) < 0)
return _errno_to_libusb(errno);
@ -226,10 +268,12 @@ obsd_close(struct libusb_device_handle *handle) @@ -226,10 +268,12 @@ obsd_close(struct libusb_device_handle *handle)
struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("close: fd %d", dpriv->fd);
if (dpriv->devname) {
usbi_dbg("close: fd %d", dpriv->fd);
close(dpriv->fd);
dpriv->fd = -1;
close(dpriv->fd);
dpriv->fd = -1;
}
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
@ -257,9 +301,8 @@ obsd_get_active_config_descriptor(struct libusb_device *dev, @@ -257,9 +301,8 @@ obsd_get_active_config_descriptor(struct libusb_device *dev,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
usb_config_descriptor_t *ucd;
usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
ucd = (usb_config_descriptor_t *) dpriv->cdesc;
len = MIN(len, UGETW(ucd->wTotalLength));
usbi_dbg("len %d", len);
@ -268,58 +311,48 @@ obsd_get_active_config_descriptor(struct libusb_device *dev, @@ -268,58 +311,48 @@ obsd_get_active_config_descriptor(struct libusb_device *dev,
*host_endian = 0;
return (LIBUSB_SUCCESS);
return (len);
}
int
obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
unsigned char *buf, size_t len, int *host_endian)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
struct usb_full_desc ufd;
struct usb_device_fdesc udf;
int fd, err;
usbi_dbg("index %d, len %d", idx, len);
if ((fd = _bus_open(dev->bus_number)) < 0)
return _errno_to_libusb(errno);
/* A config descriptor may be requested before opening the device */
if (dpriv->fd >= 0) {
fd = dpriv->fd;
} else {
fd = open(dpriv->devnode, O_RDONLY);
if (fd < 0)
return _errno_to_libusb(errno);
}
udf.udf_bus = dev->bus_number;
udf.udf_addr = dev->device_address;
udf.udf_config_index = idx;
udf.udf_size = len;
udf.udf_data = buf;
ufd.ufd_config_index = idx;
ufd.ufd_size = len;
ufd.ufd_data = buf;
usbi_dbg("index %d, len %d", udf.udf_config_index, len);
if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
err = errno;
if (dpriv->fd < 0)
close(fd);
close(fd);
return _errno_to_libusb(err);
}
if (dpriv->fd < 0)
close(fd);
close(fd);
*host_endian = 0;
return (LIBUSB_SUCCESS);
return (len);
}
int
obsd_get_configuration(struct libusb_device_handle *handle, int *config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc;
usbi_dbg("");
*config = ucd->bConfigurationValue;
if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
return _errno_to_libusb(errno);
usbi_dbg("configuration %d", *config);
usbi_dbg("bConfigurationValue %d", *config);
return (LIBUSB_SUCCESS);
}
@ -329,12 +362,15 @@ obsd_set_configuration(struct libusb_device_handle *handle, int config) @@ -329,12 +362,15 @@ obsd_set_configuration(struct libusb_device_handle *handle, int config)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("configuration %d", config);
if (dpriv->devname == NULL)
return (LIBUSB_ERROR_NOT_SUPPORTED);
usbi_dbg("bConfigurationValue %d", config);
if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
return _errno_to_libusb(errno);
return _cache_active_config_descriptor(handle->dev, dpriv->fd);
return _cache_active_config_descriptor(handle->dev);
}
int
@ -369,6 +405,9 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, @@ -369,6 +405,9 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_alt_interface intf;
if (dpriv->devname == NULL)
return (LIBUSB_ERROR_NOT_SUPPORTED);
usbi_dbg("iface %d, setting %d", iface, altsetting);
memset(&intf, 0, sizeof(intf));
@ -385,19 +424,27 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, @@ -385,19 +424,27 @@ obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
int
obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
{
struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
struct usb_ctl_request req;
int fd, err;
if ((fd = _bus_open(handle->dev->bus_number)) < 0)
return _errno_to_libusb(errno);
usbi_dbg("");
req.ucr_addr = handle->dev->device_address;
req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
req.ucr_request.bRequest = UR_CLEAR_FEATURE;
USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
USETW(req.ucr_request.wIndex, endpoint);
USETW(req.ucr_request.wLength, 0);
if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
return _errno_to_libusb(errno);
if (ioctl(fd, USB_REQUEST, &req) < 0) {
err = errno;
close(fd);
return _errno_to_libusb(err);
}
close(fd);
return (LIBUSB_SUCCESS);
}
@ -418,6 +465,7 @@ obsd_destroy_device(struct libusb_device *dev) @@ -418,6 +465,7 @@ obsd_destroy_device(struct libusb_device *dev)
usbi_dbg("");
free(dpriv->cdesc);
free(dpriv->devname);
}
int
@ -557,6 +605,8 @@ obsd_clock_gettime(int clkid, struct timespec *tp) @@ -557,6 +605,8 @@ obsd_clock_gettime(int clkid, struct timespec *tp)
int
_errno_to_libusb(int err)
{
usbi_dbg("error: %s (%d)", strerror(err), err);
switch (err) {
case EIO:
return (LIBUSB_ERROR_IO);
@ -566,52 +616,64 @@ _errno_to_libusb(int err) @@ -566,52 +616,64 @@ _errno_to_libusb(int err)
return (LIBUSB_ERROR_NO_DEVICE);
case ENOMEM:
return (LIBUSB_ERROR_NO_MEM);
case ETIMEDOUT:
return (LIBUSB_ERROR_TIMEOUT);
}
usbi_dbg("error: %s", strerror(err));
return (LIBUSB_ERROR_OTHER);
}
int
_cache_active_config_descriptor(struct libusb_device *dev, int fd)
_cache_active_config_descriptor(struct libusb_device *dev)
{
struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
struct usb_config_desc ucd;
struct usb_full_desc ufd;
struct usb_device_cdesc udc;
struct usb_device_fdesc udf;
unsigned char* buf;
int len;
int fd, len, err;
usbi_dbg("fd %d", fd);
if ((fd = _bus_open(dev->bus_number)) < 0)
return _errno_to_libusb(errno);
ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
usbi_dbg("fd %d, addr %d", fd, dev->device_address);
if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
udc.udc_bus = dev->bus_number;
udc.udc_addr = dev->device_address;
udc.udc_config_index = USB_CURRENT_CONFIG_INDEX;
if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) {
err = errno;
close(fd);
return _errno_to_libusb(errno);
}
usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
usbi_dbg("active bLength %d", udc.udc_desc.bLength);
len = UGETW(ucd.ucd_desc.wTotalLength);
len = UGETW(udc.udc_desc.wTotalLength);
buf = malloc(len);
if (buf == NULL)
return (LIBUSB_ERROR_NO_MEM);
ufd.ufd_config_index = ucd.ucd_config_index;
ufd.ufd_size = len;
ufd.ufd_data = buf;
udf.udf_bus = dev->bus_number;
udf.udf_addr = dev->device_address;
udf.udf_config_index = udc.udc_config_index;
udf.udf_size = len;
udf.udf_data = buf;
usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
usbi_dbg("index %d, len %d", udf.udf_config_index, len);
if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
err = errno;
close(fd);
free(buf);
return _errno_to_libusb(errno);
return _errno_to_libusb(err);
}
close(fd);
if (dpriv->cdesc)
free(dpriv->cdesc);
dpriv->cdesc = buf;
return (0);
return (LIBUSB_SUCCESS);
}
int
@ -626,15 +688,16 @@ _sync_control_transfer(struct usbi_transfer *itransfer) @@ -626,15 +688,16 @@ _sync_control_transfer(struct usbi_transfer *itransfer)
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
setup = (struct libusb_control_setup *)transfer->buffer;
usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
usbi_dbg("type %x request %x value %x index %d length %d timeout %d",
setup->bmRequestType, setup->bRequest,
libusb_le16_to_cpu(setup->wValue),
libusb_le16_to_cpu(setup->wIndex),
libusb_le16_to_cpu(setup->wLength), transfer->timeout);
req.ucr_addr = transfer->dev_handle->dev->device_address;
req.ucr_request.bmRequestType = setup->bmRequestType;
req.ucr_request.bRequest = setup->bRequest;
/* Don't use USETW, libusb already deals with the endianness */
/* Don't use USETW, libusbx already deals with the endianness */
(*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
(*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
(*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
@ -643,11 +706,30 @@ _sync_control_transfer(struct usbi_transfer *itransfer) @@ -643,11 +706,30 @@ _sync_control_transfer(struct usbi_transfer *itransfer)
if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
req.ucr_flags = USBD_SHORT_XFER_OK;
if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if (dpriv->devname == NULL) {
/*
* XXX If the device is not attached to ugen(4) it is
* XXX still possible to submit a control transfer but
* XXX with the default timeout only.
*/
int fd, err;
if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
return _errno_to_libusb(errno);
if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(fd, USB_REQUEST, &req)) < 0) {
err = errno;
close(fd);
return _errno_to_libusb(err);
}
close(fd);
} else {
if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
return _errno_to_libusb(errno);
if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
return _errno_to_libusb(errno);
}
itransfer->transferred = req.ucr_actlen;
@ -661,7 +743,7 @@ _access_endpoint(struct libusb_transfer *transfer) @@ -661,7 +743,7 @@ _access_endpoint(struct libusb_transfer *transfer)
{
struct handle_priv *hpriv;
struct device_priv *dpriv;
char *s, devnode[16];
char devnode[16];
int fd, endpt;
mode_t mode;
@ -674,10 +756,9 @@ _access_endpoint(struct libusb_transfer *transfer) @@ -674,10 +756,9 @@ _access_endpoint(struct libusb_transfer *transfer)
usbi_dbg("endpoint %d mode %d", endpt, mode);
if (hpriv->endpoints[endpt] < 0) {
/* Pick the right node given the control one */
strlcpy(devnode, dpriv->devnode, sizeof(devnode));
s = strchr(devnode, '.');
snprintf(s, 4, ".%02d", endpt);
/* Pick the right endpoint node */
snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
dpriv->devname, endpt);
/* We may need to read/write to the same endpoint later. */
if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
@ -694,9 +775,14 @@ int @@ -694,9 +775,14 @@ int
_sync_gen_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer;
struct device_priv *dpriv;
int fd, nr = 1;
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
if (dpriv->devname == NULL)
return (LIBUSB_ERROR_NOT_SUPPORTED);
/*
* Bulk, Interrupt or Isochronous transfer depends on the
@ -725,3 +811,13 @@ _sync_gen_transfer(struct usbi_transfer *itransfer) @@ -725,3 +811,13 @@ _sync_gen_transfer(struct usbi_transfer *itransfer)
return (0);
}
int
_bus_open(int number)
{
char busnode[16];
snprintf(busnode, sizeof(busnode), USBDEV "%d", number);
return open(busnode, O_RDWR);
}

51
compat/libusb-1.0/libusb/os/poll_posix.c

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

3
compat/libusb-1.0/libusb/os/poll_posix.h

@ -4,7 +4,8 @@ @@ -4,7 +4,8 @@
#define usbi_write write
#define usbi_read read
#define usbi_close close
#define usbi_pipe pipe
#define usbi_poll poll
int usbi_pipe(int pipefd[2]);
#endif /* LIBUSB_POLL_POSIX_H */

203
compat/libusb-1.0/libusb/os/poll_windows.c

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* poll_windows: poll compatibility wrapper for Windows
* Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com>
* Copyright © 2012-2013 RealVNC Ltd.
* Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
*
@ -21,7 +22,7 @@ @@ -21,7 +22,7 @@
*/
/*
* poll() and pipe() Windows compatibility layer for libusb 1.0
* poll() and pipe() Windows compatibility layer for libusbx 1.0
*
* The way this layer works is by using OVERLAPPED with async I/O transfers, as
* OVERLAPPED have an associated event which is flagged for I/O completion.
@ -31,7 +32,7 @@ @@ -31,7 +32,7 @@
* OVERLAPPED mode
* - call usbi_create_fd with this handle to obtain a custom fd.
* Note that if you need simultaneous R/W access, you need to call create_fd
* twice, once in _O_RDONLY and once in _O_WRONLY mode to obtain 2 separate
* twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate
* pollable fds
* - leave the core functions call the poll routine and flag POLLIN/POLLOUT
*
@ -40,12 +41,10 @@ @@ -40,12 +41,10 @@
* context.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <libusbi.h>
#include "libusbi.h"
// Uncomment to debug the polling layer
//#define DEBUG_POLL_WINDOWS
@ -53,8 +52,8 @@ @@ -53,8 +52,8 @@
#define poll_dbg usbi_dbg
#else
// MSVC++ < 2005 cannot use a variadic argument and non MSVC
// compilers produce warnings if parenthesis are omitted.
#if defined(_MSC_VER) && _MSC_VER < 1400
// compilers produce warnings if parenthesis are ommitted.
#if defined(_MSC_VER) && (_MSC_VER < 1400)
#define poll_dbg
#else
#define poll_dbg(...)
@ -65,20 +64,10 @@ @@ -65,20 +64,10 @@
#pragma warning(disable:28719)
#endif
#if defined(__CYGWIN__)
// cygwin produces a warning unless these prototypes are defined
extern int _open(char* name, int flags);
extern int _close(int fd);
extern int _snprintf(char *buffer, size_t count, const char *format, ...);
#define NUL_DEVICE "/dev/null"
#else
#define NUL_DEVICE "NUL"
#endif
#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
// public fd data
const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, RW_NONE};
const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
struct winfd poll_fd[MAX_FDS];
// internal fd data
struct {
@ -93,12 +82,25 @@ BOOLEAN is_polling_set = FALSE; @@ -93,12 +82,25 @@ BOOLEAN is_polling_set = FALSE;
LONG pipe_number = 0;
static volatile LONG compat_spinlock = 0;
#if !defined(_WIN32_WCE)
// CancelIoEx, available on Vista and later only, provides the ability to cancel
// a single transfer (OVERLAPPED) when used. As it may not be part of any of the
// platform headers, we hook into the Kernel32 system DLL directly to seek it.
static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
#define CancelIoEx_Available (pCancelIoEx != NULL)
static __inline BOOL cancel_io(int _index)
#define Use_Duplicate_Handles (pCancelIoEx == NULL)
static inline void setup_cancel_io(void)
{
HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
if (hKernel32 != NULL) {
pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
GetProcAddress(hKernel32, "CancelIoEx");
}
usbi_dbg("Will use CancelIo%s for I/O cancellation",
Use_Duplicate_Handles?"":"Ex");
}
static inline BOOL cancel_io(int _index)
{
if ((_index < 0) || (_index >= MAX_FDS)) {
return FALSE;
@ -108,7 +110,12 @@ static __inline BOOL cancel_io(int _index) @@ -108,7 +110,12 @@ static __inline BOOL cancel_io(int _index)
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
return TRUE;
}
if (CancelIoEx_Available) {
if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
// Cancel outstanding transfer via the specific callback
(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
return TRUE;
}
if (pCancelIoEx != NULL) {
return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
}
if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
@ -117,6 +124,30 @@ static __inline BOOL cancel_io(int _index) @@ -117,6 +124,30 @@ static __inline BOOL cancel_io(int _index)
usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
return FALSE;
}
#else
#define Use_Duplicate_Handles FALSE
static __inline void setup_cancel_io()
{
// No setup needed on WinCE
}
static __inline BOOL cancel_io(int _index)
{
if ((_index < 0) || (_index >= MAX_FDS)) {
return FALSE;
}
if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
return TRUE;
}
if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
// Cancel outstanding transfer via the specific callback
(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
}
return TRUE;
}
#endif
// Init
void init_polling(void)
@ -127,10 +158,7 @@ void init_polling(void) @@ -127,10 +158,7 @@ void init_polling(void)
SleepEx(0, TRUE);
}
if (!is_polling_set) {
pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
GetProcAddress(GetModuleHandleA("KERNEL32"), "CancelIoEx");
usbi_dbg("Will use CancelIo%s for I/O cancellation",
CancelIoEx_Available?"Ex":"");
setup_cancel_io();
for (i=0; i<MAX_FDS; i++) {
poll_fd[i] = INVALID_WINFD;
_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
@ -139,15 +167,15 @@ void init_polling(void) @@ -139,15 +167,15 @@ void init_polling(void)
}
is_polling_set = TRUE;
}
compat_spinlock = 0;
InterlockedExchange((LONG *)&compat_spinlock, 0);
}
// Internal function to retrieve the table index (and lock the fd mutex)
int _fd_to_index_and_lock(int fd)
static int _fd_to_index_and_lock(int fd)
{
int i;
if (fd <= 0)
if (fd < 0)
return -1;
for (i=0; i<MAX_FDS; i++) {
@ -164,7 +192,7 @@ int _fd_to_index_and_lock(int fd) @@ -164,7 +192,7 @@ int _fd_to_index_and_lock(int fd)
return -1;
}
OVERLAPPED *create_overlapped(void)
static OVERLAPPED *create_overlapped(void)
{
OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
if (overlapped == NULL) {
@ -178,7 +206,7 @@ OVERLAPPED *create_overlapped(void) @@ -178,7 +206,7 @@ OVERLAPPED *create_overlapped(void)
return overlapped;
}
void free_overlapped(OVERLAPPED *overlapped)
static void free_overlapped(OVERLAPPED *overlapped)
{
if (overlapped == NULL)
return;
@ -190,20 +218,6 @@ void free_overlapped(OVERLAPPED *overlapped) @@ -190,20 +218,6 @@ void free_overlapped(OVERLAPPED *overlapped)
free(overlapped);
}
void reset_overlapped(OVERLAPPED *overlapped)
{
HANDLE event_handle;
if (overlapped == NULL)
return;
event_handle = overlapped->hEvent;
if (event_handle != NULL) {
ResetEvent(event_handle);
}
memset(overlapped, 0, sizeof(OVERLAPPED));
overlapped->hEvent = event_handle;
}
void exit_polling(void)
{
int i;
@ -221,12 +235,8 @@ void exit_polling(void) @@ -221,12 +235,8 @@ void exit_polling(void)
// terminating, and we should be able to access the fd
// mutex lock before too long
EnterCriticalSection(&_poll_fd[i].mutex);
if ( (poll_fd[i].fd > 0) && (poll_fd[i].handle != INVALID_HANDLE_VALUE) && (poll_fd[i].handle != 0)
&& (GetFileType(poll_fd[i].handle) == FILE_TYPE_UNKNOWN) ) {
_close(poll_fd[i].fd);
}
free_overlapped(poll_fd[i].overlapped);
if (!CancelIoEx_Available) {
if (Use_Duplicate_Handles) {
// Close duplicate handle
if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
CloseHandle(poll_fd[i].handle);
@ -237,12 +247,12 @@ void exit_polling(void) @@ -237,12 +247,12 @@ void exit_polling(void)
DeleteCriticalSection(&_poll_fd[i].mutex);
}
}
compat_spinlock = 0;
InterlockedExchange((LONG *)&compat_spinlock, 0);
}
/*
* Create a fake pipe.
* As libusb only uses pipes for signaling, all we need from a pipe is an
* As libusbx only uses pipes for signaling, all we need from a pipe is an
* event. To that extent, we create a single wfd and overlapped as a means
* to access that event.
*/
@ -253,7 +263,8 @@ int usbi_pipe(int filedes[2]) @@ -253,7 +263,8 @@ int usbi_pipe(int filedes[2])
CHECK_INIT_POLLING;
overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
overlapped = create_overlapped();
if (overlapped == NULL) {
return -1;
}
@ -261,22 +272,6 @@ int usbi_pipe(int filedes[2]) @@ -261,22 +272,6 @@ int usbi_pipe(int filedes[2])
overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0;
// Read end of the "pipe"
filedes[0] = _open(NUL_DEVICE, _O_WRONLY);
if (filedes[0] < 0) {
usbi_err(NULL, "could not create pipe: errno %d", errno);
goto out1;
}
// We can use the same handle for both ends
filedes[1] = filedes[0];
poll_dbg("pipe filedes = %d", filedes[0]);
// Note: manual reset must be true (second param) as the reset occurs in read
overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!overlapped->hEvent) {
goto out2;
}
for (i=0; i<MAX_FDS; i++) {
if (poll_fd[i].fd < 0) {
EnterCriticalSection(&_poll_fd[i].mutex);
@ -286,7 +281,13 @@ int usbi_pipe(int filedes[2]) @@ -286,7 +281,13 @@ int usbi_pipe(int filedes[2])
continue;
}
poll_fd[i].fd = filedes[0];
// Use index as the unique fd number
poll_fd[i].fd = i;
// Read end of the "pipe"
filedes[0] = poll_fd[i].fd;
// We can use the same handle for both ends
filedes[1] = filedes[0];
poll_fd[i].handle = DUMMY_HANDLE;
poll_fd[i].overlapped = overlapped;
// There's no polling on the write end, so we just use READ for our needs
@ -296,12 +297,7 @@ int usbi_pipe(int filedes[2]) @@ -296,12 +297,7 @@ int usbi_pipe(int filedes[2])
return 0;
}
}
CloseHandle(overlapped->hEvent);
out2:
_close(filedes[0]);
out1:
free(overlapped);
free_overlapped(overlapped);
return -1;
}
@ -319,9 +315,9 @@ out1: @@ -319,9 +315,9 @@ out1:
* read and one for write. Using a single R/W fd is unsupported and will
* produce unexpected results
*/
struct winfd usbi_create_fd(HANDLE handle, int access_mode)
struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
{
int i, fd;
int i;
struct winfd wfd = INVALID_WINFD;
OVERLAPPED* overlapped = NULL;
@ -331,27 +327,22 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode) @@ -331,27 +327,22 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
return INVALID_WINFD;
}
if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) {
usbi_warn(NULL, "only one of _O_RDONLY or _O_WRONLY are supported.\n"
wfd.itransfer = itransfer;
wfd.cancel_fn = cancel_fn;
if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported.\n"
"If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
return INVALID_WINFD;
}
if (access_mode == _O_RDONLY) {
if (access_mode == RW_READ) {
wfd.rw = RW_READ;
} else {
wfd.rw = RW_WRITE;
}
// Ensure that we get a non system conflicting unique fd, using
// the same fd attribution system as the pipe ends
fd = _open(NUL_DEVICE, _O_WRONLY);
if (fd < 0) {
return INVALID_WINFD;
}
overlapped = create_overlapped();
if(overlapped == NULL) {
_close(fd);
return INVALID_WINFD;
}
@ -363,10 +354,11 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode) @@ -363,10 +354,11 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
LeaveCriticalSection(&_poll_fd[i].mutex);
continue;
}
wfd.fd = fd;
// Use index as the unique fd number
wfd.fd = i;
// Attempt to emulate some of the CancelIoEx behaviour on platforms
// that don't have it
if (!CancelIoEx_Available) {
if (Use_Duplicate_Handles) {
_poll_fd[i].thread_id = GetCurrentThreadId();
if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
&wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
@ -387,21 +379,15 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode) @@ -387,21 +379,15 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
}
}
free_overlapped(overlapped);
_close(fd);
return INVALID_WINFD;
}
void _free_index(int _index)
static void _free_index(int _index)
{
// Cancel any async IO (Don't care about the validity of our handles for this)
cancel_io(_index);
// close fake handle for devices
if ( (poll_fd[_index].handle != INVALID_HANDLE_VALUE) && (poll_fd[_index].handle != 0)
&& (GetFileType(poll_fd[_index].handle) == FILE_TYPE_UNKNOWN) ) {
_close(poll_fd[_index].fd);
}
// close the duplicate handle (if we have an actual duplicate)
if (!CancelIoEx_Available) {
if (Use_Duplicate_Handles) {
if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
CloseHandle(poll_fd[_index].handle);
}
@ -417,17 +403,18 @@ void _free_index(int _index) @@ -417,17 +403,18 @@ void _free_index(int _index)
*
* Note that the associated Windows handle is not closed by this call
*/
void usbi_free_fd(int fd)
void usbi_free_fd(struct winfd *wfd)
{
int _index;
CHECK_INIT_POLLING;
_index = _fd_to_index_and_lock(fd);
_index = _fd_to_index_and_lock(wfd->fd);
if (_index < 0) {
return;
}
_free_index(_index);
*wfd = INVALID_WINFD;
LeaveCriticalSection(&_poll_fd[_index].mutex);
}
@ -441,7 +428,7 @@ struct winfd fd_to_winfd(int fd) @@ -441,7 +428,7 @@ struct winfd fd_to_winfd(int fd)
CHECK_INIT_POLLING;
if (fd <= 0)
if (fd < 0)
return INVALID_WINFD;
for (i=0; i<MAX_FDS; i++) {
@ -651,15 +638,7 @@ int usbi_close(int fd) @@ -651,15 +638,7 @@ int usbi_close(int fd)
if (_index < 0) {
errno = EBADF;
} else {
if (poll_fd[_index].overlapped != NULL) {
// Must be a different event for each end of the pipe
CloseHandle(poll_fd[_index].overlapped->hEvent);
free(poll_fd[_index].overlapped);
}
r = _close(poll_fd[_index].fd);
if (r != 0) {
errno = EIO;
}
free_overlapped(poll_fd[_index].overlapped);
poll_fd[_index] = INVALID_WINFD;
LeaveCriticalSection(&_poll_fd[_index].mutex);
}
@ -672,6 +651,7 @@ int usbi_close(int fd) @@ -672,6 +651,7 @@ int usbi_close(int fd)
ssize_t usbi_write(int fd, const void *buf, size_t count)
{
int _index;
UNUSED(buf);
CHECK_INIT_POLLING;
@ -708,6 +688,7 @@ ssize_t usbi_read(int fd, void *buf, size_t count) @@ -708,6 +688,7 @@ ssize_t usbi_read(int fd, void *buf, size_t count)
{
int _index;
ssize_t r = -1;
UNUSED(buf);
CHECK_INIT_POLLING;

20
compat/libusb-1.0/libusb/os/poll_windows.h

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Windows compat: POSIX compatibility wrapper
* Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com>
* Copyright © 2012-2013 RealVNC Ltd.
* Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
*
@ -21,8 +22,6 @@ @@ -21,8 +22,6 @@
*/
#pragma once
#include <windows.h>
#if defined(_MSC_VER)
// disable /W4 MSVC warnings that are benign
#pragma warning(disable:4127) // conditional expression is constant
@ -33,12 +32,17 @@ @@ -33,12 +32,17 @@
#define STATUS_REPARSE ((LONG)0x00000104L)
#endif
#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE
#if defined(_WIN32_WCE)
// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it
#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING)
#endif
#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY)
#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
enum windows_version {
WINDOWS_UNSUPPORTED,
WINDOWS_CE,
WINDOWS_XP,
WINDOWS_2003, // also includes XP 64
WINDOWS_VISTA_AND_LATER,
@ -68,10 +72,14 @@ enum rw_type { @@ -68,10 +72,14 @@ enum rw_type {
};
// fd struct that can be used for polling on Windows
typedef int cancel_transfer(struct usbi_transfer *itransfer);
struct winfd {
int fd; // what's exposed to libusb core
HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it
OVERLAPPED* overlapped; // what will report our I/O status
struct usbi_transfer *itransfer; // Associated transfer, or NULL if completed
cancel_transfer *cancel_fn; // Function pointer to cancel transfer API
enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH)
};
extern const struct winfd INVALID_WINFD;
@ -84,8 +92,9 @@ int usbi_close(int fd); @@ -84,8 +92,9 @@ int usbi_close(int fd);
void init_polling(void);
void exit_polling(void);
struct winfd usbi_create_fd(HANDLE handle, int access_mode);
void usbi_free_fd(int fd);
struct winfd usbi_create_fd(HANDLE handle, int access_mode,
struct usbi_transfer *transfer, cancel_transfer *cancel_fn);
void usbi_free_fd(struct winfd* winfd);
struct winfd fd_to_winfd(int fd);
struct winfd handle_to_winfd(HANDLE handle);
struct winfd overlapped_to_winfd(OVERLAPPED* overlapped);
@ -114,4 +123,3 @@ do { \ @@ -114,4 +123,3 @@ do { \
} \
} while (0)
#endif

47
compat/libusb-1.0/libusb/os/threads_posix.c

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
/*
* libusb synchronization using POSIX Threads
* libusbx synchronization using POSIX Threads
*
* Copyright (C) 2011 Vitali Lovich <vlovich@aliph.com>
* Copyright (C) 2011 Peter Stuge <peter@stuge.se>
* Copyright © 2011 Vitali Lovich <vlovich@aliph.com>
* Copyright © 2011 Peter Stuge <peter@stuge.se>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -19,14 +19,19 @@ @@ -19,14 +19,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef _XOPEN_SOURCE
# if _XOPEN_SOURCE < 500
# undef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500
#if defined(__linux__) || defined(__OpenBSD__)
# if defined(__linux__)
# define _GNU_SOURCE
# else
# define _BSD_SOURCE
# endif
#else
#define _XOPEN_SOURCE 500
#endif /* _XOPEN_SOURCE */
# include <unistd.h>
# include <sys/syscall.h>
#elif defined(__APPLE__)
# include <mach/mach.h>
#elif defined(__CYGWIN__)
# include <windows.h>
#endif
#include "threads_posix.h"
@ -41,6 +46,7 @@ int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) @@ -41,6 +46,7 @@ int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
return err;
}
/* mutexattr_settype requires _GNU_SOURCE or _XOPEN_SOURCE >= 500 on Linux */
err = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_RECURSIVE);
if (err != 0)
goto finish;
@ -53,3 +59,24 @@ finish: @@ -53,3 +59,24 @@ finish:
return err;
}
int usbi_get_tid(void)
{
int ret = -1;
#if defined(__ANDROID__)
ret = gettid();
#elif defined(__linux__)
ret = syscall(SYS_gettid);
#elif defined(__OpenBSD__)
/* The following only works with OpenBSD > 5.1 as it requires
real thread support. For 5.1 and earlier, -1 is returned. */
ret = syscall(SYS_getthrid);
#elif defined(__APPLE__)
ret = mach_thread_self();
mach_port_deallocate(mach_task_self(), ret);
#elif defined(__CYGWIN__)
ret = GetCurrentThreadId();
#endif
/* TODO: NetBSD thread ID support */
return ret;
}

6
compat/libusb-1.0/libusb/os/threads_posix.h

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/*
* libusb synchronization using POSIX Threads
* libusbx synchronization using POSIX Threads
*
* Copyright (C) 2010 Peter Stuge <peter@stuge.se>
* Copyright © 2010 Peter Stuge <peter@stuge.se>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -45,4 +45,6 @@ @@ -45,4 +45,6 @@
extern int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
int usbi_get_tid(void);
#endif /* LIBUSB_THREADS_POSIX_H */

28
compat/libusb-1.0/libusb/os/threads_windows.c

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/*
* libusb synchronization on Microsoft Windows
* libusbx synchronization on Microsoft Windows
*
* Copyright (C) 2010 Michael Plante <michael.plante@gmail.com>
* Copyright © 2010 Michael Plante <michael.plante@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -25,9 +25,11 @@ @@ -25,9 +25,11 @@
#include "libusbi.h"
extern const uint64_t epoch_time;
int usbi_mutex_init(usbi_mutex_t *mutex,
const usbi_mutexattr_t *attr) {
UNUSED(attr);
if(! mutex) return ((errno=EINVAL));
*mutex = CreateMutex(NULL, FALSE, NULL);
if(!*mutex) return ((errno=ENOMEM));
@ -79,10 +81,9 @@ int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) { @@ -79,10 +81,9 @@ int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) {
return 0;
}
int usbi_cond_init(usbi_cond_t *cond,
const usbi_condattr_t *attr) {
UNUSED(attr);
if(!cond) return ((errno=EINVAL));
list_init(&cond->waiters );
list_init(&cond->not_waiting);
@ -90,16 +91,14 @@ int usbi_cond_init(usbi_cond_t *cond, @@ -90,16 +91,14 @@ int usbi_cond_init(usbi_cond_t *cond,
}
int usbi_cond_destroy(usbi_cond_t *cond) {
// This assumes no one is using this anymore. The check MAY NOT BE safe.
struct usbi_cond_perthread *pos, *prev_pos = NULL;
struct usbi_cond_perthread *pos, *next_pos = NULL;
if(!cond) return ((errno=EINVAL));
if(!list_empty(&cond->waiters)) return ((errno=EBUSY )); // (!see above!)
list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
free(prev_pos);
list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
CloseHandle(pos->event);
list_del(&pos->list);
prev_pos = pos;
free(pos);
}
free(prev_pos);
return 0;
}
@ -129,7 +128,7 @@ int usbi_cond_signal(usbi_cond_t *cond) { @@ -129,7 +128,7 @@ int usbi_cond_signal(usbi_cond_t *cond) {
// The wait function will remove its respective item from the list.
return SetEvent(pos->event) ? 0 : ((errno=EINVAL));
}
static int __inline usbi_cond_intwait(usbi_cond_t *cond,
__inline static int usbi_cond_intwait(usbi_cond_t *cond,
usbi_mutex_t *mutex,
DWORD timeout_ms) {
struct usbi_cond_perthread *pos;
@ -182,9 +181,11 @@ int usbi_cond_timedwait(usbi_cond_t *cond, @@ -182,9 +181,11 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
struct timeval targ_time, cur_time, delta_time;
struct timespec cur_time_ns;
DWORD millis;
extern const uint64_t epoch_time;
GetSystemTimeAsFileTime(&filetime);
// GetSystemTimeAsFileTime() is not available on CE
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &filetime);
rtime.LowPart = filetime.dwLowDateTime;
rtime.HighPart = filetime.dwHighDateTime;
rtime.QuadPart -= epoch_time;
@ -206,3 +207,6 @@ int usbi_cond_timedwait(usbi_cond_t *cond, @@ -206,3 +207,6 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
return usbi_cond_intwait(cond, mutex, millis);
}
int usbi_get_tid(void) {
return GetCurrentThreadId();
}

9
compat/libusb-1.0/libusb/os/threads_windows.h

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/*
* libusb synchronization on Microsoft Windows
* libusbx synchronization on Microsoft Windows
*
* Copyright (C) 2010 Michael Plante <michael.plante@gmail.com>
* Copyright © 2010 Michael Plante <michael.plante@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -21,8 +21,6 @@ @@ -21,8 +21,6 @@
#ifndef LIBUSB_THREADS_WINDOWS_H
#define LIBUSB_THREADS_WINDOWS_H
#include <windows.h>
#define usbi_mutex_static_t volatile LONG
#define USBI_MUTEX_INITIALIZER 0
@ -84,5 +82,6 @@ int usbi_cond_timedwait(usbi_cond_t *cond, @@ -84,5 +82,6 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
int usbi_cond_broadcast(usbi_cond_t *cond);
int usbi_cond_signal(usbi_cond_t *cond);
#endif /* LIBUSB_THREADS_WINDOWS_H */
int usbi_get_tid(void);
#endif /* LIBUSB_THREADS_WINDOWS_H */

1026
compat/libusb-1.0/libusb/os/wince_usb.c

File diff suppressed because it is too large Load Diff

131
compat/libusb-1.0/libusb/os/wince_usb.h

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

108
compat/libusb-1.0/libusb/os/windows_common.h

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
/*
* Windows backend common header for libusbx 1.0
*
* This file brings together header code common between
* the desktop Windows and Windows CE backends.
* Copyright © 2012-2013 RealVNC Ltd.
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
// Windows API default is uppercase - ugh!
#if !defined(bool)
#define bool BOOL
#endif
#if !defined(true)
#define true TRUE
#endif
#if !defined(false)
#define false FALSE
#endif
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
#define safe_strlen(str) ((str==NULL)?0:strlen(str))
#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0)
#define safe_stprintf _sntprintf
#define safe_tcslen(str) ((str==NULL)?0:_tcslen(str))
#define safe_unref_device(dev) do {if (dev != NULL) {libusb_unref_device(dev); dev = NULL;}} while(0)
#define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL)
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#define ERR_BUFFER_SIZE 256
#define TIMER_REQUEST_RETRY_MS 100
#define MAX_TIMER_SEMAPHORES 128
/*
* API macros - from libusb-win32 1.x
*/
#define DLL_DECLARE_PREFIXNAME(api, ret, prefixname, name, args) \
typedef ret (api * __dll_##name##_t)args; \
static __dll_##name##_t prefixname = NULL
#ifndef _WIN32_WCE
#define DLL_STRINGIFY(dll) #dll
#define DLL_GET_MODULE_HANDLE(dll) GetModuleHandleA(DLL_STRINGIFY(dll))
#define DLL_LOAD_LIBRARY(dll) LoadLibraryA(DLL_STRINGIFY(dll))
#else
#define DLL_STRINGIFY(dll) L#dll
#define DLL_GET_MODULE_HANDLE(dll) GetModuleHandle(DLL_STRINGIFY(dll))
#define DLL_LOAD_LIBRARY(dll) LoadLibrary(DLL_STRINGIFY(dll))
#endif
#define DLL_LOAD_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
do { \
HMODULE h = DLL_GET_MODULE_HANDLE(dll); \
if (!h) \
h = DLL_LOAD_LIBRARY(dll); \
if (!h) { \
if (ret_on_failure) { return LIBUSB_ERROR_NOT_FOUND; } \
else { break; } \
} \
prefixname = (__dll_##name##_t)GetProcAddress(h, \
DLL_STRINGIFY(name)); \
if (prefixname) break; \
prefixname = (__dll_##name##_t)GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \
if (prefixname) break; \
prefixname = (__dll_##name##_t)GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \
if (prefixname) break; \
if(ret_on_failure) \
return LIBUSB_ERROR_NOT_FOUND; \
} while(0)
#define DLL_DECLARE(api, ret, name, args) DLL_DECLARE_PREFIXNAME(api, ret, name, name, args)
#define DLL_LOAD(dll, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, name, name, ret_on_failure)
#define DLL_DECLARE_PREFIXED(api, ret, prefix, name, args) DLL_DECLARE_PREFIXNAME(api, ret, prefix##name, name, args)
#define DLL_LOAD_PREFIXED(dll, prefix, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, prefix##name, name, ret_on_failure)

2170
compat/libusb-1.0/libusb/os/windows_usb.c

File diff suppressed because it is too large Load Diff

532
compat/libusb-1.0/libusb/os/windows_usb.h

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* Windows backend for libusb 1.0
* Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com>
* Windows backend for libusbx 1.0
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
* Major code testing contribution by Xiaofan Chen
@ -22,6 +22,8 @@ @@ -22,6 +22,8 @@
#pragma once
#include "windows_common.h"
#if defined(_MSC_VER)
// disable /W4 MSVC warnings that are benign
#pragma warning(disable:4127) // conditional expression is constant
@ -30,17 +32,6 @@ @@ -30,17 +32,6 @@
#pragma warning(disable:4201) // nameless struct/union
#endif
// Windows API default is uppercase - ugh!
#if !defined(bool)
#define bool BOOL
#endif
#if !defined(true)
#define true TRUE
#endif
#if !defined(false)
#define false FALSE
#endif
// Missing from MSVC6 setupapi.h
#if !defined(SPDRP_ADDRESS)
#define SPDRP_ADDRESS 28
@ -50,45 +41,30 @@ @@ -50,45 +41,30 @@
#endif
#if defined(__CYGWIN__ )
#define _stricmp stricmp
// cygwin produces a warning unless these prototypes are defined
extern int _snprintf(char *buffer, size_t count, const char *format, ...);
extern char *_strdup(const char *strSource);
// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, f)
#endif
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
#define safe_strlen(str) ((str==NULL)?0:strlen(str))
#define safe_sprintf _snprintf
#define safe_unref_device(dev) do {if (dev != NULL) {libusb_unref_device(dev); dev = NULL;}} while(0)
#define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL)
static inline void upperize(char* str) {
size_t i;
if (str == NULL) return;
for (i=0; i<safe_strlen(str); i++)
str[i] = (char)toupper((int)str[i]);
}
#define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_DEVICES 256
#define MAX_USB_STRING_LENGTH 128
#define MAX_HID_REPORT_SIZE 1024
#define MAX_HID_DESCRIPTOR_SIZE 256
#define MAX_GUID_STRING_LENGTH 40
#define MAX_PATH_LENGTH 128
#define MAX_KEY_LENGTH 256
#define MAX_TIMER_SEMAPHORES 128
#define TIMER_REQUEST_RETRY_MS 100
#define ERR_BUFFER_SIZE 256
#define LIST_SEPARATOR ';'
#define HTAB_SIZE 1021
// Handle code for HID interface that have been claimed ("dibs")
#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5)
// Additional return code for HID operations that completed synchronously
#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1)
// http://msdn.microsoft.com/en-us/library/ff545978.aspx
// http://msdn.microsoft.com/en-us/library/ff545972.aspx
// http://msdn.microsoft.com/en-us/library/ff545982.aspx
@ -101,7 +77,9 @@ const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0 @@ -101,7 +77,9 @@ const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0
#if !defined(GUID_DEVINTERFACE_USB_HUB)
const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} };
#endif
const GUID GUID_NULL = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER)
const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} };
#endif
/*
@ -110,34 +88,43 @@ const GUID GUID_NULL = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x @@ -110,34 +88,43 @@ const GUID GUID_NULL = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x
#define USB_API_UNSUPPORTED 0
#define USB_API_HUB 1
#define USB_API_COMPOSITE 2
#define USB_API_WINUSB 3
#define USB_API_MAX 4
#define CLASS_GUID_UNSUPPORTED GUID_NULL
const GUID CLASS_GUID_LIBUSB_WINUSB = { 0x78A1C341, 0x4539, 0x11D3, {0xB8, 0x8D, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71} };
const GUID CLASS_GUID_COMPOSITE = { 0x36FC9E60, 0xC465, 0x11cF, {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
#define USB_API_WINUSBX 3
#define USB_API_HID 4
#define USB_API_MAX 5
// The following is used to indicate if the HID or composite extra props have already been set.
#define USB_API_SET (1<<USB_API_MAX)
// Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL)
// Must have the same values as the KUSB_DRVID enum from libusbk.h
#define SUB_API_NOTSET -1
#define SUB_API_LIBUSBK 0
#define SUB_API_LIBUSB0 1
#define SUB_API_WINUSB 2
#define SUB_API_MAX 3
#define WINUSBX_DRV_NAMES { "libusbK", "libusb0", "WinUSB"}
struct windows_usb_api_backend {
const uint8_t id;
const char* designation;
const GUID *class_guid; // The Class GUID (for fallback in case the driver name cannot be read)
const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
const uint8_t nb_driver_names;
int (*init)(struct libusb_context *ctx);
int (*exit)(void);
int (*open)(struct libusb_device_handle *dev_handle);
void (*close)(struct libusb_device_handle *dev_handle);
int (*claim_interface)(struct libusb_device_handle *dev_handle, int iface);
int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, int iface, int altsetting);
int (*release_interface)(struct libusb_device_handle *dev_handle, int iface);
int (*clear_halt)(struct libusb_device_handle *dev_handle, unsigned char endpoint);
int (*reset_device)(struct libusb_device_handle *dev_handle);
int (*submit_bulk_transfer)(struct usbi_transfer *itransfer);
int (*submit_iso_transfer)(struct usbi_transfer *itransfer);
int (*submit_control_transfer)(struct usbi_transfer *itransfer);
int (*abort_control)(struct usbi_transfer *itransfer);
int (*abort_transfers)(struct usbi_transfer *itransfer);
int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size);
int (*init)(int sub_api, struct libusb_context *ctx);
int (*exit)(int sub_api);
int (*open)(int sub_api, struct libusb_device_handle *dev_handle);
void (*close)(int sub_api, struct libusb_device_handle *dev_handle);
int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface);
int (*clear_halt)(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
int (*reset_device)(int sub_api, struct libusb_device_handle *dev_handle);
int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*abort_control)(int sub_api, struct usbi_transfer *itransfer);
int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer);
int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
};
extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
@ -151,21 +138,90 @@ extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX]; @@ -151,21 +138,90 @@ extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
* private structures definition
* with inline pseudo constructors/destructors
*/
// TODO (v2+): move hid desc to libusb.h?
struct libusb_hid_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bClassDescriptorType;
uint16_t wClassDescriptorLength;
};
#define LIBUSB_DT_HID_SIZE 9
#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \
+ LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE)
#define HID_MAX_REPORT_SIZE 1024
#define HID_IN_EP 0x81
#define HID_OUT_EP 0x02
#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F)
#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5))
#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN)
#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type))
// The following are used for HID reports IOCTLs
#define HID_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
#define HID_BUFFER_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define HID_IN_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define HID_OUT_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100)
#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101)
enum libusb_hid_request_type {
HID_REQ_GET_REPORT = 0x01,
HID_REQ_GET_IDLE = 0x02,
HID_REQ_GET_PROTOCOL = 0x03,
HID_REQ_SET_REPORT = 0x09,
HID_REQ_SET_IDLE = 0x0A,
HID_REQ_SET_PROTOCOL = 0x0B
};
enum libusb_hid_report_type {
HID_REPORT_TYPE_INPUT = 0x01,
HID_REPORT_TYPE_OUTPUT = 0x02,
HID_REPORT_TYPE_FEATURE = 0x03
};
struct hid_device_priv {
uint16_t vid;
uint16_t pid;
uint8_t config;
uint8_t nb_interfaces;
bool uses_report_ids[3]; // input, ouptput, feature
uint16_t input_report_size;
uint16_t output_report_size;
uint16_t feature_report_size;
WCHAR string[3][MAX_USB_STRING_LENGTH];
uint8_t string_index[3]; // man, prod, ser
};
typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
struct windows_device_priv {
uint8_t depth; // distance to HCD
uint8_t port; // port number on the hub
uint8_t active_config;
struct libusb_device *parent_dev; // access to parent is required for usermode ops
char *path; // device interface path
struct windows_usb_api_backend const *apib;
char *path; // device interface path
int sub_api; // for WinUSB-like APIs
struct {
char *path; // each interface needs a device interface path,
struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support),
int sub_api;
int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
uint8_t *endpoint;
bool restricted_functionality; // indicates if the interface functionality is restricted
// by Windows (eg. HID keyboards or mice cannot do R/W)
} usb_interface[USB_MAXINTERFACES];
uint8_t composite_api_flags; // composite devices require additional data
uint8_t active_config;
struct hid_device_priv *hid;
USB_DEVICE_DESCRIPTOR dev_descriptor;
unsigned char **config_descriptor; // list of pointers to the cached config descriptors
};
@ -182,15 +238,18 @@ static inline void windows_device_priv_init(libusb_device* dev) { @@ -182,15 +238,18 @@ static inline void windows_device_priv_init(libusb_device* dev) {
p->parent_dev = NULL;
p->path = NULL;
p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->composite_api_flags = 0;
p->sub_api = SUB_API_NOTSET;
p->hid = NULL;
p->active_config = 0;
p->config_descriptor = NULL;
memset(&(p->dev_descriptor), 0, sizeof(USB_DEVICE_DESCRIPTOR));
for (i=0; i<USB_MAXINTERFACES; i++) {
p->usb_interface[i].path = NULL;
p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->usb_interface[i].sub_api = SUB_API_NOTSET;
p->usb_interface[i].nb_endpoints = 0;
p->usb_interface[i].endpoint = NULL;
p->usb_interface[i].restricted_functionality = false;
}
}
@ -203,6 +262,7 @@ static inline void windows_device_priv_release(libusb_device* dev) { @@ -203,6 +262,7 @@ static inline void windows_device_priv_release(libusb_device* dev) {
safe_free(p->config_descriptor[i]);
}
safe_free(p->config_descriptor);
safe_free(p->hid);
for (i=0; i<USB_MAXINTERFACES; i++) {
safe_free(p->usb_interface[i].path);
safe_free(p->usb_interface[i].endpoint);
@ -230,6 +290,9 @@ static inline struct windows_device_handle_priv *_device_handle_priv( @@ -230,6 +290,9 @@ static inline struct windows_device_handle_priv *_device_handle_priv(
struct windows_transfer_priv {
struct winfd pollable_fd;
uint8_t interface_number;
uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
uint8_t *hid_dest; // transfer buffer destination, required for HID
size_t hid_expected_size;
};
// used to match a device driver (including filter drivers) against a supported API
@ -239,37 +302,6 @@ struct driver_lookup { @@ -239,37 +302,6 @@ struct driver_lookup {
const char* designation; // internal designation (for debug output)
};
/*
* API macros - from libusb-win32 1.x
*/
#define DLL_DECLARE_PREFIXNAME(api, ret, prefixname, name, args) \
typedef ret (api * __dll_##name##_t)args; \
static __dll_##name##_t prefixname = NULL
#define DLL_LOAD_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
do { \
HMODULE h = GetModuleHandleA(#dll); \
if (!h) \
h = LoadLibraryA(#dll); \
if (!h) { \
if (ret_on_failure) { return LIBUSB_ERROR_NOT_FOUND; }\
else { break; } \
} \
prefixname = (__dll_##name##_t)GetProcAddress(h, #name); \
if (prefixname) break; \
prefixname = (__dll_##name##_t)GetProcAddress(h, #name "A"); \
if (prefixname) break; \
prefixname = (__dll_##name##_t)GetProcAddress(h, #name "W"); \
if (prefixname) break; \
if(ret_on_failure) \
return LIBUSB_ERROR_NOT_FOUND; \
} while(0)
#define DLL_DECLARE(api, ret, name, args) DLL_DECLARE_PREFIXNAME(api, ret, name, name, args)
#define DLL_LOAD(dll, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, name, name, ret_on_failure)
#define DLL_DECLARE_PREFIXED(api, ret, prefix, name, args) DLL_DECLARE_PREFIXNAME(api, ret, prefix##name, name, args)
#define DLL_LOAD_PREFIXED(dll, prefix, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, prefix##name, name, ret_on_failure)
/* OLE32 dependency */
DLL_DECLARE_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID));
@ -284,6 +316,7 @@ DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); @@ -284,6 +316,7 @@ DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD));
DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
@ -589,20 +622,297 @@ typedef struct { @@ -589,20 +622,297 @@ typedef struct {
typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
DLL_DECLARE(WINAPI, BOOL, WinUsb_Initialize, (HANDLE, PWINUSB_INTERFACE_HANDLE));
DLL_DECLARE(WINAPI, BOOL, WinUsb_Free, (WINUSB_INTERFACE_HANDLE));
DLL_DECLARE(WINAPI, BOOL, WinUsb_GetAssociatedInterface, (WINUSB_INTERFACE_HANDLE, UCHAR, PWINUSB_INTERFACE_HANDLE));
DLL_DECLARE(WINAPI, BOOL, WinUsb_GetDescriptor, (WINUSB_INTERFACE_HANDLE, UCHAR, UCHAR, USHORT, PUCHAR, ULONG, PULONG));
DLL_DECLARE(WINAPI, BOOL, WinUsb_QueryInterfaceSettings, (WINUSB_INTERFACE_HANDLE, UCHAR, PUSB_INTERFACE_DESCRIPTOR));
DLL_DECLARE(WINAPI, BOOL, WinUsb_QueryDeviceInformation, (WINUSB_INTERFACE_HANDLE, ULONG, PULONG, PVOID));
DLL_DECLARE(WINAPI, BOOL, WinUsb_SetCurrentAlternateSetting, (WINUSB_INTERFACE_HANDLE, UCHAR));
DLL_DECLARE(WINAPI, BOOL, WinUsb_GetCurrentAlternateSetting, (WINUSB_INTERFACE_HANDLE, PUCHAR));
DLL_DECLARE(WINAPI, BOOL, WinUsb_QueryPipe, (WINUSB_INTERFACE_HANDLE, UCHAR, UCHAR, PWINUSB_PIPE_INFORMATION));
DLL_DECLARE(WINAPI, BOOL, WinUsb_SetPipePolicy, (WINUSB_INTERFACE_HANDLE, UCHAR, ULONG, ULONG, PVOID));
DLL_DECLARE(WINAPI, BOOL, WinUsb_GetPipePolicy, (WINUSB_INTERFACE_HANDLE, UCHAR, ULONG, PULONG, PVOID));
DLL_DECLARE(WINAPI, BOOL, WinUsb_ReadPipe, (WINUSB_INTERFACE_HANDLE, UCHAR, PUCHAR, ULONG, PULONG, LPOVERLAPPED));
DLL_DECLARE(WINAPI, BOOL, WinUsb_WritePipe, (WINUSB_INTERFACE_HANDLE, UCHAR, PUCHAR, ULONG, PULONG, LPOVERLAPPED));
DLL_DECLARE(WINAPI, BOOL, WinUsb_ControlTransfer, (WINUSB_INTERFACE_HANDLE, WINUSB_SETUP_PACKET, PUCHAR, ULONG, PULONG, LPOVERLAPPED));
DLL_DECLARE(WINAPI, BOOL, WinUsb_ResetPipe, (WINUSB_INTERFACE_HANDLE, UCHAR));
DLL_DECLARE(WINAPI, BOOL, WinUsb_AbortPipe, (WINUSB_INTERFACE_HANDLE, UCHAR));
DLL_DECLARE(WINAPI, BOOL, WinUsb_FlushPipe, (WINUSB_INTERFACE_HANDLE, UCHAR));
typedef BOOL (WINAPI *WinUsb_AbortPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_ControlTransfer_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
WINUSB_SETUP_PACKET SetupPacket,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
typedef BOOL (WINAPI *WinUsb_FlushPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_Free_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR AssociatedInterfaceIndex,
PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_GetCurrentAlternateSetting_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
PUCHAR AlternateSetting
);
typedef BOOL (WINAPI *WinUsb_GetDescriptor_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR DescriptorType,
UCHAR Index,
USHORT LanguageID,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred
);
typedef BOOL (WINAPI *WinUsb_GetOverlappedResult_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
LPOVERLAPPED lpOverlapped,
LPDWORD lpNumberOfBytesTransferred,
BOOL bWait
);
typedef BOOL (WINAPI *WinUsb_GetPipePolicy_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
ULONG PolicyType,
PULONG ValueLength,
PVOID Value
);
typedef BOOL (WINAPI *WinUsb_GetPowerPolicy_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
ULONG PolicyType,
PULONG ValueLength,
PVOID Value
);
typedef BOOL (WINAPI *WinUsb_Initialize_t)(
HANDLE DeviceHandle,
PWINUSB_INTERFACE_HANDLE InterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_QueryDeviceInformation_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
ULONG InformationType,
PULONG BufferLength,
PVOID Buffer
);
typedef BOOL (WINAPI *WinUsb_QueryInterfaceSettings_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR AlternateSettingNumber,
PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
);
typedef BOOL (WINAPI *WinUsb_QueryPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR AlternateInterfaceNumber,
UCHAR PipeIndex,
PWINUSB_PIPE_INFORMATION PipeInformation
);
typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
typedef BOOL (WINAPI *WinUsb_ResetPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID
);
typedef BOOL (WINAPI *WinUsb_SetCurrentAlternateSetting_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR AlternateSetting
);
typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
ULONG PolicyType,
ULONG ValueLength,
PVOID Value
);
typedef BOOL (WINAPI *WinUsb_SetPowerPolicy_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
ULONG PolicyType,
ULONG ValueLength,
PVOID Value
);
typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
PUCHAR Buffer,
ULONG BufferLength,
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle
);
/* /!\ These must match the ones from the official libusbk.h */
typedef enum _KUSB_FNID
{
KUSB_FNID_Init,
KUSB_FNID_Free,
KUSB_FNID_ClaimInterface,
KUSB_FNID_ReleaseInterface,
KUSB_FNID_SetAltInterface,
KUSB_FNID_GetAltInterface,
KUSB_FNID_GetDescriptor,
KUSB_FNID_ControlTransfer,
KUSB_FNID_SetPowerPolicy,
KUSB_FNID_GetPowerPolicy,
KUSB_FNID_SetConfiguration,
KUSB_FNID_GetConfiguration,
KUSB_FNID_ResetDevice,
KUSB_FNID_Initialize,
KUSB_FNID_SelectInterface,
KUSB_FNID_GetAssociatedInterface,
KUSB_FNID_Clone,
KUSB_FNID_QueryInterfaceSettings,
KUSB_FNID_QueryDeviceInformation,
KUSB_FNID_SetCurrentAlternateSetting,
KUSB_FNID_GetCurrentAlternateSetting,
KUSB_FNID_QueryPipe,
KUSB_FNID_SetPipePolicy,
KUSB_FNID_GetPipePolicy,
KUSB_FNID_ReadPipe,
KUSB_FNID_WritePipe,
KUSB_FNID_ResetPipe,
KUSB_FNID_AbortPipe,
KUSB_FNID_FlushPipe,
KUSB_FNID_IsoReadPipe,
KUSB_FNID_IsoWritePipe,
KUSB_FNID_GetCurrentFrameNumber,
KUSB_FNID_GetOverlappedResult,
KUSB_FNID_GetProperty,
KUSB_FNID_COUNT,
} KUSB_FNID;
typedef struct _KLIB_VERSION {
INT Major;
INT Minor;
INT Micro;
INT Nano;
} KLIB_VERSION;
typedef KLIB_VERSION* PKLIB_VERSION;
typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
PVOID* ProcAddress,
ULONG DriverID,
ULONG FunctionID
);
typedef VOID (WINAPI *LibK_GetVersion_t)(
PKLIB_VERSION Version
);
struct winusb_interface {
bool initialized;
WinUsb_AbortPipe_t AbortPipe;
WinUsb_ControlTransfer_t ControlTransfer;
WinUsb_FlushPipe_t FlushPipe;
WinUsb_Free_t Free;
WinUsb_GetAssociatedInterface_t GetAssociatedInterface;
WinUsb_GetCurrentAlternateSetting_t GetCurrentAlternateSetting;
WinUsb_GetDescriptor_t GetDescriptor;
WinUsb_GetOverlappedResult_t GetOverlappedResult;
WinUsb_GetPipePolicy_t GetPipePolicy;
WinUsb_GetPowerPolicy_t GetPowerPolicy;
WinUsb_Initialize_t Initialize;
WinUsb_QueryDeviceInformation_t QueryDeviceInformation;
WinUsb_QueryInterfaceSettings_t QueryInterfaceSettings;
WinUsb_QueryPipe_t QueryPipe;
WinUsb_ReadPipe_t ReadPipe;
WinUsb_ResetPipe_t ResetPipe;
WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting;
WinUsb_SetPipePolicy_t SetPipePolicy;
WinUsb_SetPowerPolicy_t SetPowerPolicy;
WinUsb_WritePipe_t WritePipe;
WinUsb_ResetDevice_t ResetDevice;
};
/* hid.dll interface */
#define HIDP_STATUS_SUCCESS 0x110000
typedef void* PHIDP_PREPARSED_DATA;
#pragma pack(1)
typedef struct {
ULONG Size;
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
#pragma pack()
typedef USHORT USAGE;
typedef struct {
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT NumberLinkCollectionNodes;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
} HIDP_CAPS, *PHIDP_CAPS;
typedef enum _HIDP_REPORT_TYPE {
HidP_Input,
HidP_Output,
HidP_Feature
} HIDP_REPORT_TYPE;
typedef struct _HIDP_VALUE_CAPS {
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USHORT BitField;
USHORT LinkCollection;
USAGE LinkUsage;
USAGE LinkUsagePage;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN HasNull;
UCHAR Reserved;
USHORT BitSize;
USHORT ReportCount;
USHORT Reserved2[5];
ULONG UnitsExp;
ULONG Units;
LONG LogicalMin, LogicalMax;
LONG PhysicalMin, PhysicalMax;
union {
struct {
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct {
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
} u;
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
DLL_DECLARE(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES));
DLL_DECLARE(WINAPI, VOID, HidD_GetHidGuid, (LPGUID));
DLL_DECLARE(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *));
DLL_DECLARE(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA));
DLL_DECLARE(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS));
DLL_DECLARE(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_FlushQueue, (HANDLE));
DLL_DECLARE(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA));

184
compat/libusb-1.0/libusb/strerror.c

@ -0,0 +1,184 @@ @@ -0,0 +1,184 @@
/*
* libusb strerror code
* Copyright © 2013 Hans de Goede <hdegoede@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include "libusb.h"
#include "libusbi.h"
#if defined(_MSC_VER)
#define strncasecmp _strnicmp
#endif
static size_t usbi_locale = 0;
/** \ingroup misc
* How to add a new \ref libusb_strerror() translation:
* <ol>
* <li> Download the latest \c strerror.c from:<br>
* https://raw.github.com/libusbx/libusbx/master/libusb/sterror.c </li>
* <li> Open the file in an UTF-8 capable editor </li>
* <li> Add the 2 letter <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a>
* code for your locale at the end of \c usbi_locale_supported[]<br>
* Eg. for Chinese, you would add "zh" so that:
* \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode
* becomes:
* \code... usbi_locale_supported[] = { "en", "nl", "fr", "zh" };\endcode </li>
* <li> Copy the <tt>{ / * English (en) * / ... }</tt> section and add it at the end of \c usbi_localized_errors<br>
* Eg. for Chinese, the last section of \c usbi_localized_errors could look like:
* \code
* }, { / * Chinese (zh) * /
* "Success",
* ...
* "Other error",
* }
* };\endcode </li>
* <li> Translate each of the English messages from the section you copied into your language </li>
* <li> Save the file (in UTF-8 format) and send it to \c libusbx-devel\@lists.sourceforge.net </li>
* </ol>
*/
static const char* usbi_locale_supported[] = { "en", "nl", "fr" };
static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = {
{ /* English (en) */
"Success",
"Input/Output Error",
"Invalid parameter",
"Access denied (insufficient permissions)",
"No such device (it may have been disconnected)",
"Entity not found",
"Resource busy",
"Operation timed out",
"Overflow",
"Pipe error",
"System call interrupted (perhaps due to signal)",
"Insufficient memory",
"Operation not supported or unimplemented on this platform",
"Other error",
}, { /* Dutch (nl) */
"Gelukt",
"Invoer-/uitvoerfout",
"Ongeldig argument",
"Toegang geweigerd (onvoldoende toegangsrechten)",
"Apparaat bestaat niet (verbinding met apparaat verbroken?)",
"Niet gevonden",
"Apparaat of hulpbron is bezig",
"Bewerking verlopen",
"Waarde is te groot",
"Gebroken pijp",
"Onderbroken systeemaanroep",
"Onvoldoende geheugen beschikbaar",
"Bewerking wordt niet ondersteund",
"Andere fout",
}, { /* French (fr) */
"Succès",
"Erreur d'entrée/sortie",
"Paramètre invalide",
"Accès refusé (permissions insuffisantes)",
"Périphérique introuvable (peut-être déconnecté)",
"Elément introuvable",
"Resource déjà occupée",
"Operation expirée",
"Débordement",
"Erreur de pipe",
"Appel système abandonné (peut-être à cause d’un signal)",
"Mémoire insuffisante",
"Opération non supportée or non implémentée sur cette plateforme",
"Autre erreur"
}
};
/** \ingroup misc
* Set the language, and only the language, not the encoding! used for
* translatable libusb messages.
*
* This takes a locale string in the default setlocale format: lang[-region]
* or lang[_country_region][.codeset]. Only the lang part of the string is
* used, and only 2 letter ISO 639-1 codes are accepted for it, such as "de".
* The optional region, country_region or codeset parts are ignored. This
* means that functions which return translatable strings will NOT honor the
* specified encoding.
* All strings returned are encoded as UTF-8 strings.
*
* If libusb_setlocale() is not called, all messages will be in English.
*
* The following functions return translatable strings: libusb_strerror().
* Note that the libusb log messages controlled through libusb_set_debug()
* are not translated, they are always in English.
*
* For POSIX UTF-8 environments if you want libusb to follow the standard
* locale settings, call libusb_setlocale(setlocale(LC_MESSAGES, NULL)),
* after your app has done its locale setup.
*
* \param locale locale-string in the form of lang[_country_region][.codeset]
* or lang[-region], where lang is a 2 letter ISO 639-1 code
* \returns LIBUSB_SUCCESS on success
* \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements
* \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported
* \returns a LIBUSB_ERROR code on other errors
*/
int API_EXPORTED libusb_setlocale(const char *locale)
{
size_t i;
if ( (locale == NULL) || (strlen(locale) < 2)
|| ((strlen(locale) > 2) && (locale[2] != '-') && (locale[2] != '_') && (locale[2] != '.')) )
return LIBUSB_ERROR_INVALID_PARAM;
for (i=0; i<ARRAYSIZE(usbi_locale_supported); i++) {
if (strncasecmp(usbi_locale_supported[i], locale, 2) == 0)
break;
}
if (i >= ARRAYSIZE(usbi_locale_supported)) {
return LIBUSB_ERROR_NOT_FOUND;
}
usbi_locale = i;
return LIBUSB_SUCCESS;
}
/** \ingroup misc
* Returns a constant string with a short description of the given error code,
* this description is intended for displaying to the end user and will be in
* the language set by libusb_setlocale().
*
* The returned string is encoded in UTF-8.
*
* The messages always start with a capital letter and end without any dot.
* The caller must not free() the returned string.
*
* \param errcode the error code whose description is desired
* \returns a short description of the error code in UTF-8 encoding
*/
DEFAULT_VISIBILITY const char* LIBUSB_CALL libusb_strerror(enum libusb_error errcode)
{
int errcode_index = -errcode;
if ((errcode_index < 0) || (errcode_index >= LIBUSB_ERROR_COUNT)) {
/* "Other Error", which should always be our last message, is returned */
errcode_index = LIBUSB_ERROR_COUNT - 1;
}
return usbi_localized_errors[usbi_locale][errcode_index];
}

79
compat/libusb-1.0/libusb/sync.c

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* Synchronous I/O functions for libusb
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Synchronous I/O functions for libusbx
* Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include "config.h"
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
@ -28,12 +28,12 @@ @@ -28,12 +28,12 @@
/**
* @defgroup syncio Synchronous device I/O
*
* This page documents libusb's synchronous (blocking) API for USB device I/O.
* This page documents libusbx's synchronous (blocking) API for USB device I/O.
* This interface is easy to use but has some limitations. More advanced users
* may wish to consider using the \ref asyncio "asynchronous I/O API" instead.
*/
static void LIBUSB_CALL ctrl_transfer_cb(struct libusb_transfer *transfer)
static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer)
{
int *completed = transfer->user_data;
*completed = 1;
@ -41,6 +41,24 @@ static void LIBUSB_CALL ctrl_transfer_cb(struct libusb_transfer *transfer) @@ -41,6 +41,24 @@ static void LIBUSB_CALL ctrl_transfer_cb(struct libusb_transfer *transfer)
/* caller interprets result and frees transfer */
}
static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer)
{
int r, *completed = transfer->user_data;
struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle);
while (!*completed) {
r = libusb_handle_events_completed(ctx, completed);
if (r < 0) {
if (r == LIBUSB_ERROR_INTERRUPTED)
continue;
usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying",
libusb_error_name(r));
libusb_cancel_transfer(transfer);
continue;
}
}
}
/** \ingroup syncio
* Perform a USB control transfer.
*
@ -81,7 +99,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, @@ -81,7 +99,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
if (!transfer)
return LIBUSB_ERROR_NO_MEM;
buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
if (!buffer) {
libusb_free_transfer(transfer);
return LIBUSB_ERROR_NO_MEM;
@ -93,7 +111,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, @@ -93,7 +111,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
libusb_fill_control_transfer(transfer, dev_handle, buffer,
ctrl_transfer_cb, &completed, timeout);
sync_transfer_cb, &completed, timeout);
transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER;
r = libusb_submit_transfer(transfer);
if (r < 0) {
@ -101,19 +119,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, @@ -101,19 +119,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
return r;
}
while (!completed) {
r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed);
if (r < 0) {
if (r == LIBUSB_ERROR_INTERRUPTED)
continue;
libusb_cancel_transfer(transfer);
while (!completed)
if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0)
break;
libusb_free_transfer(transfer);
return r;
}
}
sync_transfer_wait_for_completion(transfer);
if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
memcpy(data, libusb_control_transfer_get_data(transfer),
@ -149,14 +155,6 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, @@ -149,14 +155,6 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
return r;
}
static void LIBUSB_CALL bulk_transfer_cb(struct libusb_transfer *transfer)
{
int *completed = transfer->user_data;
*completed = 1;
usbi_dbg("actual_length=%d", transfer->actual_length);
/* caller interprets results and frees transfer */
}
static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *buffer, int length,
int *transferred, unsigned int timeout, unsigned char type)
@ -169,7 +167,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, @@ -169,7 +167,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
return LIBUSB_ERROR_NO_MEM;
libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
bulk_transfer_cb, &completed, timeout);
sync_transfer_cb, &completed, timeout);
transfer->type = type;
r = libusb_submit_transfer(transfer);
@ -178,19 +176,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, @@ -178,19 +176,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
return r;
}
while (!completed) {
r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed);
if (r < 0) {
if (r == LIBUSB_ERROR_INTERRUPTED)
continue;
libusb_cancel_transfer(transfer);
while (!completed)
if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0)
break;
libusb_free_transfer(transfer);
return r;
}
}
sync_transfer_wait_for_completion(transfer);
*transferred = transfer->actual_length;
switch (transfer->status) {
@ -236,9 +222,9 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, @@ -236,9 +222,9 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
* Not all of the data may have been written.
*
* Also check <tt>transferred</tt> when dealing with a timeout error code.
* libusb may have to split your transfer into a number of chunks to satisfy
* libusbx may have to split your transfer into a number of chunks to satisfy
* underlying O/S requirements, meaning that the timeout may expire after
* the first few chunks have completed. libusb is careful not to lose any data
* the first few chunks have completed. libusbx is careful not to lose any data
* that may have been transferred; do not assume that timeout conditions
* indicate a complete lack of I/O.
*
@ -284,9 +270,9 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, @@ -284,9 +270,9 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle,
* writes. Not all of the data may have been written.
*
* Also check <tt>transferred</tt> when dealing with a timeout error code.
* libusb may have to split your transfer into a number of chunks to satisfy
* libusbx may have to split your transfer into a number of chunks to satisfy
* underlying O/S requirements, meaning that the timeout may expire after
* the first few chunks have completed. libusb is careful not to lose any data
* the first few chunks have completed. libusbx is careful not to lose any data
* that may have been transferred; do not assume that timeout conditions
* indicate a complete lack of I/O.
*
@ -319,4 +305,3 @@ int API_EXPORTED libusb_interrupt_transfer( @@ -319,4 +305,3 @@ int API_EXPORTED libusb_interrupt_transfer(
return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
}

6
compat/libusb-1.0/libusb/version.h

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/* This file is parsed by m4 and windres and RC.EXE so please keep it simple. */
#include "version_nano.h"
#ifndef LIBUSB_MAJOR
#define LIBUSB_MAJOR 1
#endif
@ -6,13 +7,12 @@ @@ -6,13 +7,12 @@
#define LIBUSB_MINOR 0
#endif
#ifndef LIBUSB_MICRO
#define LIBUSB_MICRO 16
#define LIBUSB_MICRO 17
#endif
/* LIBUSB_NANO may be used for Windows internal versioning. 0 means unused. */
#ifndef LIBUSB_NANO
#define LIBUSB_NANO 0
#endif
/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */
#ifndef LIBUSB_RC
#define LIBUSB_RC "-rc10"
#define LIBUSB_RC ""
#endif

1
compat/libusb-1.0/libusb/version_nano.h

@ -0,0 +1 @@ @@ -0,0 +1 @@
#define LIBUSB_NANO 10830
Loading…
Cancel
Save