It is often said that a device usually has multiple configurations, and the configuration usually has multiple interfaces, and the interface usually has multiple endpoints. The interface represents a logical device, such as a sound card divided into recording and playback. When you access a device, you are accessing an interface (a logical device). In addition to endpoint 0, each endpoint supports only one transmission direction, and a property transmits data to and from an endpoint that is a data channel.
This article first analyzes the device, configuration, interface, settings, the relationship between endpoints, and then according to the 2440-ochi driver, analyze a device when registering to the kernel, it's the process of obtaining these descriptors.
I. The relationship between devices, configurations, interfaces, settings, endpoints
In the kernel, a USB device, whether a hub or a normal USB mouse, is described using a Usb_device structure that contains a device descriptor and multiple configurations supported by the device in the usb_device structure.
struct Usb_device {... struct device dev;struct usb_device_descriptor descriptor;//device descriptor struct Usb_host_config *config ;//Supported configuration struct Usb_host_config *actconfig;//current configuration ...};
device Descriptors
struct Usb_device_descriptor {__u8 blength;//descriptor length __u8 bdescriptortype;//Descriptor Type __le16 BCDUSB;//USB version number __u8 Bdeviceclass;//usb assigned device class __U8 Bdevicesubclass;//usb assigned sub-class __U8 Bdeviceprotocol;//usb assigned protocol __u8 BMAXPACKETSIZE0;//ENDPOINT0 Maximum Package size __le16 idvendor;//manufacturer number __le16 idproduct;//Product number __LE16 bcddevice;//Device factory number __u8 imanufacturer;//describes the index of the vendor string __u8 iproduct;//describes the index of the product string __u8 iserialnumber;//describes the index of the device serial number string __u8 bnumconfigurations;//number of possible configurations} __attribute__ ((packed));
The configuration contained in the device contains a configuration descriptor, along with the interfaces that the configuration has.
struct Usb_host_config {struct usb_config_descriptordesc;//configuration descriptor char *string;struct Usb_interface_assoc_descriptor * Intf_assoc[usb_maxiads];struct usb_interface *interface[usb_maxinterfaces];//interface struct Usb_interface_cache *intf_ cache[usb_maxinterfaces];unsigned Char *extra; int Extralen;};
Configuration Descriptor, note its wtotallength, we usually have a configuration and the interface it contains, the interface contains all the descriptors of all the descriptor at once, Wtotallength is their full length.
struct Usb_config_descriptor {__u8 blength;//descriptor length __u8 bdescriptortype;//Descriptor type number __le16 wtotallength;// The size of all data returned by the request configuration, all of the currently configured descriptors include the interfaces contained, the endpoint descriptor __u8 bnuminterfaces;//The number of interfaces supported by the configuration __u8 bconfigurationvalue;//set_ The parameter value required by the configuration command __u8 iconfiguration;//describes the index value of the configured string __u8 bmattributes;//Power mode selection __u8 bmaxpower;/ /device maximum current extracted from the bus} __attribute__ ((packed));
the interface that the configuration contains
struct Usb_interface {struct usb_host_interface *altsetting;//an interface may have multiple settings (one interface multiple functions), which means that the endpoints contained in these interfaces may have multiple functional structs. Usb_host_interface *cur_altsetting;//Current settings unsigned num_altsetting;/* number of alternate settings */struct usb_ Interface_assoc_descriptor *intf_assoc;int minor;/* Minor Number This interface was * bound to */enum Usb_interface_conditi On condition;/* state of binding */unsigned is_active:1;/* the interface are not suspended */unsigned sysfs_files_created:1 ;/* The SYSFS attributes exist */unsigned ep_devs_created:1;/* endpoint "devices" exist */unsigned unregistering:1;/* unre Gistration is in progress */unsigned needs_remote_wakeup:1;/* driver requires remote wakeup */unsigned NEEDS_ALTSETTING0: 1;/* Switch to Altsetting 0 is pending */unsigned needs_binding:1;/* needs delayed Unbind/rebind */unsigned reset_running: 1;struct device dev;/* Interface specific device info */struct device *usb_dev;atomic_t pm_usage_cnt;/* usage counter for Autosuspend */struct work_struct Reset_ws;/* For resets in atomic context */};
interface's current settings, which contain the interface descriptor and the endpoints owned by the interface
struct Usb_host_interface {struct usb_interface_descriptordesc;//interface descriptor struct Usb_host_endpoint *endpoint;char * string;/* IInterface String, if present */unsigned char *extra; /* Extra descriptors */int extralen;};
Interface Descriptor
struct Usb_interface_descriptor {__u8 blength;//descriptor length __u8 bdescriptortype;//descriptor type __U8 The number of the binterfacenumber;//interface __u8 balternatesetting;//The Alternate interface descriptor number __U8 bnumendpoints;//the end point used by the interface, not including the endpoint 0__u8 binterfaceclass;//interface type __U8 binterfacesubclass;//interface subtype __u8 binterfaceprotocol;//interface follows the Protocol __U8 iinterface;//The index value of the string describing the interface} __attribute__ ((packed));
Endpoint
struct Usb_host_endpoint {struct usb_endpoint_descriptordesc;//endpoint descriptor struct list_headurb_list;//URB queue for that endpoint void* Hcpriv;struct Ep_device *ep_dev;/* for SYSFS info */struct usb_host_ss_ep_comp*ss_ep_comp;/* for SS devices */unsigned Cha R *extra; /* Extra descriptors */int extralen;int enabled;};
Endpoint Descriptor
struct Usb_endpoint_descriptor {__u8 blength;//descriptor length __u8 bdescriptortype;//descriptor type __U8 bendpointaddress;//endpoint Address: 0~3 bit is the endpoint number, 7th bit is the transport direction __u8 bmattributes;//endpoint attribute bit 0-1 00 Control 01 Synchronous 02 Lot 03 Interrupt __le16 wmaxpacketsize;//the size of the maximum packet received or sent by this endpoint __u8 binterval;//polling The time interval for the data break endpoint//bulk transfer endpoint, and the endpoint that controls the transfer, this domain ignores//for the endpoint that interrupted the transfer, the range of this domain is 1 ~255/* Note: These-_only_ in audio endpoints. *//* use usb_dt_endpoint*_size in blength, not sizeof. */__u8
brefresh;__u8 bsynchaddress;} __attribute__ ((packed));
Second, the description of the acquisition process
1, Usb_get_device_descriptor (Usb_dev, usb_dt_device_size);
int usb_get _device_descriptor (struct usb_device *dev, unsigned int size) {struct Usb_device_descriptor *desc;int ret;if (Size > Si Zeof (*DESC)) Return-einval;desc = Kmalloc (sizeof (*DESC), Gfp_noio); if (!desc) Return-enomem;ret = Usb_get_descriptor ( Dev, usb_dt_device, 0, desc, size), if (ret >= 0) memcpy (&dev->descriptor, desc, size); Kfree (DESC); return ret;}
int usb_get_descriptor (struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) {int I;int Result;memset (buf, 0, size);/* Make sure we parse really received data */for (i = 0; i < 3; ++i) {/* retry on length 0 or error; Some devices is flakey */result = usb_control_msg (Dev, usb_rcvctrlpipe (dev, 0), Usb_req_get_descriptor, Usb_dir_in, ( Type << 8) + index, 0, buf, size,usb_ctrl_get_timeout); if (Result <= 0 && result! =-etimedout) continue;i F (Result > 1 && ((U8 *) buf) [1]! = type) {result =-enodata;continue;} break;} return result;}
2, Usb_configure_device
static int Usb_configure_device (struct Usb_device *udev) {usb_get_configuration (udev);}
int usb_get_configuration (struct usb_device *dev) {struct device *ddev = &dev->dev;int ncfg = dev-> Descriptor.bnumconfigurations;int result = 0;unsigned int Cfgno, length;unsigned char *buffer;unsigned char *bigbuffer; struct Usb_config_descriptor *desc;cfgno = 0;if (Ncfg > Usb_maxconfig) {dev->descriptor.bnumconfigurations = Ncfg = Usb_maxconfig;} length = ncfg * sizeof (struct usb_host_config);d ev->config = kzalloc (length, gfp_kernel); length = ncfg * sizeof (char *) ;d ev->rawdescriptors = kzalloc (length, gfp_kernel), buffer = Kmalloc (usb_dt_config_size, gfp_kernel);d ESC = (struct Usb_config_descriptor *) Buffer;result = 0;for (; cfgno < ncfg; cfgno++) {/* We grab just the first descriptor so We kno W How long the whole configuration is */result = Usb_get_descriptor (Dev, usb_dt_config, Cfgno, buffer, usb_dt_config_size) ;/* length is the length of all descriptors currently configured */length = MAX ((int) le16_to_cpu (desc->wtotallength), usb_dt_config_size);/* Now, we know the L Ength, get the whole thing */bIgbuffer = Kmalloc (length, gfp_kernel); <span style= "White-space:pre" ></span>/* get descriptor */result = usb_get_ Descriptor (Dev, usb_dt_config, Cfgno, Bigbuffer, length);d Ev->rawdescriptors[cfgno] = bigbuffer;/* parsing configuration descriptor */result = Usb_parse_configuration (&dev->dev, Cfgno, &dev->config[cfgno], bigbuffer, length);} result = 0;return result;}
At this point, all descriptors have been obtained.
USB Drive--device, configuration, interface, settings, relationships before endpoints, and analysis of their acquisition process