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
@@ -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)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
  }
@@ -174,6 +148,8 @@ static void clear_interface(struct libusb_interface *usb_interface)
174
148
  usb_interface->altsetting + i;
175
149
 
176
150
  free((void *)ifp->extra);
151
+ ifp->extra = NULL;
152
+ ifp->extra_length = 0;
177
153
  if (ifp->endpoint) {
178
154
  uint8_t j;
179
155
 
@@ -182,16 +158,18 @@ static void clear_interface(struct libusb_interface *usb_interface)
182
158
  ifp->endpoint + j);
183
159
  }
184
160
  free((void *)ifp->endpoint);
161
+ ifp->endpoint = NULL;
162
+ ifp->bNumEndpoints = 0;
185
163
  }
186
164
  }
187
165
  free((void *)usb_interface->altsetting);
188
166
  usb_interface->altsetting = NULL;
167
+ usb_interface->num_altsetting = 0;
189
168
  }
190
169
 
191
170
  static int parse_interface(libusb_context *ctx,
192
171
  struct libusb_interface *usb_interface, const uint8_t *buffer, int size)
193
172
  {
194
- int len;
195
173
  int r;
196
174
  int parsed = 0;
197
175
  int interface_number = -1;
@@ -212,7 +190,15 @@ static int parse_interface(libusb_context *ctx,
212
190
  usb_interface->altsetting = altsetting;
213
191
 
214
192
  ifp = altsetting + usb_interface->num_altsetting;
215
- parse_descriptor(buffer, "bbbbbbbbb", ifp);
193
+ ifp->bLength = buffer[0];
194
+ ifp->bDescriptorType = buffer[1];
195
+ ifp->bInterfaceNumber = buffer[2];
196
+ ifp->bAlternateSetting = buffer[3];
197
+ ifp->bNumEndpoints = buffer[4];
198
+ ifp->bInterfaceClass = buffer[5];
199
+ ifp->bInterfaceSubClass = buffer[6];
200
+ ifp->bInterfaceProtocol = buffer[7];
201
+ ifp->iInterface = buffer[8];
216
202
  if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
217
203
  usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
218
204
  ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
@@ -260,6 +246,10 @@ static int parse_interface(libusb_context *ctx,
260
246
  usbi_warn(ctx,
261
247
  "short extra intf desc read %d/%u",
262
248
  size, header->bLength);
249
+ /* Keep the invariant: bNumEndpoints > 0 implies
250
+ * endpoint != NULL. The endpoint array isn't
251
+ * allocated yet on this early return. */
252
+ ifp->bNumEndpoints = 0;
263
253
  return parsed;
264
254
  }
265
255
 
@@ -277,7 +267,7 @@ static int parse_interface(libusb_context *ctx,
277
267
 
278
268
  /* Copy any unknown descriptors into a storage area for */
279
269
  /* drivers to later parse */
280
- len = (int)(buffer - begin);
270
+ ptrdiff_t len = buffer - begin;
281
271
  if (len > 0) {
282
272
  void *extra = malloc((size_t)len);
283
273
 
@@ -286,9 +276,9 @@ static int parse_interface(libusb_context *ctx,
286
276
  goto err;
287
277
  }
288
278
 
289
- memcpy(extra, begin, len);
279
+ memcpy(extra, begin, (size_t)len);
290
280
  ifp->extra = extra;
291
- ifp->extra_length = len;
281
+ ifp->extra_length = (int)len;
292
282
  }
293
283
 
294
284
  if (ifp->bNumEndpoints > 0) {
@@ -341,7 +331,11 @@ static void clear_configuration(struct libusb_config_descriptor *config)
341
331
  config->interface + i);
342
332
  }
343
333
  free((void *)config->interface);
334
+ config->interface = NULL;
335
+ config->bNumInterfaces = 0;
344
336
  free((void *)config->extra);
337
+ config->extra = NULL;
338
+ config->extra_length = 0;
345
339
  }
346
340
 
347
341
  static int parse_configuration(struct libusb_context *ctx,
@@ -358,7 +352,14 @@ static int parse_configuration(struct libusb_context *ctx,
358
352
  return LIBUSB_ERROR_IO;
359
353
  }
360
354
 
361
- parse_descriptor(buffer, "bbwbbbbb", config);
355
+ config->bLength = buffer[0];
356
+ config->bDescriptorType = buffer[1];
357
+ config->wTotalLength = ReadLittleEndian16(&buffer[2]);
358
+ config->bNumInterfaces = buffer[4];
359
+ config->bConfigurationValue = buffer[5];
360
+ config->iConfiguration = buffer[6];
361
+ config->bmAttributes = buffer[7];
362
+ config->MaxPower = buffer[8];
362
363
  if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
363
364
  usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
364
365
  config->bDescriptorType, LIBUSB_DT_CONFIG);
@@ -385,7 +386,6 @@ static int parse_configuration(struct libusb_context *ctx,
385
386
  size -= config->bLength;
386
387
 
387
388
  for (i = 0; i < config->bNumInterfaces; i++) {
388
- int len;
389
389
  const uint8_t *begin;
390
390
 
391
391
  /* Skip over the rest of the Class Specific or Vendor */
@@ -421,19 +421,19 @@ static int parse_configuration(struct libusb_context *ctx,
421
421
 
422
422
  /* Copy any unknown descriptors into a storage area for */
423
423
  /* drivers to later parse */
424
- len = (int)(buffer - begin);
424
+ ptrdiff_t len = buffer - begin;
425
425
  if (len > 0) {
426
426
  uint8_t *extra = realloc((void *)config->extra,
427
- (size_t)(config->extra_length + len));
427
+ (size_t)(config->extra_length) + (size_t)len);
428
428
 
429
429
  if (!extra) {
430
430
  r = LIBUSB_ERROR_NO_MEM;
431
431
  goto err;
432
432
  }
433
433
 
434
- memcpy(extra + config->extra_length, begin, len);
434
+ memcpy(extra + config->extra_length, begin, (size_t)len);
435
435
  config->extra = extra;
436
- config->extra_length += len;
436
+ config->extra_length += (int)len;
437
437
  }
438
438
 
439
439
  r = parse_interface(ctx, usb_interface + i, buffer, size);
@@ -707,14 +707,14 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
707
707
  const struct libusb_endpoint_descriptor *endpoint,
708
708
  struct libusb_ss_endpoint_companion_descriptor **ep_comp)
709
709
  {
710
- struct usbi_descriptor_header *header;
710
+ const struct usbi_descriptor_header *header;
711
711
  const uint8_t *buffer = endpoint->extra;
712
712
  int size = endpoint->extra_length;
713
713
 
714
714
  *ep_comp = NULL;
715
715
 
716
716
  while (size >= DESC_HEADER_LENGTH) {
717
- header = (struct usbi_descriptor_header *)buffer;
717
+ header = (const struct usbi_descriptor_header *)buffer;
718
718
  if (header->bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
719
719
  if (header->bLength < DESC_HEADER_LENGTH) {
720
720
  usbi_err(ctx, "invalid descriptor length %u",
@@ -737,7 +737,11 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
737
737
  *ep_comp = malloc(sizeof(**ep_comp));
738
738
  if (!*ep_comp)
739
739
  return LIBUSB_ERROR_NO_MEM;
740
- parse_descriptor(buffer, "bbbbw", *ep_comp);
740
+ (*ep_comp)->bLength = buffer[0];
741
+ (*ep_comp)->bDescriptorType = buffer[1];
742
+ (*ep_comp)->bMaxBurst = buffer[2];
743
+ (*ep_comp)->bmAttributes = buffer[3];
744
+ (*ep_comp)->wBytesPerInterval = ReadLittleEndian16(&buffer[4]);
741
745
  return LIBUSB_SUCCESS;
742
746
  }
743
747
  return LIBUSB_ERROR_NOT_FOUND;
@@ -786,11 +790,14 @@ static int parse_bos(struct libusb_context *ctx,
786
790
  return LIBUSB_ERROR_IO;
787
791
  }
788
792
 
789
- _bos = calloc(1, sizeof(*_bos) + bos_desc->bNumDeviceCaps * sizeof(void *));
793
+ _bos = calloc(1, sizeof(*_bos) + (bos_desc->bNumDeviceCaps * sizeof(void *)));
790
794
  if (!_bos)
791
795
  return LIBUSB_ERROR_NO_MEM;
792
796
 
793
- parse_descriptor(buffer, "bbwb", _bos);
797
+ _bos->bLength = buffer[0];
798
+ _bos->bDescriptorType = buffer[1];
799
+ _bos->wTotalLength = ReadLittleEndian16(&buffer[2]);
800
+ _bos->bNumDeviceCaps = buffer[4];
794
801
  buffer += _bos->bLength;
795
802
  size -= _bos->bLength;
796
803
 
@@ -910,7 +917,7 @@ void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
910
917
  *
911
918
  * \param ctx the context to operate on, or NULL for the default context
912
919
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
913
- * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
920
+ * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION
914
921
  * LIBUSB_BT_USB_2_0_EXTENSION
915
922
  * \param usb_2_0_extension output location for the USB 2.0 Extension
916
923
  * descriptor. Only valid if 0 was returned. Must be freed with
@@ -940,7 +947,10 @@ int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
940
947
  if (!_usb_2_0_extension)
941
948
  return LIBUSB_ERROR_NO_MEM;
942
949
 
943
- parse_descriptor(dev_cap, "bbbd", _usb_2_0_extension);
950
+ _usb_2_0_extension->bLength = dev_cap->bLength;
951
+ _usb_2_0_extension->bDescriptorType = dev_cap->bDescriptorType;
952
+ _usb_2_0_extension->bDevCapabilityType = dev_cap->bDevCapabilityType;
953
+ _usb_2_0_extension->bmAttributes = ReadLittleEndian32(dev_cap->dev_capability_data);
944
954
 
945
955
  *usb_2_0_extension = _usb_2_0_extension;
946
956
  return LIBUSB_SUCCESS;
@@ -965,7 +975,7 @@ void API_EXPORTED libusb_free_usb_2_0_extension_descriptor(
965
975
  *
966
976
  * \param ctx the context to operate on, or NULL for the default context
967
977
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
968
- * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
978
+ * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
969
979
  * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
970
980
  * \param ss_usb_device_cap output location for the SuperSpeed USB Device
971
981
  * Capability descriptor. Only valid if 0 was returned. Must be freed with
@@ -995,12 +1005,151 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
995
1005
  if (!_ss_usb_device_cap)
996
1006
  return LIBUSB_ERROR_NO_MEM;
997
1007
 
998
- parse_descriptor(dev_cap, "bbbbwbbw", _ss_usb_device_cap);
1008
+ _ss_usb_device_cap->bLength = dev_cap->bLength;
1009
+ _ss_usb_device_cap->bDescriptorType = dev_cap->bDescriptorType;
1010
+ _ss_usb_device_cap->bDevCapabilityType = dev_cap->bDevCapabilityType;
1011
+ _ss_usb_device_cap->bmAttributes = dev_cap->dev_capability_data[0];
1012
+ _ss_usb_device_cap->wSpeedSupported = ReadLittleEndian16(&dev_cap->dev_capability_data[1]);
1013
+ _ss_usb_device_cap->bFunctionalitySupport = dev_cap->dev_capability_data[3];
1014
+ _ss_usb_device_cap->bU1DevExitLat = dev_cap->dev_capability_data[4];
1015
+ _ss_usb_device_cap->bU2DevExitLat = ReadLittleEndian16(&dev_cap->dev_capability_data[5]);
999
1016
 
1000
1017
  *ss_usb_device_cap = _ss_usb_device_cap;
1001
1018
  return LIBUSB_SUCCESS;
1002
1019
  }
1003
1020
 
1021
+ /// @cond DEV
1022
+ /** \internal \ingroup libusb_desc
1023
+ * We use this private struct only to parse a SuperSpeedPlus device capability
1024
+ * descriptor according to section 9.6.2.5 of the USB 3.1 specification.
1025
+ * We don't expose it.
1026
+ */
1027
+ struct internal_ssplus_capability_descriptor {
1028
+ /** The length of the descriptor. Must be equal to LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE */
1029
+ uint8_t bLength;
1030
+
1031
+ /** The type of the descriptor */
1032
+ uint8_t bDescriptorType;
1033
+
1034
+ /** Must be equal to LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY */
1035
+ uint8_t bDevCapabilityType;
1036
+
1037
+ /** Unused */
1038
+ uint8_t bReserved;
1039
+
1040
+ /** Contains the number of SublinkSpeedIDs */
1041
+ uint32_t bmAttributes;
1042
+
1043
+ /** Contains the ssid, minRxLaneCount, and minTxLaneCount */
1044
+ uint16_t wFunctionalitySupport;
1045
+
1046
+ /** Unused */
1047
+ uint16_t wReserved;
1048
+ };
1049
+ /// @endcond
1050
+
1051
+ /** \ingroup libusb_desc
1052
+ * Get a SuperSpeedPlus USB Device Capability descriptor
1053
+ *
1054
+ * Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B
1055
+ *
1056
+ * \param ctx the context to operate on, or NULL for the default context
1057
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1058
+ * \ref libusb_bos_type::LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY
1059
+ * LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY
1060
+ * \param ssplus_usb_device_cap output location for the SuperSpeedPlus USB Device
1061
+ * Capability descriptor. Only valid if 0 was returned. Must be freed with
1062
+ * libusb_free_ssplus_usb_device_capability_descriptor() after use.
1063
+ * \returns 0 on success
1064
+ * \returns a LIBUSB_ERROR code on error
1065
+ */
1066
+ int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
1067
+ libusb_context *ctx,
1068
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
1069
+ struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap)
1070
+ {
1071
+ struct libusb_ssplus_usb_device_capability_descriptor *_ssplus_cap;
1072
+
1073
+ /* Use a private struct to reuse our descriptor parsing system. */
1074
+ struct internal_ssplus_capability_descriptor parsedDescriptor;
1075
+
1076
+ /* Some size/type checks to make sure everything is in order */
1077
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY) {
1078
+ usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
1079
+ dev_cap->bDevCapabilityType,
1080
+ LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY);
1081
+ return LIBUSB_ERROR_INVALID_PARAM;
1082
+ } else if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE) {
1083
+ usbi_err(ctx, "short dev-cap descriptor read %u/%d",
1084
+ dev_cap->bLength, LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE);
1085
+ return LIBUSB_ERROR_IO;
1086
+ }
1087
+
1088
+ const uint8_t* dev_capability_data = dev_cap->dev_capability_data;
1089
+ parsedDescriptor.bLength = dev_cap->bLength;
1090
+ parsedDescriptor.bDescriptorType = dev_cap->bDescriptorType;
1091
+ parsedDescriptor.bDevCapabilityType = dev_cap->bDevCapabilityType;
1092
+ parsedDescriptor.bReserved = dev_capability_data[0];
1093
+ parsedDescriptor.bmAttributes = ReadLittleEndian32(&dev_capability_data[1]);
1094
+ parsedDescriptor.wFunctionalitySupport = ReadLittleEndian16(&dev_capability_data[5]);
1095
+ parsedDescriptor.wReserved = ReadLittleEndian16(&dev_capability_data[7]);
1096
+
1097
+ uint8_t numSublikSpeedAttributes = (parsedDescriptor.bmAttributes & 0xF) + 1;
1098
+ _ssplus_cap = malloc(sizeof(struct libusb_ssplus_usb_device_capability_descriptor) + (numSublikSpeedAttributes * sizeof(struct libusb_ssplus_sublink_attribute)));
1099
+ if (!_ssplus_cap)
1100
+ return LIBUSB_ERROR_NO_MEM;
1101
+
1102
+ /* Parse bmAttributes */
1103
+ _ssplus_cap->numSublinkSpeedAttributes = numSublikSpeedAttributes;
1104
+ _ssplus_cap->numSublinkSpeedIDs = ((parsedDescriptor.bmAttributes & 0xF0) >> 4) + 1;
1105
+
1106
+ /* Parse wFunctionalitySupport */
1107
+ _ssplus_cap->ssid = parsedDescriptor.wFunctionalitySupport & 0xF;
1108
+ _ssplus_cap->minRxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0x0F00) >> 8;
1109
+ _ssplus_cap->minTxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0xF000) >> 12;
1110
+
1111
+ /* Check that we have enough to read all the sublink attributes */
1112
+ if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE + (_ssplus_cap->numSublinkSpeedAttributes * sizeof(uint32_t))) {
1113
+ free(_ssplus_cap);
1114
+ usbi_err(ctx, "short ssplus capability descriptor, unable to read sublinks: Not enough data");
1115
+ return LIBUSB_ERROR_IO;
1116
+ }
1117
+
1118
+ /* Read the attributes */
1119
+ uint8_t* base = ((uint8_t*)dev_cap) + LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE;
1120
+ for(uint8_t i = 0 ; i < _ssplus_cap->numSublinkSpeedAttributes ; i++) {
1121
+ uint32_t attr = ReadLittleEndian32(base + (i * sizeof(uint32_t)));
1122
+ _ssplus_cap->sublinkSpeedAttributes[i].ssid = attr & 0x0f;
1123
+ _ssplus_cap->sublinkSpeedAttributes[i].mantissa = attr >> 16;
1124
+ _ssplus_cap->sublinkSpeedAttributes[i].exponent = (attr >> 4) & 0x3 ;
1125
+ _ssplus_cap->sublinkSpeedAttributes[i].type = attr & 0x40 ? LIBUSB_SSPLUS_ATTR_TYPE_ASYM : LIBUSB_SSPLUS_ATTR_TYPE_SYM;
1126
+ _ssplus_cap->sublinkSpeedAttributes[i].direction = attr & 0x80 ? LIBUSB_SSPLUS_ATTR_DIR_TX : LIBUSB_SSPLUS_ATTR_DIR_RX;
1127
+ _ssplus_cap->sublinkSpeedAttributes[i].protocol = attr & 0x4000 ? LIBUSB_SSPLUS_ATTR_PROT_SSPLUS: LIBUSB_SSPLUS_ATTR_PROT_SS;
1128
+ }
1129
+
1130
+ *ssplus_usb_device_cap = _ssplus_cap;
1131
+ return LIBUSB_SUCCESS;
1132
+ }
1133
+
1134
+ /** \ingroup libusb_desc
1135
+ * Free a SuperSpeedPlus USB Device Capability descriptor obtained from
1136
+ * libusb_get_ssplus_usb_device_capability_descriptor().
1137
+ * It is safe to call this function with a NULL ssplus_usb_device_cap
1138
+ * parameter, in which case the function simply returns.
1139
+ *
1140
+ * Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B
1141
+ *
1142
+ * \param ssplus_usb_device_cap the SuperSpeedPlus USB Device Capability descriptor
1143
+ * to free
1144
+ */
1145
+ void API_EXPORTED libusb_free_ssplus_usb_device_capability_descriptor(
1146
+ struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap)
1147
+ {
1148
+ free(ssplus_usb_device_cap);
1149
+ }
1150
+
1151
+
1152
+
1004
1153
  /** \ingroup libusb_desc
1005
1154
  * Free a SuperSpeed USB Device Capability descriptor obtained from
1006
1155
  * libusb_get_ss_usb_device_capability_descriptor().
@@ -1021,7 +1170,7 @@ void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
1021
1170
  *
1022
1171
  * \param ctx the context to operate on, or NULL for the default context
1023
1172
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1024
- * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
1173
+ * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID
1025
1174
  * LIBUSB_BT_CONTAINER_ID
1026
1175
  * \param container_id output location for the Container ID descriptor.
1027
1176
  * Only valid if 0 was returned. Must be freed with
@@ -1050,7 +1199,11 @@ int API_EXPORTED libusb_get_container_id_descriptor(libusb_context *ctx,
1050
1199
  if (!_container_id)
1051
1200
  return LIBUSB_ERROR_NO_MEM;
1052
1201
 
1053
- parse_descriptor(dev_cap, "bbbbu", _container_id);
1202
+ _container_id->bLength = dev_cap->bLength;
1203
+ _container_id->bDescriptorType = dev_cap->bDescriptorType;
1204
+ _container_id->bDevCapabilityType = dev_cap->bDevCapabilityType;
1205
+ _container_id->bReserved = dev_cap->dev_capability_data[0];
1206
+ memcpy(_container_id->ContainerID, &dev_cap->dev_capability_data[1], 16);
1054
1207
 
1055
1208
  *container_id = _container_id;
1056
1209
  return LIBUSB_SUCCESS;
@@ -1077,7 +1230,7 @@ void API_EXPORTED libusb_free_container_id_descriptor(
1077
1230
  *
1078
1231
  * \param ctx the context to operate on, or NULL for the default context
1079
1232
  * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1080
- * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
1233
+ * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
1081
1234
  * LIBUSB_BT_PLATFORM_DESCRIPTOR
1082
1235
  * \param platform_descriptor output location for the Platform descriptor.
1083
1236
  * Only valid if 0 was returned. Must be freed with
@@ -1106,13 +1259,17 @@ int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx,
1106
1259
  if (!_platform_descriptor)
1107
1260
  return LIBUSB_ERROR_NO_MEM;
1108
1261
 
1109
- parse_descriptor(dev_cap, "bbbbu", _platform_descriptor);
1262
+ _platform_descriptor->bLength = dev_cap->bLength;
1263
+ _platform_descriptor->bDescriptorType = dev_cap->bDescriptorType;
1264
+ _platform_descriptor->bDevCapabilityType = dev_cap->bDevCapabilityType;
1265
+ _platform_descriptor->bReserved = dev_cap->dev_capability_data[0];
1266
+ memcpy(_platform_descriptor->PlatformCapabilityUUID, &(dev_cap->dev_capability_data[1]), 16);
1110
1267
 
1111
- /* Capability data is located after reserved byte and 128-bit UUID */
1268
+ /* Capability data is located after reserved byte and 16 byte UUID */
1112
1269
  uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16;
