Hi fat16lib,
Your example sketch will need two more class defs... one for USBHost and one for MINMSC. Then it should be possible to run the setup().
There are three examples that use USBHost: ADK, Mouse/KDB-driver, and Android communication device (?). The way I thought of fitting in MINMSC is to make it follow USBHost interface because when I started looking into it, that was all I could find. However, I am not terribly interested in maintaining conformity with USBHost. I make use of following features of USBHost:
- USB Bus State Machine in USBHost.task()
- The general scheme to assign an USB address
- Ctl Pipe Xfr calls
- Very valuable set of header files (specially Chapter-9 Dev Framework)
I don't quite understand descriptor handling by USBHost and so I wrote that part myself. How important is it to be compatible with USBHost?
There is another subtle problem. Even though there is no hub-support in USBHost/MINMSC, there is a way to have multiple media being open at the same time on the bus. The Kingston 4-slot card reader I have can mount 4 different media types all at once... same usb-bus-adr, same dev-adr, but different luns. Note, there is only one USB device. MINMSC will allow opening handles to all these slots/luns (whether it has media or not) and the user of MINMSC (your lowest level code in this case) can drive all 4 handles at once. Under RTOS, the first I/O will proceed and the other 3 will block. Under executive loop, I may have to do the queuing myself or reject the other 3 with error.
All this means the 1-1 correspondence between an Sd2Card object and a MINMSC object cannot be maintained. So, the MINMSC is a singleton class that has multiple devices (4 for 4-slot card readers). Each higher level block-dev object will bind with exactly one of these devices under MINMSC.
Here is a short version of the header file with MINMSC class def. With this interface it should be pretty easy to open, read/write and close a block device.
typedef struct msc_devList_entry_st
{
uint8_t vendorId[ 8]; // SCSI Inquiry Vendor Id Field as is
uint8_t productId[ 16]; // SCSI Inquiry Product Id Field as is
uint8_t busId; // USB Bus Id ( DUE, PgmPort=0, Native=1)
uint8_t bAddress; // Configured USB Bus Address
uint8_t lunCount; // # LUNs ( Always at least 1 or more).
uint8_t unused;
} MSC_DEVLIST_ENTRY;
typedef struct msc_client_st
{
uint8_t clState; // Client State: One of MSC_CLST_xxx numbers.
uint8_t lun; // The 'lun' of MSC_DEV being used by client.
uint16_t msecCount; // # millisecs spent while in zombie state.
MSC_DEV * pMscDev; // The MSC_DEV being used by client.
CLIENT_CB_PTR pClientCb; // Ptr to client's callback function.
void * pContext; // Client's Context to pass during callback.
} MSC_CLIENT;
class MINMSC : public USBDeviceConfig, public UsbConfigXtracter
{
friend class Sd2Card;
private:
uint32_t cbwTag; // Changes on every new CBW-CSW pair.
uint32_t mscDevCount;
MSC_DEV mscDev[ MSC_MAXCNT_DEV];
MSC_CLIENT mscClientTable[ MSC_MAXCNT_CL_ENTRY];
void * pMasterClientContext;
MASTER_CLIENT_CB_PTR pMasterClientCb; // Only 1 master client allowed.
// The idea of having a master client is to allow someone who can monitor
// the USB Bus Events like disconnect, power problem, etc. Individual
// devices are opened by regular clients and they receive device level
// notifications like media insertion in an empty slot, media removal.
// All regular clients are accounted for in mscClientTable[] array.
protected:
/* Mandatory members */
USBHost * pUsb;
public:
MINMSC( USBHost *pUsb);
// Do not call following. They are ISR related and cannot be Private.
void mscUsbIsr( MINMSC *); // Don't call! ISRs => outside of class.
void mscDelayedClose( void);
void mscDetectMediaChange( void);
// End of Do Not Call stuff.
uint32_t mscGetVersion( char *, uint32_t bufSize);
int32_t mscRegGenTimerIsr( void * pContext, ISR_CB_PTR pIsr);
void mscUnregGenTimerIsr( int32_t handle);
void mscReadHiPrecTimer( uint32_t * pTimerHi32, uint32_t * pTimerLo32);
inline
uint32_t mscReadHiPrecTimer_Lo32( void)
{
return
MSC_TCBASE(MSC_TIMER_TC)->
TC_CHANNEL[ MSC_TIMER_TCCH_HI_PREC_CLOCK].TC_CV;
}
uint32_t mscRegisterMasterClient( void * pContext, MASTER_CLIENT_CB_PTR pMasterClientCb);
uint32_t mscDevList( MSC_DEVLIST_ENTRY * pFirst, uint32_t maxEntries);
//---------------- I/O Interface ----------------------
int32_t mscOpen( uint8_t usbBusId, uint8_t devAdr, uint8_t lun, CLIENT_CB_PTR pCb, void * pContext);
uint32_t mscReadCapacity( int32_t hndl, uint32_t * pLastBlkNum, uint32_t * pBlkSize);
uint32_t mscReadBlock( int32_t hndl, uint32_t startBlkNum, uint32_t blkCount, uint8_t * pBuf);
uint32_t mscWriteBlock( int32_t hndl, uint32_t startBlkNum, uint32_t blkCount, uint8_t * pBuf);
uint32_t mscWriteZero( int32_t hndl, uint32_t startBlkNum, uint32_t blkCount);
uint32_t mscClose( int32_t hndl);
// USBDeviceConfig implementation -- Conforming to USBHost Library.
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
virtual uint32_t Release();
virtual uint32_t Poll();
virtual uint32_t GetAddress();
virtual bool isReady();
// UsbConfigXtracter implementation -- Conforming to USBHost Library.
virtual void EndpointXtract( uint32_t conf, uint32_t iface, uint32_t alt,
uint32_t proto,
const USB_ENDPOINT_DESCRIPTOR *ep);
/* Timer Related */
MSC_TICOM mscGenTimer; // The general multi-ISR 250 usec timer
MSC_TIMER_CB mscGenTimerCb[ MSC_MAXCNT_ISR];//Gen Timer callbacks(ISRs).
MSC_TICOM mscHiPrecClock; // Hi precision clock offered by MINMSC.
uint32_t mscHiPrecClock_hi32; // The "lo32" comes from TC h/w.
/* Debugging related */
uint8_t mscDebug; // Has a collection of bits like MSCDEBUG_xxx.
};
I shall try to contact you within next few hours from my gmail account to yours and send you the Sd2Card.cpp/h for MINMSC.
Thanks.