📄 usbh_hcds_urb.c
字号:
// Function_Name: URBListEndpointSearchCancel
//
// description : URB of Endpoint of the corresponding device is canceled from the URB list
//
// Corresponding URB is serched from the link list on passed USB device information structure
// and Endpoint address, and be canceled.
//
// argument : *psSearchList (in)Pointer to URB list
// psRootDev (in)Pointer of USB device information structure of route hub
// devNum (in)USB device address
// epAddress (in)Endpoint address(Direction+EP number)
//
// return : None
===============================================================================================*/
Inline void URBListEndpointSearchCancel( USBH_HCD_LIST_HEAD *psSearchList, USBH_HCD_USBDEV *psRootDev,
unsigned char devNum, unsigned char epAddress )
{
USBH_HCD_URB *psUrb;
USBH_HCD_LIST_HEAD *psListEnd, *psList;
unsigned char usbAddress;
unsigned long pipe;
if( USBH_HCDS_ListEmpty(psSearchList) == 0 ){
/* There is URB in Queuing */
/*===================================================/
Finish search if the first list header becomes the tail and reach there /
/ because it is a link list /
/===================================================*/
psListEnd = psSearchList;
psList = psSearchList->psNext;
do{
psUrb = USBH_HCDS_ListEntry(psList, USBH_HCD_URB, sList);
pipe = psUrb->pipe;
usbAddress = USBH_HCDS_GetPipeUSBDevAdrs(pipe);
if( usbAddress == devNum ){
/* Corresponding USB device */
pipe = psUrb->pipe;
if( USBH_HCDS_GetPipeEndpointAdrs(pipe) == epAddress ){
/* Corresponding Endpoint*/
/*===============/
Cancel process/
/===============*/
USBH_HCDS_URBUnlink(psUrb, psRootDev);
/* Because connection situation of the list changes by the cancel process, return to the head */
if( USBH_HCDS_ListEmpty(psSearchList) == 1 ){
/* case of list empty */
return;
}
psList = psSearchList;
}
}
psList = psList->psNext;
}while( psList != psListEnd );
}
}
/*=============================================================================================
// Function_Name: URBTranCmpCallback
//
// description : Callback process when URB is completed
//
// When URB is completed, it is called
//
// argument : chNum (in)Channel number
// urbStatus (in)URB status
// *pParam (in)Pointer of URB structure
//
// return : None
===============================================================================================*/
static long URBTranCmpCallback( unsigned long chNum, unsigned long urbStatus, void *pParam )
{
USBH_HCD_URB *psUrb;
CH_INFO *psCHInfo;
psUrb = pParam;
/*============================/
Delete from URB active queue/
/============================*/
psCHInfo = (CH_INFO *)psUrb->pHCPriv;
if( (psCHInfo->chType == USBH_HCDS_CH_TYPE_CTRL) || (psCHInfo->chType == USBH_HCDS_CH_TYPE_BULK)
|| (psCHInfo->chType == USBH_HCDS_CH_TYPE_STRG) ){
USBH_HCDS_ListDel(&(psUrb->sList));
psUrb->pHCPriv = NULL;
/*==============================/
Call the URB Completion callback /
/==============================*/
ExecURBCallback(psUrb, urbStatus);
/* Check for queueing of URB */
CheckQueuedURB(psCHInfo);
} else {
/*==============================/
Call the URB Completion callback /
/==============================*/
ExecURBCallback(psUrb, urbStatus);
}
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: CheckQueuedURB
//
// description : Check the queueing URB
//
// Check the queueing URB of execution waiting, and execute it if existing.
//
// argument : *psUrb (in)Pointer of URB structure
//
// return : None
===============================================================================================*/
Inline void CheckQueuedURB( CH_INFO *psCHInfo )
{
USBH_HCD_LIST_HEAD *psList;
USBH_HCD_URB *psNextUrb;
unsigned int skip, allocCH;
unsigned char nextCHNum, chType;
unsigned long fifoSize;
long retValue;
psList = NULL; // Countermeasure against warning of optimizing
chType = 0; // Countermeasure against warning of optimizing
allocCH = 0;
if( psCHInfo->chType == USBH_HCDS_CH_TYPE_CTRL ){
/* When channel used by control transfer is released */
if( USBH_HCDS_ListEmpty(&(URBStatus.sCtrlURBList)) == 0 ){
/* There is URB in queueing */
psList = &(URBStatus.sCtrlURBList);
allocCH = 1;
chType = USBH_HCDS_CH_TYPE_CTRL;
}
} else if( psCHInfo->chType == USBH_HCDS_CH_TYPE_STRG ){
/* When channel used by Bulk-Only transfer is released */
if( USBH_HCDS_ListEmpty(&(URBStatus.sStrgURBList)) == 0 ){
/* There is URB in queueing */
psList = &(URBStatus.sStrgURBList);
allocCH = 1;
chType = USBH_HCDS_CH_TYPE_STRG;
}
} else {
/* When channel used by Bulk-Only transfer is released */
if( URBStatus.pendingAsyncSetupCount != 0 ){
/* Synchronous transfer(Interrupt/Isochronous)setting is being reserved */
skip = 0;
if( USBH_HCDS_ListEmpty(&(URBStatus.sIsoURBList)) == 0 ){
/* There is URB of Isochronous transfer in queueing */
psList = &(URBStatus.sIsoURBList);
allocCH = 1;
chType = USBH_HCDS_CH_TYPE_ISO;
URBStatus.pendingAsyncSetupCount--; /* Update the synchronous transfer(Interrupt/Isochronous) setting reservation counter */
skip = 1;
}
if( (skip == 0) && (USBH_HCDS_ListEmpty(&(URBStatus.sIntURBList)) == 0) ){
/* There is URB of Interrupt transfer in queueing */
psList = &(URBStatus.sIntURBList);
allocCH = 1;
chType = USBH_HCDS_CH_TYPE_INT;
URBStatus.pendingAsyncSetupCount--; /* Update the synchronous transfer(Interrupt/Isochronous) setting reservation counter */
}
}
if( allocCH == 0 ){
/* When the other allocated factor doesn't exist */
if( USBH_HCDS_ListEmpty(&(URBStatus.sBulkURBList)) == 0 ){
/* There is URB of Bulk transfer in queueing */
psList = &(URBStatus.sBulkURBList);
allocCH = 1;
chType = USBH_HCDS_CH_TYPE_BULK;
}
}
}
if( allocCH != 0 ){
psNextUrb = USBH_HCDS_ListEntry(psList->psNext, USBH_HCD_URB, sList);
psCHInfo = (CH_INFO *)psNextUrb->pHCPriv;
fifoSize = GetFIFOSize(psNextUrb, chType);
retValue = USBH_HCDS_CHAlloc(&nextCHNum, chType, fifoSize);
if( retValue == STATUS_SUCCESS ){
/* Channel allocation success */
/*=================/
Channel information update /
/=================*/
psNextUrb->pHCPriv = &URBStatus.sCHInfo[nextCHNum];
URBStatus.sCHInfo[nextCHNum].chNum = nextCHNum;
URBStatus.sCHInfo[nextCHNum].chType = chType;
/*==============================================================/
Remove from the waiting queue, put into URB active queue, and execute the channel/
/==============================================================*/
USBH_HCDS_InterruptDisable();
USBH_HCDS_ListDel(&(psNextUrb->sList));
USBH_HCDS_ListAddTail(&(psNextUrb->sList), &(URBStatus.sActiveURBList));
USBH_HCDS_InterruptEnable();
USBH_HCDS_CHTranGo(psNextUrb, nextCHNum, URBTranCmpCallback);
}
}
}
/*=============================================================================================
// Function_Name: CheckStorageModeURB
//
// description : URB parameter check at storage mode
//
// Check to see whether the URB structure at the storage mode is appropriate
//
// argument : *psUrb (in)Pointer of URB structure
//
// return : None
===============================================================================================*/
Inline long CheckStorageModeURB( USBH_HCD_URB *psUrb )
{
USBH_HCD_URB *psCBWURB, *psCSWURB, *psDataURB;
unsigned char *pCBWDataTransferLength;
unsigned long dataLength;
if( psUrb->psNext == NULL ){
/* CSW doesn't exsit */
return STATUS_INVALID_PARAMETER;
}
psCBWURB = psUrb;
if( psCBWURB->psNext->psNext == NULL ){
/* CBW + CSW */
psCSWURB = psUrb->psNext;
psDataURB = NULL;
} else {
/* CBW + DATA + CSW */
psDataURB = psUrb->psNext;
psCSWURB = psDataURB->psNext;
if( psCSWURB->psNext != NULL ){
/* Unnecessary URB is connected */
return STATUS_INVALID_PARAMETER;
}
}
if( psCBWURB->transBufLength != BO_CBW_SIZE ){
/* Differ from the data size of CBW */
return STATUS_INVALID_PARAMETER;
}
if( USBH_HCDS_GetPipeType(psCBWURB->pipe) != USBH_HCD_PIPE_BULK ){
/* Excluding the pipe for the Bulk transfer */
return STATUS_INVALID_PARAMETER;
}
if( USBH_HCDS_CheckPipeIN(psCBWURB->pipe) != 0 ){
/* Endpoint of IN direction */
return STATUS_INVALID_PARAMETER;
}
pCBWDataTransferLength = psCBWURB->pTransBuf;
dataLength = pCBWDataTransferLength[OFFSET_BO_CBW_DATA_LENGTH];
dataLength |= (pCBWDataTransferLength[OFFSET_BO_CBW_DATA_LENGTH + 1] << 8) & 0x0000FF00;
dataLength |= (pCBWDataTransferLength[OFFSET_BO_CBW_DATA_LENGTH + 2] << 16) & 0x00FF0000;
dataLength |= (pCBWDataTransferLength[OFFSET_BO_CBW_DATA_LENGTH + 3] << 24) & 0xFF000000;
if( dataLength == 0 ){
if( psDataURB != NULL ){
/* There should be no URB for Data, but there is */
return STATUS_INVALID_PARAMETER;
}
} else {
if( psDataURB == NULL ){
/* There should be URB for Data, but there isn't */
return STATUS_INVALID_PARAMETER;
}
}
if( psCSWURB->transBufLength != BO_CSW_SIZE ){
/* Differ from the data size of CSW */
return STATUS_INVALID_PARAMETER;
}
if( psCSWURB->pTransBuf == NULL ){
/* The pointer in the data buffer of CSW is NULL */
return STATUS_INVALID_PARAMETER;
}
if( USBH_HCDS_GetPipeType(psCSWURB->pipe) != USBH_HCD_PIPE_BULK ){
/* Excluding the pipe for the Bulk transfer */
return STATUS_INVALID_PARAMETER;
}
if( USBH_HCDS_CheckPipeOUT(psCSWURB->pipe) != 0 ){
/* Endpoint of OUT direction */
return STATUS_INVALID_PARAMETER;
}
if( psDataURB != NULL ){
/* When there is data URB */
if( USBH_HCDS_GetPipeType(psDataURB->pipe) != USBH_HCD_PIPE_BULK ){
/* Excluding the pipe for the Bulk transfer */
return STATUS_INVALID_PARAMETER;
}
if( psDataURB->transBufLength != 0 ){
/* Transfer data length is except 0*/
if( psDataURB->pTransBuf == NULL && (psCBWURB->transFlag & USBH_HCD_URB_DIRECT_COPY) == 0 ){
/* The pointer in the data buffer of Data is NULL excluding a direct copy */
return STATUS_INVALID_PARAMETER;
}
}
}
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: NotifyStatusChanged
//
// description : Status change notification of virtual route hub
//
// The status of hub/port of the virtual route hub is notified when changed
//
// argument : param0 (in)Not used
// param1 (in)Not used
// *pParam (in)Not used
//
// return : None
===============================================================================================*/
long NotifyStatusChanged( unsigned long param0, unsigned long param1, void *pParam )
{
unsigned long vhubStatus;
vhubStatus = param0;
if( (vhubStatus & USBH_HCDS_VHUB_HUB_STATUS) != 0 ){
*((UCHAR *)URBStatus.psRootIntUrb->pTransBuf) = HUB_BIT;
}
if( (vhubStatus & USBH_HCDS_VHUB_PORT_STATUS) != 0 ){
*((UCHAR *)URBStatus.psRootIntUrb->pTransBuf) = HUB_PORT_BIT;
}
if( vhubStatus != 0 ){
/*=====================================================/
The port status changing is notified with Interrupt IN of the route hub/
/=====================================================*/
ExecURBCallback(URBStatus.psRootIntUrb, USBH_HCD_URBSTS_SUCCESS);
}
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: ExecURBCallback
//
// description : URB completion callback processing
//
// The completion callback function of URB is called
//
// argument : *psUrb (in)Pointer of URB structure
// usbStatus (in)URB status
//
// return : None
===============================================================================================*/
Inline void ExecURBCallback( USBH_HCD_URB *psUrb, unsigned long urbStatus )
{
USBH_HCD_URB *psExecUrb;
psExecUrb = psUrb;
if( psUrb->transFlag & USBH_HCD_URB_STRG_MODE ){
/* When the Bulk-Only support function of Mass Storage Class is used */
if( urbStatus == USBH_HCD_URBSTS_SUCCESS ){
/* All URB terminated successfully */
while(1){
if( psExecUrb->psNext == NULL ){
break;
}
psExecUrb = psExecUrb->psNext;
}
} else {
while(1){
if( psExecUrb->status != USBH_HCD_URBSTS_SUCCESS ){
/* URB structure be found when terminated unsuccessfully */
break;
}
/* For URB list check Next when URB terminated abnormally, changed in order to not check the NULL */
if( psExecUrb->psNext == NULL ){
break;
}
psExecUrb = psExecUrb->psNext;
}
}
}
/*=========================/
Call the completion callback /
/=========================*/
if( psExecUrb->status != USBH_HCD_URBSTS_NOENT ){
/* The callback is called excluding the cancellation by USBH_HCD_UnlinkURB(). */
if( psExecUrb->pfnComplete != NULL ){
/* When the callback function is registered */
/* The callback function is called. (URB passed as argument is a pointer of the URB structure
passed with USBH_HCD_SubmitURB(). ) */
(psExecUrb->pfnComplete)(psUrb);
}
}
}
/*=============================================================================================
// Function_Name: GetFIFOSize
//
// description : Returned the allocated FIFO size
//
// Return the FIFO size allocated by the passed channel type
//
// argument : *psUrb (in)Pointer of URB structure
// chType (in)Channel type
//
// return : None
===============================================================================================*/
Inline unsigned long GetFIFOSize( USBH_HCD_URB *psUrb, unsigned char chType )
{
unsigned long fifoSize;
USBH_HCDS_GetPipeMaxPacketSize(psUrb->psDev, psUrb->pipe, fifoSize);
switch( chType ){
case USBH_HCDS_CH_TYPE_BULK:
case USBH_HCDS_CH_TYPE_STRG:
/* Use Double Buffer in Bulk or Storage transfer */
fifoSize *= 2;
break;
default:
/* Use Single Buffer excluding Bulk and Storage transfer */
;
}
return fifoSize;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -