mirror of
https://github.com/ARMmbed/DAPLink.git
synced 2025-07-15 22:23:09 +08:00
1051 lines
32 KiB
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
|