📄 usbd_protstorage.c
字号:
tempRet = USBD_FuncEP0StatusStageReadyA(PrvAllocId);
if (tempRet != STATUS_SUCCESS) {
/* Unable to start Status Stage */
break;
}
}
if (IS_BIT(PrvBulkOnlyStatus,USBD_PROT_STORAGE_GETMAXLUN) == TRUE) {
CLR_BIT(PrvBulkOnlyStatus,USBD_PROT_STORAGE_GETMAXLUN);
/* If GetMaxLUN had been received, return MaxLUN in Status Stage */
tempRet = USBD_FuncEPxPIOSimpleTransferA(PrvAllocId,PRV_EP0IN,(UCHAR *)&PrvMaxLUN,1);
if (tempRet != STATUS_SUCCESS) {
/* Unable to start Data Stage */
USBD_FuncSetEPxControl(PRV_EP0IN, USBD_FUNC_CE_STALLMODE, USBD_FUNC_FLAG_SET);
USBD_FuncSetEPxControl(PRV_EP0OUT, USBD_FUNC_CE_STALLMODE, USBD_FUNC_FLAG_SET);
break;
}
}
retValue = STATUS_SUCCESS;
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageRequestFail
// description : Be used when request of Mass Storage Class was unable to be received
// argument : None
// return : Finished normally STATUS_SUCCESS
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageRequestFail(void)
{
LONG retValue;
retValue = STATUS_SUCCESS;
/* Assume it as request error */
USBD_FuncSetEPxControl(PRV_EP0IN, USBD_FUNC_CE_STALLMODE, USBD_FUNC_FLAG_SET);
USBD_FuncSetEPxControl(PRV_EP0OUT, USBD_FUNC_CE_STALLMODE, USBD_FUNC_FLAG_SET);
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageXferStart
// description : Start the transfer of Storage Data
// argument : lParam0 Endpoint Number
//
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_NOT_IMPLEMENTED
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageXferStart(UCHAR *bufferPtr,ULONG xferSize,UCHAR xferDir,UCHAR xferType,UCHAR dmaCh,UCHAR xferMode)
{
LONG retValue,tempRet;
UCHAR epNumber,shortPkt;
ULONG remainXfer;
UCHAR epx;
retValue = STATUS_SUCCESS;
while (1) {
if (xferDir == USBD_PROT_STORAGE_BULKIN) {
epNumber = PrvBulkEPInfo[PRV_BULKIN].bEPNumber;
remainXfer = PrvBulkEPInfo[PRV_BULKIN].dwTotalXferSize - PrvBulkEPInfo[PRV_BULKIN].dwXferedSize;
} else {
epNumber = PrvBulkEPInfo[PRV_BULKOUT].bEPNumber;
remainXfer = PrvBulkEPInfo[PRV_BULKOUT].dwTotalXferSize - PrvBulkEPInfo[PRV_BULKOUT].dwXferedSize;
}
if (xferSize > remainXfer) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
shortPkt = 0;
if (xferMode == USBD_PROT_STORAGE_SHORTENB) {
shortPkt = 1;
}
/* Set information for transfer */
if (xferDir == USBD_PROT_STORAGE_BULKIN) {
epx = PRV_BULKIN;
} else {
epx = PRV_BULKOUT;
}
PrvBulkEPInfo[epx].dwActXferSize = xferSize;
PrvBulkEPInfo[epx].bShortPkt = shortPkt;
PrvBulkEPInfo[epx].bUseDMA = 0;
/* Event Off */
USBD_FuncSetEPxIntEvent(PrvAllocId,PrvBulkEPInfo[PRV_BULKIN].bEPNumber,0x00,0x00);
USBD_FuncSetEPxIntEvent(PrvAllocId,PrvBulkEPInfo[PRV_BULKOUT].bEPNumber,0x00,0x00);
if (xferType == USBD_PROT_STORAGE_PIOMODE) {
/* Mode of PIO transfer */
/* Set to enable the ShortPkt transfer */
if (shortPkt == 1) {
tempRet = USBD_FuncSetEPxTransferMode(PrvAllocId,epNumber,USBD_FUNC_ENB_SHORTPKT_MODE);
} else {
tempRet = USBD_FuncSetEPxTransferMode(PrvAllocId,epNumber,USBD_FUNC_DIS_SHORTPKT_MODE);
}
if (tempRet != STATUS_SUCCESS) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
/* Start to transfer */
tempRet = USBD_FuncEPxPIOSimpleTransferA(PrvAllocId,epNumber,bufferPtr,xferSize);
if (tempRet != STATUS_SUCCESS) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
PrvBulkEPInfo[epx].bState = PRV_DATA_STATE;
} else {
/* Mode of DMA transfer */
/* Mark that this Endpoint is used by DMA transfer */
tempRet = USBD_FuncStartEPxDMATransfer(PrvAllocId,epNumber);
if (tempRet != STATUS_SUCCESS) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
/* Correlate this Endpoint and DMA */
tempRet = USBD_FuncSetEPxJoinDMA(epNumber,dmaCh,1,shortPkt);
if (tempRet != STATUS_SUCCESS) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
//START DMA TRANSLATE,GO!GO!GOOO!!!
/* In order to judge the receiving of ShortPkt while in OUT transfer, enable notification for OUT_ShortAck event */
if (xferDir == USBD_PROT_STORAGE_BULKOUT) {
tempRet = USBD_FuncSetEPxIntEvent(PrvAllocId,epNumber,USBD_FUNC_IE_OUT_SHORT_ACK,0x00);
if (tempRet != STATUS_SUCCESS) {
retValue = STATUS_INVALID_PARAMETER;
break;
}
}
else
{
/* Set to enable the ShortPkt transfer */
if (shortPkt == 1) {
tempRet = USBD_FuncSetEPxTransferMode(PrvAllocId,epNumber,USBD_FUNC_ENB_SHORTPKT_MODE);
} else {
tempRet = USBD_FuncSetEPxTransferMode(PrvAllocId,epNumber,USBD_FUNC_DIS_SHORTPKT_MODE);
}
}
/* Release ForceNAK */
USBD_FuncSetEPxControl(epNumber,USBD_FUNC_CE_NAKMODE,USBD_FUNC_FLAG_CLR);
/* Set flag which means whether it is used in DMA transfer */
PrvBulkEPInfo[epx].bUseDMA = 1;
PrvBulkEPInfo[epx].bDmaCh = dmaCh;
PrvBulkEPInfo[epx].bState = PRV_DATA_STATE;
}
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageXferAbort
// description : Abort the transfer of USBD_ProtStorageXferStart
// argument : lParam0 Endpoint Number
//
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_NOT_IMPLEMENTED
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageXferAbort(void)
{
LONG retValue;
UCHAR epx;
retValue = STATUS_SUCCESS;
while (1) {
if (PrvBulkEPInfo[PRV_BULKIN].dwReqXferSize > 0) {
epx = PRV_BULKIN;
} else if (PrvBulkEPInfo[PRV_BULKOUT].dwReqXferSize > 0) {
epx = PRV_BULKOUT;
} else {
epx = 0xFF;
}
if (epx != 0xFF) {
if (PrvBulkEPInfo[epx].bUseDMA == 1) {
/* When it is Abort, remove the Join with DMA */
USBD_FuncSetEPxJoinDMA(PrvBulkEPInfo[epx].bEPNumber,PrvBulkEPInfo[epx].bDmaCh,0,0);
}
if (PrvBulkEPInfo[epx].bState == PRV_DATA_STATE) {
/* Abort the transfer if it is on transferring of Bulk data */
PrvBulkEPInfo[epx].bState = PRV_ABORT_STATE;
if (PrvBulkEPInfo[epx].bUseDMA == 0) {
USBD_FuncEPxPIOSimpleTransferAbort(PrvAllocId,PrvBulkEPInfo[epx].bEPNumber);
} else {
USBD_FuncEndEPxDMATransfer(PrvBulkEPInfo[epx].bEPNumber);
}
PrvBulkEPInfo[epx].dwActXferSize = 0;
/* abortFlag = TRUE; */
}
}
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageXferFlush
// description : If there are remained data in FIFO, flush it and finish the transfer
// argument : lParam0 Endpoint Number
//
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_NOT_IMPLEMENTED
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageXferFlush(void)
{
LONG retValue,tempRet;
UCHAR epx;
UCHAR bEPControl;
ULONG dwRemain;
retValue = STATUS_SUCCESS;
while (1) {
if (PrvBulkEPInfo[PRV_BULKIN].dwReqXferSize > 0) {
epx = PRV_BULKIN;
} else if (PrvBulkEPInfo[PRV_BULKOUT].dwReqXferSize > 0) {
epx = PRV_BULKOUT;
} else {
epx = 0xFF;
}
if (epx != 0xFF) {
if (PrvBulkEPInfo[epx].bUseDMA == 1) {
/* While flushing, remove the Join with DMA */
USBD_FuncSetEPxJoinDMA(PrvBulkEPInfo[epx].bEPNumber,PrvBulkEPInfo[epx].bDmaCh,0,0);
}
}
if (epx == PRV_BULKIN) {
/* Do flush only for transfer of IN direction */
if (PrvBulkEPInfo[epx].bState == PRV_DATA_STATE) {
USBD_FuncGetEPxControl(PrvBulkEPInfo[epx].bEPNumber,&bEPControl);
if (IS_BIT(bEPControl,USBD_FUNC_CE_ENBSHORT) == FALSE) {
/* When transmission of ShortPkt has not been enabled */
USBD_FuncGetEPxPIODataRemain(PrvBulkEPInfo[epx].bEPNumber,&dwRemain);
if (dwRemain > 0) {
if (PrvBulkEPInfo[epx].bUseDMA == 1) {
/* Register event for detecting completion of flush */
tempRet = USBD_FuncSetEPxIntEvent(PrvAllocId,PrvBulkEPInfo[PRV_BULKIN].bEPNumber,USBD_FUNC_IE_FIFOEMPTY,0x00);
if (tempRet != STATUS_SUCCESS) {
retValue = STATUS_UNSUCCESSFUL;
break;
}
}
if ((dwRemain % PrvBulkEPInfo[epx].wMaxPacket) != 0) {
/* If it can't be divided by MaxPacketSize, enable the transmission of ShortPkt */
USBD_FuncSetEPxControl(PrvBulkEPInfo[epx].bEPNumber,USBD_FUNC_CE_ENBSHORT,USBD_FUNC_FLAG_SET);
}
} else if (dwRemain == 0) {
if (PrvBulkEPInfo[epx].bUseDMA == 1) {
/* When there is no data in FIFO already */
SET_BIT(PrvInternalStatus,PRV_IR_BULKIN_TRANSFER_END);
}
}
}
}
} else if (epx == PRV_BULKOUT) {
if (PrvBulkEPInfo[epx].bUseDMA == 1) {
/* */
SET_BIT(PrvInternalStatus,PRV_IR_BULKOUT_TRANSFER_END);
}
}
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageRegisterCBRStorageXferEvent
// description : Register the callback function for notifying StorageXferEvent
// argument : pfnCallback Address of callback function to be registered
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_UNABLE_TO_REGISTER
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageRegisterCBRStorageXferEvent(CALLBACK_PROC pfnCallback)
{
LONG retValue;
retValue = STATUS_SUCCESS;
while (1) {
/* Register the callback function */
if (PrvStorageXferEventCallback != NULL) {
/* Unable to register */
retValue = STATUS_UNABLE_TO_REGISTER;
break;
}
/* Register the callback function */
PrvStorageXferEventCallback = pfnCallback;
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageUnregisterCBRStorageXferEvent
// description : Delete callback function which is registered in USBD_ProtStorageRegisterCBRStorageEvent
// argument : pfnCallback Callback function to delete
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_UNREGISTERD
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageUnregisterCBRStorageXferEvent(CALLBACK_PROC pfnCallback)
{
LONG retValue;
retValue = STATUS_SUCCESS;
while (1) {
if (pfnCallback == PrvStorageXferEventCallback) {
/* Delete the callback function */
PrvStorageXferEventCallback = NULL;
} else {
/* Unable to delete */
retValue = STATUS_UNREGISTERED;
}
break;};
return retValue;
}
/* =============================================================================
// Function_Name: USBD_ProtStorageEndpointHalt
// description : Do process for ClearFeature(ENDPOINT_HALT)
// argument : lParam0 Endpoint Number
//
// return : Finished normally STATUS_SUCCESS
// Finished abnormally STATUS_NOT_IMPLEMENTED
// flag :
// global :
// =============================================================================
*/
LONG USBD_ProtStorageEndpointHalt(ULONG lParam0,ULONG lParam1,void *pParam)
{
LONG retValue;
UCHAR bBitMask,bEPxControl,epNumber;
retValue = STATUS_NOT_IMPLEMENTED;
while (1) {
epNumber = (UCHAR)lParam0;
if (epNumber == PrvBulkEPInfo[PRV_BULKIN].bEPNumber || epNumber == PrvBulkEPInfo[PRV_BULKOUT].bEPNumber) {
/* Bulk IN or Bulk OUT Endpoint */
retValue = USBD_FuncGetEPxControl(epNumber,&bEPxControl);
bBitMask = USBD_FUNC_CE_TOGGLE;
/* Clear Toggle bit */
USBD_FuncSetEPxControl(epNumber,bBitMask,USBD_FUNC_FLAG_CLR);
if ((bEPxControl & USBD_FUNC_CE_STALLMODE) != 0) {
/* When it is mode of STALL reply */
bBitMask = USBD_FUNC_CE_FIFOCLEAR;
USBD_FuncSetEPxControl(epNumber,bBitMask,USBD_FUNC_FLAG_CLR);
if (IS_BIT(PrvInternalStatus,PRV_IR_RESET_RECOVERY) == FALSE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -