📄 usbd_protstorage.c
字号:
/*
* Part depended on USB Device Storage Class
* $Revision: 1.7 $ $Date: 2006/12/22 05:34:35 $
*/
/*=== Include =============================================================*/
#include "SPRDEF.h"
#include "USBD_ProtStorage.h"
#include "USBD_ProtEnum.h"
#include "usb_descinfo.h"
#include "usbd_func.h"
#include "usbd_if.h"
#include "fifo_if.h"
#include "SPRSTS.h"
#include <stdlib.h>
#include <string.h>
#include "led_if.h"
/*=== Define ==============================================================*/
#define MAX_OPEN (1)
/*=== Macro ===============================================================*/
#define CLR_BIT(bits,mask) ((bits) = ((bits) & ~(mask)))
#define SET_BIT(bits,mask) ((bits) = ((bits) | (mask)))
#define IS_BIT(bits,mask) (((bits) & (mask)) != 0x00 ? TRUE : FALSE)
/* MACRO to devide value of 32 bits into value of 8 bytes */
#define DWORD2BYTE_HH(dw) ((UCHAR)((dw) >> 24))
#define DWORD2BYTE_HL(dw) ((UCHAR)((dw) >> 16))
#define DWORD2BYTE_LH(dw) ((UCHAR)((dw) >> 8))
#define DWORD2BYTE_LL(dw) ((UCHAR)((dw) ))
/*=== Define ==============================================================*/
#define PRV_CLASS_CODE (0x08) /* Storage Class */
#define PRV_PROTOCOL_CODE (0x50) /* BulkOnly */
#define PRV_MAX_CMD_LEN (12) /* Command Packet Length */
#define PRV_BMREQ_DIR_MASK (0x80)
#define PRV_BMREQ_TYPE_MASK (0x60)
#define PRV_BMREQ_RECIPIENT_MASK (0x1F)
#define PRV_RECIPIENT_DEVICE (0x00)
#define PRV_RECIPIENT_INTERFACE (0x01)
#define PRV_RECIPIENT_ENDPOINT (0x02)
#define PRV_RECIPIENT_OTHER (0x03)
#define PRV_TYPE_CLASS (0x20)
#define PRV_DIR_HOST_TO_DEVICE (0x00)
#define PRV_DIR_DEVICE_TO_HOST (0x80)
#define PRV_EP0IN (0x80)
#define PRV_EP0OUT (0x00)
#define PRV_BULKIN (0x00)
#define PRV_BULKOUT (0x01)
#define PRV_BULKONLYRESET (0xFF)
#define PRV_GETMAXLUN (0xFE)
#define PRV_IDLE_STATE (0x00) /* State of Idle */
#define PRV_CBW_STATE (0x01) /* State of CBW receiving */
#define PRV_DATA_STATE (0x02) /* State of data transfer */
#define PRV_CSW_STATE (0x03) /* State of CSW transmission */
#define PRV_ABORT_STATE (0x08) /* State of abort for data transfer */
#define PRV_STALL_STATE (0x0F) /* State of STALL */
#define PRV_IR_RCVSETUP (0x0001) /* SETUP receiving */
#define PRV_IR_EP0_DATAIN_END (0x0002) /* Completion of data stage */
#define PRV_IR_EP0_STATUSSTAGE_END (0x0004) /* Completion of data stage */
#define PRV_IR_CONFIGURED (0x0010) /* Configured */
#define PRV_IR_DECONFIGURED (0x0020) /* Deconfigured */
#define PRV_IR_ALTERNATE_CHANGED (0x0080) /* Alternate Setting Changed */
#define PRV_IR_BULKIN_TRANSFER_END (0x0100) /* Completion of transfer for Bulk In */
#define PRV_IR_BULKOUT_TRANSFER_END (0x0200) /* Completion of transfer for Bulk Out */
#define PRV_IR_TRANSFER_FLUSH (0x0400) /* Request of FLUSH */
#define PRV_IR_CBW_READY (0x1000) /* Completion of preparation of CBW receiving */
#define PRV_IR_CSW_READY (0x2000) /* Completion of preparation of CSW transmission */
#define PRV_IR_RESET_RECOVERY (0x4000) /* Request of Reset Recovery */
/*=== Structure ===========================================================*/
typedef struct {
USHORT wMaxPacket; /* Size of Max Packet */
UCHAR bEPNumber; /* Endpoint number */
UCHAR bState; /* State */
UCHAR bUseDMA; /* Flag used by DMA */
UCHAR bDmaCh; /* DMA Channel */
UCHAR bShortPkt; /* Flag of receiving/transmission of ShortPkt */
ULONG dwReqXferSize; /* Size of transfer requested */
ULONG dwTotalXferSize; /* Size of actual transfer */
ULONG dwActXferSize; /* Corrent size of transfer */
ULONG dwXferedSize; /* Size of transferred */
} PRV_BULKEPINFO;
/*=== Variable ============================================================*/
static USHORT PrvAllocId;
static UCHAR PrvInterfaceNumber;
static UCHAR PrvCBW[32];
static UCHAR PrvCSW[16];
static UCHAR PrvMaxLUN;
static ULONG PrvCSWResidue;
static ULONG PrvBulkOnlyStatus;
static ULONG PrvInternalStatus;
static PRV_BULKEPINFO PrvBulkEPInfo[2];
static CALLBACK_PROC PrvStorageEventCallback;
static CALLBACK_PROC PrvStorageXferEventCallback;
static USBD_FUNC_REQUEST PrvRequest;
/*=== Function Prototype ==================================================*/
static LONG PrvRcvRequestCallback(ULONG lReqData, ULONG lParam1, void *pParam);
static LONG PrvEP0_DataInEndCallback(ULONG lEPNum, ULONG lActualXferSize, void *pParam);
static LONG PrvEP0_StatusStageEndCallback(ULONG lResult, ULONG lParam1, void *pParam);
static LONG USBD_ProtStorageAlternateChanged(ULONG lParam0,ULONG lParam1,void *pParam);
static LONG PrvBulkInPIOTransferEndCallback(ULONG lEPNum, ULONG lActualXferSize, void *pParam);
static LONG PrvBulkOutPIOTransferEndCallback(ULONG lEPNum, ULONG lActualXferSize, void *pParam);
static LONG PrvBulkOnlyEventCallback(ULONG lEvent,ULONG lParam1,void *pParam);
static LONG PrvBulkTransferShortPktCallback( ULONG lEvent, ULONG lEPNum, void *pParam);
static LONG PrvPollingProc(void);
static LONG PrvDecodeRequest(void);
static LONG PrvInitVariables(void);
static LONG PrvGoCBW(void);
static LONG PrvGoCSW(void);
static LONG PrvCheckCBW(void);
static LONG PrvFindEndpointFromConfigDescriptor(void);
/* =============================================================================
// Function_Name: USBD_ProtStorageReset
// description : Do Reset
// argument : None
// return : Finished normally STATUS_SUCCESS
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageReset(void)
{
LONG retValue;
retValue = STATUS_SUCCESS;
while (1) {
/* Initialize it */
/* Initialize variables */
PrvInitVariables();
/* Call Open and do initial setting here */
retValue = USBD_ProtStorageOpen();
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageOpen
// description : Do Open
// argument : None
// return : Finished abnormally STATUS_UNSUCCESSFUL
// Finished normally STATUS_SUCCESS
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageOpen(void)
{
LONG retValue,retFValue;
UCHAR epxBulkIn,epxBulkOut;
retValue = STATUS_UNSUCCESSFUL;
while (1) {
PrvInitVariables();
/* Get Id */
retFValue = USBD_FuncAllocID(&PrvAllocId);
if (retFValue != STATUS_SUCCESS) {
break;
}
/* Initialize information of Endpoint */
memset(&PrvBulkEPInfo[0],0x00,sizeof (PRV_BULKEPINFO));
memset(&PrvBulkEPInfo[1],0x00,sizeof (PRV_BULKEPINFO));
PrvBulkEPInfo[PRV_BULKIN].bState = PRV_IDLE_STATE;
PrvBulkEPInfo[PRV_BULKOUT].bState = PRV_IDLE_STATE;
/*---------------------------------------------------------------
* Research the Endpoint Number of BulkIn,BulkOut of BulkOnly from Configuration Descriptor,
* set Endpoint Address and MaxPacketSize to PrvBulkEPInfo
*/
retFValue = PrvFindEndpointFromConfigDescriptor();
if (retFValue != STATUS_SUCCESS) {
/* When Class is not Storage Class, or Protocol is not BulkOnly, or Endpoint is unable to be found */
break;
}
epxBulkIn = PrvBulkEPInfo[PRV_BULKIN].bEPNumber;
epxBulkOut = PrvBulkEPInfo[PRV_BULKOUT].bEPNumber;
/* Register the callback function */
/* Rcv Request */
retFValue = USBD_FuncRegisterCBRRequestDecode(PrvRcvRequestCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
/*--- Control Transfer ---*/
retFValue = USBD_FuncRegisterCBREPxPIOSimpleTransferComplete(PrvAllocId,PRV_EP0IN,PrvEP0_DataInEndCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
retFValue = USBD_FuncRegisterCBREP0StatusStageComplete(PrvAllocId,PrvEP0_StatusStageEndCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
/*--- Bulk PIO Transfer ---*/
retFValue = USBD_FuncRegisterCBREPxPIOSimpleTransferComplete(PrvAllocId,epxBulkIn,PrvBulkInPIOTransferEndCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
retFValue = USBD_FuncRegisterCBREPxPIOSimpleTransferComplete(PrvAllocId,epxBulkOut,PrvBulkOutPIOTransferEndCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
/*--- Bulk IN Short Pkt Event ---*/
retFValue = USBD_FuncRegisterCBREPxInt(PrvAllocId,epxBulkIn,PrvBulkTransferShortPktCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
/*--- Bulk OUT Short Pkt Event ---*/
retFValue = USBD_FuncRegisterCBREPxInt(PrvAllocId,epxBulkOut,PrvBulkTransferShortPktCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
/* ClearFeature(ENDPOINT_HALT) (owned by StorageClass) */
retFValue = USBD_ProtRegisterCBREnumClrEndpointHaltReqEvent(USBD_ProtStorageEndpointHalt);
if (retFValue != STATUS_SUCCESS) {
break;
}
/* Configured Event */
retFValue = USBD_ProtRegisterCBREnumConfiguredEvent(USBD_ProtStorageConfigured);
if (retFValue != STATUS_SUCCESS) {
break;
}
/* Deconfigured Event */
retFValue = USBD_ProtRegisterCBREnumDeconfiguredEvent(USBD_ProtStorageDeconfigured);
if (retFValue != STATUS_SUCCESS) {
break;
}
// Add for USBCV MSC Test
/* Set Interface Event */
retFValue = USBD_ProtRegisterCBREnumAlternateChangedEvent(USBD_ProtStorageAlternateChanged);
if (retFValue != STATUS_SUCCESS) {
break;
}
// End of USBCV MSC Test
/* Support function of BulkOnly H/W: CBW,CSW Event */
retFValue = USBD_FuncRegisterCBRBulkOnlyEvent(PrvBulkOnlyEventCallback);
if (retFValue != STATUS_SUCCESS) {
break;
}
/* Initial setting of support function of BulkOnly H/W */
/* Finished normally */
retValue = STATUS_SUCCESS;
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageGetParameter
// description : Get parameter which has been set
// argument : bType Type of parameter
// pParam Address of parameter
// wCount Number of byte for parameter
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_UNSUCCESS
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageGetParameter(UCHAR bType,void *pParam,USHORT wCount)
{
LONG retValue;
USBD_PROT_STORAGE_PARAM_MAXLUN *pMaxLUN;
USBD_PROT_STORAGE_PARAM_EPINFO *pEPInfo;
retValue = STATUS_UNSUCCESSFUL;
while (1) {
if (pParam == NULL) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
switch (bType) {
case USBD_PROT_STORAGE_TYPE_MAXLUN:
/* GetMaxLUN */
if (wCount != 4) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
pMaxLUN = (USBD_PROT_STORAGE_PARAM_MAXLUN *)pParam;
pMaxLUN->bLength = 4;
pMaxLUN->bType = USBD_PROT_STORAGE_TYPE_MAXLUN;
pMaxLUN->bMaxLUN = PrvMaxLUN;
pMaxLUN->bReserved = 0;
retValue = STATUS_SUCCESS;
break;
case USBD_PROT_STORAGE_TYPE_EPINFO:
/* Bulk EP Number */
if (wCount != 4) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
pEPInfo = (USBD_PROT_STORAGE_PARAM_EPINFO *)pParam;
pEPInfo->bLength = 4;
pEPInfo->bType = USBD_PROT_STORAGE_TYPE_EPINFO;
pEPInfo->bBulkInEPNumber = PrvBulkEPInfo[PRV_BULKIN].bEPNumber;
pEPInfo->bBulkOutEPNumber = PrvBulkEPInfo[PRV_BULKOUT].bEPNumber;
break;
default:
break;
}
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageSetParameter
// description : Set parameter
// argument : pParam Parameter to set
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_UNSUCCESS
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageSetParameter(void *pParam)
{
LONG retValue;
USBD_PROT_STORAGE_PARAM_MAXLUN *pMaxLUN;
retValue = STATUS_UNSUCCESSFUL;
while (1) {
pMaxLUN = (USBD_PROT_STORAGE_PARAM_MAXLUN *)pParam;
if (pMaxLUN == NULL) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
if (pMaxLUN->bLength != 4) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
if (pMaxLUN->bType != USBD_PROT_STORAGE_TYPE_MAXLUN) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
PrvMaxLUN = pMaxLUN->bMaxLUN;
retValue = STATUS_SUCCESS;
break;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -