usb 2.16.0 → 2.17.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 (61) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/usb/endpoint.js +1 -1
  3. package/dist/usb/endpoint.js.map +1 -1
  4. package/dist/webusb/index.d.ts +1 -1
  5. package/dist/webusb/index.js +1 -1
  6. package/dist/webusb/index.js.map +1 -1
  7. package/dist/webusb/webusb-device.d.ts +4 -4
  8. package/dist/webusb/webusb-device.js +5 -2
  9. package/dist/webusb/webusb-device.js.map +1 -1
  10. package/libusb/.clang-tidy +34 -0
  11. package/libusb/AUTHORS +7 -0
  12. package/libusb/ChangeLog +14 -0
  13. package/libusb/KEYS +123 -0
  14. package/libusb/README +0 -4
  15. package/libusb/Xcode/common.xcconfig +20 -0
  16. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +12 -12
  17. package/libusb/android/examples/unrooted_android.c +1 -0
  18. package/libusb/configure.ac +2 -2
  19. package/libusb/examples/dpfp.c +1 -1
  20. package/libusb/examples/ezusb.c +6 -1
  21. package/libusb/examples/fxload.c +7 -5
  22. package/libusb/examples/testlibusb.c +1 -0
  23. package/libusb/examples/xusb.c +136 -76
  24. package/libusb/libusb/core.c +8 -10
  25. package/libusb/libusb/descriptor.c +253 -94
  26. package/libusb/libusb/hotplug.c +27 -8
  27. package/libusb/libusb/io.c +3 -2
  28. package/libusb/libusb/libusb-1.0.def +4 -0
  29. package/libusb/libusb/libusb.h +121 -11
  30. package/libusb/libusb/libusbi.h +12 -0
  31. package/libusb/libusb/os/darwin_usb.c +93 -47
  32. package/libusb/libusb/os/emscripten_webusb.cpp +7 -2
  33. package/libusb/libusb/os/events_posix.c +4 -4
  34. package/libusb/libusb/os/linux_usbfs.c +20 -9
  35. package/libusb/libusb/os/linux_usbfs.h +13 -3
  36. package/libusb/libusb/os/netbsd_usb.c +4 -4
  37. package/libusb/libusb/os/openbsd_usb.c +2 -2
  38. package/libusb/libusb/os/sunos_usb.c +5 -5
  39. package/libusb/libusb/os/threads_posix.c +17 -16
  40. package/libusb/libusb/os/threads_posix.h +1 -1
  41. package/libusb/libusb/os/threads_windows.h +2 -2
  42. package/libusb/libusb/os/windows_winusb.c +35 -15
  43. package/libusb/libusb/sync.c +8 -5
  44. package/libusb/libusb/version.h +1 -1
  45. package/libusb/libusb/version_nano.h +1 -1
  46. package/libusb/tests/macos.c +2 -2
  47. package/libusb/tests/stress_mt.c +4 -2
  48. package/package.json +3 -3
  49. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  50. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  51. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  52. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  53. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  54. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  55. package/prebuilds/linux-ia32/node.napi.node +0 -0
  56. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  57. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  58. package/prebuilds/win32-arm64/node.napi.node +0 -0
  59. package/prebuilds/win32-ia32/node.napi.node +0 -0
  60. package/prebuilds/win32-x64/node.napi.node +0 -0
  61. package/test/webusb.coffee +2 -2
@@ -166,9 +166,11 @@ typedef SSIZE_T ssize_t;
166
166
  * <li>libusb version 1.0.25: LIBUSB_API_VERSION = 0x01000109
167
167
  * <li>libusb version 1.0.26: LIBUSB_API_VERSION = 0x01000109
168
168
  * <li>libusb version 1.0.27: LIBUSB_API_VERSION = 0x0100010A
169
+ * <li>libusb version 1.0.28: LIBUSB_API_VERSION = 0x0100010A
170
+ * <li>libusb version 1.0.29: LIBUSB_API_VERSION = 0x0100010B
169
171
  * </ul>
170
172
  */
171
- #define LIBUSB_API_VERSION 0x0100010A
173
+ #define LIBUSB_API_VERSION 0x0100010B
172
174
 
173
175
  /** \def LIBUSBX_API_VERSION
174
176
  * \ingroup libusb_misc
@@ -335,10 +337,12 @@ enum libusb_descriptor_type {
335
337
  #define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6
336
338
  #define LIBUSB_DT_BOS_SIZE 5
337
339
  #define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3
340
+ #define LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE 8
338
341
 
339
342
  /* BOS descriptor sizes */
340
343
  #define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7
341
344
  #define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10
345
+ #define LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE 12
342
346
  #define LIBUSB_BT_CONTAINER_ID_SIZE 20
343
347
  #define LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE 20
344
348
 
@@ -562,7 +566,10 @@ enum libusb_bos_type {
562
566
  LIBUSB_BT_CONTAINER_ID = 0x04,
563
567
 
564
568
  /** Platform descriptor */
565
- LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05
569
+ LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05,
570
+
571
+ /** SuperSpeedPlus device capability */
572
+ LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY = 0x0A,
566
573
  };
567
574
 
568
575
  /** \ingroup libusb_desc
@@ -927,7 +934,7 @@ struct libusb_usb_2_0_extension_descriptor {
927
934
  uint8_t bDescriptorType;
928
935
 
929
936
  /** Capability type. Will have value
930
- * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
937
+ * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION
931
938
  * LIBUSB_BT_USB_2_0_EXTENSION in this context. */
932
939
  uint8_t bDevCapabilityType;
933
940
 
@@ -953,7 +960,7 @@ struct libusb_ss_usb_device_capability_descriptor {
953
960
  uint8_t bDescriptorType;
954
961
 
955
962
  /** Capability type. Will have value
956
- * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
963
+ * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
957
964
  * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */
958
965
  uint8_t bDevCapabilityType;
959
966
 
@@ -980,6 +987,100 @@ struct libusb_ss_usb_device_capability_descriptor {
980
987
  uint16_t bU2DevExitLat;
981
988
  };
982
989
 
990
+ /** \ingroup libusb_desc
991
+ * enum used in \ref libusb_ssplus_sublink_attribute
992
+ */
993
+ enum libusb_superspeedplus_sublink_attribute_sublink_type {
994
+ LIBUSB_SSPLUS_ATTR_TYPE_SYM = 0,
995
+ LIBUSB_SSPLUS_ATTR_TYPE_ASYM = 1,
996
+ };
997
+
998
+ /** \ingroup libusb_desc
999
+ * enum used in \ref libusb_ssplus_sublink_attribute
1000
+ */
1001
+ enum libusb_superspeedplus_sublink_attribute_sublink_direction {
1002
+ LIBUSB_SSPLUS_ATTR_DIR_RX = 0,
1003
+ LIBUSB_SSPLUS_ATTR_DIR_TX = 1,
1004
+ };
1005
+
1006
+ /** \ingroup libusb_desc
1007
+ * enum used in \ref libusb_ssplus_sublink_attribute
1008
+ * Bit = Bits per second
1009
+ * Kb = Kbps
1010
+ * Mb = Mbps
1011
+ * Gb = Gbps
1012
+ */
1013
+ enum libusb_superspeedplus_sublink_attribute_exponent {
1014
+ LIBUSB_SSPLUS_ATTR_EXP_BPS = 0,
1015
+ LIBUSB_SSPLUS_ATTR_EXP_KBS = 1,
1016
+ LIBUSB_SSPLUS_ATTR_EXP_MBS = 2,
1017
+ LIBUSB_SSPLUS_ATTR_EXP_GBS = 3,
1018
+ };
1019
+
1020
+ /** \ingroup libusb_desc
1021
+ * enum used in \ref libusb_ssplus_sublink_attribute
1022
+ */
1023
+ enum libusb_superspeedplus_sublink_attribute_link_protocol {
1024
+ LIBUSB_SSPLUS_ATTR_PROT_SS = 0,
1025
+ LIBUSB_SSPLUS_ATTR_PROT_SSPLUS = 1,
1026
+ };
1027
+
1028
+ /** \ingroup libusb_desc
1029
+ * Expose \ref libusb_ssplus_usb_device_capability_descriptor.sublinkSpeedAttributes
1030
+ */
1031
+ struct libusb_ssplus_sublink_attribute {
1032
+ /** Sublink Speed Attribute ID (SSID).
1033
+ This field is an ID that uniquely identifies the speed of this sublink */
1034
+ uint8_t ssid;
1035
+
1036
+ /** This field defines the
1037
+ base 10 exponent times 3, that shall be applied to the
1038
+ mantissa. */
1039
+ enum libusb_superspeedplus_sublink_attribute_exponent exponent;
1040
+
1041
+ /** This field identifies whether the
1042
+ Sublink Speed Attribute defines a symmetric or
1043
+ asymmetric bit rate.*/
1044
+ enum libusb_superspeedplus_sublink_attribute_sublink_type type;
1045
+
1046
+ /** This field indicates if this
1047
+ Sublink Speed Attribute defines the receive or
1048
+ transmit bit rate. */
1049
+ enum libusb_superspeedplus_sublink_attribute_sublink_direction direction;
1050
+
1051
+ /** This field identifies the protocol
1052
+ supported by the link. */
1053
+ enum libusb_superspeedplus_sublink_attribute_link_protocol protocol;
1054
+
1055
+ /** This field defines the mantissa that shall be applied to the exponent when
1056
+ calculating the maximum bit rate. */
1057
+ uint16_t mantissa;
1058
+ };
1059
+
1060
+ /** \ingroup libusb_desc
1061
+ * A structure representing the SuperSpeedPlus descriptor
1062
+ * This descriptor is documented in section 9.6.2.5 of the USB 3.1 specification.
1063
+ */
1064
+ struct libusb_ssplus_usb_device_capability_descriptor {
1065
+ /** Sublink Speed Attribute Count */
1066
+ uint8_t numSublinkSpeedAttributes;
1067
+
1068
+ /** Sublink Speed ID Count */
1069
+ uint8_t numSublinkSpeedIDs;
1070
+
1071
+ /** Unique ID to indicates the minimum lane speed */
1072
+ uint8_t ssid;
1073
+
1074
+ /** This field indicates the minimum receive lane count.*/
1075
+ uint8_t minRxLaneCount;
1076
+
1077
+ /** This field indicates the minimum transmit lane count*/
1078
+ uint8_t minTxLaneCount;
1079
+
1080
+ /** Array size is \ref libusb_ssplus_usb_device_capability_descriptor.numSublinkSpeedAttributes */
1081
+ struct libusb_ssplus_sublink_attribute sublinkSpeedAttributes[];
1082
+ };
1083
+
983
1084
  /** \ingroup libusb_desc
984
1085
  * A structure representing the Container ID descriptor.
985
1086
  * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification.
@@ -995,7 +1096,7 @@ struct libusb_container_id_descriptor {
995
1096
  uint8_t bDescriptorType;
996
1097
 
997
1098
  /** Capability type. Will have value
998
- * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
1099
+ * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID
999
1100
  * LIBUSB_BT_CONTAINER_ID in this context. */
1000
1101
  uint8_t bDevCapabilityType;
1001
1102
 
@@ -1020,7 +1121,7 @@ struct libusb_platform_descriptor {
1020
1121
  uint8_t bDescriptorType;
1021
1122
 
1022
1123
  /** Capability type. Will have value
1023
- * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
1124
+ * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
1024
1125
  * LIBUSB_BT_CONTAINER_ID in this context. */
1025
1126
  uint8_t bDevCapabilityType;
1026
1127
 
@@ -1167,7 +1268,10 @@ enum libusb_speed {
1167
1268
  LIBUSB_SPEED_SUPER = 4,
1168
1269
 
1169
1270
  /** The device is operating at super speed plus (10000MBit/s). */
1170
- LIBUSB_SPEED_SUPER_PLUS = 5
1271
+ LIBUSB_SPEED_SUPER_PLUS = 5,
1272
+
1273
+ /** The device is operating at super speed plus x2 (20000MBit/s). */
1274
+ LIBUSB_SPEED_SUPER_PLUS_X2 = 6,
1171
1275
  };
1172
1276
 
1173
1277
  /** \ingroup libusb_misc
@@ -1581,7 +1685,7 @@ void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
1581
1685
  void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode);
1582
1686
  const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
1583
1687
  int LIBUSB_CALL libusb_has_capability(uint32_t capability);
1584
- const char * LIBUSB_CALL libusb_error_name(int errcode);
1688
+ const char * LIBUSB_CALL libusb_error_name(int error_code);
1585
1689
  int LIBUSB_CALL libusb_setlocale(const char *locale);
1586
1690
  const char * LIBUSB_CALL libusb_strerror(int errcode);
1587
1691
 
@@ -1625,6 +1729,12 @@ int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor(
1625
1729
  struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap);
1626
1730
  void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor(
1627
1731
  struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap);
1732
+ int LIBUSB_CALL libusb_get_ssplus_usb_device_capability_descriptor(
1733
+ libusb_context *ctx,
1734
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
1735
+ struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap);
1736
+ void LIBUSB_CALL libusb_free_ssplus_usb_device_capability_descriptor(
1737
+ struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap);
1628
1738
  int LIBUSB_CALL libusb_get_container_id_descriptor(libusb_context *ctx,
1629
1739
  struct libusb_bos_dev_capability_descriptor *dev_cap,
1630
1740
  struct libusb_container_id_descriptor **container_id);
@@ -2035,16 +2145,16 @@ static inline unsigned char *libusb_get_iso_packet_buffer_simple(
2035
2145
  /* sync I/O */
2036
2146
 
2037
2147
  int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,
2038
- uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
2148
+ uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
2039
2149
  unsigned char *data, uint16_t wLength, unsigned int timeout);
2040
2150
 
2041
2151
  int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
2042
2152
  unsigned char endpoint, unsigned char *data, int length,
2043
- int *actual_length, unsigned int timeout);
2153
+ int *transferred, unsigned int timeout);
2044
2154
 
