As shown in the figure below , With windows For example , We plug in one that doesn't USB Device driven USB, You will be prompted to install the driver


Why is there a prompt message when you plug it in ?

Because windows Bring it with you USB Bus driver ,

USB The bus driver is responsible for :

distinguish USB equipment , to USB The device finds the corresponding driver

New access USB The default address of the device ( Number ) yes 0, Before a new number is assigned ,PC Host use 0 The address communicates with it .

then USB The bus driver assigns it an address ( Number )

PC I want to visit USB Somewhere on the bus USB Equipment time , All the commands issued contain the corresponding address ( Number )

USB It's a master-slave structure . The mainframe is called Host, The slave is called Device, be-all USB transmission , from USB The host side initiates ;USB Device not available " Take the initiative " notice USB The ability of the host .

Example :USB A mouse swipe produces data immediately , But it doesn't have the ability to notify PC The computer reads the data , We have to wait passively PC Machine to read .

USB The principle of hot swappable hardware

stay USB A hub (hub) Of each downstream port D+ and D- On , They took on one... Respectively 15K Ohm pull resistance to ground . such , When the hub port is suspended , It's pulled to a low level by these two pull-down resistors .

And in the USB Device end , stay D+ perhaps D- It's connected to 1.5K Ohmic pull-up resistor . For full speed and high speed equipment , The pull-up resistor is connected to D+ On ; The low speed equipment is connected with pull-up resistor D- On . such , When the device is plugged into the hub , from 1.5K The pull-up resistance and 15K The pull-down resistor is used to divide the voltage , As a result, one of the differential data lines is pulled up . When the hub detects this state , It reports to USB Main controller ( Or it can be reported to USB Main controller ), This will detect the insertion of the device .USB High speed devices are first identified as full speed devices , And then through HOST and DEVICE The confirmation between the two , Switch to high speed mode . In high speed mode , It's the current transfer mode , This will be D+ The pull-up resistor on the is off .


USB Of 4 Big transmission type :

Control transmission (control)  

Is each USB The device must support , Usually used to get device descriptors 、 Set the status of the device, etc . One USB From the insertion to the final pull-out of the device, there must be control transmission ( Even if this USB The device is not supported by this system ).
Interrupt transmission (interrupt)

Typical devices that support interrupt transmission are USB mouse 、 USB Keyboard and so on. . Interrupt transmission doesn't mean my device is really sending an interrupt , Then the host will come and read the data . It is actually a polling way to complete data communication .USB The device will set a parameter in the device driver called interval, It is endpoint A member of . interval It means interval time , How long do I want the host to poll itself , As long as this value is determined , My host will periodically check whether there is any data to be processed

Bulk transfer (bulk)

The most typical device supporting batch transmission is U disc , It does a lot of data transfer , It can guarantee the accuracy of data , But time is not fixed .

Real time transmission (isochronous) 
USB A camera is a typical example of a real-time transmission device , It also does a lot of data transfer , The accuracy of the data cannot be guaranteed , But it's very sensitive to transmission delay , That is to say, the requirement for real-time is relatively high


USB Endpoint :

USB There will be several communication channels between the device and the host ” Endpoint ”, Each endpoint has an endpoint number , Except for the endpoint 0 Outside , Each endpoint can only work in one transport type ( Control transmission 、 Interrupt transmission 、 Bulk transfer 、 Real time transmission ) Next , In one direction of transmission

The transmission direction is based on USB From the standpoint of the mainframe ,

such as : The data of the mouse is transferred from the mouse to PC machine , The corresponding endpoint is called " Interrupt input endpoint "

And the endpoint 0 Is the default control endpoint for the device , Both output and input , be used for USB The identification process of the device


Again linux The kernel also comes with it USB Bus driver , The framework is as follows :



To be a USB host , Hardware must have USB It's the host controller ,USB The host controller is divided into 4 Kind of interface :

