📄 msd-b.c
字号:
/** I N C L U D E S **********************************************************/
#include <p18cxxx.h>
#include "system\typedefs.h"
#include "system\usb\usb.h"
#include "io_cfg.h" // I/O pin mapping
#include<string.h>
//#ifndef MSD_H
//#include "system\usb\class\msd\msd.h"
#ifdef USB_USE_MSD
#define mLED_Both_On() {mLED_2_On();mLED_3_On();}
extern SDC_Error RMediaInitialize(SDCSTATE*);
extern SDC_Error sdcardinitialize(void);
extern SDC_Error MediaInitialize();
// Global Variable for keeping state of the MSD firmware
byte MSD_State;
USB_MSD_CBW gblCBW;
byte gblCBWLength;
SDCSTATE gblFlag;
/*typedef struct
{
unsigned Peripheral_Qualifier:3;
unsigned Peripheral_DevType:5;
unsigned RMB:1; // removable medium bit = 0 means non removable;
unsigned Resv:7; // reserved
byte version; // version
unsigned Obsl:2; // obsolete
unsigned NormACA:1; // Access control co-ordinator
unsigned HiSup:1; // Hierarchical addressing support
unsigned Response_Data_Format:4; // 02 indicates response is in format defined by spec
byte AdditionalLength; // length in bytes of remaining in standard inquiry data
unsigned SCCS:1; // =1 means SCSI target device has embedded storage component
unsigned ACC:1; // access controls co-ordinator
unsigned TGPS:2; // target group port support
unsigned THPC:1; // third party copy =1 means dev supports 3rd party copy commands e.g. extended write
unsigned Reserved:2;
unsigned Protect:1; // protection information
unsigned BQUE:1; // with CMD queue to indicate full or basic task management model
unsigned EncServ:1; // enclosure service
unsigned VS:1;
unsigned multip:1; // multiport
unsigned MChngr:1; // medium changer command to control attached media changer
unsigned Obs:2;
unsigned Addr16:1; // specific to SPI-5 SCSI parallel interface
unsigned obslo:2;
unsigned wbus16:1; // specific to SPI-5
unsigned sync:1; // specific to SPI-5
unsigned linked:1; // support of linked command (SAM-3)
unsigned ob:1;
unsigned cmdque:1; // task management model
unsigned vs:1;
char vendorID[8];
char productID[16];
char productRev[4];
} InquiryResponse;*/
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);
//status=sdcardinitialize();
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)
{
//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();
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 ProcessIO(void)
{
byte i;
if(!MSD_BD_OUT.Stat.UOWN)
{
if (MSD_State==MSD_DATA_IN) {
mLED_1_On();mLED_2_On();mLED_3_On();mLED_4_On();
}
if (MSD_State==MSD_DATA_OUT) {
mLED_1On();mLED2_On();mLED_3_On();mLED_4_On();
}
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.CB.CBWCB[i]=msd_cbw.CB.CBWCB[i];
gblCBWLength=MSD_BD_OUT.Cnt; // Length of command block wrapper
MSDCommandHandler(); // decode and process the CBW
mUSBBufferReady(MSD_BD_OUT); // call after every read or write on nonEP0 EP,
// toggles DTS and gives ownership to SIE
USBDriverService(); // clears the TRNIF
}
}
}
void MSDCommandHandler(void) // In reality it is to read from EP1
{
if (isValidCBW()) {
if (isMeaningfulCBW()) {
prepareCSWData();
if (gblCBW.bCBWFlags==0x80)
MSD_State=MSD_DATA_IN;
else if (gblCBW.bCBWFlags==0x00)
MSD_State=MSD_DATA_OUT;
switch(msd_cbw.CB.Opcode) {
case INQUIRY:
MSDInquiryHandler();
break;
case READ_FORMAT_CAPACITY:
MSDReadFormattedCapacityHandler();
break;
case READ_CAPACITY:
MSDReadCapacityHandler();
break;
case READ:
MSDReadHandler();
break;
case WRITE:
break;
case REQUEST_SENSE:
RequestSenseHandler();
break;
case MODE_SENSE:
break;
case PREVENT_ALLOW_MEDIUM_REMOVAL:
break;
case TEST_UNIT_READY:
break;
case VERIFY:
break;
case STOP_START:
break;
/*
default:
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer;
MSD_BD_IN.Cnt=0x0;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
MSDErrorCSW();
break;
*/
} // end switch
} // end isMeaningfulCBW
} // end isValidCBW
MSD_State=MSD_WAIT;
}
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()
{
msd_csw.dCSWTag=gblCBW.dCBWTag;
msd_csw.dCSWSignature=0x53425355;
}
void RequestSenseHandler(void)
{
byte i;
for(i=0;i<18;i++)
msd_buffer[i]=0;
msd_buffer[0]=0xf0;
msd_buffer[2]=0x05;
msd_buffer[7]=0x0a;
msd_buffer[12]=0x20;
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer;
MSD_BD_IN.Cnt=0x12;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
MSDSuccessCSW(0x00);
}
void MSDReadFormattedCapacityHandler(void)
{
//mLED_4_On();
/*
msd_csw.dCSWTag=msd_cbw.dCBWTag;
msd_csw.dCSWSignature=0x53425355;
msd_csw.dCSWDataResidue=msd_cbw.dCBWDataTransferLength;
msd_csw.bCSWStatus=0x1;
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_csw;
MSD_BD_IN.Cnt=0x0;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_csw;
MSD_BD_IN.Cnt=0x0;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
return;
*/
msd_buffer[0]=0x01; // No of LBAs 246,016 from SD Card manual Page 3-24
msd_buffer[1]=0x02;
msd_buffer[2]=0x03;
msd_buffer[3]=0x04;
msd_buffer[4]=0x05; // Block size 512 bytes = 200h
msd_buffer[5]=0x06;
msd_buffer[6]=0x07;
msd_buffer[7]=0x08;
msd_buffer[8]=0x09; // Block size 512 bytes = 200h
msd_buffer[9]=0x10;
msd_buffer[10]=0x11;
msd_buffer[11]=0x12;
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[64];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[128];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[192];
MSD_BD_IN.Cnt=0x3c;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
MSDSuccessCSW(0x00);
}
void MSDInquiryHandler(void)
{
byte i;
byte *buffer;
memcpypgm2ram((byte *)&msd_buffer[0],(byte *)&inq_resp,sizeof(InquiryResponse));
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
MSD_BD_IN.Cnt=0x24;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
MSDSuccessCSW(msd_cbw.dCBWDataTransferLength-0x24);
}
void MSDReadCapacityHandler()
{
msd_buffer[0]=0x03; // No of LBAs 246,016 from SD Card manual Page 3-24
msd_buffer[1]=0x00;
msd_buffer[2]=0x00;
msd_buffer[3]=0x00;
msd_buffer[4]=0x00; // Block size 512 bytes = 200h
msd_buffer[5]=0x00;
msd_buffer[6]=0x02;
msd_buffer[7]=0x00;
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
MSD_BD_IN.Cnt=0x08;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
MSDSuccessCSW(0x00);
}
void MSDReadHandler()
{
word i;
SDC_Error status;
status=RMediaInitialize(&gblFlag); // media initialize reads the first sector in msd_buffer
if (status) {mLED_1_On();mLED_2_On();mLED_3_On();mLED_4_On(); return;}
//status =SECTORread(0L, (byte*)&msd_buffer[0]);
//if (status) {mLED_1_On();mLED_2_On();mLED_3_On();mLED_4_On(); return;}
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[64];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[128];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[192];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[256];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[320];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[384];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_buffer[448];
MSD_BD_IN.Cnt=0x40;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
MSDSuccessCSW(0x00);
mLED_4_On();
}
void MSDSuccessCSW(dword residue)
{
//mLED_Both_On();
//msd_cbw_csw.dCSWTag=msd_cbw_csw.dCBWTag;
//msd_cbw_csw.dCSWSignature._dword=0x53425355;
//msd_cbw_csw.dCSWDataResidue._dword = 0x0;
//msd_cbw_csw.bCSWStatus._byte=0x0;
msd_csw.dCSWTag=msd_cbw.dCBWTag;
msd_csw.dCSWSignature=0x53425355;
msd_csw.dCSWDataResidue = residue;
msd_csw.bCSWStatus=0x0;
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_csw;
MSD_BD_IN.Cnt=0x0d;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
}
void MSDErrorCSW(void)
{
//mLED_1_On();
msd_csw.dCSWTag=msd_cbw.dCBWTag;
msd_csw.dCSWSignature=0x53425355;
msd_csw.dCSWDataResidue=msd_cbw.dCBWDataTransferLength;
msd_csw.bCSWStatus=0x1;
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_csw;
MSD_BD_IN.Cnt=0x0d;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
}
void MSDInHandler(void)
{
return;
}
void MSDTxPkt(char *buffer, byte len)
{
byte i;
/*
* Value of len should be equal to or smaller than MSD_INT_IN_EP_SIZE.
* This check forces the value of len to meet the precondition.
*/
if(len > MSD_IN_EP_SIZE)
len = MSD_IN_EP_SIZE;
/*
* Copy data from user's buffer to dual-ram buffer
*/
for (i = 0; i < len; i++)
msd_buffer[i] = buffer[i];
MSD_BD_IN.ADR=(byte*)&msd_buffer;
MSD_BD_IN.Cnt = len;
mUSBBufferReady(MSD_BD_IN);
}//end MSDTxPkt
void MSDInitEP(void)
{
mInitAllLEDs();
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|_DAT0|_DTSEN; //usbmmap.h owner SIE, DAT0 expected next, data toggle sunc enable
/*
* Do not have to init Cnt of IN pipes here.
* Reason: Number of bytes to send to the host
* varies from one transaction to
* another. Cnt should equal the exact
* number of bytes to transmit for
* a given IN transaction.
* This number of bytes will only
* be known right before the data is
* sent.
*/
MSD_BD_IN.ADR = (byte*)&msd_buffer[0]; // Set buffer address
MSD_BD_IN.Stat._byte = _UCPU|_DAT1; // Set status CPU owns Data1 expected next
MSD_State=MSD_WAIT;
}//end MSDInitEP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -