📄 usb_core.c
字号:
/******************** (C) COPYRIGHT 2006 STMicroelectronics ********************
* File Name : main.c
* Author : wuyuhuai
* Date First Issued : 4/40/2008 : V1.0
* Description : str training demo main file
********************************************************************************
* History:
* 09/18/2006 : V3.0
* 09/01/2006 : V2.0
* 10/27/2003 : V1.0
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "usb_lib.h"
#include "usb_mem.h"
#include "usb_conf.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#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 macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u16_u8 StatusInfo;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : Standard_GetConfiguration
* Description : Return the current configuration variable address
* Input : Length - How many bytes are needed.
* Output : If "Length" is 0, return the length of configuration value
If "Length" is not 0, return the data buffer address.
* Return : Return 1 , if the request is invalid when "Length" is 0
Return "Buffer" if the "Length" is not 0
*******************************************************************************/
u8 *Standard_GetConfiguration(u16 Length)
{
if (Length == 0){
pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_Configuration);
return 0;
}
pUser_Standard_Requests->User_GetConfiguration();
return (u8 *)&pInformation->Current_Configuration;
}
/*******************************************************************************
* Function Name : Standard_SetConfiguration
* Description : This routine is called to set the configuration value
Then each class should configure device themself
* Input :
* Output :
* 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 : If "Length" is 0, return the length of interface value
If "Length" is not 0, return the data buffer address
* Return : Return 0, if the request is invalid when "Length" is 0
Return "Buffer" if the "Length" is not 0
*******************************************************************************/
u8 *Standard_GetInterface(u16 Length)
{
if (Length == 0){
pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_AlternateSetting);
return 0;
}
pUser_Standard_Requests->User_GetInterface();
return (u8 *)&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 :
* Output :
* 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 : If "Length" is 0, return the length of status data
If "Length" is not 0, return number of bytes have been copied
* Return : Return 0, if the request is at end of data block,
or is invalid when "Length" is 0
*******************************************************************************/
u8 *Standard_GetStatus(u16 Length)
{
if (Length == 0){
pInformation->Ctrl_Info.Usb_wLength =2;
return 0;
}
StatusInfo.w = 0;
/* Reset Status Information */
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) {/*Get Device Status */
u8 Feature = pInformation->Current_Feature;
if (ValBit(Feature, 5))
SetBit(StatusInfo0, 1); /* Remote Wakeup enabled */
if (ValBit(Feature, 6))
SetBit(StatusInfo0, 0); /* Self-powered */
else
ClrBit(StatusInfo0, 0); /* Bus-powered */
}
else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))/*Interface Status*/
return (u8 *)&StatusInfo;
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) {/*Get EndPoint Status*/
u8 Related_Endpoint;
u8 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 (u8 *)&StatusInfo;
}
/*******************************************************************************
* Function Name : Standard_ClearFeature
* Description : Clear or disable a specific feature
* Input :
* Output :
* Return :
*******************************************************************************/
RESULT Standard_ClearFeature(void)
{
u32 Type_Rec = Type_Recipient;
u32 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;
u32 Related_Endpoint;
u32 wIndex0;
u32 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)) Status =_GetEPTxStatus(Related_Endpoint);/*Get Status of endpoint & stall the request if
the related_ENdpoint is Disabled*/
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 :
* Output :
* Return :
*******************************************************************************/
RESULT Standard_SetEndPointFeature(void)
{
u32 wIndex0;
u32 Related_Endpoint;
u32 rEP;
u32 Status;
wIndex0 = pInformation->USBwIndex0;
rEP = wIndex0 & ~0x80;
Related_Endpoint = ENDP0 + rEP;
if (ValBit(pInformation->USBwIndex0, 7)) Status =_GetEPTxStatus(Related_Endpoint);/* get Status of endpoint & stall the request if
the related_ENdpoint is Disabled*/
else Status =_GetEPRxStatus(Related_Endpoint);
if (Related_Endpoint >= Device_Table.Total_Endpoint || pInformation->USBwValue !=0 || Status==0 ||
pInformation->Current_Configuration==0 /*&& Related_Endpoint!=ENDP0)*/)
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 :
* Output :
* Return :
*******************************************************************************/
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 : Address of a part of the descriptor pointed by the Usb_wOffset
The buffer pointed by this address contains at least Length bytes
* Return :
*******************************************************************************/
u8 *Standard_GetDescriptorData(u16 Length, ONE_DESCRIPTOR *pDesc)
{
u32 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 :
* Output :
* Return :
*******************************************************************************/
void DataStageOut(void)
{
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
u32 save_rLength;
save_rLength = pEPinfo->Usb_rLength;
if (pEPinfo->CopyData && save_rLength) {
u8 *Buffer;
u32 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 :
* Output :
* Return :
*******************************************************************************/
void DataStageIn(void)
{
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
u32 save_wLength = pEPinfo->Usb_wLength;
u32 ControlState = pInformation->ControlState;
u8 *DataBuffer;
u32 Length;
if ((save_wLength == 0) && (ControlState == LAST_IN_DATA))
{ /* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -