Search This Blog

May 20, 2013

How to implement USB Mass Storage Class on SiM3U1xx

1.       Introduction.
The USB mass storage device class, otherwise known as USB MSC or UMS, is a protocol that allows a Universal Serial Bus (USB) device to become accessible to a host computing device, to enable file transfers between the two. To the host device, the USB device appears similar to an external hard drive, enabling drag-and-drop file transfers.
The USB mass storage device class comprises a set of computing communications protocols defined by the USB Implementers Forum that run on the Universal Serial Bus. The standard provides an interface to a variety of storage devices.

2.       USB Mass Storage Class.
2.1.  We can find all Mass Storage Class documentation from USB Below are the list of the documentations.  Download them all into your local driver.

We can there are several specifications, which on should we take? We can have an example to go through it.

2.2. Get USB mass storage example code.
As we plan to implement USB Mass Storage Class base on LUFA on SiM3U1xx, first we can get source code from

2.2.1 Let's check descriptors.c.  In configuration descriptor, we have blow setting.

const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.MS_Interface =
.Class            = MS_CSCP_MassStorageClass,  // 0x8
.SubClass         = MS_CSCP_SCSITransparentSubclass, //0x06
.Protocol         = MS_CSCP_BulkOnlyTransportProtocol, //0x50

·         For Class =0x08, that means this is Mass Storage Class;

·         For SubClass = 0x06,  Let's check Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf, here is the table
Here is definition of SubClass:
  The Interface Descriptor of a USB Mass Storage Class device includes a bInterfaceSubClass field. This field
denotes the industry-standard command set transported by a Mass Storage Class interface. The value of the
bInterfaceSubClass field shall be set to one of the Subclass codes as shown in table 1.
The Subclass code values used in the bInterfaceSubClass field specify the industry-standard specification that
defines transport command sets transported by the interface; these Subclass codes do not specify a type of
storage device (such as a CD-ROM or floppy disk drive).
From above table, we know that our command set is "SCSI transparent command set"

·         For Protocol = 0x50, we can find below descriptions from Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf.
The Interface Descriptor of a USB Mass Storage Class device includes a bInterfaceProtocol field. This field
denotes the transport protocol used by this interface.
The USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport specification (Protocol codes 0x00 and
0x01) is approved for use only with full-speed floppy disk drives. CBI shall not be used in high-speed capable
devices, or in devices other than floppy disk drives. Usage of CBI for any new design is discouraged.
From above table, we can know protocol implementation is "USB Mass Storage Class Bulk-Only(BBB) Transport"

2.2.2 Control request for bulk-only transport, in masstorage.c
void EVENT_USB_Device_ControlRequest(void)
/* Process UFI specific control requests */
switch (USB_ControlRequest.bRequest)
case MS_REQ_MassStorageReset:  //0xFF
case MS_REQ_GetMaxLUN: // 0xFE

These two requests can be found in Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf also.
Core USB specifies that a USB control Request addressed to wIndex = bInterfaceNumber of a USB Mass
Storage Class device interface includes a bRequest field.
The meaning of the bRequest code is specific to the device vendor when the bmRequestType. Type is Vendor,
but the meaning of the bRequest code is specific to the interface class when the bmRequestType.Type is Class.

And we know for the BBB transport protocol, we need to support 0xFE and 0xFF requests.

·         USB mass storage bulk only
Since we choose USB bulk-only(BBB) transport, the specification should be usbmassbulk_10.pdf.  Let's have a  look on it.
This specification addresses Bulk-Only Transport, or in other words, transport of command, data, and status
occurring solely via Bulk endpoints (not via Interrupt or Control endpoints). This specification only uses the
default pipe to clear a STALL condition on the Bulk endpoints and to issue class-specific requests as defined
below. This specification does not require the use of an Interrupt endpoint.

3.1.  Bulk-Only Mass Storage Reset (class-specific request)
This request is used to reset the mass storage device and its associated interface.

