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);
>
>

Reply via email to