当前位置: 首页 > 工具软件 > Composite > 使用案例 >

gadget之composite

薛飞星
2023-12-01

gadget之composite

composite简介

composite英文意思为复合/综合。其为整个gadget驱动的中间层,往下注册usb_gadget_driver并与usb_udc(usb_gadget设备)绑定,往上通过usb_composite_dev与usb_composite_driver实现usb_function的绑定。usb_function、composite、udc三者相互联系共同实现usb device的功能。

struct usb_composite_dev

//作为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

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,
};
 类似资料: