The first time I came into contact with OS-related Device Driver writing, I felt quite interesting. In order not to forget what I had read, note and summary are of course indispensable. What's more, I decided to sell my life for embedded devices. Well, let's get down to it. Let me talk about the gains during this period and share with you about Linux driver development. However, this time, we only analyze the Linux USB sub-system, because on Friday, we discussed the boss's reminder. Of course, we will also mention other driver writing methods.
In fact, all the device drivers in Linux follow the same Convention-representing the structure of the driver program (which is more appropriate with the driver, it should be called a better driver, the struct should contain all the resources required by the driver. In terms of OO, It is the attributes and members of the drive object. Since the Linux kernel is written in c, We also analyze the code according to this structured idea, but I still want to elaborate these details from the OO perspective. The name of this struct is determined by the driver developer. for example, the mouse may have a struct called mouse_dev, And the keyboard may be composed of a keyboard_dev struct (dev for device, we only do device drivers ). This time, we will analyze a usb-skeleton (the skeleton of the usb driver) in the Linux kernel source code. Naturally, the device structure he defines is called usb-skel:
Struct usb_skel {
Struct usb_device * udev;/* the usb device for this device */
Struct usb_interface * interface;/* the interface for this device */
Struct semaphore limit_sem;/* limiting the number of writes in progress */
Unsigned char * bulk_in_buffer;/* the buffer to receive data */
Size_t bulk_in_size;/* the size of the receive buffer */
_ U8 bulk_in_endpointAddr;/* the address of the bulk in endpoint */
_ U8 bulk_out_endpointAddr;/* the address of the bulk out endpoint */
Struct kref;
};
Here we need to explain some detailed USB protocol specifications. USB can automatically monitor the device and call the corresponding driver to process the device, so its specification is actually quite complicated. Fortunately, we don't have to worry about most of the details, because Linux has provided corresponding solutions. As far as I understand it, the USB driver is divided into two parts, one of which is the USB bus driver. the Linux kernel is ready, and we can ignore it, but we should at least understand its functions. In the image, the USB bus driver is equivalent to laying out a path so that all information can be reached through this USB channel, which is completed by usb_core. When a device receives a USB interface, usb_core checks the information of the device, such as the manufacturer ID and product ID, or the class, subclass, and protocol of the device, to determine which driver should be called to process the device. We don't need to worry about the complicated details. What we need to do is another work-usb device driver. That is to say, we are waiting for usb_core to tell us that we have to work. For devices defined in the usb specification, they have a device framework. for developers, they probably:
From the perspective of developers, each usb device consists of several configurations, and each configuration can have multiple interfaces ), each interface has multiple settings (not given in the setting diagram), and the interface may have no or multiple endpoints ). USB data exchange is performed through the endpoint. A one-way pipeline is established between the host and each endpoint to transmit data. These interfaces can be divided into four types:
Control)
Used to configure devices, obtain device information, send commands, or obtain device status reports.
Interrupt)
When a USB host requires a device to transmit data, the interrupt endpoint transmits a small amount of data at a fixed rate. It is also used to send data to a USB device to control the device. Generally, it is not used to transmit a large amount of data.
Bulk)
It is used for reliable transmission of a large amount of data. If the space on the bus is insufficient to send the entire batch package, it will be divided into multiple packages for transmission.