Skip to content

fix(hid-rp): gamepad input report data offset for byte-wide axes - #829

Merged
finger563 merged 1 commit into
esp-cpp:mainfrom
owenpkent:fix/hid-rp-gamepad-report-offset
Sep 30, 2026
Merged

finger563 merged 1 commit into
esp-cpp:mainfrom
owenpkent:fix/hid-rp-gamepad-report-offset

Conversation

@owenpkent

Copy link
Copy Markdown
Contributor

Problem

GamepadInputReport::get_report() and set_data() skip a fixed two bytes at the front of the object. That is correct for the default uint16_t axes (the one-byte report id plus one byte of alignment padding before joystick_axes), but a report with uint8_t axes has no padding, so the copy starts one byte late:

  • X is dropped and every later field moves down one slot (the host sees Y on X, Z on Y, and so on)
  • RZ reads the brake value, 0 at rest, which pins the right stick to one edge
  • the last byte is read from past the end of the object, and set_data() writes one byte past it

With REPORT_ID == 0 there is no id byte at all, so the offset is wrong there too.

Object dump of GamepadInputReport<12, uint8_t, uint8_t, 0, 255, 0, 255, 1> with sentinel values (01 is the id, then X Y Z RZ brake accelerator hat buttons consumer):

object bytes:  01 A1 A2 A3 A4 B1 B2 01 00 00 00
get_report():  A2 A3 A4 B1 B2 01 00 00 00 C0   before (last byte is whatever follows the object)
get_report():  A1 A2 A3 A4 B1 B2 01 00 00 00   after

We hit this building an 8-bit joystick for the Xbox Adaptive Controller: the stick sat at one edge and only moved on one axis.

Fix

Derive the offset from the layout instead of hard-coding it: data_offset = REPORT_ID != 0 ? alignof(JOYSTICK_TYPE) : 0, used by both get_report() and set_data(). The default uint16_t report is unchanged (its offset is still 2).

Test

components/hid-rp/test/hid_rp_gamepad_host_test.cpp, in the same standalone style as the other hid-rp host tests. It checks the byte layout of the default report, a byte-wide report, a byte-wide report with no id, the neutral (centered) report, and the set_data() round trip. Against the current header the byte-wide cases fail on every field; with this change everything passes. hid_rp_3dconnexion_host_test and hid_rp_report_map_host_test still pass.

Not touched here, since no current report uses it: mixed widths (say uint8_t axes with uint16_t triggers) would also get padding between joystick_axes and trigger_axes, which num_data_bytes does not account for.

GamepadInputReport::get_report() and set_data() skipped a fixed two bytes
at the front of the object. That is right for the default uint16_t axes
(the one-byte report id plus one byte of alignment padding), but with
uint8_t axes there is no padding, so the copy started one byte late: X was
dropped, every later field moved down a slot, RZ read 0 and the last byte
came from past the end of the object. With REPORT_ID 0 there is no id byte
to skip at all.

Derive the offset from the layout instead: alignof(JOYSTICK_TYPE) after
the report id, 0 without one. Add a host test covering the default,
byte-wide and no-report-id layouts and the set_data() round trip.
Copilot AI balanced review requested due to automatic review settings September 30, 2026 01:05
@github-actions

Copy link
Copy Markdown

✅Static analysis result - no issues found! ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The offset correction matches the supported object layouts and is covered by focused regression tests.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes gamepad report serialization offsets for byte-wide axes and reports without IDs.

Changes:

  • Derives payload offset from report ID presence and joystick alignment.
  • Adds host tests for default, byte-wide, no-ID, neutral, and round-trip cases.
File Description
components/​hid-rp/​include/​hid-rp-gamepad.hpp Corrects payload offsets in serialization and deserialization.
components/​hid-rp/​test/​hid_rp_gamepad_host_test.cpp Adds regression coverage for affected layouts.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@finger563
finger563 merged commit a180003 into esp-cpp:main Sep 30, 2026
163 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants