📄 msd.c
字号:
/*********************************************************************
*
* Microchip USB C18 Firmware - MSD Version 1.0
*
*********************************************************************
* FileName: msd.c
* Dependencies: See INCLUDES section below
* Processor: PIC18
* Compiler: C18 2.40
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the 揅ompany? for its PICmicro?Microcontroller is intended and
* supplied to you, the Company抯 customer, for use solely and
* exclusively on Microchip PICmicro Microcontroller products. The
* software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
*
* THIS SOFTWARE IS PROVIDED IN AN 揂S IS?CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Gurinder Singh 05/31/05 Original.
********************************************************************/
/** I N C L U D E S **************************************************/
#include <p18cxxx.h>
#include "system\typedefs.h"
#include "system\usb\usb.h"
#include<string.h>
#ifdef USB_USE_MSD
/** V A R I A B L E S ************************************************/
#pragma udata
byte MSD_State; // Takes values MSD_WAIT, MSD_DATA_IN or MSD_DATA_OUT
USB_MSD_CBW gblCBW;
byte gblCBWLength;
SDCSTATE gblFlag;
RequestSenseResponse gblSenseData;
byte *ptrNextData;
/*
* Number of Blocks and Block Length are global because
* for every READ_10 and WRITE_10 command need to verify if the last LBA
* is less than gblNumBLKS
*/
DWORD gblNumBLKS=0x00,gblBLKLen=0x00;
/* Standard Response to INQUIRY command stored in ROM */
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", // this is the T10 assigned Vendor ID
"Mass Storage ",
"0001"
};
/** P R I V A T E P R O T O T Y P E S ***************************************/
void MSDCommandHandler(void);
void MSDInquiryHandler(void);
void MSDReadCapacityHandler(void);
void MSDReadHandler(void);
void MSDWriteHandler(void);
void MSDModeSenseHandler(void);
void MSDMediumRemovalHandler(void);
void MSDRequestSenseHandler(void);
void MSDTestUnitReadyHandler(void);
void MSDVerifyHandler(void);
void MSDStopStartHandler(void);
byte IsMeaningfulCBW(void);
byte IsValidCBW(void);
void PrepareCSWData(void);
void SendData(byte*, byte);
void SendCSW(void);
void ResetSenseData(void);
void MSDDataIn(void);
void MSDDataOut(void);
extern SDC_Error MediaInitialize(SDCSTATE*);
extern void SocketInitialize(void);
extern SDC_Error SectorRead(dword, byte*);
extern SDC_Error SectorWrite(dword, byte*);
extern SDC_Error CSDRead(void);
extern int DetectSDCard (void);
extern byte IsWriteProtected(void);
/** D E C L A R A T I O N S **************************************************/
#pragma code
/** C L A S S S P E C I F I C R E Q ****************************************/
/******************************************************************************
* 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 received on the control endpoint EP0
*
* Note: None
*****************************************************************************/
void USBCheckMSDRequest(void)
{
switch(SetupPkt.bRequest)
{
case MSD_RESET:
ctrl_trf_session_owner = MUID_MSD;
mDisableEP1to15(); // See usbdrv.h
if (UEP1bits.EPSTALL==1) {
UEP1bits.EPSTALL = 0;
MSDInitEP();
}
UIRbits.STALLIF = 0;
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)
}
/******************************************************************************
* Function: void ProcessIO(void)
*
* PreCondition: MSDInitEP() and SDCardInit() have beed called.
* MSDInitEP() is called from USBStdSetCfgHandler(void)(usb9.c)
* SDCardInit() is called from InitializeSystem() in main.c
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This routine is called in continuous loop from main.c
* All the Bulk Transport Commands on EndPoint 1 are
* handled here. MSD_State holds the current state of the
* Mass Storage Module.
* In MSD_WAIT State - Wait for a Command Block Wrapper (CBW)
* on EP1. If a valid and meaningful CBW is received,
* depending on the command received MSD_State is changed to
* MSD_DATA_IN if data is to be sent to host (for all commands
* other than WRITE_10)
* MSD_DATA_OUT if host is expected to send data (only in case
* of WRITE_10). At the end of Data Transfer Command Status
* Wrapper (CSW) is sent by calling SendCSW()
*
* Note: None
*****************************************************************************/
void ProcessIO(void)
{
byte i;
dword size;
if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;
if (MSD_State==MSD_DATA_IN) {
/* Send Data to Host */
if(gblCBW.dCBWDataTransferLength==0)
{
/* Finished sending the data send the Status */
/* SendCSW() send the csw and sets the state to wait */
SendCSW();
if ((msd_csw.bCSWStatus==0x00)&&(gblCBW.CBWCB[0]==INQUIRY)) {
/* Turn on the MSD LED when we have successfully*/
/*responded to the INQUIRY Command */
STMSDLED=1;
}
}
else
{
/* Still have data to Send */
MSDDataIn();
}
return;
}
if (MSD_State==MSD_DATA_OUT) {
/* Receive data from Host*/
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
}
/*
* Note that MSD_DATA_OUT State is reached only for the WRITE_10 COMMAND
* Also note that this code is reached in MSD_DATA_OUT State only after
* we have read the required amount of data from the host
* This procsssing is done in WriteCommandHandler because we have
* limited buffer space. We read from host in 64Bytes chunks
* (size of MSD_BD_OUT), fill the msd_buffer(512B) and write the
* data into the SDCard
*/
return;
}
if((MSD_BD_OUT.Stat.UOWN==_UCPU) && (MSD_State==MSD_WAIT)) {
/* If the CPU owns the BD OUT (we)and the MSD_State is WAIT*/
/* Copy the received cbw into the gblCBW */
gblCBW.dCBWSignature=msd_cbw.dCBWSignature;
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; // 3 MSB are zero
for (i=0;i<msd_cbw.bCBWCBLength;i++)
gblCBW.CBWCB[i]=msd_cbw.CBWCB[i];
gblCBWLength=MSD_BD_OUT.Cnt; // Length of CBW
if (IsValidCBW()) {
if (IsMeaningfulCBW()) {
PrepareCSWData();
/* If direction is device to host*/
if (gblCBW.bCBWFlags==0x80)
MSD_State=MSD_DATA_IN;
else if (gblCBW.bCBWFlags==0x00) {
/* If direction is host to device*/
/* prepare to read data in msd_buffer */
MSD_BD_OUT.Cnt=MSD_OUT_EP_SIZE;
MSD_BD_OUT.ADR=(byte*)&msd_buffer[0];
MSD_State=MSD_DATA_OUT;
}
/* Decode and process the valid and meaningful CBW received */
MSDCommandHandler();
}
/* NOTE:
* In case when the received CBW is not valid or meaningful,
* one can take action such as Stall the EP1 and go through reset
* recovery or turn on error LED etc.
*/
}
/*
* NOTE: Call after every read or write on nonEP0 EP
* Basically, toggles DTS and gives ownership to SIE
*/
mUSBBufferReady(MSD_BD_OUT);
/* clears the TRNIF */
USBDriverService();
}
}
/******************************************************************************
* Function: void MSDInitEP(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This routine is called from USBStdSetCfgHandler(void)
* Initializes the Bulk-In and Bulk-Out endpoints MSD_BD_IN
* and MSD_BD_OUT Size = 64B (See usbmmap.c and
* usbdefs_std_dsc.h for endpoint definitions)
*
* Note: None
*****************************************************************************/
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 (size) 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
}//end MSDInitEP
/******************************************************************************
* Function: void SDCardInit(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: gblFlag is updated according to result of Intialization
* MSD_State is set to MSD_WAIT
*
* Overview: This routine is called from InitializeSystem() in main.c
* It initializes the SD card if there is some error in
* initialization all the LEDs are turned ON.
* Also, set the MSD_State = MSD_WAIT
*
* Note: None
*****************************************************************************/
void SDCardInit(void)
{
SDC_Error status;
SocketInitialize();
mInitAllLEDs();
status=MediaInitialize(&gblFlag);
if (status) {
/* If there was some error, turn on all leds */
mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On();
gblFlag.isSDMMC=0;
} else gblFlag.isSDMMC=1;
MSD_State=MSD_WAIT;
}
/******************************************************************************
* Function: void MSDCommandHandler(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This routine is called from ProcessIO()
* when the MSD_State = MSD_WAIT. This function decodes the CBW
* Command and takes appropriate action.If the CBW command is
* not supported the Sense Data is set, CSW status
* is set to Command Failed (bCSWStatus=01h)
*
* Note: None
*****************************************************************************/
void MSDCommandHandler(void) // In reality it is to read from EP1
{
switch(gblCBW.CBWCB[0]) {
case INQUIRY:
MSDInquiryHandler();
break;
case READ_CAPACITY:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -