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.
- package/CHANGELOG.md +14 -0
- package/README.md +14 -0
- package/binding.gyp +2 -9
- package/dist/usb/bindings.d.ts +27 -2
- package/dist/usb/bindings.js.map +1 -1
- package/dist/usb/endpoint.js +1 -1
- package/dist/usb/endpoint.js.map +1 -1
- package/dist/usb/index.d.ts +0 -29
- package/dist/usb/index.js +4 -18
- package/dist/usb/index.js.map +1 -1
- package/dist/webusb/index.d.ts +1 -1
- package/dist/webusb/index.js +1 -1
- package/dist/webusb/index.js.map +1 -1
- package/dist/webusb/webusb-device.d.ts +4 -4
- package/dist/webusb/webusb-device.js +5 -2
- package/dist/webusb/webusb-device.js.map +1 -1
- package/libusb/.clang-tidy +36 -0
- package/libusb/.private/ci-build.sh +5 -1
- package/libusb/AUTHORS +21 -0
- package/libusb/ChangeLog +29 -2
- package/libusb/KEYS +123 -0
- package/libusb/README +8 -9
- package/libusb/Xcode/common.xcconfig +20 -0
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +16 -12
- package/libusb/android/examples/unrooted_android.c +1 -0
- package/libusb/configure.ac +12 -2
- package/libusb/examples/dpfp.c +1 -1
- package/libusb/examples/ezusb.c +6 -1
- package/libusb/examples/fxload.c +7 -5
- package/libusb/examples/hotplugtest.c +19 -11
- package/libusb/examples/listdevs.c +41 -3
- package/libusb/examples/testlibusb.c +1 -0
- package/libusb/examples/xusb.c +142 -77
- package/libusb/libusb/Makefile.am +4 -0
- package/libusb/libusb/core.c +183 -24
- package/libusb/libusb/descriptor.c +404 -96
- package/libusb/libusb/hotplug.c +27 -8
- package/libusb/libusb/io.c +10 -5
- package/libusb/libusb/libusb-1.0.def +14 -0
- package/libusb/libusb/libusb.h +179 -19
- package/libusb/libusb/libusbi.h +101 -25
- package/libusb/libusb/os/darwin_usb.c +216 -90
- package/libusb/libusb/os/darwin_usb.h +10 -8
- package/libusb/libusb/os/emscripten_webusb.cpp +38 -12
- package/libusb/libusb/os/events_posix.c +4 -4
- package/libusb/libusb/os/haiku_usb_raw.cpp +4 -0
- package/libusb/libusb/os/linux_usbfs.c +92 -33
- package/libusb/libusb/os/linux_usbfs.h +13 -3
- package/libusb/libusb/os/netbsd_usb.c +6 -4
- package/libusb/libusb/os/openbsd_usb.c +4 -2
- package/libusb/libusb/os/sunos_usb.c +7 -5
- package/libusb/libusb/os/threads_posix.c +20 -19
- package/libusb/libusb/os/threads_posix.h +9 -3
- package/libusb/libusb/os/threads_windows.h +4 -3
- package/libusb/libusb/os/windows_common.c +86 -1
- package/libusb/libusb/os/windows_common.h +20 -1
- package/libusb/libusb/os/windows_hotplug.c +321 -0
- package/libusb/libusb/os/windows_hotplug.h +28 -0
- package/libusb/libusb/os/windows_usbdk.c +16 -8
- package/libusb/libusb/os/windows_winusb.c +788 -56
- package/libusb/libusb/os/windows_winusb.h +11 -6
- package/libusb/libusb/sync.c +8 -5
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/msvc/Base.props +1 -1
- package/libusb/msvc/Configuration.Base.props +2 -1
- package/libusb/msvc/Configuration.DynamicLibrary.props +12 -0
- package/libusb/msvc/ProjectConfigurations.Base.props +69 -16
- package/libusb/msvc/build_all.ps1 +2 -2
- package/libusb/msvc/config.h +4 -0
- package/libusb/msvc/getopt/bits/getopt_core.h +96 -0
- package/libusb/msvc/getopt/bits/getopt_ext.h +77 -0
- package/libusb/msvc/getopt/features.h +21 -0
- package/libusb/msvc/getopt/getopt.c +456 -705
- package/libusb/msvc/getopt/getopt.h +16 -158
- package/libusb/msvc/getopt/getopt1.c +40 -69
- package/libusb/msvc/getopt/getopt_int.h +118 -0
- package/libusb/msvc/getopt/gettext.h +7 -0
- package/libusb/msvc/getopt/unistd.h +5 -0
- package/libusb/msvc/getopt.vcxproj +11 -4
- package/libusb/msvc/libusb.sln +515 -268
- package/libusb/msvc/libusb_dll.vcxproj +2 -0
- package/libusb/msvc/libusb_static.vcxproj +2 -0
- package/libusb/msvc/xusb.vcxproj +1 -1
- package/libusb/tests/Makefile.am +10 -1
- package/libusb/tests/fuzz/corpus/bos/min.bos +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/min_valid_config.bin +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_a_endpoint_null.bin +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_b_iad_oob.bin +0 -0
- package/libusb/tests/fuzz/fuzz_bos_descriptor.c +49 -0
- package/libusb/tests/fuzz/fuzz_descriptor_parsers.c +83 -0
- package/libusb/tests/macos.c +2 -2
- package/libusb/tests/stress_mt.c +6 -3
- package/libusb/tests/webusb-test-shim/index.js +6 -5
- package/libusb.gypi +5 -0
- package/package.json +3 -3
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-arm64/node.napi.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/{hotplug/libusb.cc → hotplug.cc} +2 -3
- package/src/{hotplug/hotplug.h → hotplug.h} +2 -6
- package/src/node_usb.cc +3 -3
- package/test/usb.coffee +4 -4
- package/test/webusb.coffee +22 -12
- 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
|
-
|
|
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
|
-
//
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
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
|
-
|
|
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(
|
|
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("
|
|
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 =
|
|
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
|
-
|
|
260
|
-
|
|
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
|
-
|
|
263
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
207
|
-
|
|
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
|
-
|
|
210
|
-
|
|
214
|
+
/* Wait 10ms for USB device path creation.*/
|
|
215
|
+
nanosleep(&delay_ts, NULL);
|
|
211
216
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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 &&
|
|
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
|
-
|
|
374
|
-
|
|
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
|
-
|
|
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
|
|
1326
|
-
|
|
1327
|
-
|
|
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,
|
|
1631
|
-
uint32_t num_streams, unsigned char *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
|
-
|
|
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 (
|
|
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,
|
|
98
|
-
start[
|
|
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
|
-
*(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
55
|
-
|
|
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
|
|
83
|
+
unsigned long usbi_get_tid(void)
|
|
83
84
|
{
|
|
84
|
-
static _Thread_local unsigned
|
|
85
|
-
|
|
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 = (
|
|
98
|
+
tid = (unsigned long)thread_id;
|
|
98
99
|
else
|
|
99
|
-
tid =
|
|
100
|
+
tid = ULONG_MAX;
|
|
100
101
|
#else
|
|
101
|
-
tid = (
|
|
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 = (
|
|
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 =
|
|
115
|
+
tid = ULONG_MAX;
|
|
115
116
|
#endif
|
|
116
117
|
|
|
117
|
-
if (tid ==
|
|
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 = (
|
|
122
|
+
tid = (unsigned long)(uintptr_t)pthread_self();
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
return tl_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
|
-
|
|
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(
|
|
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
|
|
102
|
+
unsigned long usbi_get_tid(void);
|
|
97
103
|
|
|
98
104
|
#endif /* LIBUSB_THREADS_POSIX_H */
|