Skip to content

Commit e6ee599

Browse files
authored
feat(hid): Update HID-RP submodule and flesh out gamepad reports (#368)
* feat(hid): Update HID-RP submodule and flesh out gamepad reports * Update HID-RP submodule to have latest changes which include more unit customization * Update hid-rp-gamepad to more closely match xbox 1708 controller descriptor * Update hid-rp-gamepad to have new XboxRumbleOutputReport descriptor * Update hid-rp-gamepad to flesh out led descriptor some more * Update hid_rp_example to include new rumble report * Update hid_service_example to include new rumble report * Update hid_service_example to exercise new consumer record button in gamepad report * Update hid_service_example to add characteristic onWrite callbacks for Rumble and LED, parsing the data that is returned This provides better HID examples and showcases the use of output reports for LED and rumble control. It also updates the examples to better match xbox wireless controller model 1708 for better compatibility. * Build and run `hid-rp/example` on QtPy ESP32s3 and ensure the output matches the 1708 descriptor * Build and run `hid_service/example` on QtPy ESP32s3 and ensure the following work with iPhone: * All gamepad inputs (including new consumer record button) * Battery input report (via game controller settings page) * Rumble output report (by pressing the `identify controller` button in the game controller settings page) * update readmes * fix sa
1 parent 2bd8277 commit e6ee599

File tree

6 files changed

+552
-42
lines changed

6 files changed

+552
-42
lines changed

components/hid-rp/example/README.md

+172-1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,175 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
3030

3131
## Example Output
3232

33-
![CleanShot 2024-03-08 at 10 41 32](https://github.com/esp-cpp/espp/assets/213467/f0d27a49-948c-436d-9e89-d4a9ab62db42)
33+
![CleanShot 2025-02-10 at 10 48 04](https://github.com/user-attachments/assets/0c980778-42fb-446d-85be-f0957722efbf)
34+
35+
Generated report descriptor:
36+
37+
```console
38+
0x5, 0x1, 0x9, 0x5, 0xa1, 0x1, 0x85, 0x1, 0x9, 0x1, 0xa1, 0x0, 0x9, 0x30, 0x9, 0x31, 0x15, 0x0, 0x27, 0xff, 0xff, 0x0, 0x0, 0x95, 0x2, 0x75, 0x10, 0x81, 0x2, 0xc0, 0x9, 0x1, 0xa1, 0x0, 0x9, 0x32, 0x9, 0x35, 0x15, 0x0, 0x27, 0xff, 0xff, 0x0, 0x0, 0x95, 0x2, 0x75, 0x10, 0x81, 0x2, 0xc0, 0x5, 0x2, 0x9, 0xc5, 0x15, 0x0, 0x26, 0xff, 0x3, 0x95, 0x1, 0x75, 0xa, 0x81, 0x2, 0x15, 0x0, 0x25, 0x0, 0x95, 0x1, 0x75, 0x6, 0x81, 0x1, 0x5, 0x2, 0x9, 0xc4, 0x15, 0x0, 0x26, 0xff, 0x3, 0x95, 0x1, 0x75, 0xa, 0x81, 0x2, 0x15, 0x0, 0x25, 0x0, 0x95, 0x1, 0x75, 0x6, 0x81, 0x1, 0x5, 0x1, 0x9, 0x39, 0x15, 0x1, 0x25, 0x8, 0x35, 0x0, 0x46, 0x3b, 0x1, 0x66, 0x14, 0x0, 0x75, 0x4, 0x95, 0x1, 0x81, 0x42, 0x15, 0x0, 0x25, 0x0, 0x35, 0x0, 0x45, 0x0, 0x65, 0x0, 0x55, 0x0, 0x95, 0x1, 0x75, 0x4, 0x81, 0x1, 0x5, 0x9, 0x19, 0x1, 0x29, 0xf, 0x15, 0x0, 0x25, 0x1, 0x75, 0x1, 0x95, 0xf, 0x81, 0x2, 0x15, 0x0, 0x25, 0x0, 0x95, 0x1, 0x75, 0x1, 0x81, 0x1, 0x5, 0xc, 0xa, 0xb2, 0x0, 0x15, 0x0, 0x25, 0x1, 0x95, 0x1, 0x75, 0x1, 0x81, 0x2, 0x15, 0x0, 0x25, 0x0, 0x95, 0x1, 0x75, 0x7, 0x81, 0x1, 0x5, 0xf, 0x9, 0x21, 0x85, 0x3, 0xa1, 0x2, 0x9, 0x97, 0x15, 0x0, 0x25, 0x1, 0x75, 0x4, 0x95, 0x1, 0x91, 0x2, 0x15, 0x0, 0x25, 0x0, 0x75, 0x4, 0x95, 0x1, 0x91, 0x3, 0x9, 0x70, 0x15, 0x0, 0x25, 0x64, 0x75, 0x8, 0x95, 0x4, 0x91, 0x2, 0x9, 0x50, 0x66, 0x1, 0x10, 0x55, 0xe, 0x15, 0x0, 0x26, 0xff, 0x0, 0x75, 0x8, 0x95, 0x1, 0x91, 0x2, 0x9, 0xa7, 0x15, 0x0, 0x26, 0xff, 0x0, 0x75, 0x8, 0x95, 0x1, 0x91, 0x2, 0x65, 0x0, 0x55, 0x0, 0x9, 0x7c, 0x15, 0x0, 0x26, 0xff, 0x0, 0x75, 0x8, 0x95, 0x1, 0x91, 0x2, 0xc0, 0x85, 0x4, 0x9, 0x20, 0x85, 0x4, 0x15, 0x0, 0x26, 0xff, 0x0, 0x75, 0x8, 0x95, 0x1, 0x9, 0x20, 0x81, 0x2, 0x85, 0x2, 0x5, 0x8, 0x19, 0x61, 0x29, 0x64, 0x15, 0x0, 0x25, 0x1, 0x75, 0x1, 0x95, 0x4, 0x91, 0x2, 0x95, 0x1, 0x75, 0x4, 0x91, 0x1, 0xc0
39+
```
40+
41+
Parsed by https://eleccelerator.com/usbdescreqparser/ :
42+
43+
```console
44+
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
45+
0x09, 0x05, // Usage (Game Pad)
46+
0xA1, 0x01, // Collection (Application)
47+
0x85, 0x01, // Report ID (1)
48+
0x09, 0x01, // Usage (Pointer)
49+
0xA1, 0x00, // Collection (Physical)
50+
0x09, 0x30, // Usage (X)
51+
0x09, 0x31, // Usage (Y)
52+
0x15, 0x00, // Logical Minimum (0)
53+
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
54+
0x95, 0x02, // Report Count (2)
55+
0x75, 0x10, // Report Size (16)
56+
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
57+
0xC0, // End Collection
58+
0x09, 0x01, // Usage (Pointer)
59+
0xA1, 0x00, // Collection (Physical)
60+
0x09, 0x32, // Usage (Z)
61+
0x09, 0x35, // Usage (Rz)
62+
0x15, 0x00, // Logical Minimum (0)
63+
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
64+
0x95, 0x02, // Report Count (2)
65+
0x75, 0x10, // Report Size (16)
66+
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
67+
0xC0, // End Collection
68+
0x05, 0x02, // Usage Page (Sim Ctrls)
69+
0x09, 0xC5, // Usage (Brake)
70+
0x15, 0x00, // Logical Minimum (0)
71+
0x26, 0xFF, 0x03, // Logical Maximum (1023)
72+
0x95, 0x01, // Report Count (1)
73+
0x75, 0x0A, // Report Size (10)
74+
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
75+
0x15, 0x00, // Logical Minimum (0)
76+
0x25, 0x00, // Logical Maximum (0)
77+
0x95, 0x01, // Report Count (1)
78+
0x75, 0x06, // Report Size (6)
79+
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
80+
0x05, 0x02, // Usage Page (Sim Ctrls)
81+
0x09, 0xC4, // Usage (Accelerator)
82+
0x15, 0x00, // Logical Minimum (0)
83+
0x26, 0xFF, 0x03, // Logical Maximum (1023)
84+
0x95, 0x01, // Report Count (1)
85+
0x75, 0x0A, // Report Size (10)
86+
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
87+
0x15, 0x00, // Logical Minimum (0)
88+
0x25, 0x00, // Logical Maximum (0)
89+
0x95, 0x01, // Report Count (1)
90+
0x75, 0x06, // Report Size (6)
91+
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
92+
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
93+
0x09, 0x39, // Usage (Hat switch)
94+
0x15, 0x01, // Logical Minimum (1)
95+
0x25, 0x08, // Logical Maximum (8)
96+
0x35, 0x00, // Physical Minimum (0)
97+
0x46, 0x3B, 0x01, // Physical Maximum (315)
98+
0x66, 0x14, 0x00, // Unit (System: English Rotation, Length: Centimeter)
99+
0x75, 0x04, // Report Size (4)
100+
0x95, 0x01, // Report Count (1)
101+
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
102+
0x15, 0x00, // Logical Minimum (0)
103+
0x25, 0x00, // Logical Maximum (0)
104+
0x35, 0x00, // Physical Minimum (0)
105+
0x45, 0x00, // Physical Maximum (0)
106+
0x65, 0x00, // Unit (None)
107+
0x55, 0x00, // Unit Exponent (0)
108+
0x95, 0x01, // Report Count (1)
109+
0x75, 0x04, // Report Size (4)
110+
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
111+
0x05, 0x09, // Usage Page (Button)
112+
0x19, 0x01, // Usage Minimum (0x01)
113+
0x29, 0x0F, // Usage Maximum (0x0F)
114+
0x15, 0x00, // Logical Minimum (0)
115+
0x25, 0x01, // Logical Maximum (1)
116+
0x75, 0x01, // Report Size (1)
117+
0x95, 0x0F, // Report Count (15)
118+
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
119+
0x15, 0x00, // Logical Minimum (0)
120+
0x25, 0x00, // Logical Maximum (0)
121+
0x95, 0x01, // Report Count (1)
122+
0x75, 0x01, // Report Size (1)
123+
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
124+
0x05, 0x0C, // Usage Page (Consumer)
125+
0x0A, 0xB2, 0x00, // Usage (Record)
126+
0x15, 0x00, // Logical Minimum (0)
127+
0x25, 0x01, // Logical Maximum (1)
128+
0x95, 0x01, // Report Count (1)
129+
0x75, 0x01, // Report Size (1)
130+
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
131+
0x15, 0x00, // Logical Minimum (0)
132+
0x25, 0x00, // Logical Maximum (0)
133+
0x95, 0x01, // Report Count (1)
134+
0x75, 0x07, // Report Size (7)
135+
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
136+
0x05, 0x0F, // Usage Page (PID Page)
137+
0x09, 0x21, // Usage (0x21)
138+
0x85, 0x03, // Report ID (3)
139+
0xA1, 0x02, // Collection (Logical)
140+
0x09, 0x97, // Usage (0x97)
141+
0x15, 0x00, // Logical Minimum (0)
142+
0x25, 0x01, // Logical Maximum (1)
143+
0x75, 0x04, // Report Size (4)
144+
0x95, 0x01, // Report Count (1)
145+
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
146+
0x15, 0x00, // Logical Minimum (0)
147+
0x25, 0x00, // Logical Maximum (0)
148+
0x75, 0x04, // Report Size (4)
149+
0x95, 0x01, // Report Count (1)
150+
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
151+
0x09, 0x70, // Usage (0x70)
152+
0x15, 0x00, // Logical Minimum (0)
153+
0x25, 0x64, // Logical Maximum (100)
154+
0x75, 0x08, // Report Size (8)
155+
0x95, 0x04, // Report Count (4)
156+
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
157+
0x09, 0x50, // Usage (0x50)
158+
0x66, 0x01, 0x10, // Unit (System: SI Linear, Time: Seconds)
159+
0x55, 0x0E, // Unit Exponent (-2)
160+
0x15, 0x00, // Logical Minimum (0)
161+
0x26, 0xFF, 0x00, // Logical Maximum (255)
162+
0x75, 0x08, // Report Size (8)
163+
0x95, 0x01, // Report Count (1)
164+
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
165+
0x09, 0xA7, // Usage (0xA7)
166+
0x15, 0x00, // Logical Minimum (0)
167+
0x26, 0xFF, 0x00, // Logical Maximum (255)
168+
0x75, 0x08, // Report Size (8)
169+
0x95, 0x01, // Report Count (1)
170+
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
171+
0x65, 0x00, // Unit (None)
172+
0x55, 0x00, // Unit Exponent (0)
173+
0x09, 0x7C, // Usage (0x7C)
174+
0x15, 0x00, // Logical Minimum (0)
175+
0x26, 0xFF, 0x00, // Logical Maximum (255)
176+
0x75, 0x08, // Report Size (8)
177+
0x95, 0x01, // Report Count (1)
178+
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
179+
0xC0, // End Collection
180+
0x85, 0x04, // Report ID (4)
181+
0x09, 0x20, // Usage (0x20)
182+
0x85, 0x04, // Report ID (4)
183+
0x15, 0x00, // Logical Minimum (0)
184+
0x26, 0xFF, 0x00, // Logical Maximum (255)
185+
0x75, 0x08, // Report Size (8)
186+
0x95, 0x01, // Report Count (1)
187+
0x09, 0x20, // Usage (0x20)
188+
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
189+
0x85, 0x02, // Report ID (2)
190+
0x05, 0x08, // Usage Page (LEDs)
191+
0x19, 0x61, // Usage Minimum (0x61)
192+
0x29, 0x64, // Usage Maximum (0x64)
193+
0x15, 0x00, // Logical Minimum (0)
194+
0x25, 0x01, // Logical Maximum (1)
195+
0x75, 0x01, // Report Size (1)
196+
0x95, 0x04, // Report Count (4)
197+
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
198+
0x95, 0x01, // Report Count (1)
199+
0x75, 0x04, // Report Size (4)
200+
0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
201+
0xC0, // End Collection
202+
203+
// 328 bytes
204+
```

components/hid-rp/example/main/hid_rp_example.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extern "C" void app_main(void) {
1717
static constexpr uint8_t battery_report_id = 4;
1818
static constexpr size_t num_buttons = 15;
1919
static constexpr int joystick_min = 0;
20-
static constexpr int joystick_max = 65534;
20+
static constexpr int joystick_max = 65535;
2121
static constexpr int trigger_min = 0;
2222
static constexpr int trigger_max = 1023;
2323

@@ -29,15 +29,20 @@ extern "C" void app_main(void) {
2929
using BatteryReport = espp::XboxBatteryInputReport<battery_report_id>;
3030
BatteryReport battery_input_report;
3131

32-
static constexpr uint8_t output_report_id = 2;
32+
static constexpr uint8_t led_output_report_id = 2;
3333
static constexpr size_t num_leds = 4;
34-
using GamepadLeds = espp::GamepadLedOutputReport<num_leds, output_report_id>;
34+
using GamepadLeds = espp::GamepadLedOutputReport<num_leds, led_output_report_id>;
3535
GamepadLeds gamepad_leds_report;
3636

37+
static constexpr uint8_t rumble_output_report_id = 3;
38+
using RumbleReport = espp::XboxRumbleOutputReport<rumble_output_report_id>;
39+
RumbleReport rumble_output_report;
40+
3741
using namespace hid::page;
3842
using namespace hid::rdf;
3943
auto raw_descriptor = descriptor(usage_page<generic_desktop>(), usage(generic_desktop::GAMEPAD),
4044
collection::application(gamepad_input_report.get_descriptor(),
45+
rumble_output_report.get_descriptor(),
4146
battery_input_report.get_descriptor(),
4247
gamepad_leds_report.get_descriptor()));
4348

0 commit comments

Comments
 (0)