OHCI(Open Host Controller Interface):  Microsoft led low speed USB1.0(1.5Mbps) And full speed USB1.1(12Mbps),OHCI The interface software is simple , The hardware is complex  

UHCI(Universal Host Controller Interface): Intel Leading low speed USB1.0(1.5Mbps) And full speed USB1.1(12Mbps), and UHCI The interface software is complex , The hardware is simple  

EHCI(Enhanced Host Controller Interface): High speed USB2.0(480Mbps),

xHCI(eXtensible Host Controller Interface):USB3.0(5.0Gbps), Adopted 9 Stitch Design , It also supports USB2.0、1.1 etc.


Let's get to the point , To analyze USB Bus driver , How to identify USB equipment

Because the kernel comes with USB drive , So let's insert a USB Keyboard to the development board to see print information

The following fields were found :


Here's the picture , Find the first paragraph in drivers/usb/core/hub.c Of the 2186 That's ok

This hub It's actually our USB The hub of the host controller , Used to manage multiple USB Interface

1. drivers/usb/core/hub.c Of the 2186 Line in hub_port_init() In the function

Who called it , As shown in the figure below , We found it through hub_thread() Function called


hub_thread() Function as follows :

 Copy code

static int hub_thread(void *__unused)
do {
       hub_events();       // Do it once hub Event function
       wait_event_interruptible(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_stop()); 
   //(1). Once at a time hub event , Will enter a wait event interrupt function
} while (!kthread_should_stop() || !list_empty(&hub_event_list));
pr_debug("%s: khubd exiting\n", usbcore_name);
return 0;

 Copy code

From the above function we get , To execute hub_events(), All have to wait khubd_wait This interrupt wakes up


2. We search ”khubd_wait”, Look who's waking up

  Find the interrupt in kick_khubd() Wake up in function , The code is as follows :

 Copy code

