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