Study Notes on USB Kernel in Linux

Source: Internet
Author: User
Tags types of functions what interface
Take notes on the USB Kernel in Linux-general Linux technology-Linux programming and kernel information. For details, refer to the following section. In Linux, the software structure of the USB subsystem is



(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // www.hyesco.com/forum/UploadFile/2004-8/200481092941432.jpg'); ">



The USB Kernel (USBD) is in the center of the system. Studying it is the first step to develop a USB driver (including a customer driver and a host driver. It provides the main data structure and interface functions for the client driver and host controller driver, including four types of functions: client Driver Management, USB device configuration and management, and host controller management, manage Protocol control command sets and data transmission. The specific code is mainly concentrated in usb. c and usb. h under linux/drivers/usb.

Main Data Structure Analysis

There are four main data structures:

USB device usb_device stores information about a USB device, including the device address, device descriptor, configuration descriptor, and so on.

The USB bus system usb_bus stores information about a USB Bus System, including the device address information on the bus, the root hub, and bandwidth usage. A usb bus system must have a host controller and a root hub. Linux supports multiple USB bus systems

The client driver usb_driver stores the client driver information, including the driver name and the function pointer provided by the driver to the USB Kernel.

(USB Request Block) urb is the data structure for USB communication. In Linux, the USB subsystem only uses such a data structure for USB communication. urb contains all the information required to establish any USB transmission and runs through the whole process of data processing on the USB protocol stack.

The following is a detailed analysis of each part.


Struct usb_device {// represents a USB device

Int devnum; // The allocated device address, ranging from 1 to 127.


Enum {
USB_SPEED_UNKNOWN = 0,/* enumerating */

USB_SPEED_LOW, USB_SPEED_FULL,/* usb 1.1 */

USB_SPEED_HIGH/* usb 2.0 */

} Speed; // device speed, low speed/full speed/High speed


Struct usb_device * tt;/* usb1.1 device on usb2.0 bus */, transaction Interpreter

Int ttport;/* device/hub port on that tt */The hub port connected by the device with the transaction interpreter function

Atomic_t refcnt;/* Reference count */Reference count


Struct semaphore serialize; // used for synchronization


Unsigned int toggle [2];/* one bit for each endpoint ([0] = IN, [1] = OUT) */bitmap for synchronous switching, each endpoint occupies one place. [0] indicates input and [1] indicates output.

Unsigned int halted [2];/* endpoint halts; one bit per endpoint # & direction; [0] = IN, [1] = OUT */indicates whether the endpoint is in the stopped status.

Int epmaxpacketin [16];/* INput endpoint specific maximums */maximum package length of the INput endpoint

Int epmaxpacketout [16];/* OUTput endpoint specific maximums */maximum package length of the OUTput endpoint

Struct usb_device * parent; // indicates the upstream hub pointer connected to the device.

Struct usb_bus * bus;/* Bus we're part of */USB bus system to which the device belongs

Struct usb_device_descriptor descriptor;/* Descriptor */device descriptor

Struct usb_config_descriptor * config;/* All of the configs */points to the configuration descriptor of the device and its contained interface descriptor, And the pointer of the endpoint Descriptor

Struct usb_config_descriptor * actconfig;/* the active configuration */current configuration descriptor pointer

Char ** rawdescriptors;/* Raw descriptors for each config */

Int have_langid;/* whether string_langid is valid yet * // whether string_langid exists

Int string_langid;/* language ID for strings */language ID associated with the character Descriptor

Void * hcpriv;/* Host Controller private data */resource pointer occupied by the device on the HCD layer, transparent to the USB Kernel Layer

/* Usbdevfs inode list */inode list of devices in usbdevfs

Struct list_head inodes;

Struct list_head filelist;

/*

* Child devices-these can be either new devices

* (If this is a hub device), or different instances

* Of this same device.

*

* Each instance needs its own set of data structures.

*/Only valid when the current device is a hub

Int maxchild;/* Number of ports if hub */Number of downstream ports of the hub

Struct usb_device * children [USB_MAXCHILDREN]; device pointer connected to the hub
};

Struct usb_bus {// USB Bus System

Int busnum;/* Bus number (in order of reg) */serial number of the current Bus system. Linux supports and numbers multiple Bus systems.

# Ifdef DEVNUM_ROUND_ROBIN

Int devnum_next;/* Next open device number in round-robin allocation */

# Endif/* DEVNUM_ROUND_ROBIN */data structure for allocating device numbers to devices connected to the subsystem

Struct usb_devmap devmap;/* Device map */data structure for allocating Device numbers to devices connected to the subsystem

Struct usb_operations * op;/* Operations (specific to the HC) */HCD is a system function set pointer provided by the USB Kernel.

Struct usb_device * root_hub;/* Root hub */pointer to the Root Hub

Struct list_head bus_list; two-way linked list pointer. the USB Kernel uses a two-way linked list to maintain all USB bus systems in the system.

Void * hcpriv;/* Host Controller private data */data related to the Host Controller, transparent to the USB Kernel Layer

Int bandwidth_allocated;/* on this Host Controller; applies to Int. and Isoc. pipes; measured in microseconds/frame; range is 0 .. 900, where 900 = 90% of a 1-millisecond frame */bandwidth usage of the current subsystem, in milliseconds/frame, value range: [0,900]

Int bandwidth_int_reqs;/* number of Interrupt requesters */current number of interrupted transmissions in the subsystem

Int bandwidth_isoc_reqs;/* number of Isoc. requesters */number of real-time transmissions in the subsystem

/* Usbdevfs inode list */inode list in usbdevfs struct list_head inodes;

Atomic_t refcnt;
};

Struct usb_driver {// call interface provided by the client driver for the USB Kernel

Const char * name; // string name of the client driver, used to avoid repeated installation and uninstallation

Void * (* probe) (// function provided to the USB Kernel to determine whether the driver can drive a certain interface of the device, and allocate resources if the driver can.

Struct usb_device * dev,/* the device */

Unsigned intf,/* what interface */

Const struct usb_device_id * id/* from id_table */

);

Void (* disconnect) (struct usb_device *, void *); // a function provided to the USB Kernel to release resources occupied by an interface of the device.

Struct list_head driver_list; // the corresponding bidirectional pointer. the USB Kernel maintains the client driver used in the USB subsystem through a bidirectional linked list.

Struct file_operations * fops;

Int minor; the minor version number of the driver.

Struct semaphore serialize;

/* Ioctl -- userspace apps can talk to drivers through usbdevfs */

Int (* ioctl) (struct usb_device * dev, unsigned int code, void * buf );

/* Support for "new-style" USB hotplugging

* Binding policy can be driven from user mode too

*/

Const struct usb_device_id * id_table;

/* Suspend before the bus suspends;


* Disconnect or resume when the bus resumes */


// Void (* suspend) (struct usb_device * dev );

// Void (* resume) (struct usb_device * dev );

};

Typedef struct urb // USB Request Block, which contains all the information required to establish any USB transmission and runs through the whole process of data processing on the USB protocol stack.

{

Spinlock_t lock; // lock for the URB

Void * hcpriv; // private data for host controller data related to host controller, transparent to USB Kernel Layer

Struct list_head urb_list; // list pointer to all active urbs bidirectional pointer, used to connect this URB to the active URB bidirectional linked list

Struct urb * next; // pointer from pointer to next URB


Struct usb_device * dev; // pointer to associated USB device accepts the USB device pointer of this URB
Unsigned int pipe; // pipe information indicates the pipeline between an endpoint of the device and the client driver.

Int status; // The status returned by returned status.

Unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | etc.

USB_DISABLE_SPD // reject short packets, that is, packets smaller than the maximum packet length

USB_ISO_ASAP // used for real-time transmission, telling the host controller to transmit the requested data immediately. If no position is set, you need to assign a value to start_frame to notify the host controller of the frame on which the request starts data transmission.

USB_ASYNC_UNLINK // tells USBD to cancel the request asynchronously.

USB_QUEUE_BULK // indicates that batch requests can be queued. Generally, the batch request endpoint of a device has only one URB.

USB_NO_FSBR // indicates that the bandwidth used by the transmission station at full speed should not be recycled.

USB_ZERO_PACKET // indicates that the data length transmitted in batches is equal to the maximum package length of the endpoint. When the host controller sends data, it sends a zero-length package to indicate that the data has ended.

USB_TIMEOUT_KILLED // this parameter is set only by HCD, indicating that a timeout occurs. The customer driver can set a timeout time for URB's processing. If the processing times out, USBD is required to end the processing of this URB. The returned information of URB will reflect this status.

Void * transfer_buffer; // associated data buffer transfers the data cache pointer to receive or send device data. It must be a physically continuous, non-page memory block that uses kmalloc (, GFP_KERNEL) Allocation

Int transfer_buffer_length; // data buffer length

Int actual_length; // actual data buffer length of actual data

Int bandwidth; // bandwidth for this transfer request (INT or ISO) this request occupies one frame of bandwidth each time, only applicable to Real-Time/interrupted transmission

Unsigned char * setup_packet; // setup packet (control only) is used to point to a pointer to a control command in control transmission. It is only applicable to control transmission.

Int start_frame; // start frame (iso/irq only) the frame number that the request starts to transmit. this parameter is applicable only to Real-Time/interrupted transmission. When the transmission is interrupted, the frame number of the first interrupted transmission that initiated the request is returned. During real-time transmission, specify the frame number for processing the first real-time request datagram packet. If USB_ISO_ASAP is set, this variable indicates that the frame number for the first real-time transmission is returned.

Int number_of_packets; // number of packets in this request (iso) the number of data packets contained in this request is only suitable for real-time transmission.

Int interval; // the cycle of the polling interval (irq only) interrupted transmission, 1 <= interval <= 255

Int error_count; // number of errors in this transfer (iso only) cumulative value of the number of transmission errors, applicable only to real-time transmission

Int timeout; // timeout (in jiffies)

Void * context; // parameters in the context for completion routine callback function

Usb_complete_t complete; // pointer to completion routine pointer to the callback function. When data transmission is complete, the host controller driver calls back the function.

Iso_packet_descriptor_t iso_frame_desc [0]; A structure array for real-time transmission. Each structure represents a data transmission.


} Urb_t, * purb_t;

Detailed analysis of functions provided by USB Kernel (USBD)



There are four main functions: client Driver Management, USB device configuration and management, Host Controller Management, Protocol control command set and data transmission management


(1) Client Driver Management



The USB Kernel uses a two-way linked list usb_driver_list to manage all client drivers. The specific management function is to install and uninstall the drivers, which correspond to usb_register and usb_deregister. the USB Kernel dynamically installs and uninstalls the driver.



Int usb_register (struct usb_driver * new_driver)



The client driver should call usb_register in the initialization function, first check whether the driver is installed for the first time, and check whether the corresponding driver item in the list of versions (16 currently) Saved By USBD is null, if not, an error is returned. If yes, add it to usb_driver_list and perform device interface scanning usb_scan_devices to detect which device interfaces in the system can be driven by this driver, the probe function provided by the driver is called. Usb_register also uses the deep Priority Algorithm to search for undriven interfaces of all devices in the system based on the system's tree structure. The driver checks whether the interfaces can be driven. If yes, allocate necessary software resources, configure and let them work.



Void usb_deregister (struct usb_driver * driver)



When the client driver needs to be detached from the system, it will call usb_deregister to set the secondary version number array saved by USBD to NULL, and then unload it from usb_driver_list, then, disconnect all device interfaces driven by the driver and release all resources. Usb_deregister will also notify available customer drivers in the system to check whether the interfaces of these devices that have lost resources can be driven by other drivers. If they are available, they will be allocated resources, make them work normally.



Other interfaces that the driver can call to manage Functions



Void usb_driver_claim_interface (struct usb_driver * driver, struct usb_interface * iface, void * priv)



Int usb_interface_claimed (struct usb_interface * iface)



Void usb_driver_release_interface (struct usb_driver * driver, struct usb_interface * iface)










Find the first device ID from the usb_device_id Array Based on the given interface or device. It is generally called when the driver binds an interface.



Const struct usb_device_id *






Usb_match_id (struct usb_device * dev, struct usb_interface * interface, const struct usb_device_id * id)










(2) configuration and management of USB devices



Supports hot swapping of USB devices. USBD allows you to configure and manage devices, including



Insert device:



When a device is inserted, the connected hub first finds the information inserted by the device, transmits the information to the driver of the hub through interrupted transmission, and confirms that a new device is inserted into the bus through information analysis, the Hub driver calls usb_connect and usb_new_device to configure the device and establish a connection with the corresponding device driver.



Void usb_connect (struct usb_device * dev)



Set new device information. Currently, the device address dev-> devnum is located and allocated. The USB command is used to configure the device by usb_new_device.



Int usb_new_device (struct usb_device * dev)



Configure the new device by referring to the Protocol, including usb_set_address to allocate the address, usb_get_descriptor to obtain the device descriptor, usb_get_configuration to obtain all the configuration descriptors of the device, and usb_set_configuration to activate the default configuration, usbdevfs_add_device is used to add a/proc/bus/usb entry. You can use usb_find_drivers to find the corresponding driver for each interface with the default configuration 0.










The root hub of the first device on the bus is integrated with the host controller. It is regarded as a plug-in at startup and the default address is 0. Linux supports multiple USB buses, that is, multiple host controllers and root hubs. Their Respective device addresses are irrelevant.










Unplug the device:



When the device is unplugged, the connected hub first detects the device disconnection signal and transmits the information to the Hub driver through interrupted transmission. The Hub driver first checks whether the device is detached, if yes, call usb_disconnect for processing.



Void usb_disconnect (struct usb_device ** pdev)



After the device is disconnected. Find the drivers for each interface configured for the current activity of the device, call the disconnect interface functions they provide, interrupt the data transmission operations between them and each interface, and release the resources they allocate for each interface. If the device is a hub, it recursively calls usb_disconnect to process its sub-devices. Release the device address, and release the inode (/proc/bus/usb entry) created for the device through usbdevfs_remove_device. usb_free_dev releases the resources allocated to the device by USBD.










Device reset:



Int usb_reset_device (struct usb_device * dev) in hub. c



USBD provides usb_reset_device for device reset. It first resets the hub port connected to the device, and then completes the configuration operation similar to the usb_new_device function. Be cautious when calling this function. Improper handling will affect the work of the device.










(3) Host Controller Management



Each host controller has a USB system called a USB bus. USBD supports multiple host controllers, that is, multiple USB buses. When a host controller is added, a USB _ bus structure is assigned to it. USBD dynamically installs and uninstalls host drivers.



When the host driver is installed, its initialization function completes the configuration and initialization of the host controller hardware, and CALLS usb_alloc_bus and usb_register_bus to register itself into USBD for access by the USB subsystem.



Struct usb_bus * usb_alloc_bus (struct usb_operations * op)



Create the bus structure usb_bus corresponding to the host controller, save the function interfaces provided by the host controller to USBD, and initialize them. Each host controller provides a set of function interfaces for USBD for actual USB communication operations.



Struct usb_operations {



Int (* allocate) (struct usb_device *); // allocate physical layer resources to the device.



Int (* deallocate) (struct usb_device *); // release the physical layer resources occupied by the device



Int (* get_frame_number) (struct usb_device * usb_dev); // provides the frame number used by the current host controller, which is generally used for real-time transmission.



Int (* submit_urb) (struct urb * purb); // actual data transmission



Int (* unlink_urb) (struct urb * purb); // end the data transmission request



};



Void usb_register_bus (struct usb_bus * bus)



Register the USB bus structure usb_bus to USBD, add it to the USB _ bus_list in the usb Kernel's bus two-way linked list, and create a/proc/bus/USB entry



When the host driver is uninstalled, call usb_deregister_bus and usb_free_bus to release resources.










The following interface functions are provided for host drivers:



Device management



Struct usb_device * usb_alloc_dev (struct usb_device * parent, struct usb_bus * bus)



Void usb_free_dev (struct usb_device * dev)



Void usb_inc_dev_use (struct usb_device * dev)










Bandwidth management



Int usb_check_bandwidth (struct usb_device * dev, struct urb * urb)



Void usb_claim_bandwidth (struct usb_device * dev, struct urb * urb, int bustime, int isoc)



Void usb_release_bandwidth (struct usb_device * dev, struct urb * urb, int isoc)

Protocol control command set and data transmission management

[1] Protocol control command set


USBD provides a set of interface functions for the device's client driver to control, control, and communicate with the device. For details, see P256. These interface functions are actually sent through usb_control_msg, and the client can also call usb_control_msg to complete its own device commands. Usb_control_msg is a synchronous communication function and does not adopt asynchronous callback.


Correspondence between the standard device command set and the functions provided by USBD


Standard Commands defined by the Protocol

Function Interface

CLEAR_FEATURE


Int usb_clear_halt (struct usb_device * dev, int pipe) only clears the end point of the stop operation, but does not clear the Remote Wake-up operation of the device.


GET_CONFIGURATION


Int usb_get_configuration (struct usb_device * dev)


GET_DESCRIPTOR


Int usb_get_descriptor (struct usb_device * dev, unsigned char type, unsigned char index, void * buf, int size)



Int usb_get_string (struct usb_device * dev, unsigned short langid, unsigned char index, void * buf, int size)



Int usb_get_device_descriptor (struct usb_device * dev)


Int _ usb_get_extra_descriptor (char * buffer, unsigned size, unsigned char type, void ** ptr ){


GET_INTERFACE


None


GET_STATUS


Int usb_get_status (struct usb_device * dev, int type, int target, void * data)


SET_ADDRESS


Int usb_set_address (struct usb_device * dev)


SET_CONFIGURATION


Int usb_set_configuration (struct usb_device * dev, int configuration)


SET_DESCRIPTOR


None, because the device generally does not support this command and cannot add new Descriptors


SET_FEATURE


None


SET_INTERFACE


Int usb_set_interface (struct usb_device * dev, int interface, int alternate)


SYNCH_FRAME


None





The correspondence between the device command set and the functions provided by USBD


Protocol-defined class commands


Function Interface


GET_DESCRIPTOR (class)


Int usb_get_class_descriptor (struct usb_device * dev, int ifnum,



Unsigned char type, unsigned char id, void * buf, int size)


GET_PROTOCOL


Int usb_get_protocol (struct usb_device * dev, int ifnum)


SET_PROTOCOL


Int usb_set_protocol (struct usb_device * dev, int ifnum, int protocol)


GET_REPORT


Int usb_get_report (struct usb_device * dev, int ifnum, unsigned char type, unsigned char id, void * buf, int size)


SET_REPORT


Int usb_set_report (struct usb_device * dev, int ifnum, unsigned char type, unsigned char id, void * buf, int size)


SET_IDLE


Int usb_set_idle (struct usb_device * dev, int ifnum, int duration, int report_id)





[2] data transmission management


Data transmission uses the URB (USB Request Block) provided by the USB Kernel ). For details, see the data structure above. Some variables are for specific transmission types.


Batch transmission: None


Transmission Control: setup_packet


Interrupted transmission: start_frame, interval


Real-time transmission: start_frame, number_packets, error_count, timeout, iso_frame_desc


The following interface functions are provided by USBD for processing URB:


Urb_t * usb_alloc_urb (int iso_packets)


It is used to allocate URB to the customer driver. iso_packets is the number of real-time data packets to be transmitted in the URB, and other data packets are transmitted as 0.


Void usb_free_urb (urb_t * urb)


Release the allocated URB corresponding to usb_alloc_urb.


Int usb_submit_urb (urb_t * urb)


Sends one or more URBS asynchronously to the USB Kernel for processing. Urb can be one or multiple, and can correspond to different endpoints.


Int usb_unlink_urb (urb_t * urb)


This indicates that data processing is canceled before the urb transfer is completed. Generally, the device is unplugged during work, or the software cancels processing of a data transmission, or calls the service when the URB transmission times out.


After the host controller driver completes data transmission in URB, it will call the urb-> complete callback function to notify the customer driver. When URB processing times out, the client driver will call usb_unlink_urb to notify HCD to cancel the transmission of this URB data.


It also provides interface functions for control transmission (see 4 Protocol control command set)


Int usb_control_msg (struct usb_device * dev, unsigned int pipe, _ u8 request, _ u8 requesttype, _ b2value, _ b2index, void * data, _ 2010size, int timeout)


Build a URL that controls transmission, send and wait for completion or timeout. This function cannot be used in interrupt processing functions, including the second half of the processing functions. If you need to send asynchronous information or send information in the interrupt processing function, use usb_submit_urb.


Provides interface functions for batch transmission


Int usb_bulk_msg (struct usb_device * usb_dev, unsigned int pipe, void * data, int len, int * actual_length, int timeout)

Build a batch-transferred URB, send and wait for completion or timeout. Similar to usb_control_msg, this function cannot be used in interrupt processing functions, including the latter half of the processing functions. If you need to send asynchronous information or send information in the interrupt processing function, use usb_submit_urb.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.