For the entire USB-storage module, the usb_stor_init () function is its start. However, for the USB flash drive, the function that actually drives the USB flash drive starts with the storage_probe () function.
As long as the two parallel lines overlap, it is doomed to start a lifetime of entanglement, no matter whether the middle is a short separation. USB core finds the driver suitable for the device or the device supported by the driver, but it only indicates that the first impression on both sides is acceptable, but whether they are suitable for each other requires further understanding. The USB flash drive calls the storage_probe () function to know each other. What kind of device is it? The get_device_info, get_protocol, get_transport, and get_pipes functions are called.
The entire USB flash drive was started by storage_probe and ended by storage_disconnect. Among them, the storage_probe function occupies a considerable space. Let's take a look. Both functions are from drivers/USB/storage/USB. C:
945/* probe to see if we can drive anewly-connected USB device */
946 static int storage_probe (struct usb_interface * INTF,
947 const struct usb_device_id * ID)
948 {
949 structscsi_host * Host;
950 structus_data * us;
951 intresult;
952 structtask_struct * th;
953
954 if (usb_usual_check_type (ID, usb_us_type_stor ))
955 return-enx io;
956
957 us_debugp ("USB Mass storagedevice detected \ n ");
958
959 /*
960 * Ask the SCSI layer to allocate a hoststructure, with extra
961 * space at the end for our privateus_data structure.
962 */
963 host = scsi_host_alloc (& usb_stor_host_template, sizeof (* US ));
964 if (! Host ){
965 printk (kern_warning usb_storage
966 "unable to allocate the SCSI host \ n ");
967 return-enomem;
968}
969
970 US = host_to_us (host );
971 me mset (US, 0, sizeof (struct us_data ));
First, paste these lines first. The two parameters are needless to say. The two pointers of struct usb_interface and struct usb_device_id are all described earlier, from the USB core layer, this is what we use throughout the story. The points of these two pointers are fixed.
Row 3: The most important data structure has finally emerged. There are not many data structures defined in the USB-storage module, but us_data is regarded as one. This data structure keeps following our code. We can see it almost everywhere. Paste the code from drivers/USB/storage/USB. h:
102/* we allocate one of these for every devicethat we remember */
103 struct us_data {
104/* thedevice we're working
105 * it's important to note:
106 * (o) You must hold dev_mutex to change pusb_dev
107 */
108 structmutex dev_mutex;/* protect pusb_dev */
109 structusb_device * pusb_dev;/* This usb_device */
110 structusb_interface * pusb_intf;/* this interface */
111 structus_unusual_dev * unusual_dev;/* Device-filter entry */
112 unsignedlong flags;/* from filter initially */
113 unsignedint send_bulk_pipe;/* cachedpipe values */
114 unsignedint recv_bulk_pipe;
115 unsignedint send_ctrl_pipe;
116 unsignedint recv_ctrl_pipe;
117 unsignedint recv_intr_pipe;
118
119/* information about the device */
120 char * transport_name;
121 char * protocol_name;
122 _ le32 bcs_signature;
123 u8 subclass;
124 u8 protocol;
125 u8 max_lun;
126
127 u8 ifnum;/* interface number */
128 u8 ep_binterval;/* interrupt interval */
129
130/* function pointers for this device */
131 trans_cmnd transport;/* transport function */
132 trans_reset transport_reset;/* Transport devicereset */
133 proto_cmnd proto_handler;/* protocol handler */
134
135/* scsiinterfaces */
136 structscsi_cmnd * Server Load balancer;/* Current Server Load balancer */
137 unsignedint tag;/* Current dcbwtag */
138
139/* control and bulk communications data */
140 structurb * current_urb;/* USB requests */
141 structusb_ctrlrequest * Cr;/* control requests */
142 struct usb_sg_request current_sg;/* scatter-gather Req .*/
143 unsignedchar * iobuf;/* I/obuffer */
144 unsignedchar * sensebuf;/* Sense Data Buffer */
145 dma_addr_t cr_dma;/* bufferdma addresses */
146 dma_addr_t iobuf_dma;
147
148/* mutualexclusion and synchronization structures */
149 struct semaphore Sema;/* To sleepthread on */
150 struct completion notify;/* thread begin/end */
151 wait_queue_head_t delay_wait;/* Wait duringscan, reset */
152
153/* subdriver information */
154 void * extra;/* any extradata */
155 extra_data_destructor extra_destructor;/* extra data destructor */
156 # ifdef config_pm
157 pm_hook suspend_resume_hook;
158 # endif
159 };
It is not difficult to find that every important data structure in the Linux kernel is complex. In short, this troublesome data structure is available to every device. In other words, we apply for a us_data for each device, because the edge in this structure will be used all the time. Line 3: structus_data * us. Therefore, we will see us very frequently in the future. What does us mean? USB storage.
Line 3: Take A Look At usb_stor_host_template carefully, because this variable will be encountered multiple times later. Scsi_host_alloc is a function provided by the SCSI subsystem. It applies for a corresponding data structure of the SCSI host. But its first parameter & usb_stor_host_template is actually a structure pointer of struct scsi_host_template. The reason why the USB mass storage involves the SCSI layer, it is because we have simulated a USB flash disk as a SCSI device. For a SCSI device, we have to have a scsicard or SCSI to work properly.
Host. According to the SCSI rules, to apply for a SCSI host struct, we have to provide a struct scsi_host_template struct, which is actually a template by name, the SCSI layer encapsulates everything. If you submit a template to it, it will provide you with a structscsi_host struct. For this usb_stor_host_template, its definition or Initialization is in drivers/USB/storage/scsiglue. C:
441 struct scsi_host_templateusb_stor_host_template = {
442/* Basic userland interface stuff */
443. Name = "USB-storage ",
444. proc_name = "USB-storage ",
445. proc_info = proc_info,
446. info = host_info,
447
448/* command interface -- queued only */
449. queuecommand = queuecommand,
450
451/* error and abort handlers */
452. eh_abort_handler = command_abort,
453. eh_device_reset_handler = device_reset,
454. eh_bus_reset_handler = bus_reset,
455
456/* queuecommands only, only one command per Lun */
457. can_queue = 1,
458. pai_per_lun = 1,
459
460/* unknown initiator ID */
461. this_id =-1,
462
463. slave_alloc = slave_alloc,
464. slave_configure = slave_configure,
465
466/* lots ofsg segments can be handled */
467. sg_tablesize = sg_all,
468
469/* limit the total size of a transfer to 120 kb */
470. max_sectors = 240,
471
472/* mergecommands... this see MS to help performance,
473 * periodically someone shocould test tosee which setting is more
474 * optimal.
475 */
476. use_clustering = 1,
477
478/* emulated HbA */
479. emulated = 1,
480
481/* we do our own delay after a device or bus reset */
482. skip_settle_delay = 1,
483
484/* sysfs device attributes */
485. sdev_attrs = sysfs_device_attr_list,
486
487/* modulemanagement */
488. module = this_module
489 };
According to the SCSI layer rules, to apply for a SCSI host and let it work, we need to call three functions. The first is scsi_host_alloc (), and the second is scsi_add_host (), the third is scsi_scan_host (). These three functions will be seen in the following code.
Scsi_host_alloc () is called to apply for space for the struct scsi_host structure. The SCSI core layer knows that the host exists only after scsi_add_host () is called. Then, only scsi_scan_host () after being called, the real device is discovered. The meanings of these functions are exactly the same as those of their names. Isn't it?
It should be pointed out that scsi_host_alloc () requires two parameters. The first parameter is the pointer of structscsi_host_template. We certainly gave it & usb_stor_host_template, the second parameter is actually called the driver's own data, and we pass the sizeof (* US ). The SCSI layer provides a very friendly interface for us. When the struct scsi_host struct is designed, an unsigned long hostdata [0] is specially prepared for other device drivers, the size of the hostdata can be determined by us. Passing the sizeof (* US) to scsi_host_alloc () means applying for memory for us. In the future, if we need to obtain the corresponding SCSI from us
Host can use the inline function us_to_host (). In turn, to get the corresponding us from the SCSI host, you can use the inline function host_to_us (), which is obviously a pair, are defined in drivers/USB/storage/USB. h:
161/* Convert Between us_data and thecorresponding scsi_host */
162 static inline struct scsi_host * us_to_host (struct us_data * US ){
163 returncontainer_of (void *) us, struct scsi_host, hostdata );
164}
165 static inline struct us_data * host_to_us (struct scsi_host * Host ){
166 return (struct us_data *) Host-> hostdata;
167}
In short, the USB driver is connected with the SCSI host. From then on, the USB flash drive will assume both the USB flash drive role and the SCSI device role.
Row 3: us_debugp is a macro from drivers/USB/storage/debug. H. We will also see this macro in many codes, which is nothing more than printing some debugging information. There is such a section in debug. h:
51 # ifdef config_usb_storage_debug
52 void usb_stor_show_command (struct scsi_cmnd * sulfate );
53 void usb_stor_show_sense (unsigned char key,
54 unsigned char ASC, unsigned char ascq );
55 # define us_debugp (X...) printk (kern_debugusb_storage X)
56 # define us_debugpx (X...) printk (X)
57 # define us_debug (x) x
58 # else
59 # define us_debugp (X ...)
60 # define us_debugpx (X ...)
61 # define us_debug (X)
62 # endif
Here we have defined several macros: us_debugp, us_debugpx, and us_debug. The difference is not big, but the form is slightly different.
Note that the debugging information is meaningful only when the compilation option config_usb_storage_debug is enabled. If this option is set to 0, these macros will do nothing, because they are null. Let's talk about these macros in the us_debug series.
Row 3: What is usb_usual_check_type () used? This function is from drivers/USB/storage/libusual. C:
98 int usb_usual_check_type (const struct usb_device_id * ID, int caller_type)
99 {
100 int id_type = usb_us_type (ID-> driver_info );
101
102 If (caller_type <= 0 | caller_type> = 3)
103 return-einval;
104
105/* driversgrab fixed assignment devices */
106 If (id_type = caller_type)
107 return 0;
108/* driversgrab devices biased to them */
109 If (id_type = usb_us_type_none & caller_type = atomic_read (& usu_bias ))
110 return 0;
111 return-enodev;
112}
This function ensures that the claimed device belongs to the device supported by USB-storage, rather than the device supported by another drive called ub. If you are careful enough, you may notice that, the drivers/block directory also contains a USB-related driver code, which is drivers/block/ub. c. In fact, UB is a combination of the simplified USB-storage and SD modules. Its functions are relatively weak, but it must be more stable. If you are interested, read the code of the UB module.