usb 2.17.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 +6 -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/index.d.ts +0 -29
- package/dist/usb/index.js +4 -18
- package/dist/usb/index.js.map +1 -1
- package/libusb/.clang-tidy +5 -3
- package/libusb/.private/ci-build.sh +5 -1
- package/libusb/AUTHORS +14 -0
- package/libusb/ChangeLog +15 -2
- package/libusb/README +8 -5
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +4 -0
- package/libusb/configure.ac +12 -2
- package/libusb/examples/hotplugtest.c +19 -11
- package/libusb/examples/listdevs.c +41 -3
- package/libusb/examples/xusb.c +6 -1
- package/libusb/libusb/Makefile.am +4 -0
- package/libusb/libusb/core.c +175 -14
- package/libusb/libusb/descriptor.c +163 -14
- package/libusb/libusb/io.c +7 -3
- package/libusb/libusb/libusb-1.0.def +10 -0
- package/libusb/libusb/libusb.h +59 -9
- package/libusb/libusb/libusbi.h +89 -25
- package/libusb/libusb/os/darwin_usb.c +126 -46
- package/libusb/libusb/os/darwin_usb.h +10 -8
- package/libusb/libusb/os/emscripten_webusb.cpp +31 -10
- package/libusb/libusb/os/haiku_usb_raw.cpp +4 -0
- package/libusb/libusb/os/linux_usbfs.c +73 -25
- package/libusb/libusb/os/netbsd_usb.c +2 -0
- package/libusb/libusb/os/openbsd_usb.c +2 -0
- package/libusb/libusb/os/sunos_usb.c +2 -0
- package/libusb/libusb/os/threads_posix.c +3 -3
- package/libusb/libusb/os/threads_posix.h +8 -2
- package/libusb/libusb/os/threads_windows.h +2 -1
- 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 +753 -41
- package/libusb/libusb/os/windows_winusb.h +11 -6
- 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/stress_mt.c +2 -1
- package/libusb/tests/webusb-test-shim/index.js +6 -5
- package/libusb.gypi +5 -0
- package/package.json +1 -1
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-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
|
@@ -49,24 +49,24 @@
|
|
|
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")));
|
|
@@ -477,6 +477,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
477
477
|
|
|
478
478
|
usbi_dbg (ctx, "converting ep address 0x%02x to pipeRef and interface", ep);
|
|
479
479
|
|
|
480
|
+
usbi_mutex_lock(&dev_handle->lock);
|
|
480
481
|
for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) {
|
|
481
482
|
cInterface = &priv->interfaces[iface];
|
|
482
483
|
|
|
@@ -492,6 +493,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
492
493
|
*interface_out = cInterface;
|
|
493
494
|
|
|
494
495
|
usbi_dbg (ctx, "pipe %d on interface %d matches", *pipep, iface);
|
|
496
|
+
usbi_mutex_unlock(&dev_handle->lock);
|
|
495
497
|
return LIBUSB_SUCCESS;
|
|
496
498
|
}
|
|
497
499
|
}
|
|
@@ -501,6 +503,8 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
|
|
|
501
503
|
/* No pipe found with the correct endpoint address */
|
|
502
504
|
usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep);
|
|
503
505
|
|
|
506
|
+
usbi_mutex_unlock(&dev_handle->lock);
|
|
507
|
+
|
|
504
508
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
505
509
|
}
|
|
506
510
|
|
|
@@ -595,7 +599,8 @@ static int darwin_device_from_service (struct libusb_context *ctx, io_service_t
|
|
|
595
599
|
usbi_dbg (ctx, "set up plugin for service retry: %s", darwin_error_str (kresult));
|
|
596
600
|
|
|
597
601
|
/* sleep for a little while before trying again */
|
|
598
|
-
|
|
602
|
+
const struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
|
|
603
|
+
nanosleep(&delay, NULL);
|
|
599
604
|
}
|
|
600
605
|
|
|
601
606
|
if (kIOReturnSuccess != kresult) {
|
|
@@ -608,7 +613,7 @@ static int darwin_device_from_service (struct libusb_context *ctx, io_service_t
|
|
|
608
613
|
}
|
|
609
614
|
|
|
610
615
|
(void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(get_device_interface_id()),
|
|
611
|
-
(LPVOID)device);
|
|
616
|
+
(LPVOID *)device);
|
|
612
617
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
613
618
|
(*plugInInterface)->Release (plugInInterface);
|
|
614
619
|
|
|
@@ -636,9 +641,8 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
|
|
|
636
641
|
process_new_device (ctx, cached_device, old_session_id);
|
|
637
642
|
}
|
|
638
643
|
|
|
639
|
-
if (cached_device->in_reenumerate) {
|
|
644
|
+
if (atomic_exchange(&cached_device->in_reenumerate, false)) {
|
|
640
645
|
usbi_dbg (NULL, "cached device in reset state. reset complete...");
|
|
641
|
-
cached_device->in_reenumerate = false;
|
|
642
646
|
}
|
|
643
647
|
|
|
644
648
|
IOObjectRelease(service);
|
|
@@ -674,7 +678,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
|
|
|
674
678
|
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
675
679
|
list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
676
680
|
if (old_device->session == session) {
|
|
677
|
-
if (old_device->in_reenumerate) {
|
|
681
|
+
if (atomic_load(&old_device->in_reenumerate)) {
|
|
678
682
|
/* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
|
|
679
683
|
* will deref if needed. */
|
|
680
684
|
usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64
|
|
@@ -735,10 +739,10 @@ static void darwin_clear_iterator (io_iterator_t iter) {
|
|
|
735
739
|
}
|
|
736
740
|
|
|
737
741
|
static void darwin_fail_startup(void) {
|
|
738
|
-
|
|
742
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
739
743
|
libusb_darwin_acfl = LIBUSB_DARWIN_STARTUP_FAILURE;
|
|
740
|
-
|
|
741
|
-
|
|
744
|
+
usbi_cond_signal (&libusb_darwin_at_cond);
|
|
745
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
742
746
|
pthread_exit (NULL);
|
|
743
747
|
}
|
|
744
748
|
|
|
@@ -822,11 +826,11 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
822
826
|
usbi_dbg (NULL, "darwin event thread ready to receive events");
|
|
823
827
|
|
|
824
828
|
/* signal the main thread that the hotplug runloop has been created. */
|
|
825
|
-
|
|
829
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
826
830
|
libusb_darwin_acfl = runloop;
|
|
827
831
|
libusb_darwin_acfls = libusb_shutdown_cfsource;
|
|
828
|
-
|
|
829
|
-
|
|
832
|
+
usbi_cond_signal (&libusb_darwin_at_cond);
|
|
833
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
830
834
|
|
|
831
835
|
/* run the runloop */
|
|
832
836
|
CFRunLoopRun();
|
|
@@ -834,11 +838,11 @@ static void *darwin_event_thread_main (void *arg0) {
|
|
|
834
838
|
usbi_dbg (NULL, "darwin event thread exiting");
|
|
835
839
|
|
|
836
840
|
/* signal the main thread that the hotplug runloop has finished. */
|
|
837
|
-
|
|
841
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
838
842
|
libusb_darwin_acfls = NULL;
|
|
839
843
|
libusb_darwin_acfl = NULL;
|
|
840
|
-
|
|
841
|
-
|
|
844
|
+
usbi_cond_signal (&libusb_darwin_at_cond);
|
|
845
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
842
846
|
|
|
843
847
|
/* remove the notification cfsource */
|
|
844
848
|
CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
|
|
@@ -898,17 +902,17 @@ static int darwin_first_time_init(void) {
|
|
|
898
902
|
return LIBUSB_ERROR_OTHER;
|
|
899
903
|
}
|
|
900
904
|
|
|
901
|
-
|
|
905
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
902
906
|
libusb_darwin_at_started = true;
|
|
903
907
|
while (NULL == libusb_darwin_acfl) {
|
|
904
|
-
|
|
908
|
+
usbi_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
905
909
|
}
|
|
906
910
|
|
|
907
911
|
if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) {
|
|
908
912
|
libusb_darwin_acfl = NULL;
|
|
909
913
|
rc = LIBUSB_ERROR_OTHER;
|
|
910
914
|
}
|
|
911
|
-
|
|
915
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
912
916
|
|
|
913
917
|
return rc;
|
|
914
918
|
}
|
|
@@ -946,25 +950,78 @@ static void darwin_exit (struct libusb_context *ctx) {
|
|
|
946
950
|
usbi_mutex_lock(&darwin_cached_devices_mutex);
|
|
947
951
|
if (0 == --init_count) {
|
|
948
952
|
/* stop the event runloop and wait for the thread to terminate. */
|
|
949
|
-
|
|
953
|
+
usbi_mutex_lock (&libusb_darwin_at_mutex);
|
|
950
954
|
if (NULL != libusb_darwin_acfls) {
|
|
951
955
|
CFRunLoopSourceSignal (libusb_darwin_acfls);
|
|
952
956
|
CFRunLoopWakeUp (libusb_darwin_acfl);
|
|
953
957
|
while (libusb_darwin_acfl)
|
|
954
|
-
|
|
958
|
+
usbi_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
|
|
955
959
|
}
|
|
956
960
|
|
|
957
961
|
if (libusb_darwin_at_started) {
|
|
958
962
|
pthread_join (libusb_darwin_at, NULL);
|
|
959
963
|
libusb_darwin_at_started = false;
|
|
960
964
|
}
|
|
961
|
-
|
|
965
|
+
usbi_mutex_unlock (&libusb_darwin_at_mutex);
|
|
962
966
|
|
|
963
967
|
darwin_cleanup_devices ();
|
|
964
968
|
}
|
|
965
969
|
usbi_mutex_unlock(&darwin_cached_devices_mutex);
|
|
966
970
|
}
|
|
967
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
|
+
|
|
968
1025
|
static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
|
|
969
1026
|
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
|
970
1027
|
UInt8 i, numConfig;
|
|
@@ -977,9 +1034,9 @@ static int get_configuration_index (struct libusb_device *dev, UInt8 config_valu
|
|
|
977
1034
|
return darwin_to_libusb (kresult);
|
|
978
1035
|
|
|
979
1036
|
for (i = 0 ; i < numConfig ; i++) {
|
|
980
|
-
(*priv->device)->GetConfigurationDescriptorPtr (priv->device, i, &desc);
|
|
1037
|
+
kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, i, &desc);
|
|
981
1038
|
|
|
982
|
-
if (desc->bConfigurationValue == config_value)
|
|
1039
|
+
if (kresult == kIOReturnSuccess && desc->bConfigurationValue == config_value)
|
|
983
1040
|
return i;
|
|
984
1041
|
}
|
|
985
1042
|
|
|
@@ -1196,7 +1253,8 @@ static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *
|
|
|
1196
1253
|
if (kIOReturnSuccess != ret) {
|
|
1197
1254
|
usbi_dbg(ctx, "kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
|
|
1198
1255
|
/* sleep for a little while before trying again */
|
|
1199
|
-
|
|
1256
|
+
struct timespec full_delay = {delay / 1000000, (delay * 1000) % 1000000000};
|
|
1257
|
+
nanosleep(&full_delay, NULL);
|
|
1200
1258
|
}
|
|
1201
1259
|
} while (kIOReturnSuccess != ret && retries--);
|
|
1202
1260
|
|
|
@@ -1258,7 +1316,15 @@ static bool get_device_port (io_service_t service, UInt8 *port) {
|
|
|
1258
1316
|
|
|
1259
1317
|
kresult = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
|
|
1260
1318
|
if (kIOReturnSuccess == kresult) {
|
|
1261
|
-
|
|
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);
|
|
1262
1328
|
IOObjectRelease (parent);
|
|
1263
1329
|
}
|
|
1264
1330
|
|
|
@@ -1315,7 +1381,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
|
|
|
1315
1381
|
list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
|
|
1316
1382
|
usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32 " against cached device with sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32,
|
|
1317
1383
|
sessionID, locationID, new_device->session, new_device->location);
|
|
1318
|
-
if (new_device->location == locationID && new_device->in_reenumerate) {
|
|
1384
|
+
if (new_device->location == locationID && atomic_load(&new_device->in_reenumerate)) {
|
|
1319
1385
|
usbi_dbg (ctx, "found cached device with matching location that is being re-enumerated");
|
|
1320
1386
|
*old_session_id = new_device->session;
|
|
1321
1387
|
break;
|
|
@@ -1479,7 +1545,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
|
|
|
1479
1545
|
|
|
1480
1546
|
} while (0);
|
|
1481
1547
|
|
|
1482
|
-
if (!cached_device->in_reenumerate && 0 == ret) {
|
|
1548
|
+
if (!atomic_load(&cached_device->in_reenumerate) && 0 == ret) {
|
|
1483
1549
|
usbi_connect_device (dev);
|
|
1484
1550
|
} else {
|
|
1485
1551
|
libusb_unref_device (dev);
|
|
@@ -1523,6 +1589,10 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
|
|
|
1523
1589
|
IOReturn kresult;
|
|
1524
1590
|
|
|
1525
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
|
+
}
|
|
1526
1596
|
/* try to open the device */
|
|
1527
1597
|
kresult = (*dpriv->device)->USBDeviceOpenSeize (dpriv->device);
|
|
1528
1598
|
if (kresult != kIOReturnSuccess) {
|
|
@@ -1824,7 +1894,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8
|
|
|
1824
1894
|
/* Do the actual claim */
|
|
1825
1895
|
kresult = (*plugInInterface)->QueryInterface(plugInInterface,
|
|
1826
1896
|
CFUUIDGetUUIDBytes(get_interface_interface_id()),
|
|
1827
|
-
(LPVOID)&IOINTERFACE(cInterface));
|
|
1897
|
+
(LPVOID *)&IOINTERFACE(cInterface));
|
|
1828
1898
|
/* We no longer need the intermediate plug-in */
|
|
1829
1899
|
/* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
|
|
1830
1900
|
(*plugInInterface)->Release (plugInInterface);
|
|
@@ -2022,7 +2092,7 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, uint8_
|
|
|
2022
2092
|
dpriv->open_count = 1;
|
|
2023
2093
|
|
|
2024
2094
|
/* clean up open interfaces */
|
|
2025
|
-
|
|
2095
|
+
darwin_close (dev_handle);
|
|
2026
2096
|
|
|
2027
2097
|
/* re-open the device */
|
|
2028
2098
|
ret = darwin_open (dev_handle);
|
|
@@ -2080,19 +2150,26 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2080
2150
|
|
|
2081
2151
|
struct libusb_context *ctx = HANDLE_CTX (dev_handle);
|
|
2082
2152
|
|
|
2083
|
-
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)) {
|
|
2084
2159
|
/* ack, two (or more) threads are trying to reset the device! abort! */
|
|
2085
2160
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2086
2161
|
}
|
|
2087
2162
|
|
|
2088
|
-
dpriv->in_reenumerate = true;
|
|
2089
|
-
|
|
2090
2163
|
/* store copies of descriptors so they can be compared after the reset */
|
|
2091
2164
|
memcpy (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor));
|
|
2092
2165
|
cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
|
|
2093
2166
|
|
|
2094
2167
|
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
2095
|
-
(*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
|
+
}
|
|
2096
2173
|
memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
|
|
2097
2174
|
}
|
|
2098
2175
|
|
|
@@ -2111,14 +2188,14 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2111
2188
|
kresult = (*dpriv->device)->USBDeviceReEnumerate (dpriv->device, options);
|
|
2112
2189
|
if (kresult != kIOReturnSuccess) {
|
|
2113
2190
|
usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
|
|
2114
|
-
dpriv->in_reenumerate
|
|
2191
|
+
atomic_store(&dpriv->in_reenumerate, false);
|
|
2115
2192
|
return darwin_to_libusb (kresult);
|
|
2116
2193
|
}
|
|
2117
2194
|
|
|
2118
2195
|
/* capture mode does not re-enumerate but it does require re-open */
|
|
2119
2196
|
if (capture) {
|
|
2120
2197
|
usbi_dbg (ctx, "darwin/reenumerate_device: restoring state...");
|
|
2121
|
-
dpriv->in_reenumerate
|
|
2198
|
+
atomic_store(&dpriv->in_reenumerate, false);
|
|
2122
2199
|
return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
|
|
2123
2200
|
}
|
|
2124
2201
|
|
|
@@ -2127,19 +2204,19 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2127
2204
|
struct timespec start;
|
|
2128
2205
|
usbi_get_monotonic_time(&start);
|
|
2129
2206
|
|
|
2130
|
-
while (dpriv->in_reenumerate) {
|
|
2131
|
-
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};
|
|
2132
2209
|
nanosleep (&delay, NULL);
|
|
2133
2210
|
|
|
2134
2211
|
struct timespec now, delta;
|
|
2135
2212
|
usbi_get_monotonic_time(&now);
|
|
2136
2213
|
TIMESPEC_SUB(&now, &start, &delta);
|
|
2137
|
-
unsigned long long elapsed_us = (unsigned long long)delta.tv_sec * USEC_PER_SEC +
|
|
2138
|
-
(unsigned long long)delta.tv_nsec / 1000ULL;
|
|
2214
|
+
unsigned long long elapsed_us = ((unsigned long long)delta.tv_sec * USEC_PER_SEC) +
|
|
2215
|
+
((unsigned long long)delta.tv_nsec / 1000ULL);
|
|
2139
2216
|
|
|
2140
2217
|
if (elapsed_us >= DARWIN_REENUMERATE_TIMEOUT_US) {
|
|
2141
2218
|
usbi_err (ctx, "darwin/reenumerate_device: timeout waiting for reenumerate");
|
|
2142
|
-
dpriv->in_reenumerate
|
|
2219
|
+
atomic_store(&dpriv->in_reenumerate, false);
|
|
2143
2220
|
return LIBUSB_ERROR_TIMEOUT;
|
|
2144
2221
|
}
|
|
2145
2222
|
}
|
|
@@ -2154,8 +2231,8 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
|
|
|
2154
2231
|
}
|
|
2155
2232
|
|
|
2156
2233
|
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
|
|
2157
|
-
|
|
2158
|
-
if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i])) != 0) {
|
|
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) {
|
|
2159
2236
|
usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
|
|
2160
2237
|
return LIBUSB_ERROR_NOT_FOUND;
|
|
2161
2238
|
}
|
|
@@ -2650,7 +2727,9 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
|
|
|
2650
2727
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
2651
2728
|
struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
|
|
2652
2729
|
const unsigned char max_transfer_type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
|
|
2730
|
+
#ifdef ENABLE_LOGGING
|
|
2653
2731
|
const char *transfer_types[] = {"control", "isoc", "bulk", "interrupt", "bulk-stream", NULL};
|
|
2732
|
+
#endif
|
|
2654
2733
|
bool is_isoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
|
|
2655
2734
|
struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
|
|
2656
2735
|
|
|
@@ -2926,6 +3005,7 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
2926
3005
|
.exit = darwin_exit,
|
|
2927
3006
|
.set_option = NULL,
|
|
2928
3007
|
.get_device_list = NULL,
|
|
3008
|
+
.get_device_string = darwin_get_device_string,
|
|
2929
3009
|
.hotplug_poll = darwin_hotplug_poll,
|
|
2930
3010
|
.wrap_sys_device = NULL,
|
|
2931
3011
|
.open = darwin_open,
|
|
@@ -117,7 +117,7 @@ struct darwin_cached_device {
|
|
|
117
117
|
UInt8 first_config, active_config, port;
|
|
118
118
|
int can_enumerate;
|
|
119
119
|
int refcount;
|
|
120
|
-
|
|
120
|
+
atomic_bool in_reenumerate;
|
|
121
121
|
int capture_count;
|
|
122
122
|
};
|
|
123
123
|
|
|
@@ -125,17 +125,19 @@ struct darwin_device_priv {
|
|
|
125
125
|
struct darwin_cached_device *dev;
|
|
126
126
|
};
|
|
127
127
|
|
|
128
|
+
struct darwin_interface {
|
|
129
|
+
usb_interface_t interface;
|
|
130
|
+
uint8_t num_endpoints;
|
|
131
|
+
CFRunLoopSourceRef cfSource;
|
|
132
|
+
uint64_t frames[256];
|
|
133
|
+
uint8_t endpoint_addrs[USB_MAXENDPOINTS];
|
|
134
|
+
};
|
|
135
|
+
|
|
128
136
|
struct darwin_device_handle_priv {
|
|
129
137
|
bool is_open;
|
|
130
138
|
CFRunLoopSourceRef cfSource;
|
|
131
139
|
|
|
132
|
-
struct darwin_interface
|
|
133
|
-
usb_interface_t interface;
|
|
134
|
-
uint8_t num_endpoints;
|
|
135
|
-
CFRunLoopSourceRef cfSource;
|
|
136
|
-
uint64_t frames[256];
|
|
137
|
-
uint8_t endpoint_addrs[USB_MAXENDPOINTS];
|
|
138
|
-
} interfaces[USB_MAXINTERFACES];
|
|
140
|
+
struct darwin_interface interfaces[USB_MAXINTERFACES];
|
|
139
141
|
};
|
|
140
142
|
|
|
141
143
|
struct darwin_transfer_priv {
|
|
@@ -538,17 +538,36 @@ private:
|
|
|
538
538
|
auto configurations_len = dev->device_descriptor.bNumConfigurations;
|
|
539
539
|
configurations.reserve(configurations_len);
|
|
540
540
|
for (uint8_t j = 0; j < configurations_len; j++) {
|
|
541
|
-
//
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
541
|
+
// Read descriptor header first to discover target length.
|
|
542
|
+
auto config_header_result = co_await_try(
|
|
543
|
+
requestDescriptor(LIBUSB_DT_CONFIG, j, LIBUSB_DT_CONFIG_SIZE));
|
|
544
|
+
if (auto error = getTransferStatus(config_header_result)) {
|
|
545
|
+
co_return error;
|
|
546
|
+
}
|
|
547
|
+
union usbi_config_desc_buf config_header = {};
|
|
548
|
+
copyFromDataView(config_header.buf, config_header_result["data"]);
|
|
549
|
+
if (config_header.desc.bDescriptorType != LIBUSB_DT_CONFIG ||
|
|
550
|
+
config_header.desc.bLength < LIBUSB_DT_CONFIG_SIZE) {
|
|
551
|
+
co_return LIBUSB_ERROR_IO;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
auto config_total_length =
|
|
555
|
+
libusb_le16_to_cpu(config_header.desc.wTotalLength);
|
|
556
|
+
if (config_total_length < LIBUSB_DT_CONFIG_SIZE) {
|
|
557
|
+
co_return LIBUSB_ERROR_IO;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
auto config_result = co_await_try(
|
|
561
|
+
requestDescriptor(LIBUSB_DT_CONFIG, j, config_total_length));
|
|
562
|
+
if (auto error = getTransferStatus(config_result)) {
|
|
549
563
|
co_return error;
|
|
550
564
|
}
|
|
551
|
-
|
|
565
|
+
|
|
566
|
+
auto configVal = config_result["data"];
|
|
567
|
+
if (configVal["byteLength"].as<size_t>() < config_total_length) {
|
|
568
|
+
co_return LIBUSB_ERROR_IO;
|
|
569
|
+
}
|
|
570
|
+
|
|
552
571
|
auto configLen = configVal["byteLength"].as<size_t>();
|
|
553
572
|
auto& config = configurations.emplace_back(
|
|
554
573
|
(usbi_configuration_descriptor*)::operator new(configLen));
|
|
@@ -623,6 +642,8 @@ val getDeviceList(libusb_context* ctx, discovered_devs** devs) {
|
|
|
623
642
|
// This can wrap around but it's the best approximation of a stable
|
|
624
643
|
// device address and port number we can provide.
|
|
625
644
|
dev->device_address = dev->port_number = (uint8_t)session_id;
|
|
645
|
+
|
|
646
|
+
usbi_connect_device(dev);
|
|
626
647
|
}
|
|
627
648
|
*devs = discovered_devs_append(*devs, dev);
|
|
628
649
|
libusb_unref_device(dev);
|
|
@@ -706,7 +727,7 @@ int em_get_config_descriptor_by_value(libusb_device* dev,
|
|
|
706
727
|
}
|
|
707
728
|
|
|
708
729
|
int em_set_configuration(libusb_device_handle* dev_handle, int config) {
|
|
709
|
-
return WebUsbDevicePtr(dev_handle)->awaitOnMain("
|
|
730
|
+
return WebUsbDevicePtr(dev_handle)->awaitOnMain("selectConfiguration", config);
|
|
710
731
|
}
|
|
711
732
|
|
|
712
733
|
int em_claim_interface(libusb_device_handle* handle, uint8_t iface) {
|
|
@@ -186,6 +186,7 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
186
186
|
/*.exit =*/ haiku_exit,
|
|
187
187
|
/*.set_option =*/ NULL,
|
|
188
188
|
/*.get_device_list =*/ NULL,
|
|
189
|
+
/*.get_device_string =*/ NULL,
|
|
189
190
|
/*.hotplug_poll =*/ NULL,
|
|
190
191
|
/*.wrap_sys_device =*/ NULL,
|
|
191
192
|
/*.open =*/ haiku_open,
|
|
@@ -214,6 +215,9 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
214
215
|
/*.kernel_driver_active =*/ NULL,
|
|
215
216
|
/*.detach_kernel_driver =*/ NULL,
|
|
216
217
|
/*.attach_kernel_driver =*/ NULL,
|
|
218
|
+
/*.endpoint_supports_raw_io =*/ NULL,
|
|
219
|
+
/*.endpoint_set_raw_io =*/ NULL,
|
|
220
|
+
/*.get_max_raw_io_transfer_size =*/ NULL,
|
|
217
221
|
|
|
218
222
|
/*.destroy_device =*/ NULL,
|
|
219
223
|
|