static void kick_khubd(struct usb_hub *hub)
       unsigned long       flags;
       to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
       spin_lock_irqsave(&hub_event_lock, flags);
       if (list_empty(&hub->event_list)) {
              list_add_tail(&hub->event_list, &hub_event_list);
              wake_up(&khubd_wait);                     // Wake up the khubd_wait This interruption
       spin_unlock_irqrestore(&hub_event_lock, flags);

 Copy code


3. Continue to search kick_khubd, Findings were hub_irq() Call in function

obviously , Is that when USB After the device is plugged in ,D+ or D- Will be pulled up , then USB The host controller will generate a hub_irq interrupt .


4. Now let's go straight to hub_port_connect_change() function , How to connect ports

 Copy code

static void hub_port_connect_change(struct usb_hub *hub, int port1,u16 portstatus, u16 portchange)
... ...
udev = usb_alloc_dev(hdev, hdev->bus, port1);    //(1) Sign up for a usb_device, And then it's going to be placed in usb On the bus
usb_set_device_state(udev, USB_STATE_POWERED); // Set up registered USB The status of the device
... ...
choose_address(udev);                              //(2) Assign an address number to the new device
  status = hub_port_init(hub, udev, port1, i);    //(3) Initialize port , And USB The device is connected
... ...
status = usb_new_device(udev);            //(4) establish USB equipment , And USB Device driver connection
... ...

 Copy code

 (usb_device Equipment structure reference :

So the final flow chart is as follows :


5. We enter hub_port_connect_change()->usb_alloc_dev(), Let's see how it's set up usb_device Of

 Copy code

 1 usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 3 {
 5        struct usb_device *dev;
 9        dev = kzalloc(sizeof(*dev), GFP_KERNEL);   // Allocate one usb_device Equipment structure
11        ... ...
15        device_initialize(&dev->dev);           // initialization usb_device
17        dev->dev.bus = &usb_bus_type;         //(1) Set up usb_device Members of device->bus be equal to usb_bus Bus
19        dev->dev.type = &usb_device_type;    // Set up usb_device Members of device->type be equal to usb_device_type
21        ... ...
23        return dev;                                        // Return to one usb_device Structure
25 }

 Copy code

(1) In the 17 Go ahead , Set up device member , It's mainly for the back 8.2 Section , register usb Bus device On the table .

among usb_bus_type Is a global variable , It's different from what we learned before platform The platform bus is similar , Belong to USB Bus , yes Linux in bus A kind of .

As shown in the figure below , Every time you create a USB equipment , perhaps USB When the device is driven ,USB The bus will call match Members to match once , send USB Equipment and USB Device drivers .

usb_bus_type The structure is as follows :

 Copy code

struct bus_type usb_bus_type = {
       .name =         "usb",              // Bus name , There is /sys/bus Next
       .match = usb_device_match,  // Match function , If the match is successful, it will call usb_driver Driven probe Members of the function
       .uevent =       usb_uevent,           // Event function
       .suspend =     usb_suspend,     // Dormancy function
       .resume =      usb_resume,    // Wake up function

 Copy code



6. We enter hub_port_connect_change()->choose_address(), Let's see how it assigns address numbers

 Copy code

static void choose_address(struct usb_device *udev)
int devnum;
struct usb_bus    *bus = udev->bus;
devnum = find_next_zero_bit(bus->devmap.devicemap, 128,bus->devnum_next); 
 // stay bus->devnum_next~128 In interval , Loop to find the next non 0( No equipment ) The number of
       if (devnum >= 128)                 // If the number is greater than or equal to 128, No spare address number found , Start from the beginning
              devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);
       bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);  // Set the next addressing interval +1
       if (devnum < 128) {                                  
              set_bit(devnum, bus->devmap.devicemap);   // Set bit
              udev->devnum = devnum;    

 Copy code

From the analysis of the above code, each address number is added continuously ,USB The interface can be connected to 127 Devices , We plug and unplug twice in a row USB keyboard , It can also be seen that , As shown in the figure below :



7. Let's see hub_port_connect_change()->hub_port_init() How do functions connect USB The equipment

 Copy code

 1 static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,int retry_counter)
 2 {
 3    ... ...
 4    for (j = 0; j < SET_ADDRESS_TRIES; ++j) 
 5   {
 6        retval = hub_set_address(udev);     //(1) Set the address , tell USB The new address number of the device
 8        if (retval >= 0)
 9                 break;
10        msleep(200);
11    }
12  retval = usb_get_device_descriptor(udev, 8);   //(2) get USB Before the device descriptor 8 Bytes
13  ... ...
15  retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);  // Retrieve device descriptor information
16  ... ...
17 }

 Copy code

(1) The above first 6 In line ,hub_set_address() Function is mainly used to tell USB The new address number of the device , hub_set_address() Function as follows :

 Copy code

static int hub_set_address(struct usb_device *udev)
       int retval;
       ... ...
       retval = usb_control_msg(udev, usb_sndaddr0pipe(),USB_REQ_SET_ADDRESS,0, udev->devnum, 0,NULL, 0, USB_CTRL_SET_TIMEOUT);   
  //(1.1) Wait for the transfer to complete
    if (retval == 0) {              // Set a new address , Transmission complete , return 0
              usb_set_device_state(udev, USB_STATE_ADDRESS);  // Set status flag
return retval;

 Copy code

  usb_control_msg() Function is used to make USB The host controller sends a control message to USB equipment , If the transmission is complete, return 0. The parameter udev Represents the target device ; The pipeline used is usb_sndaddr0pipe(), That's the default address 0 Add the control endpoint number 0; USB_REQ_SET_ADDRESS Indicates the command code , Set the address ; udev->devnum Indicates the device number of the target device to be set ; The time allowed to wait for the transmission to complete is 5 second , because USB_CTRL_SET_TIMEOUT Defined as 5000.

2) The above first 12 In line ,usb_get_device_descriptor() Function is to get the target device descriptor 8 Bytes , Why just start reading first 8 Bytes ? It's because we don't know the packet capacity supported by the other party at the beginning , this 8 Every device has four bytes , Later, according to the data of the device , adopt usb_get_device_descriptor() Reread the device description structure of the target device once .

