Gadget Bus
3 Apr 2024
Read time: 5 minute(s)
Gadget Layer 层没有定义一个标准的 Bus 总线,而是自定义了两条链表来分别存储 Device 和 Driver:
type | list | escript |
---|---|---|
Device | udc_list | 所有 Device 全集 |
Driver | gadget_driver_pending_list | 只包含没有适配 Device 的 Driver |
它们的使用场景如下:
-
在 Gadget Device 创建时,首先把 Device 加入到
udc_list
链表,然后尝试和gadget_driver_pending_list
链表中的 Driver 进行 match():usb_add_gadget_udc() → usb_add_gadget_udc_release() → usb_add_gadget(): int usb_add_gadget(struct usb_gadget *gadget) { /* (1) 将 device 加入全局链表 */ list_add_tail(&udc->list, &udc_list); /* pick up one of pending gadget drivers */ /* (2) 尝试 match gadget 的 device 和 driver */ ret = check_pending_gadget_drivers(udc); if (ret) goto err_del_udc; mutex_unlock(&udc_lock); } ↓ static int check_pending_gadget_drivers(struct usb_udc *udc) { struct usb_gadget_driver *driver; int ret = 0; /* (2.1) 遍历 `gadget_driver_pending_list` 链表中的 Driver,和 Device 进行 match() 且一个 Driver 只能 match 一个 Device,Driver match 成功后会从链表删除 */ list_for_each_entry(driver, &gadget_driver_pending_list, pending) if (!driver->udc_name || strcmp(driver->udc_name, dev_name(&udc->dev)) == 0) { /* (2.2) Match 成功,对 Device 和 Driver 进行 bind() */ ret = udc_bind_to_driver(udc, driver); if (ret != -EPROBE_DEFER) /* (2.3) Driver Match 成功后,从 pending 链表删除 */ list_del_init(&driver->pending); break; } return ret; }
-
在 Gadget Driver 创建时,首先尝试和
udc_list
链表中的 Device 进行 match(),match() 不成功则把 Driver 加入到gadget_driver_pending_list
链表中:gadget_dev_desc_UDC_store() → usb_gadget_probe_driver(): int usb_gadget_probe_driver(struct usb_gadget_driver *driver) { struct usb_udc *udc = NULL; int ret = -ENODEV; if (!driver || !driver->bind || !driver->setup) return -EINVAL; mutex_lock(&udc_lock); /* (1.1) 如果 Driver 有 udc_name,尝试和 udc_list 链表中 Device 的 Name 进行 match() */ if (driver->udc_name) { list_for_each_entry(udc, &udc_list, list) { ret = strcmp(driver->udc_name, dev_name(&udc->dev)); if (!ret) break; } if (ret) ret = -ENODEV; else if (udc->driver) ret = -EBUSY; else goto found; /* (1.2) 如果 Driver 没有 udc_name,尝试适配 udc_list 链表中第一个没有适配的 Device */ } else { list_for_each_entry(udc, &udc_list, list) { /* For now we take the first one */ if (!udc->driver) goto found; } } if (!driver->match_existing_only) { /* (2) 如果没有 match() 成功,则把 Driver 加入到 pending 链表 */ list_add_tail(&driver->pending, &gadget_driver_pending_list); pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n", driver->function); ret = 0; } mutex_unlock(&udc_lock); if (ret) pr_warn("udc-core: couldn't find an available UDC or it's busy\n"); return ret; found: /* (3) 如果 Match 成功,对 Device 和 Driver 进行 bind() */ ret = udc_bind_to_driver(udc, driver); mutex_unlock(&udc_lock); return ret; }
-
在 Device 和 Driver Match 成功时的 bind() 动作:
static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver) { int ret; dev_dbg(&udc->dev, "registering UDC driver [%s]\n", driver->function); /* (1) 数据成员的赋值 */ udc->driver = driver; udc->dev.driver = &driver->driver; udc->gadget->dev.driver = &driver->driver; usb_gadget_udc_set_speed(udc, driver->max_speed); /* (2) 调用 Gadget Driver 的 bind() 函数 */ ret = driver->bind(udc->gadget, driver); if (ret) goto err1; /* (3) 调用 Gadget Device 的 start() 函数 udc->gadget->ops->udc_start(udc->gadget, udc->driver); */ ret = usb_gadget_udc_start(udc); if (ret) { driver->unbind(udc->gadget); goto err1; } /* (4) 调用 Gadget Device 的 pullup() 函数 gadget->ops->pullup(gadget, 1/0); */ usb_udc_connect_control(udc); kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); return 0; }
注: 这里和一般的 Device 和 Driver 的适配规则有些不一样。一般的规则是一个 Dirver 可以适配多个
Device,而一个 Device 只能适配一个 Driver。而这里的规则是一个 Gadget Device 只能适配一个 Gadget Driver,而一个
Gadget Driver 只能适配一个 Gadget Device。 Gadget Driver 代表的是一个
Composite
Device
。