Skip to content

Port latest and shiniest PluggableUSB API to SAM core #3963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 12, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 52 additions & 43 deletions hardware/arduino/sam/cores/arduino/USB/PluggableUSB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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; i<modules_count; i++) {
ret = node->cb->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; i<modules_count && ret == 0; i++) {
ret = node->cb->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; i<modules_count && ret == false; i++) {
ret = node->cb->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
55 changes: 36 additions & 19 deletions hardware/arduino/sam/cores/arduino/USB/PluggableUSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

int8_t PUSB_AddFunction(PUSBListNode *node, uint8_t *interface);
PluggableUSBModule *next = NULL;

int PUSB_GetInterface(uint8_t* interfaceNum);
friend class PluggableUSB_;
};

class PluggableUSB_ {
public:
PluggableUSB_();
bool plug(PluggableUSBModule *node);
int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup);
bool setup(USBSetup& setup);

int PUSB_GetDescriptor(int8_t t);
private:
uint8_t lastIf;
uint8_t lastEp;
PluggableUSBModule* rootNode;
};

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

Expand Down
2 changes: 1 addition & 1 deletion hardware/arduino/sam/cores/arduino/USB/USBAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ bool CDC_Setup(USBSetup& setup);
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);
uint8_t USBD_SendInterfaces(void);
bool USBD_ClassInterfaceRequest(USBSetup& setup);


Expand Down
26 changes: 13 additions & 13 deletions hardware/arduino/sam/cores/arduino/USB/USBCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const DeviceDescriptor USB_DeviceDescriptor =
const DeviceDescriptor USB_DeviceDescriptorA =
D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);

const DeviceDescriptor USB_DeviceQualifier =
const QualifierDescriptor USB_DeviceQualifier =
D_QUALIFIER(0x00,0x00,0x00,64,1);

//! 7.1.20 Test Mode Support
Expand Down Expand Up @@ -130,7 +130,7 @@ class LockEP
{
irqflags_t flags;
public:
LockEP(uint32_t ep) : flags(cpu_irq_save())
LockEP(uint32_t ep __attribute__ ((unused))) : flags(cpu_irq_save())
{
}
~LockEP()
Expand Down Expand Up @@ -219,8 +219,8 @@ uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len)
return r;
}

int _cmark;
int _cend;
uint16_t _cmark;
uint16_t _cend;

void USBD_InitControl(int end)
{
Expand All @@ -229,7 +229,7 @@ void USBD_InitControl(int end)
}

// Clipped by _cmark/_cend
int USBD_SendControl(uint8_t flags, const void* d, uint32_t len)
int USBD_SendControl(uint8_t flags __attribute__ ((unused)), const void* d, uint32_t len)
{
const uint8_t* data = (const uint8_t*)d;
uint32_t length = len;
Expand Down Expand Up @@ -296,13 +296,13 @@ bool USBD_ClassInterfaceRequest(USBSetup& setup)
#endif

#ifdef PLUGGABLE_USB_ENABLED
return PUSB_Setup(setup, i);
return PluggableUSB().setup(setup);
#endif

return false;
}

int USBD_SendInterfaces(void)
uint8_t USBD_SendInterfaces(void)
{
uint8_t interfaces = 0;

Expand All @@ -311,14 +311,14 @@ 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);)
return interfaces;
}

int USBD_SendOtherInterfaces(void)
uint8_t USBD_SendOtherInterfaces(void)
{
uint8_t interfaces = 0;

Expand All @@ -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);)
Expand All @@ -342,7 +342,7 @@ static bool USBD_SendConfiguration(int maxlen)
// Count and measure interfaces
USBD_InitControl(0);
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);)
int interfaces = USBD_SendInterfaces();
uint8_t interfaces = USBD_SendInterfaces();
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)

Expand All @@ -365,7 +365,7 @@ static bool USBD_SendOtherConfiguration(int maxlen)
// Count and measure interfaces
USBD_InitControl(0);
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);)
int interfaces = USBD_SendOtherInterfaces();
uint8_t interfaces = USBD_SendOtherInterfaces();
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)

Expand Down Expand Up @@ -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);
}
Expand Down
25 changes: 20 additions & 5 deletions hardware/arduino/sam/cores/arduino/USB/USBCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -146,6 +149,18 @@ typedef struct {
uint8_t maxPower;
} ConfigDescriptor;

// Device Qualifier (only needed for USB2.0 devices)
typedef struct {
uint8_t bLength;
uint8_t dtype;
uint16_t bDescriptorType;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
} QualifierDescriptor;

// String

// Interface
Expand Down Expand Up @@ -254,16 +269,16 @@ _Pragma("pack()")
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }

#define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
{ 9, 2, (uint16_t)(_totalLength),_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }

#define D_OTHERCONFIG(_totalLength,_interfaces) \
{ 9, 7, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
{ 9, 7, (uint16_t)(_totalLength),_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }

#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }

#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
{ 7, 5, _addr,_attr,_packetSize, _interval }
{ 7, 5, (uint8_t)(_addr),_attr,_packetSize, _interval }

#define D_QUALIFIER(_class,_subClass,_proto,_packetSize0,_configs) \
{ 10, 6, 0x200, _class,_subClass,_proto,_packetSize0,_configs }
Expand Down
Loading