jfedor2/hid-remapper

Descriptor parser implementation - dealing with strangely composed descriptors

knuf-kandler opened this issue ยท 30 comments

Hi, first of all thank you for the great project, i`ve came to this idea two days ago when struggling with connection of HOTAS to VR headset just to find out today it already exists! ( : 10 minutes of soldering and i started to test it.

https://www.reddit.com/r/Quest3/comments/17t3w4i/3rd_party_controllers_problems_joysticks_hotas/

And now for the problem.

Devices involved : Meta Quest 3, hid-remapper running on single pico, Thrustmaster T.Flight HOTAS 4
Thrustmaster T.Flight HOTAS 4 is a gaming controller with 5 analog axes and few buttons and hat switch.
Problem : Only movement of X and Y axes is being recognized by the hid-remapper
Probable cause : Strangely composed descriptor is incorrectly parsed and report is not interpreted correctly
Additional Info : When connected WITHOUT hid-remapper, all axes and buttons are usable in Windows using propietary thrustmaster driver, in Android (Quest3 and my phone) only two axes (X and Y) are usable. Tried it with some Game Controller tools both in Quest and phone.

Question : How to remap the descriptor itself from its "strange(?)" form to something easily understandable for Android?

I know that hid-remapper uses its own descriptor at his hid side, so if i was able to correctly catch/interpret data from problematic axes i should be good to go. But - what is the problem with the incoming descriptor?

using WinHIDdump the descriptor in its raw form :

Thrustmaster T.Flight Hotas 4 (no serial number) (VID 1103, PID 46716, version 1.10) @ \?\hid#vid_044f&pid_b67c#6&e666289&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}

Report Descriptor:

05 01 09 04 A1 01 85 01 09 30 15 00 26 FF 03 35 00 45 00 65 00 55 00 75 10 95 01 81 02 09 31 81 02 09 32 25 FF 75 08 81 02 09 35 81 02 09 33 81 02 09 34 81 02 09 36 81 02 09 37 81 02 09 39 25 07 46 3B 01 65 14 75 04 81 42 05 09 19 01 29 0C 25 01 45 01 65 00 75 01 95 0C 81 02 06 00 FF 09 21 46 3B 01 75 08 95 33 81 02 85 F1 06 F0 FF 09 40 95 01 B1 02 09 47 95 3E B1 02 C1 00 (125 bytes)

Then i tried it to parse with https://eleccelerator.com/usbdescreqparser/

The reason why i think that there might be some discrepancy between various parsers is the fact that i tried to analyze the HOTAS in Device Monitoring Studio https://www.hhdsoftware.com/device-monitoring-studio

And parsed descriptor in DMS looks like this :

https://imgur.com/VwqRx9A

Parsed descriptor using online parse looks like this :

0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x04, // Usage (Joystick)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x09, 0x30, // Usage (X)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x03, // Logical Maximum (1023)
0x35, 0x00, // Physical Minimum (0)
0x45, 0x00, // Physical Maximum (0)
0x65, 0x00, // Unit (None)
0x55, 0x00, // Unit Exponent (0)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x31, // Usage (Y)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x32, // Usage (Z)
0x25, 0xFF, // Logical Maximum (-1)
0x75, 0x08, // Report Size (8)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x35, // Usage (Rz)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x33, // Usage (Rx)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x34, // Usage (Ry)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x36, // Usage (Slider)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x37, // Usage (Dial)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x39, // Usage (Hat switch)
0x25, 0x07, // Logical Maximum (7)
0x46, 0x3B, 0x01, // Physical Maximum (315)
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
0x75, 0x04, // Report Size (4)
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (0x01)
0x29, 0x0C, // Usage Maximum (0x0C)
0x25, 0x01, // Logical Maximum (1)
0x45, 0x01, // Physical Maximum (1)
0x65, 0x00, // Unit (None)
0x75, 0x01, // Report Size (1)
0x95, 0x0C, // Report Count (12)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x09, 0x21, // Usage (0x21)
0x46, 0x3B, 0x01, // Physical Maximum (315)
0x75, 0x08, // Report Size (8)
0x95, 0x33, // Report Count (51)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0xF1, // Report ID (-15)
0x06, 0xF0, 0xFF, // Usage Page (Vendor Defined 0xFFF0)
0x09, 0x40, // Usage (0x40)
0x95, 0x01, // Report Count (1)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x47, // Usage (0x47)
0x95, 0x3E, // Report Count (62)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC1, 0x00, // End Collection

What`s more interesting - in DMS i can see the HID report to be intepreted correctly - when i twist the stick, or move the throttle i can
see the values for corresponding axis changing :