among USB The device descriptor structure is as follows :

 Copy code

struct usb_device_descriptor {
 __u8  bLength;                          // This descriptor's size
 __u8  bDescriptorType;               // The type of descriptor , Here is the device descriptor DEVICE
 __u16 bcdUSB;                           // To specify usb Version of , such as usb2.0
 __u8  bDeviceClass;                   // class
 __u8  bDeviceSubClass;                // Subclass
 __u8  bDeviceProtocol;                  // Designated agreement
 __u8  bMaxPacketSize0;                // Endpoint 0 The corresponding maximum packet size
 __u16 idVendor;                         // manufacturer ID
 __u16 idProduct;                        // product ID
 __u16 bcdDevice;                        // The release number of the device
 __u8  iManufacturer;                    // In the string descriptor ID The index of
 __u8  iProduct;                         // The product in the string descriptor ID The index of
 __u8  iSerialNumber;                  // The index of the device serial number in the string descriptor
 __u8  bNumConfigurations;               // Number of possible configurations
} __attribute__ ((packed));

 Copy code


8. Let's see hub_port_connect_change()->usb_new_device() How functions are created USB The equipment

 Copy code

int usb_new_device(struct usb_device *udev)
   ... ...
   err = usb_get_configuration(udev);           //(1) Get the configuration description block
... ...
err = device_add(&udev->dev);     // (2) hold device Put in bus Of dev In the list , And find the corresponding device driver

 Copy code

(1) among usb_get_configuration() Function as follows , It's about getting the configuration

 Copy code

int   usb_get_configuration(struct usb_device *dev)
  ... ...
  /* USB_MAXCONFIG  Defined as 8, Indicates that there are at most... Under the device description block 8 A configuration description block  */
  /*ncfg Express   Under the device description block   How many configuration description blocks are there  */
if (ncfg > USB_MAXCONFIG) {
              dev_warn(ddev, "too many configurations: %d, "
                  "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
              dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
  ... ...
  for (cfgno = 0; cfgno < ncfg; cfgno++)   //for loop , from USB Read all the configuration description blocks in turn in the device
      result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,buffer, USB_DT_CONFIG_SIZE);
                              // Read first every time USB_DT_CONFIG_SIZE Bytes , That is to say 9 Bytes , For the time being buffer in
      ... ...
      length = max((int) le16_to_cpu(desc->wTotalLength),USB_DT_CONFIG_SIZE);
// adopt wTotalLength, Know the actual data size
      bigbuffer = kmalloc(length, GFP_KERNEL);  // And then allocate enough space
      ... ...
      result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,bigbuffer, length);
                             // In a call usb_get_descriptor, Read out the entire configuration description block , Put it in bigbuffer in
      ... ...
      dev->rawdescriptors[cfgno] = bigbuffer;   // then bigbuffer The address is in rawdescriptors In the array of pointers
      result = usb_parse_configuration(&dev->dev, cfgno,&dev->config[cfgno],
bigbuffer, length);         // Finally, in parsing each configuration block
  ... ...

 Copy code

(2) among device_add () Function as follows

 Copy code

int   usb_get_configuration(struct usb_device *dev)
 dev = get_device(dev);         // send dev be equal to usb_device Under the device member
 ... ...
if ((error = bus_add_device(dev))) //  Add this device to dev->bus Of device In the table
              goto BusError;
 ... ...
bus_attach_device(dev);           // To match the corresponding driver
 ... ...

 Copy code

  When bus_attach_device() Function match successful , Will call the driver probe function



9. Let's see usb_bus_type Members of this group usb_device_match function , See how it matches

usb_device_match The function is shown below :

 Copy code

