From ddae105dc316ca5e463404c28cf0c96949e6861d Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 12 Oct 2015 14:41:23 +0200 Subject: [PATCH] [HID] port to stable PluggableUSB API --- hardware/arduino/sam/libraries/HID/HID.cpp | 204 +++++++++------------ hardware/arduino/sam/libraries/HID/HID.h | 127 ++++++++----- 2 files changed, 169 insertions(+), 162 deletions(-) diff --git a/hardware/arduino/sam/libraries/HID/HID.cpp b/hardware/arduino/sam/libraries/HID/HID.cpp index b2a79423e..8d3a5a52e 100644 --- a/hardware/arduino/sam/libraries/HID/HID.cpp +++ b/hardware/arduino/sam/libraries/HID/HID.cpp @@ -13,156 +13,134 @@ ** 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. +** SOFTWARE. */ -#include "USB/PluggableUSB.h" #include "HID.h" -HID_ HID; +#if defined(USBCON) -static uint8_t HID_ENDPOINT_INT; - -//================================================================================ -//================================================================================ - -// HID report descriptor - -#define LSB(_x) ((_x) & 0xFF) -#define MSB(_x) ((_x) >> 8) - -#define RAWHID_USAGE_PAGE 0xFFC0 -#define RAWHID_USAGE 0x0C00 -#define RAWHID_TX_SIZE 64 -#define RAWHID_RX_SIZE 64 - -static uint8_t HID_INTERFACE; - -HIDDescriptor _hidInterface; - -static HIDDescriptorListNode* rootNode = NULL; -static uint8_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,0x40,0x01) + static HID_ obj; + 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, 0x40, 0x01) }; - return USBD_SendControl(0,&_hidInterface,sizeof(_hidInterface)); + return USBD_SendControl(0, &hidInterface, sizeof(hidInterface)); } -int HID_GetDescriptor(int8_t t) +int HID_::getDescriptor(USBSetup& setup) { - if (HID_REPORT_DESCRIPTOR_TYPE == t) { - HIDDescriptorListNode* current = rootNode; - int total = 0; - while(current != NULL) { - total += USBD_SendControl(0,current->data,current->length); - current = current->next; - } - return total; - } else { - return 0; + // 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; } + + int total = 0; + HIDSubDescriptor* node; + for (node = rootNode; node; node = node->next) { + int res = USBD_SendControl(0, node->data, node->length); + if (res == -1) + return -1; + total += res; } + return total; } -void HID_::AppendDescriptor(HIDDescriptorListNode *node) +void HID_::AppendDescriptor(HIDSubDescriptor *node) { - if (modules_count == 0) { + if (!rootNode) { rootNode = node; } else { - HIDDescriptorListNode *current = rootNode; - while(current->next != NULL) { + HIDSubDescriptor *current = rootNode; + while (current->next) { current = current->next; } current->next = node; } - modules_count++; - sizeof_hidReportDescriptor += node->length; + descriptorSize += node->length; } void HID_::SendReport(uint8_t id, const void* data, int len) { uint8_t p[64]; - const uint8_t *d = reinterpret_cast(data); - p[0] = id; - for (uint32_t i=0; i #include +#include "USB/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 @@ -42,49 +40,80 @@ #define HID_REPORT_DESCRIPTOR_TYPE 0x22 #define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 -class HIDDescriptorListNode { +// HID subclass HID1.11 Page 8 4.2 Subclass +#define HID_SUBCLASS_NONE 0 +#define HID_SUBCLASS_BOOT_INTERFACE 1 + +// 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 + +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 desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; +} HIDDescDescriptor; + +typedef struct +{ + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; +} HIDDescriptor; + +class HIDSubDescriptor { public: - HIDDescriptorListNode *next = NULL; - HIDDescriptorListNode(const void *d, const uint16_t l) : data(d), length(l) { } + HIDSubDescriptor *next = NULL; + HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } const void* data; const uint16_t length; }; -class HID_ +class HID_ : public PluggableUSBModule { public: HID_(void); int begin(void); void SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDDescriptorListNode* node); + void AppendDescriptor(HIDSubDescriptor* node); + +protected: + // Implementation of the PluggableUSBModule + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + +private: + uint32_t epType[1]; + + HIDSubDescriptor* rootNode; + uint16_t descriptorSize; + + uint8_t protocol; + uint8_t idle; }; -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 desctype; // 0x22 report - uint8_t descLenL; - uint8_t descLenH; -} HIDDescDescriptor; +// 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(); -typedef struct -{ - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; -} HIDDescriptor; +#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } -#define HID_TX HID_ENDPOINT_INT +#endif // USBCON -#define D_HIDREPORT(_descriptorLength) \ - { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } - -#define WEAK __attribute__ ((weak)) - -#endif +#endif // HID_h