Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9a9ec09

Browse filesBrowse files
RefactorFactorySuGliderme-no-devP-R-O-C-H-Y
authored
Make USBHIDKeyboard work at boot (espressif#6964)
1. Like a real keyboard, the USB interface descriptor will have an interface subclass of boot and an interface protocol of keyboard. This will cause some PC BIOS to send a SET PROTOCOL BOOT request to the device. 2. When the device sends reports to the host, if the host requested boot protocol, don't send a report ID because boot protocol does not use report IDs. 3. To work with some simple PC BIOS: a. Use endpoint address of 1 for input and output. b. Use separate reports for the shift key. These extra reports can be disabled by calling USBHIDKeyboard::setShiftKeyReports(false). Co-authored-by: Rodrigo Garcia <rodrigo.garcia@espressif.com> Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com> Co-authored-by: Jan Procházka <90197375+P-R-O-C-H-Y@users.noreply.github.com>
1 parent 89fd90d commit 9a9ec09
Copy full SHA for 9a9ec09

File tree

Expand file treeCollapse file tree

6 files changed

+50
-13
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+50
-13
lines changed

‎cores/esp32/esp32-hal-tinyusb.c

Copy file name to clipboardExpand all lines: cores/esp32/esp32-hal-tinyusb.c
+12-1Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,11 @@ static void usb_device_task(void *param) {
678678
#endif
679679
static bool tinyusb_is_initialized = false;
680680

681-
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb)
681+
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb){
682+
return tinyusb_enable_interface2(interface, descriptor_len, cb, false);
683+
}
684+
685+
esp_err_t tinyusb_enable_interface2(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb, bool reserve_endpoints)
682686
{
683687
if(tinyusb_is_initialized){
684688
log_e("TinyUSB has already started! Interface %s not enabled", (interface >= USB_INTERFACE_MAX)?"":tinyusb_interface_names[interface]);
@@ -688,6 +692,13 @@ esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descr
688692
log_e("Interface %s invalid or already enabled", (interface >= USB_INTERFACE_MAX)?"":tinyusb_interface_names[interface]);
689693
return ESP_FAIL;
690694
}
695+
if(interface == USB_INTERFACE_HID && reserve_endpoints){
696+
// Some simple PC BIOS requires specific endpoint addresses for keyboard at boot
697+
if(!tinyusb_reserve_out_endpoint(1) ||!tinyusb_reserve_in_endpoint(1)){
698+
log_e("HID Reserve Endpoints Failed");
699+
return ESP_FAIL;
700+
}
701+
}
691702
if(interface == USB_INTERFACE_CDC){
692703
if(!tinyusb_reserve_out_endpoint(3) ||!tinyusb_reserve_in_endpoint(4) || !tinyusb_reserve_in_endpoint(5)){
693704
log_e("CDC Reserve Endpoints Failed");

‎cores/esp32/esp32-hal-tinyusb.h

Copy file name to clipboardExpand all lines: cores/esp32/esp32-hal-tinyusb.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ typedef enum {
9797
typedef uint16_t (*tinyusb_descriptor_cb_t)(uint8_t * dst, uint8_t * itf);
9898

9999
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb);
100+
esp_err_t tinyusb_enable_interface2(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb, bool reserve_endpoints);
100101
uint8_t tinyusb_add_string_descriptor(const char * str);
101102
uint8_t tinyusb_get_free_duplex_endpoint(void);
102103
uint8_t tinyusb_get_free_in_endpoint(void);

‎libraries/USB/src/USBHID.cpp

Copy file name to clipboardExpand all lines: libraries/USB/src/USBHID.cpp
+15-7Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static SemaphoreHandle_t tinyusb_hid_device_input_sem = NULL;
4040
static SemaphoreHandle_t tinyusb_hid_device_input_mutex = NULL;
4141

4242
static bool tinyusb_hid_is_initialized = false;
43+
static hid_interface_protocol_enum_t tinyusb_interface_protocol = HID_ITF_PROTOCOL_NONE;
4344
static uint8_t tinyusb_loaded_hid_devices_num = 0;
4445
static uint16_t tinyusb_hid_device_descriptor_len = 0;
4546
static uint8_t * tinyusb_hid_device_descriptor = NULL;
@@ -174,7 +175,7 @@ static bool tinyusb_load_enabled_hid_devices(){
174175

175176
esp_hid_report_map_t *hid_report_map = esp_hid_parse_report_map(tinyusb_hid_device_descriptor, tinyusb_hid_device_descriptor_len);
176177
if(hid_report_map){
177-
log_d("Loaded HID Desriptor with the following reports:");
178+
log_d("Loaded HID Descriptor with the following reports:");
178179
for(uint8_t i=0; i<hid_report_map->reports_len; i++){
179180
if(hid_report_map->reports[i].protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT){
180181
log_d(" ID: %3u, Type: %7s, Size: %2u, Usage: %8s",
@@ -202,14 +203,15 @@ extern "C" uint16_t tusb_hid_load_descriptor(uint8_t * dst, uint8_t * itf)
202203
tinyusb_hid_is_initialized = true;
203204

204205
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB HID");
205-
uint8_t ep_in = tinyusb_get_free_in_endpoint();
206+
// For keyboard boot protocol, we've already called tinyusb_enable_interface2(reserve_endpoints=true)
207+
uint8_t ep_in = tinyusb_interface_protocol == HID_ITF_PROTOCOL_KEYBOARD ? 1 : tinyusb_get_free_in_endpoint();
206208
TU_VERIFY (ep_in != 0);
207-
uint8_t ep_out = tinyusb_get_free_out_endpoint();
209+
uint8_t ep_out = tinyusb_interface_protocol == HID_ITF_PROTOCOL_KEYBOARD ? 1 : tinyusb_get_free_out_endpoint();
208210
TU_VERIFY (ep_out != 0);
209211
uint8_t descriptor[TUD_HID_INOUT_DESC_LEN] = {
210212
// HID Input & Output descriptor
211213
// Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval
212-
TUD_HID_INOUT_DESCRIPTOR(*itf, str_index, HID_ITF_PROTOCOL_NONE, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), 64, 1)
214+
TUD_HID_INOUT_DESCRIPTOR(*itf, str_index, tinyusb_interface_protocol, tinyusb_hid_device_descriptor_len, ep_out, (uint8_t)(0x80 | ep_in), 64, 1)
213215
};
214216
*itf+=1;
215217
memcpy(dst, descriptor, TUD_HID_INOUT_DESC_LEN);
@@ -276,14 +278,15 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
276278
}
277279
}
278280

279-
USBHID::USBHID(){
281+
USBHID::USBHID(hid_interface_protocol_enum_t itf_protocol){
280282
if(!tinyusb_hid_devices_is_initialized){
281283
tinyusb_hid_devices_is_initialized = true;
282284
for(uint8_t i=0; i<USB_HID_DEVICES_MAX; i++){
283285
memset(&tinyusb_hid_devices[i], 0, sizeof(tinyusb_hid_device_t));
284286
}
285287
tinyusb_hid_devices_num = 0;
286-
tinyusb_enable_interface(USB_INTERFACE_HID, TUD_HID_INOUT_DESC_LEN, tusb_hid_load_descriptor);
288+
tinyusb_interface_protocol = itf_protocol;
289+
tinyusb_enable_interface2(USB_INTERFACE_HID, TUD_HID_INOUT_DESC_LEN, tusb_hid_load_descriptor, itf_protocol == HID_ITF_PROTOCOL_KEYBOARD);
287290
}
288291
}
289292

@@ -342,6 +345,11 @@ bool USBHID::SendReport(uint8_t id, const void* data, size_t len, uint32_t timeo
342345
return false;
343346
}
344347

348+
// If we're configured to support boot protocol, and the host has requested boot protocol, prevent
349+
// sending of report ID, by passing report ID of 0 to tud_hid_n_report().
350+
uint8_t effective_id = ((tinyusb_interface_protocol != HID_ITF_PROTOCOL_NONE) &&
351+
(tud_hid_n_get_protocol(0) == HID_PROTOCOL_BOOT)) ? 0 : id;
352+
345353
bool res = ready();
346354
if(!res){
347355
log_e("not ready");
@@ -352,7 +360,7 @@ bool USBHID::SendReport(uint8_t id, const void* data, size_t len, uint32_t timeo
352360
// we can wait for it to be given after calling tud_hid_n_report().
353361
xSemaphoreTake(tinyusb_hid_device_input_sem, 0);
354362

355-
res = tud_hid_n_report(0, id, data, len);
363+
res = tud_hid_n_report(0, effective_id, data, len);
356364
if(!res){
357365
log_e("report %u failed", id);
358366
} else {

‎libraries/USB/src/USBHID.h

Copy file name to clipboardExpand all lines: libraries/USB/src/USBHID.h
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class USBHIDDevice
7070
class USBHID
7171
{
7272
public:
73-
USBHID(void);
73+
USBHID(hid_interface_protocol_enum_t itf_protocol = HID_ITF_PROTOCOL_NONE);
7474
void begin(void);
7575
void end(void);
7676
bool ready(void);

‎libraries/USB/src/USBHIDKeyboard.cpp

Copy file name to clipboardExpand all lines: libraries/USB/src/USBHIDKeyboard.cpp
+19-4Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static const uint8_t report_descriptor[] = {
3333
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_REPORT_ID_KEYBOARD))
3434
};
3535

36-
USBHIDKeyboard::USBHIDKeyboard(): hid(){
36+
USBHIDKeyboard::USBHIDKeyboard(): hid(HID_ITF_PROTOCOL_KEYBOARD), shiftKeyReports(true){
3737
static bool initialized = false;
3838
if(!initialized){
3939
initialized = true;
@@ -78,6 +78,11 @@ void USBHIDKeyboard::sendReport(KeyReport* keys)
7878
hid.SendReport(HID_REPORT_ID_KEYBOARD, &report, sizeof(report));
7979
}
8080

81+
void USBHIDKeyboard::setShiftKeyReports(bool set)
82+
{
83+
shiftKeyReports = set;
84+
}
85+
8186
#define SHIFT 0x80
8287
const uint8_t _asciimap[128] =
8388
{
@@ -283,7 +288,12 @@ size_t USBHIDKeyboard::press(uint8_t k)
283288
return 0;
284289
}
285290
if (k & 0x80) { // it's a capital letter or other character reached with shift
286-
_keyReport.modifiers |= 0x02; // the left shift modifier
291+
// At boot, some PCs need a separate report with the shift key down like a real keyboard.
292+
if (shiftKeyReports) {
293+
pressRaw(HID_KEY_SHIFT_LEFT);
294+
} else {
295+
_keyReport.modifiers |= 0x02; // the left shift modifier
296+
}
287297
k &= 0x7F;
288298
}
289299
}
@@ -306,8 +316,13 @@ size_t USBHIDKeyboard::release(uint8_t k)
306316
return 0;
307317
}
308318
if (k & 0x80) { // it's a capital letter or other character reached with shift
309-
_keyReport.modifiers &= ~(0x02); // the left shift modifier
310-
k &= 0x7F;
319+
if (shiftKeyReports) {
320+
releaseRaw(k & 0x7F); // Release key without shift modifier
321+
k = HID_KEY_SHIFT_LEFT; // Below, release shift modifier
322+
} else {
323+
_keyReport.modifiers &= ~(0x02); // the left shift modifier
324+
k &= 0x7F;
325+
}
311326
}
312327
}
313328
return releaseRaw(k);

‎libraries/USB/src/USBHIDKeyboard.h

Copy file name to clipboardExpand all lines: libraries/USB/src/USBHIDKeyboard.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class USBHIDKeyboard: public USBHIDDevice, public Print
119119
private:
120120
USBHID hid;
121121
KeyReport _keyReport;
122+
bool shiftKeyReports;
122123
public:
123124
USBHIDKeyboard(void);
124125
void begin(void);
@@ -129,6 +130,7 @@ class USBHIDKeyboard: public USBHIDDevice, public Print
129130
size_t release(uint8_t k);
130131
void releaseAll(void);
131132
void sendReport(KeyReport* keys);
133+
void setShiftKeyReports(bool set);
132134

133135
//raw functions work with TinyUSB's HID_KEY_* macros
134136
size_t pressRaw(uint8_t k);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.