araghon007 / X1nput

Xinput hook for Impulse Trigger emulation
MIT License
331 stars 38 forks source link

Supporting controllers connected over bluetooth #24

Closed abdonkov closed 3 years ago

abdonkov commented 3 years ago

Is there a technical limitation that prevents you for supporting controlling that are connected over bluetooth (without the wireless dongle).

Because the controller's impulse triggers are working in supported games when I use it over bluetooth as well, so maybe it is possible to make it work.

When providing the correct Vendor Id and Product Id for the controller however, your program doesn't show any devices in the list. Do you make some checks for the properties of the device that could prevent a bluetooth controller from showing up in the list maybe?

Edit: Just found out that maybe I have inputted an incorrect vendor id. After correcting it, the device now is shown on the list, but when clicking on Test nothing happens...

The thing is here is the hardware ids for the "bluetooth XINPUT compatible device" which is the controller: BTHENUM{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&02e0 Its Vendor Id is 2045e which is larger than what it should be. And so you app doesn't find anything when I use it. But from the MS docs it looks like the VendorId is an ushort, which means we need only last 4 characters - 045e. And so when I use this Id, the app finds the HID device, but as I said when clicking Test nothing happens.

araghon007 commented 3 years ago

Well, I haven't done much experimenting with bluetooth, but I did realize that I have a laptop with a bluetooth adapter. Though when I tested it over bluetooth, the controller showed up without changing the VendorID (Though of course it did nothing). Are you using the elite controller or the normal one?

abdonkov commented 3 years ago

I'm using the normal Xbox One X controller.

Now even that the controller didn't vibrate when I clicked on Test, I tried to use it. And when injected to a game that had vibration. The vibration stopped working and the triggers didn't vibrate also. So the software correctly intercepts the Vibration I guess, but can't tell the controller to vibrate the trigger motors.

Also something interesting is that when connection the controller to the computer there are technically to devices created in the HID elements:

Name: Bluetooth XINPUT compatible device Device instance path: BTHENUM{00001124-0000-1000-8000-00805F9B34FB}_VID&0002045E_PID&02E0\7&2846DA66&0&EC83509765C3_C00000000 Hardware Ids: BTHENUM{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&02e0

Name: HID-compliant game controller Device instance path: HID{00001124-0000-1000-8000-00805F9B34FB}&VID_045E&PID_02E0&IG_00\8&302DDEDF&3&0000 Hardware Ids: HID{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&02e0

The first one always visible even when the controller is not connected and the second one shows up only when I connect the controller. I guess the first one represents the Paired bluetooth device and thats why it is always there.

As you can see both have the same VendorId and ProductId, although the Bluetooth device always shows the larger number for vendor id and the controller only in the hardware ids, but not the instance path. I don't know why that is but tehnically they should have the same vendor and product id. The values by the way are: Vendor Id: 1118 and Product Id: 736.

Now your applications only detects the second device, which should I guess be the real device corresponding to the controller because it only shows when I connect the controller. So the application finds it, but I guess there is a problem telling it what to do...

abdonkov commented 3 years ago

Just tried using the older version 2.0. That uses the Windows Gaming API, and it works with it. So I guess there is a problem with the new implementation using the HID interface...

abdonkov commented 3 years ago

After further research I probably found what is the problem as described in this stackoverflow thread: https://stackoverflow.com/questions/64732631/using-hidd-getinputreport-to-retrive-xbox-ones-button-states

It is a bit long but the problem is concluded by the author second post. All in all the HidD_SetOutputReport (which your application also uses) doesn't seem work with bluetooth connected controller, and so it is suggested to use another method of sending data to the controller through DeviceIoControl.

There is also a link to a test which uses this method here: https://gist.github.com/mmozeiko/b8ccc54037a5eaf35432396feabbe435

And here are the codes which can be seen in the example as well but not described what they are really: https://github.com/nefarius/XInputHooker/issues/1

Maybe you could check it out and see if it is possible to use this method instead of the hid report.

araghon007 commented 3 years ago

Oh huh, I was looking around before, but I didn't notice that quantus pursued his idea with reverse engineering the controller protocol further. I guess that would've been useful early on. As for the rest, I'm looking into it right now.

araghon007 commented 3 years ago

Sadly, DeviceIoControl seems to be a dead end, since IOCTL_XUSB_SET_STATE just does what XInput does, which means no trigger rumble

abdonkov commented 3 years ago

Yeah just tested it and the trigger motors didn't work sadly. I would like to ask however, why did you change to using the hid interface when making the hook? Isn't it possible to still use the Windows.Gaming.Input Api while hooking into the dll?

araghon007 commented 3 years ago

It is possible, but having to use WinRT causes compatibility issues and crashes that are very hard to debug. Plus I don't think I could come up with an implementation that is less janky then the old one.

abdonkov commented 3 years ago

Could you by any chance make it configurable whether to use the hidapi or the Windows.Gaming.Input API?

... But I guess for the best compatibility (windows 7 for example) you will have to build 2 separate X1nput.dll libs and the configurator will have to load them dynamically. Which probably is a lot work sadly...

Maybe there could be a possibility for the hidapi to work with bluetooth devices but who knows... :)

araghon007 commented 3 years ago

I was thinking about doing that, I don't think it would be too difficult, but I've already begun trying to reverse engineer the bluetooth protocol using WireShark, so we'll see where that gets me

abdonkov commented 3 years ago

You could probably use this app for easier reverse engineering: https://www.microsoft.com/en-us/p/game-controller-tester/9nblggh4pnc7

It probably uses the Windows.Gaming.Input API and it has an option to generate normal and/or impulse triggers vibration on trigger pressing.

I think it will be easier to see what values are send, when you know exactly the input, rather than trying it in a game, where the vibration will be arbitrary.

araghon007 commented 3 years ago

I tried that one, but I already made a test app that just makes the triggers rumble, without needing any input

abdonkov commented 3 years ago

Oh, yeah that sounds even easier :)

araghon007 commented 3 years ago

Well, so far I managed to send HID report with report ID 3 (no other IDs seem to work), but that doesn't work, and since I don't know much about the protocol, I'm not sure how to proceed

// Reset vibration
03 00 0E 00 0A 00 41 00 A2 03 0F 00 00 00 00 FF 00 EB

// HID set report
03 00 0E 00 0A 00 40 00 52 03 0F FF FF 00 00 FF 00 EB

// What I'm sending
0F FF FF 00 00 FF 00 EB

The first few bytes are the same, but then the 41/40 and A2/52 are different. I'm assuming that is because of using set report, and I'm sure A2 is the bluetooth alternative to 09, which should be the rumble command.

araghon007 commented 3 years ago

Nevermind, it does work, I tried changing the first byte in the report sent to the controller in X1nput Configurator to 3. Guess I was too quick to assume it does nothing. For me, the device was called HID-compliant game controller under HID devices and it showed up even without modifying the VendorID. I'll try updating the project so hopefully you could test it for yourself.

araghon007 commented 3 years ago

I have uploaded a new release now

abdonkov commented 3 years ago

Just tried it and the trigger motors are working perfectly now. Great work!

Thank you very much!