2045
2155
  int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,
2046
2156
  unsigned char endpoint, unsigned char *data, int length,
2047
- int *actual_length, unsigned int timeout);
2157
+ int *transferred, unsigned int timeout);
2048
2158
 
2049
2159
  /** \ingroup libusb_desc
2050
2160
  * Retrieve a descriptor from the default control pipe.
@@ -103,6 +103,17 @@ typedef volatile LONG usbi_atomic_t;
103
103
  #define usbi_atomic_inc(a) InterlockedIncrement((a))
104
104
  #define usbi_atomic_dec(a) InterlockedDecrement((a))
105
105
  #else
106
+ #if defined(__HAIKU__) && defined(__GNUC__) && !defined(__clang__)
107
+ /* The Haiku port of libusb has some C++ files and GCC does not define
108
+ * anything in stdatomic.h when compiled in C++11 (only in C++23).
109
+ * This appears to be a bug in gcc's stdatomic.h, and should be fixed either
110
+ * in gcc or in Haiku. Until then, use the gcc builtins. */
111
+ typedef long usbi_atomic_t;
112
+ #define usbi_atomic_load(a) __atomic_load_n((a), __ATOMIC_SEQ_CST)
113
+ #define usbi_atomic_store(a, v) __atomic_store_n((a), (v), __ATOMIC_SEQ_CST)
114
+ #define usbi_atomic_inc(a) __atomic_add_fetch((a), 1, __ATOMIC_SEQ_CST)
115
+ #define usbi_atomic_dec(a) __atomic_sub_fetch((a), 1, __ATOMIC_SEQ_CST)
116
+ #else
106
117
  #include <stdatomic.h>
107
118
  typedef atomic_long usbi_atomic_t;
108
119
  #define usbi_atomic_load(a) atomic_load((a))
@@ -110,6 +121,7 @@ typedef atomic_long usbi_atomic_t;
110
121
  #define usbi_atomic_inc(a) (atomic_fetch_add((a), 1) + 1)
111
122
  #define usbi_atomic_dec(a) (atomic_fetch_add((a), -1) - 1)
112
123
  #endif
124
+ #endif
113
125
 
114
126
  /* Internal abstractions for event handling and thread synchronization */
115
127
  #if defined(PLATFORM_POSIX)
@@ -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
@@ -70,8 +70,8 @@ static struct list_head darwin_cached_devices;
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 */
@@ -694,7 +719,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
694
719
  static void darwin_hotplug_poll (void)
