Linux usb subsystem (1) _Write a usb mouse driver

Keywords: Linux network Attribute

USB bus is a typical hot-swap bus standard. Because of its excellent performance, it has almost become the standard of current large and small devices.
USB drivers can be divided into three categories: the driver of SoC's USB controller, the driver of host USB device and the driver of USB Gadget on device. Usually, for the standardized device like USB, the driver of host controller has been written by the kernel. The driver of Gadget on device usually only runs firmware program instead of Linux, so the main task of driver engineer is to write host. USB device driver.

USB Subsystem Framework

The following chart shows the framework of the USB subsystem in Linux. Like i2c, the USB subsystem can be divided into three layers: ** Device Driver Layer - USB Core - Controller Driver Layer*

As a hot-swap bus, the biggest difference between USB and non-hot-swap bus is that the bus can not know the information of the device beforehand and when the device is inserted or pulled out, so it can not use any form to write the device information into the kernel beforehand.
In order to solve the problem of device identification caused by hot plug-in, USB bus acquires the device information of a USB device connected to the bus by enumeration, a device described step by step by step by device - > config - > interface - > endpoint. Based on the idea of separation, a set of structure is designed in the USB subsystem to describe the device information of these dimensions. In contrast, I2C bus only needs An i2c_client can describe a device.

All communication on the USB bus is initiated by the host, so in essence, USB is conducted by polling. USB bus will use polling method to continuously detect whether there is device access on the bus, and if there is device access to the corresponding D+D - there will be level changes. Then the bus will communicate with the device according to the Protocol stipulated by USB. The device will send the device information stored in itself to the host in turn. The host will organize the information according to the four-tier model. Reporting to the kernel, the USB subsystem in the kernel matches the corresponding driver. The USB device driver is oriented to the level of interface information.

As a highly standardized device, although USB itself is very complex, the kernel has done a lot of work for us. The following common device drivers have been implemented in the kernel. In many cases, the difficulty of driving depends not on the complexity of the device, but on the degree of standardization.

  • Audio equipment class
  • Communications Equipment Class
  • HID device class
  • Display Device Class
  • mass storage class
  • Power supply equipment category
  • Printing Equipment Class
  • Hub Equipment Class

A Brief Introduction to Core Structure and Method

Core structure

Based on the idea of separation, the USB subsystem also provides a structure for describing a USB device. However, based on the USB protocol, a complete description of a USB device information requires nine structures. Among these structures, the first four are used to describe the hardware information of a USB device, i.e. the information of the device itself, which is written to the device eeprom, and can be seen in any USB host. Information can be viewed by using lsusb-v command; the last five software information describing a USB device, that is, besides hardware information, Linux encapsulates some information in order to manage a USB device, which is OS-specific information; the relationship between hardware information and software information of USB device is similar to hardware interrupt and kernel interrupt in interrupt subsystem, but more complex.

  • usb_device_descriptor describes device information of a USB device
  • usb_config_descriptor describes the config information of a device
  • usb_interface_descriptor describes the interface information of a config
  • usb_endpoint_descriptor describes the endpoint information of an interface

  • Usb_device describes the software information of a USB device, including usb_device_descriptor
  • urb_host_config describes the software information of a USB device config, including usb_config_descriptor
  • usb_interface describes an interface information
  • usb_host_interface describes the settings of an interface, including usb_interface_descriptor, for which we write drivers
  • usb_host_endpoint describes the endpoint information of an interface, including usb_endpoint_descriptor, which is the smallest unit of USB communication. We read and write a device for an endpoint.

  • usb_driver describes a USB device driver, which is the core structure of USB device driver development.
  • usb_driver_id is used to identify a USB device. Its instance id_table is a domain of usb_driver. Because of the complexity of describing a device in USB bus, there are many ways to construct such an object.
  • urb (usb request block) is the data carrier in the process of USB communication, which is equivalent to i2c_msg in I2C subsystem and sk_buff in network device driver.
  • usb_hcd Describes a USB Controller Driver in SoC

Core method

  • usb_fill_int_urb is the API of registering urb and the core data encapsulation of the whole USB communication.

Detailed description of core structure and methodology

