diff --git a/hardware/arduino/sam/cores/arduino/USB/CDC.cpp b/hardware/arduino/sam/cores/arduino/USB/CDC.cpp index 4d646e723..ae1a4e150 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/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..205900550 --- /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; + 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/hardware/arduino/sam/cores/arduino/USB/USBAPI.h b/hardware/arduino/sam/cores/arduino/USB/USBAPI.h index 3cf601e9e..e79e77fe7 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) //================================================================================ //================================================================================ @@ -64,97 +68,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 @@ -167,16 +80,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; //================================================================================ //================================================================================ @@ -184,7 +88,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); //================================================================================ @@ -194,7 +98,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); //================================================================================ //================================================================================ @@ -206,7 +110,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