1
0
mirror of https://github.com/arduino/Arduino.git synced 2024-12-01 12:24:14 +01:00

Merge branch 'phid-class'

This commit is contained in:
Cristian Maglie 2015-10-07 17:05:11 +02:00
commit aa921659f6
11 changed files with 261 additions and 256 deletions

View File

@ -23,78 +23,84 @@
#if defined(USBCON)
#ifdef PLUGGABLE_USB_ENABLED
#define MAX_MODULES 6
extern uint8_t _initEndpoints[];
static u8 lastIf = CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT;
static u8 lastEp = CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT;
extern u8 _initEndpoints[];
//PUSBCallbacks cbs[MAX_MODULES];
static u8 modules_count = 0;
static PUSBListNode* rootNode = NULL;
int PUSB_GetInterface(u8* interfaceNum)
int PluggableUSB_::getInterface(uint8_t* interfaceCount)
{
int ret = 0;
PUSBListNode* node = rootNode;
for (u8 i=0; i<modules_count; i++) {
ret = node->cb->getInterface(interfaceNum);
node = node->next;
int sent = 0;
PUSBListNode* node;
for (node = rootNode; node; node = node->next) {
int res = node->getInterface(interfaceCount);
if (res < 0)
return -1;
sent += res;
}
return ret;
return sent;
}
int PUSB_GetDescriptor(int8_t t)
int PluggableUSB_::getDescriptor(int8_t type)
{
int ret = 0;
PUSBListNode* node = rootNode;
for (u8 i=0; i<modules_count && ret == 0; i++) {
ret = node->cb->getDescriptor(t);
node = node->next;
PUSBListNode* node;
for (node = rootNode; node; node = node->next) {
int ret = node->getDescriptor(type);
// ret!=0 -> request has been processed
if (ret)
return ret;
}
return ret;
return 0;
}
bool PUSB_Setup(USBSetup& setup, u8 j)
bool PluggableUSB_::setup(USBSetup& setup, uint8_t interfaceNum)
{
bool ret = false;
PUSBListNode* node = rootNode;
for (u8 i=0; i<modules_count && ret == false; i++) {
ret = node->cb->setup(setup, j);
node = node->next;
PUSBListNode* node;
for (node = rootNode; node; node = node->next) {
if (node->setup(setup, interfaceNum)) {
return true;
}
}
return ret;
return false;
}
int8_t PUSB_AddFunction(PUSBListNode *node, u8* interface)
bool PluggableUSB_::plug(PUSBListNode *node)
{
if (modules_count >= MAX_MODULES) {
return 0;
if ((lastEp + node->numEndpoints) > USB_ENDPOINTS) {
return false;
}
if (modules_count == 0) {
if (!rootNode) {
rootNode = node;
} else {
PUSBListNode *current = rootNode;
while(current->next != NULL) {
while (current->next) {
current = current->next;
}
current->next = node;
}
*interface = lastIf;
lastIf += node->cb->numInterfaces;
for ( u8 i = 0; i< node->cb->numEndpoints; i++) {
_initEndpoints[lastEp] = node->cb->endpointType[i];
node->pluggedInterface = lastIf;
node->pluggedEndpoint = lastEp;
lastIf += node->numInterfaces;
for (uint8_t i = 0; i < node->numEndpoints; i++) {
_initEndpoints[lastEp] = node->endpointType[i];
lastEp++;
}
modules_count++;
return lastEp - node->cb->numEndpoints;
return true;
// restart USB layer???
}
PluggableUSB_& PluggableUSB()
{
static PluggableUSB_ obj;
return obj;
}
PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT),
lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT),
rootNode(NULL)
{
// Empty
}
#endif
#endif /* if defined(USBCON) */
#endif /* if defined(USBCON) */

View File

@ -25,30 +25,50 @@
#if defined(USBCON)
typedef struct __attribute__((packed))
{
bool (*setup)(USBSetup& setup, u8 i);
int (*getInterface)(u8* interfaceNum);
int (*getDescriptor)(int8_t t);
int8_t numEndpoints;
int8_t numInterfaces;
uint8_t *endpointType;
} PUSBCallbacks;
class PUSBListNode {
public:
PUSBListNode(int8_t numEps, int8_t numIfs, uint8_t *epType) :
numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType)
{ }
inline uint8_t interface() const { return pluggedInterface; }
inline int8_t endpoint() const { return pluggedEndpoint; }
protected:
virtual bool setup(USBSetup& setup, uint8_t interfaceNum) = 0;
virtual int getInterface(uint8_t* interfaceCount) = 0;
virtual int getDescriptor(int8_t t) = 0;
uint8_t pluggedInterface;
int8_t pluggedEndpoint;
const int8_t numEndpoints;
const int8_t numInterfaces;
const uint8_t *endpointType;
PUSBListNode *next = NULL;
PUSBCallbacks *cb;
PUSBListNode(PUSBCallbacks *ncb) {cb = ncb;}
friend class PluggableUSB_;
};
int8_t PUSB_AddFunction(PUSBListNode *node, u8 *interface);
class PluggableUSB_ {
public:
PluggableUSB_();
bool plug(PUSBListNode *node);
int getInterface(uint8_t* interfaceCount);
int getDescriptor(int8_t type);
bool setup(USBSetup& setup, uint8_t interfaceNum);
int PUSB_GetInterface(u8* interfaceNum);
private:
uint8_t lastIf;
uint8_t lastEp;
PUSBListNode* rootNode;
};
int PUSB_GetDescriptor(int8_t t);
bool PUSB_Setup(USBSetup& setup, u8 i);
// Replacement for global singleton.
// This function prevents static-initialization-order-fiasco
// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
PluggableUSB_& PluggableUSB();
#endif

View File

@ -308,20 +308,15 @@ int USB_Send(u8 ep, const void* d, int len)
return r;
}
u8 _initEndpoints[] =
u8 _initEndpoints[USB_ENDPOINTS] =
{
0,
0, // Control Endpoint
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
#ifdef PLUGGABLE_USB_ENABLED
//allocate 3 endpoints and remove const so they can be changed by the user
0,
0,
0,
#endif
// Following endpoints are automatically initialized to 0
};
#define EP_SINGLE_64 0x32 // EP0
@ -367,7 +362,7 @@ bool ClassInterfaceRequest(USBSetup& setup)
return CDC_Setup(setup);
#ifdef PLUGGABLE_USB_ENABLED
return PUSB_Setup(setup, i);
return PluggableUSB().setup(setup, i);
#endif
return false;
}
@ -445,7 +440,7 @@ static u8 SendInterfaces()
CDC_GetInterface(&interfaces);
#ifdef PLUGGABLE_USB_ENABLED
PUSB_GetInterface(&interfaces);
PluggableUSB().getInterface(&interfaces);
#endif
return interfaces;
@ -481,7 +476,7 @@ bool SendDescriptor(USBSetup& setup)
InitControl(setup.wLength);
#ifdef PLUGGABLE_USB_ENABLED
ret = PUSB_GetDescriptor(t);
ret = PluggableUSB().getDescriptor(t);
if (ret != 0) {
return (ret > 0 ? true : false);
}

View File

@ -99,8 +99,8 @@
// bEndpointAddress in Endpoint Descriptor
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
#define USB_ENDPOINT_OUT(addr) (lowByte((addr) | 0x00))
#define USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80))
#define USB_ENDPOINT_TYPE_MASK 0x03
#define USB_ENDPOINT_TYPE_CONTROL 0x00
@ -277,4 +277,4 @@ typedef struct
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
#endif
#endif

View File

@ -1,23 +1,28 @@
/*
Copyright (c) 2011, Peter Barrett
Copyright (c) 2015, Arduino LLC
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.
/* 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.
*/
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.
*/
#define PLUGGABLE_USB_ENABLED
#if defined(EPRST6)
#define USB_ENDPOINTS 7 // AtMegaxxU4
#else
#define USB_ENDPOINTS 5 // AtMegaxxU2
#endif
#define CDC_INTERFACE_COUNT 2
#define CDC_ENPOINT_COUNT 3

View File

@ -1,153 +1,123 @@
/* 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.
*/
/*
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.
*/
#include "PluggableUSB.h"
#include "HID.h"
#if defined(USBCON)
HID_ HID;
static uint8_t HID_ENDPOINT_INT;
//================================================================================
//================================================================================
// HID Interface
static uint8_t HID_INTERFACE;
HIDDescriptor _hidInterface;
static HIDDescriptorListNode* rootNode = NULL;
static uint16_t sizeof_hidReportDescriptor = 0;
static uint8_t modules_count = 0;
//================================================================================
//================================================================================
// Driver
uint8_t _hid_protocol = 1;
uint8_t _hid_idle = 1;
int HID_GetInterface(uint8_t* interfaceNum)
HID_& HID()
{
interfaceNum[0] += 1; // uses 1
_hidInterface =
{
D_INTERFACE(HID_INTERFACE,1,3,0,0),
D_HIDREPORT(sizeof_hidReportDescriptor),
D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,USB_EP_SIZE,0x01)
};
return USB_SendControl(0,&_hidInterface,sizeof(_hidInterface));
static HID_ obj;
return obj;
}
int HID_GetDescriptor(int8_t t)
int HID_::getInterface(uint8_t* interfaceCount)
{
if (HID_REPORT_DESCRIPTOR_TYPE == t) {
HIDDescriptorListNode* current = rootNode;
*interfaceCount += 1; // uses 1
HIDDescriptor hidInterface = {
D_INTERFACE(interface(), 1, 3, 0, 0),
D_HIDREPORT(descriptorSize),
D_ENDPOINT(USB_ENDPOINT_IN(endpoint()), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
};
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
}
int HID_::getDescriptor(int8_t type)
{
if (HID_REPORT_DESCRIPTOR_TYPE == type) {
int total = 0;
while(current != NULL) {
total += USB_SendControl(TRANSFER_PGM,current->data,current->length);
current = current->next;
HIDDescriptorListNode* node;
for (node = rootNode; node; node = node->next) {
int res = USB_SendControl(TRANSFER_PGM, node->data, node->length);
if (res == -1)
return -1;
total += res;
}
return total;
} else {
return 0;
}
// Ignored
return 0;
}
void HID_::AppendDescriptor(HIDDescriptorListNode *node)
{
if (modules_count == 0) {
if (!rootNode) {
rootNode = node;
} else {
HIDDescriptorListNode *current = rootNode;
while(current->next != NULL) {
while (current->next) {
current = current->next;
}
current->next = node;
}
modules_count++;
sizeof_hidReportDescriptor += (uint16_t)node->length;
descriptorSize += node->length;
}
void HID_::SendReport(u8 id, const void* data, int len)
void HID_::SendReport(uint8_t id, const void* data, int len)
{
USB_Send(HID_TX, &id, 1);
USB_Send(HID_TX | TRANSFER_RELEASE,data,len);
USB_Send(endpoint(), &id, 1);
USB_Send(endpoint() | TRANSFER_RELEASE, data, len);
}
bool HID_Setup(USBSetup& setup, uint8_t i)
bool HID_::setup(USBSetup& setup, uint8_t interfaceNum)
{
if (HID_INTERFACE != i) {
return false;
} else {
uint8_t r = setup.bRequest;
uint8_t requestType = setup.bmRequestType;
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
{
if (HID_GET_REPORT == r)
{
//HID_GetReport();
return true;
}
if (HID_GET_PROTOCOL == r)
{
//Send8(_hid_protocol); // TODO
return true;
}
}
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
{
if (HID_SET_PROTOCOL == r)
{
_hid_protocol = setup.wValueL;
return true;
}
if (HID_SET_IDLE == r)
{
_hid_idle = setup.wValueL;
return true;
}
}
if (interface() != interfaceNum) {
return false;
}
uint8_t request = setup.bRequest;
uint8_t requestType = setup.bmRequestType;
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
{
if (request == HID_GET_REPORT) {
// TODO: HID_GetReport();
return true;
}
if (request == HID_GET_PROTOCOL) {
// TODO: Send8(protocol);
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;
}
}
return false;
}
HID_::HID_(void)
HID_::HID_(void) : PUSBListNode(1, 1, epType),
rootNode(NULL), descriptorSize(0),
protocol(1), idle(1)
{
static uint8_t endpointType[1];
endpointType[0] = EP_TYPE_INTERRUPT_IN;
static PUSBCallbacks cb = {
.setup = &HID_Setup,
.getInterface = &HID_GetInterface,
.getDescriptor = &HID_GetDescriptor,
.numEndpoints = 1,
.numInterfaces = 1,
.endpointType = endpointType,
};
static PUSBListNode node(&cb);
HID_ENDPOINT_INT = PUSB_AddFunction(&node, &HID_INTERFACE);
epType[0] = EP_TYPE_INTERRUPT_IN;
PluggableUSB().plug(this);
}
int HID_::begin(void)

View File

@ -1,38 +1,34 @@
/*
HID.h
Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
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.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
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.
*/
#ifndef HID_h
#define HID_h
#include <stdint.h>
#include <Arduino.h>
#include "PluggableUSB.h"
#if defined(USBCON)
#define _USING_HID
//================================================================================
//================================================================================
// HID 'Driver'
// HID 'Driver'
// ------------
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
@ -44,24 +40,6 @@
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
class HIDDescriptorListNode {
public:
HIDDescriptorListNode *next = NULL;
HIDDescriptorListNode(const void *d, const uint16_t l) : data(d), length(l) { }
const void* data;
uint16_t length;
};
class HID_
{
public:
HID_(void);
int begin(void);
void SendReport(uint8_t id, const void* data, int len);
void AppendDescriptor(HIDDescriptorListNode* node);
};
typedef struct
{
uint8_t len; // 9
@ -82,13 +60,46 @@ typedef struct
EndpointDescriptor in;
} HIDDescriptor;
#define HID_TX HID_ENDPOINT_INT
class HIDDescriptorListNode {
public:
HIDDescriptorListNode *next = NULL;
HIDDescriptorListNode(const void *d, const uint16_t l) : data(d), length(l) { }
#define D_HIDREPORT(_descriptorLength) \
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength & 0xFF, _descriptorLength >> 8 }
const void* data;
uint16_t length;
};
#define WEAK __attribute__ ((weak))
class HID_ : public PUSBListNode
{
public:
HID_(void);
int begin(void);
void SendReport(uint8_t id, const void* data, int len);
void AppendDescriptor(HIDDescriptorListNode* node);
#endif
protected:
// Implementation of the PUSBListNode
int getInterface(uint8_t* interfaceCount);
int getDescriptor(int8_t type);
bool setup(USBSetup& setup, uint8_t interfaceNum);
#endif
private:
uint8_t epType[1];
HIDDescriptorListNode* rootNode;
uint16_t descriptorSize;
uint8_t protocol;
uint8_t idle;
};
// 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, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) }
#endif // USBCON
#endif // HID_h

View File

@ -63,7 +63,7 @@ static const uint8_t _hidReportDescriptor[] PROGMEM = {
Keyboard_::Keyboard_(void)
{
static HIDDescriptorListNode node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
HID.AppendDescriptor(&node);
HID().AppendDescriptor(&node);
}
void Keyboard_::begin(void)
@ -76,7 +76,7 @@ void Keyboard_::end(void)
void Keyboard_::sendReport(KeyReport* keys)
{
HID.SendReport(2,keys,sizeof(KeyReport));
HID().SendReport(2,keys,sizeof(KeyReport));
}
extern

View File

@ -94,7 +94,6 @@ public:
void releaseAll(void);
};
extern Keyboard_ Keyboard;
extern HID_ HID;
#endif
#endif

View File

@ -63,7 +63,7 @@ static const uint8_t _hidReportDescriptor[] PROGMEM = {
Mouse_::Mouse_(void) : _buttons(0)
{
static HIDDescriptorListNode node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
HID.AppendDescriptor(&node);
HID().AppendDescriptor(&node);
}
void Mouse_::begin(void)
@ -89,7 +89,7 @@ void Mouse_::move(signed char x, signed char y, signed char wheel)
m[1] = x;
m[2] = y;
m[3] = wheel;
HID.SendReport(1,m,4);
HID().SendReport(1,m,4);
}
void Mouse_::buttons(uint8_t b)

View File

@ -55,7 +55,6 @@ public:
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
};
extern Mouse_ Mouse;
extern HID_ HID;
#endif
#endif