From 72c64c6f55b799e9770b59975f4df15ba5a3ec03 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 25 Jan 2024 12:29:10 -0600 Subject: [PATCH 01/22] fix HID desc fields Correct the field names for the HID descriptor. This was only filled using a macro, so no change in the resulting bytes. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HID.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index dd346c2cfd..4579ba3ab4 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -55,10 +55,10 @@ typedef struct { uint8_t len; // 9 uint8_t dtype; // 0x21 - uint8_t addr; uint8_t versionL; // 0x101 uint8_t versionH; // 0x101 uint8_t country; + uint8_t numDescs; uint8_t desctype; // 0x22 report uint8_t descLenL; uint8_t descLenH; From a54cc6d37110f48b271951924d0b1c2694309036 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sat, 27 Jan 2024 14:38:17 -0600 Subject: [PATCH 02/22] update HID version to 1.11 Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HID.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index 4579ba3ab4..f5fd1a32d2 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -120,6 +120,6 @@ class HID_ : public PluggableUSBModule { HID_ &HID(); #define D_HIDREPORT(length) \ - { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } + { 9, 0x21, 0x11, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } #endif // USBCON From ec139f1100f39074747f50f5cb920f0997f7febd Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sun, 28 Jan 2024 17:35:26 -0600 Subject: [PATCH 03/22] rough draft abstracted HIDD Signed-off-by: Taylor Yu --- .../src/BootKeyboard/BootKeyboard.cpp | 124 ++----------- .../src/BootKeyboard/BootKeyboard.h | 15 +- plugins/KeyboardioHID/src/HID.cpp | 100 +---------- plugins/KeyboardioHID/src/HID.h | 52 +----- plugins/KeyboardioHID/src/HIDD.cpp | 168 ++++++++++++++++++ plugins/KeyboardioHID/src/HIDD.h | 58 ++++++ plugins/KeyboardioHID/src/MultiHIDD.h | 42 +++++ .../src/MultiReport/AbsoluteMouse.h | 1 + .../src/MultiReport/ConsumerControl.h | 1 + .../KeyboardioHID/src/MultiReport/Gamepad.h | 1 + plugins/KeyboardioHID/src/MultiReport/Mouse.h | 1 + .../src/MultiReport/SystemControl.h | 1 + .../src/SingleReport/SingleAbsoluteMouse.cpp | 78 +------- .../src/SingleReport/SingleAbsoluteMouse.h | 13 +- 14 files changed, 301 insertions(+), 354 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HIDD.cpp create mode 100644 plugins/KeyboardioHID/src/HIDD.h create mode 100644 plugins/KeyboardioHID/src/MultiHIDD.h diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 068ab43f8c..71205667b8 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -37,50 +37,11 @@ static const uint8_t hybrid_keyboard_hid_descriptor_[] PROGMEM = { }; BootKeyboard_::BootKeyboard_(uint8_t bootkb_only_) - : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(0), leds(0), bootkb_only(bootkb_only) { -#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES - epType[0] = EP_TYPE_INTERRUPT_IN(USB_EP_SIZE); -#else - epType[0] = EP_TYPE_INTERRUPT_IN; -#endif - PluggableUSB().plug(this); -} - -int BootKeyboard_::getInterface(uint8_t *interfaceCount) { - *interfaceCount += 1; // uses 1 - size_t desclen; - if (bootkb_only) { - desclen = sizeof(boot_keyboard_hid_descriptor_); - } else { - desclen = sizeof(hybrid_keyboard_hid_descriptor_); - } - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT, HID_PROTOCOL_KEYBOARD), - D_HIDREPORT(desclen), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01), - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int BootKeyboard_::getDescriptor(USBSetup &setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } + : bootkb_only(bootkb_only_) { - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - if (bootkb_only) { - return USB_SendControl(TRANSFER_PGM, boot_keyboard_hid_descriptor_, sizeof(boot_keyboard_hid_descriptor_)); - } else { - return USB_SendControl(TRANSFER_PGM, hybrid_keyboard_hid_descriptor_, sizeof(hybrid_keyboard_hid_descriptor_)); - } + itfProtocol = HID_PROTOCOL_KEYBOARD; + setBootOnly(bootkb_only); + plug(); } @@ -94,74 +55,8 @@ void BootKeyboard_::end() { } -bool BootKeyboard_::setup(USBSetup &setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO(anyone): HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO(anyone) improve -#if defined(__AVR__) - UEDATX = protocol; -#elif defined(ARDUINO_ARCH_SAM) - USBDevice.armSend(0, &protocol, 1); -#else - USB_SendControl(TRANSFER_RELEASE, &protocol, sizeof(protocol)); -#endif - return true; - } - if (request == HID_GET_IDLE) { - // TODO(anyone) improve -#if defined(__AVR__) - UEDATX = idle; -#elif defined(ARDUINO_ARCH_SAM) - USBDevice.armSend(0, &idle, 1); -#else - USB_SendControl(TRANSFER_RELEASE, &idle, sizeof(idle)); -#endif - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) { - // Check if data has the correct length afterwards - int length = setup.wLength; - - if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { - if (length == sizeof(leds)) { - USB_RecvControl(&leds, length); - return true; - } - } - } - } - - return false; -} - uint8_t BootKeyboard_::getLeds() { - return leds; -} - -uint8_t BootKeyboard_::getProtocol() { - return protocol; + return outReport[0]; } uint8_t BootKeyboard_::getBootOnly() { @@ -180,6 +75,13 @@ uint8_t BootKeyboard_::getBootOnly() { */ void BootKeyboard_::setBootOnly(uint8_t bootonly) { bootkb_only = bootonly; + if (bootkb_only) { + reportDesc = boot_keyboard_hid_descriptor_; + descriptorSize = sizeof(boot_keyboard_hid_descriptor_); + } else { + reportDesc = hybrid_keyboard_hid_descriptor_; + descriptorSize = sizeof(hybrid_keyboard_hid_descriptor_); + } } @@ -224,7 +126,7 @@ int BootKeyboard_::sendReportUnchecked() { } else { reportlen = sizeof(out_report); } - int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &out_report, reportlen); + int returnCode = SendReport(0, &out_report, reportlen); HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &out_report, reportlen, returnCode); return returnCode; } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 851ccbf83e..6277c8c3f1 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -28,6 +28,7 @@ THE SOFTWARE. #include #include "HID.h" +#include "HIDD.h" #include "HIDTables.h" #include "HIDAliases.h" @@ -172,7 +173,7 @@ typedef union { } HID_BootKeyboardReport_Data_t; -class BootKeyboard_ : public PluggableUSBModule { +class BootKeyboard_ : public HIDD { public: /* * Change to `bootkb_only_ = 1` if you need to default to only sending @@ -195,7 +196,6 @@ class BootKeyboard_ : public PluggableUSBModule { bool wasKeyPressed(uint8_t k); uint8_t getLeds(); - uint8_t getProtocol(); uint8_t getBootOnly(); void setBootOnly(uint8_t bootonly); @@ -205,17 +205,6 @@ class BootKeyboard_ : public PluggableUSBModule { protected: HID_NKRO_KeyboardReport_Data_t report_, last_report_; - // Implementation of the PUSBListNode - int getInterface(uint8_t *interfaceCount); - int getDescriptor(USBSetup &setup); - bool setup(USBSetup &setup); - - EPTYPE_DESCRIPTOR_SIZE epType[1]; - uint8_t protocol; - uint8_t idle; - - uint8_t leds; - uint8_t bootkb_only; private: diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 835c957811..6cb51601d9 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -20,6 +20,7 @@ #include "HID.h" #include "HIDReportObserver.h" +#include "MultiHIDD.h" #include "BootKeyboard/BootKeyboard.h" #if defined(USBCON) @@ -29,15 +30,7 @@ HID_ &HID() { return obj; } -int HID_::getInterface(uint8_t *interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(descriptorSize), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)}; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - +/* Override to send all report descriptors */ int HID_::getDescriptor(USBSetup &setup) { // Check if this is a HID Class Descriptor request if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { @@ -92,98 +85,17 @@ void HID_::AppendDescriptor(HIDSubDescriptor *node) { } int HID_::SendReport(uint8_t id, const void *data, int len) { - auto result = SendReport_(id, data, len); + auto result = HIDD::SendReport(id, data, len); HIDReportObserver::observeReport(id, data, len, result); return result; } -int HID_::SendReport_(uint8_t id, const void *data, int len) { - /* On SAMD, we need to send the whole report in one batch; sending the id, and - * the report itself separately does not work, the report never arrives. Due - * to this, we merge the two into a single buffer, and send that. - * - * While the same would work for other architectures, AVR included, doing so - * costs RAM, which is something scarce on AVR. So on that platform, we opt to - * send the id and the report separately instead. */ -#ifdef ARDUINO_ARCH_SAMD - uint8_t p[64]; - p[0] = id; - memcpy(&p[1], data, len); - return USB_Send(pluggedEndpoint, p, len + 1); -#else - auto ret = USB_Send(pluggedEndpoint, &id, 1); - if (ret < 0) return ret; - auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); - if (ret2 < 0) return ret2; - return ret + ret2; -#endif -} - -bool HID_::setup(USBSetup &setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO(anyone): HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - return false; - } - if (request == HID_GET_IDLE) { - USB_SendControl(TRANSFER_RELEASE, &idle, sizeof(idle)); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - return false; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueH; - return true; - } - if (request == HID_SET_REPORT) { - uint16_t length = setup.wLength; - - if (length == sizeof(setReportData)) { - USB_RecvControl(&setReportData, length); - } else if (length == sizeof(setReportData.leds)) { - USB_RecvControl(&setReportData.leds, length); - setReportData.reportId = 0; - } - return true; - } - } - - return false; -} - HID_::HID_() - : PluggableUSBModule(1, 1, epType), - rootNode(NULL), - descriptorSize(0), - protocol(HID_REPORT_PROTOCOL), - idle(0) { + : rootNode(NULL) { // Invoke BootKeyboard constructor so it will be the first HID interface (void)BootKeyboard(); - - setReportData.reportId = 0; - setReportData.leds = 0; - -#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES - epType[0] = EP_TYPE_INTERRUPT_IN(USB_EP_SIZE); -#else - epType[0] = EP_TYPE_INTERRUPT_IN; -#endif - - PluggableUSB().plug(this); + inReportLen = USB_EP_SIZE; + plug(); } int HID_::begin() { diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index f5fd1a32d2..a945460a2e 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -53,8 +53,8 @@ #pragma pack(push, 1) typedef struct { - uint8_t len; // 9 - uint8_t dtype; // 0x21 + uint8_t len; // 9 + uint8_t dtype; // 0x21 uint8_t versionL; // 0x101 uint8_t versionH; // 0x101 uint8_t country; @@ -71,54 +71,6 @@ typedef struct { } HIDDescriptor; #pragma pack(pop) -class HIDSubDescriptor { - public: - HIDSubDescriptor *next = NULL; - HIDSubDescriptor(const void *d, const uint16_t l) - : data(d), length(l) {} - - const void *data; - const uint16_t length; -}; - -class HID_ : public PluggableUSBModule { - public: - HID_(); - int begin(); - int SendReport(uint8_t id, const void *data, int len); - void AppendDescriptor(HIDSubDescriptor *node); - uint8_t getLEDs() { - return setReportData.leds; - } - - protected: - // Implementation of the PluggableUSBModule - int getInterface(uint8_t *interfaceCount); - int getDescriptor(USBSetup &setup); - bool setup(USBSetup &setup); - uint8_t getShortName(char *name); - - int SendReport_(uint8_t id, const void *data, int len); - - private: - EPTYPE_DESCRIPTOR_SIZE epType[1]; - - HIDSubDescriptor *rootNode; - uint16_t descriptorSize; - - uint8_t protocol; - uint8_t idle; - struct { - uint8_t reportId; - uint8_t leds; - } setReportData; -}; - -// Replacement for global singleton. -// This function prevents static-initialization-order-fiasco -// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use -HID_ &HID(); - #define D_HIDREPORT(length) \ { 9, 0x21, 0x11, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } diff --git a/plugins/KeyboardioHID/src/HIDD.cpp b/plugins/KeyboardioHID/src/HIDD.cpp new file mode 100644 index 0000000000..cc6c04f09f --- /dev/null +++ b/plugins/KeyboardioHID/src/HIDD.cpp @@ -0,0 +1,168 @@ +#include "HIDD.h" +#include "HID-Settings.h" + +HIDD::HIDD( + uint8_t _protocol, + uint8_t _idle, + uint8_t _itfProtocol, + uint8_t _inReportLen, + uint8_t _interval, + const void *_reportDesc, + uint16_t _descriptorSize) + : PluggableUSBModule(1, 1, epType), + protocol(_protocol), + idle(_idle), + itfProtocol(_itfProtocol), + inReportLen(_inReportLen), + interval(_interval), + reportDesc(_reportDesc), + descriptorSize(_descriptorSize) { + +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES + epType[0] = EP_TYPE_INTERRUPT_IN(inReportLen); +#else + epType[0] = EP_TYPE_INTERRUPT_IN; +#endif +} + +/* PluggableUSB implementation: interface, etc. descriptors for config */ +int HIDD::getInterface(uint8_t *interfaceCount) { + uint8_t itfSubClass; + if (itfProtocol != HID_PROTOCOL_NONE) { + itfSubClass = HID_SUBCLASS_BOOT; + } else { + itfSubClass = HID_SUBCLASS_NONE; + } + + uint8_t epSize; +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES + epSize = inReportLen; +#else + epSize = USB_EP_SIZE; +#endif + + HIDDescriptor descSet = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, itfSubClass, itfProtocol), + D_HIDREPORT(descriptorSize), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, epSize, interval), + }; + ++*interfaceCount; + return USB_SendControl(0, &descSet, sizeof(descSet)); +} + +/* PluggableUSB implementation: class descriptors */ +int HIDD::getDescriptor(USBSetup &setup) { + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + return USB_SendControl(TRANSFER_PGM, reportDesc, descriptorSize); +} + +/* PluggableUSB implementation: control requests */ +bool HIDD::setup(USBSetup &setup) { + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO(anyone): HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + if (itfProtocol == HID_PROTOCOL_NONE) { + return false; + } + // AVR optimization; possibly not needed elsewhere +#if defined(__AVR__) + UEDATX = protocol; +#elif defined(ARDUINO_ARCH_SAM) + USBDevice.armSend(0, &protocol, 1); +#else + USB_SendControl(TRANSFER_RELEASE, &protocol, sizeof(protocol)); +#endif + return true; + } + if (request == HID_GET_IDLE) { + // AVR optimization; possibly not needed elsewhere +#if defined(__AVR__) + UEDATX = idle; +#elif defined(ARDUINO_ARCH_SAM) + USBDevice.armSend(0, &idle, 1); +#else + USB_SendControl(TRANSFER_RELEASE, &idle, sizeof(idle)); +#endif + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + if (itfProtocol == HID_PROTOCOL_NONE) { + return false; + } + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + // Check if data has the correct length afterwards + int length = setup.wLength; + + if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + if (length <= sizeof(outReport)) { + USB_RecvControl(outReport, length); + setReportCB(outReport, length); + return true; + } + } + } + } + + return false; +} + +int HIDD::SendReportNoID(const void *data, int len) { + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); +} + +int HIDD::SendReport(uint8_t id, const void *data, int len) { + if (id == 0) { + return SendReportNoID(data, len); + } + /* On SAMD, we need to send the whole report in one batch; sending the id, and + * the report itself separately does not work, the report never arrives. Due + * to this, we merge the two into a single buffer, and send that. + * + * While the same would work for other architectures, AVR included, doing so + * costs RAM, which is something scarce on AVR. So on that platform, we opt to + * send the id and the report separately instead. */ +#ifdef ARDUINO_ARCH_SAMD + uint8_t p[64]; + p[0] = id; + memcpy(&p[1], data, len); + return USB_Send(pluggedEndpoint, p, len + 1); +#else + auto ret = USB_Send(pluggedEndpoint, &id, 1); + if (ret < 0) return ret; + auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); + if (ret2 < 0) return ret2; + return ret + ret2; +#endif +} diff --git a/plugins/KeyboardioHID/src/HIDD.h b/plugins/KeyboardioHID/src/HIDD.h new file mode 100644 index 0000000000..a89a28824e --- /dev/null +++ b/plugins/KeyboardioHID/src/HIDD.h @@ -0,0 +1,58 @@ +/* HID driver back end */ + +#pragma once + +#include +#include + +#include "HID.h" + +/* Maximum length of output report sent by host */ +#define HIDD_MAX_OUTPUT_REPORT 2 + +class HIDD : public PluggableUSBModule { + public: + HIDD( + uint8_t _protocol = HID_REPORT_PROTOCOL, + uint8_t _idle = 0, + uint8_t _itfProtocol = HID_PROTOCOL_NONE, + uint8_t _inReportLen = USB_EP_SIZE, + uint8_t _interval = 1, + const void *_reportDesc = NULL, + uint16_t descriptorSize = 0); + virtual int SendReport(uint8_t id, const void *data, int len); + uint8_t getProtocol() { + return protocol; + } + + protected: + // Implementation of the PluggableUSBModule + int getInterface(uint8_t *interfaceCount); + int getDescriptor(USBSetup &setup); + bool setup(USBSetup &setup); + + void plug() { + PluggableUSB().plug(this); + } + + /* Current HID protocol: Boot or Report */ + uint8_t protocol; + uint8_t idle; + /* Interface protocol, for interface descriptor (only boot devices) */ + uint8_t itfProtocol; + uint8_t inReportLen; + uint8_t outReportLen; + uint8_t interval; + const void *reportDesc; + uint16_t descriptorSize; + + uint8_t outReport[HIDD_MAX_OUTPUT_REPORT]; + virtual void setReportCB(const void *data, uint16_t len) { + (void)data; + (void)len; + } + + private: + EPTYPE_DESCRIPTOR_SIZE epType[1]; + int SendReportNoID(const void *data, int len); +}; diff --git a/plugins/KeyboardioHID/src/MultiHIDD.h b/plugins/KeyboardioHID/src/MultiHIDD.h new file mode 100644 index 0000000000..2a26c46aec --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiHIDD.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#include "HID.h" +#include "HIDD.h" +#include "HID-Settings.h" + +class HIDSubDescriptor { + public: + HIDSubDescriptor *next = NULL; + HIDSubDescriptor(const void *d, const uint16_t l) + : data(d), length(l) {} + + const void *data; + const uint16_t length; +}; + +class HID_ : public HIDD { + public: + HID_(); + int begin(); + int SendReport(uint8_t id, const void *data, int len) override; + void AppendDescriptor(HIDSubDescriptor *node); + uint8_t getLEDs() { + return outReport[1]; + } + + protected: + // Implementation of the PluggableUSBModule + int getDescriptor(USBSetup &setup) override; + uint8_t getShortName(char *name); + + private: + HIDSubDescriptor *rootNode; +}; + +// Replacement for global singleton. +// This function prevents static-initialization-order-fiasco +// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use +HID_ &HID(); diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 3ecc1a16f9..88cf29362d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -29,6 +29,7 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" +#include "MultiHIDD.h" #include "../DeviceAPIs/AbsoluteMouseAPI.h" class AbsoluteMouse_ : public AbsoluteMouseAPI { diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index cbe8af35d6..d1d4bdec8a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -29,6 +29,7 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" +#include "MultiHIDD.h" #include "tusb_hid.h" #define DESCRIPTOR_CONSUMER_CONTROL(...) \ diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 17d02b4263..162311376e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -29,6 +29,7 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" +#include "MultiHIDD.h" #include "tusb_hid.h" // Dpad directions diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index b1b2ab14e0..d65624dd79 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -29,6 +29,7 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" +#include "MultiHIDD.h" #include "../MouseButtons.h" #include "tusb_hid.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 5807be8056..439458fa72 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -30,6 +30,7 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" #include "HIDTables.h" +#include "MultiHIDD.h" #include "tusb_hid.h" #define DESCRIPTOR_SYSTEM_CONTROL(...) \ diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 59dc1170ab..715a0a2ede 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -32,88 +32,16 @@ static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { DESCRIPTOR_ABSOLUTE_MOUSE(), }; -#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES -static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = 6; -#else -static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = USB_EP_SIZE; -#endif - - SingleAbsoluteMouse_::SingleAbsoluteMouse_() - : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { + : HIDD(HID_REPORT_PROTOCOL, 0, HID_PROTOCOL_NONE, 6, 1, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)) { // Invoke BootKeyboard constructor so it will be the first HID interface (void)BootKeyboard(); -#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES - epType[0] = EP_TYPE_INTERRUPT_IN(SINGLE_ABSOLUTEMOUSE_EP_SIZE); -#else - epType[0] = EP_TYPE_INTERRUPT_IN; -#endif - - PluggableUSB().plug(this); -} - -int SingleAbsoluteMouse_::getInterface(uint8_t *interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, SINGLE_ABSOLUTEMOUSE_EP_SIZE, 0x01)}; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int SingleAbsoluteMouse_::getDescriptor(USBSetup &setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); -} - -bool SingleAbsoluteMouse_::setup(USBSetup &setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO(anyone): HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - return false; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - return false; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) { - } - } - - return false; + plug(); } void SingleAbsoluteMouse_::sendReport(void *data, int length) { - auto result = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); + auto result = SendReport(0, data, length); HIDReportObserver::observeReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length, result); } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index 557ed3294d..2f93c8ba9e 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -28,26 +28,17 @@ THE SOFTWARE. #include #include "HID.h" +#include "HIDD.h" #include "HID-Settings.h" #include "../DeviceAPIs/AbsoluteMouseAPI.h" -class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI { +class SingleAbsoluteMouse_ : public HIDD, public AbsoluteMouseAPI { public: SingleAbsoluteMouse_(); uint8_t getLeds(); - uint8_t getProtocol(); protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t *interfaceCount); - int getDescriptor(USBSetup &setup); - bool setup(USBSetup &setup); - - EPTYPE_DESCRIPTOR_SIZE epType[1]; - uint8_t protocol; - uint8_t idle; - inline void sendReport(void *data, int length) override; }; extern SingleAbsoluteMouse_ SingleAbsoluteMouse; From 0bec55a42d62e38cf529c9c467163a1cb2d14517 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sun, 28 Jan 2024 22:01:08 -0600 Subject: [PATCH 04/22] create HIDDefs.h It contains the "portable" constants that a front-end API might use. Convert AbsoluteMouseAPI to depend on this, without needing HID.h. Signed-off-by: Taylor Yu --- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 4 +- plugins/KeyboardioHID/src/HID.h | 25 +---------- plugins/KeyboardioHID/src/HIDDefs.h | 44 +++++++++++++++++++ 3 files changed, 46 insertions(+), 27 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HIDDefs.h diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 75acf14a33..ef04610087 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -27,10 +27,8 @@ THE SOFTWARE. #pragma once #include -#include "HID.h" -#include "HID-Settings.h" +#include "HIDDefs.h" #include "MouseButtons.h" -#include "tusb_hid.h" #define DESCRIPTOR_ABSOLUTE_MOUSE(...) \ HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index a945460a2e..a000cb44ee 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -21,36 +21,13 @@ #include #include +#include "HIDDefs.h" #include "HID-Settings.h" -#include "tusb_hid.h" #if defined(USBCON) #define _USING_HID -// HID 'Driver' -// ------------ -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - -// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols -#define HID_PROTOCOL_NONE 0 -#define HID_PROTOCOL_KEYBOARD 1 -#define HID_PROTOCOL_MOUSE 2 - -// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request -// "protocol" variable is used for this purpose. -#define HID_BOOT_PROTOCOL 0 -#define HID_REPORT_PROTOCOL 1 - #pragma pack(push, 1) typedef struct { uint8_t len; // 9 diff --git a/plugins/KeyboardioHID/src/HIDDefs.h b/plugins/KeyboardioHID/src/HIDDefs.h new file mode 100644 index 0000000000..08cbec435f --- /dev/null +++ b/plugins/KeyboardioHID/src/HIDDefs.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + Permission to use, copy, modify, and/or distribute this software for + any purpose with or without fee is hereby granted, provided that the + above copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR + BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + */ + +#pragma once + +#include "tusb_hid.h" + +// HID 'Driver' +// ------------ +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B + +#define HID_HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 + +// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols +#define HID_PROTOCOL_NONE 0 +#define HID_PROTOCOL_KEYBOARD 1 +#define HID_PROTOCOL_MOUSE 2 + +// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request +// "protocol" variable is used for this purpose. +#define HID_BOOT_PROTOCOL 0 +#define HID_REPORT_PROTOCOL 1 From 23cd24c3e121f248d926c5b534579df4a65b86b8 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Mon, 29 Jan 2024 09:23:53 -0600 Subject: [PATCH 05/22] move multi-report back to HID.h This makes it easier to get the simulator tests working again. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HID-Settings.h | 89 ------------- plugins/KeyboardioHID/src/HID.cpp | 1 - plugins/KeyboardioHID/src/HID.h | 35 ++++++ plugins/KeyboardioHID/src/HIDArch.h | 117 ++++++++++++++++++ plugins/KeyboardioHID/src/HIDD.cpp | 26 ++++ plugins/KeyboardioHID/src/HIDD.h | 28 ++++- plugins/KeyboardioHID/src/MultiHIDD.h | 42 ------- .../src/MultiReport/AbsoluteMouse.h | 1 - .../src/MultiReport/ConsumerControl.h | 1 - .../KeyboardioHID/src/MultiReport/Gamepad.h | 1 - plugins/KeyboardioHID/src/MultiReport/Mouse.h | 1 - .../src/MultiReport/SystemControl.h | 1 - 12 files changed, 205 insertions(+), 138 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HIDArch.h delete mode 100644 plugins/KeyboardioHID/src/MultiHIDD.h diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index f21a3b602a..d46b11f8da 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -62,92 +62,3 @@ THE SOFTWARE. #ifndef HID_REPORTID_NKRO_KEYBOARD #define HID_REPORTID_NKRO_KEYBOARD 8 #endif - - -// Controls whether to pack messages or not. When set, any sends will be delayed -// until packing is toggled off, and sent then. This is a no-op on AVR, but is -// required for SAMD. We place a forward-declaration here to be able to avoid -// architecture-specific ifdefs elsewhere in the code. -void USB_PackMessages(bool pack); - -#if defined(ARDUINO_ARCH_AVR) - -#include - -#define EPTYPE_DESCRIPTOR_SIZE uint8_t -#define USB_Configured USBDevice.configured - -#elif defined(ARDUINO_ARCH_SAM) - -#include - -#define EPTYPE_DESCRIPTOR_SIZE uint32_t -#define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ - UOTGHS_DEVEPTCFG_EPDIR_IN | \ - UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ - UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ - UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ - UOTGHS_DEVEPTCFG_ALLOC) -#define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ - UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ - UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ - UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ - UOTGHS_DEVEPTCFG_ALLOC) -#define USB_EP_SIZE EPX_SIZE -#define USB_SendControl USBD_SendControl -#define USB_Available USBD_Available -#define USB_Recv USBD_Recv -#define USB_Send USBD_Send -#define USB_Flush USBD_Flush -#define USB_Configured USBDevice.configured - -#elif defined(ARDUINO_ARCH_SAMD) - -#include - -#define EPTYPE_DESCRIPTOR_SIZE uint32_t -#define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0); -#define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0); -#define USB_EP_SIZE EPX_SIZE -//#define USB_SendControl USBDevice.sendControl -> real C++ functions to take care of PGM overloading -#define USB_Available USBDevice.available -#define USB_Recv USBDevice.recv -#define USB_RecvControl USBDevice.recvControl -#define USB_Send USBDevice.send -#define USB_Flush USBDevice.flush -#define USB_Configured USBDevice.configured - -int USB_SendControl(void *y, uint8_t z); -int USB_SendControl(uint8_t x, const void *y, uint8_t z); - -#define TRANSFER_PGM 0 -#define TRANSFER_RELEASE 0 - -#elif defined(ARDUINO_ARCH_GD32) - -#include "USBCore.h" - -#define EPTYPE_DESCRIPTOR_SIZE unsigned int - - -// Should eventually get defined upstream -#ifndef USB_DEVICE_CLASS_HUMAN_INTERFACE -#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 -#endif - -#define ARCH_HAS_CONFIGURABLE_EP_SIZES - -constexpr uint16_t EP_TYPE_INTERRUPT_IN(uint8_t buffer_size) { - return EPDesc(USB_TRX_IN, USB_EP_ATTR_INT, buffer_size).val; -} -constexpr uint16_t EP_TYPE_INTERRUPT_OUT(uint8_t buffer_size) { - return EPDesc(USB_TRX_OUT, USB_EP_ATTR_INT, buffer_size).val; -} - -#define USB_Configured USBCore().configured - -#else - -#error "Unsupported architecture" - -#endif diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 6cb51601d9..e6b7fdb413 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -20,7 +20,6 @@ #include "HID.h" #include "HIDReportObserver.h" -#include "MultiHIDD.h" #include "BootKeyboard/BootKeyboard.h" #if defined(USBCON) diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index a000cb44ee..22b4438b33 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -22,6 +22,7 @@ #include #include #include "HIDDefs.h" +#include "HIDD.h" #include "HID-Settings.h" #if defined(USBCON) @@ -48,6 +49,40 @@ typedef struct { } HIDDescriptor; #pragma pack(pop) +class HIDSubDescriptor { + public: + HIDSubDescriptor *next = NULL; + HIDSubDescriptor(const void *d, const uint16_t l) + : data(d), length(l) {} + + const void *data; + const uint16_t length; +}; + +class HID_ : public HIDD { + public: + HID_(); + int begin(); + int SendReport(uint8_t id, const void *data, int len) override; + void AppendDescriptor(HIDSubDescriptor *node); + uint8_t getLEDs() { + return outReport[1]; + } + + protected: + // Implementation of the PluggableUSBModule + int getDescriptor(USBSetup &setup) override; + uint8_t getShortName(char *name); + + private: + HIDSubDescriptor *rootNode; +}; + +// Replacement for global singleton. +// This function prevents static-initialization-order-fiasco +// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use +HID_ &HID(); + #define D_HIDREPORT(length) \ { 9, 0x21, 0x11, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } diff --git a/plugins/KeyboardioHID/src/HIDArch.h b/plugins/KeyboardioHID/src/HIDArch.h new file mode 100644 index 0000000000..f44315a0d0 --- /dev/null +++ b/plugins/KeyboardioHID/src/HIDArch.h @@ -0,0 +1,117 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +/* Portability definitions for different PluggableUSB back ends */ + +// Controls whether to pack messages or not. When set, any sends will be delayed +// until packing is toggled off, and sent then. This is a no-op on AVR, but is +// required for SAMD. We place a forward-declaration here to be able to avoid +// architecture-specific ifdefs elsewhere in the code. +void USB_PackMessages(bool pack); + +#if defined(ARDUINO_ARCH_AVR) + +#include + +#define EPTYPE_DESCRIPTOR_SIZE uint8_t +#define USB_Configured USBDevice.configured + +#elif defined(ARDUINO_ARCH_SAM) + +#include + +#define EPTYPE_DESCRIPTOR_SIZE uint32_t +#define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ + UOTGHS_DEVEPTCFG_EPDIR_IN | \ + UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ + UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ + UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ + UOTGHS_DEVEPTCFG_ALLOC) +#define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ + UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ + UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ + UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ + UOTGHS_DEVEPTCFG_ALLOC) +#define USB_EP_SIZE EPX_SIZE +#define USB_SendControl USBD_SendControl +#define USB_Available USBD_Available +#define USB_Recv USBD_Recv +#define USB_Send USBD_Send +#define USB_Flush USBD_Flush +#define USB_Configured USBDevice.configured + +#elif defined(ARDUINO_ARCH_SAMD) + +#include + +#define EPTYPE_DESCRIPTOR_SIZE uint32_t +#define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0); +#define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0); +#define USB_EP_SIZE EPX_SIZE +//#define USB_SendControl USBDevice.sendControl -> real C++ functions to take care of PGM overloading +#define USB_Available USBDevice.available +#define USB_Recv USBDevice.recv +#define USB_RecvControl USBDevice.recvControl +#define USB_Send USBDevice.send +#define USB_Flush USBDevice.flush +#define USB_Configured USBDevice.configured + +int USB_SendControl(void *y, uint8_t z); +int USB_SendControl(uint8_t x, const void *y, uint8_t z); + +#define TRANSFER_PGM 0 +#define TRANSFER_RELEASE 0 + +#elif defined(ARDUINO_ARCH_GD32) + +#include "USBCore.h" + +#define EPTYPE_DESCRIPTOR_SIZE unsigned int + + +// Should eventually get defined upstream +#ifndef USB_DEVICE_CLASS_HUMAN_INTERFACE +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#endif + +#define ARCH_HAS_CONFIGURABLE_EP_SIZES + +constexpr uint16_t EP_TYPE_INTERRUPT_IN(uint8_t buffer_size) { + return EPDesc(USB_TRX_IN, USB_EP_ATTR_INT, buffer_size).val; +} +constexpr uint16_t EP_TYPE_INTERRUPT_OUT(uint8_t buffer_size) { + return EPDesc(USB_TRX_OUT, USB_EP_ATTR_INT, buffer_size).val; +} + +#define USB_Configured USBCore().configured + +#else + +#error "Unsupported architecture" + +#endif diff --git a/plugins/KeyboardioHID/src/HIDD.cpp b/plugins/KeyboardioHID/src/HIDD.cpp index cc6c04f09f..6ce1d6a1b9 100644 --- a/plugins/KeyboardioHID/src/HIDD.cpp +++ b/plugins/KeyboardioHID/src/HIDD.cpp @@ -1,3 +1,29 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "HID.h" #include "HIDD.h" #include "HID-Settings.h" diff --git a/plugins/KeyboardioHID/src/HIDD.h b/plugins/KeyboardioHID/src/HIDD.h index a89a28824e..84769c6c3f 100644 --- a/plugins/KeyboardioHID/src/HIDD.h +++ b/plugins/KeyboardioHID/src/HIDD.h @@ -1,3 +1,28 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + /* HID driver back end */ #pragma once @@ -5,7 +30,8 @@ #include #include -#include "HID.h" +#include "HIDArch.h" /* unfortunately needed for EPTYPE_DESCRIPTOR_SIZE */ +#include "HIDDefs.h" /* Maximum length of output report sent by host */ #define HIDD_MAX_OUTPUT_REPORT 2 diff --git a/plugins/KeyboardioHID/src/MultiHIDD.h b/plugins/KeyboardioHID/src/MultiHIDD.h deleted file mode 100644 index 2a26c46aec..0000000000 --- a/plugins/KeyboardioHID/src/MultiHIDD.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include - -#include "HID.h" -#include "HIDD.h" -#include "HID-Settings.h" - -class HIDSubDescriptor { - public: - HIDSubDescriptor *next = NULL; - HIDSubDescriptor(const void *d, const uint16_t l) - : data(d), length(l) {} - - const void *data; - const uint16_t length; -}; - -class HID_ : public HIDD { - public: - HID_(); - int begin(); - int SendReport(uint8_t id, const void *data, int len) override; - void AppendDescriptor(HIDSubDescriptor *node); - uint8_t getLEDs() { - return outReport[1]; - } - - protected: - // Implementation of the PluggableUSBModule - int getDescriptor(USBSetup &setup) override; - uint8_t getShortName(char *name); - - private: - HIDSubDescriptor *rootNode; -}; - -// Replacement for global singleton. -// This function prevents static-initialization-order-fiasco -// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use -HID_ &HID(); diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 88cf29362d..3ecc1a16f9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "MultiHIDD.h" #include "../DeviceAPIs/AbsoluteMouseAPI.h" class AbsoluteMouse_ : public AbsoluteMouseAPI { diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index d1d4bdec8a..cbe8af35d6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "MultiHIDD.h" #include "tusb_hid.h" #define DESCRIPTOR_CONSUMER_CONTROL(...) \ diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 162311376e..17d02b4263 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "MultiHIDD.h" #include "tusb_hid.h" // Dpad directions diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index d65624dd79..b1b2ab14e0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "MultiHIDD.h" #include "../MouseButtons.h" #include "tusb_hid.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 439458fa72..5807be8056 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -30,7 +30,6 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" #include "HIDTables.h" -#include "MultiHIDD.h" #include "tusb_hid.h" #define DESCRIPTOR_SYSTEM_CONTROL(...) \ From 246c0567c96cc36d7a7ff7c793f1e9936879a258 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Mon, 29 Jan 2024 10:44:31 -0600 Subject: [PATCH 06/22] clean up Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HIDD.cpp | 30 +++++++++---------- plugins/KeyboardioHID/src/HIDD.h | 24 +++++++-------- .../src/SingleReport/SingleAbsoluteMouse.cpp | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/plugins/KeyboardioHID/src/HIDD.cpp b/plugins/KeyboardioHID/src/HIDD.cpp index 6ce1d6a1b9..f7799e8318 100644 --- a/plugins/KeyboardioHID/src/HIDD.cpp +++ b/plugins/KeyboardioHID/src/HIDD.cpp @@ -28,21 +28,21 @@ THE SOFTWARE. #include "HID-Settings.h" HIDD::HIDD( - uint8_t _protocol, - uint8_t _idle, - uint8_t _itfProtocol, + const void *_reportDesc, + uint16_t _descriptorSize, uint8_t _inReportLen, + uint8_t _itfProtocol, uint8_t _interval, - const void *_reportDesc, - uint16_t _descriptorSize) - : PluggableUSBModule(1, 1, epType), - protocol(_protocol), - idle(_idle), - itfProtocol(_itfProtocol), - inReportLen(_inReportLen), - interval(_interval), - reportDesc(_reportDesc), - descriptorSize(_descriptorSize) { + uint8_t _idle) + : PluggableUSBModule(1, 1, epType) { + + reportDesc = _reportDesc; + descriptorSize = _descriptorSize; + inReportLen = _inReportLen; + itfProtocol = _itfProtocol; + interval = _interval; + idle = _idle; + protocol = HID_PROTOCOL_REPORT; #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(inReportLen); @@ -54,7 +54,7 @@ HIDD::HIDD( /* PluggableUSB implementation: interface, etc. descriptors for config */ int HIDD::getInterface(uint8_t *interfaceCount) { uint8_t itfSubClass; - if (itfProtocol != HID_PROTOCOL_NONE) { + if (itfProtocol != HID_ITF_PROTOCOL_NONE) { itfSubClass = HID_SUBCLASS_BOOT; } else { itfSubClass = HID_SUBCLASS_NONE; @@ -72,7 +72,7 @@ int HIDD::getInterface(uint8_t *interfaceCount) { D_HIDREPORT(descriptorSize), D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, epSize, interval), }; - ++*interfaceCount; + *interfaceCount += 1; return USB_SendControl(0, &descSet, sizeof(descSet)); } diff --git a/plugins/KeyboardioHID/src/HIDD.h b/plugins/KeyboardioHID/src/HIDD.h index 84769c6c3f..b517979bb1 100644 --- a/plugins/KeyboardioHID/src/HIDD.h +++ b/plugins/KeyboardioHID/src/HIDD.h @@ -39,13 +39,12 @@ THE SOFTWARE. class HIDD : public PluggableUSBModule { public: HIDD( - uint8_t _protocol = HID_REPORT_PROTOCOL, - uint8_t _idle = 0, - uint8_t _itfProtocol = HID_PROTOCOL_NONE, + const void *_reportDesc = NULL, + uint16_t descriptorSize = 0, uint8_t _inReportLen = USB_EP_SIZE, + uint8_t _itfProtocol = HID_ITF_PROTOCOL_NONE, uint8_t _interval = 1, - const void *_reportDesc = NULL, - uint16_t descriptorSize = 0); + uint8_t _idle = 0); virtual int SendReport(uint8_t id, const void *data, int len); uint8_t getProtocol() { return protocol; @@ -61,16 +60,17 @@ class HIDD : public PluggableUSBModule { PluggableUSB().plug(this); } - /* Current HID protocol: Boot or Report */ - uint8_t protocol; - uint8_t idle; + const void *reportDesc; + uint16_t descriptorSize; + uint8_t inReportLen; /* Interface protocol, for interface descriptor (only boot devices) */ uint8_t itfProtocol; - uint8_t inReportLen; - uint8_t outReportLen; uint8_t interval; - const void *reportDesc; - uint16_t descriptorSize; + uint8_t idle; + uint8_t outReportLen; + + /* Current HID protocol: Boot or Report */ + uint8_t protocol; uint8_t outReport[HIDD_MAX_OUTPUT_REPORT]; virtual void setReportCB(const void *data, uint16_t len) { diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 715a0a2ede..9e2eadd92e 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -33,7 +33,7 @@ static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { }; SingleAbsoluteMouse_::SingleAbsoluteMouse_() - : HIDD(HID_REPORT_PROTOCOL, 0, HID_PROTOCOL_NONE, 6, 1, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)) { + : HIDD(_hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse), sizeof(HID_MouseAbsoluteReport_Data_t)) { // Invoke BootKeyboard constructor so it will be the first HID interface (void)BootKeyboard(); From e1e885d85eb4c60e6e4d6093ac16f381b7c70b50 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Mon, 29 Jan 2024 11:22:42 -0600 Subject: [PATCH 07/22] move backend-independent stuff Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h | 4 ++-- plugins/KeyboardioHID/src/HID.h | 2 +- plugins/KeyboardioHID/src/HIDD.h | 2 +- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 2 +- {plugins/KeyboardioHID/src => src/kaleidoscope}/HIDDefs.h | 0 .../KeyboardioHID/src => src/kaleidoscope}/MouseButtons.h | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename {plugins/KeyboardioHID/src => src/kaleidoscope}/HIDDefs.h (100%) rename {plugins/KeyboardioHID/src => src/kaleidoscope}/MouseButtons.h (100%) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index ef04610087..cf7180fd5c 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -27,8 +27,8 @@ THE SOFTWARE. #pragma once #include -#include "HIDDefs.h" -#include "MouseButtons.h" +#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/MouseButtons.h" #define DESCRIPTOR_ABSOLUTE_MOUSE(...) \ HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index 22b4438b33..a3253f7480 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -21,7 +21,7 @@ #include #include -#include "HIDDefs.h" +#include "kaleidoscope/HIDDefs.h" #include "HIDD.h" #include "HID-Settings.h" diff --git a/plugins/KeyboardioHID/src/HIDD.h b/plugins/KeyboardioHID/src/HIDD.h index b517979bb1..6f18347054 100644 --- a/plugins/KeyboardioHID/src/HIDD.h +++ b/plugins/KeyboardioHID/src/HIDD.h @@ -31,7 +31,7 @@ THE SOFTWARE. #include #include "HIDArch.h" /* unfortunately needed for EPTYPE_DESCRIPTOR_SIZE */ -#include "HIDDefs.h" +#include "kaleidoscope/HIDDefs.h" /* Maximum length of output report sent by host */ #define HIDD_MAX_OUTPUT_REPORT 2 diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index b1b2ab14e0..ee04df392f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "../MouseButtons.h" +#include "kaleidoscope/MouseButtons.h" #include "tusb_hid.h" #define DESCRIPTOR_MOUSE(...) \ diff --git a/plugins/KeyboardioHID/src/HIDDefs.h b/src/kaleidoscope/HIDDefs.h similarity index 100% rename from plugins/KeyboardioHID/src/HIDDefs.h rename to src/kaleidoscope/HIDDefs.h diff --git a/plugins/KeyboardioHID/src/MouseButtons.h b/src/kaleidoscope/MouseButtons.h similarity index 100% rename from plugins/KeyboardioHID/src/MouseButtons.h rename to src/kaleidoscope/MouseButtons.h From 076fc4bd4236d610e2550be8c82fdcbf9fcad60a Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Mon, 29 Jan 2024 11:26:59 -0600 Subject: [PATCH 08/22] move AbsoluteMouseAPI Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 2 +- plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h | 2 +- .../kaleidoscope/driver/hid/apis}/AbsoluteMouseAPI.h | 0 .../kaleidoscope/driver/hid/apis}/AbsoluteMouseAPI.hpp | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename {plugins/KeyboardioHID/src/DeviceAPIs => src/kaleidoscope/driver/hid/apis}/AbsoluteMouseAPI.h (100%) rename {plugins/KeyboardioHID/src/DeviceAPIs => src/kaleidoscope/driver/hid/apis}/AbsoluteMouseAPI.hpp (100%) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 3ecc1a16f9..73bb9c99d3 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "../DeviceAPIs/AbsoluteMouseAPI.h" +#include "kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h" class AbsoluteMouse_ : public AbsoluteMouseAPI { public: diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index 2f93c8ba9e..a9f98b645b 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -30,7 +30,7 @@ THE SOFTWARE. #include "HID.h" #include "HIDD.h" #include "HID-Settings.h" -#include "../DeviceAPIs/AbsoluteMouseAPI.h" +#include "kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h" class SingleAbsoluteMouse_ : public HIDD, public AbsoluteMouseAPI { diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h similarity index 100% rename from plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h rename to src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.hpp similarity index 100% rename from plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp rename to src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.hpp From 3ff01b0493d9e6affc326da65c2acbbf6157eb62 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 2 Feb 2024 14:42:33 -0600 Subject: [PATCH 09/22] ConsumerControlAPI Signed-off-by: Taylor Yu --- .../src/MultiReport/ConsumerControl.cpp | 51 ------------ .../src/MultiReport/ConsumerControl.h | 48 +---------- .../driver/hid/apis/ConsumerControlAPI.h | 83 +++++++++++++++++++ .../driver/hid/apis/ConsumerControlAPI.hpp | 80 ++++++++++++++++++ 4 files changed, 165 insertions(+), 97 deletions(-) create mode 100644 src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h create mode 100644 src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index d1e0214007..f483bd4cc1 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -35,59 +35,8 @@ ConsumerControl_::ConsumerControl_() { HID().AppendDescriptor(&node); } -void ConsumerControl_::begin() { -} - -void ConsumerControl_::end() { - memset(&report_, 0, sizeof(report_)); - sendReport(); -} - -void ConsumerControl_::write(uint16_t m) { - press(m); - release(m); -} - -void ConsumerControl_::press(uint16_t m) { - // search for a free spot - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (report_.keys[i] == 0x00) { - report_.keys[i] = m; - break; - } - } -} - -void ConsumerControl_::release(uint16_t m) { - // search and release the keypress - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (report_.keys[i] == m) { - report_.keys[i] = 0x00; - // no break to delete multiple keys - } - } -} - -void ConsumerControl_::releaseAll() { - memset(&report_, 0, sizeof(report_)); -} - void ConsumerControl_::sendReportUnchecked() { HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &report_, sizeof(report_)); } -void ConsumerControl_::sendReport() { - // If the last report is different than the current report, then we need to - // send a report. We guard sendReport like this so that calling code doesn't - // end up spamming the host with empty reports if sendReport is called in a - // tight loop. - - // if the previous report is the same, return early without a new report. - if (memcmp(&last_report_, &report_, sizeof(report_)) == 0) - return; - - sendReportUnchecked(); - memcpy(&last_report_, &report_, sizeof(report_)); -} - ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index cbe8af35d6..20c1ba3c05 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -29,58 +29,14 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "tusb_hid.h" -#define DESCRIPTOR_CONSUMER_CONTROL(...) \ - HID_USAGE_PAGE(HID_USAGE_PAGE_CONSUMER), \ - \ - /* Consumer Control (Sound/Media keys) */ \ - HID_USAGE(HID_USAGE_CONSUMER_CONTROL), \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - \ - /* Report ID, if any */ \ - __VA_ARGS__ \ - \ - /* 4 Media Keys */ \ - HID_LOGICAL_MIN(0), \ - HID_LOGICAL_MAX_N(0x3ff, 2), \ - HID_USAGE_MIN(0), \ - HID_USAGE_MAX_N(0x3ff, 2), \ - HID_REPORT_COUNT(4), \ - HID_REPORT_SIZE(16), \ - HID_INPUT(HID_DATA | HID_ARRAY | HID_ABSOLUTE), \ - HID_COLLECTION_END +#include "kaleidoscope/driver/hid/apis/ConsumerControlAPI.h" -typedef union { - // Every usable Consumer key possible, up to 4 keys presses possible - uint16_t keys[4]; - struct { - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; -} HID_ConsumerControlReport_Data_t; - - -class ConsumerControl_ { +class ConsumerControl_ : public ConsumerControlAPI { public: ConsumerControl_(); - void begin(); - void end(); - void write(uint16_t m); - void press(uint16_t m); - void release(uint16_t m); - void releaseAll(); - - // Sending is public in the base class for advanced users. - void sendReport(); protected: - HID_ConsumerControlReport_Data_t report_; - HID_ConsumerControlReport_Data_t last_report_; - - private: void sendReportUnchecked(); }; extern ConsumerControl_ ConsumerControl; diff --git a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h new file mode 100644 index 0000000000..3db5611aa3 --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h @@ -0,0 +1,83 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +#include +#include "kaleidoscope/HIDDefs.h" + +#define DESCRIPTOR_CONSUMER_CONTROL(...) \ + HID_USAGE_PAGE(HID_USAGE_PAGE_CONSUMER), \ + \ + /* Consumer Control (Sound/Media keys) */ \ + HID_USAGE(HID_USAGE_CONSUMER_CONTROL), \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + \ + /* Report ID, if any */ \ + __VA_ARGS__ \ + \ + /* 4 Media Keys */ \ + HID_LOGICAL_MIN(0), \ + HID_LOGICAL_MAX_N(0x3ff, 2), \ + HID_USAGE_MIN(0), \ + HID_USAGE_MAX_N(0x3ff, 2), \ + HID_REPORT_COUNT(4), \ + HID_REPORT_SIZE(16), \ + HID_INPUT(HID_DATA | HID_ARRAY | HID_ABSOLUTE), \ + HID_COLLECTION_END + +typedef union { + // Every usable Consumer key possible, up to 4 keys presses possible + uint16_t keys[4]; + struct { + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; +} HID_ConsumerControlReport_Data_t; + + +class ConsumerControlAPI { + public: + inline ConsumerControlAPI(); + inline void begin(); + inline void end(); + inline void write(uint16_t m); + inline void press(uint16_t m); + inline void release(uint16_t m); + inline void releaseAll(); + + inline void sendReport(); + + protected: + virtual void sendReportUnchecked() = 0; + + HID_ConsumerControlReport_Data_t report_; + HID_ConsumerControlReport_Data_t last_report_; +}; + +#include "ConsumerControlAPI.hpp" diff --git a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp new file mode 100644 index 0000000000..0dd6909c8d --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp @@ -0,0 +1,80 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once + +ConsumerControlAPI::ConsumerControlAPI() + : report_{0}, last_report_{0} {} + +void ConsumerControlAPI::begin() { +} + +void ConsumerControlAPI::end() { + memset(&report_, 0, sizeof(report_)); + sendReport(); +} + +void ConsumerControlAPI::write(uint16_t m) { + press(m); + release(m); +} + +void ConsumerControlAPI::press(uint16_t m) { + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (report_.keys[i] == 0x00) { + report_.keys[i] = m; + break; + } + } +} + +void ConsumerControlAPI::release(uint16_t m) { + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (report_.keys[i] == m) { + report_.keys[i] = 0x00; + // no break to delete multiple keys + } + } +} + +void ConsumerControlAPI::releaseAll() { + memset(&report_, 0, sizeof(report_)); +} + +void ConsumerControlAPI::sendReport() { + // If the last report is different than the current report, then we need to + // send a report. We guard sendReport like this so that calling code doesn't + // end up spamming the host with empty reports if sendReport is called in a + // tight loop. + + // if the previous report is the same, return early without a new report. + if (memcmp(&last_report_, &report_, sizeof(report_)) == 0) + return; + + sendReportUnchecked(); + memcpy(&last_report_, &report_, sizeof(report_)); +} From 76a75621982f8e1b98462593bd3dc6611ede45e2 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 2 Feb 2024 15:05:07 -0600 Subject: [PATCH 10/22] MouseAPI Signed-off-by: Taylor Yu --- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 62 --------- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 86 +------------ src/kaleidoscope/driver/hid/apis/MouseAPI.h | 121 ++++++++++++++++++ src/kaleidoscope/driver/hid/apis/MouseAPI.hpp | 91 +++++++++++++ 4 files changed, 214 insertions(+), 146 deletions(-) create mode 100644 src/kaleidoscope/driver/hid/apis/MouseAPI.h create mode 100644 src/kaleidoscope/driver/hid/apis/MouseAPI.hpp diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 851352fca5..333bda9103 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -35,70 +35,8 @@ Mouse_::Mouse_() { HID().AppendDescriptor(&node); } -void Mouse_::begin() { -} - -void Mouse_::end() { - releaseAll(); - sendReport(); -} - -void Mouse_::click(uint8_t b) { - // If one or more of the buttons to be clicked was already pressed, we need to - // send a report to release it first, to guarantee that this will be a "click" - // and not merely a release. - if (report_.buttons & b) { - release(b); - sendReport(); - } - // Next, send a report with the button(s) pressed: - press(b); - sendReport(); - // Finally, send the report with the button(s) released: - release(b); - sendReport(); -} - -void Mouse_::move(int8_t x, int8_t y, int8_t v_wheel, int8_t h_wheel) { - report_.xAxis = x; - report_.yAxis = y; - report_.vWheel = v_wheel; - report_.hWheel = h_wheel; -} - -void Mouse_::releaseAll() { - memset(&report_, 0, sizeof(report_)); -} - -void Mouse_::press(uint8_t b) { - report_.buttons |= b; -} - -void Mouse_::release(uint8_t b) { - report_.buttons &= ~b; -} - -bool Mouse_::isPressed(uint8_t b) { - if ((b & report_.buttons) > 0) - return true; - return false; -} - void Mouse_::sendReportUnchecked() { HID().SendReport(HID_REPORTID_MOUSE, &report_, sizeof(report_)); } -void Mouse_::sendReport() { - // If the button state has not changed, and neither the cursor nor the wheel - // is being told to move, there is no need to send a report. This check - // prevents us from sending lots of no-op reports if the caller is in a loop - // and not checking or buggy. - if (report_.buttons != prev_report_buttons_ || - report_.xAxis != 0 || report_.yAxis != 0 || - report_.vWheel != 0 || report_.hWheel != 0) { - sendReportUnchecked(); - prev_report_buttons_ = report_.buttons; - } -} - Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index ee04df392f..42c90e0a04 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -29,95 +29,13 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "kaleidoscope/MouseButtons.h" -#include "tusb_hid.h" +#include "kaleidoscope/driver/hid/apis/MouseAPI.h" -#define DESCRIPTOR_MOUSE(...) \ - /* Mouse relative */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_MOUSE), \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - HID_USAGE(HID_USAGE_DESKTOP_POINTER), \ - HID_COLLECTION(HID_COLLECTION_PHYSICAL), \ - \ - /* Report ID, if any */ \ - __VA_ARGS__ \ - \ - /* 8 Buttons */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_BUTTON), \ - HID_USAGE_MIN(1), \ - HID_USAGE_MAX(8), \ - HID_LOGICAL_MIN(0), \ - HID_LOGICAL_MAX(1), \ - HID_REPORT_SIZE(1), \ - HID_REPORT_COUNT(8), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - /* X, Y, Wheel [-127, 127] */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_X), \ - HID_USAGE(HID_USAGE_DESKTOP_Y), \ - HID_USAGE(HID_USAGE_DESKTOP_WHEEL), \ - HID_LOGICAL_MIN(0x81), \ - HID_LOGICAL_MAX(0x7f), \ - HID_REPORT_SIZE(8), \ - HID_REPORT_COUNT(3), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_RELATIVE), \ - \ - /* Horizontal wheel */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_CONSUMER), \ - HID_USAGE_N(0x0238, 2), \ - HID_REPORT_COUNT(1), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_RELATIVE), \ - \ - /* End */ \ - HID_COLLECTION_END, \ - HID_COLLECTION_END - -typedef union { - // Mouse report: 8 buttons, position, wheel - struct { - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t vWheel; - int8_t hWheel; - }; -} HID_MouseReport_Data_t; - - -class Mouse_ { +class Mouse_ : public MouseAPI { public: Mouse_(); - void begin(); - void end(); - // Note: the following `click()` method is unlike the `move()`, `press()`, and - // `release()` methods, in that it doesn't merely modify the pending report, - // but also calls `sendReport()` at least twice. - void click(uint8_t b = MOUSE_LEFT); - void move(int8_t x, int8_t y, int8_t v_wheel = 0, int8_t h_wheel = 0); - void press(uint8_t b = MOUSE_LEFT); // press LEFT by default - void release(uint8_t b = MOUSE_LEFT); // release LEFT by default - bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default - - /** getReport returns the current report. - * - * The current report is the one to be send next time sendReport() is called. - * - * @returns A copy of the report. - */ - const HID_MouseReport_Data_t getReport() { - return report_; - } - void sendReport(); - - void releaseAll(); protected: - HID_MouseReport_Data_t report_; - uint8_t prev_report_buttons_ = 0; - - private: void sendReportUnchecked(); }; extern Mouse_ Mouse; diff --git a/src/kaleidoscope/driver/hid/apis/MouseAPI.h b/src/kaleidoscope/driver/hid/apis/MouseAPI.h new file mode 100644 index 0000000000..7cff39ced5 --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/MouseAPI.h @@ -0,0 +1,121 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +#include +#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/MouseButtons.h" + +#define DESCRIPTOR_MOUSE(...) \ + /* Mouse relative */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_MOUSE), \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + HID_USAGE(HID_USAGE_DESKTOP_POINTER), \ + HID_COLLECTION(HID_COLLECTION_PHYSICAL), \ + \ + /* Report ID, if any */ \ + __VA_ARGS__ \ + \ + /* 8 Buttons */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_BUTTON), \ + HID_USAGE_MIN(1), \ + HID_USAGE_MAX(8), \ + HID_LOGICAL_MIN(0), \ + HID_LOGICAL_MAX(1), \ + HID_REPORT_SIZE(1), \ + HID_REPORT_COUNT(8), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + /* X, Y, Wheel */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_X), \ + HID_USAGE(HID_USAGE_DESKTOP_Y), \ + HID_USAGE(HID_USAGE_DESKTOP_WHEEL), \ + HID_LOGICAL_MIN(0x81), \ + HID_LOGICAL_MAX(0x7f), \ + HID_REPORT_SIZE(8), \ + HID_REPORT_COUNT(3), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_RELATIVE), \ + \ + /* Horizontal wheel */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_CONSUMER), \ + HID_USAGE_N(0x0238, 2), \ + HID_REPORT_COUNT(1), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_RELATIVE), \ + \ + /* End */ \ + HID_COLLECTION_END, \ + HID_COLLECTION_END + +typedef union { + // Mouse report: 8 buttons, position, wheel + struct { + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t vWheel; + int8_t hWheel; + }; +} HID_MouseReport_Data_t; + + +class MouseAPI { + public: + inline MouseAPI(); + inline void begin(); + inline void end(); + // Note: the following `click()` method is unlike the `move()`, `press()`, and + // `release()` methods, in that it doesn't merely modify the pending report, + // but also calls `sendReport()` at least twice. + inline void click(uint8_t b = MOUSE_LEFT); + inline void move(int8_t x, int8_t y, int8_t v_wheel = 0, int8_t h_wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default + + /** getReport returns the current report. + * + * The current report is the one to be send next time sendReport() is called. + * + * @returns A copy of the report. + */ + const HID_MouseReport_Data_t getReport() { + return report_; + } + inline void sendReport(); + + inline void releaseAll(); + + protected: + HID_MouseReport_Data_t report_; + uint8_t prev_report_buttons_ = 0; + + virtual void sendReportUnchecked() = 0; +}; + +#include "MouseAPI.hpp" diff --git a/src/kaleidoscope/driver/hid/apis/MouseAPI.hpp b/src/kaleidoscope/driver/hid/apis/MouseAPI.hpp new file mode 100644 index 0000000000..ba8f4dbf7d --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/MouseAPI.hpp @@ -0,0 +1,91 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once + +MouseAPI::MouseAPI() + : report_{0} {} + +void MouseAPI::begin() { +} + +void MouseAPI::end() { + releaseAll(); + sendReport(); +} + +void MouseAPI::click(uint8_t b) { + // If one or more of the buttons to be clicked was already pressed, we need to + // send a report to release it first, to guarantee that this will be a "click" + // and not merely a release. + if (report_.buttons & b) { + release(b); + sendReport(); + } + // Next, send a report with the button(s) pressed: + press(b); + sendReport(); + // Finally, send the report with the button(s) released: + release(b); + sendReport(); +} + +void MouseAPI::move(int8_t x, int8_t y, int8_t v_wheel, int8_t h_wheel) { + report_.xAxis = x; + report_.yAxis = y; + report_.vWheel = v_wheel; + report_.hWheel = h_wheel; +} + +void MouseAPI::releaseAll() { + memset(&report_, 0, sizeof(report_)); +} + +void MouseAPI::press(uint8_t b) { + report_.buttons |= b; +} + +void MouseAPI::release(uint8_t b) { + report_.buttons &= ~b; +} + +bool MouseAPI::isPressed(uint8_t b) { + if ((b & report_.buttons) > 0) + return true; + return false; +} + +void MouseAPI::sendReport() { + // If the button state has not changed, and neither the cursor nor the wheel + // is being told to move, there is no need to send a report. This check + // prevents us from sending lots of no-op reports if the caller is in a loop + // and not checking or buggy. + if (report_.buttons != prev_report_buttons_ || + report_.xAxis != 0 || report_.yAxis != 0 || + report_.vWheel != 0 || report_.hWheel != 0) { + sendReportUnchecked(); + prev_report_buttons_ = report_.buttons; + } +} From 9a8a33ac1f5ffb5c5e6e8f1fa998ec9da1bec164 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 2 Feb 2024 15:27:40 -0600 Subject: [PATCH 11/22] SystemControlAPI Signed-off-by: Taylor Yu --- .../src/MultiReport/SystemControl.cpp | 26 +------ .../src/MultiReport/SystemControl.h | 40 +--------- .../driver/hid/apis/SystemControlAPI.h | 73 +++++++++++++++++++ .../driver/hid/apis/SystemControlAPI.hpp | 56 ++++++++++++++ 4 files changed, 136 insertions(+), 59 deletions(-) create mode 100644 src/kaleidoscope/driver/hid/apis/SystemControlAPI.h create mode 100644 src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 68503d1eef..4744c823a6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -35,28 +35,8 @@ SystemControl_::SystemControl_() { HID().AppendDescriptor(&node); } -void SystemControl_::begin() { -} - -void SystemControl_::end() { - releaseAll(); -} - -void SystemControl_::write(uint8_t s) { - press(s); - release(); -} - -void SystemControl_::release() { - releaseAll(); -} - -void SystemControl_::releaseAll() { - uint8_t report = 0x00; - sendReport(&report, sizeof(report)); -} -void SystemControl_::press(uint8_t s) { +bool SystemControl_::wakeupHost(uint8_t s) { if (s == HID_SYSTEM_WAKE_UP) { #ifdef __AVR__ USBDevice.wakeupHost(); @@ -67,9 +47,9 @@ void SystemControl_::press(uint8_t s) { // errors. So we simply reimplement the same thing here. USB->DEVICE.CTRLB.bit.UPRSM = 1; #endif - } else { - sendReport(&s, sizeof(s)); + return true; } + return false; } diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 5807be8056..35b1315d5f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -30,47 +30,15 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" #include "HIDTables.h" -#include "tusb_hid.h" +#include "kaleidoscope/driver/hid/apis/SystemControlAPI.h" -#define DESCRIPTOR_SYSTEM_CONTROL(...) \ - /* TODO(anyone) limit to system keys only? */ \ - /* System Control (Power Down, Sleep, Wakeup, ...) */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_SYSTEM_CONTROL), \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - \ - /* Report ID (if any) */ \ - __VA_ARGS__ \ - \ - HID_LOGICAL_MIN(0), \ - HID_LOGICAL_MAX_N(255, 2), \ - HID_USAGE_MIN(0), \ - HID_USAGE_MAX(255), \ - HID_REPORT_COUNT(1), \ - HID_REPORT_SIZE(8), \ - HID_INPUT(HID_DATA | HID_ARRAY | HID_ABSOLUTE), \ - \ - HID_COLLECTION_END - -typedef union { - // Every usable system control key possible - uint8_t key; -} HID_SystemControlReport_Data_t; - - -class SystemControl_ { +class SystemControl_ : public SystemControlAPI { public: - void begin(); - void end(); - void write(uint8_t s); - void press(uint8_t s); - void release(); - void releaseAll(); - void sendReport(void *data, int length); - SystemControl_(); protected: + void sendReport(void *data, int length); + bool wakeupHost(uint8_t s); }; diff --git a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h new file mode 100644 index 0000000000..17b427e009 --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +#include "kaleidoscope/HIDDefs.h" + +#define DESCRIPTOR_SYSTEM_CONTROL(...) \ + /* TODO(anyone) limit to system keys only? */ \ + /* System Control (Power Down, Sleep, Wakeup, ...) */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_SYSTEM_CONTROL), \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + \ + /* Report ID (if any) */ \ + __VA_ARGS__ \ + \ + HID_LOGICAL_MIN(0), \ + HID_LOGICAL_MAX_N(255, 2), \ + HID_USAGE_MIN(0), \ + HID_USAGE_MAX(255), \ + HID_REPORT_COUNT(1), \ + HID_REPORT_SIZE(8), \ + HID_INPUT(HID_DATA | HID_ARRAY | HID_ABSOLUTE), \ + \ + HID_COLLECTION_END + +typedef union { + // Every usable system control key possible + uint8_t key; +} HID_SystemControlReport_Data_t; + + +class SystemControlAPI { + public: + inline SystemControlAPI(); + + inline void begin(); + inline void end(); + inline void write(uint8_t s); + inline void press(uint8_t s); + inline void release(); + inline void releaseAll(); + + protected: + virtual void sendReport(void *data, int length) = 0; + virtual bool wakeupHost(uint8_t s) = 0; +}; + +#include "SystemControlAPI.hpp" diff --git a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp new file mode 100644 index 0000000000..dda584eadd --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp @@ -0,0 +1,56 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once + +SystemControlAPI::SystemControlAPI() { +} + +void SystemControlAPI::begin() { +} + +void SystemControlAPI::end() { + releaseAll(); +} + +void SystemControlAPI::write(uint8_t s) { + press(s); + release(); +} + +void SystemControlAPI::release() { + releaseAll(); +} + +void SystemControlAPI::releaseAll() { + uint8_t report = 0x00; + sendReport(&report, sizeof(report)); +} + +void SystemControlAPI::press(uint8_t s) { + if (!wakeupHost(s)) { + sendReport(&s, sizeof(s)); + } +} From 49dc757bb6ab23fcffd8f5d9a8187d89f0287070 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 7 Feb 2024 15:11:21 -0600 Subject: [PATCH 12/22] fixup simulator-tests Signed-off-by: Taylor Yu --- .../device/virtual/VirtualHID.cpp | 20 +------------------ testing/AbsoluteMouseReport.cpp | 4 ++-- testing/AbsoluteMouseReport.h | 4 ++-- testing/MouseReport.h | 6 +++--- 4 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/kaleidoscope/device/virtual/VirtualHID.cpp b/src/kaleidoscope/device/virtual/VirtualHID.cpp index 80ba010714..2dcc469490 100644 --- a/src/kaleidoscope/device/virtual/VirtualHID.cpp +++ b/src/kaleidoscope/device/virtual/VirtualHID.cpp @@ -37,11 +37,6 @@ HID_ &HID() { return obj; } -int HID_::getInterface(uint8_t *interfaceCount) { - *interfaceCount += 1; // uses 1 - return 0; -} - int HID_::getDescriptor(USBSetup &setup) { return 1; } @@ -67,20 +62,7 @@ int HID_::SendReport(uint8_t id, const void *data, int len) { return 1; } -bool HID_::setup(USBSetup &setup) { - return true; -} - -HID_::HID_(void) - : PluggableUSBModule(1, 1, epType), - rootNode(NULL), - descriptorSize(0), - protocol(HID_REPORT_PROTOCOL), - idle(1) { - setReportData.reportId = 0; - setReportData.leds = 0; - epType[0] = EP_TYPE_INTERRUPT_IN; - //PluggableUSB().plug(this); +HID_::HID_(void) { } int HID_::begin(void) { diff --git a/testing/AbsoluteMouseReport.cpp b/testing/AbsoluteMouseReport.cpp index 33f9e485c8..1f5cd483b3 100644 --- a/testing/AbsoluteMouseReport.cpp +++ b/testing/AbsoluteMouseReport.cpp @@ -19,8 +19,8 @@ #include // for memcpy #include // for vector -#include "MouseButtons.h" // for MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_NEXT, MOUSE_PREV, MOUS... -#include "kaleidoscope/Runtime.h" // for Runtime, Runtime_ +#include "kaleidoscope/MouseButtons.h" // for MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_NEXT, MOUSE_PREV, MOUS... +#include "kaleidoscope/Runtime.h" // for Runtime, Runtime_ namespace kaleidoscope { namespace testing { diff --git a/testing/AbsoluteMouseReport.h b/testing/AbsoluteMouseReport.h index cc204aa346..dec5298485 100644 --- a/testing/AbsoluteMouseReport.h +++ b/testing/AbsoluteMouseReport.h @@ -19,8 +19,8 @@ #include // for uint16_t, uint32_t, uint8_t, int8_t #include // for vector -#include "DeviceAPIs/AbsoluteMouseAPI.h" // for HID_MouseAbsoluteReport_Data_t -#include "HID-Settings.h" // for HID_REPORTID_MOUSE_ABSOLUTE +#include "kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h" // for HID_MouseAbsoluteReport_Data_t +#include "HID-Settings.h" // for HID_REPORTID_MOUSE_ABSOLUTE namespace kaleidoscope { namespace testing { diff --git a/testing/MouseReport.h b/testing/MouseReport.h index aa0f9333ed..34825eaa18 100644 --- a/testing/MouseReport.h +++ b/testing/MouseReport.h @@ -18,9 +18,9 @@ #include // for uint8_t, int8_t, uint32_t -#include "HID-Settings.h" // for HID_REPORTID_MOUSE -#include "MouseButtons.h" // for MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_NEXT, MOUSE_PREV, MOUSE_R... -#include "MultiReport/Mouse.h" // for HID_MouseReport_Data_t +#include "HID-Settings.h" // for HID_REPORTID_MOUSE +#include "kaleidoscope/MouseButtons.h" // for MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_NEXT, MOUSE_PREV, MOUSE_R... +#include "kaleidoscope/driver/hid/apis/MouseAPI.h" // for HID_MouseReport_Data_t namespace kaleidoscope { namespace testing { From 5439499828a93bb4aa6534893530a48f021eb678 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 7 Feb 2024 15:55:08 -0600 Subject: [PATCH 13/22] tweak formatting to shut up clang-format-15 Slight behavior change, but it's not a problem if we report a smaller endpoint size to the host than we've allocated for endpoint buffer RAM. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HIDD.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/HIDD.cpp b/plugins/KeyboardioHID/src/HIDD.cpp index f7799e8318..4c7c519b1a 100644 --- a/plugins/KeyboardioHID/src/HIDD.cpp +++ b/plugins/KeyboardioHID/src/HIDD.cpp @@ -54,23 +54,17 @@ HIDD::HIDD( /* PluggableUSB implementation: interface, etc. descriptors for config */ int HIDD::getInterface(uint8_t *interfaceCount) { uint8_t itfSubClass; + if (itfProtocol != HID_ITF_PROTOCOL_NONE) { itfSubClass = HID_SUBCLASS_BOOT; } else { itfSubClass = HID_SUBCLASS_NONE; } - uint8_t epSize; -#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES - epSize = inReportLen; -#else - epSize = USB_EP_SIZE; -#endif - HIDDescriptor descSet = { D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, itfSubClass, itfProtocol), D_HIDREPORT(descriptorSize), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, epSize, interval), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, inReportLen, interval), }; *interfaceCount += 1; return USB_SendControl(0, &descSet, sizeof(descSet)); From dec5c2937af7f6159b113afdd42942d740b4f519 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 7 Feb 2024 18:05:35 -0600 Subject: [PATCH 14/22] BootKeyboardAPI Signed-off-by: Taylor Yu --- .../src/BootKeyboard/BootKeyboard.cpp | 241 +-------------- .../src/BootKeyboard/BootKeyboard.h | 172 +---------- .../driver/hid/apis/BootKeyboardAPI.h | 218 ++++++++++++++ .../driver/hid/apis/BootKeyboardAPI.hpp | 278 ++++++++++++++++++ 4 files changed, 509 insertions(+), 400 deletions(-) create mode 100644 src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h create mode 100644 src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 71205667b8..dc1f9acea0 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -37,32 +37,17 @@ static const uint8_t hybrid_keyboard_hid_descriptor_[] PROGMEM = { }; BootKeyboard_::BootKeyboard_(uint8_t bootkb_only_) - : bootkb_only(bootkb_only_) { + : BootKeyboardAPI(bootkb_only_) { itfProtocol = HID_PROTOCOL_KEYBOARD; setBootOnly(bootkb_only); plug(); } - -void BootKeyboard_::begin() { -} - - -void BootKeyboard_::end() { - releaseAll(); - sendReport(); -} - - uint8_t BootKeyboard_::getLeds() { return outReport[0]; } -uint8_t BootKeyboard_::getBootOnly() { - return bootkb_only; -} - /* * Set whether to send only Boot Protocol regardless of whether Boot * Protocol has been requested. Used by USBQuirks to toggle protocol @@ -73,8 +58,8 @@ uint8_t BootKeyboard_::getBootOnly() { * expects, and the host probably won't see the new Report Descriptor * until after a re-attach. */ -void BootKeyboard_::setBootOnly(uint8_t bootonly) { - bootkb_only = bootonly; + +void BootKeyboard_::setReportDescriptor(uint8_t bootkb_only) { if (bootkb_only) { reportDesc = boot_keyboard_hid_descriptor_; descriptorSize = sizeof(boot_keyboard_hid_descriptor_); @@ -84,223 +69,9 @@ void BootKeyboard_::setBootOnly(uint8_t bootonly) { } } - -void BootKeyboard_::convertReport(uint8_t *boot, const uint8_t *nkro) { - uint8_t n_boot_keys = 0; - uint8_t b; - // Convert NKRO report to boot report - memset(boot, HID_KEYBOARD_NO_EVENT, BOOT_KEY_BYTES); - for (uint8_t i = 0; i < NKRO_KEY_BYTES; i++) { - b = nkro[i]; - if (b == 0) { - continue; - } - for (uint8_t j = 0; j < 8; j++) { - bool bit = b & 1; - b >>= 1; - if (bit == 0) { - continue; - } - // Check is here so we can set all BOOT_KEY_BYTES - if (n_boot_keys >= BOOT_KEY_BYTES) { - // Send rollover error if too many keys are held - memset(boot, HID_KEYBOARD_ERROR_ROLLOVER, BOOT_KEY_BYTES); - return; - } - boot[n_boot_keys++] = 8 * i + j; - } - } -} - -/* Send a report without the extra modifier change handling */ -int BootKeyboard_::sendReportUnchecked() { - HID_BootKeyboardReport_Data_t out_report; - out_report.modifiers = last_report_.modifiers; - out_report.reserved = 0; - memcpy(out_report.nkro_keys, last_report_.keys, sizeof(last_report_.keys)); - convertReport(out_report.boot_keycodes, out_report.nkro_keys); - size_t reportlen; - // Send only boot report if host requested boot protocol, or if configured as boot-only - if (protocol == HID_BOOT_PROTOCOL || bootkb_only) { - reportlen = BOOT_REPORT_LEN; - } else { - reportlen = sizeof(out_report); - } - int returnCode = SendReport(0, &out_report, reportlen); - HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &out_report, reportlen, returnCode); - return returnCode; -} - -// Sending the current HID report to the host: -// -// Depending on the differences between the current and previous HID reports, we -// might need to send one or two extra reports to guarantee that the host will -// process the changes in the correct order. There are two important scenarios -// to consider: -// -// 1. If a non-modifier keycode toggles off in the same report as a modifier -// changes, the host might process the modifier change first. For example, if -// both `shift` and `4` toggle off in the same report (most likely from a -// `LSHIFT(Key_4)` key being released), and that key has been held long enough -// to trigger character repeat, we could end up with a plain `4` in the output -// at the end of the repeat: `$$$$4` instead of `$$$$$`. -// -// 2. If a non-modifier keycode toggles on in the same report as a modifier -// changes, the host might process the non-modifer first. For example, pressing -// and holding an `LSHIFT(Key_4)` key might result in `4$$$` rather than `$$$$`. -// -// Therefore, each call to `sendReport()` must send (up to) three reports to the -// host to guarantee the correct order of processing: -// -// 1. A report with toggled-off non-modifiers removed. -// 2. A report with changes to modifiers. -// 3. A report with toggled-on non-modifiers added. - -int BootKeyboard_::sendReport() { - // If the new HID report differs from the previous one both in active modifier - // keycodes and non-modifier keycodes, we will need to send at least one extra - // report. First, we compare the modifiers bytes of the two reports. - const uint8_t old_modifiers = last_report_.modifiers; - const uint8_t new_modifiers = report_.modifiers; - - const uint8_t changed_modifiers = old_modifiers ^ new_modifiers; - - if (changed_modifiers != 0) { - // There was at least one modifier change (toggled on or off), remove any - // non-modifiers from the stored previous report that toggled off in the new - // report, and send it to the host. - bool non_modifiers_toggled_off = false; - for (uint8_t i = 0; i < NKRO_KEY_BYTES; ++i) { - byte released_keycodes = last_report_.keys[i] & ~(report_.keys[i]); - if (released_keycodes != 0) { - last_report_.keys[i] &= ~released_keycodes; - non_modifiers_toggled_off = true; - } - } - if (non_modifiers_toggled_off) { - sendReportUnchecked(); - } - // Next, update the modifiers byte of the stored previous report, and send - // it. - last_report_.modifiers = new_modifiers; - sendReportUnchecked(); - } - - // Finally, copy the new report to the previous one, and send it. - if (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)) != 0) { - memcpy(last_report_.keys, report_.keys, sizeof(report_.keys)); - return sendReportUnchecked(); - } - // A note on return values: Kaleidoscope doesn't actually check the return - // value of `sendReport()`, so this function could be changed to return - // void. It would be nice if we could do something to recover from an error - // here, but it's not at all clear what that should be. Also note that if the - // extra reports above return an error, there's not much we can do to try to - // recover. We could try to send the report again, but that would be likely to - // fail as well. - return -1; -} - -/* Returns true if the modifer key passed in will be sent during this key report - * Returns false in all other cases - * */ -bool BootKeyboard_::isModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(report_.modifiers & (1 << k)); - } - return false; -} - -/* Returns true if the modifer key passed in was being sent during the previous key report - * Returns false in all other cases - * */ -bool BootKeyboard_::wasModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(last_report_.modifiers & (1 << k)); - } - return false; -} - -/* Returns true if *any* modifier will be sent during this key report - * Returns false in all other cases - * */ -bool BootKeyboard_::isAnyModifierActive() { - return report_.modifiers > 0; -} - -/* Returns true if *any* modifier was being sent during the previous key report - * Returns false in all other cases - * */ -bool BootKeyboard_::wasAnyModifierActive() { - return last_report_.modifiers > 0; -} - - -/* Returns true if the non-modifier key passed in will be sent during this key report - * Returns false in all other cases - * */ -bool BootKeyboard_::isKeyPressed(uint8_t k) { - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (uint8_t(k) % 8); - return !!(report_.keys[k / 8] & bit); - } - return false; -} - -/* Returns true if the non-modifer key passed in was sent during the previous key report - * Returns false in all other cases - * */ -bool BootKeyboard_::wasKeyPressed(uint8_t k) { - - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (uint8_t(k) % 8); - return !!(last_report_.keys[k / 8] & bit); - } - return false; -} - - -size_t BootKeyboard_::press(uint8_t k) { - // If the key is in the range of 'printable' keys - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (uint8_t(k) % 8); - report_.keys[k / 8] |= bit; - return 1; - } else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // It's a modifier key - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - report_.modifiers |= (1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; -} - -size_t BootKeyboard_::release(uint8_t k) { - // If we're releasing a printable key - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (k % 8); - report_.keys[k / 8] &= ~bit; - return 1; - } else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // It's a modifier key - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - report_.modifiers &= ~(1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; -} - -void BootKeyboard_::releaseAll() { - // Release all keys - memset(&report_.allkeys, 0x00, sizeof(report_.allkeys)); +int BootKeyboard_::SendReport(const void *data, int len) { + int returnCode = HIDD::SendReport(0, data, len); + HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, data, len, returnCode); } /* diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 6277c8c3f1..f223b831a7 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -27,188 +27,30 @@ THE SOFTWARE. #pragma once #include +#include "kaleidoscope/driver/hid/apis/BootKeyboardAPI.h" #include "HID.h" #include "HIDD.h" #include "HIDTables.h" #include "HIDAliases.h" -// Declare the hybrid boot keyboard feature so Kaleidoscope can depend on it -#define BOOTKB_HYBRID 1 -#define BOOT_KEY_BYTES 6 -#define BOOT_REPORT_LEN 8 - -#define NKRO_KEY_BITS (4 + HID_LAST_KEY - HID_KEYBOARD_A_AND_A + 1) -#define NKRO_KEY_BYTES ((NKRO_KEY_BITS + 7) / 8) - -// See Appendix B of USB HID spec -#define DESCRIPTOR_BOOT_KEYBOARD(...) \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - \ - /* Report ID, if any */ \ - __VA_ARGS__ \ - \ - /* LEDs */ \ - HID_REPORT_COUNT(8), \ - HID_REPORT_SIZE(1), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \ - HID_USAGE_MIN(1), \ - HID_USAGE_MAX(8), \ - HID_LOGICAL_MIN(0), \ - HID_LOGICAL_MAX(1), \ - HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - /* Modifiers */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ - HID_USAGE_MIN(HID_KEYBOARD_FIRST_MODIFIER), \ - HID_USAGE_MAX(HID_KEYBOARD_LAST_MODIFIER), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - /* Reserved byte */ \ - HID_REPORT_COUNT(1), \ - HID_REPORT_SIZE(8), \ - HID_INPUT(HID_CONSTANT), \ - \ - /* Non-modifiers */ \ - HID_REPORT_COUNT(BOOT_KEY_BYTES), \ - HID_LOGICAL_MAX_N(HID_LAST_KEY, 2), \ - HID_USAGE_MIN(HID_FIRST_KEY), \ - HID_USAGE_MAX(HID_LAST_KEY), \ - HID_INPUT(HID_DATA | HID_ARRAY | HID_ABSOLUTE), \ - \ - HID_COLLECTION_END - -// Padding to round up the report to byte boundary. -#if (NKRO_KEY_BITS % 8) -#define DESCRIPTOR_HYBRID_KEYBOARD_PADDING \ - HID_REPORT_COUNT(8 - (NKRO_KEY_BITS % 8)), \ - HID_INPUT(HID_CONSTANT), -#else -#define DESCRIPTOR_HYBRID_KEYBOARD_PADDING /* empty */ -#endif - -#define DESCRIPTOR_HYBRID_KEYBOARD(...) \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - \ - /* Report ID, if any */ \ - __VA_ARGS__ \ - \ - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \ - HID_USAGE_MIN(1), \ - HID_USAGE_MAX(8), \ - HID_LOGICAL_MIN(0), \ - HID_LOGICAL_MAX(1), \ - HID_REPORT_SIZE(1), \ - HID_REPORT_COUNT(8), \ - HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - /* Key modifier byte for both boot and NKRO */ \ - HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ - HID_USAGE_MIN(HID_KEYBOARD_FIRST_MODIFIER), \ - HID_USAGE_MAX(HID_KEYBOARD_LAST_MODIFIER), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - /* Send rest of boot report as padding, so HID-aware hosts will ignore */ \ - HID_REPORT_SIZE(8), \ - HID_REPORT_COUNT(7), \ - HID_INPUT(HID_CONSTANT), \ - \ - /* NKRO key bitmap */ \ - \ - /* Padding 4 bits, to skip NO_EVENT & 3 error states. */ \ - HID_REPORT_SIZE(1), \ - HID_REPORT_COUNT(4), \ - HID_INPUT(HID_CONSTANT), \ - \ - /* Actual non-modifier keys */ \ - HID_USAGE_MIN(HID_KEYBOARD_A_AND_A), \ - HID_USAGE_MAX(HID_LAST_KEY), \ - HID_REPORT_COUNT(NKRO_KEY_BITS - 4), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - /* Padding (if needed )*/ \ - DESCRIPTOR_HYBRID_KEYBOARD_PADDING \ - \ - HID_COLLECTION_END - -/* - * Keep the current key states in a NKRO bitmap. We'll convert it to Boot - * Protocol as needed. - */ -typedef union { - // Modifiers + keymap - struct { - uint8_t modifiers; - uint8_t keys[NKRO_KEY_BYTES]; - }; - uint8_t allkeys[1 + NKRO_KEY_BYTES]; -} HID_NKRO_KeyboardReport_Data_t; - -/* - * Hybrid boot report that contains the Boot Protocol report as a prefix to - * a bitmap NKRO report. The keycodes array of the Boot Report is marked as - * padding in the Report Descriptor, so HID-aware hosts will ignore it, but - * hosts that require Boot Protocol without requesting it have a chance of - * working, assuming they can deal with the extended report. - * - * We do send only the Boot Report if the host has requested Boot Protocol. - */ -typedef union { - // Hybrid report: boot keyboard report + NKRO report - struct { - // Boot/NKRO keyboard modifiers - uint8_t modifiers; - uint8_t reserved; - // Boot keyboard non-modifier keys array - uint8_t boot_keycodes[BOOT_KEY_BYTES]; - // NKRO keyboard non-modifiers keys bitmap - uint8_t nkro_keys[NKRO_KEY_BYTES]; - }; - uint8_t bytes[BOOT_REPORT_LEN + NKRO_KEY_BYTES]; -} HID_BootKeyboardReport_Data_t; - - -class BootKeyboard_ : public HIDD { +class BootKeyboard_ : public HIDD, public BootKeyboardAPI { public: /* * Change to `bootkb_only_ = 1` if you need to default to only sending * Boot Protocol, even if in Report Protocol. */ explicit BootKeyboard_(uint8_t bootkb_only_ = 0); - size_t press(uint8_t k); - void begin(); - void end(); - size_t release(uint8_t k); - void releaseAll(); - - int sendReport(); - - bool isModifierActive(uint8_t k); - bool wasModifierActive(uint8_t k); - bool isAnyModifierActive(); - bool wasAnyModifierActive(); - bool isKeyPressed(uint8_t k); - bool wasKeyPressed(uint8_t k); uint8_t getLeds(); - uint8_t getBootOnly(); - void setBootOnly(uint8_t bootonly); - void onUSBReset(); + uint8_t getProtocol() override { + return protocol; + } protected: - HID_NKRO_KeyboardReport_Data_t report_, last_report_; - - uint8_t bootkb_only; - - private: - void convertReport(uint8_t *boot, const uint8_t *nkro); - int sendReportUnchecked(); + int SendReport(const void *data, int len) override; + void setReportDescriptor(uint8_t bootkb_only) override; }; extern BootKeyboard_ &BootKeyboard(); diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h new file mode 100644 index 0000000000..5b88e0a78c --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h @@ -0,0 +1,218 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +#include +#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/HIDTables.h" +#include "HIDAliases.h" + +// Declare the hybrid boot keyboard feature so Kaleidoscope can depend on it +#define BOOTKB_HYBRID 1 + +#define BOOT_KEY_BYTES 6 +#define BOOT_REPORT_LEN 8 + +#define NKRO_KEY_BITS (4 + HID_LAST_KEY - HID_KEYBOARD_A_AND_A + 1) +#define NKRO_KEY_BYTES ((NKRO_KEY_BITS + 7) / 8) + +// See Appendix B of USB HID spec +#define DESCRIPTOR_BOOT_KEYBOARD(...) \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + \ + /* Report ID, if any */ \ + __VA_ARGS__ \ + \ + /* LEDs */ \ + HID_REPORT_COUNT(8), \ + HID_REPORT_SIZE(1), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \ + HID_USAGE_MIN(1), \ + HID_USAGE_MAX(8), \ + HID_LOGICAL_MIN(0), \ + HID_LOGICAL_MAX(1), \ + HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + /* Modifiers */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ + HID_USAGE_MIN(HID_KEYBOARD_FIRST_MODIFIER), \ + HID_USAGE_MAX(HID_KEYBOARD_LAST_MODIFIER), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + /* Reserved byte */ \ + HID_REPORT_COUNT(1), \ + HID_REPORT_SIZE(8), \ + HID_INPUT(HID_CONSTANT), \ + \ + /* Non-modifiers */ \ + HID_REPORT_COUNT(BOOT_KEY_BYTES), \ + HID_LOGICAL_MAX_N(HID_LAST_KEY, 2), \ + HID_USAGE_MIN(HID_FIRST_KEY), \ + HID_USAGE_MAX(HID_LAST_KEY), \ + HID_INPUT(HID_DATA | HID_ARRAY | HID_ABSOLUTE), \ + \ + HID_COLLECTION_END + +// Padding to round up the report to byte boundary. +#if (NKRO_KEY_BITS % 8) +#define DESCRIPTOR_HYBRID_KEYBOARD_PADDING \ + HID_REPORT_COUNT(8 - (NKRO_KEY_BITS % 8)), \ + HID_INPUT(HID_CONSTANT), +#else +#define DESCRIPTOR_HYBRID_KEYBOARD_PADDING /* empty */ +#endif + +#define DESCRIPTOR_HYBRID_KEYBOARD(...) \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + \ + /* Report ID, if any */ \ + __VA_ARGS__ \ + \ + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \ + HID_USAGE_MIN(1), \ + HID_USAGE_MAX(8), \ + HID_LOGICAL_MIN(0), \ + HID_LOGICAL_MAX(1), \ + HID_REPORT_SIZE(1), \ + HID_REPORT_COUNT(8), \ + HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + /* Key modifier byte for both boot and NKRO */ \ + HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ + HID_USAGE_MIN(HID_KEYBOARD_FIRST_MODIFIER), \ + HID_USAGE_MAX(HID_KEYBOARD_LAST_MODIFIER), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + /* Send rest of boot report as padding, so HID-aware hosts will ignore */ \ + HID_REPORT_SIZE(8), \ + HID_REPORT_COUNT(7), \ + HID_INPUT(HID_CONSTANT), \ + \ + /* NKRO key bitmap */ \ + \ + /* Padding 4 bits, to skip NO_EVENT & 3 error states. */ \ + HID_REPORT_SIZE(1), \ + HID_REPORT_COUNT(4), \ + HID_INPUT(HID_CONSTANT), \ + \ + /* Actual non-modifier keys */ \ + HID_USAGE_MIN(HID_KEYBOARD_A_AND_A), \ + HID_USAGE_MAX(HID_LAST_KEY), \ + HID_REPORT_COUNT(NKRO_KEY_BITS - 4), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + /* Padding (if needed )*/ \ + DESCRIPTOR_HYBRID_KEYBOARD_PADDING \ + \ + HID_COLLECTION_END + +/* + * Keep the current key states in a NKRO bitmap. We'll convert it to Boot + * Protocol as needed. + */ +typedef union { + // Modifiers + keymap + struct { + uint8_t modifiers; + uint8_t keys[NKRO_KEY_BYTES]; + }; + uint8_t allkeys[1 + NKRO_KEY_BYTES]; +} HID_NKRO_KeyboardReport_Data_t; + +/* + * Hybrid boot report that contains the Boot Protocol report as a prefix to + * a bitmap NKRO report. The keycodes array of the Boot Report is marked as + * padding in the Report Descriptor, so HID-aware hosts will ignore it, but + * hosts that require Boot Protocol without requesting it have a chance of + * working, assuming they can deal with the extended report. + * + * We do send only the Boot Report if the host has requested Boot Protocol. + */ +typedef union { + // Hybrid report: boot keyboard report + NKRO report + struct { + // Boot/NKRO keyboard modifiers + uint8_t modifiers; + uint8_t reserved; + // Boot keyboard non-modifier keys array + uint8_t boot_keycodes[BOOT_KEY_BYTES]; + // NKRO keyboard non-modifiers keys bitmap + uint8_t nkro_keys[NKRO_KEY_BYTES]; + }; + uint8_t bytes[BOOT_REPORT_LEN + NKRO_KEY_BYTES]; +} HID_BootKeyboardReport_Data_t; + + +class BootKeyboardAPI { + public: + /* + * Change to `bootkb_only_ = 1` if you need to default to only sending + * Boot Protocol, even if in Report Protocol. + */ + inline explicit BootKeyboardAPI(uint8_t bootkb_only_ = 0); + inline size_t press(uint8_t k); + inline void begin(); + inline void end(); + inline size_t release(uint8_t k); + inline void releaseAll(); + + inline int sendReport(); + + inline bool isModifierActive(uint8_t k); + inline bool wasModifierActive(uint8_t k); + inline bool isAnyModifierActive(); + inline bool wasAnyModifierActive(); + inline bool isKeyPressed(uint8_t k); + inline bool wasKeyPressed(uint8_t k); + + virtual uint8_t getLeds() = 0; + + inline uint8_t getBootOnly(); + inline void setBootOnly(uint8_t bootonly); + + virtual void onUSBReset() = 0; + + protected: + virtual int SendReport(const void *data, int len) = 0; + virtual void setReportDescriptor(uint8_t bootkb_only) = 0; + virtual uint8_t getProtocol() = 0; + + HID_NKRO_KeyboardReport_Data_t report_, last_report_; + + uint8_t bootkb_only; + + private: + inline void convertReport(uint8_t *boot, const uint8_t *nkro); + inline int sendReportUnchecked(); +}; + +#include "BootKeyboardAPI.hpp" diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp new file mode 100644 index 0000000000..91173ca113 --- /dev/null +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp @@ -0,0 +1,278 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once + +BootKeyboardAPI::BootKeyboardAPI(uint8_t bootkb_only_) + : bootkb_only(bootkb_only_) { +} + + +void BootKeyboardAPI::begin() { +} + + +void BootKeyboardAPI::end() { + releaseAll(); + sendReport(); +} + + +uint8_t BootKeyboardAPI::getBootOnly() { + return bootkb_only; +} + +/* + * Set whether to send only Boot Protocol regardless of whether Boot + * Protocol has been requested. Used by USBQuirks to toggle protocol + * modes. + * + * This is only really safe to call after detaching from USB, because + * otherwise, the report format might get out of sync with what the host + * expects, and the host probably won't see the new Report Descriptor + * until after a re-attach. + */ +void BootKeyboardAPI::setBootOnly(uint8_t bootonly) { + bootkb_only = bootonly; + setReportDescriptor(bootkb_only); +} + + +void BootKeyboardAPI::convertReport(uint8_t *boot, const uint8_t *nkro) { + uint8_t n_boot_keys = 0; + uint8_t b; + // Convert NKRO report to boot report + memset(boot, HID_KEYBOARD_NO_EVENT, BOOT_KEY_BYTES); + for (uint8_t i = 0; i < NKRO_KEY_BYTES; i++) { + b = nkro[i]; + if (b == 0) { + continue; + } + for (uint8_t j = 0; j < 8; j++) { + bool bit = b & 1; + b >>= 1; + if (bit == 0) { + continue; + } + // Check is here so we can set all BOOT_KEY_BYTES + if (n_boot_keys >= BOOT_KEY_BYTES) { + // Send rollover error if too many keys are held + memset(boot, HID_KEYBOARD_ERROR_ROLLOVER, BOOT_KEY_BYTES); + return; + } + boot[n_boot_keys++] = 8 * i + j; + } + } +} + +/* Send a report without the extra modifier change handling */ +int BootKeyboardAPI::sendReportUnchecked() { + HID_BootKeyboardReport_Data_t out_report; + out_report.modifiers = last_report_.modifiers; + out_report.reserved = 0; + memcpy(out_report.nkro_keys, last_report_.keys, sizeof(last_report_.keys)); + convertReport(out_report.boot_keycodes, out_report.nkro_keys); + size_t reportlen; + // Send only boot report if host requested boot protocol, or if configured as boot-only + if (getProtocol() == HID_BOOT_PROTOCOL || bootkb_only) { + reportlen = BOOT_REPORT_LEN; + } else { + reportlen = sizeof(out_report); + } + int returnCode = SendReport(&out_report, reportlen); + return returnCode; +} + +// Sending the current HID report to the host: +// +// Depending on the differences between the current and previous HID reports, we +// might need to send one or two extra reports to guarantee that the host will +// process the changes in the correct order. There are two important scenarios +// to consider: +// +// 1. If a non-modifier keycode toggles off in the same report as a modifier +// changes, the host might process the modifier change first. For example, if +// both `shift` and `4` toggle off in the same report (most likely from a +// `LSHIFT(Key_4)` key being released), and that key has been held long enough +// to trigger character repeat, we could end up with a plain `4` in the output +// at the end of the repeat: `$$$$4` instead of `$$$$$`. +// +// 2. If a non-modifier keycode toggles on in the same report as a modifier +// changes, the host might process the non-modifer first. For example, pressing +// and holding an `LSHIFT(Key_4)` key might result in `4$$$` rather than `$$$$`. +// +// Therefore, each call to `sendReport()` must send (up to) three reports to the +// host to guarantee the correct order of processing: +// +// 1. A report with toggled-off non-modifiers removed. +// 2. A report with changes to modifiers. +// 3. A report with toggled-on non-modifiers added. + +int BootKeyboardAPI::sendReport() { + // If the new HID report differs from the previous one both in active modifier + // keycodes and non-modifier keycodes, we will need to send at least one extra + // report. First, we compare the modifiers bytes of the two reports. + const uint8_t old_modifiers = last_report_.modifiers; + const uint8_t new_modifiers = report_.modifiers; + + const uint8_t changed_modifiers = old_modifiers ^ new_modifiers; + + if (changed_modifiers != 0) { + // There was at least one modifier change (toggled on or off), remove any + // non-modifiers from the stored previous report that toggled off in the new + // report, and send it to the host. + bool non_modifiers_toggled_off = false; + for (uint8_t i = 0; i < NKRO_KEY_BYTES; ++i) { + byte released_keycodes = last_report_.keys[i] & ~(report_.keys[i]); + if (released_keycodes != 0) { + last_report_.keys[i] &= ~released_keycodes; + non_modifiers_toggled_off = true; + } + } + if (non_modifiers_toggled_off) { + sendReportUnchecked(); + } + // Next, update the modifiers byte of the stored previous report, and send + // it. + last_report_.modifiers = new_modifiers; + sendReportUnchecked(); + } + + // Finally, copy the new report to the previous one, and send it. + if (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)) != 0) { + memcpy(last_report_.keys, report_.keys, sizeof(report_.keys)); + return sendReportUnchecked(); + } + // A note on return values: Kaleidoscope doesn't actually check the return + // value of `sendReport()`, so this function could be changed to return + // void. It would be nice if we could do something to recover from an error + // here, but it's not at all clear what that should be. Also note that if the + // extra reports above return an error, there's not much we can do to try to + // recover. We could try to send the report again, but that would be likely to + // fail as well. + return -1; +} + +/* Returns true if the modifer key passed in will be sent during this key report + * Returns false in all other cases + * */ +bool BootKeyboardAPI::isModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(report_.modifiers & (1 << k)); + } + return false; +} + +/* Returns true if the modifer key passed in was being sent during the previous key report + * Returns false in all other cases + * */ +bool BootKeyboardAPI::wasModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(last_report_.modifiers & (1 << k)); + } + return false; +} + +/* Returns true if *any* modifier will be sent during this key report + * Returns false in all other cases + * */ +bool BootKeyboardAPI::isAnyModifierActive() { + return report_.modifiers > 0; +} + +/* Returns true if *any* modifier was being sent during the previous key report + * Returns false in all other cases + * */ +bool BootKeyboardAPI::wasAnyModifierActive() { + return last_report_.modifiers > 0; +} + + +/* Returns true if the non-modifier key passed in will be sent during this key report + * Returns false in all other cases + * */ +bool BootKeyboardAPI::isKeyPressed(uint8_t k) { + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !!(report_.keys[k / 8] & bit); + } + return false; +} + +/* Returns true if the non-modifer key passed in was sent during the previous key report + * Returns false in all other cases + * */ +bool BootKeyboardAPI::wasKeyPressed(uint8_t k) { + + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !!(last_report_.keys[k / 8] & bit); + } + return false; +} + + +size_t BootKeyboardAPI::press(uint8_t k) { + // If the key is in the range of 'printable' keys + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + report_.keys[k / 8] |= bit; + return 1; + } else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // It's a modifier key + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + report_.modifiers |= (1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; +} + +size_t BootKeyboardAPI::release(uint8_t k) { + // If we're releasing a printable key + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (k % 8); + report_.keys[k / 8] &= ~bit; + return 1; + } else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // It's a modifier key + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + report_.modifiers &= ~(1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; +} + +void BootKeyboardAPI::releaseAll() { + // Release all keys + memset(&report_.allkeys, 0x00, sizeof(report_.allkeys)); +} From 871bc7f6e5def50637a0e887bf2c58c5ceb676a9 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 7 Feb 2024 21:13:50 -0600 Subject: [PATCH 15/22] move HIDAliases.h Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 -- {plugins/KeyboardioHID/src => src/kaleidoscope}/HIDAliases.h | 0 src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) rename {plugins/KeyboardioHID/src => src/kaleidoscope}/HIDAliases.h (100%) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index f223b831a7..9d9ae383eb 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -30,8 +30,6 @@ THE SOFTWARE. #include "kaleidoscope/driver/hid/apis/BootKeyboardAPI.h" #include "HID.h" #include "HIDD.h" -#include "HIDTables.h" -#include "HIDAliases.h" class BootKeyboard_ : public HIDD, public BootKeyboardAPI { diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/src/kaleidoscope/HIDAliases.h similarity index 100% rename from plugins/KeyboardioHID/src/HIDAliases.h rename to src/kaleidoscope/HIDAliases.h diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h index 5b88e0a78c..7d52fe8b27 100644 --- a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include #include "kaleidoscope/HIDDefs.h" #include "kaleidoscope/HIDTables.h" -#include "HIDAliases.h" +#include "kaleidoscope/HIDAliases.h" // Declare the hybrid boot keyboard feature so Kaleidoscope can depend on it #define BOOTKB_HYBRID 1 From 3527988baa061867d8af594d6a19cbcd0c20ccc4 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 21 Feb 2024 16:22:46 -0600 Subject: [PATCH 16/22] use TinyUSB definitions for other KeyboardioHID constants Signed-off-by: Taylor Yu --- .../src/BootKeyboard/BootKeyboard.cpp | 4 ++-- plugins/KeyboardioHID/src/HID.cpp | 2 +- plugins/KeyboardioHID/src/HIDD.cpp | 18 +++++++-------- src/kaleidoscope/HIDDefs.h | 23 ------------------- .../driver/hid/apis/BootKeyboardAPI.hpp | 2 +- 5 files changed, 13 insertions(+), 36 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index dc1f9acea0..a2e9171bc8 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -39,7 +39,7 @@ static const uint8_t hybrid_keyboard_hid_descriptor_[] PROGMEM = { BootKeyboard_::BootKeyboard_(uint8_t bootkb_only_) : BootKeyboardAPI(bootkb_only_) { - itfProtocol = HID_PROTOCOL_KEYBOARD; + itfProtocol = HID_ITF_PROTOCOL_KEYBOARD; setBootOnly(bootkb_only); plug(); } @@ -81,7 +81,7 @@ int BootKeyboard_::SendReport(const void *data, int len) { * required by the HID specification. */ void BootKeyboard_::onUSBReset() { - protocol = HID_REPORT_PROTOCOL; + protocol = HID_PROTOCOL_REPORT; } __attribute__((weak)) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index e6b7fdb413..a7ec922e85 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -35,7 +35,7 @@ int HID_::getDescriptor(USBSetup &setup) { if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + if (setup.wValueH != HID_DESC_TYPE_REPORT) { return 0; } diff --git a/plugins/KeyboardioHID/src/HIDD.cpp b/plugins/KeyboardioHID/src/HIDD.cpp index 4c7c519b1a..bccd9d3a46 100644 --- a/plugins/KeyboardioHID/src/HIDD.cpp +++ b/plugins/KeyboardioHID/src/HIDD.cpp @@ -76,7 +76,7 @@ int HIDD::getDescriptor(USBSetup &setup) { if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + if (setup.wValueH != HID_DESC_TYPE_REPORT) { return 0; } @@ -98,12 +98,12 @@ bool HIDD::setup(USBSetup &setup) { uint8_t requestType = setup.bmRequestType; if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { + if (request == HID_REQ_CONTROL_GET_REPORT) { // TODO(anyone): HID_GetReport(); return true; } - if (request == HID_GET_PROTOCOL) { - if (itfProtocol == HID_PROTOCOL_NONE) { + if (request == HID_REQ_CONTROL_GET_PROTOCOL) { + if (itfProtocol == HID_ITF_PROTOCOL_NONE) { return false; } // AVR optimization; possibly not needed elsewhere @@ -116,7 +116,7 @@ bool HIDD::setup(USBSetup &setup) { #endif return true; } - if (request == HID_GET_IDLE) { + if (request == HID_REQ_CONTROL_GET_IDLE) { // AVR optimization; possibly not needed elsewhere #if defined(__AVR__) UEDATX = idle; @@ -130,18 +130,18 @@ bool HIDD::setup(USBSetup &setup) { } if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - if (itfProtocol == HID_PROTOCOL_NONE) { + if (request == HID_REQ_CONTROL_SET_PROTOCOL) { + if (itfProtocol == HID_ITF_PROTOCOL_NONE) { return false; } protocol = setup.wValueL; return true; } - if (request == HID_SET_IDLE) { + if (request == HID_REQ_CONTROL_SET_IDLE) { idle = setup.wValueL; return true; } - if (request == HID_SET_REPORT) { + if (request == HID_REQ_CONTROL_SET_REPORT) { // Check if data has the correct length afterwards int length = setup.wLength; diff --git a/src/kaleidoscope/HIDDefs.h b/src/kaleidoscope/HIDDefs.h index 08cbec435f..762d3f4777 100644 --- a/src/kaleidoscope/HIDDefs.h +++ b/src/kaleidoscope/HIDDefs.h @@ -19,26 +19,3 @@ #pragma once #include "tusb_hid.h" - -// HID 'Driver' -// ------------ -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - -// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols -#define HID_PROTOCOL_NONE 0 -#define HID_PROTOCOL_KEYBOARD 1 -#define HID_PROTOCOL_MOUSE 2 - -// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request -// "protocol" variable is used for this purpose. -#define HID_BOOT_PROTOCOL 0 -#define HID_REPORT_PROTOCOL 1 diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp index 91173ca113..03096cd8ae 100644 --- a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp @@ -96,7 +96,7 @@ int BootKeyboardAPI::sendReportUnchecked() { convertReport(out_report.boot_keycodes, out_report.nkro_keys); size_t reportlen; // Send only boot report if host requested boot protocol, or if configured as boot-only - if (getProtocol() == HID_BOOT_PROTOCOL || bootkb_only) { + if (getProtocol() == HID_PROTOCOL_BOOT || bootkb_only) { reportlen = BOOT_REPORT_LEN; } else { reportlen = sizeof(out_report); From 3708d860061ba743aee5ce7db81cb5e4d40ae3f2 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 21 Feb 2024 16:24:23 -0600 Subject: [PATCH 17/22] delete redundant inclusions of tusb_hid.h Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 1 - plugins/KeyboardioHID/src/MultiReport/Gamepad.h | 1 - 2 files changed, 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index a2e9171bc8..69fbd66bae 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -26,7 +26,6 @@ THE SOFTWARE. #include "BootKeyboard.h" #include "HIDReportObserver.h" #include "HID-Settings.h" -#include "tusb_hid.h" static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { DESCRIPTOR_BOOT_KEYBOARD(), diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 17d02b4263..4bf0e9c29c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include #include "HID.h" #include "HID-Settings.h" -#include "tusb_hid.h" // Dpad directions #define GAMEPAD_DPAD_CENTERED 0 From e71807f9a3fcf29b47f5a37312b633d8034d7e0c Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 22 Feb 2024 10:12:39 -0600 Subject: [PATCH 18/22] move HIDDefs.h to driver/hid Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HID.h | 2 +- plugins/KeyboardioHID/src/HIDD.h | 2 +- src/kaleidoscope/{ => driver/hid}/HIDDefs.h | 0 src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/MouseAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/SystemControlAPI.h | 2 +- 8 files changed, 7 insertions(+), 7 deletions(-) rename src/kaleidoscope/{ => driver/hid}/HIDDefs.h (100%) diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index a3253f7480..302598f430 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -21,7 +21,7 @@ #include #include -#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/driver/hid/HIDDefs.h" #include "HIDD.h" #include "HID-Settings.h" diff --git a/plugins/KeyboardioHID/src/HIDD.h b/plugins/KeyboardioHID/src/HIDD.h index 6f18347054..836c2c79de 100644 --- a/plugins/KeyboardioHID/src/HIDD.h +++ b/plugins/KeyboardioHID/src/HIDD.h @@ -31,7 +31,7 @@ THE SOFTWARE. #include #include "HIDArch.h" /* unfortunately needed for EPTYPE_DESCRIPTOR_SIZE */ -#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/driver/hid/HIDDefs.h" /* Maximum length of output report sent by host */ #define HIDD_MAX_OUTPUT_REPORT 2 diff --git a/src/kaleidoscope/HIDDefs.h b/src/kaleidoscope/driver/hid/HIDDefs.h similarity index 100% rename from src/kaleidoscope/HIDDefs.h rename to src/kaleidoscope/driver/hid/HIDDefs.h diff --git a/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h b/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h index cf7180fd5c..6c5c199089 100644 --- a/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h +++ b/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once #include -#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/driver/hid/HIDDefs.h" #include "kaleidoscope/MouseButtons.h" #define DESCRIPTOR_ABSOLUTE_MOUSE(...) \ diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h index 7d52fe8b27..037cfcef81 100644 --- a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once #include -#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/driver/hid/HIDDefs.h" #include "kaleidoscope/HIDTables.h" #include "kaleidoscope/HIDAliases.h" diff --git a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h index 3db5611aa3..f0993d8054 100644 --- a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h +++ b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once #include -#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/driver/hid/HIDDefs.h" #define DESCRIPTOR_CONSUMER_CONTROL(...) \ HID_USAGE_PAGE(HID_USAGE_PAGE_CONSUMER), \ diff --git a/src/kaleidoscope/driver/hid/apis/MouseAPI.h b/src/kaleidoscope/driver/hid/apis/MouseAPI.h index 7cff39ced5..37601097d1 100644 --- a/src/kaleidoscope/driver/hid/apis/MouseAPI.h +++ b/src/kaleidoscope/driver/hid/apis/MouseAPI.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once #include -#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/driver/hid/HIDDefs.h" #include "kaleidoscope/MouseButtons.h" #define DESCRIPTOR_MOUSE(...) \ diff --git a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h index 17b427e009..fd5bb8d28f 100644 --- a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h +++ b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h @@ -26,7 +26,7 @@ THE SOFTWARE. // Include guard #pragma once -#include "kaleidoscope/HIDDefs.h" +#include "kaleidoscope/driver/hid/HIDDefs.h" #define DESCRIPTOR_SYSTEM_CONTROL(...) \ /* TODO(anyone) limit to system keys only? */ \ From b5a763096f175aed556fb5796236c03c5db97016 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 22 Feb 2024 10:14:29 -0600 Subject: [PATCH 19/22] replace copyright on HIDDefs.h There are no remaining lines from the Arduino original. Signed-off-by: Taylor Yu --- src/kaleidoscope/driver/hid/HIDDefs.h | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/kaleidoscope/driver/hid/HIDDefs.h b/src/kaleidoscope/driver/hid/HIDDefs.h index 762d3f4777..a3f31de0d0 100644 --- a/src/kaleidoscope/driver/hid/HIDDefs.h +++ b/src/kaleidoscope/driver/hid/HIDDefs.h @@ -1,19 +1,18 @@ -/* - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett - - Permission to use, copy, modify, and/or distribute this software for - any purpose with or without fee is hereby granted, provided that the - above copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR - BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES - OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - SOFTWARE. +// -*- mode: c++ -*- +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2024 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ #pragma once From 36e856648dcbc1d929a365772e3f99475198997a Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 23 Feb 2024 10:39:44 -0600 Subject: [PATCH 20/22] update copyrights Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HID.cpp | 1 + plugins/KeyboardioHID/src/HIDArch.h | 2 +- plugins/KeyboardioHID/src/HIDD.cpp | 2 +- plugins/KeyboardioHID/src/HIDD.h | 2 +- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 2 +- src/kaleidoscope/device/virtual/VirtualHID.cpp | 1 + src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp | 2 +- src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp | 2 +- src/kaleidoscope/driver/hid/apis/MouseAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/MouseAPI.hpp | 2 +- src/kaleidoscope/driver/hid/apis/SystemControlAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp | 2 +- testing/AbsoluteMouseReport.cpp | 1 + testing/AbsoluteMouseReport.h | 1 + testing/MouseReport.h | 1 + 18 files changed, 18 insertions(+), 13 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index a7ec922e85..a64d0f925f 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -1,5 +1,6 @@ /* Copyright (c) 2015, Arduino LLC + Copyright (c) 2024 Keyboard.io, Inc Original code (pre-library): Copyright (c) 2011, Peter Barrett Permission to use, copy, modify, and/or distribute this software for diff --git a/plugins/KeyboardioHID/src/HIDArch.h b/plugins/KeyboardioHID/src/HIDArch.h index f44315a0d0..ab972db4a6 100644 --- a/plugins/KeyboardioHID/src/HIDArch.h +++ b/plugins/KeyboardioHID/src/HIDArch.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/plugins/KeyboardioHID/src/HIDD.cpp b/plugins/KeyboardioHID/src/HIDD.cpp index bccd9d3a46..5edafa8c70 100644 --- a/plugins/KeyboardioHID/src/HIDD.cpp +++ b/plugins/KeyboardioHID/src/HIDD.cpp @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/plugins/KeyboardioHID/src/HIDD.h b/plugins/KeyboardioHID/src/HIDD.h index 836c2c79de..1e9cef1fab 100644 --- a/plugins/KeyboardioHID/src/HIDD.h +++ b/plugins/KeyboardioHID/src/HIDD.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 73bb9c99d3..bcf4ae08e5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/device/virtual/VirtualHID.cpp b/src/kaleidoscope/device/virtual/VirtualHID.cpp index 2dcc469490..5cc08dacf0 100644 --- a/src/kaleidoscope/device/virtual/VirtualHID.cpp +++ b/src/kaleidoscope/device/virtual/VirtualHID.cpp @@ -1,5 +1,6 @@ /* Copyright (c) 2015, Arduino LLC + Copyright (C) 2024 Keyboard.io, Inc Original code (pre-library): Copyright (c) 2011, Peter Barrett Permission to use, copy, modify, and/or distribute this software for diff --git a/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h b/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h index 6c5c199089..07427a21e8 100644 --- a/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h +++ b/src/kaleidoscope/driver/hid/apis/AbsoluteMouseAPI.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h index 037cfcef81..bcf742d8fd 100644 --- a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp index 03096cd8ae..53a41fcab6 100644 --- a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h index f0993d8054..82cda5a65f 100644 --- a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h +++ b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp index 0dd6909c8d..155c8d2edc 100644 --- a/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp +++ b/src/kaleidoscope/driver/hid/apis/ConsumerControlAPI.hpp @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/MouseAPI.h b/src/kaleidoscope/driver/hid/apis/MouseAPI.h index 37601097d1..d4958e9874 100644 --- a/src/kaleidoscope/driver/hid/apis/MouseAPI.h +++ b/src/kaleidoscope/driver/hid/apis/MouseAPI.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/MouseAPI.hpp b/src/kaleidoscope/driver/hid/apis/MouseAPI.hpp index ba8f4dbf7d..6e256ffb94 100644 --- a/src/kaleidoscope/driver/hid/apis/MouseAPI.hpp +++ b/src/kaleidoscope/driver/hid/apis/MouseAPI.hpp @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h index fd5bb8d28f..9077e136b9 100644 --- a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h +++ b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.h @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp index dda584eadd..90d1dccd09 100644 --- a/src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp +++ b/src/kaleidoscope/driver/hid/apis/SystemControlAPI.hpp @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2015 NicoHood -Copyright (c) 2015-2018 Keyboard.io, Inc +Copyright (c) 2015-2024 Keyboard.io, Inc See the readme for credit to other people. diff --git a/testing/AbsoluteMouseReport.cpp b/testing/AbsoluteMouseReport.cpp index 1f5cd483b3..8edcaf3e59 100644 --- a/testing/AbsoluteMouseReport.cpp +++ b/testing/AbsoluteMouseReport.cpp @@ -1,5 +1,6 @@ /* -*- mode: c++ -*- * Copyright (C) 2020 Eric Paniagua (epaniagua@google.com) + * Copyright (C) 2024 Keyboard.io, Inc * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software diff --git a/testing/AbsoluteMouseReport.h b/testing/AbsoluteMouseReport.h index dec5298485..591d851edf 100644 --- a/testing/AbsoluteMouseReport.h +++ b/testing/AbsoluteMouseReport.h @@ -1,5 +1,6 @@ /* -*- mode: c++ -*- * Copyright (C) 2020 Eric Paniagua (epaniagua@google.com) + * Copyright (C) 2024 Keyboard.io, Inc * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software diff --git a/testing/MouseReport.h b/testing/MouseReport.h index 34825eaa18..31e12cf2e0 100644 --- a/testing/MouseReport.h +++ b/testing/MouseReport.h @@ -1,5 +1,6 @@ /* -*- mode: c++ -*- * Copyright (C) 2020 Eric Paniagua (epaniagua@google.com) + * Copyright (C) 2024 Keyboard.io, Inc * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software From 950eb606be6d262d8e64ea0e045bf1ae65d87c42 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 23 Feb 2024 10:44:42 -0600 Subject: [PATCH 21/22] clarify HIDD::SendReport call Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 9e2eadd92e..99a06e219d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -41,7 +41,7 @@ SingleAbsoluteMouse_::SingleAbsoluteMouse_() } void SingleAbsoluteMouse_::sendReport(void *data, int length) { - auto result = SendReport(0, data, length); + auto result = HIDD::SendReport(0, data, length); HIDReportObserver::observeReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length, result); } From 78feb867215bf906cbde99c5b41522a1e18b0ab2 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Mon, 26 Feb 2024 14:14:31 -0600 Subject: [PATCH 22/22] clarify BootKeyboard SendReport Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h | 2 +- src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 69fbd66bae..15277220e2 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -68,7 +68,7 @@ void BootKeyboard_::setReportDescriptor(uint8_t bootkb_only) { } } -int BootKeyboard_::SendReport(const void *data, int len) { +int BootKeyboard_::SendHIDReport(const void *data, int len) { int returnCode = HIDD::SendReport(0, data, len); HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, data, len, returnCode); } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 9d9ae383eb..8ccd780186 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -48,7 +48,7 @@ class BootKeyboard_ : public HIDD, public BootKeyboardAPI { } protected: - int SendReport(const void *data, int len) override; + int SendHIDReport(const void *data, int len) override; void setReportDescriptor(uint8_t bootkb_only) override; }; extern BootKeyboard_ &BootKeyboard(); diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h index bcf742d8fd..d2b1a835de 100644 --- a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.h @@ -202,7 +202,7 @@ class BootKeyboardAPI { virtual void onUSBReset() = 0; protected: - virtual int SendReport(const void *data, int len) = 0; + virtual int SendHIDReport(const void *data, int len) = 0; virtual void setReportDescriptor(uint8_t bootkb_only) = 0; virtual uint8_t getProtocol() = 0; diff --git a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp index 53a41fcab6..4b67d120b9 100644 --- a/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp +++ b/src/kaleidoscope/driver/hid/apis/BootKeyboardAPI.hpp @@ -101,7 +101,7 @@ int BootKeyboardAPI::sendReportUnchecked() { } else { reportlen = sizeof(out_report); } - int returnCode = SendReport(&out_report, reportlen); + int returnCode = SendHIDReport(&out_report, reportlen); return returnCode; }