First of all, the nine structures describing device information, in which the hardware information is independent, are defined in the kernel "include/uapi/linux/usbch9.h", so I will not paste the 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 sub class
--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, Usually is usb The Last Node Equipment of Tower Structure
--523-->The bus that belongs to is usb Bus
--526-->This is a device, It will be linked to the corresponding linked list.
--528-->This software device Hardware included in the structure device object
--530-->Software device All software owned config object, Corresponding hardware device All the hardware you own config
--531-->The moment, this device In use config
--557-->Product name
--558-->Product Manufacturer
--559-->product ID
--561-->Opened on this device usbfs Link List Node of File
--563-->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 hardware config object
--278-->config Name
--282-->this config Associated Interface Association Descriptor
--283-->this config Upper-related lower-level software interface array,

usb_interface

Here's a description that matches the driver directly.

 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 included setting
--164-->this interface Currently in use setting
--165-->If this interface Binding to a driver that uses the master device number, This field is interface Secondary Equipment Number of ___________; On the contrary, it's useless.. 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-->Owned Description Software endpoint Information usb_host_endpoint array
--88-->interface Name

usb_host_endpoint

endpoint is the basic unit of USB device IO

  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 Is it enabled?

Every hardware information object is included in a software information object, and the software information object is included layer by layer. So although the driver is described by interface, we can easily find config and device descriptions upward by using "list_entry()", and endpoint descriptions can be easily found by using the domain. The structure of the nine descriptive devices is shown in the following figure:

urb

Unlike platform s or i2c buses, USB buses do not allow devices to initiate communication, so as device drivers, only the required "materials" are ready to be submitted to the USB controller driver via the core layer, allowing the controller driver to poll the device with these "materials" and bring the response back. These "materials" are urbs and corresponding registration parameters. When the usb_driver matches the USB device, we prepare a urb object to register to the bus through usb_fill_int_urb()/_bulk_/_control_and send the command of sending the urb object to the controller driver through usb_submit_urb at the appropriate time. After the bus controller driver receives our sending command, it will continuously send the matching device according to the cycle set at the time of registration. Send the request, if the sub-device responds to our request, the controller driver fills in our registered urb object and calls back our registration function.
For mass storage USB devices, if the device is to work properly, in addition to these processes, also need to add the management of the buffer, which we will talk about in the next part.

usb_fill_int_urb

Initialize and register an interrupt urb. The prototype of the function 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 represents the urb object we want to register, dev represents the destination device of the urb object, pipe represents the read and write pipeline, which is obtained by usb_sndintpipe() and usb_rcvintpipe(), transfer_buffer represents the first address of the buffer for transferring data, buffer_length indicates the length of the buffer, complete_fn indicates that if the urb we send out responds, we call back the function. context is a parameter of the callback function, which is defined by the user and is equivalent to void * dev in request_irq.

usb_alloc()

Like xxx, urb uses the kernel allocation function, which does 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 objects

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-->Detection function, When usb_driver Of id_table and usb When the device information matches, it will be executed., The main job is to apply for resources., Initialization, Provide interface
--1054-->When the driver module is unloaded or the device is pulled out, it will be executed.
--1066-->Functions are still matched, just usb Equipment information is described by four dimensions, therefore id_table The content that can be filled in is also varied.

usb_register

Register a usb_driver to the kernel

usb_deregister

Log off a usb_driver

id_table

The kernel provides the following macros to construct a usb_device_id object. In fact, it fills in different domains of usb_device_id. Because of the differences of devices, different USB devices will report different device information, but whatever information they report, it must belong to the encapsulation of the following macros. You can use lsusb-v to view the hardware information of the device first, and then according to the information they provide. Hardware information determines id_table to 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 instance

The following is the ib_table filling mode in the kernel "drdrivers/hid/usbhid/usbmouse.c". It can be seen that not only macros are used in the construction, but also the attribute values of USB mouse are identified by standard macros because it is a standard device.

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 Example

The kernel "drivers/hid/usb hid/usbmouse.c" is a driver of USB mouse. Here I write one according to my own understanding. It adopts the framework of "usb interrupt device driver+input subsystem".

#define BUF_SIZE 8
MODULE_LICENSE("GPL");

//Object-oriented, encapsulating 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;
    //Distribution and Initialization of 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;
    }

    //Initialize the input device
    init_input(intf);
    //Get pipe
    interface=intf->cur_altsetting;
    endpoint=&interface->endpoint[0].desc;
    /* Use dev and endpoint to get endpoint addresses */
    pipe = usb_rcvintpipe(mouse->dev,endpoint->bEndpointAddress);
    //Register usb driver
    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);

Posted by joenjeru on Sun, 14 Apr 2019 12:57:32 -0700