Skip to content

Commit 8bfd5d7

Browse files
committed
Merge pull request #2 from arduino/master
pull master
2 parents 4dfa7e4 + c950941 commit 8bfd5d7

File tree

5 files changed

+154
-108
lines changed

5 files changed

+154
-108
lines changed

hardware/arduino/avr/cores/arduino/PluggableUSB.cpp

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -23,78 +23,93 @@
2323
#if defined(USBCON)
2424
#ifdef PLUGGABLE_USB_ENABLED
2525

26-
#define MAX_MODULES 6
26+
extern uint8_t _initEndpoints[];
2727

28-
static u8 lastIf = CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT;
29-
static u8 lastEp = CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT;
30-
31-
extern u8 _initEndpoints[];
32-
33-
//PUSBCallbacks cbs[MAX_MODULES];
34-
static u8 modules_count = 0;
35-
36-
static PUSBListNode* rootNode = NULL;
28+
int PluggableUSB_::getInterface(uint8_t* interfaceCount)
29+
{
30+
int sent = 0;
31+
PluggableUSBModule* node;
32+
for (node = rootNode; node; node = node->next) {
33+
int res = node->getInterface(interfaceCount);
34+
if (res < 0)
35+
return -1;
36+
sent += res;
37+
}
38+
return sent;
39+
}
3740

