diff --git a/hardware/arduino/sam/cores/arduino/USB/CDC.cpp b/hardware/arduino/sam/cores/arduino/USB/CDC.cpp index 0f15d82a1..306c124ff 100644 --- a/hardware/arduino/sam/cores/arduino/USB/CDC.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/CDC.cpp @@ -17,6 +17,7 @@ #include "Arduino.h" #include "USBAPI.h" #include "Reset.h" +#include "Print.h" #ifdef CDC_ENABLED @@ -103,7 +104,7 @@ int WEAK CDC_GetOtherInterface(uint8_t* interfaceNum) return USBD_SendControl(0,&_cdcOtherInterface,sizeof(_cdcOtherInterface)); } -bool WEAK CDC_Setup(Setup& setup) +bool WEAK CDC_Setup(USBSetup& setup) { uint8_t r = setup.bRequest; uint8_t requestType = setup.bmRequestType; diff --git a/hardware/arduino/sam/cores/arduino/USB/HID.cpp b/hardware/arduino/sam/cores/arduino/USB/HID.cpp deleted file mode 100644 index c243f4951..000000000 --- a/hardware/arduino/sam/cores/arduino/USB/HID.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* 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 "Arduino.h" - -#ifdef HID_ENABLED - -//#define RAWHID_ENABLED - -// Singletons for mouse and keyboard - -Mouse_ Mouse; -Keyboard_ Keyboard; - -//================================================================================ -//================================================================================ - -// 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 - -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 -}; - -_Pragma("pack(1)") -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; - -#define WEAK __attribute__ ((weak)) - -int WEAK HID_GetInterface(uint8_t* interfaceNum) -{ - interfaceNum[0] += 1; // uses 1 - return USBD_SendControl(0,&_hidInterface,sizeof(_hidInterface)); -} - -int WEAK HID_GetDescriptor(int i) -{ - return USBD_SendControl(0,_hidReportDescriptor,sizeof(_hidReportDescriptor)); -} - -void WEAK HID_SendReport(uint8_t id, const void* data, uint32_t len) -{ - uint8_t p[64]; - 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 -}; - -uint8_t USBPutChar(uint8_t c); - -// 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/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.cpp b/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.cpp new file mode 100644 index 000000000..84d781d81 --- /dev/null +++ b/hardware/arduino/sam/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/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.h b/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.h new file mode 100644 index 000000000..502da9ebc --- /dev/null +++ b/hardware/arduino/sam/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; + uint32_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/hardware/arduino/sam/cores/arduino/USB/USBAPI.h b/hardware/arduino/sam/cores/arduino/USB/USBAPI.h index eda623ddb..97e8ad6fe 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBAPI.h +++ b/hardware/arduino/sam/cores/arduino/USB/USBAPI.h @@ -22,6 +22,10 @@ #if defined __cplusplus #include "RingBuffer.h" +#include "Stream.h" +#include + +#define min(a, b) Min(a, b) //================================================================================ //================================================================================ @@ -86,97 +90,6 @@ public: }; 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; - //================================================================================ //================================================================================ // Low level API @@ -189,16 +102,7 @@ typedef struct uint8_t wValueH; uint16_t wIndex; uint16_t wLength; -} Setup; - -//================================================================================ -//================================================================================ -// HID 'Driver' - -int HID_GetInterface(uint8_t* interfaceNum); -int HID_GetDescriptor(int i); -bool HID_Setup(Setup& setup); -void HID_SendReport(uint8_t id, const void* data, uint32_t len); +} USBSetup; //================================================================================ //================================================================================ @@ -206,7 +110,7 @@ void HID_SendReport(uint8_t id, const void* data, uint32_t len); int MSC_GetInterface(uint8_t* interfaceNum); int MSC_GetDescriptor(int i); -bool MSC_Setup(Setup& setup); +bool MSC_Setup(USBSetup& setup); bool MSC_Data(uint8_t rx,uint8_t tx); //================================================================================ @@ -216,7 +120,7 @@ bool MSC_Data(uint8_t rx,uint8_t tx); int CDC_GetInterface(uint8_t* interfaceNum); int CDC_GetOtherInterface(uint8_t* interfaceNum); int CDC_GetDescriptor(int i); -bool CDC_Setup(Setup& setup); +bool CDC_Setup(USBSetup& setup); //================================================================================ //================================================================================ @@ -228,7 +132,7 @@ void USBD_InitControl(int end); int USBD_SendControl(uint8_t flags, const void* d, uint32_t len); int USBD_RecvControl(void* d, uint32_t len); int USBD_SendInterfaces(void); -bool USBD_ClassInterfaceRequest(Setup& setup); +bool USBD_ClassInterfaceRequest(USBSetup& setup); uint32_t USBD_Available(uint32_t ep); diff --git a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp index c21fda7f4..3fc6e43d6 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp @@ -18,11 +18,13 @@ #include "USBAPI.h" #include "Reset.h" #include +#include "PluggableUSB.h" +#include //#define TRACE_CORE(x) x #define TRACE_CORE(x) -static const uint32_t EndPoints[] = +uint32_t EndPoints[] = { EP_TYPE_CONTROL, @@ -32,8 +34,14 @@ static const uint32_t EndPoints[] = EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN #endif -#ifdef HID_ENABLED - EP_TYPE_INTERRUPT_IN_HID // HID_ENDPOINT_INT +#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 }; @@ -91,7 +99,7 @@ const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); const DeviceDescriptor USB_DeviceDescriptorA = - D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); + D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); const DeviceDescriptor USB_DeviceQualifier = D_QUALIFIER(0x00,0x00,0x00,64,1); @@ -274,7 +282,7 @@ int USBD_RecvControl(void* d, uint32_t len) } // Handle CLASS_INTERFACE requests -bool USBD_ClassInterfaceRequest(Setup& setup) +bool USBD_ClassInterfaceRequest(USBSetup& setup) { uint8_t i = setup.wIndex; @@ -287,11 +295,8 @@ bool USBD_ClassInterfaceRequest(Setup& setup) } #endif -#ifdef HID_ENABLED - if (HID_INTERFACE == i) - { - return HID_Setup(setup); - } +#ifdef PLUGGABLE_USB_ENABLED + return PUSB_Setup(setup, i); #endif return false; @@ -299,37 +304,33 @@ bool USBD_ClassInterfaceRequest(Setup& setup) int USBD_SendInterfaces(void) { - int total = 0; uint8_t interfaces = 0; #ifdef CDC_ENABLED - total = CDC_GetInterface(&interfaces); + CDC_GetInterface(&interfaces); #endif -#ifdef HID_ENABLED - total += HID_GetInterface(&interfaces); +#ifdef PLUGGABLE_USB_ENABLED + PUSB_GetInterface(&interfaces); #endif - total = total; // Get rid of compiler warning - TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);) + TRACE_CORE(printf("=> USBD_SendInterfaces, interfaces=%d\r\n", interfaces);) return interfaces; } int USBD_SendOtherInterfaces(void) { - int total = 0; uint8_t interfaces = 0; #ifdef CDC_ENABLED - total = CDC_GetOtherInterface(&interfaces); + CDC_GetOtherInterface(&interfaces); #endif -#ifdef HID_ENABLED - total += HID_GetInterface(&interfaces); +#ifdef PLUGGABLE_USB_ENABLED + PUSB_GetInterface(&interfaces); #endif - total = total; // Get rid of compiler warning - TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);) + TRACE_CORE(printf("=> USBD_SendInterfaces, interfaces=%d\r\n", interfaces);) return interfaces; } @@ -382,10 +383,11 @@ _Pragma("pack()") return true; } -static bool USBD_SendDescriptor(Setup& setup) +static bool USBD_SendDescriptor(USBSetup& setup) { uint8_t t = setup.wValueH; uint8_t desc_length = 0; + int ret = 0; const uint8_t* desc_addr = 0; if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) @@ -395,11 +397,11 @@ static bool USBD_SendDescriptor(Setup& setup) } USBD_InitControl(setup.wLength); -#ifdef HID_ENABLED - if (HID_REPORT_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(puts("=> USBD_SendDescriptor : HID_REPORT_DESCRIPTOR_TYPE\r\n");) - return HID_GetDescriptor(t); + +#ifdef PLUGGABLE_USB_ENABLED + ret = PUSB_GetDescriptor(t); + if (ret != 0) { + return (ret > 0 ? true : false); } #endif @@ -640,7 +642,7 @@ static void USB_ISR(void) return; } - Setup setup; + USBSetup setup; UDD_Recv(EP0, (uint8_t*)&setup, 8); UDD_ClearSetupInt(); @@ -765,7 +767,11 @@ static void USB_ISR(void) { TRACE_CORE(printf(">>> EP0 Int: SET_CONFIGURATION REQUEST_DEVICE %d\r\n", setup.wValueL);) - UDD_InitEndpoints(EndPoints, (sizeof(EndPoints) / sizeof(EndPoints[0]))); + uint32_t num_endpoints = 0; + while (EndPoints[num_endpoints] != 0) { + num_endpoints++; + } + UDD_InitEndpoints(EndPoints, num_endpoints); _usbConfiguration = setup.wValueL; #ifdef CDC_ENABLED diff --git a/hardware/arduino/sam/cores/arduino/USB/USBCore.h b/hardware/arduino/sam/cores/arduino/USB/USBCore.h index b01d7576a..c522d4482 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBCore.h +++ b/hardware/arduino/sam/cores/arduino/USB/USBCore.h @@ -58,13 +58,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 @@ -121,10 +114,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 @@ -259,26 +248,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) \ @@ -302,9 +271,6 @@ _Pragma("pack()") #define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } -#define D_HIDREPORT(_descriptorLength) \ - { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } - #define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } #define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } diff --git a/hardware/arduino/sam/cores/arduino/USB/USBDesc.h b/hardware/arduino/sam/cores/arduino/USB/USBDesc.h index 878095e24..389967cf9 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBDesc.h +++ b/hardware/arduino/sam/cores/arduino/USB/USBDesc.h @@ -18,7 +18,7 @@ #define __USBDESC_H__ #define CDC_ENABLED -#define HID_ENABLED +#define PLUGGABLE_USB_ENABLED #ifdef CDC_ENABLED #define CDC_INTERFACE_COUNT 2 @@ -28,14 +28,6 @@ #define CDC_ENPOINT_COUNT 0 #endif -#ifdef HID_ENABLED -#define HID_INTERFACE_COUNT 1 -#define HID_ENPOINT_COUNT 1 -#else -#define HID_INTERFACE_COUNT 0 -#define HID_ENPOINT_COUNT 0 -#endif - #define CDC_ACM_INTERFACE 0 // CDC ACM #define CDC_DATA_INTERFACE 1 // CDC Data #define CDC_FIRST_ENDPOINT 1 @@ -43,10 +35,6 @@ #define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1) #define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2) -#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface -#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT) -#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT) - #define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT) #ifdef CDC_ENABLED @@ -54,10 +42,6 @@ #define CDC_TX CDC_ENDPOINT_IN #endif -#ifdef HID_ENABLED -#define HID_TX HID_ENDPOINT_INT -#endif - #define IMANUFACTURER 1 #define IPRODUCT 2 diff --git a/hardware/arduino/sam/libraries/HID/HID.cpp b/hardware/arduino/sam/libraries/HID/HID.cpp new file mode 100644 index 000000000..935039096 --- /dev/null +++ b/hardware/arduino/sam/libraries/HID/HID.cpp @@ -0,0 +1,168 @@ +/* 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 USBD_SendControl(0,&_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 += USBD_SendControl(0,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[64]; + 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/hardware/arduino/sam/libraries/HID/keywords.txt b/hardware/arduino/sam/libraries/HID/keywords.txt new file mode 100644 index 000000000..32a9ba5f2 --- /dev/null +++ b/hardware/arduino/sam/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/hardware/arduino/sam/libraries/HID/library.properties b/hardware/arduino/sam/libraries/HID/library.properties new file mode 100644 index 000000000..5114f1bc5 --- /dev/null +++ b/hardware/arduino/sam/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=sam \ No newline at end of file