cancel
Showing results for 
Search instead for 
Did you mean: 

USB FS device, MSC with more than one LUN, Windows: weird problem

Eugene Solo
Senior
Posted on November 27, 2017 at 14:01

I've successfully implemented MSC device on USB FS port, it works perfectly under Windows (7 and XP) and Linux (Ubuntu 16)...

...but only if MaxLun is 0.

I've implemented 3 independent storage devices (actually, all of them are RAM-drives, for debugging purposes; just with slightly different capacity), modified some functions, modified USB BOT handler so it could track status for each LUN independently. Under Linux, I've achieved write speed about 1MB/s with some code optimizations. I've tested all LUNs under linux by formatting/writing/copying files, by playback of MP3 and video; i've copied data from system disk to ramdrive and between ramdrives, in each possible combination.

In my debugging console I see INQUIRY requests for each LUN when device is connected to Linux host (it asks for maxlun and then sends INQUIRY to each of them). I see how Linux host poking each LUN for ready flag. But Windows hosts asks only LUN0 and never asks others, never tests them for anything.

I've found (by googling) that it may be problem with Device Serial number, but I have correct device descriptor with correct serial number : twelve utf16 chars, '000000000001'.

I guess, it may be problem with the Windows host itself, but I don't know how to diagnose it. More than that, i have cardreader device with 4 LUNs and it works perfectly under same windows host!

Any ideas?

14 REPLIES 14
Posted on February 09, 2018 at 02:21

Ok, thanks. In the meantime I figured out the problem. It seems the USB MSC driver from ST and the Windows driver do not communicate properly when using LUNs with different block size. 

Posted on February 09, 2018 at 11:23

On enumeration, Windows host asks for standard descriptors: device, configuration and strings. And when it asks for strings, one of the requests is obviously incorrect (or, as I said, it maybe just my own misunderstanding of correctness): it asks for string descriptor, but requests 2 byte response. Means, device should return only header of requested descriptor (length + type, but not contents).

This is actually a valid behavior for reading variable-size descriptors:

  1. Read just enough of the descriptor to get the field containing the total length of the descriptor.
  2. Allocate buffer for the complete descriptor.
  3. Read the entire descriptor with the previously determined actual length.

(The other approach is to request the descriptor with maximum length the first time.)

So this behavior is only incorrect if the second request doesn't arrive.

Posted on February 09, 2018 at 15:25

There are numerous problems with ST MSC code. First, single LUN support is hard-coded in at least 2 places, so you cannot increase the number of LUNs until you correct this. Second, you must change the way in which ST code handles inquiry requests to provide for independent data structure for each LUN. Third, ST code stores the geometry of the last inquired LUN and uses it to check the validity of parms for any LUN it operates on. In my case I completely rewrote the msc_if.c and made several changes to SCSI layer to make both units 'LUN-config-agnostic'. I have a structure for each LUN containing its parms, inquiry data and pointers to read/write/whatever functions.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Posted on February 09, 2018 at 16:37

Thank you. I also discovered these problems today, after debugging the weird behavior of the MSC driver when using 2 LUNs. My solution to the geometry problem was to update the LUN geometry in the MSC data structure at the beginning of each read/write request instead of creating separate data structures for each LUN. This only required changes in the SCSI layer.

Another problem I discovered while making these changes is that block IDs are transformed into absolute addresses in the SCSI layer, but saved into the same uint32_t variable - this does not perform as expected for data blocks located beyond the 4GB limit. Not cool.

Posted on February 22, 2018 at 10:01

It is correct and it is not correct in same time. Windows COULD ask for header only and wait for header only, but in fact it asks for header, but awaits for full length descriptor. Linux (distro I'm using) never asks for silly descriptors.