-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathusb-device.cpp
197 lines (176 loc) · 4.69 KB
/
usb-device.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
namespace usbd {
/**
* @brief USB device base class
*
* This class is not subclassed directly by the application.
* There must always be chip specific implementation as midclass.
* This means there is a hierarchy like:
* UsbDevice <- ChipAbcUsbDevice <- ApplicationXyzUsbDevice.
*
* Typical application subclass of a chip midclass (ATSAMD in this case) looks like:
* ```cpp
* class TestDevice : public atsamd::usbd::AtSamdUsbDevice {
* public:
* TestInterface testInterface;
*
* UsbControlEndpoint controlEndpoint;
*
* UsbInterface *getInterface(int index) { return index == 0 ? &testInterface : NULL; };
*
* UsbEndpoint *getControlEndpoint() { return &controlEndpoint; };
*
* void checkDescriptor(DeviceDescriptor *deviceDesriptor) {
* deviceDesriptor->idVendor = 0xFEE0;
* deviceDesriptor->idProduct = 0x0001;
* };
*
* };
* ```
*
* Chip midclass must overload following methods:
* - void init(); - must call UsbDevice::init()
* - void setAddress(int address);
* - void startTx(int epIndex, int length);
* - void stall(int epIndex);
*/
class UsbDevice {
public:
/**
* Array of endpoints as collected by the init() method.
*/
UsbEndpoint *endpoints[MAX_ENDPOINTS];
/**
* Number of endpoints as collected by the init() method.
*/
int endpointCount;
/**
* Device initialization.
*
* Called from chip midclass init() method.
*
* UsbEndpoint::init() is responsible for collecting of endpoints from interfaces.
*/
virtual void init() {
UsbEndpoint *controlEndpoint = getControlEndpoint();
controlEndpoint->device = this;
controlEndpoint->init();
for (int i = 0; UsbInterface *interface = getInterface(i); i++) {
interface->device = this;
interface->init();
}
endpointCount = 0;
controlEndpoint->index = endpointCount++;
endpoints[controlEndpoint->index] = controlEndpoint;
for (int i = 0; UsbInterface *interface = getInterface(i); i++) {
for (int e = 0; UsbEndpoint *endpoint = interface->getEndpoint(e); e++) {
endpoint->index = endpointCount++;
endpoints[endpoint->index] = endpoint;
}
}
}
/**
* Gets control endpoint.
*
* Called internally from the library.
*
* Must be overloaded by the application subclass.
*
* @return UsbEndpoint*
*/
virtual UsbEndpoint *getControlEndpoint() = 0;
/**
* Gets interface by index.
*
* Called internally from the library.
*
* Must be overloaded by the application subclass.
*
* @param index zero based in scope of device
* @return UsbInterface*
*/
virtual UsbInterface *getInterface(int index) = 0;
/**
* Handler of device control request.
*
* Called internally from the library.
*
* May be overloaded by application subclass to implement vendor request.
*
* @param setupData
*/
virtual void setup(SetupData *setupData){};
/**
* Called when generating device descriptor.
*
* Called internally from the library.
*
* May be overloaded by application subclass to modify the default descriptor.
*
* @param deviceDesriptor
*/
virtual void checkDescriptor(DeviceDescriptor *deviceDesriptor){};
/**
* Get string identifier of the manufacturer.
*
* Called internally from the library.
*
* May be overloaded by application subclass.
*
* @return const char*
*/
virtual const char *getManufacturer() { return NULL; };
/**
* Get string identifier of the product.
*
* Called internally from the library.
*
* May be overloaded by application subclass.
*
* @return const char*
*/
virtual const char *getProduct() { return NULL; };
/**
* Get string serial number of the device.
*
* Called internally from the library.
*
* May be overloaded by application subclass or chip midclass.
*
* @return const char*
*/
virtual const char *getSerial() { return NULL; };
/**
* Sets device USB address.
*
* Called internally from the library.
*
* Must be overloaded by chip midclass.
*
* @param address
*/
virtual void setAddress(int address) = 0;
/**
* Starts transmission of the data on the given endpoint.
*
* Called internally from the library.
*
* Must be overloaded by chip midclass.
*
* @param epIndex
* @param length
*/
virtual void startTx(int epIndex, int length) = 0;
/**
* Sends stall handshake on the given endpoint.
*
* Called internally from the library.
*
* Must be overloaded by chip midclass.
*
* @param epIndex
*/
virtual void stall(int epIndex) = 0;
};
void UsbEndpoint::startTx(int length) { device->startTx(index, length); }
void UsbEndpoint::stall() { device->stall(index); }
} // namespace usbd