USB bus leads to two important linked lists! A usb bus leads to two important linked lists: A linked list of USB devices and a linked list of USB drivers. The device linked list contains USB devices in various systems and all interfaces of these devices. The driver linked list contains USB device drivers and USB drivers ). What is the difference between a USB device driver and a USB driver? The USB device driver includes some common features of the USB device and will match all USB devices. In USB core, struct usb_device_driver usb_generic_driver is defined. Usb_generic_driver is the only device driver object in the USB subsystem. The USB driver matches the interface, and the interface is a set of endpoints for specific functions. How is a device added to a device linked list? After the USB controller is inserted into the device, the USB core registers the device in the system and adds it to the USB device linked list. How is the USB device driver added to the drive linked list? When the system starts to register a USB core, the USB device driver will be registered and added to the driver chain table. How is the interface added to the device linked list? After the USB driver matches the USB device, USB core configures the device. After analyzing the structure of the device, all interfaces of the device are added to the device linked list. For example, if the mouse device has an interface, after USB core is configured for the mouse device, the interface is added to the device linked list. How does a USB driver be added to the drive linked list? When each USB driver is registered, the USB driver is added to the driver linked list. For example, for the mouse driver, the usb_mouse_init function registers the mouse driver to the USB core through usb_register (& usb_mouse_driver) and adds it to the driver chain table. Usb_mouse_driver is the structure that describes the mouse driver. After the configured status (configured status), when the device and interface of the mouse are added to the device linked list, and the mouse driver is also added to the driver list, the system enters a state called configured. To reach the configured status, it will go through a complicated process. USB core is dedicated to USB devices with no regrets. In this process, the system will create a description of the device, configuration, interface, setting, and endpoint of the device, they are described by the usb_device, usb_configuration, usb_interface, usb_host_interface, and usb_host_endpoint struct. After the device reaches the configured status, you must first pair the USB driver with the corresponding interface. For the mouse device, it is the pairing of the mouse driver and the interface in the mouse. USB core calls the usb_device_match function. By comparing the interface information in the device and the id_table in the USB driver, it preliminarily determines whether the USB driver matches the interface. After this level, USB core considers this device to be the responsibility of this driver. However, this step alone is not enough. Next, the probe function in the USB driver will be called to further check the corresponding interface. If the driver is indeed suitable for device interfaces, initialize the device and assign urb for data transmission. When the mouse device opens in the user space, it will submit the urb request block constructed by the probe function, and urb will start to be busy for data transmission. The urb request block is like a "bag" for loading. The USB driver submits the "Empty bag" to the USB core and then delivers it to the master controller, the master controller puts the data in this "bag" and then returns the "bag" filled with data to the USB driver through the USB core. This completes a data transfer. The following is the fully annotated mouse driver code usbmouse. cview plaincopy to clipboardprint? /** $ ID: usbmouse. c, V 1.15 2001/12/27 10:37:41 vojtech exp $ ** copyright (c) 1999-2001 vojtech Pavlik ** USB hidbp mouse support */# include <Linux/kernel. h> # include <Linux/slab. h> # include <Linux/module. h> # include <Linux/init. h> # include <Linux/USB/input. h> # include <Linux/hid. h>/** version information */# define driver_version "v1.6" # define driver_author "vojtech Pavlik <vojtech@ucw.cz>" # Define driver_desc "USB hid Boot Protocol mouse driver" # define driver_license "GPL" module_author (modules); module_description (driver_desc); module_license (driver_license);/** mouse structure, used to describe the mouse device. */Struct usb_mouse {/* Name of the mouse device, including the manufacturer, product category, product, and other information */Char name [128]; /* Device node name */Char phys [64];/* USB mouse is a USB device, a USB device structure must be embedded to describe its USB properties */struct usb_device * usbdev;/* the USB mouse is also an input device, an input device struct must be embedded to describe the properties of the input device */struct input_dev * dev;/* urb request packet struct, used to transmit data */struct urb * IRQ; /* address for normal transmission */signed Char * data;/* address for DMA transmission */dma_addr_t data_dma;};/** urb callback function, after urb is submitted, the urb callback function is called. * This function is used as the form parameter of the usb_fill_int_urb function and is the callback function developed for the constructed urb. */Static void usb_mouse_irq (struct urb * urb) {/* The context pointer in urb is used to save some data for the USB driver. For example, the callback function does not pass the address pointer of the memory allocated for the mouse struct in probe, but the data in the memory region needs to be used, the context pointer has helped a lot! When urb is filled, point the context pointer to the mouse struct data area. Here, create a local mouse pointer pointing to the memory applied for the mouse in the probe function, the memory stores very important data. After the urb is submitted to HC through USB core, if the result is normal, the mouse-> data points to the memory area, saving the mouse buttons and moving coordinates, the system relies on this information to respond to mouse behavior. The embedded Dev pointer in the mouse points to the memory area of input_dev */struct usb_mouse * mouse = urb-> context; signed Char * Data = mouse-> data; struct input_dev * Dev = mouse-> dev; int status;/The value of ** status is 0, indicating that urb has successfully returned the result. jump out of the loop and report the mouse event to the input subsystem. * The econnreset error message indicates that urb is sent to unlink by the usb_unlink_urb function, and the enoent error message indicates that urb is killed by the * usb_kill_urb function. Usb_kill_urb indicates that the life cycle of urb is completely terminated, while usb_unlink_urb * indicates that urb is stopped. This function will return to the callback function after urb is completely terminated. This is useful when you run the interrupt handler or wait for a spin lock *. In both cases, you cannot sleep, waiting for an urb to stop completely is likely to cause sleep. * Eshudown indicates that the USB master controller driver has encountered a serious error, or the device is pulled out immediately after the urb is submitted. * If you encounter any of the preceding three errors, you will apply for re-transmission of urb. */Switch (urb-> Status) {Case 0:/* success */break; Case-econnreset:/* unlink */case-enoent: case-eshudown: return; /*-epipe: shocould clear the halt */Default:/* Error */goto resubmit;}/** report the mouse event to the input subsystem for response. * The 0th bytes of the data array: Bit 0, 1, 2, 3, and 4 indicate the press conditions of the Left, right, middle, side, and extra keys, respectively; * 1st bytes in the data array: indicates the horizontal movement of the mouse; * 2nd bytes in the data array: indicates the vertical movement of the mouse; * 3rd bytes in the data array: rel_wheel shift. */Input_report_key (Dev, btn_left, data [0] & 0x01); input_report_key (Dev, btn_right, data [0] & 0x02); input_report_key (Dev, btn_middle, data [0] & 0x04); input_report_key (Dev, btn_side, data [0] & 0x08); input_report_key (Dev, btn_extra, data [0] & 0x10); input_report_rel (Dev, rel_x, data [1]); input_report_rel (Dev, rel_y, data [2]); input_report_rel (Dev, rel_wheel, data [3]);/** it is used for event synchronization. The preceding lines are complete mouse events, including buttons, absolute coordinates, and scroll wheel information, the input sub-* system uses this synchronous signal to differentiate each complete event report in multiple complete event reports. The following figure shows the rotation wheel information. * The coordinate movement information of buttons. ev_syc | the coordinate displacement information of buttons. ev_syc... */input_sync (Dev);/** the system needs to periodically obtain the mouse event information. Therefore, the urb request block is submitted again at the end of the urb callback function, in this way, * the new callback function will be called again and again. * In the callback function, the submitted urb must be of the gfp_atomic priority. Because the urb callback function runs in the interrupt context, you may need to apply for memory and maintain the semaphore during the process of submitting the * urb, these operations may cause the USB core to sleep, and all the sleeping lines * are not allowed. */Resubmit: Status = usb_submit_urb (urb, gfp_atomic); If (Status) Err ("can't resubmit intr, % s-% S/input0, status % d ", mouse-> usbdev-> bus-> bus_name, mouse-> usbdev-> devpath, status);}/** when the mouse device is turned on, start submitting the urb built in the probe function and enter the urb cycle. */Static int usb_mouse_open (struct input_dev * Dev) {struct usb_mouse * mouse = Dev-> private; mouse-> IRQ-> Dev = mouse-> usbdev; if (usb_submit_urb (mouse-> IRQ, gfp_kernel) Return-EIO; return 0 ;}/ ** when the mouse device is disabled, the urb lifecycle ends. */Static void usb_mouse_close (struct input_dev * Dev) {struct usb_mouse * mouse = Dev-> private; usb_kill_urb (mouse-> IRQ );} /** driver's probe function */static int usb_mouse_probe (struct usb_interface * INTF, const struct usb_device_id * ID) {/** the interface struct is included in the device struct, interface_to_usbdev is the device struct that is obtained through the interface struct. * Usb_host_interface is the struct used to describe interface settings. It is embedded in the usb_interface interface structure. * Usb_endpoint_descriptor is an endpoint descriptor structure embedded in the endpoint structure usb_host_endpoint, And the endpoint * structure is embedded in the interface setting structure. */Struct usb_device * Dev = interface_to_usbdev (INTF); struct usb_host_interface * interface; struct destination * endpoint; struct usb_mouse * mouse; struct input_dev * input_dev; int pipe, maxp; interface = INTF-> cur_altsetting;/* the mouse has only one in endpoint of the interrupt type. If (interface-> DESC. bnumendpoints! = 1) Return-enodev; endpoint = & Interface-> endpoint [0]. DESC; If (! Usb_endpoint_is_int_in (endpoint) Return-enodev;/** return the maximum data packet that can be transmitted by the corresponding endpoint. the maximum data packet returned by the mouse is 4 bytes, the specific content of the data packet is described in detail in the urb * callback function. */Pipe = usb_rcvintpipe (Dev, endpoint-> bendpointaddress); maxp = usb_maxpacket (Dev, pipe, usb_pipeout (PIPE )); /* allocate memory for the mouse device struct */mouse = kzarloc (sizeof (struct usb_mouse), gfp_kernel);/* input_dev */input_dev = input_allocate_device (); If (! Mouse |! Input_dev) goto fail1;/** the requested memory space is used for data transmission. Data is the address pointing to the space, and data_dma is the DMA ing of the memory space, * The DMA address corresponding to the memory space. When DMA transmission is used, the DMA area pointed to by data_dma is used. * otherwise, the normal memory area pointed to by data is used for transmission. * Gfp_atomic indicates no waiting. gfp_kernel is a normal priority and can be sleep. Because the mouse uses the interrupted transmission mode, * sleep is not allowed. Data is a storage area for periodically obtaining mouse events, therefore, gfp_atomic priority is used. If * cannot be allocated to memory, 0 is returned immediately. */Mouse-> DATA = usb_buffer_alloc (Dev, 8, gfp_atomic, & mouse-> data_dma); If (! Mouse-> data) goto fail1;/** applies for memory space for the urb struct. The first parameter indicates the number of packets to be transferred during transmission, and the other transmission modes are 0. * The applied memory will be filled with the usb_fill_int_urb function as shown below. */Mouse-> IRQ = usb_alloc_urb (0, gfp_kernel); If (! Mouse-> IRQ) goto fail2;/* fill in the USB device structure and input device structure */mouse-> USB Dev = dev; mouse-> Dev = input_dev; /* get the name of the mouse device */If (Dev-> manufacturer) strlcpy (mouse-> name, Dev-> manufacturer, sizeof (mouse-> name )); if (Dev-> product) {If (Dev-> manufacturer) strlcat (mouse-> name, "", sizeof (mouse-> name )); strlcat (mouse-> name, Dev-> product, sizeof (mouse-> name);} If (! Strlen (mouse-> name) snprintf (mouse-> name, sizeof (mouse-> name), "USB hidbp mouse % 04x: % 04x ", le16_to_cpu (Dev-> descriptor. idvendor), le16_to_cpu (Dev-> descriptor. idproduct);/** fill in the node name in the mouse device structure. Usb_make_path is used to obtain the path of the USB device in sysfs. format *: USB-USB bus number-path name. */Usb_make_path (Dev, mouse-> phys, sizeof (mouse-> phys); strlcat (mouse-> phys, "/input0 ", sizeof (mouse-> phys);/* assign the name of the mouse device to the input subsystem struct embedded in the mouse device */input_dev-> name = mouse-> name; /* assign the device node name of the mouse device to the embedded input subsystem structure of the mouse device */input_dev-> phys = mouse-> phys;/** input_dev input_id structure, this function is used to store vendor, device type, and device number. This function assigns the number in device descriptor * to the embedded input subsystem struct */usb_to_input_id (Dev, & input_dev-> ID ); /* cdev is the device Class Device */Input _ Dev-> cdev. dev = & INTF-> dev;/* evbit is used to describe the event. ev_key is a key event, and ev_rel is a relative coordinate event */input_dev-> evbit [0] = bit (ev_key) | bit (ev_rel);/* keybit indicates the key value, including the left-click, right-click, and Middle-click */input_dev-> keybit [long (btn_mouse)] = bit (btn_left) | bit (btn_right) | bit (btn_middle);/* relbit indicates the relative coordinate value */input_dev-> relbit [0] = bit (rel_x) | bit (rel_y ); /* Some mouse and other buttons */input_dev-> keybit [long (btn_mouse)] | = bit (btn_side) | bit (btn_extra );/ * Scroll value of the middle wheel */input_dev-> relbit [0] | = bit (rel_wheel);/* The private data item of input_dev indicates the type of the input device, here, the mouse struct object is assigned to it */input_dev-> private = mouse;/* fill in the input device to open the function pointer */input_dev-> open = usb_mouse_open; /* fill in the input device to close the function pointer */input_dev-> close = usb_mouse_close;/** fill in the constructed urb and fill the data of the previously filled mouse struct into the urb struct, submit urb in open. * When urb contains a DMA buffer to be transmitted, set urb_no_transfer_dma_map. The USB core uses the buffer to which * transfer_dma variable points, instead of the buffer to which the transfer_buffer variable points. * Urb_no_setup_dma_map is used for the setup package, and urb_no_transfer_dma_map is used for all data packages. */Usb_fill_int_urb (mouse-> IRQ, Dev, pipe, mouse-> data, (maxp> 8? 8: maxp), usb_mouse_irq, mouse, endpoint-> binterval); mouse-> IRQ-> transfer_dma = mouse-> data_dma; mouse-> IRQ-> transfer_flags | = cursor; /* register the input device with the system */input_register_device (mouse-> Dev);/** generally, in the probe function, you need to save the device information in a usb_interface struct, for later use through * usb_get_intfdata. Here, the structure information of the mouse device is stored in the driver_data data member * of the device structure embedded in the INTF interface structure, that is, INTF-> Dev-> dirver_data = mouse. */Usb_set_intfdata (INTF, mouse); Return 0; fail2: usb_buffer_free (Dev, 8, mouse-> data, mouse-> data_dma); fail1: input_free_device (input_dev ); kfree (Mouse); Return-enomem;}/** processing function for pulling out the mouse device */static void usb_mouse_disconnect (struct usb_interface * INTF) {/* Get the structure of the mouse device */struct usb_mouse * mouse = usb_get_intfdata (INTF);/* INTF-> Dev-> dirver_data = NULL, leave the pointer of the mouse device in the interface struct empty. */Usb_set_intfdata (INTF, null); If (Mouse) {/* end urb lifecycle */usb_kill_urb (mouse-> IRQ ); /* unregister the mouse device from the input subsystem */input_unregister_device (mouse-> Dev);/* release the urb bucket */usb_free_urb (mouse-> IRQ ); /* release the data storage space for mouse events */usb_buffer_free (interface_to_usbdev (INTF), 8, mouse-> data, mouse-> data_dma ); /* release the bucket for storing the mouse struct */kfree (Mouse) ;}/ ** usb_device_id struct indicates the device supported by the driver. usb_interface_info can be used to match the specified type. * The macro parameter indicates (category, subcategory, protocol ). * Usb_interface_class_hid indicates a type of HID (Human Interface Device), that is, the type of the Human-Computer Interaction device. * usb_interface_subclass_boot indicates a type of HID used in the boot phase; * usb_interface_protocol_mouse indicates that it is a mouse device and follows the mouse protocol. */Static struct usb_device_id usb_mouse_id_table [] ={{ usb_interface_info (usb_interface_class_hid, connector, usb_interface_protocol_mouse) },{}/ * terminating entry */}; /** the macro is used to let the program running in the user space know the device that the driver can support. For the USB driver, the first parameter must be * USB. */Module_device_table (USB, usb_mouse_id_table);/** structure of the mouse driver */static struct usb_driver usb_mouse_driver = {. name = "usbmouse ",. probe = usb_mouse_probe ,. disconnect = usb_mouse_disconnect ,. id_table = usb_mouse_id_table,};/** start point of the driver lifecycle, register the mouse driver with USB core. */Static int _ init usb_mouse_init (void) {int retval = usb_register (& usb_mouse_driver); If (retval = 0) Info (driver_version ":" driver_desc ); return retval;}/** the end of the driver's lifecycle, and unregister the mouse driver from the USB core. */Static void _ exit usb_mouse_exit (void) {usb_deregister (& usb_mouse_driver);} module_init (usb_mouse_init); module_exit (usb_mouse_exit );