USB Bus is a typical hot swap bus standard , Because of its excellent performance, it has almost become the standard configuration in the current large and small devices .
USB The driver of the system can be divided into 3 class :SoC Of USB The driver of the controller , Host side USB Device drivers , On the device USB Gadget drive , Usually , about USB This standardized device , The kernel has written the driver of the host controller , On the device Gadget Drivers usually only run firmware programs, not based on Linux, therefore The driver engineer's main job is to write the host side USB Device drivers .

USB Subsystem framework

The figure below shows Linux in USB The framework of the subsystem , and i2c equally ,USB The subsystem can also be divided into three layers :** Device driver layer --USB The core -- Controller driver layer *

As a hot swap bus , USB The biggest difference from non hot swap bus is that the bus can not know the information of the device in advance and when the device is inserted or pulled out , So you can't use any form to write the device information to the kernel in advance .
In order to solve the problem of device identification caused by hot swap ,USB The bus obtains an access to the bus by enumeration USB Device information for the device —— One by device->config->interface->endpoint Step by step The equipment , Based on the idea of separation ,USB In the subsystem, a set of structure is designed to describe the device information of these dimensions , by comparison ,i2c Just one bus i2c_client Can describe a device .

USB All communication on the bus is initiated by the host , So essentially ,USB It's all done by polling .USB The bus will use polling to continuously detect whether there are devices connected to the bus , If there is a device connected to the corresponding D+D- There will be a level change . Then the bus will follow USB The protocol specified communicates with the device , The device will send the device information stored in itself to the host in turn , The host sends this information according to 4 Layer models are organized . Report to the kernel , Kernel USB The subsystem then matches the corresponding driver ,USB Device drivers are for interface This level of information

As a highly standardized device , although USB It's very complicated , But the kernel has done a lot for us , The following common device drivers have been implemented in the kernel . A lot of times , The difficulty of driving doesn't depend on the complexity of the device , It's about Standardization

  • Audio devices
  • Communication equipment
  • HID Equipment class
  • Display device class
  • Mass storage device class
  • Power supply equipment
  • Printing device class
  • Hub device class

A brief introduction to the core structure and methods

Core structure

Based on the idea of separation ,USB The subsystem also provides a description of USB The structure of the device , It's just based on USB agreement , A complete description of USB Device information needs 9 Structures , In these structures , front 4 One is used to describe a USB Hardware information of the device , That is, the information of the device itself , This information is written to the device eeprom Of , In any USB Everything you see in the mainframe is the same , This information can be used lsusb -v Order to see ; after 5 A description of a USB Software information for the device , That is, in addition to hardware information ,Linux In order to manage a USB The device also encapsulates some information , yes OS-specific Information about ; USB The relationship between hardware information and software information is similar to hardware interrupt and kernel interrupt in interrupt subsystem , It's just a little more complicated .

  • usb_device_descriptor To describe a USB The equipment device Information

  • usb_config_descriptor To describe a device Of config Information

  • usb_interface_descriptor To describe a config Of interface Information

  • usb_endpoint_descriptor To describe a interface Of endpoint Information

  • usb_device Describe a USB Of device Software information for , Include usb_device_descriptor

  • urb_host_config Describe a USB equipment config Software information for , Include usb_config_descriptor

  • usb_interface Describe an interface information

  • usb_host_interface Describe a interface Setting information of , Include usb_interface_descriptor, We write drivers for this level

  • usb_host_endpoint Describe a interdace Of endpoint Information , Include usb_endpoint_descriptor, This is a USB Minimum unit of communication , We read and write a device for a endpoint

  • usb_driver Describe a usb Device drivers , It's just yes USB The core structure of device driven development

  • usb_driver_id To identify a usb equipment , In fact, for example id_table Namely usb_driver A domain in , because usb Bus describes the complexity of a device , There are many ways to construct such an object

  • urb (usb request block) Is in USB Data carrier in the process of communication , amount to i2c In the subsystem i2c_msg, In the network device driver sk_buff

  • usb_hcd Describe a SoC Medium USB Controller drive

The core approach

  • usb_fill_int_urb It's registration urb Of API, As a whole USB The core of communication is data encapsulation

The core structure and methods are described in detail

The first thing to say is that 9 A structure describing device information , The hardware information is independent of each other , Separate use These structures are in the kernel "include/uapi/linux/usbch9.h" Defined , I won't post code

usb_device_descriptor

//include/uapi/linux/usbch9.h
258 struct usb_device_descriptor { 
259         __u8  bLength;
260         __u8  bDescriptorType;
262         __le16 bcdUSB;
263         __u8  bDeviceClass;
264         __u8  bDeviceSubClass;
265         __u8  bDeviceProtocol;
266         __u8  bMaxPacketSize0;
267         __le16 idVendor;
268         __le16 idProduct;
269         __le16 bcdDevice;
270         __u8  iManufacturer;
271         __u8  iProduct;
272         __u8  iSerialNumber;
273         __u8  bNumConfigurations;
274 } __attribute__ ((packed));

struct usb_device_descriptor
--263--> Equipment category
--264--> Device subclasses
--265--> Communication protocol
--267--> seller
--268--> product ID
--272--> Serial number

usb_config_descriptor

//include/uapi/linux/usbch9.h
314 struct usb_config_descriptor {
315         __u8  bLength;
316         __u8  bDescriptorType;
317 
318         __le16 wTotalLength;
319         __u8  bNumInterfaces;
320         __u8  bConfigurationValue;
321         __u8  iConfiguration;
322         __u8  bmAttributes;
323         __u8  bMaxPower;
324 } __attribute__ ((packed));

usb_interface_descriptor

//include/uapi/linux/usbch9.h
351 struct usb_interface_descriptor {
352         __u8  bLength;
353         __u8  bDescriptorType;
354 
355         __u8  bInterfaceNumber;
356         __u8  bAlternateSetting;
357         __u8  bNumEndpoints;
358         __u8  bInterfaceClass;
359         __u8  bInterfaceSubClass;
360         __u8  bInterfaceProtocol;
361         __u8  iInterface;
362 } __attribute__ ((packed));

usb_endpoint_descriptor

//include/uapi/linux/usbch9.h
369 struct usb_endpoint_descriptor {
370         __u8  bLength;
371         __u8  bDescriptorType;
372 
373         __u8  bEndpointAddress;
374         __u8  bmAttributes;
375         __le16 wMaxPacketSize;
376         __u8  bInterval;
377 
378         /* NOTE:  these two are _only_ in audio endpoints. */
379         /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
380         __u8  bRefresh;
381         __u8  bSynchAddress;
382 } __attribute__ ((packed));

usb_device

//include/linux/usb.h
 510 struct usb_device {
 511         int             devnum;
 512         char            devpath[16];
 513         u32             route;
 522         struct usb_device *parent;
 523         struct usb_bus *bus;
 524         struct usb_host_endpoint ep0;
 526         struct device dev;
 528         struct usb_device_descriptor descriptor;
 529         struct usb_host_bos *bos;
 530         struct usb_host_config *config;
 532         struct usb_host_config *actconfig;
 557         char *product;
 558         char *manufacturer;
 559         char *serial;
 561         struct list_head filelist;
 563         int maxchild;
 568         unsigned long active_duration;
 569 
 584 };

struct usb_device
--522--> The parent device of this device , It's usually usb The last node equipment of the tower structure
--523--> The bus it belongs to is usb Bus
--526--> This is a device, Will be linked to the corresponding list
--528--> This software device The architecture contains the hardware device object
--530--> Software device All the software you have config object , Corresponding hardware device All the hardware you have config
--531--> The present , This device In use config
--557--> Product name
--558--> Product manufacturer
--559--> product ID
--561--> On this device usbfs The linked list node of the file
--563--> The maximum number of sub devices

urb_host_config

//include/linux/usb.h
 275 struct usb_host_config {
 276         struct usb_config_descriptor    desc;
 278         char *string;           /* iConfiguration string, if present */
 282         struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
 286         struct usb_interface *interface[USB_MAXINTERFACES];
 290         struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
 292         unsigned char *extra;   /* Extra descriptors */
 293         int extralen;
 294 };

struct usb_host_config
--276--> Software config Object contains the hardware config object
--278-->config The name of
--282--> This config It's related to Interface Association Descriptor
--283--> This config The next level of software associated with the top interface Array ,

usb_interface

Here's a description that directly matches the driver

 160 struct usb_interface {
 163         struct usb_host_interface *altsetting;
 165         struct usb_host_interface *cur_altsetting;    
 167         unsigned num_altsetting;        /* number of alternate settings */
 171         struct usb_interface_assoc_descriptor *intf_assoc;
 173         int minor;           
 175         enum usb_interface_condition condition;         /* state of binding */
 176         unsigned sysfs_files_created:1; /* the sysfs attributes exist */
 177         unsigned ep_devs_created:1;     /* endpoint "devices" exist */
 178         unsigned unregistering:1;       /* unregistration is in progress */
 179         unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
 180         unsigned needs_altsetting0:1;   /* switch to altsetting 0 is pending */
 181         unsigned needs_binding:1;       /* needs delayed unbind/rebind */
 182         unsigned reset_running:1;
 183         unsigned resetting_device:1;    /* true: bandwidth alloc after reset */
 185         struct device dev;              /* interface specific device info */
 186         struct device *usb_dev;
 187         atomic_t pm_usage_cnt;          /* usage counter for autosuspend */
 188         struct work_struct reset_ws;    /* for resets in atomic context */
 189 };

struct usb_interface
--163--> This interface All of the setting
--164--> This interface Currently in use setting
--165--> If this interface Bound with a driver that uses the master device number , This domain is interface The secondary device number of ; Otherwise, it doesn't work . The driver should be in probe Set this parameter in

usb_host_interface

  77 struct usb_host_interface {
  78         struct usb_interface_descriptor desc;
  80         int extralen;
  81         unsigned char *extra;   /* Extra descriptors */
  86         struct usb_host_endpoint *endpoint;
  88         char *string;           /* iInterface string, if present */
  89 };

struct usb_host_interface
--78--> This interface Corresponding hardware interface object
--86--> Have Description Software endpoint The information of usb_host_endpoint Array
--88-->interface name

usb_host_endpoint

endpoint yes USB equipment IO The basic unit of

  64 struct usb_host_endpoint {
  65         struct usb_endpoint_descriptor          desc;
  66         struct usb_ss_ep_comp_descriptor        ss_ep_comp;
  67         struct list_head                urb_list;
  68         void                            *hcpriv;
  69         struct ep_device                *ep_dev;        /* For sysfs info */
  71         unsigned char *extra;   /* Extra descriptors */
  72         int extralen;
  73         int enabled;
  74 };

struct usb_host_endpoint
--65--> This usb_host_endpoint Corresponding hardware endpoint Information
--67--> Read and write this endpoint Of usb Linked list , from usb Core layer (drivers/usb/core/file.c) maintain
--73--> This endpoint Whether it is enabled or not

Every hardware information object is contained in a software information object , And software information objects are included layer by layer , So although the drive is based on interface Description of the , But we can use "list_entry()" It's easy to find up config and device describe , It's easy to find the domain using it endpoint describe , this 9 The structure relationship of each device is shown in the figure below :

urb

And platform or i2c The difference is ,usb The bus does not allow the device to initiate communication , So as a device driver , Only what will be needed " material " Ready to submit to the usb Controller drive , Let the controller drive with these " material " To poll the device and bring the response back to . these " material " Namely urb And the corresponding registration parameters . When usb_driver and usb After the device is matched , We are going to have a urb Object passing usb_fill_int_urb()/_bulk_/_control_ Register to the bus , And pass at the right time usb_submit_urb Send this to the controller driver urb Object commands , After the bus controller driver receives our send command , We will continue to send requests to the matching devices according to the cycle set when we register , If the subdevice responds to our request , The controller driver will register us urb The object is filled in , And call back our registration function .
For mass storage USB equipment , If you want the device to work properly , Besides these processes , Also need to add to the cache management , In this part, we will talk about .

usb_fill_int_urb

Initialize and register an interrupt urb. The function prototype is as follows :

static inline void usb_fill_int_urb(struct urb *urb,struct usb_device *dev,unsigned int pipe,
                                    void *transfer_buffer,int buffer_length,usb_complete_t complete_fn,void *context,int interval)

This function has many parameters , urb It means we want to register urb object ; dev Express this urb Object's destination device ; pipe Represents a read-write pipeline , Use usb_sndintpipe() and usb_rcvintpipe() obtain ; transfer_buffer Represents the first address of the buffer to pass data ;buffer_length Represents the buffer length ;complete_fn If we send out urb There was a response , Just call back this function ; context Is the parameter of the callback function , User defined , amount to request_irq Medium void *dev; interval It's the transmission cycle , The core layer will use this parameter as a cycle to pass usb The controller drives the polling device ,

usb_alloc()

urb and xxx equally , To allocate functions with the kernel , It will do some initialization work

usb_fill_bulk_urb

Initialize and register a mass storage urb

usb_fill_control_urb

Initialize and register a control urb

usb_submit_urb

Notify the kernel to send urb object

usb_driver

