Date: Thu, 25 Jun 2026 23:04:41 +0000 From: ShengYi Hung <aokblast@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 240330a85e5f - main - libusb: don't treat EINVAL from USB_FS_COMPLETE as device detach Message-ID: <6a3db409.32d11.15fc5b49@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by aokblast: URL: https://cgit.FreeBSD.org/src/commit/?id=240330a85e5f7f5d448123902ebee4136ef221fd commit 240330a85e5f7f5d448123902ebee4136ef221fd Author: ShengYi Hung <aokblast@FreeBSD.org> AuthorDate: 2026-06-25 22:38:17 +0000 Commit: ShengYi Hung <aokblast@FreeBSD.org> CommitDate: 2026-06-25 22:58:23 +0000 libusb: don't treat EINVAL from USB_FS_COMPLETE as device detach ugen20_process() treats any non-EBUSY errno returned by USB_FS_COMPLETE as device detach and returns LIBUSB20_ERROR_OTHER. This causes libusb10 to set device_is_gone and fail all subsequent transfer with LIBUSB_ERROR_NO_DEVICE. However, USB_FS_COMPLETE can also return EINVAL when a completion references an endpoint that no longer exists, for example after SET_INTERFACE or SET_CONFIG removes and recreates endpoints. This is a transient condition and does not indicate device detach. Treat EINVAL the same as EBUSY and stop draining completions. This prevents a guest selecting an isochronous streaming altsetting from permanently breaking the passed-through device. Reviewed by: bapt Event: Halifax Hackathon 202606 Location: Peggy's Cove Rock Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D57542 --- lib/libusb/libusb20_ugen20.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/libusb/libusb20_ugen20.c b/lib/libusb/libusb20_ugen20.c index 6c838814a45d..32c8d53cd611 100644 --- a/lib/libusb/libusb20_ugen20.c +++ b/lib/libusb/libusb20_ugen20.c @@ -765,7 +765,16 @@ ugen20_process(struct libusb20_device *pdev) while (1) { if (ioctl(pdev->file, IOUSB(USB_FS_COMPLETE), &temp)) { - if (errno == EBUSY) { + if (errno == EBUSY || errno == EINVAL) { + /* + * EBUSY: no completion is pending. + * EINVAL: a dequeued completion referenced an + * endpoint that no longer exists, e.g. a stale + * completion left over after a SET_INTERFACE / + * SET_CONFIG tore the endpoints down. This is not + * a device detach, so stop draining rather than + * declaring the device gone. + */ break; } else { /* device detached */home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a3db409.32d11.15fc5b49>