3.2 Get Max LUN (class-specific request)
The device may implement several logical units that share common device characteristics.

3.3. Host/Device Packet Transfer Order
The host shall send the CBW before the associated Data-Out, and the device shall send Data-In after the
associated CBW and before the associated CSW. The host may request Data-In or CSW before sending the
associated CBW.
If the dCBWDataTransferLength is zero, the device and the host shall transfer no data between the CBW and the
associated CSW.

3.4. Command Queuing
The host shall not transfer a CBW to the device until the host has received the CSW for any outstanding CBW.
If the host issues two consecutive CBWs without an intervening CSW or reset, the device response to the second
CBW is indeterminate.

3.5. Bi-Directional Command Protocol
This specification does not provide for bi-directional data transfer in a single command.

3.6 Standard Descriptors
Just get reference from Chapter 4, compare with Descriptors.c in demo code.

3.7 Command/Data/Status Protocol

3.7.1 Command Block Wrapper (CBW)
The CBW shall start on a packet boundary and shall end as a short packet with exactly 31 (1Fh) bytes transferred.

  The command block to be executed by the device. The device shall interpret the first bCBWCBLength bytes in this field as a command block as defined by the command set identified by bInterfaceSubClass. If the command set supported by the device uses command blocks of fewer than 16 (10h) bytes in length, the significant bytes shall be transferred first, beginning with the byte at offset 15 (Fh). The device shall ignore the content of the CBWCB field past the byte at offset (15 + bCBWCBLength - 1).

3.7.2 Command Status Wrapper (CSW)
The CSW shall start on a packet boundary and shall end as a short packet with exactly 13 (0Dh) bytes transferred.

·         dCSWDataResidue:
For Data-Out the device shall report in the dCSWDataResidue the difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResidue the difference between the amount of data expected as stated in the dCBWDataTransferLength and the actual amount of relevant data sent by the device. The dCSWDataResidue shall not exceed the value sent in the dCBWDataTransferLength.

·         bCSWStatus:
bCSWStatus indicates the success or failure of the command. The device shall set this byte to zero if the command completed successfully. A non-zero value shall indicate a failure during command execution according to the  following table:

3.8. Host/Device Data Transfers
A Bulk-Only Protocol transaction begins with the host sending a CBW to the device and attempting to make the
appropriate data transfer (In, Out or none). The device receives the CBW, checks and interprets it, attempts to
satisfy the host's request, and returns status via a CSW.

·         Valid and Meaningful CBW
The host communicates its intent to the device through the CBW. The device performs two verifications on
every CBW received. First, the device verifies that what was received is a valid CBW. Next, the device
determines if the data within the CBW is meaningful.
The device shall not use the contents of the dCBWTag in any way other than to copy its value to the dCSWTag of
the corresponding CSW.

·         Valid and Meaningful CSW
The device generally communicates the results of its attempt to satisfy the host’s request through the CSW. The
host performs two verifications on every CSW received. First, the host verifies that what was received is a valid
CSW Next, the host determines if the data within the CSW is meaningful.

·         Error Handling and The Thirteen Cases
Please refer 6.4 - 6.7 in usbmassbulk_10.pdf.

·         SCSI command set
From configuration descriptors, we choose SCSI transparent command set. But What is the SCSI transparent command set? Refer to

In the Mass Storage Class Specification Overview, Table 2.1 says that devices with subclass code 06h implement the "SCSI transparent command set." The SCSI specifications are available from, but these documents don't mention a transparent command set.

According to the inventor of the subclass, subclass 06h means that the host should determine the device type by issuing a SCSI INQUIRY command. In the returned INQUIRY data, bits 4..0 of byte 0 specify a peripheral device type (PDT). The SCSI Primary Commands (SPC) specification defines various PDTs and the specifications they should comply with.

