-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
PluggableUSB.cpp
134 lines (112 loc) · 3.18 KB
/
PluggableUSB.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* @file PluggableUSB.cpp
* @author Daniel Starke
* @copyright Copyright 2020-2022 Daniel Starke
* @date 2020-05-21
* @version 2022-03-22
*/
#include "Arduino.h"
#include "PluggableUSB.h"
#ifdef USBCON
#ifdef PLUGGABLE_USB_ENABLED
/* USB endpoint description; defined and used in USBCore.cpp */
extern uint8_t _usbEndpoints[USB_ENDPOINTS];
/**
* Constructor.
*/
PluggableUSB_::PluggableUSB_():
lastIf(0),
lastEp(1),
rootNode(NULL)
{}
/**
* Adds a new USB interface node.
*
* @param[in] node - node to add
* @return true on success, else false
*/
bool PluggableUSB_::plug(PluggableUSBModule * node) {
/* maximum number of endpoints or dedicated USB memory reached? */
if ((this->lastEp + node->numEndpoints) > USB_ENDPOINTS || (((this->lastEp + node->numEndpoints) * USB_EP_SIZE) + 64) > USB_PMASIZE) return false;
/* get last node */
if (this->rootNode == NULL) {
this->rootNode = node;
} else {
PluggableUSBModule * current = this->rootNode;
while (current->next != NULL) current = current->next;
current->next = node;
}
/* append new node */
node->pluggedInterface = this->lastIf;
node->pluggedEndpoint = this->lastEp;
this->lastIf = uint8_t(this->lastIf + node->numInterfaces);
for (uint8_t i = 0; i < node->numEndpoints; i++) {
_usbEndpoints[this->lastEp] = node->endpointType[i];
this->lastEp++;
}
return true;
}
/**
* Sends the USB interface description for each plugged node to the host.
*
* @param[out] interfaceCount - filled with the number of plugged interfaces
* @return bytes sent
*/
int PluggableUSB_::getInterface(uint8_t * interfaceCount) {
int sent = 0;
for (PluggableUSBModule * node = this->rootNode; node != NULL; node = node->next) {
int res = node->getInterface(interfaceCount);
if (res < 0) return -1;
sent += res;
}
return sent;
}
/**
* Sends the USB device descriptor for each plugged node to the host.
*
* @param[in,out] setup - USB setup message
* @return bytes sent
*/
int PluggableUSB_::getDescriptor(USBSetup & setup) {
for (PluggableUSBModule * node = this->rootNode; node != NULL; node = node->next) {
int res = node->getDescriptor(setup);
if (res != 0) return res; /* request has been processed */
}
return 0;
}
/**
* Calls the USB setup handler of each plugged node.
*
* @param[in] setup - USB setup message
* @return true on success, else false
*/
bool PluggableUSB_::setup(USBSetup & setup) {
for (PluggableUSBModule * node = this->rootNode; node != NULL; node = node->next) {
if ( node->setup(setup) ) return true;
}
return false;
}
/**
* Returns the USB device serial number made up of all plugged nodes.
*
* @param[out] name - copy serial number to this buffer
* @return number of bytes copied
*/
uint8_t PluggableUSB_::getShortName(char * iSerialNum) {
uint8_t size = 0;
for (PluggableUSBModule * node = this->rootNode; node != NULL; node = node->next) {
size = uint8_t(size + node->getShortName(iSerialNum + size));
}
return size;
}
/**
* Replacement for global singleton to prevent static initialization issues.
*
* @return Global PluggableUSB_ instance.
*/
PluggableUSB_ & PluggableUSB() {
static PluggableUSB_ obj;
return obj;
}
#endif /* PLUGGABLE_USB_ENABLED */
#endif /* USBCON */