USB总线-Linux内核USB3.0设备控制器复合设备之USB gadget configfs分析(七)

本文详细解读了configfs在Linux中如何实现USB gadget设备的灵活配置,包括uac2.0的配置流程、内核中的驱动绑定机制,以及如何通过脚本控制gadget的启用和停用。介绍了关键步骤和代码分析,展示了configfs在设备管理中的优势和实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.简介

configfs是基于ram的文件系统,与sysfs的功能有所不同。sysfs是基于文件系统的kernel对象视图,虽然某些属性允许用户读写,但对象是在kernel中创建、注册、销毁,由kernel控制其生命周期。而configfs是一个基于文件系统的内核对象管理器(或称为config_items),config_items在用户空间通过mkdir显式的创建,使用rmdir销毁,在mkdir之后会出现对应的属性,可以在用户空间对这些属性进行读写,与sysfs不同的是,这些对象的生命周期完全由用户空间控制,kernel只需要响应用户空间的操作即可。configfs和sysfs两者可以共存,但不能相互取代。
早期的USB只支持单一的gadget设备,使用场景较为简单,随后加入了composite framework,用来支持多个function的gadget设备,多个function的绑定在内核中完成,若需要修改,则需要修改内核,不灵活也不方便。Linux3.11版本引入了基于configfs的usb gadget configfs。usb gadget configfs重新实现了复合设备层,使用者可以在用户空间配置和组合内核的function,灵活的构成USB复合设备,极大了提高了工作效率。

2.使用方法

下面的脚本通过usb gadget configfs配置uac2.0。在使用之前,内核需要开启UAC2.0相关配置。uac2.0的参数在/sys/kernel/config/usb_gadget/g1/configs/c.1/uac2.0文件中,可配置通道、格式、采样率等,下面的脚本使用默认配置。

#!/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

执行完上述脚本后,/sys/kernel/config/usb_gadget/g1/目录下的文件组成如下所示。b开头的文件用来配置设备描述符。functions目录下的文件用于配置function驱动的参数。


├── bcdDevice
├── bcdUSB
├── bDeviceClass
├── bDeviceProtocol
├── bDeviceSubClass
├── bMaxPacketSize0
├── configs
│   └── c.1
│       ├── bmAttributes
│       ├── MaxPower
│       ├── strings
│       │   └── 0x409
│       │       └── configuration
│       └── uac2.0 -> ../../../../usb_gadget/g1/functions/uac2.0
├── functions
│   └── uac2.0
│       ├── c_chmask      # 录音通道掩码,默认0x3
│       ├── c_srate       # 录音采样率,默认64000
│       ├── c_ssize       # 录音一帧数据所占bit位,默认16bit
│       ├── p_chmask      # 播放通道掩码,默认0x3
│       ├── p_srate       # 播放采样率,默认48000
│       ├── p_ssize       # 播放一帧数据所占bit位,默认16bit
│       └── req_number    # 分配usb请求数量,默认2个
├── idProduct
├── idVendor
├── os_desc
│   ├── b_vendor_code
│   ├── qw_sign
│   └── use
├── strings
│   └── 0x409
│       ├── manufacturer
│       ├── product
│       └── serialnumber
└── UDC    # 用于设置绑定USB控制器的名称

3.代码分析

3.1.初始化

usb gadget configfs模块的初始化函数为gadget_cfs_init。该函数调用后,会向configfs注册一个子系统,子系统使用configfs_subsystem结构体描述。子系统中又可分为组,使用config_group描述,组内又有成员,使用config_item描述。usb gadget configfs就是configfs子系统中的一个成员,成员的名称为"usb_gadget",成员的类型使用config_item_type描述,成员类型中包含了初始化函数gadgets_ops。因此usb gadget configfs子系统最终通过调用gadgets_make进行初始化。当加载libcomposite.ko模块后,会在/sys/kernel/config/目录下生成一个usb_gadget目录。

[drivers/usb/gadget/configfs.c]
static struct configfs_group_operations gadgets_ops = {
	.make_group     = &gadgets_make,
	.drop_item      = &gadgets_drop,
};

static struct config_item_type gadgets_type = {
	.ct_group_ops   = &gadgets_ops,
	.ct_owner       = THIS_MODULE,
};

static struct configfs_subsystem gadget_subsys = {
	.su_group = {
		.cg_item = {
			.ci_namebuf = "usb_gadget",
			.ci_type = &gadgets_type,
		},
	},
	.su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),
};
static int __init gadget_cfs_init(void)
{
	int ret;
	config_group_init(&gadget_subsys.su_group);
	ret = configfs_register_subsystem(&gadget_subsys);
#ifdef CONFIG_USB_CONFIGFS_UEVENT
	android_class = class_create(THIS_MODULE, "android_usb");
	if (IS_ERR(android_class))
		return PTR_ERR(android_class);
#endif
	return ret;
}
module_init(gadget_cfs_init);

gadgets_make函数的主要工作内容是设置复合设备数据结构usb_composite_dev和复合设备驱动数据结构usb_composite_driver 工作流程如下:

  1. 分配gadget_info结构体,gi->group.default_groups是一个二级指针,第一级指向了gi->default_groupsgi->default_groups是一个指针数组,保存了functions_groupconfigs_groupstrings_groupos_desc_group的地址。这样就可以通过``gi->group找到所有的config_group`。
  2. 初始化functions_groupconfigs_groupstrings_groupos_desc_group,其config_item_type分别指向functions_typeconfig_desc_typegadget_strings_strings_typeos_desc_typegadget_strings_strings_type使用USB_CONFIG_STRINGS_LANG宏定义。
  3. 初始化复合设备驱动数据结构usb_composite_driver,使用usb gadget configfs时,使用者可以直接在用户空间绑定function驱动,不需要bindunbind函数,因此configfs_do_nothingconfigfs_do_nothing实现为空。复合设备驱动的 usb_gadget_driver指向configfs_driver_templateusb_gadget_driver是function驱动和UDC驱动沟通的桥梁,非常重要。
  4. 初始化复合设备数据结构usb_composite_dev,设置USB设备描述符。
  5. 设置gi->groupconfig_item_type指向gadget_root_type,usb gadget configfs初始化的时候首先调用gadget_root_type
  6. 最后向configfs系统返回gi->group。当在/sys/kernel/config目录下创建usb_gadget时,configfs系统会调用gi->groupgi->group.default_groups保存的config_item_type。也即调用gadgets_make函数设置的gadget_root_typefunctions_typeconfig_desc_typegadget_strings_strings_typeos_desc_type
[drivers/usb/gadget/configfs.c]
static struct config_group *gadgets_make(
		struct config_group *group, const char *name)
{
    ......
    /* 分配struct gadget_info结构体 */
    gi = kzalloc(sizeof(*gi), GFP_KERNEL);
    ......
	/* 设置group,gadgets_make最终返回的是gi->group */
	gi->group.default_groups = gi->default_groups;
	gi->group.default_groups[0] = &gi->functions_group;
	gi->group.default_groups[1] = &gi->configs_group;
	gi->group.default_groups[2] = &gi->strings_group;
	gi->group.default_groups[3] = &gi->os_desc_group;

    /* 设置functions_group,可配置function驱动的参数 */
	config_group_init_type_name(&gi->functions_group, "functions",
			&functions_type);
    /* 设置configs_group,可配置USB设备参数 */
	config_group_init_type_name(&gi->configs_group, "configs",
			&config_desc_type);
    /* 设置strings_group,可配置字符串参数 */
	config_group_init_type_name(&gi->strings_group, "strings",
			&gadget_strings_strings_type);
    /* 设置os_desc_group,可配置操作系统描述符 */
	config_group_init_type_name(&gi->os_desc_group, "os_desc",
			&os_desc_type);

	/* 初始化复合设备驱动-usb_composite_driver */
	gi->composite.bind = configfs_do_nothing;    // 实现为空
	gi->composite.unbind = configfs_do_nothing;  // 实现为空
	gi->composite.suspend = NULL;
	gi->composite.resume = NULL;
	gi->composite.max_speed = USB_SPEED_SUPER;   // 支持USB3.0

	/* 初始化复合设备-usb_composite_dev */
	composite_init_dev(&gi->cdev);
	/* 设置复合设备描述符 */
	gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE;
	gi->cdev.desc.bDescriptorType = USB_DT_DEVICE;
	gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());

	/* 设置configfs的usb_gadget_driver */
	gi->composite.gadget_driver = configfs_driver_template;
	gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
	gi->composite.name = gi->composite.gadget_driver.function;

	/* 设置config_group */
	config_group_init_type_name(&gi->group, name,
				&gadget_root_type);
	/* 向configfs系统返回&gi->group */
	return &gi->group;
}
/* usb gadget configfs定义的usb_gadget_driver */
static const struct usb_gadget_driver configfs_driver_template = {
	.bind           = configfs_composite_bind,
	.unbind         = configfs_composite_unbind,
#ifdef CONFIG_USB_CONFIGFS_UEVENT
	.setup          = android_setup,
	.reset          = android_disconnect,
	.disconnect     = android_disconnect,
#else
	.setup          = composite_setup,
	.reset          = composite_disconnect,
	.disconnect     = composite_disconnect,
#endif
	.suspend	    = composite_suspend,
	.resume		    = composite_resume,

	.max_speed	    = USB_SPEED_SUPER,
	.driver = {
		.owner      = THIS_MODULE,
		.name		= "configfs-gadget",
	},
};

下面是usb gadget configfs定义的几种config_item_typeconfigfs_group_operations。当在/sys/kernel/config/usb_gadget/目录下实例化一个新的gadget实例(g1)时,首先调用gadget_root_type,在g1目录下生成bDeviceClass、bDeviceSubClass、bDeviceProtocol、bMaxPacketSize0、idVendor、idProduct、bcdDevice、bcdUSB、UDC属性文件,使用者可以在用户空间进行配置;接着调用functions_type,在g1目录下生成functions目录,绑定function驱动后,会在该目录下导出function驱动的属性文件,供使用者修改;然后调用config_desc_type,在g1目录下生成configs目录;随后调用gadget_strings_strings_type,在g1目录下生成strings目录,包含了使用字符串表示的英语ID,开发商、产品和序列号等信息。最后调用os_desc_type,在g1目录下生成os_desc目录,包含了操作系统信息,一般不需要设置。

[drivers/usb/gadget/configfs.c]
static struct configfs_attribute *gadget_root_attrs[] = {
	&gadget_dev_desc_attr_bDeviceClass,
	&gadget_dev_desc_attr_bDeviceSubClass,
	&gadget_dev_desc_attr_bDeviceProtocol,
	&gadget_dev_desc_attr_bMaxPacketSize0,
	&gadget_dev_desc_attr_idVendor,
	&gadget_dev_desc_attr_idProduct,
	&gadget_dev_desc_attr_bcdDevice,
	&gadget_dev_desc_attr_bcdUSB,
	&gadget_dev_desc_attr_UDC,
	NULL,
};
static struct config_item_type gadget_root_type = {
	.ct_item_ops	= &gadget_root_item_ops,
	.ct_attrs	= gadget_root_attrs,
	.ct_owner	= THIS_MODULE,
};


static struct configfs_group_operations functions_ops = {
	.make_group     = &function_make,
	.drop_item      = &function_drop,
};
static struct config_item_type functions_type = {
	.ct_group_ops   = &functions_ops,
	.ct_owner       = THIS_MODULE,
};


static struct configfs_group_operations config_desc_ops = {
	.make_group     = &config_desc_make,
	.drop_item      = &config_desc_drop,
};
static struct config_item_type config_desc_type = {
	.ct_group_ops   = &config_desc_ops,
	.ct_owner       = THIS_MODULE,
};


/* 定义gadget_strings_strings_type的宏 */
USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info);
[include/linux/usb/gadget_configfs.h]
#define USB_CONFIG_STRINGS_LANG(struct_in, struct_member)	\
	......                                                   \
static struct configfs_group_operations struct_in##_strings_ops = {	\
	.make_group     = &struct_in##_strings_make,			\
	.drop_item      = &struct_in##_strings_drop,			\
};									\
									\
static struct config_item_type struct_in##_strings_type = {		\
	.ct_group_ops   = &struct_in##_strings_ops,			\
	.ct_owner       = THIS_MODULE,					\
}


static struct configfs_item_operations os_desc_ops = {
	.release        = os_desc_attr_release,
	.allow_link		= os_desc_link,
	.drop_link		= os_desc_unlink,
};
static struct config_item_type os_desc_type = {
	.ct_item_ops	= &os_desc_ops,
	.ct_attrs	= os_desc_attrs,
	.ct_owner	= THIS_MODULE,
};

3.2.主要调用流程分析

下面结合uac2.0用户空间配置脚本和内核中的USB gadget configfs代码,分析一下当用户空间配置时,内核中做了什么。重点关注驱动相关的执行流程。

3.2.1.创建配置

当在用户空间执行mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/configs/c.1命令时,会调用到configfs的config_desc_make函数。主要的工作流程为:

  1. 分配一个config_usb_cfg1结构体,该结构体包含了usb_configuration结构体,保存了该USB设备的配置信息。
  2. 设置USB设备的配置描述符的某些选项。如bConfigurationValue(根据创建配置目录的名称设置,如c.1,则设置为1)、MaxPowerbmAttributes
  3. 向用户空间导出该配置属性文件,便于使用者设置。
  4. 调用usb_add_config_only函数将该配置挂到usb_composite_devconfigs链表。

config

3.2.2.获取function实例

前面提到过,function驱动有两个重要的数据结构usb_function_instanceusb_function。下面是获取usb_function_instance的过程。如下图所示,当用户空间执行mkdir /sys/kernel/config/usb_gadget/g1/functions/uac2.0时,内核会调用USB gadget configfs的function_make函数,function_make函数的主要工作是获取function驱动的usb_function_instance数据结构,执行流程如下:

  1. 调用gadget funcation API usb_get_function_instance函数,遍历func_list链表,根据名称进行匹配。用户空间输入的是uac2,则匹配uac2驱动。其定义在f_uac2.c文件中。
  2. 匹配成功回调function驱动定义的alloc_inst函数,对于uac2,则回调afunc_alloc_inst函数。
    1. 首先分配f_uac2_opts数据结构,内部包含了usb_function_instance
    2. 设置uac2的config_item_typef_uac2_func_typef_uac2_func_type会在/sys/kernel/config/usb_gadget/g1/functions/uac2.0目录下导出设置uac2音频参数的属性文件,便于用户空间设置。
    3. 设置音频参数的默认值,使用者可在用户空间修改。
  3. 将获取到的uac2的usb_function_instance挂到gadget_infoavailable_func链表。

function_make

3.2.3.获取function

下面是获取usb_function的过程。如下图所示,当用户空间执行ln -s /sys/kernel/config/usb_gadget/g1/functions/uac2.0 /sys/kernel/config/usb_gadget/g1/configs/c.1时,内核会调用USB gadget configfs的config_usb_cfg_link函数。config_usb_cfg_link函数的主要工作是获取function驱动的usb_function数据结构,执行流程如下:

  1. 通过gadget funcation API,调用uac2驱动的afunc_alloc函数。
    1. 分配f_uac2数据结构,内部包含了usb_function
    2. 填充usb_function数据结构,重要的是设置的回调函数,usb_gadget_driver在适当的时候会回调这些函数。如驱动绑定的时候会回调afunc_bind函数,解除绑定的时候会回调afunc_unbind函数,设置配置的时候会回调afunc_set_alt函数等等。
  2. 将获取到的uac2的usb_function挂到config_usb_cfgfunc_list链表。

config_usb_cfg_link

3.2.4.驱动绑定

如下图所示,当用户空间执行echo fe800000.dwc3 > /sys/kernel/config/usb_gadget/g1/UDC时,内核会调用USB gadget configfs的gadget_dev_desc_UDC_store函数。gadget_dev_desc_UDC_store函数的主要工作是将usb_gadget_driver和底层的USB控制器绑定,usb_gadget_driver相当于一个桥梁,桥的两端分别是function驱动和UDC驱动。执行流程如下:

  1. 判断输入的USB控制器名称,若输出为空或者是none,则解除usb_gadget_driver和底层USB控制器的绑定。反之调用usb_udc_attach_driver函数进行匹配USB设备控制器。
  2. 遍历udc_list链表,查找fe800000.dwc3 USB设备控制器。
  3. 找到对应的USB设备控制器,则保存绑定的usb_gadget_driver,即configfs_driver_template
  4. 回调configfs_composite_bind函数。其主要的工作内容如下:
    1. 分配端点的usb_request、分配缓冲区、设置usb_request的回调函数、复位所有端点,并将gadget的端点数量清零。
    2. function驱动保存对应的配置,并回调function驱动的bind函数,对于uac2则回调 afunc_bind 函数。
    3. 如果使用os_string,则需要分配os_string requset
  5. 调用UDC驱动接口usb_gadget_udc_start使能USB设备控制器。
  6. 调用UDC驱动接口usb_udc_connect_control连接USB主机控制器,这样USB主机就能识别并枚举USB设备。

gadget_dev_desc_UDC_store

4.总结

本节以uac2为例,介绍了USB gadget configfs用户空间的使用方法及内核中的工作流程。USB gadget configfs提供了一个便捷的配置方法,用户可以灵活的组织USB function驱动,以组成不同功能的USB设备复合设备,当配置完成后,USB gadget configfs并不参与USB设备复合设备的工作过程。usb_gadget_driver数据结构相当于一个桥梁,连同了function驱动和UDC驱动,USB gadget configfs提供usb_gadget_driver实现为configfs_driver_template,对于legacy驱动,其实现又不同。本节没有涉及uac2驱动的工作流程及数据的收发过程,这些将再uac2驱动章节进行详细介绍。

参考资料

  1. https://wowothink.com/6a85234b/
  2. https://www.codeleading.com/article/31242270244/
  3. Documentation/filesystems/configfs/configfs.txt
  4. Documentation/usb/gadget_configfs.txt
  5. Rockchip RK3399TRM V1.3 Part1
  6. Rockchip RK3399TRM V1.3 Part2
  7. Linux内核4.4.179版本源码
### 回答1: USB ConfigFS是一种用于配置USB设备内核功能模块。它是Linux内核中的一个USB配置文件系统,用于在运行时动态配置和管理USB设备。通过ConfigFS,用户可以通过系统提供的接口来创建和管理各种USB设备,包括USB设备描述符、接口、端点等。 使用USB ConfigFS,用户可以通过创建一个configFS实例来定义和配置USB设备。用户可以通过ConfigFS中的文件系统接口创建和修改设备描述符,指定设备的功能和属性。此外,也可以创建和配置USB接口和端点,定义USB设备的数据传输规则和特性。 ConfigFS的优点之一是可以在运行时动态配置USB设备。这意味着在设备运行状态下可以添加、修改和删除设备的接口和端点,而无需重新启动设备或重新加载驱动程序。这为开发人员提供了更大的灵活性和便利性。 另外,ConfigFS还提供了丰富的调试和监控功能,使用户可以通过读取和写入ConfigFS文件来检查和调整设备的配置信息。这对于故障排除和性能优化非常有帮助。 综上所述,USB ConfigFS为用户提供了一种方便的方式来配置和管理USB设备。它不仅提供了灵活性和便利性,还提供了调试和监控功能。通过ConfigFS,用户可以根据自己的需求定义和配置USB设备,以满足各种应用场景的要求。 ### 回答2USB ConfigFS 是一个针对 Linux 内核的配置文件系统,用于动态创建和管理 USB 设备。它提供了一种可编程的方法,允许用户在运行时构建和配置 USB 设备的功能。 通过 USB ConfigFS,用户可以使用 USB FunctionFS 接口创建 USB 设备。用户通过将函数驱动程序挂载到 ConfigFS 文件系统中的相应目录来定义设备功能。用户可以创建多个配置文件来定义不同的设备配置,每个配置文件可以包含多个接口,每个接口又可以包含多个接口配制。 使用 USB ConfigFS,用户可以在运行时创建和配置 USB 设备,而不需要重新编译内核或重新启动系统。这种灵活性使得 USB ConfigFS 对于测试和调试 USB 设备非常有用,同时也方便了用户对于 USB 设备进行定制化配置。 USB ConfigFS 还允许用户通过 configfs 文件系统的用户空间接口来动态控制 USB 设备的属性,例如配置设备字符串描述符、设置设备的供应商和产品 ID 等。这种灵活性使得用户可以在运行时根据需要调整设备的属性,方便了设备的定制和适应性。 总而言之,USB ConfigFS 是一个用于动态创建和管理 USB 设备的配置文件系统,在 Linux 内核中起到了重要的作用。它提供了一种可编程的方法,允许用户在运行时构建和配置 USB 设备,为测试、调试和定制化 USB 设备提供了便利。 ### 回答3USB ConfigFS 是一个用于配置 USB 协议栈的 Linux 内核配置文件系统。ConfigFS 可以在运行时动态地创建和配置 USB 设备和功能。 使用 ConfigFS,用户可以通过在/sys/kernel/config/usb_gadget/目录中创建文件和目录来创建自定义的 USB 设备。 用户可以以树状结构来组织文件和目录,其中顶层目录表示 USB 设备,子目录则表示设备的不同功能。 在每个 USB 设备目录中,可以创建配置文件、字符串描述符和功能文件。 配置文件是指定义了设备的不同配置选项,如 USB 类型、供电模式、最大功率等。 字符串描述符文件包含了设备的各种描述信息,如制造商、产品名称、序列号等。 而功能文件则指定了设备所支持的功能,如 Mass Storage、HID、Audio 等。 通过编辑这些文件和目录的属性值,可以自定义 USB 设备的各种特性和行为。 一旦设备被配置好,它就可以在 PC 端被识别为一个 USB 设备,并与 PC 进行数据交互。 ConfigFS 提供了一个灵活和可扩展的方式来创建和配置 USB 设备。 相比传统的 USB 设备管理方式,使用 ConfigFS 不需要修改或重新编译内核,并且可以在运行时动态地添加、修改和删除配置。 同时,ConfigFS 也支持 USB 设备的热插拔,可以在系统运行过程中添加或移除 USB 设备,而不需要重启系统。 总之,USB ConfigFS 提供了一个方便的工具,可以用于自定义和配置 USB 设备,并灵活地管理 USB 设备的各种功能和特性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值