I am USB in Linux, I am a USB flash drive (14) ice freezing is not a cold day

Source: Internet
Author: User
Tags 04x

 

Rome was not built in one day. Before making the USB flash drive work, we actually made a lot of preparations for the driver.

 

We continue to follow our feelings. storage_probe (), 972 to 975 rows, and a series of functions named init _ * are called at the moment. Here some lock mechanisms and wait mechanisms are involved, however, it is only initialization, but it is ignored for the time being. It will be explained later, but remember that each row of these lines is useful. It will be used later.

 

At this point, let's go down first, the associate_dev () of row 978 and the get_device_info () of row 989. These two functions need to be viewed at present.

 

First look at the associate_dev () function, defined in drivers/usb/storage/usb. c.

 

438/* Associate our private data with the USB device */

 

439 static intassociate_dev (struct us_data * us, struct usb_interface * intf)

 

440 {

 

441 US_DEBUGP ("-- % s \ n", _ FUNCTION __);

 

442

 

443/* Fill inthe device-related fields */

 

444 us-> pusb_dev = interface_to_usbdev (intf );

 

445 us-> pusb_intf = intf;

 

446 us-> ifnum = intf-> cur_altsetting-> desc. bInterfaceNumber;

 

447 US_DEBUGP ("Vendor: 0x % 04x, Product: 0x % 04x, Revision: 0x % 04x \ n ",

 

448 le16_to_cpu (us-> pusb_dev-> descriptor. idVendor ),

 

449 le16_to_cpu (us-> pusb_dev-> descriptor. idProduct ),

 

450 le16_to_cpu (us-> pusb_dev-> descriptor. bcdDevice ));

 

451 US_DEBUGP ("InterfaceSubclass: 0x % 02x, Protocol: 0x % 02x \ n ",

 

452 intf-> cur_altsetting-> desc. bInterfaceSubClass,

 

453 intf-> cur_altsetting-> desc. bInterfaceProtocol );

 

454

 

455/* Store our private data in theinterface */

 

456 usb_set_intfdata (intf, us );

 

457

 

458/* Allocate the device-related DMA-mapped buffers */

 

459 us-> cr = usb_buffer_alloc (us-> pusb_dev, sizeof (* us-> cr ),

 

460 GFP_KERNEL, & us-> cr_dma );

 

461 if (! Us-> cr ){

 

462 US_DEBUGP ("usb_ctrlrequest allocation failed \ n ");

 

463 return-ENOMEM;

 

464}

 

465

 

466 us-> iobuf = usb_buffer_alloc (us-> pusb_dev, US_IOBUF_SIZE,

 

467 GFP_KERNEL, & us-> iobuf_dma );

 

468 if (! Us-> iobuf ){

 

469 US_DEBUGP ("I/O buffer allocation failed \ n ");

 

470 return-ENOMEM;

 

471}

 

472

 

473 us-> sensebuf = kmalloc (US_SENSE_SIZE, GFP_KERNEL );

 

474 if (! Us-> sensebuf ){

 

475 US_DEBUGP ("Sense buffer allocation failed \ n ");

 

476 return-ENOMEM;

 

477}

 

478 return0;

 

479}

 

Let's first pay attention to the parameter of the associate_dev function, struct us_data * us, which is passed to us. We don't need to talk about it. We just applied for memory for it, and each initialization member is 0. This us will stay with us until our story ends. So its importance is self-evident. One of the two parameters passed in by the struct usb_interface * intf and storage_probe () functions.

 

In short, here we solemnly declare that the structus_data struct pointer is us, the struct usb_interface struct pointer intf, And the struct usb_device struct and the struct usb_device_id struct are unique in the story of the entire USB drive, that is what we mention every time. In the future, we will encounter several important data structures. struct urb and struct scsi_cmnd are also very important, but they are not unique. Maybe they are different every time, just like acting. The variables of the front-end data structures are like those of the leading actors. Even though they often show up, they are just mass actors, but this time they are only passers-by and next time they are passers-by B. Therefore, in the future, we will only talk about us, not structus_data * us, And structusb_interface * intf will also be replaced by intf.

 

The reason why us is important is that many functions need to use it and its members. In fact, what associate_dev does currently is to assign values to all members of us. After all, there is no relationship between us and the previously mentioned functions struct usb_device and struct usb_interface. Therefore, this function and several subsequent functions are designed to assign appropriate values to the members of us. The reason why we are so tempted to assign values to it is mainly because we will use it later. There is no free lunch in the world.

 

Line 3, I don't need to talk about it much, because it's just a debug statement, but I 'd like to mention the macro _ FUNCTION, in Versions later than GCC 2.95, this macro will be converted into a function name (string) during compilation. Here it is naturally the string "associate_dev, so when the function is executed here, a sentence will be printed to tell the world that we have implemented this function. This will obviously benefit the debugging program. But this is actually not a macro, because the pre-processor knows nothing about it. It can only be understood by the compiler.

 

Row 3, pusb_dev, indicates a member in point of usb device, struct us_data. According to the rules we have just agreed, I will say that it is a member of us, us-> pusb_dev = interface_to_usbdev (intf) and interface_to_usbdev as we have mentioned earlier, it means to convert the pointer of a struct interface struct into a struct usb_device struct pointer. As mentioned above, struct usb_device is useless to us, but some functions on the USB Core layer require this parameter, so we have to wait until we say that people cannot help ourselves.

 

Line 3: Assign intf to the pusb_intf of us.

 

