/**
******************************************************************************
* @file usb_core.c
* @author MCD Application Team
* @version V4.0.0
* @date 28-August-2012
* @brief Standard protocol processing (USB v2.0)
******************************************************************************
* @attention
*
*
© COPYRIGHT 2012 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
#include "usb_lib.h"
// Private definee
#define ValBit(VAR,Place) (VAR & (1 << Place))
#define SetBit(VAR,Place) (VAR |= (1 << Place))
#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255))
#define Send0LengthData() { SetEPTxCount(ENDP0,0); vSetEPTxStatus(EP_TX_VALID); }
#define vSetEPRxStatus(st) (SaveRState = st)
#define vSetEPTxStatus(st) (SaveTState = st)
#define USB_StatusIn() Send0LengthData()
#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID)
#define StatusInfo0 StatusInfo.bw.bb1 // Reverse bb0 & bb1
#define StatusInfo1 StatusInfo.bw.bb0
// Private variables
uint16_t_uint8_t StatusInfo;
bool Data_Mul_MaxPacketSize = FALSE;
// Private function prototypes
static void DataStageOut(void);
static void DataStageIn(void);
static void NoData_Setup0(void);
static void Data_Setup0(void);
// Private functions
/*******************************************************************************
* Function Name : Standard_GetConfiguration.
* Description : Return the current configuration variable address.
* Input : Length - How many bytes are needed.
* Output : None.
* Return : Return 1 , if the request is invalid when "Length" is 0.
* Return "Buffer" if the "Length" is not 0.
*******************************************************************************/
uint8_t *Standard_GetConfiguration(uint16_t Length) {
if (Length == 0) {
pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_Configuration);
return 0;
}
pUser_Standard_Requests->User_GetConfiguration();
return (uint8_t *)&pInformation->Current_Configuration;
}
/*******************************************************************************
* Function Name : Standard_SetConfiguration.
* Description : This routine is called to set the configuration value
* Then each class should configure device itself.
* Input : None.
* Output : None.
* Return : Return USB_SUCCESS, if the request is performed.
* Return USB_UNSUPPORT, if the request is invalid.
*******************************************************************************/
RESULT Standard_SetConfiguration(void) {
if ((pInformation->USBwValue0 <=
Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0)
&& (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/
{
pInformation->Current_Configuration = pInformation->USBwValue0;
pUser_Standard_Requests->User_SetConfiguration();
return USB_SUCCESS;
} else {
return USB_UNSUPPORT;
}
}
/*******************************************************************************
* Function Name : Standard_GetInterface.
* Description : Return the Alternate Setting of the current interface.
* Input : Length - How many bytes are needed.
* Output : None.
* Return : Return 0, if the request is invalid when "Length" is 0.
* Return "Buffer" if the "Length" is not 0.
*******************************************************************************/
uint8_t *Standard_GetInterface(uint16_t Length) {
if (Length == 0) {
pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_AlternateSetting);
return 0;
}
pUser_Standard_Requests->User_GetInterface();
return (uint8_t *)&pInformation->Current_AlternateSetting;
}
/*******************************************************************************
* Function Name : Standard_SetInterface.
* Description : This routine is called to set the interface.
* Then each class should configure the interface them self.
* Input : None.
* Output : None.
* Return : - Return USB_SUCCESS, if the request is performed.
* - Return USB_UNSUPPORT, if the request is invalid.
*******************************************************************************/
RESULT Standard_SetInterface(void) {
RESULT Re;
// Test if the specified Interface and Alternate Setting are supported by
// the application Firmware
Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0);
if (pInformation->Current_Configuration != 0) {
if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0)
|| (pInformation->USBwValue1 != 0)) {
return USB_UNSUPPORT;
} else if (Re == USB_SUCCESS) {
pUser_Standard_Requests->User_SetInterface();
pInformation->Current_Interface = pInformation->USBwIndex0;
pInformation->Current_AlternateSetting = pInformation->USBwValue0;
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}
/*******************************************************************************
* Function Name : Standard_GetStatus.
* Description : Copy the device request data to "StatusInfo buffer".
* Input : - Length - How many bytes are needed.
* Output : None.
* Return : Return 0, if the request is at end of data block,
* or is invalid when "Length" is 0.
*******************************************************************************/
uint8_t *Standard_GetStatus(uint16_t Length) {
if (Length == 0) {
pInformation->Ctrl_Info.Usb_wLength = 2;
return 0;
}
// Reset Status Information
StatusInfo.w = 0;
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) {
// Get Device Status
uint8_t Feature = pInformation->Current_Feature;
// Remote Wakeup enabled
if (ValBit(Feature, 5)) SetBit(StatusInfo0,1); else ClrBit(StatusInfo0,1);
// Bus-powered or self-powered
if (ValBit(Feature, 6)) SetBit(StatusInfo0,0); else ClrBit(StatusInfo0,0);
} else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) {
// Interface Status
return (uint8_t *)&StatusInfo;
} else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) {
// Get EndPoint Status
uint8_t Related_Endpoint;
uint8_t wIndex0 = pInformation->USBwIndex0;
Related_Endpoint = (wIndex0 & 0x0f);
if (ValBit(wIndex0,7)) {
// IN endpoint
if (GetTxStallStatus(Related_Endpoint)) SetBit(StatusInfo0,0); // IN Endpoint stalled
} else {
// OUT endpoint
if (GetRxStallStatus(Related_Endpoint)) SetBit(StatusInfo0,0); // OUT Endpoint stalled
}
} else {
return NULL;
}
pUser_Standard_Requests->User_GetStatus();
return (uint8_t *)&StatusInfo;
}
/*******************************************************************************
* Function Name : Standard_ClearFeature.
* Description : Clear or disable a specific feature.
* Input : None.
* Output : None.
* Return : - Return USB_SUCCESS, if the request is performed.
* - Return USB_UNSUPPORT, if the request is invalid.
*******************************************************************************/
RESULT Standard_ClearFeature(void) {
uint32_t Type_Rec = Type_Recipient;
uint32_t Status;
if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) {
// Device Clear Feature
ClrBit(pInformation->Current_Feature, 5);
return USB_SUCCESS;
} else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) {
// EndPoint Clear Feature
DEVICE* pDev;
uint32_t Related_Endpoint;
uint32_t wIndex0;
uint32_t rEP;
if ((pInformation->USBwValue != ENDPOINT_STALL) || (pInformation->USBwIndex1 != 0)) {
return USB_UNSUPPORT;
}
pDev = &Device_Table;
wIndex0 = pInformation->USBwIndex0;
rEP = wIndex0 & ~0x80;
Related_Endpoint = ENDP0 + rEP;
if (ValBit(pInformation->USBwIndex0, 7)) {
// Get Status of endpoint & stall the request if the related_ENdpoint is Disabled
Status = GetEPTxStatus(Related_Endpoint);
} else {
Status = GetEPRxStatus(Related_Endpoint);
}
if ((rEP >= pDev->Total_Endpoint) || (Status == 0) || (pInformation->Current_Configuration == 0)) {
return USB_UNSUPPORT;
}
if (wIndex0 & 0x80) {
// IN endpoint
if (GetTxStallStatus(Related_Endpoint )) {
ClearDTOG_TX(Related_Endpoint);
SetEPTxStatus(Related_Endpoint, EP_TX_VALID);
}
} else {
// OUT endpoint
if (GetRxStallStatus(Related_Endpoint)) {
if (Related_Endpoint == ENDP0) {
// After clear the STALL, enable the default endpoint receiver
SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize);
SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
} else {
ClearDTOG_RX(Related_Endpoint);
SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
}
}
}
pUser_Standard_Requests->User_ClearFeature();
return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
/*******************************************************************************
* Function Name : Standard_SetEndPointFeature
* Description : Set or enable a specific feature of EndPoint
* Input : None.
* Output : None.
* Return : - Return USB_SUCCESS, if the request is performed.
* - Return USB_UNSUPPORT, if the request is invalid.
*******************************************************************************/
RESULT Standard_SetEndPointFeature(void) {
uint32_t wIndex0 = pInformation->USBwIndex0;
uint32_t rEP = wIndex0 & ~0x80;
uint32_t Related_Endpoint = ENDP0 + rEP;
uint32_t Status;
if (ValBit(pInformation->USBwIndex0,7)) {
// get Status of endpoint & stall the request if the related_ENdpoint is Disabled
Status = GetEPTxStatus(Related_Endpoint);
} else {
Status = GetEPRxStatus(Related_Endpoint);
}
if (Related_Endpoint >= Device_Table.Total_Endpoint
|| pInformation->USBwValue != 0 || Status == 0
|| pInformation->Current_Configuration == 0) {
return USB_UNSUPPORT;
} else {
if (wIndex0 & 0x80) {
// IN endpoint
SetEPTxStatus(Related_Endpoint, EP_TX_STALL);
} else {
// OUT endpoint
SetEPRxStatus(Related_Endpoint, EP_RX_STALL);
}
}
pUser_Standard_Requests->User_SetEndPointFeature();
return USB_SUCCESS;
}
/*******************************************************************************
* Function Name : Standard_SetDeviceFeature.
* Description : Set or enable a specific feature of Device.
* Input : None.
* Output : None.
* Return : - Return USB_SUCCESS, if the request is performed.
* - Return USB_UNSUPPORT, if the request is invalid.
*******************************************************************************/
RESULT Standard_SetDeviceFeature(void) {
SetBit(pInformation->Current_Feature, 5);
pUser_Standard_Requests->User_SetDeviceFeature();
return USB_SUCCESS;
}
/*******************************************************************************
* Function Name : Standard_GetDescriptorData.
* Description : Standard_GetDescriptorData is used for descriptors transfer.
* : This routine is used for the descriptors resident in Flash
* or RAM
* pDesc can be in either Flash or RAM
* The purpose of this routine is to have a versatile way to
* response descriptors request. It allows user to generate
* certain descriptors with software or read descriptors from
* external storage part by part.
* Input : - Length - Length of the data in this transfer.
* - pDesc - A pointer points to descriptor struct.
* The structure gives the initial address of the descriptor and
* its original size.
* Output : None.
* Return : Address of a part of the descriptor pointed by the Usb_
* wOffset The buffer pointed by this address contains at least
* Length bytes.
*******************************************************************************/
uint8_t *Standard_GetDescriptorData(uint16_t Length, ONE_DESCRIPTOR *pDesc) {
uint32_t wOffset;
wOffset = pInformation->Ctrl_Info.Usb_wOffset;
if (Length == 0) {
pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset;
return 0;
}
return pDesc->Descriptor + wOffset;
}
/*******************************************************************************
* Function Name : DataStageOut.
* Description : Data stage of a Control Write Transfer.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void DataStageOut(void) {
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
uint32_t save_rLength;
save_rLength = pEPinfo->Usb_rLength;
if (pEPinfo->CopyData && save_rLength) {
uint8_t *Buffer;
uint32_t Length;
Length = pEPinfo->PacketSize;
if (Length > save_rLength) Length = save_rLength;
Buffer = (*pEPinfo->CopyData)(Length);
pEPinfo->Usb_rLength -= Length;
pEPinfo->Usb_rOffset += Length;
PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length);
}
if (pEPinfo->Usb_rLength != 0) {
vSetEPRxStatus(EP_RX_VALID);
// re-enable for next data reception
SetEPTxCount(ENDP0, 0);
vSetEPTxStatus(EP_TX_VALID);
// Expect the host to abort the data OUT stage
}
// Set the next State
if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize) {
pInformation->ControlState = OUT_DATA;
} else {
if (pEPinfo->Usb_rLength > 0) {
pInformation->ControlState = LAST_OUT_DATA;
} else if (pEPinfo->Usb_rLength == 0) {
pInformation->ControlState = WAIT_STATUS_IN;
USB_StatusIn();
}
}
}
/*******************************************************************************
* Function Name : DataStageIn.
* Description : Data stage of a Control Read Transfer.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void DataStageIn(void) {
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
uint32_t save_wLength = pEPinfo->Usb_wLength;
uint32_t ControlState = pInformation->ControlState;
uint8_t *DataBuffer;
uint32_t Length;
if ((save_wLength == 0) && (ControlState == LAST_IN_DATA)) {
if(Data_Mul_MaxPacketSize == TRUE) {
// No more data to send and empty packet
Send0LengthData();
ControlState = LAST_IN_DATA;
Data_Mul_MaxPacketSize = FALSE;
} else {
// No more data to send so STALL the TX Status
ControlState = WAIT_STATUS_OUT;
vSetEPTxStatus(EP_TX_STALL);
}
goto Expect_Status_Out; // FIXME: <--- ZOMG TEH 'GOTO' !!!!
}
Length = pEPinfo->PacketSize;
ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA;
if (Length > save_wLength) Length = save_wLength;
DataBuffer = (*pEPinfo->CopyData)(Length);
UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length);
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: // FIXME: <--- ZOMG TEH LABEL !!!!
pInformation->ControlState = ControlState;
}
/*******************************************************************************
* Function Name : NoData_Setup0.
* Description : Proceed the processing of setup request without data stage.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void NoData_Setup0(void) {
RESULT Result = USB_UNSUPPORT;
uint32_t RequestNo = pInformation->USBbRequest;
uint32_t ControlState;
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) {
// Device Request
// SET_CONFIGURATION
if (RequestNo == SET_CONFIGURATION) {
Result = Standard_SetConfiguration();
} else if (RequestNo == SET_ADDRESS) {
// SET ADDRESS
if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0)
|| (pInformation->USBwIndex != 0)
|| (pInformation->Current_Configuration != 0)) {
// Device Address should be 127 or less
ControlState = STALLED;
goto exit_NoData_Setup0;
} else {
Result = USB_SUCCESS;
}
}
/*SET FEATURE for Device*/ else if (RequestNo == SET_FEATURE) {
if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) \
&& (pInformation->USBwIndex == 0)) {
Result = Standard_SetDeviceFeature();
} else {
Result = USB_UNSUPPORT;
}
}
/*Clear FEATURE for Device */ else if (RequestNo == CLEAR_FEATURE) {
if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP
&& pInformation->USBwIndex == 0
&& ValBit(pInformation->Current_Feature, 5)) {
Result = Standard_ClearFeature();
} else {
Result = USB_UNSUPPORT;
}
}
}
/* Interface Request*/ else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) {
/*SET INTERFACE*/
if (RequestNo == SET_INTERFACE) {
Result = Standard_SetInterface();
}
}
/* EndPoint Request*/ 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 = USB_UNSUPPORT;
}
if (Result != USB_SUCCESS) {
Result = (*pProperty->Class_NoData_Setup)(RequestNo);
if (Result == USB_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:
pInformation->ControlState = ControlState;
return;
}
/*******************************************************************************
* Function Name : Data_Setup0.
* Description : Proceed the processing of setup request with data stage.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Data_Setup0(void) {
uint8_t *(*CopyRoutine)(uint16_t);
RESULT Result;
uint32_t Request_No = pInformation->USBbRequest;
uint32_t Related_Endpoint, Reserved;
uint32_t wOffset, Status;
CopyRoutine = NULL;
wOffset = 0;
/*GET DESCRIPTOR*/
if (Request_No == GET_DESCRIPTOR) {
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) {
uint8_t wValue1 = pInformation->USBwValue1;
if (wValue1 == DEVICE_DESCRIPTOR) {
CopyRoutine = pProperty->GetDeviceDescriptor;
} else if (wValue1 == CONFIG_DESCRIPTOR) {
CopyRoutine = pProperty->GetConfigDescriptor;
} else if (wValue1 == STRING_DESCRIPTOR) {
CopyRoutine = pProperty->GetStringDescriptor;
}
/* End of GET_DESCRIPTOR */
}
}
/*GET STATUS*/ else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0)
&& (pInformation->USBwLength == 0x0002)
&& (pInformation->USBwIndex1 == 0)) {
/* GET STATUS for Device*/
if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
&& (pInformation->USBwIndex == 0)) {
CopyRoutine = Standard_GetStatus;
}
/* GET STATUS for Interface*/ else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) {
if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)
&& (pInformation->Current_Configuration != 0)) {
CopyRoutine = Standard_GetStatus;
}
}
/* GET STATUS for EndPoint*/ else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) {
Related_Endpoint = (pInformation->USBwIndex0 & 0x0f);
Reserved = pInformation->USBwIndex0 & 0x70;
if (ValBit(pInformation->USBwIndex0, 7)) {
/*Get Status of endpoint & stall the request if the related_ENdpoint
is Disabled*/
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))
&& (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0)
&& (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001)
&& ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)) {
CopyRoutine = Standard_GetInterface;
}
}
if (CopyRoutine) {
pInformation->Ctrl_Info.Usb_wOffset = wOffset;
pInformation->Ctrl_Info.CopyData = CopyRoutine;
// sb in the original the cast to word was directly
// now the cast is made step by step
(*CopyRoutine)(0);
Result = USB_SUCCESS;
} else {
Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest);
if (Result == USB_NOT_READY) {
pInformation->ControlState = PAUSE;
return;
}
}
if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF) {
// Data is not ready, wait it
pInformation->ControlState = PAUSE;
return;
}
if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0)) {
// Unsupported request
pInformation->ControlState = STALLED;
return;
}
if (ValBit(pInformation->USBbmRequestType, 7)) {
// Device ==> Host
__IO uint32_t wLength = pInformation->USBwLength;
// Restrict the data length to be the one host asks for
if (pInformation->Ctrl_Info.Usb_wLength > wLength) {
pInformation->Ctrl_Info.Usb_wLength = wLength;
} else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength) {
if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) {
Data_Mul_MaxPacketSize = FALSE;
} else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0) {
Data_Mul_MaxPacketSize = TRUE;
}
}
pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize;
DataStageIn();
} else {
pInformation->ControlState = OUT_DATA;
vSetEPRxStatus(EP_RX_VALID);
// enable for next data reception
}
return;
}
/*******************************************************************************
* Function Name : Setup0_Process
* Description : Get the device request data and dispatch to individual process.
* Input : None.
* Output : None.
* Return : Post0_Process.
*******************************************************************************/
uint8_t Setup0_Process(void) {
union {
uint8_t* b;
uint16_t* w;
} pBuf;
uint16_t offset = 1;
pBuf.b = PMAAddr + (uint8_t *)(GetEPRxAddr(ENDP0) * 2);
// *2 for 32 bits addr
if (pInformation->ControlState != PAUSE) {
pInformation->USBbmRequestType = *pBuf.b++;
// bmRequestType
pInformation->USBbRequest = *pBuf.b++;
// bRequest
pBuf.w += offset;
// word not accessed because of 32 bits addressing
pInformation->USBwValue = ByteSwap(*pBuf.w++);
// wValue
pBuf.w += offset;
// word not accessed because of 32 bits addressing
pInformation->USBwIndex = ByteSwap(*pBuf.w++);
// wIndex
pBuf.w += offset;
// word not accessed because of 32 bits addressing
pInformation->USBwLength = *pBuf.w;
// wLength
}
pInformation->ControlState = SETTING_UP;
if (pInformation->USBwLength == 0) {
// Setup with no data stage
NoData_Setup0();
} else {
// Setup with data stage
Data_Setup0();
}
return Post0_Process();
}
/*******************************************************************************
* Function Name : In0_Process
* Description : Process the IN token on all default endpoint.
* Input : None.
* Output : None.
* Return : Post0_Process.
*******************************************************************************/
uint8_t In0_Process(void) {
uint32_t ControlState = pInformation->ControlState;
if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) {
DataStageIn();
// ControlState may be changed outside the function
ControlState = pInformation->ControlState;
} else if (ControlState == WAIT_STATUS_IN) {
if ((pInformation->USBbRequest == SET_ADDRESS) &&
(Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))) {
SetDeviceAddress(pInformation->USBwValue0);
pUser_Standard_Requests->User_SetDeviceAddress();
}
(*pProperty->Process_Status_IN)();
ControlState = STALLED;
} else {
ControlState = STALLED;
}
pInformation->ControlState = ControlState;
return Post0_Process();
}
/*******************************************************************************
* Function Name : Out0_Process
* Description : Process the OUT token on all default endpoint.
* Input : None.
* Output : None.
* Return : Post0_Process.
*******************************************************************************/
uint8_t Out0_Process(void) {
uint32_t ControlState = pInformation->ControlState;
if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) {
// host aborts the transfer before finish
ControlState = STALLED;
} else if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA)) {
DataStageOut();
ControlState = pInformation->ControlState;
// may be changed outside the function
} else if (ControlState == WAIT_STATUS_OUT) {
(*pProperty->Process_Status_OUT)();
ControlState = STALLED;
} else {
// Unexpect state, STALL the endpoint
ControlState = STALLED;
}
pInformation->ControlState = ControlState;
return Post0_Process();
}
/*******************************************************************************
* Function Name : Post0_Process
* Description : Stall the Endpoint 0 in case of error.
* Input : None.
* Output : None.
* Return : - 0 if the control State is in PAUSE
* - 1 if not.
*******************************************************************************/
uint8_t Post0_Process(void) {
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
if (pInformation->ControlState == STALLED) {
vSetEPRxStatus(EP_RX_STALL);
vSetEPTxStatus(EP_TX_STALL);
}
return (pInformation->ControlState == PAUSE);
}
/*******************************************************************************
* Function Name : SetDeviceAddress.
* Description : Set the device and all the used Endpoints addresses.
* Input : - Val: device address.
* Output : None.
* Return : None.
*******************************************************************************/
void SetDeviceAddress(uint8_t Val) {
uint8_t i;
uint32_t nEP = Device_Table.Total_Endpoint;
// set address in every used endpoint
for (i = 0; i < nEP; i++) SetEPAddress(i,i);
*DADDR = Val | DADDR_EF; // set device address and enable function
}
/*******************************************************************************
* Function Name : NOP_Process
* Description : No operation function.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void NOP_Process(void) {
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/