introduction
because it is necessary to use the development board equipped with Linux system as a USB slave device (virtual serial port), it is very necessary to popularize the basic concept of USB before using the Gadget driver in Linux kernel. In addition, in the process of USB device driver development, it is also necessary to capture packets of USB devices with the help of BUS Hound tools and analyze the protocol frames received by USB devices.
Basic concepts
1. USB is a master-slave structure:
a. all USB transmissions are initiated from the USB host;
B. the USB device does not have the ability to "actively" notify the USB host.
Example: the USB mouse swipes to generate data immediately, but it has no ability to notify the PC to read the data. It can only passively wait for the PC to read it.
2. There are four USB transmission types:
a. control transmission: reliable and time guaranteed, such as the identification process of USB device
b. batch transmission: reliable, time is not guaranteed, such as U SB flash disk
c. interrupt transmission: reliable and real-time, such as USB mouse
d. real time transmission: unreliable, real-time, such as USB camera
3. USB transmission object: endpoint
a. we say "read USB flash disk" and "write USB flash disk", which can be subdivided into: write data to endpoint 1 of USB flash disk and read data from endpoint 2 of USB flash disk
b. except endpoint 0, each endpoint only supports data transmission in one direction;
c. endpoint 0 is used to control transmission, which can be output or input;
d. each endpoint has a transmission type and transmission direction;
e. the endpoint is the basic unit of USB device communication, and all communications are initiated from the endpoint.
4. The input (IN) and output (OUT) in the program are all based on the position of USB host.
Example: for example, the data of the mouse is transferred from the mouse to the PC, and the corresponding endpoint is called "input endpoint"
5. According to the hierarchy of USB protocol stack:
a. a Host may have one or more devices;
b. a Device may have one or more interfaces;
c. an Interface may have one or more endpoints.
6. Main USB controller standards:
a. OHCI(Open Host Controller Interface)
b. UHCI(Universal Host Controller Interface)
c. EHCI( Enhanced Host Controller Interface)
d. xHCI (eXtensible Host Controller Interface). xHCI supports USB devices of all speeds. The purpose of xHCI is to replace the first three.
Protocol introduction
1. Five common structures for USB Driver Development:
① device descriptor is used to describe the general information of USB device. USB device has only one device descriptor. The device descriptor records the USB version number, device type, vid (manufacturer ID), PID (product ID), device serial number, etc.
struct usb_device_descriptor { __u8 bLength; // This device descriptor is 18 bytes long __u8 bDescriptorType; // Descriptor type, 0X01 __u16 bcdUSB; // USB version number, BCD code __u8 bDeviceClass; // Equipment class __u8 bDeviceSubClass; // Equipment subclass __u8 bDeviceProtocol; // Equipment protocol __u8 bMaxPacketSize0; // Maximum packet length for endpoint 0 __u16 idVendor; // Vendor ID __u16 idProduct; // Product ID __u16 bcdDevice; // Equipment version number __u8 iManufacturer; // Vendor information string descriptor index value __u8 iProduct; // Product information string descriptor index value __u8 iSerialNumber; // Product serial number string descriptor index value __u8 bNumConfigurations; // Number of possible configuration descriptors } __attribute__ ((packed));
② the bNumConfigurations field of the device descriptor defines the number of configuration descriptors of a USB device, and a USB device has at least one configuration descriptor. The configuration descriptor describes the number of interfaces that the device can provide, configuration number, power supply information, etc.
struct usb_config_descriptor { __u8 bLength; // This configuration descriptor is 9 bytes long __u8 bDescriptorType; // Configuration descriptor type: 0X02 __le16 wTotalLength; // Total length of the entire configuration information (including configuration, interface, endpoint, device class and manufacturer defined descriptor) __u8 bNumInterfaces; // The number of interfaces supported by this configuration __u8 bConfigurationValue; // The value of the configuration. A device supports multiple configurations. Different configurations are distinguished by the configuration value. __u8 iConfiguration; // String index describing this configuration __u8 bmAttributes; // Properties of this device: D7: reserved D6: self contained power supply D5: remote wake-up D4:0: reserved __u8 bMaxPower; // Bus current required in this configuration (unit: 2mA) } __attribute__ ((packed));
③ string descriptor is optional. String descriptor is used to describe some information convenient for people to read, such as manufacturer and equipment name. If a device does not have a string descriptor, the index value related to the string in other descriptors must be 0.
struct usb_string_descriptor { __u8 bLength; // Length of this string descriptor __u8 bDescriptorType; // String descriptor type, 0X03 __le16 wData[1]; /* UTF-16LE encoded */ } __attribute__ ((packed));
④. The configuration descriptor specifies the number of interfaces under the configuration. The configuration can provide one or more interfaces, and the interface descriptor is used to describe the interface properties. The interface descriptor generally records the interface number, the number of endpoints corresponding to the interface, the class described by the interface, etc.
struct usb_interface_descriptor { __u8 bLength; // Length of this interface descriptor, 9 bytes __u8 bDescriptorType; // Descriptor type, 0X04 __u8 bInterfaceNumber; // Current interface number, starting from 0 __u8 bAlternateSetting; // Current interface alternate number __u8 bNumEndpoints; // Number of endpoints for the current interface __u8 bInterfaceClass; // The class to which the current interface belongs __u8 bInterfaceSubClass; // Subclass of the current interface __u8 bInterfaceProtocol; // The protocol used by the current interface __u8 iInterface; // Index value of the current interface string } __attribute__ ((packed));
⑤. The interface descriptor defines the number of endpoints. The endpoint is the logical interface for data transmission between the device and the host. Except that endpoint 0 is a bidirectional port, other ports are unidirectional. The endpoint descriptor describes the tree transmission type, direction, packet size, endpoint number and other information.
struct usb_endpoint_descriptor { __u8 bLength; // Length of this endpoint descriptor, 7 bytes __u8 bDescriptorType; // Descriptor type, 0X05 __u8 bEndpointAddress; // Endpoint address and direction: bit3:0: endpoint number bit6:4: reserved, zero. bit7: direction, 0 output endpoint (host to device), 1 input endpoint (device to host) __u8 bmAttributes; // Endpoint attribute, bit1:0 indicates the transmission type: 00: control transmission 01: synchronous transmission 10: Batch transmission 11: Interrupt transmission Other bits reserved __le16 wMaxPacketSize; // The maximum packet length that an endpoint can send or receive __u8 bInterval; // Cycle time gap value in endpoint data transmission. This field is invalid for batch transmission and control transmission. For synchronous transmission, this field must be 1ms. For interrupted transmission, this field can be set to 1ms~255ms. /* NOTE: these two are _only_ in audio endpoints. */ /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ __u8 bRefresh; __u8 bSynchAddress; } __attribute__ ((packed));
2. USB enumeration:
after the USB device is connected with the USB host, the host will enumerate the USB device and obtain the descriptor information of the device through enumeration. After obtaining this information, the host will know what kind of driver to load and how to communicate. The USB enumeration process is as follows:
① in the first round, when the USB host detects that the USB device is inserted, it will send a bus reset signal to reset the device. After the USB device is reset, the address is 0, and the host sends data to the endpoint 0 of address 0 to request the descriptor of the device. After receiving the request, the device will send the device descriptor to the host according to the requirements of the host. After the host obtains the device descriptor sent by the device, if it is confirmed to be correct, it will return an acknowledgement packet (ACK) to the device.
② in the second round, the host resets the device again and enters the address setting stage. The host sends an address setting request packet to the endpoint 0 of address 0. The new device address is included in this packet, so there is no data process. The device enters the status process and waits for the host to request the status to return. After receiving it, the device will send a 0-byte status data packet to the host, indicating that the device has set the address. After receiving the 0-byte status data packet, the host will return an acknowledgement packet (ACK). After receiving the ACK packet sent by the host, the device will use the new device address, and the device will get a unique address.
③ in the third round, the host sends a request device descriptor packet to the new device address endpoint 0. This time, the host needs to obtain the whole device descriptor, a total of 18 bytes.
④ and are similar to step ③. Next, obtain the configuration descriptor, configuration set, string descriptor, etc.
USB packet capture tool (BUS Hound)
a convenient USB frame grabbing tool allows us to get twice the result with half the effort in the process of USB driver development. The following is the interface for BUS Hound to grab data frames:
