Mini Update: libusb Hotfix

While we usually wait for a Progress Report to write about bug fixes and other features, a regression was causing so many issues that we've decided to roll out an early monthly build and detail what happened and why right now. If you're a heavy user of Dolphin's passthrough features, this is a rather important update.

libusb Thread Safety Problems

libusb is an incredibly powerful library that facilitates direct communication to USB devices without needing to develop a kernel level driver. It also has the benefit of being cross platform between Windows, Linux, macOS, and even FreeBSD! Last Month, we saw a tremendous update to Passthrough support that fixed many issues on Dolphin's side and libusb's side, resulting in greater compatibility and stability among devices.

Unfortunately, things managed to break in another way due to some changes made to how Dolphin handles passthrough. Pretty much anyone on Windows using any sort of passthrough could potentially trigger one of the following issues, and it got particularly bad when multiple types of passthrough were combined.

  • Using multiple libusb devices at once, such as Bluetooth Passthrough and GameCube Controller Passthrough at the same time.
  • Reinitializing a libusb device during one session, such as booting multiple games rapidly or playing a game that uses ES_Launch
  • Other unknown combinations involving USB Passthrough and BlueTooth Passthrough/GameCube Controller Passthrough

If any of these conditions were triggered, Dolphin would usually crash. Sometimes, Dolphin could lock up and close without crashing, resulting in a ghost instance that would block any further instances of Dolphin from being able to use passthrough features until the user force closed the locked up instance. What caused this serious regression?

The problem stems from a change to how Dolphin handled each type of passthrough. With the latest batch of changes, Dolphin would use a single context for GameCube Controller Passthrough, Bluetooth Passthrough, and USB Passthrough. This was meant to simplify code and help accomodate usbdk users as it became unstable when we were using multiple contexts. In theory, everything should have been fine, as libusb was documented to be threadsafe in the situations we were going to be using it.

Unfortunately, this documentation is incorrect or we're misunderstanding it. While things weren't obviously wrong in isolated testing of each individual feature, it turns out that libusb would consistently deadlock when calling synchronous functions from multiple threads. The most common way to trigger this was by using two forms of passthrough at the same time. After over a week of investigation, we still have no idea if the fault is on our understanding of how libusb is supposed to work or a bug in libusb itself. Because we can't leave Dolphin in this state, we've decided to revert back to using multiple contexts and drop usbdk support.

We apologize to the sudden change in course, but this is a necessary step in providing a stable experience. These regressions, and subsequent fixes, should only affect users on Windows. At this point, we still recommend the libusbK driver, though, the WinUSB driver will also work for most devices. If you were already using one off those two drivers, you do not need to change anything, just update to the latest builds and the instability should be fixed. It is highly recommended that usbdk driver users uninstall the driver and switch to libusbK or winUSB.

If you need to change drivers, or even want to try passthrough for the first time, we have updated the guides for GameCube Controller Passthrough, Bluetooth Passthrough, and USB Passthrough