DAPLink/source/usb/usbd_core.c

1051 lines
32 KiB
C

/**
* @file usbd_core.c
* @brief USB Device core
*
* DAPLink Interface Firmware
* Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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 <string.h>
#include "rl_usb.h"
#include "usb_for_lib.h"
#include "info.h"
U16 USBD_DeviceStatus;
U8 USBD_DeviceAddress;
U8 USBD_Configuration;
U32 USBD_EndPointMask;
U32 USBD_EndPointHalt;
U32 USBD_EndPointStall; /* EP must stay stalled */
U8 USBD_NumInterfaces;
U8 USBD_HighSpeed;
U8 USBD_ZLP;
USBD_EP_DATA USBD_EP0Data;
USB_SETUP_PACKET USBD_SetupPacket;
#ifdef __RTX
OS_TID USBD_RTX_DevTask; /* USB Device Task ID */
OS_TID USBD_RTX_EPTask[16]; /* USB Endpoint Task ID's */
OS_TID USBD_RTX_CoreTask; /* USB Core Task ID */
#endif
/*
* Init USB Device Core and Hardware
* Parameters: None
* Return Value: None
*/
void usbd_init(void)
{
USBD_HighSpeed = __FALSE;
usbd_class_init();
USBD_RTX_TaskInit();
USBD_Init();
}
/*
* USB Device Connect/Disconnect Function
* Called by the User to Connect/Disconnect USB Device
* Parameters: con: Connect/Disconnect
* Return Value: None
*/
void usbd_connect(BOOL con)
{
USBD_Connect(con);
}
/*
* Reset USB Device Core
* Parameters: None
* Return Value: None
*/
void usbd_reset_core(void)
{
USBD_DeviceStatus = usbd_power;
USBD_DeviceAddress = 0;
USBD_Configuration = 0;
USBD_EndPointMask = 0x00010001;
USBD_EndPointHalt = 0x00000000;
USBD_EndPointStall = 0x00000000;
}
/*
* USB Device Configured Function
* Called by the User to check id USB Device is configured
* Parameters:
* Return Value: Configurated state (FALSE = unconfigured, TRUE = configured)
*/
BOOL usbd_configured(void)
{
if (USBD_Configuration) {
return (__TRUE);
}
return (__FALSE);
}
/*
* USB Device Request - Setup Stage
* Parameters: None
* Return Value: None
*/
void USBD_SetupStage(void)
{
USBD_ReadEP(0x00, (U8 *)&USBD_SetupPacket, sizeof(USBD_SetupPacket));
}
/*
* USB Device Request - Data In Stage
* Parameters: None
* Return Value: None
*/
void USBD_DataInStage(void)
{
U32 cnt;
if (USBD_EP0Data.Count > usbd_max_packet0) {
cnt = usbd_max_packet0;
} else {
cnt = USBD_EP0Data.Count;
}
if (!cnt) {
USBD_ZLP = 0;
}
cnt = USBD_WriteEP(0x80, USBD_EP0Data.pData, cnt);
USBD_EP0Data.pData += cnt;
USBD_EP0Data.Count -= cnt;
}
/*
* USB Device Request - Data Out Stage
* Parameters: None
* Return Value: None
*/
void USBD_DataOutStage(void)
{
U32 cnt;
cnt = USBD_ReadEP(0x00, USBD_EP0Data.pData, USBD_EP0Data.Count);
USBD_EP0Data.pData += cnt;
USBD_EP0Data.Count -= cnt;
}
/*
* USB Device Request - Status In Stage
* Parameters: None
* Return Value: None
*/
void USBD_StatusInStage(void)
{
USBD_WriteEP(0x80, NULL, 0);
}
/*
* USB Device Request - Status Out Stage
* Parameters: None
* Return Value: None
*/
void USBD_StatusOutStage(void)
{
USBD_ReadEP(0x00, USBD_EP0Buf, usbd_max_packet0);
}
/*
* Get Status USB Device Request
* Parameters: None
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqGetStatus(void)
{
U32 n, m;
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
USBD_EP0Data.pData = (U8 *)&USBD_DeviceStatus;
break;
case REQUEST_TO_INTERFACE:
if ((USBD_Configuration != 0) && (USBD_SetupPacket.wIndexL < USBD_NumInterfaces)) {
__UNALIGNED_UINT16_WRITE(USBD_EP0Buf, 0);
USBD_EP0Data.pData = USBD_EP0Buf;
} else {
return (__FALSE);
}
break;
case REQUEST_TO_ENDPOINT:
n = USBD_SetupPacket.wIndexL & 0x8F;
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n);
if (((USBD_Configuration != 0) || ((n & 0x0F) == 0)) && (USBD_EndPointMask & m)) {
__UNALIGNED_UINT16_WRITE(USBD_EP0Buf, (USBD_EndPointHalt & m) ? 1 : 0);
USBD_EP0Data.pData = USBD_EP0Buf;
} else {
return (__FALSE);
}
break;
default:
return (__FALSE);
}
return (__TRUE);
}
/*
* Set/Clear Feature USB Device Request
* Parameters: sc: 0 - Clear, 1 - Set
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqSetClrFeature(U32 sc)
{
U32 n, m;
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
if (USBD_SetupPacket.wValue == USB_FEATURE_REMOTE_WAKEUP) {
if (sc) {
USBD_WakeUpCfg(__TRUE);
USBD_DeviceStatus |= USB_GETSTATUS_REMOTE_WAKEUP;
} else {
USBD_WakeUpCfg(__FALSE);
USBD_DeviceStatus &= ~USB_GETSTATUS_REMOTE_WAKEUP;
}
} else {
return (__FALSE);
}
break;
case REQUEST_TO_INTERFACE:
return (__FALSE);
case REQUEST_TO_ENDPOINT:
n = USBD_SetupPacket.wIndexL & 0x8F;
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n);
if ((USBD_Configuration != 0) && ((n & 0x0F) != 0) && (USBD_EndPointMask & m)) {
if (USBD_SetupPacket.wValue == USB_FEATURE_ENDPOINT_STALL) {
if (sc) {
USBD_SetStallEP(n);
USBD_EndPointHalt |= m;
} else {
if ((USBD_EndPointStall & m) != 0) {
return (__TRUE);
}
USBD_ClrStallEP(n);
USBD_ReqClrFeature_MSC(n);
USBD_EndPointHalt &= ~m;
}
} else {
return (__FALSE);
}
} else {
return (__FALSE);
}
break;
default:
return (__FALSE);
}
return (__TRUE);
}
/*
* Set Address USB Device Request
* Parameters: None
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqSetAddress(void)
{
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
USBD_DeviceAddress = 0x80 | USBD_SetupPacket.wValueL;
break;
default:
return (__FALSE);
}
return (__TRUE);
}
/*
* Get Descriptor USB Device Request
* Parameters: None
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqGetDescriptor(void)
{
U8 *pD;
U32 len, n;
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
switch (USBD_SetupPacket.wValueH) {
case USB_DEVICE_DESCRIPTOR_TYPE:
USBD_EP0Data.pData = (U8 *)USBD_DeviceDescriptor;
len = USB_DEVICE_DESC_SIZE;
break;
case USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE:
if (!usbd_hs_enable) {
return (__FALSE); /* High speed not enabled */
}
if (USBD_HighSpeed == __FALSE) {
USBD_EP0Data.pData = (U8 *)USBD_DeviceQualifier;
} else {
USBD_EP0Data.pData = (U8 *)USBD_DeviceQualifier_HS;
}
len = USB_DEVICE_QUALI_SIZE;
break;
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
if ((!usbd_hs_enable) && (USBD_HighSpeed == __TRUE)) {
return (__FALSE); /* High speed request but high-speed not enabled */
}
if (USBD_HighSpeed == __FALSE) {
pD = (U8 *)USBD_ConfigDescriptor;
((USB_CONFIGURATION_DESCRIPTOR *)pD)->bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE; //same descriptor is used in other configuration
} else {
pD = (U8 *)USBD_ConfigDescriptor_HS;
((USB_CONFIGURATION_DESCRIPTOR *)pD)->bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE; //same descriptor is used in other configuration
}
for (n = 0; n != USBD_SetupPacket.wValueL; n++) {
if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength != 0) {
pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
}
}
if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength == 0) {
return (__FALSE);
}
USBD_EP0Data.pData = pD;
len = ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
break;
case USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE:
if (!usbd_hs_enable) {
return (__FALSE); /* High speed not enabled */
}
if (USBD_HighSpeed == __FALSE) {
pD = (U8 *)USBD_ConfigDescriptor_HS;
((USB_CONFIGURATION_DESCRIPTOR *)pD)->bDescriptorType = USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE; //same descriptor is used in main configuration
} else {
pD = (U8 *)USBD_ConfigDescriptor;
((USB_CONFIGURATION_DESCRIPTOR *)pD)->bDescriptorType = USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE; //same descriptor is used in main configuration
}
for (n = 0; n != USBD_SetupPacket.wValueL; n++) {
if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength != 0) {
pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
}
}
if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength == 0) {
return (__FALSE);
}
USBD_EP0Data.pData = pD;
len = ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
break;
case USB_STRING_DESCRIPTOR_TYPE:
pD = (U8 *)USBD_StringDescriptor;
// added by sam to send unique id string descriptor
if (USBD_SetupPacket.wValueL == 3) {
USBD_EP0Data.pData = (uint8_t *)info_get_unique_id_string_descriptor();
len = ((USB_STRING_DESCRIPTOR *)USBD_EP0Data.pData)->bLength;
break;
}
for (n = 0; n != USBD_SetupPacket.wValueL; n++) {
if (((USB_STRING_DESCRIPTOR *)pD)->bLength != 0) {
pD += ((USB_STRING_DESCRIPTOR *)pD)->bLength;
}
}
if (((USB_STRING_DESCRIPTOR *)pD)->bLength == 0) {
return (__FALSE);
}
USBD_EP0Data.pData = pD;
len = ((USB_STRING_DESCRIPTOR *)pD)->bLength;
break;
case USB_BINARY_OBJECT_STORE_DESCRIPTOR_TYPE:
if (!usbd_bos_enable) {
return (__FALSE); /* High speed not enabled */
}
pD = (U8 *)USBD_BinaryObjectStoreDescriptor;
USBD_EP0Data.pData = pD;
if (((USB_BINARY_OBJECT_STORE_DESCRIPTOR *)pD)->bLength == 0) {
return (__FALSE);
}
len = ((USB_BINARY_OBJECT_STORE_DESCRIPTOR *)pD)->wTotalLength;
break;
default:
return (__FALSE);
}
break;
case REQUEST_TO_INTERFACE:
if (!USBD_ReqGetDescriptor_HID(&pD, &len)) {
return (__FALSE);
}
break;
default:
return (__FALSE);
}
if (USBD_EP0Data.Count > len) {
USBD_EP0Data.Count = len;
if (!(USBD_EP0Data.Count & (usbd_max_packet0 - 1))) {
USBD_ZLP = 1;
}
}
return (__TRUE);
}
/*
* Get Configuration USB Device Request
* Parameters: None
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqGetConfiguration(void)
{
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
USBD_EP0Data.pData = &USBD_Configuration;
break;
default:
return (__FALSE);
}
return (__TRUE);
}
/*
* Set Configuration USB Device Request
* Parameters: None
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqSetConfiguration(void)
{
USB_CONFIGURATION_DESCRIPTOR *pD;
U32 alt = 0;
U32 n, m;
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
if (USBD_SetupPacket.wValueL) {
if ((!usbd_hs_enable) && (USBD_HighSpeed == __TRUE)) {
return (__FALSE); /* High speed request but high-speed not enabled */
}
if (USBD_HighSpeed == __FALSE) {
pD = (USB_CONFIGURATION_DESCRIPTOR *)USBD_ConfigDescriptor;
} else {
pD = (USB_CONFIGURATION_DESCRIPTOR *)USBD_ConfigDescriptor_HS;
}
while (pD->bLength) {
switch (pD->bDescriptorType) {
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
case USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE:
if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bConfigurationValue == USBD_SetupPacket.wValueL) {
USBD_Configuration = USBD_SetupPacket.wValueL;
USBD_NumInterfaces = ((USB_CONFIGURATION_DESCRIPTOR *)pD)->bNumInterfaces;
for (n = 0; n < usbd_if_num; n++) {
USBD_AltSetting[n] = 0;
}
for (n = 1; n < 16; n++) {
if (USBD_EndPointMask & (1 << n)) {
USBD_DisableEP(n);
}
if (USBD_EndPointMask & ((1 << 16) << n)) {
USBD_DisableEP(n | 0x80);
}
}
USBD_EndPointMask = 0x00010001;
USBD_EndPointHalt = 0x00000000;
USBD_EndPointStall = 0x00000000;
USBD_Configure(__TRUE);
if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bmAttributes & USB_CONFIG_POWERED_MASK) {
USBD_DeviceStatus |= USB_GETSTATUS_SELF_POWERED;
} else {
USBD_DeviceStatus &= ~USB_GETSTATUS_SELF_POWERED;
}
} else {
pD = (USB_CONFIGURATION_DESCRIPTOR *)((U8 *)pD + ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength);
continue;
}
break;
case USB_INTERFACE_DESCRIPTOR_TYPE:
alt = ((USB_INTERFACE_DESCRIPTOR *)pD)->bAlternateSetting;
break;
case USB_ENDPOINT_DESCRIPTOR_TYPE:
if (alt == 0) {
n = ((USB_ENDPOINT_DESCRIPTOR *)pD)->bEndpointAddress & 0x8F;
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n);
USBD_EndPointMask |= m;
USBD_ConfigEP((void *)pD);
USBD_EnableEP(n);
USBD_ResetEP(n);
}
break;
}
pD = (USB_CONFIGURATION_DESCRIPTOR *)((U8 *)pD + pD->bLength);
}
} else {
USBD_Configuration = 0;
for (n = 1; n < 16; n++) {
if (USBD_EndPointMask & (1 << n)) {
USBD_DisableEP(n);
}
if (USBD_EndPointMask & ((1 << 16) << n)) {
USBD_DisableEP(n | 0x80);
}
}
USBD_EndPointMask = 0x00010001;
USBD_EndPointHalt = 0x00000000;
USBD_EndPointStall = 0x00000000;
USBD_Configure(__FALSE);
}
if (USBD_Configuration != USBD_SetupPacket.wValueL) {
return (__FALSE);
}
break;
default:
return (__FALSE);
}
return (__TRUE);
}
/*
* Get Interface USB Device Request
* Parameters: None
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqGetInterface(void)
{
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_INTERFACE:
if ((USBD_Configuration != 0) && (USBD_SetupPacket.wIndexL < USBD_NumInterfaces)) {
USBD_EP0Data.pData = USBD_AltSetting + USBD_SetupPacket.wIndexL;
} else {
return (__FALSE);
}
break;
default:
return (__FALSE);
}
return (__TRUE);
}
/*
* Set Interface USB Device Request
* Parameters: None
* Return Value: TRUE - Success, FALSE - Error
*/
static inline BOOL USBD_ReqSetInterface(void)
{
USB_COMMON_DESCRIPTOR *pD;
U32 ifn = 0, alt = 0, old = 0, msk = 0;
U32 n, m;
BOOL set;
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_INTERFACE:
if (USBD_Configuration == 0) {
return (__FALSE);
}
set = __FALSE;
if ((!usbd_hs_enable) && (USBD_HighSpeed == __TRUE)) {
return (__FALSE); /* High speed request but high-speed not enabled */
}
if (USBD_HighSpeed == __FALSE) {
pD = (USB_COMMON_DESCRIPTOR *)USBD_ConfigDescriptor;
} else {
pD = (USB_COMMON_DESCRIPTOR *)USBD_ConfigDescriptor_HS;
}
while (pD->bLength) {
switch (pD->bDescriptorType) {
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
case USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE:
if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bConfigurationValue != USBD_Configuration) {
pD = (USB_COMMON_DESCRIPTOR *)((U8 *)pD + ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength);
continue;
}
break;
case USB_INTERFACE_DESCRIPTOR_TYPE:
ifn = ((USB_INTERFACE_DESCRIPTOR *)pD)->bInterfaceNumber;
alt = ((USB_INTERFACE_DESCRIPTOR *)pD)->bAlternateSetting;
msk = 0;
if ((ifn == USBD_SetupPacket.wIndexL) && (alt == USBD_SetupPacket.wValueL)) {
set = __TRUE;
old = USBD_AltSetting[ifn];
USBD_AltSetting[ifn] = (U8)alt;
}
break;
case USB_ENDPOINT_DESCRIPTOR_TYPE:
if (ifn == USBD_SetupPacket.wIndexL) {
n = ((USB_ENDPOINT_DESCRIPTOR *)pD)->bEndpointAddress & 0x8F;
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n);
if (alt == USBD_SetupPacket.wValueL) {
USBD_EndPointMask |= m;
USBD_EndPointHalt &= ~m;
USBD_ConfigEP((USB_ENDPOINT_DESCRIPTOR *)pD);
USBD_EnableEP(n);
USBD_ResetEP(n);
msk |= m;
} else if ((alt == old) && ((msk & m) == 0)) {
USBD_EndPointMask &= ~m;
USBD_EndPointHalt &= ~m;
USBD_DisableEP(n);
}
}
break;
}
pD = (USB_COMMON_DESCRIPTOR *)((U8 *)pD + pD->bLength);
}
break;
default:
return (__FALSE);
}
return (set);
}
/*
* USB Device Endpoint 0 Event Callback
* Parameters: event
* Return Value: none
*/
void USBD_EndPoint0(U32 event)
{
if (event & USBD_EVT_SETUP) {
USBD_SetupStage();
USBD_DirCtrlEP(USBD_SetupPacket.bmRequestType.Dir);
USBD_EP0Data.Count = USBD_SetupPacket.wLength; /* Number of bytes to transfer */
switch (USBD_SetupPacket.bmRequestType.Type) {
case REQUEST_STANDARD:
switch (USBD_SetupPacket.bRequest) {
case USB_REQUEST_GET_STATUS:
if (!USBD_ReqGetStatus()) {
goto stall;
}
USBD_DataInStage();
break;
case USB_REQUEST_CLEAR_FEATURE:
if (!USBD_ReqSetClrFeature(0)) {
goto stall;
}
USBD_StatusInStage();
#ifdef __RTX
if (__rtx) {
if (USBD_RTX_CoreTask) {
usbd_os_evt_set(USBD_EVT_CLR_FEATURE, USBD_RTX_CoreTask);
}
} else {
#endif
if (USBD_P_Feature_Event) {
USBD_P_Feature_Event();
}
#ifdef __RTX
}
#endif
break;
case USB_REQUEST_SET_FEATURE:
if (!USBD_ReqSetClrFeature(1)) {
goto stall;
}
USBD_StatusInStage();
#ifdef __RTX
if (__rtx) {
if (USBD_RTX_CoreTask) {
usbd_os_evt_set(USBD_EVT_SET_FEATURE, USBD_RTX_CoreTask);
}
} else {
#endif
if (USBD_P_Feature_Event) {
USBD_P_Feature_Event();
}
#ifdef __RTX
}
#endif
break;
case USB_REQUEST_SET_ADDRESS:
if (!USBD_ReqSetAddress()) {
goto stall;
}
USBD_SetAddress(USBD_DeviceAddress & 0x7F, 1);
USBD_StatusInStage();
break;
case USB_REQUEST_GET_DESCRIPTOR:
if (!USBD_ReqGetDescriptor()) {
goto stall;
}
USBD_DataInStage();
break;
case USB_REQUEST_SET_DESCRIPTOR:
goto stall;
case USB_REQUEST_GET_CONFIGURATION:
if (!USBD_ReqGetConfiguration()) {
goto stall;
}
USBD_DataInStage();
break;
case USB_REQUEST_SET_CONFIGURATION:
if (!USBD_ReqSetConfiguration()) {
goto stall;
}
USBD_StatusInStage();
#ifdef __RTX
if (__rtx) {
if (USBD_RTX_CoreTask) {
usbd_os_evt_set(USBD_EVT_SET_CFG, USBD_RTX_CoreTask);
}
} else {
#endif
if (USBD_P_Configure_Event) {
USBD_P_Configure_Event();
}
#ifdef __RTX
}
#endif
break;
case USB_REQUEST_GET_INTERFACE:
if (!USBD_ReqGetInterface()) {
goto stall;
}
USBD_DataInStage();
break;
case USB_REQUEST_SET_INTERFACE:
if (!USBD_ReqSetInterface()) {
goto stall;
}
USBD_StatusInStage();
#ifdef __RTX
if (__rtx) {
if (USBD_RTX_CoreTask) {
usbd_os_evt_set(USBD_EVT_SET_IF, USBD_RTX_CoreTask);
}
} else {
#endif
if (USBD_P_Interface_Event) {
USBD_P_Interface_Event();
}
#ifdef __RTX
}
#endif
break;
default:
goto stall;
}
break; /* end case REQUEST_STANDARD */
case REQUEST_CLASS:
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
goto stall; /* not supported */
case REQUEST_TO_INTERFACE:
if (USBD_EndPoint0_Setup_HID_ReqToIF()) {
goto setup_class_ok;
}
if (USBD_EndPoint0_Setup_MSC_ReqToIF()) {
goto setup_class_ok;
}
if (USBD_EndPoint0_Setup_CDC_ReqToIF()) {
goto setup_class_ok;
}
goto stall; /* not supported */
/* end case REQUEST_TO_INTERFACE */
case REQUEST_TO_ENDPOINT:
goto stall;
/* end case REQUEST_TO_ENDPOINT */
default:
goto stall;
}
setup_class_ok: /* request finished successfully */
break; /* end case REQUEST_CLASS */
case REQUEST_VENDOR:
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
if (USBD_EndPoint0_Setup_WebUSB_ReqToDevice()) {
goto setup_vendor_ok;
}
if (USBD_EndPoint0_Setup_WinUSB_ReqToDevice()) {
goto setup_vendor_ok;
}
goto stall;
default:
goto stall;
}
setup_vendor_ok:
break; /* end case REQUEST_VENDOR */
default:
stall:
if ((USBD_SetupPacket.bmRequestType.Dir == REQUEST_HOST_TO_DEVICE) &&
(USBD_SetupPacket.wLength != 0)) {
USBD_SetStallEP(0x00);
} else {
USBD_SetStallEP(0x80);
}
USBD_EP0Data.Count = 0;
break;
}
}
if (event & USBD_EVT_OUT) {
if (USBD_SetupPacket.bmRequestType.Dir == REQUEST_HOST_TO_DEVICE) {
if (USBD_EP0Data.Count) { /* still data to receive ? */
USBD_DataOutStage(); /* receive data */
if (USBD_EP0Data.Count == 0) { /* data complete ? */
switch (USBD_SetupPacket.bmRequestType.Type) {
case REQUEST_STANDARD:
goto stall_i; /* not supported */
case REQUEST_CLASS:
switch (USBD_SetupPacket.bmRequestType.Recipient) {
case REQUEST_TO_DEVICE:
goto stall_i; /* not supported */
case REQUEST_TO_INTERFACE:
if (USBD_EndPoint0_Out_HID_ReqToIF()) {
goto out_class_ok;
}
if (USBD_EndPoint0_Out_CDC_ReqToIF()) {
goto out_class_ok;
}
goto stall_i;
/* end case REQUEST_TO_INTERFACE */
case REQUEST_TO_ENDPOINT:
goto stall_i;
/* end case REQUEST_TO_ENDPOINT */
default:
goto stall_i;
}
out_class_ok: /* request finished successfully */
break; /* end case REQUEST_CLASS */
default:
stall_i:
USBD_SetStallEP(0x80);
USBD_EP0Data.Count = 0;
break;
}
}
}
} else {
USBD_StatusOutStage(); /* receive Acknowledge */
}
} /* end USBD_EVT_OUT */
if (event & USBD_EVT_IN) {
if (USBD_SetupPacket.bmRequestType.Dir == REQUEST_DEVICE_TO_HOST) {
if (USBD_EP0Data.Count || USBD_ZLP) {
USBD_DataInStage(); /* send data */
}
} else {
if (USBD_DeviceAddress & 0x80) {
USBD_DeviceAddress &= 0x7F;
USBD_SetAddress(USBD_DeviceAddress, 0);
}
}
} /* end USBD_EVT_IN */
if (event & USBD_EVT_OUT_STALL) {
USBD_ClrStallEP(0x00);
}
if (event & USBD_EVT_IN_STALL) {
USBD_ClrStallEP(0x80);
}
}
/*
* USB Device Endpoint 0 RTX Task
* Parameters: none
* Return Value: none
*/
#ifdef __RTX
void USBD_RTX_EndPoint0(void)
{
for (;;) {
usbd_os_evt_wait_or(0xFFFF, 0xFFFF);
USBD_EndPoint0(usbd_os_evt_get());
}
}
#endif