usb 2.16.0 → 2.18.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 -0
- package/README.md +14 -0
- package/binding.gyp +2 -9
- package/dist/usb/bindings.d.ts +27 -2
- package/dist/usb/bindings.js.map +1 -1
- package/dist/usb/endpoint.js +1 -1
- package/dist/usb/endpoint.js.map +1 -1
- package/dist/usb/index.d.ts +0 -29
- package/dist/usb/index.js +4 -18
- package/dist/usb/index.js.map +1 -1
- package/dist/webusb/index.d.ts +1 -1
- package/dist/webusb/index.js +1 -1
- package/dist/webusb/index.js.map +1 -1
- package/dist/webusb/webusb-device.d.ts +4 -4
- package/dist/webusb/webusb-device.js +5 -2
- package/dist/webusb/webusb-device.js.map +1 -1
- package/libusb/.clang-tidy +36 -0
- package/libusb/.private/ci-build.sh +5 -1
- package/libusb/AUTHORS +21 -0
- package/libusb/ChangeLog +29 -2
- package/libusb/KEYS +123 -0
- package/libusb/README +8 -9
- package/libusb/Xcode/common.xcconfig +20 -0
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +16 -12
- package/libusb/android/examples/unrooted_android.c +1 -0
- package/libusb/configure.ac +12 -2
- package/libusb/examples/dpfp.c +1 -1
- package/libusb/examples/ezusb.c +6 -1
- package/libusb/examples/fxload.c +7 -5
- package/libusb/examples/hotplugtest.c +19 -11
- package/libusb/examples/listdevs.c +41 -3
- package/libusb/examples/testlibusb.c +1 -0
- package/libusb/examples/xusb.c +142 -77
- package/libusb/libusb/Makefile.am +4 -0
- package/libusb/libusb/core.c +183 -24
- package/libusb/libusb/descriptor.c +404 -96
- package/libusb/libusb/hotplug.c +27 -8
- package/libusb/libusb/io.c +10 -5
- package/libusb/libusb/libusb-1.0.def +14 -0
- package/libusb/libusb/libusb.h +179 -19
- package/libusb/libusb/libusbi.h +101 -25
- package/libusb/libusb/os/darwin_usb.c +216 -90
- package/libusb/libusb/os/darwin_usb.h +10 -8
- package/libusb/libusb/os/emscripten_webusb.cpp +38 -12
- package/libusb/libusb/os/events_posix.c +4 -4
- package/libusb/libusb/os/haiku_usb_raw.cpp +4 -0
- package/libusb/libusb/os/linux_usbfs.c +92 -33
- package/libusb/libusb/os/linux_usbfs.h +13 -3
- package/libusb/libusb/os/netbsd_usb.c +6 -4
- package/libusb/libusb/os/openbsd_usb.c +4 -2
- package/libusb/libusb/os/sunos_usb.c +7 -5
- package/libusb/libusb/os/threads_posix.c +20 -19
- package/libusb/libusb/os/threads_posix.h +9 -3
- package/libusb/libusb/os/threads_windows.h +4 -3
- package/libusb/libusb/os/windows_common.c +86 -1
- package/libusb/libusb/os/windows_common.h +20 -1
- package/libusb/libusb/os/windows_hotplug.c +321 -0
- package/libusb/libusb/os/windows_hotplug.h +28 -0
- package/libusb/libusb/os/windows_usbdk.c +16 -8
- package/libusb/libusb/os/windows_winusb.c +788 -56
- package/libusb/libusb/os/windows_winusb.h +11 -6
- package/libusb/libusb/sync.c +8 -5
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/msvc/Base.props +1 -1
- package/libusb/msvc/Configuration.Base.props +2 -1
- package/libusb/msvc/Configuration.DynamicLibrary.props +12 -0
- package/libusb/msvc/ProjectConfigurations.Base.props +69 -16
- package/libusb/msvc/build_all.ps1 +2 -2
- package/libusb/msvc/config.h +4 -0
- package/libusb/msvc/getopt/bits/getopt_core.h +96 -0
- package/libusb/msvc/getopt/bits/getopt_ext.h +77 -0
- package/libusb/msvc/getopt/features.h +21 -0
- package/libusb/msvc/getopt/getopt.c +456 -705
- package/libusb/msvc/getopt/getopt.h +16 -158
- package/libusb/msvc/getopt/getopt1.c +40 -69
- package/libusb/msvc/getopt/getopt_int.h +118 -0
- package/libusb/msvc/getopt/gettext.h +7 -0
- package/libusb/msvc/getopt/unistd.h +5 -0
- package/libusb/msvc/getopt.vcxproj +11 -4
- package/libusb/msvc/libusb.sln +515 -268
- package/libusb/msvc/libusb_dll.vcxproj +2 -0
- package/libusb/msvc/libusb_static.vcxproj +2 -0
- package/libusb/msvc/xusb.vcxproj +1 -1
- package/libusb/tests/Makefile.am +10 -1
- package/libusb/tests/fuzz/corpus/bos/min.bos +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/min_valid_config.bin +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_a_endpoint_null.bin +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_b_iad_oob.bin +0 -0
- package/libusb/tests/fuzz/fuzz_bos_descriptor.c +49 -0
- package/libusb/tests/fuzz/fuzz_descriptor_parsers.c +83 -0
- package/libusb/tests/macos.c +2 -2
- package/libusb/tests/stress_mt.c +6 -3
- package/libusb/tests/webusb-test-shim/index.js +6 -5
- package/libusb.gypi +5 -0
- package/package.json +3 -3
- 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/{hotplug/libusb.cc → hotplug.cc} +2 -3
- package/src/{hotplug/hotplug.h → hotplug.h} +2 -6
- package/src/node_usb.cc +3 -3
- package/test/usb.coffee +4 -4
- package/test/webusb.coffee +22 -12
- package/src/hotplug/windows.cc +0 -168
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
/* Default timeout to 10s for reenumerate. This is needed because USBDeviceReEnumerate
|
|
42
42
|
* does not return error status on macOS. */
|
|
43
|
-
#define DARWIN_REENUMERATE_TIMEOUT_US (
|
|
43
|
+
#define DARWIN_REENUMERATE_TIMEOUT_US (10ULL * USEC_PER_SEC)
|
|
44
44
|
|
|
45
45
|
#include <AvailabilityMacros.h>
|
|
46
46
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
|
|
@@ -49,29 +49,29 @@
|
|
|
49
49
|
|
|
50
50
|
#include "darwin_usb.h"
|
|
51
51
|
|
|
52
|
-
static int init_count = 0;
|
|
53
|
-
|
|
54
52
|
/* Both kIOMasterPortDefault or kIOMainPortDefault are synonyms for 0. */
|
|
55
53
|
static const mach_port_t darwin_default_master_port = 0;
|
|
56
54
|
|
|
57
55
|
/* async event thread */
|
|
58
56
|
/* if both this mutex and darwin_cached_devices_mutex are to be acquired then
|
|
59
57
|
darwin_cached_devices_mutex must be acquired first. */
|
|
60
|
-
static
|
|
61
|
-
static
|
|
58
|
+
static usbi_mutex_static_t libusb_darwin_at_mutex = USBI_MUTEX_INITIALIZER;
|
|
59
|
+
static usbi_cond_t libusb_darwin_at_cond = USBI_COND_INITIALIZER;
|
|
62
60
|
|
|
63
61
|
#define LIBUSB_DARWIN_STARTUP_FAILURE ((CFRunLoopRef) -1)
|
|
64
62
|
|
|
65
63
|
static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
|
|
66
64
|
static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
|
|
67
65
|
|
|
68
|
-
static usbi_mutex_t darwin_cached_devices_mutex =
|
|
66
|
+
static usbi_mutex_t darwin_cached_devices_mutex = USBI_MUTEX_INITIALIZER;
|
|
69
67
|
static struct list_head darwin_cached_devices;
|
|
68
|
+
static int init_count;
|
|
69
|
+
|
|
70
70
|
static const char *darwin_device_class = "IOUSBDevice";
|
|
71
71
|
|
|
72
72
|
uint32_t libusb_testonly_fake_running_version __attribute__ ((visibility ("hidden")));
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
uint32_t libusb_testonly_using_running_interface_version __attribute__ ((visibility ("hidden")));
|
|
74
|
+
uint32_t libusb_testonly_using_running_device_version __attribute__ ((visibility ("hidden")));
|
|
75
75
|
bool libusb_testonly_clear_running_version_cache __attribute__ ((visibility ("hidden")));
|
|
76
76
|
|
|
77
77
|
#define DARWIN_CACHED_DEVICE(a) (((struct darwin_device_priv *)usbi_get_device_priv((a)))->dev)
|
|
@@ -173,7 +173,7 @@ static CFUUIDRef get_interface_interface_id(void) {
|
|
|
173
173
|
return get_interface_interface()->interface_id;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
static
|
|
176
|
+
static uint32_t get_interface_interface_version(void) {
|
|
177
177
|
return get_interface_interface()->version;
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -244,7 +244,7 @@ static CFUUIDRef get_device_interface_id(void) {
|
|
|
244
244
|
return get_device_interface()->interface_id;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
static
|
|
247
|
+
static uint32_t get_device_interface_version(void) {
|
|
248
248
|
return get_device_interface()->version;
|
|
249
249
|
}
|
|
250
250
|
|
|
@@ -252,7 +252,7 @@ struct darwin_pipe_properties {
|
|
|
252
252
|
uint8_t number;
|
|
253
253
|
uint8_t direction;
|
|
254
254
|
uint8_t transfer_type;
|
|
255
|
-
uint16_t max_packet_size;
|
|
255
|
+
uint16_t max_packet_size; // without multipliers, not "full"
|
|
256
256
|
uint8_t interval;
|
|
257
257
|
};
|
|
258
258
|
typedef struct darwin_pipe_properties darwin_pipe_properties_t;
|
|
@@ -262,8 +262,16 @@ static IOReturn darwin_get_pipe_properties(struct darwin_interface *cInterface,
|
|
|
262
262
|
|
|
263
263
|
#if (MAX_INTERFACE_VERSION >= 550)
|
|
264
264
|
if (get_interface_interface_version() >= 550) {
|
|
265
|
+
// GetPipePropertiesV3 returns a "cooked" wMaxPacketSize (premultiplied by burst and mul). This not what we want.
|
|
266
|
+
// We only call GetPipePropertiesV3 to fill the fields needed to call GetEndpointPropertiesV3.
|
|
265
267
|
IOUSBEndpointProperties pipe_properties = {.bVersion = kUSBEndpointPropertiesVersion3};
|
|
266
268
|
kresult = (*IOINTERFACE_V(cInterface, 550))->GetPipePropertiesV3 (IOINTERFACE(cInterface), pipe, &pipe_properties);
|
|
269
|
+
if (kIOReturnSuccess != kresult) {
|
|
270
|
+
return kresult;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// GetEndpointPropertiesV3 returns the wMaxPacketSize without burst and mul multipliers.
|
|
274
|
+
kresult = (*IOINTERFACE_V(cInterface, 550))->GetEndpointPropertiesV3 (IOINTERFACE(cInterface), &pipe_properties);
|
|
267
275
|
if (kIOReturnSuccess == kresult) {
|
|
268
276
|
out->number = pipe_properties.bEndpointNumber;
|
|
269
277
|
out->direction = pipe_properties.bDirection;
|
|
@@ -274,9 +282,26 @@ static IOReturn darwin_get_pipe_properties(struct darwin_interface *cInterface,
|
|
|
274
282
|
return kresult;
|
|
275
283
|
}
|
|
276
284
|
#endif
|
|
277
|
-
|
|
285
|
+
// GetPipeProperties returns a "cooked" version of max_packet_size which includes burst and mul. What we want is the
|
|
286
|
+
// original maxPacketSize so we can send zero-length packet when requested by users.
|
|
287
|
+
// We only call GetPipeProperties to retrieve the parameters needed to call GetEndpointProperties.
|
|
288
|
+
kresult = (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction,
|
|
278
289
|
&out->number, &out->transfer_type, &out->max_packet_size,
|
|
279
290
|
&out->interval);
|
|
291
|
+
if (kIOReturnSuccess != kresult) {
|
|
292
|
+
return kresult;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// To call GetEndpointProperties we also need altSetting
|
|
296
|
+
UInt8 altSetting;
|
|
297
|
+
kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting(IOINTERFACE(cInterface), &altSetting);
|
|
298
|
+
if (kIOReturnSuccess != kresult) {
|
|
299
|
+
return kresult;
|
|
300
|
+
}
|
|
301
|
+
// Retrieve "uncooked" version of maxPacketSize
|
|
302
|
+
return (*IOINTERFACE(cInterface))->GetEndpointProperties(IOINTERFACE(cInterface), altSetting, out->number,
|
|
303
|
+
out->direction, &out->transfer_type, &out->max_packet_size,
|
|
304
|
+
&out->interval);
|
|
280
305
|
}
|
|
281
306
|
|
|
282
307
|
#if defined(ENABLE_LOGGING)
|
|
@@ -370,11 +395,11 @@ uint32_t get_running_version(void) {
|
|
|
370
395
|
* it provides the exact macOS version instead of the approximate version (as below). */
|
|
371
396
|
ret = sysctlbyname("kern.osproductversion", os_version_string, &os_version_string_len, NULL, 0);
|
|
372
397
|
if (ret == 0) {
|
|
373
|
-
int major = 10, minor = 0, patch = 0;
|
|
374
|
-
ret = sscanf(os_version_string, "%
|
|
398
|
+
unsigned int major = 10, minor = 0, patch = 0;
|
|
399
|
+
ret = sscanf(os_version_string, "%u.%u.%u", &major, &minor, &patch);
|
|
375
400
|
if (ret < 2) {
|
|
376
401
|
usbi_err (NULL, "could not determine the running OS version, assuming 10.0, kern.osproductversion=%s", os_version_string);
|
|
377
|
-
return
|
|
402
|
+
return 10 * 10000;
|
|
378
403
|
}
|
|
379
404
|
return (major * 10000) + (minor * 100) + patch;
|
|
380
405
|
}
|
|
@@ -386,17 +411,17 @@ uint32_t get_running_version(void) {
|
|
|
386
411
|
ret = sysctlbyname("kern.osrelease", os_release_string, &os_release_string_len, NULL, 0);
|
|
387
412
|
if (ret != 0) {
|
|
388
413
|
usbi_err (NULL, "could not read kern.osrelease, errno=", errno);
|
|
389
|
-
return
|
|
414
|
+
return 10 * 10000;
|
|
390
415
|
}
|
|
391
416
|
|
|
392
|
-
int darwin_major = 1, darwin_minor = 0;
|
|
393
|
-
ret = sscanf(os_release_string, "%
|
|
417
|
+
unsigned int darwin_major = 1, darwin_minor = 0;
|
|
418
|
+
ret = sscanf(os_release_string, "%u.%u", &darwin_major, &darwin_minor);
|
|
394
419
|
if (ret < 1) {
|
|
395
420
|
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
|
|
421
|
+
return 10 * 10000;
|
|
397
422
|
}
|
|
398
423
|
|
|
399
|
-
int major = 10, minor = 0, patch = 0;
|
|
424
|
+
unsigned int major = 10, minor = 0, patch = 0;
|
|
400
425
|
|
|
401
426
|
if (1 == darwin_major && darwin_minor < 4) {
|
|
402
427
|
/* 10.0.x */
|
|
@@ -452,6 +477,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
452
477
|
|
|
453
478
|
usbi_dbg (ctx, "converting ep address 0x%02x to pipeRef and interface", ep);
|
|
454
479
|
|
|
480
|
+
usbi_mutex_lock(&dev_handle->lock);
|
|
455
481
|
for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) {
|
|
456
482
|
cInterface = &priv->interfaces[iface];
|
|
457
483
|
|
|
@@ -467,6 +493,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
467
493
|
*interface_out = cInterface;
|
|
468
494
|
|
|
469
495
|
usbi_dbg (ctx, "pipe %d on interface %d matches", *pipep, iface);
|
|
496
|
+
usbi_mutex_unlock(&dev_handle->lock);
|
|
470
497
|
return LIBUSB_SUCCESS;
|
|
471
498
|
}
|
|
472
499
|
}
|
|
@@ -476,6 +503,8 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
476
503
|
/* No pipe found with the correct endpoint address */
|
|
477
504
|
usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep);
|
|
478
505
|
|
|
506
|
+
usbi_mutex_unlock(&dev_handle->lock);
|
|
507
|
+
|
|
479
508
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
480
509
|
}
|
|
481
510
|
|
|
@@ -570,7 +599,8 @@ static int darwin_device_from_service (struct libusb_context *ctx, io_service_t
|
|
|
570
599
|
usbi_dbg (ctx, "set up plugin for service retry: %s", darwin_error_str (kresult));
|
|
571
600
|
|
|
572
601
|
/* sleep for a little while before trying again */
|
|
573
|
-
|
|
602
|
+
const struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
|
|
603
|
+
nanosleep(&delay, NULL);
|
|
574
604
|
}
|
|
575
605
|
|
|
576
606
|
if (kIOReturnSuccess != kresult) {
|
|
@@ -583,7 +613,7 @@ static int darwin_device_from_service (struct libusb_context *ctx, io_service_t
|
|
|
583
613
|
}
|
|
584
614
|
|
|
585
615
|
(void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(get_device_interface_id()),
|
|
586
|
-
(LPVOID)device);
|
|
616
|
+
(LPVOID *)device);
|
|
587
617
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
588
618
|
(*plugInInterface)->Release (plugInInterface);
|
|
589
619
|
|
|
@@ -611,9 +641,8 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
|
|
|
611
641
|
process_new_device (ctx, cached_device, old_session_id);
|
|
612
642
|
}
|
|
613
643
|
|
|
614
|
-
if (cached_device->in_reenumerate) {
|
|
644
|
+
if (atomic_exchange(&cached_device->in_reenumerate, false)) {
|
|
615
645
|
usbi_dbg (NULL, "cached device in reset state. reset complete...");
|
|
616
|
-
cached_device->in_reenumerate = false;
|
|
617
646
|
}
|
|
618
647
|
|
|
619
648
|
IOObjectRelease(service);
|
|
@@ -649,7 +678,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
649
678
|
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
650
679
|
list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
651
680
|
if (old_device->session == session) {
|
|
652
|
-
if (old_device->in_reenumerate) {
|
|
681
|
+
if (atomic_load(&old_device->in_reenumerate)) {
|
|
653
682
|
/* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
|
|
654
683
|
* will deref if needed. */
|
|
655
684
|
usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64
|
|
@@ -694,7 +723,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
694
723
|
static void darwin_hotplug_poll (void)
|
|
695
724
|
{
|
|
696
725
|
/* not sure if 1 ms will be too long/short but it should work ok */
|
|
697
|
-
mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec =
|
|
726
|
+
mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000UL};
|
|
698
727
|
|
|
699
728
|
/* since a kernel thread may notify the IOIterators used for
|
|
700
729
|
* hotplug notification we can't just clear the iterators.
|
|
@@ -710,10 +739,10 @@ static void darwin_clear_iterator (io_iterator_t iter) {
|
|
|
710
739
|
}
|
|
711
740
|
|
|
712
741
|
static void darwin_fail_startup(void) {
|
|
713
|
-
|
|
742
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
714
743
|
libusb_darwin_acfl = LIBUSB_DARWIN_STARTUP_FAILURE;
|
|
715
|
-
|
|
716
|
-
|
|
744
|
+
usbi_cond_signal (&libusb_darwin_at_cond);
|
|
745
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
717
746
|
pthread_exit (NULL);
|
|
718
747
|
}
|
|
719
748
|
|
|
@@ -797,11 +826,11 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
797
826
|
usbi_dbg (NULL, "darwin event thread ready to receive events");
|
|
798
827
|
|
|
799
828
|
/* signal the main thread that the hotplug runloop has been created. */
|
|
800
|
-
|
|
829
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
801
830
|
libusb_darwin_acfl = runloop;
|
|
802
831
|
libusb_darwin_acfls = libusb_shutdown_cfsource;
|
|
803
|
-
|
|
804
|
-
|
|
832
|
+
usbi_cond_signal (&libusb_darwin_at_cond);
|
|
833
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
805
834
|
|
|
806
835
|
/* run the runloop */
|
|
807
836
|
CFRunLoopRun();
|
|
@@ -809,11 +838,11 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
809
838
|
usbi_dbg (NULL, "darwin event thread exiting");
|
|
810
839
|
|
|
811
840
|
/* signal the main thread that the hotplug runloop has finished. */
|
|
812
|
-
|
|
841
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
813
842
|
libusb_darwin_acfls = NULL;
|
|
814
843
|
libusb_darwin_acfl = NULL;
|
|
815
|
-
|
|
816
|
-
|
|
844
|
+
usbi_cond_signal (&libusb_darwin_at_cond);
|
|
845
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
817
846
|
|
|
818
847
|
/* remove the notification cfsource */
|
|
819
848
|
CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
|
|
@@ -873,17 +902,17 @@ static int darwin_first_time_init(void) {
|
|
|
873
902
|
return LIBUSB_ERROR_OTHER;
|
|
874
903
|
}
|
|
875
904
|
|
|
876
|
-
|
|
905
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
877
906
|
libusb_darwin_at_started = true;
|
|
878
907
|
while (NULL == libusb_darwin_acfl) {
|
|
879
|
-
|
|
908
|
+
usbi_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
880
909
|
}
|
|
881
910
|
|
|
882
911
|
if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) {
|
|
883
912
|
libusb_darwin_acfl = NULL;
|
|
884
913
|
rc = LIBUSB_ERROR_OTHER;
|
|
885
914
|
}
|
|
886
|
-
|
|
915
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
887
916
|
|
|
888
917
|
return rc;
|
|
889
918
|
}
|
|
@@ -921,25 +950,78 @@ static void darwin_exit (struct libusb_context *ctx) {
|
|
|
921
950
|
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
922
951
|
if (0 == --init_count) {
|
|
923
952
|
/* stop the event runloop and wait for the thread to terminate. */
|
|
924
|
-
|
|
953
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
925
954
|
if (NULL != libusb_darwin_acfls) {
|
|
926
955
|
CFRunLoopSourceSignal (libusb_darwin_acfls);
|
|
927
956
|
CFRunLoopWakeUp (libusb_darwin_acfl);
|
|
928
957
|
while (libusb_darwin_acfl)
|
|
929
|
-
|
|
958
|
+
usbi_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
930
959
|
}
|
|
931
960
|
|
|
932
961
|
if (libusb_darwin_at_started) {
|
|
933
962
|
pthread_join (libusb_darwin_at, NULL);
|
|
934
963
|
libusb_darwin_at_started = false;
|
|
935
964
|
}
|
|
936
|
-
|
|
965
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
937
966
|
|
|
938
967
|
darwin_cleanup_devices ();
|
|
939
968
|
}
|
|
940
969
|
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
941
970
|
}
|
|
942
971
|
|
|
972
|
+
static int darwin_get_device_string(struct libusb_device *dev,
|
|
973
|
+
enum libusb_device_string_type string_type, char *buffer, int length) {
|
|
974
|
+
|
|
975
|
+
if (length <= 0)
|
|
976
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
977
|
+
|
|
978
|
+
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
|
979
|
+
io_iterator_t deviceIterator;
|
|
980
|
+
io_service_t service;
|
|
981
|
+
kern_return_t kresult;
|
|
982
|
+
CFStringRef cf;
|
|
983
|
+
|
|
984
|
+
kresult = usb_setup_device_iterator (&deviceIterator, priv->location);
|
|
985
|
+
if (kresult != kIOReturnSuccess)
|
|
986
|
+
return darwin_to_libusb (kresult);
|
|
987
|
+
|
|
988
|
+
service = IOIteratorNext (deviceIterator);
|
|
989
|
+
IOObjectRelease(deviceIterator);
|
|
990
|
+
if (service == IO_OBJECT_NULL)
|
|
991
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
992
|
+
|
|
993
|
+
switch (string_type) {
|
|
994
|
+
case LIBUSB_DEVICE_STRING_MANUFACTURER:
|
|
995
|
+
cf = IORegistryEntryCreateCFProperty(service, CFSTR(kUSBVendorString), kCFAllocatorDefault, 0);
|
|
996
|
+
break;
|
|
997
|
+
case LIBUSB_DEVICE_STRING_PRODUCT:
|
|
998
|
+
cf = IORegistryEntryCreateCFProperty(service, CFSTR(kUSBProductString), kCFAllocatorDefault, 0);
|
|
999
|
+
break;
|
|
1000
|
+
case LIBUSB_DEVICE_STRING_SERIAL_NUMBER:
|
|
1001
|
+
cf = IORegistryEntryCreateCFProperty(service, CFSTR(kUSBSerialNumberString), kCFAllocatorDefault, 0);
|
|
1002
|
+
break;
|
|
1003
|
+
case LIBUSB_DEVICE_STRING_COUNT: /* intentional fall-through, avoid -Wswitch-enum */
|
|
1004
|
+
default:
|
|
1005
|
+
IOObjectRelease(service);
|
|
1006
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
IOObjectRelease(service);
|
|
1010
|
+
if (cf == NULL)
|
|
1011
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1012
|
+
|
|
1013
|
+
long cfUsedIndex = 0;
|
|
1014
|
+
CFStringGetBytes(cf, CFRangeMake(0, CFStringGetLength(cf)), kCFStringEncodingUTF8, '?', false,
|
|
1015
|
+
(uint8_t *) buffer, length - 1, &cfUsedIndex);
|
|
1016
|
+
CFRelease(cf);
|
|
1017
|
+
|
|
1018
|
+
if (cfUsedIndex <= 0)
|
|
1019
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
1020
|
+
|
|
1021
|
+
buffer[cfUsedIndex] = '\0';
|
|
1022
|
+
return (int) cfUsedIndex + 1;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
943
1025
|
static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
|
|
944
1026
|
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
|
945
1027
|
UInt8 i, numConfig;
|
|
@@ -952,9 +1034,9 @@ static int get_configuration_index (struct libusb_device *dev, UInt8 config_valu
|
|
|
952
1034
|
return darwin_to_libusb (kresult);
|
|
953
1035
|
|
|
954
1036
|
for (i = 0 ; i < numConfig ; i++) {
|
|
955
|
-
(*priv->device)->GetConfigurationDescriptorPtr (priv->device, i, &desc);
|
|
1037
|
+
kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, i, &desc);
|
|
956
1038
|
|
|
957
|
-
if (desc->bConfigurationValue == config_value)
|
|
1039
|
+
if (kresult == kIOReturnSuccess && desc->bConfigurationValue == config_value)
|
|
958
1040
|
return i;
|
|
959
1041
|
}
|
|
960
1042
|
|
|
@@ -1092,7 +1174,7 @@ static IOReturn darwin_request_descriptor (usb_device_t device, UInt8 desc, UInt
|
|
|
1092
1174
|
static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
|
|
1093
1175
|
usb_device_t device = dev->device;
|
|
1094
1176
|
int retries = 1;
|
|
1095
|
-
long delay = 30000;
|
|
1177
|
+
long delay = 30000; /* microseconds */
|
|
1096
1178
|
int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
|
|
1097
1179
|
int is_open = 0;
|
|
1098
1180
|
IOReturn ret = 0, ret2;
|
|
@@ -1171,7 +1253,8 @@ static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *
|
|
|
1171
1253
|
if (kIOReturnSuccess != ret) {
|
|
1172
1254
|
usbi_dbg(ctx, "kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
|
|
1173
1255
|
/* sleep for a little while before trying again */
|
|
1174
|
-
|
|
1256
|
+
struct timespec full_delay = {delay / 1000000, (delay * 1000) % 1000000000};
|
|
1257
|
+
nanosleep(&full_delay, NULL);
|
|
1175
1258
|
}
|
|
1176
1259
|
} while (kIOReturnSuccess != ret && retries--);
|
|
1177
1260
|
|
|
@@ -1233,7 +1316,15 @@ static bool get_device_port (io_service_t service, UInt8 *port) {
|
|
|
1233
1316
|
|
|
1234
1317
|
kresult = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
|
|
1235
1318
|
if (kIOReturnSuccess == kresult) {
|
|
1236
|
-
|
|
1319
|
+
/*
|
|
1320
|
+
macOS 10 to 15 always had port number property as "port".
|
|
1321
|
+
macOS 26 has changed it to "usb-port-number".
|
|
1322
|
+
For the same binaries to run correctly on both macOS 15 and macOS 26+,
|
|
1323
|
+
we have to detect os version at runtime and use correct port name property.
|
|
1324
|
+
*/
|
|
1325
|
+
uint32_t os_version = get_running_version();
|
|
1326
|
+
CFStringRef cfstrPort = os_version < 260000 ? CFSTR("port") : CFSTR("usb-port-number");
|
|
1327
|
+
ret = get_ioregistry_value_data (parent, cfstrPort, 1, port);
|
|
1237
1328
|
IOObjectRelease (parent);
|
|
1238
1329
|
}
|
|
1239
1330
|
|
|
@@ -1242,17 +1333,18 @@ static bool get_device_port (io_service_t service, UInt8 *port) {
|
|
|
1242
1333
|
|
|
1243
1334
|
/* Returns 1 on success, 0 on failure. */
|
|
1244
1335
|
static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) {
|
|
1245
|
-
IOReturn kresult;
|
|
1246
|
-
io_service_t parent;
|
|
1247
|
-
|
|
1248
1336
|
/* Walk up the tree in the IOService plane until we find a parent that has a sessionID */
|
|
1249
|
-
parent = service;
|
|
1250
|
-
|
|
1337
|
+
io_service_t parent = service;
|
|
1338
|
+
do {
|
|
1339
|
+
IOReturn kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent);
|
|
1340
|
+
if (kresult != kIOReturnSuccess) {
|
|
1341
|
+
break;
|
|
1342
|
+
}
|
|
1251
1343
|
if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) {
|
|
1252
1344
|
/* Success */
|
|
1253
1345
|
return true;
|
|
1254
1346
|
}
|
|
1255
|
-
}
|
|
1347
|
+
} while (true);
|
|
1256
1348
|
|
|
1257
1349
|
/* We ran out of parents */
|
|
1258
1350
|
return false;
|
|
@@ -1289,7 +1381,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
|
|
|
1289
1381
|
list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
1290
1382
|
usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32 " against cached device with sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32,
|
|
1291
1383
|
sessionID, locationID, new_device->session, new_device->location);
|
|
1292
|
-
if (new_device->location == locationID && new_device->in_reenumerate) {
|
|
1384
|
+
if (new_device->location == locationID && atomic_load(&new_device->in_reenumerate)) {
|
|
1293
1385
|
usbi_dbg (ctx, "found cached device with matching location that is being re-enumerated");
|
|
1294
1386
|
*old_session_id = new_device->session;
|
|
1295
1387
|
break;
|
|
@@ -1361,6 +1453,8 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
|
|
|
1361
1453
|
|
|
1362
1454
|
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
1363
1455
|
|
|
1456
|
+
assert((ret == LIBUSB_SUCCESS) ? (*cached_out != NULL) : true);
|
|
1457
|
+
|
|
1364
1458
|
return ret;
|
|
1365
1459
|
}
|
|
1366
1460
|
|
|
@@ -1434,6 +1528,9 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1434
1528
|
#endif
|
|
1435
1529
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
|
1436
1530
|
case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
|
|
1531
|
+
#endif
|
|
1532
|
+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
|
|
1533
|
+
case kUSBDeviceSpeedSuperPlusBy2: dev->speed = LIBUSB_SPEED_SUPER_PLUS_X2; break;
|
|
1437
1534
|
#endif
|
|
1438
1535
|
default:
|
|
1439
1536
|
usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
|
|
@@ -1448,7 +1545,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1448
1545
|
|
|
1449
1546
|
} while (0);
|
|
1450
1547
|
|
|
1451
|
-
if (!cached_device->in_reenumerate && 0 == ret) {
|
|
1548
|
+
if (!atomic_load(&cached_device->in_reenumerate) && 0 == ret) {
|
|
1452
1549
|
usbi_connect_device (dev);
|
|
1453
1550
|
} else {
|
|
1454
1551
|
libusb_unref_device (dev);
|
|
@@ -1471,6 +1568,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
|
|
|
1471
1568
|
|
|
1472
1569
|
while ((service = IOIteratorNext (deviceIterator))) {
|
|
1473
1570
|
ret = darwin_get_cached_device (ctx, service, &cached_device, &old_session_id);
|
|
1571
|
+
assert((ret >= 0) ? (cached_device != NULL) : true);
|
|
1474
1572
|
if (ret < 0 || !cached_device->can_enumerate) {
|
|
1475
1573
|
continue;
|
|
1476
1574
|
}
|
|
@@ -1491,6 +1589,10 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
1491
1589
|
IOReturn kresult;
|
|
1492
1590
|
|
|
1493
1591
|
if (0 == dpriv->open_count) {
|
|
1592
|
+
if (!dpriv->device) {
|
|
1593
|
+
usbi_err(HANDLE_CTX(dev_handle), "device interface is NULL, cannot open");
|
|
1594
|
+
return LIBUSB_ERROR_NO_DEVICE;
|
|
1595
|
+
}
|
|
1494
1596
|
/* try to open the device */
|
|
1495
1597
|
kresult = (*dpriv->device)->USBDeviceOpenSeize (dpriv->device);
|
|
1496
1598
|
if (kresult != kIOReturnSuccess) {
|
|
@@ -1792,7 +1894,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8
|
|
|
1792
1894
|
/* Do the actual claim */
|
|
1793
1895
|
kresult = (*plugInInterface)->QueryInterface(plugInInterface,
|
|
1794
1896
|
CFUUIDGetUUIDBytes(get_interface_interface_id()),
|
|
1795
|
-
(LPVOID)&IOINTERFACE(cInterface));
|
|
1897
|
+
(LPVOID *)&IOINTERFACE(cInterface));
|
|
1796
1898
|
/* We no longer need the intermediate plug-in */
|
|
1797
1899
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
1798
1900
|
(*plugInInterface)->Release (plugInInterface);
|
|
@@ -1868,9 +1970,10 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin
|
|
|
1868
1970
|
if (kresult != kIOReturnSuccess)
|
|
1869
1971
|
usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
|
|
1870
1972
|
|
|
1871
|
-
|
|
1872
|
-
if (
|
|
1873
|
-
usbi_warn (HANDLE_CTX (dev_handle), "Release: %
|
|
1973
|
+
ULONG refCount = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
|
|
1974
|
+
if (refCount != 0) {
|
|
1975
|
+
usbi_warn (HANDLE_CTX (dev_handle), "Release final refCount: %u", refCount);
|
|
1976
|
+
}
|
|
1874
1977
|
|
|
1875
1978
|
IOINTERFACE(cInterface) = NULL;
|
|
1876
1979
|
|
|
@@ -1972,7 +2075,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
|
|
|
1972
2075
|
return darwin_to_libusb (kresult);
|
|
1973
2076
|
}
|
|
1974
2077
|
|
|
1975
|
-
static int darwin_restore_state (struct libusb_device_handle *dev_handle,
|
|
2078
|
+
static int darwin_restore_state (struct libusb_device_handle *dev_handle, uint8_t active_config,
|
|
1976
2079
|
unsigned long claimed_interfaces) {
|
|
1977
2080
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
1978
2081
|
struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
|
|
@@ -1989,7 +2092,7 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
|
|
|
1989
2092
|
dpriv->open_count = 1;
|
|
1990
2093
|
|
|
1991
2094
|
/* clean up open interfaces */
|
|
1992
|
-
|
|
2095
|
+
darwin_close (dev_handle);
|
|
1993
2096
|
|
|
1994
2097
|
/* re-open the device */
|
|
1995
2098
|
ret = darwin_open (dev_handle);
|
|
@@ -2037,7 +2140,7 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
|
|
|
2037
2140
|
static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, bool capture) {
|
|
2038
2141
|
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
|
|
2039
2142
|
unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
|
|
2040
|
-
|
|
2143
|
+
uint8_t active_config = dpriv->active_config;
|
|
2041
2144
|
UInt32 options = 0;
|
|
2042
2145
|
IOUSBDeviceDescriptor descriptor;
|
|
2043
2146
|
IOUSBConfigurationDescriptorPtr cached_configuration;
|
|
@@ -2047,19 +2150,26 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2047
2150
|
|
|
2048
2151
|
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
2049
2152
|
|
|
2050
|
-
if (dpriv->
|
|
2153
|
+
if (!dpriv->device) {
|
|
2154
|
+
usbi_warn(ctx, "darwin_reenumerate_device: device interface is NULL");
|
|
2155
|
+
return LIBUSB_ERROR_NO_DEVICE;
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
if (atomic_exchange(&dpriv->in_reenumerate, true)) {
|
|
2051
2159
|
/* ack, two (or more) threads are trying to reset the device! abort! */
|
|
2052
2160
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2053
2161
|
}
|
|
2054
2162
|
|
|
2055
|
-
dpriv->in_reenumerate = true;
|
|
2056
|
-
|
|
2057
2163
|
/* store copies of descriptors so they can be compared after the reset */
|
|
2058
2164
|
memcpy (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor));
|
|
2059
2165
|
cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
|
|
2060
2166
|
|
|
2061
2167
|
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
2062
|
-
(*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
2168
|
+
kresult = (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
2169
|
+
if (kresult != kIOReturnSuccess) {
|
|
2170
|
+
atomic_store(&dpriv->in_reenumerate, false);
|
|
2171
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
|
2172
|
+
}
|
|
2063
2173
|
memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
|
|
2064
2174
|
}
|
|
2065
2175
|
|
|
@@ -2078,14 +2188,14 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2078
2188
|
kresult = (*dpriv->device)->USBDeviceReEnumerate (dpriv->device, options);
|
|
2079
2189
|
if (kresult != kIOReturnSuccess) {
|
|
2080
2190
|
usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
|
|
2081
|
-
dpriv->in_reenumerate
|
|
2191
|
+
atomic_store(&dpriv->in_reenumerate, false);
|
|
2082
2192
|
return darwin_to_libusb (kresult);
|
|
2083
2193
|
}
|
|
2084
2194
|
|
|
2085
2195
|
/* capture mode does not re-enumerate but it does require re-open */
|
|
2086
2196
|
if (capture) {
|
|
2087
2197
|
usbi_dbg (ctx, "darwin/reenumerate_device: restoring state...");
|
|
2088
|
-
dpriv->in_reenumerate
|
|
2198
|
+
atomic_store(&dpriv->in_reenumerate, false);
|
|
2089
2199
|
return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
|
|
2090
2200
|
}
|
|
2091
2201
|
|
|
@@ -2094,18 +2204,19 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2094
2204
|
struct timespec start;
|
|
2095
2205
|
usbi_get_monotonic_time(&start);
|
|
2096
2206
|
|
|
2097
|
-
while (dpriv->in_reenumerate) {
|
|
2098
|
-
struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
|
|
2207
|
+
while (atomic_load(&dpriv->in_reenumerate)) {
|
|
2208
|
+
const struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
|
|
2099
2209
|
nanosleep (&delay, NULL);
|
|
2100
2210
|
|
|
2101
|
-
struct timespec now;
|
|
2211
|
+
struct timespec now, delta;
|
|
2102
2212
|
usbi_get_monotonic_time(&now);
|
|
2103
|
-
|
|
2104
|
-
|
|
2213
|
+
TIMESPEC_SUB(&now, &start, &delta);
|
|
2214
|
+
unsigned long long elapsed_us = ((unsigned long long)delta.tv_sec * USEC_PER_SEC) +
|
|
2215
|
+
((unsigned long long)delta.tv_nsec / 1000ULL);
|
|
2105
2216
|
|
|
2106
2217
|
if (elapsed_us >= DARWIN_REENUMERATE_TIMEOUT_US) {
|
|
2107
2218
|
usbi_err (ctx, "darwin/reenumerate_device: timeout waiting for reenumerate");
|
|
2108
|
-
dpriv->in_reenumerate
|
|
2219
|
+
atomic_store(&dpriv->in_reenumerate, false);
|
|
2109
2220
|
return LIBUSB_ERROR_TIMEOUT;
|
|
2110
2221
|
}
|
|
2111
2222
|
}
|
|
@@ -2113,15 +2224,15 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2113
2224
|
/* compare descriptors */
|
|
2114
2225
|
usbi_dbg (ctx, "darwin/reenumerate_device: checking whether descriptors changed");
|
|
2115
2226
|
|
|
2116
|
-
if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
|
|
2227
|
+
if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor)) != 0) {
|
|
2117
2228
|
/* device descriptor changed. need to return not found. */
|
|
2118
2229
|
usbi_dbg (ctx, "darwin/reenumerate_device: device descriptor changed");
|
|
2119
2230
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2120
2231
|
}
|
|
2121
2232
|
|
|
2122
2233
|
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
2123
|
-
|
|
2124
|
-
if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
|
|
2234
|
+
kresult = (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
|
|
2235
|
+
if (kresult != kIOReturnSuccess || memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i])) != 0) {
|
|
2125
2236
|
usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
|
|
2126
2237
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2127
2238
|
}
|
|
@@ -2150,7 +2261,7 @@ static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
|
|
|
2150
2261
|
ret = darwin_reenumerate_device (dev_handle, false);
|
|
2151
2262
|
if ((ret == LIBUSB_SUCCESS || ret == LIBUSB_ERROR_NOT_FOUND) && dpriv->capture_count > 0) {
|
|
2152
2263
|
int capture_count;
|
|
2153
|
-
|
|
2264
|
+
uint8_t active_config = dpriv->active_config;
|
|
2154
2265
|
unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
|
|
2155
2266
|
|
|
2156
2267
|
/* save old capture_count */
|
|
@@ -2399,10 +2510,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
|
|
|
2399
2510
|
|
|
2400
2511
|
if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
|
|
2401
2512
|
/* Full speed */
|
|
2402
|
-
cInterface->frames[transfer->endpoint] = frame + (
|
|
2513
|
+
cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1));
|
|
2403
2514
|
else
|
|
2404
2515
|
/* High/super speed */
|
|
2405
|
-
cInterface->frames[transfer->endpoint] = frame + (
|
|
2516
|
+
cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1)) / 8;
|
|
2406
2517
|
|
|
2407
2518
|
if (kresult != kIOReturnSuccess) {
|
|
2408
2519
|
usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
|
|
@@ -2616,7 +2727,9 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
|
|
|
2616
2727
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
2617
2728
|
struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
|
|
2618
2729
|
const unsigned char max_transfer_type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
|
|
2730
|
+
#ifdef ENABLE_LOGGING
|
|
2619
2731
|
const char *transfer_types[] = {"control", "isoc", "bulk", "interrupt", "bulk-stream", NULL};
|
|
2732
|
+
#endif
|
|
2620
2733
|
bool is_isoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
|
|
2621
2734
|
struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
|
|
2622
2735
|
|
|
@@ -2691,7 +2804,8 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
|
|
|
2691
2804
|
|
|
2692
2805
|
/* find the minimum number of supported streams on the endpoint list */
|
|
2693
2806
|
for (i = 0 ; i < num_endpoints ; ++i) {
|
|
2694
|
-
|
|
2807
|
+
rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
|
|
2808
|
+
if (0 != rc) {
|
|
2695
2809
|
return rc;
|
|
2696
2810
|
}
|
|
2697
2811
|
|
|
@@ -2724,7 +2838,8 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
|
|
|
2724
2838
|
int rc;
|
|
2725
2839
|
|
|
2726
2840
|
for (int i = 0 ; i < num_endpoints ; ++i) {
|
|
2727
|
-
|
|
2841
|
+
rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
|
|
2842
|
+
if (0 != rc)
|
|
2728
2843
|
return rc;
|
|
2729
2844
|
|
|
2730
2845
|
(*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams);
|
|
@@ -2888,15 +3003,27 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
2888
3003
|
.caps = USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
|
|
2889
3004
|
.init = darwin_init,
|
|
2890
3005
|
.exit = darwin_exit,
|
|
2891
|
-
.
|
|
2892
|
-
.
|
|
3006
|
+
.set_option = NULL,
|
|
3007
|
+
.get_device_list = NULL,
|
|
3008
|
+
.get_device_string = darwin_get_device_string,
|
|
2893
3009
|
.hotplug_poll = darwin_hotplug_poll,
|
|
2894
|
-
|
|
3010
|
+
.wrap_sys_device = NULL,
|
|
2895
3011
|
.open = darwin_open,
|
|
2896
3012
|
.close = darwin_close,
|
|
3013
|
+
.get_active_config_descriptor = darwin_get_active_config_descriptor,
|
|
3014
|
+
.get_config_descriptor = darwin_get_config_descriptor,
|
|
3015
|
+
.get_config_descriptor_by_value = NULL,
|
|
2897
3016
|
.get_configuration = darwin_get_configuration,
|
|
2898
3017
|
.set_configuration = darwin_set_configuration,
|
|
2899
3018
|
|
|
3019
|
+
#if MAX_INTERFACE_VERSION >= 700
|
|
3020
|
+
.claim_interface = darwin_capture_claim_interface,
|
|
3021
|
+
.release_interface = darwin_capture_release_interface,
|
|
3022
|
+
#else
|
|
3023
|
+
.claim_interface = darwin_claim_interface,
|
|
3024
|
+
.release_interface = darwin_release_interface,
|
|
3025
|
+
#endif
|
|
3026
|
+
|
|
2900
3027
|
.set_interface_altsetting = darwin_set_interface_altsetting,
|
|
2901
3028
|
.clear_halt = darwin_clear_halt,
|
|
2902
3029
|
.reset_device = darwin_reset_device,
|
|
@@ -2906,25 +3033,24 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
2906
3033
|
.free_streams = darwin_free_streams,
|
|
2907
3034
|
#endif
|
|
2908
3035
|
|
|
3036
|
+
.dev_mem_alloc = NULL,
|
|
3037
|
+
.dev_mem_free = NULL,
|
|
2909
3038
|
.kernel_driver_active = darwin_kernel_driver_active,
|
|
2910
3039
|
|
|
2911
3040
|
#if MAX_INTERFACE_VERSION >= 700
|
|
2912
3041
|
.detach_kernel_driver = darwin_detach_kernel_driver,
|
|
2913
3042
|
.attach_kernel_driver = darwin_attach_kernel_driver,
|
|
2914
|
-
.claim_interface = darwin_capture_claim_interface,
|
|
2915
|
-
.release_interface = darwin_capture_release_interface,
|
|
2916
|
-
#else
|
|
2917
|
-
.claim_interface = darwin_claim_interface,
|
|
2918
|
-
.release_interface = darwin_release_interface,
|
|
2919
3043
|
#endif
|
|
2920
3044
|
|
|
2921
3045
|
.destroy_device = darwin_destroy_device,
|
|
2922
3046
|
|
|
2923
3047
|
.submit_transfer = darwin_submit_transfer,
|
|
2924
3048
|
.cancel_transfer = darwin_cancel_transfer,
|
|
2925
|
-
|
|
3049
|
+
.clear_transfer_priv = NULL,
|
|
3050
|
+
.handle_events = NULL,
|
|
2926
3051
|
.handle_transfer_completion = darwin_handle_transfer_completion,
|
|
2927
3052
|
|
|
3053
|
+
.context_priv_size = 0,
|
|
2928
3054
|
.device_priv_size = sizeof(struct darwin_device_priv),
|
|
2929
3055
|
.device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
|
|
2930
3056
|
.transfer_priv_size = sizeof(struct darwin_transfer_priv),
|