📄 msdnotworking.c
字号:
/** I N C L U D E S **********************************************************/
#include <p18cxxx.h>
#include "system\typedefs.h"
#include "system\usb\usb.h"
#include "fileio.h"
//#include "system\sdcard\sdcard.h"
#include<string.h>
//#ifndef MSD_H
//#include "system\usb\class\msd\msd.h"
#ifdef USB_USE_MSD
//#define USB_USE_MSD
#define mLED_Both_On() {mLED_2_On();mLED_3_On();}
#define CSD_SIZE 16
extern CSD gblCSDReg; // declared in sdcard.c
extern SDC_Error RMediaInitialize(SDCSTATE*);
extern SDC_Error sdcardinitialize(void);
extern SDC_Error MediaInitialize();
extern void SocketInitialize(void);
extern byte MediaDetect(void);
extern void DetectSDCard(void);
extern SDC_Error SECTORread(dword, byte*);
extern SDC_Error CSDread(byte*);
extern CETYPE StartupCard(DISK *, byte *, CARDSTATUS *);
dword ConvertLBASector(dword LBA);
// Global Variable for keeping state of the MSD firmware
byte MSD_State;
byte MSD_Data;
USB_MSD_CBW gblCBW;
byte gblCBWLength;
SDCSTATE gblFlag;
RequestSenseResponse gblSenseData;
byte *ptrNextData;
dword dataLen;
FILE gblFile; // The global file structure
DISK gblDisk; // The global disk structure
CARDSTATUS gblCardStatus;
DWORD gblNumBLKS=0x00,gblBLKLen=0x00; // made global because need to verify if the last lba is less than gblNumBLKS
// for every read and write command
dword gblLBA=0x269;
const rom InquiryResponse inq_resp = {
0x00, // peripheral device is connected, direct access block device
0x80, // removable
0x04, // version = 00=> does not conform to any standard, 4=> SPC-2
0x02, // response is in format specified by SPC-2
0x20, // n-4 = 36-4=32= 0x20
0x00, // sccs etc.
0x00, // bque=1 and cmdque=0, indicates simple queueing 00 is obsolete,
// but as in case of other device, we are just using 00
0x00, // 00 obsolete, 0x80 for basic task queueing
"Microchp",
"Ma$$ Storage ",
"0001"
};
/**************************************************
Initialize the SD Card
***************************************************/
void MSInit(void)
{
SDC_Error status;
SocketInitialize();
mInitAllLEDs();
status=RMediaInitialize(&gblFlag);
if (status) { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On();} // If there was some error, turn on all leds
MSD_State=MSD_WAIT;
}
/******************************************************************************
* Function: void USBCheckMSDRequest(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This routine handles the standard RESET and GET_MAX_LUN command requests on control endpoint
*
* Note: None
*****************************************************************************/
void USBCheckMSDRequest(void)
{
//mLED_2_On();
//if(SetupPkt.Recipient != RCPT_INTF) return;
//if(SetupPkt.bIntfID != MSD_INTF_ID) return;
//if(SetupPkt.RequestType != CLASS) return;
switch(SetupPkt.bRequest)
{
case MSD_RESET:
ctrl_trf_session_owner = MUID_MSD;
mDisableEP1to15(); // See usbdrv.h
//MSDInitEP();
// mLED_2_On();
if (UEP1bits.EPSTALL==1) {
//USBPrepareForNextSetupTrf(); // Firmware work-around
UEP1bits.EPSTALL = 0;
mLED_3_On();
MSDInitEP();
}
UIRbits.STALLIF = 0;
/*
MSD_UEP = EP_OUT_IN|HSHK_EN; // Enable 2 data pipes
MSD_BD_OUT.Cnt=sizeof(msd_cbw);
MSD_BD_OUT.ADR=(byte*)&msd_cbw;
MSD_BD_OUT.Stat._byte = _USIE|_DTSEN; //usbmmap.h owner SIE, DAT0 expected next, data toggle sunc enable
MSD_BD_IN.ADR = (byte*)&msd_buffer[0]; // Set buffer address
MSD_BD_IN.Stat._byte = _UCPU; // Set status CPU owns Data1 expected next
*/
break;
case GET_MAX_LUN:
ctrl_trf_session_owner = MUID_MSD;
CtrlTrfData._byte[0] = MAX_LUN;
wCount._word = 1;
pSrc.bRam = (unsigned char*)&CtrlTrfData;
usb_stat.ctrl_trf_mem = _RAM;
break;
} //end switch(SetupPkt.bRequest)
}
void sendCSW(void)
{
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_csw;
MSD_BD_IN.Cnt=MSD_CSW_SIZE;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
//while(mMSDRxIsBusy());
MSD_BD_OUT.Cnt=sizeof(msd_cbw);
MSD_BD_OUT.ADR=(byte*)&msd_cbw; // in MSD_DATA_OUT state the address was changed to point tomsd_buffer
MSD_State=MSD_WAIT;
}
void sendData(byte* dataAddr, byte dataSize)
{
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=dataAddr;
MSD_BD_IN.Cnt=dataSize;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
}
void MSDDataIn(void)
{
byte i;
dword size;
// Case (status==0) and (data to be sent > MSD_IN_EP_SIZE)
if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue>=MSD_IN_EP_SIZE)) {
// write next chunk of data to EP Buffer and send
sendData(ptrNextData,MSD_IN_EP_SIZE);
gblCBW.dCBWDataTransferLength-= MSD_IN_EP_SIZE;
msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
ptrNextData+=MSD_IN_EP_SIZE;
} else {
if (msd_csw.bCSWStatus!=0x0) { // error path status!=0
size=mMin(MSD_IN_EP_SIZE,gblCBW.dCBWDataTransferLength);
for (i=0;i<size;i++) msd_buffer[i]=0; // prepare 0 data
if (gblCBW.dCBWDataTransferLength > MSD_IN_EP_SIZE) { // Case (status!=0) and (data to be sent > MSD_IN_EP_SIZE)
// write next chunk of data to EP Buffer and send
sendData((byte*)&msd_buffer[0],MSD_IN_EP_SIZE);
gblCBW.dCBWDataTransferLength -= MSD_IN_EP_SIZE;
msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
} else { // Case (status!=0) and (data to be sent < MSD_IN_EP_SIZE)
// write next chunk of data to EP Buffer and send
sendData((byte*)&msd_buffer[0],gblCBW.dCBWDataTransferLength);
gblCBW.dCBWDataTransferLength = 0; // we have sent 0s for what was expected by host
msd_csw.dCSWDataResidue -= gblCBW.dCBWDataTransferLength;
}
} else { // Case (status ==0) and (data to be sent < MSD_IN_EP_SIZE)
// write next chunk of data to EP Buffer and send
sendData(ptrNextData,msd_csw.dCSWDataResidue);
gblCBW.dCBWDataTransferLength -= msd_csw.dCSWDataResidue ; // we have sent all the data that was expected by host
msd_csw.dCSWDataResidue = gblCBW.dCBWDataTransferLength;
gblCBW.dCBWDataTransferLength = 0; // in case the host expected more than what we had to send
// setting DataTransferLength=0 will ensure sending CSW
}
}
//mUSBBufferReady(MSD_BD_IN);
//USBDriverService();
}
void MSDDataOut(void)
{
while(mMSDRxIsBusy());
// We can only read 64 bytes at a time;
dataLen+=MSD_BD_OUT.Cnt;
//if(MSD_BD_OUT.Cnt==MSD_OUT_EP_SIZE) {
ptrNextData+=MSD_BD_OUT.Cnt;
MSD_BD_OUT.ADR=(byte*)ptrNextData; // else need not update the pointer as that will be last chunk
if (dataLen==0x0200)
MSD_BD_OUT.ADR=(byte*)&msd_buffer[0];
//}
// if we have received data in excess of what host was to send
//if (gblCBW.dCBWDataTransferLength<MSD_BD_OUT.Cnt) {
// msd_csw.bCSWStatus=0x02;
// gblCBW.dCBWDataTransferLength=0;
//} else {
gblCBW.dCBWDataTransferLength-=MSD_BD_OUT.Cnt;
msd_csw.dCSWDataResidue-=MSD_BD_OUT.Cnt;
//}
mUSBBufferReady(MSD_BD_OUT);
USBDriverService();
}
void ProcessIO(void)
{
byte i;
dword size;
if (MSD_State==MSD_DATA_IN) {
// Send data to host
if(gblCBW.dCBWDataTransferLength==0) { sendCSW(); } // finished sending the data send the status
else // still have data to send
MSDDataIn(); // else dCBWDataTransferLength==0
return;
}
if (MSD_State==MSD_DATA_OUT) {
if(gblCBW.dCBWDataTransferLength==0) { // finished receiving the data prepare and send the status
//if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue!=0))
// msd_csw.bCSWStatus=0x02;
sendCSW(); // sends the csw and sets the state to wait
ptrNextData=(byte*)&msd_buffer[0];
} else {
mLED_1_On(); mLED_2_On();
}
//else { // else of if DataTransferLength == 0
// basically the code will not come here because only place the OUT transaction is required (i think!!)
// is write and during processing of the data itself, the OUT data is read
//MSDDataOut();
//}
return;
}
if(!MSD_BD_OUT.Stat.UOWN) // If the CPU owns the BD OUT
{
if (MSD_State==MSD_WAIT) {
gblCBW.dCBWSignature=msd_cbw.dCBWSignature; // copy the received cbw into the gblCBW
gblCBW.dCBWTag=msd_cbw.dCBWTag;
gblCBW.dCBWDataTransferLength=msd_cbw.dCBWDataTransferLength;
gblCBW.bCBWFlags=msd_cbw.bCBWFlags;
gblCBW.bCBWLUN=msd_cbw.bCBWLUN;
gblCBW.bCBWCBLength=msd_cbw.bCBWCBLength; // Here most significant 3bits are zero
for (i=0;i<msd_cbw.bCBWCBLength;i++)
gblCBW.CBWCB[i]=msd_cbw.CBWCB[i];
gblCBWLength=MSD_BD_OUT.Cnt; // Length of command block wrapper
mUSBBufferReady(MSD_BD_OUT); // call after every read or write on nonEP0 EP,
// toggles DTS and gives ownership to SIE
USBDriverService(); // clears the TRNIF
if (isValidCBW()) {
if (isMeaningfulCBW()) {
prepareCSWData();
if (gblCBW.bCBWFlags==0x80)
MSD_State=MSD_DATA_IN;
else if (gblCBW.bCBWFlags==0x00) {
// prepare to read data in msd_buffer
MSD_BD_OUT.Cnt=MSD_OUT_EP_SIZE;
MSD_BD_OUT.ADR=(byte*)&msd_buffer[0];
dataLen=0x0;
ptrNextData=(byte*)&msd_buffer[0];
MSD_State=MSD_DATA_OUT;
}
// do this before because we may read data in write command
MSDCommandHandler(); // decode and process the CBW
// If dCBWDataTransferLength=0&&dCSWDataResidue!=0 dCSWStatus=0x02
// else nothing go to data transfer state
} else { // else of isMeaningfulCBW
;
// Stall EP1 ??
}
} else { // else of isValidCBW
;
// Stall EP1
}
}
}
}
void MSDCommandHandler(void) // In reality it is to read from EP1
{
switch(gblCBW.CBWCB[0]) {
case INQUIRY:
MSDInquiryHandler();
break;
/* case READ_FORMAT_CAPACITY: // will be handled in default case, whenever upsupported command is received
MSDReadFormatCapacityHandler();
break;*/
case READ_CAPACITY:
MSDReadCapacityHandler();
break;
case READ_10:
MSDReadHandler();
break;
case WRITE_10:
MSDWriteHandler();
break;
case REQUEST_SENSE:
MSDRequestSenseHandler();
break;
case MODE_SENSE:
MSDModeSenseHandler();
break;
case PREVENT_ALLOW_MEDIUM_REMOVAL:
MSDMediumRemovalHandler();
break;
case TEST_UNIT_READY:
MSDTestUnitReadyHandler();
break;
case VERIFY:
MSDVerifyHandler();
break;
case STOP_START:
MSDStopStartHandler();
break;
default:
ResetSenseData();
gblSenseData.SenseKey=S_ILLEGAL_REQUEST;
gblSenseData.ASC=ASC_INVALID_COMMAND_OPCODE;
gblSenseData.ASCQ=ASCQ_INVALID_COMMAND_OPCODE;
msd_csw.bCSWStatus=0x01;
msd_csw.dCSWDataResidue=0x00;
break;
} // end switch
// MSD_State=MSD_WAIT;
ptrNextData=(byte*)&msd_buffer[0];
}
byte isValidCBW()
{
if ((gblCBWLength!=0x1f)||(gblCBW.dCBWSignature!=0x43425355)) return FALSE;
else return TRUE;
}
byte isMeaningfulCBW()
{
// 3msb bits of CBWCBLength are reserved and must be 0, 4msb bits of CBWLUN are reserved and must be 0
// valid CBWCBLength is between 1 and 16B
// flags only msb indicates data direction rest must be 0
if ((gblCBW.bCBWLUN<=0x0f)&&(gblCBW.bCBWCBLength<=0x10)&&(gblCBW.bCBWCBLength>=0x01)&&(gblCBW.bCBWFlags==0x00|gblCBW.bCBWFlags==0x80))
return TRUE;
else return FALSE;
}
void prepareCSWData()
{
// prepare the tag and signature.
// Residue and Status we will get after decoding and executing the command
msd_csw.dCSWTag=gblCBW.dCBWTag;
msd_csw.dCSWSignature=0x53425355;
}
void MSDInquiryHandler(void)
{
byte i;
byte *buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -