linux usb gadget

2019-04-14 19:14发布

上一篇谈到了usb host以及usb core,这一篇来介绍下usb gadget,usb gadget较usb host出现较晚,随着linux越来越用作嵌入式设备而出现,是一套独立的架构,独立于usb core。


由上图可以看出gadget架构有两个核心抽象层,composite framework和udc core。 composite framework: 由写一个gadget driver需要处理的一些common部分抽象而成,如:ep0 common部分处理(与硬件无关的部分),get descriptor,set configuration等。 由于要处理set configuration,所以composite framework需要知道usb的config以及添加进来的function(usb interface)。 核心函数如下: usb_compostie_probe: 提供给上层的接口,用来注册一个usb composite driver,上图中的android, serial, usb massstorage都是composite driver usb_add_config: 添加一个config usb_add_function: 添加一个function(interface), 如adb,mass storage,serial,rndis。 composite_setup: 处理ep0的setup请求
udc core: 由每一个usd device controller需要提供给composite framework的接口抽象而成,这样usb devcie controller部分就只需要focus在与硬件相关的部分
下面我们以android为例来追一下具体的调用流程 android的init模块会调用 usb_composite_probe(&android_usb_driver, android_bind); 1772 int usb_composite_probe(struct usb_composite_driver *driver, 1773 int (*bind)(struct usb_composite_dev *cdev)) 1774 { 1775 int rc; 1776 if (!driver || !driver->dev || !bind || composite) 1777 return -EINVAL; 1778 1779 if (!driver->name) 1780 driver->name = "composite"; 1781 if (!driver->iProduct) 1782 driver->iProduct = driver->name; 1783 composite_driver.function = (char *) driver->name; 1784 composite_driver.driver.name = driver->name; 1785 composite_driver.max_speed = 1786 min_t(u8, composite_driver.max_speed, driver->max_speed); 1787 composite = driver; 1788 composite_gadget_bind = bind; 1789 rc = switch_dev_register(&compositesdev); 1790 INIT_WORK(&cdusbcmdwork, ctusbcmd_do_work); 1791 if (rc < 0) 1792 pr_err("%s: switch_dev_register fail", __func__); 1793 1794 return usb_gadget_probe_driver(&composite_driver, composite_bind); 1795 }
从代码中可以看出,usb_composite_probe主要是将注册进来的usb_composite_driver(这里是android_usb_driver)与usb_gadget_driver(这里是composite_driver)联系起来,然后调用udc core提供的函数:usb_gadget_probe_driver,并提供callback function: composite_bind给udc core. 先来看composite_bind 1576 static int composite_bind(struct usb_gadget *gadget) 1577 { 1578 struct usb_composite_dev *cdev; 1579 int status = -ENOMEM; 1580 1581 cdev = kzalloc(sizeof *cdev, GFP_KERNEL); 1582 if (!cdev) 1583 return status; 1584 1585 spin_lock_init(&cdev->lock); 1586 cdev->gadget = gadget; 1587 set_gadget_data(gadget, cdev); 1588 INIT_LIST_HEAD(&cdev->configs); 1589 1590 /* preallocate control response and buffer */ 1591 cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); 1592 if (!cdev->req) 1593 goto fail; 1594 cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); 1595 if (!cdev->req->buf) 1596 goto fail; 1597 cdev->req->complete = composite_setup_complete; 1598 gadget->ep0->driver_data = cdev; 1599 1600 cdev->bufsiz = USB_BUFSIZ; 1601 cdev->driver = composite; 1602 1603 INIT_DELAYED_WORK(&cdev->request_reset, composite_request_reset); 1604 /* 1605 * As per USB compliance update, a device that is actively drawing 1606 * more than 100mA from USB must report itself as bus-powered in 1607 * the GetStatus(DEVICE) call. 1608 */ 1609 if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW) 1610 usb_gadget_set_selfpowered(gadget); 1611 1612 /* interface and string IDs start at zero via kzalloc. 1613 * we force endpoints to start unassigned; few controller 1614 * drivers will zero ep->driver_data. 1615 */ 1616 usb_ep_autoconfig_reset(cdev->gadget); 1617 1618 /* composite gadget needs to assign strings for whole device (like 1619 * serial number), register function drivers, potentially update 1620 * power state and consumption, etc 1621 */ 1622 status = composite_gadget_bind(cdev); 1623 if (status < 0) 1624 goto fail; 1625 1626 cdev->desc = *composite->dev; 1627 1628 /* standardized runtime overrides for device ID data */ 1629 if (idVendor) 1630 cdev->desc.idVendor = cpu_to_le16(idVendor); 1631 if (idProduct) 1632 cdev->desc.idProduct = cpu_to_le16(idProduct); 1633 if (bcdDevice) 1634 cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); 1635 1636 /* string overrides */ 1637 if (iManufacturer || !cdev->desc.iManufacturer) { 1638 if (!iManufacturer && !composite->iManufacturer && 1639 !*composite_manufacturer) 1640 snprintf(composite_manufacturer, 1641 sizeof composite_manufacturer, 1642 "%s %s with %s", 1643 init_utsname()->sysname, 1644 init_utsname()->release, 1645 gadget->name); 1646 1647 cdev->manufacturer_override = 1648 override_id(cdev, &cdev->desc.iManufacturer); 1649 } 1650 1651 if (iProduct || (!cdev->desc.iProduct && composite->iProduct)) 1652 cdev->product_override = 1653 override_id(cdev, &cdev->desc.iProduct); 1654 1655 if (iSerialNumber) 1656 cdev->serial_override = 1657 override_id(cdev, &cdev->desc.iSerialNumber); 1658 1659 /* has userspace failed to provide a serial number? */ 1660 if (composite->needs_serial && !cdev->desc.iSerialNumber) 1661 WARNING(cdev, "userspace failed to provide iSerialNumber "); 1662 1663 /* finish up */ 1664 status = device_create_file(&gadget->dev, &dev_attr_suspended); 1665 if (status) 1666 goto fail; 1667 1668 INFO(cdev, "%s ready ", composite->name); 1669 return 0; 1670 1671 fail: 1672 composite_unbind(gadget); 1673 return status; 1674 }
可以看出,composite_bind一开始就新建usb_composite_dev并建立usb_gadget与usb_composite_dev的关系。接下来,usb_ep_alloc_request(gadget->ep0) 分配ep0 usb request. cdev->driver = composite, 这里指定usb_composite_dev的driver为usb_composite_probe注册进来的usb_composite_driver: android_usb_driver status = composite_gadget_bind(cdev); 这里调用的是usb_composite_probe传进来的android_bind,android_bind会调用usb_add_config来添加config。具体的每一个function的添加会在调用usb_add_config时传进来的callback function中完成(这里是android_bind_config,这个函数会调用每一个需要添加的function的bind_config, 而bind_config调用的是usb_add_function)
接下来我们看 usb_gadget_probe_driver,这个函数主要调用usb_gadget_start 119 static inline int usb_gadget_start(struct usb_gadget *gadget, 120 struct usb_gadget_driver *driver, 121 int (*bind)(struct usb_gadget *)) 122 { 123 return gadget->ops->start(driver, bind); 124
可以看出这个函数是udc core层实现的一个接口函数,具体实现在对应的usb device controller中 从参数可以看出,这个函数会将usb_gadget_driver和usb_gadget对应起来,并调用bind(这里为composite_bind,前面已经介绍过了他的作用)。
到这里,上图中的所有模块就已经介绍完了,对于整个gadget大体也有一个概念,不过疑问也来了,这里只涉及到了ep0,别的endpoind如何处理呢? 下面我们以adb为例做个简单的介绍 在composite_bind中有提到,他会调用到每一个需要添加的function的bind_config,adb算是其中一个function,那么我们从adb的bind_config看起。
629 static int adb_bind_config(struct usb_configuration *c) 630 { 631 struct adb_dev *dev = _adb_dev; 632 633 printk(KERN_INFO "adb_bind_config "); 634 635 dev->cdev = c->cdev; 636 dev->function.name = "adb"; 637 dev->function.descriptors = fs_adb_descs; 638 dev->function.hs_descriptors = hs_adb_descs; 639 dev->function.bind = adb_function_bind; 640 dev->function.unbind = adb_function_unbind; 641 dev->function.set_alt = adb_function_set_alt; 642 dev->function.disable = adb_function_disable; 643 644 return usb_add_function(c, &dev->function); 645 }
可以看到正如我们前面所说,这里会调用usb_add_function,在usb_add_function中会调用function.bind,也就是adb_function_bind。 525 static int 526 adb_function_bind(struct usb_configuration *c, struct usb_function *f) 527 { 528 struct usb_composite_dev *cdev = c->cdev; 529 struct adb_dev *dev = func_to_adb(f); 530 int id; 531 int ret; 532 533 dev->cdev = cdev; 534 DBG(cdev, "adb_function_bind dev: %p ", dev); 535 536 /* allocate interface ID(s) */ 537 id = usb_interface_id(c, f); 538 if (id < 0) 539 return id; 540 adb_interface_desc.bInterfaceNumber = id; 541 542 /* allocate endpoints */ 543 ret = adb_create_bulk_endpoints(dev, &adb_fullspeed_in_desc, 544 &adb_fullspeed_out_desc); 545 if (ret) 546 return ret; 547 548 /* support high speed hardware */ 549 if (gadget_is_dualspeed(c->cdev->gadget)) { 550 adb_highspeed_in_desc.bEndpointAddress = 551 adb_fullspeed_in_desc.bEndpointAddress; 552 adb_highspeed_out_desc.bEndpointAddress = 553 adb_fullspeed_out_desc.bEndpointAddress; 554 } 555 556 DBG(cdev, "%s speed %s: IN/%s, OUT/%s ", 557 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 558 f->name, dev->ep_in->name, dev->ep_out->name); 559 return 0; 560 }
可以看出主要的调用是 adb_create_bulk_endpoints 226 static int adb_create_bulk_endpoints(struct adb_dev *dev, 227 struct usb_endpoint_descriptor *in_desc, 228 struct usb_endpoint_descriptor *out_desc) 229 { 230 struct usb_composite_dev *cdev = dev->cdev; 231 struct usb_request *req; 232 struct usb_ep *ep; 233 int i; 234 235 DBG(cdev, "create_bulk_endpoints dev: %p ", dev); 236 237 ep = usb_ep_autoconfig(cdev->gadget, in_desc); 238 if (!ep) { 239 DBG(cdev, "usb_ep_autoconfig for ep_in failed "); 240 return -ENODEV; 241 } 242 DBG(cdev, "usb_ep_autoconfig for ep_in got %s ", ep->name); 243 ep->driver_data = dev; /* claim the endpoint */ 244 dev->ep_in = ep; 245 246 ep = usb_ep_autoconfig(cdev->gadget, out_desc); 247 if (!ep) { 248 DBG(cdev, "usb_ep_autoconfig for ep_out failed "); 249 return -ENODEV; 250 } 251 DBG(cdev, "usb_ep_autoconfig for adb ep_out got %s ", ep->name); 252 ep->driver_data = dev; /* claim the endpoint */ 253 dev->ep_out = ep; 254 255 /* now allocate requests for our endpoints */ 256 req = adb_request_new(dev->ep_out, ADB_BULK_BUFFER_SIZE); 257 if (!req) 258 goto fail; 259 req->complete = adb_complete_out; 260 dev->rx_req = req; 261 262 for (i = 0; i < TX_REQ_MAX; i++) { 263 req = adb_request_new(dev->ep_in, ADB_BULK_BUFFER_SIZE); 264 if (!req) 265 goto fail; 266 req->complete = adb_complete_in; 267 adb_req_put(dev, &dev->tx_idle, req); 268 } 269 270 return 0; 271 272 fail: 273 printk(KERN_ERR "adb_bind() could not allocate requests "); 274 return -1;275 }
从这个函数可以看出function如何与gadget建立关系 1. 通过usb_ep_autoconfig(cdev->gadget, in_desc)分配gadget初始化注册的endpoint 2. 通过adb_request_new(主要调用usb_ep_alloc_request)来分配对应的endpoint的request 3. req->complete = adb_complete_out 指定request的complete函数,这个函数会在usb device controller对应的endpoint收发中断完成之后被调用
















热门文章