gadget 框架如下,代码都在 drivers/usb/gadget下面
USB gadget 驱动剖析
dwc3 封装了usb_gadget 和usb_gadget_driver,dwc3 代表了最底层的设备控制器驱动
composite 框架是composite.c
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
struct dwc3_trb *ep0_trb;
void *ep0_bounce;
void *scratchbuf;
u8 *setup_buf;
dma_addr_t ctrl_req_addr;
dma_addr_t ep0_trb_addr;
dma_addr_t ep0_bounce_addr;
dma_addr_t scratch_addr;
struct dwc3_request ep0_usb_req;
/* device lock */
spinlock_t lock;
struct device *dev;
struct platform_device *xhci;//child dev
struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
struct dwc3_event_buffer **ev_buffs;
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];//ep0,ep1... for device mode
struct usb_gadget gadget;//udc.gadget point this
struct usb_gadget_driver *gadget_driver;//point to composite_driver_template @composite.c
。。。。。。。。。。。。。。。。。
}
struct usb_gadget_driver {//提供一个通用的usb gadget driver 模板,向下注册到udc,向上给functions driver提供bind 回调等
char *function;
enum usb_device_speed max_speed;
int (*bind)(struct usb_gadget *gadget,
struct usb_gadget_driver *driver);
void (*unbind)(struct usb_gadget *);
int (*setup)(struct usb_gadget *,
const struct usb_ctrlrequest *);
void (*disconnect)(struct usb_gadget *);
void (*suspend)(struct usb_gadget *);
void (*resume)(struct usb_gadget *);
void (*reset)(struct usb_gadget *);
/* FIXME support safe rmmod */
struct device_driver driver;
};
usb_gadget_driver 的一个实例 定义在composite.c
static const struct usb_gadget_driver composite_driver_template = {
.bind = composite_bind, //bind usb_gadget and usb_gadget_driver
.unbind = composite_unbind,
.setup = composite_setup,
.reset = composite_disconnect,
.disconnect = composite_disconnect,
.suspend = composite_suspend,
.resume = composite_resume,
.driver = {
.owner = THIS_MODULE,
},
};
struct usb_gadget {//represents a usb slave device
struct work_struct work;//usb_gadget_state_work
struct usb_udc *udc;//udc 控制器
/* readonly to gadget driver */
const struct usb_gadget_ops *ops;//udc ops
struct usb_ep *ep0;
struct list_head ep_list; /* of usb_ep */
enum usb_device_speed speed;
enum usb_device_speed max_speed;
enum usb_device_state state;
const char *name;
struct device dev;// this abstract device.
unsigned out_epnum;
unsigned in_epnum;
unsigned is_dualspeed:1;
unsigned sg_supported:1;
unsigned is_otg:1;
unsigned is_a_peripheral:1;
unsigned b_hnp_enable:1;
unsigned a_hnp_support:1;
unsigned a_alt_hnp_support:1;
unsigned quirk_ep_out_aligned_size:1;
unsigned is_selfpowered:1;
};
usb_udc 封装了usb gadget和usb_gadget_driver
struct usb_udc {
struct usb_gadget_driver *driver;// define @composite.c
struct usb_gadget *gadget;//device,define @udc
struct device dev;//the child device to the actual controller
struct list_head list;
bool vbus;
};
upper layer上面是复合设备和复合驱动
struct usb_composite_dev {//represents one composite usb gadget
struct usb_gadget *gadget;//read-only, abstracts the gadget's usb peripheral controller
struct usb_request *req;
struct usb_request *os_desc_req;//ep0 request
struct usb_configuration *config;
/* OS String is a custom (yet popular) extension to the USB standard. */
u8 qw_sign[OS_STRING_QW_SIGN_LEN];
u8 b_vendor_code;
struct usb_configuration *os_desc_config;
unsigned int use_os_string:1;
/* private: */
/* internals */
unsigned int suspended:1;
struct usb_device_descriptor desc;
struct list_head configs;//配置描述符的list head
struct list_head gstrings;
struct usb_composite_driver *driver;//对应的驱动
u8 next_string_id;
char *def_manufacturer;
/* the gadget driver won't enable the data pullup
* while the deactivation count is nonzero.
*/
unsigned deactivations;
/* the composite driver won't complete the control transfer's
* data/status stages till delayed_status is zero.
*/
int delayed_status;
/* protects deactivations and delayed_status counts*/
spinlock_t lock;
unsigned setup_pending:1;
unsigned os_desc_pending:1;
};
struct usb_composite_driver {
const char *name;
const struct usb_device_descriptor *dev;//设备描述符
struct usb_gadget_strings **strings;//字符串描述符
enum usb_device_speed max_speed;
unsigned needs_serial:1;
// 用于分配整个设备共享的资源,使用usb_add_config添加配置,必须实现
int (*bind)(struct usb_composite_dev *cdev);//用于和复合设备绑定
int (*unbind)(struct usb_composite_dev *);
void (*disconnect)(struct usb_composite_dev *);
/* global suspend hooks */
void (*suspend)(struct usb_composite_dev *);
void (*resume)(struct usb_composite_dev *);
struct usb_gadget_driver gadget_driver;//向udc层提供的接口变量,[email protected]
//Gadget driver controlling this driver,父类,struct usb_composite_driver 是子类
};
dwc3 gadget 如何初始化并添加到udc系统中
dwc3_probe---dwc3_core_init_mode---dwc3_gadget_init
mass_storage legacy的复合设备驱动和注册
static struct usb_composite_driver msg_driver = {
.name = "g_mass_storage",
.dev = &msg_device_desc,//设备描述符
.max_speed = USB_SPEED_SUPER,
.needs_serial = 1,
.strings = dev_strings,//字符串描述符
.bind = msg_bind,
.unbind = msg_unbind,
};
static int __init msg_init(void)
{
return usb_composite_probe(&msg_driver);
}
module_init(msg_init);
/**
* usb_composite_probe() - register a composite driver
* @driver: the driver to register
*
* Context: single threaded during gadget setup
*
* This function is used to register drivers using the composite driver
* framework. The return value is zero, or a negative errno value.
* Those values normally come from the driver's @bind method, which does
* all the work of setting up the driver to match the hardware.
*
* On successful return, the gadget is ready to respond to requests from
* the host, unless one of its components invokes usb_gadget_disconnect()
* while it was binding. That would usually be done in order to wait for
* some userspace participation.
*/
int usb_composite_probe(struct usb_composite_driver *driver)//register a composite driver,向上提供的接口
{
struct usb_gadget_driver *gadget_driver;
if (!driver || !driver->dev || !driver->bind)
return -EINVAL;
if (!driver->name)
driver->name = "composite";
driver->gadget_driver = composite_driver_template;//基类驱动赋值
gadget_driver = &driver->gadget_driver;//ptr to composite_driver_template
gadget_driver->function = (char *) driver->name;
gadget_driver->driver.name = driver->name;
gadget_driver->max_speed = driver->max_speed;//fill field
return usb_gadget_probe_driver(gadget_driver);
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)//@udc-core.c
{
struct usb_udc *udc = NULL;
int ret;
if (!driver || !driver->bind || !driver->setup)
return -EINVAL;
mutex_lock(&udc_lock);
list_for_each_entry(udc, &udc_list, list) {//udc 就是控制器驱动
/* For now we take the first one */
if (!udc->driver)//no driver ,so need find the right one
goto found;
}
pr_debug("couldn't find an available UDC\n");//udc 控制器注册的时候就注册到链表上了udc gadget就指向了实际的已经填充的gadget结构体
mutex_unlock(&udc_lock);
return -ENODEV;
found:
ret = udc_bind_to_driver(udc, driver);//关键
mutex_unlock(&udc_lock);
return ret;
}
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);
udc->driver = driver;
udc->dev.driver = &driver->driver;//driver 地址赋值
udc->gadget->dev.driver = &driver->driver;
ret = driver->bind(udc->gadget, driver);//composite_bind @composite.c
if (ret)
goto err1;
ret = usb_gadget_udc_start(udc);//dwc3_gadget_start
if (ret) {
driver->unbind(udc->gadget);
goto err1;
}
usb_udc_connect_control(udc);//会回调到usb_gadget的pillup函数,配置上拉,连接到host
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);//send event
return 0;
}
composite_bind中会创建复合设备,复合设备和复合驱动会绑定到一起。
文章评论