In 1991, one introduced the concept of pipelines in Linux and used pipelines in many places, such as file systems and device drivers. So we can see that there are various pipelines in Linux. But the same thing is that all pipelines are used to transmit things, but some pipelines are transmitted...
In 1991, one introduced the concept of pipelines in Linux and used pipelines in many places, such as file systems and device drivers. So we can see that there are various pipelines in Linux. But the same thing is that all pipelines are used to transmit things, but some pipelines transmit real material while some pipelines transmit data.
The pipe we see in the USB code is used for data transmission and communication. Communication is from both parties, and it is impossible to speak to yourself. In USB communication, one side must be the host, and the other is what? Is it a device? To be more specific, what truly communicates with the host is the endpoint of the device. We can also say specifically about the endpoints. from the hardware point of view, it actually exists and is implemented as a kind of FIFO. the number of endpoints supported is an important indicator of the interface chip.
In terms of concept, the endpoint is the end point of the communication flow between the host and the USB device. Hosts and devices can communicate with each other or transmit data. First, the device is connected to the USB bus. in order to distinguish each device, the USB bus assigns a serial number to each device. then, to achieve multiple communications, the device provides multiple endpoints, it is also necessary to compile the number, so that the host will eventually contact the endpoint.
There are four channels in the USB World, which correspond to four transmission modes in the USB world: control transmission corresponding control pipeline, interrupt transmission corresponding to interrupted pipeline, batch transmission corresponding to batch pipeline, and when transmission corresponding. Every device in the USB world needs a pipe to survive in the USB world. The emergence of pipelines is to let us distinguish between endpoints, or connection endpoints. I remember that "Tang Bohu's mosquito coils" once said: "data links between hosts and endpoints are called pipelines ."
For example, Fudan University has a main campus, which can also be called a teaching area (including some laboratories). If you have to go to the teaching area and view the teaching area as a host, what is opposite, in addition, there are many student dormitory buildings. when there are more dormitory buildings, we will assign a number to each building, such as Building 1, Building 2 ,......, Building 36 ,......, Each building is regarded as a device.
The main campus of Fudan University is a host. each dormitory is a device, and the dormitory you live in is an endpoint. What about pipelines? It is difficult for a pipe to correspond to a physical object in reality. it cannot be said that it is a road leading to the dormitory at the main entrance of Fudan University, but it should be understood in other ways. It contains a lot of things. you can paste it with the label on the parcel, for example, it writes the recipient's address on it, including the number of buildings, the number of rooms, and the USB, that is, the device number and the endpoint number. after knowing these two numbers, the goods will be able to determine its destination, and the USB host will be able to know which endpoint it communicates.
In addition to the two numbers, the MPs queue also contains other information. For example, it contains the communication direction. that is to say, you can tell from the tag that building 36, 201, is the recipient or the sender, although in reality it does not need to be stated, because the courier must know that you are the recipient. The pipeline also contains the pipeline type. for example, if your parcel is delivered from Shenzhen, then how to transfer it depends on the express delivery company. The express delivery company must provide different types of services, some are fast, slow, and some may have insurance. you can choose different service types based on the amount of money you make. The same applies to MPs queues because the USB device endpoints have different types, so the MPs queues contain a field to record this. Okay. let's check the actual pipeline.
Looking at these macros, the first one on display is usb_sndctrlpipe, which is defined in include/linux/usb. h. first, list the code related to this pile of things:
1432 static inline unsigned int _ create_pipe (struct usb_device * dev,
1433 unsigned int endpoint)
1434 {
1435 return (dev-> devnum <8) | (endpoint <15 );
1436}
1437
1438/* Create various pipes ...*/
1439 # define usb_sndctrlpipe (dev, endpoint )\
1440 (PIPE_CONTROL <30) | _ create_pipe (dev, endpoint ))
1441 # define usb_rcvctrlpipe (dev, endpoint )\
1442 (PIPE_CONTROL <30) |__ create_pipe (dev, endpoint) | USB_DIR_IN)
1443 # define usb_sndisocpipe (dev, endpoint )\
1444 (PIPE_ISOCHRONOUS <30) | _ create_pipe (dev, endpoint ))
1445 # define usb_rcvisocpipe (dev, endpoint )\
1446 (PIPE_ISOCHRONOUS <30) | _ create_pipe (dev, endpoint) | USB_DIR_IN)
1447 # define usb_sndbulkpipe (dev, endpoint )\
1448 (PIPE_BULK <30) | _ create_pipe (dev, endpoint ))
1449 # define usb_rcvbulkpipe (dev, endpoint )\
1450 (PIPE_BULK <30) | _ create_pipe (dev, endpoint) | USB_DIR_IN)
1451 # define usb_sndintpipe (dev, endpoint )\
1452 (PIPE_INTERRUPT <30) | _ create_pipe (dev, endpoint ))
1453 # define usb_rcvintpipe (dev, endpoint )\
1454 (PIPE_INTERRUPT <30) |__ create_pipe (dev, endpoint) | USB_DIR_IN)
1455
Let's take a look at row 3 and expand the macro. PIPE_CONTROL is also a macro defined in the same file, include/linux/usb. h:
1405/* NOTE: these are not the standard USB_ENDPOINT_XFER _ * values !! */
1406/* (yet... they're the values used by usbfs )*/
1407 # define PIPE_ISOCHRONOUS 0
1408 # define PIPE_INTERRUPT 1
1409 # define PIPE_CONTROL 2
1410 # define PIPE_BULK 3
There are four USB transmission modes: synchronous transmission, interrupted transmission, control transmission, and batch transmission. Which of the four types of transmission a device can support is the property of the device itself, which is determined during hardware design. For example, a pure USB flash drive must support batch transmission and control transmission. Different transmission requirements have different endpoints, so for a USB flash drive, it must have batch endpoints and control endpoints, so you have to use the corresponding pipelines to contact different endpoints. Here we can see four macros, where PIPE_ISOCHRONOUS is the channel for sign, PIPE_INTERRUPT is the interruption channel, PIPE_CONTROL is the control channel, and PIPE_BULK is the batch channel.
In addition, _ create_pipe is also a macro. the above definition shows that it provides the device number and endpoint number for constructing a macro. In the kernel, an unsigned int type variable is used to characterize a pipeline, where 8-bit ~ The 14-bit device number, namely, devnum, 15-bit ~ The 18-bit is the endpoint. We can also see that there is such a macro, USB_DIR_IN, which is used to mark the direction of data transmission in the pipeline. one pipeline can only be input or output, and the fish and the bear's paw cannot have both, we have already introduced this macro.
In the pipeline, 7th bits (bit 7) indicate the direction. So here 0x80 means that bit 7 is set to 1, which indicates that the transmission direction is from the device to the host, that is, IN; and if this bit is 0, it indicates that the transmission direction is from the host to the device, that is, OUT. Because USB_DIR_OUT is 0 and USB_DIR_IN is 1, we can see that only USB_DIR_IN is used when defining the MPs queue, but USB_DIR_OUT is not used because it is 0, any number or zero phase is meaningless.
In this way, we will know that in the get_pipes function, the first row and the second row are the values assigned to the control input and control output pipelines of us, and the pipelines are unidirectional. But there is an exception, that is, the control endpoint. The control endpoint is bidirectional. for example, in building 36, 201, this endpoint can be either an external message or a recipient address. The USB specification specifies that each USB device must have at least one control endpoint, and its endpoint is 0. Do other endpoints have to be determined by specific devices, but this endpoint is no matter what the device is, as long as it is in the USB, then you have to follow this rule, not to discuss. So we can see that the value of the endpoint variable passed in row 764 and row 765 is 0. Obviously, the two pipelines constructed by the pipeline correspond to the control endpoint of No. 0. The following lines construct the bulk and interrupt pipelines (if there is an interrupt endpoint ).
For batch endpoints and interrupt endpoints (if any), there is a bEndpointAddress field in their endpoint descriptors. this field has eight bits in total, but it contains a lot of information, for example, whether the endpoint is an input endpoint or an output endpoint, such as the endpoint address (allocated to it during bus enumeration) and the endpoint number of the endpoint. However, you must use a mask USB_ENDPOINT_NUMBER_MASK to obtain the endpoint number of bEndpointAddress and USB_ENDPOINT_NUMBER_MASK. (Just like a Tibetan poem, you have to follow a specific method to understand it, and the specific method here is the mask phase with USB_ENDPOINT_NUMBER_MASK .)
Row 3: For the interrupt endpoint, you must use the bInterval field in the endpoint descriptor to indicate the interrupt request interval of the endpoint.
At this point, the get_pipes function is complete and the information is saved to us. Next, we should play its role. Return to the storage_probe () function. Row 3 passes us as a parameter to the usb_stor_acquire_resources () function. This function is the climax of the story. Every person of Insight who has read this function will suddenly become open-minded, and will feel deeply, suddenly seeing spring and seeing the light, it turns out that the device drivers in Linux work like this!
1004/* Acquireall the other resources and add the host */
1005 result = usb_stor_acquire_resources (us );
1006 if (result)
1007 goto BadDevice;
1008 result = scsi_add_host (host, & intf-> dev );
1009 if (result ){
1010 printk (KERN_WARNING USB_STORAGE
1011 "Unable to add the scsi host \ n ");
1012 goto BadDevice;
1013}
Let's look at the usb_stor_acquire_resources function. It is defined in drivers/usb/storage/usb. c:
778/* Initialize all the dynamic resources weneed */
779 static int usb_stor_acquire_resources (structus_data * us)
780 {
781 int p;
782 struct task_struct * th;
783
784 us-> current_urb = usb_alloc_urb (0, GFP_KERNEL );
785 if (! Us-> current_urb ){
786 US_DEBUGP ("URB allocation failed \ n ");
787 return-ENOMEM;
788}
789
790/* Justbefore we start our control thread, initialize
791 * the device if it needs initialization */
792 if (us-> unusual_dev-> initFunction ){
793 p = us-> unusual_dev-> initFunction (us );
794 if (p)
795 return p;
796}
797
798/* Start up our control thread */
799 th = kthread_create (usb_stor_control_thread, us, "usb-storage ");
800 if (IS_ERR (th )){
801 printk (KERN_WARNING USB_STORAGE
802 "Unable to start control thread \ n ");
803 return PTR_ERR (th );
804}
805
806/* Take areference to the host for the control thread and
807 * count it among all the threads we havelaunched. Then
808 * start it up .*/
809 scsi_host_get (us_to_host (us ));
810 atomic_inc (& total_threads );
811 wake_up_process (th );
812
813 return 0;
814}
"When she was romantic, she smiled in the dark ". A savvy person should be able to find the line of code "laugh in the box" from this function at a glance. that's right, it's Line 3, kthread_create (), this function has created many classic Linux kernel modules. it is precisely because of its existence that writing certain device drivers in Linux has become very simple.
It can be said that for some device drivers, kthread_create () is almost the soul of the entire driver, or the soul of the Linux kernel module. No matter how deep it is hidden, she is always as bright and outstanding as the dark Firefly. To put it bluntly, for many modules, you only need to find the line kthread_create (), and basically you will know how this module works.