1 /*
2  * Copyright (c) 2024, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usbd_cdc_acm.h"
8 #include "usbd_msc.h"
9 
10 /*!< endpoint address */
11 #define CDC_IN_EP  0x81
12 #define CDC_OUT_EP 0x02
13 #define CDC_INT_EP 0x83
14 
15 #define MSC_IN_EP  0x84
16 #define MSC_OUT_EP 0x05
17 
18 #define USBD_VID           0xFFFF
19 #define USBD_PID           0xFFFF
20 #define USBD_MAX_POWER     100
21 #define USBD_LANGID_STRING 1033
22 
23 /*!< config descriptor size */
24 #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN)
25 
26 #ifdef CONFIG_USB_HS
27 #define CDC_MAX_MPS 512
28 #else
29 #define CDC_MAX_MPS 64
30 #endif
31 
32 #ifdef CONFIG_USB_HS
33 #define MSC_MAX_MPS 512
34 #else
35 #define MSC_MAX_MPS 64
36 #endif
37 
38 #ifdef CONFIG_USBDEV_ADVANCE_DESC
39 static const uint8_t device_descriptor[] = {
40     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
41 };
42 
43 static const uint8_t config_descriptor[] = {
44     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
45     CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
46     MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00)
47 };
48 
49 static const uint8_t device_quality_descriptor[] = {
50     ///////////////////////////////////////
51     /// device qualifier descriptor
52     ///////////////////////////////////////
53     0x0a,
54     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
55     0x00,
56     0x02,
57     0x00,
58     0x00,
59     0x00,
60     0x40,
61     0x00,
62     0x00,
63 };
64 
65 static const char *string_descriptors[] = {
66     (const char[]){ 0x09, 0x04 }, /* Langid */
67     "CherryUSB",                  /* Manufacturer */
68     "CherryUSB CDC MSC DEMO",     /* Product */
69     "2022123456",                 /* Serial Number */
70 };
71 
device_descriptor_callback(uint8_t speed)72 static const uint8_t *device_descriptor_callback(uint8_t speed)
73 {
74     return device_descriptor;
75 }
76 
config_descriptor_callback(uint8_t speed)77 static const uint8_t *config_descriptor_callback(uint8_t speed)
78 {
79     return config_descriptor;
80 }
81 
device_quality_descriptor_callback(uint8_t speed)82 static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
83 {
84     return device_quality_descriptor;
85 }
86 
string_descriptor_callback(uint8_t speed,uint8_t index)87 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
88 {
89     if (index > 3) {
90         return NULL;
91     }
92     return string_descriptors[index];
93 }
94 
95 const struct usb_descriptor cdc_msc_descriptor = {
96     .device_descriptor_callback = device_descriptor_callback,
97     .config_descriptor_callback = config_descriptor_callback,
98     .device_quality_descriptor_callback = device_quality_descriptor_callback,
99     .string_descriptor_callback = string_descriptor_callback
100 };
101 #else
102 /*!< global descriptor */
103 static const uint8_t cdc_msc_descriptor[] = {
104     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
105     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
106     CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
107     MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00),
108     ///////////////////////////////////////
109     /// string0 descriptor
110     ///////////////////////////////////////
111     USB_LANGID_INIT(USBD_LANGID_STRING),
112     ///////////////////////////////////////
113     /// string1 descriptor
114     ///////////////////////////////////////
115     0x14,                       /* bLength */
116     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
117     'C', 0x00,                  /* wcChar0 */
118     'h', 0x00,                  /* wcChar1 */
119     'e', 0x00,                  /* wcChar2 */
120     'r', 0x00,                  /* wcChar3 */
121     'r', 0x00,                  /* wcChar4 */
122     'y', 0x00,                  /* wcChar5 */
123     'U', 0x00,                  /* wcChar6 */
124     'S', 0x00,                  /* wcChar7 */
125     'B', 0x00,                  /* wcChar8 */
126     ///////////////////////////////////////
127     /// string2 descriptor
128     ///////////////////////////////////////
129     0x26,                       /* bLength */
130     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
131     'C', 0x00,                  /* wcChar0 */
132     'h', 0x00,                  /* wcChar1 */
133     'e', 0x00,                  /* wcChar2 */
134     'r', 0x00,                  /* wcChar3 */
135     'r', 0x00,                  /* wcChar4 */
136     'y', 0x00,                  /* wcChar5 */
137     'U', 0x00,                  /* wcChar6 */
138     'S', 0x00,                  /* wcChar7 */
139     'B', 0x00,                  /* wcChar8 */
140     ' ', 0x00,                  /* wcChar9 */
141     'C', 0x00,                  /* wcChar10 */
142     '-', 0x00,                  /* wcChar11 */
143     'M', 0x00,                  /* wcChar12 */
144     ' ', 0x00,                  /* wcChar13 */
145     'D', 0x00,                  /* wcChar14 */
146     'E', 0x00,                  /* wcChar15 */
147     'M', 0x00,                  /* wcChar16 */
148     'O', 0x00,                  /* wcChar17 */
149     ///////////////////////////////////////
150     /// string3 descriptor
151     ///////////////////////////////////////
152     0x16,                       /* bLength */
153     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
154     '2', 0x00,                  /* wcChar0 */
155     '0', 0x00,                  /* wcChar1 */
156     '2', 0x00,                  /* wcChar2 */
157     '2', 0x00,                  /* wcChar3 */
158     '1', 0x00,                  /* wcChar4 */
159     '2', 0x00,                  /* wcChar5 */
160     '3', 0x00,                  /* wcChar6 */
161     '4', 0x00,                  /* wcChar7 */
162     '5', 0x00,                  /* wcChar8 */
163     '6', 0x00,                  /* wcChar9 */
164 #ifdef CONFIG_USB_HS
165     ///////////////////////////////////////
166     /// device qualifier descriptor
167     ///////////////////////////////////////
168     0x0a,
169     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
170     0x00,
171     0x02,
172     0x00,
173     0x00,
174     0x00,
175     0x40,
176     0x00,
177     0x00,
178 #endif
179     0x00
180 };
181 #endif
182 
183 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
184 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
185 
186 volatile bool ep_tx_busy_flag = false;
187 
usbd_event_handler(uint8_t busid,uint8_t event)188 static void usbd_event_handler(uint8_t busid, uint8_t event)
189 {
190     switch (event) {
191         case USBD_EVENT_RESET:
192             break;
193         case USBD_EVENT_CONNECTED:
194             break;
195         case USBD_EVENT_DISCONNECTED:
196             break;
197         case USBD_EVENT_RESUME:
198             break;
199         case USBD_EVENT_SUSPEND:
200             break;
201         case USBD_EVENT_CONFIGURED:
202             ep_tx_busy_flag = false;
203             /* setup first out ep read transfer */
204             usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
205             break;
206         case USBD_EVENT_SET_REMOTE_WAKEUP:
207             break;
208         case USBD_EVENT_CLR_REMOTE_WAKEUP:
209             break;
210 
211         default:
212             break;
213     }
214 }
215 
usbd_cdc_acm_bulk_out(uint8_t busid,uint8_t ep,uint32_t nbytes)216 void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
217 {
218     USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
219     /* setup next out ep read transfer */
220     usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
221 }
222 
usbd_cdc_acm_bulk_in(uint8_t busid,uint8_t ep,uint32_t nbytes)223 void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
224 {
225     USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
226 
227     if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
228         /* send zlp */
229         usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
230     } else {
231         ep_tx_busy_flag = false;
232     }
233 }
234 
235 /*!< endpoint call back */
236 struct usbd_endpoint cdc_out_ep = {
237     .ep_addr = CDC_OUT_EP,
238     .ep_cb = usbd_cdc_acm_bulk_out
239 };
240 
241 struct usbd_endpoint cdc_in_ep = {
242     .ep_addr = CDC_IN_EP,
243     .ep_cb = usbd_cdc_acm_bulk_in
244 };
245 
246 struct usbd_interface intf0;
247 struct usbd_interface intf1;
248 struct usbd_interface intf2;
249 
cdc_acm_msc_init(uint8_t busid,uintptr_t reg_base)250 void cdc_acm_msc_init(uint8_t busid, uintptr_t reg_base)
251 {
252 #ifdef CONFIG_USBDEV_ADVANCE_DESC
253     usbd_desc_register(busid, &cdc_msc_descriptor);
254 #else
255     usbd_desc_register(busid, cdc_msc_descriptor);
256 #endif
257     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
258     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
259     usbd_add_endpoint(busid, &cdc_out_ep);
260     usbd_add_endpoint(busid, &cdc_in_ep);
261     usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
262 
263     usbd_initialize(busid, reg_base, usbd_event_handler);
264 }
265 
266 volatile uint8_t dtr_enable = 0;
267 
usbd_cdc_acm_set_dtr(uint8_t busid,uint8_t intf,bool dtr)268 void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
269 {
270     if (dtr) {
271         dtr_enable = 1;
272     } else {
273         dtr_enable = 0;
274     }
275 }
276 
cdc_acm_data_send_with_dtr_test(uint8_t busid)277 void cdc_acm_data_send_with_dtr_test(uint8_t busid)
278 {
279     if (dtr_enable) {
280         memset(&write_buffer[10], 'a', 2038);
281         ep_tx_busy_flag = true;
282         usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
283         while (ep_tx_busy_flag) {
284         }
285     }
286 }
287 
288 #define BLOCK_SIZE  512
289 #define BLOCK_COUNT 10
290 
291 typedef struct
292 {
293     uint8_t BlockSpace[BLOCK_SIZE];
294 } BLOCK_TYPE;
295 
296 BLOCK_TYPE mass_block[BLOCK_COUNT];
297 
usbd_msc_get_cap(uint8_t busid,uint8_t lun,uint32_t * block_num,uint32_t * block_size)298 void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
299 {
300     *block_num = 1000; //Pretend having so many buffer,not has actually.
301     *block_size = BLOCK_SIZE;
302 }
usbd_msc_sector_read(uint8_t busid,uint8_t lun,uint32_t sector,uint8_t * buffer,uint32_t length)303 int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
304 {
305     if (sector < 10)
306         memcpy(buffer, mass_block[sector].BlockSpace, length);
307     return 0;
308 }
309 
usbd_msc_sector_write(uint8_t busid,uint8_t lun,uint32_t sector,uint8_t * buffer,uint32_t length)310 int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
311 {
312     if (sector < 10)
313         memcpy(mass_block[sector].BlockSpace, buffer, length);
314     return 0;
315 }