rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
usbcfg.cpp
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
3 Modified for RusEFI
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16*/
17
18#include "pch.h"
19#include "mmc_card.h"
20
21#if HAL_USE_SERIAL_USB
22
23#include "usbcfg.h"
24
25/* Virtual serial port over USB.*/
26SerialUSBDriver SDU1;
27
28/*
29 * Endpoints to be used for USBD1.
30 */
31#define USBD1_DATA_REQUEST_EP 2
32#define USBD1_DATA_AVAILABLE_EP 2
33#define USBD1_INTERRUPT_REQUEST_EP 3
34
35#if HAL_USE_USB_MSD
36 // Descriptor that includes MSD is larger and has an extra interface
37 #define DESCRIPTOR_SIZE 98
38 #define NUM_INTERFACES 3
39 #define USB_MSD_EP_SIZE 64
40
41 #define MSD_IF 0
42 #define CDC_INT_IF 1
43 #define CDC_DATA_IF 2
44#else
45 // Alternate descriptor is smaller, no MSD
46 #define DESCRIPTOR_SIZE 75
47 #define NUM_INTERFACES 2
48
49 // only two interfaces
50 #define CDC_INT_IF 0
51 #define CDC_DATA_IF 1
52#endif
53
54/*
55 * USB Device Descriptor.
56 */
57static const uint8_t vcom_device_descriptor_data[18] = {
58 USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */
59 0xEF, /* bDeviceClass ( misc ). */
60 0x02, /* bDeviceSubClass. */
61 0x01, /* bDeviceProtocol. */
62 0x40, /* bMaxPacketSize. */
63 0x0483, /* idVendor (ST). */
64 0x5740, /* idProduct. */
65 0x0200, /* bcdDevice. */
66 1, /* iManufacturer. */
67 2, /* iProduct. */
68 3, /* iSerialNumber. */
69 1) /* bNumConfigurations. */
70};
71
72/*
73 * Device Descriptor wrapper.
74 */
75static const USBDescriptor vcom_device_descriptor = {
78};
79
80/* Configuration Descriptor tree for a CDC.*/
81static const uint8_t vcom_configuration_descriptor_data[DESCRIPTOR_SIZE] = {
82 /* Configuration Descriptor.*/
83 USB_DESC_CONFIGURATION(DESCRIPTOR_SIZE,/* wTotalLength. */
84 NUM_INTERFACES,/* bNumInterfaces. */
85 0x01, /* bConfigurationValue. */
86 0, /* iConfiguration. */
87 0x80, /* bmAttributes (bus powered). */
88 200), /* bMaxPower (400mA). */
89#if HAL_USE_USB_MSD
90 USB_DESC_INTERFACE (MSD_IF, /* bInterfaceNumber. */
91 0x00, /* bAlternateSetting. */
92 0x02, /* bNumEndpoints. */
93 0x08, /* bInterfaceClass (mass storage) */
94 0x06, /* bInterfaceSubClass (SCSI
95 transparent storage class). */
96 0x50, /* bInterfaceProtocol (Bulk Only). */
97 0), /* iInterface. */
98 /* Mass Storage Data In Endpoint Descriptor.*/
99 USB_DESC_ENDPOINT (USB_MSD_DATA_EP | 0x80,
100 0x02, /* bmAttributes (Bulk). */
101 64, /* wMaxPacketSize. */
102 0x00), /* bInterval. 1ms */
103 /* Mass Storage Data Out Endpoint Descriptor.*/
104 USB_DESC_ENDPOINT (USB_MSD_DATA_EP,
105 0x02, /* bmAttributes (Bulk). */
106 64, /* wMaxPacketSize. */
107 0x00), /* bInterval. 1ms */
108#endif // HAL_USE_USB_MSD
109 // CDC
110 /* IAD Descriptor - describes that EP2+3 belong to CDC */
111 USB_DESC_INTERFACE_ASSOCIATION(CDC_INT_IF, /* bFirstInterface. */
112 0x02, /* bInterfaceCount. */
113 0x02, /* bFunctionClass (CDC). */
114 0x02, /* bFunctionSubClass. (2) */
115 0x01, /* bFunctionProtocol (1) */
116 2), /* iInterface. */
117 /* Interface Descriptor.*/
118 USB_DESC_INTERFACE (CDC_INT_IF, /* bInterfaceNumber. */
119 0x00, /* bAlternateSetting. */
120 0x01, /* bNumEndpoints. */
121 0x02, /* bInterfaceClass (Communications
122 Interface Class, CDC section
123 4.2). */
124 0x02, /* bInterfaceSubClass (Abstract
125 Control Model, CDC section 4.3). */
126 0x01, /* bInterfaceProtocol (AT commands,
127 CDC section 4.4). */
128 0), /* iInterface. */
129 /* Header Functional Descriptor (CDC section 5.2.3).*/
130 USB_DESC_BYTE (5), /* bLength. */
131 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
132 USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header
133 Functional Descriptor. */
134 USB_DESC_BCD (0x0110), /* bcdCDC. */
135 /* Call Management Functional Descriptor. */
136 USB_DESC_BYTE (5), /* bFunctionLength. */
137 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
138 USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management
139 Functional Descriptor). */
140 USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */
141 USB_DESC_BYTE (CDC_DATA_IF), /* bDataInterface. */
142 /* ACM Functional Descriptor.*/
143 USB_DESC_BYTE (4), /* bFunctionLength. */
144 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
145 USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract
146 Control Management Descriptor). */
147 USB_DESC_BYTE (0x02), /* bmCapabilities. */
148 /* Union Functional Descriptor.*/
149 USB_DESC_BYTE (5), /* bFunctionLength. */
150 USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
151 USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union
152 Functional Descriptor). */
153 USB_DESC_BYTE (CDC_INT_IF), /* bMasterInterface (Communication
154 Class Interface). */
155 USB_DESC_BYTE (CDC_DATA_IF), /* bSlaveInterface0 (Data Class
156 Interface). */
157 /* Endpoint 3 Descriptor.*/
158 USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80,
159 0x03, /* bmAttributes (Interrupt). */
160 0x0008, /* wMaxPacketSize. */
161 0xFF), /* bInterval. */
162 /* Interface Descriptor.*/
163 USB_DESC_INTERFACE (CDC_DATA_IF, /* bInterfaceNumber. */
164 0x00, /* bAlternateSetting. */
165 0x02, /* bNumEndpoints. */
166 0x0A, /* bInterfaceClass (Data Class
167 Interface, CDC section 4.5). */
168 0x00, /* bInterfaceSubClass (CDC section
169 4.6). */
170 0x00, /* bInterfaceProtocol (CDC section
171 4.7). */
172 0x00), /* iInterface. */
173 /* Endpoint 2 Descriptor.*/
174 USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/
175 0x02, /* bmAttributes (Bulk). */
176 0x0040, /* wMaxPacketSize. */
177 0x00), /* bInterval. */
178 /* Endpoint 2 Descriptor.*/
179 USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/
180 0x02, /* bmAttributes (Bulk). */
181 0x0040, /* wMaxPacketSize. */
182 0x00) /* bInterval. */
183};
184
185/*
186 * Configuration Descriptor wrapper.
187 */
192
193/*
194 * U.S. English language identifier.
195 */
196static const uint8_t vcom_string0[] = {
197 USB_DESC_BYTE(4), /* bLength. */
198 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
199 USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
200};
201
202/*
203 * Vendor string.
204 */
205static const uint8_t vcom_string1[] = {
206 USB_DESC_BYTE(22), /* bLength. */
207 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
208 'r', 0, 'u', 0, 's', 0, 'E', 0, 'F', 0, 'I', 0, ' ', 0, 'L', 0,
209 'L', 0, 'C', 0
210};
211
212// STRING_CONTENT length + 2?
213#ifndef USB_DESCRIPTOR_B_LENGTH
214#define USB_DESCRIPTOR_B_LENGTH (56 + 2)
215#endif
216
217#ifndef USB_DESCRIPTOR_STRING_CONTENT
218#define USB_DESCRIPTOR_STRING_CONTENT 'r', 0, 'u', 0, 's', 0, 'E', 0, 'F', 0, 'I', 0, ' ', 0, 'E', 0, \
219 'n', 0, 'g', 0, 'i', 0, 'n', 0, 'e', 0, ' ', 0, 'M', 0, 'a', 0, \
220 'n', 0, 'a', 0, 'g', 0, 'e', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, \
221 ' ', 0, 'E', 0, 'C', 0, 'U', 0
222#endif
223
224/*
225 * Device Description string.
226 */
227static const uint8_t vcom_string2[] = {
228 USB_DESC_BYTE(USB_DESCRIPTOR_B_LENGTH), /* bLength. */
229 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
230 USB_DESCRIPTOR_STRING_CONTENT, 0
231};
232
233/*
234 * Serial Number string.
235 */
236
237#ifdef BOARD_SERIAL
238static_assert(strlen(BOARD_SERIAL) == 24, "BOARD_SERIAL incorrect length, should be 24 chars");
239static const uint8_t vcom_string3[] = {
240 USB_DESC_BYTE(50), /* bLength. */
241 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
242 BOARD_SERIAL[ 0], 0, BOARD_SERIAL[ 1], 0, BOARD_SERIAL[ 2], 0, BOARD_SERIAL[ 3], 0,
243 BOARD_SERIAL[ 4], 0, BOARD_SERIAL[ 5], 0, BOARD_SERIAL[ 6], 0, BOARD_SERIAL[ 7], 0,
244 BOARD_SERIAL[ 8], 0, BOARD_SERIAL[ 9], 0, BOARD_SERIAL[10], 0, BOARD_SERIAL[11], 0,
245 BOARD_SERIAL[12], 0, BOARD_SERIAL[13], 0, BOARD_SERIAL[14], 0, BOARD_SERIAL[15], 0,
246 BOARD_SERIAL[16], 0, BOARD_SERIAL[17], 0, BOARD_SERIAL[18], 0, BOARD_SERIAL[19], 0,
247 BOARD_SERIAL[20], 0, BOARD_SERIAL[21], 0, BOARD_SERIAL[22], 0, BOARD_SERIAL[23], 0,
248 0
249};
250#else
251static uint8_t vcom_string3[] = {
252 USB_DESC_BYTE(50), /* bLength. */
253 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
254 '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0,
255 '8', 0, '9', 0, 'A', 0, 'B', 0, 'C', 0, 'D', 0, 'E', 0, 'F', 0,
256 '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0,
257 0
258};
259#endif
260
261/*
262 * Strings wrappers array.
263 */
264static const USBDescriptor vcom_strings[] = {
265 {sizeof vcom_string0, vcom_string0},
266 {sizeof vcom_string1, vcom_string1},
267 {sizeof vcom_string2, vcom_string2},
268 {sizeof vcom_string3, vcom_string3}
269};
270
271#ifndef BOARD_SERIAL
272static char nib2char(uint8_t nibble) {
273 if (nibble > 0x9) {
274 return nibble - 0xA + 'A';
275 } else {
276 return nibble + '0';
277 }
278}
279
280void usbPopulateSerialNumber(const uint8_t* serialNumber, size_t bytes) {
281 if (bytes > 12) {
282 bytes = 12;
283 }
284
285 // Skip the first two bytes (metadata)
286 uint8_t* dst = &vcom_string3[2];
287
288 for (size_t i = 0; i < bytes; i++) {
289 uint8_t byte = serialNumber[i];
290
291 uint8_t lowNibble = byte & 0xF;
292 uint8_t highNibble = byte >> 4;
293
294 // Descriptor strings are UCS16, so write every other byte
295 dst[4 * i] = nib2char(highNibble);
296 dst[4 * i + 2] = nib2char(lowNibble);
297 }
298}
299#endif // BOARD_SERIAL
300
301/*
302 * Handles the GET_DESCRIPTOR callback. All required descriptors must be
303 * handled here.
304 */
305static const USBDescriptor *get_descriptor(USBDriver *usbp,
306 uint8_t dtype,
307 uint8_t dindex,
308 uint16_t lang) {
309
310 (void)usbp;
311 (void)lang;
312 switch (dtype) {
313 case USB_DESCRIPTOR_DEVICE:
315 case USB_DESCRIPTOR_CONFIGURATION:
317 case USB_DESCRIPTOR_STRING:
318 if (dindex < 4)
319 return &vcom_strings[dindex];
320 }
321 return NULL;
322}
323
324#if HAL_USE_USB_MSD
325 /**
326 * @brief IN MSD state
327 */
328 static USBInEndpointState msdInstate;
329
330 /**
331 * @brief OUT MSD state
332 */
333 static USBOutEndpointState msdOutstate;
334
335 /**
336 * @brief MSD initialization structure (both IN and OUT).
337 */
338 static const USBEndpointConfig msdEpConfig = {
339 USB_EP_MODE_TYPE_BULK,
340 NULL,
341 NULL,
342 NULL,
343 USB_MSD_EP_SIZE,
344 USB_MSD_EP_SIZE,
345 &msdInstate,
347 4,
348 NULL
349 };
350#endif //HAL_USE_MSD
351
352// IN CDC data state.
353static USBInEndpointState cdcDataInstate;
354// OUT CDC data state.
355static USBOutEndpointState cdcDataOutstate;
356// CDC data initialization structure (both IN and OUT).
357static const USBEndpointConfig cdcDataEpConfig = {
358 USB_EP_MODE_TYPE_BULK,
359 NULL,
360 sduDataTransmitted,
361 sduDataReceived,
362 0x0040,
363 0x0040,
366 4,
367 NULL
368};
369
370// IN CDC interrupt state.
371static USBInEndpointState cdcInterruptInstate;
372// CDC interrupt initialization structure (IN only).
373static const USBEndpointConfig cdcInterruptEpConfig = {
374 USB_EP_MODE_TYPE_INTR,
375 NULL,
376 sduInterruptTransmitted,
377 NULL,
378 0x0010,
379 0x0000,
381 NULL,
382 1,
383 NULL
384};
385
386/*
387 * Handles the USB driver global events.
388 */
389static void usb_event(USBDriver *usbp, usbevent_t event) {
390 switch (event) {
391 case USB_EVENT_ADDRESS:
392 return;
393 case USB_EVENT_CONFIGURED:
394 chSysLockFromISR();
395
396 /* Enables the endpoints specified into the configuration.
397 Note, this callback is invoked from an ISR so I-Class functions
398 must be used.*/
399#if HAL_USE_USB_MSD
400 usbInitEndpointI(usbp, USB_MSD_DATA_EP, &msdEpConfig);
401#endif
402
403 usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &cdcDataEpConfig);
404 usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &cdcInterruptEpConfig);
405
406 /* Resetting the state of the CDC subsystem.*/
407 sduConfigureHookI(&SDU1);
408
409 #if HAL_USE_USB_MSD
410 // Tell the MMC thread to wake up and mount the card as a USB device
412 #endif
413
414 chSysUnlockFromISR();
415 return;
416 case USB_EVENT_RESET:
417 /* Falls into.*/
418 case USB_EVENT_UNCONFIGURED:
419 /* Falls into.*/
420 case USB_EVENT_SUSPEND:
421 chSysLockFromISR();
422
423 /* Disconnection event on suspend.*/
424 sduSuspendHookI(&SDU1);
425
426 chSysUnlockFromISR();
427 return;
428 case USB_EVENT_WAKEUP:
429 chSysLockFromISR();
430
431 /* Disconnection event on suspend.*/
432 sduWakeupHookI(&SDU1);
433
434 chSysUnlockFromISR();
435 return;
436 case USB_EVENT_STALLED:
437 return;
438 }
439 return;
440}
441
442/*
443 * Handles the USB driver global events.
444 */
445static void sof_handler(USBDriver *usbp) {
446
447 (void)usbp;
448
449 osalSysLockFromISR();
450 sduSOFHookI(&SDU1);
451 osalSysUnlockFromISR();
452}
453
454// We need a custom hook to handle both MSD and CDC at the same time
455static bool hybridRequestHook(USBDriver *usbp) {
456#if HAL_USE_USB_MSD
457 // Try the MSD driver first
458 if (msd_request_hook_new(usbp)) {
459 return true;
460 }
461#endif // HAL_USE_USB_MSD
462
463 // if not MSD, it must be serial
464 return sduRequestsHook(usbp);
465}
466
467/*
468 * USB driver configuration.
469 */
470const USBConfig usbcfg = {
471 usb_event,
475};
476
477/*
478 * Serial over USB driver configuration.
479 */
480const SerialUSBConfig serusbcfg = {
481#if STM32_USB_USE_OTG1
482 .usbp = &USBD1,
483#elif STM32_USB_USE_OTG2
484 .usbp = &USBD2,
485#else
486 #error Serial over USB needs OTG1 or OTG2 to be enabled
487#endif
488 .bulk_in = USBD1_DATA_REQUEST_EP,
489 .bulk_out = USBD1_DATA_AVAILABLE_EP,
490 .int_in = USBD1_INTERRUPT_REQUEST_EP
491};
492
493#endif /* EFI_USB_SERIAL */
bool msd_request_hook_new(USBDriver *usbp)
void onUsbConnectedNotifyMmcI()
Definition mmc_card.cpp:426
static void usb_event(USBDriver *usbp, usbevent_t event)
Definition usbcfg.cpp:389
static const uint8_t vcom_string3[]
Definition usbcfg.cpp:239
static const uint8_t vcom_string0[]
Definition usbcfg.cpp:196
SerialUSBDriver SDU1
Definition usbcfg.cpp:26
static const uint8_t vcom_configuration_descriptor_data[DESCRIPTOR_SIZE]
Definition usbcfg.cpp:81
static const uint8_t vcom_device_descriptor_data[18]
Definition usbcfg.cpp:57
const USBConfig usbcfg
Definition usbcfg.cpp:470
static bool hybridRequestHook(USBDriver *usbp)
Definition usbcfg.cpp:455
static USBInEndpointState cdcInterruptInstate
Definition usbcfg.cpp:371
static const uint8_t vcom_string2[]
Definition usbcfg.cpp:227
static const USBEndpointConfig msdEpConfig
MSD initialization structure (both IN and OUT).
Definition usbcfg.cpp:338
static USBInEndpointState cdcDataInstate
Definition usbcfg.cpp:353
static const USBDescriptor * get_descriptor(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang)
Definition usbcfg.cpp:305
static void sof_handler(USBDriver *usbp)
Definition usbcfg.cpp:445
static const USBEndpointConfig cdcDataEpConfig
Definition usbcfg.cpp:357
static const USBDescriptor vcom_strings[]
Definition usbcfg.cpp:264
static const USBEndpointConfig cdcInterruptEpConfig
Definition usbcfg.cpp:373
static const uint8_t vcom_string1[]
Definition usbcfg.cpp:205
static USBOutEndpointState msdOutstate
OUT MSD state.
Definition usbcfg.cpp:333
static USBOutEndpointState cdcDataOutstate
Definition usbcfg.cpp:355
static const USBDescriptor vcom_device_descriptor
Definition usbcfg.cpp:75
const SerialUSBConfig serusbcfg
Definition usbcfg.cpp:480
void usbPopulateSerialNumber(const uint8_t *serialNumber, size_t bytes)
Definition usbcfg.cpp:280
static char nib2char(uint8_t nibble)
Definition usbcfg.cpp:272
static USBInEndpointState msdInstate
IN MSD state.
Definition usbcfg.cpp:328
static const USBDescriptor vcom_configuration_descriptor
Definition usbcfg.cpp:188