From c65dc6680e03d3174ce2ad0ca6b96e3c4c77bb21 Mon Sep 17 00:00:00 2001 From: tobozo Date: Fri, 3 Nov 2023 12:49:45 +0100 Subject: [PATCH 1/2] Added absolute mouse support --- libraries/USB/src/USBHIDMouse.cpp | 123 ++++++++++++++++++++++------- libraries/USB/src/USBHIDMouse.h | 64 ++++++++++++--- libraries/USB/src/tusb_hid_mouse.h | 98 +++++++++++++++++++++++ 3 files changed, 245 insertions(+), 40 deletions(-) create mode 100644 libraries/USB/src/tusb_hid_mouse.h diff --git a/libraries/USB/src/USBHIDMouse.cpp b/libraries/USB/src/USBHIDMouse.cpp index e71d26570fb..5e031768ffa 100644 --- a/libraries/USB/src/USBHIDMouse.cpp +++ b/libraries/USB/src/USBHIDMouse.cpp @@ -25,31 +25,107 @@ #include "USBHIDMouse.h" -static const uint8_t report_descriptor[] = { - TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(HID_REPORT_ID_MOUSE)) -}; - -USBHIDMouse::USBHIDMouse(): hid(), _buttons(0){ +USBHIDMouseBase::USBHIDMouseBase(HIDMouseType_t *type) : hid(), _buttons(0), _type(type) +{ static bool initialized = false; if(!initialized){ initialized = true; - hid.addDevice(this, sizeof(report_descriptor)); + hid.addDevice(this, _type->descriptor_size); } +}; + +uint16_t USBHIDMouseBase::_onGetDescriptor(uint8_t* dst) +{ + memcpy(dst, _type->report_descriptor, _type->descriptor_size); + return _type->descriptor_size; } -uint16_t USBHIDMouse::_onGetDescriptor(uint8_t* dst){ - memcpy(dst, report_descriptor, sizeof(report_descriptor)); - return sizeof(report_descriptor); + +void USBHIDMouseBase::buttons(uint8_t b) +{ + if (b != _buttons){ + _buttons = b; + } } -void USBHIDMouse::begin(){ + +void USBHIDMouseBase::begin() +{ hid.begin(); } -void USBHIDMouse::end(){ +void USBHIDMouseBase::end() +{ +} + + +void USBHIDMouseBase::press(uint8_t b) +{ + this->buttons(_buttons | b); +} + +void USBHIDMouseBase::release(uint8_t b) +{ + this->buttons(_buttons & ~b); +} + +bool USBHIDMouseBase::isPressed(uint8_t b) +{ + if ((b & _buttons) > 0) { + return true; + } + return false; +} + + + +static const uint8_t abs_mouse_report_descriptor[] = { + TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(HID_REPORT_ID_MOUSE)) +}; + +HIDMouseType_t HIDMouseAbs = { HID_MOUSE_ABSOLUTE, abs_mouse_report_descriptor, sizeof(abs_mouse_report_descriptor), sizeof(hid_abs_mouse_report_t) }; + + +void USBHIDAbsoluteMouse::move(int16_t x, int16_t y, int8_t wheel, int8_t pan) +{ + hid_abs_mouse_report_t report; + report.buttons = _buttons; + report.x = _lastx = x; + report.y = _lasty = y; + report.wheel = wheel; + report.pan = pan; + sendReport(report); } -void USBHIDMouse::move(int8_t x, int8_t y, int8_t wheel, int8_t pan){ + +void USBHIDAbsoluteMouse::click(uint8_t b) +{ + _buttons = b; + move(_lastx,_lasty); + _buttons = 0; + move(_lastx,_lasty); +} + +void USBHIDAbsoluteMouse::buttons(uint8_t b) +{ + if (b != _buttons){ + _buttons = b; + move(_lastx,_lasty); + } +} + + + +static const uint8_t rel_mouse_report_descriptor[] = { + TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(HID_REPORT_ID_MOUSE)) +}; + +HIDMouseType_t HIDMouseRel = { HID_MOUSE_RELATIVE, rel_mouse_report_descriptor, sizeof(rel_mouse_report_descriptor), sizeof(hid_mouse_report_t) }; + + + +void USBHIDRelativeMouse::move(int8_t x, int8_t y, int8_t wheel, int8_t pan) +{ hid_mouse_report_t report = { .buttons = _buttons, .x = x, @@ -57,37 +133,26 @@ void USBHIDMouse::move(int8_t x, int8_t y, int8_t wheel, int8_t pan){ .wheel = wheel, .pan = pan }; - hid.SendReport(HID_REPORT_ID_MOUSE, &report, sizeof(report)); + sendReport(report); } -void USBHIDMouse::click(uint8_t b){ + +void USBHIDRelativeMouse::click(uint8_t b) +{ _buttons = b; move(0,0); _buttons = 0; move(0,0); } -void USBHIDMouse::buttons(uint8_t b){ +void USBHIDRelativeMouse::buttons(uint8_t b) +{ if (b != _buttons){ _buttons = b; move(0,0); } } -void USBHIDMouse::press(uint8_t b){ - buttons(_buttons | b); -} - -void USBHIDMouse::release(uint8_t b){ - buttons(_buttons & ~b); -} - -bool USBHIDMouse::isPressed(uint8_t b){ - if ((b & _buttons) > 0) { - return true; - } - return false; -} #endif /* CONFIG_TINYUSB_HID_ENABLED */ #endif /* SOC_USB_OTG_SUPPORTED */ diff --git a/libraries/USB/src/USBHIDMouse.h b/libraries/USB/src/USBHIDMouse.h index f69e371c798..0830c24ea78 100644 --- a/libraries/USB/src/USBHIDMouse.h +++ b/libraries/USB/src/USBHIDMouse.h @@ -34,26 +34,68 @@ #define MOUSE_FORWARD 0x10 #define MOUSE_ALL 0x1F -class USBHIDMouse: public USBHIDDevice { -private: - USBHID hid; - uint8_t _buttons; - void buttons(uint8_t b); - bool write(int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +#include "./tusb_hid_mouse.h" + +enum MousePositioning_t +{ + HID_MOUSE_RELATIVE, + HID_MOUSE_ABSOLUTE +}; + +struct HIDMouseType_t +{ + MousePositioning_t positioning; + const uint8_t* report_descriptor; + size_t descriptor_size; + size_t report_size; +}; + +extern HIDMouseType_t HIDMouseRel; +extern HIDMouseType_t HIDMouseAbs; + + +class USBHIDMouseBase: public USBHIDDevice { public: - USBHIDMouse(void); + USBHIDMouseBase(HIDMouseType_t *type); void begin(void); void end(void); - - void click(uint8_t b = MOUSE_LEFT); - void move(int8_t x, int8_t y, int8_t wheel = 0, int8_t pan = 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 - + template bool sendReport(T report) { return hid.SendReport( HID_REPORT_ID_MOUSE, &report, _type->report_size ); }; // internal use uint16_t _onGetDescriptor(uint8_t* buffer); + virtual void buttons(uint8_t b); +protected: + USBHID hid; + uint8_t _buttons; + HIDMouseType_t *_type; +}; + + +class USBHIDRelativeMouse: public USBHIDMouseBase { +public: + USBHIDRelativeMouse(void): USBHIDMouseBase(&HIDMouseRel) { } + void move(int8_t x, int8_t y, int8_t wheel = 0, int8_t pan = 0); + void click(uint8_t b = MOUSE_LEFT); + void buttons(uint8_t b) override; +}; + + +class USBHIDAbsoluteMouse: public USBHIDMouseBase { +public: + USBHIDAbsoluteMouse(void): USBHIDMouseBase(&HIDMouseAbs) { } + void move(int16_t x, int16_t y, int8_t wheel = 0, int8_t pan = 0); + void click(uint8_t b = MOUSE_LEFT); + void buttons(uint8_t b) override; +private: + int16_t _lastx = 0; + int16_t _lasty = 0; }; + +// don't break examples and old sketches +typedef USBHIDRelativeMouse USBHIDMouse; + #endif /* CONFIG_TINYUSB_HID_ENABLED */ #endif /* SOC_USB_OTG_SUPPORTED */ diff --git a/libraries/USB/src/tusb_hid_mouse.h b/libraries/USB/src/tusb_hid_mouse.h new file mode 100644 index 00000000000..6cf35c4aa6f --- /dev/null +++ b/libraries/USB/src/tusb_hid_mouse.h @@ -0,0 +1,98 @@ +#pragma once + +#include "class/hid/hid_device.h" + +#if !defined TUD_HID_REPORT_DESC_ABSMOUSE + // This version of arduino-esp32 does not handle absolute mouse natively. + // Let's throw a minimalistic implementation of absmouse driver. + // See: https://github.com/hathach/tinyusb/pull/1363 + // Also see: https://github.com/espressif/arduino-esp32/pull/6331 + + extern "C" { + + // Absolute Mouse data struct is a copy of the relative mouse struct + // with int16_t instead of int8_t for X and Y coordinates. + typedef struct TU_ATTR_PACKED + { + uint8_t buttons = 0; + int16_t x = 0; + int16_t y = 0; + int8_t wheel = 0; + int8_t pan = 0; + } hid_abs_mouse_report_t; + + + // Absolute Mouse Report Descriptor Template applies those datatype changes too + #define TUD_HID_REPORT_DESC_ABSMOUSE(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */\ + __VA_ARGS__ \ + HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ + HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ + HID_USAGE_MIN ( 1 ) ,\ + HID_USAGE_MAX ( 5 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + /* Left, Right, Middle, Backward, Forward buttons */ \ + HID_REPORT_COUNT( 5 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 3 bit padding */ \ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 3 ) ,\ + HID_INPUT ( HID_CONSTANT ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + /* X, Y absolute position [0, 32767] */ \ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_LOGICAL_MIN ( 0x00 ) ,\ + HID_LOGICAL_MAX_N( 0x7FFF, 2 ) ,\ + HID_REPORT_SIZE ( 16 ) ,\ + HID_REPORT_COUNT ( 2 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* Vertical wheel scroll [-127, 127] */ \ + HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ + /* Horizontal wheel scroll [-127, 127] */ \ + HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ + HID_LOGICAL_MIN ( 0x81 ), \ + HID_LOGICAL_MAX ( 0x7f ), \ + HID_REPORT_COUNT( 1 ), \ + HID_REPORT_SIZE ( 8 ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ + HID_COLLECTION_END , \ + HID_COLLECTION_END \ + + static inline bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) + { + hid_abs_mouse_report_t report = + { + .buttons = buttons, + .x = x, + .y = y, + .wheel = vertical, + .pan = horizontal + }; + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); + } + + static inline bool tud_hid_abs_mouse_report(uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) + { + return tud_hid_n_abs_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); + } + + + } // end extern "C" + +#else + #pragma message "This file is now safe to delete along with its include from USBHIDMouse.h" +#endif + From a9ba21dc4186036d9e45c143d6f85c9c70597991 Mon Sep 17 00:00:00 2001 From: tobozo Date: Sat, 11 Nov 2023 11:51:26 +0100 Subject: [PATCH 2/2] make click() virtual --- libraries/USB/src/USBHIDMouse.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/USB/src/USBHIDMouse.h b/libraries/USB/src/USBHIDMouse.h index 0830c24ea78..3bf31b46685 100644 --- a/libraries/USB/src/USBHIDMouse.h +++ b/libraries/USB/src/USBHIDMouse.h @@ -65,7 +65,8 @@ class USBHIDMouseBase: public USBHIDDevice { template bool sendReport(T report) { return hid.SendReport( HID_REPORT_ID_MOUSE, &report, _type->report_size ); }; // internal use uint16_t _onGetDescriptor(uint8_t* buffer); - virtual void buttons(uint8_t b); + virtual void click(uint8_t b) = 0; + virtual void buttons(uint8_t b) = 0; protected: USBHID hid; uint8_t _buttons; @@ -77,7 +78,7 @@ class USBHIDRelativeMouse: public USBHIDMouseBase { public: USBHIDRelativeMouse(void): USBHIDMouseBase(&HIDMouseRel) { } void move(int8_t x, int8_t y, int8_t wheel = 0, int8_t pan = 0); - void click(uint8_t b = MOUSE_LEFT); + void click(uint8_t b = MOUSE_LEFT) override; void buttons(uint8_t b) override; }; @@ -86,7 +87,7 @@ class USBHIDAbsoluteMouse: public USBHIDMouseBase { public: USBHIDAbsoluteMouse(void): USBHIDMouseBase(&HIDMouseAbs) { } void move(int16_t x, int16_t y, int8_t wheel = 0, int8_t pan = 0); - void click(uint8_t b = MOUSE_LEFT); + void click(uint8_t b = MOUSE_LEFT) override; void buttons(uint8_t b) override; private: int16_t _lastx = 0;