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
@@ -30,49 +30,18 @@
30
30
  * for detected devices
31
31
  */
32
32
 
33
- #define READ_LE16(p) ((uint16_t) \
34
- (((uint16_t)((p)[1]) << 8) | \
35
- ((uint16_t)((p)[0]))))
36
-
37
- #define READ_LE32(p) ((uint32_t) \
38
- (((uint32_t)((p)[3]) << 24) | \
39
- ((uint32_t)((p)[2]) << 16) | \
40
- ((uint32_t)((p)[1]) << 8) | \
41
- ((uint32_t)((p)[0]))))
42
-
43
- static void parse_descriptor(const void *source, const char *descriptor, void *dest)
33
+ static inline uint16_t ReadLittleEndian16(const uint8_t p[2])
44
34
  {
45
- const uint8_t *sp = source;
46
- uint8_t *dp = dest;
47
- char field_type;
48
-
49
- while (*descriptor) {
50
- field_type = *descriptor++;
51
- switch (field_type) {
52
- case 'b': /* 8-bit byte */
53
- *dp++ = *sp++;
54
- break;
55
- case 'w': /* 16-bit word, convert from little endian to CPU */
56
- dp += ((uintptr_t)dp & 1); /* Align to 16-bit word boundary */
57
-
58
- *((uint16_t *)dp) = READ_LE16(sp);
59
- sp += 2;
60
- dp += 2;
61
- break;
62
- case 'd': /* 32-bit word, convert from little endian to CPU */
63
- dp += 4 - ((uintptr_t)dp & 3); /* Align to 32-bit word boundary */
35
+ return (uint16_t)((uint16_t)p[1] << 8 |
36
+ (uint16_t)p[0]);
37
+ }
64
38
 
65
- *((uint32_t *)dp) = READ_LE32(sp);
66
- sp += 4;
67
- dp += 4;
68
- break;
69
- case 'u': /* 16 byte UUID */
70
- memcpy(dp, sp, 16);
71
- sp += 16;
72
- dp += 16;
73
- break;
74
- }
75
- }
39
+ static inline uint32_t ReadLittleEndian32(const uint8_t p[4])
40
+ {
41
+ return (uint32_t)((uint32_t)p[3] << 24 |
42
+ (uint32_t)p[2] << 16 |
43
+ (uint32_t)p[1] << 8 |
44
+ (uint32_t)p[0]);
76
45
  }
77
46
 
78
47
  static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
