📄 usb_core.c
字号:
DWORD *pTxBuff;
if (save_wLength == 0)
{
/* no more data to send so STALL the TX Status*/
ControlState = WAIT_STATUS_OUT;
vSetEPTxStatus(EP_TX_STALL);
goto Expect_Status_Out;
}
Length = pEPinfo->PacketSize;
ControlState = (save_wLength < Length) ? LAST_IN_DATA : IN_DATA;
/* Same as UsbWrite */
if (Length > save_wLength)
Length = save_wLength;
DataBuffer = (*pEPinfo->CopyData)(Length);
/* transfer data from buffer to PMA */
pTxBuff = (DWORD *)(PMAAddr + GetEPTxAddr(ENDP0));
for(i=0;i < Length;)
{
tmp = *DataBuffer;
tmp|=*(DataBuffer+1)<<8;
tmp|=*(DataBuffer+2)<<16;
tmp|=*(DataBuffer+3)<<24;
DataBuffer = DataBuffer+4;
i=i+4;
*pTxBuff=tmp;
pTxBuff++;
}
SetEPTxCount(ENDP0, Length);
pEPinfo->Usb_wLength -= Length;
pEPinfo->Usb_wOffset += Length;
vSetEPTxStatus(EP_TX_VALID);
USB_StatusOut();/* Expect the host to abort the data IN stage */
Expect_Status_Out: pInformation->ControlState = ControlState;
}/* DataStageIn */
/*******************************************************************************
* Function Name : NoData_Setup0
* Description : Proceed the processing of setup request without data stage
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void NoData_Setup0()
{
DEVICE_INFO *pInfo = pInformation;
RESULT Result;
BYTE RequestNo = pInformation->USBbRequest;
BYTE ControlState;
/*Standard Device Requests*/
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
/*SET_CONFIGURATION*/
if (RequestNo == SET_CONFIGURATION)
Result = Standard_SetConfiguration();
/*SET ADDRESS*/
else if (RequestNo == SET_ADDRESS)
{
if(pInfo->USBwValue0 > 127 || pInfo->USBwValue1!=0
||pInfo->USBwIndex!=0 || pInfo->Current_Configuration!=0)
{
ControlState = STALLED;
goto exit_NoData_Setup0;
}
else Result = USB_SUCCESS;
}
/*SET FEATURE*/
else if (RequestNo == SET_FEATURE)
{
if (pInfo->USBwValue0==DEVICE_REMOTE_WAKEUP && pInfo->USBwIndex==0
&& ValBit(pInfo->Current_Feature,5))
Result = Standard_SetDeviceFeature();
else
Result = UNSUPPORT;
}
/*Clear FEATURE */
else if (RequestNo == CLEAR_FEATURE)
{
if (pInfo->USBwValue0==DEVICE_REMOTE_WAKEUP && pInfo->USBwIndex==0
&&ValBit(pInfo->Current_Feature,5))
Result = Standard_ClearFeature();
else
Result = UNSUPPORT;
}
}
/*Standard Interface Requests*/
else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
{
/*SET INTERFACE*/
if (RequestNo == SET_INTERFACE)
Result = Standard_SetInterface();
}
/*Standard EndPoint Requests*/
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
/*CLEAR FEATURE for EndPoint*/
if (RequestNo == CLEAR_FEATURE)
Result = Standard_ClearFeature();
/*SET FEATURE for EndPoint*/
else if (RequestNo == SET_FEATURE)
{
Result = Standard_SetEndPointFeature();
}
}
else Result = UNSUPPORT;
if (Result != USB_SUCCESS)
{
/*Check and Process possible Class_NoData_Setup Requests*/
Result = (*pProperty->Class_NoData_Setup)(RequestNo);
if (Result == NOT_READY)
{
ControlState = PAUSE;
goto exit_NoData_Setup0;
}
}
if (Result != USB_SUCCESS)
{
ControlState = STALLED;
goto exit_NoData_Setup0;
}
ControlState = WAIT_STATUS_IN; /* After no data stage SETUP */
USB_StatusIn();
exit_NoData_Setup0:
pInfo->ControlState = ControlState;
return;
} /* NoData_Setup0 */
/*******************************************************************************
* Function Name : Data_Setup0
* Description : Processing Setup Requests with data stage
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void Data_Setup0()
{
DEVICE_INFO *pInfo = pInformation;
DEVICE_PROP *pProp = pProperty;
BYTE *(*CopyRoutine)(WORD);
RESULT Result;
BYTE Request_No = pInfo->USBbRequest;
BYTE *pbLen;
BYTE Related_Endpoint,Reserved;
WORD wOffset,wLen,Status;
CopyRoutine = NULL;
wOffset = 0;
/*GET_DESCRIPTOR*/
if (Request_No == GET_DESCRIPTOR)
{
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
BYTE wValue1 = pInfo->USBwValue1;
if (wValue1 == DEVICE_DESCRIPTOR)
CopyRoutine = pProp->GetDeviceDescriptor;
else if (wValue1 == CONFIG_DESCRIPTOR)
CopyRoutine = pProp->GetConfigDescriptor;
else if (wValue1 == STRING_DESCRIPTOR)
{
wOffset = pInfo->USBwValue0;
CopyRoutine = pProp->GetStringDescriptor;
}
}
}
/*GET STATUS*/
else if (Request_No == GET_STATUS && pInfo->USBwValue==0
&& pInfo->USBwLength == 0x0002 && pInfo->USBwIndex1==0)
{
/* GET STATUS for Device*/
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT) && pInfo->USBwIndex==0)
{
CopyRoutine = Standard_GetStatus;
}
/* GET STATUS for Interface*/
else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
{
if ((*pProp->Class_Get_Interface_Setting)(pInfo->USBwIndex0,0)==USB_SUCCESS
&& pInfo->Current_Configuration!=0)
CopyRoutine = Standard_GetStatus;
}
/* GET STATUS for EndPoint*/
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
Related_Endpoint = (pInfo->USBwIndex0 & 0x0f);
Reserved= pInfo->USBwIndex0 & 0x70;
if (ValBit(pInfo->USBwIndex0, 7))
Status =_GetEPTxStatus(Related_Endpoint);
else Status =_GetEPRxStatus(Related_Endpoint);
if(Related_Endpoint < Device_Table.Total_Endpoint && Reserved==0 && Status != 0)
CopyRoutine = Standard_GetStatus;
}
}
/*GET CONFIGURATION*/
else if (Request_No == GET_CONFIGURATION)
{
if ( Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT) )
CopyRoutine = Standard_GetConfiguration;
}
/*GET INTERFACE*/
else if (Request_No == GET_INTERFACE)
{
if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)
&& pInfo->Current_Configuration!=0 && pInfo->USBwValue==0
&& pInfo->USBwIndex1==0 && pInfo->USBwLength == 0x0001
&& (*pProperty->Class_Get_Interface_Setting)(pInfo->USBwIndex0,0)==USB_SUCCESS)
CopyRoutine = Standard_GetInterface;
}
if (CopyRoutine)
{
pInfo->Ctrl_Info.Usb_wOffset = wOffset;
pInfo->Ctrl_Info.CopyData = CopyRoutine;
pbLen = (*CopyRoutine)(0);
wLen = (WORD)((DWORD)pbLen);
pInfo->Ctrl_Info.Usb_wLength = wLen;
Result = USB_SUCCESS;
}
else
{
/*check and process possible Class_Data_Setup request*/
Result = (*pProp->Class_Data_Setup)(pInfo->USBbRequest);
if(Result == NOT_READY)
{
pInfo->ControlState = PAUSE;
return;
}
}
if (pInfo->Ctrl_Info.Usb_wLength == -1)
{
/* Data is not ready, wait it */
pInfo->ControlState = PAUSE;
return;
}
if (Result == UNSUPPORT || pInfo->Ctrl_Info.Usb_wLength == 0)
{
/* Unsupported request */
pInfo->ControlState = STALLED;
return;
}
if (ValBit(pInfo->USBbmRequestType, 7))
{
/* Device ==> Host */
WORD wLength = pInfo->USBwLength;
/* Restrict the data length to be the one host asks */
if (pInfo->Ctrl_Info.Usb_wLength > wLength)
pInfo->Ctrl_Info.Usb_wLength = wLength;
pInfo->Ctrl_Info.PacketSize = pProp->MaxPacketSize;
DataStageIn();
}
else
{
pInfo->ControlState = OUT_DATA;
vSetEPRxStatus(EP_RX_VALID);/* enable for next data reception */
}
return;
} /* Data_Setup0 */
/*******************************************************************************
* Function Name : Setup0_Process
* Description : Setup Token processing (entry point)
* Input : None
* Output : None
* Return : (see Post0_Process)
*******************************************************************************/
BYTE Setup0_Process()
{
DEVICE_INFO *pInfo = pInformation;
WORD* pBuf;
pBuf= (WORD *)(GetEPRxAddr(ENDP0)+PMAAddr);
if (pInfo->ControlState != PAUSE)
{
pInfo->USBbmRequestType = (*pBuf)&0xFF; /* bmRequestType */
pInfo->USBbRequest = ((*pBuf)&0xFF00)>>8; /* bRequest */
pInfo->USBwValue = ByteSwap(*(pBuf+1)); /* wValue */
pInfo->USBwIndex = ByteSwap(*(pBuf+2)); /* wIndex */
pInfo->USBwLength = *(pBuf+3); /* wLength */
}
pInfo->ControlState = SETTING_UP;
if (pInfo->USBwLength == 0)
{
/* Setup with no data stage */
NoData_Setup0();
}
else
{
/* Setup with data stage */
Data_Setup0();
}
return Post0_Process();
} /* Setup0_Process */
/*******************************************************************************
* Function Name : In0_Process
* Description : Process the IN tocken on control endpoint
* Input : None
* Output : None
* Return : (see Post0_Process)
*******************************************************************************/
BYTE In0_Process()
{
DEVICE_INFO *pInfo = pInformation;
BYTE ControlState = pInfo->ControlState;
if (ControlState == IN_DATA || ControlState == LAST_IN_DATA)
{
DataStageIn();
ControlState = pInfo->ControlState;
}
else if (ControlState == WAIT_STATUS_IN)
{
if (pInfo->USBbRequest == SET_ADDRESS &&
Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT) )
{
SetDeviceAddress(pInfo->USBwValue0);
}
(*pProperty->Process_Status_IN)();
ControlState = STALLED;
}
else
ControlState = STALLED;
pInfo->ControlState = ControlState;
return Post0_Process();
} /* In0_Process */
/*******************************************************************************
* Function Name : Out0_Process
* Description : Process the OUT token on control endpoint
* Input : None
* Output : None
* Return : (see Post0_Process)
*******************************************************************************/
BYTE Out0_Process()
{
DEVICE_INFO *pInfo = pInformation;
BYTE ControlState = pInfo->ControlState;
if(ControlState == OUT_DATA || ControlState == LAST_OUT_DATA)
DataStageOut();
else if (ControlState == WAIT_STATUS_OUT)
{
(*pProperty->Process_Status_OUT)();
ControlState = STALLED;
}
else if (ControlState == IN_DATA || ControlState == LAST_IN_DATA)
{
/* host aborts the transfer before finish */
ControlState = STALLED;
}
/* Unexpect state, STALL the endpoint */
else
{
ControlState = STALLED;
}
pInfo->ControlState = ControlState;
return Post0_Process();
} /* Out0_Process */
/*******************************************************************************
* Function Name : Post0_Process
* Description : Stalls ENDPOINT0 if ControlState = STALLED
* Input : None
* Output : None
* Return : 0: if ControlState is not " PAUSE "
* 1: if ControlState is "PAUSE"
*******************************************************************************/
BYTE Post0_Process()
{
_SetEPRxCount(ENDP0, STD_MAXPACKETSIZE);
if (pInformation->ControlState == STALLED)
{
vSetEPRxStatus(EP_RX_STALL);
vSetEPTxStatus(EP_TX_STALL);
}
return (pInformation->ControlState == PAUSE);
} /* Post0_Process */
/*******************************************************************************
* Function Name : SetDeviceAddress
* Description : Set Device Address
* Input : Val: Device Address
* Output : None
* Return : None
*******************************************************************************/
void SetDeviceAddress(BYTE Val)
{
int i;
DEVICE *pDevice = &Device_Table;
/* BYTE EP0 = pDevice->EP0; */
int nEP = pDevice->Total_Endpoint;
/* set address in every used endpoint */
for(i=0;i<nEP;i++)
{
_SetEPAddress((BYTE)i, (BYTE)i);
} /* for */
_SetDADDR(Val|DADDR_EF); /* set device address and enable function */
} /* SetDeviceAddress */
/*******************************************************************************
* Function Name : NOP_Process
* Description : Do Nothing
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void NOP_Process(void)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -