composite英文意思为复合/综合。其为整个gadget驱动的中间层,往下注册usb_gadget_driver并与usb_udc(usb_gadget设备)绑定,往上通过usb_composite_dev与usb_composite_driver实现usb_function的绑定。usb_function、composite、udc三者相互联系共同实现usb device的功能。
//作为composite复合设备,所有composite设备都必须实现该结构体。
struct usb_composite_dev {
struct usb_gadget *gadget; //设备和gadget交互,gadget与udc交互
struct usb_request *req; //used for control responses; buffer is pre-allocated
struct usb_request *os_desc_req; //used for OS descriptors responses; buffer is pre-allocated
struct usb_configuration *config; //当前激活的配置
/* OS String is a custom (yet popular) extension to the USB standard. */
u8 qw_sign[OS_STRING_QW_SIGN_LEN]; //qwSignature part of the OS string
u8 b_vendor_code; //bMS_VendorCode part of the OS string
struct usb_configuration *os_desc_config; //the configuration to be used with OS descriptors
unsigned int use_os_string:1; //false by default, interested gadgets set it
/* private: */
/* internals */
unsigned int suspended:1;
struct usb_device_descriptor desc; //设备描述符,唯一
struct list_head configs; //配置链表
struct list_head gstrings; //字符描述链表
struct usb_composite_driver *driver; //设备绑定的composite驱动
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;
/* public: */
unsigned int setup_pending:1;
unsigned int os_desc_pending:1;
};
USB_COMPOSITE_DEV的创建
源码:/drivers/usb/gadget/composite.c
static int composite_bind(struct usb_gadget *gadget,
struct usb_gadget_driver *gdriver)
{
struct usb_composite_dev *cdev;
struct usb_composite_driver *composite = to_cdriver(gdriver);
int status = -ENOMEM;
cdev = kzalloc(sizeof *cdev, GFP_KERNEL);//创建usb_composite_dev
if (!cdev)
return status;
spin_lock_init(&cdev->lock);
cdev->gadget = gadget;
set_gadget_data(gadget, cdev);
INIT_LIST_HEAD(&cdev->configs);
INIT_LIST_HEAD(&cdev->gstrings);
//初始化conctrl req
status = composite_dev_prepare(composite, cdev);
if (status)
goto fail;
/* composite gadget needs to assign strings for whole device (like
* serial number), register function drivers, potentially update
* power state and consumption, etc
*/
//初始化设备描述符、字符描述付等
status = composite->bind(cdev);
if (status < 0)
goto fail;
if (cdev->use_os_string) {
status = composite_os_desc_req_prepare(cdev, gadget->ep0);
if (status)
goto fail;
}
update_unchanged_dev_desc(&cdev->desc, composite->dev);
/* has userspace failed to provide a serial number? */
if (composite->needs_serial && !cdev->desc.iSerialNumber)
WARNING(cdev, "userspace failed to provide iSerialNumber\n");
INFO(cdev, "%s ready\n", composite->name);
return 0;
fail:
__composite_unbind(gadget, false);
return status;
}
int composite_dev_prepare(struct usb_composite_driver *composite,
struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
int ret = -ENOMEM;
/* preallocate control response and buffer */
cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
if (!cdev->req)
return -ENOMEM;
//USB_COMP_EP0_BUFSIZ=4096
cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
if (!cdev->req->buf)
goto fail;
//创建设备文件
ret = device_create_file(&gadget->dev, &dev_attr_suspended);
if (ret)
goto fail_dev;
cdev->req->complete = composite_setup_complete;
cdev->req->context = cdev;
gadget->ep0->driver_data = cdev;
cdev->driver = composite;
/*
* As per USB compliance update, a device that is actively drawing
* more than 100mA from USB must report itself as bus-powered in
* the GetStatus(DEVICE) call.
*/
if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
usb_gadget_set_selfpowered(gadget);
/* interface and string IDs start at zero via kzalloc.
* we force endpoints to start unassigned; few controller
* drivers will zero ep->driver_data.
*/
usb_ep_autoconfig_reset(gadget);
return 0;
fail_dev:
kfree(cdev->req->buf);
fail:
usb_ep_free_request(gadget->ep0, cdev->req);
cdev->req = NULL;
return ret;
}
struct usb_composite_driver {//所有compesite驱动必须填充该结构体
const char *name;
const struct usb_device_descriptor *dev; //必须实现
struct usb_gadget_strings **strings;
enum usb_device_speed max_speed;
unsigned needs_serial:1;
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;这个地方的驱动由composite提供,所有和composite相关的驱动都会默认分配该驱动。
};
usb_composite_driver的创建,以serial.c为例:
源码:/drivers/usb/gadget/legacy/serial.c
static struct usb_composite_driver gserial_driver = {
.name = "g_serial",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_SUPER,
.bind = gs_bind,
.unbind = gs_unbind,
};