1 /*
2 * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include "esp32s2/rom/usb/usb_common.h"
9 #include "soc/soc.h"
10 #include "hal/efuse_hal.h"
11
12 /* USB CDC descriptor.
13 * Note that we aren't using the one in ROM since it doesn't
14 * set "serial" to the MAC address.
15 * However overriding the descriptor is cheap - we can reuse most
16 * of its components from ROM.
17 */
18
19 /* This is not const, since the MAC address is only known at run time */
20 static struct string_descriptor s_str_serial_descr = {
21 .bLength = 2 + 2 * 17,
22 .bDescriptorType = 0x03,
23 .bString={'0', '0', ':', '0', '0', ':', '0', '0', ':', '0', '0', ':', '0', '0', ':', '0', '0'}
24 };
25
26 static const struct rom_usb_descriptors s_acm_usb_descriptors_override = {
27 .device_descr = &general_device_descr,
28 .config_descr = { &acm_config_descr },
29 .string_count = 4,
30 .string0_descr = &string0_descr,
31 .string_descrs = {
32 &str_manu_descr,
33 &str_prod_descr,
34 &s_str_serial_descr
35 }
36 };
37
nibble_to_hex_u16(uint8_t b)38 static inline uint16_t nibble_to_hex_u16(uint8_t b)
39 {
40 if (b < 0xa) {
41 return '0' + b;
42 } else {
43 return 'a' + b - 0xa;
44 }
45 }
46
rom_usb_cdc_set_descriptor_patch(void)47 void rom_usb_cdc_set_descriptor_patch(void)
48 {
49 uint8_t mac_bytes[6];
50 efuse_hal_get_mac(mac_bytes);
51 /* Convert to UTF16 string */
52 #pragma GCC diagnostic push
53 #if __GNUC__ >= 9
54 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
55 #endif
56 uint16_t* dst = s_str_serial_descr.bString;
57 for (int i = 0; i < 6; ++i) {
58 uint8_t b = mac_bytes[5 - i]; /* printing from the MSB */
59 *dst++ = nibble_to_hex_u16(b >> 4);
60 *dst++ = nibble_to_hex_u16(b & 0xf);
61 dst++;
62 }
63 #pragma GCC diagnostic pop
64
65 /* Override the pointer to descriptors structure */
66 rom_usb_curr_desc = &s_acm_usb_descriptors_override;
67 }
68
69 /* On ESP32-S2, ROM doesn't provide interfaces to clear usb_dev and usb_dw_ctrl structures.
70 * Starting from ESP32-S3, usb_dev_deinit and usb_dw_ctrl_deinit ROM functions are available.
71 * Here we implement the missing functionality for the ESP32-S2.
72 */
usb_dev_deinit(void)73 void usb_dev_deinit(void)
74 {
75 extern char rom_usb_dev, rom_usb_dev_end;
76 memset((void *) &rom_usb_dev, 0, &rom_usb_dev_end - &rom_usb_dev);
77 }
78
usb_dw_ctrl_deinit(void)79 void usb_dw_ctrl_deinit(void)
80 {
81 extern char rom_usb_dw_ctrl, rom_usb_dw_ctrl_end;
82 memset((void *) &rom_usb_dw_ctrl, 0, &rom_usb_dw_ctrl_end - &rom_usb_dw_ctrl);
83 }
84