参考文章:https://www.cnblogs.com/linhaostudy/p/17016238.html
struct usb_udc {
struct usb_gadget_driver *driver;//代表一个gadget设备driver
struct usb_gadget *gadget;//代表一个udc设备
struct device dev;
struct list_head list;
bool vbus;
};
composite.c
- usb_gadget_driver是function驱动和UDC驱动沟通的桥梁
static const struct usb_gadget_driver composite_driver_template = {
.bind = composite_bind,
.unbind = composite_unbind,
.setup = composite_setup,
.reset = composite_disconnect,
.disconnect = composite_disconnect,
.suspend = composite_suspend,
.resume = composite_resume,
.driver = {
.owner = THIS_MODULE,
},
};
driver->gadget_driver = composite_driver_template//composite.c
usb_composite_probe//composite.c
usb_gadget_probe_driver(gadget_driver)//udc\core.c
udc_bind_to_driver(udc, driver)//udc\core.c
usb_gadget_udc_start(udc)//udc\core.c
static inline int usb_gadget_udc_start(struct usb_udc *udc)
{
return udc->gadget->ops->udc_start(udc->gadget, udc->driver);
}
configfs.c
- usb_gadget_driver
static const struct usb_gadget_driver configfs_driver_template = {
.bind = configfs_composite_bind,
.unbind = configfs_composite_unbind,
.setup = configfs_composite_setup,
.reset = configfs_composite_disconnect,
.disconnect = configfs_composite_disconnect,
.suspend = configfs_composite_suspend,
.resume = configfs_composite_resume,
.max_speed = USB_SPEED_SUPER_PLUS,
.driver = {
.owner = THIS_MODULE,
.name = "configfs-gadget",
},
.match_existing_only = 1,
};
gadgets_make
gi->composite.gadget_driver = configfs_driver_template
- Function驱动和UDC驱动绑定的时候通过调用usb_gadget_probe_driver间接调用usb_gadget_udc_start开启UDC
- udc_bind_to_driver将usb_gadget_driver和底层的USB控制器绑定,usb_gadget_driver相当于一个桥梁,桥的两端分别是function驱动和UDC驱动
gadget_dev_desc_UDC_store//configfs.c
usb_gadget_probe_driver(&gi->composite.gadget_driver)//core.c
udc_bind_to_driver(udc, driver)//core.c
driver->bind(udc->gadget, driver)//core.c 回调usb_gadget_driver的bind函数
usb_gadget_udc_start(udc)usb_udc_connect_control 使能USB设备控制器
udc->gadget->ops->udc_start(udc->gadget, udc->driver)//core.c
ambarella_udc_start
ambarella_udc_enable(udc) /* Enable udc */
usb_udc_connect_control(udc)//core.c 连接USB主机控制器,这样USB主机就能识别并枚举USB设备
usb_gadget_connect(udc->gadget)//core.c
static const struct usb_gadget_ops ambarella_ops = {
.get_frame = ambarella_udc_get_frame,
.wakeup = ambarella_udc_wakeup,
.pullup = ambarella_udc_pullup,
.vbus_session = ambarella_udc_vbus_session,
/*.set_selfpowered: Always selfpowered */
.udc_start = ambarella_udc_start,
.udc_stop = ambarella_udc_stop,
};
分配端点0的usb_request
driver->bind(udc->gadget, driver)//core.c 回调usb_gadget_driver的bind函数
composite_dev_prepare(composite, cdev)
/*GFP_KERNEL是内核内存分配时最常用的,无内存可用时可引起休眠。*/
cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL)//composite.c
req = ep->ops->alloc_request(ep, gfp_flags)//core.c 回调
GFP_KERNEL
是内核内存分配时最常用的,无内存可用时可引起休眠。
GFP_ATOMIC
用来从中断处理和进程上下文之外的其他代码中分配内存,从不睡眠。
GFP_KERNEL
内核内存的正常分配,可能睡眠。
GFP_USER
用来为用户空间页来分配内存,它可能睡眠。
GFP_HIGHUSER
如同 GFP_USER, 但是从高端内存分配, 如果有, 高端内存在下一个子节描述.
GFP_NOIO
根本不允许任何 I/O 初始化。
GFP_NOFS
这个标志功能如同 GFP_KERNEL, 但是它们增加限制到内核能做的来满足请求。一个 GFP_NOFS 分配不允许进行任何文件系统调用,而 GFP_NOIO 根本不允许任何 I/O 初始化。它们主要地用在文件系统和虚拟内存代码,那里允许一个分配睡眠,但是递归的文件系统调用会是一个坏主意。