diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index daca74cc6..0f1016848 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -58,10 +58,8 @@ static volatile LineInfo _usbLineInfo = { 0x00 // lineState }; -static const CDCDescriptor _cdcInterface = { - #if (defined CDC_ENABLED) && defined(HID_ENABLED) +static CDCDescriptor _cdcInterface = { D_IAD(0, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0), - #endif // CDC communication interface D_INTERFACE(CDC_ACM_INTERFACE, 1, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0), @@ -79,17 +77,23 @@ static const CDCDescriptor _cdcInterface = { }; _Pragma("pack()") -const void* CDC_GetInterface(void) +const void* _CDC_GetInterface(void) { return &_cdcInterface; } -uint32_t CDC_GetInterfaceLength(void) +uint32_t _CDC_GetInterfaceLength(void) { return sizeof(_cdcInterface); } -bool CDC_Setup(Setup& setup) +int CDC_GetInterface(uint8_t* interfaceNum) +{ + interfaceNum[0] += 2; // uses 2 + return USBDevice.sendControl(&_cdcInterface,sizeof(_cdcInterface)); +} + +bool CDC_Setup(USBSetup& setup) { uint8_t requestType = setup.bmRequestType; uint8_t r = setup.bRequest; @@ -181,7 +185,7 @@ int Serial_::available(void) return CDC_SERIAL_BUFFER_SIZE; } if (buffer->head == buffer->tail) { - USB->DEVICE.DeviceEndpoint[2].EPINTENSET.reg = USB_DEVICE_EPINTENCLR_TRCPT(1); + USB->DEVICE.DeviceEndpoint[CDC_ENDPOINT_OUT].EPINTENSET.reg = USB_DEVICE_EPINTENCLR_TRCPT(1); } return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE; } diff --git a/cores/arduino/USB/HID.cpp b/cores/arduino/USB/HID.cpp deleted file mode 100644 index edcc2167c..000000000 --- a/cores/arduino/USB/HID.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/* - Copyright (c) 2014 Arduino LLC. All right reserved. - - 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. - - 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 -*/ - -#include - -#ifdef HID_ENABLED - -//#define RAWHID_ENABLED - -// Singletons for mouse and keyboard -Mouse_ Mouse; -Keyboard_ Keyboard; - -//================================================================================ -//================================================================================ - -#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 - -// HID report descriptor -_Pragma("pack(1)") -extern const uint8_t _hidReportDescriptor[] = { - // Mouse - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54 - 0x09, 0x02, // USAGE (Mouse) - 0xa1, 0x01, // COLLECTION (Application) - 0x09, 0x01, // USAGE (Pointer) - 0xa1, 0x00, // COLLECTION (Physical) - 0x85, 0x01, // REPORT_ID (1) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x03, // USAGE_MAXIMUM (Button 3) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x95, 0x03, // REPORT_COUNT (3) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x05, // REPORT_SIZE (5) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x38, // USAGE (Wheel) - 0x15, 0x81, // LOGICAL_MINIMUM (-127) - 0x25, 0x7f, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x03, // REPORT_COUNT (3) - 0x81, 0x06, // INPUT (Data,Var,Rel) - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION - - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x02, // REPORT_ID (2) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - - 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) - 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - - 0x95, 0x08, // REPORT_COUNT (8) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - - 0x95, 0x06, // REPORT_COUNT (6) - 0x75, 0x08, // REPORT_SIZE (8) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x65, // LOGICAL_MAXIMUM (101) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - - 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) - 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) - 0x81, 0x00, // INPUT (Data,Ary,Abs) - 0xc0, // END_COLLECTION - -#ifdef RAWHID_ENABLED - // RAW HID - 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 - 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), - - 0xA1, 0x01, // Collection 0x01 - 0x85, 0x03, // REPORT_ID (3) - 0x75, 0x08, // report size = 8 bits - 0x15, 0x00, // logical minimum = 0 - 0x26, 0xFF, 0x00, // logical maximum = 255 - - 0x95, 64, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) - - 0x95, 64, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0 // end collection -#endif -}; - -extern const HIDDescriptor _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) -}; -_Pragma("pack()") - -//================================================================================ -//================================================================================ -// Driver - -uint8_t _hid_protocol = 1; -uint8_t _hid_idle = 1; - -const void* HID_GetInterface(void) -{ - return &_hidInterface; -} - -uint32_t HID_GetInterfaceLength(void) -{ - return sizeof( _hidInterface ); -} - -uint32_t HID_SizeReportDescriptor(void) -{ - return sizeof(_hidReportDescriptor); -} - -uint32_t HID_GetDescriptor(void) -{ - return USBDevice.sendControl(_hidReportDescriptor, sizeof(_hidReportDescriptor)); -} - -void HID_SendReport(uint8_t id, const void* data, uint32_t len) -{ - uint8_t p[8]; - const uint8_t *d = reinterpret_cast(data); - - p[0] = id; - for (uint32_t i=0; i 0) - return true; - return false; -} - -//================================================================================ -//================================================================================ -// Keyboard - -Keyboard_::Keyboard_(void) -{ -} - -void Keyboard_::begin(void) -{ -} - -void Keyboard_::end(void) -{ -} - -void Keyboard_::sendReport(KeyReport* keys) -{ - HID_SendReport(2,keys,sizeof(KeyReport)); -} - -#define SHIFT 0x80 -extern const uint8_t _asciimap[128] = -{ - 0x00, // NUL - 0x00, // SOH - 0x00, // STX - 0x00, // ETX - 0x00, // EOT - 0x00, // ENQ - 0x00, // ACK - 0x00, // BEL - 0x2a, // BS Backspace - 0x2b, // TAB Tab - 0x28, // LF Enter - 0x00, // VT - 0x00, // FF - 0x00, // CR - 0x00, // SO - 0x00, // SI - 0x00, // DEL - 0x00, // DC1 - 0x00, // DC2 - 0x00, // DC3 - 0x00, // DC4 - 0x00, // NAK - 0x00, // SYN - 0x00, // ETB - 0x00, // CAN - 0x00, // EM - 0x00, // SUB - 0x00, // ESC - 0x00, // FS - 0x00, // GS - 0x00, // RS - 0x00, // US - - 0x2c, // ' ' - 0x1e|SHIFT, // ! - 0x34|SHIFT, // " - 0x20|SHIFT, // # - 0x21|SHIFT, // $ - 0x22|SHIFT, // % - 0x24|SHIFT, // & - 0x34, // ' - 0x26|SHIFT, // ( - 0x27|SHIFT, // ) - 0x25|SHIFT, // * - 0x2e|SHIFT, // + - 0x36, // , - 0x2d, // - - 0x37, // . - 0x38, // / - 0x27, // 0 - 0x1e, // 1 - 0x1f, // 2 - 0x20, // 3 - 0x21, // 4 - 0x22, // 5 - 0x23, // 6 - 0x24, // 7 - 0x25, // 8 - 0x26, // 9 - 0x33|SHIFT, // : - 0x33, // ; - 0x36|SHIFT, // < - 0x2e, // = - 0x37|SHIFT, // > - 0x38|SHIFT, // ? - 0x1f|SHIFT, // @ - 0x04|SHIFT, // A - 0x05|SHIFT, // B - 0x06|SHIFT, // C - 0x07|SHIFT, // D - 0x08|SHIFT, // E - 0x09|SHIFT, // F - 0x0a|SHIFT, // G - 0x0b|SHIFT, // H - 0x0c|SHIFT, // I - 0x0d|SHIFT, // J - 0x0e|SHIFT, // K - 0x0f|SHIFT, // L - 0x10|SHIFT, // M - 0x11|SHIFT, // N - 0x12|SHIFT, // O - 0x13|SHIFT, // P - 0x14|SHIFT, // Q - 0x15|SHIFT, // R - 0x16|SHIFT, // S - 0x17|SHIFT, // T - 0x18|SHIFT, // U - 0x19|SHIFT, // V - 0x1a|SHIFT, // W - 0x1b|SHIFT, // X - 0x1c|SHIFT, // Y - 0x1d|SHIFT, // Z - 0x2f, // [ - 0x31, // bslash - 0x30, // ] - 0x23|SHIFT, // ^ - 0x2d|SHIFT, // _ - 0x35, // ` - 0x04, // a - 0x05, // b - 0x06, // c - 0x07, // d - 0x08, // e - 0x09, // f - 0x0a, // g - 0x0b, // h - 0x0c, // i - 0x0d, // j - 0x0e, // k - 0x0f, // l - 0x10, // m - 0x11, // n - 0x12, // o - 0x13, // p - 0x14, // q - 0x15, // r - 0x16, // s - 0x17, // t - 0x18, // u - 0x19, // v - 0x1a, // w - 0x1b, // x - 0x1c, // y - 0x1d, // z - 0x2f|SHIFT, // - 0x31|SHIFT, // | - 0x30|SHIFT, // } - 0x35|SHIFT, // ~ - 0 // DEL -}; - -// press() adds the specified key (printing, non-printing, or modifier) -// to the persistent key report and sends the report. Because of the way -// USB HID works, the host acts like the key remains pressed until we -// call release(), releaseAll(), or otherwise clear the report and resend. -size_t Keyboard_::press(uint8_t k) -{ - uint8_t i; - if (k >= 136) { // it's a non-printing key (not a modifier) - k = k - 136; - } else if (k >= 128) { // it's a modifier key - _keyReport.modifiers |= (1<<(k-128)); - k = 0; - } else { // it's a printing key - k = _asciimap[k]; - if (!k) { - setWriteError(); - return 0; - } - if (k & 0x80) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k &= 0x7F; - } - } - - // Add k to the key report only if it's not already present - // and if there is an empty slot. - if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && - _keyReport.keys[2] != k && _keyReport.keys[3] != k && - _keyReport.keys[4] != k && _keyReport.keys[5] != k) { - - for (i=0; i<6; i++) { - if (_keyReport.keys[i] == 0x00) { - _keyReport.keys[i] = k; - break; - } - } - if (i == 6) { - setWriteError(); - return 0; - } - } - sendReport(&_keyReport); - return 1; -} - -// release() takes the specified key out of the persistent key report and -// sends the report. This tells the OS the key is no longer pressed and that -// it shouldn't be repeated any more. -size_t Keyboard_::release(uint8_t k) -{ - uint8_t i; - if (k >= 136) { // it's a non-printing key (not a modifier) - k = k - 136; - } else if (k >= 128) { // it's a modifier key - _keyReport.modifiers &= ~(1<<(k-128)); - k = 0; - } else { // it's a printing key - k = _asciimap[k]; - if (!k) { - return 0; - } - if (k & 0x80) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k &= 0x7F; - } - } - - // Test the key report to see if k is present. Clear it if it exists. - // Check all positions in case the key is present more than once (which it shouldn't be) - for (i=0; i<6; i++) { - if (0 != k && _keyReport.keys[i] == k) { - _keyReport.keys[i] = 0x00; - } - } - - sendReport(&_keyReport); - return 1; -} - -void Keyboard_::releaseAll(void) -{ - _keyReport.keys[0] = 0; - _keyReport.keys[1] = 0; - _keyReport.keys[2] = 0; - _keyReport.keys[3] = 0; - _keyReport.keys[4] = 0; - _keyReport.keys[5] = 0; - _keyReport.modifiers = 0; - sendReport(&_keyReport); -} - -size_t Keyboard_::write(uint8_t c) -{ - uint8_t p = 0; - - p = press(c); // Keydown - release(c); // Keyup - - return (p); // Just return the result of press() since release() almost always returns 1 -} - -#endif diff --git a/cores/arduino/USB/PluggableUSB.cpp b/cores/arduino/USB/PluggableUSB.cpp new file mode 100644 index 000000000..84d781d81 --- /dev/null +++ b/cores/arduino/USB/PluggableUSB.cpp @@ -0,0 +1,98 @@ +/* + PluggableUSB.cpp + Copyright (c) 2015 Arduino LLC + + 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. + + 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 +*/ + +#include "USBAPI.h" +#include "USBDesc.h" +#include "PluggableUSB.h" + +#ifdef PLUGGABLE_USB_ENABLED + +#define MAX_MODULES 6 + +static uint8_t lastIf = CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT; +static uint8_t lastEp = CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT; + +extern uint32_t EndPoints[]; + +//PUSBCallbacks cbs[MAX_MODULES]; +static uint8_t modules_count = 0; + +static PUSBListNode* rootNode = NULL; + +int PUSB_GetInterface(uint8_t* interfaceNum) +{ + int ret = 0; + PUSBListNode* node = rootNode; + for (uint8_t i=0; icb->getInterface(interfaceNum); + node = node->next; + } + return ret; +} + +int PUSB_GetDescriptor(int8_t t) +{ + int ret = 0; + PUSBListNode* node = rootNode; + for (uint8_t i=0; icb->getDescriptor(t); + node = node->next; + } + return ret; +} + +bool PUSB_Setup(USBSetup& setup, uint8_t j) +{ + bool ret = false; + PUSBListNode* node = rootNode; + for (uint8_t i=0; icb->setup(setup, j); + node = node->next; + } + return ret; +} + +int8_t PUSB_AddFunction(PUSBListNode *node, uint8_t* interface) +{ + if (modules_count >= MAX_MODULES) { + return 0; + } + + if (modules_count == 0) { + rootNode = node; + } else { + PUSBListNode *current = rootNode; + while(current->next != NULL) { + current = current->next; + } + current->next = node; + } + + *interface = lastIf; + lastIf += node->cb->numInterfaces; + for ( uint8_t i = 0; i< node->cb->numEndpoints; i++) { + EndPoints[lastEp] = node->cb->endpointType[i]; + lastEp++; + } + modules_count++; + return lastEp - node->cb->numEndpoints; + // restart USB layer??? +} + +#endif \ No newline at end of file diff --git a/cores/arduino/USB/PluggableUSB.h b/cores/arduino/USB/PluggableUSB.h new file mode 100644 index 000000000..205900550 --- /dev/null +++ b/cores/arduino/USB/PluggableUSB.h @@ -0,0 +1,63 @@ +/* + PluggableUSB.h + Copyright (c) 2015 Arduino LLC + + 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. + + 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 +*/ + +#ifndef PUSB_h +#define PUSB_h + +#include "USBAPI.h" +#include + +#if defined(USBCON) + +typedef struct __attribute__((packed)) +{ + bool (*setup)(USBSetup& setup, uint8_t i); + int (*getInterface)(uint8_t* interfaceNum); + int (*getDescriptor)(int8_t t); + int8_t numEndpoints; + int8_t numInterfaces; + uint8_t *endpointType; +} PUSBCallbacks; + +typedef struct +{ + uint8_t interface; + uint8_t firstEndpoint; +} PUSBReturn; + +class PUSBListNode { +public: + PUSBListNode *next = NULL; + PUSBCallbacks *cb; + PUSBListNode(PUSBCallbacks *ncb) {cb = ncb;} +}; + +int8_t PUSB_AddFunction(PUSBListNode *node, uint8_t *interface); + +int PUSB_GetInterface(uint8_t* interfaceNum); + +int PUSB_GetDescriptor(int8_t t); + +bool PUSB_Setup(USBSetup& setup, uint8_t i); + +void PUSB_Begin(); + +#endif + +#endif diff --git a/cores/arduino/USB/USBAPI.h b/cores/arduino/USB/USBAPI.h index bbb0a3e03..e92f9f8c2 100644 --- a/cores/arduino/USB/USBAPI.h +++ b/cores/arduino/USB/USBAPI.h @@ -50,7 +50,7 @@ typedef struct { uint8_t wValueH; uint16_t wIndex; uint16_t wLength; -} Setup; +} USBSetup; class USBDeviceClass { public: @@ -66,19 +66,23 @@ class USBDeviceClass { bool connected(); // Setup API - bool handleClassInterfaceSetup(Setup &setup); - bool handleStandardSetup(Setup &setup); - bool sendDescriptor(Setup &setup); + bool handleClassInterfaceSetup(USBSetup &setup); + bool handleStandardSetup(USBSetup &setup); + bool sendDescriptor(USBSetup &setup); // Control EndPoint API uint32_t sendControl(const void *data, uint32_t len); uint32_t recvControl(void *data, uint32_t len); - bool sendConfiguration(uint32_t maxlen); + uint32_t sendConfiguration(uint32_t maxlen); bool sendStringDescriptor(const uint8_t *string, uint8_t maxlen); + void initControl(int end); + uint8_t SendInterfaces(uint32_t* total); // Generic EndPoint API + void initEndpoints(void); void initEP(uint32_t ep, uint32_t type); void handleEndpoint(uint8_t ep); + uint16_t packMessages(bool val); uint32_t send(uint32_t ep, const void *data, uint32_t len); void sendZlp(uint32_t ep); @@ -127,126 +131,24 @@ class Serial_ : public Stream }; extern Serial_ SerialUSB; -//================================================================================ -//================================================================================ -// Mouse - -#define MOUSE_LEFT 1 -#define MOUSE_RIGHT 2 -#define MOUSE_MIDDLE 4 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) - -class Mouse_ -{ -private: - uint8_t _buttons; - void buttons(uint8_t b); -public: - Mouse_(void); - void begin(void); - void end(void); - void click(uint8_t b = MOUSE_LEFT); - void move(signed char x, signed char y, signed char 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_ALL); // check all buttons by default -}; -extern Mouse_ Mouse; - -//================================================================================ -//================================================================================ -// Keyboard - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 - -#define KEY_UP_ARROW 0xDA -#define KEY_DOWN_ARROW 0xD9 -#define KEY_LEFT_ARROW 0xD8 -#define KEY_RIGHT_ARROW 0xD7 -#define KEY_BACKSPACE 0xB2 -#define KEY_TAB 0xB3 -#define KEY_RETURN 0xB0 -#define KEY_ESC 0xB1 -#define KEY_INSERT 0xD1 -#define KEY_DELETE 0xD4 -#define KEY_PAGE_UP 0xD3 -#define KEY_PAGE_DOWN 0xD6 -#define KEY_HOME 0xD2 -#define KEY_END 0xD5 -#define KEY_CAPS_LOCK 0xC1 -#define KEY_F1 0xC2 -#define KEY_F2 0xC3 -#define KEY_F3 0xC4 -#define KEY_F4 0xC5 -#define KEY_F5 0xC6 -#define KEY_F6 0xC7 -#define KEY_F7 0xC8 -#define KEY_F8 0xC9 -#define KEY_F9 0xCA -#define KEY_F10 0xCB -#define KEY_F11 0xCC -#define KEY_F12 0xCD - -// Low level key report: up to 6 keys and shift, ctrl etc at once -typedef struct -{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; -} KeyReport; - -class Keyboard_ : public Print -{ -private: - KeyReport _keyReport; - void sendReport(KeyReport* keys); -public: - Keyboard_(void); - void begin(void); - void end(void); - virtual size_t write(uint8_t k); - virtual size_t press(uint8_t k); - virtual size_t release(uint8_t k); - virtual void releaseAll(void); -}; -extern Keyboard_ Keyboard; - -//================================================================================ -//================================================================================ -// HID 'Driver' - -const void* HID_GetInterface(void); -uint32_t HID_GetInterfaceLength(void); -uint32_t HID_SizeReportDescriptor(void); - -uint32_t HID_GetDescriptor(void); -bool HID_Setup(Setup& setup); -void HID_SendReport(uint8_t id, const void* data, uint32_t len); - //================================================================================ //================================================================================ // MSC 'Driver' uint32_t MSC_GetInterface(uint8_t* interfaceNum); uint32_t MSC_GetDescriptor(uint32_t i); -bool MSC_Setup(Setup& setup); +bool MSC_Setup(USBSetup& setup); bool MSC_Data(uint8_t rx,uint8_t tx); //================================================================================ //================================================================================ // CDC 'Driver' -const void* CDC_GetInterface(/*uint8_t* interfaceNum*/); -uint32_t CDC_GetInterfaceLength(void); +int CDC_GetInterface(uint8_t* interfaceNum); +const void* _CDC_GetInterface(void); +uint32_t _CDC_GetInterfaceLength(void); uint32_t CDC_GetOtherInterface(uint8_t* interfaceNum); uint32_t CDC_GetDescriptor(uint32_t i); -bool CDC_Setup(Setup& setup); +bool CDC_Setup(USBSetup& setup); #endif // __cplusplus diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 99009e835..586ddf08b 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -19,10 +19,12 @@ #include #include "SAMD21_USBDevice.h" +#include "PluggableUSB.h" #include #include #include +#include USBDevice_SAMD21G18x usbd; @@ -64,13 +66,8 @@ const uint8_t STRING_MANUFACTURER[] = USB_MANUFACTURER; // DEVICE DESCRIPTOR -#if (defined CDC_ENABLED) && defined(HID_ENABLED) -const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); -#elif defined(CDC_ENABLED) // CDC only -const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x02, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); -#else // HID only +const DeviceDescriptor USB_DeviceDescriptorB = D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); -#endif //================================================================== @@ -107,79 +104,72 @@ bool USBDeviceClass::sendStringDescriptor(const uint8_t *string, uint8_t maxlen) return USBDevice.sendControl((uint8_t*)buff, l*2); } -// Construct a dynamic configuration descriptor -// This really needs dynamic endpoint allocation etc -bool USBDeviceClass::sendConfiguration(uint32_t maxlen) +bool _dry_run = false; +bool _pack_message = false; +uint16_t _pack_size = 0; +uint8_t _pack_buffer[256]; + +uint16_t USBDeviceClass::packMessages(bool val) { - uint8_t cache_buffer[128]; - uint8_t i; + if (val) { + _pack_message = true; + _pack_size = 0; + } else { + _pack_message = false; + sendControl(_pack_buffer, _pack_size); + } +} - const uint8_t* interfaces; - uint32_t interfaces_length = 0; - uint8_t num_interfaces[1]; +uint8_t USBDeviceClass::SendInterfaces(uint32_t* total) +{ + uint8_t interfaces = 0; - num_interfaces[0] = 0; +#if defined(CDC_ENABLED) + total[0] += CDC_GetInterface(&interfaces); +#endif -#if defined(CDC_ENABLED) && defined(HID_ENABLED) - num_interfaces[0] += 3; - interfaces = (const uint8_t*) CDC_GetInterface(); - interfaces_length = CDC_GetInterfaceLength() + HID_GetInterfaceLength(); - if (maxlen > CDC_GetInterfaceLength() + HID_GetInterfaceLength() + sizeof(ConfigDescriptor)) - { - maxlen = CDC_GetInterfaceLength() + HID_GetInterfaceLength() + sizeof(ConfigDescriptor); - } -#elif defined(CDC_ENABLED) - num_interfaces[0] += 2; - interfaces = (const uint8_t*) CDC_GetInterface(); - interfaces_length += CDC_GetInterfaceLength(); - if (maxlen > CDC_GetInterfaceLength() + sizeof(ConfigDescriptor)) - { - maxlen = CDC_GetInterfaceLength() + sizeof(ConfigDescriptor); - } -#elif defined(HID_ENABLED) - num_interfaces[0] += 1; - interfaces = (const uint8_t*) HID_GetInterface(); - interfaces_length += HID_GetInterfaceLength(); - if (maxlen > HID_GetInterfaceLength() + sizeof(ConfigDescriptor)) - { - maxlen = HID_GetInterfaceLength() + sizeof(ConfigDescriptor); - } +#ifdef PLUGGABLE_USB_ENABLED + total[0] += PUSB_GetInterface(&interfaces); #endif -_Pragma("pack(1)") - ConfigDescriptor config = D_CONFIG((uint16_t)(interfaces_length + sizeof(ConfigDescriptor)), num_interfaces[0]); -_Pragma("pack()") + return interfaces; +} - memcpy(cache_buffer, &config, sizeof(ConfigDescriptor)); +// Construct a dynamic configuration descriptor +// This really needs dynamic endpoint allocation etc +uint32_t USBDeviceClass::sendConfiguration(uint32_t maxlen) +{ + uint32_t total = 0; + // Count and measure interfaces + _dry_run = true; + uint8_t interfaces = SendInterfaces(&total); -#if defined(CDC_ENABLED) && defined(HID_ENABLED) - for (i=0; i sizeof(cache_buffer)) { - maxlen = sizeof(cache_buffer); + // Now send them + _dry_run = false; + + if (maxlen == sizeof(ConfigDescriptor)) { + sendControl(&config, sizeof(ConfigDescriptor)); + return true; } - return sendControl(cache_buffer, maxlen); + + packMessages(true); + sendControl(&config, sizeof(ConfigDescriptor)); + SendInterfaces(&total); + packMessages(false); + + return true; } -bool USBDeviceClass::sendDescriptor(Setup &setup) +bool USBDeviceClass::sendDescriptor(USBSetup &setup) { uint8_t t = setup.wValueH; uint8_t desc_length = 0; + bool _cdcComposite; + int ret; const uint8_t *desc_addr = 0; if (t == USB_CONFIGURATION_DESCRIPTOR_TYPE) @@ -187,22 +177,20 @@ bool USBDeviceClass::sendDescriptor(Setup &setup) return USBDevice.sendConfiguration(setup.wLength); } -#if defined(HID_ENABLED) - if (t == HID_REPORT_DESCRIPTOR_TYPE) - { - return HID_GetDescriptor(); - } - - if (t == HID_HID_DESCRIPTOR_TYPE) - { - uint8_t tab[9] = D_HIDREPORT((uint8_t)HID_SizeReportDescriptor()); - return USBDevice.sendControl(tab, sizeof(tab)); +#ifdef PLUGGABLE_USB_ENABLED + ret = PUSB_GetDescriptor(t); + if (ret != 0) { + return (ret > 0 ? true : false); } #endif if (t == USB_DEVICE_DESCRIPTOR_TYPE) { - desc_addr = (const uint8_t*)&USB_DeviceDescriptor; + if (setup.wLength == 8) + _cdcComposite = 1; + + desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptorB : (const uint8_t*)&USB_DeviceDescriptor; + if (*desc_addr > setup.wLength) { desc_length = setup.wLength; } @@ -269,7 +257,7 @@ void USBDeviceClass::handleEndpoint(uint8_t ep) } #endif -#if defined(HID_ENABLED) +#if defined(PLUGGABLE_USB_ENABLED) // Empty #endif } @@ -355,7 +343,7 @@ bool USBDeviceClass::configured() return _usbConfiguration != 0; } -bool USBDeviceClass::handleClassInterfaceSetup(Setup& setup) +bool USBDeviceClass::handleClassInterfaceSetup(USBSetup& setup) { uint8_t i = setup.wIndex; @@ -369,19 +357,44 @@ bool USBDeviceClass::handleClassInterfaceSetup(Setup& setup) } #endif - #if defined(HID_ENABLED) - if (HID_INTERFACE == i) - { - if (HID_Setup(setup) == false) { - sendZlp(0); - } - return true; + #if defined(PLUGGABLE_USB_ENABLED) + bool ret = PUSB_Setup(setup, i); + if ( ret == false) { + sendZlp(0); } + return ret; #endif return false; } +uint32_t EndPoints[] = +{ + USB_ENDPOINT_TYPE_CONTROL, + +#ifdef CDC_ENABLED + USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_ACM + USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0), // CDC_ENDPOINT_OUT + USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_IN +#endif + +#ifdef PLUGGABLE_USB_ENABLED + //allocate 6 endpoints and remove const so they can be changed by the user + 0, + 0, + 0, + 0, + 0, + 0, +#endif +}; + +void USBDeviceClass::initEndpoints() { + for (uint8_t i = 1; i < sizeof(EndPoints) && EndPoints[i] != 0; i++) { + initEP(i, EndPoints[i]); + } +} + void USBDeviceClass::initEP(uint32_t ep, uint32_t config) { if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0))) @@ -638,6 +651,15 @@ uint32_t USBDeviceClass::sendControl(const void* _data, uint32_t len) uint32_t sent = 0; uint32_t pos = 0; + if (_dry_run == true) + return length; + + if (_pack_message == true) { + memcpy(&_pack_buffer[_pack_size], data, len); + _pack_size += len; + return length; + } + while (len > 0) { sent = armSend(EP0, data + pos, len); @@ -654,7 +676,7 @@ void USBDeviceClass::sendZlp(uint32_t ep) usbd.epBank1SetByteCount(ep, 0); } -bool USBDeviceClass::handleStandardSetup(Setup &setup) +bool USBDeviceClass::handleStandardSetup(USBSetup &setup) { switch (setup.bRequest) { case GET_STATUS: @@ -731,15 +753,8 @@ bool USBDeviceClass::handleStandardSetup(Setup &setup) case SET_CONFIGURATION: if (REQUEST_DEVICE == (setup.bmRequestType & REQUEST_RECIPIENT)) { - #if defined(HID_ENABLED) - initEP(HID_ENDPOINT_INT, USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)); - #endif - #if defined(CDC_ENABLED) - initEP(CDC_ENDPOINT_ACM, USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)); - initEP(CDC_ENDPOINT_OUT, USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0)); - initEP(CDC_ENDPOINT_IN, USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)); - #endif + initEndpoints(); _usbConfiguration = setup.wValueL; #if defined(CDC_ENABLED) @@ -770,6 +785,10 @@ bool USBDeviceClass::handleStandardSetup(Setup &setup) void USBDeviceClass::ISRHandler() { + + if (_pack_message == true) { + return; + } // End-Of-Reset if (usbd.isEndOfResetInterrupt()) { @@ -795,7 +814,7 @@ void USBDeviceClass::ISRHandler() { usbd.epBank0AckSetupReceived(0); - Setup *setup = reinterpret_cast(udd_ep_out_cache_buffer[0]); + USBSetup *setup = reinterpret_cast(udd_ep_out_cache_buffer[0]); /* Clear the Bank 0 ready flag on Control OUT */ // The RAM Buffer is empty: we can receive data diff --git a/cores/arduino/USB/USBCore.h b/cores/arduino/USB/USBCore.h index d584fdfc9..0d2dc7854 100644 --- a/cores/arduino/USB/USBCore.h +++ b/cores/arduino/USB/USBCore.h @@ -70,13 +70,6 @@ #define MSC_RESET 0xFF #define MSC_GET_MAX_LUN 0xFE -#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 - // Descriptors // #define USB_DEVICE_DESC_SIZE 18 @@ -120,10 +113,6 @@ #define MSC_SUBCLASS_SCSI 0x06 #define MSC_PROTOCOL_BULK_ONLY 0x50 -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - _Pragma("pack(1)") // Device @@ -234,10 +223,8 @@ typedef struct typedef struct { -#if (defined CDC_ENABLED) && defined(HID_ENABLED) // IAD IADDescriptor iad; // Only needed on compound device -#endif // Control InterfaceDescriptor cif; CDCCSInterfaceDescriptor header; @@ -259,26 +246,6 @@ typedef struct EndpointDescriptor out; } MSCDescriptor; -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; - _Pragma("pack()") #define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ @@ -308,10 +275,6 @@ _Pragma("pack()") { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } /* iadclasscode_r10.pdf, Table 9–Z. Standard Interface Association Descriptor * bLength, bDescriptorType, bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol, iFunction */ -#define D_HIDREPORT(_descriptorLength) \ - { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } -/* HID1_11.pdf E.8 HID Descriptor (Mouse) - * bLength, bDescriptorType, bcdHID, bCountryCode, bNumDescriptors, bDescriptorType, wItemLength */ // Functional Descriptor General Format #define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } diff --git a/cores/arduino/USB/USBDesc.h b/cores/arduino/USB/USBDesc.h index 655fb6d01..2282a7182 100644 --- a/cores/arduino/USB/USBDesc.h +++ b/cores/arduino/USB/USBDesc.h @@ -21,18 +21,25 @@ // CDC or HID can be enabled together. #define CDC_ENABLED -#define HID_ENABLED +#define PLUGGABLE_USB_ENABLED + +#ifdef CDC_ENABLED +#define CDC_INTERFACE_COUNT 2 +#define CDC_ENPOINT_COUNT 3 +#endif // CDC #define CDC_ACM_INTERFACE 0 // CDC ACM #define CDC_DATA_INTERFACE 1 // CDC Data +#define CDC_FIRST_ENDPOINT 1 #define CDC_ENDPOINT_ACM 1 #define CDC_ENDPOINT_OUT 2 #define CDC_ENDPOINT_IN 3 -// HID -#define HID_INTERFACE 2 // HID -#define HID_ENDPOINT_INT 4 +#ifdef CDC_ENABLED +#define CDC_RX CDC_ENDPOINT_OUT +#define CDC_TX CDC_ENDPOINT_IN +#endif // Defined string description #define IMANUFACTURER 1 diff --git a/cores/arduino/USB/samd21_host.c b/cores/arduino/USB/samd21_host.c index cc9062fe6..8bde134fa 100644 --- a/cores/arduino/USB/samd21_host.c +++ b/cores/arduino/USB/samd21_host.c @@ -298,7 +298,7 @@ uhd_vbus_state_t UHD_GetVBUSState(void) * \retval 0 success. * \retval 1 error. */ -uint32_t UHD_Pipe0_Alloc(uint32_t /* ul_add */, uint32_t ul_ep_size) +uint32_t UHD_Pipe0_Alloc(uint32_t ul_add , uint32_t ul_ep_size) { if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) ) ul_ep_size = USB_PCKSIZE_SIZE_8_BYTES; // Low Speed diff --git a/libraries/HID/HID.cpp b/libraries/HID/HID.cpp new file mode 100644 index 000000000..2679faa54 --- /dev/null +++ b/libraries/HID/HID.cpp @@ -0,0 +1,176 @@ +/* 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 "USB/PluggableUSB.h" +#include "HID.h" + +HID_ HID; + +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) +{ + 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) + }; + return USBDevice.sendControl(&_hidInterface,sizeof(_hidInterface)); +} + +int HID_GetDescriptor(int8_t t) +{ + if (HID_REPORT_DESCRIPTOR_TYPE == t) { + HIDDescriptorListNode* current = rootNode; + int total = 0; + while(current != NULL) { + total += USBDevice.sendControl(current->cb->descriptor,current->cb->length); + current = current->next; + } + return total; + } else { + return 0; + } +} + +void HID_::AppendDescriptor(HIDDescriptorListNode *node) +{ + if (modules_count == 0) { + rootNode = node; + } else { + HIDDescriptorListNode *current = rootNode; + while(current->next != NULL) { + current = current->next; + } + current->next = node; + } + modules_count++; + sizeof_hidReportDescriptor += node->cb->length; +} + +void HID_::SendReport(uint8_t id, const void* data, int len) +{ + uint8_t p[8]; + const uint8_t *d = reinterpret_cast(data); + + p[0] = id; + for (uint32_t i=0; i +#include + +#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 + +typedef struct __attribute__((packed)) { + uint8_t length; + const void* descriptor; +} HID_Descriptor; + +class HIDDescriptorListNode { +public: + HIDDescriptorListNode *next = NULL; + const HID_Descriptor * cb; + HIDDescriptorListNode(const HID_Descriptor *ncb) {cb = ncb;} +}; + +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 + 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; + +#define HID_TX HID_ENDPOINT_INT + +#define D_HIDREPORT(_descriptorLength) \ + { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } + +#define WEAK __attribute__ ((weak)) + +#endif \ No newline at end of file diff --git a/libraries/HID/keywords.txt b/libraries/HID/keywords.txt new file mode 100644 index 000000000..32a9ba5f2 --- /dev/null +++ b/libraries/HID/keywords.txt @@ -0,0 +1,21 @@ +####################################### +# Syntax Coloring Map HID +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +HID KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +SendReport KEYWORD2 +AppendDescriptor KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +HID_TX LITERAL1 \ No newline at end of file diff --git a/libraries/HID/library.properties b/libraries/HID/library.properties new file mode 100644 index 000000000..b175b1ede --- /dev/null +++ b/libraries/HID/library.properties @@ -0,0 +1,8 @@ +name=HID +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Module for PluggableUSB infrastructure. Exposes an API for devices like Keyboards, Mice and Gamepads +paragraph= +url=http://www.arduino.cc/en/Reference/HID +architectures=samd \ No newline at end of file