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