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.
Files changed (114) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +14 -0
  3. package/binding.gyp +2 -9
  4. package/dist/usb/bindings.d.ts +27 -2
  5. package/dist/usb/bindings.js.map +1 -1
  6. package/dist/usb/endpoint.js +1 -1
  7. package/dist/usb/endpoint.js.map +1 -1
  8. package/dist/usb/index.d.ts +0 -29
  9. package/dist/usb/index.js +4 -18
  10. package/dist/usb/index.js.map +1 -1
  11. package/dist/webusb/index.d.ts +1 -1
  12. package/dist/webusb/index.js +1 -1
  13. package/dist/webusb/index.js.map +1 -1
  14. package/dist/webusb/webusb-device.d.ts +4 -4
  15. package/dist/webusb/webusb-device.js +5 -2
  16. package/dist/webusb/webusb-device.js.map +1 -1
  17. package/libusb/.clang-tidy +36 -0
  18. package/libusb/.private/ci-build.sh +5 -1
  19. package/libusb/AUTHORS +21 -0
  20. package/libusb/ChangeLog +29 -2
  21. package/libusb/KEYS +123 -0
  22. package/libusb/README +8 -9
  23. package/libusb/Xcode/common.xcconfig +20 -0
  24. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +16 -12
  25. package/libusb/android/examples/unrooted_android.c +1 -0
  26. package/libusb/configure.ac +12 -2
  27. package/libusb/examples/dpfp.c +1 -1
  28. package/libusb/examples/ezusb.c +6 -1
  29. package/libusb/examples/fxload.c +7 -5
  30. package/libusb/examples/hotplugtest.c +19 -11
  31. package/libusb/examples/listdevs.c +41 -3
  32. package/libusb/examples/testlibusb.c +1 -0
  33. package/libusb/examples/xusb.c +142 -77
  34. package/libusb/libusb/Makefile.am +4 -0
  35. package/libusb/libusb/core.c +183 -24
  36. package/libusb/libusb/descriptor.c +404 -96
  37. package/libusb/libusb/hotplug.c +27 -8
  38. package/libusb/libusb/io.c +10 -5
  39. package/libusb/libusb/libusb-1.0.def +14 -0
  40. package/libusb/libusb/libusb.h +179 -19
  41. package/libusb/libusb/libusbi.h +101 -25
  42. package/libusb/libusb/os/darwin_usb.c +216 -90
  43. package/libusb/libusb/os/darwin_usb.h +10 -8
  44. package/libusb/libusb/os/emscripten_webusb.cpp +38 -12
  45. package/libusb/libusb/os/events_posix.c +4 -4
  46. package/libusb/libusb/os/haiku_usb_raw.cpp +4 -0
  47. package/libusb/libusb/os/linux_usbfs.c +92 -33
  48. package/libusb/libusb/os/linux_usbfs.h +13 -3
  49. package/libusb/libusb/os/netbsd_usb.c +6 -4
  50. package/libusb/libusb/os/openbsd_usb.c +4 -2
  51. package/libusb/libusb/os/sunos_usb.c +7 -5
  52. package/libusb/libusb/os/threads_posix.c +20 -19
  53. package/libusb/libusb/os/threads_posix.h +9 -3
  54. package/libusb/libusb/os/threads_windows.h +4 -3
  55. package/libusb/libusb/os/windows_common.c +86 -1
  56. package/libusb/libusb/os/windows_common.h +20 -1
  57. package/libusb/libusb/os/windows_hotplug.c +321 -0
  58. package/libusb/libusb/os/windows_hotplug.h +28 -0
  59. package/libusb/libusb/os/windows_usbdk.c +16 -8
  60. package/libusb/libusb/os/windows_winusb.c +788 -56
  61. package/libusb/libusb/os/windows_winusb.h +11 -6
  62. package/libusb/libusb/sync.c +8 -5
  63. package/libusb/libusb/version.h +1 -1
  64. package/libusb/libusb/version_nano.h +1 -1
  65. package/libusb/msvc/Base.props +1 -1
  66. package/libusb/msvc/Configuration.Base.props +2 -1
  67. package/libusb/msvc/Configuration.DynamicLibrary.props +12 -0
  68. package/libusb/msvc/ProjectConfigurations.Base.props +69 -16
  69. package/libusb/msvc/build_all.ps1 +2 -2
  70. package/libusb/msvc/config.h +4 -0
  71. package/libusb/msvc/getopt/bits/getopt_core.h +96 -0
  72. package/libusb/msvc/getopt/bits/getopt_ext.h +77 -0
  73. package/libusb/msvc/getopt/features.h +21 -0
  74. package/libusb/msvc/getopt/getopt.c +456 -705
  75. package/libusb/msvc/getopt/getopt.h +16 -158
  76. package/libusb/msvc/getopt/getopt1.c +40 -69
  77. package/libusb/msvc/getopt/getopt_int.h +118 -0
  78. package/libusb/msvc/getopt/gettext.h +7 -0
  79. package/libusb/msvc/getopt/unistd.h +5 -0
  80. package/libusb/msvc/getopt.vcxproj +11 -4
  81. package/libusb/msvc/libusb.sln +515 -268
  82. package/libusb/msvc/libusb_dll.vcxproj +2 -0
  83. package/libusb/msvc/libusb_static.vcxproj +2 -0
  84. package/libusb/msvc/xusb.vcxproj +1 -1
  85. package/libusb/tests/Makefile.am +10 -1
  86. package/libusb/tests/fuzz/corpus/bos/min.bos +0 -0
  87. package/libusb/tests/fuzz/corpus/descriptor_parsers/min_valid_config.bin +0 -0
  88. package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_a_endpoint_null.bin +0 -0
  89. package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_b_iad_oob.bin +0 -0
  90. package/libusb/tests/fuzz/fuzz_bos_descriptor.c +49 -0
  91. package/libusb/tests/fuzz/fuzz_descriptor_parsers.c +83 -0
  92. package/libusb/tests/macos.c +2 -2
  93. package/libusb/tests/stress_mt.c +6 -3
  94. package/libusb/tests/webusb-test-shim/index.js +6 -5
  95. package/libusb.gypi +5 -0
  96. package/package.json +3 -3
  97. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  98. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  99. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  100. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  101. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  102. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  103. package/prebuilds/linux-ia32/node.napi.node +0 -0
  104. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  105. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  106. package/prebuilds/win32-arm64/node.napi.node +0 -0
  107. package/prebuilds/win32-ia32/node.napi.node +0 -0
  108. package/prebuilds/win32-x64/node.napi.node +0 -0
  109. package/src/{hotplug/libusb.cc → hotplug.cc} +2 -3
  110. package/src/{hotplug/hotplug.h → hotplug.h} +2 -6
  111. package/src/node_usb.cc +3 -3
  112. package/test/usb.coffee +4 -4
  113. package/test/webusb.coffee +22 -12
  114. 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 (10 * USEC_PER_SEC)
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 pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
61
- static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
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 = PTHREAD_MUTEX_INITIALIZER;
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
- int libusb_testonly_using_running_interface_version __attribute__ ((visibility ("hidden")));
74
- int libusb_testonly_using_running_device_version __attribute__ ((visibility ("hidden")));
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 int get_interface_interface_version(void) {
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 int get_device_interface_version(void) {
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
- return (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction,
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, "%i.%i.%i", &major, &minor, &patch);
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 100000;
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 100000;
414
+ return 10 * 10000;
390
415
  }
391
416
 
392
- int darwin_major = 1, darwin_minor = 0;
393
- ret = sscanf(os_release_string, "%i.%i", &darwin_major, &darwin_minor);
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 100000;
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
- nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
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 = 1000000ul};
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
- pthread_mutex_lock (&libusb_darwin_at_mutex);
742
+ usbi_mutex_lock (&libusb_darwin_at_mutex);
714
743
  libusb_darwin_acfl = LIBUSB_DARWIN_STARTUP_FAILURE;
715
- pthread_cond_signal (&libusb_darwin_at_cond);
716
- pthread_mutex_unlock (&libusb_darwin_at_mutex);
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
- pthread_mutex_lock (&libusb_darwin_at_mutex);
829
+ usbi_mutex_lock (&libusb_darwin_at_mutex);
801
830
  libusb_darwin_acfl = runloop;
802
831
  libusb_darwin_acfls = libusb_shutdown_cfsource;
803
- pthread_cond_signal (&libusb_darwin_at_cond);
804
- pthread_mutex_unlock (&libusb_darwin_at_mutex);
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
- pthread_mutex_lock (&libusb_darwin_at_mutex);
841
+ usbi_mutex_lock (&libusb_darwin_at_mutex);
813
842
  libusb_darwin_acfls = NULL;
814
843
  libusb_darwin_acfl = NULL;
815
- pthread_cond_signal (&libusb_darwin_at_cond);
816
- pthread_mutex_unlock (&libusb_darwin_at_mutex);
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
- pthread_mutex_lock (&libusb_darwin_at_mutex);
905
+ usbi_mutex_lock (&libusb_darwin_at_mutex);
877
906
  libusb_darwin_at_started = true;
878
907
  while (NULL == libusb_darwin_acfl) {
879
- pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
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
- pthread_mutex_unlock (&libusb_darwin_at_mutex);
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
- pthread_mutex_lock (&libusb_darwin_at_mutex);
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
- pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
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
- pthread_mutex_unlock (&libusb_darwin_at_mutex);
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; // microseconds
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
- nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000}, NULL);
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
- ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port);
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
- while((kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent)) == kIOReturnSuccess) {
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
- kresult = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
1872
- if (kresult != kIOReturnSuccess)
1873
- usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
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, int8_t active_config,
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
- (void) darwin_close (dev_handle);
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
- int8_t active_config = dpriv->active_config;
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->in_reenumerate) {
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 = false;
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 = false;
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
- unsigned long elapsed_us = (now.tv_sec - start.tv_sec) * USEC_PER_SEC +
2104
- (now.tv_nsec - start.tv_nsec) / 1000;
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 = false;
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
- (void) (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
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
- int8_t active_config = dpriv->active_config;
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 + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1));
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 + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)) / 8;
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
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) {
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
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface)))
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
- .get_active_config_descriptor = darwin_get_active_config_descriptor,
2892
- .get_config_descriptor = darwin_get_config_descriptor,
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),