本文介绍如何通过configfs的方式创建一些usb设备, 我们以uac2设备为例介绍一下整个流程。
首先看一下driver/usb/gadget/function下的所有文件都是使用DECLARE_USB_FUNCTION_INIT注册一个usb_function_driver。
613 #define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
614 static struct usb_function_driver _name ## usb_func = { \
615 .name = __stringify(_name), \
616 .mod = THIS_MODULE, \
617 .alloc_inst = _inst_alloc, \
618 .alloc_func = _func_alloc, \
619 }; \
620 MODULE_ALIAS("usbfunc:"__stringify(_name));
621
622 #define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc) \
623 DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
624 static int __init _name ## mod_init(void) \
625 { \
626 return usb_function_register(&_name ## usb_func); \
627 } \
628 static void __exit _name ## mod_exit(void) \
629 { \
630 usb_function_unregister(&_name ## usb_func); \
631 } \
632 module_init(_name ## mod_init); \
633 module_exit(_name ## mod_exit)
在usb_function_register中会将usb_function_driver挂载到func_list全局链表上。
91 int usb_function_register(struct usb_function_driver *newf)
92 {
93 struct usb_function_driver *fd;
94 int ret;
95
96 ret = -EEXIST;
97
98 mutex_lock(&func_lock);
99 list_for_each_entry(fd, &func_list, list) {
100 if (!strcmp(fd->name, newf->name))
101 goto out;
102 }
103 ret = 0;
104 list_add_tail(&newf->list, &func_list);
105 out:
106 mutex_unlock(&func_lock);
107 return ret;
108 }
109 EXPORT_SYMBOL_GPL(usb_function_register);
f_uac2.c同样是通过DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc)注册了一个uac2的driver到系统中。
我们再接着看一下drivers/usb/gadget/configfs.c这个文件,可以看到它注册了一个名字为usb_gadget的configfs_subsystem。configfs_subsystem最主要的成员其实就是一个config_group,可以看到config_group->config_item->config_item_type就是gadgets_type, gadgets_type的configfs_group_operations就是gadgets_ops。
1651 static struct configfs_group_operations gadgets_ops = {
1652 .make_group = &gadgets_make,
1653 .drop_item = &gadgets_drop,
1654 };
1655
1656 static const struct config_item_type gadgets_type = {
1657 .ct_group_ops = &gadgets_ops,
1658 .ct_owner = THIS_MODULE,
1659 };
1660
1661 static struct configfs_subsystem gadget_subsys = {
1662 .su_group = {
1663 .cg_item = {
1664 .ci_namebuf = "usb_gadget",
1665 .ci_type = &gadgets_type,
1666 },
1667 },
1668 .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),
1669 };
1670
1671 void unregister_gadget_item(struct config_item *item)
1672 {
1673 struct gadget_info *gi = to_gadget_info(item);
1674
1675 mutex_lock(&gi->lock);
1676 unregister_gadget(gi);
1677 mutex_unlock(&gi->lock);
1678 }
1679 EXPORT_SYMBOL_GPL(unregister_gadget_item);
1680
1681 static int __init gadget_cfs_init(void)
1682 {
1683 int ret;
1684
1685 config_group_init(&gadget_subsys.su_group);
1686
1687 ret = configfs_register_subsystem(&gadget_subsys);
1688 return ret;
1689 }
1690 module_init(gadget_cfs_init);
1691
1692 static void __exit gadget_cfs_exit(void)
1693 {
1694 configfs_unregister_subsystem(&gadget_subsys);
1695 }
1696 module_exit(gadget_cfs_exit);
我们接着看一下这个uac2设备在用户态是如何被激活并使用的。
#!/bin/bash
function start_uac2()
{
# usb_gadget依赖于libcomposite模块
modprobe libcomposite
# 挂载config文件系统
mount -t configfs none /sys/kernel/config
# 创建g1目录,实例化一个新的gadget模板
echo "mkdir /sys/kernel/config/usb_gadget/g1"
mkdir -m 0770 /sys/kernel/config/usb_gadget/g1
# 设置产品的VendorID、ProductID及USB规范版本号
echo "Setting Vendor Product ID's and bcdDevice"
echo 0x2207 > /sys/kernel/config/usb_gadget/g1/idVendor
echo 0x0019 > /sys/kernel/config/usb_gadget/g1/idProduct
# 设备版本号
echo 0x0200 > /sys/kernel/config/usb_gadget/g1/bcdDevice
# USB 1.1: 0x0110
# USB 2.0: 0x0200, USB 2.1: 0x0210, USB 2.5: 0x0250
# USB 3.0: 0x0300, USB 3.1: 0x0310, USB 3.2: 0x0320
# echo 0x0210 > /sys/kernel/config/usb_gadget/g1/bcdUSB
# 实例化英语ID,开发商、产品和序列号字符串写入内核
echo "Setting English strings"
mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/strings/0x409
echo "0123456789ABCDEF" > /sys/kernel/config/usb_gadget/g1/strings/0x409/serialnumber
echo "rockchip" > /sys/kernel/config/usb_gadget/g1/strings/0x409/manufacturer
echo "USB Audio Device" > /sys/kernel/config/usb_gadget/g1/strings/0x409/product
# Creating Config
echo "Creating Config"
mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/configs/c.1
mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409
echo "uac2" > /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409/configuration
echo 500 > /sys/kernel/config/usb_gadget/g1/configs/c.1/MaxPower
# bind functions
# uac2 need to put before uvc, otherwise uvc + uac2 enumerate failed in win10
echo "Creating UAC2 gadget functionality : uac2.0"
mkdir /sys/kernel/config/usb_gadget/g1/functions/uac2.0
ln -s /sys/kernel/config/usb_gadget/g1/functions/uac2.0 /sys/kernel/config/usb_gadget/g1/configs/c.1
# Binding USB Device Controller
echo "Binding USB Device Controller"
echo fe800000.dwc3 > /sys/kernel/config/usb_gadget/g1/UDC
}
function stop_uac2()
{
# Disabling the gadget
echo "Disabling the USB gadget"
echo "" > /sys/kernel/config/usb_gadget/g1/UDC
# Remove functions from configurations
rm /sys/kernel/config/usb_gadget/g1/configs/c.1/uac2.0
# Remove strings directories in configurations
rmdir /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409
# remove the configurations
rmdir /sys/kernel/config/usb_gadget/g1/configs/c.1
# Remove functions (function modules are not unloaded, though)
rmdir /sys/kernel/config/usb_gadget/g1/functions/uac2.0
# Remove strings directories in the gadget
rmdir /sys/kernel/config/usb_gadget/g1/strings/0x409
# finally remove the gadget
rmdir /sys/kernel/config/usb_gadget/g1
}
usage()
{
echo "Usage: ./usb-gadget-uac2.sh start|stop"
echo " options:"
echo " start start uac2.0 gadget"
echo " stop stop uac2.0 gadget"
}
case $1 in
start)
start_uac2
;;
stop)
stop_uac2
;;
*)
usage
exit 1
;;
esac
exit 0
执行mkdir -m 0770 /sys/kernel/config/usb_gadget/g1后会执行gadgets_make回调,gadgets_make的第一参数就是usb_gadget这个configfs_subsystem对应的config_group,第二个参数就是"g1"。可以看到在sys/kernel/config/usb_gadget/g1这个config_group里面创建了好多的configfs_attribute 和config_group。这个函数还有分配一个gadget_info结构,这个gadget_info中保存了这个gadget设备的所有信息。
352 static struct configfs_attribute *gadget_root_attrs[] = {
353 &gadget_dev_desc_attr_bDeviceClass,
354 &gadget_dev_desc_attr_bDeviceSubClass,
355 &gadget_dev_desc_attr_bDeviceProtocol,
356 &gadget_dev_desc_attr_bMaxPacketSize0,
357 &gadget_dev_desc_attr_idVendor,
358 &gadget_dev_desc_attr_idProduct,
359 &gadget_dev_desc_attr_bcdDevice,
360 &gadget_dev_desc_attr_bcdUSB,
361 &gadget_dev_desc_attr_UDC,
362 &gadget_dev_desc_attr_max_speed,
363 NULL,
364 };
564 static const struct config_item_type gadget_root_type = {
565 .ct_item_ops = &gadget_root_item_ops,
566 .ct_attrs = gadget_root_attrs,
567 .ct_owner = THIS_MODULE,
568 };
1588 static struct config_group *gadgets_make(
1589 struct config_group *group,
1590 const char *name)
1591 {
1592 struct gadget_info *gi;
1593
1594 gi = kzalloc(sizeof(*gi), GFP_KERNEL);
1595 if (!gi)
1596 return ERR_PTR(-ENOMEM);
1597
1598 config_group_init_type_name(&gi->group, name, &gadget_root_type);
1599
1600 config_group_init_type_name(&gi->functions_group, "functions",
1601 &functions_type);
1602 configfs_add_default_group(&gi->functions_group, &gi->group);
1603
1604 config_group_init_type_name(&gi->configs_group, "configs",
1605 &config_desc_type);
1606 configfs_add_default_group(&gi->configs_group, &gi->group);
1607
1608 config_group_init_type_name(&gi->strings_group, "strings",
1609 &gadget_strings_strings_type);
1610 configfs_add_default_group(&gi->strings_group, &gi->group);
1611
1612 config_group_init_type_name(&gi->os_desc_group, "os_desc",
1613 &os_desc_type);
1614 configfs_add_default_group(&gi->os_desc_group, &gi->group);
1615
1616 gi->composite.bind = configfs_do_nothing;
1617 gi->composite.unbind = configfs_do_nothing;
1618 gi->composite.suspend = NULL;
1619 gi->composite.resume = NULL;
1620 gi->composite.max_speed = USB_SPEED_SUPER_PLUS;
1621
1622 spin_lock_init(&gi->spinlock);
1623 mutex_init(&gi->lock);
1624 INIT_LIST_HEAD(&gi->string_list);
1625 INIT_LIST_HEAD(&gi->available_func);
1626
1627 composite_init_dev(&gi->cdev);
1628 gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE;
1629 gi->cdev.desc.bDescriptorType = USB_DT_DEVICE;
1630 gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());
1631
1632 gi->composite.gadget_driver = configfs_driver_template;
1633
1634 gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
1635 gi->composite.name = gi->composite.gadget_driver.function;
1636
1637 if (!gi->composite.gadget_driver.function)
1638 goto err;
1639
1640 return &gi->group;
1641 err:
1642 kfree(gi);
1643 return ERR_PTR(-ENOMEM);
1644 }
我们可以看到gadet_info中包含一个复合设备结构usb_composite_dev 和一个复活设备驱动usb_composite_driver 。它们的初始化也是在gadgets_make中。
35 struct gadget_info {
36 struct config_group group;
37 struct config_group functions_group;
38 struct config_group configs_group;
39 struct config_group strings_group;
40 struct config_group os_desc_group;
41
42 struct mutex lock;
43 struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
44 struct list_head string_list;
45 struct list_head available_func;
46
47 struct usb_composite_driver composite;
48 struct usb_composite_dev cdev;
49 bool use_os_desc;
50 char b_vendor_code;
51 char qw_sign[OS_STRING_QW_SIGN_LEN];
52 spinlock_t spinlock;
53 bool unbind;
54 };
执行mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/configs/c.1会执行config_desc_make回调。主要就是分配了一个config_usb_cfg 结构,调用config_group_init_type_name对config_usb_cfg ->config_group进行了初始化,初始的config_item_type为gadget_config_type。 并且调用usb_add_config_only函数,最后返回config_usb_cfg ->config_group。这个"c.1"后面的1就是配置描述符的id号。
671 static struct config_group *config_desc_make(
672 struct config_group *group,
673 const char *name)
674 {
675 struct gadget_info *gi;
676 struct config_usb_cfg *cfg;
677 char buf[MAX_NAME_LEN];
678 char *num_str;
679 u8 num;
680 int ret;
681
682 gi = container_of(group, struct gadget_info, configs_group);
683 ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
684 if (ret >= MAX_NAME_LEN)
685 return ERR_PTR(-ENAMETOOLONG);
686
687 num_str = strchr(buf, '.');
688 if (!num_str) {
689 pr_err("Unable to locate . in name.bConfigurationValue\n");
690 return ERR_PTR(-EINVAL);
691 }
692
693 *num_str = '\0';
694 num_str++;
695
696 if (!strlen(buf))
697 return ERR_PTR(-EINVAL);
698
699 ret = kstrtou8(num_str, 0, &num);
700 if (ret)
701 return ERR_PTR(ret);
702
703 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
704 if (!cfg)
705 return ERR_PTR(-ENOMEM);
706 cfg->c.label = kstrdup(buf, GFP_KERNEL);
707 if (!cfg->c.label) {
708 ret = -ENOMEM;
709 goto err;
710 }
711 cfg->c.bConfigurationValue = num;
712 cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW;
713 cfg->c.bmAttributes = USB_CONFIG_ATT_ONE;
714 INIT_LIST_HEAD(&cfg->string_list);
715 INIT_LIST_HEAD(&cfg->func_list);
716
717 config_group_init_type_name(&cfg->group, name,
718 &gadget_config_type);
719
720 config_group_init_type_name(&cfg->strings_group, "strings",
721 &gadget_config_name_strings_type);
722 configfs_add_default_group(&cfg->strings_group, &cfg->group);
723
724 ret = usb_add_config_only(&gi->cdev, &cfg->c);
725 if (ret)
726 goto err;
727
728 return &cfg->group;
729 err:
730 kfree(cfg->c.label);
731 kfree(cfg);
732 return ERR_PTR(ret);
733 }
gadget_config_type定义如下,重点关注的就是里面定义的configfs_item_operations为gadget_config_item_ops。
498 static struct configfs_item_operations gadget_config_item_ops = {
499 .release = gadget_config_attr_release,
500 .allow_link = config_usb_cfg_link,
501 .drop_link = config_usb_cfg_unlink,
502 };
558 static const struct config_item_type gadget_config_type = {
559 .ct_item_ops = &gadget_config_item_ops,
560 .ct_attrs = gadget_config_attrs,
561 .ct_owner = THIS_MODULE,
562 };
usb_add_config_only主要就是将config_usb_cfg->usb_configuration 结构挂到gadget_info->usb_composite_dev->configs链表上,同时将config_usb_cfg->usb_configuration->usb_composite_dev赋值为gadget_info->usb_composite_dev,并将这个配置描述符里的接口描述符清0。
960 int usb_add_config_only(struct usb_composite_dev *cdev,
961 struct usb_configuration *config)
962 {
963 struct usb_configuration *c;
964
965 if (!config->bConfigurationValue)
966 return -EINVAL;
967
968 /* Prevent duplicate configuration identifiers */
969 list_for_each_entry(c, &cdev->configs, list) {
970 if (c->bConfigurationValue == config->bConfigurationValue)
971 return -EBUSY;
972 }
973
974 config->cdev = cdev;
975 list_add_tail(&config->list, &cdev->configs);
976
977 INIT_LIST_HEAD(&config->functions);
978 config->next_interface_id = 0;
979 memset(config->interface, 0, sizeof(config->interface));
980
981 return 0;
982 }
执行mkdir /sys/kernel/config/usb_gadget/g1/functions/uac2.0后,会执行function_make回调。在function_make中主要是调用usb_get_function_instance获取usb_function_instance,调用config_item_set_name将fusb_function_instance>config_group->config_item的name设置为"uac2.0",然后将这个usb_get_function_instance挂载到gadget_info的available_func链表上,最后返回了usb_get_function_instance->config_group。
577 static struct config_group *function_make(
578 struct config_group *group,
579 const char *name)
580 {
581 struct gadget_info *gi;
582 struct usb_function_instance *fi;
583 char buf[MAX_NAME_LEN];
584 char *func_name;
585 char *instance_name;
586 int ret;
587
588 ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
589 if (ret >= MAX_NAME_LEN)
590 return ERR_PTR(-ENAMETOOLONG);
591
592 func_name = buf;
593 instance_name = strchr(func_name, '.');
594 if (!instance_name) {
595 pr_err("Unable to locate . in FUNC.INSTANCE\n");
596 return ERR_PTR(-EINVAL);
597 }
598 *instance_name = '\0';
599 instance_name++;
600
601 fi = usb_get_function_instance(func_name);
602 if (IS_ERR(fi))
603 return ERR_CAST(fi);
604
605 ret = config_item_set_name(&fi->group.cg_item, "%s", name);
606 if (ret) {
607 usb_put_function_instance(fi);
608 return ERR_PTR(ret);
609 }
610 if (fi->set_inst_name) {
611 ret = fi->set_inst_name(fi, instance_name);
612 if (ret) {
613 usb_put_function_instance(fi);
614 return ERR_PTR(ret);
615 }
616 }
617
618 gi = container_of(group, struct gadget_info, functions_group);
619
620 mutex_lock(&gi->lock);
621 list_add_tail(&fi->cfs_list, &gi->available_func);
622 mutex_unlock(&gi->lock);
623 return &fi->group;
624 }
usb_get_function_instance最终会调用到try_get_usb_function_instance,在func_list链表中找到对应的usb_function_driver,在调用usb_function_driver里的alloc_inst回调。
12 static struct usb_function_instance *try_get_usb_function_instance(const char *name)
13 {
14 struct usb_function_driver *fd;
15 struct usb_function_instance *fi;
16
17 fi = ERR_PTR(-ENOENT);
18 mutex_lock(&func_lock);
19 list_for_each_entry(fd, &func_list, list) {
20
21 if (strcmp(name, fd->name))
22 continue;
23
24 if (!try_module_get(fd->mod)) {
25 fi = ERR_PTR(-EBUSY);
26 break;
27 }
28 fi = fd->alloc_inst();
29 if (IS_ERR(fi))
30 module_put(fd->mod);
31 else
32 fi->fd = fd;
33 break;
34 }
35 mutex_unlock(&func_lock);
36 return fi;
37 }
uac2.0的alloc_inst回调就是afunc_alloc_inst,在afunc_alloc_inst主要就是申请了f_uac2_opts结构,f_uac2_opts里包含了usb_function_instance,usb_function_instance又包含了一个config_group结构,使用config_group_init_type_name对这个config_group结构进行了初始化, 添加了相关的属性文件,这个config_group就是用来对不同的funcution进行配置的。
2109 static struct configfs_attribute *f_uac2_attrs[] = {
2110 &f_uac2_opts_attr_p_chmask,
2111 &f_uac2_opts_attr_p_srate,
2112 &f_uac2_opts_attr_p_ssize,
2113 &f_uac2_opts_attr_p_hs_bint,
2114 &f_uac2_opts_attr_c_chmask,
2115 &f_uac2_opts_attr_c_srate,
2116 &f_uac2_opts_attr_c_ssize,
2117 &f_uac2_opts_attr_c_hs_bint,
2118 &f_uac2_opts_attr_c_sync,
2119 &f_uac2_opts_attr_req_number,
2120 &f_uac2_opts_attr_fb_max,
2121
2122 &f_uac2_opts_attr_p_mute_present,
2123 &f_uac2_opts_attr_p_volume_present,
2124 &f_uac2_opts_attr_p_volume_min,
2125 &f_uac2_opts_attr_p_volume_max,
2126 &f_uac2_opts_attr_p_volume_res,
2127
2128 &f_uac2_opts_attr_c_mute_present,
2129 &f_uac2_opts_attr_c_volume_present,
2130 &f_uac2_opts_attr_c_volume_min,
2131 &f_uac2_opts_attr_c_volume_max,
2132 &f_uac2_opts_attr_c_volume_res,
2133
2134 &f_uac2_opts_attr_function_name,
2135
2136 NULL,
2137 };
2138
2139 static const struct config_item_type f_uac2_func_type = {
2140 .ct_item_ops = &f_uac2_item_ops,
2141 .ct_attrs = f_uac2_attrs,
2142 .ct_owner = THIS_MODULE,
2143 };
2153 static struct usb_function_instance *afunc_alloc_inst(void)
2154 {
2155 struct f_uac2_opts *opts;
2156
2157 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
2158 if (!opts)
2159 return ERR_PTR(-ENOMEM);
2160
2161 mutex_init(&opts->lock);
2162 opts->func_inst.free_func_inst = afunc_free_inst;
2163
2164 config_group_init_type_name(&opts->func_inst.group, "",
2165 &f_uac2_func_type);
2166
2167 opts->p_chmask = UAC2_DEF_PCHMASK;
2168 opts->p_srates[0] = UAC2_DEF_PSRATE;
2169 opts->p_ssize = UAC2_DEF_PSSIZE;
2170 opts->p_hs_bint = UAC2_DEF_PHSBINT;
2171 opts->c_chmask = UAC2_DEF_CCHMASK;
2172 opts->c_srates[0] = UAC2_DEF_CSRATE;
2173 opts->c_ssize = UAC2_DEF_CSSIZE;
2174 opts->c_hs_bint = UAC2_DEF_CHSBINT;
2175 opts->c_sync = UAC2_DEF_CSYNC;
2176
2177 opts->p_mute_present = UAC2_DEF_MUTE_PRESENT;
2178 opts->p_volume_present = UAC2_DEF_VOLUME_PRESENT;
2179 opts->p_volume_min = UAC2_DEF_MIN_DB;
2180 opts->p_volume_max = UAC2_DEF_MAX_DB;
2181 opts->p_volume_res = UAC2_DEF_RES_DB;
2182
2183 opts->c_mute_present = UAC2_DEF_MUTE_PRESENT;
2184 opts->c_volume_present = UAC2_DEF_VOLUME_PRESENT;
2185 opts->c_volume_min = UAC2_DEF_MIN_DB;
2186 opts->c_volume_max = UAC2_DEF_MAX_DB;
2187 opts->c_volume_res = UAC2_DEF_RES_DB;
2188
2189 opts->req_number = UAC2_DEF_REQ_NUM;
2190 opts->fb_max = FBACK_FAST_MAX;
2191
2192 snprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink");
2193
2194 return &opts->func_inst;
2195 }
执行ln -s /sys/kernel/config/usb_gadget/g1/functions/uac2.0 /sys/kernel/config/usb_gadget/g1/configs/c.1后,会调用到config_usb_cfg_link。在config_usb_cfg_link里,调用usb_get_function得到usb_function结构,并挂载到config_usb_cfg的func_list链表上。
411 static int config_usb_cfg_link(
412 struct config_item *usb_cfg_ci,
413 struct config_item *usb_func_ci)
414 {
415 struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
416 struct usb_composite_dev *cdev = cfg->c.cdev;
417 struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
418
419 struct config_group *group = to_config_group(usb_func_ci);
420 struct usb_function_instance *fi = container_of(group,
421 struct usb_function_instance, group);
422 struct usb_function_instance *a_fi;
423 struct usb_function *f;
424 int ret;
425
426 mutex_lock(&gi->lock);
427 /*
428 * Make sure this function is from within our _this_ gadget and not
429 * from another gadget or a random directory.
430 * Also a function instance can only be linked once.
431 */
432 list_for_each_entry(a_fi, &gi->available_func, cfs_list) {
433 if (a_fi == fi)
434 break;
435 }
436 if (a_fi != fi) {
437 ret = -EINVAL;
438 goto out;
439 }
440
441 list_for_each_entry(f, &cfg->func_list, list) {
442 if (f->fi == fi) {
443 ret = -EEXIST;
444 goto out;
445 }
446 }
447
448 f = usb_get_function(fi);
449 if (IS_ERR(f)) {
450 ret = PTR_ERR(f);
451 goto out;
452 }
453
454 /* stash the function until we bind it to the gadget */
455 list_add_tail(&f->list, &cfg->func_list);
456 ret = 0;
457 out:
458 mutex_unlock(&gi->lock);
459 return ret;
460 }
usb_get_function主要是调用afunc_alloc回调,创建usb_funciton结构,初始化后返回。
57 struct usb_function *usb_get_function(struct usb_function_instance *fi)
58 {
59 struct usb_function *f;
60
61 f = fi->fd->alloc_func(fi);
62 if (IS_ERR(f))
63 return f;
64 f->fi = fi;
65 return f;
66 }
2225 static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
2226 {
2227 struct f_uac2 *uac2;
2228 struct f_uac2_opts *opts;
2229
2230 uac2 = kzalloc(sizeof(*uac2), GFP_KERNEL);
2231 if (uac2 == NULL)
2232 return ERR_PTR(-ENOMEM);
2233
2234 opts = container_of(fi, struct f_uac2_opts, func_inst);
2235 mutex_lock(&opts->lock);
2236 ++opts->refcnt;
2237 mutex_unlock(&opts->lock);
2238
2239 uac2->g_audio.func.name = "uac2_func";
2240 uac2->g_audio.func.bind = afunc_bind;
2241 uac2->g_audio.func.unbind = afunc_unbind;
2242 uac2->g_audio.func.set_alt = afunc_set_alt;
2243 uac2->g_audio.func.get_alt = afunc_get_alt;
2244 uac2->g_audio.func.disable = afunc_disable;
2245 uac2->g_audio.func.suspend = afunc_suspend;
2246 uac2->g_audio.func.setup = afunc_setup;
2247 uac2->g_audio.func.free_func = afunc_free;
2248
2249 return &uac2->g_audio.func;
2250 }
我们看下CONFIGFS_ATTR的定义
123 #define CONFIGFS_ATTR(_pfx, _name) \
124 static struct configfs_attribute _pfx##attr_##_name = { \
125 .ca_name = __stringify(_name), \
126 .ca_mode = S_IRUGO | S_IWUSR, \
127 .ca_owner = THIS_MODULE, \
128 .show = _pfx##_name##_show, \
129 .store = _pfx##_name##_store, \
130 }
根据上面CONFIGFS_ATTR的定义可以看出,执行echo fe800000.dwc3 > /sys/kernel/config/usb_gadget/g1/UDC后会调用gadget_dev_desc_UDC_store函数,在这个函数中会调用usb_gadget_probe_driver,probe一个gadget driver,根据前面的分析这个gadget driver就是configfs_driver_template。
1569 static const struct usb_gadget_driver configfs_driver_template = {
1570 .bind = configfs_composite_bind,
1571 .unbind = configfs_composite_unbind,
1572
1573 .setup = configfs_composite_setup,
1574 .reset = configfs_composite_reset,
1575 .disconnect = configfs_composite_disconnect,
1576
1577 .suspend = configfs_composite_suspend,
1578 .resume = configfs_composite_resume,
1579
1580 .max_speed = USB_SPEED_SUPER_PLUS,
1581 .driver = {
1582 .owner = THIS_MODULE,
1583 .name = "configfs-gadget",
1584 },
1585 .match_existing_only = 1,
1586 };
257 static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
258 const char *page, size_t len)
259 {
260 struct gadget_info *gi = to_gadget_info(item);
261 char *name;
262 int ret;
263
264 if (strlen(page) < len)
265 return -EOVERFLOW;
266
267 name = kstrdup(page, GFP_KERNEL);
268 if (!name)
269 return -ENOMEM;
270 if (name[len - 1] == '\n')
271 name[len - 1] = '\0';
272
273 mutex_lock(&gi->lock);
274
275 if (!strlen(name)) {
276 ret = unregister_gadget(gi);
277 if (ret)
278 goto err;
279 kfree(name);
280 } else {
281 if (gi->composite.gadget_driver.udc_name) {
282 ret = -EBUSY;
283 goto err;
284 }
285 gi->composite.gadget_driver.udc_name = name;
286 ret = usb_gadget_probe_driver(&gi->composite.gadget_driver);
287 if (ret) {
288 gi->composite.gadget_driver.udc_name = NULL;
289 goto err;
290 }
291 }
292 mutex_unlock(&gi->lock);
293 return len;
294 err:
295 kfree(name);
296 mutex_unlock(&gi->lock);
297 return ret;
298 }
usb_gadget_probe_driver里面主要就是同过udc_name,从udc_list链表里面找到对应的usb_udc。udc_list我们在前面的文章介绍过,上面会挂载所有的udc控制器设备,我们前面文章也介绍过在device_add时没有给它匹配驱动,是在usb_gadget_probe_driver中通过udc_bind_to_driver绑定的驱动。
1524 int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
1525 {
1526 struct usb_udc *udc = NULL;
1527 int ret = -ENODEV;
1528
1529 if (!driver || !driver->bind || !driver->setup)
1530 return -EINVAL;
1531
1532 mutex_lock(&udc_lock);
1533 if (driver->udc_name) {
1534 list_for_each_entry(udc, &udc_list, list) {
1535 ret = strcmp(driver->udc_name, dev_name(&udc->dev));
1536 if (!ret)
1537 break;
1538 }
1539 if (ret)
1540 ret = -ENODEV;
1541 else if (udc->driver)
1542 ret = -EBUSY;
1543 else
1544 goto found;
1545 } else {
1546 list_for_each_entry(udc, &udc_list, list) {
1547 /* For now we take the first one */
1548 if (!udc->driver)
1549 goto found;
1550 }
1551 }
1552
1553 if (!driver->match_existing_only) {
1554 list_add_tail(&driver->pending, &gadget_driver_pending_list);
1555 pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
1556 driver->function);
1557 ret = 0;
1558 }
1559
1560 mutex_unlock(&udc_lock);
1561 if (ret)
1562 pr_warn("udc-core: couldn't find an available UDC or it's busy\n");
1563 return ret;
1564 found:
1565 ret = udc_bind_to_driver(udc, driver);
1566 mutex_unlock(&udc_lock);
1567 return ret;
1568 }
udc_bind_to_driver中除了 调用udc->gadget->dev.driver = &driver->driver将device和device_driver绑定到一起,还会调用usb_gadget_drive里的bind回调。这个函数做的事情比较多, 我们后面一条条的分析。
1490 static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
1491 {
1492 int ret;
1493
1494 dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
1495 driver->function);
1496
1497 udc->driver = driver;
1498 udc->gadget->dev.driver = &driver->driver;
1499
1500 usb_gadget_udc_set_speed(udc, driver->max_speed);
1501
1502 ret = driver->bind(udc->gadget, driver);
1503 if (ret)
1504 goto err1;
1505 ret = usb_gadget_udc_start(udc);
1506 if (ret) {
1507 driver->unbind(udc->gadget);
1508 goto err1;
1509 }
1510 usb_gadget_enable_async_callbacks(udc);
1511 usb_udc_connect_control(udc);
1512
1513 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
1514 return 0;
1515 err1:
1516 if (ret != -EISNAM)
1517 dev_err(&udc->dev, "failed to start %s: %d\n",
1518 udc->driver->function, ret);
1519 udc->driver = NULL;
1520 udc->gadget->dev.driver = NULL;
1521 return ret;
1522 }
bind回调其实就是configfs_composite_bind,configfs_composite_bind主要作用就是遍历usb_composite_dev里的所有usb_configuration,然后再遍历usb_configuration对应的所有usb_function,最后调用usb_add_function把usb_configuration和下面所有的usb_function绑定到一起。
1283 static int configfs_composite_bind(struct usb_gadget *gadget,
1284 struct usb_gadget_driver *gdriver)
1285 {
1286 struct usb_composite_driver *composite = to_cdriver(gdriver);
1287 struct gadget_info *gi = container_of(composite,
1288 struct gadget_info, composite);
1289 struct usb_composite_dev *cdev = &gi->cdev;
1290 struct usb_configuration *c;
1291 struct usb_string *s;
1292 unsigned i;
1293 int ret;
1294
1295 /* the gi->lock is hold by the caller */
1296 gi->unbind = 0;
1297 cdev->gadget = gadget;
1298 set_gadget_data(gadget, cdev);
1299 ret = composite_dev_prepare(composite, cdev);
1300 if (ret)
1301 return ret;
1302 /* and now the gadget bind */
1303 ret = -EINVAL;
1304
1305 if (list_empty(&gi->cdev.configs)) {
1306 pr_err("Need at least one configuration in %s.\n",
1307 gi->composite.name);
1308 goto err_comp_cleanup;
1309 }
1310
1311
1312 list_for_each_entry(c, &gi->cdev.configs, list) {
1313 struct config_usb_cfg *cfg;
1314
1315 cfg = container_of(c, struct config_usb_cfg, c);
1316 if (list_empty(&cfg->func_list)) {
1317 pr_err("Config %s/%d of %s needs at least one function.\n",
1318 c->label, c->bConfigurationValue,
1319 gi->composite.name);
1320 goto err_comp_cleanup;
1321 }
1322 }
1323
1324 /* init all strings */
1325 if (!list_empty(&gi->string_list)) {
1326 struct gadget_strings *gs;
1327
1328 i = 0;
1329 list_for_each_entry(gs, &gi->string_list, list) {
1330
1331 gi->gstrings[i] = &gs->stringtab_dev;
1332 gs->stringtab_dev.strings = gs->strings;
1333 gs->strings[USB_GADGET_MANUFACTURER_IDX].s =
1334 gs->manufacturer;
1335 gs->strings[USB_GADGET_PRODUCT_IDX].s = gs->product;
1336 gs->strings[USB_GADGET_SERIAL_IDX].s = gs->serialnumber;
1337 i++;
1338 }
1339 gi->gstrings[i] = NULL;
1340 s = usb_gstrings_attach(&gi->cdev, gi->gstrings,
1341 USB_GADGET_FIRST_AVAIL_IDX);
1342 if (IS_ERR(s)) {
1343 ret = PTR_ERR(s);
1344 goto err_comp_cleanup;
1345 }
1346
1347 gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id;
1348 gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id;
1349 gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
1350 }
1351
1352 if (gi->use_os_desc) {
1353 cdev->use_os_string = true;
1354 cdev->b_vendor_code = gi->b_vendor_code;
1355 memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
1356 }
1357
1358 if (gadget_is_otg(gadget) && !otg_desc[0]) {
1359 struct usb_descriptor_header *usb_desc;
1360
1361 usb_desc = usb_otg_descriptor_alloc(gadget);
1362 if (!usb_desc) {
1363 ret = -ENOMEM;
1364 goto err_comp_cleanup;
1365 }
1366 usb_otg_descriptor_init(gadget, usb_desc);
1367 otg_desc[0] = usb_desc;
1368 otg_desc[1] = NULL;
1369 }
1370
1371 /* Go through all configs, attach all functions */
1372 list_for_each_entry(c, &gi->cdev.configs, list) {
1373 struct config_usb_cfg *cfg;
1374 struct usb_function *f;
1375 struct usb_function *tmp;
1376 struct gadget_config_name *cn;
1377
1378 if (gadget_is_otg(gadget))
1379 c->descriptors = otg_desc;
1380
1381 cfg = container_of(c, struct config_usb_cfg, c);
1382 if (!list_empty(&cfg->string_list)) {
1383 i = 0;
1384 list_for_each_entry(cn, &cfg->string_list, list) {
1385 cfg->gstrings[i] = &cn->stringtab_dev;
1386 cn->stringtab_dev.strings = &cn->strings;
1387 cn->strings.s = cn->configuration;
1388 i++;
1389 }
1390 cfg->gstrings[i] = NULL;
1391 s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1);
1392 if (IS_ERR(s)) {
1393 ret = PTR_ERR(s);
1394 goto err_comp_cleanup;
1395 }
1396 c->iConfiguration = s[0].id;
1397 }
1398
1399 list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
1400 list_del(&f->list);
1401 ret = usb_add_function(c, f);
1402 if (ret) {
1403 list_add(&f->list, &cfg->func_list);
1404 goto err_purge_funcs;
1405 }
1406 }
1407 ret = usb_gadget_check_config(cdev->gadget);
1408 if (ret)
1409 goto err_purge_funcs;
1410
1411 usb_ep_autoconfig_reset(cdev->gadget);
1412 }
1413 if (cdev->use_os_string) {
1414 ret = composite_os_desc_req_prepare(cdev, gadget->ep0);
1415 if (ret)
1416 goto err_purge_funcs;
1417 }
1418
1419 usb_ep_autoconfig_reset(cdev->gadget);
1420 return 0;
1421
1422 err_purge_funcs:
1423 purge_configs_funcs(gi);
1424 err_comp_cleanup:
1425 composite_dev_cleanup(cdev);
1426 return ret;
1427 }
usb_add_function这个函数主要就是调用了value = function->bind(config, function)这个回调。对应uac2设备就是afunc_bind。afunc_bind的主要作用就是填充各种描述符,调用usb_ep_autoconfig分配ep,然后调用g_audio_setup函数创建音频设备,这里就不贴代码了。
287 /**
288 * usb_add_function() - add a function to a configuration
289 * @config: the configuration
290 * @function: the function being added
291 * Context: single threaded during gadget setup
292 *
293 * After initialization, each configuration must have one or more
294 * functions added to it. Adding a function involves calling its @bind()
295 * method to allocate resources such as interface and string identifiers
296 * and endpoints.
297 *
298 * This function returns the value of the function's bind(), which is
299 * zero for success else a negative errno value.
300 */
301 int usb_add_function(struct usb_configuration *config,
302 struct usb_function *function)
303 {
304 int value = -EINVAL;
305
306 DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
307 function->name, function,
308 config->label, config);
309
310 if (!function->set_alt || !function->disable)
311 goto done;
312
313 function->config = config;
314 list_add_tail(&function->list, &config->functions);
315
316 if (function->bind_deactivated) {
317 value = usb_function_deactivate(function);
318 if (value)
319 goto done;
320 }
321
322 /* REVISIT *require* function->bind? */
323 if (function->bind) {
324 value = function->bind(config, function);
325 if (value < 0) {
326 list_del(&function->list);
327 function->config = NULL;
328 }
329 } else
330 value = 0;
331
332 /* We allow configurations that don't work at both speeds.
333 * If we run into a lowspeed Linux system, treat it the same
334 * as full speed ... it's the function drivers that will need
335 * to avoid bulk and ISO transfers.
336 */
337 if (!config->fullspeed && function->fs_descriptors)
338 config->fullspeed = true;
339 if (!config->highspeed && function->hs_descriptors)
340 config->highspeed = true;
341 if (!config->superspeed && function->ss_descriptors)
342 config->superspeed = true;
343 if (!config->superspeed_plus && function->ssp_descriptors)
344 config->superspeed_plus = true;
345
346 done:
347 if (value)
348 DBG(config->cdev, "adding '%s'/%p --> %d\n",
349 function->name, function, value);
350 return value;
351 }
352 EXPORT_SYMBOL_GPL(usb_add_function);
353
354 void usb_remove_function(struct usb_configuration *c, struct usb_function *f)
355 {
356 if (f->disable)
357 f->disable(f);
358
359 bitmap_zero(f->endpoints, 32);
360 list_del(&f->list);
361 if (f->unbind)
362 f->unbind(c, f);
363
364 if (f->bind_deactivated)
365 usb_function_activate(f);
366 }
usb_ep_autoconfig内部会调用usb_ep_autoconfig_ss,在 usb_ep_autoconfig_ss中gadget->ops->match_ep dwc3的gadget驱动没有实现,所以会通过端口描述符找一个没有使用的ep。有了这个usb_ep结构,uac2驱动就可以使用它进行数据收发了。
63 struct usb_ep *usb_ep_autoconfig_ss(
64 struct usb_gadget *gadget,
65 struct usb_endpoint_descriptor *desc,
66 struct usb_ss_ep_comp_descriptor *ep_comp
67 )
68 {
69 struct usb_ep *ep;
70
71 if (gadget->ops->match_ep) {
72 ep = gadget->ops->match_ep(gadget, desc, ep_comp);
73 if (ep)
74 goto found_ep;
75 }
76
77 /* Second, look at endpoints until an unclaimed one looks usable */
78 list_for_each_entry (ep, &gadget->ep_list, ep_list) {
79 if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
80 goto found_ep;
81 }
82
83 /* Fail */
84 return NULL;
85 found_ep:
86
87 /*
88 * If the protocol driver hasn't yet decided on wMaxPacketSize
89 * and wants to know the maximum possible, provide the info.
90 */
91 if (desc->wMaxPacketSize == 0)
92 desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
93
94 /* report address */
95 desc->bEndpointAddress &= USB_DIR_IN;
96 if (isdigit(ep->name[2])) {
97 u8 num = simple_strtoul(&ep->name[2], NULL, 10);
98 desc->bEndpointAddress |= num;
99 } else if (desc->bEndpointAddress & USB_DIR_IN) {
100 if (++gadget->in_epnum > 15)
101 return NULL;
102 desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
103 } else {
104 if (++gadget->out_epnum > 15)
105 return NULL;
106 desc->bEndpointAddress |= gadget->out_epnum;
107 }
108
109 ep->address = desc->bEndpointAddress;
110 ep->desc = NULL;
111 ep->comp_desc = NULL;
112 ep->claimed = true;
113 return ep;
114 }
接着看udc_bind_to_driver函数,继续调用usb_gadget_udc_start, 里面其实主要就是调用了dwc3_gadget_start回调,在dwc3_gadget_start里主要就是注册了dwc3中断处理函数。后面继续调用usb_udc_connect_control函数,在usb_udc_connect_control函数里主要会调用到dwc3_gadget_pullup回调,在dwc3_gadget_pullup中就开始枚举流程了。
我们就介绍这么多,可以看到尽管我们尽量忽略一些细节介绍梗概,但是流程还是太复杂了。我后面再简单总结一下整个过程。
1.设备控制器驱动使用usb_gadget来抽象一个USB设备控制器硬件,使用usb_gadget_ops来实现对设备控制器的配置,使用usb_ep_ops实现实际的数据收发工作。
2.使用usb_gadget_driver 来抽象一个USB设备控制器的驱动,外界对这个设备控制器的管理就是通过这个驱动实现的。
3.使用usb_composite_dev来抽象一个复合设备,这个符合设备下会有多个usb_configuration ,每个usb_configuration 下又会有多个usb_funciton。function对应的是接口描述符,每个fuction会分配实际的usb_ep,function的具体功能就是通过这些ep实现的。
标签:function,configfs,usb,gadget,name,config,struct From: https://blog.csdn.net/liverdream/article/details/145286088