1048 struct usb_driver {
1049         const char *name;
1051         int (*probe) (struct usb_interface *intf,
1052                       const struct usb_device_id *id);
1054         void (*disconnect) (struct usb_interface *intf);
1056         int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
1057                         void *buf);
1059         int (*suspend) (struct usb_interface *intf, pm_message_t message);
1060         int (*resume) (struct usb_interface *intf);
1061         int (*reset_resume)(struct usb_interface *intf);
1063         int (*pre_reset)(struct usb_interface *intf);
1064         int (*post_reset)(struct usb_interface *intf);
1066         const struct usb_device_id *id_table;
1068         struct usb_dynids dynids;
1069         struct usbdrv_wrap drvwrap;
1070         unsigned int no_dynamic_id:1;
1071         unsigned int supports_autosuspend:1;
1072         unsigned int disable_hub_initiated_lpm:1;
1073         unsigned int soft_unbind:1;
1074 };

struct usb_driver
--1049-->usb Name of equipment
--1051--> Probe function , When usb_driver Of id_table and usb It will be executed when the device information matches , The main job is to apply for resources , initialization , Provide the interface
--1054--> It is executed when the driver module is unloaded or the device is pulled out
--1066--> The function is still the same as matching , It's just usb The device information of is provided by 4 There are three dimensions to describe , therefore id_table There's a variety of things that can be filled in

usb_register

Sign up for a usb_driver To kernel

usb_deregister

Cancel one usb_driver

id_table

The following macro constructs are provided usb_device_id object , In fact, that's right usb_device_id Different fields in are populated , Because of the differences in equipment , Different USB The device will report different device information , But no matter what information is reported , It must be an encapsulation of the following macros . You can use it first lsusb -v View the hardware information of the device , And then according to the hardware information it provides id_table Write the corresponding driver

USB_DEVICE

 811 #define USB_DEVICE(vend, prod) \
 812         .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
 813         .idVendor = (vend), \
 814         .idProduct = (prod)

USB_DEVICE_VER

 825 #define USB_DEVICE_VER(vend, prod, lo, hi) \
 826         .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
 827         .idVendor = (vend), \
 828         .idProduct = (prod), \
 829         .bcdDevice_lo = (lo), \
 830         .bcdDevice_hi = (hi)

USB_DEVICE_INTERFACE_CLASS

 841 #define USB_DEVICE_INTERFACE_CLASS(vend, prod, cl) \
 842         .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
 843                        USB_DEVICE_ID_MATCH_INT_CLASS, \
 844         .idVendor = (vend), \
 845         .idProduct = (prod), \
 846         .bInterfaceClass = (cl)

USB_DEVICE_INTERFACE_PROTOCOL

 857 #define USB_DEVICE_INTERFACE_PROTOCOL(vend, prod, pr) \
 858         .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
 859                        USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
 860         .idVendor = (vend), \
 861         .idProduct = (prod), \
 862         .bInterfaceProtocol = (pr)

USB_DEVICE_INTERFACE_NUMBER

 873 #define USB_DEVICE_INTERFACE_NUMBER(vend, prod, num) \
 874         .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
 875                        USB_DEVICE_ID_MATCH_INT_NUMBER, \
 876         .idVendor = (vend), \
 877         .idProduct = (prod), \
 878         .bInterfaceNumber = (num)

USB_DEVICE_INFO

 889 #define USB_DEVICE_INFO(cl, sc, pr) \
 890         .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, \
 891         .bDeviceClass = (cl), \
 892         .bDeviceSubClass = (sc), \
 893         .bDeviceProtocol = (pr)
 894

USB_INTERFACE_INFO

 904 #define USB_INTERFACE_INFO(cl, sc, pr) \   
 905         .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \
 906         .bInterfaceClass = (cl), \
 907         .bInterfaceSubClass = (sc), \
 908         .bInterfaceProtocol = (pr)

USB_DEVICE_AND_INTERFACE_INFO

 924 #define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, cl, sc, pr) \
 925         .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
 926                 | USB_DEVICE_ID_MATCH_DEVICE, \
 927         .idVendor = (vend), \
 928         .idProduct = (prod), \
 929         .bInterfaceClass = (cl), \
 930         .bInterfaceSubClass = (sc), \
 931         .bInterfaceProtocol = (pr)

USB_VENDOR_AND_INTERFACE_INFO

 946 #define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \
 947         .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
 948                 | USB_DEVICE_ID_MATCH_VENDOR, \
 949         .idVendor = (vend), \
 950         .bInterfaceClass = (cl), \
 951         .bInterfaceSubClass = (sc), \
 952         .bInterfaceProtocol = (pr)
 953

id_table example

Here's the kernel "drdrivers/hid/usbhid/usbmouse.c" Medium ib_table How to fill in , It can be seen that , Not only does the construction use macros , because USB The mouse is standard equipment , Its property values are also identified by standard macros

