Merge "Upgrade libusb to de38189e8014fa393f4d8c1d9d3fdf5e2a95899d" into main
diff --git a/.clang-tidy b/.clang-tidy
index 6349aa8..1f59ae9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -2,19 +2,10 @@
Checks: "-*,\
boost-*,\
bugprone-*,\
--bugprone-assignment-in-if-condition,\
--bugprone-branch-clone,\
-bugprone-easily-swappable-parameters,\
--bugprone-implicit-widening-of-multiplication-result,\
--bugprone-macro-parentheses,\
--bugprone-misplaced-widening-cast,\
-bugprone-narrowing-conversions,\
--bugprone-reserved-identifier,\
-bugprone-signed-char-misuse,\
--bugprone-suspicious-string-compare,\
-bugprone-switch-missing-default-case,\
--bugprone-unsafe-functions,\
--bugprone-too-small-loop-variable,\
clang-analyzer-*,\
-clang-analyzer-core.NullDereference,\
-clang-analyzer-deadcode.DeadStores,\
@@ -36,12 +27,8 @@
-readability-else-after-return,\
-readability-identifier-length,\
-readability-function-cognitive-complexity,\
--readability-inconsistent-declaration-parameter-name,\
-readability-isolate-declaration,\
-readability-magic-numbers,\
--readability-non-const-parameter,\
--readability-uppercase-literal-suffix,\
--readability-misleading-indentation,\
"
#WarningsAsErrors: "*"
...
diff --git a/KEYS b/KEYS
new file mode 100644
index 0000000..06d0148
--- /dev/null
+++ b/KEYS
@@ -0,0 +1,123 @@
+This file contains the PGP keys of libusb release managers.
+
+Users:
+ pgp < KEYS
+or
+ gpg --import KEYS
+
+Maintainers:
+ pgp -kxa <your name> and append it to this file.
+or
+ (pgpk -ll <your name> && pgpk -xa <your name>) >> this file.
+or
+ (gpg --list-sigs <your name> && gpg --armor --export <your name>) >> this file.
+
+pub rsa4096 2020-06-23 [SC]
+ C68187379B23DE9EFC46651E2C80FF56C6830A0E
+uid [ultimate] Tormod Volden <[email protected]>
+sub rsa4096 2020-06-23 [E]
+sub rsa4096 2020-06-23 [S]
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=5EaQ
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/METADATA b/METADATA
index 6db0d54..ee4e958 100644
--- a/METADATA
+++ b/METADATA
@@ -1,6 +1,6 @@
# This project was upgraded with external_updater.
# Usage: tools/external_updater/updater.sh update external/libusb
-# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+# For more info, check https://cs.android.com/android/platform/superproject/main/+/main:tools/external_updater/README.md
name: "libusb"
description: "libusb is a library for USB device access from Linux, macOS, Windows, OpenBSD/NetBSD and Haiku userspace."
@@ -8,13 +8,13 @@
license_type: RESTRICTED
last_upgrade_date {
year: 2024
- month: 5
- day: 28
+ month: 11
+ day: 14
}
homepage: "https://libusb.info/"
identifier {
type: "Git"
value: "https://github.com/libusb/libusb"
- version: "2a138c6f12988c42eaa9dd663581faa700c44abe"
+ version: "de38189e8014fa393f4d8c1d9d3fdf5e2a95899d"
}
}
diff --git a/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj
index 4fe9462..680bc19 100644
--- a/Xcode/libusb.xcodeproj/project.pbxproj
+++ b/Xcode/libusb.xcodeproj/project.pbxproj
@@ -231,22 +231,22 @@
/* Begin PBXFileReference section */
006AD41C1C8C5A90007F8C6A /* hotplugtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = hotplugtest; sourceTree = BUILT_PRODUCTS_DIR; };
- 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+ 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
008A23C6236C8445004854AA /* stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stress.c; sourceTree = "<group>"; usesTabs = 1; };
008A23CA236C849A004854AA /* libusb_testlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libusb_testlib.h; sourceTree = "<group>"; usesTabs = 1; };
008A23CB236C849A004854AA /* testlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testlib.c; sourceTree = "<group>"; usesTabs = 1; };
008A23D3236C8594004854AA /* stress */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stress; sourceTree = BUILT_PRODUCTS_DIR; };
008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libusb-1.0.0.dylib"; sourceTree = BUILT_PRODUCTS_DIR; };
- 008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
- 008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
- 008FBF561628B7E800BC5BE2 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+ 008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
+ 008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
+ 008FBF561628B7E800BC5BE2 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
008FBF5A1628B7E800BC5BE2 /* libusb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF671628B7E800BC5BE2 /* libusbi.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusbi.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = darwin_usb.c; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = darwin_usb.h; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
008FBF741628B7E800BC5BE2 /* threads_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_posix.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF751628B7E800BC5BE2 /* threads_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_posix.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
- 008FBF7A1628B7E800BC5BE2 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+ 008FBF7A1628B7E800BC5BE2 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
008FBF7B1628B7E800BC5BE2 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF7C1628B7E800BC5BE2 /* version_nano.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version_nano.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFA41628B84200BC5BE2 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
@@ -264,7 +264,7 @@
008FC0051628BBDB00BC5BE2 /* dpfp_threaded */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dpfp_threaded; sourceTree = BUILT_PRODUCTS_DIR; };
008FC0151628BC0300BC5BE2 /* fxload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fxload; sourceTree = BUILT_PRODUCTS_DIR; };
008FC0261628BC6B00BC5BE2 /* listdevs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = listdevs; sourceTree = BUILT_PRODUCTS_DIR; };
- 1438D77817A2ED9F00166101 /* hotplug.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplug.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+ 1438D77817A2ED9F00166101 /* hotplug.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = hotplug.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
1438D77E17A2F0EA00166101 /* strerror.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = strerror.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
1443EE8416417E63007E0579 /* common.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = common.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
1443EE8516417E63007E0579 /* debug.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
@@ -278,17 +278,17 @@
14EC13E42B3D5BBE00CF9AD0 /* netbsd_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = netbsd_usb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13E52B3D5BBE00CF9AD0 /* events_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = events_windows.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13E62B3D5BBE00CF9AD0 /* haiku_usb_raw.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb_raw.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
- 14EC13E72B3D5BBE00CF9AD0 /* linux_netlink.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_netlink.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 14EC13E72B3D5BBE00CF9AD0 /* linux_netlink.c */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = linux_netlink.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
14EC13E82B3D5BBE00CF9AD0 /* haiku_usb_backend.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_backend.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13E92B3D5BBE00CF9AD0 /* haiku_usb_raw.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_usb_raw.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13EA2B3D5BBE00CF9AD0 /* linux_usbfs.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = linux_usbfs.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13EB2B3D5BBE00CF9AD0 /* sunos_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sunos_usb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
- 14EC13EC2B3D5BBE00CF9AD0 /* linux_udev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_udev.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 14EC13EC2B3D5BBE00CF9AD0 /* linux_udev.c */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = linux_udev.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
14EC13ED2B3D5BBE00CF9AD0 /* haiku_usb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = haiku_usb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13EE2B3D5BBE00CF9AD0 /* events_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = events_windows.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13EF2B3D5BBE00CF9AD0 /* null_usb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = null_usb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13F02B3D5BBE00CF9AD0 /* haiku_pollfs.cpp */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = haiku_pollfs.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
- 14EC13F12B3D5BBE00CF9AD0 /* linux_usbfs.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = linux_usbfs.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 14EC13F12B3D5BBE00CF9AD0 /* linux_usbfs.c */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = sourcecode.c.c; path = linux_usbfs.c; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
14EC13F22B3D5BC800CF9AD0 /* windows_common.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_common.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13F32B3D5BC800CF9AD0 /* threads_windows.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_windows.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13F42B3D5BC800CF9AD0 /* windows_winusb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_winusb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
@@ -297,10 +297,10 @@
14EC13F72B3D5BC800CF9AD0 /* threads_windows.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_windows.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13F82B3D5BC800CF9AD0 /* windows_usbdk.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = windows_usbdk.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
14EC13F92B3D5BC800CF9AD0 /* windows_usbdk.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = windows_usbdk.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
- 1472E1592B43D66B00850BA3 /* init_context.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = init_context.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 1472E1592B43D66B00850BA3 /* init_context.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = init_context.c; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
1472E15A2B43D68600850BA3 /* stress_mt.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = stress_mt.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
- 1472E15D2B43D68600850BA3 /* macos.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = macos.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
- 1472E15F2B43D68600850BA3 /* set_option.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = set_option.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 1472E15D2B43D68600850BA3 /* macos.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = macos.c; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
+ 1472E15F2B43D68600850BA3 /* set_option.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = set_option.c; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
1472E1602B43D69800850BA3 /* umockdev.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = umockdev.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
2018D95E24E453BA001589B2 /* events_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = events_posix.c; sourceTree = "<group>"; };
2018D96024E453D0001589B2 /* events_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = events_posix.h; sourceTree = "<group>"; };
diff --git a/examples/dpfp.c b/examples/dpfp.c
index 2949383..6a63cd9 100644
--- a/examples/dpfp.c
+++ b/examples/dpfp.c
@@ -388,7 +388,7 @@
return -1;
fputs("P5 384 289 255 ", f);
- (void)fwrite(data + 64, 1, 384*289, f);
+ (void)fwrite(data + 64, 1, 384L*289L, f);
fclose(f);
printf("saved image to %s\n", filename);
return 0;
diff --git a/examples/ezusb.c b/examples/ezusb.c
index 4bed12a..75cdd4f 100644
--- a/examples/ezusb.c
+++ b/examples/ezusb.c
@@ -815,7 +815,12 @@
}
/* at least write the interrupt vectors (at 0x0000) for reset! */
- rewind(image);
+ status = fseek(image, 0L, SEEK_SET);
+ if (status < 0) {
+ logerror("unable to rewind file %s\n", path);
+ ret = status;
+ goto exit;
+ }
if (verbose)
logerror("2nd stage: write on-chip memory\n");
status = parse_ihex(image, &ctx, is_external, ram_poke);
diff --git a/examples/fxload.c b/examples/fxload.c
index 2526083..0e5fdf4 100644
--- a/examples/fxload.c
+++ b/examples/fxload.c
@@ -38,7 +38,9 @@
#include <syslog.h>
static bool dosyslog = false;
#include <strings.h>
-#define _stricmp strcasecmp
+#define libusb_strcasecmp strcasecmp
+#else
+#define libusb_strcasecmp _stricmp
#endif
#ifndef FXLOAD_VERSION
@@ -263,13 +265,13 @@
for (i=0; i<ARRAYSIZE(path); i++) {
if (path[i] != NULL) {
ext = path[i] + strlen(path[i]) - 4;
- if ((_stricmp(ext, ".hex") == 0) || (strcmp(ext, ".ihx") == 0))
+ if ((libusb_strcasecmp(ext, ".hex") == 0) || (libusb_strcasecmp(ext, ".ihx") == 0))
img_type[i] = IMG_TYPE_HEX;
- else if (_stricmp(ext, ".iic") == 0)
+ else if (libusb_strcasecmp(ext, ".iic") == 0)
img_type[i] = IMG_TYPE_IIC;
- else if (_stricmp(ext, ".bix") == 0)
+ else if (libusb_strcasecmp(ext, ".bix") == 0)
img_type[i] = IMG_TYPE_BIX;
- else if (_stricmp(ext, ".img") == 0)
+ else if (libusb_strcasecmp(ext, ".img") == 0)
img_type[i] = IMG_TYPE_IMG;
else {
logerror("%s is not a recognized image type\n", path[i]);
diff --git a/examples/xusb.c b/examples/xusb.c
index 1ee4639..65c2d6a 100644
--- a/examples/xusb.c
+++ b/examples/xusb.c
@@ -66,7 +66,7 @@
va_end(args);
}
-#define ERR_EXIT(errcode) do { perr(" %s\n", libusb_strerror((enum libusb_error)errcode)); return -1; } while (0)
+#define ERR_EXIT(errcode) do { perr(" %s\n", libusb_strerror((enum libusb_error)(errcode))); return -1; } while (0)
#define CALL_CHECK(fcall) do { int _r=fcall; if (_r < 0) ERR_EXIT(_r); } while (0)
#define CALL_CHECK_CLOSE(fcall, hdl) do { int _r=fcall; if (_r < 0) { libusb_close(hdl); ERR_EXIT(_r); } } while (0)
#define B(x) (((x)!=0)?1:0)
@@ -546,11 +546,14 @@
get_sense(handle, endpoint_in, endpoint_out);
} else {
display_buffer_hex(data, size);
- if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) {
- if (fwrite(data, 1, (size_t)size, fd) != (unsigned int)size) {
- perr(" unable to write binary data\n");
+ if (binary_dump) {
+ fd = fopen(binary_name, "w");
+ if (fd != NULL) {
+ if (fwrite(data, 1, (size_t)size, fd) != (unsigned int)size) {
+ perr(" unable to write binary data\n");
+ }
+ fclose(fd);
}
- fclose(fd);
}
}
free(data);
@@ -559,16 +562,16 @@
}
// HID
-static int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int type)
+static int get_hid_record_size(const uint8_t *hid_report_descriptor, int size, int type)
{
- uint8_t i, j = 0;
+ uint8_t j = 0;
uint8_t offset;
int record_size[3] = {0, 0, 0};
unsigned int nb_bits = 0, nb_items = 0;
bool found_record_marker;
found_record_marker = false;
- for (i = hid_report_descriptor[0]+1; i < size; i += offset) {
+ for (int i = hid_report_descriptor[0]+1; i < size; i += offset) {
offset = (hid_report_descriptor[i]&0x03) + 1;
if (offset == 4)
offset = 5;
@@ -628,11 +631,14 @@
return -1;
}
display_buffer_hex(hid_report_descriptor, (unsigned int)descriptor_size);
- if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) {
- if (fwrite(hid_report_descriptor, 1, (size_t)descriptor_size, fd) != (size_t)descriptor_size) {
- printf(" Error writing descriptor to file\n");
+ if (binary_dump) {
+ fd = fopen(binary_name, "w");
+ if (fd != NULL) {
+ if (fwrite(hid_report_descriptor, 1, (size_t)descriptor_size, fd) != (size_t)descriptor_size) {
+ printf(" Error writing descriptor to file\n");
+ }
+ fclose(fd);
}
- fclose(fd);
}
size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE);
@@ -1077,9 +1083,25 @@
return 0;
}
+static void display_help(const char *progname)
+{
+ printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [-x] [-s] [-p] [-w] [vid:pid]\n", progname);
+ printf(" -h : display usage\n");
+ printf(" -d : enable debug output\n");
+ printf(" -i : print topology and speed info\n");
+ printf(" -j : test composite FTDI based JTAG device\n");
+ printf(" -k : test Mass Storage device\n");
+ printf(" -b file : dump Mass Storage data to file 'file'\n");
+ printf(" -p : test Sony PS3 SixAxis controller\n");
+ printf(" -s : test Microsoft Sidewinder Precision Pro (HID)\n");
+ printf(" -x : test Microsoft XBox Controller Type S\n");
+ printf(" -l lang : language to report errors in (ISO 639-1)\n");
+ printf(" -w : force the use of device requests when querying WCID descriptors\n");
+ printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n");
+}
+
int main(int argc, char** argv)
{
- bool show_help = false;
bool debug_mode = false;
const struct libusb_version* version;
int j, r;
@@ -1096,7 +1118,12 @@
if (((uint8_t*)&endian_test)[0] == 0xBE) {
printf("Despite their natural superiority for end users, big endian\n"
"CPUs are not supported with this program, sorry.\n");
- return 0;
+ return EXIT_FAILURE;
+ }
+
+ if ((argc == 1) || (argc > 7)) {
+ display_help(argv[0]);
+ return EXIT_FAILURE;
}
if (argc >= 2) {
@@ -1117,7 +1144,7 @@
case 'b':
if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) {
printf(" Option -b requires a file name\n");
- return 1;
+ return EXIT_FAILURE;
}
binary_name = argv[++j];
binary_dump = true;
@@ -1125,7 +1152,7 @@
case 'l':
if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) {
printf(" Option -l requires an ISO 639-1 language parameter\n");
- return 1;
+ return EXIT_FAILURE;
}
error_lang = argv[++j];
break;
@@ -1162,9 +1189,12 @@
PID = 0x0289;
test_mode = USE_XBOX;
break;
+ case 'h':
+ display_help(argv[0]);
+ return EXIT_SUCCESS;
default:
- show_help = true;
- break;
+ display_help(argv[0]);
+ return EXIT_FAILURE;
}
} else {
for (i=0; i<arglen; i++) {
@@ -1174,34 +1204,18 @@
if (i != arglen) {
if (sscanf(argv[j], "%x:%x" , &tmp_vid, &tmp_pid) != 2) {
printf(" Please specify VID & PID as \"vid:pid\" in hexadecimal format\n");
- return 1;
+ return EXIT_FAILURE;
}
VID = (uint16_t)tmp_vid;
PID = (uint16_t)tmp_pid;
} else {
- show_help = true;
+ display_help(argv[0]);
+ return EXIT_FAILURE;
}
}
}
}
- if ((show_help) || (argc == 1) || (argc > 7)) {
- printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [-x] [-s] [-p] [-w] [vid:pid]\n", argv[0]);
- printf(" -h : display usage\n");
- printf(" -d : enable debug output\n");
- printf(" -i : print topology and speed info\n");
- printf(" -j : test composite FTDI based JTAG device\n");
- printf(" -k : test Mass Storage device\n");
- printf(" -b file : dump Mass Storage data to file 'file'\n");
- printf(" -p : test Sony PS3 SixAxis controller\n");
- printf(" -s : test Microsoft Sidewinder Precision Pro (HID)\n");
- printf(" -x : test Microsoft XBox Controller Type S\n");
- printf(" -l lang : language to report errors in (ISO 639-1)\n");
- printf(" -w : force the use of device requests when querying WCID descriptors\n");
- printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n");
- return 0;
- }
-
version = libusb_get_version();
printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano);
@@ -1214,7 +1228,7 @@
}
if (r < 0)
- return r;
+ return EXIT_FAILURE;
// If not set externally, and no debug option was given, use info log level
if ((old_dbg_str == NULL) && (!debug_mode))
@@ -1225,14 +1239,18 @@
printf("Invalid or unsupported locale '%s': %s\n", error_lang, libusb_strerror((enum libusb_error)r));
}
- test_device(VID, PID);
+ r = test_device(VID, PID);
libusb_exit(NULL);
+ if (r < 0)
+ return EXIT_FAILURE;
+
+
if (debug_mode) {
snprintf(str, sizeof(str), "LIBUSB_DEBUG=%s", (old_dbg_str == NULL)?"":old_dbg_str);
str[sizeof(str) - 1] = 0; // Windows may not NUL terminate the string
}
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/libusb/core.c b/libusb/core.c
index 7461737..676c397 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -2380,14 +2380,19 @@
*/
static enum libusb_log_level get_env_debug_level(void)
{
+ enum libusb_log_level level = LIBUSB_LOG_LEVEL_NONE;
const char *dbg = getenv("LIBUSB_DEBUG");
- enum libusb_log_level level;
if (dbg) {
- int dbg_level = atoi(dbg);
+ char *end = NULL;
+ long dbg_level = strtol(dbg, &end, 10);
+ if (dbg == end ||
+ *end != '\0' ||
+ dbg_level < LIBUSB_LOG_LEVEL_NONE ||
+ dbg_level > LIBUSB_LOG_LEVEL_DEBUG) {
+ usbi_warn(NULL, "LIBUSB_DEBUG is invalid or out of range; clamping");
+ }
dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG);
level = (enum libusb_log_level)dbg_level;
- } else {
- level = LIBUSB_LOG_LEVEL_NONE;
}
return level;
}
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index 493507f..e8f9581 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -30,54 +30,18 @@
* for detected devices
*/
-#define READ_LE16(p) ((uint16_t) \
- (((uint16_t)((p)[1]) << 8) | \
- ((uint16_t)((p)[0]))))
-
-#define READ_LE32(p) ((uint32_t) \
- (((uint32_t)((p)[3]) << 24) | \
- ((uint32_t)((p)[2]) << 16) | \
- ((uint32_t)((p)[1]) << 8) | \
- ((uint32_t)((p)[0]))))
-
-static void parse_descriptor(const void *source, const char *descriptor, void *dest)
+static inline uint16_t ReadLittleEndian16(const uint8_t p[2])
{
- const uint8_t *sp = source;
- uint8_t *dp = dest;
- char field_type;
+ return (uint16_t)((uint16_t)p[1] << 8 |
+ (uint16_t)p[0]);
+}
- while (*descriptor) {
- field_type = *descriptor++;
- switch (field_type) {
- case 'b': /* 8-bit byte */
- *dp++ = *sp++;
- break;
- case 'w': /* 16-bit word, convert from little endian to CPU */
- dp += ((uintptr_t)dp & 1); /* Align to 16-bit word boundary */
-
- *((uint16_t *)dp) = READ_LE16(sp);
- sp += 2;
- dp += 2;
- break;
- case 'd': /* 32-bit word, convert from little endian to CPU (4-byte align dst before write). */
- dp += 4 - ((uintptr_t)dp & 3); /* Align to 32-bit word boundary */
-
- *((uint32_t *)dp) = READ_LE32(sp);
- sp += 4;
- dp += 4;
- break;
- case 'i': /* 32-bit word, convert from little endian to CPU (no dst alignment before write) */
- *((uint32_t *)dp) = READ_LE32(sp);
- sp += 4;
- dp += 4;
- break;
- case 'u': /* 16 byte UUID */
- memcpy(dp, sp, 16);
- sp += 16;
- dp += 16;
- break;
- }
- }
+static inline uint32_t ReadLittleEndian32(const uint8_t p[4])
+{
+ return (uint32_t)((uint32_t)p[3] << 24 |
+ (uint32_t)p[2] << 16 |
+ (uint32_t)p[1] << 8 |
+ (uint32_t)p[0]);
}
static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
@@ -92,7 +56,6 @@
const uint8_t *begin;
void *extra;
int parsed = 0;
- int len;
if (size < DESC_HEADER_LENGTH) {
usbi_err(ctx, "short endpoint descriptor read %d/%d",
@@ -114,10 +77,16 @@
return parsed;
}
- if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE)
- parse_descriptor(buffer, "bbbbwbbb", endpoint);
- else
- parse_descriptor(buffer, "bbbbwb", endpoint);
+ endpoint->bLength = buffer[0];
+ endpoint->bDescriptorType = buffer[1];
+ endpoint->bEndpointAddress = buffer[2];
+ endpoint->bmAttributes = buffer[3];
+ endpoint->wMaxPacketSize = ReadLittleEndian16(&buffer[4]);
+ endpoint->bInterval = buffer[6];
+ if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE) {
+ endpoint->bRefresh = buffer[7];
+ endpoint->bSynchAddress = buffer[8];
+ }
buffer += header->bLength;
size -= header->bLength;
@@ -153,7 +122,7 @@
/* Copy any unknown descriptors into a storage area for drivers */
/* to later parse */
- len = (int)(buffer - begin);
+ ptrdiff_t len = buffer - begin;
if (len <= 0)
return parsed;
@@ -163,7 +132,7 @@
memcpy(extra, begin, (size_t)len);
endpoint->extra = extra;
- endpoint->extra_length = len;
+ endpoint->extra_length = (int)len;
return parsed;
}
@@ -196,7 +165,6 @@
static int parse_interface(libusb_context *ctx,
struct libusb_interface *usb_interface, const uint8_t *buffer, int size)
{
- int len;
int r;
int parsed = 0;
int interface_number = -1;
@@ -217,7 +185,15 @@
usb_interface->altsetting = altsetting;
ifp = altsetting + usb_interface->num_altsetting;
- parse_descriptor(buffer, "bbbbbbbbb", ifp);
+ ifp->bLength = buffer[0];
+ ifp->bDescriptorType = buffer[1];
+ ifp->bInterfaceNumber = buffer[2];
+ ifp->bAlternateSetting = buffer[3];
+ ifp->bNumEndpoints = buffer[4];
+ ifp->bInterfaceClass = buffer[5];
+ ifp->bInterfaceSubClass = buffer[6];
+ ifp->bInterfaceProtocol = buffer[7];
+ ifp->iInterface = buffer[8];
if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
@@ -282,7 +258,7 @@
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
- len = (int)(buffer - begin);
+ ptrdiff_t len = buffer - begin;
if (len > 0) {
void *extra = malloc((size_t)len);
@@ -293,7 +269,7 @@
memcpy(extra, begin, (size_t)len);
ifp->extra = extra;
- ifp->extra_length = len;
+ ifp->extra_length = (int)len;
}
if (ifp->bNumEndpoints > 0) {
@@ -363,7 +339,14 @@
return LIBUSB_ERROR_IO;
}
- parse_descriptor(buffer, "bbwbbbbb", config);
+ config->bLength = buffer[0];
+ config->bDescriptorType = buffer[1];
+ config->wTotalLength = ReadLittleEndian16(&buffer[2]);
+ config->bNumInterfaces = buffer[4];
+ config->bConfigurationValue = buffer[5];
+ config->iConfiguration = buffer[6];
+ config->bmAttributes = buffer[7];
+ config->MaxPower = buffer[8];
if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
config->bDescriptorType, LIBUSB_DT_CONFIG);
@@ -390,7 +373,6 @@
size -= config->bLength;
for (i = 0; i < config->bNumInterfaces; i++) {
- int len;
const uint8_t *begin;
/* Skip over the rest of the Class Specific or Vendor */
@@ -426,10 +408,10 @@
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
- len = (int)(buffer - begin);
+ ptrdiff_t len = buffer - begin;
if (len > 0) {
uint8_t *extra = realloc((void *)config->extra,
- (size_t)(config->extra_length + len));
+ (size_t)(config->extra_length) + (size_t)len);
if (!extra) {
r = LIBUSB_ERROR_NO_MEM;
@@ -438,10 +420,10 @@
memcpy(extra + config->extra_length, begin, (size_t)len);
config->extra = extra;
- config->extra_length += len;
+ config->extra_length += (int)len;
}
- r = parse_interface(ctx, usb_interface + i, buffer, size);
+ r = parse_interface(ctx, usb_interface + i, buffer, (int)size);
if (r < 0)
goto err;
if (r == 0) {
@@ -712,14 +694,14 @@
const struct libusb_endpoint_descriptor *endpoint,
struct libusb_ss_endpoint_companion_descriptor **ep_comp)
{
- struct usbi_descriptor_header *header;
+ const struct usbi_descriptor_header *header;
const uint8_t *buffer = endpoint->extra;
int size = endpoint->extra_length;
*ep_comp = NULL;
while (size >= DESC_HEADER_LENGTH) {
- header = (struct usbi_descriptor_header *)buffer;
+ header = (const struct usbi_descriptor_header *)buffer;
if (header->bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
if (header->bLength < DESC_HEADER_LENGTH) {
usbi_err(ctx, "invalid descriptor length %u",
@@ -742,7 +724,11 @@
*ep_comp = malloc(sizeof(**ep_comp));
if (!*ep_comp)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(buffer, "bbbbw", *ep_comp);
+ (*ep_comp)->bLength = buffer[0];
+ (*ep_comp)->bDescriptorType = buffer[1];
+ (*ep_comp)->bMaxBurst = buffer[2];
+ (*ep_comp)->bmAttributes = buffer[3];
+ (*ep_comp)->wBytesPerInterval = ReadLittleEndian16(&buffer[4]);
return LIBUSB_SUCCESS;
}
return LIBUSB_ERROR_NOT_FOUND;
@@ -795,7 +781,10 @@
if (!_bos)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(buffer, "bbwb", _bos);
+ _bos->bLength = buffer[0];
+ _bos->bDescriptorType = buffer[1];
+ _bos->wTotalLength = ReadLittleEndian16(&buffer[2]);
+ _bos->bNumDeviceCaps = buffer[4];
buffer += _bos->bLength;
size -= _bos->bLength;
@@ -915,7 +904,7 @@
*
* \param ctx the context to operate on, or NULL for the default context
* \param dev_cap Device Capability descriptor with a bDevCapabilityType of
- * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
+ * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION
* LIBUSB_BT_USB_2_0_EXTENSION
* \param usb_2_0_extension output location for the USB 2.0 Extension
* descriptor. Only valid if 0 was returned. Must be freed with
@@ -945,7 +934,10 @@
if (!_usb_2_0_extension)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbd", _usb_2_0_extension);
+ _usb_2_0_extension->bLength = dev_cap->bLength;
+ _usb_2_0_extension->bDescriptorType = dev_cap->bDescriptorType;
+ _usb_2_0_extension->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _usb_2_0_extension->bmAttributes = ReadLittleEndian32(dev_cap->dev_capability_data);
*usb_2_0_extension = _usb_2_0_extension;
return LIBUSB_SUCCESS;
@@ -970,7 +962,7 @@
*
* \param ctx the context to operate on, or NULL for the default context
* \param dev_cap Device Capability descriptor with a bDevCapabilityType of
- * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
+ * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
* LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
* \param ss_usb_device_cap output location for the SuperSpeed USB Device
* Capability descriptor. Only valid if 0 was returned. Must be freed with
@@ -1000,24 +992,48 @@
if (!_ss_usb_device_cap)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbbwbbw", _ss_usb_device_cap);
+ _ss_usb_device_cap->bLength = dev_cap->bLength;
+ _ss_usb_device_cap->bDescriptorType = dev_cap->bDescriptorType;
+ _ss_usb_device_cap->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _ss_usb_device_cap->bmAttributes = dev_cap->dev_capability_data[0];
+ _ss_usb_device_cap->wSpeedSupported = ReadLittleEndian16(&dev_cap->dev_capability_data[1]);
+ _ss_usb_device_cap->bFunctionalitySupport = dev_cap->dev_capability_data[3];
+ _ss_usb_device_cap->bU1DevExitLat = dev_cap->dev_capability_data[4];
+ _ss_usb_device_cap->bU2DevExitLat = ReadLittleEndian16(&dev_cap->dev_capability_data[5]);
*ss_usb_device_cap = _ss_usb_device_cap;
return LIBUSB_SUCCESS;
}
-/* We use this private struct only to parse a SuperSpeedPlus device capability
- descriptor according to section 9.6.2.5 of the USB 3.1 specification.
- We don't expose it. */
+/// @cond DEV
+/** \internal \ingroup libusb_desc
+ * We use this private struct only to parse a SuperSpeedPlus device capability
+ * descriptor according to section 9.6.2.5 of the USB 3.1 specification.
+ * We don't expose it.
+ */
struct internal_ssplus_capability_descriptor {
+ /** The length of the descriptor. Must be equal to LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE */
uint8_t bLength;
+
+ /** The type of the descriptor */
uint8_t bDescriptorType;
+
+ /** Must be equal to LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY */
uint8_t bDevCapabilityType;
+
+ /** Unused */
uint8_t bReserved;
+
+ /** Contains the number of SublinkSpeedIDs */
uint32_t bmAttributes;
+
+ /** Contains the ssid, minRxLaneCount, and minTxLaneCount */
uint16_t wFunctionalitySupport;
+
+ /** Unused */
uint16_t wReserved;
};
+/// @endcond
int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
libusb_context *ctx,
@@ -1041,8 +1057,14 @@
return LIBUSB_ERROR_IO;
}
- /* We can only parse the non-variable size part of the SuperSpeedPlus descriptor. The attributes have to be read "manually". */
- parse_descriptor(dev_cap, "bbbbiww", &parsedDescriptor);
+ const uint8_t* dev_capability_data = dev_cap->dev_capability_data;
+ parsedDescriptor.bLength = dev_cap->bLength;
+ parsedDescriptor.bDescriptorType = dev_cap->bDescriptorType;
+ parsedDescriptor.bDevCapabilityType = dev_cap->bDevCapabilityType;
+ parsedDescriptor.bReserved = dev_capability_data[0];
+ parsedDescriptor.bmAttributes = ReadLittleEndian32(&dev_capability_data[1]);
+ parsedDescriptor.wFunctionalitySupport = ReadLittleEndian16(&dev_capability_data[5]);
+ parsedDescriptor.wReserved = ReadLittleEndian16(&dev_capability_data[7]);
uint8_t numSublikSpeedAttributes = (parsedDescriptor.bmAttributes & 0xF) + 1;
_ssplus_cap = malloc(sizeof(struct libusb_ssplus_usb_device_capability_descriptor) + numSublikSpeedAttributes * sizeof(struct libusb_ssplus_sublink_attribute));
@@ -1067,7 +1089,7 @@
/* Read the attributes */
uint8_t* base = ((uint8_t*)dev_cap) + LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE;
for(uint8_t i = 0 ; i < _ssplus_cap->numSublinkSpeedAttributes ; i++) {
- uint32_t attr = READ_LE32(base + i * sizeof(uint32_t));
+ uint32_t attr = ReadLittleEndian32(base + i * sizeof(uint32_t));
_ssplus_cap->sublinkSpeedAttributes[i].ssid = attr & 0x0f;
_ssplus_cap->sublinkSpeedAttributes[i].mantissa = attr >> 16;
_ssplus_cap->sublinkSpeedAttributes[i].exponent = (attr >> 4) & 0x3 ;
@@ -1108,7 +1130,7 @@
*
* \param ctx the context to operate on, or NULL for the default context
* \param dev_cap Device Capability descriptor with a bDevCapabilityType of
- * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
+ * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID
* LIBUSB_BT_CONTAINER_ID
* \param container_id output location for the Container ID descriptor.
* Only valid if 0 was returned. Must be freed with
@@ -1137,7 +1159,11 @@
if (!_container_id)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbbu", _container_id);
+ _container_id->bLength = dev_cap->bLength;
+ _container_id->bDescriptorType = dev_cap->bDescriptorType;
+ _container_id->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _container_id->bReserved = dev_cap->dev_capability_data[0];
+ memcpy(_container_id->ContainerID, &dev_cap->dev_capability_data[1], 16);
*container_id = _container_id;
return LIBUSB_SUCCESS;
@@ -1164,7 +1190,7 @@
*
* \param ctx the context to operate on, or NULL for the default context
* \param dev_cap Device Capability descriptor with a bDevCapabilityType of
- * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
+ * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
* LIBUSB_BT_PLATFORM_DESCRIPTOR
* \param platform_descriptor output location for the Platform descriptor.
* Only valid if 0 was returned. Must be freed with
@@ -1193,13 +1219,17 @@
if (!_platform_descriptor)
return LIBUSB_ERROR_NO_MEM;
- parse_descriptor(dev_cap, "bbbbu", _platform_descriptor);
+ _platform_descriptor->bLength = dev_cap->bLength;
+ _platform_descriptor->bDescriptorType = dev_cap->bDescriptorType;
+ _platform_descriptor->bDevCapabilityType = dev_cap->bDevCapabilityType;
+ _platform_descriptor->bReserved = dev_cap->dev_capability_data[0];
+ memcpy(_platform_descriptor->PlatformCapabilityUUID, &(dev_cap->dev_capability_data[1]), 16);
- /* Capability data is located after reserved byte and 128-bit UUID */
+ /* Capability data is located after reserved byte and 16 byte UUID */
uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16;
/* Capability data length is total descriptor length minus initial fields */
- size_t capability_data_length = _platform_descriptor->bLength - (16 + 4);
+ size_t capability_data_length = dev_cap->bLength - (3 + 1 + 16);
memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length);
@@ -1255,9 +1285,7 @@
r = libusb_get_string_descriptor(dev_handle, 0, 0, str.buf, 4);
if (r < 0)
return r;
- else if (r != 4 || str.desc.bLength < 4)
- return LIBUSB_ERROR_IO;
- else if (str.desc.bDescriptorType != LIBUSB_DT_STRING)
+ else if (r != 4 || str.desc.bLength < 4 || str.desc.bDescriptorType != LIBUSB_DT_STRING)
return LIBUSB_ERROR_IO;
else if (str.desc.bLength & 1)
usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for language ID string descriptor", str.desc.bLength);
@@ -1266,9 +1294,7 @@
r = libusb_get_string_descriptor(dev_handle, desc_index, langid, str.buf, sizeof(str.buf));
if (r < 0)
return r;
- else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r)
- return LIBUSB_ERROR_IO;
- else if (str.desc.bDescriptorType != LIBUSB_DT_STRING)
+ else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r || str.desc.bDescriptorType != LIBUSB_DT_STRING)
return LIBUSB_ERROR_IO;
else if ((str.desc.bLength & 1) || str.desc.bLength != r)
usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor (read %d)", str.desc.bLength, r);
@@ -1314,12 +1340,18 @@
/* First pass: Iterate through desc list, count number of IADs */
iad_array->length = 0;
while (consumed < size) {
- parse_descriptor(buf, "bb", &header);
- if (header.bLength < 2) {
+ header.bLength = buf[0];
+ header.bDescriptorType = buf[1];
+ if (header.bLength < DESC_HEADER_LENGTH) {
usbi_err(ctx, "invalid descriptor bLength %d",
header.bLength);
return LIBUSB_ERROR_IO;
}
+ else if (header.bLength > size) {
+ usbi_warn(ctx, "short config descriptor read %d/%u",
+ size, header.bLength);
+ return LIBUSB_ERROR_IO;
+ }
if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
iad_array->length++;
buf += header.bLength;
@@ -1335,15 +1367,29 @@
iad_array->iad = iad;
/* Second pass: Iterate through desc list, fill IAD structures */
- consumed = 0;
+ int remaining = size;
i = 0;
- while (consumed < size) {
- parse_descriptor(buffer, "bb", &header);
- if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
- parse_descriptor(buffer, "bbbbbbbb", &iad[i++]);
- buffer += header.bLength;
- consumed += header.bLength;
- }
+ do {
+ header.bLength = buffer[0];
+ header.bDescriptorType = buffer[1];
+ if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION && (remaining >= LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE)) {
+ iad[i].bLength = buffer[0];
+ iad[i].bDescriptorType = buffer[1];
+ iad[i].bFirstInterface = buffer[2];
+ iad[i].bInterfaceCount = buffer[3];
+ iad[i].bFunctionClass = buffer[4];
+ iad[i].bFunctionSubClass = buffer[5];
+ iad[i].bFunctionProtocol = buffer[6];
+ iad[i].iFunction = buffer[7];
+ i++;
+ }
+
+ remaining -= header.bLength;
+ if (remaining < DESC_HEADER_LENGTH) {
+ break;
+ }
+ buffer += header.bLength;
+ } while (1);
}
return LIBUSB_SUCCESS;
diff --git a/libusb/libusb.h b/libusb/libusb.h
index fa1ca6b..f0f15ca 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -335,6 +335,7 @@
#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6
#define LIBUSB_DT_BOS_SIZE 5
#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3
+#define LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE 8
/* BOS descriptor sizes */
#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7
@@ -565,7 +566,7 @@
/** Platform descriptor */
LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05,
- /* SuperSpeedPlus device capability */
+ /** SuperSpeedPlus device capability */
LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY = 0x0A,
};
@@ -931,7 +932,7 @@
uint8_t bDescriptorType;
/** Capability type. Will have value
- * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
+ * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION
* LIBUSB_BT_USB_2_0_EXTENSION in this context. */
uint8_t bDevCapabilityType;
@@ -957,7 +958,7 @@
uint8_t bDescriptorType;
/** Capability type. Will have value
- * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
+ * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
* LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */
uint8_t bDevCapabilityType;
@@ -1074,7 +1075,7 @@
/** This field indicates the minimum transmit lane count*/
uint8_t minTxLaneCount;
- /** num attrtibutes= \ref libusb_ssplus_usb_device_capability_descriptor.numSublinkSpeedAttributes= */
+ /** Array size is \ref libusb_ssplus_usb_device_capability_descriptor.numSublinkSpeedAttributes */
struct libusb_ssplus_sublink_attribute sublinkSpeedAttributes[];
};
@@ -1093,7 +1094,7 @@
uint8_t bDescriptorType;
/** Capability type. Will have value
- * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
+ * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID
* LIBUSB_BT_CONTAINER_ID in this context. */
uint8_t bDevCapabilityType;
@@ -1118,7 +1119,7 @@
uint8_t bDescriptorType;
/** Capability type. Will have value
- * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
+ * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
* LIBUSB_BT_CONTAINER_ID in this context. */
uint8_t bDevCapabilityType;
@@ -1682,7 +1683,7 @@
void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode);
const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
int LIBUSB_CALL libusb_has_capability(uint32_t capability);
-const char * LIBUSB_CALL libusb_error_name(int errcode);
+const char * LIBUSB_CALL libusb_error_name(int error_code);
int LIBUSB_CALL libusb_setlocale(const char *locale);
const char * LIBUSB_CALL libusb_strerror(int errcode);
@@ -2142,16 +2143,16 @@
/* sync I/O */
int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,
- uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
+ uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char *data, uint16_t wLength, unsigned int timeout);
int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *data, int length,
- int *actual_length, unsigned int timeout);
+ int *transferred, unsigned int timeout);
int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *data, int length,
- int *actual_length, unsigned int timeout);
+ int *transferred, unsigned int timeout);
/** \ingroup libusb_desc
* Retrieve a descriptor from the default control pipe.
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index 7bb496b..6f64c3e 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -252,7 +252,7 @@
uint8_t number;
uint8_t direction;
uint8_t transfer_type;
- uint16_t max_packet_size;
+ uint16_t max_packet_size; // without multipliers, not "full"
uint8_t interval;
};
typedef struct darwin_pipe_properties darwin_pipe_properties_t;
@@ -262,8 +262,16 @@
#if (MAX_INTERFACE_VERSION >= 550)
if (get_interface_interface_version() >= 550) {
+ // GetPipePropertiesV3 returns a "cooked" wMaxPacketSize (premultiplied by burst and mul). This not what we want.
+ // We only call GetPipePropertiesV3 to fill the fields needed to call GetEndpointPropertiesV3.
IOUSBEndpointProperties pipe_properties = {.bVersion = kUSBEndpointPropertiesVersion3};
kresult = (*IOINTERFACE_V(cInterface, 550))->GetPipePropertiesV3 (IOINTERFACE(cInterface), pipe, &pipe_properties);
+ if (kIOReturnSuccess != kresult) {
+ return kresult;
+ }
+
+ // GetEndpointPropertiesV3 returns the wMaxPacketSize without burst and mul multipliers.
+ kresult = (*IOINTERFACE_V(cInterface, 550))->GetEndpointPropertiesV3 (IOINTERFACE(cInterface), &pipe_properties);
if (kIOReturnSuccess == kresult) {
out->number = pipe_properties.bEndpointNumber;
out->direction = pipe_properties.bDirection;
@@ -274,9 +282,26 @@
return kresult;
}
#endif
- return (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction,
+ // GetPipeProperties returns a "cooked" version of max_packet_size which includes burst and mul. What we want is the
+ // original maxPacketSize so we can send zero-length packet when requested by users.
+ // We only call GetPipeProperties to retrieve the parameters needed to call GetEndpointProperties.
+ kresult = (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction,
&out->number, &out->transfer_type, &out->max_packet_size,
&out->interval);
+ if (kIOReturnSuccess != kresult) {
+ return kresult;
+ }
+
+ // To call GetEndpointProperties we also need altSetting
+ UInt8 altSetting;
+ kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting(IOINTERFACE(cInterface), &altSetting);
+ if (kIOReturnSuccess != kresult) {
+ return kresult;
+ }
+ // Retrieve "uncooked" version of maxPacketSize
+ return (*IOINTERFACE(cInterface))->GetEndpointProperties(IOINTERFACE(cInterface), altSetting, out->number,
+ out->direction, &out->transfer_type, &out->max_packet_size,
+ &out->interval);
}
#if defined(ENABLE_LOGGING)
@@ -694,7 +719,7 @@
static void darwin_hotplug_poll (void)
{
/* not sure if 1 ms will be too long/short but it should work ok */
- mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000ul};
+ mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000UL};
/* since a kernel thread may notify the IOIterators used for
* hotplug notification we can't just clear the iterators.
@@ -2123,7 +2148,7 @@
/* compare descriptors */
usbi_dbg (ctx, "darwin/reenumerate_device: checking whether descriptors changed");
- if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
+ if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor)) != 0) {
/* device descriptor changed. need to return not found. */
usbi_dbg (ctx, "darwin/reenumerate_device: device descriptor changed");
return LIBUSB_ERROR_NOT_FOUND;
@@ -2131,7 +2156,7 @@
for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
(void) (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
- if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
+ if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i])) != 0) {
usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -2409,10 +2434,10 @@
if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
/* Full speed */
- cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1));
+ cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1));
else
/* High/super speed */
- cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)) / 8;
+ cInterface->frames[transfer->endpoint] = frame + (UInt64)transfer->num_iso_packets * (1UL << (pipe_properties.interval - 1)) / 8;
if (kresult != kIOReturnSuccess) {
usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
@@ -2701,7 +2726,8 @@
/* find the minimum number of supported streams on the endpoint list */
for (i = 0 ; i < num_endpoints ; ++i) {
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) {
+ rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
+ if (0 != rc) {
return rc;
}
@@ -2734,7 +2760,8 @@
int rc;
for (int i = 0 ; i < num_endpoints ; ++i) {
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface)))
+ rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
+ if (0 != rc)
return rc;
(*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams);
diff --git a/libusb/os/emscripten_webusb.cpp b/libusb/os/emscripten_webusb.cpp
index ced9ad8..0d7fec9 100644
--- a/libusb/os/emscripten_webusb.cpp
+++ b/libusb/os/emscripten_webusb.cpp
@@ -586,12 +586,17 @@
}
val getDeviceList(libusb_context* ctx, discovered_devs** devs) {
+ // Check if browser supports USB
+ val navigator_usb = val::global("navigator")["usb"];
+ if (navigator_usb == val::undefined()) {
+ co_return (int) LIBUSB_ERROR_NOT_SUPPORTED;
+ }
// C++ equivalent of `await navigator.usb.getDevices()`. Note: at this point
// we must already have some devices exposed - caller must have called
// `await navigator.usb.requestDevice(...)` in response to user interaction
// before going to LibUSB. Otherwise this list will be empty.
auto web_usb_devices =
- co_await_try(val::global("navigator")["usb"].call<val>("getDevices"));
+ co_await_try(navigator_usb.call<val>("getDevices"));
for (auto&& web_usb_device : web_usb_devices) {
auto session_id = getDeviceSessionId(web_usb_device);
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 8c7b3a9..049d565 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -541,7 +541,7 @@
errno = 0;
value = strtol(buf, &endptr, 10);
- if (value < 0 || value > (long)max_value || errno) {
+ if (buf == endptr || value < 0 || value > (long)max_value || errno) {
usbi_err(ctx, "attribute %s contains an invalid value: '%s'", attr, buf);
return LIBUSB_ERROR_INVALID_PARAM;
} else if (*endptr != '\0') {
@@ -1033,7 +1033,7 @@
{
struct libusb_context *ctx = DEVICE_CTX(dev);
struct libusb_device *it;
- char *parent_sysfs_dir, *tmp;
+ char *parent_sysfs_dir, *tmp, *end;
int ret, add_parent = 1;
/* XXX -- can we figure out the topology when using usbfs? */
@@ -1048,7 +1048,16 @@
if ((tmp = strrchr(parent_sysfs_dir, '.')) ||
(tmp = strrchr(parent_sysfs_dir, '-'))) {
- dev->port_number = atoi(tmp + 1);
+ const char *start = tmp + 1;
+ long port_number = strtol(start, &end, 10);
+ if (port_number < 0 || port_number > INT_MAX || start == end || '\0' != *end) {
+ usbi_warn(ctx, "Can not parse sysfs_dir: %s, unexpected parent info",
+ parent_sysfs_dir);
+ free(parent_sysfs_dir);
+ return LIBUSB_ERROR_OTHER;
+ } else {
+ dev->port_number = (int)port_number;
+ }
*tmp = '\0';
} else {
usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info",
diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
index 1238ffa..5c64674 100644
--- a/libusb/os/linux_usbfs.h
+++ b/libusb/os/linux_usbfs.h
@@ -174,7 +174,17 @@
{
#if defined(HAVE_LIBUDEV)
return linux_udev_start_event_monitor();
-#elif !defined(__ANDROID__)
+/*
+* __ANDROID__: preprocessor macro defined automatically by GCC for all Android
+* targets (i.e. both Android native applications, and Android OS-level
+* services)
+*
+* ANDROID_OS: compilation flag that should be set for using libusb from programs
+* running on Android at OS level (e.g. Android platform services).
+* The programs using libusb built with the ANDROID_OS flag must have
+* permission to access netlink sockets.
+*/
+#elif !defined(__ANDROID__) || defined(ANDROID_OS)
return linux_netlink_start_event_monitor();
#else
return LIBUSB_SUCCESS;
@@ -185,7 +195,7 @@
{
#if defined(HAVE_LIBUDEV)
linux_udev_stop_event_monitor();
-#elif !defined(__ANDROID__)
+#elif !defined(__ANDROID__) || defined(ANDROID_OS)
linux_netlink_stop_event_monitor();
#endif
}
@@ -194,7 +204,7 @@
{
#if defined(HAVE_LIBUDEV)
linux_udev_hotplug_poll();
-#elif !defined(__ANDROID__)
+#elif !defined(__ANDROID__) || defined(ANDROID_OS)
linux_netlink_hotplug_poll();
#endif
}
diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c
index ebafdf0..a9a50b2 100644
--- a/libusb/os/netbsd_usb.c
+++ b/libusb/os/netbsd_usb.c
@@ -444,6 +444,8 @@
int
_errno_to_libusb(int err)
{
+ usbi_dbg(NULL, "error: %s (%d)", strerror(err), err);
+
switch (err) {
case EIO:
return LIBUSB_ERROR_IO;
@@ -456,11 +458,9 @@
case EWOULDBLOCK:
case ETIMEDOUT:
return LIBUSB_ERROR_TIMEOUT;
+ default:
+ return LIBUSB_ERROR_OTHER;
}
-
- usbi_dbg(NULL, "error: %s (%d)", strerror(err), err);
-
- return LIBUSB_ERROR_OTHER;
}
int
diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c
index 2a85d1f..13bda30 100644
--- a/libusb/os/openbsd_usb.c
+++ b/libusb/os/openbsd_usb.c
@@ -495,9 +495,9 @@
return LIBUSB_ERROR_NO_MEM;
case ETIMEDOUT:
return LIBUSB_ERROR_TIMEOUT;
+ default:
+ return LIBUSB_ERROR_OTHER;
}
-
- return LIBUSB_ERROR_OTHER;
}
int
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index a30f3de..c77bd20 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -29,6 +29,7 @@
#include <setupapi.h>
#include <ctype.h>
#include <stdio.h>
+#include <stdlib.h>
#include "libusbi.h"
#include "windows_winusb.h"
@@ -1229,6 +1230,9 @@
{
char buffer[MAX_KEY_LENGTH];
DWORD size;
+ const char *start = NULL;
+ char *end = NULL;
+ long long port;
// First try SPDRP_LOCATION_INFORMATION, which returns a REG_SZ. The string *may* have a format
// similar to "Port_#0002.Hub_#000D", in which case we can extract the port number. However, we
@@ -1237,7 +1241,15 @@
NULL, (PBYTE)buffer, sizeof(buffer), NULL)) {
// Check for the required format.
if (strncmp(buffer, "Port_#", 6) == 0) {
- *port_nr = atoi(buffer + 6);
+ start = buffer + 6;
+ // Note that 0 is both strtoll's sentinel return value to indicate failure, as well
+ // as (obviously) the return value for the literal "0". Fortunately we can always treat
+ // 0 as a failure, since Windows USB port numbers are numbered 1..n.
+ port = strtoll(start, &end, 10);
+ if (port <= 0 || port >= ULONG_MAX || end == start || (*end != '.' && *end != '\0')) {
+ return false;
+ }
+ *port_nr = (DWORD)port;
return true;
}
}
@@ -1251,7 +1263,12 @@
// Find the last "#USB(x)" substring
for (char *token = strrchr(buffer, '#'); token != NULL; token = strrchr(buffer, '#')) {
if (strncmp(token, "#USB(", 5) == 0) {
- *port_nr = atoi(token + 5);
+ start = token + 5;
+ port = strtoll(start, &end, 10);
+ if (port <= 0 || port >= ULONG_MAX || end == start || (*end != ')' && *end != '\0')) {
+ return false;
+ }
+ *port_nr = (DWORD)port;
return true;
}
// Shorten the string and try again.
@@ -3499,24 +3516,26 @@
return i;
}
-static int _hid_get_device_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
+static int _hid_get_device_descriptor(struct libusb_device *dev, struct hid_device_priv *hid_priv, void *data, size_t *size)
{
struct libusb_device_descriptor d;
+ /* Copy some values from the cached device descriptor
+ * because we cannot get them through HID */
d.bLength = LIBUSB_DT_DEVICE_SIZE;
d.bDescriptorType = LIBUSB_DT_DEVICE;
- d.bcdUSB = 0x0200; /* 2.00 */
- d.bDeviceClass = 0;
- d.bDeviceSubClass = 0;
- d.bDeviceProtocol = 0;
- d.bMaxPacketSize0 = 64; /* fix this! */
+ d.bcdUSB = dev->device_descriptor.bcdUSB;
+ d.bDeviceClass = dev->device_descriptor.bDeviceClass;
+ d.bDeviceSubClass = dev->device_descriptor.bDeviceSubClass;
+ d.bDeviceProtocol = dev->device_descriptor.bDeviceProtocol;
+ d.bMaxPacketSize0 = dev->device_descriptor.bMaxPacketSize0;
d.idVendor = (uint16_t)hid_priv->vid;
d.idProduct = (uint16_t)hid_priv->pid;
- d.bcdDevice = 0x0100;
+ d.bcdDevice = dev->device_descriptor.bcdDevice;
d.iManufacturer = hid_priv->string_index[0];
d.iProduct = hid_priv->string_index[1];
d.iSerialNumber = hid_priv->string_index[2];
- d.bNumConfigurations = 1;
+ d.bNumConfigurations = dev->device_descriptor.bNumConfigurations;
if (*size > LIBUSB_DT_DEVICE_SIZE)
*size = LIBUSB_DT_DEVICE_SIZE;
@@ -3744,7 +3763,7 @@
switch (type) {
case LIBUSB_DT_DEVICE:
usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_DEVICE");
- return _hid_get_device_descriptor(priv->hid, data, size);
+ return _hid_get_device_descriptor(dev, priv->hid, data, size);
case LIBUSB_DT_CONFIG:
usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_CONFIG");
if (!_index)
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 0fa03f1..de724b2 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11906
+#define LIBUSB_NANO 11941
diff --git a/tests/stress_mt.c b/tests/stress_mt.c
index 3a8f321..ab0a36f 100644
--- a/tests/stress_mt.c
+++ b/tests/stress_mt.c
@@ -114,7 +114,8 @@
for (ti->iteration = 0; ti->iteration < ITERS && !ti->err; ti->iteration++) {
libusb_context *ctx = NULL;
- if ((ti->err = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0)) != 0) {
+ ti->err = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0);
+ if (ti->err != 0) {
break;
}
if (ti->enumerate) {
@@ -127,7 +128,8 @@
for (int i = 0; i < ti->devcount && ti->err == 0; i++) {
libusb_device *dev = devs[i];
struct libusb_device_descriptor desc;
- if ((ti->err = libusb_get_device_descriptor(dev, &desc)) != 0) {
+ ti->err = libusb_get_device_descriptor(dev, &desc);
+ if (ti->err != 0) {
break;
}
if (no_access[i]) {