diff --git a/.gitignore b/.gitignore
index 9247b0e..307f047 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/libusb-1.0.22.tar.gz
+SOURCES/libusb-1.0.23.tar.gz
diff --git a/.libusbx.metadata b/.libusbx.metadata
index a1e1319..8a066e9 100644
--- a/.libusbx.metadata
+++ b/.libusbx.metadata
@@ -1 +1 @@
-cdb45a2d679e2ccbc3a8193f843e3f0c7187f74c SOURCES/libusb-1.0.22.tar.gz
+c8ebcc7d0a14f910151b3066326d8ba126894b88 SOURCES/libusb-1.0.23.tar.gz
diff --git a/SOURCES/0001-fix-constant-not-in-range-of-enumerated-type.patch b/SOURCES/0001-fix-constant-not-in-range-of-enumerated-type.patch
new file mode 100644
index 0000000..8c0d694
--- /dev/null
+++ b/SOURCES/0001-fix-constant-not-in-range-of-enumerated-type.patch
@@ -0,0 +1,38 @@
+From 41b71fbf664efd6ba8a5233dfd1a1fca15228908 Mon Sep 17 00:00:00 2001
+From: mrstock <info@niub.it>
+Date: Fri, 20 Sep 2019 14:36:07 +0200
+Subject: [PATCH 01/10] fix constant not in range of enumerated type
+
+fix "Integer constant not in range of enumerated type 'enum libusb_transfer_status'"
+
+LIBUSB_ERROR_NO_DEVICE doesn't exist on enum libusb_transfer_status
+
+(cherry picked from commit 906e706f8abdff626370e59b880f340cf54e3632)
+---
+ libusb/sync.c         | 2 +-
+ libusb/version_nano.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libusb/sync.c b/libusb/sync.c
+index 70942ac..863fe5c 100644
+--- a/libusb/sync.c
++++ b/libusb/sync.c
+@@ -62,7 +62,7 @@ static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer)
+ 		}
+ 		if (NULL == transfer->dev_handle) {
+ 			/* transfer completion after libusb_close() */
+-			transfer->status = LIBUSB_ERROR_NO_DEVICE;
++			transfer->status = LIBUSB_TRANSFER_NO_DEVICE;
+ 			*completed = 1;
+ 		}
+ 	}
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index 02179a4..dfa2fc9 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11397
++#define LIBUSB_NANO 11399
+-- 
+2.26.1
+
diff --git a/SOURCES/0002-Doxygen-add-libusb_wrap_sys_device-in-the-API-list.patch b/SOURCES/0002-Doxygen-add-libusb_wrap_sys_device-in-the-API-list.patch
new file mode 100644
index 0000000..78e98cf
--- /dev/null
+++ b/SOURCES/0002-Doxygen-add-libusb_wrap_sys_device-in-the-API-list.patch
@@ -0,0 +1,33 @@
+From 476239823fa3b800fda1ded87b60f9f7dd10cff2 Mon Sep 17 00:00:00 2001
+From: Ludovic Rousseau <ludovic.rousseau@free.fr>
+Date: Wed, 30 Oct 2019 12:56:47 +0100
+Subject: [PATCH 02/10] Doxygen: add libusb_wrap_sys_device() in the API list
+
+(cherry picked from commit e4923e77e953d10fa1edda70e2e57adc79cf1d12)
+---
+ libusb/core.c         | 1 +
+ libusb/version_nano.h | 2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 741bf99..6d025fa 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -442,6 +442,7 @@ if (cfg != desired)
+   * - libusb_unlock_event_waiters()
+   * - libusb_unref_device()
+   * - libusb_wait_for_event()
++  * - libusb_wrap_sys_device()
+   *
+   * \section Structures
+   * - libusb_bos_descriptor
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index dfa2fc9..a41e19e 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11399
++#define LIBUSB_NANO 11404
+-- 
+2.26.1
+
diff --git a/SOURCES/0003-Linux-backend-fix-ressource-leak.patch b/SOURCES/0003-Linux-backend-fix-ressource-leak.patch
new file mode 100644
index 0000000..423c762
--- /dev/null
+++ b/SOURCES/0003-Linux-backend-fix-ressource-leak.patch
@@ -0,0 +1,41 @@
+From 686536a2862f0d69e0075316ef54c1f927d134a3 Mon Sep 17 00:00:00 2001
+From: Ludovic Rousseau <ludovic.rousseau@free.fr>
+Date: Fri, 1 Nov 2019 16:04:02 +0100
+Subject: [PATCH 03/10] Linux backend: fix ressource leak
+
+Issue detected by Coverity:
+22. leaked_handle: Handle variable fd going out of scope leaks the handle.
+
+Signed-off-by: Ludovic Rousseau <ludovic.rousseau@free.fr>
+(cherry picked from commit 1bb774ca7e5cb100e1fb7ac287e561b2155da70e)
+---
+ libusb/os/linux_usbfs.c | 4 ++++
+ libusb/version_nano.h   | 2 +-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index 63fe592..dace935 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -1049,7 +1049,11 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
+ 	}
+ 
+ 	if (sysfs_dir && sysfs_can_relate_devices)
++	{
++		if (fd != wrapped_fd)
++			close(fd);
+ 		return LIBUSB_SUCCESS;
++	}
+ 
+ 	/* cache active config */
+ 	if (wrapped_fd < 0)
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index a41e19e..aebe182 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11404
++#define LIBUSB_NANO 11411
+-- 
+2.26.1
+
diff --git a/SOURCES/0004-Linux-Improved-system-out-of-memory-handling.patch b/SOURCES/0004-Linux-Improved-system-out-of-memory-handling.patch
new file mode 100644
index 0000000..5a381c5
--- /dev/null
+++ b/SOURCES/0004-Linux-Improved-system-out-of-memory-handling.patch
@@ -0,0 +1,36 @@
+From d3018d249a98fcf93d36baec32b80b7ef5a8ee68 Mon Sep 17 00:00:00 2001
+From: Slash Gordon <slash.gordon.dev@gmail.com>
+Date: Tue, 3 Dec 2019 12:47:38 +0100
+Subject: [PATCH 04/10] Linux: Improved system out of memory handling
+
+Maps ENOMEM system error to LIBUSB_ERROR_NO_MEM.
+
+(cherry picked from commit 97ece77c4a6eaafd0a74fd3b73e290ec97d71eb5)
+---
+ libusb/os/linux_usbfs.c | 2 ++
+ libusb/version_nano.h   | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index dace935..53530cd 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -2079,6 +2079,8 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
+ 		if (r < 0) {
+ 			if (errno == ENODEV) {
+ 				r = LIBUSB_ERROR_NO_DEVICE;
++			} else if (errno == ENOMEM) {
++				r = LIBUSB_ERROR_NO_MEM;
+ 			} else {
+ 				usbi_err(TRANSFER_CTX(transfer),
+ 					"submiturb failed error %d errno=%d", r, errno);
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index aebe182..41a03d1 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11411
++#define LIBUSB_NANO 11412
+-- 
+2.26.1
+
diff --git a/SOURCES/0005-linux_udev-silently-ignore-bind-action.patch b/SOURCES/0005-linux_udev-silently-ignore-bind-action.patch
new file mode 100644
index 0000000..2b06cde
--- /dev/null
+++ b/SOURCES/0005-linux_udev-silently-ignore-bind-action.patch
@@ -0,0 +1,46 @@
+From 2922440e42230d3d1b63397e99efa331f499c755 Mon Sep 17 00:00:00 2001
+From: John Keeping <john@metanate.com>
+Date: Tue, 12 Nov 2019 14:01:40 +0000
+Subject: [PATCH 05/10] linux_udev: silently ignore "bind" action
+
+When a driver is bound to a device, udev emits a "bind" action that
+causes libusb to log an error message:
+
+	libusb: error [udev_hotplug_event] ignoring udev action bind
+
+Since we know this action is not relevant for libusb, silently ignore it
+to avoid people thinking there is something wrong.
+
+There is already a debug log entry for the action, so there is no need
+to add a duplicate here.
+
+Signed-off-by: John Keeping <john@metanate.com>
+(cherry picked from commit f20f2be7825e34b5273af17fc0740c60bd352b32)
+---
+ libusb/os/linux_udev.c | 2 ++
+ libusb/version_nano.h  | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/libusb/os/linux_udev.c b/libusb/os/linux_udev.c
+index bea03e3..b09d299 100644
+--- a/libusb/os/linux_udev.c
++++ b/libusb/os/linux_udev.c
+@@ -262,6 +262,8 @@ static void udev_hotplug_event(struct udev_device* udev_dev)
+ 			linux_hotplug_enumerate(busnum, devaddr, sys_name);
+ 		} else if (detached) {
+ 			linux_device_disconnected(busnum, devaddr);
++		} else if (strncmp(udev_action, "bind", 4) == 0) {
++			/* silently ignore "known unhandled" action */
+ 		} else {
+ 			usbi_err(NULL, "ignoring udev action %s", udev_action);
+ 		}
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index 41a03d1..1764dec 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11412
++#define LIBUSB_NANO 11413
+-- 
+2.26.1
+
diff --git a/SOURCES/0006-Add-Null-POSIX-backend.patch b/SOURCES/0006-Add-Null-POSIX-backend.patch
new file mode 100644
index 0000000..24049cd
--- /dev/null
+++ b/SOURCES/0006-Add-Null-POSIX-backend.patch
@@ -0,0 +1,294 @@
+From 23557c82fd09b4ab7b106c13287a3ec8291f42dc Mon Sep 17 00:00:00 2001
+From: Pino Toscano <toscano.pino@tiscali.it>
+Date: Fri, 27 Dec 2019 18:41:28 +0100
+Subject: [PATCH 06/10] Add Null POSIX backend
+
+Add a simple null backend for POSIX platforms that reports no available
+devices, and provides no capabilities. Make use of this new backend on
+all the OSes without an existing backend, so libusb can be built even on
+OSes without USB support.
+
+(cherry picked from commit 53572d7e5eee79266139399924c7491174be1670)
+---
+ configure.ac          |  13 +++-
+ libusb/Makefile.am    |   7 +-
+ libusb/libusbi.h      |   2 +-
+ libusb/os/null_usb.c  | 176 ++++++++++++++++++++++++++++++++++++++++++
+ libusb/version_nano.h |   2 +-
+ 5 files changed, 196 insertions(+), 4 deletions(-)
+ create mode 100644 libusb/os/null_usb.c
+
+diff --git a/configure.ac b/configure.ac
+index da8a158..ddde325 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -100,7 +100,9 @@ case $host in
+ 	threads=posix
+ 	;;
+ *)
+-	AC_MSG_ERROR([unsupported operating system $host])
++	AC_MSG_RESULT([Null])
++	backend="null"
++	threads="posix"
+ esac
+ 
+ case $backend in
+@@ -186,6 +188,14 @@ haiku)
+ 	AC_CHECK_HEADERS([poll.h])
+ 	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
+ 	;;
++null)
++	AC_DEFINE(OS_NULL, 1, [Null backend])
++	AC_SUBST(OS_NULL)
++	THREAD_CFLAGS="-pthread"
++	LIBS="-pthread"
++	AC_CHECK_HEADERS([poll.h])
++	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
++	;;
+ esac
+ 
+ AC_SUBST(LIBS)
+@@ -197,6 +207,7 @@ AM_CONDITIONAL(OS_SUNOS, test "x$backend" = xsunos)
+ AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd)
+ AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows)
+ AM_CONDITIONAL(OS_HAIKU, test "x$backend" = xhaiku)
++AM_CONDITIONAL(OS_NULL, test "x$backend" = xnull)
+ AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix)
+ AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = xyes)
+ AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes)
+diff --git a/libusb/Makefile.am b/libusb/Makefile.am
+index e4da62e..466b633 100644
+--- a/libusb/Makefile.am
++++ b/libusb/Makefile.am
+@@ -22,13 +22,14 @@ WINDOWS_USB_SRC = libusb-1.0.def libusb-1.0.rc \
+ WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c
+ HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \
+ 		os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp
++NULL_USB_SRC = os/null_usb.c
+ 
+ EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \
+ 	$(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \
+ 	$(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \
+ 	$(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \
+ 	$(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
+-	$(HAIKU_USB_SRC) \
++	$(HAIKU_USB_SRC) $(NULL_USB_SRC) \
+ 	os/linux_udev.c os/linux_netlink.c
+ 
+ if OS_LINUX
+@@ -64,6 +65,10 @@ libusb_haiku_la_SOURCES = $(HAIKU_USB_SRC)
+ libusb_1_0_la_LIBADD = libusb_haiku.la
+ endif
+ 
++if OS_NULL
++OS_SRC = $(NULL_USB_SRC)
++endif
++
+ if OS_WINDOWS
+ OS_SRC = $(WINDOWS_USB_SRC)
+ 
+diff --git a/libusb/libusbi.h b/libusb/libusbi.h
+index 0a677bd..4cb6141 100644
+--- a/libusb/libusbi.h
++++ b/libusb/libusbi.h
+@@ -575,7 +575,7 @@ int usbi_clear_event(struct libusb_context *ctx);
+ 
+ /* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
+ #if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\
+-	defined(OS_HAIKU) || defined(OS_SUNOS)
++	defined(OS_HAIKU) || defined(OS_SUNOS) || defined(OS_NULL)
+ #include <unistd.h>
+ #include "os/poll_posix.h"
+ #elif defined(OS_WINDOWS) || defined(OS_WINCE)
+diff --git a/libusb/os/null_usb.c b/libusb/os/null_usb.c
+new file mode 100644
+index 0000000..97fa0b8
+--- /dev/null
++++ b/libusb/os/null_usb.c
+@@ -0,0 +1,176 @@
++/*
++ * Copyright © 2019 Pino Toscano <toscano.pino@tiscali.it>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "libusbi.h"
++
++static int
++null_get_device_list(struct libusb_context * ctx,
++	struct discovered_devs **discdevs)
++{
++	return LIBUSB_SUCCESS;
++}
++
++static int
++null_open(struct libusb_device_handle *handle)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static void
++null_close(struct libusb_device_handle *handle)
++{
++}
++
++static int
++null_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
++    int *host_endian)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_get_active_config_descriptor(struct libusb_device *dev,
++    unsigned char *buf, size_t len, int *host_endian)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
++    unsigned char *buf, size_t len, int *host_endian)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_set_configuration(struct libusb_device_handle *handle, int config)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_claim_interface(struct libusb_device_handle *handle, int iface)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_release_interface(struct libusb_device_handle *handle, int iface)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
++    int altsetting)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_reset_device(struct libusb_device_handle *handle)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_submit_transfer(struct usbi_transfer *itransfer)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_cancel_transfer(struct usbi_transfer *itransfer)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static void
++null_clear_transfer_priv(struct usbi_transfer *itransfer)
++{
++}
++
++static int
++null_handle_transfer_completion(struct usbi_transfer *itransfer)
++{
++	return LIBUSB_ERROR_NOT_SUPPORTED;
++}
++
++static int
++null_clock_gettime(int clkid, struct timespec *tp)
++{
++	switch (clkid) {
++	case USBI_CLOCK_MONOTONIC:
++		return clock_gettime(CLOCK_REALTIME, tp);
++	case USBI_CLOCK_REALTIME:
++		return clock_gettime(CLOCK_REALTIME, tp);
++	default:
++		return LIBUSB_ERROR_INVALID_PARAM;
++	}
++}
++
++const struct usbi_os_backend usbi_backend = {
++	.name = "Null backend",
++	.caps = 0,
++	.init = NULL,
++	.exit = NULL,
++	.set_option = NULL,
++	.get_device_list = null_get_device_list,
++	.hotplug_poll = NULL,
++	.wrap_sys_device = NULL,
++	.open = null_open,
++	.close = null_close,
++	.get_device_descriptor = null_get_device_descriptor,
++	.get_active_config_descriptor = null_get_active_config_descriptor,
++	.get_config_descriptor = null_get_config_descriptor,
++	.get_config_descriptor_by_value = NULL,
++	.get_configuration = NULL,
++	.set_configuration = null_set_configuration,
++	.claim_interface = null_claim_interface,
++	.release_interface = null_release_interface,
++	.set_interface_altsetting = null_set_interface_altsetting,
++	.clear_halt = null_clear_halt,
++	.reset_device = null_reset_device,
++	.alloc_streams = NULL,
++	.free_streams = NULL,
++	.dev_mem_alloc = NULL,
++	.dev_mem_free = NULL,
++	.kernel_driver_active = NULL,
++	.detach_kernel_driver = NULL,
++	.attach_kernel_driver = NULL,
++	.destroy_device = NULL,
++	.submit_transfer = null_submit_transfer,
++	.cancel_transfer = null_cancel_transfer,
++	.clear_transfer_priv = null_clear_transfer_priv,
++	.handle_events = NULL,
++	.handle_transfer_completion = null_handle_transfer_completion,
++	.clock_gettime = null_clock_gettime,
++#ifdef USBI_TIMERFD_AVAILABLE
++	.get_timerfd_clockid = NULL,
++#endif
++	.context_priv_size = 0,
++	.device_priv_size = 0,
++	.device_handle_priv_size = 0,
++	.transfer_priv_size = 0,
++};
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index 1764dec..4150474 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11413
++#define LIBUSB_NANO 11415
+-- 
+2.26.1
+
diff --git a/SOURCES/0007-core-fix-build-warning-on-newer-versions-of-gcc.patch b/SOURCES/0007-core-fix-build-warning-on-newer-versions-of-gcc.patch
new file mode 100644
index 0000000..01fdaeb
--- /dev/null
+++ b/SOURCES/0007-core-fix-build-warning-on-newer-versions-of-gcc.patch
@@ -0,0 +1,128 @@
+From fec6ad30dcb5917f03a53676f4f3ac68126e2fde Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Fri, 10 Jan 2020 20:04:52 +0100
+Subject: [PATCH 07/10] core: fix build warning on newer versions of gcc
+
+When building libusb on a "newer" version of gcc (9.2), a lot of
+warnings are thrown about zero-length messages as being part of a format
+string.
+
+An example of this is:
+
+descriptor.c:546:11: warning: zero-length gnu_printf format string [-Wformat-zero-length]
+  546 |  usbi_dbg("");
+      |           ^~
+
+Fix this up by replacing all calls of:
+	usbi_dbg("");
+with
+	usbi_dbg(" ");
+as obviously we still want to keep the implicit tracing message in the
+log.
+
+Closes #674
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
+(cherry picked from commit 0bf84e4d516c4488e5fcf4b10e3a7263c13019e1)
+---
+ libusb/core.c         | 10 +++++-----
+ libusb/descriptor.c   |  2 +-
+ libusb/io.c           |  4 ++--
+ libusb/version_nano.h |  2 +-
+ 4 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 6d025fa..0048dad 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -813,7 +813,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
+ 	int r = 0;
+ 	ssize_t i, len;
+ 	USBI_GET_CONTEXT(ctx);
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 
+ 	if (!discdevs)
+ 		return LIBUSB_ERROR_NO_MEM;
+@@ -1493,7 +1493,7 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
+ 
+ 	if (!dev_handle)
+ 		return;
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 
+ 	ctx = HANDLE_CTX(dev_handle);
+ 	handling_events = usbi_handling_events(ctx);
+@@ -1576,7 +1576,7 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle,
+ {
+ 	int r = LIBUSB_ERROR_NOT_SUPPORTED;
+ 
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 	if (usbi_backend.get_configuration)
+ 		r = usbi_backend.get_configuration(dev_handle, config);
+ 
+@@ -1844,7 +1844,7 @@ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle,
+  */
+ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle)
+ {
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 	if (!dev_handle->dev->attached)
+ 		return LIBUSB_ERROR_NO_DEVICE;
+ 
+@@ -2368,7 +2368,7 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx)
+ 	struct timeval tv = { 0, 0 };
+ 	int destroying_default_context = 0;
+ 
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 	USBI_GET_CONTEXT(ctx);
+ 
+ 	/* if working with default context, only actually do the deinitialization
+diff --git a/libusb/descriptor.c b/libusb/descriptor.c
+index 53905e6..53d1f6f 100644
+--- a/libusb/descriptor.c
++++ b/libusb/descriptor.c
+@@ -543,7 +543,7 @@ int usbi_device_cache_descriptor(libusb_device *dev)
+ int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
+ 	struct libusb_device_descriptor *desc)
+ {
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 	memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
+ 	       sizeof (dev->device_descriptor));
+ 	return 0;
+diff --git a/libusb/io.c b/libusb/io.c
+index 978b09a..77a048f 100644
+--- a/libusb/io.c
++++ b/libusb/io.c
+@@ -1330,7 +1330,7 @@ static int disarm_timerfd(struct libusb_context *ctx)
+ 	const struct itimerspec disarm_timer = { { 0, 0 }, { 0, 0 } };
+ 	int r;
+ 
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 	r = timerfd_settime(ctx->timerfd, 0, &disarm_timer, NULL);
+ 	if (r < 0)
+ 		return LIBUSB_ERROR_OTHER;
+@@ -1912,7 +1912,7 @@ void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
+ 	int pending_events;
+ 	USBI_GET_CONTEXT(ctx);
+ 
+-	usbi_dbg("");
++	usbi_dbg(" ");
+ 	usbi_mutex_lock(&ctx->event_data_lock);
+ 
+ 	pending_events = usbi_pending_events(ctx);
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index 4150474..8e487b0 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11415
++#define LIBUSB_NANO 11421
+-- 
+2.26.1
+
diff --git a/SOURCES/0008-core-Fix-libusb_get_max_iso_packet_size-for-superspe.patch b/SOURCES/0008-core-Fix-libusb_get_max_iso_packet_size-for-superspe.patch
new file mode 100644
index 0000000..74a34e9
--- /dev/null
+++ b/SOURCES/0008-core-Fix-libusb_get_max_iso_packet_size-for-superspe.patch
@@ -0,0 +1,53 @@
+From d29196dcc4a126dabf7d4131e3843c3b25fe8c35 Mon Sep 17 00:00:00 2001
+From: Chris Dickens <christopher.a.dickens@gmail.com>
+Date: Mon, 13 Jan 2020 14:07:31 -0800
+Subject: [PATCH 08/10] core: Fix libusb_get_max_iso_packet_size() for
+ superspeed plus
+
+The current logic fails to consider superspeed plus devices properly.
+Fix this by checking for superspeed or greater instead of matching
+against superspeed.
+
+Closes #553
+
+Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
+(cherry picked from commit dbd4991a2478ae57e39347bf8610e636554e4c1f)
+---
+ libusb/core.c         | 6 +++---
+ libusb/version_nano.h | 2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 0048dad..5c0a2e0 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -1121,8 +1121,8 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev,
+ 		goto out;
+ 	}
+ 
+-	speed = libusb_get_device_speed( dev );
+-	if (speed == LIBUSB_SPEED_SUPER) {
++	speed = libusb_get_device_speed(dev);
++	if (speed >= LIBUSB_SPEED_SUPER) {
+ 		r = libusb_get_ss_endpoint_companion_descriptor(dev->ctx, ep, &ss_ep_cmp);
+ 		if (r == LIBUSB_SUCCESS) {
+ 			r = ss_ep_cmp->wBytesPerInterval;
+@@ -1131,7 +1131,7 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev,
+ 	}
+ 
+ 	/* If the device isn't a SuperSpeed device or retrieving the SS endpoint didn't worked. */
+-	if (speed != LIBUSB_SPEED_SUPER || r < 0) {
++	if (speed < LIBUSB_SPEED_SUPER || r < 0) {
+ 		val = ep->wMaxPacketSize;
+ 		ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3);
+ 
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index 8e487b0..57c2b1d 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11421
++#define LIBUSB_NANO 11426
+-- 
+2.26.1
+
diff --git a/SOURCES/0009-core-Do-not-attempt-to-destroy-a-default-context-tha.patch b/SOURCES/0009-core-Do-not-attempt-to-destroy-a-default-context-tha.patch
new file mode 100644
index 0000000..e2dd208
--- /dev/null
+++ b/SOURCES/0009-core-Do-not-attempt-to-destroy-a-default-context-tha.patch
@@ -0,0 +1,80 @@
+From d414a9c447c79b0e39587998f71f8576605b4fb4 Mon Sep 17 00:00:00 2001
+From: Chris Dickens <christopher.a.dickens@gmail.com>
+Date: Mon, 13 Jan 2020 15:05:00 -0800
+Subject: [PATCH 09/10] core: Do not attempt to destroy a default context that
+ doesn't exist
+
+Calling libusb_exit(NULL) when a successful call to libusb_init(NULL)
+has not been made results in a segmentation violation. This is
+definitely a user error, but we can easily guard against it.
+
+Closes #511
+
+Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
+(cherry picked from commit a5624b22267ec0e146825d3fe94d9e4b2f5ae503)
+---
+ libusb/core.c         | 16 +++++++++++-----
+ libusb/version_nano.h |  2 +-
+ 2 files changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/libusb/core.c b/libusb/core.c
+index 5c0a2e0..26df871 100644
+--- a/libusb/core.c
++++ b/libusb/core.c
+@@ -2305,7 +2305,7 @@ int API_EXPORTED libusb_init(libusb_context **context)
+ 	usbi_mutex_static_lock(&active_contexts_lock);
+ 	if (first_init) {
+ 		first_init = 0;
+-		list_init (&active_contexts_list);
++		list_init(&active_contexts_list);
+ 	}
+ 	list_add (&ctx->list, &active_contexts_list);
+ 	usbi_mutex_static_unlock(&active_contexts_lock);
+@@ -2337,7 +2337,7 @@ err_free_ctx:
+ 	}
+ 
+ 	usbi_mutex_static_lock(&active_contexts_lock);
+-	list_del (&ctx->list);
++	list_del(&ctx->list);
+ 	usbi_mutex_static_unlock(&active_contexts_lock);
+ 
+ 	usbi_mutex_lock(&ctx->usb_devs_lock);
+@@ -2375,6 +2375,12 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx)
+ 	 * if we're the last user */
+ 	usbi_mutex_static_lock(&default_context_lock);
+ 	if (ctx == usbi_default_context) {
++		if (!usbi_default_context) {
++			usbi_dbg("no default context, not initialized?");
++			usbi_mutex_static_unlock(&default_context_lock);
++			return;
++		}
++
+ 		if (--default_context_refcnt > 0) {
+ 			usbi_dbg("not destroying default context");
+ 			usbi_mutex_static_unlock(&default_context_lock);
+@@ -2390,12 +2396,12 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx)
+ 		 */
+ 		destroying_default_context = 1;
+ 	} else {
+-		// Unlock default context, as we're not modifying it.
++		/* Unlock default context, as we're not modifying it. */
+ 		usbi_mutex_static_unlock(&default_context_lock);
+-  }
++	}
+ 
+ 	usbi_mutex_static_lock(&active_contexts_lock);
+-	list_del (&ctx->list);
++	list_del(&ctx->list);
+ 	usbi_mutex_static_unlock(&active_contexts_lock);
+ 
+ 	if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index 57c2b1d..3247cec 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11426
++#define LIBUSB_NANO 11427
+-- 
+2.26.1
+
diff --git a/SOURCES/0010-linux_usbfs-Wait-until-all-URBs-have-been-reaped-bef.patch b/SOURCES/0010-linux_usbfs-Wait-until-all-URBs-have-been-reaped-bef.patch
new file mode 100644
index 0000000..0f4b634
--- /dev/null
+++ b/SOURCES/0010-linux_usbfs-Wait-until-all-URBs-have-been-reaped-bef.patch
@@ -0,0 +1,264 @@
+From e0a164b50a1f11ead9f47da0233f6f954e04127f Mon Sep 17 00:00:00 2001
+From: Chris Dickens <christopher.a.dickens@gmail.com>
+Date: Thu, 16 Jan 2020 14:17:12 -0800
+Subject: [PATCH 10/10] linux_usbfs: Wait until all URBs have been reaped
+ before freeing them
+
+Prior to this change, the URBs allocated for an individual transfer were
+freed when the last URB in the transfer was reaped. Normally this causes
+no issues because URBs are reaped in the order they were submitted. If
+the device is disconnected while multiple URBs are queued, these URBs
+may be reaped in an order that does not match that of submission.
+
+Change the logic to free the URBs when all the URBs of a transfer have
+been reaped rather than the last one. While in here, improve some debug
+messages.
+
+Closes #607
+
+Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
+(cherry picked from commit 9eda802d947d9c4212eb3f821fa51956029dade0)
+---
+ libusb/os/linux_usbfs.c | 60 ++++++++++++++++++++---------------------
+ libusb/version_nano.h   |  2 +-
+ 2 files changed, 31 insertions(+), 31 deletions(-)
+
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index 53530cd..4179b9a 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -944,7 +944,7 @@ 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 ret=%d errno=%d", r, errno);
++			"get configuration failed, errno=%d", errno);
+ 		priv->active_config = -1;
+ 	} else {
+ 		if (active_config > 0) {
+@@ -1401,7 +1401,7 @@ static int initialize_handle(struct libusb_device_handle *handle, int fd)
+ 		if (errno == ENOTTY)
+ 			usbi_dbg("getcap not available");
+ 		else
+-			usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno);
++			usbi_err(HANDLE_CTX(handle), "getcap failed, errno=%d", errno);
+ 		hpriv->caps = 0;
+ 		if (supports_flag_zero_packet)
+ 			hpriv->caps |= USBFS_CAP_ZERO_PACKET;
+@@ -1426,7 +1426,7 @@ static int op_wrap_sys_device(struct libusb_context *ctx,
+ 	if (r < 0) {
+ 		r = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci);
+ 		if (r < 0) {
+-			usbi_err(ctx, "connectinfo failed (%d)", errno);
++			usbi_err(ctx, "connectinfo failed, errno=%d", errno);
+ 			return LIBUSB_ERROR_IO;
+ 		}
+ 		/* There is no ioctl to get the bus number. We choose 0 here
+@@ -1537,7 +1537,8 @@ static int op_set_configuration(struct libusb_device_handle *handle, int config)
+ 		else if (errno == ENODEV)
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+-		usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno);
++		usbi_err(HANDLE_CTX(handle),
++			"set configuration failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 
+@@ -1560,7 +1561,7 @@ static int claim_interface(struct libusb_device_handle *handle, int iface)
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"claim interface failed, error %d errno %d", r, errno);
++			"claim interface failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 	return 0;
+@@ -1575,7 +1576,7 @@ static int release_interface(struct libusb_device_handle *handle, int iface)
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"release interface failed, error %d errno %d", r, errno);
++			"release interface failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 	return 0;
+@@ -1598,7 +1599,7 @@ static int op_set_interface(struct libusb_device_handle *handle, int iface,
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"setintf failed error %d errno %d", r, errno);
++			"set interface failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 
+@@ -1618,7 +1619,7 @@ static int op_clear_halt(struct libusb_device_handle *handle,
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"clear_halt failed error %d errno %d", r, errno);
++			"clear halt failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 
+@@ -1650,7 +1651,7 @@ static int op_reset_device(struct libusb_device_handle *handle)
+ 		}
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"reset failed error %d errno %d", r, errno);
++			"reset failed, errno=%d", errno);
+ 		ret = LIBUSB_ERROR_OTHER;
+ 		goto out;
+ 	}
+@@ -1708,7 +1709,7 @@ static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"streams-ioctl failed error %d errno %d", r, errno);
++			"streams-ioctl failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 	return r;
+@@ -1770,7 +1771,7 @@ static int op_kernel_driver_active(struct libusb_device_handle *handle,
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"get driver failed error %d errno %d", r, errno);
++			"get driver failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 
+@@ -1804,7 +1805,7 @@ static int op_detach_kernel_driver(struct libusb_device_handle *handle,
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"detach failed error %d errno %d", r, errno);
++			"detach failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	}
+ 
+@@ -1834,7 +1835,7 @@ static int op_attach_kernel_driver(struct libusb_device_handle *handle,
+ 			return LIBUSB_ERROR_BUSY;
+ 
+ 		usbi_err(HANDLE_CTX(handle),
+-			"attach failed error %d errno %d", r, errno);
++			"attach failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	} else if (r == 0) {
+ 		return LIBUSB_ERROR_NOT_FOUND;
+@@ -1863,7 +1864,7 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 		}
+ 		usbi_err(HANDLE_CTX(handle),
+-			"disconnect-and-claim failed errno %d", errno);
++			"disconnect-and-claim failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_OTHER;
+ 	} else if (r == 0)
+ 		return 0;
+@@ -2083,7 +2084,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
+ 				r = LIBUSB_ERROR_NO_MEM;
+ 			} else {
+ 				usbi_err(TRANSFER_CTX(transfer),
+-					"submiturb failed error %d errno=%d", r, errno);
++					"submiturb failed, errno=%d", errno);
+ 				r = LIBUSB_ERROR_IO;
+ 			}
+ 
+@@ -2241,7 +2242,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
+ 				r = LIBUSB_ERROR_INVALID_PARAM;
+ 			} else {
+ 				usbi_err(TRANSFER_CTX(transfer),
+-					"submiturb failed error %d errno=%d", r, errno);
++					"submiturb failed, errno=%d", errno);
+ 				r = LIBUSB_ERROR_IO;
+ 			}
+ 
+@@ -2316,7 +2317,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer)
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+ 		usbi_err(TRANSFER_CTX(transfer),
+-			"submiturb failed error %d errno=%d", r, errno);
++			"submiturb failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_IO;
+ 	}
+ 	return 0;
+@@ -2498,10 +2499,10 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer,
+ 		goto cancel_remaining;
+ 	}
+ 
+-	/* if we're the last urb or we got less data than requested then we're
++	/* if we've reaped all urbs or we got less data than requested then we're
+ 	 * done */
+-	if (urb_idx == tpriv->num_urbs - 1) {
+-		usbi_dbg("last URB in transfer --> complete!");
++	if (tpriv->num_retired == tpriv->num_urbs) {
++		usbi_dbg("all URBs in transfer reaped --> complete!");
+ 		goto completed;
+ 	} else if (urb->actual_length < urb->buffer_length) {
+ 		usbi_dbg("short transfer %d/%d --> complete!",
+@@ -2577,15 +2578,15 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
+ 			break;
+ 		case -ENODEV:
+ 		case -ESHUTDOWN:
+-			usbi_dbg("device removed");
++			usbi_dbg("packet %d - device removed", i);
+ 			lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE;
+ 			break;
+ 		case -EPIPE:
+-			usbi_dbg("detected endpoint stall");
++			usbi_dbg("packet %d - detected endpoint stall", i);
+ 			lib_desc->status = LIBUSB_TRANSFER_STALL;
+ 			break;
+ 		case -EOVERFLOW:
+-			usbi_dbg("overflow error");
++			usbi_dbg("packet %d - overflow error", i);
+ 			lib_desc->status = LIBUSB_TRANSFER_OVERFLOW;
+ 			break;
+ 		case -ETIME:
+@@ -2594,12 +2595,12 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
+ 		case -ECOMM:
+ 		case -ENOSR:
+ 		case -EXDEV:
+-			usbi_dbg("low-level USB error %d", urb_desc->status);
++			usbi_dbg("packet %d - low-level USB error %d", i, urb_desc->status);
+ 			lib_desc->status = LIBUSB_TRANSFER_ERROR;
+ 			break;
+ 		default:
+ 			usbi_warn(TRANSFER_CTX(transfer),
+-				"unrecognised urb status %d", urb_desc->status);
++				"packet %d - unrecognised urb status %d", i, urb_desc->status);
+ 			lib_desc->status = LIBUSB_TRANSFER_ERROR;
+ 			break;
+ 		}
+@@ -2643,9 +2644,9 @@ static int handle_iso_completion(struct usbi_transfer *itransfer,
+ 		break;
+ 	}
+ 
+-	/* if we're the last urb then we're done */
+-	if (urb_idx == num_urbs) {
+-		usbi_dbg("last URB in transfer --> complete!");
++	/* if we've reaped all urbs then we're done */
++	if (tpriv->num_retired == num_urbs) {
++		usbi_dbg("all URBs in transfer reaped --> complete!");
+ 		free_iso_urbs(tpriv);
+ 		usbi_mutex_unlock(&itransfer->lock);
+ 		return usbi_handle_transfer_completion(itransfer, status);
+@@ -2733,8 +2734,7 @@ static int reap_for_handle(struct libusb_device_handle *handle)
+ 		if (errno == ENODEV)
+ 			return LIBUSB_ERROR_NO_DEVICE;
+ 
+-		usbi_err(HANDLE_CTX(handle), "reap failed error %d errno=%d",
+-			r, errno);
++		usbi_err(HANDLE_CTX(handle), "reap failed, errno=%d", errno);
+ 		return LIBUSB_ERROR_IO;
+ 	}
+ 
+diff --git a/libusb/version_nano.h b/libusb/version_nano.h
+index 3247cec..f496998 100644
+--- a/libusb/version_nano.h
++++ b/libusb/version_nano.h
+@@ -1 +1 @@
+-#define LIBUSB_NANO 11427
++#define LIBUSB_NANO 11428
+-- 
+2.26.1
+
diff --git a/SOURCES/1000-Downstream-fix-covscan-issue-close-fd-called-twice.patch b/SOURCES/1000-Downstream-fix-covscan-issue-close-fd-called-twice.patch
new file mode 100644
index 0000000..7416a1d
--- /dev/null
+++ b/SOURCES/1000-Downstream-fix-covscan-issue-close-fd-called-twice.patch
@@ -0,0 +1,47 @@
+From 5466375683a48bd650091781991d9e4facd06ba6 Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Fri, 26 Jun 2020 21:35:46 +0300
+Subject: [PATCH] Downstream: fix covscan issue: close(fd) called twice
+
+Seems it's already fixed upstream, but by several commits, that
+change more things.
+
+This simple patch, just prevents the case of calling close(fd) twice
+
+Warning is:
+Error: USE_AFTER_FREE (CWE-416): [#def2]
+libusb-1.0.23/libusb/os/linux_usbfs.c:1043: closed_arg: "close(int)" closes "fd".
+libusb-1.0.23/libusb/os/linux_usbfs.c:1054: double_close: Calling "close(int)"
+closes handle "fd" which has already been closed.
+---
+ libusb/os/linux_usbfs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
+index 4179b9a..537f0dd 100644
+--- a/libusb/os/linux_usbfs.c
++++ b/libusb/os/linux_usbfs.c
+@@ -1039,8 +1039,10 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
+ 		priv->descriptors_len += r;
+ 	} while (priv->descriptors_len == descriptors_size);
+ 
+-	if (fd != wrapped_fd)
++	if (fd != wrapped_fd) {
+ 		close(fd);
++		fd = -1;
++	}
+ 
+ 	if (priv->descriptors_len < DEVICE_DESC_LENGTH) {
+ 		usbi_err(ctx, "short descriptor read (%d)",
+@@ -1050,7 +1052,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
+ 
+ 	if (sysfs_dir && sysfs_can_relate_devices)
+ 	{
+-		if (fd != wrapped_fd)
++		if ((fd >= 0) && (fd != wrapped_fd))
+ 			close(fd);
+ 		return LIBUSB_SUCCESS;
+ 	}
+-- 
+2.26.2
+
diff --git a/SPECS/libusbx.spec b/SPECS/libusbx.spec
index bfdcd5b..6c4f161 100644
--- a/SPECS/libusbx.spec
+++ b/SPECS/libusbx.spec
@@ -1,12 +1,27 @@
 Summary:        Library for accessing USB devices
 Name:           libusbx
-Version:        1.0.22
-Release:        1%{?dist}
+Version:        1.0.23
+Release:        3%{?dist}
 # upstream libusbx has merged back with libusb and is now called libusb again
 # but we already have a libusb package for the old libusb-compat-0.1, renaming
 # that to libusb-compat while at the same time giving this its name is a bit
 # tricky, lets stick with the libusbx name for now
 Source0:        https://github.com/libusb/libusb/archive/v%{version}/libusb-%{version}.tar.gz
+Patch0001:      0001-fix-constant-not-in-range-of-enumerated-type.patch
+Patch0002:      0002-Doxygen-add-libusb_wrap_sys_device-in-the-API-list.patch
+Patch0003:      0003-Linux-backend-fix-ressource-leak.patch
+Patch0004:      0004-Linux-Improved-system-out-of-memory-handling.patch
+Patch0005:      0005-linux_udev-silently-ignore-bind-action.patch
+Patch0006:      0006-Add-Null-POSIX-backend.patch
+Patch0007:      0007-core-fix-build-warning-on-newer-versions-of-gcc.patch
+Patch0008:      0008-core-Fix-libusb_get_max_iso_packet_size-for-superspe.patch
+Patch0009:      0009-core-Do-not-attempt-to-destroy-a-default-context-tha.patch
+Patch0010:      0010-linux_usbfs-Wait-until-all-URBs-have-been-reaped-bef.patch
+
+# Downstream only - a simple fix for a covscan issue.
+Patch1000:      1000-Downstream-fix-covscan-issue-close-fd-called-twice.patch
+
+
 License:        LGPLv2+
 Group:          System Environment/Libraries
 URL:            http://libusb.info
@@ -49,8 +64,17 @@ BuildArch:      noarch
 This package contains API documentation for %{name}.
 
 
+%package        tests-examples
+Summary:        Tests and examples for %{name}
+Requires:       %{name}%{?_isa} = %{version}-%{release}
+
+%description tests-examples
+This package contains tests and examples for %{name}.
+
+
 %prep
-%setup -q -n libusb-%{version}
+%autosetup -S git_am -n libusb-%{version}
+chmod -x examples/*.c
 mkdir -p m4
 autoreconf -ivf
 
@@ -61,13 +85,33 @@ make %{?_smp_mflags}
 pushd doc
 make docs
 popd
+pushd tests
+make
+popd
 
 
 %install
 %make_install
+mkdir -p $RPM_BUILD_ROOT%{_bindir}
+install -m 755 tests/.libs/stress $RPM_BUILD_ROOT%{_bindir}/libusb-test-stress
+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
+# So we only install a subset of more generic / useful examples
+for i in fxload listdevs xusb; do
+    install -m 755 examples/.libs/$i \
+        $RPM_BUILD_ROOT%{_bindir}/libusb-example-$i
+done
 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-libusb
+LD_LIBRARY_PATH=libusb/.libs $RPM_BUILD_ROOT%{_bindir}/libusb-example-listdevs
+
+
 %ldconfig_scriptlets
 
 
@@ -84,8 +128,31 @@ rm $RPM_BUILD_ROOT%{_libdir}/*.la
 %files devel-doc
 %doc doc/html examples/*.c
 
+%files tests-examples
+%{_bindir}/libusb-example-fxload
+%{_bindir}/libusb-example-listdevs
+%{_bindir}/libusb-example-xusb
+%{_bindir}/libusb-test-stress
+%{_bindir}/libusb-test-libusb
+
 
 %changelog
+* Fri Jun 26 2020 Uri Lublin <uril@redhat.com> - 1.0.23-3
+- Fix covscan warning
+  Related: rhbz#1825941
+
+* Thu May 14 2020 Victor Toso <victortoso@redhat.com> - 1.0.23-2
+- Cherry pick a few fixes since 1.0.23 release
+- Related: rhbz#1825941
+
+* Tue May 05 2020 Victor Toso <victortoso@redhat.com> - 1.0.23-1
+- Update to 1.0.23
+- Resolves: rhbz#1825941
+
+* Mon Feb 17 2020 Hans de Goede <hdegoede@redhat.com> - 1.0.22-2
+- Add tests-examples subpackage for use by gating tests
+- Resolves: rhbz#1681769
+
 * Wed Aug 22 2018 Victor Toso <victortoso@redhat.com> - 1.0.22-1
 - Update to 1.0.22
 - Resolves: rhbz#1620092