Skip to content

Absolute mouse support (was #6331) #8831

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 94 additions & 29 deletions libraries/USB/src/USBHIDMouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,69 +25,134 @@

#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,
.y = y,
.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 */
64 changes: 53 additions & 11 deletions libraries/USB/src/USBHIDMouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename T> 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 */
98 changes: 98 additions & 0 deletions libraries/USB/src/tusb_hid_mouse.h
Original file line number Diff line number Diff line change
@@ -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