@@ -87,7 +56,6 @@ static int parse_endpoint(struct libusb_context *ctx,
87
56
  const uint8_t *begin;
88
57
  void *extra;
89
58
  int parsed = 0;
90
- int len;
91
59
 
92
60
  if (size < DESC_HEADER_LENGTH) {
93
61
  usbi_err(ctx, "short endpoint descriptor read %d/%d",
@@ -109,10 +77,16 @@ static int parse_endpoint(struct libusb_context *ctx,
109
77
  return parsed;
110
78
  }
111
79
 
112
- if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE)
113
- parse_descriptor(buffer, "bbbbwbbb", endpoint);
114
- else
115
- parse_descriptor(buffer, "bbbbwb", endpoint);
80
+ endpoint->bLength = buffer[0];
81
+ endpoint->bDescriptorType = buffer[1];
82
+ endpoint->bEndpointAddress = buffer[2];
83
+ endpoint->bmAttributes = buffer[3];
84
+ endpoint->wMaxPacketSize = ReadLittleEndian16(&buffer[4]);
85
+ endpoint->bInterval = buffer[6];
86
+ if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE) {
87
+ endpoint->bRefresh = buffer[7];
88
+ endpoint->bSynchAddress = buffer[8];
89
+ }
116
90
 
117
91
  buffer += header->bLength;
118
92
  size -= header->bLength;
@@ -148,7 +122,7 @@ static int parse_endpoint(struct libusb_context *ctx,
148
122
 
149
123
  /* Copy any unknown descriptors into a storage area for drivers */
150
124
  /* to later parse */
151
- len = (int)(buffer - begin);
125
+ ptrdiff_t len = buffer - begin;
152
126
  if (len <= 0)
153
127
  return parsed;
154
128
 
@@ -156,9 +130,9 @@ static int parse_endpoint(struct libusb_context *ctx,
156
130
  if (!extra)
157
131
  return LIBUSB_ERROR_NO_MEM;
158
132
 
159
- memcpy(extra, begin, len);
133
+ memcpy(extra, begin, (size_t)len);
160
134
  endpoint->extra = extra;
161
- endpoint->extra_length = len;
135
+ endpoint->extra_length = (int)len;
162
136
 
163
137
  return parsed;
164
138
  }
@@ -191,7 +165,6 @@ static void clear_interface(struct libusb_interface *usb_interface)
191
165
  static int parse_interface(libusb_context *ctx,
192
166
  struct libusb_interface *usb_interface, const uint8_t *buffer, int size)
193
167
  {
194
- int len;
195
168
  int r;
196
169
  int parsed = 0;
197
170
  int interface_number = -1;
@@ -212,7 +185,15 @@ static int parse_interface(libusb_context *ctx,
212
185
  usb_interface->altsetting = altsetting;
213
186
 
214
187
  ifp = altsetting + usb_interface->num_altsetting;
215
- parse_descriptor(buffer, "bbbbbbbbb", ifp);
188
+ ifp->bLength = buffer[0];
189
+ ifp->bDescriptorType = buffer[1];
190
+ ifp->bInterfaceNumber = buffer[2];
191
+ ifp->bAlternateSetting = buffer[3];
192
+ ifp->bNumEndpoints = buffer[4];
193
+ ifp->bInterfaceClass = buffer[5];
194
+ ifp->bInterfaceSubClass = buffer[6];
195
+ ifp->bInterfaceProtocol = buffer[7];
196
+ ifp->iInterface = buffer[8];
216
197
  if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
217
198
  usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
218
199
  ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
@@ -277,7 +258,7 @@ static int parse_interface(libusb_context *ctx,
277
258
 
278
259
  /* Copy any unknown descriptors into a storage area for */
279
260
  /* drivers to later parse */
280
- len = (int)(buffer - begin);
261
+ ptrdiff_t len = buffer - begin;
281
262
  if (len > 0) {
282
263
  void *extra = malloc((size_t)len);
283
264
 
@@ -286,9 +267,9 @@ static int parse_interface(libusb_context *ctx,
286
267
  goto err;
287
268
  }
288
269
 
289
- memcpy(extra, begin, len);
270
+ memcpy(extra, begin, (size_t)len);
290
271
  ifp->extra = extra;
291
- ifp->extra_length = len;
272
+ ifp->extra_length = (int)len;
292
273
  }
293
274
 
294
275
  if (ifp->bNumEndpoints > 0) {
@@ -358,7 +339,14 @@ static int parse_configuration(struct libusb_context *ctx,
358
339
  return LIBUSB_ERROR_IO;
359
340
  }
360
341
 
361
- parse_descriptor(buffer, "bbwbbbbb", config);
342
+ config->bLength = buffer[0];
343
+ config->bDescriptorType = buffer[1];
344
+ config->wTotalLength = ReadLittleEndian16(&buffer[2]);
345
+ config->bNumInterfaces = buffer[4];
346
+ config->bConfigurationValue = buffer[5];
347
+ config->iConfiguration = buffer[6];
348
+ config->bmAttributes = buffer[7];
349
+ config->MaxPower = buffer[8];
362
350
  if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
363
351
  usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
364
352
  config->bDescriptorType, LIBUSB_DT_CONFIG);
@@ -385,7 +373,6 @@ static int parse_configuration(struct libusb_context *ctx,
385
373
  size -= config->bLength;
386
374
 
387
375
  for (i = 0; i < config->bNumInterfaces; i++) {
388
- int len;
389
376
  const uint8_t *begin;
390
377
 
391
378
  /* Skip over the rest of the Class Specific or Vendor */
@@ -421,22 +408,22 @@ static int parse_configuration(struct libusb_context *ctx,
421
408
 
422
409
  /* Copy any unknown descriptors into a storage area for */
423
410
  /* drivers to later parse */
424
- len = (int)(buffer - begin);
411
+ ptrdiff_t len = buffer - begin;
425
412
  if (len > 0) {
426
413
  uint8_t *extra = realloc((void *)config->extra,
427
- (size_t)(config->extra_length + len));
414
+ (size_t)(config->extra_length) + (size_t)len);
428
415
 
429
416
  if (!extra) {
430
417
  r = LIBUSB_ERROR_NO_MEM;
431
418
  goto err;
432
419
  }
433
420
 
434
- memcpy(extra + config->extra_length, begin, len);
421
+ memcpy(extra + config->extra_length, begin, (size_t)len);
435
422
  config->extra = extra;
436
- config->extra_length += len;
423
+ config->extra_length += (int)len;
437
424
  }
438
425
 
439
- r = parse_interface(ctx, usb_interface + i, buffer, size);
426
+ r = parse_interface(ctx, usb_interface + i, buffer, (int)size);
440
427
  if (r < 0)
441
428
  goto err;
442
429
  if (r == 0) {
@@ -707,14 +694,14 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
707
694
  const struct libusb_endpoint_descriptor *endpoint,
708
695
  struct libusb_ss_endpoint_companion_descriptor **ep_comp)
709
696
  {
710
- struct usbi_descriptor_header *header;
697
+ const struct usbi_descriptor_header *header;
711
698
  const uint8_t *buffer = endpoint->extra;
712
699
  int size = endpoint->extra_length;
713
700
 
714
701
  *ep_comp = NULL;
715
702
 
716
703
  while (size >= DESC_HEADER_LENGTH) {
717
- header = (struct usbi_descriptor_header *)buffer;
704
+ header = (const struct usbi_descriptor_header *)buffer;
718
705
  if (header->bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
719
706
  if (header->bLength < DESC_HEADER_LENGTH) {
720
707
  usbi_err(ctx, "invalid descriptor length %u",
@@ -737,7 +724,11 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
737
724
  *ep_comp = malloc(sizeof(**ep_comp));
738
725
  if (!*ep_comp)
739
726
  return LIBUSB_ERROR_NO_MEM;
740
- parse_descriptor(buffer, "bbbbw", *ep_comp);
727
+ (*ep_comp)->bLength = buffer[0];
728
+ (*ep_comp)->bDescriptorType = buffer[1];
729
+ (*ep_comp)->bMaxBurst = buffer[2];
730
+ (*ep_comp)->bmAttributes = buffer[3];
731
+ (*ep_comp)->wBytesPerInterval = ReadLittleEndian16(&buffer[4]);
741
732
  return LIBUSB_SUCCESS;
742
733
  }
743
734
  return LIBUSB_ERROR_NOT_FOUND;
@@ -790,7 +781,10 @@ static int parse_bos(struct libusb_context *ctx,
790
781
  if (!_bos)
791
782
  return LIBUSB_ERROR_NO_MEM;
792
783
 
793
- parse_descriptor(buffer, "bbwb", _bos);
784
+ _bos->bLength = buffer[0];
785
+ _bos->bDescriptorType = buffer[1];
786
+ _bos->wTotalLength = ReadLittleEndian16(&buffer[2]);
787
+ _bos->bNumDeviceCaps = buffer[4];
794
788
  buffer += _bos->bLength;
795
789
  size -= _bos->bLength;
796
790
 
@@ -910,7 +904,7 @@ void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
910
904
  *
911
905
  * \param ctx the context to operate on, or NULL for the default context
912
906
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
913
- * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
907
+ * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION
914
908
  * LIBUSB_BT_USB_2_0_EXTENSION
915
909
  * \param usb_2_0_extension output location for the USB 2.0 Extension
916
910
  * descriptor. Only valid if 0 was returned. Must be freed with
@@ -940,7 +934,10 @@ int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
940
934
  if (!_usb_2_0_extension)
941
935
  return LIBUSB_ERROR_NO_MEM;
942
936
 
943
- parse_descriptor(dev_cap, "bbbd", _usb_2_0_extension);
937
+ _usb_2_0_extension->bLength = dev_cap->bLength;
938
+ _usb_2_0_extension->bDescriptorType = dev_cap->bDescriptorType;
939
+ _usb_2_0_extension->bDevCapabilityType = dev_cap->bDevCapabilityType;
940
+ _usb_2_0_extension->bmAttributes = ReadLittleEndian32(dev_cap->dev_capability_data);
944
941
 
945
942
  *usb_2_0_extension = _usb_2_0_extension;
946
943
  return LIBUSB_SUCCESS;
@@ -965,7 +962,7 @@ void API_EXPORTED libusb_free_usb_2_0_extension_descriptor(
965
962
  *
966
963
  * \param ctx the context to operate on, or NULL for the default context
967
964
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
968
- * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
965
+ * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
969
966
  * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
970
967
  * \param ss_usb_device_cap output location for the SuperSpeed USB Device
971
968
  * Capability descriptor. Only valid if 0 was returned. Must be freed with
@@ -995,12 +992,150 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
995
992
  if (!_ss_usb_device_cap)
996
993
  return LIBUSB_ERROR_NO_MEM;
997
994
 
998
- parse_descriptor(dev_cap, "bbbbwbbw", _ss_usb_device_cap);
995
+ _ss_usb_device_cap->bLength = dev_cap->bLength;
996
+ _ss_usb_device_cap->bDescriptorType = dev_cap->bDescriptorType;
997
+ _ss_usb_device_cap->bDevCapabilityType = dev_cap->bDevCapabilityType;
998
+ _ss_usb_device_cap->bmAttributes = dev_cap->dev_capability_data[0];
999
+ _ss_usb_device_cap->wSpeedSupported = ReadLittleEndian16(&dev_cap->dev_capability_data[1]);
1000
+ _ss_usb_device_cap->bFunctionalitySupport = dev_cap->dev_capability_data[3];
1001
+ _ss_usb_device_cap->bU1DevExitLat = dev_cap->dev_capability_data[4];
1002
+ _ss_usb_device_cap->bU2DevExitLat = ReadLittleEndian16(&dev_cap->dev_capability_data[5]);
999
1003
 
1000
1004
  *ss_usb_device_cap = _ss_usb_device_cap;
1001
1005
  return LIBUSB_SUCCESS;
1002
1006
  }
1003
1007
 
1008
+ /// @cond DEV
1009
+ /** \internal \ingroup libusb_desc
1010
+ * We use this private struct only to parse a SuperSpeedPlus device capability
1011
+ * descriptor according to section 9.6.2.5 of the USB 3.1 specification.
1012
+ * We don't expose it.
1013
+ */
1014
+ struct internal_ssplus_capability_descriptor {
1015
+ /** The length of the descriptor. Must be equal to LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE */
1016
+ uint8_t bLength;
1017
+
1018
+ /** The type of the descriptor */
1019
+ uint8_t bDescriptorType;
1020
+
1021
+ /** Must be equal to LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY */
1022
+ uint8_t bDevCapabilityType;
1023
+
1024
+ /** Unused */
1025
+ uint8_t bReserved;
1026
+
1027
+ /** Contains the number of SublinkSpeedIDs */
1028
+ uint32_t bmAttributes;
1029
+
1030
+ /** Contains the ssid, minRxLaneCount, and minTxLaneCount */
1031
+ uint16_t wFunctionalitySupport;
1032
+
1033
+ /** Unused */
1034
+ uint16_t wReserved;
1035
+ };
1036
+ /// @endcond
1037
+
1038
+ /** \ingroup libusb_desc
1039
+ * Get a SuperSpeedPlus USB Device Capability descriptor
1040
+ *
1041
+ * Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B
1042
+ *
1043
+ * \param ctx the context to operate on, or NULL for the default context
1044
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1045
+ * \ref libusb_bos_type::LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY
1046
+ * LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY
1047
+ * \param ssplus_usb_device_cap output location for the SuperSpeedPlus USB Device
1048
+ * Capability descriptor. Only valid if 0 was returned. Must be freed with
1049
+ * libusb_free_ssplus_usb_device_capability_descriptor() after use.
1050
+ * \returns 0 on success
1051
+ * \returns a LIBUSB_ERROR code on error
1052
+ */
1053
+ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
1054
+ libusb_context *ctx,
1055
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
1056
+ struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap)
1057
+ {
1058
+ struct libusb_ssplus_usb_device_capability_descriptor *_ssplus_cap;
1059
+
1060
+ /* Use a private struct to reuse our descriptor parsing system. */
1061
+ struct internal_ssplus_capability_descriptor parsedDescriptor;
1062
+
1063
+ /* Some size/type checks to make sure everything is in order */
1064
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY) {
1065
+ usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
1066
+ dev_cap->bDevCapabilityType,
1067
+ LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY);
1068
+ return LIBUSB_ERROR_INVALID_PARAM;
1069
+ } else if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE) {
1070
+ usbi_err(ctx, "short dev-cap descriptor read %u/%d",
1071
+ dev_cap->bLength, LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE);
1072
+ return LIBUSB_ERROR_IO;
1073
+ }
1074
+
1075
+ const uint8_t* dev_capability_data = dev_cap->dev_capability_data;
1076
+ parsedDescriptor.bLength = dev_cap->bLength;
1077
+ parsedDescriptor.bDescriptorType = dev_cap->bDescriptorType;
1078
+ parsedDescriptor.bDevCapabilityType = dev_cap->bDevCapabilityType;
1079
+ parsedDescriptor.bReserved = dev_capability_data[0];
1080
+ parsedDescriptor.bmAttributes = ReadLittleEndian32(&dev_capability_data[1]);
1081
+ parsedDescriptor.wFunctionalitySupport = ReadLittleEndian16(&dev_capability_data[5]);
1082
+ parsedDescriptor.wReserved = ReadLittleEndian16(&dev_capability_data[7]);
1083
+
1084
+ uint8_t numSublikSpeedAttributes = (parsedDescriptor.bmAttributes & 0xF) + 1;
1085
+ _ssplus_cap = malloc(sizeof(struct libusb_ssplus_usb_device_capability_descriptor) + numSublikSpeedAttributes * sizeof(struct libusb_ssplus_sublink_attribute));
1086
+ if (!_ssplus_cap)
1087
+ return LIBUSB_ERROR_NO_MEM;
1088
+
1089
+ /* Parse bmAttributes */
1090
+ _ssplus_cap->numSublinkSpeedAttributes = numSublikSpeedAttributes;
1091
+ _ssplus_cap->numSublinkSpeedIDs = ((parsedDescriptor.bmAttributes & 0xF0) >> 4) + 1;
1092
+
1093
+ /* Parse wFunctionalitySupport */
1094
+ _ssplus_cap->ssid = parsedDescriptor.wFunctionalitySupport & 0xF;
1095
+ _ssplus_cap->minRxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0x0F00) >> 8;
1096
+ _ssplus_cap->minTxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0xF000) >> 12;
1097
+
1098
+ /* Check that we have enough to read all the sublink attributes */
1099
+ if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE + _ssplus_cap->numSublinkSpeedAttributes * sizeof(uint32_t)) {
1100
+ usbi_err(ctx, "short ssplus capability descriptor, unable to read sublinks: Not enough data");
1101
+ return LIBUSB_ERROR_IO;
1102
+ }
1103
+
1104
+ /* Read the attributes */
1105
+ uint8_t* base = ((uint8_t*)dev_cap) + LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE;
1106
+ for(uint8_t i = 0 ; i < _ssplus_cap->numSublinkSpeedAttributes ; i++) {
1107
+ uint32_t attr = ReadLittleEndian32(base + i * sizeof(uint32_t));
1108
+ _ssplus_cap->sublinkSpeedAttributes[i].ssid = attr & 0x0f;
1109
+ _ssplus_cap->sublinkSpeedAttributes[i].mantissa = attr >> 16;
1110
+ _ssplus_cap->sublinkSpeedAttributes[i].exponent = (attr >> 4) & 0x3 ;
1111
+ _ssplus_cap->sublinkSpeedAttributes[i].type = attr & 0x40 ? LIBUSB_SSPLUS_ATTR_TYPE_ASYM : LIBUSB_SSPLUS_ATTR_TYPE_SYM;
1112
+ _ssplus_cap->sublinkSpeedAttributes[i].direction = attr & 0x80 ? LIBUSB_SSPLUS_ATTR_DIR_TX : LIBUSB_SSPLUS_ATTR_DIR_RX;
1113
+ _ssplus_cap->sublinkSpeedAttributes[i].protocol = attr & 0x4000 ? LIBUSB_SSPLUS_ATTR_PROT_SSPLUS: LIBUSB_SSPLUS_ATTR_PROT_SS;
1114
+ }
1115
+
1116
+ *ssplus_usb_device_cap = _ssplus_cap;
1117
+ return LIBUSB_SUCCESS;
1118
+ }
1119
+
1120
+ /** \ingroup libusb_desc
1121
+ * Free a SuperSpeedPlus USB Device Capability descriptor obtained from
1122
+ * libusb_get_ssplus_usb_device_capability_descriptor().
1123
+ * It is safe to call this function with a NULL ssplus_usb_device_cap
1124
+ * parameter, in which case the function simply returns.
1125
+ *
1126
+ * Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B
1127
+ *
1128
+ * \param ssplus_usb_device_cap the SuperSpeedPlus USB Device Capability descriptor
1129
+ * to free
1130
+ */
1131
+ void API_EXPORTED libusb_free_ssplus_usb_device_capability_descriptor(
1132
+ struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap)
1133
+ {
1134
+ free(ssplus_usb_device_cap);
1135
+ }
1136
+
1137
+
1138
+
1004
1139
  /** \ingroup libusb_desc
1005
1140
  * Free a SuperSpeed USB Device Capability descriptor obtained from
1006
1141
  * libusb_get_ss_usb_device_capability_descriptor().
@@ -1021,7 +1156,7 @@ void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
1021
1156
  *
1022
1157
  * \param ctx the context to operate on, or NULL for the default context
1023
1158
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1024
- * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
1159
+ * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID
1025
1160
  * LIBUSB_BT_CONTAINER_ID
1026
1161
  * \param container_id output location for the Container ID descriptor.
1027
1162
  * Only valid if 0 was returned. Must be freed with
@@ -1050,7 +1185,11 @@ int API_EXPORTED libusb_get_container_id_descriptor(libusb_context *ctx,
1050
1185
  if (!_container_id)
1051
1186
  return LIBUSB_ERROR_NO_MEM;
1052
1187
 
1053
- parse_descriptor(dev_cap, "bbbbu", _container_id);
1188
+ _container_id->bLength = dev_cap->bLength;
1189
+ _container_id->bDescriptorType = dev_cap->bDescriptorType;
1190
+ _container_id->bDevCapabilityType = dev_cap->bDevCapabilityType;
1191
+ _container_id->bReserved = dev_cap->dev_capability_data[0];
1192
+ memcpy(_container_id->ContainerID, &dev_cap->dev_capability_data[1], 16);
1054
1193
 
1055
1194
  *container_id = _container_id;
1056
1195
  return LIBUSB_SUCCESS;
@@ -1077,7 +1216,7 @@ void API_EXPORTED libusb_free_container_id_descriptor(
1077
1216
  *
1078
1217
  * \param ctx the context to operate on, or NULL for the default context
1079
1218
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1080
- * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
1219
+ * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
1081
1220
  * LIBUSB_BT_PLATFORM_DESCRIPTOR
1082
1221
  * \param platform_descriptor output location for the Platform descriptor.
1083
1222
  * Only valid if 0 was returned. Must be freed with
@@ -1106,13 +1245,17 @@ int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx,
1106
1245
  if (!_platform_descriptor)
1107
1246
  return LIBUSB_ERROR_NO_MEM;
1108
1247
 
1109
- parse_descriptor(dev_cap, "bbbbu", _platform_descriptor);
1248
+ _platform_descriptor->bLength = dev_cap->bLength;
1249
+ _platform_descriptor->bDescriptorType = dev_cap->bDescriptorType;
1250
+ _platform_descriptor->bDevCapabilityType = dev_cap->bDevCapabilityType;
1251
+ _platform_descriptor->bReserved = dev_cap->dev_capability_data[0];
1252
+ memcpy(_platform_descriptor->PlatformCapabilityUUID, &(dev_cap->dev_capability_data[1]), 16);
1110
1253
 
1111
- /* Capability data is located after reserved byte and 128-bit UUID */
1254
+ /* Capability data is located after reserved byte and 16 byte UUID */
1112
1255
  uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16;
1113
1256
 
1114
1257
  /* Capability data length is total descriptor length minus initial fields */
1115
- size_t capability_data_length = _platform_descriptor->bLength - (16 + 4);
1258
+ size_t capability_data_length = dev_cap->bLength - (3 + 1 + 16);
1116
1259
 
1117
1260
  memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length);
1118
1261
 
@@ -1168,9 +1311,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha
1168
1311
  r = libusb_get_string_descriptor(dev_handle, 0, 0, str.buf, 4);
1169
1312
  if (r < 0)
1170
1313
  return r;
1171
- else if (r != 4 || str.desc.bLength < 4)
1172
- return LIBUSB_ERROR_IO;
1173
- else if (str.desc.bDescriptorType != LIBUSB_DT_STRING)
1314
+ else if (r != 4 || str.desc.bLength < 4 || str.desc.bDescriptorType != LIBUSB_DT_STRING)
1174
1315
  return LIBUSB_ERROR_IO;
1175
1316
  else if (str.desc.bLength & 1)
1176
1317
  usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for language ID string descriptor", str.desc.bLength);
@@ -1179,9 +1320,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha
1179
1320
  r = libusb_get_string_descriptor(dev_handle, desc_index, langid, str.buf, sizeof(str.buf));
1180
1321
  if (r < 0)
1181
1322
  return r;
1182
- else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r)
1183
- return LIBUSB_ERROR_IO;
1184
- else if (str.desc.bDescriptorType != LIBUSB_DT_STRING)
1323
+ else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r || str.desc.bDescriptorType != LIBUSB_DT_STRING)
1185
1324
  return LIBUSB_ERROR_IO;
1186
1325
  else if ((str.desc.bLength & 1) || str.desc.bLength != r)
1187
1326
  usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor (read %d)", str.desc.bLength, r);
@@ -1224,15 +1363,21 @@ static int parse_iad_array(struct libusb_context *ctx,
1224
1363
  return LIBUSB_ERROR_IO;
1225
1364
  }
1226
1365
 
1227
- // First pass: Iterate through desc list, count number of IADs
1366
+ /* First pass: Iterate through desc list, count number of IADs */
1228
1367
  iad_array->length = 0;
1229
1368
  while (consumed < size) {
1230
- parse_descriptor(buf, "bb", &header);
1231
- if (header.bLength < 2) {
1369
+ header.bLength = buf[0];
1370
+ header.bDescriptorType = buf[1];
1371
+ if (header.bLength < DESC_HEADER_LENGTH) {
1232
1372
  usbi_err(ctx, "invalid descriptor bLength %d",
1233
1373
  header.bLength);
1234
1374
  return LIBUSB_ERROR_IO;
1235
1375
  }
1376
+ else if (header.bLength > size) {
1377
+ usbi_warn(ctx, "short config descriptor read %d/%u",
1378
+ size, header.bLength);
1379
+ return LIBUSB_ERROR_IO;
1380
+ }
1236
1381
  if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
1237
1382
  iad_array->length++;
1238
1383
  buf += header.bLength;
@@ -1241,22 +1386,36 @@ static int parse_iad_array(struct libusb_context *ctx,
1241
1386
 
1242
1387
  iad_array->iad = NULL;
1243
1388
  if (iad_array->length > 0) {
1244
- iad = calloc(iad_array->length, sizeof(*iad));
1389
+ iad = calloc((size_t)iad_array->length, sizeof(*iad));
1245
1390
  if (!iad)
1246
1391
  return LIBUSB_ERROR_NO_MEM;
1247
1392
 
1248
1393
  iad_array->iad = iad;
1249
1394
 
1250
- // Second pass: Iterate through desc list, fill IAD structures
1251
- consumed = 0;
1395
+ /* Second pass: Iterate through desc list, fill IAD structures */
1396
+ int remaining = size;
1252
1397
  i = 0;
1253
- while (consumed < size) {
1254
- parse_descriptor(buffer, "bb", &header);
1255
- if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
1256
- parse_descriptor(buffer, "bbbbbbbb", &iad[i++]);
1257
- buffer += header.bLength;
1258
- consumed += header.bLength;
1259
- }
1398
+ do {
1399
+ header.bLength = buffer[0];
1400
+ header.bDescriptorType = buffer[1];
1401
+ if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION && (remaining >= LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE)) {
1402
+ iad[i].bLength = buffer[0];
1403
+ iad[i].bDescriptorType = buffer[1];
1404
+ iad[i].bFirstInterface = buffer[2];
1405
+ iad[i].bInterfaceCount = buffer[3];
1406
+ iad[i].bFunctionClass = buffer[4];
1407
+ iad[i].bFunctionSubClass = buffer[5];
1408
+ iad[i].bFunctionProtocol = buffer[6];
1409
+ iad[i].iFunction = buffer[7];
1410
+ i++;
1411
+ }
1412
+
1413
+ remaining -= header.bLength;
1414
+ if (remaining < DESC_HEADER_LENGTH) {
1415
+ break;
1416
+ }
1417
+ buffer += header.bLength;
1418
+ } while (1);
1260
1419
  }
1261
1420
 
1262
1421
  return LIBUSB_SUCCESS;
@@ -161,6 +161,27 @@ void usbi_hotplug_init(struct libusb_context *ctx)
161
161
  usbi_atomic_store(&ctx->hotplug_ready, 1);
162
162
  }
163
163
 
164
+ static void usbi_recursively_remove_parents(struct libusb_device *dev, struct libusb_device *next_dev)
165
+ {
166
+ if (dev && dev->parent_dev) {
167
+ if (usbi_atomic_load(&dev->parent_dev->refcnt) == 1) {
168
+ /* The parent was processed before this device in the list and
169
+ * therefore has its ref count already decremented for its own ref.
170
+ * The only remaining counted ref comes from its remaining single child.
171
+ * It will thus be released when its child will be released. So we
172
+ * can remove it from the list. This is safe as parent_dev cannot be
173
+ * equal to next_dev given that we know at this point that it was
174
+ * previously seen in the list. */
175
+ assert (dev->parent_dev != next_dev);
176
+ if (dev->parent_dev->list.next && dev->parent_dev->list.prev) {
177
+ list_del(&dev->parent_dev->list);
178
+ }
179
+ }
180
+
181
+ usbi_recursively_remove_parents(dev->parent_dev, next_dev);
182
+ }
183
+ }
184
+
164
185
  void usbi_hotplug_exit(struct libusb_context *ctx)
165
186
  {
166
187
  struct usbi_hotplug_callback *hotplug_cb, *next_cb;
@@ -193,7 +214,8 @@ void usbi_hotplug_exit(struct libusb_context *ctx)
193
214
  free(msg);
194
215
  }
195
216
 
196
- /* free all discovered devices. due to parent references loop until no devices are freed. */
217
+ usbi_mutex_lock(&ctx->usb_devs_lock); /* hotplug thread might still be processing an already triggered event, possibly accessing this list as well */
218
+ /* free all discovered devices */
197
219
  for_each_device_safe(ctx, dev, next_dev) {
198
220
  /* remove the device from the usb_devs list only if there are no
199
221
  * references held, otherwise leave it on the list so that a
@@ -201,15 +223,12 @@ void usbi_hotplug_exit(struct libusb_context *ctx)
201
223
  if (usbi_atomic_load(&dev->refcnt) == 1) {
202
224
  list_del(&dev->list);
203
225
  }
204
- if (dev->parent_dev && usbi_atomic_load(&dev->parent_dev->refcnt) == 1) {
205
- /* the parent was before this device in the list and will be released.
206
- remove it from the list. this is safe as parent_dev can not be
207
- equal to next_dev. */
208
- assert (dev->parent_dev != next_dev);
209
- list_del(&dev->parent_dev->list);
210
- }
226
+
227
+ usbi_recursively_remove_parents(dev, next_dev);
228
+
211
229
  libusb_unref_device(dev);
212
230
  }
231
+ usbi_mutex_unlock(&ctx->usb_devs_lock);
213
232
 
214
233
  usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
215
234
  }
@@ -1714,6 +1714,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
1714
1714
  flags = transfer->flags;
1715
1715
  transfer->status = status;
1716
1716
  transfer->actual_length = itransfer->transferred;
1717
+ assert(transfer->actual_length >= 0);
1717
1718
  usbi_dbg(ctx, "transfer %p has callback %p",
1718
1719
  (void *) transfer, transfer->callback);
1719
1720
  if (transfer->callback) {
@@ -2044,7 +2045,7 @@ int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
2044
2045
  return 0;
2045
2046
  }
2046
2047
 
2047
- // NB: flying_transfers_lock must be held when calling this
2048
+ /* NB: flying_transfers_lock must be held when calling this */
2048
2049
  static void handle_timeout(struct usbi_transfer *itransfer)
2049
2050
  {
2050
2051
  struct libusb_transfer *transfer =
@@ -2060,7 +2061,7 @@ static void handle_timeout(struct usbi_transfer *itransfer)
2060
2061
  "async cancel failed %d", r);
2061
2062
  }
