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
@@ -117,7 +117,7 @@ struct darwin_cached_device {
117
117
  UInt8 first_config, active_config, port;
118
118
  int can_enumerate;
119
119
  int refcount;
120
- bool in_reenumerate;
120
+ atomic_bool in_reenumerate;
121
121
  int capture_count;
122
122
  };
123
123
 
@@ -125,17 +125,19 @@ struct darwin_device_priv {
125
125
  struct darwin_cached_device *dev;
126
126
  };
127
127
 
128
+ struct darwin_interface {
129
+ usb_interface_t interface;
130
+ uint8_t num_endpoints;
131
+ CFRunLoopSourceRef cfSource;
132
+ uint64_t frames[256];
133
+ uint8_t endpoint_addrs[USB_MAXENDPOINTS];
134
+ };
135
+
128
136
  struct darwin_device_handle_priv {
129
137
  bool is_open;
130
138
  CFRunLoopSourceRef cfSource;
131
139
 
132
- struct darwin_interface {
133
- usb_interface_t interface;
134
- uint8_t num_endpoints;
135
- CFRunLoopSourceRef cfSource;
136
- uint64_t frames[256];
137
- uint8_t endpoint_addrs[USB_MAXENDPOINTS];
138
- } interfaces[USB_MAXINTERFACES];
140
+ struct darwin_interface interfaces[USB_MAXINTERFACES];
139
141
  };
140
142
 
