usb_composite_driver的创建于注册
源码:drivers/usb/legacy/serial.c
//创建usb_composite_driver
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,
};
static int __init init(void)
{
/* We *could* export two configs; that'd be much cleaner...
* but neither of these product IDs was defined that way.
*/bConfigurationValue、class、pid等
//初始化
if (use_acm) {
serial_config_driver.label = "CDC ACM config";
serial_config_driver.bConfigurationValue = 2;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_PRODUCT_ID);
} else if (use_obex) {
serial_config_driver.label = "CDC OBEX config";
serial_config_driver.bConfigurationValue = 3;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
} else {
serial_config_driver.label = "Generic Serial config";
serial_config_driver.bConfigurationValue = 1;
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
device_desc.idProduct =
cpu_to_le16(GS_PRODUCT_ID);
}
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
//注册usb_composite_driver与usb_composite_dev
return usb_composite_probe(&gserial_driver);
}
module_init(init);
static void __exit cleanup(void)
{
usb_composite_unregister(&gserial_driver);
}
module_exit(cleanup);
注意adb、mtp等功能已经通过g_ffs.c(functionfs)来与应用通信,如果没有这个的话,也可以通过g_adb.c来通信。(需要确认版本问题。)只要有合适的functionfs driver来实现。
usb_gadget_driver的创建与注册
//创建usb_gadget_driver
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,
},
};
int usb_composite_probe(struct usb_composite_driver *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;
gadget_driver->function = (char *) driver->name;
gadget_driver->driver.name = driver->name;
gadget_driver->max_speed = driver->max_speed;
//注册usb_gadget_driver
return usb_gadget_probe_driver(gadget_driver);
}
EXPORT_SYMBOL_GPL(usb_composite_probe);
//注册usb_gadget_driver
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
{
struct usb_udc *udc = NULL;
int ret = -ENODEV;
if (!driver || !driver->bind || !driver->setup)
return -EINVAL;
mutex_lock(&udc_lock);
if (driver->udc_name) {
list_for_each_entry(udc, &udc_list, list) {
ret = strcmp(driver->udc_name, dev_name(&udc->dev));
if (!ret)
break;
}
if (ret)
ret = -ENODEV;
else if (udc->driver)
ret = -EBUSY;
else
goto found;
} else {
list_for_each_entry(udc, &udc_list, list) {
/* For now we take the first one */
if (!udc->driver)
goto found;
}
}
//无udc设备,则将usb_gadget_driver添加到gadget_driver_pending_list链表
if (!driver->match_existing_only) {
list_add_tail(&driver->pending, &gadget_driver_pending_list);
pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
driver->function);
ret = 0;
}
mutex_unlock(&udc_lock);
return ret;
found:
//udc设备与usb_gadget_driver绑定
ret = udc_bind_to_driver(udc, driver);
mutex_unlock(&udc_lock);
return ret;
}
usb_gadget的创建及注册
源码:linux4.19.123-drivers/usb/gadget/udc/s3c2410_udc.c
static const struct usb_ep_ops s3c2410_ep_ops = {
.enable = s3c2410_udc_ep_enable,
.disable = s3c2410_udc_ep_disable,
.alloc_request = s3c2410_udc_alloc_request,
.free_request = s3c2410_udc_free_request,
.queue = s3c2410_udc_queue,
.dequeue = s3c2410_udc_dequeue,
.set_halt = s3c2410_udc_set_halt,
};
static const struct usb_gadget_ops s3c2410_ops = {
.get_frame = s3c2410_udc_get_frame,
.wakeup = s3c2410_udc_wakeup,
.set_selfpowered = s3c2410_udc_set_selfpowered,
.pullup = s3c2410_udc_pullup,
.vbus_session = s3c2410_udc_vbus_session,
.vbus_draw = s3c2410_vbus_draw,
.udc_start = s3c2410_udc_start,
.udc_stop = s3c2410_udc_stop,
};
/*---------------------------------------------------------------------------*/
static struct s3c2410_udc memory = {
//usb_gadget初始化
.gadget = {
.ops = &s3c2410_ops,
.ep0 = &memory.ep[0].ep,
.name = gadget_name,
.dev = {
.init_name = "gadget",
},
},
/* control endpoint */
.ep[0] = {
.num = 0,
.ep = {
.name = ep0name,
.ops = &s3c2410_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
},
/* first group of endpoints */
.ep[1] = {
.num = 1,
.ep = {
.name = "ep1-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
.bEndpointAddress = 1,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
},
.ep[2] = {
.num = 2,
.ep = {
.name = "ep2-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
.bEndpointAddress = 2,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
},
.ep[3] = {
.num = 3,
.ep = {
.name = "ep3-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
.bEndpointAddress = 3,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
},
.ep[4] = {
.num = 4,
.ep = {
.name = "ep4-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
.bEndpointAddress = 4,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
}
};
/*
* probe - binds to the platform device
*/
static int s3c2410_udc_probe(struct platform_device *pdev)
{
struct s3c2410_udc *udc = &memory;
struct device *dev = &pdev->dev;
int retval;
int irq;
dev_dbg(dev, "%s()\n", __func__);
......
//创建/注册udc,注册usb_gadget
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (retval)
goto err_add_udc;
......
return 0;
err_add_udc:
if (udc_info && !udc_info->udc_command &&
gpio_is_valid(udc_info->pullup_pin))
gpio_free(udc_info->pullup_pin);
err_vbus_irq:
if (udc_info && udc_info->vbus_pin > 0)
free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
err_gpio_claim:
if (udc_info && udc_info->vbus_pin > 0)
gpio_free(udc_info->vbus_pin);
err_int:
free_irq(IRQ_USBD, udc);
err_map:
iounmap(base_addr);
err_mem:
release_mem_region(rsrc_start, rsrc_len);
return retval;
}
usb_udc的创建及注册
源码:linux-4.19.123-drivers/usb/gadget/udc/core.c
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);
//创建usb_udc
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
goto err_put_gadget;
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->gadget = gadget;
gadget->udc = udc;
mutex_lock(&udc_lock);
//将新创建的usb_udc添加到udc_list链表中
list_add_tail(&udc->list, &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;
}
小结
至此,已完成usb_gadget_driver、usb_composite_driver、usb_gadget、usb_udc等几个核心结构体的创建及注册。后面将介绍usb_composite_dev等的创建及注册,以及usb_gadget_driver与usb_udc的绑定过程。
标签:usb,框架,gadget,driver,dev,udc,s3c2410,驱动 From: https://www.cnblogs.com/linhaostudy/p/18398597