1113
1270
 
1114
1271
  /* Capability data length is total descriptor length minus initial fields */
1115
- size_t capability_data_length = _platform_descriptor->bLength - (16 + 4);
1272
+ size_t capability_data_length = dev_cap->bLength - (3 + 1 + 16);
1116
1273
 
1117
1274
  memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length);
1118
1275
 
@@ -1168,20 +1325,17 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha
1168
1325
  r = libusb_get_string_descriptor(dev_handle, 0, 0, str.buf, 4);
1169
1326
  if (r < 0)
1170
1327
  return r;
1171
- else if (r != 4 || str.desc.bLength < 4)
1328
+ else if (r != 4 || str.desc.bLength < 4 || str.desc.bDescriptorType != LIBUSB_DT_STRING) {
1329
+ usbi_warn(HANDLE_CTX(dev_handle), "invalid language ID string descriptor");
1172
1330
  return LIBUSB_ERROR_IO;
1173
- else if (str.desc.bDescriptorType != LIBUSB_DT_STRING)
1174
- return LIBUSB_ERROR_IO;
1175
- else if (str.desc.bLength & 1)
1331
+ } else if (str.desc.bLength & 1)
1176
1332
  usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for language ID string descriptor", str.desc.bLength);
1177
1333
 
1178
1334
  langid = libusb_le16_to_cpu(str.desc.wData[0]);
1179
1335
  r = libusb_get_string_descriptor(dev_handle, desc_index, langid, str.buf, sizeof(str.buf));
1180
1336
  if (r < 0)
1181
1337
  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)
1338
+ else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r || str.desc.bDescriptorType != LIBUSB_DT_STRING)
1185
1339
  return LIBUSB_ERROR_IO;
1186
1340
  else if ((str.desc.bLength & 1) || str.desc.bLength != r)
1187
1341
  usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor (read %d)", str.desc.bLength, r);
@@ -1224,15 +1378,21 @@ static int parse_iad_array(struct libusb_context *ctx,
1224
1378
  return LIBUSB_ERROR_IO;
1225
1379
  }
1226
1380
 
1227
- // First pass: Iterate through desc list, count number of IADs
1381
+ /* First pass: Iterate through desc list, count number of IADs */
1228
1382
  iad_array->length = 0;
1229
- while (consumed < size) {
1230
- parse_descriptor(buf, "bb", &header);
1231
- if (header.bLength < 2) {
1383
+ while (size - consumed >= DESC_HEADER_LENGTH) {
1384
+ header.bLength = buf[0];
1385
+ header.bDescriptorType = buf[1];
1386
+ if (header.bLength < DESC_HEADER_LENGTH) {
1232
1387
  usbi_err(ctx, "invalid descriptor bLength %d",
1233
1388
  header.bLength);
1234
1389
  return LIBUSB_ERROR_IO;
1235
1390
  }
1391
+ else if (header.bLength > size - consumed) {
1392
+ usbi_warn(ctx, "short config descriptor read %d/%u",
1393
+ size - consumed, header.bLength);
1394
+ return LIBUSB_ERROR_IO;
1395
+ }
1236
1396
  if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
1237
1397
  iad_array->length++;
1238
1398
  buf += header.bLength;
@@ -1241,22 +1401,36 @@ static int parse_iad_array(struct libusb_context *ctx,
1241
1401
 
1242
1402
  iad_array->iad = NULL;
1243
1403
  if (iad_array->length > 0) {
1244
- iad = calloc(iad_array->length, sizeof(*iad));
1404
+ iad = calloc((size_t)iad_array->length, sizeof(*iad));
1245
1405
  if (!iad)
1246
1406
  return LIBUSB_ERROR_NO_MEM;
1247
1407
 
1248
1408
  iad_array->iad = iad;
1249
1409
 
1250
- // Second pass: Iterate through desc list, fill IAD structures
1251
- consumed = 0;
1410
+ /* Second pass: Iterate through desc list, fill IAD structures */
1411
+ int remaining = size;
1252
1412
  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
- }
1413
+ do {
1414
+ header.bLength = buffer[0];
1415
+ header.bDescriptorType = buffer[1];
1416
+ if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION && (remaining >= LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE)) {
1417
+ iad[i].bLength = buffer[0];
1418
+ iad[i].bDescriptorType = buffer[1];
1419
+ iad[i].bFirstInterface = buffer[2];
1420
+ iad[i].bInterfaceCount = buffer[3];
1421
+ iad[i].bFunctionClass = buffer[4];
1422
+ iad[i].bFunctionSubClass = buffer[5];
1423
+ iad[i].bFunctionProtocol = buffer[6];
1424
+ iad[i].iFunction = buffer[7];
1425
+ i++;
1426
+ }
1427
+
1428
+ remaining -= header.bLength;
1429
+ if (remaining < DESC_HEADER_LENGTH) {
1430
+ break;
1431
+ }
1432
+ buffer += header.bLength;
1433
+ } while (1);
1260
1434
  }
1261
1435
 
1262
1436
  return LIBUSB_SUCCESS;
@@ -1397,3 +1571,137 @@ void API_EXPORTED libusb_free_interface_association_descriptors(
1397
1571
  free((void*)iad_array->iad);
1398
1572
  free(iad_array);
1399
1573
  }
1574
+
1575
+ /*
1576
+ * \brief Copy a UTF-8 string with proper truncation if needed.
1577
+ *
1578
+ * \param tgt The target utf-8 string. If NULL, then tgt is ignored,
1579
+ * tgt_size is forced to 0, and this function returns the
1580
+ * required tgt_size for a subsequent call to this function.
1581
+ * \param src The source utf-8 string. If NULL, then
1582
+ * the source string is empty, the return length is 1,
1583
+ * and, if tgt is not NULL, this function
1584
+ * sets tgt[0] to the null terminator.
1585
+ * \param tgt_size The size of target in bytes.
1586
+ * \return the length of src in bytes, including the null terminator.
1587
+ *
1588
+ * utf8_copy(NULL, src, 0) is equivalent to strlen(src) + 1.
1589
+ */
1590
+ static int usbi_utf8_copy(char *tgt, char const *src, int tgt_size) {
1591
+ uint8_t* t = (uint8_t*)tgt;
1592
+ uint8_t const* s = (uint8_t const*)src;
1593
+
1594
+ if (NULL == src) {
1595
+ if ((NULL != tgt) && (tgt_size > 0)) {
1596
+ tgt[0] = 0;
1597
+ }
1598
+ return 1;
1599
+ }
1600
+
1601
+ if ((NULL == tgt) || (tgt_size <= 0)) {
1602
+ return (int)(strlen(src) + 1);
1603
+ }
1604
+
1605
+ // copy UTF-8 string and compute length
1606
+ int k = 0;
1607
+ for (k = 0; s[k]; ++k) {
1608
+ if (k < tgt_size) {
1609
+ t[k] = s[k];
1610
+ } else {
1611
+ break;
1612
+ }
1613
+ }
1614
+
1615
+ if (k >= tgt_size) {
1616
+ // truncate respecting UTF-8 character boundaries
1617
+ int idx = tgt_size - 1;
1618
+ while (idx && (0x80 == (t[idx] & 0xC0))) { // utf-8 continuation byte
1619
+ --idx;
1620
+ }
1621
+ t[idx] = 0;
1622
+ return (int)(strlen(src) + 1);
1623
+ } else {
1624
+ t[k++] = 0;
1625
+ return k;
1626
+ }
1627
+ }
1628
+
1629
+ /** \ingroup libusb_desc
1630
+ * Retrieve a device string without needing to open the device.
1631
+ *
1632
+ * Since version v1.0.30 \ref LIBUSB_API_VERSION >= 0x0100010C
1633
+ *
1634
+ * \param dev the target device
1635
+ * \param string_type the string type to retrieve
1636
+ * \param data the data buffer for the UTF-8 encoded string.
1637
+ * \param length the size of the data buffer in bytes.
1638
+ * USB string descriptors cannot be longer than
1639
+ * LIBUSB_DEVICE_STRING_BYTES_MAX.
1640
+ * \returns a negative error code or
1641
+ * the actual string length in bytes including the null terminator.
1642
+ * \see libusb_get_string_descriptor()
1643
+ * \see libusb_get_string_descriptor_ascii()
1644
+ *
1645
+ * This function works when the device is still closed since it relies
1646
+ * on the operating system to provide the string. The operating system
1647
+ * normally reads and caches the common string descriptors during
1648
+ * USB enumeration.
1649
+ *
1650
+ * Since the USB string descriptor could be processed by the OS,
1651
+ * this function returns a UTF-8 encoded string.
1652
+ *
1653
+ * The string will be returned untranslated or in the default OS language
1654
+ * when supported by the OS and USB device.
1655
+ *
1656
+ * One way to call this function is using a buffer on the stack:
1657
+ *
1658
+ * char buffer[LIBUSB_DEVICE_STRING_BYTES_MAX];
1659
+ * int ret = libusb_get_device_string(dev, LIBUSB_DEVICE_STRING_SERIAL_NUMBER, buffer, sizeof(buffer));
1660
+ * if (ret < 0) {
1661
+ * // handle error
1662
+ * }
1663
+ *
1664
+ * This function is commonly used to get the serial number to allow
1665
+ * for device selection before opening the selected device.
1666
+ */
1667
+ int API_EXPORTED libusb_get_device_string(libusb_device *dev,
1668
+ enum libusb_device_string_type string_type, char *data, int length) {
1669
+ char * s;
1670
+ if (NULL == dev) {
1671
+ return LIBUSB_ERROR_INVALID_PARAM;
1672
+ }
1673
+ if ((string_type < 0) || (string_type >= LIBUSB_DEVICE_STRING_COUNT)) {
1674
+ return LIBUSB_ERROR_INVALID_PARAM;
1675
+ }
1676
+ if (length <= 0) {
1677
+ return LIBUSB_ERROR_INVALID_PARAM;
1678
+ }
1679
+ if (NULL == data) {
1680
+ length = 0;
1681
+ data = NULL;
1682
+ } else if (length > 0) {
1683
+ *data = 0; // return an empty string on errors when possible
1684
+ }
1685
+
1686
+ if (NULL == dev->device_strings_utf8[string_type]) {
1687
+ if (usbi_backend.get_device_string) {
1688
+ s = malloc(LIBUSB_DEVICE_STRING_BYTES_MAX);
1689
+ int rv = usbi_backend.get_device_string(dev, string_type, s, LIBUSB_DEVICE_STRING_BYTES_MAX);
1690
+ if (rv < 0) {
1691
+ free(s);
1692
+ return rv;
1693
+ } else {
1694
+ dev->device_strings_utf8[string_type] = s;
1695
+ }
1696
+ } else {
1697
+ return LIBUSB_ERROR_NOT_SUPPORTED;
1698
+ }
1699
+ }
1700
+
1701
+ s = dev->device_strings_utf8[string_type];
1702
+ if (NULL == s) {
1703
+ return LIBUSB_ERROR_NOT_SUPPORTED;
1704
+ }
1705
+
1706
+ return usbi_utf8_copy(data, s, length);
1707
+ }