695
720
  {
696
721
  /* 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};
722
+ mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000UL};
698
723
 
699
724
  /* since a kernel thread may notify the IOIterators used for
700
725
  * hotplug notification we can't just clear the iterators.
@@ -1092,7 +1117,7 @@ static IOReturn darwin_request_descriptor (usb_device_t device, UInt8 desc, UInt
1092
1117
  static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
1093
1118
  usb_device_t device = dev->device;
1094
1119
  int retries = 1;
1095
- long delay = 30000; // microseconds
1120
+ long delay = 30000; /* microseconds */
1096
1121
  int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
1097
1122
  int is_open = 0;
1098
1123
  IOReturn ret = 0, ret2;
@@ -1242,17 +1267,18 @@ static bool get_device_port (io_service_t service, UInt8 *port) {
1242
1267
 
1243
1268
  /* Returns 1 on success, 0 on failure. */
1244
1269
  static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) {
1245
- IOReturn kresult;
1246
- io_service_t parent;
1247
-
1248
1270
  /* 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) {
1271
+ io_service_t parent = service;
1272
+ do {
1273
+ IOReturn kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent);
1274
+ if (kresult != kIOReturnSuccess) {
1275
+ break;
1276
+ }
1251
1277
  if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) {
1252
1278
  /* Success */
1253
1279
  return true;
1254
1280
  }
1255
- }
1281
+ } while (true);
1256
1282
 
1257
1283
  /* We ran out of parents */
1258
1284
  return false;
@@ -1361,6 +1387,8 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
1361
1387
 
1362
1388
  usbi_mutex_unlock(&darwin_cached_devices_mutex);
1363
1389
 
1390
+ assert((ret == LIBUSB_SUCCESS) ? (*cached_out != NULL) : true);
1391
+
1364
1392
  return ret;
1365
1393
  }
1366
1394
 
@@ -1434,6 +1462,9 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
1434
1462
  #endif
1435
1463
  #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
1436
1464
  case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
1465
+ #endif
1466
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
1467
+ case kUSBDeviceSpeedSuperPlusBy2: dev->speed = LIBUSB_SPEED_SUPER_PLUS_X2; break;
1437
1468
  #endif
1438
1469
  default:
1439
1470
  usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
@@ -1471,6 +1502,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
1471
1502
 
1472
1503
  while ((service = IOIteratorNext (deviceIterator))) {
1473
1504
  ret = darwin_get_cached_device (ctx, service, &cached_device, &old_session_id);
1505
+ assert((ret >= 0) ? (cached_device != NULL) : true);
1474
1506
  if (ret < 0 || !cached_device->can_enumerate) {
1475
1507
  continue;
1476
1508
  }
@@ -1868,9 +1900,10 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin
1868
1900
  if (kresult != kIOReturnSuccess)
1869
1901
  usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
1870
1902
 
1871
- kresult = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
1872
- if (kresult != kIOReturnSuccess)
1873
- usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
1903
+ ULONG refCount = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
1904
+ if (refCount != 0) {
1905
+ usbi_warn (HANDLE_CTX (dev_handle), "Release final refCount: %u", refCount);
1906
+ }
1874
1907
 
1875
1908
  IOINTERFACE(cInterface) = NULL;
1876
1909
 
@@ -1972,7 +2005,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
1972
2005
  return darwin_to_libusb (kresult);
1973
2006
  }
1974
2007
 
