USB device creation process and driving study notes

It describes the source code analysis of the USB device inserted into the device creation process, and takes the mouse driver in the interrupt transmission mode as an example, and describes the USB driver implementation process.



USB device creation process

What work does the system do when a USB device is plugged in? In general: After inserting the USB device, the USB control recognizes the USB device, and will trigger an interrupt to the system, wake up the sleeping thread in the interrupt function, obtain the USB device information in the thread, and create the USB device.

Refer to the hub.c file for this process. The USB controller triggers the interrupt entry function: hub_irq. The entire call flow is as follows:

->hub_irq //产生中断(由USB控制器程序完成中断触发)
    ->kick_khubd(hub); 
       ->wake_up(&khubd_wait); //唤醒khubd_wait,khubd线程继续执行

The execution in the hub_thread loop thread is as follows:

->hub_thread
   ->wait_event_freezable(khubd_wait,  !list_empty(&hub_event_list) //khubd_wait列队被唤醒,开始往下执行↓
->hub_events   //遍历获取hub集线器上的ubs device
   ->  hub_port_connect_change(hub, i, portstatus, portchange);  锁定这个usbhub
     ->udev = usb_alloc_dev(hdev, hdev->bus, port1); 申请分配一个USB设备udev,
       ->dev->dev.type = &usb_device_type;指定总线为usb_device_type(方便后续match用)
     ->choose_devnum(udev);获取一个空余的USB编号(地址)
     ->status = hub_port_init(hub, udev, port1, i);
       -> hub_set_address(udev, devnum);把编号地址写进usb (udev->devnum)
       ->usb_get_device_descriptor(udev, 8); 获取该硬件的设备描述符 
     ->usb_new_device(udev);
        ->usb_enumerate_device(udev);   获取并解析设备/接口描述符等信息
      -> device_add(&udev->dev);  add设备。把该设备添加到USB总线

It can be seen from the above process that the kernel has acquired several key USB parameters: device descriptor; configuration descriptor; interface descriptor, etc. The structure affiliation of these pieces of information is located in ch9.h in the kernel:

A USB device descriptor: (including manufacturer ID information, device ID, configuration description number...) usb_device_descriptor-
  "configuration description (attributes, number of interfaces, configuration information, etc...) usb_config_descriptor-
     "interface description (class/subclass information, Protocol, port number, interface meaning: such as a USB with simultaneous recording and playback...) usb_interface_descriptor
(For example, the USB mouse interface description class is: ergonomic device class HID, subclass: 1, protocol: mouse)
       -" Endpoint information (input /Output, real-time, transmission type, packet size, message length...) usb_endpoint_descriptor


The last executed device_add will put dev into the dev linked list of the usb bus, and then call the bus usb_device_match function to traverse and compare the idtable of each USB driver. After the match is successful, the corresponding probe function of the USB driver will be called (this process is linux Commonly used bus-device-drive principle in the system)

The idtable matching method of the driver has 2 types to match:

  • Method 1: Through the interface description: USB_INTERFACE_INFO (class, subclass, protocol) to complete the device matching
  • Method 2: Complete device matching through manufacturer ID and device ID: USB_DEVICE (manufacturer ID, device ID)

USB driver writing (interrupt transmission mode)

The entire creation process of the USB device and bus matching are done automatically by the system, so the user is only required to write the corresponding USB device driver.

For example: a mouse type USB device.

  • After inserting the device, it will match the corresponding driver, and then call the probe function . The probe function needs to be initialized: register the input event that needs to be generated; the allocation and initialization of Urb (USB data transmission carrier); bind the interrupt function of urb communication.

  • When the external USB data is input, the USB controller will automatically trigger the interrupt function of urb communication when the data is received. The urb data is received and parsed in the interrupt function to complete the required operations (such as clicking, moving and other event reporting) , so the interrupt function is an important body for the realization of the USB function.

  • When the USB device is unplugged, disconnect will be called, mainly to do some removal, logout, and release operations.

Therefore, the driver involves: probe; interrupt function; disconnect function. The three-part implementation structure is roughly as follows:
(For details, please refer to usbmouse.c example)


probe(struct usb_interface *intf, const struct usb_device_id *id)函数:
->    
    //根据接口获取USB设备
    struct usb_device *dev = interface_to_usbdev(intf);  
    
        //根据接口获取端点
    interface = intf->cur_altsetting;
    endpoint = &interface->endpoint[0].desc;

     /*input 事件3要素:申请,配置,注册*/
    input_dev = input_allocate_device(); //申请设备
    __set_bit(EV_KEY,input_dev->evbit); //配置事件类型:按键
    __set_bit(EV_REL,input_dev->evbit); //配置事件类型:位移
    __set_bit(REL_X,input_dev->absbit); //配置具体事件:x方向相对位移
    ...
    input_register_device(input_dev); //注册事件

    /*定义数据传输3要素:端点长度,源地址,目的地址*/
    len=endpoint->wMaxPacketSize;    //自定义数据长度,这里定义为端点最大包大小
    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); //端点源地址
    vir_addr=usb_alloc_coherent(dev, len, GFP_ATOMIC, &dma_phy_addr); //目的地址,申请一段连续物理内存作为目的地址,长度为len

    //申请urb - USB REQUEST BLOCK(定义数据传输产生中断函数)可以理解urb为usb数据通信载体
    urb_t =usb_alloc_urb(0, GFP_KERNEL);//申请URB   
    usb_fill_int_urb(urb_t, dev, pipe, NULL,  //填充urb,中断传输方式
             (maxp > 8 ? 8 : maxp),
            test_irq_function, NULL, endpoint->bInterval);  //中断函数为test_irq_function
            即:USB数据传输到USB控制器,USB控制器会实时扫描数据,有数据会触发一中断,NULL为中断传入参数

    usb_submit_urb(urb_t, GFP_KERNEL);//提交urb

===========================================================================================

test_irq_function urb(struct urb *urb)  中断函数(即:USB数据传输到USB控制器,USB控制器会实时扫描数据,有数据会触发中断)
->
    data=urb->context->data
    input_report_key(dev, BTN_LEFT, data[0] & 0x01); //解析数据,上报事件(BTN_LEFT:左键)
    //input_report_rel(dev, REL_X,  data[1]);//位移上报
    ...
    input_sync(dev); //事件同步
    
    usb_submit_urb(urb, GFP_ATOMIC); //提交urb

===========================================================================================

disconnect(struct usb_interface *intf)函数:(USB设备拔出后调用)
->      
      usb_kill_urb(urb_t);
      input_unregister_device(input_dev);
      usb_free_urb(urb_t);
      usb_free_coherent(interface_to_usbdev(intf), len, vir_addr, &dma_phy_addr);
       

The above-mentioned driver describes the realization of the USB mouse type driver, the interrupt transmission method adopted, and the realization of the input event. USB also involves storage, audio and video and other types, and its transmission and implementation methods are different. Therefore, it is necessary to understand the concepts of the following transmission methods:

  • Interruption: Transmit a small amount of fixed data, one-way input: mouse, keyboard, etc. The above is the interruption transmission method.
  • Control: Control transmission is two-way transmission, and the amount of data is usually small.
  • Bulk: usually used for USB storage, bulk data transfer.
  • Isochronous: It is also a batch data transmission, but timeliness is ensured, and it is not guaranteed whether the data arrives, such as: audio and video equipment.

This article mainly introduces the realization of the interrupt transmission method. Other transmission methods have similar frameworks in the USB driver.

Guess you like

Origin blog.csdn.net/ludaoyi88/article/details/113664790