May 18, 2011
USB mass storage device (Mass Storage) is a file storage unit from the device (Gadget). In the master host (any control system) on it to form U-disk, in a Linux host from the device control system, it Gadget driver to form, from a communication device from the host device.
Gadget Mass Storage USB device is a typical example of the use Gadget drivers, it shows to adapt to increasing the throughput of the dual-buffer technique, gives the host a USB host device the detection of a large storage device drivers typical method.
large memory storage devices **** often raised by Chi Pu Qiang Zheng commanded the word Di ü? Candlestick ∠? File “choose large file storage device by the module option” ro “restricted access. If the optional module option” removable “, indicating whether it is a move to the media.
GadgetMass Storage Device Support Control – Bulk (CB Control-Bulk), Control – Bulk – interrupt (CBI Control-Bulk-Interrupt) and only the bulk (Bulk-Only) transmission, the optional “transport” module option Choose It also supports the following protocols: RBC (0×01), ATAPI, or SFF-8020i (0×02), QIC-157 (0c03), the optional “protocol” module option to choose.
large storage devices can have multiple logical unit (LUN), each file has its own LUN, LUN number of optional modules from the options “luns” (1 to
select the corresponding file with comma separated. ” file “or” or “a list of definitions from the default LUN number” file “to get the number of elements, if the” file “is not available, compared with 1 if the” removable “is not set, then each LUN must specify the file and if the “removable” is set, not defined or empty a file name means that the LUN media not loaded. large storage module options options described in Table 3. Module Option Description
file = filename [, filename ...] If the “removable” is not set, used to store the file or block device name is required.
ro = b [, b. ..] default is false, only read access to the logical value.
removable default is false, the logic values ??can be moved to the media.
luns = N The default value of N = the number of file names is supported by the LUN number.
transport = XXX Default value is BBB (Bulk-Only), transmission name (CB, CBI, or BBB) .
protocol = YYY Default is SCSI, the protocol name (RBC, 8020, or ATAPI, QIC, UFI, 8070, or SCSI, 1-6 items may also be supported).
vendor = 0xVVVV default value is 0×0525 (NetChip), USB suppliers ID.
product = 0xPPPP default value is 0xa4a5 (FSG), USB product ID.
< br /> release = 0xRRRR USB Release Number (bcdDevice).
buflen = N default N =, using the buffer size (page size is an integer multiple of).
stall in accordance with the type of USB device controller to determine the default value (usually true), whether the driver to stop bulk endpoints agreed to a logical value.
For the Gadget device, the minimum requirements are: only a bulk-in endpoint and one bulk-out is required (one interrupt-out is also necessary for CBI). The minimum memory requirement is two 16k buffer, parameters can be configured through the buffer size.
if not set CONFIG_USB_FILE_STORAGE_TEST compile-time option, only the “file”, “ro”, “removable”, and “luns” option is available,
file path name and ro Set in the sysfs filesystem gadget / lun subdirectory under the “ro” and “file” file attribute. If the “removable” option is set, write to these files will simulate up / install the media ( write a blank line means the pop-up) control when the media is loaded, “ro” is not promised to change the settings.
The Gadget drivers are based on Gadget Zero, SCSI (Small Computer System Inte *** ce) SCSI II command interface based on interface specifications, individual exceptions (such as: control code 0×23, the READ FORMAT CAPACITIES) based USB Mass Storage Class UFI Command Specification (Universal Serial Bus Mass Storage Class UFI Command Specification).
FSG (File Storage Gadget) driver design is very straightforward: it is a main thread with most of the work.
interrupt handling routine domain controller driver from the callback: block (bulk ) and interrupt request (interrupt) request completion notification (completion notification) event, ep0 events and disconnected events by calling the wake function wakeup, the event completion is transmitted to complete the main thread.
many ep0 request During the interrupt is processed, but set the interface SetInte *** ce, set the reset request and device configuration SetConfiguration by SIGUSR1 signal to “exception (exception)” in the form forwarded to the thread (as they should interrupt any ongoing file I / O manipulation).
thread main task is to achieve the standard SCSI commands interactively / data / status of the thread and it full of subroutine hang sigal / exception (signal / abnormal) test – all These options (polling) is necessary to determine, because the kernel does not command set jmp / longjmp equivalent statement.
long as the thread alive, it will keep a reference to a large storage device file, which will prevent rely on in a large storage device file system file unload (umount) and may be manipulated in such a closed system, caused the subject. In order to prevent these topics, threads to capture INT, TERM, and KILL signals and to manipulate them into EXIT exception.
normal manipulation of the thread, the thread in the Gadget of the fsg_bind () callback period started, and in fsg_unbind () during the stop, but it also can receive a signal out, and when the thread is dead time, so Gadget is no sense to run, so the thread exits before the cancellation Gadget drivers so there are two questions: first, the driver off in two places; second, is out of the thread should be able to indirectly, calling fsg_unbind (), fsg_unbind () should be able to tell the thread to exit sequence. The first topic identification through the use of atomic REGISTERED resolved, the driver will be canceled only once a second title by making fsg_unbind () check fsg-> state to solve, if the state has been set FSG_STATE_TERMINATED, it will not try to stop the thread.
In order to provide maximum throughput, the driver uses a buffer header (structure fsg_buffhd) ring line (circular pipeline) From the principle point of lines can be arbitrarily long, two commonly used in practice (eg: Double buffer), each buffer with a bulk-in head, and a bulk-out request pointer (because the buffer can be used as input in and out, transfer to the host point of view direction is always defined), head also points to the buffer cache and a variety of state parameters.
use the pipeline to follow a simple protocol, there is a parameter fsg -> next_buffhd_to_fill point to the next head of the buffer used in the first buffer at any time may still be using an earlier request, so each has a buffer header state parameter indicates that it is EMPTY, FULL, or BUSY. typical The first use is to wait for the buffer to EMPTY, file I / O or USB I / O to fill the buffer (the buffer header is BUSY period), when the I / O buffer header identifies the completion to FULL. then the buffer will be cleared empty (possibly again through USB I / O, this period marked as BUSY), and finally re-identified as EMPTY (possibly through completion routine).
on the state level to respond to the request ep0 there are some details to pay attention to. ep0 some, such as equipment reset request can interrupt an ongoing file I / O control, which may occur a long time in the delay period, the host may give the initial ep0 request and issue a new one. When the this occurs, the driver should inform the host the completion of the initial request, the host will not wait for it, so the driver ep0 request to each assigned a unique label, and maintain a long-running track and associated anomalies request of the label value (device reset, the interface changes or configuration changes) when exception processing is complete, only if the request tag that is currently ep0 unusual request label value, the state-level response is submitted, so that only recently received ep0 request get a state-level response.
FSG driver code including Gadget of the details of the deal, USB Mass Storage SCSI protocol handling and processing. code in the driver / usb / Gadget / file_storage.c in. large storage device object structure fsg_dev represents a large storage device, the character “fsg” is the abbreviation for File Storage and it continues to the base class structure of the USB usb_gadget, usb_ep, usb_request, including the transmission request, transmission buffer, SCSI command data block and thread tasks, etc. structure fsg_dev listed below: struct fsg_dev {spinlock_t lock; struct usb_gadget * gadget; / / large file storage device file to use semaphores to protect struct rw_semaphore filesem; struct usb_ep * ep0; / / gadget-> ep0 copy of the struct usb_request * ep0req; / / control request volatileunsignedint ep0_req_tag; / / control label request, identify the request of the expired constchar * ep0req_name; / / control request name struct usb_request * intreq; / / interrupt request volatileint intreq_busy; / / interrupt request busy struct fsg_buffhd * intr_buffhd; / / interrupt request buffer header unsignedint bulk_out_maxpacket; / / bulk_out the maximum packet size enum fsg_state state; / / set the state of exception handling unsignedint exception_req_tag; / / exception request label, identify the request of the expired u8 config, new_config ; unsignedint running: 1; unsignedint bulk_in_enabled: 1; unsignedint bulk_out_enabled: 1; unsignedint intr_in_enabled: 1; unsignedint phase_error: 1; unsignedint short_packet_received: 1; unsignedint bad_lun_okay: 1; unsignedlong atomic_bitflags; # define REGISTERED 0 # define CLEAR_BULK_HALTS 1 # define SUSPENDED 2 / / use the endpoint struct usb_ep * bulk_in; struct usb_ep * bulk_out; struct usb_ep * intr_in; struct fsg_buffhd * next_buffhd_to_fill; / / next fill bufferstruct fsg_buffhd * next_buffhd_to_drain; / / the next empty the bufferstruct fsg_buffhd buffhds [NUM_BUFFERS] ; / / Use two buffer wait_queue_head_t thread_wqh; int thread_wakeup_needed; / / need to wake up the thread struct completion thread_notifier; / / thread notifier int thread_pid; struct task_struct * thread_task; / / thread task sigset_t thread_signal_mask; / / threads signal mask int cmnd_size ; u8 cmnd [MAX_COMMAND_SIZE]; / / SCSI command data block length of 16enum data_direction data_dir; / ??/ data direction u32 data_size; u32 data_size_from_cmnd; u32 tag; unsignedint lun; u32 residue; u32 usb_amount_left; int cbbuf_cmnd_size; u8 cbbuf_cmnd [MAX_COMMAND_SIZE] ; / / length of the command buffer 16 unsignedint nluns; struct lun * luns; struct lun * curlun;};
structure fsg_buffhd the buffer header structure, it is the state of governance and the use of buffer The USB request buffer which lists the following structure: struct fsg_buffhd {void * buf; / / buffer pointer dma_addr_t dma; / / DMA address volatileenum fsg_buffer_state state; / / state is full, empty, busy. struct fsg_buffhd * next; unsignedint bulk_out_intended_length; struct usb_request * inreq; / / entered into the request volatileint inreq_busy; struct usb_request * outreq; / / output request volatileint outreq_busy;};
structure represents a logical unit lun, lun list structure as follows: struct lun {struct file * filp; loff_t file_length; / / file length loff_t num_sectors; / / number of sectors unsignedint ro: 1; unsignedint prevent_medium_removal: 1; unsignedint registered: 1; u32 sense_data; u32 sense_data_info; u32 unit_attention_data; struct device dev;};
function fsg_init registered driver structure instance fsg_driver, and activate the device controller functions as follows: staticstruct fsg_dev * the_fsg; staticstruct usb_gadget_driver fsg_driver; staticint __init fsg_init (void) {int rc; struct fsg_dev * fsg; if ((rc = fsg_alloc ())!= 0) return rc; fsg = the_fsg; / / register the driver and activate the device if ((rc = usb_gadget_register_driver (