HidSharp icon indicating copy to clipboard operation
HidSharp copied to clipboard

Error reading XBox One Controller analogue values

Open RogerHardiman opened this issue 1 year ago • 3 comments

Hi When Parsing the InputReport from an XBox Controller (hardwired on USB) I get NaN for the analogue joystick values. I can see the values are present int he raw data but Parsing the InputReport returns NaN

It looks like the valid range (physical and logical) for the XBox controller is Min=0 Max=0

So I'm guessing a bug where this library computes the ranges.

Has anyone else come across this issue?

Happy to dig into the code, and do a PR if needed.

Roger

RogerHardiman avatar Jan 02 '25 18:01 RogerHardiman

The Report bytes are here:-

05 01 09 05 A1 01 09 00 A1 00 09 30 15 00 35 00 65 00 55 00 75 10 95 01 81 02 09 31 81 02 C1 00 09 00 A1 00 09 33 81 02 09 34 81 02 C1 00 09 00 A1 00 09 32 81 02 C1 00 05 09 19 01 29 10 25 01 45 01 75 01 95 10 81 02 05 01 09 39 15 01 25 08 46 3B 10 65 0E 75 04 95 01 81 42 15 00 25 01 45 01 65 00 75 01 95 14 81 03 C1 00

And https://eleccelerator.com/usbdescreqparser/ translates this to the following:-

0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x05, // Usage (Game Pad) 0xA1, 0x01, // Collection (Application) 0x09, 0x00, // Usage (Undefined) 0xA1, 0x00, // Collection (Physical) 0x09, 0x30, // Usage (X) 0x15, 0x00, // Logical Minimum (0) <- NO LOGICAL MAXIMUM DEFINED. This library uses 0 0x35, 0x00, // Physical Minimum (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) 0xC1, 0x00, // End Collection 0x09, 0x00, // Usage (Undefined) 0xA1, 0x00, // Collection (Physical) 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) 0xC1, 0x00, // End Collection 0x09, 0x00, // Usage (Undefined) 0xA1, 0x00, // Collection (Physical) 0x09, 0x32, // Usage (Z) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC1, 0x00, // End Collection 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) 0x29, 0x10, // Usage Maximum (0x10) 0x25, 0x01, // Logical Maximum (1) 0x45, 0x01, // Physical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x10, // Report Count (16) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x39, // Usage (Hat switch) 0x15, 0x01, // Logical Minimum (1) 0x25, 0x08, // Logical Maximum (8) 0x46, 0x3B, 0x10, // Physical Maximum (4155) 0x65, 0x0E, // Unit (None) 0x75, 0x04, // Report Size (4) 0x95, 0x01, // Report Count (1) 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x45, 0x01, // Physical Maximum (1) 0x65, 0x00, // Unit (None) 0x75, 0x01, // Report Size (1) 0x95, 0x14, // Report Count (20) 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC1, 0x00, // End Collection

// 107 bytes

Note there is no Logical Maximum for the X Axis. Do we just define the maximum as (2^16)-1, ie 65535 as it is a 16 bit value

Note, a different Joystick (from CH Products) has min and max defined, e.g. 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)

RogerHardiman avatar Jan 03 '25 13:01 RogerHardiman

Please note that the HID report descriptor on Windows is reconstructed by HidSharp using its own - faulty, see #15 - logic. So you have to fetch the actual HID report descriptor out of a Linux / Mac host machine to get a correct picture.

benedekkupper avatar Jan 03 '25 20:01 benedekkupper

Thank you for explaining the Report is reconstructed on Windows. Plugging the XBox One controller into Linux does not give me a HID report descriptor. Ubuntu detects it as a XInput protocol (and not HID) device and uses the Linux driver called "xpad"

I am wondering if the controller supports HID or if Microsoft fake the HID messages in the Windows driver.

Anyway I can see the cause of my problems.

  1. HidSharp uses the Win API to get HID Capabilities. The Win API docs tell me LogicalMax and PhysicalMax are a Signed LONG (signed 32 bit)

  2. HIDSharp reads the caps into a structure with an 'int' field and this value is -1 so I assume the 4 bytes are 0xFF FF FF FF I think Microsoft should have returned 0x00 00 FF FF (ie 65535).

Are we supposed to AND Mask the Max value with the bit length?

The only other device I have here reports a LogicalMax of 1023 so don't have anything else that has a max of 65535 or -1 depending on how you interpret the raw value.

Could we add a special case? I'd prefer the code to be correct but don't know if an AND Mask is the right thing to do.

RogerHardiman avatar Jan 06 '25 16:01 RogerHardiman