1 /*
2  * Copyright (c) 2025, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usbd_cdc_acm.h"
8 
9 /*!< endpoint address */
10 #define CDC_IN_EP  0x81
11 #define CDC_OUT_EP 0x02
12 #define CDC_INT_EP 0x83
13 
14 #define USBD_VID           0xFFFF
15 #define USBD_PID           0xFFFF
16 #define USBD_MAX_POWER     100
17 #define USBD_LANGID_STRING 1033
18 
19 /*!< config descriptor size */
20 #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
21 
22 #ifdef CONFIG_USB_HS
23 #define CDC_MAX_MPS 512
24 #else
25 #define CDC_MAX_MPS 64
26 #endif
27 
28 #ifdef CONFIG_USBDEV_ADVANCE_DESC
29 static const uint8_t device_descriptor[] = {
30     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
31 };
32 
33 static const uint8_t config_descriptor[] = {
34     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
35     CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
36 };
37 
38 static const uint8_t device_quality_descriptor[] = {
39     ///////////////////////////////////////
40     /// device qualifier descriptor
41     ///////////////////////////////////////
42     0x0a,
43     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
44     0x00,
45     0x02,
46     0x00,
47     0x00,
48     0x00,
49     0x40,
50     0x00,
51     0x00,
52 };
53 
54 static const char *string_descriptors[] = {
55     (const char[]){ 0x09, 0x04 }, /* Langid */
56     "CherryUSB",                  /* Manufacturer */
57     "CherryUSB CDC DEMO",         /* Product */
58     "2022123456",                 /* Serial Number */
59 };
60 
device_descriptor_callback(uint8_t speed)61 static const uint8_t *device_descriptor_callback(uint8_t speed)
62 {
63     return device_descriptor;
64 }
65 
config_descriptor_callback(uint8_t speed)66 static const uint8_t *config_descriptor_callback(uint8_t speed)
67 {
68     return config_descriptor;
69 }
70 
device_quality_descriptor_callback(uint8_t speed)71 static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
72 {
73     return device_quality_descriptor;
74 }
75 
string_descriptor_callback(uint8_t speed,uint8_t index)76 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
77 {
78     if (index > 3) {
79         return NULL;
80     }
81     return string_descriptors[index];
82 }
83 
84 const struct usb_descriptor cdc_descriptor = {
85     .device_descriptor_callback = device_descriptor_callback,
86     .config_descriptor_callback = config_descriptor_callback,
87     .device_quality_descriptor_callback = device_quality_descriptor_callback,
88     .string_descriptor_callback = string_descriptor_callback
89 };
90 #else
91 /*!< global descriptor */
92 static const uint8_t cdc_descriptor[] = {
93     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
94     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
95     CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
96     ///////////////////////////////////////
97     /// string0 descriptor
98     ///////////////////////////////////////
99     USB_LANGID_INIT(USBD_LANGID_STRING),
100     ///////////////////////////////////////
101     /// string1 descriptor
102     ///////////////////////////////////////
103     0x14,                       /* bLength */
104     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
105     'C', 0x00,                  /* wcChar0 */
106     'h', 0x00,                  /* wcChar1 */
107     'e', 0x00,                  /* wcChar2 */
108     'r', 0x00,                  /* wcChar3 */
109     'r', 0x00,                  /* wcChar4 */
110     'y', 0x00,                  /* wcChar5 */
111     'U', 0x00,                  /* wcChar6 */
112     'S', 0x00,                  /* wcChar7 */
113     'B', 0x00,                  /* wcChar8 */
114     ///////////////////////////////////////
115     /// string2 descriptor
116     ///////////////////////////////////////
117     0x26,                       /* bLength */
118     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
119     'C', 0x00,                  /* wcChar0 */
120     'h', 0x00,                  /* wcChar1 */
121     'e', 0x00,                  /* wcChar2 */
122     'r', 0x00,                  /* wcChar3 */
123     'r', 0x00,                  /* wcChar4 */
124     'y', 0x00,                  /* wcChar5 */
125     'U', 0x00,                  /* wcChar6 */
126     'S', 0x00,                  /* wcChar7 */
127     'B', 0x00,                  /* wcChar8 */
128     ' ', 0x00,                  /* wcChar9 */
129     'C', 0x00,                  /* wcChar10 */
130     'D', 0x00,                  /* wcChar11 */
131     'C', 0x00,                  /* wcChar12 */
132     ' ', 0x00,                  /* wcChar13 */
133     'D', 0x00,                  /* wcChar14 */
134     'E', 0x00,                  /* wcChar15 */
135     'M', 0x00,                  /* wcChar16 */
136     'O', 0x00,                  /* wcChar17 */
137     ///////////////////////////////////////
138     /// string3 descriptor
139     ///////////////////////////////////////
140     0x16,                       /* bLength */
141     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
142     '2', 0x00,                  /* wcChar0 */
143     '0', 0x00,                  /* wcChar1 */
144     '2', 0x00,                  /* wcChar2 */
145     '2', 0x00,                  /* wcChar3 */
146     '1', 0x00,                  /* wcChar4 */
147     '2', 0x00,                  /* wcChar5 */
148     '3', 0x00,                  /* wcChar6 */
149     '4', 0x00,                  /* wcChar7 */
150     '5', 0x00,                  /* wcChar8 */
151     '6', 0x00,                  /* wcChar9 */
152 #ifdef CONFIG_USB_HS
153     ///////////////////////////////////////
154     /// device qualifier descriptor
155     ///////////////////////////////////////
156     0x0a,
157     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
158     0x00,
159     0x02,
160     0x00,
161     0x00,
162     0x00,
163     0x40,
164     0x00,
165     0x00,
166 #endif
167     0x00
168 };
169 #endif
170 
usbd_event_handler(uint8_t busid,uint8_t event)171 static void usbd_event_handler(uint8_t busid, uint8_t event)
172 {
173     switch (event) {
174         case USBD_EVENT_RESET:
175             break;
176         case USBD_EVENT_CONNECTED:
177             break;
178         case USBD_EVENT_DISCONNECTED:
179             break;
180         case USBD_EVENT_RESUME:
181             break;
182         case USBD_EVENT_SUSPEND:
183             break;
184         case USBD_EVENT_CONFIGURED:
185 
186             break;
187         case USBD_EVENT_SET_REMOTE_WAKEUP:
188             break;
189         case USBD_EVENT_CLR_REMOTE_WAKEUP:
190             break;
191 
192         default:
193             break;
194     }
195 }
196 
197 extern void usbd_cdc_acm_serial_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep);
198 
cdc_acm_chardev_init(uint8_t busid,uintptr_t reg_base)199 void cdc_acm_chardev_init(uint8_t busid, uintptr_t reg_base)
200 {
201 #ifdef CONFIG_USBDEV_ADVANCE_DESC
202     usbd_desc_register(busid, &cdc_descriptor);
203 #else
204     usbd_desc_register(busid, cdc_descriptor);
205 #endif
206     usbd_cdc_acm_serial_init(busid, CDC_IN_EP, CDC_OUT_EP);
207     usbd_initialize(busid, reg_base, usbd_event_handler);
208 }