Date: Wed, 11 Mar 2026 16:53:43 +0000 From: Bjoern A. Zeeb <bz@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 4c7dbe9f794f - stable/15 - usb: umass: add SCSIEJECT quirk and fix RTW8821CU_CD (USB mode switch) Message-ID: <69b19e17.456d1.47de9198@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch stable/15 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=4c7dbe9f794f601c8abf791078fbe57e0a8a63e5 commit 4c7dbe9f794f601c8abf791078fbe57e0a8a63e5 Author: Bjoern A. Zeeb <bz@FreeBSD.org> AuthorDate: 2026-01-26 13:19:37 +0000 Commit: Bjoern A. Zeeb <bz@FreeBSD.org> CommitDate: 2026-03-11 16:53:25 +0000 usb: umass: add SCSIEJECT quirk and fix RTW8821CU_CD (USB mode switch) Several Realtek (and lots other) USB dongles present themselves as CDROM device first. Upon eject they do a mode switch and suddenly are a different kind of device (sometimes even with different IDs), e.g., a wireless dongle. In order to avoid the CDROM stage and rather than adding the quirk handling to more drivers, add support to umass and if enabled automatically eject the "CDROM" to make it the real device. Longer-term some other drivers could stop using their hand-rolled support for this. It is unclear as-to how much we need the list of (eject) quirks from u3g here, or if these are very specific to that kind of devices. Sponsored by: The FreeBSD Foundation Fixes: b3b6a959c85a, 9c0cce328363 Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D54901 (cherry picked from commit b4daeded66b5e950ed8e618d66915b863c2414b1) --- sys/dev/usb/quirk/usb_quirk.c | 2 +- sys/dev/usb/storage/umass.c | 57 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c index 802ea2b2ae6a..69e16c91604f 100644 --- a/sys/dev/usb/quirk/usb_quirk.c +++ b/sys/dev/usb/quirk/usb_quirk.c @@ -532,7 +532,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_NO_INQUIRY, UQ_CFG_INDEX_0), USB_QUIRK(SMART2, G2MEMKEY, UQ_MSC_NO_INQUIRY), USB_QUIRK_REV(RALINK, RT_STOR, 0x0001, 0x0001, UQ_MSC_IGNORE), - USB_QUIRK(REALTEK, RTW8821CU_CD, UQ_MSC_IGNORE), + USB_QUIRK(REALTEK, RTW8821CU_CD, UQ_MSC_EJECT_SCSIEJECT), /* Non-standard USB MIDI devices */ USB_QUIRK(ROLAND, UM1, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SC8850, UQ_AU_VENDOR_CLASS), diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c index cacf4ddf8f16..0ee6ea992fa7 100644 --- a/sys/dev/usb/storage/umass.c +++ b/sys/dev/usb/storage/umass.c @@ -115,6 +115,7 @@ #include <sys/sx.h> #include <sys/unistd.h> #include <sys/callout.h> +#include <sys/eventhandler.h> #include <sys/malloc.h> #include <sys/priv.h> @@ -124,6 +125,7 @@ #include "usbdevs.h" #include <dev/usb/quirk/usb_quirk.h> +#include <dev/usb/usb_msctest.h> #include <cam/cam.h> #include <cam/cam_ccb.h> @@ -705,6 +707,59 @@ static const uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = { #define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */ #define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */ +static void +umass_autoinst_eject_quirks(void *arg __unused, struct usb_device *udev, + struct usb_attach_arg *uaa) +{ + struct usb_interface *iface; + struct usb_interface_descriptor *id; + + if (uaa->dev_state != UAA_DEV_READY) + return; + + iface = usbd_get_iface(udev, 0); + if (iface == NULL) + return; + + id = iface->idesc; + if (id == NULL || id->bInterfaceClass != UICLASS_MASS) + return; + + if (usb_test_quirk(uaa, UQ_MSC_EJECT_SCSIEJECT)) { + int error; + + error = usb_msc_eject(uaa->device, 0, MSC_EJECT_STOPUNIT); + if (error == 0) + uaa->dev_state = UAA_DEV_EJECTING; + else + printf("UMASS failed to eject by SCSI eject STOPUNIT " + "command based on quirk: %d\n", error); + } +} + +static eventhandler_tag umass_drv_evh_tag; + +static int +umass_driver_evh(struct module *mod, int what, void *arg) +{ + + switch (what) { + case MOD_LOAD: + umass_drv_evh_tag = EVENTHANDLER_REGISTER(usb_dev_configured, + umass_autoinst_eject_quirks, NULL, EVENTHANDLER_PRI_ANY); + break; + case MOD_UNLOAD: + if (umass_drv_evh_tag != NULL) + EVENTHANDLER_DEREGISTER(usb_dev_configured, + umass_drv_evh_tag); + break; + default: + return (EOPNOTSUPP); + } + + return (0); +} + static device_method_t umass_methods[] = { /* Device interface */ DEVMETHOD(device_probe, umass_probe), @@ -725,7 +780,7 @@ static const STRUCT_USB_HOST_ID __used umass_devs[] = { {USB_IFACE_CLASS(UICLASS_MASS),}, }; -DRIVER_MODULE(umass, uhub, umass_driver, NULL, NULL); +DRIVER_MODULE(umass, uhub, umass_driver, umass_driver_evh, NULL); MODULE_DEPEND(umass, usb, 1, 1, 1); MODULE_DEPEND(umass, cam, 1, 1, 1); MODULE_VERSION(umass, 1);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69b19e17.456d1.47de9198>
