gadget之udc

gadget之udc

简介

udc全称为(usb device conctrl),usb设备控制器,其为某soc的usb device的控制器,将usb device的功能抽象,转换成一个个可实现的实例。相关源码如下:

//udc的核心层代码
drivers/usb/gadget/core.c 
//某udc控制器的代码,具体需要编写udc驱动者实现
drivers/usb/gadget/fotg210-udc.c
drivers/usb/gadget/s3c2410_udc.c

struct usb_udc

/**
 * struct usb_udc - describes one usb device controller
 * @driver - the gadget driver pointer. For use by the class code
 * @dev - the child device to the actual controller
 * @gadget - the gadget. For use by the class code
 * @list - for use by the udc class driver
 * @vbus - for udcs who care about vbus status, this value is real vbus status;
 * for udcs who do not care about vbus status, this value is always true
 *
 * This represents the internal data structure which is used by the UDC-class
 * to hold information about udc driver and gadget together.
 */
struct usb_udc {
	struct usb_gadget_driver	*driver;
	struct usb_gadget		*gadget;
	struct device			dev;
	struct list_head		list;
	bool				vbus;
};

usb_udc初始化及创建:

/**
 * usb_add_gadget_udc - adds a new gadget to the udc class driver list
 * @parent: the parent device to this udc. Usually the controller
 * driver's device.
 * @gadget: the gadget to be added to the list
 *
 * Returns zero on success, negative errno otherwise.
 */
int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
{
	return usb_add_gadget_udc_release(parent, gadget, NULL);
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);

/**
 * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
 * @parent: the parent device to this udc. Usually the controller driver's
 * device.
 * @gadget: the gadget to be added to the list.
 * @release: a gadget release function.
 *
 * Returns zero on success, negative errno otherwise.
 * Calls the gadget release function in the latter case.
 */
int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
		void (*release)(struct device *dev))
{
	struct usb_udc		*udc;
	int			ret = -ENOMEM;

	dev_set_name(&gadget->dev, "gadget");
	INIT_WORK(&gadget->work, usb_gadget_state_work);
	gadget->dev.parent = parent;

	if (release)
		gadget->dev.release = release;
	else
		gadget->dev.release = usb_udc_nop_release;

	device_initialize(&gadget->dev);

    //创建一个udc设备
	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
	if (!udc)
		goto err_put_gadget;

    //初始化udc相关成员
	device_initialize(&udc->dev);
	udc->dev.release = usb_udc_release;
	udc->dev.class = udc_class;
	udc->dev.groups = usb_udc_attr_groups;
	udc->dev.parent = parent;
	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
	if (ret)
		goto err_put_udc;

	ret = device_add(&gadget->dev);
	if (ret)
		goto err_put_udc;

    //udc 与 usb_gadget绑定
	udc->gadget = gadget;
	gadget->udc = udc;

	mutex_lock(&udc_lock);
	list_add_tail(&udc->list, &udc_list);//将udc设备添加到udc_list链表中

	ret = device_add(&udc->dev);
	if (ret)
		goto err_unlist_udc;

	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
	udc->vbus = true;

	/* pick up one of pending gadget drivers */
	ret = check_pending_gadget_drivers(udc);
	if (ret)
		goto err_del_udc;

	mutex_unlock(&udc_lock);

	return 0;

 err_del_udc:
	device_del(&udc->dev);

 err_unlist_udc:
	list_del(&udc->list);
	mutex_unlock(&udc_lock);

	device_del(&gadget->dev);

 err_put_udc:
	put_device(&udc->dev);

 err_put_gadget:
	put_device(&gadget->dev);
	return ret;
}

/* should be called with udc_lock held */
static int check_pending_gadget_drivers(struct usb_udc *udc)
{
	struct usb_gadget_driver *driver;
	int ret = 0;
    
    //遍历gadget_driver_pending_list链表,如有usb_gadget_driver注册,则将其与udc设备绑定
	list_for_each_entry(driver, &gadget_driver_pending_list, pending)
		if (!driver->udc_name || strcmp(driver->udc_name,
						dev_name(&udc->dev)) == 0) {
			ret = udc_bind_to_driver(udc, driver);
			if (ret != -EPROBE_DEFER)
				list_del_init(&driver->pending);
			break;
		}

	return ret;
}

usb_udc与usb_gadget_driver绑定


/* ------------------------------------------------------------------------- */

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与usb_gadget_driver绑定
	udc->driver = driver;
	udc->dev.driver = &driver->driver;
	udc->gadget->dev.driver = &driver->driver;

	usb_gadget_udc_set_speed(udc, driver->max_speed);

    //调用usb_gadget_driver.bind,详见gadget之usb_gadget
    //源码为:drivers/usb/gadget/composite.c
	ret = driver->bind(udc->gadget, driver);
	if (ret)
		goto err1;
	
	//回调usb_gadget的udc_start函数,启动udc控制器
	//该功能需udc控制器驱动实现
	ret = usb_gadget_udc_start(udc);
	if (ret) {
		driver->unbind(udc->gadget);
		goto err1;
	}
	
	//源码见:drivers/usb/gadget/udc/core.c
	//会回调到usb_gadget的pillup函数,配置上拉,连接到host
	//该功能需udc控制器驱动实现
	usb_udc_connect_control(udc);

	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
	return 0;
err1:
	if (ret != -EISNAM)
		dev_err(&udc->dev, "failed to start %s: %d\n",
			udc->driver->function, ret);
	udc->driver = NULL;
	udc->dev.driver = NULL;
	udc->gadget->dev.driver = NULL;
	return ret;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值