I am USB in Linux, I am a USB flash drive (19). Will it be far away in spring? (5)

Source: Internet
Author: User
After reading get_transport (), continue to read the get_protocol () and get_pipes () functions. Still from drivers/usb/storage/usb. c: 672staticintget_protocol (structus_data * us) 673 {674 switch (us-& gt; subclass) {675

 

After reading get_transport (), continue to read the get_protocol () and get_pipes () functions. Still from drivers/usb/storage/usb. c:

 

672 static int get_protocol (struct us_data * us)

 

673 {

 

674 switch (us-> subclass ){

 

675 caseUS_ SC _RBC:

 

676 us-> protocol_name = "Reduced Block Commands (RBC )";

 

677 us-> proto_handler = usb_stor_transparent_scsi_command;

 

678 break;

 

679

 

680 case US_ SC _8020:

 

681 us-> protocol_name = "8020i ";

 

682 us-> proto_handler = usb_stor_ATAPI_command;

 

683 us-> max_lun = 0;

 

684 break;

 

685

 

686 caseUS_ SC _QIC:

 

687 us-> protocol_name = "QIC-157 ";

 

688 us-> proto_handler = usb_stor_qic157_command;

 

689 us-> max_lun = 0;

 

690 break;

 

691

 

692 caseUS_ SC _8070:

 

693 us-> protocol_name = "8070i ";

 

694 us-> proto_handler = usb_stor_ATAPI_command;

 

695 us-> max_lun = 0;

 

696 break;

 

697

 

698 caseUS_ SC _SCSI:

 

699 us-> protocol_name = "Transparent SCSI ";

 

700 us-> proto_handler = usb_stor_transparent_scsi_command;

 

701 break;

 

702

 

703 caseUS_ SC _UFI:

 

704 us-> protocol_name = "Uniform Floppy Interface (UFI )";

 

705 us-> proto_handler = usb_stor_ufi_command;

 

706 break;

 

707

 

708 # ifdef CONFIG_USB_STORAGE_ISD200

 

709 case US_ SC _ISD200:

 

710 us-> protocol_name = "ISD200 ATA/ATAPI ";

 

711 us-> proto_handler = isd200_ata_command;

 

712 break;

 

713 # endif

 

714

 

Default 715:

 

716 return-EIO;

 

717}

 

718 US_DEBUGP ("Protocol: % s \ n", us-> protocol_name );

 

719 return 0;

 

720}

 

This code is easy to understand. It is determined by us-> subclass. For a USB flash drive, spec specifies that its SubClass is US_ SC _SCSI, so here is two assignment statements: one is to make us protocol_name "Transparent SCSI ", the other is to set us proto_handler to usb_stor_transparent_scsi_command, which is a function pointer.

 

Then get_pipes (), from drivers/usb/storage/usb. c:

 

723 static int get_pipes (struct us_data * us)

 

724 {

 

725 structusb_host_interface * altsetting =

 

726 us-> pusb_intf-> cur_altsetting;

 

727 int I;

 

728 struct usb_endpoint_descriptor * ep;

 

729 struct usb_endpoint_descriptor * ep_in = NULL;

 

730 struct usb_endpoint_descriptor * ep_out = NULL;

 

731 structusb_endpoint_descriptor * ep_int = NULL;

 

732

 

733 /*

 

734 * Find the first endpoint of each type we need.

 

735 * We are expecting a minimum of 2 endpoints-in and out (bulk ).

 

736 * An optional interrupt-in is OK (necessary for CBI protocol ).

 

737 * We will ignore any others.

 

738 */

 

739 for (I = 0; I desc. bNumEndpoints; I ++ ){

 

740 ep = & altsetting-> endpoint [I]. desc;

 

741

 

742 if (usb_endpoint_xfer_bulk (ep )){

 

743 if (usb_endpoint_dir_in (ep )){

 

744 if (! Ep_in)

 

745 ep_in = ep;

 

746} else {

 

747 if (! Ep_out)

 

748 ep_out = ep;

 

749}

 

750}

 

751

 

752 else if (usb_endpoint_is_int_in (ep )){

 

753 if (! Ep_int)

 

754 ep_int = ep;

 

755}

 

756}

 

757

 

758 if (! Ep_in |! Ep_out | (us-> protocol = US_PR_CBI &&! Ep_int )){

 

759 US_DEBUGP ("Endpoint sanity check failed! Rejectingdev. \ n ");

 

760 return-EIO;

 

761}

 

762

 

763/* Calculate and store the pipevalues */

 

764 us> send_ctrl_pipe = usb_sndctrlpipe (us-> pusb_dev, 0 );

 

765 us-> recv_ctrl_pipe = usb_rcvctrlpipe (us-> pusb_dev, 0 );

 

766 us-> send_bulk_pipe = usb_sndbulkpipe (us-> pusb_dev,

 

767 ep_out-> bEndpointAddress & USB_ENDPOINT_NUMBER_MASK );

 

768 us-> recv_bulk_pipe = usb_rcvbulkpipe (us-> pusb_dev,

 

769 ep_in-> bEndpointAddress & USB_ENDPOINT_NUMBER_MASK );

 

770 if (ep_int ){

 

771 us-> recv_intr_pipe = usb_rcvintpipe (us-> pusb_dev,

 

772 ep_int-> bEndpointAddress & USB_ENDPOINT_NUMBER_MASK );

 

773 us-> ep_bInterval = ep_int-> bInterval;

 

774}

 

775 return 0;

 

776}

 

This function can be said to be a complicated one. Please let me give you a try.

 

Row 3, us-> pusb_intf. remember the value assigned in associate_dev. if you do not remember it, check it again. That's right, us-> pusb_intf is the interface (pointer) that we mentioned most often in our story ). Its member cur_altsetting is the current setting. I have also encountered this problem when talking about associate_dev. it is a struct pointer of structusb_host_interface. Now we use another pointer to temporarily replace altsetting. Next we will use its members desc and endpoint.

 

Looking back at structusb_host_interface, we can see its two members: struct usb_interface_descriptor desc and struct usb_host_endpoint * endpoint. Among them, desc is needless to say, it is the interface descriptor of this interface, and the endpoint pointer records several endpoints, they are stored in the form of an array, and the endpoint points to the array header. These are all set during USB Core enumeration. we don't need to worry about them, just use them. The definition of struct usb_host_endpoint is provided here, from include/linux/usb. h:

 

59 struct usb_host_endpoint {

 

60 structusb_endpoint_descriptor desc;

 

61 structlist_head urb_list;

 

62 void * hcpriv;

 

63 struct ep_device * ep_dev;/* For sysfs info */

 

64

 

65 unsigned char * extra;/* Extra descriptors */

 

66 intextralen;

 

67 };

 

Then we define several struct pointers of struct usb_endpoint_descriptor. As the name suggests, this is the descriptor of the corresponding endpoint. The definition is from include/linux/usb/ch9.h:

 

312/* USB_DT_ENDPOINT: Endpoint descriptor */

 

313 struct usb_endpoint_descriptor {

 

314 _ u8 bLength;

 

315 _ u8 bDescriptorType;

 

316

 

317 _ u8 bEndpointAddress;

 

318 _ u8 bmAttributes;

 

319 _ le16wMaxPacketSize;

 

320 _ u8 bInterval;

 

321

 

322/* NOTE: these two are _ only _ in audio endpoints .*/

 

323/* use USB_DT_ENDPOINT * _ SIZE inbLength, not sizeof .*/

 

324 _ u8 bRefresh;

 

325 _ u8 bSynchAddress;

 

326} _ attribute _ (packed ));

 

So far, the four descriptors are made one by one. before proceeding, let's make a conclusion: What is a descriptor? Each USB device has four descriptors. here we use a USB flash drive as an example. Have you heard of Flash Memory? Intel, Samsung, these are Flash Memory, of course, usually referred to as Flash. What role does Flash play in a USB Flash disk? Flash is used to store data for users, and Flash in a USB Flash disk is equivalent to a hard disk in a PC, which stores data mainly. In addition to storing data for users, the device also needs to store some inherent information of the device itself. for example, who is the last name of the device? Who produced it? There is still some information. for example, the device has several configurations, several interfaces, and many other features.

 

In this world, apart from Flashmemory, there is also an object called EEPROM, which is also used for storage. it is the predecessor of EEPROM, flash is a low-cost ROM product developed based on the EEPROM technology.

 

The same as Flash, the EEPROM requires an electrical erasure, but the EEPROM can be erased in bytes, unlike Flash, in this way, it is convenient to use the EEPROM only when few data changes are required. Therefore, this feature of EEPROM makes its circuit more complex and the integration is not high. one bit requires two tubes: one to store the charge information and the other to act as the switch. Therefore, the cost of EEPROM is high. Flash simplifies some circuits and reduces the cost a lot.

 

Therefore, the USB device usually has a Flash chip and an EEPROM chip. Flash is used to store data for customers, while EEPROM is used to store information of devices. This is why when Intel sells Flash chips to Motorola, the mobile phone manufacturer we see is Motorola rather than Intel, because although we wrote our vendor ID in Flash, however, for the final finished products, the provided information is from the EEPROM, so when you connect the USB device to the computer through the USB interface, if the computer can display the manufacturer, so it must be the final packaging manufacturer, rather than the Flash manufacturer. What is written in the EEPROM? In what format? This is exactly what USB spec stipulates. this format is the descriptor format. Device descriptors, configuration descriptors, interface descriptors, endpoint descriptors, and other device-specific descriptors of certain categories, such as Hub descriptors, are very standard, in particular, each USB device supports these four standard descriptors. Therefore, the USB Core layer can read them with the same code, instead of letting our device drivers read them by themselves. this is the benefit of centralized power, everything everyone has to do is simply let the above-mentioned items be done together.

 

Rows from 739 to 756 are in a loop. bNumEndpoints is a member of the interface descriptor, indicating the number of endpoints of this interface. However, this does not include endpoint 0, endpoint 0 must be provided by any USB device. this endpoint is used for control transmission, that is, it is a control endpoint. Because of this, even if a device does not have any settings, the USB host can start to communicate with it, even if it does not know other endpoints, but at least know that it must have a zero-number endpoint, or a control endpoint.

 

In addition, USB Mass Storage usually has two batch endpoints for batch transmission, that is, batch transmission. We read and write files in the USB flash drive in batches. Therefore, there is no doubt that for the Mass Storage device, batch transmission is its main way of working. The principle is very simple. We use a USB flash disk to read and write files. Dealing with these descriptors is nothing more than helping us ultimately achieve file read and write, which is the true mission of every USB storage device.

 

So let's take a look at what the Loop is doing. altsetting-> endpoint [I]. desc, we can see from the definition of the struct usb_host_endpoint, that is, desc is a variable of struct usb_endpoint_descriptor. We have just defined four pointers for such struct: ep, ep_in, ep_out, and ep_int. it is very simple. it is used to record the endpoint descriptor. ep_in is used to Bulk-IN, and ep_out is used to Bulk-OUT, ep_int is used to record the interrupt endpoint (if any ). While ep is just a temporary pointer.

 

Let's take a look at structusb_endpoint_descriptor. in its members, bmAttributes represents an attribute with a total of eight bits. bit1 and bit0 are collectively referred to as Transfer Type, that is, transmission Type, 00 indicates control, 01 indicates, and so on, 10 indicates batch processing, and 11 indicates interruption. Therefore, by comparing these members, you can determine the transmission type of the endpoint. this function usb_endpoint_xfer_bulk () is defined in include/linux/usb. h:

 

571 static inline int usb_endpoint_xfer_bulk (conststruct usb_endpoint _ descriptor * epd)

 

572 {

 

573 return (epd-> bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) =

 

574 USB_ENDPOINT_XFER_BULK );

 

575}

 

