usb 2.1.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +3 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/usb/bindings.d.ts +4 -0
- package/dist/usb/device.js +5 -0
- package/dist/usb/device.js.map +1 -1
- package/libusb/.gitattributes +2 -6
- package/libusb/.private/appveyor_build.sh +22 -0
- package/libusb/.private/bm.sh +1 -1
- package/libusb/.private/ci-build.sh +67 -0
- package/libusb/.private/post-rewrite.sh +5 -1
- package/libusb/.private/pre-commit.sh +5 -1
- package/libusb/.private/wbs.txt +4 -19
- package/libusb/.travis.yml +32 -23
- package/libusb/AUTHORS +76 -3
- package/libusb/ChangeLog +41 -3
- package/libusb/INSTALL_WIN.txt +22 -44
- package/libusb/Makefile.am +32 -10
- package/libusb/{README.md → README} +2 -2
- package/libusb/README.git +3 -3
- package/libusb/Xcode/common.xcconfig +23 -19
- package/libusb/Xcode/config.h +25 -13
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +511 -109
- package/libusb/android/README +90 -54
- package/libusb/android/config.h +23 -43
- package/libusb/android/examples/unrooted_android.c +301 -0
- package/libusb/android/examples/unrooted_android.h +36 -0
- package/libusb/android/jni/Android.mk +1 -1
- package/libusb/android/jni/Application.mk +16 -0
- package/libusb/android/jni/examples.mk +63 -29
- package/libusb/android/jni/libusb.mk +14 -8
- package/libusb/android/jni/tests.mk +13 -24
- package/libusb/appveyor.yml +69 -30
- package/libusb/autogen.sh +5 -3
- package/libusb/bootstrap.sh +6 -2
- package/libusb/configure.ac +302 -228
- package/libusb/doc/Makefile.in +22 -0
- package/libusb/doc/doxygen.cfg.in +460 -223
- package/libusb/examples/Makefile.am +6 -13
- package/libusb/examples/dpfp.c +276 -73
- package/libusb/examples/ezusb.c +18 -8
- package/libusb/examples/ezusb.h +6 -17
- package/libusb/examples/fxload.c +4 -5
- package/libusb/examples/hotplugtest.c +1 -1
- package/libusb/examples/sam3u_benchmark.c +59 -24
- package/libusb/examples/testlibusb.c +138 -104
- package/libusb/examples/xusb.c +26 -22
- package/libusb/libusb/Makefile.am +57 -70
- package/libusb/libusb/Makefile.am.extra +26 -0
- package/libusb/libusb/core.c +420 -423
- package/libusb/libusb/descriptor.c +365 -419
- package/libusb/libusb/hotplug.c +197 -104
- package/libusb/libusb/io.c +491 -528
- package/libusb/libusb/libusb-1.0.def +7 -3
- package/libusb/libusb/libusb-1.0.rc +1 -9
- package/libusb/libusb/libusb.h +295 -226
- package/libusb/libusb/libusbi.h +587 -314
- package/libusb/libusb/os/darwin_usb.c +634 -317
- package/libusb/libusb/os/darwin_usb.h +39 -15
- package/libusb/libusb/os/events_posix.c +300 -0
- package/libusb/libusb/os/events_posix.h +59 -0
- package/libusb/libusb/os/events_windows.c +214 -0
- package/libusb/{msvc/missing.h → libusb/os/events_windows.h} +25 -11
- package/libusb/libusb/os/haiku_pollfs.cpp +14 -9
- package/libusb/libusb/os/haiku_usb.h +12 -12
- package/libusb/libusb/os/haiku_usb_backend.cpp +36 -37
- package/libusb/libusb/os/haiku_usb_raw.cpp +80 -116
- package/libusb/libusb/os/linux_netlink.c +55 -63
- package/libusb/libusb/os/linux_udev.c +61 -69
- package/libusb/libusb/os/linux_usbfs.c +926 -1015
- package/libusb/libusb/os/linux_usbfs.h +74 -57
- package/libusb/libusb/os/netbsd_usb.c +103 -168
- package/libusb/libusb/os/null_usb.c +111 -0
- package/libusb/libusb/os/openbsd_usb.c +71 -120
- package/libusb/libusb/os/sunos_usb.c +289 -375
- package/libusb/libusb/os/sunos_usb.h +0 -1
- package/libusb/libusb/os/threads_posix.c +81 -32
- package/libusb/libusb/os/threads_posix.h +19 -23
- package/libusb/libusb/os/threads_windows.c +9 -95
- package/libusb/libusb/os/threads_windows.h +33 -31
- package/libusb/libusb/os/windows_common.c +904 -0
- package/libusb/libusb/os/windows_common.h +329 -42
- package/libusb/libusb/os/windows_usbdk.c +161 -267
- package/libusb/libusb/os/windows_usbdk.h +5 -2
- package/libusb/libusb/os/windows_winusb.c +1326 -1190
- package/libusb/libusb/os/windows_winusb.h +167 -167
- package/libusb/libusb/strerror.c +20 -30
- package/libusb/libusb/sync.c +20 -21
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/msvc/.gitattributes +3 -0
- package/libusb/msvc/config.h +27 -20
- package/libusb/msvc/{hotplugtest_2012.vcxproj → dpfp_2013.vcxproj} +14 -10
- package/libusb/msvc/dpfp_2013.vcxproj.filters +26 -0
- package/libusb/msvc/{listdevs_2010.vcxproj → dpfp_2015.vcxproj} +14 -9
- package/libusb/msvc/dpfp_2015.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_2017.vcxproj +106 -0
- package/libusb/msvc/dpfp_2017.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_2019.vcxproj +106 -0
- package/libusb/msvc/dpfp_2019.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_threaded_2013.vcxproj +87 -0
- package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_threaded_2015.vcxproj +87 -0
- package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_threaded_2017.vcxproj +106 -0
- package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +26 -0
- package/libusb/msvc/{fxload_2012.vcxproj → dpfp_threaded_2019.vcxproj} +32 -17
- package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +26 -0
- package/libusb/msvc/fxload_2013.vcxproj +6 -3
- package/libusb/msvc/fxload_2013.vcxproj.filters +35 -0
- package/libusb/msvc/fxload_2015.vcxproj +6 -3
- package/libusb/msvc/fxload_2015.vcxproj.filters +35 -0
- package/libusb/msvc/fxload_2017.vcxproj +6 -7
- package/libusb/msvc/fxload_2017.vcxproj.filters +35 -0
- package/libusb/msvc/{fxload_2010.vcxproj → fxload_2019.vcxproj} +29 -6
- package/libusb/msvc/fxload_2019.vcxproj.filters +35 -0
- package/libusb/{examples → msvc}/getopt/getopt.c +0 -0
- package/libusb/{examples → msvc}/getopt/getopt.h +0 -0
- package/libusb/{examples → msvc}/getopt/getopt1.c +0 -0
- package/libusb/msvc/getopt_2013.vcxproj +4 -5
- package/libusb/msvc/getopt_2013.vcxproj.filters +26 -0
- package/libusb/msvc/getopt_2015.vcxproj +4 -4
- package/libusb/msvc/getopt_2015.vcxproj.filters +26 -0
- package/libusb/msvc/getopt_2017.vcxproj +4 -10
- package/libusb/msvc/getopt_2017.vcxproj.filters +26 -0
- package/libusb/msvc/{getopt_2012.vcxproj → getopt_2019.vcxproj} +25 -6
- package/libusb/msvc/getopt_2019.vcxproj.filters +26 -0
- package/libusb/msvc/hotplugtest_2013.vcxproj +6 -3
- package/libusb/msvc/hotplugtest_2013.vcxproj.filters +23 -0
- package/libusb/msvc/hotplugtest_2015.vcxproj +6 -3
- package/libusb/msvc/hotplugtest_2015.vcxproj.filters +23 -0
- package/libusb/msvc/hotplugtest_2017.vcxproj +6 -7
- package/libusb/msvc/hotplugtest_2017.vcxproj.filters +23 -0
- package/libusb/msvc/hotplugtest_2019.vcxproj +105 -0
- package/libusb/msvc/hotplugtest_2019.vcxproj.filters +23 -0
- package/libusb/msvc/libusb_2013.sln +50 -20
- package/libusb/msvc/libusb_2015.sln +51 -21
- package/libusb/msvc/libusb_2017.sln +90 -36
- package/libusb/msvc/libusb_2019.sln +240 -0
- package/libusb/msvc/libusb_dll_2013.vcxproj +6 -9
- package/libusb/msvc/libusb_dll_2013.vcxproj.filters +94 -0
- package/libusb/msvc/libusb_dll_2015.vcxproj +6 -8
- package/libusb/msvc/libusb_dll_2015.vcxproj.filters +94 -0
- package/libusb/msvc/libusb_dll_2017.vcxproj +6 -16
- package/libusb/msvc/libusb_dll_2017.vcxproj.filters +94 -0
- package/libusb/msvc/{libusb_dll_2010.vcxproj → libusb_dll_2019.vcxproj} +27 -9
- package/libusb/msvc/libusb_dll_2019.vcxproj.filters +94 -0
- package/libusb/msvc/libusb_static_2013.vcxproj +5 -9
- package/libusb/msvc/libusb_static_2013.vcxproj.filters +80 -0
- package/libusb/msvc/libusb_static_2015.vcxproj +5 -8
- package/libusb/msvc/libusb_static_2015.vcxproj.filters +80 -0
- package/libusb/msvc/libusb_static_2017.vcxproj +5 -8
- package/libusb/msvc/libusb_static_2017.vcxproj.filters +80 -0
- package/libusb/msvc/{libusb_static_2010.vcxproj → libusb_static_2019.vcxproj} +26 -9
- package/libusb/msvc/libusb_static_2019.vcxproj.filters +80 -0
- package/libusb/msvc/listdevs_2013.vcxproj +6 -3
- package/libusb/msvc/listdevs_2013.vcxproj.filters +23 -0
- package/libusb/msvc/listdevs_2015.vcxproj +6 -3
- package/libusb/msvc/listdevs_2015.vcxproj.filters +23 -0
- package/libusb/msvc/listdevs_2017.vcxproj +6 -7
- package/libusb/msvc/listdevs_2017.vcxproj.filters +23 -0
- package/libusb/msvc/listdevs_2019.vcxproj +105 -0
- package/libusb/msvc/listdevs_2019.vcxproj.filters +23 -0
- package/libusb/msvc/{listdevs_2012.vcxproj → sam3u_benchmark_2013.vcxproj} +13 -9
- package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +26 -0
- package/libusb/msvc/{hotplugtest_2010.vcxproj → sam3u_benchmark_2015.vcxproj} +13 -8
- package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +26 -0
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj +106 -0
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +26 -0
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj +106 -0
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +26 -0
- package/libusb/msvc/stress_2013.vcxproj +4 -2
- package/libusb/msvc/stress_2013.vcxproj.filters +32 -0
- package/libusb/msvc/stress_2015.vcxproj +4 -2
- package/libusb/msvc/stress_2015.vcxproj.filters +32 -0
- package/libusb/msvc/stress_2017.vcxproj +4 -6
- package/libusb/msvc/stress_2017.vcxproj.filters +32 -0
- package/libusb/msvc/{stress_2010.vcxproj → stress_2019.vcxproj} +26 -4
- package/libusb/msvc/stress_2019.vcxproj.filters +32 -0
- package/libusb/msvc/testlibusb_2013.vcxproj +6 -3
- package/libusb/msvc/testlibusb_2013.vcxproj.filters +23 -0
- package/libusb/msvc/testlibusb_2015.vcxproj +6 -3
- package/libusb/msvc/testlibusb_2015.vcxproj.filters +23 -0
- package/libusb/msvc/testlibusb_2017.vcxproj +6 -7
- package/libusb/msvc/testlibusb_2017.vcxproj.filters +23 -0
- package/libusb/msvc/{testlibusb_2010.vcxproj → testlibusb_2019.vcxproj} +28 -5
- package/libusb/msvc/testlibusb_2019.vcxproj.filters +23 -0
- package/libusb/msvc/xusb_2013.vcxproj +6 -3
- package/libusb/msvc/xusb_2013.vcxproj.filters +23 -0
- package/libusb/msvc/xusb_2015.vcxproj +6 -3
- package/libusb/msvc/xusb_2015.vcxproj.filters +23 -0
- package/libusb/msvc/xusb_2017.vcxproj +6 -7
- package/libusb/msvc/xusb_2017.vcxproj.filters +23 -0
- package/libusb/msvc/{xusb_2010.vcxproj → xusb_2019.vcxproj} +28 -5
- package/libusb/msvc/xusb_2019.vcxproj.filters +23 -0
- package/libusb/tests/Makefile.am +1 -0
- package/libusb/tests/libusb_testlib.h +12 -43
- package/libusb/tests/stress.c +59 -50
- package/libusb/tests/testlib.c +78 -171
- package/libusb.gypi +10 -11
- package/package.json +1 -1
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/device.cc +12 -7
- package/src/node_usb.cc +10 -0
- package/test/usb.coffee +6 -0
- package/tsc/index.ts +2 -0
- package/tsc/usb/bindings.ts +5 -0
- package/tsc/usb/device.ts +6 -0
- package/libusb/.private/bd.cmd +0 -89
- package/libusb/.private/bwince.cmd +0 -57
- package/libusb/.private/wbs_wince.txt +0 -42
- package/libusb/Brewfile +0 -4
- package/libusb/appveyor_cygwin.bat +0 -11
- package/libusb/appveyor_minGW.bat +0 -19
- package/libusb/doc/Makefile.am +0 -9
- package/libusb/examples/dpfp_threaded.c +0 -557
- package/libusb/libusb/hotplug.h +0 -99
- package/libusb/libusb/os/poll_posix.c +0 -84
- package/libusb/libusb/os/poll_posix.h +0 -14
- package/libusb/libusb/os/poll_windows.c +0 -447
- package/libusb/libusb/os/poll_windows.h +0 -98
- package/libusb/libusb/os/wince_usb.c +0 -888
- package/libusb/libusb/os/wince_usb.h +0 -126
- package/libusb/libusb/os/windows_nt_common.c +0 -1010
- package/libusb/libusb/os/windows_nt_common.h +0 -110
- package/libusb/libusb/os/windows_nt_shared_types.h +0 -147
- package/libusb/msvc/appveyor.bat +0 -27
- package/libusb/msvc/ddk_build.cmd +0 -219
- package/libusb/msvc/errno.h +0 -102
- package/libusb/msvc/fxload_sources +0 -23
- package/libusb/msvc/getopt_2005.vcproj +0 -288
- package/libusb/msvc/getopt_2010.vcxproj +0 -72
- package/libusb/msvc/getopt_sources +0 -24
- package/libusb/msvc/hotplugtest_sources +0 -20
- package/libusb/msvc/inttypes.h +0 -295
- package/libusb/msvc/libusb.dsw +0 -71
- package/libusb/msvc/libusb_2005.sln +0 -95
- package/libusb/msvc/libusb_2010.sln +0 -105
- package/libusb/msvc/libusb_2012.sln +0 -105
- package/libusb/msvc/libusb_dll.dsp +0 -194
- package/libusb/msvc/libusb_dll_2005.vcproj +0 -464
- package/libusb/msvc/libusb_dll_2012.vcxproj +0 -107
- package/libusb/msvc/libusb_dll_wince.vcproj +0 -1251
- package/libusb/msvc/libusb_sources +0 -43
- package/libusb/msvc/libusb_static.dsp +0 -174
- package/libusb/msvc/libusb_static_2005.vcproj +0 -390
- package/libusb/msvc/libusb_static_2012.vcxproj +0 -98
- package/libusb/msvc/libusb_static_wince.vcproj +0 -1179
- package/libusb/msvc/libusb_wince.sln +0 -246
- package/libusb/msvc/listdevs.dsp +0 -103
- package/libusb/msvc/listdevs_2005.vcproj +0 -360
- package/libusb/msvc/listdevs_sources +0 -20
- package/libusb/msvc/listdevs_wince.vcproj +0 -1120
- package/libusb/msvc/missing.c +0 -80
- package/libusb/msvc/stdint.h +0 -256
- package/libusb/msvc/stress_2005.vcproj +0 -390
- package/libusb/msvc/stress_2012.vcxproj +0 -87
- package/libusb/msvc/stress_sources +0 -21
- package/libusb/msvc/stress_wince.vcproj +0 -1128
- package/libusb/msvc/testlibusb_2012.vcxproj +0 -83
- package/libusb/msvc/testlibusb_sources +0 -20
- package/libusb/msvc/xusb.dsp +0 -102
- package/libusb/msvc/xusb_2005.vcproj +0 -344
- package/libusb/msvc/xusb_2012.vcxproj +0 -83
- package/libusb/msvc/xusb_sources +0 -20
- package/libusb/msvc/xusb_wince.vcproj +0 -1120
- package/libusb/travis-autogen.sh +0 -39
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* -*- Mode: C; indent-tabs-mode:nil -*- */
|
|
2
2
|
/*
|
|
3
3
|
* darwin backend for libusb 1.0
|
|
4
|
-
* Copyright © 2008-
|
|
5
|
-
* Copyright © 2019
|
|
4
|
+
* Copyright © 2008-2021 Nathan Hjelm <hjelmn@cs.unm.edu>
|
|
5
|
+
* Copyright © 2019-2021 Google LLC. All rights reserved.
|
|
6
6
|
*
|
|
7
7
|
* This library is free software; you can redistribute it and/or
|
|
8
8
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -19,11 +19,10 @@
|
|
|
19
19
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
#include
|
|
22
|
+
#include <config.h>
|
|
23
23
|
#include <assert.h>
|
|
24
24
|
#include <time.h>
|
|
25
25
|
#include <ctype.h>
|
|
26
|
-
#include <errno.h>
|
|
27
26
|
#include <pthread.h>
|
|
28
27
|
#include <stdio.h>
|
|
29
28
|
#include <stdlib.h>
|
|
@@ -42,61 +41,50 @@
|
|
|
42
41
|
* function. Its use is also conditionalized to only older deployment targets. */
|
|
43
42
|
#define OBJC_SILENCE_GC_DEPRECATIONS 1
|
|
44
43
|
|
|
44
|
+
/* Default timeout to 10s for reenumerate. This is needed because USBDeviceReEnumerate
|
|
45
|
+
* does not return error status on macOS. */
|
|
46
|
+
#define DARWIN_REENUMERATE_TIMEOUT_US 10000000
|
|
47
|
+
|
|
45
48
|
#include <AvailabilityMacros.h>
|
|
46
49
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
|
|
47
50
|
#include <objc/objc-auto.h>
|
|
48
51
|
#endif
|
|
49
52
|
|
|
50
|
-
#
|
|
51
|
-
/* Apple deprecated the darwin atomics in 10.12 in favor of C11 atomics */
|
|
52
|
-
#include <stdatomic.h>
|
|
53
|
-
#define libusb_darwin_atomic_fetch_add(x, y) atomic_fetch_add(x, y)
|
|
54
|
-
|
|
55
|
-
_Atomic int32_t initCount = ATOMIC_VAR_INIT(0);
|
|
56
|
-
#else
|
|
57
|
-
/* use darwin atomics if the target is older than 10.12 */
|
|
58
|
-
#include <libkern/OSAtomic.h>
|
|
59
|
-
|
|
60
|
-
/* OSAtomicAdd32Barrier returns the new value */
|
|
61
|
-
#define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y)
|
|
62
|
-
|
|
63
|
-
static volatile int32_t initCount = 0;
|
|
64
|
-
|
|
65
|
-
#endif
|
|
53
|
+
#include "darwin_usb.h"
|
|
66
54
|
|
|
67
|
-
|
|
68
|
-
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
|
69
|
-
#define OSX_USE_CLOCK_GETTIME 1
|
|
70
|
-
#else
|
|
71
|
-
#define OSX_USE_CLOCK_GETTIME 0
|
|
72
|
-
#endif
|
|
55
|
+
static int init_count = 0;
|
|
73
56
|
|
|
74
|
-
|
|
57
|
+
/* Both kIOMasterPortDefault or kIOMainPortDefault are synonyms for 0. */
|
|
58
|
+
static const mach_port_t darwin_default_master_port = 0;
|
|
75
59
|
|
|
76
60
|
/* async event thread */
|
|
77
61
|
static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
78
62
|
static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
|
|
79
63
|
|
|
80
|
-
#if !
|
|
64
|
+
#if !defined(HAVE_CLOCK_GETTIME)
|
|
81
65
|
static clock_serv_t clock_realtime;
|
|
82
66
|
static clock_serv_t clock_monotonic;
|
|
83
67
|
#endif
|
|
84
68
|
|
|
69
|
+
#define LIBUSB_DARWIN_STARTUP_FAILURE ((CFRunLoopRef) -1)
|
|
70
|
+
|
|
85
71
|
static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
|
|
86
72
|
static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
|
|
87
73
|
|
|
88
74
|
static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
89
|
-
static struct list_head darwin_cached_devices
|
|
90
|
-
static const char *darwin_device_class =
|
|
75
|
+
static struct list_head darwin_cached_devices;
|
|
76
|
+
static const char *darwin_device_class = "IOUSBDevice";
|
|
91
77
|
|
|
92
|
-
#define DARWIN_CACHED_DEVICE(a) ((
|
|
78
|
+
#define DARWIN_CACHED_DEVICE(a) (((struct darwin_device_priv *)usbi_get_device_priv((a)))->dev)
|
|
93
79
|
|
|
94
80
|
/* async event thread */
|
|
95
81
|
static pthread_t libusb_darwin_at;
|
|
96
82
|
|
|
97
|
-
static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index,
|
|
98
|
-
static int darwin_claim_interface(struct libusb_device_handle *dev_handle,
|
|
99
|
-
static int darwin_release_interface(struct libusb_device_handle *dev_handle,
|
|
83
|
+
static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len);
|
|
84
|
+
static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
|
|
85
|
+
static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
|
|
86
|
+
static int darwin_reenumerate_device(struct libusb_device_handle *dev_handle, bool capture);
|
|
87
|
+
static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint);
|
|
100
88
|
static int darwin_reset_device(struct libusb_device_handle *dev_handle);
|
|
101
89
|
static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0);
|
|
102
90
|
|
|
@@ -104,7 +92,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx);
|
|
|
104
92
|
static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
|
|
105
93
|
UInt64 old_session_id);
|
|
106
94
|
|
|
107
|
-
static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
|
|
95
|
+
static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out,
|
|
108
96
|
UInt64 *old_session_id);
|
|
109
97
|
|
|
110
98
|
#if defined(ENABLE_LOGGING)
|
|
@@ -122,6 +110,9 @@ static const char *darwin_error_str (IOReturn result) {
|
|
|
122
110
|
case kIOReturnExclusiveAccess:
|
|
123
111
|
return "another process has device opened for exclusive access";
|
|
124
112
|
case kIOUSBPipeStalled:
|
|
113
|
+
#if defined(kUSBHostReturnPipeStalled)
|
|
114
|
+
case kUSBHostReturnPipeStalled:
|
|
115
|
+
#endif
|
|
125
116
|
return "pipe is stalled";
|
|
126
117
|
case kIOReturnError:
|
|
127
118
|
return "could not establish a connection to the Darwin kernel";
|
|
@@ -141,6 +132,8 @@ static const char *darwin_error_str (IOReturn result) {
|
|
|
141
132
|
return "out of resources";
|
|
142
133
|
case kIOUSBHighSpeedSplitError:
|
|
143
134
|
return "high speed split error";
|
|
135
|
+
case kIOUSBUnknownPipeErr:
|
|
136
|
+
return "pipe ref not recognized";
|
|
144
137
|
default:
|
|
145
138
|
snprintf(string_buffer, sizeof(string_buffer), "unknown error (0x%x)", result);
|
|
146
139
|
return string_buffer;
|
|
@@ -159,11 +152,16 @@ static enum libusb_error darwin_to_libusb (IOReturn result) {
|
|
|
159
152
|
case kIOReturnExclusiveAccess:
|
|
160
153
|
return LIBUSB_ERROR_ACCESS;
|
|
161
154
|
case kIOUSBPipeStalled:
|
|
155
|
+
#if defined(kUSBHostReturnPipeStalled)
|
|
156
|
+
case kUSBHostReturnPipeStalled:
|
|
157
|
+
#endif
|
|
162
158
|
return LIBUSB_ERROR_PIPE;
|
|
163
159
|
case kIOReturnBadArgument:
|
|
164
160
|
return LIBUSB_ERROR_INVALID_PARAM;
|
|
165
161
|
case kIOUSBTransactionTimeout:
|
|
166
162
|
return LIBUSB_ERROR_TIMEOUT;
|
|
163
|
+
case kIOUSBUnknownPipeErr:
|
|
164
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
167
165
|
case kIOReturnNotResponding:
|
|
168
166
|
case kIOReturnAborted:
|
|
169
167
|
case kIOReturnError:
|
|
@@ -184,6 +182,7 @@ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev)
|
|
|
184
182
|
(*(cached_dev->device))->Release(cached_dev->device);
|
|
185
183
|
cached_dev->device = NULL;
|
|
186
184
|
}
|
|
185
|
+
IOObjectRelease (cached_dev->service);
|
|
187
186
|
free (cached_dev);
|
|
188
187
|
}
|
|
189
188
|
}
|
|
@@ -193,14 +192,16 @@ static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) {
|
|
|
193
192
|
}
|
|
194
193
|
|
|
195
194
|
static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp, struct darwin_interface **interface_out) {
|
|
196
|
-
struct darwin_device_handle_priv *priv = (
|
|
195
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
197
196
|
|
|
198
197
|
/* current interface */
|
|
199
198
|
struct darwin_interface *cInterface;
|
|
200
199
|
|
|
201
200
|
uint8_t i, iface;
|
|
202
201
|
|
|
203
|
-
|
|
202
|
+
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
|
203
|
+
|
|
204
|
+
usbi_dbg (ctx, "converting ep address 0x%02x to pipeRef and interface", ep);
|
|
204
205
|
|
|
205
206
|
for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) {
|
|
206
207
|
cInterface = &priv->interfaces[iface];
|
|
@@ -216,7 +217,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
216
217
|
if (interface_out)
|
|
217
218
|
*interface_out = cInterface;
|
|
218
219
|
|
|
219
|
-
usbi_dbg ("pipe %d on interface %d matches", *pipep, iface);
|
|
220
|
+
usbi_dbg (ctx, "pipe %d on interface %d matches", *pipep, iface);
|
|
220
221
|
return LIBUSB_SUCCESS;
|
|
221
222
|
}
|
|
222
223
|
}
|
|
@@ -257,7 +258,7 @@ static IOReturn usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32
|
|
|
257
258
|
CFRelease (locationCF);
|
|
258
259
|
}
|
|
259
260
|
|
|
260
|
-
return IOServiceGetMatchingServices(
|
|
261
|
+
return IOServiceGetMatchingServices(darwin_default_master_port, matchingDict, deviceIterator);
|
|
261
262
|
}
|
|
262
263
|
|
|
263
264
|
/* Returns 1 on success, 0 on failure. */
|
|
@@ -298,7 +299,7 @@ static bool get_ioregistry_value_data (io_service_t service, CFStringRef propert
|
|
|
298
299
|
return success;
|
|
299
300
|
}
|
|
300
301
|
|
|
301
|
-
static usb_device_t **darwin_device_from_service (io_service_t service)
|
|
302
|
+
static usb_device_t **darwin_device_from_service (struct libusb_context *ctx, io_service_t service)
|
|
302
303
|
{
|
|
303
304
|
io_cf_plugin_ref_t *plugInInterface = NULL;
|
|
304
305
|
usb_device_t **device;
|
|
@@ -317,14 +318,14 @@ static usb_device_t **darwin_device_from_service (io_service_t service)
|
|
|
317
318
|
break;
|
|
318
319
|
}
|
|
319
320
|
|
|
320
|
-
usbi_dbg ("set up plugin for service retry: %s", darwin_error_str (kresult));
|
|
321
|
+
usbi_dbg (ctx, "set up plugin for service retry: %s", darwin_error_str (kresult));
|
|
321
322
|
|
|
322
323
|
/* sleep for a little while before trying again */
|
|
323
324
|
nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
|
|
324
325
|
}
|
|
325
326
|
|
|
326
327
|
if (kIOReturnSuccess != kresult || !plugInInterface) {
|
|
327
|
-
usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (kresult));
|
|
328
|
+
usbi_dbg (ctx, "could not set up plugin for service: %s", darwin_error_str (kresult));
|
|
328
329
|
return NULL;
|
|
329
330
|
}
|
|
330
331
|
|
|
@@ -347,18 +348,18 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
|
|
|
347
348
|
usbi_mutex_lock(&active_contexts_lock);
|
|
348
349
|
|
|
349
350
|
while ((service = IOIteratorNext(add_devices))) {
|
|
350
|
-
ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
|
|
351
|
+
ret = darwin_get_cached_device (NULL, service, &cached_device, &old_session_id);
|
|
351
352
|
if (ret < 0 || !cached_device->can_enumerate) {
|
|
352
353
|
continue;
|
|
353
354
|
}
|
|
354
355
|
|
|
355
356
|
/* add this device to each active context's device list */
|
|
356
|
-
|
|
357
|
+
for_each_context(ctx) {
|
|
357
358
|
process_new_device (ctx, cached_device, old_session_id);
|
|
358
359
|
}
|
|
359
360
|
|
|
360
361
|
if (cached_device->in_reenumerate) {
|
|
361
|
-
usbi_dbg ("cached device in reset state. reset complete...");
|
|
362
|
+
usbi_dbg (NULL, "cached device in reset state. reset complete...");
|
|
362
363
|
cached_device->in_reenumerate = false;
|
|
363
364
|
}
|
|
364
365
|
|
|
@@ -375,7 +376,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
375
376
|
struct darwin_cached_device *old_device;
|
|
376
377
|
|
|
377
378
|
io_service_t device;
|
|
378
|
-
UInt64 session;
|
|
379
|
+
UInt64 session, locationID;
|
|
379
380
|
int ret;
|
|
380
381
|
|
|
381
382
|
usbi_mutex_lock(&active_contexts_lock);
|
|
@@ -385,6 +386,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
385
386
|
|
|
386
387
|
/* get the location from the i/o registry */
|
|
387
388
|
ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
|
|
389
|
+
(void) get_ioregistry_value_number (device, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
|
|
388
390
|
IOObjectRelease (device);
|
|
389
391
|
if (!ret)
|
|
390
392
|
continue;
|
|
@@ -397,7 +399,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
397
399
|
if (old_device->in_reenumerate) {
|
|
398
400
|
/* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
|
|
399
401
|
* will deref if needed. */
|
|
400
|
-
usbi_dbg ("detected device
|
|
402
|
+
usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64 ", locationID: 0x%" PRIx64,
|
|
403
|
+
session, locationID);
|
|
401
404
|
|
|
402
405
|
/* the device object is no longer usable so go ahead and release it */
|
|
403
406
|
if (old_device->device) {
|
|
@@ -419,8 +422,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
419
422
|
continue;
|
|
420
423
|
}
|
|
421
424
|
|
|
422
|
-
|
|
423
|
-
usbi_dbg ("notifying context %p of device disconnect", ctx);
|
|
425
|
+
for_each_context(ctx) {
|
|
426
|
+
usbi_dbg (ctx, "notifying context %p of device disconnect", ctx);
|
|
424
427
|
|
|
425
428
|
dev = usbi_get_device_by_session_id(ctx, (unsigned long) session);
|
|
426
429
|
if (dev) {
|
|
@@ -443,7 +446,7 @@ static void darwin_hotplug_poll (void)
|
|
|
443
446
|
/* since a kernel thread may notify the IOIterators used for
|
|
444
447
|
* hotplug notification we can't just clear the iterators.
|
|
445
448
|
* instead just wait until all IOService providers are quiet */
|
|
446
|
-
(void) IOKitWaitQuiet (
|
|
449
|
+
(void) IOKitWaitQuiet (darwin_default_master_port, &timeout);
|
|
447
450
|
}
|
|
448
451
|
|
|
449
452
|
static void darwin_clear_iterator (io_iterator_t iter) {
|
|
@@ -453,10 +456,20 @@ static void darwin_clear_iterator (io_iterator_t iter) {
|
|
|
453
456
|
IOObjectRelease (device);
|
|
454
457
|
}
|
|
455
458
|
|
|
459
|
+
static void darwin_fail_startup(void) {
|
|
460
|
+
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
461
|
+
libusb_darwin_acfl = LIBUSB_DARWIN_STARTUP_FAILURE;
|
|
462
|
+
pthread_cond_signal (&libusb_darwin_at_cond);
|
|
463
|
+
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
464
|
+
pthread_exit (NULL);
|
|
465
|
+
}
|
|
466
|
+
|
|
456
467
|
static void *darwin_event_thread_main (void *arg0) {
|
|
457
468
|
IOReturn kresult;
|
|
458
469
|
struct libusb_context *ctx = (struct libusb_context *)arg0;
|
|
459
470
|
CFRunLoopRef runloop;
|
|
471
|
+
CFRunLoopSourceRef libusb_shutdown_cfsource;
|
|
472
|
+
CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
|
|
460
473
|
|
|
461
474
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
462
475
|
/* Set this thread's name, so it can be seen in the debugger
|
|
@@ -475,13 +488,12 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
475
488
|
#endif
|
|
476
489
|
|
|
477
490
|
/* hotplug (device arrival/removal) sources */
|
|
478
|
-
CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
|
|
479
491
|
CFRunLoopSourceRef libusb_notification_cfsource;
|
|
480
492
|
io_notification_port_t libusb_notification_port;
|
|
481
493
|
io_iterator_t libusb_rem_device_iterator;
|
|
482
494
|
io_iterator_t libusb_add_device_iterator;
|
|
483
495
|
|
|
484
|
-
usbi_dbg ("creating hotplug event source");
|
|
496
|
+
usbi_dbg (ctx, "creating hotplug event source");
|
|
485
497
|
|
|
486
498
|
runloop = CFRunLoopGetCurrent ();
|
|
487
499
|
CFRetain (runloop);
|
|
@@ -490,11 +502,11 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
490
502
|
memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
|
|
491
503
|
libusb_shutdown_cfsourcectx.info = runloop;
|
|
492
504
|
libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
|
|
493
|
-
|
|
494
|
-
CFRunLoopAddSource(runloop,
|
|
505
|
+
libusb_shutdown_cfsource = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
|
|
506
|
+
CFRunLoopAddSource(runloop, libusb_shutdown_cfsource, kCFRunLoopDefaultMode);
|
|
495
507
|
|
|
496
508
|
/* add the notification port to the run loop */
|
|
497
|
-
libusb_notification_port = IONotificationPortCreate (
|
|
509
|
+
libusb_notification_port = IONotificationPortCreate (darwin_default_master_port);
|
|
498
510
|
libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port);
|
|
499
511
|
CFRunLoopAddSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
|
|
500
512
|
|
|
@@ -506,8 +518,9 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
506
518
|
|
|
507
519
|
if (kresult != kIOReturnSuccess) {
|
|
508
520
|
usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
|
|
509
|
-
|
|
510
|
-
|
|
521
|
+
CFRelease (libusb_shutdown_cfsource);
|
|
522
|
+
CFRelease (runloop);
|
|
523
|
+
darwin_fail_startup ();
|
|
511
524
|
}
|
|
512
525
|
|
|
513
526
|
/* create notifications for attached devices */
|
|
@@ -518,32 +531,41 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
518
531
|
|
|
519
532
|
if (kresult != kIOReturnSuccess) {
|
|
520
533
|
usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
|
|
521
|
-
|
|
522
|
-
|
|
534
|
+
CFRelease (libusb_shutdown_cfsource);
|
|
535
|
+
CFRelease (runloop);
|
|
536
|
+
darwin_fail_startup ();
|
|
523
537
|
}
|
|
524
538
|
|
|
525
539
|
/* arm notifiers */
|
|
526
540
|
darwin_clear_iterator (libusb_rem_device_iterator);
|
|
527
541
|
darwin_clear_iterator (libusb_add_device_iterator);
|
|
528
542
|
|
|
529
|
-
usbi_dbg ("darwin event thread ready to receive events");
|
|
543
|
+
usbi_dbg (ctx, "darwin event thread ready to receive events");
|
|
530
544
|
|
|
531
545
|
/* signal the main thread that the hotplug runloop has been created. */
|
|
532
546
|
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
533
547
|
libusb_darwin_acfl = runloop;
|
|
548
|
+
libusb_darwin_acfls = libusb_shutdown_cfsource;
|
|
534
549
|
pthread_cond_signal (&libusb_darwin_at_cond);
|
|
535
550
|
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
536
551
|
|
|
537
552
|
/* run the runloop */
|
|
538
553
|
CFRunLoopRun();
|
|
539
554
|
|
|
540
|
-
usbi_dbg ("darwin event thread exiting");
|
|
555
|
+
usbi_dbg (ctx, "darwin event thread exiting");
|
|
556
|
+
|
|
557
|
+
/* signal the main thread that the hotplug runloop has finished. */
|
|
558
|
+
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
559
|
+
libusb_darwin_acfls = NULL;
|
|
560
|
+
libusb_darwin_acfl = NULL;
|
|
561
|
+
pthread_cond_signal (&libusb_darwin_at_cond);
|
|
562
|
+
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
541
563
|
|
|
542
564
|
/* remove the notification cfsource */
|
|
543
565
|
CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
|
|
544
566
|
|
|
545
567
|
/* remove the shutdown cfsource */
|
|
546
|
-
CFRunLoopRemoveSource(runloop,
|
|
568
|
+
CFRunLoopRemoveSource(runloop, libusb_shutdown_cfsource, kCFRunLoopDefaultMode);
|
|
547
569
|
|
|
548
570
|
/* delete notification port */
|
|
549
571
|
IONotificationPortDestroy (libusb_notification_port);
|
|
@@ -552,51 +574,79 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
552
574
|
IOObjectRelease (libusb_rem_device_iterator);
|
|
553
575
|
IOObjectRelease (libusb_add_device_iterator);
|
|
554
576
|
|
|
555
|
-
CFRelease (
|
|
577
|
+
CFRelease (libusb_shutdown_cfsource);
|
|
556
578
|
CFRelease (runloop);
|
|
557
579
|
|
|
558
|
-
libusb_darwin_acfls = NULL;
|
|
559
|
-
libusb_darwin_acfl = NULL;
|
|
560
|
-
|
|
561
580
|
pthread_exit (NULL);
|
|
562
581
|
}
|
|
563
582
|
|
|
564
583
|
/* cleanup function to destroy cached devices */
|
|
565
|
-
static void
|
|
584
|
+
static void darwin_cleanup_devices(void) {
|
|
566
585
|
struct darwin_cached_device *dev, *next;
|
|
567
586
|
|
|
568
|
-
usbi_mutex_lock(&darwin_cached_devices_lock);
|
|
569
587
|
list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
570
588
|
darwin_deref_cached_device(dev);
|
|
571
589
|
}
|
|
572
|
-
usbi_mutex_unlock(&darwin_cached_devices_lock);
|
|
573
590
|
}
|
|
574
591
|
|
|
575
592
|
static int darwin_init(struct libusb_context *ctx) {
|
|
593
|
+
bool first_init;
|
|
576
594
|
int rc;
|
|
577
595
|
|
|
578
|
-
|
|
579
|
-
if (LIBUSB_SUCCESS != rc) {
|
|
580
|
-
return rc;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) {
|
|
584
|
-
#if !OSX_USE_CLOCK_GETTIME
|
|
585
|
-
/* create the clocks that will be used if clock_gettime() is not available */
|
|
586
|
-
host_name_port_t host_self;
|
|
596
|
+
first_init = (1 == ++init_count);
|
|
587
597
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
598
|
+
do {
|
|
599
|
+
if (first_init) {
|
|
600
|
+
if (NULL == darwin_cached_devices.next) {
|
|
601
|
+
list_init (&darwin_cached_devices);
|
|
602
|
+
}
|
|
603
|
+
assert(list_empty(&darwin_cached_devices));
|
|
604
|
+
#if !defined(HAVE_CLOCK_GETTIME)
|
|
605
|
+
/* create the clocks that will be used if clock_gettime() is not available */
|
|
606
|
+
host_name_port_t host_self;
|
|
607
|
+
|
|
608
|
+
host_self = mach_host_self();
|
|
609
|
+
host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
|
|
610
|
+
host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
|
|
611
|
+
mach_port_deallocate(mach_task_self(), host_self);
|
|
592
612
|
#endif
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
rc = darwin_scan_devices (ctx);
|
|
616
|
+
if (LIBUSB_SUCCESS != rc)
|
|
617
|
+
break;
|
|
593
618
|
|
|
594
|
-
|
|
619
|
+
if (first_init) {
|
|
620
|
+
rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
|
|
621
|
+
if (0 != rc) {
|
|
622
|
+
usbi_err (ctx, "could not create event thread, error %d", rc);
|
|
623
|
+
rc = LIBUSB_ERROR_OTHER;
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
595
626
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
627
|
+
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
628
|
+
while (!libusb_darwin_acfl)
|
|
629
|
+
pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
630
|
+
if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) {
|
|
631
|
+
libusb_darwin_acfl = NULL;
|
|
632
|
+
rc = LIBUSB_ERROR_OTHER;
|
|
633
|
+
}
|
|
634
|
+
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
635
|
+
|
|
636
|
+
if (0 != rc)
|
|
637
|
+
pthread_join (libusb_darwin_at, NULL);
|
|
638
|
+
}
|
|
639
|
+
} while (0);
|
|
640
|
+
|
|
641
|
+
if (LIBUSB_SUCCESS != rc) {
|
|
642
|
+
if (first_init) {
|
|
643
|
+
darwin_cleanup_devices ();
|
|
644
|
+
#if !defined(HAVE_CLOCK_GETTIME)
|
|
645
|
+
mach_port_deallocate(mach_task_self(), clock_realtime);
|
|
646
|
+
mach_port_deallocate(mach_task_self(), clock_monotonic);
|
|
647
|
+
#endif
|
|
648
|
+
}
|
|
649
|
+
--init_count;
|
|
600
650
|
}
|
|
601
651
|
|
|
602
652
|
return rc;
|
|
@@ -604,31 +654,27 @@ static int darwin_init(struct libusb_context *ctx) {
|
|
|
604
654
|
|
|
605
655
|
static void darwin_exit (struct libusb_context *ctx) {
|
|
606
656
|
UNUSED(ctx);
|
|
607
|
-
if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) {
|
|
608
|
-
#if !OSX_USE_CLOCK_GETTIME
|
|
609
|
-
mach_port_deallocate(mach_task_self(), clock_realtime);
|
|
610
|
-
mach_port_deallocate(mach_task_self(), clock_monotonic);
|
|
611
|
-
#endif
|
|
612
657
|
|
|
658
|
+
if (0 == --init_count) {
|
|
613
659
|
/* stop the event runloop and wait for the thread to terminate. */
|
|
614
|
-
|
|
660
|
+
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
661
|
+
CFRunLoopSourceSignal (libusb_darwin_acfls);
|
|
615
662
|
CFRunLoopWakeUp (libusb_darwin_acfl);
|
|
663
|
+
while (libusb_darwin_acfl)
|
|
664
|
+
pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
665
|
+
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
616
666
|
pthread_join (libusb_darwin_at, NULL);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
667
|
|
|
620
|
-
|
|
621
|
-
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
|
622
|
-
|
|
623
|
-
/* return cached copy */
|
|
624
|
-
memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH);
|
|
668
|
+
darwin_cleanup_devices ();
|
|
625
669
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
670
|
+
#if !defined(HAVE_CLOCK_GETTIME)
|
|
671
|
+
mach_port_deallocate(mach_task_self(), clock_realtime);
|
|
672
|
+
mach_port_deallocate(mach_task_self(), clock_monotonic);
|
|
673
|
+
#endif
|
|
674
|
+
}
|
|
629
675
|
}
|
|
630
676
|
|
|
631
|
-
static int get_configuration_index (struct libusb_device *dev,
|
|
677
|
+
static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
|
|
632
678
|
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
|
633
679
|
UInt8 i, numConfig;
|
|
634
680
|
IOUSBConfigurationDescriptorPtr desc;
|
|
@@ -650,7 +696,7 @@ static int get_configuration_index (struct libusb_device *dev, int config_value)
|
|
|
650
696
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
651
697
|
}
|
|
652
698
|
|
|
653
|
-
static int darwin_get_active_config_descriptor(struct libusb_device *dev,
|
|
699
|
+
static int darwin_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len) {
|
|
654
700
|
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
|
655
701
|
int config_index;
|
|
656
702
|
|
|
@@ -662,10 +708,10 @@ static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsign
|
|
|
662
708
|
return config_index;
|
|
663
709
|
|
|
664
710
|
assert(config_index >= 0 && config_index <= UINT8_MAX);
|
|
665
|
-
return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len
|
|
711
|
+
return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len);
|
|
666
712
|
}
|
|
667
713
|
|
|
668
|
-
static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index,
|
|
714
|
+
static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len) {
|
|
669
715
|
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
|
670
716
|
IOUSBConfigurationDescriptorPtr desc;
|
|
671
717
|
IOReturn kresult;
|
|
@@ -681,9 +727,6 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi
|
|
|
681
727
|
len = libusb_le16_to_cpu(desc->wTotalLength);
|
|
682
728
|
|
|
683
729
|
memmove (buffer, desc, len);
|
|
684
|
-
|
|
685
|
-
/* GetConfigurationDescriptorPtr returns the descriptor in USB bus order */
|
|
686
|
-
*host_endian = 0;
|
|
687
730
|
}
|
|
688
731
|
|
|
689
732
|
ret = darwin_to_libusb (kresult);
|
|
@@ -710,8 +753,9 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
|
|
|
710
753
|
|
|
711
754
|
/* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is
|
|
712
755
|
not usable anyway */
|
|
713
|
-
if (0x05ac == dev->dev_descriptor.idVendor &&
|
|
714
|
-
|
|
756
|
+
if (0x05ac == libusb_le16_to_cpu (dev->dev_descriptor.idVendor) &&
|
|
757
|
+
0x8005 == libusb_le16_to_cpu (dev->dev_descriptor.idProduct)) {
|
|
758
|
+
usbi_dbg (ctx, "ignoring configuration on root hub simulation");
|
|
715
759
|
dev->active_config = 0;
|
|
716
760
|
return LIBUSB_SUCCESS;
|
|
717
761
|
}
|
|
@@ -753,8 +797,8 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
|
|
|
753
797
|
} else
|
|
754
798
|
/* not configured */
|
|
755
799
|
dev->active_config = 0;
|
|
756
|
-
|
|
757
|
-
usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config);
|
|
800
|
+
|
|
801
|
+
usbi_dbg (ctx, "active config: %u, first config: %u", dev->active_config, dev->first_config);
|
|
758
802
|
|
|
759
803
|
return LIBUSB_SUCCESS;
|
|
760
804
|
}
|
|
@@ -779,7 +823,7 @@ static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UI
|
|
|
779
823
|
return (*device)->DeviceRequestTO (device, &req);
|
|
780
824
|
}
|
|
781
825
|
|
|
782
|
-
static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_device *dev) {
|
|
826
|
+
static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
|
|
783
827
|
usb_device_t **device = dev->device;
|
|
784
828
|
int retries = 1;
|
|
785
829
|
long delay = 30000; // microseconds
|
|
@@ -817,7 +861,7 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
|
|
|
817
861
|
0 == dev->dev_descriptor.bcdUSB)) {
|
|
818
862
|
/* work around for incorrectly configured devices */
|
|
819
863
|
if (try_reconfigure && is_open) {
|
|
820
|
-
usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again...");
|
|
864
|
+
usbi_dbg(ctx, "descriptor appears to be invalid. resetting configuration before trying again...");
|
|
821
865
|
|
|
822
866
|
/* set the first configuration */
|
|
823
867
|
(*device)->SetConfiguration(device, 1);
|
|
@@ -848,7 +892,7 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
|
|
|
848
892
|
if (kIOReturnSuccess != ret2) {
|
|
849
893
|
/* prevent log spew from poorly behaving devices. this indicates the
|
|
850
894
|
os actually had trouble communicating with the device */
|
|
851
|
-
usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2));
|
|
895
|
+
usbi_dbg(ctx, "could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2));
|
|
852
896
|
} else
|
|
853
897
|
unsuspended = 1;
|
|
854
898
|
|
|
@@ -857,7 +901,7 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
|
|
|
857
901
|
}
|
|
858
902
|
|
|
859
903
|
if (kIOReturnSuccess != ret) {
|
|
860
|
-
usbi_dbg("kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
|
|
904
|
+
usbi_dbg(ctx, "kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
|
|
861
905
|
/* sleep for a little while before trying again */
|
|
862
906
|
nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000}, NULL);
|
|
863
907
|
}
|
|
@@ -873,10 +917,10 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
|
|
|
873
917
|
if (ret != kIOReturnSuccess) {
|
|
874
918
|
/* a debug message was already printed out for this error */
|
|
875
919
|
if (LIBUSB_CLASS_HUB == bDeviceClass)
|
|
876
|
-
usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
|
|
920
|
+
usbi_dbg (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
|
|
877
921
|
idVendor, idProduct, darwin_error_str (ret), ret);
|
|
878
922
|
else
|
|
879
|
-
usbi_warn (
|
|
923
|
+
usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
|
|
880
924
|
idVendor, idProduct, darwin_error_str (ret), ret);
|
|
881
925
|
return darwin_to_libusb (ret);
|
|
882
926
|
}
|
|
@@ -889,20 +933,20 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
|
|
|
889
933
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
890
934
|
}
|
|
891
935
|
|
|
892
|
-
usbi_dbg ("cached device descriptor:");
|
|
893
|
-
usbi_dbg (" bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType);
|
|
894
|
-
usbi_dbg (" bcdUSB: 0x%04x", dev->dev_descriptor.bcdUSB);
|
|
895
|
-
usbi_dbg (" bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass);
|
|
896
|
-
usbi_dbg (" bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass);
|
|
897
|
-
usbi_dbg (" bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol);
|
|
898
|
-
usbi_dbg (" bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0);
|
|
899
|
-
usbi_dbg (" idVendor: 0x%04x", dev->dev_descriptor.idVendor);
|
|
900
|
-
usbi_dbg (" idProduct: 0x%04x", dev->dev_descriptor.idProduct);
|
|
901
|
-
usbi_dbg (" bcdDevice: 0x%04x", dev->dev_descriptor.bcdDevice);
|
|
902
|
-
usbi_dbg (" iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer);
|
|
903
|
-
usbi_dbg (" iProduct: 0x%02x", dev->dev_descriptor.iProduct);
|
|
904
|
-
usbi_dbg (" iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber);
|
|
905
|
-
usbi_dbg (" bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations);
|
|
936
|
+
usbi_dbg (ctx, "cached device descriptor:");
|
|
937
|
+
usbi_dbg (ctx, " bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType);
|
|
938
|
+
usbi_dbg (ctx, " bcdUSB: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.bcdUSB));
|
|
939
|
+
usbi_dbg (ctx, " bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass);
|
|
940
|
+
usbi_dbg (ctx, " bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass);
|
|
941
|
+
usbi_dbg (ctx, " bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol);
|
|
942
|
+
usbi_dbg (ctx, " bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0);
|
|
943
|
+
usbi_dbg (ctx, " idVendor: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.idVendor));
|
|
944
|
+
usbi_dbg (ctx, " idProduct: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
|
|
945
|
+
usbi_dbg (ctx, " bcdDevice: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.bcdDevice));
|
|
946
|
+
usbi_dbg (ctx, " iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer);
|
|
947
|
+
usbi_dbg (ctx, " iProduct: 0x%02x", dev->dev_descriptor.iProduct);
|
|
948
|
+
usbi_dbg (ctx, " iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber);
|
|
949
|
+
usbi_dbg (ctx, " bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations);
|
|
906
950
|
|
|
907
951
|
dev->can_enumerate = 1;
|
|
908
952
|
|
|
@@ -946,7 +990,7 @@ static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_ses
|
|
|
946
990
|
return false;
|
|
947
991
|
}
|
|
948
992
|
|
|
949
|
-
static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
|
|
993
|
+
static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out,
|
|
950
994
|
UInt64 *old_session_id) {
|
|
951
995
|
struct darwin_cached_device *new_device;
|
|
952
996
|
UInt64 sessionID = 0, parent_sessionID = 0;
|
|
@@ -963,28 +1007,28 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
|
|
|
963
1007
|
(void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
|
|
964
1008
|
(void) get_ioregistry_value_number (service, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
|
|
965
1009
|
if (!get_device_port (service, &port)) {
|
|
966
|
-
usbi_dbg("could not get connected port number");
|
|
1010
|
+
usbi_dbg(ctx, "could not get connected port number");
|
|
967
1011
|
}
|
|
968
1012
|
|
|
969
|
-
usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID);
|
|
1013
|
+
usbi_dbg(ctx, "finding cached device for sessionID 0x%" PRIx64, sessionID);
|
|
970
1014
|
|
|
971
1015
|
if (get_device_parent_sessionID(service, &parent_sessionID)) {
|
|
972
|
-
usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID);
|
|
1016
|
+
usbi_dbg(ctx, "parent sessionID: 0x%" PRIx64, parent_sessionID);
|
|
973
1017
|
}
|
|
974
1018
|
|
|
975
1019
|
usbi_mutex_lock(&darwin_cached_devices_lock);
|
|
976
1020
|
do {
|
|
977
1021
|
list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
978
|
-
usbi_dbg("matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
|
|
1022
|
+
usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
|
|
979
1023
|
sessionID, locationID, new_device->session, new_device->location);
|
|
980
1024
|
if (new_device->location == locationID && new_device->in_reenumerate) {
|
|
981
|
-
usbi_dbg ("found cached device with matching location that is being re-enumerated");
|
|
1025
|
+
usbi_dbg (ctx, "found cached device with matching location that is being re-enumerated");
|
|
982
1026
|
*old_session_id = new_device->session;
|
|
983
1027
|
break;
|
|
984
1028
|
}
|
|
985
1029
|
|
|
986
1030
|
if (new_device->session == sessionID) {
|
|
987
|
-
usbi_dbg("using cached device for device");
|
|
1031
|
+
usbi_dbg(ctx, "using cached device for device");
|
|
988
1032
|
*cached_out = new_device;
|
|
989
1033
|
break;
|
|
990
1034
|
}
|
|
@@ -993,9 +1037,9 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
|
|
|
993
1037
|
if (*cached_out)
|
|
994
1038
|
break;
|
|
995
1039
|
|
|
996
|
-
usbi_dbg("caching new device with sessionID 0x%" PRIx64, sessionID);
|
|
1040
|
+
usbi_dbg(ctx, "caching new device with sessionID 0x%" PRIx64, sessionID);
|
|
997
1041
|
|
|
998
|
-
device = darwin_device_from_service (service);
|
|
1042
|
+
device = darwin_device_from_service (ctx, service);
|
|
999
1043
|
if (!device) {
|
|
1000
1044
|
ret = LIBUSB_ERROR_NO_DEVICE;
|
|
1001
1045
|
break;
|
|
@@ -1019,6 +1063,9 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
|
|
|
1019
1063
|
(*device)->GetLocationID (device, &new_device->location);
|
|
1020
1064
|
new_device->port = port;
|
|
1021
1065
|
new_device->parent_session = parent_sessionID;
|
|
1066
|
+
} else {
|
|
1067
|
+
/* release the ref to old device's service */
|
|
1068
|
+
IOObjectRelease (new_device->service);
|
|
1022
1069
|
}
|
|
1023
1070
|
|
|
1024
1071
|
/* keep track of devices regardless of if we successfully enumerate them to
|
|
@@ -1027,15 +1074,20 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
|
|
|
1027
1074
|
|
|
1028
1075
|
new_device->session = sessionID;
|
|
1029
1076
|
new_device->device = device;
|
|
1077
|
+
new_device->service = service;
|
|
1078
|
+
|
|
1079
|
+
/* retain the service */
|
|
1080
|
+
IOObjectRetain (service);
|
|
1030
1081
|
|
|
1031
1082
|
/* cache the device descriptor */
|
|
1032
|
-
ret = darwin_cache_device_descriptor(new_device);
|
|
1083
|
+
ret = darwin_cache_device_descriptor(ctx, new_device);
|
|
1033
1084
|
if (ret)
|
|
1034
1085
|
break;
|
|
1035
1086
|
|
|
1036
1087
|
if (new_device->can_enumerate) {
|
|
1037
1088
|
snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address,
|
|
1038
|
-
new_device->dev_descriptor.idVendor,
|
|
1089
|
+
libusb_le16_to_cpu (new_device->dev_descriptor.idVendor),
|
|
1090
|
+
libusb_le16_to_cpu (new_device->dev_descriptor.idProduct),
|
|
1039
1091
|
new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass);
|
|
1040
1092
|
}
|
|
1041
1093
|
} while (0);
|
|
@@ -1060,14 +1112,14 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1060
1112
|
break;
|
|
1061
1113
|
|
|
1062
1114
|
if (0 != old_session_id) {
|
|
1063
|
-
usbi_dbg ("re-using existing device from context %p for with session 0x%" PRIx64 " new session 0x%" PRIx64,
|
|
1115
|
+
usbi_dbg (ctx, "re-using existing device from context %p for with session 0x%" PRIx64 " new session 0x%" PRIx64,
|
|
1064
1116
|
ctx, old_session_id, cached_device->session);
|
|
1065
1117
|
/* save the libusb device before the session id is updated */
|
|
1066
1118
|
dev = usbi_get_device_by_session_id (ctx, (unsigned long) old_session_id);
|
|
1067
1119
|
}
|
|
1068
1120
|
|
|
1069
1121
|
if (!dev) {
|
|
1070
|
-
usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64,
|
|
1122
|
+
usbi_dbg (ctx, "allocating new device in context %p for with session 0x%" PRIx64,
|
|
1071
1123
|
ctx, cached_device->session);
|
|
1072
1124
|
|
|
1073
1125
|
dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
|
|
@@ -1075,22 +1127,33 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1075
1127
|
return LIBUSB_ERROR_NO_MEM;
|
|
1076
1128
|
}
|
|
1077
1129
|
|
|
1078
|
-
priv = (
|
|
1130
|
+
priv = usbi_get_device_priv(dev);
|
|
1079
1131
|
|
|
1080
1132
|
priv->dev = cached_device;
|
|
1081
1133
|
darwin_ref_cached_device (priv->dev);
|
|
1082
1134
|
dev->port_number = cached_device->port;
|
|
1135
|
+
/* the location ID encodes the path to the device. the top byte of the location ID contains the bus number
|
|
1136
|
+
(numbered from 0). the remaining bytes can be used to construct the device tree for that bus. */
|
|
1083
1137
|
dev->bus_number = cached_device->location >> 24;
|
|
1084
1138
|
assert(cached_device->address <= UINT8_MAX);
|
|
1085
1139
|
dev->device_address = (uint8_t)cached_device->address;
|
|
1086
1140
|
} else {
|
|
1087
|
-
priv = (
|
|
1141
|
+
priv = usbi_get_device_priv(dev);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
static_assert(sizeof(dev->device_descriptor) == sizeof(cached_device->dev_descriptor),
|
|
1145
|
+
"mismatch between libusb and IOKit device descriptor sizes");
|
|
1146
|
+
memcpy(&dev->device_descriptor, &cached_device->dev_descriptor, LIBUSB_DT_DEVICE_SIZE);
|
|
1147
|
+
usbi_localize_device_descriptor(&dev->device_descriptor);
|
|
1148
|
+
dev->session_data = cached_device->session;
|
|
1149
|
+
|
|
1150
|
+
if (NULL != dev->parent_dev) {
|
|
1151
|
+
libusb_unref_device(dev->parent_dev);
|
|
1152
|
+
dev->parent_dev = NULL;
|
|
1088
1153
|
}
|
|
1089
1154
|
|
|
1090
1155
|
if (cached_device->parent_session > 0) {
|
|
1091
1156
|
dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
|
|
1092
|
-
} else {
|
|
1093
|
-
dev->parent_dev = NULL;
|
|
1094
1157
|
}
|
|
1095
1158
|
|
|
1096
1159
|
(*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed);
|
|
@@ -1099,7 +1162,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1099
1162
|
case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
|
|
1100
1163
|
case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break;
|
|
1101
1164
|
case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break;
|
|
1102
|
-
#if MAC_OS_X_VERSION_MAX_ALLOWED >=
|
|
1165
|
+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
|
|
1103
1166
|
case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
|
|
1104
1167
|
#endif
|
|
1105
1168
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
|
@@ -1113,7 +1176,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1113
1176
|
if (ret < 0)
|
|
1114
1177
|
break;
|
|
1115
1178
|
|
|
1116
|
-
usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address,
|
|
1179
|
+
usbi_dbg (ctx, "found device with address %d port = %d parent = %p at %p", dev->device_address,
|
|
1117
1180
|
dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path);
|
|
1118
1181
|
|
|
1119
1182
|
} while (0);
|
|
@@ -1140,7 +1203,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
|
|
|
1140
1203
|
return darwin_to_libusb (kresult);
|
|
1141
1204
|
|
|
1142
1205
|
while ((service = IOIteratorNext (deviceIterator))) {
|
|
1143
|
-
ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
|
|
1206
|
+
ret = darwin_get_cached_device (ctx, service, &cached_device, &old_session_id);
|
|
1144
1207
|
if (ret < 0 || !cached_device->can_enumerate) {
|
|
1145
1208
|
continue;
|
|
1146
1209
|
}
|
|
@@ -1156,7 +1219,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
|
|
|
1156
1219
|
}
|
|
1157
1220
|
|
|
1158
1221
|
static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
1159
|
-
struct darwin_device_handle_priv *priv = (
|
|
1222
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1160
1223
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1161
1224
|
IOReturn kresult;
|
|
1162
1225
|
|
|
@@ -1192,20 +1255,20 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
1192
1255
|
|
|
1193
1256
|
CFRetain (libusb_darwin_acfl);
|
|
1194
1257
|
|
|
1195
|
-
/* add the cfSource to the
|
|
1258
|
+
/* add the cfSource to the async run loop */
|
|
1196
1259
|
CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes);
|
|
1197
1260
|
}
|
|
1198
1261
|
|
|
1199
1262
|
/* device opened successfully */
|
|
1200
1263
|
dpriv->open_count++;
|
|
1201
1264
|
|
|
1202
|
-
usbi_dbg ("device open for access");
|
|
1265
|
+
usbi_dbg (HANDLE_CTX(dev_handle), "device open for access");
|
|
1203
1266
|
|
|
1204
1267
|
return 0;
|
|
1205
1268
|
}
|
|
1206
1269
|
|
|
1207
1270
|
static void darwin_close (struct libusb_device_handle *dev_handle) {
|
|
1208
|
-
struct darwin_device_handle_priv *priv = (
|
|
1271
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1209
1272
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1210
1273
|
IOReturn kresult;
|
|
1211
1274
|
int i;
|
|
@@ -1217,6 +1280,10 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
|
|
|
1217
1280
|
}
|
|
1218
1281
|
|
|
1219
1282
|
dpriv->open_count--;
|
|
1283
|
+
if (NULL == dpriv->device) {
|
|
1284
|
+
usbi_warn (HANDLE_CTX (dev_handle), "darwin_close device missing IOService");
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1220
1287
|
|
|
1221
1288
|
/* make sure all interfaces are released */
|
|
1222
1289
|
for (i = 0 ; i < USB_MAXINTERFACES ; i++)
|
|
@@ -1244,10 +1311,10 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
|
|
|
1244
1311
|
}
|
|
1245
1312
|
}
|
|
1246
1313
|
|
|
1247
|
-
static int darwin_get_configuration(struct libusb_device_handle *dev_handle,
|
|
1314
|
+
static int darwin_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config) {
|
|
1248
1315
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1249
1316
|
|
|
1250
|
-
*config =
|
|
1317
|
+
*config = dpriv->active_config;
|
|
1251
1318
|
|
|
1252
1319
|
return LIBUSB_SUCCESS;
|
|
1253
1320
|
}
|
|
@@ -1255,9 +1322,10 @@ static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int
|
|
|
1255
1322
|
static enum libusb_error darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
|
|
1256
1323
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1257
1324
|
IOReturn kresult;
|
|
1258
|
-
|
|
1325
|
+
uint8_t i;
|
|
1259
1326
|
|
|
1260
|
-
|
|
1327
|
+
if (config == -1)
|
|
1328
|
+
config = 0;
|
|
1261
1329
|
|
|
1262
1330
|
/* Setting configuration will invalidate the interface, so we need
|
|
1263
1331
|
to reclaim it. First, dispose of existing interfaces, if any. */
|
|
@@ -1279,7 +1347,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d
|
|
|
1279
1347
|
return LIBUSB_SUCCESS;
|
|
1280
1348
|
}
|
|
1281
1349
|
|
|
1282
|
-
static IOReturn darwin_get_interface (usb_device_t **darwin_device,
|
|
1350
|
+
static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
|
|
1283
1351
|
IOUSBFindInterfaceRequest request;
|
|
1284
1352
|
IOReturn kresult;
|
|
1285
1353
|
io_iterator_t interface_iterator;
|
|
@@ -1316,8 +1384,8 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, int ifc, io_
|
|
|
1316
1384
|
return kIOReturnSuccess;
|
|
1317
1385
|
}
|
|
1318
1386
|
|
|
1319
|
-
static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
|
|
1320
|
-
struct darwin_device_handle_priv *priv = (
|
|
1387
|
+
static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, uint8_t iface) {
|
|
1388
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1321
1389
|
|
|
1322
1390
|
/* current interface */
|
|
1323
1391
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
@@ -1328,13 +1396,15 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
|
|
|
1328
1396
|
UInt8 dont_care1, dont_care3;
|
|
1329
1397
|
UInt16 dont_care2;
|
|
1330
1398
|
int rc;
|
|
1399
|
+
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
1400
|
+
|
|
1331
1401
|
|
|
1332
|
-
usbi_dbg ("building table of endpoints.");
|
|
1402
|
+
usbi_dbg (ctx, "building table of endpoints.");
|
|
1333
1403
|
|
|
1334
1404
|
/* retrieve the total number of endpoints on this interface */
|
|
1335
1405
|
kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep);
|
|
1336
1406
|
if (kresult != kIOReturnSuccess) {
|
|
1337
|
-
usbi_err (
|
|
1407
|
+
usbi_err (ctx, "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
|
|
1338
1408
|
return darwin_to_libusb (kresult);
|
|
1339
1409
|
}
|
|
1340
1410
|
|
|
@@ -1367,7 +1437,7 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
|
|
|
1367
1437
|
cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
|
|
1368
1438
|
}
|
|
1369
1439
|
|
|
1370
|
-
usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
|
|
1440
|
+
usbi_dbg (ctx, "interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
|
|
1371
1441
|
cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK);
|
|
1372
1442
|
}
|
|
1373
1443
|
|
|
@@ -1376,44 +1446,44 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
|
|
|
1376
1446
|
return LIBUSB_SUCCESS;
|
|
1377
1447
|
}
|
|
1378
1448
|
|
|
1379
|
-
static int darwin_claim_interface(struct libusb_device_handle *dev_handle,
|
|
1449
|
+
static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
|
|
1380
1450
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1381
|
-
struct darwin_device_handle_priv *priv = (
|
|
1451
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1382
1452
|
io_service_t usbInterface = IO_OBJECT_NULL;
|
|
1383
1453
|
IOReturn kresult;
|
|
1384
1454
|
enum libusb_error ret;
|
|
1385
1455
|
IOCFPlugInInterface **plugInInterface = NULL;
|
|
1386
1456
|
SInt32 score;
|
|
1387
1457
|
|
|
1388
|
-
assert(iface >= 0 && iface <= UINT8_MAX);
|
|
1389
|
-
|
|
1390
1458
|
/* current interface */
|
|
1391
1459
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
1392
1460
|
|
|
1393
|
-
|
|
1461
|
+
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
1462
|
+
|
|
1463
|
+
kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
|
|
1394
1464
|
if (kresult != kIOReturnSuccess)
|
|
1395
1465
|
return darwin_to_libusb (kresult);
|
|
1396
1466
|
|
|
1397
1467
|
/* make sure we have an interface */
|
|
1398
1468
|
if (!usbInterface && dpriv->first_config != 0) {
|
|
1399
|
-
usbi_info (
|
|
1469
|
+
usbi_info (ctx, "no interface found; setting configuration: %d", dpriv->first_config);
|
|
1400
1470
|
|
|
1401
1471
|
/* set the configuration */
|
|
1402
|
-
ret = darwin_set_configuration (dev_handle, dpriv->first_config);
|
|
1472
|
+
ret = darwin_set_configuration (dev_handle, (int) dpriv->first_config);
|
|
1403
1473
|
if (ret != LIBUSB_SUCCESS) {
|
|
1404
|
-
usbi_err (
|
|
1474
|
+
usbi_err (ctx, "could not set configuration");
|
|
1405
1475
|
return ret;
|
|
1406
1476
|
}
|
|
1407
1477
|
|
|
1408
|
-
kresult = darwin_get_interface (dpriv->device,
|
|
1478
|
+
kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
|
|
1409
1479
|
if (kresult != kIOReturnSuccess) {
|
|
1410
|
-
usbi_err (
|
|
1480
|
+
usbi_err (ctx, "darwin_get_interface: %s", darwin_error_str(kresult));
|
|
1411
1481
|
return darwin_to_libusb (kresult);
|
|
1412
1482
|
}
|
|
1413
1483
|
}
|
|
1414
1484
|
|
|
1415
1485
|
if (!usbInterface) {
|
|
1416
|
-
|
|
1486
|
+
usbi_info (ctx, "interface not found");
|
|
1417
1487
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1418
1488
|
}
|
|
1419
1489
|
|
|
@@ -1425,12 +1495,12 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1425
1495
|
(void)IOObjectRelease (usbInterface);
|
|
1426
1496
|
|
|
1427
1497
|
if (kresult != kIOReturnSuccess) {
|
|
1428
|
-
usbi_err (
|
|
1498
|
+
usbi_err (ctx, "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult));
|
|
1429
1499
|
return darwin_to_libusb (kresult);
|
|
1430
1500
|
}
|
|
1431
1501
|
|
|
1432
1502
|
if (!plugInInterface) {
|
|
1433
|
-
usbi_err (
|
|
1503
|
+
usbi_err (ctx, "plugin interface not found");
|
|
1434
1504
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1435
1505
|
}
|
|
1436
1506
|
|
|
@@ -1442,14 +1512,14 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1442
1512
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
1443
1513
|
(*plugInInterface)->Release (plugInInterface);
|
|
1444
1514
|
if (kresult != kIOReturnSuccess || !cInterface->interface) {
|
|
1445
|
-
usbi_err (
|
|
1515
|
+
usbi_err (ctx, "QueryInterface: %s", darwin_error_str(kresult));
|
|
1446
1516
|
return darwin_to_libusb (kresult);
|
|
1447
1517
|
}
|
|
1448
1518
|
|
|
1449
1519
|
/* claim the interface */
|
|
1450
1520
|
kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface);
|
|
1451
1521
|
if (kresult != kIOReturnSuccess) {
|
|
1452
|
-
|
|
1522
|
+
usbi_info (ctx, "USBInterfaceOpen: %s", darwin_error_str(kresult));
|
|
1453
1523
|
return darwin_to_libusb (kresult);
|
|
1454
1524
|
}
|
|
1455
1525
|
|
|
@@ -1458,7 +1528,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1458
1528
|
if (ret) {
|
|
1459
1529
|
/* this should not happen */
|
|
1460
1530
|
darwin_release_interface (dev_handle, iface);
|
|
1461
|
-
usbi_err (
|
|
1531
|
+
usbi_err (ctx, "could not build endpoint table");
|
|
1462
1532
|
return ret;
|
|
1463
1533
|
}
|
|
1464
1534
|
|
|
@@ -1467,7 +1537,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1467
1537
|
/* create async event source */
|
|
1468
1538
|
kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource);
|
|
1469
1539
|
if (kresult != kIOReturnSuccess) {
|
|
1470
|
-
usbi_err (
|
|
1540
|
+
usbi_err (ctx, "could not create async event source");
|
|
1471
1541
|
|
|
1472
1542
|
/* can't continue without an async event source */
|
|
1473
1543
|
(void)darwin_release_interface (dev_handle, iface);
|
|
@@ -1478,13 +1548,13 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1478
1548
|
/* add the cfSource to the async thread's run loop */
|
|
1479
1549
|
CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode);
|
|
1480
1550
|
|
|
1481
|
-
usbi_dbg ("interface opened");
|
|
1551
|
+
usbi_dbg (ctx, "interface opened");
|
|
1482
1552
|
|
|
1483
1553
|
return LIBUSB_SUCCESS;
|
|
1484
1554
|
}
|
|
1485
1555
|
|
|
1486
|
-
static int darwin_release_interface(struct libusb_device_handle *dev_handle,
|
|
1487
|
-
struct darwin_device_handle_priv *priv = (
|
|
1556
|
+
static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
|
|
1557
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1488
1558
|
IOReturn kresult;
|
|
1489
1559
|
|
|
1490
1560
|
/* current interface */
|
|
@@ -1501,6 +1571,7 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
|
|
|
1501
1571
|
if (cInterface->cfSource) {
|
|
1502
1572
|
CFRunLoopRemoveSource (libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode);
|
|
1503
1573
|
CFRelease (cInterface->cfSource);
|
|
1574
|
+
cInterface->cfSource = NULL;
|
|
1504
1575
|
}
|
|
1505
1576
|
|
|
1506
1577
|
kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface);
|
|
@@ -1516,8 +1587,32 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
|
|
|
1516
1587
|
return darwin_to_libusb (kresult);
|
|
1517
1588
|
}
|
|
1518
1589
|
|
|
1519
|
-
static int
|
|
1520
|
-
|
|
1590
|
+
static int check_alt_setting_and_clear_halt(struct libusb_device_handle *dev_handle, uint8_t altsetting, struct darwin_interface *cInterface) {
|
|
1591
|
+
enum libusb_error ret;
|
|
1592
|
+
IOReturn kresult;
|
|
1593
|
+
uint8_t current_alt_setting;
|
|
1594
|
+
|
|
1595
|
+
kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, ¤t_alt_setting);
|
|
1596
|
+
if (kresult == kIOReturnSuccess && altsetting != current_alt_setting) {
|
|
1597
|
+
return LIBUSB_ERROR_PIPE;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
for (int i = 0 ; i < cInterface->num_endpoints ; i++) {
|
|
1601
|
+
ret = darwin_clear_halt(dev_handle, cInterface->endpoint_addrs[i]);
|
|
1602
|
+
if (LIBUSB_SUCCESS != ret) {
|
|
1603
|
+
usbi_warn(HANDLE_CTX (dev_handle), "error clearing pipe halt for endpoint %d", i);
|
|
1604
|
+
if (LIBUSB_ERROR_NOT_FOUND == ret) {
|
|
1605
|
+
/* may need to re-open the interface */
|
|
1606
|
+
return ret;
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
return LIBUSB_SUCCESS;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting) {
|
|
1615
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1521
1616
|
IOReturn kresult;
|
|
1522
1617
|
enum libusb_error ret;
|
|
1523
1618
|
|
|
@@ -1527,21 +1622,42 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand
|
|
|
1527
1622
|
if (!cInterface->interface)
|
|
1528
1623
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
1529
1624
|
|
|
1530
|
-
|
|
1531
|
-
kresult
|
|
1532
|
-
|
|
1533
|
-
|
|
1625
|
+
kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting);
|
|
1626
|
+
if (kresult == kIOReturnSuccess) {
|
|
1627
|
+
/* update the list of endpoints */
|
|
1628
|
+
ret = get_endpoints (dev_handle, iface);
|
|
1629
|
+
if (ret) {
|
|
1630
|
+
/* this should not happen */
|
|
1631
|
+
darwin_release_interface (dev_handle, iface);
|
|
1632
|
+
usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
|
|
1633
|
+
}
|
|
1634
|
+
return ret;
|
|
1635
|
+
}
|
|
1534
1636
|
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
darwin_release_interface (dev_handle, iface);
|
|
1540
|
-
usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
|
|
1637
|
+
usbi_warn (HANDLE_CTX (dev_handle), "SetAlternateInterface: %s", darwin_error_str(kresult));
|
|
1638
|
+
|
|
1639
|
+
ret = darwin_to_libusb(kresult);
|
|
1640
|
+
if (ret != LIBUSB_ERROR_PIPE) {
|
|
1541
1641
|
return ret;
|
|
1542
1642
|
}
|
|
1543
1643
|
|
|
1544
|
-
|
|
1644
|
+
/* If a device only supports a default setting for the specified interface, then a STALL
|
|
1645
|
+
(kIOUSBPipeStalled) may be returned. Ref: USB 2.0 specs 9.4.10.
|
|
1646
|
+
Mimic the behaviour in e.g. the Linux kernel: in such case, reset all endpoints
|
|
1647
|
+
of the interface (as would have been done per 9.1.1.5) and return success. */
|
|
1648
|
+
|
|
1649
|
+
ret = check_alt_setting_and_clear_halt(dev_handle, altsetting, cInterface);
|
|
1650
|
+
if (LIBUSB_ERROR_NOT_FOUND == ret) {
|
|
1651
|
+
/* For some reason we need to reclaim the interface after the pipe error with some versions of macOS */
|
|
1652
|
+
ret = darwin_claim_interface (dev_handle, iface);
|
|
1653
|
+
if (LIBUSB_SUCCESS != ret) {
|
|
1654
|
+
darwin_release_interface (dev_handle, iface);
|
|
1655
|
+
usbi_err (HANDLE_CTX (dev_handle), "could not reclaim interface: %s", darwin_error_str(kresult));
|
|
1656
|
+
}
|
|
1657
|
+
ret = check_alt_setting_and_clear_halt(dev_handle, altsetting, cInterface);
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
return ret;
|
|
1545
1661
|
}
|
|
1546
1662
|
|
|
1547
1663
|
static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) {
|
|
@@ -1568,10 +1684,12 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
|
|
|
1568
1684
|
static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config,
|
|
1569
1685
|
unsigned long claimed_interfaces) {
|
|
1570
1686
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1571
|
-
struct darwin_device_handle_priv *priv = (
|
|
1687
|
+
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1572
1688
|
int open_count = dpriv->open_count;
|
|
1573
1689
|
int ret;
|
|
1574
1690
|
|
|
1691
|
+
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
1692
|
+
|
|
1575
1693
|
/* clear claimed interfaces temporarily */
|
|
1576
1694
|
dev_handle->claimed_interfaces = 0;
|
|
1577
1695
|
|
|
@@ -1591,28 +1709,28 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
|
|
|
1591
1709
|
}
|
|
1592
1710
|
|
|
1593
1711
|
if (dpriv->active_config != active_config) {
|
|
1594
|
-
usbi_dbg ("darwin/restore_state: restoring configuration %d...", active_config);
|
|
1712
|
+
usbi_dbg (ctx, "darwin/restore_state: restoring configuration %d...", active_config);
|
|
1595
1713
|
|
|
1596
1714
|
ret = darwin_set_configuration (dev_handle, active_config);
|
|
1597
1715
|
if (LIBUSB_SUCCESS != ret) {
|
|
1598
|
-
usbi_dbg ("darwin/restore_state: could not restore configuration");
|
|
1716
|
+
usbi_dbg (ctx, "darwin/restore_state: could not restore configuration");
|
|
1599
1717
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1600
1718
|
}
|
|
1601
1719
|
}
|
|
1602
1720
|
|
|
1603
|
-
usbi_dbg ("darwin/restore_state: reclaiming interfaces");
|
|
1721
|
+
usbi_dbg (ctx, "darwin/restore_state: reclaiming interfaces");
|
|
1604
1722
|
|
|
1605
1723
|
if (claimed_interfaces) {
|
|
1606
|
-
for (
|
|
1724
|
+
for (uint8_t iface = 0 ; iface < USB_MAXINTERFACES ; ++iface) {
|
|
1607
1725
|
if (!(claimed_interfaces & (1U << iface))) {
|
|
1608
1726
|
continue;
|
|
1609
1727
|
}
|
|
1610
1728
|
|
|
1611
|
-
usbi_dbg ("darwin/restore_state: re-claiming interface %
|
|
1729
|
+
usbi_dbg (ctx, "darwin/restore_state: re-claiming interface %u", iface);
|
|
1612
1730
|
|
|
1613
1731
|
ret = darwin_claim_interface (dev_handle, iface);
|
|
1614
1732
|
if (LIBUSB_SUCCESS != ret) {
|
|
1615
|
-
usbi_dbg ("darwin/restore_state: could not claim interface %
|
|
1733
|
+
usbi_dbg (ctx, "darwin/restore_state: could not claim interface %u", iface);
|
|
1616
1734
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1617
1735
|
}
|
|
1618
1736
|
|
|
@@ -1620,21 +1738,24 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
|
|
|
1620
1738
|
}
|
|
1621
1739
|
}
|
|
1622
1740
|
|
|
1623
|
-
usbi_dbg ("darwin/restore_state: device state restored");
|
|
1741
|
+
usbi_dbg (ctx, "darwin/restore_state: device state restored");
|
|
1624
1742
|
|
|
1625
1743
|
return LIBUSB_SUCCESS;
|
|
1626
1744
|
}
|
|
1627
1745
|
|
|
1628
|
-
static int
|
|
1746
|
+
static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, bool capture) {
|
|
1629
1747
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1630
1748
|
unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
|
|
1631
1749
|
int8_t active_config = dpriv->active_config;
|
|
1750
|
+
UInt32 options = 0;
|
|
1632
1751
|
IOUSBDeviceDescriptor descriptor;
|
|
1633
1752
|
IOUSBConfigurationDescriptorPtr cached_configuration;
|
|
1634
1753
|
IOUSBConfigurationDescriptor *cached_configurations;
|
|
1635
1754
|
IOReturn kresult;
|
|
1636
1755
|
UInt8 i;
|
|
1637
1756
|
|
|
1757
|
+
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
1758
|
+
|
|
1638
1759
|
if (dpriv->in_reenumerate) {
|
|
1639
1760
|
/* ack, two (or more) threads are trying to reset the device! abort! */
|
|
1640
1761
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
@@ -1651,63 +1772,125 @@ static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
|
|
|
1651
1772
|
memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
|
|
1652
1773
|
}
|
|
1653
1774
|
|
|
1775
|
+
/* if we need to release capture */
|
|
1776
|
+
if (HAS_CAPTURE_DEVICE()) {
|
|
1777
|
+
if (capture) {
|
|
1778
|
+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
|
1779
|
+
options |= kUSBReEnumerateCaptureDeviceMask;
|
|
1780
|
+
#endif
|
|
1781
|
+
}
|
|
1782
|
+
} else {
|
|
1783
|
+
capture = false;
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1654
1786
|
/* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
|
|
1655
|
-
kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device,
|
|
1787
|
+
kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, options);
|
|
1656
1788
|
if (kresult != kIOReturnSuccess) {
|
|
1657
|
-
usbi_err (
|
|
1789
|
+
usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
|
|
1658
1790
|
dpriv->in_reenumerate = false;
|
|
1659
1791
|
return darwin_to_libusb (kresult);
|
|
1660
1792
|
}
|
|
1661
1793
|
|
|
1662
|
-
|
|
1794
|
+
/* capture mode does not re-enumerate but it does require re-open */
|
|
1795
|
+
if (capture) {
|
|
1796
|
+
usbi_dbg (ctx, "darwin/reenumerate_device: restoring state...");
|
|
1797
|
+
dpriv->in_reenumerate = false;
|
|
1798
|
+
return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
usbi_dbg (ctx, "darwin/reenumerate_device: waiting for re-enumeration to complete...");
|
|
1802
|
+
|
|
1803
|
+
struct timespec start;
|
|
1804
|
+
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
1663
1805
|
|
|
1664
1806
|
while (dpriv->in_reenumerate) {
|
|
1665
1807
|
struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
|
|
1666
1808
|
nanosleep (&delay, NULL);
|
|
1809
|
+
|
|
1810
|
+
struct timespec now;
|
|
1811
|
+
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
1812
|
+
UInt32 elapsed = (now.tv_sec - start.tv_sec) * 1000000 + (now.tv_nsec - start.tv_nsec) / 1000;
|
|
1813
|
+
|
|
1814
|
+
if (elapsed >= DARWIN_REENUMERATE_TIMEOUT_US) {
|
|
1815
|
+
usbi_err (ctx, "darwin/reenumerate_device: timeout waiting for reenumerate");
|
|
1816
|
+
dpriv->in_reenumerate = false;
|
|
1817
|
+
return LIBUSB_ERROR_TIMEOUT;
|
|
1818
|
+
}
|
|
1667
1819
|
}
|
|
1668
1820
|
|
|
1669
1821
|
/* compare descriptors */
|
|
1670
|
-
usbi_dbg ("darwin/
|
|
1822
|
+
usbi_dbg (ctx, "darwin/reenumerate_device: checking whether descriptors changed");
|
|
1671
1823
|
|
|
1672
1824
|
if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
|
|
1673
1825
|
/* device descriptor changed. need to return not found. */
|
|
1674
|
-
usbi_dbg ("darwin/
|
|
1826
|
+
usbi_dbg (ctx, "darwin/reenumerate_device: device descriptor changed");
|
|
1675
1827
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1676
1828
|
}
|
|
1677
1829
|
|
|
1678
1830
|
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
1679
1831
|
(void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
1680
1832
|
if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
|
|
1681
|
-
usbi_dbg ("darwin/
|
|
1833
|
+
usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
|
|
1682
1834
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1683
1835
|
}
|
|
1684
1836
|
}
|
|
1685
1837
|
|
|
1686
|
-
usbi_dbg ("darwin/
|
|
1838
|
+
usbi_dbg (ctx, "darwin/reenumerate_device: device reset complete. restoring state...");
|
|
1687
1839
|
|
|
1688
1840
|
return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
|
|
1689
1841
|
}
|
|
1690
1842
|
|
|
1691
|
-
static int
|
|
1843
|
+
static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
|
|
1692
1844
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1693
|
-
io_service_t usbInterface;
|
|
1694
|
-
CFTypeRef driver;
|
|
1695
1845
|
IOReturn kresult;
|
|
1696
1846
|
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
|
|
1701
|
-
|
|
1847
|
+
if (dpriv->capture_count > 0) {
|
|
1848
|
+
/* we have to use ResetDevice as USBDeviceReEnumerate() loses the authorization for capture */
|
|
1849
|
+
kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
|
|
1702
1850
|
return darwin_to_libusb (kresult);
|
|
1851
|
+
} else {
|
|
1852
|
+
return darwin_reenumerate_device (dev_handle, false);
|
|
1703
1853
|
}
|
|
1854
|
+
}
|
|
1704
1855
|
|
|
1705
|
-
|
|
1706
|
-
|
|
1856
|
+
static io_service_t usb_find_interface_matching_location (const io_name_t class_name, UInt8 interface_number, UInt32 location) {
|
|
1857
|
+
CFMutableDictionaryRef matchingDict = IOServiceMatching (class_name);
|
|
1858
|
+
CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable (kCFAllocatorDefault, 0,
|
|
1859
|
+
&kCFTypeDictionaryKeyCallBacks,
|
|
1860
|
+
&kCFTypeDictionaryValueCallBacks);
|
|
1861
|
+
CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
|
|
1862
|
+
CFTypeRef interfaceCF = CFNumberCreate (NULL, kCFNumberSInt8Type, &interface_number);
|
|
1707
1863
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1864
|
+
CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
|
|
1865
|
+
CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
|
|
1866
|
+
CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBHostMatchingPropertyInterfaceNumber), interfaceCF);
|
|
1710
1867
|
|
|
1868
|
+
CFRelease (interfaceCF);
|
|
1869
|
+
CFRelease (locationCF);
|
|
1870
|
+
CFRelease (propertyMatchDict);
|
|
1871
|
+
|
|
1872
|
+
return IOServiceGetMatchingService (darwin_default_master_port, matchingDict);
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, uint8_t interface) {
|
|
1876
|
+
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1877
|
+
io_service_t usb_interface, child = IO_OBJECT_NULL;
|
|
1878
|
+
|
|
1879
|
+
/* locate the IO registry entry for this interface */
|
|
1880
|
+
usb_interface = usb_find_interface_matching_location (kIOUSBHostInterfaceClassName, interface, dpriv->location);
|
|
1881
|
+
if (0 == usb_interface) {
|
|
1882
|
+
/* check for the legacy class entry */
|
|
1883
|
+
usb_interface = usb_find_interface_matching_location (kIOUSBInterfaceClassName, interface, dpriv->location);
|
|
1884
|
+
if (0 == usb_interface) {
|
|
1885
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
/* if the IO object has a child entry in the IO Registry it has a kernel driver attached */
|
|
1890
|
+
(void) IORegistryEntryGetChildEntry (usb_interface, kIOServicePlane, &child);
|
|
1891
|
+
IOObjectRelease (usb_interface);
|
|
1892
|
+
if (IO_OBJECT_NULL != child) {
|
|
1893
|
+
IOObjectRelease (child);
|
|
1711
1894
|
return 1;
|
|
1712
1895
|
}
|
|
1713
1896
|
|
|
@@ -1715,21 +1898,8 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle,
|
|
|
1715
1898
|
return 0;
|
|
1716
1899
|
}
|
|
1717
1900
|
|
|
1718
|
-
/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */
|
|
1719
|
-
static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
|
|
1720
|
-
UNUSED(dev_handle);
|
|
1721
|
-
UNUSED(interface);
|
|
1722
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
1723
|
-
}
|
|
1724
|
-
|
|
1725
|
-
static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
|
|
1726
|
-
UNUSED(dev_handle);
|
|
1727
|
-
UNUSED(interface);
|
|
1728
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
1729
|
-
}
|
|
1730
|
-
|
|
1731
1901
|
static void darwin_destroy_device(struct libusb_device *dev) {
|
|
1732
|
-
struct darwin_device_priv *dpriv = (
|
|
1902
|
+
struct darwin_device_priv *dpriv = usbi_get_device_priv(dev);
|
|
1733
1903
|
|
|
1734
1904
|
if (dpriv->dev) {
|
|
1735
1905
|
/* need to hold the lock in case this is the last reference to the device */
|
|
@@ -1745,11 +1915,16 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
|
|
|
1745
1915
|
|
|
1746
1916
|
IOReturn ret;
|
|
1747
1917
|
uint8_t transferType;
|
|
1748
|
-
|
|
1749
|
-
uint8_t direction, number, interval, pipeRef;
|
|
1918
|
+
uint8_t pipeRef;
|
|
1750
1919
|
uint16_t maxPacketSize;
|
|
1751
1920
|
|
|
1752
1921
|
struct darwin_interface *cInterface;
|
|
1922
|
+
#if InterfaceVersion >= 550
|
|
1923
|
+
IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
|
|
1924
|
+
#else
|
|
1925
|
+
/* None of the values below are used in libusb for bulk transfers */
|
|
1926
|
+
uint8_t direction, number, interval;
|
|
1927
|
+
#endif
|
|
1753
1928
|
|
|
1754
1929
|
if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
|
|
1755
1930
|
usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
|
|
@@ -1757,8 +1932,15 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
|
|
|
1757
1932
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1758
1933
|
}
|
|
1759
1934
|
|
|
1935
|
+
#if InterfaceVersion >= 550
|
|
1936
|
+
ret = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, pipeRef, &pipeProperties);
|
|
1937
|
+
|
|
1938
|
+
transferType = pipeProperties.bTransferType;
|
|
1939
|
+
maxPacketSize = pipeProperties.wMaxPacketSize;
|
|
1940
|
+
#else
|
|
1760
1941
|
ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
|
|
1761
1942
|
&transferType, &maxPacketSize, &interval);
|
|
1943
|
+
#endif
|
|
1762
1944
|
|
|
1763
1945
|
if (ret) {
|
|
1764
1946
|
usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
|
|
@@ -1834,7 +2016,7 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
|
|
|
1834
2016
|
|
|
1835
2017
|
static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
1836
2018
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1837
|
-
struct darwin_transfer_priv *tpriv =
|
|
2019
|
+
struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
|
|
1838
2020
|
|
|
1839
2021
|
IOReturn kresult;
|
|
1840
2022
|
uint8_t direction, number, interval, pipeRef, transferType;
|
|
@@ -1926,7 +2108,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
|
|
|
1926
2108
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1927
2109
|
struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer;
|
|
1928
2110
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
|
|
1929
|
-
struct darwin_transfer_priv *tpriv =
|
|
2111
|
+
struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
|
|
1930
2112
|
|
|
1931
2113
|
IOReturn kresult;
|
|
1932
2114
|
|
|
@@ -2015,8 +2197,10 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
|
|
|
2015
2197
|
uint8_t pipeRef, iface;
|
|
2016
2198
|
IOReturn kresult;
|
|
2017
2199
|
|
|
2200
|
+
struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
|
|
2201
|
+
|
|
2018
2202
|
if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface, &cInterface) != 0) {
|
|
2019
|
-
usbi_err (
|
|
2203
|
+
usbi_err (ctx, "endpoint not found on any open interface");
|
|
2020
2204
|
|
|
2021
2205
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2022
2206
|
}
|
|
@@ -2024,7 +2208,7 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
|
|
|
2024
2208
|
if (!dpriv->device)
|
|
2025
2209
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
2026
2210
|
|
|
2027
|
-
usbi_warn (
|
|
2211
|
+
usbi_warn (ctx, "aborting all transactions on interface %d pipe %d", iface, pipeRef);
|
|
2028
2212
|
|
|
2029
2213
|
/* abort transactions */
|
|
2030
2214
|
#if InterfaceVersion >= 550
|
|
@@ -2034,7 +2218,7 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
|
|
|
2034
2218
|
#endif
|
|
2035
2219
|
(*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef);
|
|
2036
2220
|
|
|
2037
|
-
usbi_dbg ("calling clear pipe stall to clear the data toggle bit");
|
|
2221
|
+
usbi_dbg (ctx, "calling clear pipe stall to clear the data toggle bit");
|
|
2038
2222
|
|
|
2039
2223
|
/* newer versions of darwin support clearing additional bits on the device's endpoint */
|
|
2040
2224
|
kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
|
|
@@ -2058,22 +2242,12 @@ static int darwin_cancel_transfer(struct usbi_transfer *itransfer) {
|
|
|
2058
2242
|
}
|
|
2059
2243
|
}
|
|
2060
2244
|
|
|
2061
|
-
static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) {
|
|
2062
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
2063
|
-
struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
|
|
2064
|
-
|
|
2065
|
-
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && tpriv->isoc_framelist) {
|
|
2066
|
-
free (tpriv->isoc_framelist);
|
|
2067
|
-
tpriv->isoc_framelist = NULL;
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2071
2245
|
static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) {
|
|
2072
2246
|
struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon;
|
|
2073
2247
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
2074
|
-
struct darwin_transfer_priv *tpriv =
|
|
2248
|
+
struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
|
|
2075
2249
|
|
|
2076
|
-
usbi_dbg ("an async io operation has completed");
|
|
2250
|
+
usbi_dbg (TRANSFER_CTX(transfer), "an async io operation has completed");
|
|
2077
2251
|
|
|
2078
2252
|
/* if requested write a zero packet */
|
|
2079
2253
|
if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
|
|
@@ -2096,6 +2270,8 @@ static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer
|
|
|
2096
2270
|
if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT)
|
|
2097
2271
|
result = kIOUSBTransactionTimeout;
|
|
2098
2272
|
|
|
2273
|
+
struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
|
|
2274
|
+
|
|
2099
2275
|
switch (result) {
|
|
2100
2276
|
case kIOReturnUnderrun:
|
|
2101
2277
|
case kIOReturnSuccess:
|
|
@@ -2103,90 +2279,80 @@ static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer
|
|
|
2103
2279
|
case kIOReturnAborted:
|
|
2104
2280
|
return LIBUSB_TRANSFER_CANCELLED;
|
|
2105
2281
|
case kIOUSBPipeStalled:
|
|
2106
|
-
usbi_dbg ("transfer error: pipe is stalled");
|
|
2282
|
+
usbi_dbg (ctx, "transfer error: pipe is stalled");
|
|
2107
2283
|
return LIBUSB_TRANSFER_STALL;
|
|
2108
2284
|
case kIOReturnOverrun:
|
|
2109
|
-
usbi_warn (
|
|
2285
|
+
usbi_warn (ctx, "transfer error: data overrun");
|
|
2110
2286
|
return LIBUSB_TRANSFER_OVERFLOW;
|
|
2111
2287
|
case kIOUSBTransactionTimeout:
|
|
2112
|
-
usbi_warn (
|
|
2288
|
+
usbi_warn (ctx, "transfer error: timed out");
|
|
2113
2289
|
itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
|
|
2114
2290
|
return LIBUSB_TRANSFER_TIMED_OUT;
|
|
2115
2291
|
default:
|
|
2116
|
-
usbi_warn (
|
|
2292
|
+
usbi_warn (ctx, "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
|
|
2117
2293
|
return LIBUSB_TRANSFER_ERROR;
|
|
2118
2294
|
}
|
|
2119
2295
|
}
|
|
2120
2296
|
|
|
2121
2297
|
static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
|
|
2122
2298
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
2123
|
-
struct darwin_transfer_priv *tpriv =
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
bool
|
|
2127
|
-
|
|
2128
|
-
|
|
2299
|
+
struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
|
|
2300
|
+
const unsigned char max_transfer_type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
|
|
2301
|
+
const char *transfer_types[] = {"control", "isoc", "bulk", "interrupt", "bulk-stream", NULL};
|
|
2302
|
+
bool is_isoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
|
|
2303
|
+
struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
|
|
2304
|
+
|
|
2305
|
+
if (transfer->type > max_transfer_type) {
|
|
2306
|
+
usbi_err (ctx, "unknown endpoint type %d", transfer->type);
|
|
2307
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2308
|
+
}
|
|
2129
2309
|
|
|
2130
|
-
if (
|
|
2131
|
-
usbi_err (
|
|
2310
|
+
if (NULL == tpriv) {
|
|
2311
|
+
usbi_err (ctx, "malformed request is missing transfer priv");
|
|
2132
2312
|
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2133
2313
|
}
|
|
2134
2314
|
|
|
2135
|
-
usbi_dbg ("handling %s
|
|
2136
|
-
isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result);
|
|
2315
|
+
usbi_dbg (ctx, "handling transfer completion type %s with kernel status %d", transfer_types[transfer->type], tpriv->result);
|
|
2137
2316
|
|
|
2138
|
-
if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) {
|
|
2139
|
-
if (
|
|
2317
|
+
if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result || kIOUSBTransactionTimeout == tpriv->result) {
|
|
2318
|
+
if (is_isoc && tpriv->isoc_framelist) {
|
|
2140
2319
|
/* copy isochronous results back */
|
|
2141
2320
|
|
|
2142
|
-
for (i = 0; i < transfer->num_iso_packets ; i++) {
|
|
2321
|
+
for (int i = 0; i < transfer->num_iso_packets ; i++) {
|
|
2143
2322
|
struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
|
|
2144
2323
|
lib_desc->status = darwin_transfer_status (itransfer, tpriv->isoc_framelist[i].frStatus);
|
|
2145
2324
|
lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
|
|
2146
2325
|
}
|
|
2147
|
-
} else if (!
|
|
2326
|
+
} else if (!is_isoc) {
|
|
2148
2327
|
itransfer->transferred += tpriv->size;
|
|
2328
|
+
}
|
|
2149
2329
|
}
|
|
2150
2330
|
|
|
2151
2331
|
/* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */
|
|
2152
2332
|
return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result));
|
|
2153
2333
|
}
|
|
2154
2334
|
|
|
2155
|
-
|
|
2156
|
-
|
|
2335
|
+
#if !defined(HAVE_CLOCK_GETTIME)
|
|
2336
|
+
void usbi_get_monotonic_time(struct timespec *tp) {
|
|
2157
2337
|
mach_timespec_t sys_time;
|
|
2158
|
-
clock_serv_t clock_ref;
|
|
2159
|
-
|
|
2160
|
-
switch (clk_id) {
|
|
2161
|
-
case USBI_CLOCK_REALTIME:
|
|
2162
|
-
/* CLOCK_REALTIME represents time since the epoch */
|
|
2163
|
-
clock_ref = clock_realtime;
|
|
2164
|
-
break;
|
|
2165
|
-
case USBI_CLOCK_MONOTONIC:
|
|
2166
|
-
/* use system boot time as reference for the monotonic clock */
|
|
2167
|
-
clock_ref = clock_monotonic;
|
|
2168
|
-
break;
|
|
2169
|
-
default:
|
|
2170
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2171
|
-
}
|
|
2172
2338
|
|
|
2173
|
-
|
|
2339
|
+
/* use system boot time as reference for the monotonic clock */
|
|
2340
|
+
clock_get_time (clock_monotonic, &sys_time);
|
|
2174
2341
|
|
|
2175
2342
|
tp->tv_sec = sys_time.tv_sec;
|
|
2176
2343
|
tp->tv_nsec = sys_time.tv_nsec;
|
|
2344
|
+
}
|
|
2177
2345
|
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2187
|
-
}
|
|
2188
|
-
#endif
|
|
2346
|
+
void usbi_get_real_time(struct timespec *tp) {
|
|
2347
|
+
mach_timespec_t sys_time;
|
|
2348
|
+
|
|
2349
|
+
/* CLOCK_REALTIME represents time since the epoch */
|
|
2350
|
+
clock_get_time (clock_realtime, &sys_time);
|
|
2351
|
+
|
|
2352
|
+
tp->tv_sec = sys_time.tv_sec;
|
|
2353
|
+
tp->tv_nsec = sys_time.tv_nsec;
|
|
2189
2354
|
}
|
|
2355
|
+
#endif
|
|
2190
2356
|
|
|
2191
2357
|
#if InterfaceVersion >= 550
|
|
2192
2358
|
static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints,
|
|
@@ -2196,7 +2362,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
|
|
|
2196
2362
|
uint8_t pipeRef;
|
|
2197
2363
|
int rc, i;
|
|
2198
2364
|
|
|
2199
|
-
/* find the
|
|
2365
|
+
/* find the minimum number of supported streams on the endpoint list */
|
|
2200
2366
|
for (i = 0 ; i < num_endpoints ; ++i) {
|
|
2201
2367
|
if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) {
|
|
2202
2368
|
return rc;
|
|
@@ -2247,13 +2413,161 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
|
|
|
2247
2413
|
}
|
|
2248
2414
|
#endif
|
|
2249
2415
|
|
|
2416
|
+
#if InterfaceVersion >= 700
|
|
2417
|
+
|
|
2418
|
+
/* macOS APIs for getting entitlement values */
|
|
2419
|
+
|
|
2420
|
+
#if TARGET_OS_OSX
|
|
2421
|
+
#include <Security/Security.h>
|
|
2422
|
+
#else
|
|
2423
|
+
typedef struct __SecTask *SecTaskRef;
|
|
2424
|
+
extern SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator);
|
|
2425
|
+
extern CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error);
|
|
2426
|
+
#endif
|
|
2427
|
+
|
|
2428
|
+
static bool darwin_has_capture_entitlements (void) {
|
|
2429
|
+
SecTaskRef task;
|
|
2430
|
+
CFTypeRef value;
|
|
2431
|
+
bool entitled;
|
|
2432
|
+
|
|
2433
|
+
task = SecTaskCreateFromSelf (kCFAllocatorDefault);
|
|
2434
|
+
if (task == NULL) {
|
|
2435
|
+
return false;
|
|
2436
|
+
}
|
|
2437
|
+
value = SecTaskCopyValueForEntitlement(task, CFSTR("com.apple.vm.device-access"), NULL);
|
|
2438
|
+
CFRelease (task);
|
|
2439
|
+
entitled = value && (CFGetTypeID (value) == CFBooleanGetTypeID ()) && CFBooleanGetValue (value);
|
|
2440
|
+
if (value) {
|
|
2441
|
+
CFRelease (value);
|
|
2442
|
+
}
|
|
2443
|
+
return entitled;
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
static int darwin_reload_device (struct libusb_device_handle *dev_handle) {
|
|
2447
|
+
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
2448
|
+
enum libusb_error err;
|
|
2449
|
+
|
|
2450
|
+
usbi_mutex_lock(&darwin_cached_devices_lock);
|
|
2451
|
+
(*(dpriv->device))->Release(dpriv->device);
|
|
2452
|
+
dpriv->device = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service);
|
|
2453
|
+
if (!dpriv->device) {
|
|
2454
|
+
err = LIBUSB_ERROR_NO_DEVICE;
|
|
2455
|
+
} else {
|
|
2456
|
+
err = LIBUSB_SUCCESS;
|
|
2457
|
+
}
|
|
2458
|
+
usbi_mutex_unlock(&darwin_cached_devices_lock);
|
|
2459
|
+
|
|
2460
|
+
return err;
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
/* On macOS, we capture an entire device at once, not individual interfaces. */
|
|
2464
|
+
|
|
2465
|
+
static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, uint8_t interface) {
|
|
2466
|
+
UNUSED(interface);
|
|
2467
|
+
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
2468
|
+
IOReturn kresult;
|
|
2469
|
+
enum libusb_error err;
|
|
2470
|
+
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
2471
|
+
|
|
2472
|
+
if (HAS_CAPTURE_DEVICE()) {
|
|
2473
|
+
} else {
|
|
2474
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
if (dpriv->capture_count == 0) {
|
|
2478
|
+
usbi_dbg (ctx, "attempting to detach kernel driver from device");
|
|
2479
|
+
|
|
2480
|
+
if (darwin_has_capture_entitlements ()) {
|
|
2481
|
+
/* request authorization */
|
|
2482
|
+
kresult = IOServiceAuthorize (dpriv->service, kIOServiceInteractionAllowed);
|
|
2483
|
+
if (kresult != kIOReturnSuccess) {
|
|
2484
|
+
usbi_warn (ctx, "IOServiceAuthorize: %s", darwin_error_str(kresult));
|
|
2485
|
+
return darwin_to_libusb (kresult);
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
/* we need start() to be called again for authorization status to refresh */
|
|
2489
|
+
err = darwin_reload_device (dev_handle);
|
|
2490
|
+
if (err != LIBUSB_SUCCESS) {
|
|
2491
|
+
return err;
|
|
2492
|
+
}
|
|
2493
|
+
} else {
|
|
2494
|
+
usbi_info (ctx, "no capture entitlements. may not be able to detach the kernel driver for this device");
|
|
2495
|
+
if (0 != geteuid()) {
|
|
2496
|
+
usbi_warn (ctx, "USB device capture requires either an entitlement (com.apple.vm.device-access) or root privilege");
|
|
2497
|
+
return LIBUSB_ERROR_ACCESS;
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
/* reset device to release existing drivers */
|
|
2502
|
+
err = darwin_reenumerate_device (dev_handle, true);
|
|
2503
|
+
if (err != LIBUSB_SUCCESS) {
|
|
2504
|
+
return err;
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
dpriv->capture_count++;
|
|
2508
|
+
return LIBUSB_SUCCESS;
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
|
|
2512
|
+
static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, uint8_t interface) {
|
|
2513
|
+
UNUSED(interface);
|
|
2514
|
+
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
2515
|
+
|
|
2516
|
+
if (HAS_CAPTURE_DEVICE()) {
|
|
2517
|
+
} else {
|
|
2518
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
dpriv->capture_count--;
|
|
2522
|
+
if (dpriv->capture_count > 0) {
|
|
2523
|
+
return LIBUSB_SUCCESS;
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
usbi_dbg (HANDLE_CTX (dev_handle), "reenumerating device for kernel driver attach");
|
|
2527
|
+
|
|
2528
|
+
/* reset device to attach kernel drivers */
|
|
2529
|
+
return darwin_reenumerate_device (dev_handle, false);
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
static int darwin_capture_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
|
|
2533
|
+
enum libusb_error ret;
|
|
2534
|
+
if (dev_handle->auto_detach_kernel_driver && darwin_kernel_driver_active(dev_handle, iface)) {
|
|
2535
|
+
ret = darwin_detach_kernel_driver (dev_handle, iface);
|
|
2536
|
+
if (ret != LIBUSB_SUCCESS) {
|
|
2537
|
+
usbi_info (HANDLE_CTX (dev_handle), "failed to auto-detach the kernel driver for this device, ret=%d", ret);
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
return darwin_claim_interface (dev_handle, iface);
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
static int darwin_capture_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
|
|
2545
|
+
enum libusb_error ret;
|
|
2546
|
+
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
2547
|
+
|
|
2548
|
+
ret = darwin_release_interface (dev_handle, iface);
|
|
2549
|
+
if (ret != LIBUSB_SUCCESS) {
|
|
2550
|
+
return ret;
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
if (dev_handle->auto_detach_kernel_driver && dpriv->capture_count > 0) {
|
|
2554
|
+
ret = darwin_attach_kernel_driver (dev_handle, iface);
|
|
2555
|
+
if (LIBUSB_SUCCESS != ret) {
|
|
2556
|
+
usbi_info (HANDLE_CTX (dev_handle), "on attempt to reattach the kernel driver got ret=%d", ret);
|
|
2557
|
+
}
|
|
2558
|
+
/* ignore the error as the interface was successfully released */
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
return LIBUSB_SUCCESS;
|
|
2562
|
+
}
|
|
2563
|
+
|
|
2564
|
+
#endif
|
|
2565
|
+
|
|
2250
2566
|
const struct usbi_os_backend usbi_backend = {
|
|
2251
2567
|
.name = "Darwin",
|
|
2252
|
-
.caps =
|
|
2568
|
+
.caps = USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
|
|
2253
2569
|
.init = darwin_init,
|
|
2254
2570
|
.exit = darwin_exit,
|
|
2255
|
-
.get_device_list = NULL, /* not needed */
|
|
2256
|
-
.get_device_descriptor = darwin_get_device_descriptor,
|
|
2257
2571
|
.get_active_config_descriptor = darwin_get_active_config_descriptor,
|
|
2258
2572
|
.get_config_descriptor = darwin_get_config_descriptor,
|
|
2259
2573
|
.hotplug_poll = darwin_hotplug_poll,
|
|
@@ -2262,8 +2576,6 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
2262
2576
|
.close = darwin_close,
|
|
2263
2577
|
.get_configuration = darwin_get_configuration,
|
|
2264
2578
|
.set_configuration = darwin_set_configuration,
|
|
2265
|
-
.claim_interface = darwin_claim_interface,
|
|
2266
|
-
.release_interface = darwin_release_interface,
|
|
2267
2579
|
|
|
2268
2580
|
.set_interface_altsetting = darwin_set_interface_altsetting,
|
|
2269
2581
|
.clear_halt = darwin_clear_halt,
|
|
@@ -2275,19 +2587,24 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
2275
2587
|
#endif
|
|
2276
2588
|
|
|
2277
2589
|
.kernel_driver_active = darwin_kernel_driver_active,
|
|
2590
|
+
|
|
2591
|
+
#if InterfaceVersion >= 700
|
|
2278
2592
|
.detach_kernel_driver = darwin_detach_kernel_driver,
|
|
2279
2593
|
.attach_kernel_driver = darwin_attach_kernel_driver,
|
|
2594
|
+
.claim_interface = darwin_capture_claim_interface,
|
|
2595
|
+
.release_interface = darwin_capture_release_interface,
|
|
2596
|
+
#else
|
|
2597
|
+
.claim_interface = darwin_claim_interface,
|
|
2598
|
+
.release_interface = darwin_release_interface,
|
|
2599
|
+
#endif
|
|
2280
2600
|
|
|
2281
2601
|
.destroy_device = darwin_destroy_device,
|
|
2282
2602
|
|
|
2283
2603
|
.submit_transfer = darwin_submit_transfer,
|
|
2284
2604
|
.cancel_transfer = darwin_cancel_transfer,
|
|
2285
|
-
.clear_transfer_priv = darwin_clear_transfer_priv,
|
|
2286
2605
|
|
|
2287
2606
|
.handle_transfer_completion = darwin_handle_transfer_completion,
|
|
2288
2607
|
|
|
2289
|
-
.clock_gettime = darwin_clock_gettime,
|
|
2290
|
-
|
|
2291
2608
|
.device_priv_size = sizeof(struct darwin_device_priv),
|
|
2292
2609
|
.device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
|
|
2293
2610
|
.transfer_priv_size = sizeof(struct darwin_transfer_priv),
|