xref: /nrf52832-nimble/rt-thread/components/drivers/usb/usbdevice/class/winusb.c (revision 104654410c56c573564690304ae786df310c91fc)
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