ShadowBlip / InputPlumber

Open source input router and remapper daemon for Linux
GNU General Public License v3.0
63 stars 9 forks source link

L4/R4 and trackpad for GPD Win Mini #157

Open justinweiss opened 1 month ago

justinweiss commented 1 month ago

I couldn't get L4/R4 on the GPD Win Mini to respond as paddles on "Test Device Inputs" in Steam, and I couldn't map them to anything with a yaml config.. They also don't show in the InputPlumber logs when pressed. I can see the GPD Win Mini recognized from the InputPlumber logs.

I verified that usb-0000:63:00.3-3/input1 sends KEY_SYSRQ and KEY_PAUSE for the physical L4/R4 buttons. They act as a key repeat instead of a single press, hold, release though.

I also noticed that the trackpad and physical keyboard aren't in the composite device config. The trackpad doesn't have a physical click, and gamescope-session doesn't support tap-to-click, so it would be perfect if inputplumber could map or handle a tap as a physical click.

the physical touchpad on the Win Mini is

NAME="HTIX5288:00 093A:0255 Touchpad"
PHYS="i2c-HTIX5288:00"

and the physical keyboard is

NAME="AT Translated Set 2 keyboard"
PHYS="isa0060/serio0/input0"

Ultimately my goal would be to create a config that would map trackpad with simulated click, L4/R4, buttons, and gyro all to a simulated DS5 or Steam Deck controller, so I could use it all with Steam Input.

Happy to help collect data or try things.

pastaq commented 1 month ago

We're going to need some packet captures of the hid reports in action for the touchpad and back buttons. On arch Linux you can install the hid-tools package to get access to hid-decode and hid-recorder

First we'll need the report descriptor for each device hid-decode can provide that information. You need to give it the full path (e.g. sudo hid-decode /dev/hidraw0)

After that we'll need a udev attribute walk for each device udevadm info /dev/hidraw0 --attribute-walk

Finally, an hid-recorder capture of each event per device. Hid-recorder has decent output and will produce a straight raw output, as well as a formated display of the event. Here are some examples: https://github.com/ShadowBlip/InputPlumber/blob/1f2ad006f001f112e8ece9e29c528b56e86c0ec2/src/drivers/lego/hid_report.rs#L33-L35

We need all that data so we can interpret it properly.

For the back paddles, one capture where left is the only button pressed, one with right only, one with both where left is pressed first, and one with both where right is pressed first

For the touchpad, one each with a single touch in each corner, and one with as many touches as it will detect.

And for good measure one of each with nothing happening.

The keyboard will be easy to add, but I don't recommend it unless there is a specific thing you want to translate on it.

For gyro I just need the name. You should be able to use cat /sys/bus/iio/devices/iio:device0/name

aarron-lee commented 1 month ago

So just as some additional context, the L4/R4 on GPD devices are actually macro buttons that repeat an up to 3-key macro at a regular interval. This is built into the firmware, there's no way to turn them into simple buttons.

HHD had to do some hacky logic to make the buttons pretend to be L4/R4 buttons that can support hold actions, and as a side effect of the hacky workaround, there's very noticeable latency when it comes to detecting when the button is released. You can see the hhd implementation here

edit: here's a video recording on the Chimera discord of the L4/R4 button behavior

justinweiss commented 1 month ago

It looks like the back buttons are hidraw1 and the trackpad is hidraw3.

Gyro is i2c-BMI0160:00 (but is actually a 260)

pastaq commented 1 month ago

I haven't forgotten about this, I've just been preoccupied with the ROG Ally X and some things I had to do for OrangePi. I'll try to take a look at this sometime this week.

pastaq commented 1 month ago

@justinweiss the timing for the back paddle events seems... sporadic. Its almost like they are randomly coming in between 0.02s and 0.3s. Can you confirm if there is a consistent delay when holding, and the delay from the last event is different in any way? It looks as though I will need to set a "Last event" timer that resets for every event received and is longer than the maximum observed delay between events when held. That won't be very difficult, but I'd like to ensure that delay is as low as is reasonable with a 10% margin to prevent erroneous up events.

pastaq commented 1 month ago

As for the trackpad, many of them support up to 10 fingers but used 4 inputs per report, and swap the index around as needed to report each to the kernel. We generally add this overhead to every touchpad device. Does this touchpad have a button BTW? Also, where is it physically located?

justinweiss commented 1 month ago

Not a problem at all! Thanks for taking a look.

There's no button on the touchpad and it doesn't depress, which is why having a tap is important :-) No other way to get a click. The touchpad is in the top center, between the sets of controls: image

Here's a longer capture: back_button_record_long.txt

I held R4 for around 5 seconds, then released for about 5 seconds, then held for about 10 seconds, then released.

It looks like it sends Pause for around 300ms and then releases for around 20ms, and repeats for as long as it's being held down. It's hard to tell whether the delay from the last event is different, but it seems like it always waits the full 300ms before sending the release event when you release the button.

(I have not changed the mappings, and I think it's reasonable to only support the default mappings)

aarron-lee commented 1 month ago

image

This is what the remapping UI looks like in Windows for the L4/R4, for reference.

pastaq commented 1 month ago

image

This is what the remapping UI looks like in Windows for the L4/R4, for reference.

That makes the design make a lot more sense. It's for stringing combos together to cheat at fighting games. Lol

pastaq commented 1 month ago

Not a problem at all! Thanks for taking a look.

There's no button on the touchpad and it doesn't depress, which is why having a tap is important :-) No other way to get a click. The touchpad is in the top center, between the sets of controls: image

Here's a longer capture: back_button_record_long.txt

I held R4 for around 5 seconds, then released for about 5 seconds, then held for about 10 seconds, then released.

It looks like it sends Pause for around 300ms and then releases for around 20ms, and repeats for as long as it's being held down. It's hard to tell whether the delay from the last event is different, but it seems like it always waits the full 300ms before sending the release event when you release the button.

(I have not changed the mappings, and I think it's reasonable to only support the default mappings)

This helps, thanks. Might take some time tuning but if you should get a new down event for the key in question within 20ms we should be able to use that as the trigger for the fastest response time. I think double hold might make this longer but we can test that. We actually already do something like this for touchpads to determine if a press is still being held or not so the logic is simple.