xref: /nrf52832-nimble/rt-thread/components/drivers/usb/usbhost/core/core.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2011-12-12     Yi Qiu      first version
9  */
10 
11 #include <rtthread.h>
12 #include <drivers/usb_host.h>
13 
14 static struct uinstance dev[USB_MAX_DEVICE];
15 
16 /**
17  * This function will allocate an usb device instance from system.
18  *
19  * @param parent the hub instance to which the new allocated device attached.
20  * @param port the hub port.
21  *
22  * @return the allocate instance on successful, or RT_NULL on failure.
23  */
rt_usbh_alloc_instance(uhcd_t uhcd)24 uinst_t rt_usbh_alloc_instance(uhcd_t uhcd)
25 {
26     int i;
27 
28     /* lock scheduler */
29     rt_enter_critical();
30 
31     for(i=0; i<USB_MAX_DEVICE; i++)
32     {
33         /* to find an idle instance handle */
34         if(dev[i].status != DEV_STATUS_IDLE) continue;
35 
36         /* initialize the usb device instance */
37         rt_memset(&dev[i], 0, sizeof(struct uinstance));
38 
39         dev[i].status = DEV_STATUS_BUSY;
40         dev[i].index = i + 1;
41         dev[i].address = 0;
42         dev[i].max_packet_size = 0x8;
43         rt_list_init(&dev[i].pipe);
44         dev[i].hcd = uhcd;
45         /* unlock scheduler */
46         rt_exit_critical();
47         return &dev[i];
48     }
49 
50     /* unlock scheduler */
51     rt_exit_critical();
52 
53     return RT_NULL;
54 }
55 
56 /**
57  * This function will attatch an usb device instance to a host controller,
58  * and do device enumunation process.
59  *
60  * @param hcd the host controller driver.
61  * @param device the usb device instance.
62  *
63  * @return the error code, RT_EOK on successfully.
64  */
65 static struct uendpoint_descriptor ep0_out_desc =
66 {
67     /*endpoint descriptor*/
68     USB_DESC_LENGTH_ENDPOINT,
69     USB_DESC_TYPE_ENDPOINT,
70     0x00 | USB_DIR_OUT,
71     USB_EP_ATTR_CONTROL,
72     0x00,
73     0x00,
74 };
75 static struct uendpoint_descriptor ep0_in_desc =
76 {
77     /*endpoint descriptor*/
78     USB_DESC_LENGTH_ENDPOINT,
79     USB_DESC_TYPE_ENDPOINT,
80     0x00 | USB_DIR_IN,
81     USB_EP_ATTR_CONTROL,
82     0x00,
83     0x00,
84 };
rt_usbh_attatch_instance(uinst_t device)85 rt_err_t rt_usbh_attatch_instance(uinst_t device)
86 {
87     int i = 0;
88     rt_err_t ret = RT_EOK;
89     struct uconfig_descriptor cfg_desc;
90     udev_desc_t dev_desc;
91     uintf_desc_t intf_desc;
92     uep_desc_t ep_desc;
93     rt_uint8_t ep_index;
94     upipe_t pipe;
95     ucd_t drv;
96 
97     RT_ASSERT(device != RT_NULL);
98 
99     rt_memset(&cfg_desc, 0, sizeof(struct uconfig_descriptor));
100     dev_desc = &device->dev_desc;
101 
102     /* alloc address 0 ep0 pipe*/
103     ep0_out_desc.wMaxPacketSize = 8;
104     ep0_in_desc.wMaxPacketSize = 8;
105     rt_usb_hcd_alloc_pipe(device->hcd, &device->pipe_ep0_out, device, &ep0_out_desc);
106     rt_usb_hcd_alloc_pipe(device->hcd, &device->pipe_ep0_in, device, &ep0_in_desc);
107 
108     RT_DEBUG_LOG(RT_DEBUG_USB, ("start enumnation\n"));
109 
110     /* get device descriptor head */
111     ret = rt_usbh_get_descriptor(device, USB_DESC_TYPE_DEVICE, (void*)dev_desc, 8);
112     if(ret != RT_EOK)
113     {
114         rt_kprintf("get device descriptor head failed\n");
115         return ret;
116     }
117 
118     /* reset bus */
119     rt_usbh_hub_reset_port(device->parent_hub, device->port);
120     rt_thread_delay(2);
121     rt_usbh_hub_clear_port_feature(device->parent_hub, i + 1, PORT_FEAT_C_CONNECTION);
122     /* set device address */
123     ret = rt_usbh_set_address(device);
124     if(ret != RT_EOK)
125     {
126         rt_kprintf("set device address failed\n");
127         return ret;
128     }
129     /* free address 0 ep0 pipe*/
130 
131     rt_usb_hcd_free_pipe(device->hcd,device->pipe_ep0_out);
132     rt_usb_hcd_free_pipe(device->hcd,device->pipe_ep0_in);
133 
134     /* set device max packet size */
135     ep0_out_desc.wMaxPacketSize = device->dev_desc.bMaxPacketSize0;
136     ep0_in_desc.wMaxPacketSize = device->dev_desc.bMaxPacketSize0;
137 
138     /* alloc true address ep0 pipe*/
139     rt_usb_hcd_alloc_pipe(device->hcd, &device->pipe_ep0_out, device, &ep0_out_desc);
140     rt_usb_hcd_alloc_pipe(device->hcd, &device->pipe_ep0_in, device, &ep0_in_desc);
141     RT_DEBUG_LOG(RT_DEBUG_USB, ("get device descriptor length %d\n",
142                                 dev_desc->bLength));
143 
144     /* get full device descriptor again */
145     ret = rt_usbh_get_descriptor(device, USB_DESC_TYPE_DEVICE, (void*)dev_desc, dev_desc->bLength);
146     if(ret != RT_EOK)
147     {
148         rt_kprintf("get full device descriptor failed\n");
149         return ret;
150     }
151 
152     RT_DEBUG_LOG(RT_DEBUG_USB, ("Vendor ID 0x%x\n", dev_desc->idVendor));
153     RT_DEBUG_LOG(RT_DEBUG_USB, ("Product ID 0x%x\n", dev_desc->idProduct));
154 
155     /* get configuration descriptor head */
156     ret = rt_usbh_get_descriptor(device, USB_DESC_TYPE_CONFIGURATION, &cfg_desc, 18);
157     if(ret != RT_EOK)
158     {
159         rt_kprintf("get configuration descriptor head failed\n");
160         return ret;
161     }
162 
163     /* alloc memory for configuration descriptor */
164     device->cfg_desc = (ucfg_desc_t)rt_malloc(cfg_desc.wTotalLength);
165     rt_memset(device->cfg_desc, 0, cfg_desc.wTotalLength);
166 
167     /* get full configuration descriptor */
168     ret = rt_usbh_get_descriptor(device, USB_DESC_TYPE_CONFIGURATION,
169         device->cfg_desc, cfg_desc.wTotalLength);
170     if(ret != RT_EOK)
171     {
172         rt_kprintf("get full configuration descriptor failed\n");
173         return ret;
174     }
175 
176     /* set configuration */
177     ret = rt_usbh_set_configure(device, 1);
178     if(ret != RT_EOK)
179     {
180         return ret;
181     }
182     for(i=0; i<device->cfg_desc->bNumInterfaces; i++)
183     {
184         /* get interface descriptor through configuration descriptor */
185         ret = rt_usbh_get_interface_descriptor(device->cfg_desc, i, &intf_desc);
186         if(ret != RT_EOK)
187         {
188             rt_kprintf("rt_usb_get_interface_descriptor error\n");
189             return -RT_ERROR;
190         }
191 
192         RT_DEBUG_LOG(RT_DEBUG_USB, ("interface class 0x%x, subclass 0x%x\n",
193                                     intf_desc->bInterfaceClass,
194                                     intf_desc->bInterfaceSubClass));
195         /* alloc pipe*/
196         for(ep_index = 0; ep_index < intf_desc->bNumEndpoints; ep_index++)
197         {
198             rt_usbh_get_endpoint_descriptor(intf_desc, ep_index, &ep_desc);
199             if(ep_desc != RT_NULL)
200             {
201                 if(rt_usb_hcd_alloc_pipe(device->hcd, &pipe, device, ep_desc) != RT_EOK)
202                 {
203                     rt_kprintf("alloc pipe failed\n");
204                     return RT_ERROR;
205                 }
206                 rt_usb_instance_add_pipe(device,pipe);
207             }
208             else
209             {
210                 rt_kprintf("get endpoint desc failed\n");
211                 return RT_ERROR;
212             }
213         }
214         /* find driver by class code found in interface descriptor */
215         drv = rt_usbh_class_driver_find(intf_desc->bInterfaceClass,
216             intf_desc->bInterfaceSubClass);
217 
218         if(drv != RT_NULL)
219         {
220             /* allocate memory for interface device */
221             device->intf[i] = (struct uhintf*)rt_malloc(sizeof(struct uhintf));
222             device->intf[i]->drv = drv;
223             device->intf[i]->device = device;
224             device->intf[i]->intf_desc = intf_desc;
225             device->intf[i]->user_data = RT_NULL;
226 
227             /* open usb class driver */
228             ret = rt_usbh_class_driver_enable(drv, (void*)device->intf[i]);
229             if(ret != RT_EOK)
230             {
231                 rt_kprintf("interface %d run class driver error\n", i);
232             }
233         }
234         else
235         {
236             rt_kprintf("find usb device driver failed\n");
237             continue;
238         }
239     }
240 
241     return RT_EOK;
242 }
243 
244 /**
245  * This function will detach an usb device instance from its host controller,
246  * and release all resource.
247  *
248  * @param device the usb device instance.
249  *
250  * @return the error code, RT_EOK on successfully.
251  */
rt_usbh_detach_instance(uinst_t device)252 rt_err_t rt_usbh_detach_instance(uinst_t device)
253 {
254     int i = 0;
255     rt_list_t * l;
256     if(device == RT_NULL)
257     {
258         rt_kprintf("no usb instance to detach\n");
259         return -RT_ERROR;
260     }
261 
262     /* free configration descriptor */
263     if (device->cfg_desc) {
264         for (i = 0; i < device->cfg_desc->bNumInterfaces; i++)
265         {
266             if (device->intf[i] == RT_NULL) continue;
267             if (device->intf[i]->drv == RT_NULL) continue;
268 
269             RT_ASSERT(device->intf[i]->device == device);
270 
271             RT_DEBUG_LOG(RT_DEBUG_USB, ("free interface instance %d\n", i));
272             rt_usbh_class_driver_disable(device->intf[i]->drv, (void*)device->intf[i]);
273             rt_free(device->intf[i]);
274         }
275         rt_free(device->cfg_desc);
276     }
277 
278     rt_usb_hcd_free_pipe(device->hcd,device->pipe_ep0_out);
279     rt_usb_hcd_free_pipe(device->hcd,device->pipe_ep0_in);
280 
281     while(device->pipe.next!= &device->pipe)
282     {
283         l = device->pipe.next;
284         rt_list_remove(l);
285         rt_usb_hcd_free_pipe(device->hcd,rt_list_entry(l,struct upipe,list));
286     }
287     rt_memset(device, 0, sizeof(struct uinstance));
288 
289     return RT_EOK;
290 }
291 
292 /**
293  * This function will do USB_REQ_GET_DESCRIPTO' bRequest for the usb device instance,
294  *
295  * @param device the usb device instance.
296  * @param type the type of descriptor bRequest.
297  * @param buffer the data buffer to save requested data
298  * @param nbytes the size of buffer
299  *
300  * @return the error code, RT_EOK on successfully.
301  */
rt_usbh_get_descriptor(uinst_t device,rt_uint8_t type,void * buffer,int nbytes)302 rt_err_t rt_usbh_get_descriptor(uinst_t device, rt_uint8_t type, void* buffer,
303     int nbytes)
304 {
305     struct urequest setup;
306     int timeout = USB_TIMEOUT_BASIC;
307 
308     RT_ASSERT(device != RT_NULL);
309 
310     setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD |
311         USB_REQ_TYPE_DEVICE;
312     setup.bRequest = USB_REQ_GET_DESCRIPTOR;
313     setup.wIndex = 0;
314     setup.wLength = nbytes;
315     setup.wValue = type << 8;
316 
317     if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) == 8)
318     {
319         if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, buffer, nbytes, timeout) == nbytes)
320         {
321             if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_out, RT_NULL, 0, timeout) == 0)
322             {
323                 return RT_EOK;
324             }
325         }
326     }
327     return RT_ERROR;
328 }
329 
330 /**
331  * This function will set an address to the usb device.
332  *
333  * @param device the usb device instance.
334  *
335  * @return the error code, RT_EOK on successfully.
336  */
rt_usbh_set_address(uinst_t device)337 rt_err_t rt_usbh_set_address(uinst_t device)
338 {
339     struct urequest setup;
340     int timeout = USB_TIMEOUT_BASIC;
341 
342     RT_ASSERT(device != RT_NULL);
343 
344     RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_set_address\n"));
345 
346     setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
347         USB_REQ_TYPE_DEVICE;
348     setup.bRequest = USB_REQ_SET_ADDRESS;
349     setup.wIndex = 0;
350     setup.wLength = 0;
351     setup.wValue = device->index;
352 
353     if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) != 8)
354     {
355         return RT_ERROR;
356     }
357     if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, RT_NULL, 0, timeout) == 0)
358     {
359         device->address = device->index;
360     }
361 
362     return RT_EOK;
363 }
364 
365 /**
366  * This function will set a configuration to the usb device.
367  *
368  * @param device the usb device instance.
369  * @param config the configuration number.
370   *
371  * @return the error code, RT_EOK on successfully.
372  */
rt_usbh_set_configure(uinst_t device,int config)373 rt_err_t rt_usbh_set_configure(uinst_t device, int config)
374 {
375     struct urequest setup;
376     int timeout = USB_TIMEOUT_BASIC;
377 
378     /* check parameter */
379     RT_ASSERT(device != RT_NULL);
380 
381     setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
382         USB_REQ_TYPE_DEVICE;
383     setup.bRequest = USB_REQ_SET_CONFIGURATION;
384     setup.wIndex = 0;
385     setup.wLength = 0;
386     setup.wValue = config;
387 
388     if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) != 8)
389     {
390         return RT_ERROR;
391     }
392     if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, RT_NULL, 0, timeout) != 0)
393     {
394         return RT_ERROR;
395     }
396     return RT_EOK;
397 }
398 
399 /**
400  * This function will set an interface to the usb device.
401  *
402  * @param device the usb device instance.
403  * @param intf the interface number.
404  *
405  * @return the error code, RT_EOK on successfully.
406  */
rt_usbh_set_interface(uinst_t device,int intf)407 rt_err_t rt_usbh_set_interface(uinst_t device, int intf)
408 {
409     struct urequest setup;
410     int timeout = USB_TIMEOUT_BASIC;
411 
412     /* check parameter */
413     RT_ASSERT(device != RT_NULL);
414 
415     setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
416         USB_REQ_TYPE_INTERFACE;
417     setup.bRequest = USB_REQ_SET_INTERFACE;
418     setup.wIndex = 0;
419     setup.wLength = 0;
420     setup.wValue = intf;
421 
422     if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) != 8)
423     {
424         return RT_ERROR;
425     }
426 
427     return RT_EOK;
428 }
429 
430 /**
431  * This function will clear feature for the endpoint of the usb device.
432  *
433  * @param device the usb device instance.
434  * @param endpoint the endpoint number of the usb device.
435  *
436  * @return the error code, RT_EOK on successfully.
437  */
rt_usbh_clear_feature(uinst_t device,int endpoint,int feature)438 rt_err_t rt_usbh_clear_feature(uinst_t device, int endpoint, int feature)
439 {
440     struct urequest setup;
441     int timeout = USB_TIMEOUT_BASIC;
442 
443     /* check parameter */
444     RT_ASSERT(device != RT_NULL);
445 
446     setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
447         USB_REQ_TYPE_ENDPOINT;
448     setup.bRequest = USB_REQ_CLEAR_FEATURE;
449     setup.wIndex = endpoint;
450     setup.wLength = 0;
451     setup.wValue = feature;
452 
453     if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) != 8)
454     {
455         return RT_ERROR;
456     }
457 
458     return RT_EOK;
459 }
460 
461 /**
462  * This function will get an interface descriptor from the configuration descriptor.
463  *
464  * @param cfg_desc the point of configuration descriptor structure.
465  * @param num the number of interface descriptor.
466  * @intf_desc the point of interface descriptor point.
467  *
468  * @return the error code, RT_EOK on successfully.
469  */
rt_usbh_get_interface_descriptor(ucfg_desc_t cfg_desc,int num,uintf_desc_t * intf_desc)470 rt_err_t rt_usbh_get_interface_descriptor(ucfg_desc_t cfg_desc, int num,
471     uintf_desc_t* intf_desc)
472 {
473     rt_uint32_t ptr, depth = 0;
474     udesc_t desc;
475 
476     /* check parameter */
477     RT_ASSERT(cfg_desc != RT_NULL);
478 
479     ptr = (rt_uint32_t)cfg_desc + cfg_desc->bLength;
480     while(ptr < (rt_uint32_t)cfg_desc + cfg_desc->wTotalLength)
481     {
482         if(depth++ > 0x20)
483         {
484             *intf_desc = RT_NULL;
485             return -RT_EIO;
486         }
487         desc = (udesc_t)ptr;
488         if(desc->type == USB_DESC_TYPE_INTERFACE)
489         {
490             if(((uintf_desc_t)desc)->bInterfaceNumber == num)
491             {
492                 *intf_desc = (uintf_desc_t)desc;
493 
494                 RT_DEBUG_LOG(RT_DEBUG_USB,
495                              ("rt_usb_get_interface_descriptor: %d\n", num));
496                 return RT_EOK;
497             }
498         }
499         ptr = (rt_uint32_t)desc + desc->bLength;
500     }
501 
502     rt_kprintf("rt_usb_get_interface_descriptor %d failed\n", num);
503     return -RT_EIO;
504 }
505 
506 /**
507  * This function will get an endpoint descriptor from the interface descriptor.
508  *
509  * @param intf_desc the point of interface descriptor structure.
510  * @param num the number of endpoint descriptor.
511  * @param ep_desc the point of endpoint descriptor point.
512  *
513  * @return the error code, RT_EOK on successfully.
514  */
rt_usbh_get_endpoint_descriptor(uintf_desc_t intf_desc,int num,uep_desc_t * ep_desc)515 rt_err_t rt_usbh_get_endpoint_descriptor(uintf_desc_t intf_desc, int num,
516     uep_desc_t* ep_desc)
517 {
518     int count = 0, depth = 0;
519     rt_uint32_t ptr;
520     udesc_t desc;
521 
522     /* check parameter */
523     RT_ASSERT(intf_desc != RT_NULL);
524     RT_ASSERT(num < intf_desc->bNumEndpoints);
525     *ep_desc = RT_NULL;
526 
527     ptr = (rt_uint32_t)intf_desc + intf_desc->bLength;
528     while(count < intf_desc->bNumEndpoints)
529     {
530         if(depth++ > 0x20)
531         {
532             *ep_desc = RT_NULL;
533             return -RT_EIO;
534         }
535         desc = (udesc_t)ptr;
536         if(desc->type == USB_DESC_TYPE_ENDPOINT)
537         {
538             if(num == count)
539             {
540                 *ep_desc = (uep_desc_t)desc;
541 
542                 RT_DEBUG_LOG(RT_DEBUG_USB,
543                              ("rt_usb_get_endpoint_descriptor: %d\n", num));
544                 return RT_EOK;
545             }
546             else count++;
547         }
548         ptr = (rt_uint32_t)desc + desc->bLength;
549     }
550 
551     rt_kprintf("rt_usb_get_endpoint_descriptor %d failed\n", num);
552     return -RT_EIO;
553 }
554 
rt_usb_hcd_pipe_xfer(uhcd_t hcd,upipe_t pipe,void * buffer,int nbytes,int timeout)555 int rt_usb_hcd_pipe_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, int nbytes, int timeout)
556 {
557     rt_size_t remain_size;
558     rt_size_t send_size;
559     remain_size = nbytes;
560     rt_uint8_t * pbuffer = (rt_uint8_t *)buffer;
561     do
562     {
563         RT_DEBUG_LOG(RT_DEBUG_USB,("pipe transform remain size,: %d\n", remain_size));
564         send_size = (remain_size > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : remain_size;
565         if(hcd->ops->pipe_xfer(pipe, USBH_PID_DATA, pbuffer, send_size, timeout) == send_size)
566         {
567             remain_size -= send_size;
568             pbuffer += send_size;
569         }
570         else
571         {
572             return 0;
573         }
574     }while(remain_size > 0);
575     return nbytes;
576 }
577