fix(usb): strip web-config reports 0xF6-0xF9 so the HID descriptor byte-matches a real DS5

The OLED Edition declared four extra feature reports (0xF6-0xF9, the WebHID config
IDs) in the DualSense HID descriptor, making it 321 bytes vs a genuine DS5's 289.
Games' native DualSense parser (Cyberpunk, etc.) rejects the mismatch and falls
back to generic/Xbox, so adaptive triggers never fire in a game -- the long-standing
"triggers only work in the OLED self-test" bug.

Remove the four declarations and the runtime wDescriptorLength patch that overrode
them (0x41->0x21) so the descriptor is byte-identical to a real DS5 (289 bytes). The
firmware still handles 0xF6-0xF9; they're just undeclared now and work over hidraw on
Linux exactly like 0xFD. Trade-off: the browser WebHID config tool can't reach them
(OLED + hidraw config still work).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MarcelineVPQ
2026-06-07 10:36:10 -06:00
co-authored by Claude Opus 4.8
parent 5e5aa71cfe
commit 36687ce76d
+11 -20
View File
@@ -372,7 +372,7 @@ uint8_t descriptor_configuration[] = {
0x00, // bCountryCode: Not localized 0x00, // bCountryCode: Not localized
0x01, // bNumDescriptors: 1 report descriptor 0x01, // bNumDescriptors: 1 report descriptor
0x22, // bDescriptorType: Report 0x22, // bDescriptorType: Report
0x41, 0x01, // wDescriptorLength: 321 (0x0141) DS 0x21, 0x01, // wDescriptorLength: 289 (0x0121) DS (F6-F9 removed to byte-match a real DS5)
// 0xB5, 0x01, // wDescriptorLength: 437 (0x01B5) DSE // 0xB5, 0x01, // wDescriptorLength: 437 (0x01B5) DSE
// Endpoint Descriptor (HID IN: EP4) // Endpoint Descriptor (HID IN: EP4)
@@ -418,7 +418,7 @@ uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
descriptor_configuration[offset - 1] = bInterval; descriptor_configuration[offset - 1] = bInterval;
descriptor_configuration[offset - 8] = bInterval; descriptor_configuration[offset - 8] = bInterval;
if (ds_mode()) { if (ds_mode()) {
descriptor_configuration[offset - 16] = 0x41; descriptor_configuration[offset - 16] = 0x21; // wDescriptorLength lo = 289 (0x0121); F6-F9 removed to byte-match a real DS5
}else { }else {
descriptor_configuration[offset - 16] = 0xB5; descriptor_configuration[offset - 16] = 0xB5;
} }
@@ -571,26 +571,17 @@ uint8_t const desc_hid_report_ds[] = {
0x09, 0x36, // Usage (0x36) 0x09, 0x36, // Usage (0x36)
0x95, 0x03, // Report Count (3) 0x95, 0x03, // Report Count (3)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0xF6, // Report ID (-10) // NOTE: web-config feature reports 0xF6-0xF9 are intentionally NOT declared
0x09, 0x37, // Usage (Vendor 0x37) // here. Declaring them made this descriptor 321 bytes vs a genuine DS5's 289,
0x95, 0x3F, // Report Count (63) // and games' native DualSense parser rejected the mismatch -> no adaptive
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) // triggers in-game (the long-standing "triggers only work in the OLED test"
0x85, 0xF7, // Report ID (-9) // bug). The firmware still HANDLES 0xF6-0xF9 (src/cmd.cpp); on Linux they
0x09, 0x38, // Usage (Vendor 0x38) // work fine undeclared over hidraw, exactly like 0xFD. Trade-off: the browser
0x95, 0x3F, // Report Count (63) // WebHID config tool can't reach them (OLED + hidraw config still work).
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0xF8, // Report ID (-8)
0x09, 0x39, // Usage (Vendor 0x39)
0x95, 0x3F, // Report Count (63)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0xF9, // Report ID (-7)
0x09, 0x3A, // Usage (Vendor 0x3A)
0x95, 0x3F, // Report Count (63)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection 0xC0, // End Collection
// 321 bytes // 289 bytes — byte-identical to a real DualSense
}; };
static_assert(sizeof(desc_hid_report_ds) == 0x0141); static_assert(sizeof(desc_hid_report_ds) == 0x0121);
uint8_t const desc_hid_report_dse[] = { uint8_t const desc_hid_report_dse[] = {
0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)