Sometimes I am also troubled by this problem. I don't know whether I don't understand or whether the world is changing too fast. Even Linux introduces the concept of expiration. Set a time. If the time has reached, some things will happen.
For example, if you want to bake a cake at 09:15 and we want to bake it for 45 minutes, we hope that the alarm will sound at. When the time is up, the alarm will keep ringing as expected. In the computer, you also need to do such a thing. Some things require time control, especially network and communication. If data transmission is involved, you must consider timeout. In other words, you just need to set an alarm clock. If you haven't done what you should do at the given time, stop it and don't do it. There must be a problem. For example, if the cake has been baked for 45 minutes and the color has not changed, you must have a problem. Don't bake it. Check whether the oven is broken first, or is there a power outage.
Here, we need to use an alarm clock, or a professional timer. If the time is reached, execute a function. The Linux Kernel Time mechanism has been implemented. You only need to follow the instructions to call the corresponding interface function. Check the code. Line 2: The wait_for_completion_interruptible_timeout () function is called. The kernel/sched. c defines several such functions. We don't want to look at their definitions, but we can "Paste" their declarations from include/linux/completion. h:
45 extern void FASTCALL (wait_for_completion (structcompletion *));
46 extern intFASTCALL (wait_for_completion_interruptible (struct completion * x ));
47 extern unsigned long FASTCALL (wait_for_completion_timeout (structcompletion * x,
48 unsigned long timeout ));
49 extern unsigned longFASTCALL (wait_for_completion_interruptible_timeout (
50 struct completion * x, unsigned long timeout ));
Obviously, wait_for_completion is the most basic function in this series, and several other functions are extension functions based on it. A function corresponding to wait_for_completion is complete (). The method and function are as follows.
First, we need to use init_completion to initialize a struct variable of struct completion, and then call wait_for_completion (), so that the current process will enter sleep and be in a waiting state, another process may do something.
After it completes a certain task, it will call the complete () function. Once it calls the complete () function, the sleeping process will be awakened. In this way, a synchronization mechanism or a waiting mechanism is implemented.
The wait_for_completion_interruptible_timeout () function we use now is enhanced in a simple synchronization mechanism. There are two possibilities for it to be awakened. One is to wake up by the process that calls the complete () function, or set an alarm, when the time arrives, the alarm goes off.
This solution is used as an example. For example, if I had to take the test the next day when I was a child, I either told my mom that she would remember to call me the next morning or set an alarm when my mom was not at home, when the time is up, the alarm will wake me up.
In short, the alarm clock is set here, and the time is MAX_SCHEDULE_TIMEOUT. In this way, we hope that you do not submit an urb for half a day and no one will handle it. If no one does, it means the problem is solved, don't waste time. Undo this urb and submit it again. So we can see that the us_f1_x_urb_active flag is cleared in Row 3. If timeleft is smaller than or equal to 0, we will call the usb_kill_urb () function to cancel the current urb.
In addition to this alarm clock, how does this synchronization mechanism work in our case? Don't forget our sentence "init_completion (& urb_done)". "urb_done" is a struct completion struct variable. This definition appears in the 1st rows of the usb_stor _ msg_common () function. Obviously, completion is a very important structure of the synchronization mechanism in Linux. At the same time, we passed & urb_done as 1st parameters to wait_for_completion_interruptible_timeout (). Therefore, we are waiting to see where the complete () function that sends the wake-up signal is called. In other words, when will the function wake up once it goes to bed.
Do you still remember setting a urb-> complete pointer when you call usb_fill_bulk_urb () to fill in urb? That's right, we saw urb-> complete = usb_stor_blocking_completion, which is equivalent to sending a message to the USB host controller driver. Therefore, when the urb transmission is complete, the USB Host Controller will wake it up, but will not wake it up directly. Instead, it will execute the function pointed to by the previously set urb complete () function pointer, that is, call the usb_stor_blocking_completion () function to truly wake it up. The usb_stor_blocking_completion () function is defined in drivers/usb/storage/transport. c:
111 static void usb_stor_blocking_completion (structurb * urb)
112 {
113 struct completion * urb_done_ptr = (structcompletion *) urb-> context;
114
115 complete (urb_done_ptr );
116}
This function has two sentences, but it calls the complete () function. urb_done_ptr is assigned as urb-> context, and what is urb-> context? In the usb_stor _ msg_common () function, is there row 138 that grants the initialized urb_done to it? Obviously, this is the process that wakes up just now. In other words, wait_for_completion () will wake up and continue.
There are only a few lines of code left below. First, clear_bit () clears us_f1_x_urb_active, indicating that the urb is no longer active. This is because everything is done. If it times out, the same is true. urb must be revoked. Of course, you do not need to set it to active. In the last sentence, the usb_stor _ msg_common () function returns the result. return us-> current_urb-> status, and the returned result is the "status" of urb ". So we can finally leave this function. That is, we will return to usb_stor_bulk_transfer_buf. The remaining lines of code are nothing more than processing the results.
Let's look back at the usb_stor_Bulk_transport () function. Row 3: The usb_stor_bulk_transfer_buf () function is called. 1st parameters, us. Needless to say. 2nd parameters, us-> send_bulk_pipe. As a USB flash drive, IN addition to a control pipe, it also has two batch pipelines, one is IN and the other is OUT. After the ups and downs of the past, we have no longer been confused about the terms in USB. The so-called pipe is nothing more than an unsigned int type number. Us-> send_bulk_pipe and the us-> recv_bulk_pipe that we will immediately encounter are obtained by calling the get_pipes () function in the memorable storage_probe. Then, take a closer look at the 3rd bcb parameters.
Row 3 defines the pointer bcb, which is the pointer of the structbulk_cb_wrap struct. This is a data structure specially prepared for the Bulk-only protocol, from drivers/usb/storage/transport. h:
50/* command block wrapper */
51 struct bulk_cb_wrap {
52 _ le32 Signature;/* contains 'usbc '*/
53 _ u32 Tag;/* uniqueper command id */
54 _ le32 DataTransferLength;/* size ofdata */
55 _ u8 Flags;/* direction in bit 0 */
56 _ u8 Lun;/* LUNnormally 0 */
57 _ u8 Length;/* of the CDB */
58 _ u8 CDB [16];/* maxcommand */
59 };
Another data structure is defined in the same file: struct bulk_cs_wrap.
66/* command status wrapper */
67 struct bulk_cs_wrap {
68 _ le32 Signature;/* shoshould = 'usbs '*/
69 _ u32 Tag;/* same asoriginal command */
70 _ le32 Residue;/* amountnot transferred */
71 _ u8 Status;/* seebelow */
72 _ u8 Filler [18];
73 };
The two data structures correspond to CBW and CSW, namely, Command Block Wrapper and Command Status Wrapper. Now, we need to pay attention to the USB Mass Storage Bulk-only Transport protocol, because the USB flash drive transmits data in the way specified by this Protocol. The Bulk-only transmission method is to first send a CBW to the device by the host, and then the device receives the CBW, which will explain it and then execute what it should do as defined in the CBW, then it returns a CSW to the host.
CBW is actually a command package, while CSW is actually a State package. (Is the status after the command is executed successful or failed? So you need to use such a status package ).
In this case, we can check what the rows before calling usb_stor_Bulk_transport () in the usb_bulk_transfer_buf () function are doing. Obviously, these rows are all in preparation for calling the function usb_stor_bulk_transfer_buf (). the amazing part is still in usb_stor_bulk_transfer_buf.
Row 3: struct bulk_cb_wrap * bcb. The value is (struct bulk_cb_wrap *) us-> iobuf. Row 3, struct bulk_cs_wrap * bcs, also assigned to (struct bulk_cb_wrap *) us-> iobuf, then defines the variable transfer_length of an unsignedint and assigned the value of "sr-> request_bufflen. Then, assign values to the members of bcb. 4.36.1 and fig 4.36.2 describe the data formats of CBW and CSW respectively.
Byte \ bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
0-3 |
DCBWSignature |
4-7 |
DCBWTag |
8-11 |
DCBWDataTransferLength |
12 |
BmCBWFlags |
13 |
Reserved (0) |
BCBWLUN |
14 |
Reserved (0) |
BCBWCBLength |
15-30 |
CBWCB |
Figure 4.36.1 CBW
Byte \ bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
0-3 |
DCBWSignature ("LaMS ") |
|
4-7 |
DCBWTag |
|
8-11 |
DCSWDataResidue |
|
12 |
BCSWStatus |
|
Figure 4.36.2 CSW
Line 3, bcb-> Signature = cpu_to_le32 (US_BULK_CB_SIGN), and Signature corresponds to the first four Bytes of CBW in USB Mass Storage spec, that is, dCBWSignature, US_BULK_CB_SIGN is defined in drivers/usb/storage/transport. h:
62 # define US_BULK_CB_SIGN 0x43425355/* spells out USBC */
I don't know who specified it. Only by writing 43425355h in dCBWSignature can a data packet be a CBW. In addition, the transmission of CBW complies with Little Endian, so the cpu_to_le32 () macro needs to be used to convert the data format.
Then bcb-> DataTransferLength corresponds to dCBWDataTransferLength in CBW. This indicates how many Bytes the ho host wants to transmit from this endpoint. Here, cpu_to_le32 (transfer_length) is assigned to it. Transfer_length has just been mentioned, that is, the port number of the server is> request_bufflen. In fact, the most important record for these variable names is the same thing.
Bcb-> Flags, corresponding to bmCBWFlags in CBW, bcb-> Flags = sulfate-> SC _data_direction = DMA_FROM_DEVICE? 1 <7: 0; indicates the direction of data transmission. As described earlier, DMA_FROM_DEVICE indicates that data is transmitted from the device to the primary storage. BmCBWFlags is 8-bit, where bit7 indicates the direction; 0 indicates Data-Out, that is, from host to the device; 1 indicates Data-in, that is, from the device to the host. Therefore, if the value is 1, it must be shifted to seven places.
Bcb-> Tag = sulfate-> serial_number. This Tag corresponds to the dCBWTag In the CBW. The significance of dCBWTag is that the host sends the Tag and the device prints the content of the Tag. Specifically, the device will send a CSW back, and a dCSWTag in CSW will have the same content as the dCBWTag, so in fact this is similar to the connector code. Each SCSI command is assigned a serial_number, which is used in the Tag.
Bcb-> Lun = sulfate-> device-> lun. The corresponding bCBWLUN In the CBW indicates the LUN to which the command is sent. We know that if a device supports multiple Luns, obviously, each LUN has a number. For example, if you want to read and write a partition on a USB flash drive, you must specify the partition. If the device does not support multiple Luns, it is set to 0. However, it should be noted that bcb-> Lun does not exactly correspond to bCBWLUN in CBW. bCBWLUN only has four bits. In our definition, the LUN has eight bits, the lower 4 bits are used to correspond to bCBWLUN, while the higher 4 bits are used to represent the target id. Therefore, we will judge whether the US_FL_SCM_MULT_TARG flag is set in us-> flags. If so, it indicates that multiple targets are supported, so we will record which target is used.
Bcb-> Length = sulfate-> Bytes _len, which corresponds to bCBWCBLength in CBW, that is, the effective Length of the command, in Bytes. The valid length of the SCSI command can only be 1 to 16. Next we will have a CDB array with 16 elements in total. The reason is that the cmnd in struct scsi_cmnd has already been mentioned. In the second row, the second row copies the contents of the command src-> cmnd array to bcb-> CDB.
At this time, usb_stor_bulk_transfer_buf is officially called. The third parameter passed to it is bcb, and the fourth parameter is US_BULK_CB_WRAP_LEN. It is also defined in drivers/usb/storage/transport. h:
61 # define US_BULK_CB_WRAP_LEN 31
31 is the length of the CBW, And the CBW is 31 Bytes. Usb_stor_bulk_transfer_buf is nothing more than submitting an urb, and then you don't have to worry about it. Wait for the result. The final result is returned by interpret_urb_result (). If the transfer is correct, USB_STOR_XFER_GOOD is returned. if the transfer is incorrect, usb_stor_Bulk_transport () is returned directly. The return value is USB_STOR_TRANSPORT_ERROR. If it is correct, continue to the next step to reach the real data transmission stage. Before you start the data transmission phase, let's first check the interpret_urb_result () function.