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); //指针指向PMA中的EP0的Rx Buffer地址
if (pInformation->ControlState != PAUSE) //PAUSE状态下不取buffer中的数据
{
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; //SETTING_UP表示当前状态是SETUP中
//分2种类型的Setup,有后续DATA的和无DATA的。
if (pInformation->USBwLength == 0)
{
/* Setup with no data stage */
NoData_Setup0();
}
else
{
/* Setup with data stage */
Data_Setup0();
}
return Post0_Process();
}
USB Setup数据格式用一个结构说明:
typedef struct _USB_SETUP_PACKET
{
REQUEST_TYPE bmRequestType;
BYTE bRequest;
WORD_BYTE wValue;
WORD_BYTE wIndex;
WORD wLength;
} USB_SETUP_PACKET;
bmRequestType:bit7表示后续数据包(必须是DATA0)的方向,0表示OUT,1表示IN;bit6-bit5表示请求类型,0表示标准请求,1表示Class的请求,2表示厂商的请求,3是预留值;bit4-bit0表示接收这个SETUP包的是谁,0是设备,1是接口,2是端点,3是其他未知的,4-31是预留值。
bRequest:表示本描述符的请求类型,USB2.0定义了如下的编码:
GET_STATUS 0
CLEAR_FEATURE 1
Reserved for future use 2
SET_FEATURE 3
Reserved for future use 4
SET_ADDRESS 5
GET_DESCRIPTOR 6
SET_DESCRIPTOR 7
GET_CONFIGURATION 8
SET_CONFIGURATION 9
GET_INTERFACE 10
SET_INTERFACE 11
SYNCH_FRAME 12
wValue:根据不同的bRequest而设置不同的值。一般就是传送参数给设备标明这是什么请求。
wIndex:根据不同的bRequest而设置不同的值。一般用来说明端点号或者说明接口标识。
wLength:是根据bRequest来决定下一阶段发送数据的长度。
NoData_Setup0和Data_Setup0是分别处理没有后续DATA包和有后续DATA包的SETUP过程。
Post0_Process的作用是如果NoData_Setup0和Data_Setup0发生错误,就STALL端点0
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);
}