1975
- static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config,
2008
+ static int darwin_restore_state (struct libusb_device_handle *dev_handle, uint8_t active_config,
1976
2009
  unsigned long claimed_interfaces) {
1977
2010
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1978
2011
  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
@@ -2037,7 +2070,7 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
2037
2070
  static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, bool capture) {
2038
2071
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
2039
2072
  unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
2040
- int8_t active_config = dpriv->active_config;
2073
+ uint8_t active_config = dpriv->active_config;
2041
2074
  UInt32 options = 0;
2042
2075
  IOUSBDeviceDescriptor descriptor;
2043
2076
  IOUSBConfigurationDescriptorPtr cached_configuration;
@@ -2098,10 +2131,11 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
2098
2131
  struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
2099
2132
  nanosleep (&delay, NULL);
2100
2133
 
2101
- struct timespec now;
2134
+ struct timespec now, delta;
2102
2135
  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;
2136
+ 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;
2105
2139
 
2106
2140
  if (elapsed_us >= DARWIN_REENUMERATE_TIMEOUT_US) {
2107
2141
  usbi_err (ctx, "darwin/reenumerate_device: timeout waiting for reenumerate");
@@ -2113,7 +2147,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
2113
2147
  /* compare descriptors */
2114
2148
  usbi_dbg (ctx, "darwin/reenumerate_device: checking whether descriptors changed");
2115
2149
 
2116
- if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
2150
+ if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor)) != 0) {
2117
2151
  /* device descriptor changed. need to return not found. */
2118
2152
  usbi_dbg (ctx, "darwin/reenumerate_device: device descriptor changed");
2119
2153
  return LIBUSB_ERROR_NOT_FOUND;
@@ -2121,7 +2155,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
2121
2155
 
2122
2156
  for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
2123
2157
  (void) (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
2124
- if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
2158
+ if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i])) != 0) {
2125
2159
  usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
2126
2160
  return LIBUSB_ERROR_NOT_FOUND;
2127
2161
  }
@@ -2150,7 +2184,7 @@ static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
2150
2184
  ret = darwin_reenumerate_device (dev_handle, false);
2151
2185
  if ((ret == LIBUSB_SUCCESS || ret == LIBUSB_ERROR_NOT_FOUND) && dpriv->capture_count > 0) {
2152
2186
  int capture_count;
2153
- int8_t active_config = dpriv->active_config;
2187
+ uint8_t active_config = dpriv->active_config;
2154
2188
  unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
2155
2189
 
2156
2190
  /* save old capture_count */
@@ -2399,10 +2433,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
2399
2433
 
2400
2434
  if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
2401
2435
  /* Full speed */
2402
- cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1));
2436
+ cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1));
2403
2437
  else
2404
2438
  /* High/super speed */
2405
- cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)) / 8;
2439
+ cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1)) / 8;
2406
2440
 
2407
2441
  if (kresult != kIOReturnSuccess) {
2408
2442
  usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
@@ -2691,7 +2725,8 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
2691
2725
 
2692
2726
  /* find the minimum number of supported streams on the endpoint list */
2693
2727
  for (i = 0 ; i < num_endpoints ; ++i) {
2694
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) {
2728
+ rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
2729
+ if (0 != rc) {
2695
2730
  return rc;
2696
2731
  }
2697
2732
 
@@ -2724,7 +2759,8 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
2724
2759
  int rc;
2725
2760
 
2726
2761
  for (int i = 0 ; i < num_endpoints ; ++i) {
2727
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface)))
2762
+ rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
2763
+ if (0 != rc)
2728
2764
  return rc;
2729
2765
 
2730
2766
  (*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams);
@@ -2888,15 +2924,26 @@ const struct usbi_os_backend usbi_backend = {
2888
2924
  .caps = USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
2889
2925
  .init = darwin_init,
2890
2926
  .exit = darwin_exit,
2891
- .get_active_config_descriptor = darwin_get_active_config_descriptor,
2892
- .get_config_descriptor = darwin_get_config_descriptor,
2927
+ .set_option = NULL,
2928
+ .get_device_list = NULL,
2893
2929
  .hotplug_poll = darwin_hotplug_poll,
2894
-
2930
+ .wrap_sys_device = NULL,
2895
2931
  .open = darwin_open,
2896
2932
  .close = darwin_close,
2933
+ .get_active_config_descriptor = darwin_get_active_config_descriptor,
2934
+ .get_config_descriptor = darwin_get_config_descriptor,
2935
+ .get_config_descriptor_by_value = NULL,
2897
2936
  .get_configuration = darwin_get_configuration,
2898
2937
  .set_configuration = darwin_set_configuration,
2899
2938
 
2939
+ #if MAX_INTERFACE_VERSION >= 700
2940
+ .claim_interface = darwin_capture_claim_interface,
2941
+ .release_interface = darwin_capture_release_interface,
2942
+ #else
2943
+ .claim_interface = darwin_claim_interface,
2944
+ .release_interface = darwin_release_interface,
2945
+ #endif
2946
+
2900
2947
  .set_interface_altsetting = darwin_set_interface_altsetting,
2901
2948
  .clear_halt = darwin_clear_halt,
2902
2949
  .reset_device = darwin_reset_device,
@@ -2906,25 +2953,24 @@ const struct usbi_os_backend usbi_backend = {
2906
2953
  .free_streams = darwin_free_streams,
2907
2954
  #endif
2908
2955
 
2956
+ .dev_mem_alloc = NULL,
2957
+ .dev_mem_free = NULL,
2909
2958
  .kernel_driver_active = darwin_kernel_driver_active,
2910
2959
 
2911
2960
  #if MAX_INTERFACE_VERSION >= 700
2912
2961
  .detach_kernel_driver = darwin_detach_kernel_driver,
2913
2962
  .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
2963
  #endif
2920
2964
 
2921
2965
  .destroy_device = darwin_destroy_device,
2922
2966
 
2923
2967
  .submit_transfer = darwin_submit_transfer,
2924
2968
  .cancel_transfer = darwin_cancel_transfer,
2925
-
2969
+ .clear_transfer_priv = NULL,
2970
+ .handle_events = NULL,
2926
2971
  .handle_transfer_completion = darwin_handle_transfer_completion,
2927
2972
 
2973
+ .context_priv_size = 0,
2928
2974
  .device_priv_size = sizeof(struct darwin_device_priv),
2929
2975
  .device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
2930
2976
  .transfer_priv_size = sizeof(struct darwin_transfer_priv),
@@ -586,12 +586,17 @@ unsigned long getDeviceSessionId(val& web_usb_device) {
586
586
  }
587
587
 
588
588
  val getDeviceList(libusb_context* ctx, discovered_devs** devs) {
589
+ // Check if browser supports USB
590
+ val navigator_usb = val::global("navigator")["usb"];
591
+ if (navigator_usb == val::undefined()) {
592
+ co_return (int) LIBUSB_ERROR_NOT_SUPPORTED;
593
+ }
589
594
  // C++ equivalent of `await navigator.usb.getDevices()`. Note: at this point
590
595
  // we must already have some devices exposed - caller must have called
591
596
  // `await navigator.usb.requestDevice(...)` in response to user interaction
592
597
  // before going to LibUSB. Otherwise this list will be empty.
593
598
  auto web_usb_devices =
594
- co_await_try(val::global("navigator")["usb"].call<val>("getDevices"));
599
+ co_await_try(navigator_usb.call<val>("getDevices"));
595
600
  for (auto&& web_usb_device : web_usb_devices) {
596
601
  auto session_id = getDeviceSessionId(web_usb_device);
597
602
 
@@ -844,7 +849,7 @@ int em_handle_transfer_completion(usbi_transfer* itransfer) {
844
849
  #pragma clang diagnostic ignored "-Wmissing-field-initializers"
845
850
  extern "C" const usbi_os_backend usbi_backend = {
846
851
  .name = "Emscripten + WebUSB backend",
847
- .caps = LIBUSB_CAP_HAS_CAPABILITY,
852
+ .caps = 0,
848
853
  .get_device_list = em_get_device_list,
849
854
  .open = em_open,
850
855
  .close = em_close,
@@ -256,11 +256,11 @@ int usbi_wait_for_events(struct libusb_context *ctx,
256
256
 
257
257
  usbi_dbg(ctx, "poll() %u fds with timeout in %dms", (unsigned int)nfds, timeout_ms);
258
258
  #ifdef __EMSCRIPTEN__
259
- // Emscripten's poll doesn't actually block, so we need to use an out-of-band
260
- // waiting signal.
259
+ /* Emscripten's poll doesn't actually block, so we need to use an
260
+ * out-of-band waiting signal. */
261
261
  em_libusb_wait(&ctx->event.has_event, 0, timeout_ms);
262
- // Emscripten ignores timeout_ms, but set it to 0 for future-proofing in case
263
- // they ever implement real poll.
262
+ /* Emscripten ignores timeout_ms, but set it to 0 for future-proofing
263
+ * in case they ever implement real poll. */
264
264
  timeout_ms = 0;
265
265
  #endif
266
266
  num_ready = poll(fds, nfds, timeout_ms);