aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/demos/AVR/RT-PRO-MICRO/usbcfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/demos/AVR/RT-PRO-MICRO/usbcfg.c')
-rw-r--r--lib/chibios/demos/AVR/RT-PRO-MICRO/usbcfg.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/lib/chibios/demos/AVR/RT-PRO-MICRO/usbcfg.c b/lib/chibios/demos/AVR/RT-PRO-MICRO/usbcfg.c
new file mode 100644
index 000000000..5018a7b97
--- /dev/null
+++ b/lib/chibios/demos/AVR/RT-PRO-MICRO/usbcfg.c
@@ -0,0 +1,401 @@
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 0x1b4f, /* idVendor (Sparkfun). */
46 0x9206, /* idProduct. */
47 0x0200, /* bcdDevice. */
48 1, /* iManufacturer. */
49 2, /* 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(18), /* bLength. */
161 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
162 'S', 0, 'p', 0, 'a', 0, 'r', 0, 'k', 0, 'f', 0, 'u', 0, 'n', 0,
163};
164
165/*
166 * Device Description string.
167 */
168static ROMCONST uint8_t vcom_string2[] = {
169 USB_DESC_BYTE(56), /* bLength. */
170 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
171 'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0,
172 'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0,
173 'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0,
174 'o', 0, 'r', 0, 't', 0
175};
176
177/*
178 * Serial Number string.
179 */
180static ROMCONST uint8_t vcom_string3[] = {
181 USB_DESC_BYTE(8), /* bLength. */
182 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
183 '0' + CH_KERNEL_MAJOR, 0,
184 '0' + CH_KERNEL_MINOR, 0,
185 '0' + CH_KERNEL_PATCH, 0
186};
187
188/*
189 * Strings wrappers array.
190 */
191static ROMCONST USBDescriptor vcom_strings[] = {
192 {sizeof vcom_string0, vcom_string0},
193 {sizeof vcom_string1, vcom_string1},
194 {sizeof vcom_string2, vcom_string2},
195 {sizeof vcom_string3, vcom_string3}
196};
197
198/*
199 * Handles the GET_DESCRIPTOR callback. All required descriptors must be
200 * handled here.
201 */
202static const USBDescriptor *get_descriptor(USBDriver *usbp,
203 uint8_t dtype,
204 uint8_t dindex,
205 uint16_t lang) {
206
207 (void)usbp;
208 (void)lang;
209 switch (dtype) {
210 case USB_DESCRIPTOR_DEVICE:
211 return &vcom_device_descriptor;
212 case USB_DESCRIPTOR_CONFIGURATION:
213 return &vcom_configuration_descriptor;
214 case USB_DESCRIPTOR_STRING:
215 if (dindex < 4)
216 return &vcom_strings[dindex];
217 }
218 return NULL;
219}
220
221/**
222 * @brief IN EP1 state.
223 */
224static USBInEndpointState ep1state;
225
226/**
227 * @brief EP1 initialization structure (IN).
228 */
229static const USBEndpointConfig ep1config = {
230 USB_EP_MODE_TYPE_BULK,
231 NULL,
232 sduDataTransmitted,
233 NULL,
234 0x0040,
235 0x0000,
236 &ep1state,
237 NULL,
238};
239
240/**
241 * @brief INTR EP2 state.
242 */
243static USBInEndpointState ep2state;
244
245/**
246 * @brief EP2 initialization structure.
247 */
248static const USBEndpointConfig ep2config = {
249 USB_EP_MODE_TYPE_INTR,
250 NULL,
251 sduInterruptTransmitted,
252 NULL,
253 0x0010,
254 0x0000,
255 &ep2state,
256 NULL
257};
258
259/**
260 * @brief OUT EP3 state.
261 */
262static USBOutEndpointState ep3state;
263
264/**
265 * @brief EP3 initialization structure (OUT).
266 */
267static const USBEndpointConfig ep3config = {
268 USB_EP_MODE_TYPE_BULK,
269 NULL,
270 NULL,
271 sduDataReceived,
272 0x0000,
273 0x0040,
274 NULL,
275 &ep3state,
276};
277
278/*
279 * Handles the USB driver global events.
280 */
281static void usb_event(USBDriver *usbp, usbevent_t event) {
282 extern SerialUSBDriver SDU1;
283
284 switch (event) {
285 case USB_EVENT_ADDRESS:
286 return;
287 case USB_EVENT_CONFIGURED:
288 chSysLockFromISR();
289
290 /* Enables the endpoints specified into the configuration.
291 Note, this callback is invoked from an ISR so I-Class functions
292 must be used.*/
293 usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config);
294 usbInitEndpointI(usbp, USBD1_DATA_AVAILABLE_EP, &ep2config);
295 usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep3config);
296
297 /* Resetting the state of the CDC subsystem.*/
298 sduConfigureHookI(&SDU1);
299
300 chSysUnlockFromISR();
301 return;
302 case USB_EVENT_RESET:
303 /* Falls into.*/
304 case USB_EVENT_UNCONFIGURED:
305 /* Falls into.*/
306 case USB_EVENT_SUSPEND:
307 chSysLockFromISR();
308
309 /* Disconnection event on suspend.*/
310 sduSuspendHookI(&SDU1);
311
312 chSysUnlockFromISR();
313 return;
314 case USB_EVENT_WAKEUP:
315 chSysLockFromISR();
316
317 /* Connection event on wakeup.*/
318 sduWakeupHookI(&SDU1);
319
320 chSysUnlockFromISR();
321 return;
322 case USB_EVENT_STALLED:
323 return;
324 }
325 return;
326}
327
328bool usb_setup_hook(USBDriver *usbp) {
329 /* Override GET_DESCRIPTOR requests to return data from program memory */
330 if ((usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | USB_RTYPE_TYPE_MASK)) ==
331 (USB_RTYPE_RECIPIENT_DEVICE | USB_RTYPE_TYPE_STD) &&
332 usbp->setup[1] == USB_REQ_GET_DESCRIPTOR) {
333 const uint8_t dtype = usbp->setup[3];
334 const uint8_t dindex = usbp->setup[2];
335 const AVR_USB_TX_BUF_ADDRESS_SPACE uint8_t *ddata = NULL;
336 size_t dsize = 0;
337 switch (dtype) {
338 case USB_DESCRIPTOR_DEVICE:
339 dsize = sizeof(vcom_device_descriptor_data);
340 ddata = vcom_device_descriptor_data;
341 break;
342 case USB_DESCRIPTOR_CONFIGURATION:
343 dsize = sizeof(vcom_configuration_descriptor_data);
344 ddata = vcom_configuration_descriptor_data;
345 break;
346 case USB_DESCRIPTOR_STRING:
347 if (dindex == 0) {
348 dsize = sizeof(vcom_string0);
349 ddata = vcom_string0;
350 } else if (dindex == 1) {
351 dsize = sizeof(vcom_string1);
352 ddata = vcom_string1;
353 } else if (dindex == 2) {
354 dsize = sizeof(vcom_string2);
355 ddata = vcom_string2;
356 } else if (dindex == 3) {
357 dsize = sizeof(vcom_string3);
358 ddata = vcom_string3;
359 }
360 break;
361 }
362 if (ddata == NULL) {
363 return false;
364 }
365
366 usbSetupTransfer(usbp, ddata, dsize, NULL);
367 return true;
368 }
369 return sduRequestsHook(usbp);
370}
371
372/*
373 * Handles the USB driver start of frame event.
374 */
375static void sof_handler(USBDriver *usbp) {
376 (void)usbp;
377
378 osalSysLockFromISR();
379 sduSOFHookI(&SDU1);
380 osalSysUnlockFromISR();
381}
382
383/*
384 * USB driver configuration.
385 */
386const USBConfig usbcfg = {
387 usb_event,
388 get_descriptor,
389 usb_setup_hook,
390 sof_handler
391};
392
393/*
394 * Serial over USB driver configuration.
395 */
396const SerialUSBConfig serusbcfg = {
397 &USBD1,
398 USBD1_DATA_REQUEST_EP,
399 USBD1_DATA_AVAILABLE_EP,
400 USBD1_INTERRUPT_REQUEST_EP
401};