2062
2063
 
2063
- // NB: flying_transfers_lock must be held when calling this
2064
+ /* NB: flying_transfers_lock must be held when calling this */
2064
2065
  static void handle_timeouts_locked(struct libusb_context *ctx)
2065
2066
  {
2066
2067
  struct timespec systime;
@@ -50,6 +50,8 @@ EXPORTS
50
50
  libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
51
51
  libusb_free_ss_usb_device_capability_descriptor
52
52
  libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
53
+ libusb_free_ssplus_usb_device_capability_descriptor
54
+ libusb_free_ssplus_usb_device_capability_descriptor@4 = libusb_free_ssplus_usb_device_capability_descriptor
53
55
  libusb_free_streams
54
56
  libusb_free_streams@12 = libusb_free_streams
55
57
  libusb_free_transfer
@@ -108,6 +110,8 @@ EXPORTS
108
110
  libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
109
111
  libusb_get_ss_usb_device_capability_descriptor
110
112
  libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
113
+ libusb_get_ssplus_usb_device_capability_descriptor
114
+ libusb_get_ssplus_usb_device_capability_descriptor@12 = libusb_get_ssplus_usb_device_capability_descriptor
111
115
  libusb_get_string_descriptor_ascii
112
116
  libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
113
117
  libusb_get_usb_2_0_extension_descriptor