Re: git: b4daeded66b5 - main - usb: umass: add SCSIEJECT quirk and fix RTW8821CU_CD (USB mode switch)
Date: Sat, 14 Mar 2026 23:48:23 UTC
On Monday, March 9, 2026, Bjoern A. Zeeb <bz@freebsd.org> wrote:
> The branch main has been updated by bz:
>
> URL: https://cgit.FreeBSD.org/src/commit/?id=
> b4daeded66b5e950ed8e618d66915b863c2414b1
>
> commit b4daeded66b5e950ed8e618d66915b863c2414b1
> 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-09 14:35:31 +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.
Hi!
Wouldn't be better to initiate these kind of ejects from devd rather than
from kernel?
>
> Sponsored by: The FreeBSD Foundation
> Fixes: b3b6a959c85a, 9c0cce328363
> Reviewed by: imp
> Differential Revision: https://reviews.freebsd.org/D54901
> ---
> 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 04441b2a344b..303f76f37fb0 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);
>
>