Linux系统USB设备枚举基础
2025-04-27
0
0
在Linux&UVC驱动栈(https://www.usbzh.com/article/detail-1322.html )一文中,描述符UVC设备的驱动栈。
从图可以知道,当USB物理设备插入USB集线器中后,USB主机控制器识别到USB物理设备,然后调用USBCore驱动的usb_new_dvice回调函数注册usb_device结构体,usb_device结构体会根据”drivers\usb\core\generic.c”来匹配,在其probe函数中会做如下操作。
- usb_choose_configuration
- usb_set_configuration
- malloc usb_device
- 设备usb_interface
- 注册usb_interface
- malloc usb_device
注册的usb_interface属于USB的逻辑设备,会根据其class,subclass等兼容ID信息或者PID_VID硬件信息注册其对应的类驱动程序。
usbcore
usbcore驱动配置如下:
struct usb_device_driver usb_generic_driver = {
.name = "usb",
.probe = generic_probe,
.disconnect = generic_disconnect,
#ifdef CONFIG_PM
.suspend = generic_suspend,
.resume = generic_resume,
#endif
.supports_autosuspend = 1,
};
可以看到,当有新的设备来临时也即当有新的USB物理设备插入时,会调用.probe的generic_probe函数。
static int generic_probe(struct usb_device *udev)
{
int err, c;
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
if (udev->authorized == 0)
dev_err(&udev->dev, "Device is not authorized for usage\n");
else {
//1.set_configuration
c = usb_choose_configuration(udev);
if (c >= 0) {
//2.set configuration
err = usb_set_configuration(udev, c);
if (err && err != -ENODEV) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
/* This need not be fatal. The user can try to
* set other configurations. */
}
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);
return 0;
}
选择配置
一个USB可以有多个配置描述符,但一次只能选择一个。
这里返回选择的配置描述符的索引
int usb_choose_configuration(struct usb_device *udev)
{
struct usb_host_config *best = null;
struct usb_host_config* c = udev->config;
int num_configs = udev->descriptor.bNumConfigurations;
for (i = 0; i < num_configs; (i++, c++)) {
struct usb_interface_descriptor *desc = NULL;
/* It's possible that a config has no interfaces! */
if (c->desc.bNumInterfaces > 0)
desc = &c->intf_cache[0]->altsetting->desc;
//uac3的特殊处理
//微软非标准的网卡特殊处理
//自定义设备处理
else if (udev->descriptor.bDeviceClass !=USB_CLASS_VENDOR_SPEC &&
(desc && desc->bInterfaceClass !=USB_CLASS_VENDOR_SPEC)){
best = c;
break;
}
else if (!best)
best = c;
}
if (best) {
i = best->desc.bConfigurationValue;
} else {
i = -1;
}
return i;
}
选择配置
选择配置详见usb_set_configuration函数。