📄 usb_core.c
字号:
/******************** (C) COPYRIGHT 2003 STMicroelectronics ********************
* File Name : usb_core.c
* Author : MCD Application Team
* Date First Issued : 27/10/2003
* Description : standard protocol processing (USB v1.1)
*
********************************************************************************/
#include "USB_lib.h"
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#define ValBit(VAR,Place) (VAR & (1<<Place))
#define SetBit(VAR,Place) ( VAR |= (1<<Place) )
#define ClrBit(VAR,Place) ( VAR &= ((1<<Place)^255) )
BYTE *Standard_GetStatus(WORD Length);
RESULT Standard_ClearFeature(void);
RESULT Standard_SetFeature(void);
#define Send0LengthData() { \
_SetEPTxCount(ENDP0, 0); \
vSetEPTxStatus(EP_TX_VALID); \
}
#define Sendn0LengthData(ep) { \
_SetEPTxCount(ep, 0); \
vSetEPTxStatus(EP_TX_VALID); \
}
/* cells saving status during interrupt servicing */
WORD SaveRState;
WORD SaveTState;
#define vSetEPRxStatus(st) (SaveRState = st)
#define vSetEPTxStatus(st) (SaveTState = st)
#define USB_StatusInn(ep) Sendn0LengthData(ep)
#define USB_StatusIn() Send0LengthData()
#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID)
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_GetConfiguration
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 0, if the request is invalid when "Length" is 0
Return "Buffer" if the "Length" is not 0
DESCRIPTION:
Return the current configuration variable address
NOTICE:
This routine is used for devices with only one configuration,
User should write their own routine to process GET_CONFIGURATION
if their device has more than one configuration.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
BYTE *Standard_GetConfiguration(WORD Length)
{
int cnf;
if (Length == 0)
return (BYTE *)sizeof(pInformation->Current_Configuration);
cnf=pInformation->Current_Configuration;
uart_printf("Standard_GetConfiguration %d call",cnf);
return (BYTE *)&pInformation->Current_Configuration;
} /* Standard_GetConfiguration */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_SetConfiguration
INPUT:
OUTPUT:
RETURN: Return SUCCESS, if the request is performed
Return UNSUPPORT, if the request is invalid
DESCRIPTION:
The class calls this routine to get the configuration value
Then each class should configure device themself
NOTICE:
This routine is used for devices with only one configuration.
User should write their own routine to process SET_CONFIGURATION
if their device has more than one configuration.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
RESULT Standard_SetConfiguration(void)
{
int cnf;
BYTE wValue0 = pInformation->USBwValue0;
if (1)//wValue0 <= Device_Table.Total_Configuration)
{
/* If the number of configuration is within the range */
pInformation->Current_Configuration = wValue0;
cnf = wValue0;
uart_printf("Standard_SetConfiguration call %d ",cnf);
return SUCCESS;
}
else
return UNSUPPORT;
} /* Standard_SetConfiguration */
BYTE* Standard_GetMaxLun(WORD Length)
{
if (Length == 0)
return (BYTE*)1;
uart_printf("Standard_GetMaxLun call",pInformation->Current_Interface++);
return (BYTE*)&pInformation->Current_Interface;
} /* Standard_SetConfiguration */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_GetInterface
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
DESCRIPTION:
Return the current interface variable address
NOTICE:
This routine is used for devices with only one configuration and one interface,
User should write their own routine to process GET_INTERFACE
if their device has more than one configuration or one interface
or one alternative setting.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
BYTE *Standard_GetInterface(WORD Length)
{
if (Length == 0)
return (BYTE *)sizeof(pInformation->Current_Interface);
uart_printf("Standard_GetInterface call",0);
return (BYTE *)&pInformation->Current_Interface;
} /* Standard_GetInterface */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_SetInterface
INPUT:
OUTPUT:
RETURN: Return SUCCESS, if the request is performed
Return UNSUPPORT, if the request is invalid
DESCRIPTION:
The class calls this routine to get the interface value
Then each class should configure the interface themself
NOTICE:
This routine is used for devices with only one configuration and
one interface with one alternative setting.
User should write their own routine to process SET_INTERFACE
if their device has more than one configuration or one interface
or one alternative setting.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
RESULT Standard_SetInterface(void)
{
DEVICE_INFO *pInfo = pInformation;
if (pInfo->USBwValue0 != 0 || pInfo->USBwIndex0 != 0)
return UNSUPPORT;
uart_printf("Standard_SetInterface call",0);
/* I have only one interface & one alternative setting */
pInfo->Current_Interface = 0;
return SUCCESS;
} /* Standard_SetInterface */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_GetStatus
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
DESCRIPTION:
Copy the device request data to "StatusInfo buffer"
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
WORD_BYTE StatusInfo;
#define StatusInfo0 StatusInfo.bw.bb1 /* Reverse bb0 & bb1 */
#define StatusInfo1 StatusInfo.bw.bb0
BYTE *Standard_GetStatus(WORD Length)
{
DEVICE_INFO *pInfo = pInformation;
BYTE Type_Rec;
if (Length == 0)
return (BYTE *)2;
uart_printf("Standard_GetStatus call",0);
StatusInfo.w = 0; /* Reset Status Information */
Type_Rec = Type_Recipient;
if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) {
BYTE Feature = pInfo->Current_Feature;
if (ValBit(Feature, 5))
SetBit(StatusInfo0, 1); /* Remote Wakeup enabled */
if (ValBit(Feature, 7))
; /* ClrBit(StatusInfo0, 0); */ /* Bus-powered */
else if (ValBit(Feature, 6))
SetBit(StatusInfo0, 0); /* Self-powered */
}
else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) {
BYTE Related_Endpoint;
BYTE wIndex0 = pInfo->USBwIndex0;
Related_Endpoint = ENDP0 + (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;
return (BYTE *)&StatusInfo;
} /* Standard_GetStatus */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_ClearFeature
INPUT:
OUTPUT: none
DESCRIPTION:
Clear or disable a specific feature
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
RESULT Standard_ClearFeature(void)
{
DEVICE_INFO *pInfo = pInformation;
BYTE Type_Rec = Type_Recipient;
BYTE wValue0 = pInfo->USBwValue0;
uart_printf("Standard_ClearFeature call",0);
if ( Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT) ) {
if (wValue0 != DEVICE_REMOTE_WAKEUP)
return UNSUPPORT;
ClrBit(pInfo->Current_Feature, 5);
return SUCCESS;
}
else if ( Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT) ) {
DEVICE* pDev;
BYTE Related_Endpoint;
BYTE wIndex0;
BYTE rEP;
if (wValue0 != ENDPOINT_STALL)
return UNSUPPORT;
pDev = &Device_Table;
wIndex0 = pInfo->USBwIndex0;
rEP = wIndex0 & ~0x80;
if (rEP >= pDev->Total_Endpoint)
return UNSUPPORT;
/* EPindex should be equal to Device_Table.EP0 */
Related_Endpoint = ENDP0 + rEP;
if (wIndex0 & 0x80) { /* IN endpoint */
if (_GetTxStallStatus(Related_Endpoint ))
_SetEPTxStatus(Related_Endpoint, EP_TX_NAK);
}
else { /* OUT endpoint */
if (_GetRxStallStatus(Related_Endpoint)){
if (Related_Endpoint == ENDP0) {
/* After clear the STALL, enable the default endpoint receiver */
SetEPRxCount(Related_Endpoint, STD_MAXPACKETSIZE);
_SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
}
else
_SetEPRxStatus(Related_Endpoint, EP_RX_NAK);
}
}
return SUCCESS;
}
return UNSUPPORT;
} /* Standard_ClearFeature */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_SetFeature
INPUT:
OUTPUT: none
DESCRIPTION:
Set or enable a specific feature
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
RESULT Standard_SetFeature(void)
{
DEVICE_INFO *pInfo = pInformation;
BYTE Type_Rec = Type_Recipient;
BYTE wValue0 = pInfo->USBwValue0;
uart_printf("Standard_SetFeature call",0);
if ( Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT) ) {
if (wValue0 != DEVICE_REMOTE_WAKEUP)
return UNSUPPORT;
SetBit(pInfo->Current_Feature, 5);
/****************************************/
return SUCCESS;
}
else if ( Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT) ) {
DEVICE* pDev;
BYTE Related_Endpoint;
BYTE wIndex0;
BYTE rEP;
if (wValue0 != ENDPOINT_STALL)
return UNSUPPORT;
pDev = &Device_Table;
wIndex0 = pInfo->USBwIndex0;
rEP = wIndex0 & ~0x80;
if (rEP >= pDev->Total_Endpoint)
return UNSUPPORT;
Related_Endpoint = ENDP0 + rEP;
if (wIndex0 & 0x80) { /* IN endpoint */
_SetEPTxStatus(Related_Endpoint, EP_TX_STALL);
}
else { /* OUT endpoint */
_SetEPRxStatus(Related_Endpoint, EP_RX_STALL);
}
return SUCCESS;
}
return UNSUPPORT;
} /* Standard_SetFeature */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
NAME: Standard_GetDescriptorData
Standard_GetStringDescriptor
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
DESCRIPTION:
These 2 routines only used for the descriptors resident in ROM or RAM
pDesc can be in either ROM or RAM
Standard_GetStringDescriptor is used for transfer string descriptor
The purpose of these 2 routines 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.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
BYTE *Standard_GetStringDescriptor(WORD Length, ONE_DESCRIPTOR *pDesc)
{
int len, offset, wOffset;
wOffset = pInformation->Ctrl_Info.Usb_wOffset;
if (Length == 0) {
offset = 0;
do {
len = (int)*(pDesc->Descriptor + offset);
if (wOffset >= 0 && wOffset < len) {
len -= wOffset;
if (len > 0)
return (BYTE*)len;
break;
}
wOffset -= len;
offset += len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -