1 /*
2  * Copyright (c) 2024, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usbd_adb.h"
8 
9 /*!< endpoint address */
10 #define WINUSB_IN_EP       0x81
11 #define WINUSB_OUT_EP      0x02
12 
13 #define USBD_VID           0xFFFF
14 #define USBD_PID           0xFFFF
15 #define USBD_MAX_POWER     100
16 #define USBD_LANGID_STRING 1033
17 
18 /*!< config descriptor size */
19 #define USB_CONFIG_SIZE    (9 + 9 + 7 + 7)
20 
21 #ifdef CONFIG_USB_HS
22 #define WINUSB_MAX_MPS 512
23 #else
24 #define WINUSB_MAX_MPS 64
25 #endif
26 
27 #define WCID_VENDOR_CODE 0x17
28 #define ADB_INTF_NUM 0
29 
30 __ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
31     ///////////////////////////////////////
32     /// MS OS string descriptor
33     ///////////////////////////////////////
34     0x12,                       /* bLength */
35     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
36     /* MSFT100 */
37     'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
38     '1', 0x00, '0', 0x00, '0', 0x00,            /* wcChar_7 */
39     WCID_VENDOR_CODE,                           /* bVendorCode */
40     0x00,                                       /* bReserved */
41 };
42 
43 __ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
44     ///////////////////////////////////////
45     /// WCID descriptor
46     ///////////////////////////////////////
47     0x28, 0x00, 0x00, 0x00,                   /* dwLength */
48     0x00, 0x01,                               /* bcdVersion */
49     0x04, 0x00,                               /* wIndex */
50     0x01,                                     /* bCount */
51     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
52 
53     ///////////////////////////////////////
54     /// WCID function descriptor
55     ///////////////////////////////////////
56     ADB_INTF_NUM, /* bFirstInterfaceNumber */
57     0x01, /* bReserved */
58     /* Compatible ID */
59     'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8: WINUSB */
60     /*  */
61     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
62     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* bReserved_6 */
63 };
64 
65 __ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
66     ///////////////////////////////////////
67     /// WCID property descriptor
68     ///////////////////////////////////////
69     0x8e, 0x00, 0x00, 0x00, /* dwLength */
70     0x00, 0x01,             /* bcdVersion */
71     0x05, 0x00,             /* wIndex */
72     0x01, 0x00,             /* wCount */
73 
74     ///////////////////////////////////////
75     /// registry propter descriptor
76     ///////////////////////////////////////
77     0x84, 0x00, 0x00, 0x00, /* dwSize */
78     0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
79     0x28, 0x00,             /* wPropertyNameLength */
80     /* DeviceInterfaceGUID */
81     'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00,  /* wcName_20 */
82     'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00,  /* wcName_20 */
83     't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00,  /* wcName_20 */
84     'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00,  /* wcName_20 */
85     'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
86     0x4e, 0x00, 0x00, 0x00,                      /* dwPropertyDataLength */
87     /* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
88     '{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
89     'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
90     '5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
91     '4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
92     '8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
93     'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
94     '-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
95     'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
96     'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
97     '6', 0x00, '}', 0x00, 0x00, 0x00,           /* wcData_39 */
98 };
99 
100 const uint8_t *WINUSB_IFx_WCIDProperties[] = {
101     WINUSB_IF0_WCIDProperties,
102 };
103 
104 struct usb_msosv1_descriptor msosv1_desc = {
105     .string = WCID_StringDescriptor_MSOS,
106     .vendor_code = WCID_VENDOR_CODE,
107     .compat_id = WINUSB_WCIDDescriptor,
108     .comp_id_property = WINUSB_IFx_WCIDProperties,
109 };
110 
111 #ifdef CONFIG_USBDEV_ADVANCE_DESC
112 static const uint8_t device_descriptor[] = {
113     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01)
114 };
115 
116 static const uint8_t config_descriptor[] = {
117     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
118     ADB_DESCRIPTOR_INIT(ADB_INTF_NUM, WINUSB_IN_EP, WINUSB_OUT_EP, WINUSB_MAX_MPS)
119 };
120 
121 static const uint8_t device_quality_descriptor[] = {
122     ///////////////////////////////////////
123     /// device qualifier descriptor
124     ///////////////////////////////////////
125     0x0a,
126     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
127     0x00,
128     0x02,
129     0x00,
130     0x00,
131     0x00,
132     0x40,
133     0x00,
134     0x00,
135 };
136 
137 static const char *string_descriptors[] = {
138     (const char[]){ 0x09, 0x04 }, /* Langid */
139     "CherryUSB",                  /* Manufacturer */
140     "CherryADB",                  /* Product */
141     "CherryADB2024",              /* Serial Number */
142 };
143 
device_descriptor_callback(uint8_t speed)144 static const uint8_t *device_descriptor_callback(uint8_t speed)
145 {
146     return device_descriptor;
147 }
148 
config_descriptor_callback(uint8_t speed)149 static const uint8_t *config_descriptor_callback(uint8_t speed)
150 {
151     return config_descriptor;
152 }
153 
device_quality_descriptor_callback(uint8_t speed)154 static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
155 {
156     return device_quality_descriptor;
157 }
158 
string_descriptor_callback(uint8_t speed,uint8_t index)159 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
160 {
161     if (index > 3) {
162         return NULL;
163     }
164     return string_descriptors[index];
165 }
166 
167 const struct usb_descriptor adb_descriptor = {
168     .device_descriptor_callback = device_descriptor_callback,
169     .config_descriptor_callback = config_descriptor_callback,
170     .device_quality_descriptor_callback = device_quality_descriptor_callback,
171     .string_descriptor_callback = string_descriptor_callback,
172     .msosv1_descriptor = &msosv1_desc
173 };
174 #else
175 /*!< global descriptor */
176 static const uint8_t adb_descriptor[] = {
177     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
178     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
179     ADB_DESCRIPTOR_INIT(ADB_INTF_NUM, WINUSB_IN_EP, WINUSB_OUT_EP, WINUSB_MAX_MPS),
180     ///////////////////////////////////////
181     /// string0 descriptor
182     ///////////////////////////////////////
183     USB_LANGID_INIT(USBD_LANGID_STRING),
184     ///////////////////////////////////////
185     /// string1 descriptor
186     ///////////////////////////////////////
187     0x14,                       /* bLength */
188     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
189     'C', 0x00,                  /* wcChar0 */
190     'h', 0x00,                  /* wcChar1 */
191     'e', 0x00,                  /* wcChar2 */
192     'r', 0x00,                  /* wcChar3 */
193     'r', 0x00,                  /* wcChar4 */
194     'y', 0x00,                  /* wcChar5 */
195     'U', 0x00,                  /* wcChar6 */
196     'S', 0x00,                  /* wcChar7 */
197     'B', 0x00,                  /* wcChar8 */
198     ///////////////////////////////////////
199     /// string2 descriptor
200     ///////////////////////////////////////
201     0x14,                       /* bLength */
202     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
203     'C', 0x00,                  /* wcChar0 */
204     'h', 0x00,                  /* wcChar1 */
205     'e', 0x00,                  /* wcChar2 */
206     'r', 0x00,                  /* wcChar3 */
207     'r', 0x00,                  /* wcChar4 */
208     'y', 0x00,                  /* wcChar5 */
209     'A', 0x00,                  /* wcChar6 */
210     'D', 0x00,                  /* wcChar7 */
211     'B', 0x00,                  /* wcChar8 */
212     ///////////////////////////////////////
213     /// string3 descriptor
214     ///////////////////////////////////////
215     0x1C,                       /* bLength */
216     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
217     'C', 0x00,                  /* wcChar0 */
218     'h', 0x00,                  /* wcChar1 */
219     'e', 0x00,                  /* wcChar2 */
220     'r', 0x00,                  /* wcChar3 */
221     'r', 0x00,                  /* wcChar4 */
222     'y', 0x00,                  /* wcChar5 */
223     'A', 0x00,                  /* wcChar6 */
224     'D', 0x00,                  /* wcChar7 */
225     'B', 0x00,                  /* wcChar8 */
226     '2', 0x00,                  /* wcChar9 */
227     '0', 0x00,                  /* wcChar10 */
228     '2', 0x00,                  /* wcChar11 */
229     '4', 0x00,                  /* wcChar12 */
230 #ifdef CONFIG_USB_HS
231     ///////////////////////////////////////
232     /// device qualifier descriptor
233     ///////////////////////////////////////
234     0x0a,
235     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
236     0x00,
237     0x02,
238     0x00,
239     0x00,
240     0x00,
241     0x40,
242     0x00,
243     0x00,
244 #endif
245     0x00
246 };
247 #endif
248 
usbd_event_handler(uint8_t busid,uint8_t event)249 static void usbd_event_handler(uint8_t busid, uint8_t event)
250 {
251     switch (event) {
252         case USBD_EVENT_RESET:
253             break;
254         case USBD_EVENT_CONNECTED:
255             break;
256         case USBD_EVENT_DISCONNECTED:
257             break;
258         case USBD_EVENT_RESUME:
259             break;
260         case USBD_EVENT_SUSPEND:
261             break;
262         case USBD_EVENT_CONFIGURED:
263 
264             break;
265         case USBD_EVENT_SET_REMOTE_WAKEUP:
266             break;
267         case USBD_EVENT_CLR_REMOTE_WAKEUP:
268             break;
269 
270         default:
271             break;
272     }
273 }
274 
275 static struct usbd_interface intf0;
276 
277 #ifdef RT_USING_MSH
278 extern void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep);
279 #else
280 extern int shell_init(bool need_login);
281 #endif
cherryadb_init(uint8_t busid,uint32_t reg_base)282 void cherryadb_init(uint8_t busid, uint32_t reg_base)
283 {
284 #ifdef RT_USING_MSH
285     usbd_adb_shell_init(WINUSB_IN_EP, WINUSB_OUT_EP);
286 #else
287     /* default password is : 12345678 */
288     /* shell_init() must be called in-task */
289     if (0 != shell_init(false)) {
290         /* shell failed to be initialized */
291         printf("Failed to initialize shell\r\n");
292         for (;;) {
293             ;
294         }
295     }
296 #endif
297 #ifdef CONFIG_USBDEV_ADVANCE_DESC
298     usbd_desc_register(busid, &adb_descriptor);
299 #else
300     usbd_desc_register(busid, adb_descriptor);
301 #endif
302 #ifndef CONFIG_USBDEV_ADVANCE_DESC
303     usbd_msosv1_desc_register(busid, &msosv1_desc);
304 #endif
305     usbd_add_interface(busid, usbd_adb_init_intf(busid, &intf0, WINUSB_IN_EP, WINUSB_OUT_EP));
306     usbd_initialize(busid, reg_base, usbd_event_handler);
307 }
308