Search code examples
cembeddedusb

Understanding and decoding of standard USB commands to endpoint zero?


I'm trying to write USB initialization routine for 8 bit RISC MCU. Datasheet link given below.

My goal is to write device prototype code, which will let host to enumerate successfully my device and send/receive data.

In the SDK of this IC there is a UFI static library without sources, which has only few functions defined in the header file:

//
// Command/Data/Status Protocol
//
typedef struct _CBW // Command Block Wrapper
{
    unsigned char dSignature[4];    // 43425355h (little endian)
    unsigned char dTag[4];
    unsigned char dDataTransferLength[4];
    unsigned char bmFlags;          // Bit 7    0 = Data-Out from host to the device.
                                    //          1 = Data-In from the device to host.
                                    // Bit 6    Obsolete
    unsigned char bLUN;
    unsigned char bCBLength;
    unsigned char CB[0x10];         // offset: (15 + bCBLength - 1)
} CBW;
typedef struct _CSW // Command Status Wrapper
{
    unsigned char dSignature[4];    // 53425355h (little endian)
    unsigned char dTag[4];
    unsigned char dDataResidue[4];
    unsigned char bStatus;          // 00h  Command Passed ("good status")
                                    // 01h  Command Failed
                                    // 02h  Phase Error
                                    // 03h and 04h  Reserved (Obsolete)
} CSW;

#define COMMAND_PASSED 0x00
#define COMMAND_FAILED 0x01
#define PHASE_ERROR    0x02

enum
{
UFI_MODE_TIMESYNC = 1,
UFI_MODE_DOWNSTART,
UFI_MODE_DOWNFINISH,
UFI_MODE_IGNORE,
UFI_MODE_NORMAL
};

//
// UFI Command
//
#define INQUIRY                      0x12
#define READ_FORMAT_CAPACITIES       0x23
#define READ_CAPACITY                0x25
#define READ_10                      0x28
#define REQUEST_SENSE                0x03
#define TEST_UNIT_READY              0x00
#define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
#define WRITE_10                     0x2a
#define VERIFY                       0x2f

typedef struct
{
    UCHAR memType; // 0:eflash 1:s-flash
    ULONG tgtAddr; // Target address to write
    ULONG totSize; // Total size of data
    ULONG curSize; // Downloaded size of data
}stUfiDwnStatus;

UFI_EXT CBW g_cbw;
UFI_EXT CSW g_csw;
UFI_EXT unsigned char g_bUfiWriteMode;
UFI_EXT unsigned char g_bUfiWriteMode_post;
UFI_EXT stUfiDwnStatus g_ufiDwnStaus;



void UFI_proc(void);
void UFI_InitMem(UCHAR *buf, UCHAR *name);  // Buffer size must be larger than 0x200
void UFI_InitFuncEFlash(void (*funcSectorErase)(UCHAR AddH, UCHAR AddM, UCHAR AddL),
                        void (*funcPageProgram)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer),
                        void (*funcRead)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer) );
void UFI_InitFuncSFlash(void (*funcBlockErase)(UCHAR AddH, UCHAR AddM, UCHAR AddL),
                        void (*funcPageProgram)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer),
                        void (*funcRead)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer) );

Somehow I have to use this library in order to set my device as mass storage to avoid dealing with custom host device drivers.

The problem is that I don't know from where to start. Particularly I don't understand how to configure EP0? The USB feature list is mentioning

Understanding and decoding of standard USB commands to endpoint zero

What exactly this means? Documentation is really scarce and I don't know what logic to follow in order to initialize USB device at least on device side. I read generally about USB but I can't bind that knowledge to the way I have to construct my code... I have done coding of all peripherals on this IC, except USB.

Any idea would be highly appreciated.

https://www.dropbox.com/s/qd9d25oxxvh23ia/BMC51A_UM_REV1.0.pdf


Solution

  • The "standard USB commands to endpoint zero" are described in Chapter 9 of the USB Specification. I usually refer to revision 2.0, which you can find here:

    http://www.usb.org/developers/docs/usb20_docs/

    Just download the ZIP file, find usb_20.pdf, and go to Chapter 9. That chapter defines control transfers on endpoint zero that are used by the USB host to get descriptors and set up the device. The USB specification is about 600 pages but it is very readable and you should be able to learn a lot from it.

    To make your device behave like a Mass Storage Device, you need to implement some more functionality that is described in the USB-IF Device Class Documents in the Mass Storage category:

    http://www.usb.org/developers/docs/devclass_docs/

    If you are using USB at this level, you will need some way to look at low-level traffic on the bus. I recommend using a hardware USB protocol analyzer but you might find a software solution too. You could use an oscilloscope also, but it will take you many minutes to decode each packet and find what you are looking for.

    The code you posted does not look like it has anything to do with standard USB commands. It might be related to MSD class or maybe it is some custom protocol.