X[0..1023]: 512 - X axis
Y[0..1023]: 522 - Y axis
Z[0..255]: 128 - Throttle
Rz[0..255]: 128 - rotating primary stick (different input same parameter)
Rx[0..255]: 255
Ry[0..255]: 255
Slider[0..255]: 128
Dial[0..255]: 128 - secondary analog axis on throttle
Hat Switch[0x0..0x7]/[0x0..0x13b]: 0x8
BUTTON1 pressed: 0
BUTTON2 pressed: 0
BUTTON3 pressed: 0
BUTTON4 pressed: 0
BUTTON5 pressed: 0
BUTTON6 pressed: 0
BUTTON7 pressed: 0
BUTTON8 pressed: 0
BUTTON9 pressed: 0
BUTTON10 pressed: 0
BUTTON11 pressed: 0
BUTTON12 pressed: 0

Any ideas what why hid-remapper does not see these axes - Z, Rz, and Dial ? (same question applies for Android Game controller SDL)

thx for help and rgds

Hi,

Can you dump the HID report descriptor (and some input traffic while you're at it) using Wireshark?

Sadly WinHIDdump doesn't give you the actual descriptor as sent by the device to the host, but some reconstructed form after it was parsed by Windows. To help troubleshoot what HID Remapper possibly gets wrong, we would really need the actual bits it's getting.

To capture the descriptor using Wireshark, start the capture and then plug the joystick in.

hotas4.zip

This is from USBpcap

05010905a10185010930093109320935150026ff007508950481020939150025073500463b016514750495018142650005091901290e150025017501950e81020600ff0920750695018102050109330934150026ff007508950281020600ff09219536810285050922951f910285030a2127952fb102c006f0ff0940a10185f00947953fb10285f10948953fb10285f20949950fb10285f30a01479507b102c0

trace attached

moved all axes and buttons.

while monitoring device in DMS i can identify the axes in raw view by eye. there is a huge vendor specific part in the report though

Oh, I did not know that Wireshark can parse the reports! :D that`s because it has descriptor avaiable in trace, right? you can see all the axes moving (X, Y, Z, Rz) and buttons being pushed in there, nice ( :

The thing i do not understand is how it can correctly interpret 2-bytes for X and Y when there is size(8) count(4) for X,Y,Z,Rz.

It seems that the joystick initially starts in PS4 mode, VID=0x044f, PID=0xb67b, with a report descriptor that looks the same on all PS4 controllers:

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x05,        // Usage (Game Pad)
0xA1, 0x01,        // Collection (Application)
0x85, 0x01,        //   Report ID (1)
0x09, 0x30,        //   Usage (X)
0x09, 0x31,        //   Usage (Y)
0x09, 0x32,        //   Usage (Z)
0x09, 0x35,        //   Usage (Rz)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8)
0x95, 0x04,        //   Report Count (4)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x39,        //   Usage (Hat switch)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x07,        //   Logical Maximum (7)
0x35, 0x00,        //   Physical Minimum (0)
0x46, 0x3B, 0x01,  //   Physical Maximum (315)
0x65, 0x14,        //   Unit (System: English Rotation, Length: Centimeter)
0x75, 0x04,        //   Report Size (4)
0x95, 0x01,        //   Report Count (1)
0x81, 0x42,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
0x65, 0x00,        //   Unit (None)
0x05, 0x09,        //   Usage Page (Button)
0x19, 0x01,        //   Usage Minimum (0x01)
0x29, 0x0E,        //   Usage Maximum (0x0E)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x75, 0x01,        //   Report Size (1)
0x95, 0x0E,        //   Report Count (14)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0x00, 0xFF,  //   Usage Page (Vendor Defined 0xFF00)
0x09, 0x20,        //   Usage (0x20)
0x75, 0x06,        //   Report Size (6)
0x95, 0x01,        //   Report Count (1)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01,        //   Usage Page (Generic Desktop Ctrls)
0x09, 0x33,        //   Usage (Rx)
0x09, 0x34,        //   Usage (Ry)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8)
0x95, 0x02,        //   Report Count (2)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0x00, 0xFF,  //   Usage Page (Vendor Defined 0xFF00)
0x09, 0x21,        //   Usage (0x21)
0x95, 0x36,        //   Report Count (54)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0x05,        //   Report ID (5)
0x09, 0x22,        //   Usage (0x22)
0x95, 0x1F,        //   Report Count (31)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0x03,        //   Report ID (3)
0x0A, 0x21, 0x27,  //   Usage (0x2721)
0x95, 0x2F,        //   Report Count (47)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection
0x06, 0xF0, 0xFF,  // Usage Page (Vendor Defined 0xFFF0)
0x09, 0x40,        // Usage (0x40)
0xA1, 0x01,        // Collection (Application)
0x85, 0xF0,        //   Report ID (-16)
0x09, 0x47,        //   Usage (0x47)
0x95, 0x3F,        //   Report Count (63)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0xF1,        //   Report ID (-15)
0x09, 0x48,        //   Usage (0x48)
0x95, 0x3F,        //   Report Count (63)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0xF2,        //   Report ID (-14)
0x09, 0x49,        //   Usage (0x49)
0x95, 0x0F,        //   Report Count (15)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0xF3,        //   Report ID (-13)
0x0A, 0x01, 0x47,  //   Usage (0x4701)
0x95, 0x07,        //   Report Count (7)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection

The interesting data is sent in the 54 byte long vendor specific part.

Then the Windows software for the joystick sends some command to it (I'm guessing it's the SET_REPORTs to report ID 0xF1) that switches it to PC mode, at which point it enumerates again with VID=0x044f, PID=0xb67c and a report descriptor as follows:

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x04,        // Usage (Joystick)
0xA1, 0x01,        // Collection (Application)
0x85, 0x01,        //   Report ID (1)
0x09, 0x30,        //   Usage (X)
0x09, 0x31,        //   Usage (Y)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x03,  //   Logical Maximum (1023)
0x75, 0x10,        //   Report Size (16)
0x95, 0x02,        //   Report Count (2)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x32,        //   Usage (Z)
0x09, 0x35,        //   Usage (Rz)
0x09, 0x33,        //   Usage (Rx)
0x09, 0x34,        //   Usage (Ry)
0x09, 0x36,        //   Usage (Slider)
0x09, 0x37,        //   Usage (Dial)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8)
0x95, 0x06,        //   Report Count (6)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x39,        //   Usage (Hat switch)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x07,        //   Logical Maximum (7)
0x35, 0x00,        //   Physical Minimum (0)
0x46, 0x3B, 0x01,  //   Physical Maximum (315)
0x65, 0x14,        //   Unit (System: English Rotation, Length: Centimeter)
0x75, 0x04,        //   Report Size (4)
0x95, 0x01,        //   Report Count (1)
0x81, 0x42,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
0x65, 0x00,        //   Unit (None)
0x05, 0x09,        //   Usage Page (Button)
0x19, 0x01,        //   Usage Minimum (0x01)
0x29, 0x0C,        //   Usage Maximum (0x0C)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x75, 0x01,        //   Report Size (1)
0x95, 0x0C,        //   Report Count (12)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0x00, 0xFF,  //   Usage Page (Vendor Defined 0xFF00)
0x09, 0x21,        //   Usage (0x21)
0x75, 0x08,        //   Report Size (8)
0x95, 0x33,        //   Report Count (51)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x06, 0xF0, 0xFF,  //   Usage Page (Vendor Defined 0xFFF0)
0x09, 0x40,        //   Usage (0x40)
0x85, 0xF1,        //   Report ID (-15)
0x09, 0x47,        //   Usage (0x47)
0x75, 0x08,        //   Report Size (8)
0x95, 0x3F,        //   Report Count (63)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection

When you connect it to HID Remapper, it doesn't send the special command that switches the joystick to PC mode so it continues in PS4 mode. The problem with that is that the PS4 mode report descriptor doesn't really describe the contents of the report properly.

There are two ways we could go about this.

We could emulate what the Windows software does and send the special command that switches the joystick to PC mode and hope everything works then (I'm not sure if HID Remapper would handle the device switching modes well, I seem to recall I had some issues in a similar situation with Logitech wheels).

Or we could make a "quirk" for the PS4 mode report descriptor. It's a mechanism that HID Remapper already uses for some trackballs that have broken report descriptors. It essentially adds special handling after it recognizes a device by VID/PID and report descriptor, fixing the broken parts of the descriptor.

I would suggest the second option as it would fit into the existing mechanism in HID Remapper.

For that to work we would need to know in which bits of the report the relevant data is being sent. We could probably find this information on the Internet as all PS4 joysticks likely use the same report layout. Or you could try sniffing some traffic while the joystick is in PS4 mode. You can probably uninstall the Windows software for the joystick (so that it stays in PS4 mode after plugging in) and try Wireshark again.

Oh, i see !

My fault, my fault. The device has a dedicated button to switch between the modes PS4/PC and it seems the driver in windows remembers the last state. Green LED = PC mode , Red LED = PS4 mode. And i had it set up in PC mode.

So i think the default mode is PS4 and i will do another trace in that mode. There is a functional difference between the modes which i noticed previously - in PS4 mode moving secondary analog axis on throttle and rotating the stick results in change of the same parameter Rz. In PC mode these two physical inputs are separated into Rz and Slider (i think).

Will do another trace in PS4 mode now.

Thank you very much for your time!

PS4 mode hopefully, with LED in RED - PS4, this mode is always present when connecting it to Android device.

Moved - X, Y, stick rotate, throttle, secondary axis on throttle, buttons. You can see that Rz moved twice.

HOTAS4_PS4_mode.zip

I don't know how the mode LED works, but this second trace looks like the first one, there's a mode switch at the beginning (new VID/PID and new report descriptor).

I`ll try to make a trace with mode switching.

hotas4_mode_switching.zip
This one started in RED mode (PS4) then i switched it with the button to PC mode (at least indicated by LED) then again back to PS4 mode.

moved it in every mode a bit

Is the correct desciptor needed if the reports are the same datawise? I mean, can we just take the correct parts from the report itself? Is there any bytemask doable using expressions?

Working theory is that the data sent is not the same between the modes.

This last trace looks the same, just one PS4->PC switch at the beginning. It seems the Windows driver has a way of overriding whatever mode you set from the joystick.

Can you try it on a machine that doesn't have Thrustmaster's software installed? Or a Linux box perhaps?

Tried to cleaned everything related to Thrustmaster, it got even two running services installed.

Now it looks much much different. Only X a Y is being sent in reports, some buttons work.

I think the device is pretty much useless in this mode, if it is even correct mode. I do not know if PS4 would interact with is similarly as windows and that proprietary thrustmaster sw.
hotas_cleared.zip

No, no, it's good. I mean the PS4 mode descriptor is indeed mostly useless, but we can see where the data goes in the dump so we can make a quirk for it. Give me a minute.

Oh, understood. Of course. I can see some bytes moving there, maybe i could make another trace with movement of each axis at once and report it with timestamps.

Anyway, output descriptors are selectable only from those few templates? How we should pass it to Android to make it understand clearly? I still don`t understand how it works in linux/android. Does the OS tries to map the controls and then provides them to the apps solely according descriptor or is it some other magic involved there? What are those kernel modules for? I can see some vendor specific files there.

https://github.com/walterschell/tflight4

Give this firmware a go: remapper_hotas_quirk.zip. If if didn't mess up the bit positions, all axes should be exposed (as some usage I made up).

As for output descriptors, do you mean in HID Remapper? Yeah, you can only select the ones you see, but if you want you can compile your own version and change the output descriptor to whatever you want.

In theory the way it works is the descriptor correctly describes the contents of the reports and the operating system or some layer between it and the application can extract the input state from them. In practice manufacturers often mess this up and make devices with bogus report descriptors, because they are the ones who then write the software or driver that interprets the report. So their software doesn't actually parse the report descriptor, it just knows that axis N will be there at byte M. Of course this causes problems when you want to use such a device on another operating system without the manufacturer's software.

On the PS4 only the basic inputs that you can find on a DualShock are properly described in the descriptor, additional axes and buttons for devices like steering wheels and flight sticks are just part of a giant vendor specific blob and of course the PS4 knows how to interpret it without having to parse the descriptor and we must add special cases to our software.

In a perfect world, devices that only have buttons and axes and don't require special configuration would just work on all operating systems without any software from the manufacturer.

And yeah, that repository includes exactly the information we needed and got from the dumps. In it you can see two report descriptors, the first one is the one that the joystick sends and the second one is the one it would send if we lived in a perfect world.

IT WORKS !

All of the axes are correctly seen in monitor !

thanks a lot, now i `ll try to map it to something understablem for the Quest / Android

thx again !

I`ll give a little update :

  • I was able to map stick axes, rotate and throttle to nintendo switch left and right stick analog axes, this worked OK, however not all buttons are recognized by the game. This is OK as i can see them switching in controller analysis tool in Android and the game uses some middle layer for providing input from OS to the Unity and they do not fully support nintendo switch controller :

https://guavaman.com/projects/rewired/docs/SupportedControllers.html

So i started trying to map different buttons to see which of them are recognized by the game.

problems :

it seems that those larger codes of the axes ( 0xfefe0001 - nothing strange in hex though) are being saved strangely and when i reconnect the mapper to reconfigure it i can see that the value of the expression starts with something like 0x-1003... then after second reconnection to configurator i can see just 0x00000 there

Then after some fiddling to get those values right each time i reconfigure it mapper started to behave really weird - after connecting it to Android device via OTG it stays up until i move some of the axes, then it directly hangs up and blue LED is on continuously - i can see this happened because the RED led on the HOTAS turns off immediately. What`s interesting touching buttons does not cause this, only moving either of the axes.

Of course i tried it reflash few times but now it hangs this way even after it is freshly flashed and i have not configured it at all.

Isnt the configuration stored in a flash so i could messed something persistently ? Ill try to erase the flash completely.

Erasing the flash helped.

when i reconnect it to configurator, original expression like this :

0xfefe0003 input_state

is read from the device like this :

0x-101fffd input_state

The negative hex thing looks like some silly bug, I need to investigate.

The negative hex thing looks like some silly bug, I need to investigate.

That should now be fixed. It was just in the web UI, but it would mess up the configuration if you saved it back to the device.

Hi, wanted to test it, but UI said i am running old version, so reflashed with today`s release and lost those 0xfefe... axes again in monitor.

Is it needed to be able to see it in monitor as confirmation that mapper sees them or i can just blindly config it by json and it will work?

Yeah, sorry, the changes from the build I posted above aren't in the latest release, you can either continue using that build and just use https://www.jfedor.org/hid-remapper-config/v9/ for configuration or I will rebase that branch later (it's in the repository BTW if you want to see the changes).

(And no, it won't work in the current official release.)

Oh, i see, so that negative hex bug is fixed in ui v9 too. thank you ( :

now it is time to find some rpi laying somewhere around and start to mess with the default descriptors as i would need to compile it on my own.

thing is that when in "ps4 arcade stick mode" it is not recognized by the Android properly and even primary stick axes are swapped with analog trigger axes. I think that Dualshock4 is so popular that it has the best support in Android so mimicking DS4 should result in highest number of usable axes and buttons in games. Even that middleware (rewired) shows it as fully supported, while nintendo switch is only "partially mapped" what explains that only some of the buttons are passed to the game in nintendo switch mode, but all of them are visible in Game Controller Test app in Android.

Are usable targets dynamically rendered in UI according selected descriptor or is it just static profile chosen when changing the modes?

If you recompile with a modified descriptor, the target usages will be selectable in the UI, though they won't have pretty names.

I suspect some systems/applications also have mappings hardcoded to VID/PID. The PS4 arcade stick descriptor is pretty much identical to a DS4 descriptor. VID/PID can be faked too, though we currently only do it for the Switch mode.

If you don't want to setup a build environment, you can just fork and edit on GitHub and let GitHub Actions build it for you.

yes, modification of VID/PID was my first idea as in ps4 arcade mode it showed completely different values than in this collected info about DS4. Also Android can "name" the controller in Switch mode identifying it as Nintendo Switch, but in ps4 mode it shows only generic "gamepad"

https://www.psdevwiki.com/ps4/DS4-USB

Did not find where those values are in source files yet (not part of hid descriptor, right?)

They're not part of the descriptor, but they're in our_descriptor.cc. Just follow the Switch example.

I know it is a silly question but i`ve spent a day trying to find out how to run Actions on forked repo and did not succeed yet. ( :

Is there any special prerequisite to enable Actions? I can see them with your workflows predefined in yaml, but i do not know, how to run them ( :

I think there's a big button to enable them in the Actions tab? If not try the repository Settings screen and then Actions in the menu on the left.

i have this in project setting selected :

Actions permissions

  • Any action or reusable workflow can be used, regardless of who authored it or where it is defined.
    (tried to resaved it)

But Actions tab shows just this

https://imgur.com/3aFfWkC

added a workflow_dispatch: in on:
button appeared

After you enable the workflows you have to make another trivial commit that changes something under firmware/. It won't trigger on previously existing commits.

Great!

Took a quirk youve made for the hotas4, corrected vid and pid for ps4 controller and voilaaa. Both phones and quest3`s Androids are recognizing it correctly as PS4 controller with all axes identified correctly!

thank you very much, i`ve learned a lot ( :