On Monday, March 9, 2026, Bjoern A. Zeeb <[email protected]> wrote: > The branch main has been updated by bz: > > URL: https://cgit.FreeBSD.org/src/commit/?id= > b4daeded66b5e950ed8e618d66915b863c2414b1 > > commit b4daeded66b5e950ed8e618d66915b863c2414b1 > Author: Bjoern A. Zeeb <[email protected]> > AuthorDate: 2026-01-26 13:19:37 +0000 > Commit: Bjoern A. Zeeb <[email protected]> > 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); > >