The macro USB_ENDPOINT_XFERTYPE_MASK is defined in include/linux/usb/ch9.h:

 

338 # define USB_ENDPOINT_XFERTYPE_MASK 0x03/* in bmAttributes */

 

339 # define USB_ENDPOINT_XFER_CONTROL 0

 

340 # define USB_ENDPOINT_XFER_ISOC 1

 

341 # define USB_ENDPOINT_XFER_BULK 2

 

342 # define USB_ENDPOINT_XFER_INT 3

 

From the preceding annotations, we can see that row 742 is used to determine whether the description of this endpoint descriptor is a batch endpoint. If yes, continue the comparison. Let's first look at bEndpointAddress. another member of this struct usb_endpoint_descriptor is also eight bits, or one Byte. bit7 indicates the direction of this endpoint, 0 indicates OUT, and 1 indicates IN. The OUT and IN are for the host, the OUT is from the host to the device, and the IN is from the device to the host. Therefore, you can compare this member to determine the direction of the endpoint. the Function usb_endpoint_dir_in () for this task also comes from include/linux/usb. h:

 

549 static inline int usb_endpoint_dir_in (conststruct usb_endpoint _ descriptor * epd)

 

550 {

 

551 return (epd-> bEndpointAddress & USB_ENDPOINT_DIR_MASK) = USB_DIR_IN );

 

