Skip to content

Commit f36e483

Browse files
committed
Parse and assign report IDs to devices
This allows one device to have multiple report IDs, but also requires that different devices do not use the same report ID
1 parent 0eeacc8 commit f36e483

14 files changed

+230
-137
lines changed

libraries/USB/src/USBHID.cpp

+118-35
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "esp32-hal.h"
1515
#include "esp32-hal-tinyusb.h"
1616
#include "USBHID.h"
17+
#include "esp_hid_common.h"
1718

1819
#if CFG_TUD_HID
1920
#define USB_HID_DEVICES_MAX 10
@@ -46,16 +47,26 @@ void log_print_buf(const uint8_t *b, size_t len){
4647
}
4748
}
4849

50+
typedef struct {
51+
USBHIDDevice * device;
52+
uint8_t reports_num;
53+
uint8_t * report_ids;
54+
} tinyusb_hid_device_t;
55+
56+
static tinyusb_hid_device_t tinyusb_hid_devices[USB_HID_DEVICES_MAX];
57+
58+
static uint8_t tinyusb_hid_devices_num = 0;
59+
static bool tinyusb_hid_devices_is_initialized = false;
60+
static xSemaphoreHandle tinyusb_hid_device_input_sem = NULL;
61+
static xSemaphoreHandle tinyusb_hid_device_input_mutex = NULL;
4962

5063
static bool tinyusb_hid_is_initialized = false;
51-
static tinyusb_hid_device_descriptor_cb_t tinyusb_loaded_hid_devices_callbacks[USB_HID_DEVICES_MAX];
5264
static uint8_t tinyusb_loaded_hid_devices_num = 0;
53-
static uint8_t tinyusb_loaded_hid_devices_report_id = 1;
5465
static uint16_t tinyusb_hid_device_descriptor_len = 0;
5566
static uint8_t * tinyusb_hid_device_descriptor = NULL;
5667
static const char * tinyusb_hid_device_report_types[4] = {"INVALID", "INPUT", "OUTPUT", "FEATURE"};
5768

58-
static bool tinyusb_enable_hid_device(uint16_t descriptor_len, tinyusb_hid_device_descriptor_cb_t cb){
69+
static bool tinyusb_enable_hid_device(uint16_t descriptor_len, USBHIDDevice * device){
5970
if(tinyusb_hid_is_initialized){
6071
log_e("TinyUSB HID has already started! Device not enabled");
6172
return false;
@@ -65,36 +76,118 @@ static bool tinyusb_enable_hid_device(uint16_t descriptor_len, tinyusb_hid_devic
6576
return false;
6677
}
6778
tinyusb_hid_device_descriptor_len += descriptor_len;
68-
tinyusb_loaded_hid_devices_callbacks[tinyusb_loaded_hid_devices_num++] = cb;
69-
log_d("Device enabled");
79+
tinyusb_hid_devices[tinyusb_loaded_hid_devices_num++].device = device;
80+
81+
log_d("Device[%u] len: %u", tinyusb_loaded_hid_devices_num-1, descriptor_len);
7082
return true;
7183
}
7284

73-
static uint16_t tinyusb_load_hid_descriptor(uint8_t interface, uint8_t * dst, uint8_t report_id)
74-
{
75-
if(interface < USB_HID_DEVICES_MAX && tinyusb_loaded_hid_devices_callbacks[interface] != NULL){
76-
return tinyusb_loaded_hid_devices_callbacks[interface](dst, report_id);
85+
USBHIDDevice * tinyusb_get_device_by_report_id(uint8_t report_id){
86+
for(uint8_t i=0; i<tinyusb_loaded_hid_devices_num; i++){
87+
tinyusb_hid_device_t * device = &tinyusb_hid_devices[i];
88+
if(device->device && device->reports_num){
89+
for(uint8_t r=0; r<device->reports_num; r++){
90+
if(report_id == device->report_ids[r]){
91+
return device->device;
92+
}
93+
}
94+
}
95+
}
96+
return NULL;
97+
}
98+
99+
static uint16_t tinyusb_on_get_feature(uint8_t report_id, uint8_t* buffer, uint16_t reqlen){
100+
USBHIDDevice * device = tinyusb_get_device_by_report_id(report_id);
101+
if(device){
102+
return device->_onGetFeature(report_id, buffer, reqlen);
77103
}
78104
return 0;
79105
}
80106

107+
static bool tinyusb_on_set_feature(uint8_t report_id, const uint8_t* buffer, uint16_t reqlen){
108+
USBHIDDevice * device = tinyusb_get_device_by_report_id(report_id);
109+
if(device){
110+
device->_onSetFeature(report_id, buffer, reqlen);
111+
return true;
112+
}
113+
return false;
114+
}
115+
116+
static bool tinyusb_on_set_output(uint8_t report_id, const uint8_t* buffer, uint16_t reqlen){
117+
USBHIDDevice * device = tinyusb_get_device_by_report_id(report_id);
118+
if(device){
119+
device->_onOutput(report_id, buffer, reqlen);
120+
return true;
121+
}
122+
return false;
123+
}
124+
125+
static uint16_t tinyusb_on_add_descriptor(uint8_t device_index, uint8_t * dst){
126+
uint16_t res = 0;
127+
uint8_t report_id = 0, reports_num = 0;
128+
tinyusb_hid_device_t * device = &tinyusb_hid_devices[device_index];
129+
if(device->device){
130+
res = device->device->_onGetDescriptor(dst);
131+
if(res){
132+
133+
esp_hid_report_map_t *hid_report_map = esp_hid_parse_report_map(dst, res);
134+
if(hid_report_map){
135+
if(device->report_ids){
136+
free(device->report_ids);
137+
}
138+
device->reports_num = hid_report_map->reports_len;
139+
device->report_ids = (uint8_t*)malloc(device->reports_num);
140+
memset(device->report_ids, 0, device->reports_num);
141+
reports_num = device->reports_num;
142+
143+
for(uint8_t i=0; i<device->reports_num; i++){
144+
if(hid_report_map->reports[i].protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT){
145+
report_id = hid_report_map->reports[i].report_id;
146+
for(uint8_t r=0; r<device->reports_num; r++){
147+
if(report_id == device->report_ids[r]){
148+
//already added
149+
reports_num--;
150+
break;
151+
} else if(!device->report_ids[r]){
152+
//empty slot
153+
device->report_ids[r] = report_id;
154+
break;
155+
}
156+
}
157+
} else {
158+
reports_num--;
159+
}
160+
}
161+
device->reports_num = reports_num;
162+
esp_hid_free_report_map(hid_report_map);
163+
}
164+
165+
}
166+
}
167+
return res;
168+
}
169+
170+
81171
static bool tinyusb_load_enabled_hid_devices(){
172+
if(tinyusb_hid_device_descriptor != NULL){
173+
return true;
174+
}
82175
tinyusb_hid_device_descriptor = (uint8_t *)malloc(tinyusb_hid_device_descriptor_len);
83176
if (tinyusb_hid_device_descriptor == NULL) {
84177
log_e("HID Descriptor Malloc Failed");
85178
return false;
86179
}
87180
uint8_t * dst = tinyusb_hid_device_descriptor;
88181

89-
for(uint8_t i=0; i<USB_HID_DEVICES_MAX; i++){
90-
uint16_t len = tinyusb_load_hid_descriptor(i, dst, i+1);
182+
for(uint8_t i=0; i<tinyusb_loaded_hid_devices_num; i++){
183+
uint16_t len = tinyusb_on_add_descriptor(i, dst);
91184
if (!len) {
92185
break;
93186
} else {
94187
dst += len;
95188
}
96189
}
97-
log_d("Load Done: reports: %u, descr_len: %u", tinyusb_loaded_hid_devices_report_id - 1, tinyusb_hid_device_descriptor_len);
190+
98191
return true;
99192
}
100193

@@ -125,12 +218,6 @@ extern "C" uint16_t tusb_hid_load_descriptor(uint8_t * dst, uint8_t * itf)
125218

126219

127220

128-
static USBHIDDevice * tinyusb_hid_devices[USB_HID_DEVICES_MAX+1];
129-
static uint8_t tinyusb_hid_devices_num = 0;
130-
static bool tinyusb_hid_devices_is_initialized = false;
131-
static xSemaphoreHandle tinyusb_hid_device_input_sem = NULL;
132-
static xSemaphoreHandle tinyusb_hid_device_input_mutex = NULL;
133-
134221

135222
// Invoked when received GET HID REPORT DESCRIPTOR request
136223
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
@@ -165,38 +252,36 @@ bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate){
165252
// Application must fill buffer report's content and return its length.
166253
// Return zero will cause the stack to STALL request
167254
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen){
168-
if(report_id < USB_HID_DEVICES_MAX && tinyusb_hid_devices[report_id]){
169-
return tinyusb_hid_devices[report_id]->_onGetFeature(buffer, reqlen);
255+
uint16_t res = tinyusb_on_get_feature(report_id, buffer, reqlen);
256+
if(!res){
257+
log_d("instance: %u, report_id: %u, report_type: %s, reqlen: %u", instance, report_id, tinyusb_hid_device_report_types[report_type], reqlen);
170258
}
171-
log_d("instance: %u, report_id: %u, report_type: %s, reqlen: %u", instance, report_id, tinyusb_hid_device_report_types[report_type], reqlen);
172-
return 0;
259+
return res;
173260
}
174261

175262
// Invoked when received SET_REPORT control request or
176263
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
177264
void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize){
178265
if(!report_id && !report_type){
179266
report_id = buffer[0];
180-
if(report_id < USB_HID_DEVICES_MAX && tinyusb_hid_devices[report_id]){
181-
tinyusb_hid_devices[report_id]->_onOutput(buffer+1, bufsize-1);
182-
} else {
267+
if(!tinyusb_on_set_output(report_id, buffer+1, bufsize-1)){
183268
log_d("instance: %u, report_id: %u, report_type: %s, bufsize: %u", instance, *buffer, tinyusb_hid_device_report_types[HID_REPORT_TYPE_OUTPUT], bufsize-1);
184-
log_print_buf(buffer+1, bufsize-1);
269+
//log_print_buf(buffer+1, bufsize-1);
185270
}
186271
} else {
187-
if(report_id < USB_HID_DEVICES_MAX && tinyusb_hid_devices[report_id]){
188-
tinyusb_hid_devices[report_id]->_onSetFeature(buffer, bufsize);
189-
} else {
272+
if(!tinyusb_on_set_feature(report_id, buffer, bufsize)){
190273
log_d("instance: %u, report_id: %u, report_type: %s, bufsize: %u", instance, report_id, tinyusb_hid_device_report_types[report_type], bufsize);
191-
log_print_buf(buffer, bufsize);
274+
//log_print_buf(buffer, bufsize);
192275
}
193276
}
194277
}
195278

196279
USBHID::USBHID(){
197280
if(!tinyusb_hid_devices_is_initialized){
198281
tinyusb_hid_devices_is_initialized = true;
199-
memset(tinyusb_hid_devices, 0, sizeof(tinyusb_hid_devices));
282+
for(uint8_t i=0; i<USB_HID_DEVICES_MAX; i++){
283+
memset(&tinyusb_hid_devices[i], 0, sizeof(tinyusb_hid_device_t));
284+
}
200285
tinyusb_hid_devices_num = 0;
201286
tinyusb_enable_interface(USB_INTERFACE_HID, TUD_HID_INOUT_DESC_LEN, tusb_hid_load_descriptor);
202287
}
@@ -259,13 +344,11 @@ bool USBHID::SendReport(uint8_t id, const void* data, size_t len, uint32_t timeo
259344
return res;
260345
}
261346

262-
bool USBHID::addDevice(USBHIDDevice * device, uint16_t descriptor_len, tinyusb_hid_device_descriptor_cb_t cb){
347+
bool USBHID::addDevice(USBHIDDevice * device, uint16_t descriptor_len){
263348
if(device && tinyusb_loaded_hid_devices_num < USB_HID_DEVICES_MAX){
264-
if(!tinyusb_enable_hid_device(descriptor_len, cb)){
349+
if(!tinyusb_enable_hid_device(descriptor_len, device)){
265350
return false;
266351
}
267-
device->id = tinyusb_loaded_hid_devices_num;
268-
tinyusb_hid_devices[tinyusb_loaded_hid_devices_num] = device;
269352
return true;
270353
}
271354
return false;

libraries/USB/src/USBHID.h

+17-9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@
2222
#include "class/hid/hid.h"
2323
#include "esp_event.h"
2424

25+
// Used by the included TinyUSB drivers
26+
enum {
27+
HID_REPORT_ID_NONE,
28+
HID_REPORT_ID_KEYBOARD,
29+
HID_REPORT_ID_MOUSE,
30+
HID_REPORT_ID_GAMEPAD,
31+
HID_REPORT_ID_CONSUMER_CONTROL,
32+
HID_REPORT_ID_SYSTEM_CONTROL,
33+
HID_REPORT_ID_VENDOR
34+
};
35+
2536
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_HID_EVENTS);
2637

2738
typedef enum {
@@ -43,16 +54,13 @@ typedef struct {
4354
};
4455
} arduino_usb_hid_event_data_t;
4556

46-
typedef uint16_t (*tinyusb_hid_device_descriptor_cb_t)(uint8_t * dst, uint8_t report_id);
47-
4857
class USBHIDDevice
4958
{
5059
public:
51-
uint8_t id;
52-
USBHIDDevice():id(0){}
53-
virtual uint16_t _onGetFeature(uint8_t* buffer, uint16_t len){return 0;}
54-
virtual void _onSetFeature(const uint8_t* buffer, uint16_t len){}
55-
virtual void _onOutput(const uint8_t* buffer, uint16_t len){}
60+
virtual uint16_t _onGetDescriptor(uint8_t* buffer){return 0;}
61+
virtual uint16_t _onGetFeature(uint8_t report_id, uint8_t* buffer, uint16_t len){return 0;}
62+
virtual void _onSetFeature(uint8_t report_id, const uint8_t* buffer, uint16_t len){}
63+
virtual void _onOutput(uint8_t report_id, const uint8_t* buffer, uint16_t len){}
5664
};
5765

5866
class USBHID
@@ -61,10 +69,10 @@ class USBHID
6169
USBHID(void);
6270
void begin(void);
6371
void end(void);
64-
bool SendReport(uint8_t id, const void* data, size_t len, uint32_t timeout_ms = 100);
72+
bool SendReport(uint8_t report_id, const void* data, size_t len, uint32_t timeout_ms = 100);
6573
void onEvent(esp_event_handler_t callback);
6674
void onEvent(arduino_usb_hid_event_t event, esp_event_handler_t callback);
67-
static bool addDevice(USBHIDDevice * device, uint16_t descriptor_len, tinyusb_hid_device_descriptor_cb_t cb);
75+
static bool addDevice(USBHIDDevice * device, uint16_t descriptor_len);
6876
};
6977

7078
#endif

libraries/USB/src/USBHIDConsumerControl.cpp

+10-12
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,26 @@
1818

1919
#if CFG_TUD_HID
2020

21-
static uint16_t tinyusb_hid_device_descriptor_cb(uint8_t * dst, uint8_t report_id){
22-
uint8_t report_descriptor[] = {
23-
TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(report_id))
24-
};
25-
memcpy(dst, report_descriptor, sizeof(report_descriptor));
26-
return sizeof(report_descriptor);
27-
}
21+
static const uint8_t report_descriptor[] = {
22+
TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(HID_REPORT_ID_CONSUMER_CONTROL))
23+
};
2824

2925
USBHIDConsumerControl::USBHIDConsumerControl(): hid(){
3026
static bool initialized = false;
3127
if(!initialized){
3228
initialized = true;
33-
uint8_t report_descriptor[] = {
34-
TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(0))
35-
};
36-
hid.addDevice(this, sizeof(report_descriptor), tinyusb_hid_device_descriptor_cb);
29+
hid.addDevice(this, sizeof(report_descriptor));
3730
} else {
3831
isr_log_e("Only one instance of USBHIDConsumerControl is allowed!");
3932
abort();
4033
}
4134
}
4235

36+
uint16_t USBHIDConsumerControl::_onGetDescriptor(uint8_t* dst){
37+
memcpy(dst, report_descriptor, sizeof(report_descriptor));
38+
return sizeof(report_descriptor);
39+
}
40+
4341
void USBHIDConsumerControl::begin(){
4442
hid.begin();
4543
}
@@ -48,7 +46,7 @@ void USBHIDConsumerControl::end(){
4846
}
4947

5048
bool USBHIDConsumerControl::send(uint16_t value){
51-
return hid.SendReport(id, &value, 2);
49+
return hid.SendReport(HID_REPORT_ID_CONSUMER_CONTROL, &value, 2);
5250
}
5351

5452
size_t USBHIDConsumerControl::press(uint16_t k){

libraries/USB/src/USBHIDConsumerControl.h

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ class USBHIDConsumerControl: public USBHIDDevice {
7777
void end(void);
7878
size_t press(uint16_t k);
7979
size_t release();
80+
81+
// internal use
82+
uint16_t _onGetDescriptor(uint8_t* buffer);
8083
};
8184

8285
#endif

0 commit comments

Comments
 (0)