qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

USB port claiming / set configuration problems


From: Ben Leslie
Subject: USB port claiming / set configuration problems
Date: Thu, 4 Mar 2021 14:45:32 +1100

I have encountered a number of devices (mostly mobile phones) which seem to get very confused if a "SET CONFIGURATION" control transfer (for the same interface) is performed twice.

Specifically, after receiving a 2nd SET CONFIGURATION (for the same interface) the device times out on future bulk output transfers. (Sometimes PING-NAK continues until the overall transfer times out, in other cases the PING itself timeouts after ~200 PING-NAKs).

While I'm fairly confident in saying that the USB firmware on these devices is broken they seem to work enough to be operable when running a native operating system.

Unfortunately when running the same operating system virtualized under Qemu we are able to trigger this bug.

This was originally found using an older (4.2) version of Qemu. It seems like that the patch bfe44898848614cfcb3a269bc965afbe1f0f331c was able to solve the issue for some of the devices we see. Specifically, this avoids actually performing a SET CONFIGURATION control transfer if there is only a single configuration. The commit message "Seems some devices become confused when we call libusb_set_configuration()." seems to confirm some of the behaviour we have been seeing.

Unfortunately, while this appears to have solved the issue for devices with a single configuration we still appear to have problems when hitting devices with multiple configurations (which is not surprising given that the commit only changed behaviour for single-configuration devices).

To attempt a work-around and validate the theory I change the `usb_host_set_config` function (in host-libusb.c) such that it first checks if the current active configuration matches the request configuration, and if so skips performing the actual SET CONFIGURATION control transfer.

Would a patch of this nature be the right approach?
Perhaps this check could replace the number of configurations check?

Taking a step back here, the larger problem is that Linux host performs various control transfers prior to qemu (and therefore the guest operating system) gaining control of the device.
This means the sequence of control transfers with the device is inherently going to be different when the guest OS is virtualized as compared to running natively. For well behaving devices this really shouldn't matter, but not all devices are well behaving!

USBDEVFS has support for `USBDEVFS_CLAIM_PORT` (and `USBDEVFS_RELEASE_PORT`) ioctls. From the definition this seem designed to limit the interaction that Linux kernel might have with a device on a claimed port, which seems perfect for this use case. This in fact used in previous version of qemu if we go back to the host-linux.c days, but with the change over to host-libusb.c this functionality was lost.

Was this intentional? Would adding support to host-libusb to use these ioctl to claim the port be beneficial? Based on a simple test program and hardware USB traces for a device connected to a 'claimed' port the kernel does indeed leave the device in an unconfigured state. (Although it still performs some basic control transfers to gather descriptor, and strangely seems to in this case make an explicit SET CONFIGURATION transfer, but sets configuration to zero, rather than an actual configuration, which, at least for the devices I was able to test with, avoided the problems of calling SET CONFIGURATION (1) twice). Integrating this support back into host-libusb.c is a little more involved than the work around described above, so I'd appreciate any feedback before going down that path.

Thanks,

Ben










reply via email to

[Prev in Thread] Current Thread [Next in Thread]