Page 1 of 1

USB Mass Storage Big Endian?

Posted: Wed Jan 27, 2016 9:41 pm
by SpyderTL
I was just about to post a message asking why I am getting junk back from my USB CD-ROM device when I send a SCSI READ CAPACITY 10 (0x25) command, but then it hit me that the information is correct, but the bytes are in reverse order.

I'm using OHCI, and giving the IN bulk endpoint a memory buffer of 8 bytes. Unless the SCSI spec says that the response should be big endian, I have no idea how this is possible. Surely the USB controller isn't swapping bytes on the fly...

Googling for "SCSI big endian little endian", first hit says:
Other CPUs, such as the Sun SPARC system, IBM's PowerPC, and Hewlett-Packard Precision Architecture systems, as well as SCSI devices and network protocols use a "big endian" model, where the most significant byte is at the lowest address in memory.
Sonofa........ okay. I'm going to edit the Wiki page tonight to add a SCSI page, that simply says "SCSI devices are Big Endian", and click save. :)

Okay... second question. The Bulk-Only USB Mass Storage Device specifications state that:
The CBW shall start on a packet boundary and shall end as a
short packet with exactly 31 (1Fh) bytes transferred. Fields
appear aligned to byte offsets equal to a multiple of their byte
size. All subsequent data and the CSW shall start at a new
packet boundary.

The CSW shall start on a packet boundary and shall end as a short packet with exactly 13 (0Dh) bytes
transferred. Fields appear aligned to byte offsets equal to a multiple of their byte size.
I'm not exactly sure what this is trying to say, as it is a little ambiguous. Is it saying that, in my case (SCSI READ CAPACITY above), I should send 31 bytes to the OUT endpoint, then read 8 bytes from the IN endpoint to get the data from the SCSI device, then read 13 bytes from the IN endpoint to get the status block from the USB device?

I tried sending 31 bytes to the OUT endpoint, and reading 21 bytes from the IN endpoint, and the command failed.

What do the specs above mean by "shall start on a packet boundary", if the out packet is 31 bytes, the response data is 8 bytes, and the response status block is 13 bytes? Does it mean that I should read 13 data bytes as well, so that it will be "aligned"? (I highly doubt that...)

Thanks, guys.

Re: USB Mass Storage Big Endian?

Posted: Thu Jan 28, 2016 2:25 pm
by shmx
SpyderTL wrote:I was just about to post a message asking why I am getting junk back from my USB CD-ROM device when I send a SCSI READ CAPACITY 10 (0x25) command, but then it hit me that the information is correct, but the bytes are in reverse order.
Yes, SCSI command params are big endian.
SpyderTL wrote:I'm using OHCI, and giving the IN bulk endpoint a memory buffer of 8 bytes
Why 8?
SpyderTL wrote:I should send 31 bytes to the OUT endpoint, then read 8 bytes from the IN endpoint to get the data from the SCSI device, then read 13 bytes from the IN endpoint to get the status block from the USB device?
Yes.
My code:

Code: Select all

static DWORD USBHDDGetLBASize(USB_HDD_DRIVE *Drive)
{
	USB_MASS_STORAGE_CBW cmd;
	USB_MASS_STORAGE_SCSI10 *scsi;
	USB_MASS_STORAGE_CSW result;
	USB_HOST_INTERFACE *host;
	DWORD capacity[2];
	
	scsi = (USB_MASS_STORAGE_SCSI10 *)cmd.CBWCB;
	cmd.dCBWSignature = 0x43425355;
	cmd.dCBWTag = 0;
	cmd.bmCBWFlags = 0x80;
	cmd.bCBWLUN = 0;
	cmd.bCBWCBLength = sizeof(*scsi);
	cmd.dCBWDataTransferLength = sizeof(capacity);
	scsi->LUN = 0;
	scsi->Control = 0;
	scsi->Res = 0;
	scsi->LBA = 0;
	scsi->OpCode = 0x25;
	scsi->Length = sizeof(capacity);
	host = Drive->Device->HostInterface;
	if(!host->USBSendBulkPackage(Drive->Device, Drive->BulkEndPointOUT, 1, &cmd, sizeof(cmd)))
		return 0;
	if(!host->USBSendBulkPackage(Drive->Device, Drive->BulkEndPointIN, 0, capacity, sizeof(capacity)))
		return 0;
	if(!host->USBSendBulkPackage(Drive->Device, Drive->BulkEndPointIN, 0, &result, sizeof(result)))
		return 0;
	if( (result.dCBWSignature != 0x53425355) || (result.bCSWStatus != 0) )
		return 0;
	return swap_32(capacity[0]);
}
I'm not sure that the command applies to CD-ROM (why is it needed? 2016 already). With USB HDD this command working.

Re: USB Mass Storage Big Endian?

Posted: Thu Jan 28, 2016 2:54 pm
by SpyderTL
shmx wrote:
SpyderTL wrote:I'm using OHCI, and giving the IN bulk endpoint a memory buffer of 8 bytes
Why 8?
The same reason you are using an 8 byte buffer. :)

Code: Select all

	DWORD capacity[2];
	scsi->Length = sizeof(capacity);
shmx wrote:I'm not sure that the command applies to CD-ROM (why is it needed? 2016 already).
If for nothing else, I want to be able to play Audio CDs :)
shmx wrote:With USB HDD this command working.
Cool.. That's exactly what I needed.

Thanks.

Re: USB Mass Storage Big Endian?

Posted: Thu Jan 28, 2016 3:15 pm
by shmx
SpyderTL wrote:The same reason you are using an 8 byte buffer.
Now I understand what you mean.