Valkirie / HandheldCompanion

ControllerService
Other
1.09k stars 86 forks source link

Replace ViGEmBus/Hidhide requirement with WinUSB #1042

Open jonshipman opened 2 months ago

jonshipman commented 2 months ago

https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation

In my head, it seems like you could have the software remove the OEM controller drivers and install the WinUSB driver for the same device. Dolphin uses this to natively interact with Wii Controllers. It would be more work, but would remove needing users setting up/configuring these applications.

So you'd need a dictionary of all the supported handheld gamepads, identify the one in use, remove the device driver, install WinUSB for the device, then have Handheld companion handle the button presses via software.

CasperH2O commented 2 months ago

Hey Jon, not sure I follow, we use Vigembus to create either a virtual DualShock4 or virtual Xbox360 and HidHide is used to hide certain HID devices, in HCs case the physical built in controller of various devices. Can WinUSB do this also?

jonshipman commented 2 months ago

WinUSB is a kernel mode stack driver allowing direct software control of hardware. So yes, however, it would mean interpreting the device in Handheld Companion vs. leaving that up to Vigembus.

I own a Legion GO so it has a bit of a unique situation. It uses four device ids (17ef:6182 - 17ef:6185) to reference the different hardware states of the controllers. 82 being both controllers connected and 84 would be both detached. In this scenario, you would query for the device "17ef:6182" and uninstall the driver associated with that device id and install a custom inf referencing WinUSB. In Handheld Companion, you'd have the service listen to "17ef:6182" and do actions for the bytes sent (https://old.reddit.com/r/LegionGo/comments/17u5nz4/linux_usbhiddump_m_17ef6182_e_all_this_shows_that for specific bytes for the Legion)

I may try a POC application that goes through the flow. I think this approach may improve overall stability of application and remove the dependencies (which Windows doesn't really do a good job of providing a framework).

CasperH2O commented 2 months ago

@jonshipman sounds promising. Could be quite the challenge in supporting all the various devices though.

@nefarius what is your opinion on this alternate approach?

nefarius commented 2 months ago

We've successfully eliminated the need for HidHide in our DS4Windows fork, please have a look. I also added reliable and tested code to my device management library for hot swapping to WinUSB and back. I recommend this approach, it works well. Feel free to ask me anything about the details.

nefarius commented 2 months ago

Here's an example you can adapt into a PoC and run on one of your preferred game pads https://github.com/nefarius/Nefarius.Utilities.DeviceManagement/blob/d1b8cbf47f123d397c217cf60f37d68b5b789552/App/Program.cs

nefarius commented 2 months ago

And no, WinUSB can't replace ViGEmBus, it is meant to replace the default HIDCLASS drivers on the physical input device, though. So you can bypass all of that and directly talk to the device. This is all already implemented and working in Vapour Input, linked above.

nefarius commented 2 months ago

Also the migration to this approach will not be done in 5 steps. After switching to WinUSB you need to talk USB to your controller, not HID, so you need to add all the work in crafting packets into your app that would usually be offloaded to hidusb.sys like adding wrappers to craft GET_REPORT, SET_FEATURE etc. requests.

I also provide a WinUSB library for .NET to simplify interaction 😉