New designs should use bInterfaceSubClass = 06h (SCSI transparent command set).  The device's response to a SCSI INQUIRY command is then the single source where the device declares its command set (via the PERIPHERAL DEVICE TYPE (PDT) and VERSION codes). 

What commands should my device support?
In the response to a SCSI INQUIRY command, a device returns a PERIPHERAL DEVICE TYPE code and a VERSION code. For hard drives, flash drives, and similar devices, PERIPHERAL DEVICE TYPE = 00h (direct access block device) and VERSION = 04h (SPC-2) or 05h (SPC-3). The code in the VERSION corresponds to a command set, and the command set's specification lists mandatory commands.

So, we choose SPC-2 (04h), not like 00h in LUFA mass storage demo code.

4.1 SPC-2 specification.
Goto T10 org, found the documentation,  but it requires membership which I don't have. Google it and find below link works.

4.2. Inquiry Command
Let check Inquiry command definition in spc2r20.pdf. The INQUIRY command (see table 45) requests that information regarding parameters of the target and a component logical unit be sent to the application client.

If both the EVPD and CMDDT bits are zero, the device server shall return the standard INQUIRY data .
When the EVPD bit is one, the PAGE OR OPERATION CODE field specifies which page of vital product data  information the device server shall return.

The Device type and Version:

Now we have done with Inquiry command.

In practice, we got READ FORMAT CAPACITIES(23h) from Windows which don't defined in spc2 spec. Also no implemented by mass storage demo code. And code will stall the endpoint. Command 23h is READ FORMAT CAPACITIES in the Multimedia Commands (MMC) specification from We can a little information in spc2r20.pdf.
From above table, we can see READ FORMAT CAPACITIES belong to MMC-2
The READ FORMAT CAPACITIES command (Table 271) allows the Initiator to request a list of the possible format capacities for an installed random-Writable media. This command also has the capability to report the capacity for a media when it is installed.

4.4. SCSI Read 10 and Write 10 command
We won't find these two commands in spc2 spec, however, Windows indeed read/write removal disk by these two commands. We can get descriptions from below link.

·         The READ (10) command (see table 90) requests that the device server read the specified logical block(s) and
transfer them to the data-in buffer.

The WRITE (10) command (see table 189) requests that the device server transfer the specified logical
block(s) from the data-out buffer and write them.

This command also cannot find in SPC2 spec, and we can find it in
The READ CAPACITY (10) command (see table 108) requests that the device server transfer 8 bytes of parameter data describing the capacity and medium format of the direct-access block device to the data-in buffer.

4.6 SCSI other commands
  In SPC2 spec, we can find other SCSI commands.

·         Modification in source code.
Now, we need implement all above into the USB mass storage demo. Of course, most of the protocol has been done. But it cannot run unless we make modifications.

5.1. In SCSI.c,
·          Change Inquiry data
Change version from 0 to 4, which choose SPC-2. Also change strings of VendorID, ProductID, RevisionID.
·         Add page Inquiry data
Add it for non-standard Inquiry request.
static uint8_t Page_Inquiry_Data[] =
Also modify SCSI_Command_Inquiry() to handle non-standard request.
Add function to handle this command.
·         Add external global variables sector_count and sector_size which store SD card size and page size.
·         Change Read10 and Write10 function,
Replace dataflash read/write with SD card read/write functions. Change the handle routine according the interrupt driven method.

5.2 In Descriptors.c
Change the VID/PID, and strings accordingly.

5.3 In MassStorage.c
·         Change hardware initialization function.
·         Change USB CBW handler routine from polling mode to interrupt state driven
void EVENT_USB_common_request(void) call from USB interrupt handler.

·         Validation.
Build project, download firmware into SiM3U167 board. PC appear a disk icon. Right click on it, select format disk. It format successful. Read/Write large data, Read:400KBytes, Write:240KBytes. Capture the enumeration stage USB protocol. 

7.       Source code