1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2017-11-16 ZYH first version
9 */
10 #include <rthw.h>
11 #include <rtdevice.h>
12 #include <drivers/usb_device.h>
13 #include "winusb.h"
14 struct winusb_device
15 {
16 struct rt_device parent;
17 void (*cmd_handler)(rt_uint8_t *buffer,rt_size_t size);
18 rt_uint8_t cmd_buff[256];
19 uep_t ep_out;
20 uep_t ep_in;
21 };
22 #define WINUSB_INTF_STR_INDEX 13
23 typedef struct winusb_device * winusb_device_t;
24
25 rt_align(4)
26 static struct udevice_descriptor dev_desc =
27 {
28 USB_DESC_LENGTH_DEVICE, //bLength;
29 USB_DESC_TYPE_DEVICE, //type;
30 USB_BCD_VERSION, //bcdUSB;
31 0x00, //bDeviceClass;
32 0x00, //bDeviceSubClass;
33 0x00, //bDeviceProtocol;
34 0x40, //bMaxPacketSize0;
35 _VENDOR_ID, //idVendor;
36 _PRODUCT_ID, //idProduct;
37 USB_BCD_DEVICE, //bcdDevice;
38 USB_STRING_MANU_INDEX, //iManufacturer;
39 USB_STRING_PRODUCT_INDEX, //iProduct;
40 USB_STRING_SERIAL_INDEX, //iSerialNumber;
41 USB_DYNAMIC, //bNumConfigurations;
42 };
43
44 //FS and HS needed
45 rt_align(4)
46 static struct usb_qualifier_descriptor dev_qualifier =
47 {
48 sizeof(dev_qualifier), //bLength
49 USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType
50 0x0200, //bcdUSB
51 0xFF, //bDeviceClass
52 0x00, //bDeviceSubClass
53 0x00, //bDeviceProtocol
54 64, //bMaxPacketSize0
55 0x01, //bNumConfigurations
56 0,
57 };
58
59 rt_align(4)
60 struct winusb_descriptor _winusb_desc =
61 {
62 #ifdef RT_USB_DEVICE_COMPOSITE
63 /* Interface Association Descriptor */
64 {
65 USB_DESC_LENGTH_IAD,
66 USB_DESC_TYPE_IAD,
67 USB_DYNAMIC,
68 0x01,
69 0xFF,
70 0x00,
71 0x00,
72 0x00,
73 },
74 #endif
75 /*interface descriptor*/
76 {
77 USB_DESC_LENGTH_INTERFACE, //bLength;
78 USB_DESC_TYPE_INTERFACE, //type;
79 USB_DYNAMIC, //bInterfaceNumber;
80 0x00, //bAlternateSetting;
81 0x02, //bNumEndpoints
82 0xFF, //bInterfaceClass;
83 0x00, //bInterfaceSubClass;
84 0x00, //bInterfaceProtocol;
85 #ifdef RT_USB_DEVICE_COMPOSITE
86 WINUSB_INTF_STR_INDEX,
87 #else
88 0x00, //iInterface;
89 #endif
90 },
91 /*endpoint descriptor*/
92 {
93 USB_DESC_LENGTH_ENDPOINT,
94 USB_DESC_TYPE_ENDPOINT,
95 USB_DYNAMIC | USB_DIR_OUT,
96 USB_EP_ATTR_BULK,
97 USB_DYNAMIC,
98 0x00,
99 },
100 /*endpoint descriptor*/
101 {
102 USB_DESC_LENGTH_ENDPOINT,
103 USB_DESC_TYPE_ENDPOINT,
104 USB_DYNAMIC | USB_DIR_IN,
105 USB_EP_ATTR_BULK,
106 USB_DYNAMIC,
107 0x00,
108 },
109 };
110
111 rt_align(4)
112 const static char* _ustring[] =
113 {
114 "Language",
115 "RT-Thread Team.",
116 "RTT Win USB",
117 "32021919830108",
118 "Configuration",
119 "Interface",
120 USB_STRING_OS//must be
121 };
122
123 rt_align(4)
124 struct usb_os_proerty winusb_proerty[] =
125 {
126 USB_OS_PROPERTY_DESC(USB_OS_PROPERTY_TYPE_REG_SZ,"DeviceInterfaceGUID",RT_WINUSB_GUID),
127 };
128
129 rt_align(4)
130 struct usb_os_function_comp_id_descriptor winusb_func_comp_id_desc =
131 {
132 .bFirstInterfaceNumber = USB_DYNAMIC,
133 .reserved1 = 0x01,
134 .compatibleID = {'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00},
135 .subCompatibleID = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
136 .reserved2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
137 };
138
_ep_out_handler(ufunction_t func,rt_size_t size)139 static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
140 {
141 winusb_device_t winusb_device = (winusb_device_t)func->user_data;
142 if(winusb_device->parent.rx_indicate != RT_NULL)
143 {
144 winusb_device->parent.rx_indicate(&winusb_device->parent, size);
145 }
146 return RT_EOK;
147 }
148
_ep_in_handler(ufunction_t func,rt_size_t size)149 static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
150 {
151 winusb_device_t winusb_device = (winusb_device_t)func->user_data;
152 if(winusb_device->parent.tx_complete != RT_NULL)
153 {
154 winusb_device->parent.tx_complete(&winusb_device->parent, winusb_device->ep_in->buffer);
155 }
156 return RT_EOK;
157 }
158 static ufunction_t cmd_func = RT_NULL;
_ep0_cmd_handler(udevice_t device,rt_size_t size)159 static rt_err_t _ep0_cmd_handler(udevice_t device, rt_size_t size)
160 {
161 winusb_device_t winusb_device;
162
163 if(cmd_func != RT_NULL)
164 {
165 winusb_device = (winusb_device_t)cmd_func->user_data;
166 cmd_func = RT_NULL;
167 if(winusb_device->cmd_handler != RT_NULL)
168 {
169 winusb_device->cmd_handler(winusb_device->cmd_buff,size);
170 }
171 }
172 dcd_ep0_send_status(device->dcd);
173 return RT_EOK;
174 }
_ep0_cmd_read(ufunction_t func,ureq_t setup)175 static rt_err_t _ep0_cmd_read(ufunction_t func, ureq_t setup)
176 {
177 winusb_device_t winusb_device = (winusb_device_t)func->user_data;
178 cmd_func = func;
179 rt_usbd_ep0_read(func->device,winusb_device->cmd_buff,setup->wLength,_ep0_cmd_handler);
180 return RT_EOK;
181 }
_interface_handler(ufunction_t func,ureq_t setup)182 static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
183 {
184 switch(setup->bRequest)
185 {
186 case 'A':
187 switch(setup->wIndex)
188 {
189 case 0x05:
190 usbd_os_proerty_descriptor_send(func,setup,winusb_proerty,sizeof(winusb_proerty)/sizeof(winusb_proerty[0]));
191 break;
192 }
193 break;
194 case 0x0A://customer
195 _ep0_cmd_read(func, setup);
196 break;
197 }
198
199 return RT_EOK;
200 }
_function_enable(ufunction_t func)201 static rt_err_t _function_enable(ufunction_t func)
202 {
203 RT_ASSERT(func != RT_NULL);
204 return RT_EOK;
205 }
_function_disable(ufunction_t func)206 static rt_err_t _function_disable(ufunction_t func)
207 {
208 RT_ASSERT(func != RT_NULL);
209 return RT_EOK;
210 }
211
212 static struct ufunction_ops ops =
213 {
214 _function_enable,
215 _function_disable,
216 RT_NULL,
217 };
218
_winusb_descriptor_config(winusb_desc_t winusb,rt_uint8_t cintf_nr,rt_uint8_t device_is_hs)219 static rt_err_t _winusb_descriptor_config(winusb_desc_t winusb, rt_uint8_t cintf_nr, rt_uint8_t device_is_hs)
220 {
221 #ifdef RT_USB_DEVICE_COMPOSITE
222 winusb->iad_desc.bFirstInterface = cintf_nr;
223 #endif
224 winusb->ep_out_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
225 winusb->ep_in_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
226 winusb_func_comp_id_desc.bFirstInterfaceNumber = cintf_nr;
227 return RT_EOK;
228 }
229
win_usb_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)230 static rt_ssize_t win_usb_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
231 {
232 if(((ufunction_t)dev->user_data)->device->state != USB_STATE_CONFIGURED)
233 {
234 return 0;
235 }
236 winusb_device_t winusb_device = (winusb_device_t)dev;
237 winusb_device->ep_out->buffer = buffer;
238 winusb_device->ep_out->request.buffer = buffer;
239 winusb_device->ep_out->request.size = size;
240 winusb_device->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
241 rt_usbd_io_request(((ufunction_t)dev->user_data)->device,winusb_device->ep_out,&winusb_device->ep_out->request);
242 return size;
243 }
win_usb_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)244 static rt_ssize_t win_usb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
245 {
246 if(((ufunction_t)dev->user_data)->device->state != USB_STATE_CONFIGURED)
247 {
248 return 0;
249 }
250 winusb_device_t winusb_device = (winusb_device_t)dev;
251 winusb_device->ep_in->buffer = (void *)buffer;
252 winusb_device->ep_in->request.buffer = winusb_device->ep_in->buffer;
253 winusb_device->ep_in->request.size = size;
254 winusb_device->ep_in->request.req_type = UIO_REQUEST_WRITE;
255 rt_usbd_io_request(((ufunction_t)dev->user_data)->device,winusb_device->ep_in,&winusb_device->ep_in->request);
256 return size;
257 }
win_usb_control(rt_device_t dev,int cmd,void * args)258 static rt_err_t win_usb_control(rt_device_t dev, int cmd, void *args)
259 {
260 winusb_device_t winusb_device = (winusb_device_t)dev;
261 if(RT_DEVICE_CTRL_CONFIG == cmd)
262 {
263 winusb_device->cmd_handler = (void(*)(rt_uint8_t*,rt_size_t))args;
264 }
265 return RT_EOK;
266 }
267
268 #ifdef RT_USING_DEVICE_OPS
269 const static struct rt_device_ops winusb_device_ops =
270 {
271 RT_NULL,
272 RT_NULL,
273 RT_NULL,
274 win_usb_read,
275 win_usb_write,
276 win_usb_control,
277 };
278 #endif
279
rt_usb_winusb_init(ufunction_t func)280 static rt_err_t rt_usb_winusb_init(ufunction_t func)
281 {
282 winusb_device_t winusb_device = (winusb_device_t)func->user_data;
283 winusb_device->parent.type = RT_Device_Class_Miscellaneous;
284
285 #ifdef RT_USING_DEVICE_OPS
286 winusb_device->parent.ops = &winusb_device_ops;
287 #else
288 winusb_device->parent.init = RT_NULL;
289 winusb_device->parent.open = RT_NULL;
290 winusb_device->parent.close = RT_NULL;
291 winusb_device->parent.read = win_usb_read;
292 winusb_device->parent.write = win_usb_write;
293 winusb_device->parent.control = win_usb_control;
294 #endif
295
296 winusb_device->parent.user_data = func;
297
298
299 return rt_device_register(&winusb_device->parent, "winusb", RT_DEVICE_FLAG_RDWR);
300 }
301
rt_usbd_function_winusb_create(udevice_t device)302 ufunction_t rt_usbd_function_winusb_create(udevice_t device)
303 {
304 ufunction_t func;
305 winusb_device_t winusb_device;
306
307 uintf_t winusb_intf;
308 ualtsetting_t winusb_setting;
309 winusb_desc_t winusb_desc;
310
311 /* parameter check */
312 RT_ASSERT(device != RT_NULL);
313
314 /* set usb device string description */
315 #ifdef RT_USB_DEVICE_COMPOSITE
316 rt_usbd_device_set_interface_string(device, WINUSB_INTF_STR_INDEX, _ustring[2]);
317 #else
318 rt_usbd_device_set_string(device, _ustring);
319 #endif
320
321 /* create a cdc function */
322 func = rt_usbd_function_new(device, &dev_desc, &ops);
323 rt_usbd_device_set_qualifier(device, &dev_qualifier);
324
325 /* allocate memory for cdc vcom data */
326 winusb_device = (winusb_device_t)rt_malloc(sizeof(struct winusb_device));
327 if (winusb_device == NULL)
328 return RT_NULL;
329 rt_memset((void *)winusb_device, 0, sizeof(struct winusb_device));
330 func->user_data = (void*)winusb_device;
331 /* create an interface object */
332 winusb_intf = rt_usbd_interface_new(device, _interface_handler);
333
334 /* create an alternate setting object */
335 winusb_setting = rt_usbd_altsetting_new(sizeof(struct winusb_descriptor));
336
337 /* config desc in alternate setting */
338 rt_usbd_altsetting_config_descriptor(winusb_setting, &_winusb_desc, (rt_off_t)&((winusb_desc_t)0)->intf_desc);
339
340 /* configure the hid interface descriptor */
341 _winusb_descriptor_config(winusb_setting->desc, winusb_intf->intf_num, device->dcd->device_is_hs);
342
343 /* create endpoint */
344 winusb_desc = (winusb_desc_t)winusb_setting->desc;
345 winusb_device->ep_out = rt_usbd_endpoint_new(&winusb_desc->ep_out_desc, _ep_out_handler);
346 winusb_device->ep_in = rt_usbd_endpoint_new(&winusb_desc->ep_in_desc, _ep_in_handler);
347
348 /* add the int out and int in endpoint to the alternate setting */
349 rt_usbd_altsetting_add_endpoint(winusb_setting, winusb_device->ep_out);
350 rt_usbd_altsetting_add_endpoint(winusb_setting, winusb_device->ep_in);
351
352 /* add the alternate setting to the interface, then set default setting */
353 rt_usbd_interface_add_altsetting(winusb_intf, winusb_setting);
354 rt_usbd_set_altsetting(winusb_intf, 0);
355
356 /* add the interface to the mass storage function */
357 rt_usbd_function_add_interface(func, winusb_intf);
358
359 rt_usbd_os_comp_id_desc_add_os_func_comp_id_desc(device->os_comp_id_desc, &winusb_func_comp_id_desc);
360 /* initilize winusb */
361 rt_usb_winusb_init(func);
362 return func;
363 }
364
365 struct udclass winusb_class =
366 {
367 .rt_usbd_function_create = rt_usbd_function_winusb_create
368 };
369
rt_usbd_winusb_class_register(void)370 int rt_usbd_winusb_class_register(void)
371 {
372 rt_usbd_class_register(&winusb_class);
373 return 0;
374 }
375 INIT_PREV_EXPORT(rt_usbd_winusb_class_register);
376