552}

 

Macro USB_DIR_IN and USB_ENDPOINT_DIR_MASK are still from include/linux/usb_ch9.h:

 

48 # define USB_DIR_OUT 0/* to device */

 

49 # define USB_DIR_IN 0x80/* to host */

 

336 # define USB_ENDPOINT_DIR_MASK 0x80

 

Therefore, it is obvious to point ep_in and ep_out to the specified endpoint descriptor.

 

In the next row, usb_endpoint_is_int_in () comes from include/linux/usb. h:

 

646 static inline int usb_endpoint_is_int_in (conststruct usb_endpoint _ descriptor * epd)

 

647 {

 

648 return (usb_endpoint_xfer_int (epd) & usb_endpoint_dir_in (epd ));

 

649}

 

With the above two functions as the basis, this function will no longer need to be mentioned. In short, the else if function in row 752 is to let the ep_int point to the interrupt endpoint if the endpoint is the interrupt endpoint. We have said that each type of USB device has an uncertain number of endpoints on it and must comply with the specifications of such devices. the USB Mass Storage Specification specifies that, a usb Mass Storage device must have at least two bulk endpoints, which are obviously required. Undoubtedly, there may be an Interrupt endpoint, which supports the CBI protocol, that is, the Control/Bulk/Interrupt protocol. We have also said that the USB flash drive complies with the Bulk-only protocol and does not require an interrupt endpoint.

 

