usb 2.12.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -1
- package/README.md +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/usb/bindings.js +1 -1
- package/dist/usb/bindings.js.map +1 -1
- package/dist/usb/capability.js.map +1 -1
- package/dist/usb/device.js.map +1 -1
- package/dist/usb/endpoint.d.ts +1 -0
- package/dist/usb/endpoint.js +2 -2
- package/dist/usb/endpoint.js.map +1 -1
- package/dist/usb/index.js.map +1 -1
- package/dist/usb/interface.js +2 -2
- package/dist/usb/interface.js.map +1 -1
- package/dist/webusb/index.d.ts +2 -2
- package/dist/webusb/index.js.map +1 -1
- package/dist/webusb/webusb-device.js +10 -10
- package/dist/webusb/webusb-device.js.map +1 -1
- package/libusb/.codespellrc +3 -0
- package/libusb/.private/appveyor_build.sh +5 -1
- package/libusb/.private/ci-build.sh +26 -1
- package/libusb/.private/ci-container-build.sh +2 -5
- package/libusb/.private/wbs.txt +5 -8
- package/libusb/AUTHORS +22 -0
- package/libusb/ChangeLog +19 -2
- package/libusb/HACKING +25 -0
- package/libusb/INSTALL_WIN.txt +11 -10
- package/libusb/NEWS +2 -2
- package/libusb/README +3 -2
- package/libusb/README.git +1 -1
- package/libusb/Xcode/common.xcconfig +8 -1
- package/libusb/Xcode/config.h +0 -6
- package/libusb/Xcode/debug.xcconfig +4 -1
- package/libusb/Xcode/libusb.xcconfig +1 -1
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +60 -30
- package/libusb/Xcode/libusb_debug.xcconfig +1 -1
- package/libusb/Xcode/libusb_release.xcconfig +1 -1
- package/libusb/Xcode/release.xcconfig +1 -1
- package/libusb/appveyor.yml +33 -9
- package/libusb/configure.ac +68 -37
- package/libusb/examples/dpfp.c +2 -2
- package/libusb/examples/fxload.c +2 -2
- package/libusb/examples/hotplugtest.c +28 -13
- package/libusb/examples/listdevs.c +1 -1
- package/libusb/examples/sam3u_benchmark.c +1 -1
- package/libusb/examples/testlibusb.c +1 -1
- package/libusb/examples/xusb.c +74 -19
- package/libusb/libusb/Makefile.am +11 -1
- package/libusb/libusb/core.c +364 -186
- package/libusb/libusb/descriptor.c +276 -16
- package/libusb/libusb/hotplug.c +5 -4
- package/libusb/libusb/io.c +72 -61
- package/libusb/libusb/libusb-1.0.def +14 -1
- package/libusb/libusb/libusb.h +245 -76
- package/libusb/libusb/libusbi.h +35 -13
- package/libusb/libusb/os/darwin_usb.c +542 -279
- package/libusb/libusb/os/darwin_usb.h +44 -115
- package/libusb/libusb/os/emscripten_webusb.cpp +870 -0
- package/libusb/libusb/os/events_posix.c +40 -0
- package/libusb/libusb/os/events_posix.h +3 -0
- package/libusb/libusb/os/linux_usbfs.c +27 -16
- package/libusb/libusb/os/netbsd_usb.c +36 -36
- package/libusb/libusb/os/openbsd_usb.c +34 -34
- package/libusb/libusb/os/sunos_usb.c +25 -15
- package/libusb/libusb/os/threads_posix.c +1 -5
- package/libusb/libusb/os/windows_common.c +13 -5
- package/libusb/libusb/os/windows_common.h +8 -0
- package/libusb/libusb/os/windows_winusb.c +366 -174
- package/libusb/libusb/os/windows_winusb.h +13 -9
- package/libusb/libusb/strerror.c +5 -5
- package/libusb/libusb/sync.c +24 -19
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/msvc/Base.props +60 -0
- package/libusb/msvc/Configuration.Application.props +7 -0
- package/libusb/msvc/Configuration.Base.props +47 -0
- package/libusb/msvc/Configuration.DynamicLibrary.props +21 -0
- package/libusb/msvc/Configuration.StaticLibrary.props +7 -0
- package/libusb/msvc/ProjectConfigurations.Base.props +69 -0
- package/libusb/msvc/build_all.ps1 +17 -0
- package/libusb/msvc/config.h +2 -2
- package/libusb/msvc/dpfp.vcxproj +33 -0
- package/libusb/msvc/dpfp_threaded.vcxproj +38 -0
- package/libusb/msvc/fxload.vcxproj +46 -0
- package/libusb/msvc/getopt.vcxproj +33 -0
- package/libusb/msvc/hotplugtest.vcxproj +32 -0
- package/libusb/msvc/init_context.vcxproj +35 -0
- package/libusb/msvc/libusb.sln +542 -0
- package/libusb/msvc/libusb_dll.vcxproj +61 -0
- package/libusb/msvc/libusb_static.vcxproj +49 -0
- package/libusb/msvc/listdevs.vcxproj +32 -0
- package/libusb/msvc/sam3u_benchmark.vcxproj +33 -0
- package/libusb/msvc/set_option.vcxproj +35 -0
- package/libusb/msvc/stress.vcxproj +35 -0
- package/libusb/msvc/stress_mt.vcxproj +33 -0
- package/libusb/msvc/testlibusb.vcxproj +32 -0
- package/libusb/msvc/xusb.vcxproj +38 -0
- package/libusb/tests/Makefile.am +25 -3
- package/libusb/tests/init_context.c +153 -0
- package/libusb/tests/macos.c +130 -0
- package/libusb/tests/set_option.c +253 -0
- package/libusb/tests/stress.c +17 -14
- package/libusb/tests/stress_mt.c +265 -0
- package/libusb/tests/testlib.c +1 -1
- package/libusb/tests/umockdev.c +9 -9
- package/libusb/tests/webusb-test-shim/index.js +12 -0
- package/libusb/tests/webusb-test-shim/package-lock.json +50 -0
- package/libusb/tests/webusb-test-shim/package.json +10 -0
- package/package.json +7 -7
- 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-arm64/node.napi.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 +15 -5
- package/libusb/msvc/dpfp_2013.vcxproj +0 -87
- package/libusb/msvc/dpfp_2013.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_2015.vcxproj +0 -87
- package/libusb/msvc/dpfp_2015.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_2017.vcxproj +0 -106
- package/libusb/msvc/dpfp_2017.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_2019.vcxproj +0 -106
- package/libusb/msvc/dpfp_2019.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2013.vcxproj +0 -87
- package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2015.vcxproj +0 -87
- package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2017.vcxproj +0 -106
- package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2019.vcxproj +0 -106
- package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +0 -26
- package/libusb/msvc/fxload_2013.vcxproj +0 -94
- package/libusb/msvc/fxload_2013.vcxproj.filters +0 -35
- package/libusb/msvc/fxload_2015.vcxproj +0 -94
- package/libusb/msvc/fxload_2015.vcxproj.filters +0 -35
- package/libusb/msvc/fxload_2017.vcxproj +0 -113
- package/libusb/msvc/fxload_2017.vcxproj.filters +0 -35
- package/libusb/msvc/fxload_2019.vcxproj +0 -113
- package/libusb/msvc/fxload_2019.vcxproj.filters +0 -35
- package/libusb/msvc/getopt_2013.vcxproj +0 -72
- package/libusb/msvc/getopt_2013.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2015.vcxproj +0 -73
- package/libusb/msvc/getopt_2015.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2017.vcxproj +0 -92
- package/libusb/msvc/getopt_2017.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2019.vcxproj +0 -92
- package/libusb/msvc/getopt_2019.vcxproj.filters +0 -26
- package/libusb/msvc/hotplugtest_2013.vcxproj +0 -86
- package/libusb/msvc/hotplugtest_2013.vcxproj.filters +0 -23
- package/libusb/msvc/hotplugtest_2015.vcxproj +0 -86
- package/libusb/msvc/hotplugtest_2015.vcxproj.filters +0 -23
- package/libusb/msvc/hotplugtest_2017.vcxproj +0 -105
- package/libusb/msvc/hotplugtest_2017.vcxproj.filters +0 -23
- package/libusb/msvc/hotplugtest_2019.vcxproj +0 -105
- package/libusb/msvc/hotplugtest_2019.vcxproj.filters +0 -23
- package/libusb/msvc/libusb_2013.sln +0 -137
- package/libusb/msvc/libusb_2015.sln +0 -137
- package/libusb/msvc/libusb_2017.sln +0 -240
- package/libusb/msvc/libusb_2019.sln +0 -240
- package/libusb/msvc/libusb_dll_2013.vcxproj +0 -104
- package/libusb/msvc/libusb_dll_2013.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_dll_2015.vcxproj +0 -105
- package/libusb/msvc/libusb_dll_2015.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_dll_2017.vcxproj +0 -124
- package/libusb/msvc/libusb_dll_2017.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_dll_2019.vcxproj +0 -124
- package/libusb/msvc/libusb_dll_2019.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_static_2013.vcxproj +0 -94
- package/libusb/msvc/libusb_static_2013.vcxproj.filters +0 -80
- package/libusb/msvc/libusb_static_2015.vcxproj +0 -95
- package/libusb/msvc/libusb_static_2015.vcxproj.filters +0 -80
- package/libusb/msvc/libusb_static_2017.vcxproj +0 -114
- package/libusb/msvc/libusb_static_2017.vcxproj.filters +0 -80
- package/libusb/msvc/libusb_static_2019.vcxproj +0 -114
- package/libusb/msvc/libusb_static_2019.vcxproj.filters +0 -80
- package/libusb/msvc/listdevs_2013.vcxproj +0 -86
- package/libusb/msvc/listdevs_2013.vcxproj.filters +0 -23
- package/libusb/msvc/listdevs_2015.vcxproj +0 -86
- package/libusb/msvc/listdevs_2015.vcxproj.filters +0 -23
- package/libusb/msvc/listdevs_2017.vcxproj +0 -105
- package/libusb/msvc/listdevs_2017.vcxproj.filters +0 -23
- package/libusb/msvc/listdevs_2019.vcxproj +0 -105
- package/libusb/msvc/listdevs_2019.vcxproj.filters +0 -23
- package/libusb/msvc/sam3u_benchmark_2013.vcxproj +0 -87
- package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +0 -26
- package/libusb/msvc/sam3u_benchmark_2015.vcxproj +0 -87
- package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +0 -26
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj +0 -106
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +0 -26
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj +0 -106
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +0 -26
- package/libusb/msvc/stress_2013.vcxproj +0 -89
- package/libusb/msvc/stress_2013.vcxproj.filters +0 -32
- package/libusb/msvc/stress_2015.vcxproj +0 -89
- package/libusb/msvc/stress_2015.vcxproj.filters +0 -32
- package/libusb/msvc/stress_2017.vcxproj +0 -108
- package/libusb/msvc/stress_2017.vcxproj.filters +0 -32
- package/libusb/msvc/stress_2019.vcxproj +0 -108
- package/libusb/msvc/stress_2019.vcxproj.filters +0 -32
- package/libusb/msvc/testlibusb_2013.vcxproj +0 -86
- package/libusb/msvc/testlibusb_2013.vcxproj.filters +0 -23
- package/libusb/msvc/testlibusb_2015.vcxproj +0 -86
- package/libusb/msvc/testlibusb_2015.vcxproj.filters +0 -23
- package/libusb/msvc/testlibusb_2017.vcxproj +0 -105
- package/libusb/msvc/testlibusb_2017.vcxproj.filters +0 -23
- package/libusb/msvc/testlibusb_2019.vcxproj +0 -105
- package/libusb/msvc/testlibusb_2019.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2013.vcxproj +0 -86
- package/libusb/msvc/xusb_2013.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2015.vcxproj +0 -86
- package/libusb/msvc/xusb_2015.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2017.vcxproj +0 -105
- package/libusb/msvc/xusb_2017.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2019.vcxproj +0 -105
- package/libusb/msvc/xusb_2019.vcxproj.filters +0 -23
- package/prebuilds/android-arm/usb.armv7.node +0 -0
- package/prebuilds/android-arm64/usb.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/usb.node +0 -0
- package/prebuilds/linux-arm/usb.armv6.node +0 -0
- package/prebuilds/linux-arm/usb.armv7.node +0 -0
- package/prebuilds/linux-arm64/usb.armv8.node +0 -0
- package/prebuilds/linux-ia32/usb.node +0 -0
- package/prebuilds/linux-x64/usb.glibc.node +0 -0
- package/prebuilds/linux-x64/usb.musl.node +0 -0
- package/prebuilds/win32-arm64/usb.node +0 -0
- package/prebuilds/win32-ia32/usb.node +0 -0
- package/prebuilds/win32-x64/usb.node +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* -*- Mode: C; indent-tabs-mode:nil -*- */
|
|
2
2
|
/*
|
|
3
3
|
* darwin backend for libusb 1.0
|
|
4
|
-
* Copyright © 2008-
|
|
5
|
-
* Copyright © 2019-
|
|
4
|
+
* Copyright © 2008-2023 Nathan Hjelm <hjelmn@cs.unm.edu>
|
|
5
|
+
* Copyright © 2019-2023 Google LLC. All rights reserved.
|
|
6
6
|
*
|
|
7
7
|
* This library is free software; you can redistribute it and/or
|
|
8
8
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -32,10 +32,7 @@
|
|
|
32
32
|
#include <fcntl.h>
|
|
33
33
|
#include <sys/sysctl.h>
|
|
34
34
|
|
|
35
|
-
#include <mach/
|
|
36
|
-
#include <mach/clock_types.h>
|
|
37
|
-
#include <mach/mach_host.h>
|
|
38
|
-
#include <mach/mach_port.h>
|
|
35
|
+
#include <mach/mach_time.h>
|
|
39
36
|
|
|
40
37
|
/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector
|
|
41
38
|
* function. Its use is also conditionalized to only older deployment targets. */
|
|
@@ -58,28 +55,34 @@ static int init_count = 0;
|
|
|
58
55
|
static const mach_port_t darwin_default_master_port = 0;
|
|
59
56
|
|
|
60
57
|
/* async event thread */
|
|
58
|
+
/* if both this mutex and darwin_cached_devices_mutex are to be acquired then
|
|
59
|
+
darwin_cached_devices_mutex must be acquired first. */
|
|
61
60
|
static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
62
61
|
static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
|
|
63
62
|
|
|
64
|
-
#if !defined(HAVE_CLOCK_GETTIME)
|
|
65
|
-
static clock_serv_t clock_realtime;
|
|
66
|
-
static clock_serv_t clock_monotonic;
|
|
67
|
-
#endif
|
|
68
|
-
|
|
69
63
|
#define LIBUSB_DARWIN_STARTUP_FAILURE ((CFRunLoopRef) -1)
|
|
70
64
|
|
|
71
65
|
static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
|
|
72
66
|
static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
|
|
73
67
|
|
|
74
|
-
static usbi_mutex_t
|
|
68
|
+
static usbi_mutex_t darwin_cached_devices_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
75
69
|
static struct list_head darwin_cached_devices;
|
|
76
70
|
static const char *darwin_device_class = "IOUSBDevice";
|
|
77
71
|
|
|
72
|
+
uint32_t libusb_testonly_fake_running_version __attribute__ ((visibility ("hidden")));
|
|
73
|
+
int libusb_testonly_using_running_interface_version __attribute__ ((visibility ("hidden")));
|
|
74
|
+
int libusb_testonly_using_running_device_version __attribute__ ((visibility ("hidden")));
|
|
75
|
+
bool libusb_testonly_clear_running_version_cache __attribute__ ((visibility ("hidden")));
|
|
76
|
+
|
|
78
77
|
#define DARWIN_CACHED_DEVICE(a) (((struct darwin_device_priv *)usbi_get_device_priv((a)))->dev)
|
|
79
78
|
|
|
80
79
|
/* async event thread */
|
|
81
80
|
static pthread_t libusb_darwin_at;
|
|
82
81
|
|
|
82
|
+
/* protected by libusb_darwin_at_mutex */
|
|
83
|
+
static bool libusb_darwin_at_started;
|
|
84
|
+
|
|
85
|
+
static void darwin_exit(struct libusb_context *ctx);
|
|
83
86
|
static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len);
|
|
84
87
|
static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
|
|
85
88
|
static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
|
|
@@ -96,6 +99,186 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
96
99
|
static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out,
|
|
97
100
|
UInt64 *old_session_id);
|
|
98
101
|
|
|
102
|
+
struct darwin_iokit_interface {
|
|
103
|
+
uint32_t min_os_version;
|
|
104
|
+
uint32_t version;
|
|
105
|
+
CFUUIDRef interface_id;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
static const struct darwin_iokit_interface *get_interface_interface(void) {
|
|
109
|
+
const struct darwin_iokit_interface interfaces[] = {
|
|
110
|
+
#if defined(kIOUSBInterfaceInterfaceID800)
|
|
111
|
+
{
|
|
112
|
+
.min_os_version = 101200,
|
|
113
|
+
.version = 800,
|
|
114
|
+
.interface_id = kIOUSBInterfaceInterfaceID800,
|
|
115
|
+
},
|
|
116
|
+
#endif
|
|
117
|
+
#if defined(kIOUSBInterfaceInterfaceID700)
|
|
118
|
+
{
|
|
119
|
+
.min_os_version = 101000,
|
|
120
|
+
.version = 700,
|
|
121
|
+
.interface_id = kIOUSBInterfaceInterfaceID700,
|
|
122
|
+
},
|
|
123
|
+
#endif
|
|
124
|
+
#if defined(kIOUSBInterfaceInterfaceID650)
|
|
125
|
+
{
|
|
126
|
+
.min_os_version = 100900,
|
|
127
|
+
.version = 650,
|
|
128
|
+
.interface_id = kIOUSBInterfaceInterfaceID650
|
|
129
|
+
},
|
|
130
|
+
#endif
|
|
131
|
+
#if defined(kIOUSBInterfaceInterfaceID550)
|
|
132
|
+
{
|
|
133
|
+
.min_os_version = 100803,
|
|
134
|
+
.version = 550,
|
|
135
|
+
.interface_id = kIOUSBInterfaceInterfaceID550,
|
|
136
|
+
},
|
|
137
|
+
#endif
|
|
138
|
+
#if defined(kIOUSBInterfaceInterfaceID245)
|
|
139
|
+
{
|
|
140
|
+
.min_os_version = 100407,
|
|
141
|
+
.version = 245,
|
|
142
|
+
.interface_id = kIOUSBInterfaceInterfaceID245,
|
|
143
|
+
},
|
|
144
|
+
#endif
|
|
145
|
+
{
|
|
146
|
+
.min_os_version = 100000,
|
|
147
|
+
.version = 220,
|
|
148
|
+
.interface_id = kIOUSBInterfaceInterfaceID220,
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
.version = 0,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
static struct darwin_iokit_interface cached_interface = {.version = 0};
|
|
155
|
+
if (libusb_testonly_clear_running_version_cache) {
|
|
156
|
+
memset (&cached_interface, 0, sizeof (cached_interface));
|
|
157
|
+
}
|
|
158
|
+
if (0 == cached_interface.version) {
|
|
159
|
+
uint32_t os_version = get_running_version();
|
|
160
|
+
for (int i = 0 ; interfaces[i].version > 0 ; ++i) {
|
|
161
|
+
if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) {
|
|
162
|
+
cached_interface = interfaces[i];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
libusb_testonly_using_running_interface_version = cached_interface.version;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return &cached_interface;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static CFUUIDRef get_interface_interface_id(void) {
|
|
173
|
+
return get_interface_interface()->interface_id;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
static int get_interface_interface_version(void) {
|
|
177
|
+
return get_interface_interface()->version;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static const struct darwin_iokit_interface *get_device_interface(void) {
|
|
181
|
+
struct darwin_iokit_interface interfaces[] = {
|
|
182
|
+
#if defined(kIOUSBDeviceInterfaceID650)
|
|
183
|
+
{
|
|
184
|
+
.min_os_version = 100900,
|
|
185
|
+
.version = 650,
|
|
186
|
+
.interface_id = kIOUSBDeviceInterfaceID650,
|
|
187
|
+
},
|
|
188
|
+
#endif
|
|
189
|
+
#if defined(kIOUSBDeviceInterfaceID500)
|
|
190
|
+
{
|
|
191
|
+
.min_os_version = 100703,
|
|
192
|
+
.version = 500,
|
|
193
|
+
.interface_id = kIOUSBDeviceInterfaceID500,
|
|
194
|
+
},
|
|
195
|
+
#endif
|
|
196
|
+
#if defined(kIOUSBDeviceInterfaceID320)
|
|
197
|
+
{
|
|
198
|
+
.min_os_version = 100504,
|
|
199
|
+
.version = 320,
|
|
200
|
+
.interface_id = kIOUSBDeviceInterfaceID320,
|
|
201
|
+
},
|
|
202
|
+
#endif
|
|
203
|
+
#if defined(kIOUSBDeviceInterfaceID300)
|
|
204
|
+
{
|
|
205
|
+
.min_os_version = 100500,
|
|
206
|
+
.version = 300,
|
|
207
|
+
.interface_id = kIOUSBDeviceInterfaceID300,
|
|
208
|
+
},
|
|
209
|
+
#endif
|
|
210
|
+
#if defined(kIOUSBDeviceInterfaceID245)
|
|
211
|
+
{
|
|
212
|
+
.min_os_version = 100407,
|
|
213
|
+
.version = 245,
|
|
214
|
+
.interface_id = kIOUSBDeviceInterfaceID245,
|
|
215
|
+
},
|
|
216
|
+
#endif
|
|
217
|
+
{
|
|
218
|
+
.min_os_version = 100000,
|
|
219
|
+
.version = 197,
|
|
220
|
+
.interface_id = kIOUSBDeviceInterfaceID197,
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
.version = 0,
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
static struct darwin_iokit_interface cached_interface = {.version = 0};
|
|
227
|
+
if (libusb_testonly_clear_running_version_cache) {
|
|
228
|
+
memset (&cached_interface, 0, sizeof (cached_interface));
|
|
229
|
+
}
|
|
230
|
+
if (0 == cached_interface.version) {
|
|
231
|
+
uint32_t os_version = get_running_version();
|
|
232
|
+
for (int i = 0 ; interfaces[i].version > 0 ; ++i) {
|
|
233
|
+
if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) {
|
|
234
|
+
cached_interface = interfaces[i];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
libusb_testonly_using_running_device_version = cached_interface.version;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return &cached_interface;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
static CFUUIDRef get_device_interface_id(void) {
|
|
244
|
+
return get_device_interface()->interface_id;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static int get_device_interface_version(void) {
|
|
248
|
+
return get_device_interface()->version;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
struct darwin_pipe_properties {
|
|
252
|
+
uint8_t number;
|
|
253
|
+
uint8_t direction;
|
|
254
|
+
uint8_t transfer_type;
|
|
255
|
+
uint16_t max_packet_size;
|
|
256
|
+
uint8_t interval;
|
|
257
|
+
};
|
|
258
|
+
typedef struct darwin_pipe_properties darwin_pipe_properties_t;
|
|
259
|
+
|
|
260
|
+
static IOReturn darwin_get_pipe_properties(struct darwin_interface *cInterface, uint8_t pipe, darwin_pipe_properties_t *out) {
|
|
261
|
+
IOReturn kresult;
|
|
262
|
+
|
|
263
|
+
#if (MAX_INTERFACE_VERSION >= 550)
|
|
264
|
+
if (get_interface_interface_version() >= 550) {
|
|
265
|
+
IOUSBEndpointProperties pipe_properties = {.bVersion = kUSBEndpointPropertiesVersion3};
|
|
266
|
+
kresult = (*IOINTERFACE_V(cInterface, 550))->GetPipePropertiesV3 (IOINTERFACE(cInterface), pipe, &pipe_properties);
|
|
267
|
+
if (kIOReturnSuccess == kresult) {
|
|
268
|
+
out->number = pipe_properties.bEndpointNumber;
|
|
269
|
+
out->direction = pipe_properties.bDirection;
|
|
270
|
+
out->transfer_type = pipe_properties.bTransferType;
|
|
271
|
+
out->max_packet_size = pipe_properties.wMaxPacketSize;
|
|
272
|
+
out->interval = pipe_properties.bInterval;
|
|
273
|
+
}
|
|
274
|
+
return kresult;
|
|
275
|
+
}
|
|
276
|
+
#endif
|
|
277
|
+
return (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction,
|
|
278
|
+
&out->number, &out->transfer_type, &out->max_packet_size,
|
|
279
|
+
&out->interval);
|
|
280
|
+
}
|
|
281
|
+
|
|
99
282
|
#if defined(ENABLE_LOGGING)
|
|
100
283
|
static const char *darwin_error_str (IOReturn result) {
|
|
101
284
|
static char string_buffer[50];
|
|
@@ -172,7 +355,72 @@ static enum libusb_error darwin_to_libusb (IOReturn result) {
|
|
|
172
355
|
}
|
|
173
356
|
}
|
|
174
357
|
|
|
175
|
-
|
|
358
|
+
uint32_t get_running_version(void) {
|
|
359
|
+
if (libusb_testonly_fake_running_version > 0) {
|
|
360
|
+
return libusb_testonly_fake_running_version;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
int ret;
|
|
364
|
+
#if !defined(TARGET_OS_OSX) || TARGET_OS_OSX == 1
|
|
365
|
+
char os_version_string[64] = {'\0'};;
|
|
366
|
+
size_t os_version_string_len = sizeof(os_version_string) - 1;
|
|
367
|
+
|
|
368
|
+
/* newer versions of macOS provide a sysctl for the OS version but this is not useful for iOS without
|
|
369
|
+
* code detecting this is iOS and a mapping from iOS -> macOS version. it is still useful to have since
|
|
370
|
+
* it provides the exact macOS version instead of the approximate version (as below). */
|
|
371
|
+
ret = sysctlbyname("kern.osproductversion", os_version_string, &os_version_string_len, NULL, 0);
|
|
372
|
+
if (ret == 0) {
|
|
373
|
+
int major = 10, minor = 0, patch = 0;
|
|
374
|
+
ret = sscanf(os_version_string, "%i.%i.%i", &major, &minor, &patch);
|
|
375
|
+
if (ret < 2) {
|
|
376
|
+
usbi_err (NULL, "could not determine the running OS version, assuming 10.0, kern.osproductversion=%s", os_version_string);
|
|
377
|
+
return 100000;
|
|
378
|
+
}
|
|
379
|
+
return (major * 10000) + (minor * 100) + patch;
|
|
380
|
+
}
|
|
381
|
+
#endif
|
|
382
|
+
|
|
383
|
+
char os_release_string[64] = {'\0'};
|
|
384
|
+
size_t os_release_string_len = sizeof(os_release_string) - 1;
|
|
385
|
+
/* if the version can not be detected libusb assumes 10.0 so ignore any error here */
|
|
386
|
+
ret = sysctlbyname("kern.osrelease", os_release_string, &os_release_string_len, NULL, 0);
|
|
387
|
+
if (ret != 0) {
|
|
388
|
+
usbi_err (NULL, "could not read kern.osrelease, errno=", errno);
|
|
389
|
+
return 100000;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
int darwin_major = 1, darwin_minor = 0;
|
|
393
|
+
ret = sscanf(os_release_string, "%i.%i", &darwin_major, &darwin_minor);
|
|
394
|
+
if (ret < 1) {
|
|
395
|
+
usbi_err (NULL, "could not determine the running Darwin version, assuming 1.3 (OS X 10.0), kern.osrelease=%s", os_release_string);
|
|
396
|
+
return 100000;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
int major = 10, minor = 0, patch = 0;
|
|
400
|
+
|
|
401
|
+
if (1 == darwin_major && darwin_minor < 4) {
|
|
402
|
+
/* 10.0.x */
|
|
403
|
+
} else if (darwin_major < 6) {
|
|
404
|
+
/* assume 10.1 for anything in this range */
|
|
405
|
+
minor = 1;
|
|
406
|
+
} else if (darwin_major < 20) {
|
|
407
|
+
/* from macOS 10.2 through 10.15 the minor version can be calculated from the darwin_major by subtracting 4 and
|
|
408
|
+
* the patch level almost always matches darwin_minor. when the darwin_minor does not match the OS X patch level
|
|
409
|
+
* it is usually because Apple did not change it in a particular point release. when darwin_minor is changed it
|
|
410
|
+
* always matches the OS X/macOS patch level. */
|
|
411
|
+
minor = darwin_major - 4;
|
|
412
|
+
patch = darwin_minor;
|
|
413
|
+
} else {
|
|
414
|
+
/* unlikely to be used as kern.osproductversion is available from 10.10 on */
|
|
415
|
+
major = darwin_major - 9;
|
|
416
|
+
minor = darwin_minor;
|
|
417
|
+
/* ignore the patch level in this range */
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return (major * 10000) + (minor * 100) + patch;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/* this function must be called with the darwin_cached_devices_mutex held */
|
|
176
424
|
static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) {
|
|
177
425
|
cached_dev->refcount--;
|
|
178
426
|
/* free the device and remove it from the cache */
|
|
@@ -180,7 +428,7 @@ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev)
|
|
|
180
428
|
list_del(&cached_dev->list);
|
|
181
429
|
|
|
182
430
|
if (cached_dev->device) {
|
|
183
|
-
(*
|
|
431
|
+
(*cached_dev->device)->Release(cached_dev->device);
|
|
184
432
|
cached_dev->device = NULL;
|
|
185
433
|
}
|
|
186
434
|
IOObjectRelease (cached_dev->service);
|
|
@@ -300,12 +548,12 @@ static bool get_ioregistry_value_data (io_service_t service, CFStringRef propert
|
|
|
300
548
|
return success;
|
|
301
549
|
}
|
|
302
550
|
|
|
303
|
-
static
|
|
551
|
+
static int darwin_device_from_service (struct libusb_context *ctx, io_service_t service, usb_device_t* device)
|
|
304
552
|
{
|
|
305
553
|
io_cf_plugin_ref_t *plugInInterface = NULL;
|
|
306
|
-
usb_device_t **device;
|
|
307
554
|
IOReturn kresult;
|
|
308
555
|
SInt32 score;
|
|
556
|
+
|
|
309
557
|
const int max_retries = 5;
|
|
310
558
|
|
|
311
559
|
/* The IOCreatePlugInInterfaceForService function might consistently return
|
|
@@ -325,17 +573,21 @@ static usb_device_t **darwin_device_from_service (struct libusb_context *ctx, io
|
|
|
325
573
|
nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
|
|
326
574
|
}
|
|
327
575
|
|
|
328
|
-
if (kIOReturnSuccess != kresult
|
|
576
|
+
if (kIOReturnSuccess != kresult) {
|
|
329
577
|
usbi_dbg (ctx, "could not set up plugin for service: %s", darwin_error_str (kresult));
|
|
330
|
-
return
|
|
578
|
+
return darwin_to_libusb(kresult);
|
|
579
|
+
}
|
|
580
|
+
if (!plugInInterface) {
|
|
581
|
+
usbi_dbg (ctx, "could not set up plugin for service");
|
|
582
|
+
return LIBUSB_ERROR_OTHER;
|
|
331
583
|
}
|
|
332
584
|
|
|
333
|
-
(void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(
|
|
334
|
-
(LPVOID)
|
|
585
|
+
(void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(get_device_interface_id()),
|
|
586
|
+
(LPVOID)device);
|
|
335
587
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
336
588
|
(*plugInInterface)->Release (plugInInterface);
|
|
337
589
|
|
|
338
|
-
return
|
|
590
|
+
return LIBUSB_SUCCESS;
|
|
339
591
|
}
|
|
340
592
|
|
|
341
593
|
static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
|
|
@@ -377,8 +629,6 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
377
629
|
struct darwin_cached_device *old_device;
|
|
378
630
|
|
|
379
631
|
io_service_t device;
|
|
380
|
-
UInt64 session, locationID;
|
|
381
|
-
int ret;
|
|
382
632
|
|
|
383
633
|
usbi_mutex_lock(&active_contexts_lock);
|
|
384
634
|
|
|
@@ -386,7 +636,9 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
386
636
|
bool is_reenumerating = false;
|
|
387
637
|
|
|
388
638
|
/* get the location from the i/o registry */
|
|
389
|
-
|
|
639
|
+
UInt64 session = 0;
|
|
640
|
+
bool ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
|
|
641
|
+
UInt32 locationID = 0;
|
|
390
642
|
(void) get_ioregistry_value_number (device, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
|
|
391
643
|
IOObjectRelease (device);
|
|
392
644
|
if (!ret)
|
|
@@ -394,18 +646,18 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
394
646
|
|
|
395
647
|
/* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function
|
|
396
648
|
otherwise no cached device will ever get freed */
|
|
397
|
-
usbi_mutex_lock(&
|
|
649
|
+
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
398
650
|
list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
399
651
|
if (old_device->session == session) {
|
|
400
652
|
if (old_device->in_reenumerate) {
|
|
401
653
|
/* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
|
|
402
654
|
* will deref if needed. */
|
|
403
|
-
usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64
|
|
404
|
-
|
|
655
|
+
usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64
|
|
656
|
+
", locationID: 0x%" PRIx32, session, locationID);
|
|
405
657
|
|
|
406
658
|
/* the device object is no longer usable so go ahead and release it */
|
|
407
659
|
if (old_device->device) {
|
|
408
|
-
(*
|
|
660
|
+
(*old_device->device)->Release(old_device->device);
|
|
409
661
|
old_device->device = NULL;
|
|
410
662
|
}
|
|
411
663
|
|
|
@@ -418,7 +670,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
418
670
|
}
|
|
419
671
|
}
|
|
420
672
|
|
|
421
|
-
usbi_mutex_unlock(&
|
|
673
|
+
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
422
674
|
if (is_reenumerating) {
|
|
423
675
|
continue;
|
|
424
676
|
}
|
|
@@ -466,8 +718,8 @@ static void darwin_fail_startup(void) {
|
|
|
466
718
|
}
|
|
467
719
|
|
|
468
720
|
static void *darwin_event_thread_main (void *arg0) {
|
|
721
|
+
UNUSED(arg0);
|
|
469
722
|
IOReturn kresult;
|
|
470
|
-
struct libusb_context *ctx = (struct libusb_context *)arg0;
|
|
471
723
|
CFRunLoopRef runloop;
|
|
472
724
|
CFRunLoopSourceRef libusb_shutdown_cfsource;
|
|
473
725
|
CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
|
|
@@ -495,7 +747,7 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
495
747
|
io_iterator_t libusb_add_device_iterator;
|
|
496
748
|
|
|
497
749
|
/* ctx must only be used for logging during thread startup */
|
|
498
|
-
usbi_dbg (
|
|
750
|
+
usbi_dbg (NULL, "creating hotplug event source");
|
|
499
751
|
|
|
500
752
|
runloop = CFRunLoopGetCurrent ();
|
|
501
753
|
CFRetain (runloop);
|
|
@@ -519,7 +771,7 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
519
771
|
NULL, &libusb_rem_device_iterator);
|
|
520
772
|
|
|
521
773
|
if (kresult != kIOReturnSuccess) {
|
|
522
|
-
usbi_err (
|
|
774
|
+
usbi_err (NULL, "could not add hotplug event source: %s", darwin_error_str (kresult));
|
|
523
775
|
CFRelease (libusb_shutdown_cfsource);
|
|
524
776
|
CFRelease (runloop);
|
|
525
777
|
darwin_fail_startup ();
|
|
@@ -532,7 +784,7 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
532
784
|
NULL, &libusb_add_device_iterator);
|
|
533
785
|
|
|
534
786
|
if (kresult != kIOReturnSuccess) {
|
|
535
|
-
usbi_err (
|
|
787
|
+
usbi_err (NULL, "could not add hotplug event source: %s", darwin_error_str (kresult));
|
|
536
788
|
CFRelease (libusb_shutdown_cfsource);
|
|
537
789
|
CFRelease (runloop);
|
|
538
790
|
darwin_fail_startup ();
|
|
@@ -542,7 +794,7 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
542
794
|
darwin_clear_iterator (libusb_rem_device_iterator);
|
|
543
795
|
darwin_clear_iterator (libusb_add_device_iterator);
|
|
544
796
|
|
|
545
|
-
usbi_dbg (
|
|
797
|
+
usbi_dbg (NULL, "darwin event thread ready to receive events");
|
|
546
798
|
|
|
547
799
|
/* signal the main thread that the hotplug runloop has been created. */
|
|
548
800
|
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
@@ -582,73 +834,82 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
582
834
|
pthread_exit (NULL);
|
|
583
835
|
}
|
|
584
836
|
|
|
585
|
-
/* cleanup function to destroy cached devices */
|
|
837
|
+
/* cleanup function to destroy cached devices. must be called with a lock on darwin_cached_devices_mutex */
|
|
586
838
|
static void darwin_cleanup_devices(void) {
|
|
587
839
|
struct darwin_cached_device *dev, *next;
|
|
588
840
|
|
|
589
841
|
list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
842
|
+
if (dev->refcount > 1) {
|
|
843
|
+
usbi_err(NULL, "device still referenced at libusb_exit");
|
|
844
|
+
}
|
|
590
845
|
darwin_deref_cached_device(dev);
|
|
591
846
|
}
|
|
592
847
|
}
|
|
593
848
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
849
|
+
/* must be called with a lock on darwin_cached_devices_mutex */
|
|
850
|
+
static int darwin_first_time_init(void) {
|
|
851
|
+
if (NULL == darwin_cached_devices.next) {
|
|
852
|
+
list_init (&darwin_cached_devices);
|
|
853
|
+
}
|
|
597
854
|
|
|
598
|
-
|
|
855
|
+
/* cache the interface versions that will be used. as a sanity check verify
|
|
856
|
+
* that the interface versions are non-zero. */
|
|
857
|
+
const struct darwin_iokit_interface *interface_interface = get_interface_interface();
|
|
858
|
+
const struct darwin_iokit_interface *device_interface = get_device_interface();
|
|
859
|
+
if (0 == interface_interface->version || 0 == device_interface->version) {
|
|
860
|
+
usbi_err(NULL, "could not determine the device or interface interface to use with this version "
|
|
861
|
+
"of macOS (or MacOS X), current_running_version = %" PRIu32, get_running_version());
|
|
862
|
+
return LIBUSB_ERROR_OTHER;
|
|
863
|
+
}
|
|
599
864
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
assert(list_empty(&darwin_cached_devices));
|
|
606
|
-
#if !defined(HAVE_CLOCK_GETTIME)
|
|
607
|
-
/* create the clocks that will be used if clock_gettime() is not available */
|
|
608
|
-
host_name_port_t host_self;
|
|
609
|
-
|
|
610
|
-
host_self = mach_host_self();
|
|
611
|
-
host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
|
|
612
|
-
host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
|
|
613
|
-
mach_port_deallocate(mach_task_self(), host_self);
|
|
614
|
-
#endif
|
|
615
|
-
}
|
|
865
|
+
if (!list_empty(&darwin_cached_devices)) {
|
|
866
|
+
usbi_err(NULL, "libusb_device reference not released on last exit. will not continue");
|
|
867
|
+
return LIBUSB_ERROR_OTHER;
|
|
868
|
+
}
|
|
616
869
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
870
|
+
int rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, NULL);
|
|
871
|
+
if (0 != rc) {
|
|
872
|
+
usbi_err (NULL, "could not create event thread, error %d", rc);
|
|
873
|
+
return LIBUSB_ERROR_OTHER;
|
|
874
|
+
}
|
|
620
875
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
break;
|
|
627
|
-
}
|
|
876
|
+
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
877
|
+
libusb_darwin_at_started = true;
|
|
878
|
+
while (NULL == libusb_darwin_acfl) {
|
|
879
|
+
pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
880
|
+
}
|
|
628
881
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
rc = LIBUSB_ERROR_OTHER;
|
|
635
|
-
}
|
|
636
|
-
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
882
|
+
if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) {
|
|
883
|
+
libusb_darwin_acfl = NULL;
|
|
884
|
+
rc = LIBUSB_ERROR_OTHER;
|
|
885
|
+
}
|
|
886
|
+
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
637
887
|
|
|
638
|
-
|
|
639
|
-
|
|
888
|
+
return rc;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
static int darwin_init_context(struct libusb_context *ctx) {
|
|
892
|
+
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
893
|
+
|
|
894
|
+
bool first_init = (1 == ++init_count);
|
|
895
|
+
|
|
896
|
+
if (first_init) {
|
|
897
|
+
int rc = darwin_first_time_init();
|
|
898
|
+
if (LIBUSB_SUCCESS != rc) {
|
|
899
|
+
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
900
|
+
return rc;
|
|
640
901
|
}
|
|
641
|
-
}
|
|
902
|
+
}
|
|
903
|
+
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
904
|
+
|
|
905
|
+
return darwin_scan_devices (ctx);
|
|
906
|
+
}
|
|
642
907
|
|
|
908
|
+
static int darwin_init(struct libusb_context *ctx) {
|
|
909
|
+
int rc = darwin_init_context(ctx);
|
|
643
910
|
if (LIBUSB_SUCCESS != rc) {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
#if !defined(HAVE_CLOCK_GETTIME)
|
|
647
|
-
mach_port_deallocate(mach_task_self(), clock_realtime);
|
|
648
|
-
mach_port_deallocate(mach_task_self(), clock_monotonic);
|
|
649
|
-
#endif
|
|
650
|
-
}
|
|
651
|
-
--init_count;
|
|
911
|
+
/* clean up any allocated resources */
|
|
912
|
+
darwin_exit(ctx);
|
|
652
913
|
}
|
|
653
914
|
|
|
654
915
|
return rc;
|
|
@@ -657,23 +918,26 @@ static int darwin_init(struct libusb_context *ctx) {
|
|
|
657
918
|
static void darwin_exit (struct libusb_context *ctx) {
|
|
658
919
|
UNUSED(ctx);
|
|
659
920
|
|
|
921
|
+
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
660
922
|
if (0 == --init_count) {
|
|
661
923
|
/* stop the event runloop and wait for the thread to terminate. */
|
|
662
924
|
pthread_mutex_lock (&libusb_darwin_at_mutex);
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
925
|
+
if (NULL != libusb_darwin_acfls) {
|
|
926
|
+
CFRunLoopSourceSignal (libusb_darwin_acfls);
|
|
927
|
+
CFRunLoopWakeUp (libusb_darwin_acfl);
|
|
928
|
+
while (libusb_darwin_acfl)
|
|
929
|
+
pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
if (libusb_darwin_at_started) {
|
|
933
|
+
pthread_join (libusb_darwin_at, NULL);
|
|
934
|
+
libusb_darwin_at_started = false;
|
|
935
|
+
}
|
|
667
936
|
pthread_mutex_unlock (&libusb_darwin_at_mutex);
|
|
668
|
-
pthread_join (libusb_darwin_at, NULL);
|
|
669
937
|
|
|
670
938
|
darwin_cleanup_devices ();
|
|
671
|
-
|
|
672
|
-
#if !defined(HAVE_CLOCK_GETTIME)
|
|
673
|
-
mach_port_deallocate(mach_task_self(), clock_realtime);
|
|
674
|
-
mach_port_deallocate(mach_task_self(), clock_monotonic);
|
|
675
|
-
#endif
|
|
676
939
|
}
|
|
940
|
+
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
677
941
|
}
|
|
678
942
|
|
|
679
943
|
static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
|
|
@@ -683,12 +947,12 @@ static int get_configuration_index (struct libusb_device *dev, UInt8 config_valu
|
|
|
683
947
|
IOReturn kresult;
|
|
684
948
|
|
|
685
949
|
/* is there a simpler way to determine the index? */
|
|
686
|
-
kresult = (*
|
|
950
|
+
kresult = (*priv->device)->GetNumberOfConfigurations (priv->device, &numConfig);
|
|
687
951
|
if (kresult != kIOReturnSuccess)
|
|
688
952
|
return darwin_to_libusb (kresult);
|
|
689
953
|
|
|
690
954
|
for (i = 0 ; i < numConfig ; i++) {
|
|
691
|
-
(*
|
|
955
|
+
(*priv->device)->GetConfigurationDescriptorPtr (priv->device, i, &desc);
|
|
692
956
|
|
|
693
957
|
if (desc->bConfigurationValue == config_value)
|
|
694
958
|
return i;
|
|
@@ -740,7 +1004,7 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi
|
|
|
740
1004
|
|
|
741
1005
|
/* check whether the os has configured the device */
|
|
742
1006
|
static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
|
|
743
|
-
usb_device_t
|
|
1007
|
+
usb_device_t darwin_device = dev->device;
|
|
744
1008
|
|
|
745
1009
|
IOUSBConfigurationDescriptorPtr configDesc;
|
|
746
1010
|
IOUSBFindInterfaceRequest request;
|
|
@@ -776,7 +1040,7 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
|
|
|
776
1040
|
request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
|
|
777
1041
|
request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
|
|
778
1042
|
|
|
779
|
-
kresult = (*
|
|
1043
|
+
kresult = (*darwin_device)->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
|
|
780
1044
|
if (kresult != kIOReturnSuccess)
|
|
781
1045
|
return darwin_to_libusb (kresult);
|
|
782
1046
|
|
|
@@ -805,7 +1069,7 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
|
|
|
805
1069
|
return LIBUSB_SUCCESS;
|
|
806
1070
|
}
|
|
807
1071
|
|
|
808
|
-
static IOReturn darwin_request_descriptor (usb_device_t
|
|
1072
|
+
static IOReturn darwin_request_descriptor (usb_device_t device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
|
|
809
1073
|
IOUSBDevRequestTO req;
|
|
810
1074
|
|
|
811
1075
|
assert(buffer_size <= UINT16_MAX);
|
|
@@ -826,7 +1090,7 @@ static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UI
|
|
|
826
1090
|
}
|
|
827
1091
|
|
|
828
1092
|
static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
|
|
829
|
-
usb_device_t
|
|
1093
|
+
usb_device_t device = dev->device;
|
|
830
1094
|
int retries = 1;
|
|
831
1095
|
long delay = 30000; // microseconds
|
|
832
1096
|
int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
|
|
@@ -877,15 +1141,17 @@ static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *
|
|
|
877
1141
|
|
|
878
1142
|
if (kIOReturnSuccess != ret && is_open && try_unsuspend) {
|
|
879
1143
|
/* device may be suspended. unsuspend it and try again */
|
|
880
|
-
#if
|
|
881
|
-
|
|
1144
|
+
#if MAX_DEVICE_VERSION >= 320
|
|
1145
|
+
if (get_device_interface_version() >= 320) {
|
|
1146
|
+
UInt32 info = 0;
|
|
882
1147
|
|
|
883
|
-
|
|
884
|
-
|
|
1148
|
+
/* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */
|
|
1149
|
+
(void)(*IODEVICE_V(device, 320))->GetUSBDeviceInformation (device, &info);
|
|
885
1150
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1151
|
+
/* note that the device was suspended */
|
|
1152
|
+
if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
|
|
1153
|
+
try_unsuspend = 1;
|
|
1154
|
+
}
|
|
889
1155
|
#endif
|
|
890
1156
|
|
|
891
1157
|
if (try_unsuspend) {
|
|
@@ -998,7 +1264,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
|
|
|
998
1264
|
UInt64 sessionID = 0, parent_sessionID = 0;
|
|
999
1265
|
UInt32 locationID = 0;
|
|
1000
1266
|
enum libusb_error ret = LIBUSB_SUCCESS;
|
|
1001
|
-
usb_device_t
|
|
1267
|
+
usb_device_t device;
|
|
1002
1268
|
UInt8 port = 0;
|
|
1003
1269
|
|
|
1004
1270
|
/* assuming sessionID != 0 normally (never seen it be 0) */
|
|
@@ -1018,10 +1284,10 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
|
|
|
1018
1284
|
usbi_dbg(ctx, "parent sessionID: 0x%" PRIx64, parent_sessionID);
|
|
1019
1285
|
}
|
|
1020
1286
|
|
|
1021
|
-
usbi_mutex_lock(&
|
|
1287
|
+
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
1022
1288
|
do {
|
|
1023
1289
|
list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
1024
|
-
usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%
|
|
1290
|
+
usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32 " against cached device with sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32,
|
|
1025
1291
|
sessionID, locationID, new_device->session, new_device->location);
|
|
1026
1292
|
if (new_device->location == locationID && new_device->in_reenumerate) {
|
|
1027
1293
|
usbi_dbg (ctx, "found cached device with matching location that is being re-enumerated");
|
|
@@ -1041,9 +1307,8 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
|
|
|
1041
1307
|
|
|
1042
1308
|
usbi_dbg(ctx, "caching new device with sessionID 0x%" PRIx64, sessionID);
|
|
1043
1309
|
|
|
1044
|
-
|
|
1045
|
-
if (
|
|
1046
|
-
ret = LIBUSB_ERROR_NO_DEVICE;
|
|
1310
|
+
ret = darwin_device_from_service (ctx, service, &device);
|
|
1311
|
+
if (LIBUSB_SUCCESS != ret) {
|
|
1047
1312
|
break;
|
|
1048
1313
|
}
|
|
1049
1314
|
|
|
@@ -1094,7 +1359,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
|
|
|
1094
1359
|
}
|
|
1095
1360
|
} while (0);
|
|
1096
1361
|
|
|
1097
|
-
usbi_mutex_unlock(&
|
|
1362
|
+
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
1098
1363
|
|
|
1099
1364
|
return ret;
|
|
1100
1365
|
}
|
|
@@ -1158,7 +1423,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1158
1423
|
dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
|
|
1159
1424
|
}
|
|
1160
1425
|
|
|
1161
|
-
(*
|
|
1426
|
+
(*priv->dev->device)->GetDeviceSpeed (priv->dev->device, &devSpeed);
|
|
1162
1427
|
|
|
1163
1428
|
switch (devSpeed) {
|
|
1164
1429
|
case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
|
|
@@ -1227,7 +1492,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
1227
1492
|
|
|
1228
1493
|
if (0 == dpriv->open_count) {
|
|
1229
1494
|
/* try to open the device */
|
|
1230
|
-
kresult = (*
|
|
1495
|
+
kresult = (*dpriv->device)->USBDeviceOpenSeize (dpriv->device);
|
|
1231
1496
|
if (kresult != kIOReturnSuccess) {
|
|
1232
1497
|
usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult));
|
|
1233
1498
|
|
|
@@ -1242,12 +1507,13 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
1242
1507
|
}
|
|
1243
1508
|
|
|
1244
1509
|
/* create async event source */
|
|
1245
|
-
kresult = (*
|
|
1510
|
+
kresult = (*dpriv->device)->CreateDeviceAsyncEventSource (dpriv->device,
|
|
1511
|
+
&priv->cfSource);
|
|
1246
1512
|
if (kresult != kIOReturnSuccess) {
|
|
1247
1513
|
usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult));
|
|
1248
1514
|
|
|
1249
1515
|
if (priv->is_open) {
|
|
1250
|
-
(*
|
|
1516
|
+
(*dpriv->device)->USBDeviceClose (dpriv->device);
|
|
1251
1517
|
}
|
|
1252
1518
|
|
|
1253
1519
|
priv->is_open = false;
|
|
@@ -1303,7 +1569,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
|
|
|
1303
1569
|
|
|
1304
1570
|
if (priv->is_open) {
|
|
1305
1571
|
/* close the device */
|
|
1306
|
-
kresult = (*
|
|
1572
|
+
kresult = (*dpriv->device)->USBDeviceClose(dpriv->device);
|
|
1307
1573
|
if (kresult != kIOReturnSuccess) {
|
|
1308
1574
|
/* Log the fact that we had a problem closing the file, however failing a
|
|
1309
1575
|
* close isn't really an error, so return success anyway */
|
|
@@ -1335,7 +1601,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d
|
|
|
1335
1601
|
if (dev_handle->claimed_interfaces & (1U << i))
|
|
1336
1602
|
darwin_release_interface (dev_handle, i);
|
|
1337
1603
|
|
|
1338
|
-
kresult = (*
|
|
1604
|
+
kresult = (*dpriv->device)->SetConfiguration (dpriv->device, (UInt8)config);
|
|
1339
1605
|
if (kresult != kIOReturnSuccess)
|
|
1340
1606
|
return darwin_to_libusb (kresult);
|
|
1341
1607
|
|
|
@@ -1349,7 +1615,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d
|
|
|
1349
1615
|
return LIBUSB_SUCCESS;
|
|
1350
1616
|
}
|
|
1351
1617
|
|
|
1352
|
-
static IOReturn darwin_get_interface (usb_device_t
|
|
1618
|
+
static IOReturn darwin_get_interface (usb_device_t darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
|
|
1353
1619
|
IOUSBFindInterfaceRequest request;
|
|
1354
1620
|
IOReturn kresult;
|
|
1355
1621
|
io_iterator_t interface_iterator;
|
|
@@ -1364,7 +1630,7 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc,
|
|
|
1364
1630
|
request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
|
|
1365
1631
|
request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
|
|
1366
1632
|
|
|
1367
|
-
kresult = (*
|
|
1633
|
+
kresult = (*darwin_device)->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
|
|
1368
1634
|
if (kresult != kIOReturnSuccess)
|
|
1369
1635
|
return kresult;
|
|
1370
1636
|
|
|
@@ -1386,29 +1652,34 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc,
|
|
|
1386
1652
|
return kIOReturnSuccess;
|
|
1387
1653
|
}
|
|
1388
1654
|
|
|
1655
|
+
static const struct libusb_interface_descriptor *get_interface_descriptor_by_number(struct libusb_device_handle *dev_handle, struct libusb_config_descriptor *conf_desc, int iface, uint8_t altsetting)
|
|
1656
|
+
{
|
|
1657
|
+
int i;
|
|
1658
|
+
|
|
1659
|
+
for (i = 0; i < conf_desc->bNumInterfaces; i++) {
|
|
1660
|
+
if (altsetting < conf_desc->interface[i].num_altsetting && conf_desc->interface[i].altsetting[altsetting].bInterfaceNumber == iface) {
|
|
1661
|
+
return &conf_desc->interface[i].altsetting[altsetting];
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
usbi_err(HANDLE_CTX(dev_handle), "interface %d with altsetting %d not found for device", iface, (int)altsetting);
|
|
1666
|
+
return NULL;
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1389
1669
|
static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, uint8_t iface) {
|
|
1390
1670
|
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
1391
1671
|
|
|
1392
1672
|
/* current interface */
|
|
1393
1673
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
1394
|
-
#if InterfaceVersion >= 550
|
|
1395
|
-
IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
|
|
1396
|
-
#else
|
|
1397
|
-
UInt8 dont_care1, dont_care3;
|
|
1398
|
-
UInt16 dont_care2;
|
|
1399
|
-
#endif
|
|
1400
|
-
|
|
1401
1674
|
IOReturn kresult;
|
|
1402
|
-
|
|
1403
|
-
UInt8 numep, direction, number;
|
|
1675
|
+
uint8_t numep;
|
|
1404
1676
|
int rc;
|
|
1405
1677
|
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
1406
1678
|
|
|
1407
|
-
|
|
1408
1679
|
usbi_dbg (ctx, "building table of endpoints.");
|
|
1409
1680
|
|
|
1410
1681
|
/* retrieve the total number of endpoints on this interface */
|
|
1411
|
-
kresult = (*(cInterface
|
|
1682
|
+
kresult = (*IOINTERFACE(cInterface))->GetNumEndpoints(IOINTERFACE(cInterface), &numep);
|
|
1412
1683
|
if (kresult != kIOReturnSuccess) {
|
|
1413
1684
|
usbi_err (ctx, "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
|
|
1414
1685
|
return darwin_to_libusb (kresult);
|
|
@@ -1416,21 +1687,16 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
|
|
|
1416
1687
|
|
|
1417
1688
|
/* iterate through pipe references */
|
|
1418
1689
|
for (UInt8 i = 1 ; i <= numep ; i++) {
|
|
1419
|
-
|
|
1420
|
-
kresult = (
|
|
1421
|
-
number = pipeProperties.bEndpointNumber;
|
|
1422
|
-
direction = pipeProperties.bDirection;
|
|
1423
|
-
#else
|
|
1424
|
-
kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
|
|
1425
|
-
&dont_care2, &dont_care3);
|
|
1426
|
-
#endif
|
|
1690
|
+
darwin_pipe_properties_t pipe_properties;
|
|
1691
|
+
kresult = darwin_get_pipe_properties(cInterface, i, &pipe_properties);
|
|
1427
1692
|
if (kresult != kIOReturnSuccess) {
|
|
1428
1693
|
/* probably a buggy device. try to get the endpoint address from the descriptors */
|
|
1429
1694
|
struct libusb_config_descriptor *config;
|
|
1695
|
+
const struct libusb_interface_descriptor *if_desc;
|
|
1430
1696
|
const struct libusb_endpoint_descriptor *endpoint_desc;
|
|
1431
1697
|
UInt8 alt_setting;
|
|
1432
1698
|
|
|
1433
|
-
kresult = (*(cInterface
|
|
1699
|
+
kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting (IOINTERFACE(cInterface), &alt_setting);
|
|
1434
1700
|
if (kresult != kIOReturnSuccess) {
|
|
1435
1701
|
usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface");
|
|
1436
1702
|
return darwin_to_libusb (kresult);
|
|
@@ -1441,15 +1707,19 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
|
|
|
1441
1707
|
return rc;
|
|
1442
1708
|
}
|
|
1443
1709
|
|
|
1444
|
-
|
|
1445
|
-
|
|
1710
|
+
if_desc = get_interface_descriptor_by_number (dev_handle, config, iface, alt_setting);
|
|
1711
|
+
if (if_desc == NULL) {
|
|
1712
|
+
libusb_free_config_descriptor (config);
|
|
1446
1713
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1447
1714
|
}
|
|
1448
|
-
|
|
1715
|
+
|
|
1716
|
+
endpoint_desc = if_desc->endpoint + i - 1;
|
|
1449
1717
|
|
|
1450
1718
|
cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress;
|
|
1719
|
+
libusb_free_config_descriptor (config);
|
|
1451
1720
|
} else {
|
|
1452
|
-
cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) |
|
|
1721
|
+
cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == pipe_properties.direction) << kUSBRqDirnShift) |
|
|
1722
|
+
(pipe_properties.number & LIBUSB_ENDPOINT_ADDRESS_MASK));
|
|
1453
1723
|
}
|
|
1454
1724
|
|
|
1455
1725
|
usbi_dbg (ctx, "interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
|
|
@@ -1521,18 +1791,22 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8
|
|
|
1521
1791
|
|
|
1522
1792
|
/* Do the actual claim */
|
|
1523
1793
|
kresult = (*plugInInterface)->QueryInterface(plugInInterface,
|
|
1524
|
-
CFUUIDGetUUIDBytes(
|
|
1525
|
-
(LPVOID)&cInterface
|
|
1794
|
+
CFUUIDGetUUIDBytes(get_interface_interface_id()),
|
|
1795
|
+
(LPVOID)&IOINTERFACE(cInterface));
|
|
1526
1796
|
/* We no longer need the intermediate plug-in */
|
|
1527
1797
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
1528
1798
|
(*plugInInterface)->Release (plugInInterface);
|
|
1529
|
-
if (kresult != kIOReturnSuccess
|
|
1799
|
+
if (kresult != kIOReturnSuccess) {
|
|
1530
1800
|
usbi_err (ctx, "QueryInterface: %s", darwin_error_str(kresult));
|
|
1531
1801
|
return darwin_to_libusb (kresult);
|
|
1532
1802
|
}
|
|
1803
|
+
if (!IOINTERFACE(cInterface)) {
|
|
1804
|
+
usbi_err (ctx, "QueryInterface: returned null interface");
|
|
1805
|
+
return LIBUSB_ERROR_OTHER;
|
|
1806
|
+
}
|
|
1533
1807
|
|
|
1534
1808
|
/* claim the interface */
|
|
1535
|
-
kresult = (*(cInterface
|
|
1809
|
+
kresult = (*IOINTERFACE(cInterface))->USBInterfaceOpen(IOINTERFACE(cInterface));
|
|
1536
1810
|
if (kresult != kIOReturnSuccess) {
|
|
1537
1811
|
usbi_info (ctx, "USBInterfaceOpen: %s", darwin_error_str(kresult));
|
|
1538
1812
|
return darwin_to_libusb (kresult);
|
|
@@ -1550,7 +1824,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8
|
|
|
1550
1824
|
cInterface->cfSource = NULL;
|
|
1551
1825
|
|
|
1552
1826
|
/* create async event source */
|
|
1553
|
-
kresult = (*(cInterface
|
|
1827
|
+
kresult = (*IOINTERFACE(cInterface))->CreateInterfaceAsyncEventSource (IOINTERFACE(cInterface), &cInterface->cfSource);
|
|
1554
1828
|
if (kresult != kIOReturnSuccess) {
|
|
1555
1829
|
usbi_err (ctx, "could not create async event source");
|
|
1556
1830
|
|
|
@@ -1576,8 +1850,9 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin
|
|
|
1576
1850
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
1577
1851
|
|
|
1578
1852
|
/* Check to see if an interface is open */
|
|
1579
|
-
if (!cInterface
|
|
1853
|
+
if (!IOINTERFACE(cInterface)) {
|
|
1580
1854
|
return LIBUSB_SUCCESS;
|
|
1855
|
+
}
|
|
1581
1856
|
|
|
1582
1857
|
/* clean up endpoint data */
|
|
1583
1858
|
cInterface->num_endpoints = 0;
|
|
@@ -1589,15 +1864,15 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin
|
|
|
1589
1864
|
cInterface->cfSource = NULL;
|
|
1590
1865
|
}
|
|
1591
1866
|
|
|
1592
|
-
kresult = (*(cInterface
|
|
1867
|
+
kresult = (*IOINTERFACE(cInterface))->USBInterfaceClose(IOINTERFACE(cInterface));
|
|
1593
1868
|
if (kresult != kIOReturnSuccess)
|
|
1594
1869
|
usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
|
|
1595
1870
|
|
|
1596
|
-
kresult = (*(cInterface
|
|
1871
|
+
kresult = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
|
|
1597
1872
|
if (kresult != kIOReturnSuccess)
|
|
1598
1873
|
usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
|
|
1599
1874
|
|
|
1600
|
-
cInterface
|
|
1875
|
+
IOINTERFACE(cInterface) = NULL;
|
|
1601
1876
|
|
|
1602
1877
|
return darwin_to_libusb (kresult);
|
|
1603
1878
|
}
|
|
@@ -1607,7 +1882,7 @@ static int check_alt_setting_and_clear_halt(struct libusb_device_handle *dev_han
|
|
|
1607
1882
|
IOReturn kresult;
|
|
1608
1883
|
uint8_t current_alt_setting;
|
|
1609
1884
|
|
|
1610
|
-
kresult = (*(cInterface
|
|
1885
|
+
kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting (IOINTERFACE(cInterface), ¤t_alt_setting);
|
|
1611
1886
|
if (kresult == kIOReturnSuccess && altsetting != current_alt_setting) {
|
|
1612
1887
|
return LIBUSB_ERROR_PIPE;
|
|
1613
1888
|
}
|
|
@@ -1634,10 +1909,11 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand
|
|
|
1634
1909
|
/* current interface */
|
|
1635
1910
|
struct darwin_interface *cInterface = &priv->interfaces[iface];
|
|
1636
1911
|
|
|
1637
|
-
if (!cInterface
|
|
1912
|
+
if (!IOINTERFACE(cInterface)) {
|
|
1638
1913
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
1914
|
+
}
|
|
1639
1915
|
|
|
1640
|
-
kresult = (*(cInterface
|
|
1916
|
+
kresult = (*IOINTERFACE(cInterface))->SetAlternateInterface (IOINTERFACE(cInterface), altsetting);
|
|
1641
1917
|
if (kresult == kIOReturnSuccess) {
|
|
1642
1918
|
/* update the list of endpoints */
|
|
1643
1919
|
ret = get_endpoints (dev_handle, iface);
|
|
@@ -1689,7 +1965,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
|
|
|
1689
1965
|
}
|
|
1690
1966
|
|
|
1691
1967
|
/* newer versions of darwin support clearing additional bits on the device's endpoint */
|
|
1692
|
-
kresult = (*(cInterface
|
|
1968
|
+
kresult = (*IOINTERFACE(cInterface))->ClearPipeStallBothEnds(IOINTERFACE(cInterface), pipeRef);
|
|
1693
1969
|
if (kresult != kIOReturnSuccess)
|
|
1694
1970
|
usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult));
|
|
1695
1971
|
|
|
@@ -1783,12 +2059,12 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
1783
2059
|
cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
|
|
1784
2060
|
|
|
1785
2061
|
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
1786
|
-
(*
|
|
2062
|
+
(*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
1787
2063
|
memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
|
|
1788
2064
|
}
|
|
1789
2065
|
|
|
1790
2066
|
/* if we need to release capture */
|
|
1791
|
-
if (
|
|
2067
|
+
if (get_running_version() >= 101000) {
|
|
1792
2068
|
if (capture) {
|
|
1793
2069
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
|
1794
2070
|
options |= kUSBReEnumerateCaptureDeviceMask;
|
|
@@ -1799,7 +2075,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
1799
2075
|
}
|
|
1800
2076
|
|
|
1801
2077
|
/* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
|
|
1802
|
-
kresult = (*
|
|
2078
|
+
kresult = (*dpriv->device)->USBDeviceReEnumerate (dpriv->device, options);
|
|
1803
2079
|
if (kresult != kIOReturnSuccess) {
|
|
1804
2080
|
usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
|
|
1805
2081
|
dpriv->in_reenumerate = false;
|
|
@@ -1844,7 +2120,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
1844
2120
|
}
|
|
1845
2121
|
|
|
1846
2122
|
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
1847
|
-
(void) (*
|
|
2123
|
+
(void) (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
1848
2124
|
if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
|
|
1849
2125
|
usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
|
|
1850
2126
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
@@ -1864,7 +2140,7 @@ static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
|
|
|
1864
2140
|
#if !defined(TARGET_OS_OSX) || TARGET_OS_OSX == 1
|
|
1865
2141
|
if (dpriv->capture_count > 0) {
|
|
1866
2142
|
/* we have to use ResetDevice as USBDeviceReEnumerate() loses the authorization for capture */
|
|
1867
|
-
kresult = (*
|
|
2143
|
+
kresult = (*dpriv->device)->ResetDevice (dpriv->device);
|
|
1868
2144
|
ret = darwin_to_libusb (kresult);
|
|
1869
2145
|
} else {
|
|
1870
2146
|
ret = darwin_reenumerate_device (dev_handle, false);
|
|
@@ -1945,10 +2221,10 @@ static void darwin_destroy_device(struct libusb_device *dev) {
|
|
|
1945
2221
|
|
|
1946
2222
|
if (dpriv->dev) {
|
|
1947
2223
|
/* need to hold the lock in case this is the last reference to the device */
|
|
1948
|
-
usbi_mutex_lock(&
|
|
2224
|
+
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
1949
2225
|
darwin_deref_cached_device (dpriv->dev);
|
|
1950
2226
|
dpriv->dev = NULL;
|
|
1951
|
-
usbi_mutex_unlock(&
|
|
2227
|
+
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
1952
2228
|
}
|
|
1953
2229
|
}
|
|
1954
2230
|
|
|
@@ -1956,17 +2232,10 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
|
|
|
1956
2232
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1957
2233
|
|
|
1958
2234
|
IOReturn ret;
|
|
1959
|
-
uint8_t transferType;
|
|
1960
2235
|
uint8_t pipeRef;
|
|
1961
|
-
uint16_t maxPacketSize;
|
|
1962
2236
|
|
|
1963
2237
|
struct darwin_interface *cInterface;
|
|
1964
|
-
|
|
1965
|
-
IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
|
|
1966
|
-
#else
|
|
1967
|
-
/* None of the values below are used in libusb for bulk transfers */
|
|
1968
|
-
uint8_t direction, number, interval;
|
|
1969
|
-
#endif
|
|
2238
|
+
darwin_pipe_properties_t pipe_properties;
|
|
1970
2239
|
|
|
1971
2240
|
if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
|
|
1972
2241
|
usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
|
|
@@ -1974,47 +2243,38 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
|
|
|
1974
2243
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
1975
2244
|
}
|
|
1976
2245
|
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
transferType = pipeProperties.bTransferType;
|
|
1981
|
-
maxPacketSize = pipeProperties.wMaxPacketSize;
|
|
1982
|
-
#else
|
|
1983
|
-
ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
|
|
1984
|
-
&transferType, &maxPacketSize, &interval);
|
|
1985
|
-
#endif
|
|
1986
|
-
|
|
1987
|
-
if (ret) {
|
|
2246
|
+
ret = darwin_get_pipe_properties(cInterface, pipeRef, &pipe_properties);
|
|
2247
|
+
if (kIOReturnSuccess != ret) {
|
|
1988
2248
|
usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
|
|
1989
2249
|
darwin_error_str(ret), ret);
|
|
1990
2250
|
return darwin_to_libusb (ret);
|
|
1991
2251
|
}
|
|
1992
2252
|
|
|
1993
|
-
if (0 != (transfer->length %
|
|
2253
|
+
if (0 != (transfer->length % pipe_properties.max_packet_size)) {
|
|
1994
2254
|
/* do not need a zero packet */
|
|
1995
2255
|
transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET;
|
|
1996
2256
|
}
|
|
1997
2257
|
|
|
1998
2258
|
/* submit the request */
|
|
1999
2259
|
/* timeouts are unavailable on interrupt endpoints */
|
|
2000
|
-
if (
|
|
2260
|
+
if (pipe_properties.transfer_type == kUSBInterrupt) {
|
|
2001
2261
|
if (IS_XFERIN(transfer))
|
|
2002
|
-
ret = (*(cInterface
|
|
2003
|
-
|
|
2262
|
+
ret = (*IOINTERFACE(cInterface))->ReadPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
|
|
2263
|
+
(UInt32)transfer->length, darwin_async_io_callback, itransfer);
|
|
2004
2264
|
else
|
|
2005
|
-
ret = (*(cInterface
|
|
2006
|
-
|
|
2265
|
+
ret = (*IOINTERFACE(cInterface))->WritePipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
|
|
2266
|
+
(UInt32)transfer->length, darwin_async_io_callback, itransfer);
|
|
2007
2267
|
} else {
|
|
2008
2268
|
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
|
|
2009
2269
|
|
|
2010
2270
|
if (IS_XFERIN(transfer))
|
|
2011
|
-
ret = (*(cInterface
|
|
2012
|
-
|
|
2013
|
-
|
|
2271
|
+
ret = (*IOINTERFACE(cInterface))->ReadPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
|
|
2272
|
+
(UInt32)transfer->length, transfer->timeout, transfer->timeout,
|
|
2273
|
+
darwin_async_io_callback, itransfer);
|
|
2014
2274
|
else
|
|
2015
|
-
ret = (*(cInterface
|
|
2016
|
-
|
|
2017
|
-
|
|
2275
|
+
ret = (*IOINTERFACE(cInterface))->WritePipeAsyncTO(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
|
|
2276
|
+
(UInt32)transfer->length, transfer->timeout, transfer->timeout,
|
|
2277
|
+
darwin_async_io_callback, itransfer);
|
|
2018
2278
|
}
|
|
2019
2279
|
|
|
2020
2280
|
if (ret)
|
|
@@ -2024,7 +2284,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
|
|
|
2024
2284
|
return darwin_to_libusb (ret);
|
|
2025
2285
|
}
|
|
2026
2286
|
|
|
2027
|
-
#if
|
|
2287
|
+
#if MAX_INTERFACE_VERSION >= 550
|
|
2028
2288
|
static int submit_stream_transfer(struct usbi_transfer *itransfer) {
|
|
2029
2289
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
2030
2290
|
struct darwin_interface *cInterface;
|
|
@@ -2037,16 +2297,22 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
|
|
|
2037
2297
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2038
2298
|
}
|
|
2039
2299
|
|
|
2300
|
+
if (get_interface_interface_version() < 550) {
|
|
2301
|
+
usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version %d does not support bulk stream transfers",
|
|
2302
|
+
get_interface_interface_version());
|
|
2303
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2040
2306
|
itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
|
|
2041
2307
|
|
|
2042
2308
|
if (IS_XFERIN(transfer))
|
|
2043
|
-
ret = (*(cInterface
|
|
2044
|
-
|
|
2045
|
-
|
|
2309
|
+
ret = (*IOINTERFACE_V(cInterface, 550))->ReadStreamsPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, itransfer->stream_id,
|
|
2310
|
+
transfer->buffer, (UInt32)transfer->length, transfer->timeout,
|
|
2311
|
+
transfer->timeout, darwin_async_io_callback, itransfer);
|
|
2046
2312
|
else
|
|
2047
|
-
ret = (*(cInterface
|
|
2048
|
-
|
|
2049
|
-
|
|
2313
|
+
ret = (*IOINTERFACE_V(cInterface, 550))->WriteStreamsPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, itransfer->stream_id,
|
|
2314
|
+
transfer->buffer, (UInt32)transfer->length, transfer->timeout,
|
|
2315
|
+
transfer->timeout, darwin_async_io_callback, itransfer);
|
|
2050
2316
|
|
|
2051
2317
|
if (ret)
|
|
2052
2318
|
usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
|
|
@@ -2061,18 +2327,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
2061
2327
|
struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
|
|
2062
2328
|
|
|
2063
2329
|
IOReturn kresult;
|
|
2064
|
-
uint8_t pipeRef
|
|
2330
|
+
uint8_t pipeRef;
|
|
2065
2331
|
UInt64 frame;
|
|
2066
2332
|
AbsoluteTime atTime;
|
|
2067
2333
|
int i;
|
|
2068
|
-
|
|
2069
|
-
IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
|
|
2070
|
-
#else
|
|
2071
|
-
/* None of the values below are used in libusb for iso transfers */
|
|
2072
|
-
uint8_t direction, number, transferType;
|
|
2073
|
-
uint16_t maxPacketSize;
|
|
2074
|
-
#endif
|
|
2075
|
-
|
|
2334
|
+
darwin_pipe_properties_t pipe_properties;
|
|
2076
2335
|
struct darwin_interface *cInterface;
|
|
2077
2336
|
|
|
2078
2337
|
/* construct an array of IOUSBIsocFrames, reuse the old one if the sizes are the same */
|
|
@@ -2103,13 +2362,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
2103
2362
|
}
|
|
2104
2363
|
|
|
2105
2364
|
/* determine the properties of this endpoint and the speed of the device */
|
|
2106
|
-
|
|
2107
|
-
kresult = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, pipeRef, &pipeProperties);
|
|
2108
|
-
interval = pipeProperties.bInterval;
|
|
2109
|
-
#else
|
|
2110
|
-
kresult = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
|
|
2111
|
-
&transferType, &maxPacketSize, &interval);
|
|
2112
|
-
#endif
|
|
2365
|
+
kresult = darwin_get_pipe_properties(cInterface, pipeRef, &pipe_properties);
|
|
2113
2366
|
if (kresult != kIOReturnSuccess) {
|
|
2114
2367
|
usbi_err (TRANSFER_CTX (transfer), "failed to get pipe properties: %d", kresult);
|
|
2115
2368
|
free(tpriv->isoc_framelist);
|
|
@@ -2119,7 +2372,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
2119
2372
|
}
|
|
2120
2373
|
|
|
2121
2374
|
/* Last but not least we need the bus frame number */
|
|
2122
|
-
kresult = (*(cInterface
|
|
2375
|
+
kresult = (*IOINTERFACE(cInterface))->GetBusFrameNumber(IOINTERFACE(cInterface), &frame, &atTime);
|
|
2123
2376
|
if (kresult != kIOReturnSuccess) {
|
|
2124
2377
|
usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult);
|
|
2125
2378
|
free(tpriv->isoc_framelist);
|
|
@@ -2136,20 +2389,20 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
2136
2389
|
|
|
2137
2390
|
/* submit the request */
|
|
2138
2391
|
if (IS_XFERIN(transfer))
|
|
2139
|
-
kresult = (*(cInterface
|
|
2140
|
-
|
|
2141
|
-
|
|
2392
|
+
kresult = (*IOINTERFACE(cInterface))->ReadIsochPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, frame,
|
|
2393
|
+
(UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
|
|
2394
|
+
itransfer);
|
|
2142
2395
|
else
|
|
2143
|
-
kresult = (*(cInterface
|
|
2144
|
-
|
|
2145
|
-
|
|
2396
|
+
kresult = (*IOINTERFACE(cInterface))->WriteIsochPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, frame,
|
|
2397
|
+
(UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
|
|
2398
|
+
itransfer);
|
|
2146
2399
|
|
|
2147
2400
|
if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
|
|
2148
2401
|
/* Full speed */
|
|
2149
|
-
cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1));
|
|
2402
|
+
cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1));
|
|
2150
2403
|
else
|
|
2151
2404
|
/* High/super speed */
|
|
2152
|
-
cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)) / 8;
|
|
2405
|
+
cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)) / 8;
|
|
2153
2406
|
|
|
2154
2407
|
if (kresult != kIOReturnSuccess) {
|
|
2155
2408
|
usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
|
|
@@ -2197,10 +2450,11 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
|
|
|
2197
2450
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2198
2451
|
}
|
|
2199
2452
|
|
|
2200
|
-
kresult = (*(cInterface
|
|
2453
|
+
kresult = (*IOINTERFACE(cInterface))->ControlRequestAsyncTO (IOINTERFACE(cInterface), pipeRef,
|
|
2454
|
+
&(tpriv->req), darwin_async_io_callback, itransfer);
|
|
2201
2455
|
} else
|
|
2202
2456
|
/* control request on endpoint 0 */
|
|
2203
|
-
kresult = (*
|
|
2457
|
+
kresult = (*dpriv->device)->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer);
|
|
2204
2458
|
|
|
2205
2459
|
if (kresult != kIOReturnSuccess)
|
|
2206
2460
|
usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult));
|
|
@@ -2220,7 +2474,7 @@ static int darwin_submit_transfer(struct usbi_transfer *itransfer) {
|
|
|
2220
2474
|
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
|
2221
2475
|
return submit_iso_transfer(itransfer);
|
|
2222
2476
|
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
|
|
2223
|
-
#if
|
|
2477
|
+
#if MAX_INTERFACE_VERSION >= 550
|
|
2224
2478
|
return submit_stream_transfer(itransfer);
|
|
2225
2479
|
#else
|
|
2226
2480
|
usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers");
|
|
@@ -2239,10 +2493,11 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) {
|
|
|
2239
2493
|
|
|
2240
2494
|
usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe");
|
|
2241
2495
|
|
|
2242
|
-
if (!dpriv->device)
|
|
2496
|
+
if (!dpriv->device) {
|
|
2243
2497
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
2498
|
+
}
|
|
2244
2499
|
|
|
2245
|
-
kresult = (*
|
|
2500
|
+
kresult = (*dpriv->device)->USBDeviceAbortPipeZero (dpriv->device);
|
|
2246
2501
|
|
|
2247
2502
|
return darwin_to_libusb (kresult);
|
|
2248
2503
|
}
|
|
@@ -2262,23 +2517,29 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
|
|
|
2262
2517
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2263
2518
|
}
|
|
2264
2519
|
|
|
2265
|
-
if (!dpriv->device)
|
|
2520
|
+
if (!dpriv->device) {
|
|
2266
2521
|
return LIBUSB_ERROR_NO_DEVICE;
|
|
2522
|
+
}
|
|
2267
2523
|
|
|
2268
2524
|
usbi_warn (ctx, "aborting all transactions on interface %d pipe %d", iface, pipeRef);
|
|
2269
2525
|
|
|
2270
2526
|
/* abort transactions */
|
|
2271
|
-
#if
|
|
2272
|
-
if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type)
|
|
2273
|
-
(*(cInterface
|
|
2274
|
-
else
|
|
2527
|
+
#if MAX_INTERFACE_VERSION >= 550
|
|
2528
|
+
if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type && get_interface_interface_version() >= 550) {
|
|
2529
|
+
kresult = (*IOINTERFACE_V(cInterface, 550))->AbortStreamsPipe (IOINTERFACE(cInterface), pipeRef, itransfer->stream_id);
|
|
2530
|
+
} else
|
|
2275
2531
|
#endif
|
|
2276
|
-
|
|
2532
|
+
{
|
|
2533
|
+
kresult = (*IOINTERFACE(cInterface))->AbortPipe (IOINTERFACE(cInterface), pipeRef);
|
|
2534
|
+
}
|
|
2277
2535
|
|
|
2278
|
-
usbi_dbg (ctx, "calling clear pipe stall to clear the data toggle bit");
|
|
2279
2536
|
|
|
2280
|
-
|
|
2281
|
-
|
|
2537
|
+
if (get_interface_interface_version() <= 245) {
|
|
2538
|
+
/* with older releases of IOUSBFamily the OS always clears the host side data toggle. for
|
|
2539
|
+
consistency also clear the data toggle on the device. */
|
|
2540
|
+
usbi_dbg (ctx, "calling ClearPipeStallBothEnds to clear the data toggle bit");
|
|
2541
|
+
kresult = (*IOINTERFACE(cInterface))->ClearPipeStallBothEnds(IOINTERFACE(cInterface), pipeRef);
|
|
2542
|
+
}
|
|
2282
2543
|
|
|
2283
2544
|
return darwin_to_libusb (kresult);
|
|
2284
2545
|
}
|
|
@@ -2313,7 +2574,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
|
|
|
2313
2574
|
|
|
2314
2575
|
(void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface);
|
|
2315
2576
|
|
|
2316
|
-
(*(cInterface
|
|
2577
|
+
(*IOINTERFACE(cInterface))->WritePipe (IOINTERFACE(cInterface), pipeRef, transfer->buffer, 0);
|
|
2317
2578
|
}
|
|
2318
2579
|
|
|
2319
2580
|
tpriv->result = result;
|
|
@@ -2389,29 +2650,38 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
|
|
|
2389
2650
|
return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result));
|
|
2390
2651
|
}
|
|
2391
2652
|
|
|
2392
|
-
#if !defined(HAVE_CLOCK_GETTIME)
|
|
2393
2653
|
void usbi_get_monotonic_time(struct timespec *tp) {
|
|
2394
|
-
|
|
2654
|
+
/* Check if the SDK is new enough to declare clock_gettime(), and the deployment target is at least 10.12. */
|
|
2655
|
+
#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
|
|
2656
|
+
clock_gettime(CLOCK_MONOTONIC, tp);
|
|
2657
|
+
#else
|
|
2658
|
+
mach_timebase_info_data_t machTimeBaseInfo;
|
|
2659
|
+
mach_timebase_info(&machTimeBaseInfo);
|
|
2395
2660
|
|
|
2396
|
-
|
|
2397
|
-
|
|
2661
|
+
uint64_t uptime = mach_absolute_time();
|
|
2662
|
+
uint64_t uptimeNano = uptime * machTimeBaseInfo.numer / machTimeBaseInfo.denom;
|
|
2398
2663
|
|
|
2399
|
-
|
|
2400
|
-
|
|
2664
|
+
uint64_t uptimeSeconds = uptimeNano / NSEC_PER_SEC;
|
|
2665
|
+
uint64_t uptimeNanoRemainder = uptimeNano - (uptimeSeconds * NSEC_PER_SEC);
|
|
2666
|
+
|
|
2667
|
+
tp->tv_sec = uptimeSeconds;
|
|
2668
|
+
tp->tv_nsec = uptimeNanoRemainder;
|
|
2669
|
+
#endif
|
|
2401
2670
|
}
|
|
2402
2671
|
|
|
2403
2672
|
void usbi_get_real_time(struct timespec *tp) {
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
tp->
|
|
2411
|
-
|
|
2673
|
+
/* Check if the SDK is new enough to declare clock_gettime(), and the deployment target is at least 10.12. */
|
|
2674
|
+
#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
|
|
2675
|
+
clock_gettime(CLOCK_REALTIME, tp);
|
|
2676
|
+
#else
|
|
2677
|
+
struct timeval tv;
|
|
2678
|
+
gettimeofday(&tv, NULL);
|
|
2679
|
+
tp->tv_sec = tv.tv_sec;
|
|
2680
|
+
tp->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
|
|
2412
2681
|
#endif
|
|
2682
|
+
}
|
|
2413
2683
|
|
|
2414
|
-
#if
|
|
2684
|
+
#if MAX_INTERFACE_VERSION >= 550
|
|
2415
2685
|
static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints,
|
|
2416
2686
|
int num_endpoints) {
|
|
2417
2687
|
struct darwin_interface *cInterface;
|
|
@@ -2425,7 +2695,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
|
|
|
2425
2695
|
return rc;
|
|
2426
2696
|
}
|
|
2427
2697
|
|
|
2428
|
-
(*(cInterface
|
|
2698
|
+
(*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams);
|
|
2429
2699
|
if (num_streams > supportsStreams)
|
|
2430
2700
|
num_streams = supportsStreams;
|
|
2431
2701
|
}
|
|
@@ -2438,7 +2708,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
|
|
|
2438
2708
|
for (i = 0 ; i < num_endpoints ; ++i) {
|
|
2439
2709
|
(void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
|
|
2440
2710
|
|
|
2441
|
-
rc = (*(cInterface
|
|
2711
|
+
rc = (*IOINTERFACE_V(cInterface, 550))->CreateStreams (IOINTERFACE(cInterface), pipeRef, num_streams);
|
|
2442
2712
|
if (kIOReturnSuccess != rc)
|
|
2443
2713
|
return darwin_to_libusb(rc);
|
|
2444
2714
|
}
|
|
@@ -2457,11 +2727,11 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
|
|
|
2457
2727
|
if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface)))
|
|
2458
2728
|
return rc;
|
|
2459
2729
|
|
|
2460
|
-
(*(cInterface
|
|
2730
|
+
(*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams);
|
|
2461
2731
|
if (0 == supportsStreams)
|
|
2462
2732
|
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2463
2733
|
|
|
2464
|
-
rc = (*(cInterface
|
|
2734
|
+
rc = (*IOINTERFACE_V(cInterface, 550))->CreateStreams (IOINTERFACE(cInterface), pipeRef, 0);
|
|
2465
2735
|
if (kIOReturnSuccess != rc)
|
|
2466
2736
|
return darwin_to_libusb(rc);
|
|
2467
2737
|
}
|
|
@@ -2470,7 +2740,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
|
|
|
2470
2740
|
}
|
|
2471
2741
|
#endif
|
|
2472
2742
|
|
|
2473
|
-
#if
|
|
2743
|
+
#if MAX_INTERFACE_VERSION >= 700
|
|
2474
2744
|
|
|
2475
2745
|
/* macOS APIs for getting entitlement values */
|
|
2476
2746
|
|
|
@@ -2504,15 +2774,10 @@ static int darwin_reload_device (struct libusb_device_handle *dev_handle) {
|
|
|
2504
2774
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
2505
2775
|
enum libusb_error err;
|
|
2506
2776
|
|
|
2507
|
-
usbi_mutex_lock(&
|
|
2508
|
-
(*
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
err = LIBUSB_ERROR_NO_DEVICE;
|
|
2512
|
-
} else {
|
|
2513
|
-
err = LIBUSB_SUCCESS;
|
|
2514
|
-
}
|
|
2515
|
-
usbi_mutex_unlock(&darwin_cached_devices_lock);
|
|
2777
|
+
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
2778
|
+
(*dpriv->device)->Release(dpriv->device);
|
|
2779
|
+
err = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service, &dpriv->device);
|
|
2780
|
+
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
2516
2781
|
|
|
2517
2782
|
return err;
|
|
2518
2783
|
}
|
|
@@ -2526,8 +2791,7 @@ static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle,
|
|
|
2526
2791
|
enum libusb_error err;
|
|
2527
2792
|
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
2528
2793
|
|
|
2529
|
-
if (
|
|
2530
|
-
} else {
|
|
2794
|
+
if (get_interface_interface_version() < 700) {
|
|
2531
2795
|
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
2532
2796
|
}
|
|
2533
2797
|
|
|
@@ -2570,8 +2834,7 @@ static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle,
|
|
|
2570
2834
|
UNUSED(interface);
|
|
2571
2835
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
2572
2836
|
|
|
2573
|
-
if (
|
|
2574
|
-
} else {
|
|
2837
|
+
if (get_interface_interface_version() < 700) {
|
|
2575
2838
|
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
2576
2839
|
}
|
|
2577
2840
|
|
|
@@ -2638,14 +2901,14 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
2638
2901
|
.clear_halt = darwin_clear_halt,
|
|
2639
2902
|
.reset_device = darwin_reset_device,
|
|
2640
2903
|
|
|
2641
|
-
#if
|
|
2904
|
+
#if MAX_INTERFACE_VERSION >= 550
|
|
2642
2905
|
.alloc_streams = darwin_alloc_streams,
|
|
2643
2906
|
.free_streams = darwin_free_streams,
|
|
2644
2907
|
#endif
|
|
2645
2908
|
|
|
2646
2909
|
.kernel_driver_active = darwin_kernel_driver_active,
|
|
2647
2910
|
|
|
2648
|
-
#if
|
|
2911
|
+
#if MAX_INTERFACE_VERSION >= 700
|
|
2649
2912
|
.detach_kernel_driver = darwin_detach_kernel_driver,
|
|
2650
2913
|
.attach_kernel_driver = darwin_attach_kernel_driver,
|
|
2651
2914
|
.claim_interface = darwin_capture_claim_interface,
|