Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nsyshid: add linux support using libusb #946

Closed
wants to merge 1 commit into from

Conversation

ssievert42
Copy link
Contributor

This adds USB hid support to the linux build using libusb.

Works nicely with the Lego Dimensions portal (and has seen several hours of (ab)use); I can't test with any other devices though because I don't own them or the games that use them.

Libusb needs to be installed as a system dependency.

To be able to use a device, one needs to add some udev rules. For example to use the Lego Dimensions portal, you'd need to create a file /etc/udev/rules.d/99-lego-dimensions-portal.rules with the following contents:

# allow applications to talk to the lego dimensions portal
# place this file in '/etc/udev/rules.d/'
# after that you need to reboot or run 'sudo udevadm control --reload' and replug the device for the rules to apply
SUBSYSTEM=="usb", ATTRS{idVendor}=="0e6f", ATTRS{idProduct}=="0241", MODE="0666"

Some things aren't implemented, but it seems like they are not needed for Lego Dimensions to function properly.

This has been cooking for a while (and at least somewhat working since may 2023). I always told myself that I would implement the missing stuff, but never got around to it 😅
So, since at least the device I wanted to support seems to work very well, I'm just gonna declare this as ready now.

Note that I am not experienced at all when it comes to working with usb devices or libusb. Suggestions how to improve this are very welcome :)

One neat thing that is included here as well is hotplug support - having to restart the game because of a flaky USB connection drove me mad enough to add this.
For hotplug support there needs to be someone that regularily calls libusb_handle_events_completed. I did this with a separate thread, but feel like there should be a better place to call this from.

Originally, I wanted to wrap only the parts that were different in preprocessor statements, but I ended up changing a bunch of other stuff as well and have no way to (easily) test on windows, so the implementation using libusb is completely separate from the native windows one.

Should ideally close #275 but, as I said above, I've got no way to test devices other than the Lego Dimensions portal.

Flatpak build: Shouldn't cause any issues, because libusb is already bundled by the line - shared-modules/libusb/libusb.json in the modules section of info.cemu.Cemu.yml.
AppImage: Seems to assume that libusb is part of the base system because it is on the excludelist and thus shouldn't cause any issues either.

This might also work on macOS if we were to bundle libusb (and in nsyshid.cpp the #elif __linux__ is replaced by something like #elif __unix__ and we always link against libusb by replacing if (UNIX AND NOT APPLE) with if (UNIX) in src/Cafe/CMakeLists.txt), but I don't know anything about macOS USB handling / permissions and have no way to test on that OS.

Things that I'd have liked to add, but am not planning to, and probably belong in another pr anyways:

  • device whitelist - Currently, this exposes all USB devices to the emulated Wii U
  • proper device descriptor passthrough - export_HIDGetDescriptor creates pretty much the same config descriptor for all devices

@Exzap
Copy link
Member

Exzap commented Aug 23, 2023

Appreciate the effort. However this seems to replicate a lot of the work done in PR #903. Can you coordinate with the author there and work towards either a unified PR or something that will keep both libusb and emulated devices support intact.

@ssievert42
Copy link
Contributor Author

I didn't notice #903, at least that wasn't there when I started hacking on this 😅
Support for emulated devices is a new feature, that would be added by #903 and maybe follow up PRs, right?
#903 still seems rather wip, but I guess it should be easy enough for me to wrap the passthrough device stuff in this PR in a way that can then be extended to completely emulated devices, and used in #903.
Would you rather keep the native Windows device handling, or completely switch to libusb on Windows as well? The problem I could see with switching to libusb on Windows is, that neither my implementation, nor the code in #903 attempt to do control transfers.

@ssievert42 ssievert42 marked this pull request as draft August 24, 2023 10:11
@Exzap
Copy link
Member

Exzap commented Aug 24, 2023

From what I understand, libusb would require the zadig drivers on Windows while the Windows HID API works with the default windows drivers requiring no extra steps from the user. I'd say we don't need to have Windows HID API because most users coming from Dolphin will already have the zadig libusb drivers installed anyway, but it would still be nice to have it. However it's not a priority and can be added back with a separate PR.

I'd follow the advice suggested by @deReeperJosh in the other PR and implement the devices as a class with virtual methods that roughly match the Wii U API. Then new back-end APIs (libusb, emulated devices or Windows HID) can easily be added by inheriting from the device class and implementing the methods.

@ssievert42
Copy link
Contributor Author

Superseded by #950

@ssievert42 ssievert42 closed this Aug 26, 2023
@Funkeemonkee06
Copy link

Funkeemonkee06 commented Sep 18, 2023

hey, could you tell me where to find the information for and how to wire a udev rule?

@ssievert42
Copy link
Contributor Author

Hi @Funkeemonkee06, the arch wiki has a bunch of good info on that :)

If all you want to do is use a device like the Lego Dimensions portal, you have to figure out that device's vendor and product id.
That's as simple as running lsusb both while your device is connected, and while your device isn't connected, and comparing the output. Ideally you should be able to identify the device by it's name alone.
For example, lsusb prints this for the Lego Dimensions portal on my computer:
Bus 007 Device 005: ID 0e6f:0241 Logic3 LEGO READER V2.10
Where 0e6f is the vendorId and 0241 is the productId.
Then you simply plug that into the corresponding places in this line:
SUBSYSTEM=="usb", ATTRS{idVendor}=="0e6f", ATTRS{idProduct}=="0241", MODE="0666"

By the way: This PR is outdated and #950 contains basically everything that was included here, but in a more abstracted way, plus some other stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Linux] [Skylanders] USB Support for Portal of Power
3 participants