There is nothing to say about the code from lines 758 to lines 761. it is unreasonable to determine whether ep_in or ep_out exists, or whether it complies with the CBI protocol but does not interrupt the endpoint. of course, errors will occur!

 

There is a small piece of code left. let's look at it in the next section. It should be said that after this function is completed, we will start the most exciting part. it is the great usb_stor_acquire_resources (). Darkness is approaching, and Dawn has taken us on the road. Let's look forward to it together. At the same time, let's make a summary. previously we spent a lot of space to pave the way for usb_stor_acquire_resources (). let's review what it did?

 

First, we start from storage_probe and call a total of five functions, which are assocaite_dev, get_device_info, get_transport, get_protocol, and get_pipes. What is our purpose? It is very simple to build a data structure. it is the legendary struct us_data, and its name is us. We have built it, applied for memory for it, and assigned values to its elements, so that we can make good use of it in the future.

 

These five functions are not difficult, and you must write them. What's hard is how to define struct us_data. Don't forget that this data structure was designed by code writers for the usb-storage module. The so-called programming is nothing more than adding algorithms to the data structure. That's right. this is defined in drivers/usb/storage/usb. the data structure in h is up to 60 rows. we still haven't met many of her members, but don't worry. we will see it later. Well, although get_pipes has not been mentioned for a short time, we can say goodbye to the five functions in advance. Xi Murong said that if we have to separate them, we should say goodbye, I also want to save a thank you in my heart. thank you for giving you a memory.

Related Article

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.