Linux USB驱动源代码分析
+ -

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

注册的usb_interface属于USB的逻辑设备,会根据其class,subclass等兼容ID信息或者PID_VID硬件信息注册其对应的类驱动程序。

文章参考:https://ldd.100ask.net/zh/12_USB/08_1.html

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函数。

0 篇笔记 写笔记

LINUX系统USB设备驱动栈
内核打印Linux系统的内核打印可以通过如下命令来显示:cat /proc/kmsg &而在Windows系统则可以通过DbgViewer或者Windbg查看,当然,前提条件是需要配置注册表项。Linux内核打印默认是7个等级,使用函数printk来进行内核打印,相当于Windows的......
Linux&UVC驱动栈
以下内容仅代表个人观点,有很大概率不准确。作业初学者,仅为学习笔记而已,勿全当真。但本人会随着认识而修正本文错误的观点。Windows系统有驱动层级结构,Linux应该也有。作为初学者,需要多读多学,并对新学的知识进行总结。本人根据自己的理解对Linux系统UVC驱动栈进行绘制图。最底层的......
Linux系统USB设备枚举基础
在Linux&UVC驱动栈(https://www.usbzh.com/article/detail-1322.html )一文中,描述符UVC设备的驱动栈。从图可以知道,当USB物理设备插入USB集线器中后,USB主机控制器识别到USB物理设备,然后调用USBCore驱动的usb_new......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!