Line 2, ifnum of us, first look at the cur_altsetting of intf, this is easy to confuse the layman. The USB device has a configuration, which we mentioned earlier, and there is another setting (setting ). A little strange, aren't these two words the same thing? Let's take our most familiar mobile phone for example. If you don't talk about the configuration, you just need to set it. Various configurations of a mobile phone may have been determined. For example, the vibration or ringtones are determined, and various functions are determined. However, the sound size can be changed. Generally, the volume of a mobile phone is changed one by one, it is about five or six cells, so this can be considered a setting. Cur_altsetting indicates the current setting. Cur_altsetting is a pointer to struct usb_host_interface. This struct is defined in include/linux/usb. h:

 

69/* host-side wrapper for one interfacesetting's parsed descriptors */

 

70 struct usb_host_interface {

 

71 struct usb_interface_descriptordesc;

 

72

 

73/* arrayof desc. bNumEndpoint endpoints associated with this

 

74 * interface setting. these will be in no participant order.

 

75 */

 

76 struct usb_host_endpoint * endpoint;

 

77

 

78 char * string;/* iInterface string, if present */

 

79 unsignedchar * extra;/* Extradescriptors */

 

80 intextralen;

 

81 };

 

Its member desc is a struct usb_interface_descriptor struct variable. The struct is defined as a direct correspondence with the USB protocol and defined as include/linux/usb/ch9.h. (The name ch9 is used here because many of the items in this file correspond to chapter 2.0 of USB spec 9th, chapter 9 .)

 

294/* USB_DT_INTERFACE: Interface descriptor */

 

295 struct usb_interface_descriptor {

 

296 _ u8 bLength;

 

297 _ u8 bDescriptorType;

 

298

 

299 _ u8 bInterfaceNumber;

 

300 _ u8 bAlternateSetting;

 

301 _ u8 bNumEndpoints;

 

302 _ u8 bInterfaceClass;

 

303 _ u8 bInterfaceSubClass;

 

304 _ u8 bInterfaceProtocol;

 

305 _ u8 iInterface;

 

306} _ attribute _ (packed ));

 

Here we mention bInterfaceNumber. A device can have multiple interfaces, so each interface must have a serial number. Otherwise, how can we differentiate it? All the things in these descriptors are fixed in the device edge at the factory time, and here we can use bInterfaceNumber to assign values, the reason is that USB Core has already completed these lessons when initializing the device. Otherwise, we will be unable to do so.

 

In short, us-> ifnum is like this, and eventually it is equal to the number of our current interface.

 

Lines 447 to 453 are two debugging statements that print more descriptor information, including the device descriptor and interface descriptor.

 

Line 2: usb_set_intfdata (). This is actually an inline function. It is just a line of code, which is also defined in include/linux/usb. h:

 

168 staticinline void usb_set_intfdata (struct usb_interface * intf, void * data)

 

169 {

 

170 dev_set_drvdata (& intf-> dev, data );

 

171}

 

Interestingly, the dev_set_drvdata function is also an inline function with only one line of code defined in include/linux/device. h:

 

491 static inline void

Includev_set_drvdata (struct device * dev, void * data)

493 {

494 dev-> driver_data = data;

495}

 

Therefore, in combination, the final task is to make & intf-> dev-> driver_data = data, that is, & intf-> dev-> driver_data = us.

 

Go down and apply for memory. Both us-> cr and us-> iobuf are pointers. Let them point to two segments of memory space, which will be used below. Note that the function usb_buffer_alloc () is provided by USB Core. You just need to call it. We can see from the name that it is used to apply for memory. The first parameter is the pointer of the struct usb_device struct, so we need to pass a pusb_dev. The third parameter, GFP_KERNEL is a flag applied for memory. This flag is usually used for Memory Applications. Unless the context is interrupted and cannot be sleep, GPF_ATOMIC is used. There are not many requirements here. The buffer size applied by the second parameter. For cr, sizeof (* us-> cr) is passed, while for iobuf, US_IOBUF_SIZE is passed. This is a macro, the size is 64, which is defined by us, from drivers/usb/storage/usb. h:

 

90 # define US_IOBUF_SIZE 64/* Size of the DMA-mapped I/O buffer */

 

91 # define US_SENSE_SIZE 18/* Size of the autosense data buffer */

 

The fourth parameter of usb_buffer_alloc () is very interesting. The first parameter we pass is & us-> cr_dma, and the second parameter is & us-> iobuf_dma, which involves DMA transmission. These two parameters are not previously assigned values. On the contrary, they are assigned values after the function is called. Both cr_dma and iobuf_dma are dma_addr_t variables, which are specially prepared for DMA transmission in the Linux kernel. To support DMA transmission, usb_buffer_alloc not only applies for addresses, but also establishes DMA ing. cr_dma and iobuf_dma are the dma addresses that record cr and iobuf. What is cr? What are the functions of these DMA addresses? We will meet you later. It will be no longer necessary to talk about these DMA addresses. Now we need to know that the space requested by usb_buffer_alloc is returned to cr and iobuf respectively. By the way, the memory space applied for with usb_buffer_alloc needs to be released with its partner usb_buffer_free.

 

For rows 461 and 468, check whether the memory is successful after each application. This is the Convention. The key to whether the driver can drive the device is to check whether the application can be applied for memory space. If the application fails to be applied for any memory space, the entire driver will not work properly.

 

In addition, we also saw 473 rows. We also applied for memory for us-> sensebuf. For sense buffer, let's wait until we talk about the SCSI command data transmission. Now we don't need to know about it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.