usb 1.7.2 → 1.8.1-libusb.4
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/.gitmodules +1 -1
- package/Readme.md +2 -2
- package/binding.gyp +2 -2
- package/libusb/.private/pre-commit.sh +7 -1
- package/libusb/.travis.yml +49 -0
- package/libusb/AUTHORS +44 -3
- package/libusb/Brewfile +4 -0
- package/libusb/ChangeLog +74 -2
- package/libusb/README.md +32 -0
- package/libusb/TODO +1 -1
- package/libusb/Xcode/common.xcconfig +12 -0
- package/libusb/Xcode/config.h +25 -0
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
- package/libusb/android/README +4 -2
- package/libusb/android/config.h +75 -0
- package/libusb/appveyor.yml +41 -0
- package/libusb/appveyor_cygwin.bat +11 -0
- package/libusb/appveyor_minGW.bat +19 -0
- package/libusb/autogen.sh +1 -1
- package/libusb/bootstrap.sh +3 -16
- package/libusb/configure.ac +108 -80
- package/libusb/doc/doxygen.cfg.in +1785 -739
- package/libusb/examples/Makefile.am +1 -1
- package/libusb/examples/dpfp.c +3 -1
- package/libusb/examples/dpfp_threaded.c +23 -10
- package/libusb/examples/ezusb.c +3 -3
- package/libusb/examples/ezusb.h +2 -2
- package/libusb/examples/fxload.c +31 -9
- package/libusb/examples/hotplugtest.c +35 -7
- package/libusb/examples/listdevs.c +3 -1
- package/libusb/examples/sam3u_benchmark.c +3 -3
- package/libusb/examples/testlibusb.c +277 -0
- package/libusb/examples/xusb.c +40 -34
- package/libusb/libusb/Makefile.am +49 -23
- package/libusb/libusb/core.c +855 -457
- package/libusb/libusb/descriptor.c +72 -78
- package/libusb/libusb/hotplug.c +122 -76
- package/libusb/libusb/hotplug.h +42 -25
- package/libusb/libusb/io.c +625 -390
- package/libusb/libusb/libusb-1.0.def +12 -0
- package/libusb/libusb/libusb.h +218 -150
- package/libusb/libusb/libusbi.h +346 -176
- package/libusb/libusb/os/darwin_usb.c +604 -319
- package/libusb/libusb/os/darwin_usb.h +61 -20
- package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
- package/libusb/libusb/os/haiku_usb.h +113 -0
- package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
- package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
- package/libusb/libusb/os/haiku_usb_raw.h +188 -0
- package/libusb/libusb/os/linux_netlink.c +186 -146
- package/libusb/libusb/os/linux_udev.c +36 -14
- package/libusb/libusb/os/linux_usbfs.c +426 -225
- package/libusb/libusb/os/linux_usbfs.h +5 -3
- package/libusb/libusb/os/netbsd_usb.c +21 -77
- package/libusb/libusb/os/openbsd_usb.c +32 -115
- package/libusb/libusb/os/poll_posix.c +38 -5
- package/libusb/libusb/os/poll_posix.h +3 -0
- package/libusb/libusb/os/poll_windows.c +277 -626
- package/libusb/libusb/os/poll_windows.h +11 -44
- package/libusb/libusb/os/sunos_usb.c +1695 -0
- package/libusb/libusb/os/sunos_usb.h +80 -0
- package/libusb/libusb/os/threads_posix.c +24 -26
- package/libusb/libusb/os/threads_posix.h +73 -21
- package/libusb/libusb/os/threads_windows.c +71 -157
- package/libusb/libusb/os/threads_windows.h +68 -44
- package/libusb/libusb/os/wince_usb.c +276 -420
- package/libusb/libusb/os/wince_usb.h +23 -28
- package/libusb/libusb/os/windows_common.h +78 -58
- package/libusb/libusb/os/windows_nt_common.c +1010 -0
- package/libusb/libusb/os/windows_nt_common.h +110 -0
- package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
- package/libusb/libusb/os/windows_usbdk.c +830 -0
- package/libusb/libusb/os/windows_usbdk.h +103 -0
- package/libusb/libusb/os/windows_winusb.c +4391 -0
- package/libusb/libusb/os/windows_winusb.h +783 -0
- package/libusb/libusb/strerror.c +41 -7
- package/libusb/libusb/sync.c +41 -13
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/libusb-1.0.pc.in +1 -1
- package/libusb/msvc/appveyor.bat +27 -0
- package/libusb/msvc/config.h +5 -4
- package/libusb/msvc/ddk_build.cmd +87 -43
- package/libusb/msvc/fxload_2010.vcxproj +24 -104
- package/libusb/msvc/fxload_2012.vcxproj +24 -107
- package/libusb/msvc/fxload_2013.vcxproj +24 -107
- package/libusb/msvc/fxload_2015.vcxproj +91 -0
- package/libusb/msvc/fxload_2017.vcxproj +114 -0
- package/libusb/msvc/fxload_sources +1 -1
- package/libusb/msvc/getopt_2010.vcxproj +16 -75
- package/libusb/msvc/getopt_2012.vcxproj +16 -79
- package/libusb/msvc/getopt_2013.vcxproj +16 -79
- package/libusb/msvc/getopt_2015.vcxproj +73 -0
- package/libusb/msvc/getopt_2017.vcxproj +98 -0
- package/libusb/msvc/getopt_sources +6 -2
- package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
- package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
- package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
- package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
- package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
- package/libusb/msvc/hotplugtest_sources +1 -1
- package/libusb/msvc/libusb_2005.sln +20 -20
- package/libusb/msvc/libusb_2010.sln +57 -46
- package/libusb/msvc/libusb_2012.sln +57 -46
- package/libusb/msvc/libusb_2013.sln +57 -50
- package/libusb/msvc/libusb_2015.sln +59 -52
- package/libusb/msvc/libusb_2017.sln +186 -0
- package/libusb/msvc/libusb_dll.dsp +2 -2
- package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
- package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
- package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
- package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
- package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
- package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
- package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
- package/libusb/msvc/libusb_sources +10 -5
- package/libusb/msvc/libusb_static.dsp +2 -2
- package/libusb/msvc/libusb_static_2005.vcproj +32 -4
- package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
- package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
- package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
- package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
- package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
- package/libusb/msvc/libusb_static_wince.vcproj +20 -26
- package/libusb/msvc/libusb_wince.sln +88 -88
- package/libusb/msvc/listdevs_2010.vcxproj +16 -99
- package/libusb/msvc/listdevs_2012.vcxproj +16 -102
- package/libusb/msvc/listdevs_2013.vcxproj +16 -102
- package/libusb/msvc/listdevs_2015.vcxproj +83 -0
- package/libusb/msvc/listdevs_2017.vcxproj +106 -0
- package/libusb/msvc/listdevs_sources +2 -1
- package/libusb/msvc/stress_2010.vcxproj +20 -101
- package/libusb/msvc/stress_2012.vcxproj +20 -104
- package/libusb/msvc/stress_2013.vcxproj +20 -104
- package/libusb/msvc/stress_2015.vcxproj +87 -0
- package/libusb/msvc/stress_2017.vcxproj +110 -0
- package/libusb/msvc/stress_sources +21 -0
- package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
- package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
- package/libusb/msvc/testlibusb_sources +20 -0
- package/libusb/msvc/xusb_2010.vcxproj +17 -98
- package/libusb/msvc/xusb_2012.vcxproj +17 -101
- package/libusb/msvc/xusb_2013.vcxproj +17 -101
- package/libusb/msvc/xusb_2015.vcxproj +83 -0
- package/libusb/msvc/xusb_2017.vcxproj +106 -0
- package/libusb/msvc/xusb_sources +1 -1
- package/libusb/tests/stress.c +2 -2
- package/libusb/tests/testlib.c +0 -4
- package/libusb/travis-autogen.sh +39 -0
- package/libusb.gypi +13 -2
- package/package.json +20 -11
- 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 +1 -1
- package/usb.js +51 -5
- package/.github/workflows/prebuild.yml +0 -49
- package/libusb/INSTALL +0 -234
- package/libusb/README +0 -28
- package/libusb/libusb/os/windows_usb.c +0 -5347
- package/libusb/libusb/os/windows_usb.h +0 -971
- package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
- package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
- package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
- package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
- package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
- package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
- package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
- package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
- package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
- package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
- package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
- package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
- package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
- package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
- package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* -*- Mode: C; indent-tabs-mode:nil -*- */
|
|
2
2
|
/*
|
|
3
3
|
* darwin backend for libusb 1.0
|
|
4
|
-
* Copyright © 2008-
|
|
4
|
+
* Copyright © 2008-2019 Nathan Hjelm <hjelmn@users.sourceforge.net>
|
|
5
|
+
* Copyright © 2019 Google LLC. All rights reserved.
|
|
5
6
|
*
|
|
6
7
|
* This library is free software; you can redistribute it and/or
|
|
7
8
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -19,6 +20,8 @@
|
|
|
19
20
|
*/
|
|
20
21
|
|
|
21
22
|
#include "config.h"
|
|
23
|
+
#include <assert.h>
|
|
24
|
+
#include <time.h>
|
|
22
25
|
#include <ctype.h>
|
|
23
26
|
#include <errno.h>
|
|
24
27
|
#include <pthread.h>
|
|
@@ -28,32 +31,63 @@
|
|
|
28
31
|
#include <sys/types.h>
|
|
29
32
|
#include <unistd.h>
|
|
30
33
|
#include <fcntl.h>
|
|
31
|
-
#include <
|
|
34
|
+
#include <sys/sysctl.h>
|
|
32
35
|
|
|
33
36
|
#include <mach/clock.h>
|
|
34
37
|
#include <mach/clock_types.h>
|
|
35
38
|
#include <mach/mach_host.h>
|
|
36
39
|
#include <mach/mach_port.h>
|
|
37
40
|
|
|
41
|
+
/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector
|
|
42
|
+
* function. Its use is also conditionalized to only older deployment targets. */
|
|
43
|
+
#define OBJC_SILENCE_GC_DEPRECATIONS 1
|
|
44
|
+
|
|
38
45
|
#include <AvailabilityMacros.h>
|
|
39
|
-
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
46
|
+
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
|
|
40
47
|
#include <objc/objc-auto.h>
|
|
41
48
|
#endif
|
|
42
49
|
|
|
50
|
+
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
|
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
|
|
66
|
+
|
|
67
|
+
/* On 10.12 and later, use newly available clock_*() functions */
|
|
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
|
|
73
|
+
|
|
43
74
|
#include "darwin_usb.h"
|
|
44
75
|
|
|
45
76
|
/* async event thread */
|
|
46
77
|
static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
47
78
|
static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
|
|
48
79
|
|
|
80
|
+
#if !OSX_USE_CLOCK_GETTIME
|
|
49
81
|
static clock_serv_t clock_realtime;
|
|
50
82
|
static clock_serv_t clock_monotonic;
|
|
83
|
+
#endif
|
|
51
84
|
|
|
52
85
|
static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
|
|
53
|
-
static
|
|
86
|
+
static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
|
|
54
87
|
|
|
55
88
|
static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
56
89
|
static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
|
|
90
|
+
static const char *darwin_device_class = kIOUSBDeviceClassName;
|
|
57
91
|
|
|
58
92
|
#define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev))
|
|
59
93
|
|
|
@@ -66,11 +100,15 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
|
|
|
66
100
|
static int darwin_reset_device(struct libusb_device_handle *dev_handle);
|
|
67
101
|
static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0);
|
|
68
102
|
|
|
69
|
-
static
|
|
70
|
-
static
|
|
103
|
+
static enum libusb_error darwin_scan_devices(struct libusb_context *ctx);
|
|
104
|
+
static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
|
|
105
|
+
UInt64 old_session_id);
|
|
106
|
+
|
|
107
|
+
static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
|
|
108
|
+
UInt64 *old_session_id);
|
|
71
109
|
|
|
72
110
|
#if defined(ENABLE_LOGGING)
|
|
73
|
-
static const char *darwin_error_str (
|
|
111
|
+
static const char *darwin_error_str (IOReturn result) {
|
|
74
112
|
static char string_buffer[50];
|
|
75
113
|
switch (result) {
|
|
76
114
|
case kIOReturnSuccess:
|
|
@@ -110,7 +148,7 @@ static const char *darwin_error_str (int result) {
|
|
|
110
148
|
}
|
|
111
149
|
#endif
|
|
112
150
|
|
|
113
|
-
static
|
|
151
|
+
static enum libusb_error darwin_to_libusb (IOReturn result) {
|
|
114
152
|
switch (result) {
|
|
115
153
|
case kIOReturnUnderrun:
|
|
116
154
|
case kIOReturnSuccess:
|
|
@@ -142,7 +180,10 @@ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev)
|
|
|
142
180
|
if (0 == cached_dev->refcount) {
|
|
143
181
|
list_del(&cached_dev->list);
|
|
144
182
|
|
|
145
|
-
(
|
|
183
|
+
if (cached_dev->device) {
|
|
184
|
+
(*(cached_dev->device))->Release(cached_dev->device);
|
|
185
|
+
cached_dev->device = NULL;
|
|
186
|
+
}
|
|
146
187
|
free (cached_dev);
|
|
147
188
|
}
|
|
148
189
|
}
|
|
@@ -157,14 +198,14 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
157
198
|
/* current interface */
|
|
158
199
|
struct darwin_interface *cInterface;
|
|
159
200
|
|
|
160
|
-
|
|
201
|
+
uint8_t i, iface;
|
|
161
202
|
|
|
162
203
|
usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep);
|
|
163
204
|
|
|
164
205
|
for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) {
|
|
165
206
|
cInterface = &priv->interfaces[iface];
|
|
166
207
|
|
|
167
|
-
if (dev_handle->claimed_interfaces & (
|
|
208
|
+
if (dev_handle->claimed_interfaces & (1U << iface)) {
|
|
168
209
|
for (i = 0 ; i < cInterface->num_endpoints ; i++) {
|
|
169
210
|
if (cInterface->endpoint_addrs[i] == ep) {
|
|
170
211
|
*pipep = i + 1;
|
|
@@ -176,7 +217,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
176
217
|
*interface_out = cInterface;
|
|
177
218
|
|
|
178
219
|
usbi_dbg ("pipe %d on interface %d matches", *pipep, iface);
|
|
179
|
-
return
|
|
220
|
+
return LIBUSB_SUCCESS;
|
|
180
221
|
}
|
|
181
222
|
}
|
|
182
223
|
}
|
|
@@ -188,8 +229,8 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
188
229
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
189
230
|
}
|
|
190
231
|
|
|
191
|
-
static
|
|
192
|
-
CFMutableDictionaryRef matchingDict = IOServiceMatching(
|
|
232
|
+
static IOReturn usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
|
|
233
|
+
CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class);
|
|
193
234
|
|
|
194
235
|
if (!matchingDict)
|
|
195
236
|
return kIOReturnError;
|
|
@@ -199,54 +240,91 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 loca
|
|
|
199
240
|
&kCFTypeDictionaryKeyCallBacks,
|
|
200
241
|
&kCFTypeDictionaryValueCallBacks);
|
|
201
242
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
|
|
243
|
+
/* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this
|
|
244
|
+
internally (CFNumberType of locationID is kCFNumberSInt32Type) */
|
|
245
|
+
CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
|
|
206
246
|
|
|
247
|
+
if (propertyMatchDict && locationCF) {
|
|
207
248
|
CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
|
|
208
|
-
/* release our reference to the CFNumber (CFDictionarySetValue retains it) */
|
|
209
|
-
CFRelease (locationCF);
|
|
210
|
-
|
|
211
249
|
CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
|
|
212
|
-
/* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */
|
|
213
|
-
CFRelease (propertyMatchDict);
|
|
214
250
|
}
|
|
215
251
|
/* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */
|
|
252
|
+
|
|
253
|
+
/* release our references as per the Create Rule */
|
|
254
|
+
if (propertyMatchDict)
|
|
255
|
+
CFRelease (propertyMatchDict);
|
|
256
|
+
if (locationCF)
|
|
257
|
+
CFRelease (locationCF);
|
|
216
258
|
}
|
|
217
259
|
|
|
218
260
|
return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
|
|
219
261
|
}
|
|
220
262
|
|
|
221
263
|
/* Returns 1 on success, 0 on failure. */
|
|
222
|
-
static
|
|
264
|
+
static bool get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
|
|
223
265
|
CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
|
|
224
|
-
|
|
266
|
+
Boolean success = 0;
|
|
225
267
|
|
|
226
268
|
if (cfNumber) {
|
|
227
269
|
if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) {
|
|
228
|
-
|
|
270
|
+
success = CFNumberGetValue(cfNumber, type, p);
|
|
229
271
|
}
|
|
230
272
|
|
|
231
273
|
CFRelease (cfNumber);
|
|
232
274
|
}
|
|
233
275
|
|
|
234
|
-
return
|
|
276
|
+
return (success != 0);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Returns 1 on success, 0 on failure. */
|
|
280
|
+
static bool get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) {
|
|
281
|
+
CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
|
|
282
|
+
bool success = false;
|
|
283
|
+
|
|
284
|
+
if (cfData) {
|
|
285
|
+
if (CFGetTypeID (cfData) == CFDataGetTypeID ()) {
|
|
286
|
+
CFIndex length = CFDataGetLength (cfData);
|
|
287
|
+
if (length < size) {
|
|
288
|
+
size = length;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
CFDataGetBytes (cfData, CFRangeMake(0, size), p);
|
|
292
|
+
success = true;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
CFRelease (cfData);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return success;
|
|
235
299
|
}
|
|
236
300
|
|
|
237
301
|
static usb_device_t **darwin_device_from_service (io_service_t service)
|
|
238
302
|
{
|
|
239
303
|
io_cf_plugin_ref_t *plugInInterface = NULL;
|
|
240
304
|
usb_device_t **device;
|
|
241
|
-
|
|
305
|
+
IOReturn kresult;
|
|
242
306
|
SInt32 score;
|
|
307
|
+
const int max_retries = 5;
|
|
308
|
+
|
|
309
|
+
/* The IOCreatePlugInInterfaceForService function might consistently return
|
|
310
|
+
an "out of resources" error with certain USB devices the first time we run
|
|
311
|
+
it. The reason is still unclear, but retrying fixes the problem */
|
|
312
|
+
for (int count = 0; count < max_retries; count++) {
|
|
313
|
+
kresult = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
|
|
314
|
+
kIOCFPlugInInterfaceID, &plugInInterface,
|
|
315
|
+
&score);
|
|
316
|
+
if (kIOReturnSuccess == kresult && plugInInterface) {
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
243
319
|
|
|
244
|
-
|
|
245
|
-
kIOCFPlugInInterfaceID, &plugInInterface,
|
|
246
|
-
&score);
|
|
320
|
+
usbi_dbg ("set up plugin for service retry: %s", darwin_error_str (kresult));
|
|
247
321
|
|
|
248
|
-
|
|
249
|
-
|
|
322
|
+
/* sleep for a little while before trying again */
|
|
323
|
+
nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (kIOReturnSuccess != kresult || !plugInInterface) {
|
|
327
|
+
usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (kresult));
|
|
250
328
|
return NULL;
|
|
251
329
|
}
|
|
252
330
|
|
|
@@ -259,15 +337,29 @@ static usb_device_t **darwin_device_from_service (io_service_t service)
|
|
|
259
337
|
}
|
|
260
338
|
|
|
261
339
|
static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
|
|
340
|
+
UNUSED(ptr);
|
|
341
|
+
struct darwin_cached_device *cached_device;
|
|
342
|
+
UInt64 old_session_id;
|
|
262
343
|
struct libusb_context *ctx;
|
|
263
344
|
io_service_t service;
|
|
345
|
+
int ret;
|
|
264
346
|
|
|
265
347
|
usbi_mutex_lock(&active_contexts_lock);
|
|
266
348
|
|
|
267
349
|
while ((service = IOIteratorNext(add_devices))) {
|
|
350
|
+
ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
|
|
351
|
+
if (ret < 0 || !cached_device->can_enumerate) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
|
|
268
355
|
/* add this device to each active context's device list */
|
|
269
356
|
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
|
|
270
|
-
process_new_device (ctx,
|
|
357
|
+
process_new_device (ctx, cached_device, old_session_id);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (cached_device->in_reenumerate) {
|
|
361
|
+
usbi_dbg ("cached device in reset state. reset complete...");
|
|
362
|
+
cached_device->in_reenumerate = false;
|
|
271
363
|
}
|
|
272
364
|
|
|
273
365
|
IOObjectRelease(service);
|
|
@@ -277,8 +369,10 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
|
|
|
277
369
|
}
|
|
278
370
|
|
|
279
371
|
static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
372
|
+
UNUSED(ptr);
|
|
280
373
|
struct libusb_device *dev = NULL;
|
|
281
374
|
struct libusb_context *ctx;
|
|
375
|
+
struct darwin_cached_device *old_device;
|
|
282
376
|
|
|
283
377
|
io_service_t device;
|
|
284
378
|
UInt64 session;
|
|
@@ -287,12 +381,44 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
287
381
|
usbi_mutex_lock(&active_contexts_lock);
|
|
288
382
|
|
|
289
383
|
while ((device = IOIteratorNext (rem_devices)) != 0) {
|
|
384
|
+
bool is_reenumerating = false;
|
|
385
|
+
|
|
290
386
|
/* get the location from the i/o registry */
|
|
291
387
|
ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
|
|
292
388
|
IOObjectRelease (device);
|
|
293
389
|
if (!ret)
|
|
294
390
|
continue;
|
|
295
391
|
|
|
392
|
+
/* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function
|
|
393
|
+
otherwise no cached device will ever get freed */
|
|
394
|
+
usbi_mutex_lock(&darwin_cached_devices_lock);
|
|
395
|
+
list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
396
|
+
if (old_device->session == session) {
|
|
397
|
+
if (old_device->in_reenumerate) {
|
|
398
|
+
/* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
|
|
399
|
+
* will deref if needed. */
|
|
400
|
+
usbi_dbg ("detected device detatched due to re-enumeration");
|
|
401
|
+
|
|
402
|
+
/* the device object is no longer usable so go ahead and release it */
|
|
403
|
+
if (old_device->device) {
|
|
404
|
+
(*(old_device->device))->Release(old_device->device);
|
|
405
|
+
old_device->device = NULL;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
is_reenumerating = true;
|
|
409
|
+
} else {
|
|
410
|
+
darwin_deref_cached_device (old_device);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
usbi_mutex_unlock(&darwin_cached_devices_lock);
|
|
418
|
+
if (is_reenumerating) {
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
|
|
296
422
|
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
|
|
297
423
|
usbi_dbg ("notifying context %p of device disconnect", ctx);
|
|
298
424
|
|
|
@@ -311,11 +437,11 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
311
437
|
|
|
312
438
|
static void darwin_hotplug_poll (void)
|
|
313
439
|
{
|
|
314
|
-
/* not sure if
|
|
315
|
-
mach_timespec_t timeout = {.tv_sec =
|
|
440
|
+
/* not sure if 1 ms will be too long/short but it should work ok */
|
|
441
|
+
mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000ul};
|
|
316
442
|
|
|
317
|
-
/* since a kernel thread may
|
|
318
|
-
* hotplug
|
|
443
|
+
/* since a kernel thread may notify the IOIterators used for
|
|
444
|
+
* hotplug notification we can't just clear the iterators.
|
|
319
445
|
* instead just wait until all IOService providers are quiet */
|
|
320
446
|
(void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout);
|
|
321
447
|
}
|
|
@@ -332,19 +458,24 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
332
458
|
struct libusb_context *ctx = (struct libusb_context *)arg0;
|
|
333
459
|
CFRunLoopRef runloop;
|
|
334
460
|
|
|
461
|
+
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
335
462
|
/* Set this thread's name, so it can be seen in the debugger
|
|
336
463
|
and crash reports. */
|
|
337
|
-
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
338
464
|
pthread_setname_np ("org.libusb.device-hotplug");
|
|
465
|
+
#endif
|
|
339
466
|
|
|
467
|
+
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
|
|
340
468
|
/* Tell the Objective-C garbage collector about this thread.
|
|
341
469
|
This is required because, unlike NSThreads, pthreads are
|
|
342
470
|
not automatically registered. Although we don't use
|
|
343
|
-
Objective-C, we use CoreFoundation, which does.
|
|
471
|
+
Objective-C, we use CoreFoundation, which does.
|
|
472
|
+
Garbage collection support was entirely removed in 10.12,
|
|
473
|
+
so don't bother there. */
|
|
344
474
|
objc_registerThreadWithCollector();
|
|
345
475
|
#endif
|
|
346
476
|
|
|
347
477
|
/* hotplug (device arrival/removal) sources */
|
|
478
|
+
CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
|
|
348
479
|
CFRunLoopSourceRef libusb_notification_cfsource;
|
|
349
480
|
io_notification_port_t libusb_notification_port;
|
|
350
481
|
io_iterator_t libusb_rem_device_iterator;
|
|
@@ -355,6 +486,13 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
355
486
|
runloop = CFRunLoopGetCurrent ();
|
|
356
487
|
CFRetain (runloop);
|
|
357
488
|
|
|
489
|
+
/* add the shutdown cfsource to the run loop */
|
|
490
|
+
memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
|
|
491
|
+
libusb_shutdown_cfsourcectx.info = runloop;
|
|
492
|
+
libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
|
|
493
|
+
libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
|
|
494
|
+
CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
|
|
495
|
+
|
|
358
496
|
/* add the notification port to the run loop */
|
|
359
497
|
libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault);
|
|
360
498
|
libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port);
|
|
@@ -362,7 +500,7 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
362
500
|
|
|
363
501
|
/* create notifications for removed devices */
|
|
364
502
|
kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification,
|
|
365
|
-
IOServiceMatching(
|
|
503
|
+
IOServiceMatching(darwin_device_class),
|
|
366
504
|
darwin_devices_detached,
|
|
367
505
|
ctx, &libusb_rem_device_iterator);
|
|
368
506
|
|
|
@@ -374,7 +512,7 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
374
512
|
|
|
375
513
|
/* create notifications for attached devices */
|
|
376
514
|
kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification,
|
|
377
|
-
IOServiceMatching(
|
|
515
|
+
IOServiceMatching(darwin_device_class),
|
|
378
516
|
darwin_devices_attached,
|
|
379
517
|
ctx, &libusb_add_device_iterator);
|
|
380
518
|
|
|
@@ -404,6 +542,9 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
404
542
|
/* remove the notification cfsource */
|
|
405
543
|
CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
|
|
406
544
|
|
|
545
|
+
/* remove the shutdown cfsource */
|
|
546
|
+
CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
|
|
547
|
+
|
|
407
548
|
/* delete notification port */
|
|
408
549
|
IONotificationPortDestroy (libusb_notification_port);
|
|
409
550
|
|
|
@@ -411,8 +552,10 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
411
552
|
IOObjectRelease (libusb_rem_device_iterator);
|
|
412
553
|
IOObjectRelease (libusb_add_device_iterator);
|
|
413
554
|
|
|
555
|
+
CFRelease (libusb_darwin_acfls);
|
|
414
556
|
CFRelease (runloop);
|
|
415
557
|
|
|
558
|
+
libusb_darwin_acfls = NULL;
|
|
416
559
|
libusb_darwin_acfl = NULL;
|
|
417
560
|
|
|
418
561
|
pthread_exit (NULL);
|
|
@@ -430,7 +573,6 @@ static void __attribute__((destructor)) _darwin_finalize(void) {
|
|
|
430
573
|
}
|
|
431
574
|
|
|
432
575
|
static int darwin_init(struct libusb_context *ctx) {
|
|
433
|
-
host_name_port_t host_self;
|
|
434
576
|
int rc;
|
|
435
577
|
|
|
436
578
|
rc = darwin_scan_devices (ctx);
|
|
@@ -438,13 +580,16 @@ static int darwin_init(struct libusb_context *ctx) {
|
|
|
438
580
|
return rc;
|
|
439
581
|
}
|
|
440
582
|
|
|
441
|
-
if (
|
|
442
|
-
|
|
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;
|
|
443
587
|
|
|
444
588
|
host_self = mach_host_self();
|
|
445
589
|
host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
|
|
446
590
|
host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
|
|
447
591
|
mach_port_deallocate(mach_task_self(), host_self);
|
|
592
|
+
#endif
|
|
448
593
|
|
|
449
594
|
pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
|
|
450
595
|
|
|
@@ -457,13 +602,17 @@ static int darwin_init(struct libusb_context *ctx) {
|
|
|
457
602
|
return rc;
|
|
458
603
|
}
|
|
459
604
|
|
|
460
|
-
static void darwin_exit (
|
|
461
|
-
|
|
605
|
+
static void darwin_exit (struct libusb_context *ctx) {
|
|
606
|
+
UNUSED(ctx);
|
|
607
|
+
if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) {
|
|
608
|
+
#if !OSX_USE_CLOCK_GETTIME
|
|
462
609
|
mach_port_deallocate(mach_task_self(), clock_realtime);
|
|
463
610
|
mach_port_deallocate(mach_task_self(), clock_monotonic);
|
|
611
|
+
#endif
|
|
464
612
|
|
|
465
613
|
/* stop the event runloop and wait for the thread to terminate. */
|
|
466
|
-
|
|
614
|
+
CFRunLoopSourceSignal(libusb_darwin_acfls);
|
|
615
|
+
CFRunLoopWakeUp (libusb_darwin_acfl);
|
|
467
616
|
pthread_join (libusb_darwin_at, NULL);
|
|
468
617
|
}
|
|
469
618
|
}
|
|
@@ -476,7 +625,7 @@ static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char
|
|
|
476
625
|
|
|
477
626
|
*host_endian = 0;
|
|
478
627
|
|
|
479
|
-
return
|
|
628
|
+
return LIBUSB_SUCCESS;
|
|
480
629
|
}
|
|
481
630
|
|
|
482
631
|
static int get_configuration_index (struct libusb_device *dev, int config_value) {
|
|
@@ -512,7 +661,8 @@ static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsign
|
|
|
512
661
|
if (config_index < 0)
|
|
513
662
|
return config_index;
|
|
514
663
|
|
|
515
|
-
|
|
664
|
+
assert(config_index >= 0 && config_index <= UINT8_MAX);
|
|
665
|
+
return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len, host_endian);
|
|
516
666
|
}
|
|
517
667
|
|
|
518
668
|
static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) {
|
|
@@ -544,12 +694,12 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi
|
|
|
544
694
|
}
|
|
545
695
|
|
|
546
696
|
/* check whether the os has configured the device */
|
|
547
|
-
static
|
|
697
|
+
static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
|
|
548
698
|
usb_device_t **darwin_device = dev->device;
|
|
549
699
|
|
|
550
700
|
IOUSBConfigurationDescriptorPtr configDesc;
|
|
551
701
|
IOUSBFindInterfaceRequest request;
|
|
552
|
-
|
|
702
|
+
IOReturn kresult;
|
|
553
703
|
io_iterator_t interface_iterator;
|
|
554
704
|
io_service_t firstInterface;
|
|
555
705
|
|
|
@@ -558,6 +708,14 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin
|
|
|
558
708
|
return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */
|
|
559
709
|
}
|
|
560
710
|
|
|
711
|
+
/* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is
|
|
712
|
+
not usable anyway */
|
|
713
|
+
if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) {
|
|
714
|
+
usbi_dbg ("ignoring configuration on root hub simulation");
|
|
715
|
+
dev->active_config = 0;
|
|
716
|
+
return LIBUSB_SUCCESS;
|
|
717
|
+
}
|
|
718
|
+
|
|
561
719
|
/* find the first configuration */
|
|
562
720
|
kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc);
|
|
563
721
|
dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1;
|
|
@@ -573,7 +731,7 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin
|
|
|
573
731
|
request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
|
|
574
732
|
|
|
575
733
|
kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
|
|
576
|
-
if (kresult)
|
|
734
|
+
if (kresult != kIOReturnSuccess)
|
|
577
735
|
return darwin_to_libusb (kresult);
|
|
578
736
|
|
|
579
737
|
/* iterate once */
|
|
@@ -598,20 +756,22 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin
|
|
|
598
756
|
|
|
599
757
|
usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config);
|
|
600
758
|
|
|
601
|
-
return
|
|
759
|
+
return LIBUSB_SUCCESS;
|
|
602
760
|
}
|
|
603
761
|
|
|
604
|
-
static
|
|
762
|
+
static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
|
|
605
763
|
IOUSBDevRequestTO req;
|
|
606
764
|
|
|
765
|
+
assert(buffer_size <= UINT16_MAX);
|
|
766
|
+
|
|
607
767
|
memset (buffer, 0, buffer_size);
|
|
608
768
|
|
|
609
769
|
/* Set up request for descriptor/ */
|
|
610
770
|
req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
|
|
611
771
|
req.bRequest = kUSBRqGetDescriptor;
|
|
612
|
-
req.wValue = desc << 8;
|
|
772
|
+
req.wValue = (UInt16)(desc << 8);
|
|
613
773
|
req.wIndex = desc_index;
|
|
614
|
-
req.wLength = buffer_size;
|
|
774
|
+
req.wLength = (UInt16)buffer_size;
|
|
615
775
|
req.pData = buffer;
|
|
616
776
|
req.noDataTimeout = 20;
|
|
617
777
|
req.completionTimeout = 100;
|
|
@@ -619,12 +779,13 @@ static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 d
|
|
|
619
779
|
return (*device)->DeviceRequestTO (device, &req);
|
|
620
780
|
}
|
|
621
781
|
|
|
622
|
-
static
|
|
782
|
+
static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_device *dev) {
|
|
623
783
|
usb_device_t **device = dev->device;
|
|
624
|
-
int retries = 1
|
|
784
|
+
int retries = 1;
|
|
785
|
+
long delay = 30000; // microseconds
|
|
625
786
|
int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
|
|
626
787
|
int is_open = 0;
|
|
627
|
-
|
|
788
|
+
IOReturn ret = 0, ret2;
|
|
628
789
|
UInt8 bDeviceClass;
|
|
629
790
|
UInt16 idProduct, idVendor;
|
|
630
791
|
|
|
@@ -677,7 +838,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
|
|
|
677
838
|
(void)(*device)->GetUSBDeviceInformation (device, &info);
|
|
678
839
|
|
|
679
840
|
/* note that the device was suspended */
|
|
680
|
-
if (info & (
|
|
841
|
+
if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
|
|
681
842
|
try_unsuspend = 1;
|
|
682
843
|
#endif
|
|
683
844
|
|
|
@@ -696,9 +857,9 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
|
|
|
696
857
|
}
|
|
697
858
|
|
|
698
859
|
if (kIOReturnSuccess != ret) {
|
|
699
|
-
usbi_dbg("kernel responded with code: 0x%08x. sleeping for %
|
|
860
|
+
usbi_dbg("kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
|
|
700
861
|
/* sleep for a little while before trying again */
|
|
701
|
-
|
|
862
|
+
nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000}, NULL);
|
|
702
863
|
}
|
|
703
864
|
} while (kIOReturnSuccess != ret && retries--);
|
|
704
865
|
|
|
@@ -715,7 +876,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
|
|
|
715
876
|
usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
|
|
716
877
|
idVendor, idProduct, darwin_error_str (ret), ret);
|
|
717
878
|
else
|
|
718
|
-
usbi_warn (
|
|
879
|
+
usbi_warn (NULL, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
|
|
719
880
|
idVendor, idProduct, darwin_error_str (ret), ret);
|
|
720
881
|
return darwin_to_libusb (ret);
|
|
721
882
|
}
|
|
@@ -723,7 +884,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
|
|
|
723
884
|
/* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */
|
|
724
885
|
if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) {
|
|
725
886
|
/* not a valid device */
|
|
726
|
-
usbi_warn (
|
|
887
|
+
usbi_warn (NULL, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device",
|
|
727
888
|
idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
|
|
728
889
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
729
890
|
}
|
|
@@ -748,35 +909,80 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
|
|
|
748
909
|
return LIBUSB_SUCCESS;
|
|
749
910
|
}
|
|
750
911
|
|
|
751
|
-
|
|
752
|
-
|
|
912
|
+
/* Returns 1 on success, 0 on failure. */
|
|
913
|
+
static bool get_device_port (io_service_t service, UInt8 *port) {
|
|
914
|
+
IOReturn kresult;
|
|
915
|
+
io_service_t parent;
|
|
916
|
+
bool ret = false;
|
|
917
|
+
|
|
918
|
+
if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) {
|
|
919
|
+
return true;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
kresult = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
|
|
923
|
+
if (kIOReturnSuccess == kresult) {
|
|
924
|
+
ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port);
|
|
925
|
+
IOObjectRelease (parent);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
return ret;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/* Returns 1 on success, 0 on failure. */
|
|
932
|
+
static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) {
|
|
933
|
+
IOReturn kresult;
|
|
934
|
+
io_service_t parent;
|
|
935
|
+
|
|
936
|
+
/* Walk up the tree in the IOService plane until we find a parent that has a sessionID */
|
|
937
|
+
parent = service;
|
|
938
|
+
while((kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent)) == kIOReturnSuccess) {
|
|
939
|
+
if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) {
|
|
940
|
+
/* Success */
|
|
941
|
+
return true;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/* We ran out of parents */
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
|
|
950
|
+
UInt64 *old_session_id) {
|
|
753
951
|
struct darwin_cached_device *new_device;
|
|
754
952
|
UInt64 sessionID = 0, parent_sessionID = 0;
|
|
755
|
-
|
|
953
|
+
UInt32 locationID = 0;
|
|
954
|
+
enum libusb_error ret = LIBUSB_SUCCESS;
|
|
756
955
|
usb_device_t **device;
|
|
757
|
-
io_service_t parent;
|
|
758
|
-
kern_return_t result;
|
|
759
956
|
UInt8 port = 0;
|
|
760
957
|
|
|
958
|
+
/* assuming sessionID != 0 normally (never seen it be 0) */
|
|
959
|
+
*old_session_id = 0;
|
|
960
|
+
*cached_out = NULL;
|
|
961
|
+
|
|
761
962
|
/* get some info from the io registry */
|
|
762
963
|
(void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
|
|
763
|
-
(void) get_ioregistry_value_number (service, CFSTR("
|
|
964
|
+
(void) get_ioregistry_value_number (service, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
|
|
965
|
+
if (!get_device_port (service, &port)) {
|
|
966
|
+
usbi_dbg("could not get connected port number");
|
|
967
|
+
}
|
|
764
968
|
|
|
765
969
|
usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID);
|
|
766
970
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
if (kIOReturnSuccess == result) {
|
|
770
|
-
(void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID);
|
|
771
|
-
IOObjectRelease(parent);
|
|
971
|
+
if (get_device_parent_sessionID(service, &parent_sessionID)) {
|
|
972
|
+
usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID);
|
|
772
973
|
}
|
|
773
974
|
|
|
774
975
|
usbi_mutex_lock(&darwin_cached_devices_lock);
|
|
775
976
|
do {
|
|
776
|
-
*cached_out = NULL;
|
|
777
|
-
|
|
778
977
|
list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
779
|
-
usbi_dbg("matching sessionID 0x%" PRIx64 " against cached device with sessionID 0x%" PRIx64
|
|
978
|
+
usbi_dbg("matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
|
|
979
|
+
sessionID, locationID, new_device->session, new_device->location);
|
|
980
|
+
if (new_device->location == locationID && new_device->in_reenumerate) {
|
|
981
|
+
usbi_dbg ("found cached device with matching location that is being re-enumerated");
|
|
982
|
+
*old_session_id = new_device->session;
|
|
983
|
+
break;
|
|
984
|
+
}
|
|
985
|
+
|
|
780
986
|
if (new_device->session == sessionID) {
|
|
781
987
|
usbi_dbg("using cached device for device");
|
|
782
988
|
*cached_out = new_device;
|
|
@@ -795,28 +1001,35 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
|
|
|
795
1001
|
break;
|
|
796
1002
|
}
|
|
797
1003
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
1004
|
+
if (!(*old_session_id)) {
|
|
1005
|
+
new_device = calloc (1, sizeof (*new_device));
|
|
1006
|
+
if (!new_device) {
|
|
1007
|
+
ret = LIBUSB_ERROR_NO_MEM;
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
803
1010
|
|
|
804
|
-
|
|
805
|
-
|
|
1011
|
+
/* add this device to the cached device list */
|
|
1012
|
+
list_add(&new_device->list, &darwin_cached_devices);
|
|
806
1013
|
|
|
807
|
-
|
|
1014
|
+
(*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address);
|
|
808
1015
|
|
|
809
|
-
|
|
810
|
-
|
|
1016
|
+
/* keep a reference to this device */
|
|
1017
|
+
darwin_ref_cached_device(new_device);
|
|
1018
|
+
|
|
1019
|
+
(*device)->GetLocationID (device, &new_device->location);
|
|
1020
|
+
new_device->port = port;
|
|
1021
|
+
new_device->parent_session = parent_sessionID;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/* keep track of devices regardless of if we successfully enumerate them to
|
|
1025
|
+
prevent them from being enumerated multiple times */
|
|
1026
|
+
*cached_out = new_device;
|
|
811
1027
|
|
|
812
|
-
new_device->device = device;
|
|
813
1028
|
new_device->session = sessionID;
|
|
814
|
-
|
|
815
|
-
new_device->port = port;
|
|
816
|
-
new_device->parent_session = parent_sessionID;
|
|
1029
|
+
new_device->device = device;
|
|
817
1030
|
|
|
818
1031
|
/* cache the device descriptor */
|
|
819
|
-
ret = darwin_cache_device_descriptor(
|
|
1032
|
+
ret = darwin_cache_device_descriptor(new_device);
|
|
820
1033
|
if (ret)
|
|
821
1034
|
break;
|
|
822
1035
|
|
|
@@ -829,55 +1042,56 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
|
|
|
829
1042
|
|
|
830
1043
|
usbi_mutex_unlock(&darwin_cached_devices_lock);
|
|
831
1044
|
|
|
832
|
-
/* keep track of devices regardless of if we successfully enumerate them to
|
|
833
|
-
prevent them from being enumerated multiple times */
|
|
834
|
-
|
|
835
|
-
*cached_out = new_device;
|
|
836
|
-
|
|
837
1045
|
return ret;
|
|
838
1046
|
}
|
|
839
1047
|
|
|
840
|
-
static
|
|
1048
|
+
static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
|
|
1049
|
+
UInt64 old_session_id) {
|
|
841
1050
|
struct darwin_device_priv *priv;
|
|
842
1051
|
struct libusb_device *dev = NULL;
|
|
843
|
-
struct darwin_cached_device *cached_device;
|
|
844
1052
|
UInt8 devSpeed;
|
|
845
|
-
|
|
1053
|
+
enum libusb_error ret = LIBUSB_SUCCESS;
|
|
846
1054
|
|
|
847
1055
|
do {
|
|
848
|
-
ret = darwin_get_cached_device (ctx, service, &cached_device);
|
|
849
|
-
|
|
850
|
-
if (ret < 0 || !cached_device->can_enumerate) {
|
|
851
|
-
return ret;
|
|
852
|
-
}
|
|
853
|
-
|
|
854
1056
|
/* check current active configuration (and cache the first configuration value--
|
|
855
1057
|
which may be used by claim_interface) */
|
|
856
1058
|
ret = darwin_check_configuration (ctx, cached_device);
|
|
857
1059
|
if (ret)
|
|
858
1060
|
break;
|
|
859
1061
|
|
|
860
|
-
|
|
861
|
-
|
|
1062
|
+
if (0 != old_session_id) {
|
|
1063
|
+
usbi_dbg ("re-using existing device from context %p for with session 0x%" PRIx64 " new session 0x%" PRIx64,
|
|
1064
|
+
ctx, old_session_id, cached_device->session);
|
|
1065
|
+
/* save the libusb device before the session id is updated */
|
|
1066
|
+
dev = usbi_get_device_by_session_id (ctx, (unsigned long) old_session_id);
|
|
1067
|
+
}
|
|
862
1068
|
|
|
863
|
-
dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
|
|
864
1069
|
if (!dev) {
|
|
865
|
-
|
|
866
|
-
|
|
1070
|
+
usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64,
|
|
1071
|
+
ctx, cached_device->session);
|
|
1072
|
+
|
|
1073
|
+
dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
|
|
1074
|
+
if (!dev) {
|
|
1075
|
+
return LIBUSB_ERROR_NO_MEM;
|
|
1076
|
+
}
|
|
867
1077
|
|
|
868
|
-
|
|
1078
|
+
priv = (struct darwin_device_priv *)dev->os_priv;
|
|
869
1079
|
|
|
870
|
-
|
|
871
|
-
|
|
1080
|
+
priv->dev = cached_device;
|
|
1081
|
+
darwin_ref_cached_device (priv->dev);
|
|
1082
|
+
dev->port_number = cached_device->port;
|
|
1083
|
+
dev->bus_number = cached_device->location >> 24;
|
|
1084
|
+
assert(cached_device->address <= UINT8_MAX);
|
|
1085
|
+
dev->device_address = (uint8_t)cached_device->address;
|
|
1086
|
+
} else {
|
|
1087
|
+
priv = (struct darwin_device_priv *)dev->os_priv;
|
|
1088
|
+
}
|
|
872
1089
|
|
|
873
1090
|
if (cached_device->parent_session > 0) {
|
|
874
1091
|
dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
|
|
875
1092
|
} else {
|
|
876
1093
|
dev->parent_dev = NULL;
|
|
877
1094
|
}
|
|
878
|
-
dev->port_number = cached_device->port;
|
|
879
|
-
dev->bus_number = cached_device->location >> 24;
|
|
880
|
-
dev->device_address = cached_device->address;
|
|
881
1095
|
|
|
882
1096
|
(*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed);
|
|
883
1097
|
|
|
@@ -885,8 +1099,11 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
|
|
|
885
1099
|
case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
|
|
886
1100
|
case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break;
|
|
887
1101
|
case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break;
|
|
888
|
-
#if
|
|
1102
|
+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
|
889
1103
|
case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
|
|
1104
|
+
#endif
|
|
1105
|
+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
|
1106
|
+
case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
|
|
890
1107
|
#endif
|
|
891
1108
|
default:
|
|
892
1109
|
usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
|
|
@@ -898,9 +1115,10 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
|
|
|
898
1115
|
|
|
899
1116
|
usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address,
|
|
900
1117
|
dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path);
|
|
1118
|
+
|
|
901
1119
|
} while (0);
|
|
902
1120
|
|
|
903
|
-
if (0 == ret) {
|
|
1121
|
+
if (!cached_device->in_reenumerate && 0 == ret) {
|
|
904
1122
|
usbi_connect_device (dev);
|
|
905
1123
|
} else {
|
|
906
1124
|
libusb_unref_device (dev);
|
|
@@ -909,24 +1127,32 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
|
|
|
909
1127
|
return ret;
|
|
910
1128
|
}
|
|
911
1129
|
|
|
912
|
-
static
|
|
1130
|
+
static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
|
|
1131
|
+
struct darwin_cached_device *cached_device;
|
|
1132
|
+
UInt64 old_session_id;
|
|
913
1133
|
io_iterator_t deviceIterator;
|
|
914
1134
|
io_service_t service;
|
|
915
|
-
|
|
1135
|
+
IOReturn kresult;
|
|
1136
|
+
int ret;
|
|
916
1137
|
|
|
917
1138
|
kresult = usb_setup_device_iterator (&deviceIterator, 0);
|
|
918
1139
|
if (kresult != kIOReturnSuccess)
|
|
919
1140
|
return darwin_to_libusb (kresult);
|
|
920
1141
|
|
|
921
1142
|
while ((service = IOIteratorNext (deviceIterator))) {
|
|
922
|
-
|
|
1143
|
+
ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
|
|
1144
|
+
if (ret < 0 || !cached_device->can_enumerate) {
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
(void) process_new_device (ctx, cached_device, old_session_id);
|
|
923
1149
|
|
|
924
1150
|
IOObjectRelease(service);
|
|
925
1151
|
}
|
|
926
1152
|
|
|
927
1153
|
IOObjectRelease(deviceIterator);
|
|
928
1154
|
|
|
929
|
-
return
|
|
1155
|
+
return LIBUSB_SUCCESS;
|
|
930
1156
|
}
|
|
931
1157
|
|
|
932
1158
|
static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
@@ -945,9 +1171,9 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
945
1171
|
}
|
|
946
1172
|
|
|
947
1173
|
/* it is possible to perform some actions on a device that is not open so do not return an error */
|
|
948
|
-
priv->is_open =
|
|
1174
|
+
priv->is_open = false;
|
|
949
1175
|
} else {
|
|
950
|
-
priv->is_open =
|
|
1176
|
+
priv->is_open = true;
|
|
951
1177
|
}
|
|
952
1178
|
|
|
953
1179
|
/* create async event source */
|
|
@@ -959,7 +1185,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
959
1185
|
(*(dpriv->device))->USBDeviceClose (dpriv->device);
|
|
960
1186
|
}
|
|
961
1187
|
|
|
962
|
-
priv->is_open =
|
|
1188
|
+
priv->is_open = false;
|
|
963
1189
|
|
|
964
1190
|
return darwin_to_libusb (kresult);
|
|
965
1191
|
}
|
|
@@ -973,14 +1199,6 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
973
1199
|
/* device opened successfully */
|
|
974
1200
|
dpriv->open_count++;
|
|
975
1201
|
|
|
976
|
-
/* create a file descriptor for notifications */
|
|
977
|
-
pipe (priv->fds);
|
|
978
|
-
|
|
979
|
-
/* set the pipe to be non-blocking */
|
|
980
|
-
fcntl (priv->fds[1], F_SETFD, O_NONBLOCK);
|
|
981
|
-
|
|
982
|
-
usbi_add_pollfd(HANDLE_CTX(dev_handle), priv->fds[0], POLLIN);
|
|
983
|
-
|
|
984
1202
|
usbi_dbg ("device open for access");
|
|
985
1203
|
|
|
986
1204
|
return 0;
|
|
@@ -994,7 +1212,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
|
|
|
994
1212
|
|
|
995
1213
|
if (dpriv->open_count == 0) {
|
|
996
1214
|
/* something is probably very wrong if this is the case */
|
|
997
|
-
usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open
|
|
1215
|
+
usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!");
|
|
998
1216
|
return;
|
|
999
1217
|
}
|
|
1000
1218
|
|
|
@@ -1002,7 +1220,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
|
|
|
1002
1220
|
|
|
1003
1221
|
/* make sure all interfaces are released */
|
|
1004
1222
|
for (i = 0 ; i < USB_MAXINTERFACES ; i++)
|
|
1005
|
-
if (dev_handle->claimed_interfaces & (
|
|
1223
|
+
if (dev_handle->claimed_interfaces & (1U << i))
|
|
1006
1224
|
libusb_release_interface (dev_handle, i);
|
|
1007
1225
|
|
|
1008
1226
|
if (0 == dpriv->open_count) {
|
|
@@ -1017,20 +1235,13 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
|
|
|
1017
1235
|
if (priv->is_open) {
|
|
1018
1236
|
/* close the device */
|
|
1019
1237
|
kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device);
|
|
1020
|
-
if (kresult) {
|
|
1238
|
+
if (kresult != kIOReturnSuccess) {
|
|
1021
1239
|
/* Log the fact that we had a problem closing the file, however failing a
|
|
1022
1240
|
* close isn't really an error, so return success anyway */
|
|
1023
1241
|
usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult));
|
|
1024
1242
|
}
|
|
1025
1243
|
}
|
|
1026
1244
|
}
|
|
1027
|
-
|
|
1028
|
-
/* file descriptors are maintained per-instance */
|
|
1029
|
-
usbi_remove_pollfd (HANDLE_CTX (dev_handle), priv->fds[0]);
|
|
1030
|
-
close (priv->fds[1]);
|
|
1031
|
-
close (priv->fds[0]);
|
|
1032
|
-
|
|
1033
|
-
priv->fds[0] = priv->fds[1] = -1;
|
|
1034
1245
|
}
|
|
1035
1246
|
|
|
1036
1247
|
static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) {
|
|
@@ -1038,40 +1249,42 @@ static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int
|
|
|
1038
1249
|
|
|
1039
1250
|
*config = (int) dpriv->active_config;
|
|
1040
1251
|
|
|
1041
|
-
return
|
|
1252
|
+
return LIBUSB_SUCCESS;
|
|
1042
1253
|
}
|
|
1043
1254
|
|
|
1044
|
-
static
|
|
1255
|
+
static enum libusb_error darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
|
|
1045
1256
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1046
1257
|
IOReturn kresult;
|
|
1047
1258
|
int i;
|
|
1048
1259
|
|
|
1260
|
+
assert(config >= 0 && config <= UINT8_MAX);
|
|
1261
|
+
|
|
1049
1262
|
/* Setting configuration will invalidate the interface, so we need
|
|
1050
1263
|
to reclaim it. First, dispose of existing interfaces, if any. */
|
|
1051
1264
|
for (i = 0 ; i < USB_MAXINTERFACES ; i++)
|
|
1052
|
-
if (dev_handle->claimed_interfaces & (
|
|
1265
|
+
if (dev_handle->claimed_interfaces & (1U << i))
|
|
1053
1266
|
darwin_release_interface (dev_handle, i);
|
|
1054
1267
|
|
|
1055
|
-
kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config);
|
|
1268
|
+
kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, (UInt8)config);
|
|
1056
1269
|
if (kresult != kIOReturnSuccess)
|
|
1057
1270
|
return darwin_to_libusb (kresult);
|
|
1058
1271
|
|
|
1059
1272
|
/* Reclaim any interfaces. */
|
|
1060
1273
|
for (i = 0 ; i < USB_MAXINTERFACES ; i++)
|
|
1061
|
-
if (dev_handle->claimed_interfaces & (
|
|
1274
|
+
if (dev_handle->claimed_interfaces & (1U << i))
|
|
1062
1275
|
darwin_claim_interface (dev_handle, i);
|
|
1063
1276
|
|
|
1064
|
-
dpriv->active_config = config;
|
|
1277
|
+
dpriv->active_config = (UInt8)config;
|
|
1065
1278
|
|
|
1066
|
-
return
|
|
1279
|
+
return LIBUSB_SUCCESS;
|
|
1067
1280
|
}
|
|
1068
1281
|
|
|
1069
|
-
static
|
|
1282
|
+
static IOReturn darwin_get_interface (usb_device_t **darwin_device, int ifc, io_service_t *usbInterfacep) {
|
|
1070
1283
|
IOUSBFindInterfaceRequest request;
|
|
1071
|
-
|
|
1284
|
+
IOReturn kresult;
|
|
1072
1285
|
io_iterator_t interface_iterator;
|
|
1073
1286
|
UInt8 bInterfaceNumber;
|
|
1074
|
-
|
|
1287
|
+
bool ret;
|
|
1075
1288
|
|
|
1076
1289
|
*usbInterfacep = IO_OBJECT_NULL;
|
|
1077
1290
|
|
|
@@ -1082,7 +1295,7 @@ static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_s
|
|
|
1082
1295
|
request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
|
|
1083
1296
|
|
|
1084
1297
|
kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
|
|
1085
|
-
if (kresult)
|
|
1298
|
+
if (kresult != kIOReturnSuccess)
|
|
1086
1299
|
return kresult;
|
|
1087
1300
|
|
|
1088
1301
|
while ((*usbInterfacep = IOIteratorNext(interface_iterator))) {
|
|
@@ -1100,64 +1313,84 @@ static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_s
|
|
|
1100
1313
|
/* done with the interface iterator */
|
|
1101
1314
|
IOObjectRelease(interface_iterator);
|
|
1102
1315
|
|
|
1103
|
-
return
|
|
1316
|
+
return kIOReturnSuccess;
|
|
1104
1317
|
}
|
|
1105
1318
|
|
|
1106
|
-
static
|
|
1319
|
+
static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
|
|
1107
1320
|
struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
|
|
1108
1321
|
|
|
1109
1322
|
/* current interface */
|
|
1110
1323
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
1111
1324
|
|
|
1112
|
-
|
|
1325
|
+
IOReturn kresult;
|
|
1113
1326
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
int
|
|
1327
|
+
UInt8 numep, direction, number;
|
|
1328
|
+
UInt8 dont_care1, dont_care3;
|
|
1329
|
+
UInt16 dont_care2;
|
|
1330
|
+
int rc;
|
|
1118
1331
|
|
|
1119
1332
|
usbi_dbg ("building table of endpoints.");
|
|
1120
1333
|
|
|
1121
1334
|
/* retrieve the total number of endpoints on this interface */
|
|
1122
1335
|
kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep);
|
|
1123
|
-
if (kresult) {
|
|
1336
|
+
if (kresult != kIOReturnSuccess) {
|
|
1124
1337
|
usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
|
|
1125
1338
|
return darwin_to_libusb (kresult);
|
|
1126
1339
|
}
|
|
1127
1340
|
|
|
1128
1341
|
/* iterate through pipe references */
|
|
1129
|
-
for (i = 1 ; i <= numep ; i++) {
|
|
1342
|
+
for (UInt8 i = 1 ; i <= numep ; i++) {
|
|
1130
1343
|
kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
|
|
1131
1344
|
&dont_care2, &dont_care3);
|
|
1132
1345
|
|
|
1133
1346
|
if (kresult != kIOReturnSuccess) {
|
|
1134
|
-
|
|
1347
|
+
/* probably a buggy device. try to get the endpoint address from the descriptors */
|
|
1348
|
+
struct libusb_config_descriptor *config;
|
|
1349
|
+
const struct libusb_endpoint_descriptor *endpoint_desc;
|
|
1350
|
+
UInt8 alt_setting;
|
|
1351
|
+
|
|
1352
|
+
kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting);
|
|
1353
|
+
if (kresult != kIOReturnSuccess) {
|
|
1354
|
+
usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface");
|
|
1355
|
+
return darwin_to_libusb (kresult);
|
|
1356
|
+
}
|
|
1135
1357
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1358
|
+
rc = libusb_get_active_config_descriptor (dev_handle->dev, &config);
|
|
1359
|
+
if (LIBUSB_SUCCESS != rc) {
|
|
1360
|
+
return rc;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1;
|
|
1138
1364
|
|
|
1139
|
-
|
|
1365
|
+
cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress;
|
|
1366
|
+
} else {
|
|
1367
|
+
cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
|
|
1368
|
+
}
|
|
1140
1369
|
|
|
1141
|
-
cInterface->endpoint_addrs[i - 1]
|
|
1370
|
+
usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
|
|
1371
|
+
cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK);
|
|
1142
1372
|
}
|
|
1143
1373
|
|
|
1144
1374
|
cInterface->num_endpoints = numep;
|
|
1145
1375
|
|
|
1146
|
-
return
|
|
1376
|
+
return LIBUSB_SUCCESS;
|
|
1147
1377
|
}
|
|
1148
1378
|
|
|
1149
1379
|
static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) {
|
|
1150
1380
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1151
1381
|
struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
|
|
1152
1382
|
io_service_t usbInterface = IO_OBJECT_NULL;
|
|
1153
|
-
IOReturn
|
|
1383
|
+
IOReturn kresult;
|
|
1384
|
+
enum libusb_error ret;
|
|
1154
1385
|
IOCFPlugInInterface **plugInInterface = NULL;
|
|
1155
1386
|
SInt32 score;
|
|
1156
1387
|
|
|
1388
|
+
assert(iface >= 0 && iface <= UINT8_MAX);
|
|
1389
|
+
|
|
1157
1390
|
/* current interface */
|
|
1158
1391
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
1159
1392
|
|
|
1160
|
-
kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
|
|
1393
|
+
kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface);
|
|
1161
1394
|
if (kresult != kIOReturnSuccess)
|
|
1162
1395
|
return darwin_to_libusb (kresult);
|
|
1163
1396
|
|
|
@@ -1166,14 +1399,14 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1166
1399
|
usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config);
|
|
1167
1400
|
|
|
1168
1401
|
/* set the configuration */
|
|
1169
|
-
|
|
1170
|
-
if (
|
|
1402
|
+
ret = darwin_set_configuration (dev_handle, dpriv->first_config);
|
|
1403
|
+
if (ret != LIBUSB_SUCCESS) {
|
|
1171
1404
|
usbi_err (HANDLE_CTX (dev_handle), "could not set configuration");
|
|
1172
|
-
return
|
|
1405
|
+
return ret;
|
|
1173
1406
|
}
|
|
1174
1407
|
|
|
1175
|
-
kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
|
|
1176
|
-
if (kresult) {
|
|
1408
|
+
kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface);
|
|
1409
|
+
if (kresult != kIOReturnSuccess) {
|
|
1177
1410
|
usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
|
|
1178
1411
|
return darwin_to_libusb (kresult);
|
|
1179
1412
|
}
|
|
@@ -1191,7 +1424,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1191
1424
|
/* ignore release error */
|
|
1192
1425
|
(void)IOObjectRelease (usbInterface);
|
|
1193
1426
|
|
|
1194
|
-
if (kresult) {
|
|
1427
|
+
if (kresult != kIOReturnSuccess) {
|
|
1195
1428
|
usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult));
|
|
1196
1429
|
return darwin_to_libusb (kresult);
|
|
1197
1430
|
}
|
|
@@ -1203,30 +1436,30 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1203
1436
|
|
|
1204
1437
|
/* Do the actual claim */
|
|
1205
1438
|
kresult = (*plugInInterface)->QueryInterface(plugInInterface,
|
|
1206
|
-
CFUUIDGetUUIDBytes(
|
|
1439
|
+
CFUUIDGetUUIDBytes(InterfaceInterfaceID),
|
|
1207
1440
|
(LPVOID)&cInterface->interface);
|
|
1208
1441
|
/* We no longer need the intermediate plug-in */
|
|
1209
1442
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
1210
1443
|
(*plugInInterface)->Release (plugInInterface);
|
|
1211
|
-
if (kresult || !cInterface->interface) {
|
|
1444
|
+
if (kresult != kIOReturnSuccess || !cInterface->interface) {
|
|
1212
1445
|
usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult));
|
|
1213
1446
|
return darwin_to_libusb (kresult);
|
|
1214
1447
|
}
|
|
1215
1448
|
|
|
1216
1449
|
/* claim the interface */
|
|
1217
1450
|
kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface);
|
|
1218
|
-
if (kresult) {
|
|
1451
|
+
if (kresult != kIOReturnSuccess) {
|
|
1219
1452
|
usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult));
|
|
1220
1453
|
return darwin_to_libusb (kresult);
|
|
1221
1454
|
}
|
|
1222
1455
|
|
|
1223
1456
|
/* update list of endpoints */
|
|
1224
|
-
|
|
1225
|
-
if (
|
|
1457
|
+
ret = get_endpoints (dev_handle, iface);
|
|
1458
|
+
if (ret) {
|
|
1226
1459
|
/* this should not happen */
|
|
1227
1460
|
darwin_release_interface (dev_handle, iface);
|
|
1228
1461
|
usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
|
|
1229
|
-
return
|
|
1462
|
+
return ret;
|
|
1230
1463
|
}
|
|
1231
1464
|
|
|
1232
1465
|
cInterface->cfSource = NULL;
|
|
@@ -1247,7 +1480,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
|
|
|
1247
1480
|
|
|
1248
1481
|
usbi_dbg ("interface opened");
|
|
1249
1482
|
|
|
1250
|
-
return
|
|
1483
|
+
return LIBUSB_SUCCESS;
|
|
1251
1484
|
}
|
|
1252
1485
|
|
|
1253
1486
|
static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) {
|
|
@@ -1271,14 +1504,14 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
|
|
|
1271
1504
|
}
|
|
1272
1505
|
|
|
1273
1506
|
kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface);
|
|
1274
|
-
if (kresult)
|
|
1507
|
+
if (kresult != kIOReturnSuccess)
|
|
1275
1508
|
usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
|
|
1276
1509
|
|
|
1277
1510
|
kresult = (*(cInterface->interface))->Release(cInterface->interface);
|
|
1278
1511
|
if (kresult != kIOReturnSuccess)
|
|
1279
1512
|
usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
|
|
1280
1513
|
|
|
1281
|
-
cInterface->interface = IO_OBJECT_NULL;
|
|
1514
|
+
cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL;
|
|
1282
1515
|
|
|
1283
1516
|
return darwin_to_libusb (kresult);
|
|
1284
1517
|
}
|
|
@@ -1286,6 +1519,7 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
|
|
|
1286
1519
|
static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) {
|
|
1287
1520
|
struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
|
|
1288
1521
|
IOReturn kresult;
|
|
1522
|
+
enum libusb_error ret;
|
|
1289
1523
|
|
|
1290
1524
|
/* current interface */
|
|
1291
1525
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
@@ -1293,17 +1527,18 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand
|
|
|
1293
1527
|
if (!cInterface->interface)
|
|
1294
1528
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
1295
1529
|
|
|
1296
|
-
|
|
1530
|
+
assert(altsetting >= 0 && altsetting <= UINT8_MAX);
|
|
1531
|
+
kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, (UInt8)altsetting);
|
|
1297
1532
|
if (kresult != kIOReturnSuccess)
|
|
1298
1533
|
darwin_reset_device (dev_handle);
|
|
1299
1534
|
|
|
1300
1535
|
/* update list of endpoints */
|
|
1301
|
-
|
|
1302
|
-
if (
|
|
1536
|
+
ret = get_endpoints (dev_handle, iface);
|
|
1537
|
+
if (ret) {
|
|
1303
1538
|
/* this should not happen */
|
|
1304
1539
|
darwin_release_interface (dev_handle, iface);
|
|
1305
1540
|
usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
|
|
1306
|
-
return
|
|
1541
|
+
return ret;
|
|
1307
1542
|
}
|
|
1308
1543
|
|
|
1309
1544
|
return darwin_to_libusb (kresult);
|
|
@@ -1324,62 +1559,133 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
|
|
|
1324
1559
|
|
|
1325
1560
|
/* newer versions of darwin support clearing additional bits on the device's endpoint */
|
|
1326
1561
|
kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
|
|
1327
|
-
if (kresult)
|
|
1562
|
+
if (kresult != kIOReturnSuccess)
|
|
1328
1563
|
usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult));
|
|
1329
1564
|
|
|
1330
1565
|
return darwin_to_libusb (kresult);
|
|
1331
1566
|
}
|
|
1332
1567
|
|
|
1568
|
+
static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config,
|
|
1569
|
+
unsigned long claimed_interfaces) {
|
|
1570
|
+
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1571
|
+
struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
|
|
1572
|
+
int open_count = dpriv->open_count;
|
|
1573
|
+
int ret;
|
|
1574
|
+
|
|
1575
|
+
/* clear claimed interfaces temporarily */
|
|
1576
|
+
dev_handle->claimed_interfaces = 0;
|
|
1577
|
+
|
|
1578
|
+
/* close and re-open the device */
|
|
1579
|
+
priv->is_open = false;
|
|
1580
|
+
dpriv->open_count = 1;
|
|
1581
|
+
|
|
1582
|
+
/* clean up open interfaces */
|
|
1583
|
+
(void) darwin_close (dev_handle);
|
|
1584
|
+
|
|
1585
|
+
/* re-open the device */
|
|
1586
|
+
ret = darwin_open (dev_handle);
|
|
1587
|
+
dpriv->open_count = open_count;
|
|
1588
|
+
if (LIBUSB_SUCCESS != ret) {
|
|
1589
|
+
/* could not restore configuration */
|
|
1590
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
if (dpriv->active_config != active_config) {
|
|
1594
|
+
usbi_dbg ("darwin/restore_state: restoring configuration %d...", active_config);
|
|
1595
|
+
|
|
1596
|
+
ret = darwin_set_configuration (dev_handle, active_config);
|
|
1597
|
+
if (LIBUSB_SUCCESS != ret) {
|
|
1598
|
+
usbi_dbg ("darwin/restore_state: could not restore configuration");
|
|
1599
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
usbi_dbg ("darwin/restore_state: reclaiming interfaces");
|
|
1604
|
+
|
|
1605
|
+
if (claimed_interfaces) {
|
|
1606
|
+
for (int iface = 0 ; iface < USB_MAXINTERFACES ; ++iface) {
|
|
1607
|
+
if (!(claimed_interfaces & (1U << iface))) {
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
usbi_dbg ("darwin/restore_state: re-claiming interface %d", iface);
|
|
1612
|
+
|
|
1613
|
+
ret = darwin_claim_interface (dev_handle, iface);
|
|
1614
|
+
if (LIBUSB_SUCCESS != ret) {
|
|
1615
|
+
usbi_dbg ("darwin/restore_state: could not claim interface %d", iface);
|
|
1616
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
dev_handle->claimed_interfaces |= 1U << iface;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
usbi_dbg ("darwin/restore_state: device state restored");
|
|
1624
|
+
|
|
1625
|
+
return LIBUSB_SUCCESS;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1333
1628
|
static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
|
|
1334
1629
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1630
|
+
unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
|
|
1631
|
+
int8_t active_config = dpriv->active_config;
|
|
1335
1632
|
IOUSBDeviceDescriptor descriptor;
|
|
1336
1633
|
IOUSBConfigurationDescriptorPtr cached_configuration;
|
|
1337
|
-
IOUSBConfigurationDescriptor
|
|
1338
|
-
bool reenumerate = false;
|
|
1634
|
+
IOUSBConfigurationDescriptor *cached_configurations;
|
|
1339
1635
|
IOReturn kresult;
|
|
1340
|
-
|
|
1636
|
+
UInt8 i;
|
|
1341
1637
|
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
return darwin_to_libusb (kresult);
|
|
1638
|
+
if (dpriv->in_reenumerate) {
|
|
1639
|
+
/* ack, two (or more) threads are trying to reset the device! abort! */
|
|
1640
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1346
1641
|
}
|
|
1347
1642
|
|
|
1348
|
-
|
|
1349
|
-
usbi_dbg ("darwin/reset_device: checking if device descriptor changed");
|
|
1643
|
+
dpriv->in_reenumerate = true;
|
|
1350
1644
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1645
|
+
/* store copies of descriptors so they can be compared after the reset */
|
|
1646
|
+
memcpy (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor));
|
|
1647
|
+
cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
|
|
1353
1648
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
}
|
|
1649
|
+
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
1650
|
+
(*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
1651
|
+
memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
|
|
1652
|
+
}
|
|
1359
1653
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1654
|
+
/* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
|
|
1655
|
+
kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
|
|
1656
|
+
if (kresult != kIOReturnSuccess) {
|
|
1657
|
+
usbi_err (HANDLE_CTX (dev_handle), "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
|
|
1658
|
+
dpriv->in_reenumerate = false;
|
|
1659
|
+
return darwin_to_libusb (kresult);
|
|
1660
|
+
}
|
|
1363
1661
|
|
|
1364
|
-
|
|
1365
|
-
(*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
1662
|
+
usbi_dbg ("darwin/reset_device: waiting for re-enumeration to complete...");
|
|
1366
1663
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1664
|
+
while (dpriv->in_reenumerate) {
|
|
1665
|
+
struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
|
|
1666
|
+
nanosleep (&delay, NULL);
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
/* compare descriptors */
|
|
1670
|
+
usbi_dbg ("darwin/reset_device: checking whether descriptors changed");
|
|
1373
1671
|
|
|
1374
|
-
if (
|
|
1375
|
-
|
|
1376
|
-
|
|
1672
|
+
if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
|
|
1673
|
+
/* device descriptor changed. need to return not found. */
|
|
1674
|
+
usbi_dbg ("darwin/reset_device: device descriptor changed");
|
|
1377
1675
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1378
1676
|
}
|
|
1379
1677
|
|
|
1380
|
-
|
|
1678
|
+
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
1679
|
+
(void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
1680
|
+
if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
|
|
1681
|
+
usbi_dbg ("darwin/reset_device: configuration descriptor %d changed", i);
|
|
1682
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1381
1685
|
|
|
1382
|
-
|
|
1686
|
+
usbi_dbg ("darwin/reset_device: device reset complete. restoring state...");
|
|
1687
|
+
|
|
1688
|
+
return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
|
|
1383
1689
|
}
|
|
1384
1690
|
|
|
1385
1691
|
static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) {
|
|
@@ -1388,8 +1694,9 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle,
|
|
|
1388
1694
|
CFTypeRef driver;
|
|
1389
1695
|
IOReturn kresult;
|
|
1390
1696
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1697
|
+
assert(interface >= 0 && interface <= UINT8_MAX);
|
|
1698
|
+
kresult = darwin_get_interface (dpriv->device, (uint8_t)interface, &usbInterface);
|
|
1699
|
+
if (kresult != kIOReturnSuccess) {
|
|
1393
1700
|
usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
|
|
1394
1701
|
|
|
1395
1702
|
return darwin_to_libusb (kresult);
|
|
@@ -1410,14 +1717,14 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle,
|
|
|
1410
1717
|
|
|
1411
1718
|
/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */
|
|
1412
1719
|
static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
|
|
1413
|
-
(
|
|
1414
|
-
(
|
|
1720
|
+
UNUSED(dev_handle);
|
|
1721
|
+
UNUSED(interface);
|
|
1415
1722
|
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
1416
1723
|
}
|
|
1417
1724
|
|
|
1418
1725
|
static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
|
|
1419
|
-
(
|
|
1420
|
-
(
|
|
1726
|
+
UNUSED(dev_handle);
|
|
1727
|
+
UNUSED(interface);
|
|
1421
1728
|
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
1422
1729
|
}
|
|
1423
1730
|
|
|
@@ -1469,21 +1776,21 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
|
|
|
1469
1776
|
if (transferType == kUSBInterrupt) {
|
|
1470
1777
|
if (IS_XFERIN(transfer))
|
|
1471
1778
|
ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer,
|
|
1472
|
-
transfer->length, darwin_async_io_callback, itransfer);
|
|
1779
|
+
(UInt32)transfer->length, darwin_async_io_callback, itransfer);
|
|
1473
1780
|
else
|
|
1474
1781
|
ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
|
|
1475
|
-
transfer->length, darwin_async_io_callback, itransfer);
|
|
1782
|
+
(UInt32)transfer->length, darwin_async_io_callback, itransfer);
|
|
1476
1783
|
} else {
|
|
1477
|
-
itransfer->
|
|
1784
|
+
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
|
|
1478
1785
|
|
|
1479
1786
|
if (IS_XFERIN(transfer))
|
|
1480
1787
|
ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
|
|
1481
|
-
transfer->length, transfer->timeout, transfer->timeout,
|
|
1482
|
-
darwin_async_io_callback,
|
|
1788
|
+
(UInt32)transfer->length, transfer->timeout, transfer->timeout,
|
|
1789
|
+
darwin_async_io_callback, itransfer);
|
|
1483
1790
|
else
|
|
1484
1791
|
ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
|
|
1485
|
-
transfer->length, transfer->timeout, transfer->timeout,
|
|
1486
|
-
darwin_async_io_callback,
|
|
1792
|
+
(UInt32)transfer->length, transfer->timeout, transfer->timeout,
|
|
1793
|
+
darwin_async_io_callback, itransfer);
|
|
1487
1794
|
}
|
|
1488
1795
|
|
|
1489
1796
|
if (ret)
|
|
@@ -1506,16 +1813,16 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
|
|
|
1506
1813
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1507
1814
|
}
|
|
1508
1815
|
|
|
1509
|
-
itransfer->
|
|
1816
|
+
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
|
|
1510
1817
|
|
|
1511
1818
|
if (IS_XFERIN(transfer))
|
|
1512
1819
|
ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
|
|
1513
|
-
transfer->buffer, transfer->length, transfer->timeout,
|
|
1514
|
-
transfer->timeout, darwin_async_io_callback,
|
|
1820
|
+
transfer->buffer, (UInt32)transfer->length, transfer->timeout,
|
|
1821
|
+
transfer->timeout, darwin_async_io_callback, itransfer);
|
|
1515
1822
|
else
|
|
1516
1823
|
ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
|
|
1517
|
-
transfer->buffer, transfer->length, transfer->timeout,
|
|
1518
|
-
transfer->timeout, darwin_async_io_callback,
|
|
1824
|
+
transfer->buffer, (UInt32)transfer->length, transfer->timeout,
|
|
1825
|
+
transfer->timeout, darwin_async_io_callback, itransfer);
|
|
1519
1826
|
|
|
1520
1827
|
if (ret)
|
|
1521
1828
|
usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
|
|
@@ -1538,22 +1845,25 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
1538
1845
|
|
|
1539
1846
|
struct darwin_interface *cInterface;
|
|
1540
1847
|
|
|
1541
|
-
/* construct an array of IOUSBIsocFrames, reuse the old one if
|
|
1542
|
-
if (tpriv->
|
|
1848
|
+
/* construct an array of IOUSBIsocFrames, reuse the old one if the sizes are the same */
|
|
1849
|
+
if (tpriv->num_iso_packets != transfer->num_iso_packets) {
|
|
1543
1850
|
free(tpriv->isoc_framelist);
|
|
1544
1851
|
tpriv->isoc_framelist = NULL;
|
|
1545
1852
|
}
|
|
1546
1853
|
|
|
1547
1854
|
if (!tpriv->isoc_framelist) {
|
|
1548
1855
|
tpriv->num_iso_packets = transfer->num_iso_packets;
|
|
1549
|
-
tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
|
|
1856
|
+
tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc ((size_t)transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
|
|
1550
1857
|
if (!tpriv->isoc_framelist)
|
|
1551
1858
|
return LIBUSB_ERROR_NO_MEM;
|
|
1552
1859
|
}
|
|
1553
1860
|
|
|
1554
1861
|
/* copy the frame list from the libusb descriptor (the structures differ only is member order) */
|
|
1555
|
-
for (i = 0 ; i < transfer->num_iso_packets ; i++)
|
|
1556
|
-
|
|
1862
|
+
for (i = 0 ; i < transfer->num_iso_packets ; i++) {
|
|
1863
|
+
unsigned int length = transfer->iso_packet_desc[i].length;
|
|
1864
|
+
assert(length <= UINT16_MAX);
|
|
1865
|
+
tpriv->isoc_framelist[i].frReqCount = (UInt16)length;
|
|
1866
|
+
}
|
|
1557
1867
|
|
|
1558
1868
|
/* determine the interface/endpoint to use */
|
|
1559
1869
|
if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
|
|
@@ -1568,7 +1878,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
1568
1878
|
|
|
1569
1879
|
/* Last but not least we need the bus frame number */
|
|
1570
1880
|
kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime);
|
|
1571
|
-
if (kresult) {
|
|
1881
|
+
if (kresult != kIOReturnSuccess) {
|
|
1572
1882
|
usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult);
|
|
1573
1883
|
free(tpriv->isoc_framelist);
|
|
1574
1884
|
tpriv->isoc_framelist = NULL;
|
|
@@ -1588,19 +1898,19 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
1588
1898
|
/* submit the request */
|
|
1589
1899
|
if (IS_XFERIN(transfer))
|
|
1590
1900
|
kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
|
|
1591
|
-
transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
|
|
1901
|
+
(UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
|
|
1592
1902
|
itransfer);
|
|
1593
1903
|
else
|
|
1594
1904
|
kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
|
|
1595
|
-
transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
|
|
1905
|
+
(UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
|
|
1596
1906
|
itransfer);
|
|
1597
1907
|
|
|
1598
1908
|
if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
|
|
1599
1909
|
/* Full speed */
|
|
1600
|
-
cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (
|
|
1910
|
+
cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1));
|
|
1601
1911
|
else
|
|
1602
1912
|
/* High/super speed */
|
|
1603
|
-
cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (
|
|
1913
|
+
cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)) / 8;
|
|
1604
1914
|
|
|
1605
1915
|
if (kresult != kIOReturnSuccess) {
|
|
1606
1916
|
usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
|
|
@@ -1620,9 +1930,9 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
|
|
|
1620
1930
|
|
|
1621
1931
|
IOReturn kresult;
|
|
1622
1932
|
|
|
1623
|
-
|
|
1933
|
+
memset(&tpriv->req, 0, sizeof(tpriv->req));
|
|
1624
1934
|
|
|
1625
|
-
/* IOUSBDeviceInterface expects the request in cpu
|
|
1935
|
+
/* IOUSBDeviceInterface expects the request in cpu endianness */
|
|
1626
1936
|
tpriv->req.bmRequestType = setup->bmRequestType;
|
|
1627
1937
|
tpriv->req.bRequest = setup->bRequest;
|
|
1628
1938
|
/* these values should be in bus order from libusb_fill_control_setup */
|
|
@@ -1634,7 +1944,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
|
|
|
1634
1944
|
tpriv->req.completionTimeout = transfer->timeout;
|
|
1635
1945
|
tpriv->req.noDataTimeout = transfer->timeout;
|
|
1636
1946
|
|
|
1637
|
-
itransfer->
|
|
1947
|
+
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
|
|
1638
1948
|
|
|
1639
1949
|
/* all transfers in libusb-1.0 are async */
|
|
1640
1950
|
|
|
@@ -1761,9 +2071,7 @@ static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) {
|
|
|
1761
2071
|
static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) {
|
|
1762
2072
|
struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon;
|
|
1763
2073
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1764
|
-
struct
|
|
1765
|
-
struct darwin_msg_async_io_complete message = {.itransfer = itransfer, .result = result,
|
|
1766
|
-
.size = (UInt32) (uintptr_t) arg0};
|
|
2074
|
+
struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
|
|
1767
2075
|
|
|
1768
2076
|
usbi_dbg ("an async io operation has completed");
|
|
1769
2077
|
|
|
@@ -1777,12 +2085,15 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
|
|
|
1777
2085
|
(*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0);
|
|
1778
2086
|
}
|
|
1779
2087
|
|
|
1780
|
-
|
|
1781
|
-
|
|
2088
|
+
tpriv->result = result;
|
|
2089
|
+
tpriv->size = (UInt32) (uintptr_t) arg0;
|
|
2090
|
+
|
|
2091
|
+
/* signal the core that this transfer is complete */
|
|
2092
|
+
usbi_signal_transfer_completion(itransfer);
|
|
1782
2093
|
}
|
|
1783
2094
|
|
|
1784
|
-
static
|
|
1785
|
-
if (itransfer->
|
|
2095
|
+
static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer *itransfer, IOReturn result) {
|
|
2096
|
+
if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT)
|
|
1786
2097
|
result = kIOUSBTransactionTimeout;
|
|
1787
2098
|
|
|
1788
2099
|
switch (result) {
|
|
@@ -1799,7 +2110,7 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
|
|
|
1799
2110
|
return LIBUSB_TRANSFER_OVERFLOW;
|
|
1800
2111
|
case kIOUSBTransactionTimeout:
|
|
1801
2112
|
usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out");
|
|
1802
|
-
itransfer->
|
|
2113
|
+
itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
|
|
1803
2114
|
return LIBUSB_TRANSFER_TIMED_OUT;
|
|
1804
2115
|
default:
|
|
1805
2116
|
usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
|
|
@@ -1807,78 +2118,42 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
|
|
|
1807
2118
|
}
|
|
1808
2119
|
}
|
|
1809
2120
|
|
|
1810
|
-
static
|
|
2121
|
+
static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
|
|
1811
2122
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1812
2123
|
struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
2124
|
+
bool isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
|
|
2125
|
+
bool isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type;
|
|
2126
|
+
bool isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type;
|
|
2127
|
+
bool isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type;
|
|
1817
2128
|
int i;
|
|
1818
2129
|
|
|
1819
2130
|
if (!isIsoc && !isBulk && !isControl && !isInterrupt) {
|
|
1820
2131
|
usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
|
|
1821
|
-
return;
|
|
2132
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1822
2133
|
}
|
|
1823
2134
|
|
|
1824
2135
|
usbi_dbg ("handling %s completion with kernel status %d",
|
|
1825
|
-
isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", result);
|
|
2136
|
+
isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result);
|
|
1826
2137
|
|
|
1827
|
-
if (kIOReturnSuccess == result || kIOReturnUnderrun == result) {
|
|
2138
|
+
if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) {
|
|
1828
2139
|
if (isIsoc && tpriv->isoc_framelist) {
|
|
1829
2140
|
/* copy isochronous results back */
|
|
1830
2141
|
|
|
1831
2142
|
for (i = 0; i < transfer->num_iso_packets ; i++) {
|
|
1832
2143
|
struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
|
|
1833
|
-
lib_desc->status =
|
|
2144
|
+
lib_desc->status = darwin_transfer_status (itransfer, tpriv->isoc_framelist[i].frStatus);
|
|
1834
2145
|
lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
|
|
1835
2146
|
}
|
|
1836
2147
|
} else if (!isIsoc)
|
|
1837
|
-
itransfer->transferred +=
|
|
2148
|
+
itransfer->transferred += tpriv->size;
|
|
1838
2149
|
}
|
|
1839
2150
|
|
|
1840
2151
|
/* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */
|
|
1841
|
-
usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, result));
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) {
|
|
1845
|
-
struct darwin_msg_async_io_complete message;
|
|
1846
|
-
POLL_NFDS_TYPE i = 0;
|
|
1847
|
-
ssize_t ret;
|
|
1848
|
-
|
|
1849
|
-
usbi_mutex_lock(&ctx->open_devs_lock);
|
|
1850
|
-
|
|
1851
|
-
for (i = 0; i < nfds && num_ready > 0; i++) {
|
|
1852
|
-
struct pollfd *pollfd = &fds[i];
|
|
1853
|
-
|
|
1854
|
-
usbi_dbg ("checking fd %i with revents = %x", pollfd->fd, pollfd->revents);
|
|
1855
|
-
|
|
1856
|
-
if (!pollfd->revents)
|
|
1857
|
-
continue;
|
|
1858
|
-
|
|
1859
|
-
num_ready--;
|
|
1860
|
-
|
|
1861
|
-
if (pollfd->revents & POLLERR) {
|
|
1862
|
-
/* this probably will never happen so ignore the error an move on. */
|
|
1863
|
-
continue;
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
/* there is only one type of message */
|
|
1867
|
-
ret = read (pollfd->fd, &message, sizeof (message));
|
|
1868
|
-
if (ret < (ssize_t) sizeof (message)) {
|
|
1869
|
-
usbi_dbg ("WARNING: short read on async io completion pipe\n");
|
|
1870
|
-
continue;
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
darwin_handle_callback (message.itransfer, message.result, message.size);
|
|
1874
|
-
}
|
|
1875
|
-
|
|
1876
|
-
usbi_mutex_unlock(&ctx->open_devs_lock);
|
|
1877
|
-
|
|
1878
|
-
return 0;
|
|
2152
|
+
return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result));
|
|
1879
2153
|
}
|
|
1880
2154
|
|
|
1881
2155
|
static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
|
|
2156
|
+
#if !OSX_USE_CLOCK_GETTIME
|
|
1882
2157
|
mach_timespec_t sys_time;
|
|
1883
2158
|
clock_serv_t clock_ref;
|
|
1884
2159
|
|
|
@@ -1900,7 +2175,17 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
|
|
|
1900
2175
|
tp->tv_sec = sys_time.tv_sec;
|
|
1901
2176
|
tp->tv_nsec = sys_time.tv_nsec;
|
|
1902
2177
|
|
|
1903
|
-
return
|
|
2178
|
+
return LIBUSB_SUCCESS;
|
|
2179
|
+
#else
|
|
2180
|
+
switch (clk_id) {
|
|
2181
|
+
case USBI_CLOCK_MONOTONIC:
|
|
2182
|
+
return clock_gettime(CLOCK_MONOTONIC, tp);
|
|
2183
|
+
case USBI_CLOCK_REALTIME:
|
|
2184
|
+
return clock_gettime(CLOCK_REALTIME, tp);
|
|
2185
|
+
default:
|
|
2186
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2187
|
+
}
|
|
2188
|
+
#endif
|
|
1904
2189
|
}
|
|
1905
2190
|
|
|
1906
2191
|
#if InterfaceVersion >= 550
|
|
@@ -1935,7 +2220,8 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
|
|
|
1935
2220
|
return darwin_to_libusb(rc);
|
|
1936
2221
|
}
|
|
1937
2222
|
|
|
1938
|
-
|
|
2223
|
+
assert(num_streams <= INT_MAX);
|
|
2224
|
+
return (int)num_streams;
|
|
1939
2225
|
}
|
|
1940
2226
|
|
|
1941
2227
|
static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) {
|
|
@@ -1961,9 +2247,9 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
|
|
|
1961
2247
|
}
|
|
1962
2248
|
#endif
|
|
1963
2249
|
|
|
1964
|
-
const struct usbi_os_backend
|
|
2250
|
+
const struct usbi_os_backend usbi_backend = {
|
|
1965
2251
|
.name = "Darwin",
|
|
1966
|
-
.caps =
|
|
2252
|
+
.caps = 0,
|
|
1967
2253
|
.init = darwin_init,
|
|
1968
2254
|
.exit = darwin_exit,
|
|
1969
2255
|
.get_device_list = NULL, /* not needed */
|
|
@@ -1998,12 +2284,11 @@ const struct usbi_os_backend darwin_backend = {
|
|
|
1998
2284
|
.cancel_transfer = darwin_cancel_transfer,
|
|
1999
2285
|
.clear_transfer_priv = darwin_clear_transfer_priv,
|
|
2000
2286
|
|
|
2001
|
-
.
|
|
2287
|
+
.handle_transfer_completion = darwin_handle_transfer_completion,
|
|
2002
2288
|
|
|
2003
2289
|
.clock_gettime = darwin_clock_gettime,
|
|
2004
2290
|
|
|
2005
2291
|
.device_priv_size = sizeof(struct darwin_device_priv),
|
|
2006
2292
|
.device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
|
|
2007
2293
|
.transfer_priv_size = sizeof(struct darwin_transfer_priv),
|
|
2008
|
-
.add_iso_packet_size = 0,
|
|
2009
2294
|
};
|