Home >System Tutorial >LINUX >How does Linux identify the USB device I plugged in?

How does Linux identify the USB device I plugged in?

PHPz
PHPzforward
2024-02-09 14:15:15952browse

I. Introduction

When learning the Linux operating system, have you ever had this question: Why can our computers recognize and use different USB devices? Why doesn’t Linux system use the mouse as a keyboard? Let us discuss the identification and loading process of USB devices in Linux systems.

2. Identification and loading of USB devices

When we plug a USB device into the computer, the Linux kernel will automatically detect and load the corresponding driver so that the device can work normally. Next, we will delve into the identification and loading process of USB devices in Linux systems.

How does Linux identify the USB device I plugged in?

2.1 USB controller detects device insertion

The USB controller is a hardware device used to control devices on the USB bus. When you plug in a USB device, the USB controller detects the voltage change and sends an interrupt signal. This interrupt signal is sent to the USB controller interrupt line on the processor, telling the Linux kernel that a new USB device is plugged in.

2.2 Kernel detects and loads the driver

When the kernel receives the interrupt signal from the USB controller, it will call the usbcore module in the USB subsystem, which is responsible for detecting new USB devices and loading the corresponding driver. usbcoreThe module will first detect the device descriptor, which includes the device's manufacturer ID, product ID, category code and other information.

If a matching driver already exists, the usbcore module will load the driver. If there is no matching driver, it will try to load a universal driver that can support most USB devices.

2.3 The driver registers with the USB subsystem

Once the correct driver is loaded, it registers with the USB subsystem and tells it which devices it can handle. This step usually involves registering the class of the USB device (such as storage device, input device, etc.) with the kernel.

This process includes registering a new USB device driver with the kernel and specifying the device's manufacturer ID, product ID and other information in the driver. Once the driver is successfully registered, the USB subsystem can match the device with the correct driver.

2.4 USB subsystem creates device node

The USB subsystem will next create a device node for the device. A device node is a special file in the /dev directory that allows user space programs to communicate with the device. The name of the device node is usually dynamically generated by the kernel based on the device's manufacturer ID, product ID, serial number and other information.

The creation of device nodes is achieved through the udev daemon process. This daemon process monitors device plug-in and unplug events in the system and automatically creates or deletes corresponding device nodes. Once the device node is created, the kernel can assign access rights to the device to user-space programs.

2.5 Driver initialization device

After the driver is notified that a new device is inserted, it will initialize the device. Initialization may include setting the device's transfer rate, allocating memory buffers, etc. After device initialization is complete, the driver reports to the USB subsystem that the device is ready.

2.6 User space program opens the device:

Finally, user space programs can open device nodes and communicate with the device. The permissions of device nodes are usually set to only allow access to the root user or users in relevant groups. User space programs can use system calls such as read and write to send commands to the device and receive data.

Through this process, the Linux system can automatically identify the device and load the corresponding driver so that the device can work normally. This is also why when we plug in a USB device, we don't need to manually install any drivers or perform any other operations to start using the device directly.

When you plug in a USB device, the Linux system will automatically perform the above steps to automatically identify the device and load the corresponding driver so that the device can work normally. Let's analyze the process from the code level.

3. Code implementation explanation

Below I will explain the identification and loading process of USB devices in Linux systems through some sample codes. These sample codes are just to explain the principles, the actual code will be more complex.

3.1 Detection device insertion

When a USB device is plugged into the system, an interrupt signal is generated, which is captured by the USB controller interrupt line on the processor and processed by the kernel's USB subsystem. Here is a sample code that demonstrates how to detect USB device plug-in and unplug events:

#include 
#include 

int main() {
    libusb_device **devs;
    libusb_context *ctx = NULL;

    int r = libusb_init(&ctx);
    if (r printf("Failed to initialize libusb\n");
        return 1;
    }

    // 扫描USB总线并列出所有连接的设备
    ssize_t cnt = libusb_get_device_list(ctx, &devs);
    if (cnt printf("Failed to get device list\n");
        return 1;
    }

    // 遍历设备列表,检测插入和拔出事件
    for (int i = 0; i if (r printf("Failed to get device descriptor\n");
            continue;
        }

        printf("Vendor ID: 0x%04x, Product ID: 0x%04x\n", desc.idVendor, desc.idProduct);
    }

    // 释放设备列表
    libusb_free_device_list(devs, 1);

    // 退出libusb
    libusb_exit(ctx);

    return 0;
}

This code uses the libusb library, which is a C language library used to access USB devices. It provides an API for initializing the USB subsystem and scanning the USB bus, as well as an API for accessing USB devices.

3.2 Loading the driver

Once a device is detected as plugged in, the USB subsystem attempts to load an appropriate driver. Below is a sample driver code, which is responsible for supporting USB storage devices (such as USB flash drives):

#include 
#include 

static struct usb_device_id storage_devices[] = {
    { USB_DEVICE(0xabcd, 0x1234) },
    { USB_DEVICE(0xffff, 0xffff) },
    { }
};
MODULE_DEVICE_TABLE(usb, storage_devices);

static int storage_probe(struct usb_interface *interface, const struct usb_device_id *id) {
    // 初始化设备并注册
    return 0;
}

static void storage_disconnect(struct usb_interface *interface) {
    // 释放设备
}

static struct usb_driver storage_driver = {
    .name = "usb-storage",
    .probe = storage_probe,
    .disconnect = storage_disconnect,
    .id_table = storage_devices,
};

module_usb_driver(storage_driver);

This code demonstrates a simple driver that can handle the insertion and removal events of USB storage devices. When loading a driver, the kernel searches the list of loaded drivers for a driver that matches the device.

If a matching driver is found, the kernel will use that driver to manage the device. If no matching driver is found, the kernel will not load any driver.

3.3 Device Registration

Once a driver matching the device is found, the driver will be loaded and started, it will attempt to initialize the device and register it with the kernel. Below is a sample code that demonstrates how to initialize a USB storage device and register it with the kernel:

static int storage_probe(struct usb_interface *interface, const struct usb_device_id *id) {
    struct usb_device *dev = interface_to_usbdev(interface);

    // 获取设备描述符
    struct usb_device_descriptor desc;
    int r = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &desc, sizeof(desc));
    if (r "Failed to get device descriptor\n");
        return r;
    }

    // 打印设备信息
    printk(KERN_INFO "USB storage device detected: Vendor ID=0x%04x, Product ID=0x%04x\n", desc.idVendor, desc.idProduct);

    // 初始化设备并注册到内核
    // ...

    return 0;
}

The above sample code uses the kernel's usb_get_descriptor() function to obtain the device descriptor, and uses the printk() function to record the device information to the kernel log.

When the driver will call the device initialization function and register it with the kernel, but since the process of device initialization and registration varies from device to device, this part of the code is omitted here.

3.4 设备访问

一旦设备已经被注册到内核,用户空间程序就可以通过设备节点来访问设备。在Linux系统中,设备节点是一种特殊的文件,可以通过标准文件I/O函数来访问。下面是一个示例代码,演示如何打开并读取USB存储设备:

#include 
#include 
#include 

int main() {
    // 打开设备节点
    int fd = open("/dev/sdb", O_RDONLY);
    if (fd printf("Failed to open device\n");
        return 1;
    }

    // 读取设备数据
    char buf[1024];
    ssize_t n = read(fd, buf, sizeof(buf));
    if (n printf("Failed to read device\n");
        close(fd);
        return 1;
    }

    // 关闭设备节点
    close(fd);

    return 0;
}

这段代码使用了标准的文件I/O函数来访问设备节点。在这个例子中,设备节点的路径是/dev/sdb,这是一个典型的USB存储设备节点。接下来,程序将设备节点作为文件打开,并使用read()函数从设备中读取数据。一旦完成数据的读取,程序将关闭设备节点并退出。

四、结语

Linux系统识别USB设备的过程可以分为四个步骤:设备连接、驱动匹配、设备注册和设备访问。当用户将USB设备插入计算机时,内核将通过USB总线来检测设备的插入事件,并尝试查找与设备匹配的驱动程序。一旦找到了匹配的驱动程序,驱动程序将被加载并启动,它将尝试对设备进行初始化,并将其注册到内核。一旦设备已经被注册到内核,用户空间程序就可以通过设备节点来访问设备。

在Linux系统中,驱动程序是非常重要的组成部分,它们负责管理和控制系统中的各种设备。对于USB设备而言,内核提供了一个通用的USB驱动框架,它可以自动检测和加载驱动程序,并为用户提供了一个简单而强大的USB设备访问接口。通过深入理解USB驱动程序的工作原理,我们可以更好地理解Linux系统中设备管理的内部机制,这对于开发和调试设备驱动程序非常有帮助。

The above is the detailed content of How does Linux identify the USB device I plugged in?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:lxlinux.net. If there is any infringement, please contact admin@php.cn delete