From 9997b296049e2d6263e21a3c0f441627a8b3409b Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 20 May 2022 23:34:15 -0500 Subject: [PATCH 1/3] Fix switching between boot protocol and report protocol This changes the variable used to decide which type of report to send to the host, without changing the `getDescriptor()` and `setup()` methods, which still do whatever they do with the `protocol` variable, and `UEDATX`. I don't understand why this works, but it seems to allow proper switching between boot protocol and report protocol on macOS & Linux (the two machines I have access to). --- src/BootKeyboard/BootKeyboard.cpp | 12 ++++++++++-- src/BootKeyboard/BootKeyboard.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/BootKeyboard/BootKeyboard.cpp b/src/BootKeyboard/BootKeyboard.cpp index 3a2cd59b..769e1d41 100644 --- a/src/BootKeyboard/BootKeyboard.cpp +++ b/src/BootKeyboard/BootKeyboard.cpp @@ -237,11 +237,19 @@ uint8_t BootKeyboard_::getLeds() { } uint8_t BootKeyboard_::getProtocol() { - return protocol; + if (boot_protocol_) { + return HID_BOOT_PROTOCOL; + } else { + return HID_REPORT_PROTOCOL; + } } void BootKeyboard_::setProtocol(uint8_t protocol) { - this->protocol = protocol; + if (protocol == HID_BOOT_PROTOCOL) { + boot_protocol_ = true; + } else { + boot_protocol_ = false; + } } int BootKeyboard_::sendReport() { diff --git a/src/BootKeyboard/BootKeyboard.h b/src/BootKeyboard/BootKeyboard.h index d7cfeadb..a81aff0b 100644 --- a/src/BootKeyboard/BootKeyboard.h +++ b/src/BootKeyboard/BootKeyboard.h @@ -76,6 +76,7 @@ class BootKeyboard_ : public PluggableUSBModule { EPTYPE_DESCRIPTOR_SIZE epType[1]; uint8_t protocol; + bool boot_protocol_{false}; uint8_t idle; uint8_t leds; From 36060157473f1dcceb1949680cab34f330d5bec4 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 20 May 2022 23:35:55 -0500 Subject: [PATCH 2/3] Add debugging output for keyboard reports This writes to the serial port, demonstrating when the keyboard is actually sending reports using either NKRO or Boot protocol. --- src/BootKeyboard/BootKeyboard.cpp | 6 ++++++ src/MultiReport/Keyboard.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/BootKeyboard/BootKeyboard.cpp b/src/BootKeyboard/BootKeyboard.cpp index 769e1d41..6995e985 100644 --- a/src/BootKeyboard/BootKeyboard.cpp +++ b/src/BootKeyboard/BootKeyboard.cpp @@ -254,6 +254,12 @@ void BootKeyboard_::setProtocol(uint8_t protocol) { int BootKeyboard_::sendReport() { if (memcmp(&last_report_, &report_, sizeof(report_))) { + Serial.print(F("sending boot report: ")); + for (byte i{0}; i < 8; ++i) { + Serial.print(F(" ")); + Serial.print(report_.bytes[i], HEX); + } + Serial.println(); // if the two reports are different, send a report int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &report_, sizeof(report_)); HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &report_, sizeof(report_), returnCode); diff --git a/src/MultiReport/Keyboard.cpp b/src/MultiReport/Keyboard.cpp index b776bc8a..5e63c7b1 100644 --- a/src/MultiReport/Keyboard.cpp +++ b/src/MultiReport/Keyboard.cpp @@ -95,6 +95,12 @@ void Keyboard_::end() { } int Keyboard_::sendReportUnchecked() { + Serial.print(F("sending nkro report:")); + for (byte i{0}; i < 29; ++i) { + Serial.print(F(" ")); + Serial.print(report_.allkeys[i], HEX); + } + Serial.println(); return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &last_report_, sizeof(last_report_)); } From b8001cd3235194d20b9af5b10029818dd1868a16 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 20 May 2022 23:43:41 -0500 Subject: [PATCH 3/3] Comment the relevant line where it seems things should fail I don't understand why what I've done works. This comment is meant to simply highlight the line in the code that seems to be the cause of boot protocol failing without the earlier changes I made (i.e. `boot_protocol_`). --- src/BootKeyboard/BootKeyboard.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/BootKeyboard/BootKeyboard.cpp b/src/BootKeyboard/BootKeyboard.cpp index 6995e985..ed307414 100644 --- a/src/BootKeyboard/BootKeyboard.cpp +++ b/src/BootKeyboard/BootKeyboard.cpp @@ -153,6 +153,11 @@ bool BootKeyboard_::setup(USBSetup& setup) { if (request == HID_GET_PROTOCOL) { // TODO improve #ifdef __AVR__ + // This is where the `protocol` variable is used to set...something, but I don't + // know what. With the change that I've made to use `boot_protocol_` instead, this + // would always be set to `HID_REPORT_PROTOCOL`, even when sending boot protocol + // reports (successfully). It doesn't seem correct, but it works on macOS and Linux + // (or at least, my old Ubuntu machine). UEDATX = protocol; #endif #ifdef ARDUINO_ARCH_SAM