aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo <thinkabit.ukim@gmail.com>2021-02-14 08:46:45 -0300
committerLeo <thinkabit.ukim@gmail.com>2021-02-15 09:16:47 +0000
commit2e9ba9de33fd839f8e64d2b36f440c310eb4fb77 (patch)
tree551872f5e146ef6cc08ea7d6e9cb524a7cc9f736
parent6572e84de23d3bedd6f754b13d3d034a2a78fcea (diff)
downloadaports-2e9ba9de33fd839f8e64d2b36f440c310eb4fb77.tar.gz
aports-2e9ba9de33fd839f8e64d2b36f440c310eb4fb77.tar.bz2
aports-2e9ba9de33fd839f8e64d2b36f440c310eb4fb77.tar.xz
main/libusb: fix handling buggy USB devices
See: https://github.com/libusb/libusb/commit/f38f09da98acc63966b65b72029b1f7f81166bef Fixes #12426
-rw-r--r--main/libusb/APKBUILD6
-rw-r--r--main/libusb/f38f09da98acc63966b65b72029b1f7f81166bef.patch217
2 files changed, 221 insertions, 2 deletions
diff --git a/main/libusb/APKBUILD b/main/libusb/APKBUILD
index 7c99044dbb..9489a73505 100644
--- a/main/libusb/APKBUILD
+++ b/main/libusb/APKBUILD
@@ -2,7 +2,7 @@
pkgname=libusb
pkgver=1.0.24
_ver=${pkgver/_/-}
-pkgrel=0
+pkgrel=1
pkgdesc="Library that enables userspace access to USB devices"
url="https://libusb.info/"
arch="all"
@@ -11,6 +11,7 @@ subpackages="$pkgname-dev"
replaces="libusbx"
makedepends="linux-headers"
source="https://github.com/libusb/libusb/releases/download/v$pkgver/libusb-$pkgver.tar.bz2
+ f38f09da98acc63966b65b72029b1f7f81166bef.patch
"
build() {
@@ -31,4 +32,5 @@ package() {
make DESTDIR="$pkgdir" install
}
-sha512sums="5aea36a530aaa15c6dd656d0ed3ce204522c9946d8d39ffbb290dab4a98cda388a2598da4995123d1032324056090bd429e702459626d3e8d7daeebc4e7ff3dc libusb-1.0.24.tar.bz2"
+sha512sums="5aea36a530aaa15c6dd656d0ed3ce204522c9946d8d39ffbb290dab4a98cda388a2598da4995123d1032324056090bd429e702459626d3e8d7daeebc4e7ff3dc libusb-1.0.24.tar.bz2
+fdfc2b02eb996661c75ce01652b623afa4339612c2fc84331187ad55ac93d94abe20f48bf3ec891138ebdb8703a29e8b45643518e896f298562f93a5749e014c f38f09da98acc63966b65b72029b1f7f81166bef.patch"
diff --git a/main/libusb/f38f09da98acc63966b65b72029b1f7f81166bef.patch b/main/libusb/f38f09da98acc63966b65b72029b1f7f81166bef.patch
new file mode 100644
index 0000000000..94395318c5
--- /dev/null
+++ b/main/libusb/f38f09da98acc63966b65b72029b1f7f81166bef.patch
@@ -0,0 +1,217 @@
+From f38f09da98acc63966b65b72029b1f7f81166bef Mon Sep 17 00:00:00 2001
+From: Chris Dickens <christopher.a.dickens@gmail.com>
+Date: Mon, 8 Feb 2021 11:56:13 -0800
+Subject: [PATCH] linux_usbfs: Gracefully handle buggy devices with a
+ configuration 0
+
+The USB spec states that a configuration value of 0 is reserved and is
+used to indicate the device in not configured (e.g. is in the address
+state). Unfortunately some devices do exist that violate this and use 0
+as the bConfigurationValue of the configuration descriptor.
+
+Improve how the Linux backend handles such non-conformant devices by
+adding special handling around the configuration value 0. Most devices
+will not require this special handling, but for those that do there is
+no way to distinguish between the device being unconfigured and using
+configuration 0.
+
+Closes #850
+
+Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
+---
+ libusb/os/linux_usbfs.c | 94 ++++++++++++++++++++++++++---------------
+ libusb/version_nano.h | 2 +-
+ 2 files changed, 60 insertions(+), 36 deletions(-)
+
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index ebf8cfed..3a1894cf 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -128,7 +128,7 @@ struct linux_device_priv {
+ void *descriptors;
+ size_t descriptors_len;
+ struct config_descriptor *config_descriptors;
+- uint8_t active_config; /* cache val for !sysfs_available */
++ int active_config; /* cache val for !sysfs_available */
+ };
+
+ struct linux_device_handle_priv {
+@@ -169,6 +169,21 @@ struct linux_transfer_priv {
+ int iso_packet_offset;
+ };
+
++static int dev_has_config0(struct libusb_device *dev)
++{
++ struct linux_device_priv *priv = usbi_get_device_priv(dev);
++ struct config_descriptor *config;
++ uint8_t idx;
++
++ for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) {
++ config = &priv->config_descriptors[idx];
++ if (config->desc->bConfigurationValue == 0)
++ return 1;
++ }
++
++ return 0;
++}
++
+ static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
+ {
+ struct libusb_context *ctx = DEVICE_CTX(dev);
+@@ -574,22 +589,12 @@ static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
+ }
+
+ /* read the bConfigurationValue for a device */
+-static int sysfs_get_active_config(struct libusb_device *dev, uint8_t *config)
++static int sysfs_get_active_config(struct libusb_device *dev, int *config)
+ {
+ struct linux_device_priv *priv = usbi_get_device_priv(dev);
+- int ret, tmp;
+-
+- ret = read_sysfs_attr(DEVICE_CTX(dev), priv->sysfs_dir, "bConfigurationValue",
+- UINT8_MAX, &tmp);
+- if (ret < 0)
+- return ret;
+
+- if (tmp == -1)
+- tmp = 0; /* unconfigured */
+-
+- *config = (uint8_t)tmp;
+-
+- return 0;
++ return read_sysfs_attr(DEVICE_CTX(dev), priv->sysfs_dir, "bConfigurationValue",
++ UINT8_MAX, config);
+ }
+
+ int linux_get_device_address(struct libusb_context *ctx, int detached,
+@@ -765,6 +770,9 @@ static int parse_config_descriptors(struct libusb_device *dev)
+ }
+ }
+
++ if (config_desc->bConfigurationValue == 0)
++ usbi_warn(ctx, "device has configuration 0");
++
+ priv->config_descriptors[idx].desc = config_desc;
+ priv->config_descriptors[idx].actual_len = config_len;
+
+@@ -798,7 +806,7 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
+ {
+ struct linux_device_priv *priv = usbi_get_device_priv(dev);
+ void *config_desc;
+- uint8_t active_config;
++ int active_config;
+ int r;
+
+ if (priv->sysfs_dir) {
+@@ -810,12 +818,12 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
+ active_config = priv->active_config;
+ }
+
+- if (active_config == 0) {
++ if (active_config == -1) {
+ usbi_err(DEVICE_CTX(dev), "device unconfigured");
+ return LIBUSB_ERROR_NOT_FOUND;
+ }
+
+- r = op_get_config_descriptor_by_value(dev, active_config, &config_desc);
++ r = op_get_config_descriptor_by_value(dev, (uint8_t)active_config, &config_desc);
+ if (r < 0)
+ return r;
+
+@@ -863,17 +871,26 @@ static int usbfs_get_active_config(struct libusb_device *dev, int fd)
+
+ /* we hit this error path frequently with buggy devices :( */
+ usbi_warn(DEVICE_CTX(dev), "get configuration failed, errno=%d", errno);
++
++ /* assume the current configuration is the first one if we have
++ * the configuration descriptors, otherwise treat the device
++ * as unconfigured. */
++ if (priv->config_descriptors)
++ priv->active_config = (int)priv->config_descriptors[0].desc->bConfigurationValue;
++ else
++ priv->active_config = -1;
+ } else if (active_config == 0) {
+- /* some buggy devices have a configuration 0, but we're
+- * reaching into the corner of a corner case here, so let's
+- * not support buggy devices in these circumstances.
+- * stick to the specs: a configuration value of 0 means
+- * unconfigured. */
+- usbi_warn(DEVICE_CTX(dev), "active cfg 0? assuming unconfigured device");
++ if (dev_has_config0(dev)) {
++ /* some buggy devices have a configuration 0, but we're
++ * reaching into the corner of a corner case here. */
++ priv->active_config = 0;
++ } else {
++ priv->active_config = -1;
++ }
++ } else {
++ priv->active_config = (int)active_config;
+ }
+
+- priv->active_config = active_config;
+-
+ return LIBUSB_SUCCESS;
+ }
+
+@@ -1004,9 +1021,9 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
+ usbi_warn(ctx, "Missing rw usbfs access; cannot determine "
+ "active configuration descriptor");
+ if (priv->config_descriptors)
+- priv->active_config = priv->config_descriptors[0].desc->bConfigurationValue;
++ priv->active_config = (int)priv->config_descriptors[0].desc->bConfigurationValue;
+ else
+- priv->active_config = 0; /* No config dt */
++ priv->active_config = -1; /* No config dt */
+
+ return LIBUSB_SUCCESS;
+ }
+@@ -1428,22 +1445,27 @@ static int op_get_configuration(struct libusb_device_handle *handle,
+ uint8_t *config)
+ {
+ struct linux_device_priv *priv = usbi_get_device_priv(handle->dev);
++ int active_config;
+ int r;
+
+ if (priv->sysfs_dir) {
+- r = sysfs_get_active_config(handle->dev, config);
++ r = sysfs_get_active_config(handle->dev, &active_config);
+ } else {
+ struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
+
+ r = usbfs_get_active_config(handle->dev, hpriv->fd);
+ if (r == LIBUSB_SUCCESS)
+- *config = priv->active_config;
++ active_config = priv->active_config;
+ }
+ if (r < 0)
+ return r;
+
+- if (*config == 0)
+- usbi_err(HANDLE_CTX(handle), "device unconfigured");
++ if (active_config == -1) {
++ usbi_warn(HANDLE_CTX(handle), "device unconfigured");
++ active_config = 0;
++ }
++
++ *config = (uint8_t)active_config;
+
+ return 0;
+ }
+@@ -1467,11 +1489,13 @@ static int op_set_configuration(struct libusb_device_handle *handle, int config)
+ return LIBUSB_ERROR_OTHER;
+ }
+
+- if (config == -1)
+- config = 0;
++ /* if necessary, update our cached active config descriptor */
++ if (!priv->sysfs_dir) {
++ if (config == 0 && !dev_has_config0(handle->dev))
++ config = -1;
+
+- /* update our cached active config descriptor */
+- priv->active_config = (uint8_t)config;
++ priv->active_config = config;
++ }
+
+ return LIBUSB_SUCCESS;
+ }