diff --git a/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.cpp b/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.cpp index 84d781d81..0f2d08c0d 100644 --- a/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.cpp @@ -19,80 +19,89 @@ #include "USBAPI.h" #include "USBDesc.h" +#include "USBCore.h" #include "PluggableUSB.h" +#if defined(USBCON) #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 PluggableUSB_::getInterface(uint8_t* interfaceCount) { - int ret = 0; - PUSBListNode* node = rootNode; - for (uint8_t i=0; icb->getInterface(interfaceNum); - node = node->next; + int sent = 0; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) { + int res = node->getInterface(interfaceCount); + if (res < 0) + return -1; + sent += res; } - return ret; + return sent; } -int PUSB_GetDescriptor(int8_t t) +int PluggableUSB_::getDescriptor(USBSetup& setup) { - int ret = 0; - PUSBListNode* node = rootNode; - for (uint8_t i=0; icb->getDescriptor(t); - node = node->next; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) { + int ret = node->getDescriptor(setup); + // ret!=0 -> request has been processed + if (ret) + return ret; } - return ret; + return 0; } -bool PUSB_Setup(USBSetup& setup, uint8_t j) +bool PluggableUSB_::setup(USBSetup& setup) { - bool ret = false; - PUSBListNode* node = rootNode; - for (uint8_t i=0; icb->setup(setup, j); - node = node->next; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) { + if (node->setup(setup)) { + return true; + } } - return ret; + return false; } -int8_t PUSB_AddFunction(PUSBListNode *node, uint8_t* interface) +bool PluggableUSB_::plug(PluggableUSBModule *node) { - if (modules_count >= MAX_MODULES) { - return 0; + if ((lastEp + node->numEndpoints) > USB_ENDPOINTS) { + return false; } - if (modules_count == 0) { + if (!rootNode) { rootNode = node; } else { - PUSBListNode *current = rootNode; - while(current->next != NULL) { + PluggableUSBModule *current = rootNode; + while (current->next) { 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]; + node->pluggedInterface = lastIf; + node->pluggedEndpoint = lastEp; + lastIf += node->numInterfaces; + for (uint8_t i = 0; i < node->numEndpoints; i++) { + EndPoints[lastEp] = node->endpointType[i]; lastEp++; } - modules_count++; - return lastEp - node->cb->numEndpoints; + return true; // restart USB layer??? } +PluggableUSB_& PluggableUSB() +{ + static PluggableUSB_ obj; + return obj; +} + +PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT), + lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT), + rootNode(NULL) +{ + // Empty +} + +#endif #endif \ 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 index c53aae66f..eb18ca253 100644 --- a/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.h +++ b/hardware/arduino/sam/cores/arduino/USB/PluggableUSB.h @@ -25,30 +25,47 @@ #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; - -class PUSBListNode { +class PluggableUSBModule { public: - PUSBListNode *next = NULL; - PUSBCallbacks *cb; - PUSBListNode(PUSBCallbacks *ncb) {cb = ncb;} + PluggableUSBModule(uint8_t numEps, uint8_t numIfs, uint32_t *epType) : + numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType) + { } + +protected: + virtual bool setup(USBSetup& setup) = 0; + virtual int getInterface(uint8_t* interfaceCount) = 0; + virtual int getDescriptor(USBSetup& setup) = 0; + + uint8_t pluggedInterface; + uint8_t pluggedEndpoint; + + const uint8_t numEndpoints; + const uint8_t numInterfaces; + const uint32_t *endpointType; + + PluggableUSBModule *next = NULL; + + friend class PluggableUSB_; }; -int8_t PUSB_AddFunction(PUSBListNode *node, uint8_t *interface); +class PluggableUSB_ { +public: + PluggableUSB_(); + bool plug(PluggableUSBModule *node); + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); -int PUSB_GetInterface(uint8_t* interfaceNum); +private: + uint8_t lastIf; + uint8_t lastEp; + PluggableUSBModule* rootNode; +}; -int PUSB_GetDescriptor(int8_t t); - -bool PUSB_Setup(USBSetup& setup, uint8_t i); +// Replacement for global singleton. +// This function prevents static-initialization-order-fiasco +// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use +PluggableUSB_& PluggableUSB(); #endif diff --git a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp index 3fc6e43d6..421b48f7e 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp @@ -296,7 +296,7 @@ bool USBD_ClassInterfaceRequest(USBSetup& setup) #endif #ifdef PLUGGABLE_USB_ENABLED - return PUSB_Setup(setup, i); + return PluggableUSB().setup(setup); #endif return false; @@ -311,7 +311,7 @@ int USBD_SendInterfaces(void) #endif #ifdef PLUGGABLE_USB_ENABLED - PUSB_GetInterface(&interfaces); + PluggableUSB().getInterface(&interfaces); #endif TRACE_CORE(printf("=> USBD_SendInterfaces, interfaces=%d\r\n", interfaces);) @@ -327,7 +327,7 @@ int USBD_SendOtherInterfaces(void) #endif #ifdef PLUGGABLE_USB_ENABLED - PUSB_GetInterface(&interfaces); + PluggableUSB().getInterface(&interfaces); #endif TRACE_CORE(printf("=> USBD_SendInterfaces, interfaces=%d\r\n", interfaces);) @@ -399,7 +399,7 @@ static bool USBD_SendDescriptor(USBSetup& setup) USBD_InitControl(setup.wLength); #ifdef PLUGGABLE_USB_ENABLED - ret = PUSB_GetDescriptor(t); + ret = PluggableUSB().getDescriptor(setup); if (ret != 0) { return (ret > 0 ? true : false); } diff --git a/hardware/arduino/sam/cores/arduino/USB/USBCore.h b/hardware/arduino/sam/cores/arduino/USB/USBCore.h index c522d4482..10df90ba7 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBCore.h +++ b/hardware/arduino/sam/cores/arduino/USB/USBCore.h @@ -46,8 +46,9 @@ #define REQUEST_OTHER 0x03 #define REQUEST_RECIPIENT 0x1F -#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE) -#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE) +#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) // Class requests @@ -91,6 +92,8 @@ #define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) #define USB_ENDPOINT_IN(addr) ((addr) | 0x80) +#define USB_ENDPOINTS 7 + #define USB_ENDPOINT_TYPE_MASK 0x03 #define USB_ENDPOINT_TYPE_CONTROL 0x00 #define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01