Compare commits
9 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9568c3f303 | ||
|
|
ff9cb1c8b6 | ||
|
|
261c00aec2 | ||
|
|
11a16ae2a8 | ||
|
|
07d18ab2e1 | ||
|
|
2084da7d5a | ||
|
|
4acb687232 | ||
|
|
653f1fe105 | ||
|
|
300a088323 |
13 changed files with 1405 additions and 358 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
/libusb-1.0.24.tar.bz2
|
||||
/libusb-1.0.25.tar.bz2
|
||||
|
|
|
|||
158
0001-core-Install-first-context-as-implicit-default.patch
Normal file
158
0001-core-Install-first-context-as-implicit-default.patch
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
From d46cbbac4851ce6e49d8dacb0daa328453eb8a84 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Berg <bberg@redhat.com>
|
||||
Date: Tue, 22 Feb 2022 11:45:38 +0100
|
||||
Subject: [PATCH] core: Install first context as implicit default
|
||||
|
||||
There was a behaviour change in libusb, which triggers issues when the
|
||||
API is misused. This caused gutenprint to crash, see
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2055504
|
||||
|
||||
For now, work around this by installing an implicit default. But, change
|
||||
the code to log an error in case this "feature" is being used.
|
||||
---
|
||||
libusb/core.c | 16 +++++++++++++---
|
||||
libusb/libusbi.h | 15 ++++++++++++++-
|
||||
tests/umockdev.c | 31 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 58 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libusb/core.c b/libusb/core.c
|
||||
index 1c1ada1..c75ddae 100644
|
||||
--- a/libusb/core.c
|
||||
+++ b/libusb/core.c
|
||||
@@ -41,6 +41,7 @@ static libusb_log_cb log_handler;
|
||||
#endif
|
||||
|
||||
struct libusb_context *usbi_default_context;
|
||||
+struct libusb_context *usbi_fallback_context;
|
||||
static int default_context_refcnt;
|
||||
static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER;
|
||||
static struct usbi_option default_context_options[LIBUSB_OPTION_MAX];
|
||||
@@ -2284,7 +2285,7 @@ int API_EXPORTED libusb_init(libusb_context **ctx)
|
||||
|
||||
usbi_mutex_static_lock(&default_context_lock);
|
||||
|
||||
- if (!ctx && usbi_default_context) {
|
||||
+ if (!ctx && default_context_refcnt > 0) {
|
||||
usbi_dbg(usbi_default_context, "reusing default context");
|
||||
default_context_refcnt++;
|
||||
usbi_mutex_static_unlock(&default_context_lock);
|
||||
@@ -2354,9 +2355,15 @@ int API_EXPORTED libusb_init(libusb_context **ctx)
|
||||
goto err_io_exit;
|
||||
}
|
||||
|
||||
- if (ctx)
|
||||
+ if (ctx) {
|
||||
*ctx = _ctx;
|
||||
|
||||
+ if (!usbi_fallback_context) {
|
||||
+ usbi_fallback_context = _ctx;
|
||||
+ usbi_warn(usbi_fallback_context, "installing new context as implicit default");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
usbi_mutex_static_unlock(&default_context_lock);
|
||||
|
||||
return 0;
|
||||
@@ -2429,6 +2436,8 @@ void API_EXPORTED libusb_exit(libusb_context *ctx)
|
||||
|
||||
if (!ctx)
|
||||
usbi_default_context = NULL;
|
||||
+ if (ctx == usbi_fallback_context)
|
||||
+ usbi_fallback_context = NULL;
|
||||
|
||||
usbi_mutex_static_unlock(&default_context_lock);
|
||||
|
||||
@@ -2575,7 +2584,8 @@ static void log_v(struct libusb_context *ctx, enum libusb_log_level level,
|
||||
#else
|
||||
enum libusb_log_level ctx_level;
|
||||
|
||||
- ctx = usbi_get_context(ctx);
|
||||
+ ctx = ctx ? ctx : usbi_default_context;
|
||||
+ ctx = ctx ? ctx : usbi_fallback_context;
|
||||
if (ctx)
|
||||
ctx_level = ctx->debug;
|
||||
else
|
||||
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
|
||||
index 5f0d5c2..580add8 100644
|
||||
--- a/libusb/libusbi.h
|
||||
+++ b/libusb/libusbi.h
|
||||
@@ -436,13 +436,26 @@ struct libusb_context {
|
||||
};
|
||||
|
||||
extern struct libusb_context *usbi_default_context;
|
||||
+extern struct libusb_context *usbi_fallback_context;
|
||||
|
||||
extern struct list_head active_contexts_list;
|
||||
extern usbi_mutex_static_t active_contexts_lock;
|
||||
|
||||
static inline struct libusb_context *usbi_get_context(struct libusb_context *ctx)
|
||||
{
|
||||
- return ctx ? ctx : usbi_default_context;
|
||||
+ static int warned = 0;
|
||||
+
|
||||
+ if (!ctx) {
|
||||
+ ctx = usbi_default_context;
|
||||
+ }
|
||||
+ if (!ctx) {
|
||||
+ ctx = usbi_fallback_context;
|
||||
+ if (ctx && warned == 0) {
|
||||
+ usbi_err(ctx, "API misuse! Using non-default context as implicit default.");
|
||||
+ warned = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ return ctx;
|
||||
}
|
||||
|
||||
enum usbi_event_flags {
|
||||
diff --git a/tests/umockdev.c b/tests/umockdev.c
|
||||
index b2af512..0e73f94 100644
|
||||
--- a/tests/umockdev.c
|
||||
+++ b/tests/umockdev.c
|
||||
@@ -551,6 +551,32 @@ test_open_close(UMockdevTestbedFixture * fixture, UNUSED_DATA)
|
||||
libusb_close(handle);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_implicit_default(UMockdevTestbedFixture * fixture, UNUSED_DATA)
|
||||
+{
|
||||
+ libusb_device **devs = NULL;
|
||||
+
|
||||
+ clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
|
||||
+ g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
|
||||
+ libusb_free_device_list(devs, TRUE);
|
||||
+ assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[usbi_get_context\\].*implicit default");
|
||||
+
|
||||
+ /* Only warns once */
|
||||
+ g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
|
||||
+ libusb_free_device_list(devs, TRUE);
|
||||
+ clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
|
||||
+
|
||||
+ libusb_init(NULL);
|
||||
+ g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
|
||||
+ libusb_exit(NULL);
|
||||
+
|
||||
+ /* We free late, causing a warning from libusb_exit. However,
|
||||
+ * we never see this warning (i.e. test success) because it is on a
|
||||
+ * different context.
|
||||
+ */
|
||||
+ libusb_free_device_list(devs, TRUE);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
test_close_flying(UMockdevTestbedFixture * fixture, UNUSED_DATA)
|
||||
{
|
||||
@@ -932,6 +958,11 @@ main(int argc, char **argv)
|
||||
test_open_close,
|
||||
test_fixture_teardown);
|
||||
|
||||
+ g_test_add("/libusb/implicit-default", UMockdevTestbedFixture, NULL,
|
||||
+ test_fixture_setup_with_canon,
|
||||
+ test_implicit_default,
|
||||
+ test_fixture_teardown);
|
||||
+
|
||||
g_test_add("/libusb/close-flying", UMockdevTestbedFixture, NULL,
|
||||
test_fixture_setup_with_canon,
|
||||
test_close_flying,
|
||||
--
|
||||
2.35.1
|
||||
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
From c486d01297a366aae8dcd3f715d0bfd8b995949b Mon Sep 17 00:00:00 2001
|
||||
From: Chris Dickens <christopher.a.dickens@gmail.com>
|
||||
Date: Mon, 8 Feb 2021 09:27:20 -0800
|
||||
Subject: [PATCH 1/2] linux_usbfs: Accept sysfs attributes not terminated with
|
||||
newline
|
||||
|
||||
Benjamin Berg reports that some CI systems that simulate sysfs devices
|
||||
are causing libusb to report errors because such systems are not
|
||||
conforming to the sysfs pattern of terminating attribute values with a
|
||||
newline character. Reduce the severity of encountering such
|
||||
non-conforming attibute values from an error that prevents enumeration
|
||||
to a warning message.
|
||||
|
||||
Closes #857
|
||||
|
||||
Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
|
||||
---
|
||||
libusb/os/linux_usbfs.c | 12 +++++++-----
|
||||
libusb/version_nano.h | 2 +-
|
||||
2 files changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
|
||||
index 4882c0f..ebf8cfe 100644
|
||||
--- a/libusb/os/linux_usbfs.c
|
||||
+++ b/libusb/os/linux_usbfs.c
|
||||
@@ -505,7 +505,7 @@ static int read_sysfs_attr(struct libusb_context *ctx,
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
- r = read(fd, buf, sizeof(buf));
|
||||
+ r = read(fd, buf, sizeof(buf) - 1);
|
||||
if (r < 0) {
|
||||
r = errno;
|
||||
close(fd);
|
||||
@@ -523,16 +523,18 @@ static int read_sysfs_attr(struct libusb_context *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- /* The kernel does *not* NULL-terminate the string, but every attribute
|
||||
+ /* The kernel does *not* NUL-terminate the string, but every attribute
|
||||
* should be terminated with a newline character. */
|
||||
if (!isdigit(buf[0])) {
|
||||
usbi_err(ctx, "attribute %s doesn't have numeric value?", attr);
|
||||
return LIBUSB_ERROR_IO;
|
||||
} else if (buf[r - 1] != '\n') {
|
||||
- usbi_err(ctx, "attribute %s doesn't end with newline?", attr);
|
||||
- return LIBUSB_ERROR_IO;
|
||||
+ usbi_warn(ctx, "attribute %s doesn't end with newline?", attr);
|
||||
+ } else {
|
||||
+ /* Remove the terminating newline character */
|
||||
+ r--;
|
||||
}
|
||||
- buf[r - 1] = '\0';
|
||||
+ buf[r] = '\0';
|
||||
|
||||
errno = 0;
|
||||
value = strtol(buf, &endptr, 10);
|
||||
--
|
||||
2.29.2
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
From f6d2cb561402c3b6d3627c0eb89e009b503d9067 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Dickens <christopher.a.dickens@gmail.com>
|
||||
Date: Sun, 13 Dec 2020 15:49:19 -0800
|
||||
Subject: [PATCH] linux_usbfs: Fix parsing of descriptors for
|
||||
multi-configuration devices
|
||||
|
||||
Commit e2be556bd2 ("linux_usbfs: Parse config descriptors during device
|
||||
initialization") introduced a regression for devices with multiple
|
||||
configurations. The logic that verifies the reported length of the
|
||||
configuration descriptors failed to count the length of the
|
||||
configuration descriptor itself and would truncate the actual length by
|
||||
9 bytes, leading to a parsing error for subsequent descriptors.
|
||||
|
||||
Closes #825
|
||||
|
||||
Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
|
||||
---
|
||||
libusb/os/linux_usbfs.c | 12 ++++++++----
|
||||
libusb/version_nano.h | 2 +-
|
||||
2 files changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
|
||||
index fb2ed53..4d2dc8d 100644
|
||||
--- a/libusb/os/linux_usbfs.c
|
||||
+++ b/libusb/os/linux_usbfs.c
|
||||
@@ -641,7 +641,12 @@ static int seek_to_next_config(struct libusb_context *ctx,
|
||||
uint8_t *buffer, size_t len)
|
||||
{
|
||||
struct usbi_descriptor_header *header;
|
||||
- int offset = 0;
|
||||
+ int offset;
|
||||
+
|
||||
+ /* Start seeking past the config descriptor */
|
||||
+ offset = LIBUSB_DT_CONFIG_SIZE;
|
||||
+ buffer += LIBUSB_DT_CONFIG_SIZE;
|
||||
+ len -= LIBUSB_DT_CONFIG_SIZE;
|
||||
|
||||
while (len > 0) {
|
||||
if (len < 2) {
|
||||
@@ -718,7 +723,7 @@ static int parse_config_descriptors(struct libusb_device *dev)
|
||||
}
|
||||
|
||||
if (priv->sysfs_dir) {
|
||||
- /*
|
||||
+ /*
|
||||
* In sysfs wTotalLength is ignored, instead the kernel returns a
|
||||
* config descriptor with verified bLength fields, with descriptors
|
||||
* with an invalid bLength removed.
|
||||
@@ -727,8 +732,7 @@ static int parse_config_descriptors(struct libusb_device *dev)
|
||||
int offset;
|
||||
|
||||
if (num_configs > 1 && idx < num_configs - 1) {
|
||||
- offset = seek_to_next_config(ctx, buffer + LIBUSB_DT_CONFIG_SIZE,
|
||||
- remaining - LIBUSB_DT_CONFIG_SIZE);
|
||||
+ offset = seek_to_next_config(ctx, buffer, remaining);
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
sysfs_config_len = (uint16_t)offset;
|
||||
--
|
||||
2.29.2
|
||||
|
||||
1038
0001-tests-Add-some-umockdev-based-tests.patch
Normal file
1038
0001-tests-Add-some-umockdev-based-tests.patch
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,220 +0,0 @@
|
|||
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 2/2] 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 ebf8cfe..3a1894c 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;
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
||||
24
1058.patch
Normal file
24
1058.patch
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
From 2529a3fc4f987f93e0774af865ac7cb6557bd0c2 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Berg <bberg@redhat.com>
|
||||
Date: Fri, 4 Feb 2022 22:50:28 +0100
|
||||
Subject: [PATCH] core: Unset device ctx if it has been destroyed
|
||||
|
||||
Devices can outlive their context in some cases (in particular with
|
||||
python garbage collection). Guard against this happening by clearing the
|
||||
ctx pointer so that it is not pointing to uninitialized memory.
|
||||
---
|
||||
libusb/core.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/libusb/core.c b/libusb/core.c
|
||||
index 7893ac23..1c1ada14 100644
|
||||
--- a/libusb/core.c
|
||||
+++ b/libusb/core.c
|
||||
@@ -2441,6 +2441,7 @@ void API_EXPORTED libusb_exit(libusb_context *ctx)
|
||||
for_each_device(_ctx, dev) {
|
||||
usbi_warn(_ctx, "device %d.%d still referenced",
|
||||
dev->bus_number, dev->device_address);
|
||||
+ DEVICE_CTX(dev) = NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&_ctx->open_devs))
|
||||
133
1073.patch
Normal file
133
1073.patch
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
From 1cb11c5ba0d1d1266fe4ddd70f29d081f9d16802 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Berg <bberg@redhat.com>
|
||||
Date: Tue, 15 Feb 2022 11:13:41 +0100
|
||||
Subject: [PATCH] io: Track device in usbi_transfer
|
||||
|
||||
transfer->dev_handle currently has the behaviour that it will be unset
|
||||
if the device is closed. The sync API uses this fact to catch an error
|
||||
case.
|
||||
|
||||
In other cases, transfer->dev_handle will keep its value, which means
|
||||
that if the transfer lives longer than the device handle, the pointer
|
||||
becomes invalid.
|
||||
|
||||
The transfer does however keep a reference to the device, which owns the
|
||||
pointer to the context. As such, we can track this reference internal to
|
||||
the transfer, and it is set while the transfer is in-flight.
|
||||
|
||||
With this, switch the logging infrastructure to use itransfer->dev->ctx
|
||||
while checking that itransfer->dev is non-NULL.
|
||||
|
||||
Note that this was a regression caused by 6cae9c6dbd74 ("core: update
|
||||
usbi_dbg to take the context as an argument"), specifically when
|
||||
resolving the context while freeing a transfer after closing a device.
|
||||
|
||||
Note that the transfer will now keep a reference to the device until it
|
||||
is free'ed. This allows it to use the correct context for logging even
|
||||
in libusb_free_transfer.
|
||||
|
||||
The alternative to all this would be to just explicitly pass NULL to the
|
||||
log handler in libusb_free_transfer.
|
||||
---
|
||||
libusb/io.c | 20 ++++++++++++--------
|
||||
libusb/libusbi.h | 10 +++++++---
|
||||
2 files changed, 19 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libusb/io.c b/libusb/io.c
|
||||
index 0d2ac9ea..b919e9d9 100644
|
||||
--- a/libusb/io.c
|
||||
+++ b/libusb/io.c
|
||||
@@ -1344,6 +1344,8 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
|
||||
|
||||
itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
|
||||
usbi_mutex_destroy(&itransfer->lock);
|
||||
+ if (itransfer->dev)
|
||||
+ libusb_unref_device(itransfer->dev);
|
||||
|
||||
priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
|
||||
ptr = (unsigned char *)itransfer - priv_size;
|
||||
@@ -1489,9 +1491,15 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
|
||||
{
|
||||
struct usbi_transfer *itransfer =
|
||||
LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
|
||||
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
|
||||
+ struct libusb_context *ctx;
|
||||
int r;
|
||||
|
||||
+ assert(transfer->dev_handle);
|
||||
+ if (itransfer->dev)
|
||||
+ libusb_unref_device(itransfer->dev);
|
||||
+ itransfer->dev = libusb_ref_device(transfer->dev_handle->dev);
|
||||
+
|
||||
+ ctx = HANDLE_CTX(transfer->dev_handle);
|
||||
usbi_dbg(ctx, "transfer %p", transfer);
|
||||
|
||||
/*
|
||||
@@ -1551,8 +1559,6 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
|
||||
r = usbi_backend.submit_transfer(itransfer);
|
||||
if (r == LIBUSB_SUCCESS) {
|
||||
itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
|
||||
- /* keep a reference to this device */
|
||||
- libusb_ref_device(transfer->dev_handle->dev);
|
||||
}
|
||||
usbi_mutex_unlock(&itransfer->lock);
|
||||
|
||||
@@ -1659,7 +1665,6 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
||||
{
|
||||
struct libusb_transfer *transfer =
|
||||
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
- struct libusb_device_handle *dev_handle = transfer->dev_handle;
|
||||
struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
|
||||
uint8_t flags;
|
||||
int r;
|
||||
@@ -1693,7 +1698,6 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
||||
* this point. */
|
||||
if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
|
||||
libusb_free_transfer(transfer);
|
||||
- libusb_unref_device(dev_handle->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1727,10 +1731,10 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *itransfer)
|
||||
* function will be called the next time an event handler runs. */
|
||||
void usbi_signal_transfer_completion(struct usbi_transfer *itransfer)
|
||||
{
|
||||
- libusb_device_handle *dev_handle = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->dev_handle;
|
||||
+ struct libusb_device *dev = itransfer->dev;
|
||||
|
||||
- if (dev_handle) {
|
||||
- struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
||||
+ if (dev) {
|
||||
+ struct libusb_context *ctx = DEVICE_CTX(dev);
|
||||
unsigned int event_flags;
|
||||
|
||||
usbi_mutex_lock(&ctx->event_data_lock);
|
||||
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
|
||||
index 158a9af5..5f0d5c2e 100644
|
||||
--- a/libusb/libusbi.h
|
||||
+++ b/libusb/libusbi.h
|
||||
@@ -329,10 +329,11 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
|
||||
#endif /* ENABLE_LOGGING */
|
||||
|
||||
#define DEVICE_CTX(dev) ((dev)->ctx)
|
||||
-#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev))
|
||||
-#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle))
|
||||
+#define HANDLE_CTX(handle) ((handle) ? DEVICE_CTX((handle)->dev) : NULL)
|
||||
#define ITRANSFER_CTX(itransfer) \
|
||||
- (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)))
|
||||
+ ((itransfer)->dev ? DEVICE_CTX((itransfer)->dev) : NULL)
|
||||
+#define TRANSFER_CTX(transfer) \
|
||||
+ (ITRANSFER_CTX(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)))
|
||||
|
||||
#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN))
|
||||
#define IS_EPOUT(ep) (!IS_EPIN(ep))
|
||||
@@ -562,6 +563,9 @@ struct usbi_transfer {
|
||||
uint32_t state_flags; /* Protected by usbi_transfer->lock */
|
||||
uint32_t timeout_flags; /* Protected by the flying_stransfers_lock */
|
||||
|
||||
+ /* This is used for logging mostly. As long as it is set, the */
|
||||
+ struct libusb_device *dev;
|
||||
+
|
||||
/* this lock is held during libusb_submit_transfer() and
|
||||
* libusb_cancel_transfer() (allowing the OS backend to prevent duplicate
|
||||
* cancellation, submission-during-cancellation, etc). the OS backend
|
||||
30
changelog
Normal file
30
changelog
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
* Mon Feb 28 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-8
|
||||
- Fix changelog and release version
|
||||
|
||||
* Mon Feb 28 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-7
|
||||
- Update patches and fix spec file
|
||||
|
||||
* Tue Feb 22 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-6
|
||||
- Work around API misuse in gutenprint
|
||||
|
||||
* Tue Feb 22 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-5
|
||||
- Add umockdev based tests
|
||||
|
||||
* Tue Feb 22 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-4
|
||||
- Update regression fix patch for late transfer free's
|
||||
|
||||
* Tue Feb 15 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-3
|
||||
- Fix a crash if a transfer outlives closing the device
|
||||
|
||||
* Thu Feb 10 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-2
|
||||
- Fix a crash after libusb_exit API has been misused
|
||||
|
||||
* Wed Feb 02 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-1
|
||||
- Update to 1.0.25
|
||||
|
||||
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.24-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
|
||||
|
||||
* Tue Jan 19 18:47:55 CET 2021 Benjamin Berg <bberg@redhat.com> - 1.0.24-3
|
||||
- New libusb1 package replacing libusbx
|
||||
Resolves: #1918269
|
||||
29
libusb1.spec
29
libusb1.spec
|
|
@ -1,20 +1,29 @@
|
|||
Summary: Library for accessing USB devices
|
||||
Name: libusb1
|
||||
Version: 1.0.24
|
||||
Release: 4%{?dist}
|
||||
Version: 1.0.25
|
||||
Release: %autorelease -b 7
|
||||
Source0: https://github.com/libusb/libusb/releases/download/v%{version}/libusb-%{version}.tar.bz2
|
||||
License: LGPLv2+
|
||||
URL: http://libusb.info
|
||||
BuildRequires: systemd-devel doxygen libtool
|
||||
BuildRequires: umockdev-devel
|
||||
BuildRequires: make
|
||||
BuildRequires: gcc
|
||||
# libusbx was removed in F34
|
||||
Provides: libusbx = %{version}-%{release}
|
||||
Obsoletes: libusbx < %{version}-%{release}
|
||||
|
||||
Patch001: 0001-linux_usbfs-Accept-sysfs-attributes-not-terminated-w.patch
|
||||
Patch002: 0001-linux_usbfs-Fix-parsing-of-descriptors-for-multi-con.patch
|
||||
Patch003: 0002-linux_usbfs-Gracefully-handle-buggy-devices-with-a-c.patch
|
||||
# Fix a crash after libusb_exit API has been misused
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2050638
|
||||
Patch0001: https://github.com/libusb/libusb/pull/1058.patch
|
||||
# Fix a crash if a transfer outlives closing the device
|
||||
Patch0002: https://github.com/libusb/libusb/pull/1073.patch
|
||||
# Add umockdev based tests from https://github.com/libusb/libusb/pull/1078
|
||||
Patch0003: 0001-tests-Add-some-umockdev-based-tests.patch
|
||||
|
||||
# Work around API misuse in gutenprint
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2056326
|
||||
Patch9999: 0001-core-Install-first-context-as-implicit-default.patch
|
||||
|
||||
%description
|
||||
This package provides a way for applications to access USB devices.
|
||||
|
|
@ -80,6 +89,7 @@ popd
|
|||
%{make_install}
|
||||
mkdir -p $RPM_BUILD_ROOT%{_bindir}
|
||||
install -m 755 tests/.libs/stress $RPM_BUILD_ROOT%{_bindir}/libusb-test-stress
|
||||
install -m 755 tests/.libs/umockdev $RPM_BUILD_ROOT%{_bindir}/libusb-test-umockdev
|
||||
install -m 755 examples/.libs/testlibusb \
|
||||
$RPM_BUILD_ROOT%{_bindir}/libusb-test-libusb
|
||||
# Some examples are very device-specific / require specific hw and miss --help
|
||||
|
|
@ -94,6 +104,7 @@ rm $RPM_BUILD_ROOT%{_libdir}/*.la
|
|||
%check
|
||||
LD_LIBRARY_PATH=libusb/.libs ldd $RPM_BUILD_ROOT%{_bindir}/libusb-test-stress
|
||||
LD_LIBRARY_PATH=libusb/.libs $RPM_BUILD_ROOT%{_bindir}/libusb-test-stress
|
||||
LD_LIBRARY_PATH=libusb/.libs $RPM_BUILD_ROOT%{_bindir}/libusb-test-umockdev
|
||||
LD_LIBRARY_PATH=libusb/.libs $RPM_BUILD_ROOT%{_bindir}/libusb-test-libusb
|
||||
LD_LIBRARY_PATH=libusb/.libs $RPM_BUILD_ROOT%{_bindir}/libusb-example-listdevs
|
||||
|
||||
|
|
@ -119,13 +130,9 @@ LD_LIBRARY_PATH=libusb/.libs $RPM_BUILD_ROOT%{_bindir}/libusb-example-listdevs
|
|||
%{_bindir}/libusb-example-listdevs
|
||||
%{_bindir}/libusb-example-xusb
|
||||
%{_bindir}/libusb-test-stress
|
||||
%{_bindir}/libusb-test-umockdev
|
||||
%{_bindir}/libusb-test-libusb
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.24-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
|
||||
|
||||
* Tue Jan 19 18:47:55 CET 2021 Benjamin Berg <bberg@redhat.com> - 1.0.24-3
|
||||
- New libusb1 package replacing libusbx
|
||||
Resolves: #1918269
|
||||
%autochangelog
|
||||
|
|
|
|||
2
sources
2
sources
|
|
@ -1 +1 @@
|
|||
SHA512 (libusb-1.0.24.tar.bz2) = 5aea36a530aaa15c6dd656d0ed3ce204522c9946d8d39ffbb290dab4a98cda388a2598da4995123d1032324056090bd429e702459626d3e8d7daeebc4e7ff3dc
|
||||
SHA512 (libusb-1.0.25.tar.bz2) = f1e6e5577d4bd1ff136927dc66c615014a06ac332ddd797b1d1ad5f7b68e2405e66068dcb210e2f0ae3e31681603ef72efbd88bf7fbe0eb41ce700fdc3f92f9d
|
||||
|
|
|
|||
|
|
@ -4,5 +4,6 @@ set -e
|
|||
|
||||
ldd /usr/bin/libusb-test-stress
|
||||
/usr/bin/libusb-test-stress
|
||||
/usr/bin/libusb-test-umockdev
|
||||
/usr/bin/libusb-test-libusb
|
||||
/usr/bin/libusb-example-listdevs
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
---
|
||||
- hosts: localhost
|
||||
roles:
|
||||
- role: standard-test-source
|
||||
tags:
|
||||
- always
|
||||
required_packages:
|
||||
- git
|
||||
# Running these tests does not require the sources
|
||||
- role: standard-test-basic
|
||||
tags:
|
||||
- atomic
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue