usb 2.17.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 +6 -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/index.d.ts +0 -29
- package/dist/usb/index.js +4 -18
- package/dist/usb/index.js.map +1 -1
- package/libusb/.clang-tidy +5 -3
- package/libusb/.private/ci-build.sh +5 -1
- package/libusb/AUTHORS +14 -0
- package/libusb/ChangeLog +15 -2
- package/libusb/README +8 -5
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +4 -0
- package/libusb/configure.ac +12 -2
- package/libusb/examples/hotplugtest.c +19 -11
- package/libusb/examples/listdevs.c +41 -3
- package/libusb/examples/xusb.c +6 -1
- package/libusb/libusb/Makefile.am +4 -0
- package/libusb/libusb/core.c +175 -14
- package/libusb/libusb/descriptor.c +163 -14
- package/libusb/libusb/io.c +7 -3
- package/libusb/libusb/libusb-1.0.def +10 -0
- package/libusb/libusb/libusb.h +59 -9
- package/libusb/libusb/libusbi.h +89 -25
- package/libusb/libusb/os/darwin_usb.c +126 -46
- package/libusb/libusb/os/darwin_usb.h +10 -8
- package/libusb/libusb/os/emscripten_webusb.cpp +31 -10
- package/libusb/libusb/os/haiku_usb_raw.cpp +4 -0
- package/libusb/libusb/os/linux_usbfs.c +73 -25
- package/libusb/libusb/os/netbsd_usb.c +2 -0
- package/libusb/libusb/os/openbsd_usb.c +2 -0
- package/libusb/libusb/os/sunos_usb.c +2 -0
- package/libusb/libusb/os/threads_posix.c +3 -3
- package/libusb/libusb/os/threads_posix.h +8 -2
- package/libusb/libusb/os/threads_windows.h +2 -1
- 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 +753 -41
- package/libusb/libusb/os/windows_winusb.h +11 -6
- 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/stress_mt.c +2 -1
- package/libusb/tests/webusb-test-shim/index.js +6 -5
- package/libusb.gypi +5 -0
- package/package.json +1 -1
- 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
|
@@ -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
|
|
|
@@ -199,19 +201,25 @@ static int get_usbfs_fd(struct libusb_device *dev, int access_mode, int silent)
|
|
|
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) {
|
|
@@ -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;
|
|
@@ -1254,6 +1297,10 @@ static int usbfs_get_device_list(struct libusb_context *ctx)
|
|
|
1254
1297
|
buses = opendir(USB_DEVTMPFS_PATH);
|
|
1255
1298
|
|
|
1256
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
|
+
}
|
|
1257
1304
|
usbi_err(ctx, "opendir buses failed, errno=%d", errno);
|
|
1258
1305
|
return LIBUSB_ERROR_IO;
|
|
1259
1306
|
}
|
|
@@ -1331,10 +1378,10 @@ static int linux_default_scan_devices(struct libusb_context *ctx)
|
|
|
1331
1378
|
* any autosuspended USB devices. however, sysfs is not available
|
|
1332
1379
|
* everywhere, so we need a usbfs fallback too.
|
|
1333
1380
|
*/
|
|
1334
|
-
if (sysfs_available)
|
|
1335
|
-
return
|
|
1336
|
-
|
|
1337
|
-
|
|
1381
|
+
if (sysfs_available && sysfs_get_device_list(ctx) == LIBUSB_SUCCESS)
|
|
1382
|
+
return LIBUSB_SUCCESS;
|
|
1383
|
+
|
|
1384
|
+
return usbfs_get_device_list(ctx);
|
|
1338
1385
|
}
|
|
1339
1386
|
#endif
|
|
1340
1387
|
|
|
@@ -2760,7 +2807,7 @@ static int op_handle_events(struct libusb_context *ctx,
|
|
|
2760
2807
|
} while (r == 0);
|
|
2761
2808
|
}
|
|
2762
2809
|
|
|
2763
|
-
usbi_handle_disconnect(handle);
|
|
2810
|
+
usbi_handle_disconnect(ctx, handle);
|
|
2764
2811
|
continue;
|
|
2765
2812
|
}
|
|
2766
2813
|
|
|
@@ -2787,6 +2834,7 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
2787
2834
|
.init = op_init,
|
|
2788
2835
|
.exit = op_exit,
|
|
2789
2836
|
.set_option = op_set_option,
|
|
2837
|
+
.get_device_string = op_get_device_string,
|
|
2790
2838
|
.hotplug_poll = op_hotplug_poll,
|
|
2791
2839
|
.get_active_config_descriptor = op_get_active_config_descriptor,
|
|
2792
2840
|
.get_config_descriptor = op_get_config_descriptor,
|
|
@@ -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);
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
# include <sys/lwp.h>
|
|
39
39
|
#endif
|
|
40
40
|
|
|
41
|
-
void usbi_cond_init(
|
|
41
|
+
void usbi_cond_init(usbi_cond_t *cond)
|
|
42
42
|
{
|
|
43
43
|
#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
|
|
44
44
|
pthread_condattr_t condattr;
|
|
@@ -52,8 +52,8 @@ void usbi_cond_init(pthread_cond_t *cond)
|
|
|
52
52
|
#endif
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
int usbi_cond_timedwait(
|
|
56
|
-
|
|
55
|
+
int usbi_cond_timedwait(usbi_cond_t *cond,
|
|
56
|
+
usbi_mutex_t *mutex, const struct timeval *tv)
|
|
57
57
|
{
|
|
58
58
|
struct timespec timeout;
|
|
59
59
|
int r;
|
|
@@ -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));
|
|
@@ -50,7 +50,8 @@ static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
|
|
|
50
50
|
}
|
|
51
51
|
static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
|
|
52
52
|
{
|
|
53
|
-
|
|
53
|
+
int mutexIsLocked = TryEnterCriticalSection(mutex) != 0;
|
|
54
|
+
return mutexIsLocked;
|
|
54
55
|
}
|
|
55
56
|
static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
|
|
56
57
|
{
|
|
@@ -29,6 +29,10 @@
|
|
|
29
29
|
#include "libusbi.h"
|
|
30
30
|
#include "windows_common.h"
|
|
31
31
|
|
|
32
|
+
#if defined(LIBUSB_WINDOWS_HOTPLUG)
|
|
33
|
+
#include "windows_hotplug.h"
|
|
34
|
+
#endif
|
|
35
|
+
|
|
32
36
|
#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
|
|
33
37
|
|
|
34
38
|
#define STATUS_SUCCESS ((ULONG_PTR)0UL)
|
|
@@ -492,9 +496,11 @@ static unsigned __stdcall windows_iocp_thread(void *arg)
|
|
|
492
496
|
}
|
|
493
497
|
|
|
494
498
|
itransfer = TRANSFER_PRIV_TO_USBI_TRANSFER(transfer_priv);
|
|
499
|
+
#ifdef ENABLE_LOGGING
|
|
495
500
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
496
501
|
usbi_dbg(ctx, "transfer %p completed, length %lu",
|
|
497
502
|
transfer, ULONG_CAST(num_bytes));
|
|
503
|
+
#endif
|
|
498
504
|
usbi_signal_transfer_completion(itransfer);
|
|
499
505
|
}
|
|
500
506
|
|
|
@@ -565,6 +571,18 @@ static int windows_init(struct libusb_context *ctx)
|
|
|
565
571
|
|
|
566
572
|
r = LIBUSB_SUCCESS;
|
|
567
573
|
|
|
574
|
+
#if defined(LIBUSB_WINDOWS_HOTPLUG)
|
|
575
|
+
if (init_count == 1) {
|
|
576
|
+
r = windows_start_event_monitor(); // Start-up hotplug event handler
|
|
577
|
+
if (r != LIBUSB_SUCCESS) {
|
|
578
|
+
usbi_err(ctx, "error starting hotplug event monitor");
|
|
579
|
+
goto init_exit;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
windows_initial_scan_devices(ctx);
|
|
584
|
+
#endif
|
|
585
|
+
|
|
568
586
|
init_exit: // Holds semaphore here
|
|
569
587
|
if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
|
|
570
588
|
if (usbdk_available) {
|
|
@@ -596,6 +614,9 @@ static void windows_exit(struct libusb_context *ctx)
|
|
|
596
614
|
|
|
597
615
|
// Only works if exits and inits are balanced exactly
|
|
598
616
|
if (--init_count == 0) { // Last exit
|
|
617
|
+
#if defined(LIBUSB_WINDOWS_HOTPLUG)
|
|
618
|
+
windows_stop_event_monitor();
|
|
619
|
+
#endif
|
|
599
620
|
if (usbdk_available) {
|
|
600
621
|
usbdk_backend.exit(ctx);
|
|
601
622
|
usbdk_available = false;
|
|
@@ -624,11 +645,23 @@ static int windows_set_option(struct libusb_context *ctx, enum libusb_option opt
|
|
|
624
645
|
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
625
646
|
}
|
|
626
647
|
|
|
648
|
+
#if !defined(LIBUSB_WINDOWS_HOTPLUG)
|
|
627
649
|
static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
|
|
628
650
|
{
|
|
629
651
|
struct windows_context_priv *priv = usbi_get_context_priv(ctx);
|
|
630
652
|
return priv->backend->get_device_list(ctx, discdevs);
|
|
631
653
|
}
|
|
654
|
+
#endif
|
|
655
|
+
|
|
656
|
+
static int windows_get_device_string(libusb_device *dev,
|
|
657
|
+
enum libusb_device_string_type string_type, char *data, int length)
|
|
658
|
+
{
|
|
659
|
+
struct windows_context_priv* priv = usbi_get_context_priv(DEVICE_CTX(dev));
|
|
660
|
+
if (NULL != priv->backend->get_device_string) {
|
|
661
|
+
return priv->backend->get_device_string(dev, string_type, data, length);
|
|
662
|
+
}
|
|
663
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
664
|
+
}
|
|
632
665
|
|
|
633
666
|
static int windows_open(struct libusb_device_handle *dev_handle)
|
|
634
667
|
{
|
|
@@ -717,6 +750,37 @@ static void windows_destroy_device(struct libusb_device *dev)
|
|
|
717
750
|
priv->backend->destroy_device(dev);
|
|
718
751
|
}
|
|
719
752
|
|
|
753
|
+
static int windows_endpoint_supports_raw_io(libusb_device_handle* dev_handle,
|
|
754
|
+
uint8_t endpoint)
|
|
755
|
+
{
|
|
756
|
+
struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
|
|
757
|
+
if (priv->backend->endpoint_supports_raw_io)
|
|
758
|
+
return priv->backend->endpoint_supports_raw_io(dev_handle, endpoint);
|
|
759
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
static int windows_endpoint_set_raw_io(libusb_device_handle* dev_handle,
|
|
763
|
+
uint8_t endpoint, int enable)
|
|
764
|
+
{
|
|
765
|
+
struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
|
|
766
|
+
|
|
767
|
+
if (priv->backend->endpoint_supports_raw_io == NULL
|
|
768
|
+
|| priv->backend->endpoint_supports_raw_io(dev_handle, endpoint) != 1
|
|
769
|
+
|| priv->backend->endpoint_set_raw_io == NULL)
|
|
770
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
771
|
+
|
|
772
|
+
return priv->backend->endpoint_set_raw_io(dev_handle, endpoint, enable);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
static int windows_get_max_raw_io_transfer_size(struct libusb_device_handle *dev_handle,
|
|
776
|
+
uint8_t endpoint)
|
|
777
|
+
{
|
|
778
|
+
struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
|
|
779
|
+
if (priv->backend->get_max_raw_io_transfer_size)
|
|
780
|
+
return priv->backend->get_max_raw_io_transfer_size(dev_handle, endpoint);
|
|
781
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
782
|
+
}
|
|
783
|
+
|
|
720
784
|
static int windows_submit_transfer(struct usbi_transfer *itransfer)
|
|
721
785
|
{
|
|
722
786
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
@@ -800,15 +864,26 @@ static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
|
|
|
800
864
|
struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
|
|
801
865
|
enum libusb_transfer_status status, istatus;
|
|
802
866
|
DWORD result, bytes_transferred;
|
|
867
|
+
HANDLE transfer_handle;
|
|
868
|
+
|
|
869
|
+
/*
|
|
870
|
+
* The submit path runs with itransfer->lock held. Grab the handle under
|
|
871
|
+
* the same lock so we do not race with submission/completion bookkeeping.
|
|
872
|
+
*/
|
|
873
|
+
usbi_mutex_lock(&itransfer->lock);
|
|
874
|
+
transfer_handle = transfer_priv->handle;
|
|
875
|
+
usbi_mutex_unlock(&itransfer->lock);
|
|
803
876
|
|
|
804
|
-
if (GetOverlappedResult(
|
|
877
|
+
if (GetOverlappedResult(transfer_handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
|
|
805
878
|
result = NO_ERROR;
|
|
806
879
|
else
|
|
807
880
|
result = GetLastError();
|
|
808
881
|
|
|
882
|
+
#ifdef ENABLE_LOGGING
|
|
809
883
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
810
884
|
usbi_dbg(ctx, "handling transfer %p completion with errcode %lu, length %lu",
|
|
811
885
|
transfer, ULONG_CAST(result), ULONG_CAST(bytes_transferred));
|
|
886
|
+
#endif
|
|
812
887
|
|
|
813
888
|
switch (result) {
|
|
814
889
|
case NO_ERROR:
|
|
@@ -843,7 +918,9 @@ static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
|
|
|
843
918
|
break;
|
|
844
919
|
}
|
|
845
920
|
|
|
921
|
+
usbi_mutex_lock(&itransfer->lock);
|
|
846
922
|
transfer_priv->handle = NULL;
|
|
923
|
+
usbi_mutex_unlock(&itransfer->lock);
|
|
847
924
|
|
|
848
925
|
// Backend-specific cleanup
|
|
849
926
|
backend->clear_transfer_priv(itransfer);
|
|
@@ -888,7 +965,12 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
888
965
|
windows_init,
|
|
889
966
|
windows_exit,
|
|
890
967
|
windows_set_option,
|
|
968
|
+
#if defined(LIBUSB_WINDOWS_HOTPLUG)
|
|
969
|
+
NULL, /* get_device_list */
|
|
970
|
+
#else
|
|
891
971
|
windows_get_device_list,
|
|
972
|
+
#endif
|
|
973
|
+
windows_get_device_string,
|
|
892
974
|
NULL, /* hotplug_poll */
|
|
893
975
|
NULL, /* wrap_sys_device */
|
|
894
976
|
windows_open,
|
|
@@ -910,6 +992,9 @@ const struct usbi_os_backend usbi_backend = {
|
|
|
910
992
|
NULL, /* kernel_driver_active */
|
|
911
993
|
NULL, /* detach_kernel_driver */
|
|
912
994
|
NULL, /* attach_kernel_driver */
|
|
995
|
+
windows_endpoint_supports_raw_io,
|
|
996
|
+
windows_endpoint_set_raw_io,
|
|
997
|
+
windows_get_max_raw_io_transfer_size,
|
|
913
998
|
windows_destroy_device,
|
|
914
999
|
windows_submit_transfer,
|
|
915
1000
|
windows_cancel_transfer,
|
|
@@ -242,13 +242,23 @@ struct usbdk_device_priv {
|
|
|
242
242
|
|
|
243
243
|
struct winusb_device_priv {
|
|
244
244
|
bool initialized;
|
|
245
|
+
#if defined(LIBUSB_WINDOWS_HOTPLUG)
|
|
246
|
+
bool seen_during_scan; // set true for each device encountered during windows_get_device_list
|
|
247
|
+
bool seen_before_scan; // set true for each device encountered before windows_get_device_list
|
|
248
|
+
#endif
|
|
245
249
|
bool root_hub;
|
|
246
250
|
uint8_t active_config;
|
|
251
|
+
uint16_t langid; // cached USB language ID for string descriptor requests
|
|
247
252
|
uint8_t depth; // distance to HCD
|
|
248
253
|
const struct windows_usb_api_backend *apib;
|
|
249
254
|
char *dev_id;
|
|
250
255
|
char *path; // device interface path
|
|
251
256
|
int sub_api; // for WinUSB-like APIs
|
|
257
|
+
usbi_mutex_t interface_lock; // protects usb_interface[] against concurrent
|
|
258
|
+
// claim/release/altsetting from different handles,
|
|
259
|
+
// and concurrent enumeration setup
|
|
260
|
+
// (set_composite_interface, set_hid_interface,
|
|
261
|
+
// and HUB_PASS/DEV_PASS in winusb_get_device_list)
|
|
252
262
|
struct {
|
|
253
263
|
char *path; // each interface needs a device interface path,
|
|
254
264
|
const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support),
|
|
@@ -275,7 +285,7 @@ struct usbdk_device_handle_priv {
|
|
|
275
285
|
// Not currently used
|
|
276
286
|
char dummy;
|
|
277
287
|
};
|
|
278
|
-
|
|
288
|
+
|
|
279
289
|
enum WINUSB_ZLP {
|
|
280
290
|
WINUSB_ZLP_UNSET = 0,
|
|
281
291
|
WINUSB_ZLP_OFF = 1,
|
|
@@ -320,6 +330,8 @@ struct windows_backend {
|
|
|
320
330
|
void (*exit)(struct libusb_context *ctx);
|
|
321
331
|
int (*get_device_list)(struct libusb_context *ctx,
|
|
322
332
|
struct discovered_devs **discdevs);
|
|
333
|
+
int (*get_device_string)(libusb_device *dev,
|
|
334
|
+
enum libusb_device_string_type string_type, char *data, int length);
|
|
323
335
|
int (*open)(struct libusb_device_handle *dev_handle);
|
|
324
336
|
void (*close)(struct libusb_device_handle *dev_handle);
|
|
325
337
|
int (*get_active_config_descriptor)(struct libusb_device *device,
|
|
@@ -342,6 +354,13 @@ struct windows_backend {
|
|
|
342
354
|
int (*cancel_transfer)(struct usbi_transfer *itransfer);
|
|
343
355
|
void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
|
|
344
356
|
enum libusb_transfer_status (*copy_transfer_data)(struct usbi_transfer *itransfer, DWORD length);
|
|
357
|
+
int (*endpoint_supports_raw_io)(struct libusb_device_handle *dev_handle,
|
|
358
|
+
uint8_t endpoint);
|
|
359
|
+
int (*endpoint_set_raw_io)(struct libusb_device_handle *dev_handle,
|
|
360
|
+
uint8_t endpoint, int enable);
|
|
361
|
+
int (*get_max_raw_io_transfer_size)(
|
|
362
|
+
struct libusb_device_handle *dev_handle,
|
|
363
|
+
uint8_t endpoint);
|
|
345
364
|
};
|
|
346
365
|
|
|
347
366
|
struct windows_context_priv {
|