aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/demos/AVR/RT-ARDUINO-LEONARDO/usbcfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/demos/AVR/RT-ARDUINO-LEONARDO/usbcfg.c')
-rw-r--r--lib/chibios/demos/AVR/RT-ARDUINO-LEONARDO/usbcfg.c402
1 files changed, 402 insertions, 0 deletions
diff --git a/lib/chibios/demos/AVR/RT-ARDUINO-LEONARDO/usbcfg.c b/lib/chibios/demos/AVR/RT-ARDUINO-LEONARDO/usbcfg.c
new file mode 100644
index 000000000..629a48f24
--- /dev/null
+++ b/lib/chibios/demos/AVR/RT-ARDUINO-LEONARDO/usbcfg.c
@@ -0,0 +1,402 @@
1/*
2 ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#include "ch.h"
18#include "hal.h"
19#include "usbcfg.h"
20
21/*
22 * Endpoints to be used for USBD1.
23 */
24#define USBD1_DATA_REQUEST_EP 1
25#define USBD1_DATA_AVAILABLE_EP 3
26#define USBD1_INTERRUPT_REQUEST_EP 2
27
28#if (AVR_USB_USE_NAMED_ADDRESS_SPACES == TRUE) && defined(__FLASH)
29# undef ROMCONST
30# define ROMCONST const __flash
31#endif
32
33/* Virtual serial port over USB.*/
34SerialUSBDriver SDU1;
35
36/*
37 * USB Device Descriptor.
38 */
39static ROMCONST uint8_t vcom_device_descriptor_data[18] = {
40 USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */
41 0x02, /* bDeviceClass (CDC). */
42 0x00, /* bDeviceSubClass. */
43 0x00, /* bDeviceProtocol. */
44 0x40, /* bMaxPacketSize. */
45 0x2341, /* idVendor (Arduino LLC). */
46 0x0036, /* idProduct. */
47 0x0200, /* bcdDevice. */
48 2, /* iManufacturer. */
49 1, /* iProduct. */
50 3, /* iSerialNumber. */
51 1) /* bNumConfigurations. */
52};
53
54/*
55 * Device Descriptor wrapper.
56 */
57static ROMCONST USBDescriptor vcom_device_descriptor = {
58 sizeof vcom_device_descriptor_data,
59 vcom_device_descriptor_data
60};
61
62/* Configuration Descriptor tree for a CDC.*/
63static ROMCONST uint8_t vcom_configuration_descriptor_data[67] = {
64 /* Configuration Descriptor.*/
65 USB_DESC_CONFIGURATION(67, /* wTotalLength. */
66 0x02, /* bNumInterfaces. */
67 0x01, /* bConfigurationValue. */
68 0, /* iConfiguration. */
69 0xC0, /* bmAttributes (self powered). */
70 50), /* bMaxPower (100mA). */
71 /* Interface Descriptor.*/
72 USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */
73 0x00, /* bAlternateSetting. */
74 0x01, /* bNumEndpoints. */
75 0x02, /* bInterfaceClass (Communications
76 Interface Class, CDC section
77 4.2). */
78 0x02, /* bInterfaceSubClass (Abstract
79 Control Model, CDC section 4.3). */
80 0x01, /* bInterfaceProtocol (AT commands,
81 CDC section 4.4). */
82 0), /* iInterface. */
83 /* Header Functional Descriptor (CDC section 5.2.3).*/
84 USB_DESC_BYTE (5), /* bLength. */
85 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
86 USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header
87 Functional Descriptor. */
88 USB_DESC_BCD (0x0110), /* bcdCDC. */
89 /* Call Management Functional Descriptor. */
90 USB_DESC_BYTE (5), /* bFunctionLength. */
91 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
92 USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management
93 Functional Descriptor). */
94 USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */
95 USB_DESC_BYTE (0x01), /* bDataInterface. */
96 /* ACM Functional Descriptor.*/
97 USB_DESC_BYTE (4), /* bFunctionLength. */
98 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
99 USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract
100 Control Management Descriptor). */
101 USB_DESC_BYTE (0x02), /* bmCapabilities. */
102 /* Union Functional Descriptor.*/
103 USB_DESC_BYTE (5), /* bFunctionLength. */
104 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
105 USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union
106 Functional Descriptor). */
107 USB_DESC_BYTE (0x00), /* bMasterInterface (Communication
108 Class Interface). */
109 USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class
110 Interface). */
111 /* Endpoint 2 Descriptor.*/
112 USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80,
113 0x03, /* bmAttributes (Interrupt). */
114 0x0008, /* wMaxPacketSize. */
115 0xFF), /* bInterval. */
116 /* Interface Descriptor.*/
117 USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */
118 0x00, /* bAlternateSetting. */
119 0x02, /* bNumEndpoints. */
120 0x0A, /* bInterfaceClass (Data Class
121 Interface, CDC section 4.5). */
122 0x00, /* bInterfaceSubClass (CDC section
123 4.6). */
124 0x00, /* bInterfaceProtocol (CDC section
125 4.7). */
126 0x00), /* iInterface. */
127 /* Endpoint 3 Descriptor.*/
128 USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/
129 0x02, /* bmAttributes (Bulk). */
130 0x0040, /* wMaxPacketSize. */
131 0x00), /* bInterval. */
132 /* Endpoint 1 Descriptor.*/
133 USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/
134 0x02, /* bmAttributes (Bulk). */
135 0x0040, /* wMaxPacketSize. */
136 0x00) /* bInterval. */
137};
138
139/*
140 * Configuration Descriptor wrapper.
141 */
142static ROMCONST USBDescriptor vcom_configuration_descriptor = {
143 sizeof vcom_configuration_descriptor_data,
144 vcom_configuration_descriptor_data
145};
146
147/*
148 * U.S. English language identifier.
149 */
150static ROMCONST uint8_t vcom_string0[] = {
151 USB_DESC_BYTE(4), /* bLength. */
152 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
153 USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
154};
155
156/*
157 * Vendor string.
158 */
159static ROMCONST uint8_t vcom_string1[] = {
160 USB_DESC_BYTE(24), /* bLength. */
161 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
162 'A', 0, 'r', 0, 'd', 0, 'u', 0, 'i', 0, 'n', 0, 'o', 0,
163 ' ', 0, 'L', 0, 'L', 0, 'C', 0
164};
165
166/*
167 * Device Description string.
168 */
169static ROMCONST uint8_t vcom_string2[] = {
170 USB_DESC_BYTE(56), /* bLength. */
171 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
172 'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0,
173 'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0,
174 'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0,
175 'o', 0, 'r', 0, 't', 0
176};
177
178/*
179 * Serial Number string.
180 */
181static ROMCONST uint8_t vcom_string3[] = {
182 USB_DESC_BYTE(8), /* bLength. */
183 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
184 '0' + CH_KERNEL_MAJOR, 0,
185 '0' + CH_KERNEL_MINOR, 0,
186 '0' + CH_KERNEL_PATCH, 0
187};
188
189/*
190 * Strings wrappers array.
191 */
192static ROMCONST USBDescriptor vcom_strings[] = {
193 {sizeof vcom_string0, vcom_string0},
194 {sizeof vcom_string1, vcom_string1},
195 {sizeof vcom_string2, vcom_string2},
196 {sizeof vcom_string3, vcom_string3}
197};
198
199/*
200 * Handles the GET_DESCRIPTOR callback. All required descriptors must be
201 * handled here.
202 */
203static const USBDescriptor *get_descriptor(USBDriver *usbp,
204 uint8_t dtype,
205 uint8_t dindex,
206 uint16_t lang) {
207
208 (void)usbp;
209 (void)lang;
210 switch (dtype) {
211 case USB_DESCRIPTOR_DEVICE:
212 return &vcom_device_descriptor;
213 case USB_DESCRIPTOR_CONFIGURATION:
214 return &vcom_configuration_descriptor;
215 case USB_DESCRIPTOR_STRING:
216 if (dindex < 4)
217 return &vcom_strings[dindex];
218 }
219 return NULL;
220}
221
222/**
223 * @brief IN EP1 state.
224 */
225static USBInEndpointState ep1state;
226
227/**
228 * @brief EP1 initialization structure (IN).
229 */
230static const USBEndpointConfig ep1config = {
231 USB_EP_MODE_TYPE_BULK,
232 NULL,
233 sduDataTransmitted,
234 NULL,
235 0x0040,
236 0x0000,
237 &ep1state,
238 NULL,
239};
240
241/**
242 * @brief INTR EP2 state.
243 */
244static USBInEndpointState ep2state;
245
246/**
247 * @brief EP2 initialization structure.
248 */
249static const USBEndpointConfig ep2config = {
250 USB_EP_MODE_TYPE_INTR,
251 NULL,
252 sduInterruptTransmitted,
253 NULL,
254 0x0010,
255 0x0000,
256 &ep2state,
257 NULL
258};
259
260/**
261 * @brief OUT EP3 state.
262 */
263static USBOutEndpointState ep3state;
264
265/**
266 * @brief EP3 initialization structure (OUT).
267 */
268static const USBEndpointConfig ep3config = {
269 USB_EP_MODE_TYPE_BULK,
270 NULL,
271 NULL,
272 sduDataReceived,
273 0x0000,
274 0x0040,
275 NULL,
276 &ep3state,
277};
278
279/*
280 * Handles the USB driver global events.
281 */
282static void usb_event(USBDriver *usbp, usbevent_t event) {
283 extern SerialUSBDriver SDU1;
284
285 switch (event) {
286 case USB_EVENT_ADDRESS:
287 return;
288 case USB_EVENT_CONFIGURED:
289 chSysLockFromISR();
290
291 /* Enables the endpoints specified into the configuration.
292 Note, this callback is invoked from an ISR so I-Class functions
293 must be used.*/
294 usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config);
295 usbInitEndpointI(usbp, USBD1_DATA_AVAILABLE_EP, &ep2config);
296 usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep3config);
297
298 /* Resetting the state of the CDC subsystem.*/
299 sduConfigureHookI(&SDU1);
300
301 chSysUnlockFromISR();
302 return;
303 case USB_EVENT_RESET:
304 /* Falls into.*/
305 case USB_EVENT_UNCONFIGURED:
306 /* Falls into.*/
307 case USB_EVENT_SUSPEND:
308 chSysLockFromISR();
309
310 /* Disconnection event on suspend.*/
311 sduSuspendHookI(&SDU1);
312
313 chSysUnlockFromISR();
314 return;
315 case USB_EVENT_WAKEUP:
316 chSysLockFromISR();
317
318 /* Connection event on wakeup.*/
319 sduWakeupHookI(&SDU1);
320
321 chSysUnlockFromISR();
322 return;
323 case USB_EVENT_STALLED:
324 return;
325 }
326 return;
327}
328
329bool usb_setup_hook(USBDriver *usbp) {
330 /* Override GET_DESCRIPTOR requests to return data from program memory */
331 if ((usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | USB_RTYPE_TYPE_MASK)) ==
332 (USB_RTYPE_RECIPIENT_DEVICE | USB_RTYPE_TYPE_STD) &&
333 usbp->setup[1] == USB_REQ_GET_DESCRIPTOR) {
334 const uint8_t dtype = usbp->setup[3];
335 const uint8_t dindex = usbp->setup[2];
336 const AVR_USB_TX_BUF_ADDRESS_SPACE uint8_t *ddata = NULL;
337 size_t dsize = 0;
338 switch (dtype) {
339 case USB_DESCRIPTOR_DEVICE:
340 dsize = sizeof(vcom_device_descriptor_data);
341 ddata = vcom_device_descriptor_data;
342 break;
343 case USB_DESCRIPTOR_CONFIGURATION:
344 dsize = sizeof(vcom_configuration_descriptor_data);
345 ddata = vcom_configuration_descriptor_data;
346 break;
347 case USB_DESCRIPTOR_STRING:
348 if (dindex == 0) {
349 dsize = sizeof(vcom_string0);
350 ddata = vcom_string0;
351 } else if (dindex == 1) {
352 dsize = sizeof(vcom_string1);
353 ddata = vcom_string1;
354 } else if (dindex == 2) {
355 dsize = sizeof(vcom_string2);
356 ddata = vcom_string2;
357 } else if (dindex == 3) {
358 dsize = sizeof(vcom_string3);
359 ddata = vcom_string3;
360 }
361 break;
362 }
363 if (ddata == NULL) {
364 return false;
365 }
366
367 usbSetupTransfer(usbp, ddata, dsize, NULL);
368 return true;
369 }
370 return sduRequestsHook(usbp);
371}
372
373/*
374 * Handles the USB driver start of frame event.
375 */
376static void sof_handler(USBDriver *usbp) {
377 (void)usbp;
378
379 osalSysLockFromISR();
380 sduSOFHookI(&SDU1);
381 osalSysUnlockFromISR();
382}
383
384/*
385 * USB driver configuration.
386 */
387const USBConfig usbcfg = {
388 usb_event,
389 get_descriptor,
390 usb_setup_hook,
391 sof_handler
392};
393
394/*
395 * Serial over USB driver configuration.
396 */
397const SerialUSBConfig serusbcfg = {
398 &USBD1,
399 USBD1_DATA_REQUEST_EP,
400 USBD1_DATA_AVAILABLE_EP,
401 USBD1_INTERRUPT_REQUEST_EP
402};