141
143
  struct darwin_transfer_priv {
@@ -538,17 +538,36 @@ private:
538
538
  auto configurations_len = dev->device_descriptor.bNumConfigurations;
539
539
  configurations.reserve(configurations_len);
540
540
  for (uint8_t j = 0; j < configurations_len; j++) {
541
- // Note: requesting more than (platform-specific limit) bytes
542
- // here will cause the transfer to fail, see
543
- // https://crbug.com/1489414. Use the most common limit of 4096
544
- // bytes for now.
545
- constexpr uint16_t MAX_CTRL_BUFFER_LENGTH = 4096;
546
- auto result = co_await_try(
547
- requestDescriptor(LIBUSB_DT_CONFIG, j, MAX_CTRL_BUFFER_LENGTH));
548
- if (auto error = getTransferStatus(result)) {
541
+ // Read descriptor header first to discover target length.
542
+ auto config_header_result = co_await_try(
543
+ requestDescriptor(LIBUSB_DT_CONFIG, j, LIBUSB_DT_CONFIG_SIZE));
544
+ if (auto error = getTransferStatus(config_header_result)) {
549
545
  co_return error;
550
546
  }
551
- auto configVal = result["data"];
547
+ union usbi_config_desc_buf config_header = {};
548
+ copyFromDataView(config_header.buf, config_header_result["data"]);
549
+ if (config_header.desc.bDescriptorType != LIBUSB_DT_CONFIG ||
550
+ config_header.desc.bLength < LIBUSB_DT_CONFIG_SIZE) {
551
+ co_return LIBUSB_ERROR_IO;
552
+ }
553
+
554
+ auto config_total_length =
555
+ libusb_le16_to_cpu(config_header.desc.wTotalLength);
556
+ if (config_total_length < LIBUSB_DT_CONFIG_SIZE) {
557
+ co_return LIBUSB_ERROR_IO;
558
+ }
559
+
560
+ auto config_result = co_await_try(
561
+ requestDescriptor(LIBUSB_DT_CONFIG, j, config_total_length));
562
+ if (auto error = getTransferStatus(config_result)) {
563
+ co_return error;
564
+ }
565
+
566
+ auto configVal = config_result["data"];
567
+ if (configVal["byteLength"].as<size_t>() < config_total_length) {
568
+ co_return LIBUSB_ERROR_IO;
569
+ }
570
+
552
571
  auto configLen = configVal["byteLength"].as<size_t>();
553
572
  auto& config = configurations.emplace_back(
554
573
  (usbi_configuration_descriptor*)::operator new(configLen));
@@ -586,12 +605,17 @@ unsigned long getDeviceSessionId(val& web_usb_device) {
586
605
  }
587
606
 
588
607
  val getDeviceList(libusb_context* ctx, discovered_devs** devs) {
608
+ // Check if browser supports USB
609
+ val navigator_usb = val::global("navigator")["usb"];
610
+ if (navigator_usb == val::undefined()) {
611
+ co_return (int) LIBUSB_ERROR_NOT_SUPPORTED;
612
+ }
589
613
  // C++ equivalent of `await navigator.usb.getDevices()`. Note: at this point
590
614
  // we must already have some devices exposed - caller must have called
591
615
  // `await navigator.usb.requestDevice(...)` in response to user interaction
592
616
  // before going to LibUSB. Otherwise this list will be empty.
593
617
  auto web_usb_devices =
594
- co_await_try(val::global("navigator")["usb"].call<val>("getDevices"));
618
+ co_await_try(navigator_usb.call<val>("getDevices"));
595
619
  for (auto&& web_usb_device : web_usb_devices) {
596
620
  auto session_id = getDeviceSessionId(web_usb_device);
597
621
 
@@ -618,6 +642,8 @@ val getDeviceList(libusb_context* ctx, discovered_devs** devs) {
618
642
  // This can wrap around but it's the best approximation of a stable
619
643
  // device address and port number we can provide.
620
644
  dev->device_address = dev->port_number = (uint8_t)session_id;
645
+
646
+ usbi_connect_device(dev);
621
647
  }
622
648
  *devs = discovered_devs_append(*devs, dev);
623
649
  libusb_unref_device(dev);
@@ -701,7 +727,7 @@ int em_get_config_descriptor_by_value(libusb_device* dev,
701
727
  }
702
728
 
703
729
  int em_set_configuration(libusb_device_handle* dev_handle, int config) {
704
- return WebUsbDevicePtr(dev_handle)->awaitOnMain("setConfiguration", config);
730
+ return WebUsbDevicePtr(dev_handle)->awaitOnMain("selectConfiguration", config);
705
731
  }
706
732
 
707
733
  int em_claim_interface(libusb_device_handle* handle, uint8_t iface) {
@@ -844,7 +870,7 @@ int em_handle_transfer_completion(usbi_transfer* itransfer) {
844
870
  #pragma clang diagnostic ignored "-Wmissing-field-initializers"
845
871
  extern "C" const usbi_os_backend usbi_backend = {
846
872
  .name = "Emscripten + WebUSB backend",
847
- .caps = LIBUSB_CAP_HAS_CAPABILITY,
873
+ .caps = 0,
848
874
  .get_device_list = em_get_device_list,
849
875
  .open = em_open,
850
876
  .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);
@@ -186,6 +186,7 @@ const struct usbi_os_backend usbi_backend = {
186
186
  /*.exit =*/ haiku_exit,
187
187
  /*.set_option =*/ NULL,
188
188
  /*.get_device_list =*/ NULL,
189
+ /*.get_device_string =*/ NULL,
189
190
  /*.hotplug_poll =*/ NULL,
190
191
  /*.wrap_sys_device =*/ NULL,
191
192
  /*.open =*/ haiku_open,
@@ -214,6 +215,9 @@ const struct usbi_os_backend usbi_backend = {
214
215
  /*.kernel_driver_active =*/ NULL,
215
216
  /*.detach_kernel_driver =*/ NULL,
216
217
  /*.attach_kernel_driver =*/ NULL,
218
+ /*.endpoint_supports_raw_io =*/ NULL,
219
+ /*.endpoint_set_raw_io =*/ NULL,
220
+ /*.get_max_raw_io_transfer_size =*/ NULL,
217
221
 
218
222
  /*.destroy_device =*/ NULL,
219
223
 
@@ -98,6 +98,8 @@ static int init_count = 0;
98
98
  /* Serialize scan-devices, event-thread, and poll */
99
99
  usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER;
100
100
 
101
+ static int open_sysfs_attr(struct libusb_context *ctx,
102
+ const char *sysfs_dir, const char *attr);
101
103
  static int linux_scan_devices(struct libusb_context *ctx);
102
104
  static int detach_kernel_driver_and_claim(struct libusb_device_handle *, uint8_t);
103
105
 
@@ -182,7 +184,7 @@ static int dev_has_config0(struct libusb_device *dev)
182
184
  return 0;
183
185
  }
184
186
 
185
- static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
187
+ static int get_usbfs_fd(struct libusb_device *dev, int access_mode, int silent)
186
188
  {
187
189
  struct libusb_context *ctx = DEVICE_CTX(dev);
188
190
  char path[24];
@@ -195,28 +197,34 @@ static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
195
197
  snprintf(path, sizeof(path), USB_DEVTMPFS_PATH "/%03u/%03u",
196
198
  dev->bus_number, dev->device_address);
197
199
 
198
- fd = open(path, mode | O_CLOEXEC);
200
+ fd = open(path, access_mode | O_CLOEXEC);
199
201
  if (fd != -1)
200
202
  return fd; /* Success */
201
203
 
204
+ /* TODO: fix race between netlink and usbfs https://github.com/libusb/libusb/issues/1691 */
202
205
  if (errno == ENOENT) {
203
206
  const long delay_ms = 10L;
204
207
  const struct timespec delay_ts = { 0L, delay_ms * 1000L * 1000L };
208
+ uint8_t retry = 3;
205
209
 
206
- if (!silent)
207
- usbi_err(ctx, "File doesn't exist, wait %ld ms and try again", delay_ms);
210
+ while (retry-- > 0) {
211
+ if (!silent)
212
+ usbi_err(ctx, "File doesn't exist, wait %ld ms and try again", delay_ms);
208
213
 
209
- /* Wait 10ms for USB device path creation.*/
210
- nanosleep(&delay_ts, NULL);
214
+ /* Wait 10ms for USB device path creation.*/
215
+ nanosleep(&delay_ts, NULL);
211
216
 
212
- fd = open(path, mode | O_CLOEXEC);
213
- if (fd != -1)
214
- return fd; /* Success */
217
+ fd = open(path, access_mode | O_CLOEXEC);
218
+ if (fd != -1)
219
+ return fd; /* Success */
220
+ if (errno != ENOENT)
221
+ break;
222
+ }
215
223
  }
216
224
 
217
225
  if (!silent) {
218
226
  usbi_err(ctx, "libusb couldn't open USB device %s, errno=%d", path, errno);
219
- if (errno == EACCES && mode == O_RDWR)
227
+ if (errno == EACCES && access_mode == O_RDWR)
220
228
  usbi_err(ctx, "libusb requires write access to USB device nodes");
221
229
  }
222
230
 
@@ -293,16 +301,7 @@ static const char *find_usbfs_path(void)
293
301
  }
294
302
  }
295
303
 
296
- /* On udev based systems without any usb-devices /dev/bus/usb will not
297
- * exist. So if we've not found anything and we're using udev for hotplug
298
- * simply assume /dev/bus/usb rather then making libusb_init fail.
299
- * Make the same assumption for Android where SELinux policies might block us
300
- * from reading /dev on newer devices. */
301
- #if defined(HAVE_LIBUDEV) || defined(__ANDROID__)
302
- return USB_DEVTMPFS_PATH;
303
- #else
304
304
  return NULL;
305
- #endif
306
305
  }
307
306
 
308
307
  static int get_kernel_version(struct libusb_context *ctx,
@@ -370,12 +369,16 @@ static int op_init(struct libusb_context *ctx)
370
369
 
371
370
  usbfs_path = find_usbfs_path();
372
371
  if (!usbfs_path) {
373
- usbi_err(ctx, "could not find usbfs");
374
- return LIBUSB_ERROR_OTHER;
372
+ /* On udev based systems without any usb devices /dev/bus/usb will not
373
+ * exist. On android and other systems SELinux policies might block us
374
+ * from reading /dev. Nonetheless it's the default for most modern linux
375
+ systems including those using udev alternatives such as busybox's mdev. */
376
+ usbfs_path = USB_DEVTMPFS_PATH;
377
+ usbi_dbg(ctx, "could not find usbfs, defaulting to %s", usbfs_path);
378
+ } else {
379
+ usbi_dbg(ctx, "found usbfs at %s", usbfs_path);
375
380
  }
376
381
 
377
- usbi_dbg(ctx, "found usbfs at %s", usbfs_path);
378
-
379
382
  if (!max_iso_packet_len) {
380
383
  if (kernel_version_ge(&kversion, 5, 2, 0))
381
384
  max_iso_packet_len = 98304;
@@ -452,6 +455,46 @@ static int op_set_option(struct libusb_context *ctx, enum libusb_option option,
452
455
  return LIBUSB_ERROR_NOT_SUPPORTED;
453
456
  }
454
457
 
458
+ static int op_get_device_string(struct libusb_device *dev,
459
+ enum libusb_device_string_type string_type, char *buffer, int length)
460
+ {
461
+ ssize_t r;
462
+ int fd;
463
+ struct linux_device_priv *priv = usbi_get_device_priv(dev);
464
+ struct libusb_context* ctx = DEVICE_CTX(dev);
465
+ const char * attr;
466
+
467
+ switch (string_type) {
468
+ case LIBUSB_DEVICE_STRING_MANUFACTURER: attr = "manufacturer"; break;
469
+ case LIBUSB_DEVICE_STRING_PRODUCT: attr = "product"; break;
470
+ case LIBUSB_DEVICE_STRING_SERIAL_NUMBER: attr = "serial"; break;
471
+ case LIBUSB_DEVICE_STRING_COUNT:
472
+ /* intentional fall-through, avoid -Wswitch-enum */
473
+ default:
474
+ return LIBUSB_ERROR_INVALID_PARAM;
475
+ }
476
+ fd = open_sysfs_attr(ctx, priv->sysfs_dir, attr);
477
+ if (fd < 0)
478
+ return LIBUSB_ERROR_IO;
479
+
480
+ r = read(fd, buffer, length - 1); // leave space for null terminator
481
+ if (r < 0) {
482
+ r = errno;
483
+ close(fd);
484
+ if (r == ENODEV)
485
+ return LIBUSB_ERROR_NO_DEVICE;
486
+ usbi_err(ctx, "attribute %s read failed, errno=%zd", attr, r);
487
+ return LIBUSB_ERROR_IO;
488
+ }
489
+ close(fd);
490
+ buffer[r] = 0; // add null terminator
491
+ while (r && ((buffer[r] == 0) || (buffer[r] == '\n'))) {
492
+ buffer[r--] = 0;
493
+ }
494
+ ++r;
495
+ return r;
496
+ }
497
+
455
498
  static int linux_scan_devices(struct libusb_context *ctx)
456
499
  {
457
500
  int ret;
@@ -541,7 +584,7 @@ static int read_sysfs_attr(struct libusb_context *ctx,
541
584
 
542
585
  errno = 0;
543
586
  value = strtol(buf, &endptr, 10);
544
- if (value < 0 || value > (long)max_value || errno) {
587
+ if (buf == endptr || value < 0 || value > (long)max_value || errno) {
545
588
  usbi_err(ctx, "attribute %s contains an invalid value: '%s'", attr, buf);
546
589
  return LIBUSB_ERROR_INVALID_PARAM;
547
590
  } else if (*endptr != '\0') {
@@ -933,6 +976,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
933
976
  case 480: dev->speed = LIBUSB_SPEED_HIGH; break;
934
977
  case 5000: dev->speed = LIBUSB_SPEED_SUPER; break;
935
978
  case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
979
+ case 20000: dev->speed = LIBUSB_SPEED_SUPER_PLUS_X2; break;
936
980
  default:
937
981
  usbi_warn(ctx, "unknown device speed: %d Mbps", speed);
938
982
  }
@@ -1032,7 +1076,7 @@ static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_di
1032
1076
  {
1033
1077
  struct libusb_context *ctx = DEVICE_CTX(dev);
1034
1078
  struct libusb_device *it;
1035
- char *parent_sysfs_dir, *tmp;
1079
+ char *parent_sysfs_dir, *tmp, *end;
1036
1080
  int ret, add_parent = 1;
1037
1081
 
1038
1082
  /* XXX -- can we figure out the topology when using usbfs? */
@@ -1047,7 +1091,16 @@ static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_di
1047
1091
 
1048
1092
  if ((tmp = strrchr(parent_sysfs_dir, '.')) ||
1049
1093
  (tmp = strrchr(parent_sysfs_dir, '-'))) {
1050
- dev->port_number = atoi(tmp + 1);
1094
+ const char *start = tmp + 1;
1095
+ long port_number = strtol(start, &end, 10);
1096
+ if (port_number < 0 || port_number > INT_MAX || start == end || '\0' != *end) {
1097
+ usbi_warn(ctx, "Can not parse sysfs_dir: %s, unexpected parent info",
1098
+ parent_sysfs_dir);
1099
+ free(parent_sysfs_dir);
1100
+ return LIBUSB_ERROR_OTHER;
1101
+ } else {
1102
+ dev->port_number = (int)port_number;
1103
+ }
1051
1104
  *tmp = '\0';
1052
1105
  } else {
1053
1106
  usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info",
@@ -1244,6 +1297,10 @@ static int usbfs_get_device_list(struct libusb_context *ctx)
1244
1297
  buses = opendir(USB_DEVTMPFS_PATH);
1245
1298
 
1246
1299
  if (!buses) {
1300
+ if (!usbdev_names && errno == ENOENT) {
1301
+ /* The path does not exist if there are no devices plugged in */
1302
+ return LIBUSB_SUCCESS;
1303
+ }
1247
1304
  usbi_err(ctx, "opendir buses failed, errno=%d", errno);
1248
1305
  return LIBUSB_ERROR_IO;
1249
1306
  }
@@ -1321,10 +1378,10 @@ static int linux_default_scan_devices(struct libusb_context *ctx)
1321
1378
  * any autosuspended USB devices. however, sysfs is not available
1322
1379
  * everywhere, so we need a usbfs fallback too.
1323
1380
  */
1324
- if (sysfs_available)
1325
- return sysfs_get_device_list(ctx);
1326
- else
1327
- return usbfs_get_device_list(ctx);
1381
+ if (sysfs_available && sysfs_get_device_list(ctx) == LIBUSB_SUCCESS)
1382
+ return LIBUSB_SUCCESS;
1383
+
1384
+ return usbfs_get_device_list(ctx);
1328
1385
  }
1329
1386
  #endif
1330
1387
 
@@ -1627,8 +1684,9 @@ out:
1627
1684
  return ret;
1628
1685
  }
1629
1686
 
1630
- static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
1631
- uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
1687
+ static int do_streams_ioctl(struct libusb_device_handle *handle,
1688
+ unsigned long req, uint32_t num_streams, unsigned char *endpoints,
1689
+ int num_endpoints)
1632
1690
  {
1633
1691
  struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1634
1692
  int r, fd = hpriv->fd;
@@ -2749,7 +2807,7 @@ static int op_handle_events(struct libusb_context *ctx,
2749
2807
  } while (r == 0);
2750
2808
  }
2751
2809
 
2752
- usbi_handle_disconnect(handle);
2810
+ usbi_handle_disconnect(ctx, handle);
2753
2811
  continue;
2754
2812
  }
2755
2813
 
@@ -2776,6 +2834,7 @@ const struct usbi_os_backend usbi_backend = {
2776
2834
  .init = op_init,
2777
2835
  .exit = op_exit,
2778
2836
  .set_option = op_set_option,
2837
+ .get_device_string = op_get_device_string,
2779
2838
  .hotplug_poll = op_hotplug_poll,
2780
2839
  .get_active_config_descriptor = op_get_active_config_descriptor,
2781
2840
  .get_config_descriptor = op_get_config_descriptor,
@@ -174,7 +174,17 @@ static inline int linux_start_event_monitor(void)
174
174
  {
175
175
  #if defined(HAVE_LIBUDEV)
176
176
  return linux_udev_start_event_monitor();
177
- #elif !defined(__ANDROID__)
177
+ /*
178
+ * __ANDROID__: preprocessor macro defined automatically by GCC for all Android
179
+ * targets (i.e. both Android native applications, and Android OS-level
180
+ * services)
181
+ *
182
+ * ANDROID_OS: compilation flag that should be set for using libusb from programs
183
+ * running on Android at OS level (e.g. Android platform services).
184
+ * The programs using libusb built with the ANDROID_OS flag must have
185
+ * permission to access netlink sockets.
186
+ */
187
+ #elif !defined(__ANDROID__) || defined(ANDROID_OS)
178
188
  return linux_netlink_start_event_monitor();
179
189
  #else
180
190
  return LIBUSB_SUCCESS;
@@ -185,7 +195,7 @@ static inline void linux_stop_event_monitor(void)
185
195
  {
186
196
  #if defined(HAVE_LIBUDEV)
187
197
  linux_udev_stop_event_monitor();
188
- #elif !defined(__ANDROID__)
198
+ #elif !defined(__ANDROID__) || defined(ANDROID_OS)
189
199
  linux_netlink_stop_event_monitor();
190
200
  #endif
191
201
  }
@@ -194,7 +204,7 @@ static inline void linux_hotplug_poll(void)
194
204
  {
195
205
  #if defined(HAVE_LIBUDEV)
196
206
  linux_udev_hotplug_poll();
197
- #elif !defined(__ANDROID__)
207
+ #elif !defined(__ANDROID__) || defined(ANDROID_OS)
198
208
  linux_netlink_hotplug_poll();
199
209
  #endif
200
210
  }
@@ -171,6 +171,8 @@ netbsd_get_device_list(struct libusb_context * ctx,
171
171
 
172
172
  if ((err = usbi_sanitize_device(dev)))
173
173
  goto error;
174
+
175
+ usbi_connect_device(dev);
174
176
  }
175
177
  close(fd);
176
178
 
@@ -444,6 +446,8 @@ netbsd_handle_transfer_completion(struct usbi_transfer *itransfer)
444
446
  int
445
447
  _errno_to_libusb(int err)
446
448
  {
449
+ usbi_dbg(NULL, "error: %s (%d)", strerror(err), err);
450
+
447
451
  switch (err) {
448
452
  case EIO:
449
453
  return LIBUSB_ERROR_IO;
@@ -456,11 +460,9 @@ _errno_to_libusb(int err)
456
460
  case EWOULDBLOCK:
457
461
  case ETIMEDOUT:
458
462
  return LIBUSB_ERROR_TIMEOUT;
463
+ default:
464
+ return LIBUSB_ERROR_OTHER;
459
465
  }
460
-
461
- usbi_dbg(NULL, "error: %s (%d)", strerror(err), err);
462
-
463
- return LIBUSB_ERROR_OTHER;
464
466
  }
465
467
 
466
468
  int
@@ -200,6 +200,8 @@ obsd_get_device_list(struct libusb_context * ctx,
200
200
  libusb_unref_device(dev);
201
201
  continue;
202
202
  }
203
+
204
+ usbi_connect_device(dev);
203
205
  }
204
206
 
205
207
  ddd = discovered_devs_append(*discdevs, dev);
@@ -495,9 +497,9 @@ _errno_to_libusb(int err)
495
497
  return LIBUSB_ERROR_NO_MEM;
496
498
  case ETIMEDOUT:
497
499
  return LIBUSB_ERROR_TIMEOUT;
500
+ default:
501
+ return LIBUSB_ERROR_OTHER;
498
502
  }
499
-
500
- return LIBUSB_ERROR_OTHER;
501
503
  }
502
504
 
503
505
  int
@@ -86,7 +86,7 @@ static int sunos_get_link(di_devlink_t devlink, void *arg)
86
86
  const char *p;
87
87
  const char *q;
88
88
 
89
- if (larg->path) {
89
+ if (link_arg->path) {
90
90
  char *content = (char *)di_devlink_content(devlink);
91
91
  char *start = strstr(content, "/devices/");
92
92
  start += strlen("/devices");
@@ -94,8 +94,8 @@ static int sunos_get_link(di_devlink_t devlink, void *arg)
94
94
 
95
95
  /* line content must have minor node */
96
96
  if (start == NULL ||
97
- strncmp(start, larg->path, larg->len) != 0 ||
98
- start[larg->len] != ':')
97
+ strncmp(start, link_arg->path, link_arg->len) != 0 ||
98
+ start[link_arg->len] != ':')
99
99
  return (DI_WALK_CONTINUE);
100
100
  }
101
101
 
@@ -103,7 +103,7 @@ static int sunos_get_link(di_devlink_t devlink, void *arg)
103
103
  q = strrchr(p, '/');
104
104
  usbi_dbg(NULL, "%s", q);
105
105
 
106
- *(larg->linkpp) = strndup(p, strlen(p) - strlen(q));
106
+ *(link_arg->linkpp) = strndup(p, strlen(p) - strlen(q));
107
107
 
108
108
  return (DI_WALK_TERMINATE);
109
109
  }
@@ -171,7 +171,7 @@ sunos_usb_ioctl(struct libusb_device *dev, int cmd)
171
171
 
172
172
  nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
173
173
  nvlist_add_int32(nvlist, "port", dev->port_number);
174
- //find the hub path
174
+ /* find the hub path */
175
175
  snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath);
176
176
  usbi_dbg(DEVICE_CTX(dev), "ioctl hub path: %s", path_arg);
177
177
 
@@ -627,6 +627,8 @@ sunos_add_devices(di_devlink_t link, void *arg)
627
627
  usbi_dbg(NULL, "sanitize failed: ");
628
628
  return (DI_WALK_TERMINATE);
629
629
  }
630
+
631
+ usbi_connect_device(dev);
630
632
  } else {
631
633
  devpriv = usbi_get_device_priv(dev);
632
634
  usbi_dbg(NULL, "Dev %s exists", devpriv->ugenpath);
@@ -22,6 +22,7 @@
22
22
  #include "libusbi.h"
23
23
 
24
24
  #include <errno.h>
25
+ #include <limits.h>
25
26
  #if defined(__ANDROID__)
26
27
  # include <unistd.h>
27
28
  #elif defined(__HAIKU__)
@@ -37,7 +38,7 @@
37
38
  # include <sys/lwp.h>
38
39
  #endif
39
40
 
40
- void usbi_cond_init(pthread_cond_t *cond)
41
+ void usbi_cond_init(usbi_cond_t *cond)
41
42
  {
42
43
  #ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
43
44
  pthread_condattr_t condattr;
@@ -51,8 +52,8 @@ void usbi_cond_init(pthread_cond_t *cond)
51
52
  #endif
52
53
  }
53
54
 
54
- int usbi_cond_timedwait(pthread_cond_t *cond,
55
- pthread_mutex_t *mutex, const struct timeval *tv)
55
+ int usbi_cond_timedwait(usbi_cond_t *cond,
56
+ usbi_mutex_t *mutex, const struct timeval *tv)
56
57
  {
57
58
  struct timespec timeout;
58
59
  int r;
@@ -79,47 +80,47 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
79
80
  return LIBUSB_ERROR_OTHER;
80
81
  }
81
82
 
82
- unsigned int usbi_get_tid(void)
83
+ unsigned long usbi_get_tid(void)
83
84
  {
84
- static _Thread_local unsigned int tl_tid;
85
- int tid;
85
+ static _Thread_local unsigned long tl_tid;
86
+ unsigned long tid;
86
87
 
87
88
  if (tl_tid)
88
89
  return tl_tid;
89
90
 
90
91
  #if defined(__ANDROID__)
91
- tid = gettid();
92
+ tid = (unsigned long)gettid();
92
93
  #elif defined(__APPLE__)
93
94
  #ifdef HAVE_PTHREAD_THREADID_NP
94
95
  uint64_t thread_id;
95
96
 
96
97
  if (pthread_threadid_np(NULL, &thread_id) == 0)
97
- tid = (int)thread_id;
98
+ tid = (unsigned long)thread_id;
98
99
  else
99
- tid = -1;
100
+ tid = ULONG_MAX;
100
101
  #else
101
- tid = (int)pthread_mach_thread_np(pthread_self());
102
+ tid = (unsigned long)pthread_mach_thread_np(pthread_self());
102
103
  #endif
103
104
  #elif defined(__HAIKU__)
104
- tid = get_pthread_thread_id(pthread_self());
105
+ tid = (unsigned long)get_pthread_thread_id(pthread_self());
105
106
  #elif defined(__linux__)
106
- tid = (int)syscall(SYS_gettid);
107
+ tid = (unsigned long)syscall(SYS_gettid);
107
108
  #elif defined(__NetBSD__)
108
- tid = _lwp_self();
109
+ tid = (unsigned long)_lwp_self();
109
110
  #elif defined(__OpenBSD__)
110
- tid = getthrid();
111
+ tid = (unsigned long)getthrid();
111
112
  #elif defined(__sun__)
112
- tid = _lwp_self();
113
+ tid = (unsigned long)_lwp_self();
113
114
  #else
114
- tid = -1;
115
+ tid = ULONG_MAX;
115
116
  #endif
116
117
 
117
- if (tid == -1) {
118
+ if (tid == ULONG_MAX) {
118
119
  /* If we don't have a thread ID, at least return a unique
119
120
  * value that can be used to distinguish individual
120
121
  * threads. */
121
- tid = (int)(intptr_t)pthread_self();
122
+ tid = (unsigned long)(uintptr_t)pthread_self();
122
123
  }
123
124
 
124
- return tl_tid = (unsigned int)tid;
125
+ return tl_tid = tid;
125
126
  }
@@ -51,21 +51,27 @@ static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
51
51
  }
52
52
  static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
53
53
  {
54
- return pthread_mutex_trylock(mutex) == 0;
54
+ int mutexIsLocked = pthread_mutex_trylock(mutex) == 0;
55
+ return mutexIsLocked;
55
56
  }
56
57
  static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
57
58
  {
58
59
  PTHREAD_CHECK(pthread_mutex_destroy(mutex));
59
60
  }
60
61
 
62
+ #define USBI_COND_INITIALIZER PTHREAD_COND_INITIALIZER
61
63
  typedef pthread_cond_t usbi_cond_t;
62
- void usbi_cond_init(pthread_cond_t *cond);
64
+ void usbi_cond_init(usbi_cond_t *cond);
63
65
  static inline void usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
64
66
  {
65
67
  PTHREAD_CHECK(pthread_cond_wait(cond, mutex));
66
68
  }
67
69
  int usbi_cond_timedwait(usbi_cond_t *cond,
68
70
  usbi_mutex_t *mutex, const struct timeval *tv);
71
+ static inline void usbi_cond_signal(usbi_cond_t *cond)
72
+ {
73
+ PTHREAD_CHECK(pthread_cond_signal(cond));
74
+ }
69
75
  static inline void usbi_cond_broadcast(usbi_cond_t *cond)
70
76
  {
71
77
  PTHREAD_CHECK(pthread_cond_broadcast(cond));
@@ -93,6 +99,6 @@ static inline void usbi_tls_key_delete(usbi_tls_key_t key)
93
99
  PTHREAD_CHECK(pthread_key_delete(key));
94
100
  }
95
101
 
96
- unsigned int usbi_get_tid(void);
102
+ unsigned long usbi_get_tid(void);
97
103
 
98
104
  #endif /* LIBUSB_THREADS_POSIX_H */