static int usb_device_match(struct device *dev, struct device_driver *drv)
       if (is_usb_device(dev)) {                       // Judgment is not USB equipment
              if (!is_usb_device_driver(drv))
                     return 0;
              return 1;
else {                                                // Otherwise, it would be USB Drive or USB Interface of equipment
              struct usb_interface *intf;
              struct usb_driver *usb_drv;
              const struct usb_device_id *id;           
              if (is_usb_device_driver(drv))   // If it is USB drive , There's no need to match , direct return
                     return 0; 
              intf = to_usb_interface(dev);               // obtain USB Interface of equipment
              usb_drv = to_usb_driver(drv);                    // obtain USB drive
              id = usb_match_id(intf, usb_drv->id_table);  // matching USB Members of the drive id_table
              if (id)
                     return 1;
              id = usb_match_dynamic_id(intf, usb_drv);
              if (id)
                     return 1;
       return 0;

 Copy code

Obviously it's a match USB Driven id_table


10. that USB Driven id_table How to define ?

id_table Its structure is usb_device_id, As shown below :

 Copy code

struct usb_device_id {
       __u16             match_flags;   // And usb The device matches that type ? The comparison type macro is as follows :
 //USB_DEVICE_ID_MATCH_INT_INFO :  Used to match the device's interface descriptor 3 Members
 //USB_DEVICE_ID_MATCH_DEV_INFO:  Used to match device descriptors 3 Members
 //USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION:  Used to match specific USB The equipment 4 Members
 //USB_DEVICE_ID_MATCH_DEVICE: Used to match specific USB The equipment 2 Members (idVendor and idProduct)
       /*  following 4 A match describes a specific USB equipment  */
       __u16             idVendor;              // manufacturer ID
       __u16             idProduct;             // product ID
       __u16             bcdDevice_lo;        // The lower version number of the device
       __u16             bcdDevice_hi;        // The higher version number of the device
       /* following 3 One is used to compare device descriptors */
       __u8        bDeviceClass;                    // Equipment class
       __u8        bDeviceSubClass;                 // Device subclasses
       __u8        bDeviceProtocol;                 // Equipment agreement
       /*  following 3 One is used to compare device interface descriptors  */
       __u8        bInterfaceClass;                   // Interface type
       __u8        bInterfaceSubClass;             // Interface subtype
       __u8        bInterfaceProtocol;           // The protocol that the interface follows
       /* not matched against */
       kernel_ulong_t       driver_info;


 ( The device description conforms to the interface descriptor structure reference :

We refer to /drivers/hid/usbhid/usbmouse.c( Built in kernel USB Mouse drive ), How it is used , As shown in the figure below :


It was discovered through USB_INTERFACE_INFO() This macro defines . The macro looks like this :

#define USB_INTERFACE_INFO(cl,sc,pr) \
       .match_flags = USB_DEVICE_ID_MATCH_INT_INFO,  \    // Set up id_table Of .match_flags member
      .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
                                                         // Set up id_table Of 3 Members , Used to match USB The equipment 3 Members 

And then take the usb_mouse_id_table [] Inside 3 Put a value into the macro USB_INTERFACE_INFO(cl,sc,pr) in :


.bInterfaceClass =USB_INTERFACE_CLASS_HID;  
   // Set matching USB The interface type of is HID class ,  because USB_INTERFACE_CLASS_HID=0x03
   //HID Class is a human-computer interaction device , such as :USB keyboard ,USB mouse ,USB Touch Pad ,USB The joystick has to be filled in 0X03
   // Set matching USB The interface subtype of is boot device
  // Set matching USB The interface protocol of is USB Mouse protocol , be equal to 2
  // When .bInterfaceProtocol=1 That is to say USB_INTERFACE_PROTOCOL_KEYBOARD when , Express USB Keyboard protocol 


Here's the picture , We can also pass windows You can also find the protocol number of the mouse on the , It's also 2:


among VID: It means the manufacturer (vendor)ID

PID: According to the product (Product) ID


summary : When we plug in USB Equipment time , The system will get USB Equipment of equipment 、 To configure 、 Interface 、 Data from the endpoint , And create new devices , So our driver needs to write id_table To match the USB equipment