230 static struct usb_device_id usb_mouse_id_table [] = {
231         { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
232                 USB_INTERFACE_PROTOCOL_MOUSE) },
233         { }     /* Terminating entry */
234 };

USB Mouse instance

kernel "drivers/hid/usbhid/usbmouse.c" It's just one. usb Mouse drive , Here I have written one according to my own understanding , It's using "usb Interrupt device driver +input Subsystem " frame

#define BUF_SIZE 8
MODULE_LICENSE("GPL");
// object-oriented ,  Encapsulate classes according to requirements
struct xj_mouse {
char name[128];
struct usb_device *dev;
struct urb *msg;
struct input_dev *input;
signed char *buf;
};
struct xj_mouse *mouse;
static int usb_mouse_open(struct input_dev *dev)
{
struct xj_mouse *mouse = input_get_drvdata(dev);
mouse->msg->dev = mouse->dev;
if (usb_submit_urb(mouse->msg, GFP_KERNEL))
return -EIO;
return 0;
}
static void usb_mouse_close(struct input_dev *dev)
{
struct xj_mouse *mouse = input_get_drvdata(dev);
usb_kill_urb(mouse->msg);
}
static int init_input(struct usb_interface * intf)
{
int err=0;
struct usb_device *dev = mouse->dev;
struct input_dev *input_dev = mouse->input;
input_dev->name = mouse->name;
usb_to_input_id(dev, &input_dev->id);
input_dev->dev.parent = &intf->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |BIT_MASK(BTN_EXTRA);
input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
input_set_drvdata(input_dev, mouse);
input_dev->open = usb_mouse_open;
input_dev->close = usb_mouse_close;
err = input_register_device(mouse->input);
return 0;
}
static void completion(struct urb * msg)
{
int status;
signed char *buf = mouse->buf;
struct input_dev *input = mouse->input;
input_report_key(input, BTN_LEFT,   buf[0] & 0x01);
input_report_key(input, BTN_RIGHT,  buf[0] & 0x02);
input_report_key(input, BTN_MIDDLE, buf[0] & 0x04);
input_report_key(input, BTN_SIDE,   buf[0] & 0x08);
input_report_key(input, BTN_EXTRA,  buf[0] & 0x10);
input_report_rel(input, REL_X,     buf[1]);
input_report_rel(input, REL_Y,     buf[2]);
input_report_rel(input, REL_WHEEL, buf[3]);
input_sync(input);
status = usb_submit_urb (msg, GFP_ATOMIC);
}
static int probe(struct usb_interface *intf, const struct usb_device_id *id)
{
int pipe;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
// Distribute 、 Initialize the personality structure
mouse = (struct xj_mouse *)kzalloc(sizeof(struct xj_mouse),GFP_KERNEL);
mouse->dev=interface_to_usbdev(intf);
mouse->msg=usb_alloc_urb(0,GFP_KERNEL);
mouse->input=input_allocate_device();
mouse->buf=(void *)kzalloc(BUF_SIZE,GFP_KERNEL);
if (mouse->dev->manufacturer){
strlcpy(mouse->name, mouse->dev->manufacturer, sizeof(mouse->name));
mouse->input->name = mouse->name;
}
// initialization input equipment
init_input(intf);
// obtain pipe
interface=intf->cur_altsetting;
endpoint=&interface->endpoint[0].desc;
/*  Use dev and endpoint Get the endpoint address  */
pipe = usb_rcvintpipe(mouse->dev,endpoint->bEndpointAddress);
// register usb drive
usb_fill_int_urb(mouse->msg,mouse->dev,pipe,mouse->buf,BUF_SIZE,completion,mouse->msg,endpoint->bInterval);
return 0;
}
static void disconnect(struct usb_interface *intf)
{
struct xj_mouse *tmp_mouse = usb_get_intfdata (intf);
usb_set_intfdata(intf, NULL);
if (tmp_mouse) {
usb_kill_urb(tmp_mouse->msg);
input_unregister_device(tmp_mouse->input);
usb_free_urb(tmp_mouse->msg);
kfree(tmp_mouse->buf);
kfree(tmp_mouse);
}
}
static struct usb_device_id id_table [] ={
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,USB_INTERFACE_PROTOCOL_MOUSE) },
{},
};
struct usb_driver mouse_drv = {
.name = "xj_mouse_drv",
.probe = probe,
.disconnect = disconnect,
.id_table = id_table,
};
module_usb_driver(mouse_drv);