Solved Prevent driver from claiming particular USB device?

Is there an existing mechanism to prevent umass from claiming a specific mass storage device while allowing normal behavior for other devices?

I have a USB mass storage device I'd like to pass through to a VirtualBox VM and my experience is that the fight between umass on the host
and the guest driver is not pretty. I could take umass out of the kernel and only kldload it when needed for other devices but that's something of a
pain and doesn't cover all use cases.

Context is 12.1-RELEASE.

Thanks!
 
Right, I've read that and understand it - the VM sees the device just fine.

The problem is that umass on the host claims the device and so both umass and the guest driver try to control it with unpleasant results.

Absent some better solution, my current plan is to try writing a simple no-op driver that will glom onto my device more tightly than umass
does and then just stay out of the way.
 
Unfortunately, we have only kldload/kldunload, which load/unload a driver. There is no "kld detach" programm. ;D

Writing a simple no-op device driver is not that hard, actually.
 
Thanks *ross (et. al.)!

I have to admit that my last attempt at this was several years ago. Host was FreeBSD (probably 10.X) and guest was windows 7.
The symptoms, according to my notes, were that the device (or maybe the whole OS) would hang on the guest side. After building
a kernel without umass, everything was fine.

I now have a situation where I want to do the same thing and am looking for a better solution. So I'm currently rummaging through the
docs and kernel source to try to understand how to get a no-op driver to recognize and claim the device.

Thanks again.
 
OK, I'll give it another go with the stock setup and report my findings. I'm awaiting delivery of an old-style USB host adapter
with UHCI companion controllers which I'll need for VirtualBox USB pass-through to work, so it may be a couple of days.
 
Apparently, everything I thought I knew is wrong. I hate it when that happens...

I thought the limitation on VirtualBox USB pass-through of high-speed devices was actually an inability of VB to deal with EHCI
controllers in the absence of the "extension pack", thus the need for a UHCI companion controller. I also convinced myself that
umass was interfering with the guest OS's access to the device. It seems I was mistaken on both counts, although I think a UHCI
companion is still necessary to get the "hw.usb.ehci.no_hs" trick to work for a device that advertises itself as high speed.

Just plugged my device (a Brother P-touch label maker if anyone cares - it presents itself as an itty-bitty disk) into a relatively
modern, presumably EHCI only USB port on my 12.1 machine with umass present. The windows VM guest was a bit sluggish
in figuring out what it was dealing with but it got there eventually and the device works fine.

Sorry for the noise!
 
Think I spoke too soon.

Tried it again a short time ago after getting my devd rules set up so the device permissions would automatically be
suitable for pass-through. Running a 12.1-RELEASE-p1 kernel identical to GENERIC except umass commented out.
Had umass added to the "kld_list" line in /etc/rc.conf so it was loaded. VirtualBox built locally from ports tree updated
a couple of weeks ago.

Turned on device, then started windows VM. Device was seen by windows and the auto-launch dialog appeared.
Upon trying to launch the app (an executable on the device's emulated "disk"), windows locked up hard.

Killed the VM and unloaded umass. Moved umass out of the way so it wouldn't autoload. Tried again and everything
worked fine. Admittedly not absolutely conclusive but I'll run more trials to be sure.

Looks like I'm back in the driver writing business.
 
After the guest locked up, are there any errors on the host console (check by running dmesg)? What about in the guest Windows Event Log? Is there anything running on your host system that might automatically mount the USB disk (check whether it has been mounted somewhere by running mount | grep da0, assuming the USB disk appears as /dev/da0; you will see the identifier in the console)?

Have you found reports of any similar VirtualBox issues related to Windows guests with other host operating systems?
 
Here's dmesg(8) output for a pair of tests first with and then without umass(4) loaded:

Code:
ugen2.4: <Brother P-touch 2430PC> at usbus2
umass0 on uhub3
umass0: <Brother P-touch 2430PC, class 0/0, rev 1.10/1.00, addr 4> on usbus2
umass0:  SCSI over Bulk-Only; quirks = 0x8100
umass0:2:0: Attached to scbus2
da0 at umass-sim0 bus 0 scbus2 target 0 lun 0
da0: <Brother P-touch 2430PC 0.12> Removable Direct Access SCSI-2 device
da0: Serial Number 100C9F361255
da0: 1.000MB/s transfers
da0: 1MB (3041 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>
GEOM_PART: integrity check failed (da0, MBR)
GEOM_PART: integrity check failed (diskid/DISK-100C9F361255, MBR)
ugen2.4: <Brother P-touch 2430PC> at usbus2 (disconnected)
umass0: at uhub3, port 6, addr 4 (disconnected)
da0 at umass-sim0 bus 0 scbus2 target 0 lun 0
da0: <Brother P-touch 2430PC 0.12>  s/n 100C9F361255 detached
(da0:umass-sim0:0:0:0): Periph destroyed
umass0: detached
ugen2.4: <Brother P-touch 2430PC> at usbus2
vboxdrv: XXXXXXXXXXXXXXXX VMMR0.r0
vboxdrv: XXXXXXXXXXXXXXXX VBoxDDR0.r0
ugen2.4: <Brother P-touch 2430PC> at usbus2 (disconnected)

I don't know what the story is on the GEOM integrity check, but in past episodes this issue has come up with normal flash drives
so I tend to discount that.

The Windows event log is interesting: I see a few instances of ID=51
Code:
An error was detected on device \Device\Harddisk1\D during a paging operation.
and a whole pile of ID=11
Code:
The driver detected a controller error on \Device\Harddisk1\D.
Weirdly enough, the latter occurred during the successful earlier test (though again, Windows took an unusually long time to
recognize the device).

With umass(4) unloaded, I get no suspicious Windows events during use of the device.

I'm running x11-wm/xfce4 on the host. I know of nothing that should be explicitly accessing da0 although all this gvfs stuff is pretty
opaque to me. The disk device /dev/da0 does not show as mounted at any time.

I haven't encountered any reports of this with other hosts. For what it's worth, when I last encountered this several years ago, I ended up being
forced to install xubuntu in place of FreeBSD due to the need to have the extension pack for other reasons. After doing that, I didn't run into
similar problems.

If there's interest in tracking this down, I'm happy to help by gathering debug output or running test code. I wonder if attempting to access the
underlying ugen(4) node in some way while umass(4) is loaded would reveal anything.

Having said that, it seems like having umass(4) loaded while something else is using the lower layer device is asking for
trouble. Maybe this is a

Patient: "Doctor, it hurts when I do this!"
Doctor: "Then don't do that!"

sort of situation.

Thanks!
 
Apparently, at the end of 2019 someone added "detach_kernel_driver" functionality to usbconfig(8)

So you can try: usbconfig -d ugen2.4 detach_kernel_driver, then check dmesg. Maybe there is a better way than using "-d ugen2.4".

Edit: Is it just me, or does the man page link to FreeBSD-10.1-RELEASE man page? ?
 
Is it just me, or does the man page link to FreeBSD-10.1-RELEASE man page?
Nope, it was really happening. The reason is that we actually configured [MAN] to work for everything making [PMAN] somewhat obsolete. So its configuration wasn't updated any more. I fixed that, so it should be pointing to the 12.1-RELEASE man pages now.
 
Apparently, at the end of 2019 someone added "detach_kernel_driver" functionality to usbconfig(8)

So you can try: usbconfig -d ugen2.4 detach_kernel_driver, then check dmesg. Maybe there is a better way than using "-d ugen2.4".

Edit: Is it just me, or does the man page link to FreeBSD-10.1-RELEASE man page? ?

That's outstanding! Based on preliminary testing, it solves my problem perfectly.

Thank you!
 
Thanks, Elazar, I wasn't aware of the ability to detach a kernel driver from a USB device.

It would be interesting to know if that is how VirtualBox handles USB passthrough on other operating systems. For example, on a Windows VirtualBox host, is the USB device invisible to the host OS once passed to a guest? If so it might be worth suggesting to the VirtualBox developers that the function that Elazar highlighted is called on FreeBSD when USB device is passed to the guest.
 
I don't know anything about VMs, but usbconfig simply calls "usb_detach_kernel_module" from libusb. Libusb is a cross-platform library. Probably VirtualBox developers know it very well. ;D
 
Thanks, Elazar, I wasn't aware of the ability to detach a kernel driver from a USB device.

It would be interesting to know if that is how VirtualBox handles USB passthrough on other operating systems. For example, on a Windows VirtualBox host, is the USB device invisible to the host OS once passed to a guest? If so it might be worth suggesting to the VirtualBox developers that the function that Elazar highlighted is called on FreeBSD when USB device is passed to the guest.

So, I did a bit of spelunking in the sources of emulators/virtualbox-ose and it appears to me as if it's trying to do this even on FreeBSD.
It doesn't use libusb but implements its own interface.

In src/VBox/Devices/USB/freebsd/USBProxyDevice-freebsd.cpp, one finds
Code:
/**
 * Claims an interface.
 * @returns success indicator.
 */
static DECLCALLBACK(int) usbProxyFreeBSDClaimInterface(PUSBPROXYDEV pProxyDev, int iIf)
{
    int rc;

    LogFlow(("usbProxyFreeBSDClaimInterface: pProxyDev=%s "
             "ifnum=%x\n", pProxyDev->pUsbIns->pszName, iIf));

    /*
     * Try to detach kernel driver on this interface, ignore any
     * failures
     */
    usbProxyFreeBSDDoIoCtl(pProxyDev, USB_IFACE_DRIVER_DETACH, &iIf, true);

    /* Try to claim interface */
    return usbProxyFreeBSDDoIoCtl(pProxyDev, USB_CLAIM_INTERFACE, &iIf, true);
}
Why this isn't working is a mystery to me. If some spare time shows up, I'll try to investigate further.
 
It looks similar to libusb. An ioctl() with USB_IFACE_DRIVER_DETACH.

Code:
static int
ugen20_detach_kernel_driver(struct libusb20_device *pdev,
    uint8_t iface_index)
{
    int temp = iface_index;

    if (ioctl(pdev->file_ctrl, IOUSB(USB_IFACE_DRIVER_DETACH), &temp)) {
        return (LIBUSB20_ERROR_OTHER);
    }
    return (0);            /* kernel driver is detached */
}
 
...and suddenly it occurs to me that it probably isn't working because the uid under which vbox is running
doesn't have PRIV_DRIVER privileges. Don't particularly want to run vbox as root. Maybe a custom mac module
would be needed to solve this?
 
Back
Top