38-
int PUSB_GetInterface(u8* interfaceNum)
41+
int PluggableUSB_::getDescriptor(USBSetup& setup)
3942
{
40-
int ret = 0;
41-
PUSBListNode* node = rootNode;
42-
for (u8 i=0; i<modules_count; i++) {
43-
ret = node->cb->getInterface(interfaceNum);
44-
node = node->next;
43+
PluggableUSBModule* node;
44+
for (node = rootNode; node; node = node->next) {
45+
int ret = node->getDescriptor(setup);
46+
// ret!=0 -> request has been processed
47+
if (ret)
48+
return ret;
4549
}
46-
return ret;
50+
return 0;
4751
}
4852

49-
int PUSB_GetDescriptor(int8_t t)
53+
void PluggableUSB_::getShortName(char *iSerialNum)
5054
{
51-
int ret = 0;
52-
PUSBListNode* node = rootNode;
53-
for (u8 i=0; i<modules_count && ret == 0; i++) {
54-
ret = node->cb->getDescriptor(t);
55-
node = node->next;
55+
PluggableUSBModule* node;
56+
for (node = rootNode; node; node = node->next) {
57+
iSerialNum += node->getShortName(iSerialNum);
5658
}
57-
return ret;
59+
*iSerialNum = 0;
5860
}
5961

60-
bool PUSB_Setup(USBSetup& setup, u8 j)
62+
bool PluggableUSB_::setup(USBSetup& setup)
6163
{
62-
bool ret = false;
63-
PUSBListNode* node = rootNode;
64-
for (u8 i=0; i<modules_count && ret == false; i++) {
65-
ret = node->cb->setup(setup, j);
66-
node = node->next;
64+
PluggableUSBModule* node;
65+
for (node = rootNode; node; node = node->next) {
66+
if (node->setup(setup)) {
67+
return true;
68+
}
6769
}
68-
return ret;
70+
return false;
6971
}
7072

71-
int8_t PUSB_AddFunction(PUSBListNode *node, u8* interface)
73+
bool PluggableUSB_::plug(PluggableUSBModule *node)
7274
{
73-
if (modules_count >= MAX_MODULES) {
74-
return 0;
75+
if ((lastEp + node->numEndpoints) > USB_ENDPOINTS) {
76+
return false;
7577
}
7678

77-
if (modules_count == 0) {
79+
if (!rootNode) {
7880
rootNode = node;
7981
} else {
80-
PUSBListNode *current = rootNode;
81-
while(current->next != NULL) {
82+
PluggableUSBModule *current = rootNode;
83+
while (current->next) {
8284
current = current->next;
8385
}
8486
current->next = node;
8587
}
8688

87-
*interface = lastIf;
88-
lastIf += node->cb->numInterfaces;
89-
for ( u8 i = 0; i< node->cb->numEndpoints; i++) {
90-
_initEndpoints[lastEp] = node->cb->endpointType[i];
89+
node->pluggedInterface = lastIf;
90+
node->pluggedEndpoint = lastEp;
91+
lastIf += node->numInterfaces;
92+
for (uint8_t i = 0; i < node->numEndpoints; i++) {
93+
_initEndpoints[lastEp] = node->endpointType[i];
9194
lastEp++;
9295
}
93-
modules_count++;
94-
return lastEp - node->cb->numEndpoints;
96+
return true;
9597
// restart USB layer???
9698
}
9799

100+
PluggableUSB_& PluggableUSB()
101+
{
102+
static PluggableUSB_ obj;
103+
return obj;
104+
}
105+
106+
PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT),
107+
lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT),
108+
rootNode(NULL)
109+
{
110+
// Empty
111+
}
112+
98113
#endif
99114

100-
#endif /* if defined(USBCON) */
115+
#endif /* if defined(USBCON) */

hardware/arduino/avr/cores/arduino/PluggableUSB.h

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,49 @@
2525

2626
#if defined(USBCON)
2727

28-
typedef struct __attribute__((packed))
29-
{
30-
bool (*setup)(USBSetup& setup, u8 i);
31-
int (*getInterface)(u8* interfaceNum);
32-
int (*getDescriptor)(int8_t t);
33-
int8_t numEndpoints;
34-
int8_t numInterfaces;
35-
uint8_t *endpointType;
36-
} PUSBCallbacks;
37-
38-
class PUSBListNode {
28+
class PluggableUSBModule {
3929
public:
40-
PUSBListNode *next = NULL;
41-
PUSBCallbacks *cb;
42-
PUSBListNode(PUSBCallbacks *ncb) {cb = ncb;}
43-
};
30+
PluggableUSBModule(uint8_t numEps, uint8_t numIfs, uint8_t *epType) :
31+
numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType)
32+
{ }
33+
34+
protected:
35+
virtual bool setup(USBSetup& setup) = 0;
36+
virtual int getInterface(uint8_t* interfaceCount) = 0;
37+
virtual int getDescriptor(USBSetup& setup) = 0;
38+
virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; }
39+
40+
uint8_t pluggedInterface;
41+
uint8_t pluggedEndpoint;
42+
43+
const uint8_t numEndpoints;
44+
const uint8_t numInterfaces;
45+
const uint8_t *endpointType;
4446

45-
int8_t PUSB_AddFunction(PUSBListNode *node, u8 *interface);
47+
PluggableUSBModule *next = NULL;
4648

47-
int PUSB_GetInterface(u8* interfaceNum);
49+
friend class PluggableUSB_;
50+
};
51+
52+
class PluggableUSB_ {
53+
public:
54+
PluggableUSB_();
55+
bool plug(PluggableUSBModule *node);
56+
int getInterface(uint8_t* interfaceCount);
57+
int getDescriptor(USBSetup& setup);
58+
bool setup(USBSetup& setup);
59+
void getShortName(char *iSerialNum);
4860

49-
int PUSB_GetDescriptor(int8_t t);
61+
private:
62+
uint8_t lastIf;
63+
uint8_t lastEp;
64+
PluggableUSBModule* rootNode;
65+
};
5066

51-
bool PUSB_Setup(USBSetup& setup, u8 i);
67+
// Replacement for global singleton.
68+
// This function prevents static-initialization-order-fiasco
69+
// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
70+
PluggableUSB_& PluggableUSB();
5271

5372
#endif
5473

hardware/arduino/avr/cores/arduino/USBCore.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "USBAPI.h"
2020
#include "PluggableUSB.h"
21+
#include <stdlib.h>
2122

2223
#if defined(USBCON)
2324

@@ -69,10 +70,10 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER;
6970

7071
// DEVICE DESCRIPTOR
7172
const DeviceDescriptor USB_DeviceDescriptor =
72-
D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
73+
D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
7374

7475
const DeviceDescriptor USB_DeviceDescriptorB =
75-
D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
76+
D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
7677

7778
//==================================================================
7879
//==================================================================
@@ -308,20 +309,15 @@ int USB_Send(u8 ep, const void* d, int len)
308309
return r;
309310
}
310311

311-
u8 _initEndpoints[] =
312+
u8 _initEndpoints[USB_ENDPOINTS] =
312313
{
313-
0,
314+
0, // Control Endpoint
314315

315-
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
316-
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
317-
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
316+
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
317+
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
318+
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
318319

319-
#ifdef PLUGGABLE_USB_ENABLED
320-
//allocate 3 endpoints and remove const so they can be changed by the user
321-
0,
322-
0,
323-
0,
324-
#endif
320+
// Following endpoints are automatically initialized to 0
325321
};
326322

327323
#define EP_SINGLE_64 0x32 // EP0
@@ -367,7 +363,7 @@ bool ClassInterfaceRequest(USBSetup& setup)
367363
return CDC_Setup(setup);
368364

369365
#ifdef PLUGGABLE_USB_ENABLED
370-
return PUSB_Setup(setup, i);
366+
return PluggableUSB().setup(setup);
371367
#endif
372368
return false;
373369
}
@@ -414,11 +410,12 @@ int USB_SendControl(u8 flags, const void* d, int len)
414410
// Send a USB descriptor string. The string is stored in PROGMEM as a
415411
// plain ASCII string but is sent out as UTF-16 with the correct 2-byte
416412
// prefix
417-
static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) {
413+
static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len, uint8_t flags) {
418414
SendControl(2 + string_len * 2);
419415
SendControl(3);
416+
bool pgm = flags & TRANSFER_PGM;
420417
for(u8 i = 0; i < string_len; i++) {
421-
bool r = SendControl(pgm_read_byte(&string_P[i]));
418+
bool r = SendControl(pgm ? pgm_read_byte(&string_P[i]) : string_P[i]);
422419
r &= SendControl(0); // high byte
423420
if(!r) {
424421
return false;
@@ -445,7 +442,7 @@ static u8 SendInterfaces()
445442
CDC_GetInterface(&interfaces);
446443

447444
#ifdef PLUGGABLE_USB_ENABLED
448-
PUSB_GetInterface(&interfaces);
445+
PluggableUSB().getInterface(&interfaces);
449446
#endif
450447

451448
return interfaces;
@@ -481,7 +478,7 @@ bool SendDescriptor(USBSetup& setup)
481478

482479
InitControl(setup.wLength);
483480
#ifdef PLUGGABLE_USB_ENABLED
484-
ret = PUSB_GetDescriptor(t);
481+
ret = PluggableUSB().getDescriptor(setup);
485482
if (ret != 0) {
486483
return (ret > 0 ? true : false);
487484
}
@@ -500,10 +497,17 @@ bool SendDescriptor(USBSetup& setup)
500497
desc_addr = (const u8*)&STRING_LANGUAGE;
501498
}
502499
else if (setup.wValueL == IPRODUCT) {
503-
return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT));
500+
return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM);
504501
}
505502
else if (setup.wValueL == IMANUFACTURER) {
506-
return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER));
503+
return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER), TRANSFER_PGM);
504+
}
505+
else if (setup.wValueL == ISERIAL) {
506+
#ifdef PLUGGABLE_USB_ENABLED
507+
char name[ISERIAL_MAX_LEN];
508+
PluggableUSB().getShortName(name);
509+
return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0);
510+
#endif
507511
}
508512
else
509513
return false;

hardware/arduino/avr/cores/arduino/USBCore.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@
4949
#define REQUEST_OTHER 0x03
5050
#define REQUEST_RECIPIENT 0x03
5151

52-
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE)
53-
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE)
52+
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE)
53+
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE)
54+
#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE)
5455

5556
// Class requests
5657

@@ -99,8 +100,8 @@
99100

100101
// bEndpointAddress in Endpoint Descriptor
101102
#define USB_ENDPOINT_DIRECTION_MASK 0x80
102-
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
103-
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
103+
#define USB_ENDPOINT_OUT(addr) (lowByte((addr) | 0x00))
104+
#define USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80))
104105

105106
#define USB_ENDPOINT_TYPE_MASK 0x03
106107
#define USB_ENDPOINT_TYPE_CONTROL 0x00
@@ -277,4 +278,4 @@ typedef struct
277278
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
278279

279280

280-
#endif
281+
#endif

0 commit comments

Comments
 (0)