mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/m480_usbd.c@173:e131a1973e81, 2017-09-15 (annotated)
- Committer:
- AnnaBridge
- Date:
- Fri Sep 15 14:59:18 2017 +0100
- Revision:
- 173:e131a1973e81
- Parent:
- 172:7d866c31b3c5
This updates the lib to the mbed lib v 151
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 172:7d866c31b3c5 | 1 | /**************************************************************************//** |
AnnaBridge | 172:7d866c31b3c5 | 2 | * @file usbd.c |
AnnaBridge | 172:7d866c31b3c5 | 3 | * @version V1.00 |
AnnaBridge | 172:7d866c31b3c5 | 4 | * @brief M480 USBD driver source file |
AnnaBridge | 172:7d866c31b3c5 | 5 | * |
AnnaBridge | 172:7d866c31b3c5 | 6 | * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. |
AnnaBridge | 172:7d866c31b3c5 | 7 | *****************************************************************************/ |
AnnaBridge | 172:7d866c31b3c5 | 8 | |
AnnaBridge | 172:7d866c31b3c5 | 9 | #include <string.h> |
AnnaBridge | 172:7d866c31b3c5 | 10 | #include "M480.h" |
AnnaBridge | 172:7d866c31b3c5 | 11 | |
AnnaBridge | 172:7d866c31b3c5 | 12 | #ifdef __cplusplus |
AnnaBridge | 172:7d866c31b3c5 | 13 | extern "C" |
AnnaBridge | 172:7d866c31b3c5 | 14 | { |
AnnaBridge | 172:7d866c31b3c5 | 15 | #endif |
AnnaBridge | 172:7d866c31b3c5 | 16 | |
AnnaBridge | 172:7d866c31b3c5 | 17 | /** @addtogroup M480_Device_Driver M480 Device Driver |
AnnaBridge | 172:7d866c31b3c5 | 18 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 19 | */ |
AnnaBridge | 172:7d866c31b3c5 | 20 | |
AnnaBridge | 172:7d866c31b3c5 | 21 | /** @addtogroup M480_USBD_Driver USBD Driver |
AnnaBridge | 172:7d866c31b3c5 | 22 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 23 | */ |
AnnaBridge | 172:7d866c31b3c5 | 24 | |
AnnaBridge | 172:7d866c31b3c5 | 25 | |
AnnaBridge | 172:7d866c31b3c5 | 26 | /** @addtogroup M480_USBD_EXPORTED_FUNCTIONS USBD Exported Functions |
AnnaBridge | 172:7d866c31b3c5 | 27 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 28 | */ |
AnnaBridge | 172:7d866c31b3c5 | 29 | |
AnnaBridge | 172:7d866c31b3c5 | 30 | /* Global variables for Control Pipe */ |
AnnaBridge | 172:7d866c31b3c5 | 31 | uint8_t g_usbd_SetupPacket[8] = {0ul}; /*!< Setup packet buffer */ |
AnnaBridge | 172:7d866c31b3c5 | 32 | volatile uint8_t g_usbd_RemoteWakeupEn = 0ul; /*!< Remote wake up function enable flag */ |
AnnaBridge | 172:7d866c31b3c5 | 33 | |
AnnaBridge | 172:7d866c31b3c5 | 34 | /** |
AnnaBridge | 172:7d866c31b3c5 | 35 | * @cond HIDDEN_SYMBOLS |
AnnaBridge | 172:7d866c31b3c5 | 36 | */ |
AnnaBridge | 172:7d866c31b3c5 | 37 | static uint8_t *g_usbd_CtrlInPointer = 0; |
AnnaBridge | 172:7d866c31b3c5 | 38 | static uint8_t *g_usbd_CtrlOutPointer = 0; |
AnnaBridge | 172:7d866c31b3c5 | 39 | static volatile uint32_t g_usbd_CtrlInSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 40 | static volatile uint32_t g_usbd_CtrlOutSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 41 | static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 42 | static volatile uint32_t g_usbd_UsbAddr = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 43 | static volatile uint32_t g_usbd_UsbConfig = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 44 | static volatile uint32_t g_usbd_CtrlMaxPktSize = 8ul; |
AnnaBridge | 172:7d866c31b3c5 | 45 | static volatile uint32_t g_usbd_UsbAltInterface = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 46 | /** |
AnnaBridge | 172:7d866c31b3c5 | 47 | * @endcond |
AnnaBridge | 172:7d866c31b3c5 | 48 | */ |
AnnaBridge | 172:7d866c31b3c5 | 49 | |
AnnaBridge | 172:7d866c31b3c5 | 50 | const S_USBD_INFO_T *g_usbd_sInfo; /*!< A pointer for USB information structure */ |
AnnaBridge | 172:7d866c31b3c5 | 51 | |
AnnaBridge | 172:7d866c31b3c5 | 52 | VENDOR_REQ g_usbd_pfnVendorRequest = NULL; /*!< USB Vendor Request Functional Pointer */ |
AnnaBridge | 172:7d866c31b3c5 | 53 | CLASS_REQ g_usbd_pfnClassRequest = NULL; /*!< USB Class Request Functional Pointer */ |
AnnaBridge | 172:7d866c31b3c5 | 54 | SET_INTERFACE_REQ g_usbd_pfnSetInterface = NULL; /*!< USB Set Interface Functional Pointer */ |
AnnaBridge | 172:7d866c31b3c5 | 55 | SET_CONFIG_CB g_usbd_pfnSetConfigCallback = NULL; /*!< USB Set configuration callback function pointer */ |
AnnaBridge | 172:7d866c31b3c5 | 56 | uint32_t g_u32EpStallLock = 0ul; /*!< Bit map flag to lock specified EP when SET_FEATURE */ |
AnnaBridge | 172:7d866c31b3c5 | 57 | |
AnnaBridge | 172:7d866c31b3c5 | 58 | /** |
AnnaBridge | 172:7d866c31b3c5 | 59 | * @brief This function makes USBD module to be ready to use |
AnnaBridge | 172:7d866c31b3c5 | 60 | * |
AnnaBridge | 172:7d866c31b3c5 | 61 | * @param[in] param The structure of USBD information. |
AnnaBridge | 172:7d866c31b3c5 | 62 | * @param[in] pfnClassReq USB Class request callback function. |
AnnaBridge | 172:7d866c31b3c5 | 63 | * @param[in] pfnSetInterface USB Set Interface request callback function. |
AnnaBridge | 172:7d866c31b3c5 | 64 | * |
AnnaBridge | 172:7d866c31b3c5 | 65 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 66 | * |
AnnaBridge | 172:7d866c31b3c5 | 67 | * @details This function will enable USB controller, USB PHY transceiver and pull-up resistor of USB_D+ pin. USB PHY will drive SE0 to bus. |
AnnaBridge | 172:7d866c31b3c5 | 68 | */ |
AnnaBridge | 172:7d866c31b3c5 | 69 | void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface) |
AnnaBridge | 172:7d866c31b3c5 | 70 | { |
AnnaBridge | 172:7d866c31b3c5 | 71 | g_usbd_sInfo = param; |
AnnaBridge | 172:7d866c31b3c5 | 72 | g_usbd_pfnClassRequest = pfnClassReq; |
AnnaBridge | 172:7d866c31b3c5 | 73 | g_usbd_pfnSetInterface = pfnSetInterface; |
AnnaBridge | 172:7d866c31b3c5 | 74 | |
AnnaBridge | 172:7d866c31b3c5 | 75 | /* get EP0 maximum packet size */ |
AnnaBridge | 172:7d866c31b3c5 | 76 | g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7]; |
AnnaBridge | 172:7d866c31b3c5 | 77 | |
AnnaBridge | 172:7d866c31b3c5 | 78 | /* Initial USB engine */ |
AnnaBridge | 172:7d866c31b3c5 | 79 | USBD->ATTR = 0x6D0ul; |
AnnaBridge | 172:7d866c31b3c5 | 80 | /* Force SE0 */ |
AnnaBridge | 172:7d866c31b3c5 | 81 | USBD_SET_SE0(); |
AnnaBridge | 172:7d866c31b3c5 | 82 | } |
AnnaBridge | 172:7d866c31b3c5 | 83 | |
AnnaBridge | 172:7d866c31b3c5 | 84 | /** |
AnnaBridge | 172:7d866c31b3c5 | 85 | * @brief This function makes USB host to recognize the device |
AnnaBridge | 172:7d866c31b3c5 | 86 | * |
AnnaBridge | 172:7d866c31b3c5 | 87 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 88 | * |
AnnaBridge | 172:7d866c31b3c5 | 89 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 90 | * |
AnnaBridge | 172:7d866c31b3c5 | 91 | * @details Enable WAKEUP, FLDET, USB and BUS interrupts. Disable software-disconnect function after 100ms delay with SysTick timer. |
AnnaBridge | 172:7d866c31b3c5 | 92 | */ |
AnnaBridge | 172:7d866c31b3c5 | 93 | void USBD_Start(void) |
AnnaBridge | 172:7d866c31b3c5 | 94 | { |
AnnaBridge | 172:7d866c31b3c5 | 95 | /* Disable software-disconnect function */ |
AnnaBridge | 172:7d866c31b3c5 | 96 | USBD_CLR_SE0(); |
AnnaBridge | 172:7d866c31b3c5 | 97 | USBD->ATTR = 0x7D0ul; |
AnnaBridge | 172:7d866c31b3c5 | 98 | |
AnnaBridge | 172:7d866c31b3c5 | 99 | /* Clear USB-related interrupts before enable interrupt */ |
AnnaBridge | 172:7d866c31b3c5 | 100 | USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP); |
AnnaBridge | 172:7d866c31b3c5 | 101 | |
AnnaBridge | 172:7d866c31b3c5 | 102 | /* Enable USB-related interrupts. */ |
AnnaBridge | 172:7d866c31b3c5 | 103 | USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP); |
AnnaBridge | 172:7d866c31b3c5 | 104 | } |
AnnaBridge | 172:7d866c31b3c5 | 105 | |
AnnaBridge | 172:7d866c31b3c5 | 106 | /** |
AnnaBridge | 172:7d866c31b3c5 | 107 | * @brief Get the received SETUP packet |
AnnaBridge | 172:7d866c31b3c5 | 108 | * |
AnnaBridge | 172:7d866c31b3c5 | 109 | * @param[in] buf A buffer pointer used to store 8-byte SETUP packet. |
AnnaBridge | 172:7d866c31b3c5 | 110 | * |
AnnaBridge | 172:7d866c31b3c5 | 111 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 112 | * |
AnnaBridge | 172:7d866c31b3c5 | 113 | * @details Store SETUP packet to a user-specified buffer. |
AnnaBridge | 172:7d866c31b3c5 | 114 | * |
AnnaBridge | 172:7d866c31b3c5 | 115 | */ |
AnnaBridge | 172:7d866c31b3c5 | 116 | void USBD_GetSetupPacket(uint8_t *buf) |
AnnaBridge | 172:7d866c31b3c5 | 117 | { |
AnnaBridge | 172:7d866c31b3c5 | 118 | USBD_MemCopy(buf, g_usbd_SetupPacket, 8ul); |
AnnaBridge | 172:7d866c31b3c5 | 119 | } |
AnnaBridge | 172:7d866c31b3c5 | 120 | |
AnnaBridge | 172:7d866c31b3c5 | 121 | /** |
AnnaBridge | 172:7d866c31b3c5 | 122 | * @brief Process SETUP packet |
AnnaBridge | 172:7d866c31b3c5 | 123 | * |
AnnaBridge | 172:7d866c31b3c5 | 124 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 125 | * |
AnnaBridge | 172:7d866c31b3c5 | 126 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 127 | * |
AnnaBridge | 172:7d866c31b3c5 | 128 | * @details Parse SETUP packet and perform the corresponding action. |
AnnaBridge | 172:7d866c31b3c5 | 129 | * |
AnnaBridge | 172:7d866c31b3c5 | 130 | */ |
AnnaBridge | 172:7d866c31b3c5 | 131 | void USBD_ProcessSetupPacket(void) |
AnnaBridge | 172:7d866c31b3c5 | 132 | { |
AnnaBridge | 172:7d866c31b3c5 | 133 | /* Get SETUP packet from USB buffer */ |
AnnaBridge | 172:7d866c31b3c5 | 134 | USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8ul); |
AnnaBridge | 172:7d866c31b3c5 | 135 | |
AnnaBridge | 172:7d866c31b3c5 | 136 | /* Check the request type */ |
AnnaBridge | 172:7d866c31b3c5 | 137 | switch(g_usbd_SetupPacket[0] & 0x60ul) { |
AnnaBridge | 172:7d866c31b3c5 | 138 | case REQ_STANDARD: { |
AnnaBridge | 172:7d866c31b3c5 | 139 | USBD_StandardRequest(); |
AnnaBridge | 172:7d866c31b3c5 | 140 | break; |
AnnaBridge | 172:7d866c31b3c5 | 141 | } |
AnnaBridge | 172:7d866c31b3c5 | 142 | case REQ_CLASS: { |
AnnaBridge | 172:7d866c31b3c5 | 143 | if(g_usbd_pfnClassRequest != NULL) { |
AnnaBridge | 172:7d866c31b3c5 | 144 | g_usbd_pfnClassRequest(); |
AnnaBridge | 172:7d866c31b3c5 | 145 | } |
AnnaBridge | 172:7d866c31b3c5 | 146 | break; |
AnnaBridge | 172:7d866c31b3c5 | 147 | } |
AnnaBridge | 172:7d866c31b3c5 | 148 | case REQ_VENDOR: { |
AnnaBridge | 172:7d866c31b3c5 | 149 | if(g_usbd_pfnVendorRequest != NULL) { |
AnnaBridge | 172:7d866c31b3c5 | 150 | g_usbd_pfnVendorRequest(); |
AnnaBridge | 172:7d866c31b3c5 | 151 | } |
AnnaBridge | 172:7d866c31b3c5 | 152 | break; |
AnnaBridge | 172:7d866c31b3c5 | 153 | } |
AnnaBridge | 172:7d866c31b3c5 | 154 | default: { |
AnnaBridge | 172:7d866c31b3c5 | 155 | /* Setup error, stall the device */ |
AnnaBridge | 172:7d866c31b3c5 | 156 | USBD_SET_EP_STALL(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 157 | USBD_SET_EP_STALL(EP1); |
AnnaBridge | 172:7d866c31b3c5 | 158 | break; |
AnnaBridge | 172:7d866c31b3c5 | 159 | } |
AnnaBridge | 172:7d866c31b3c5 | 160 | } |
AnnaBridge | 172:7d866c31b3c5 | 161 | } |
AnnaBridge | 172:7d866c31b3c5 | 162 | |
AnnaBridge | 172:7d866c31b3c5 | 163 | /** |
AnnaBridge | 172:7d866c31b3c5 | 164 | * @brief Process GetDescriptor request |
AnnaBridge | 172:7d866c31b3c5 | 165 | * |
AnnaBridge | 172:7d866c31b3c5 | 166 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 167 | * |
AnnaBridge | 172:7d866c31b3c5 | 168 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 169 | * |
AnnaBridge | 172:7d866c31b3c5 | 170 | * @details Parse GetDescriptor request and perform the corresponding action. |
AnnaBridge | 172:7d866c31b3c5 | 171 | * |
AnnaBridge | 172:7d866c31b3c5 | 172 | */ |
AnnaBridge | 172:7d866c31b3c5 | 173 | void USBD_GetDescriptor(void) |
AnnaBridge | 172:7d866c31b3c5 | 174 | { |
AnnaBridge | 172:7d866c31b3c5 | 175 | uint32_t u32Len; |
AnnaBridge | 172:7d866c31b3c5 | 176 | |
AnnaBridge | 172:7d866c31b3c5 | 177 | u32Len = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 178 | u32Len = g_usbd_SetupPacket[7]; |
AnnaBridge | 172:7d866c31b3c5 | 179 | u32Len <<= 8ul; |
AnnaBridge | 172:7d866c31b3c5 | 180 | u32Len += g_usbd_SetupPacket[6]; |
AnnaBridge | 172:7d866c31b3c5 | 181 | |
AnnaBridge | 172:7d866c31b3c5 | 182 | switch(g_usbd_SetupPacket[3]) { |
AnnaBridge | 172:7d866c31b3c5 | 183 | /* Get Device Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 184 | case DESC_DEVICE: { |
AnnaBridge | 172:7d866c31b3c5 | 185 | u32Len = USBD_Minimum(u32Len, (uint32_t)LEN_DEVICE); |
AnnaBridge | 172:7d866c31b3c5 | 186 | USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len); |
AnnaBridge | 172:7d866c31b3c5 | 187 | |
AnnaBridge | 172:7d866c31b3c5 | 188 | break; |
AnnaBridge | 172:7d866c31b3c5 | 189 | } |
AnnaBridge | 172:7d866c31b3c5 | 190 | /* Get Configuration Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 191 | case DESC_CONFIG: { |
AnnaBridge | 172:7d866c31b3c5 | 192 | uint32_t u32TotalLen; |
AnnaBridge | 172:7d866c31b3c5 | 193 | |
AnnaBridge | 172:7d866c31b3c5 | 194 | u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3]; |
AnnaBridge | 172:7d866c31b3c5 | 195 | u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8); |
AnnaBridge | 172:7d866c31b3c5 | 196 | |
AnnaBridge | 172:7d866c31b3c5 | 197 | u32Len = USBD_Minimum(u32Len, u32TotalLen); |
AnnaBridge | 172:7d866c31b3c5 | 198 | USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len); |
AnnaBridge | 172:7d866c31b3c5 | 199 | |
AnnaBridge | 172:7d866c31b3c5 | 200 | break; |
AnnaBridge | 172:7d866c31b3c5 | 201 | } |
AnnaBridge | 172:7d866c31b3c5 | 202 | |
AnnaBridge | 172:7d866c31b3c5 | 203 | /* Get BOS Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 204 | case DESC_BOS: { |
AnnaBridge | 172:7d866c31b3c5 | 205 | u32Len = USBD_Minimum(u32Len, LEN_BOS+LEN_BOSCAP); |
AnnaBridge | 172:7d866c31b3c5 | 206 | USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8BosDesc, u32Len); |
AnnaBridge | 172:7d866c31b3c5 | 207 | break; |
AnnaBridge | 172:7d866c31b3c5 | 208 | } |
AnnaBridge | 172:7d866c31b3c5 | 209 | /* Get HID Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 210 | case DESC_HID: { |
AnnaBridge | 172:7d866c31b3c5 | 211 | /* CV3.0 HID Class Descriptor Test, |
AnnaBridge | 172:7d866c31b3c5 | 212 | Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */ |
AnnaBridge | 172:7d866c31b3c5 | 213 | uint32_t u32ConfigDescOffset; /* u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index) */ |
AnnaBridge | 172:7d866c31b3c5 | 214 | u32Len = USBD_Minimum(u32Len, LEN_HID); |
AnnaBridge | 172:7d866c31b3c5 | 215 | u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]]; |
AnnaBridge | 172:7d866c31b3c5 | 216 | USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len); |
AnnaBridge | 172:7d866c31b3c5 | 217 | |
AnnaBridge | 172:7d866c31b3c5 | 218 | break; |
AnnaBridge | 172:7d866c31b3c5 | 219 | } |
AnnaBridge | 172:7d866c31b3c5 | 220 | /* Get Report Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 221 | case DESC_HID_RPT: { |
AnnaBridge | 172:7d866c31b3c5 | 222 | u32Len = USBD_Minimum(u32Len, g_usbd_sInfo->gu32HidReportSize[g_usbd_SetupPacket[4]]); |
AnnaBridge | 172:7d866c31b3c5 | 223 | USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HidReportDesc[g_usbd_SetupPacket[4]], u32Len); |
AnnaBridge | 172:7d866c31b3c5 | 224 | break; |
AnnaBridge | 172:7d866c31b3c5 | 225 | } |
AnnaBridge | 172:7d866c31b3c5 | 226 | /* Get String Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 227 | case DESC_STRING: { |
AnnaBridge | 172:7d866c31b3c5 | 228 | /* Get String Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 229 | if(g_usbd_SetupPacket[2] < 4ul) { |
AnnaBridge | 172:7d866c31b3c5 | 230 | u32Len = USBD_Minimum(u32Len, g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0]); |
AnnaBridge | 172:7d866c31b3c5 | 231 | USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]], u32Len); |
AnnaBridge | 172:7d866c31b3c5 | 232 | |
AnnaBridge | 172:7d866c31b3c5 | 233 | |
AnnaBridge | 172:7d866c31b3c5 | 234 | break; |
AnnaBridge | 172:7d866c31b3c5 | 235 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 236 | /* Not support. Reply STALL. */ |
AnnaBridge | 172:7d866c31b3c5 | 237 | USBD_SET_EP_STALL(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 238 | USBD_SET_EP_STALL(EP1); |
AnnaBridge | 172:7d866c31b3c5 | 239 | break; |
AnnaBridge | 172:7d866c31b3c5 | 240 | } |
AnnaBridge | 172:7d866c31b3c5 | 241 | } |
AnnaBridge | 172:7d866c31b3c5 | 242 | default: |
AnnaBridge | 172:7d866c31b3c5 | 243 | /* Not support. Reply STALL.*/ |
AnnaBridge | 172:7d866c31b3c5 | 244 | USBD_SET_EP_STALL(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 245 | USBD_SET_EP_STALL(EP1); |
AnnaBridge | 172:7d866c31b3c5 | 246 | break; |
AnnaBridge | 172:7d866c31b3c5 | 247 | } |
AnnaBridge | 172:7d866c31b3c5 | 248 | } |
AnnaBridge | 172:7d866c31b3c5 | 249 | |
AnnaBridge | 172:7d866c31b3c5 | 250 | /** |
AnnaBridge | 172:7d866c31b3c5 | 251 | * @brief Process standard request |
AnnaBridge | 172:7d866c31b3c5 | 252 | * |
AnnaBridge | 172:7d866c31b3c5 | 253 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 254 | * |
AnnaBridge | 172:7d866c31b3c5 | 255 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 256 | * |
AnnaBridge | 172:7d866c31b3c5 | 257 | * @details Parse standard request and perform the corresponding action. |
AnnaBridge | 172:7d866c31b3c5 | 258 | * |
AnnaBridge | 172:7d866c31b3c5 | 259 | */ |
AnnaBridge | 172:7d866c31b3c5 | 260 | void USBD_StandardRequest(void) |
AnnaBridge | 172:7d866c31b3c5 | 261 | { |
AnnaBridge | 172:7d866c31b3c5 | 262 | uint32_t addr; |
AnnaBridge | 172:7d866c31b3c5 | 263 | /* clear global variables for new request */ |
AnnaBridge | 172:7d866c31b3c5 | 264 | g_usbd_CtrlInPointer = 0; |
AnnaBridge | 172:7d866c31b3c5 | 265 | g_usbd_CtrlInSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 266 | |
AnnaBridge | 172:7d866c31b3c5 | 267 | if((g_usbd_SetupPacket[0] & 0x80ul) == 0x80ul) { /* request data transfer direction */ |
AnnaBridge | 172:7d866c31b3c5 | 268 | /* Device to host */ |
AnnaBridge | 172:7d866c31b3c5 | 269 | switch(g_usbd_SetupPacket[1]) { |
AnnaBridge | 173:e131a1973e81 | 270 | case USBD_GET_CONFIGURATION: { |
AnnaBridge | 172:7d866c31b3c5 | 271 | /* Return current configuration setting */ |
AnnaBridge | 172:7d866c31b3c5 | 272 | /* Data stage */ |
AnnaBridge | 172:7d866c31b3c5 | 273 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 274 | M8(addr) = (uint8_t)g_usbd_UsbConfig; |
AnnaBridge | 172:7d866c31b3c5 | 275 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 276 | USBD_SET_PAYLOAD_LEN(EP0, 1ul); |
AnnaBridge | 172:7d866c31b3c5 | 277 | /* Status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 278 | USBD_PrepareCtrlOut(0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 279 | break; |
AnnaBridge | 172:7d866c31b3c5 | 280 | } |
AnnaBridge | 173:e131a1973e81 | 281 | case USBD_GET_DESCRIPTOR: { |
AnnaBridge | 172:7d866c31b3c5 | 282 | USBD_GetDescriptor(); |
AnnaBridge | 172:7d866c31b3c5 | 283 | USBD_PrepareCtrlOut(0, 0ul); /* For status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 284 | break; |
AnnaBridge | 172:7d866c31b3c5 | 285 | } |
AnnaBridge | 173:e131a1973e81 | 286 | case USBD_GET_INTERFACE: { |
AnnaBridge | 172:7d866c31b3c5 | 287 | /* Return current interface setting */ |
AnnaBridge | 172:7d866c31b3c5 | 288 | /* Data stage */ |
AnnaBridge | 172:7d866c31b3c5 | 289 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 290 | M8(addr) = (uint8_t)g_usbd_UsbAltInterface; |
AnnaBridge | 172:7d866c31b3c5 | 291 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 292 | USBD_SET_PAYLOAD_LEN(EP0, 1ul); |
AnnaBridge | 172:7d866c31b3c5 | 293 | /* Status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 294 | USBD_PrepareCtrlOut(0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 295 | break; |
AnnaBridge | 172:7d866c31b3c5 | 296 | } |
AnnaBridge | 173:e131a1973e81 | 297 | case USBD_GET_STATUS: { |
AnnaBridge | 172:7d866c31b3c5 | 298 | /* Device */ |
AnnaBridge | 172:7d866c31b3c5 | 299 | if(g_usbd_SetupPacket[0] == 0x80ul) { |
AnnaBridge | 172:7d866c31b3c5 | 300 | uint8_t u8Tmp; |
AnnaBridge | 172:7d866c31b3c5 | 301 | |
AnnaBridge | 172:7d866c31b3c5 | 302 | u8Tmp = (uint8_t)0ul; |
AnnaBridge | 172:7d866c31b3c5 | 303 | if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x40ul) == 0x40ul) { |
AnnaBridge | 172:7d866c31b3c5 | 304 | u8Tmp |= (uint8_t)1ul; /* Self-Powered/Bus-Powered.*/ |
AnnaBridge | 172:7d866c31b3c5 | 305 | } |
AnnaBridge | 172:7d866c31b3c5 | 306 | if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x20ul) == 0x20ul) { |
AnnaBridge | 172:7d866c31b3c5 | 307 | u8Tmp |= (uint8_t)(g_usbd_RemoteWakeupEn << 1ul); /* Remote wake up */ |
AnnaBridge | 172:7d866c31b3c5 | 308 | } |
AnnaBridge | 172:7d866c31b3c5 | 309 | |
AnnaBridge | 172:7d866c31b3c5 | 310 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 311 | M8(addr) = u8Tmp; |
AnnaBridge | 172:7d866c31b3c5 | 312 | |
AnnaBridge | 172:7d866c31b3c5 | 313 | } |
AnnaBridge | 172:7d866c31b3c5 | 314 | /* Interface */ |
AnnaBridge | 172:7d866c31b3c5 | 315 | else if(g_usbd_SetupPacket[0] == 0x81ul) { |
AnnaBridge | 172:7d866c31b3c5 | 316 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 317 | M8(addr) = (uint8_t)0ul; |
AnnaBridge | 172:7d866c31b3c5 | 318 | } |
AnnaBridge | 172:7d866c31b3c5 | 319 | /* Endpoint */ |
AnnaBridge | 172:7d866c31b3c5 | 320 | else if(g_usbd_SetupPacket[0] == 0x82ul) { |
AnnaBridge | 172:7d866c31b3c5 | 321 | uint8_t ep = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul); |
AnnaBridge | 172:7d866c31b3c5 | 322 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 323 | M8(addr) = (uint8_t)(USBD_GetStall(ep) ? 1ul : 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 324 | } |
AnnaBridge | 172:7d866c31b3c5 | 325 | |
AnnaBridge | 172:7d866c31b3c5 | 326 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0) + 1ul; |
AnnaBridge | 172:7d866c31b3c5 | 327 | M8(addr) = (uint8_t)0ul; |
AnnaBridge | 172:7d866c31b3c5 | 328 | /* Data stage */ |
AnnaBridge | 172:7d866c31b3c5 | 329 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 330 | USBD_SET_PAYLOAD_LEN(EP0, 2ul); |
AnnaBridge | 172:7d866c31b3c5 | 331 | /* Status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 332 | USBD_PrepareCtrlOut(0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 333 | break; |
AnnaBridge | 172:7d866c31b3c5 | 334 | } |
AnnaBridge | 172:7d866c31b3c5 | 335 | default: { |
AnnaBridge | 172:7d866c31b3c5 | 336 | /* Setup error, stall the device */ |
AnnaBridge | 172:7d866c31b3c5 | 337 | USBD_SET_EP_STALL(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 338 | USBD_SET_EP_STALL(EP1); |
AnnaBridge | 172:7d866c31b3c5 | 339 | break; |
AnnaBridge | 172:7d866c31b3c5 | 340 | } |
AnnaBridge | 172:7d866c31b3c5 | 341 | } |
AnnaBridge | 172:7d866c31b3c5 | 342 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 343 | /* Host to device */ |
AnnaBridge | 172:7d866c31b3c5 | 344 | switch(g_usbd_SetupPacket[1]) { |
AnnaBridge | 173:e131a1973e81 | 345 | case USBD_CLEAR_FEATURE: { |
AnnaBridge | 172:7d866c31b3c5 | 346 | if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT) { |
AnnaBridge | 172:7d866c31b3c5 | 347 | uint32_t epNum, i; |
AnnaBridge | 172:7d866c31b3c5 | 348 | |
AnnaBridge | 172:7d866c31b3c5 | 349 | /* EP number stall is not allow to be clear in MSC class "Error Recovery Test". |
AnnaBridge | 172:7d866c31b3c5 | 350 | a flag: g_u32EpStallLock is added to support it */ |
AnnaBridge | 172:7d866c31b3c5 | 351 | epNum = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul); |
AnnaBridge | 172:7d866c31b3c5 | 352 | for(i = 0ul; i < USBD_MAX_EP; i++) { |
AnnaBridge | 172:7d866c31b3c5 | 353 | if(((USBD->EP[i].CFG & 0xFul) == epNum) && ((g_u32EpStallLock & (1ul << i)) == 0ul)) { |
AnnaBridge | 172:7d866c31b3c5 | 354 | USBD->EP[i].CFGP &= ~USBD_CFGP_SSTALL_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 355 | } |
AnnaBridge | 172:7d866c31b3c5 | 356 | } |
AnnaBridge | 172:7d866c31b3c5 | 357 | } else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP) { |
AnnaBridge | 172:7d866c31b3c5 | 358 | g_usbd_RemoteWakeupEn = (uint8_t)0; |
AnnaBridge | 172:7d866c31b3c5 | 359 | } |
AnnaBridge | 172:7d866c31b3c5 | 360 | |
AnnaBridge | 172:7d866c31b3c5 | 361 | /* Status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 362 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 363 | USBD_SET_PAYLOAD_LEN(EP0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 364 | break; |
AnnaBridge | 172:7d866c31b3c5 | 365 | } |
AnnaBridge | 173:e131a1973e81 | 366 | case USBD_SET_ADDRESS: { |
AnnaBridge | 172:7d866c31b3c5 | 367 | g_usbd_UsbAddr = g_usbd_SetupPacket[2]; |
AnnaBridge | 172:7d866c31b3c5 | 368 | /* Status Stage */ |
AnnaBridge | 172:7d866c31b3c5 | 369 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 370 | USBD_SET_PAYLOAD_LEN(EP0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 371 | |
AnnaBridge | 172:7d866c31b3c5 | 372 | break; |
AnnaBridge | 172:7d866c31b3c5 | 373 | } |
AnnaBridge | 173:e131a1973e81 | 374 | case USBD_SET_CONFIGURATION: { |
AnnaBridge | 172:7d866c31b3c5 | 375 | g_usbd_UsbConfig = g_usbd_SetupPacket[2]; |
AnnaBridge | 172:7d866c31b3c5 | 376 | |
AnnaBridge | 172:7d866c31b3c5 | 377 | if(g_usbd_pfnSetConfigCallback) { |
AnnaBridge | 172:7d866c31b3c5 | 378 | g_usbd_pfnSetConfigCallback(); |
AnnaBridge | 172:7d866c31b3c5 | 379 | } |
AnnaBridge | 172:7d866c31b3c5 | 380 | |
AnnaBridge | 172:7d866c31b3c5 | 381 | /* Status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 382 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 383 | USBD_SET_PAYLOAD_LEN(EP0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 384 | break; |
AnnaBridge | 172:7d866c31b3c5 | 385 | } |
AnnaBridge | 173:e131a1973e81 | 386 | case USBD_SET_FEATURE: { |
AnnaBridge | 172:7d866c31b3c5 | 387 | if( (g_usbd_SetupPacket[0] & 0xFul) == 0ul ) { /* 0: device */ |
AnnaBridge | 172:7d866c31b3c5 | 388 | if((g_usbd_SetupPacket[2] == 3ul) && (g_usbd_SetupPacket[3] == 0ul)) { /* 3: HNP enable */ |
AnnaBridge | 172:7d866c31b3c5 | 389 | OTG->CTL |= (OTG_CTL_HNPREQEN_Msk | OTG_CTL_BUSREQ_Msk); |
AnnaBridge | 172:7d866c31b3c5 | 390 | } |
AnnaBridge | 172:7d866c31b3c5 | 391 | } |
AnnaBridge | 172:7d866c31b3c5 | 392 | if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT) { |
AnnaBridge | 172:7d866c31b3c5 | 393 | USBD_SetStall((uint8_t)(g_usbd_SetupPacket[4] & 0xFul)); |
AnnaBridge | 172:7d866c31b3c5 | 394 | } else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP) { |
AnnaBridge | 172:7d866c31b3c5 | 395 | g_usbd_RemoteWakeupEn = (uint8_t)1ul; |
AnnaBridge | 172:7d866c31b3c5 | 396 | } |
AnnaBridge | 172:7d866c31b3c5 | 397 | |
AnnaBridge | 172:7d866c31b3c5 | 398 | /* Status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 399 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 400 | USBD_SET_PAYLOAD_LEN(EP0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 401 | |
AnnaBridge | 172:7d866c31b3c5 | 402 | break; |
AnnaBridge | 172:7d866c31b3c5 | 403 | } |
AnnaBridge | 173:e131a1973e81 | 404 | case USBD_SET_INTERFACE: { |
AnnaBridge | 172:7d866c31b3c5 | 405 | g_usbd_UsbAltInterface = g_usbd_SetupPacket[2]; |
AnnaBridge | 172:7d866c31b3c5 | 406 | if(g_usbd_pfnSetInterface != NULL) { |
AnnaBridge | 172:7d866c31b3c5 | 407 | g_usbd_pfnSetInterface(g_usbd_UsbAltInterface); |
AnnaBridge | 172:7d866c31b3c5 | 408 | } |
AnnaBridge | 172:7d866c31b3c5 | 409 | /* Status stage */ |
AnnaBridge | 172:7d866c31b3c5 | 410 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 411 | USBD_SET_PAYLOAD_LEN(EP0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 412 | break; |
AnnaBridge | 172:7d866c31b3c5 | 413 | } |
AnnaBridge | 172:7d866c31b3c5 | 414 | default: { |
AnnaBridge | 172:7d866c31b3c5 | 415 | /* Setup error, stall the device */ |
AnnaBridge | 172:7d866c31b3c5 | 416 | USBD_SET_EP_STALL(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 417 | USBD_SET_EP_STALL(EP1); |
AnnaBridge | 172:7d866c31b3c5 | 418 | break; |
AnnaBridge | 172:7d866c31b3c5 | 419 | } |
AnnaBridge | 172:7d866c31b3c5 | 420 | } |
AnnaBridge | 172:7d866c31b3c5 | 421 | } |
AnnaBridge | 172:7d866c31b3c5 | 422 | } |
AnnaBridge | 172:7d866c31b3c5 | 423 | |
AnnaBridge | 172:7d866c31b3c5 | 424 | /** |
AnnaBridge | 172:7d866c31b3c5 | 425 | * @brief Prepare the first Control IN pipe |
AnnaBridge | 172:7d866c31b3c5 | 426 | * |
AnnaBridge | 172:7d866c31b3c5 | 427 | * @param[in] pu8Buf The pointer of data sent to USB host. |
AnnaBridge | 172:7d866c31b3c5 | 428 | * @param[in] u32Size The IN transfer size. |
AnnaBridge | 172:7d866c31b3c5 | 429 | * |
AnnaBridge | 172:7d866c31b3c5 | 430 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 431 | * |
AnnaBridge | 172:7d866c31b3c5 | 432 | * @details Prepare data for Control IN transfer. |
AnnaBridge | 172:7d866c31b3c5 | 433 | * |
AnnaBridge | 172:7d866c31b3c5 | 434 | */ |
AnnaBridge | 172:7d866c31b3c5 | 435 | void USBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size) |
AnnaBridge | 172:7d866c31b3c5 | 436 | { |
AnnaBridge | 172:7d866c31b3c5 | 437 | uint32_t addr; |
AnnaBridge | 172:7d866c31b3c5 | 438 | if(u32Size > g_usbd_CtrlMaxPktSize) { |
AnnaBridge | 172:7d866c31b3c5 | 439 | /* Data size > MXPLD */ |
AnnaBridge | 172:7d866c31b3c5 | 440 | g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize; |
AnnaBridge | 172:7d866c31b3c5 | 441 | g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize; |
AnnaBridge | 172:7d866c31b3c5 | 442 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 443 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 444 | USBD_MemCopy((uint8_t *)addr, pu8Buf, g_usbd_CtrlMaxPktSize); |
AnnaBridge | 172:7d866c31b3c5 | 445 | USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize); |
AnnaBridge | 172:7d866c31b3c5 | 446 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 447 | /* Data size <= MXPLD */ |
AnnaBridge | 172:7d866c31b3c5 | 448 | g_usbd_CtrlInPointer = 0; |
AnnaBridge | 172:7d866c31b3c5 | 449 | g_usbd_CtrlInSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 450 | USBD_SET_DATA1(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 451 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 452 | USBD_MemCopy((uint8_t *)addr, pu8Buf, u32Size); |
AnnaBridge | 172:7d866c31b3c5 | 453 | USBD_SET_PAYLOAD_LEN(EP0, u32Size); |
AnnaBridge | 172:7d866c31b3c5 | 454 | } |
AnnaBridge | 172:7d866c31b3c5 | 455 | } |
AnnaBridge | 172:7d866c31b3c5 | 456 | |
AnnaBridge | 172:7d866c31b3c5 | 457 | /** |
AnnaBridge | 172:7d866c31b3c5 | 458 | * @brief Repeat Control IN pipe |
AnnaBridge | 172:7d866c31b3c5 | 459 | * |
AnnaBridge | 172:7d866c31b3c5 | 460 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 461 | * |
AnnaBridge | 172:7d866c31b3c5 | 462 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 463 | * |
AnnaBridge | 172:7d866c31b3c5 | 464 | * @details This function processes the remained data of Control IN transfer. |
AnnaBridge | 172:7d866c31b3c5 | 465 | * |
AnnaBridge | 172:7d866c31b3c5 | 466 | */ |
AnnaBridge | 172:7d866c31b3c5 | 467 | void USBD_CtrlIn(void) |
AnnaBridge | 172:7d866c31b3c5 | 468 | { |
AnnaBridge | 172:7d866c31b3c5 | 469 | static uint8_t u8ZeroFlag = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 470 | uint32_t addr; |
AnnaBridge | 172:7d866c31b3c5 | 471 | |
AnnaBridge | 172:7d866c31b3c5 | 472 | if(g_usbd_CtrlInSize) { |
AnnaBridge | 172:7d866c31b3c5 | 473 | /* Process remained data */ |
AnnaBridge | 172:7d866c31b3c5 | 474 | if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize) { |
AnnaBridge | 172:7d866c31b3c5 | 475 | /* Data size > MXPLD */ |
AnnaBridge | 172:7d866c31b3c5 | 476 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 477 | USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize); |
AnnaBridge | 172:7d866c31b3c5 | 478 | USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize); |
AnnaBridge | 172:7d866c31b3c5 | 479 | g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize; |
AnnaBridge | 172:7d866c31b3c5 | 480 | g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize; |
AnnaBridge | 172:7d866c31b3c5 | 481 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 482 | /* Data size <= MXPLD */ |
AnnaBridge | 172:7d866c31b3c5 | 483 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); |
AnnaBridge | 172:7d866c31b3c5 | 484 | USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize); |
AnnaBridge | 172:7d866c31b3c5 | 485 | USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize); |
AnnaBridge | 172:7d866c31b3c5 | 486 | if(g_usbd_CtrlInSize == g_usbd_CtrlMaxPktSize) { |
AnnaBridge | 172:7d866c31b3c5 | 487 | u8ZeroFlag = (uint8_t)1ul; |
AnnaBridge | 172:7d866c31b3c5 | 488 | } |
AnnaBridge | 172:7d866c31b3c5 | 489 | g_usbd_CtrlInPointer = 0; |
AnnaBridge | 172:7d866c31b3c5 | 490 | g_usbd_CtrlInSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 491 | } |
AnnaBridge | 172:7d866c31b3c5 | 492 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 493 | /* In ACK for Set address */ |
AnnaBridge | 173:e131a1973e81 | 494 | if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == USBD_SET_ADDRESS)) { |
AnnaBridge | 172:7d866c31b3c5 | 495 | addr = USBD_GET_ADDR(); |
AnnaBridge | 172:7d866c31b3c5 | 496 | if((addr != g_usbd_UsbAddr) && (addr == 0ul)) { |
AnnaBridge | 172:7d866c31b3c5 | 497 | USBD_SET_ADDR(g_usbd_UsbAddr); |
AnnaBridge | 172:7d866c31b3c5 | 498 | } |
AnnaBridge | 172:7d866c31b3c5 | 499 | } |
AnnaBridge | 172:7d866c31b3c5 | 500 | |
AnnaBridge | 172:7d866c31b3c5 | 501 | /* For the case of data size is integral times maximum packet size */ |
AnnaBridge | 172:7d866c31b3c5 | 502 | if(u8ZeroFlag) { |
AnnaBridge | 172:7d866c31b3c5 | 503 | USBD_SET_PAYLOAD_LEN(EP0, 0ul); |
AnnaBridge | 172:7d866c31b3c5 | 504 | u8ZeroFlag = (uint8_t)0ul; |
AnnaBridge | 172:7d866c31b3c5 | 505 | } |
AnnaBridge | 172:7d866c31b3c5 | 506 | } |
AnnaBridge | 172:7d866c31b3c5 | 507 | } |
AnnaBridge | 172:7d866c31b3c5 | 508 | |
AnnaBridge | 172:7d866c31b3c5 | 509 | /** |
AnnaBridge | 172:7d866c31b3c5 | 510 | * @brief Prepare the first Control OUT pipe |
AnnaBridge | 172:7d866c31b3c5 | 511 | * |
AnnaBridge | 172:7d866c31b3c5 | 512 | * @param[in] pu8Buf The pointer of data received from USB host. |
AnnaBridge | 172:7d866c31b3c5 | 513 | * @param[in] u32Size The OUT transfer size. |
AnnaBridge | 172:7d866c31b3c5 | 514 | * |
AnnaBridge | 172:7d866c31b3c5 | 515 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 516 | * |
AnnaBridge | 172:7d866c31b3c5 | 517 | * @details This function is used to prepare the first Control OUT transfer. |
AnnaBridge | 172:7d866c31b3c5 | 518 | * |
AnnaBridge | 172:7d866c31b3c5 | 519 | */ |
AnnaBridge | 172:7d866c31b3c5 | 520 | void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size) |
AnnaBridge | 172:7d866c31b3c5 | 521 | { |
AnnaBridge | 172:7d866c31b3c5 | 522 | g_usbd_CtrlOutPointer = pu8Buf; |
AnnaBridge | 172:7d866c31b3c5 | 523 | g_usbd_CtrlOutSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 524 | g_usbd_CtrlOutSizeLimit = u32Size; |
AnnaBridge | 172:7d866c31b3c5 | 525 | USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize); |
AnnaBridge | 172:7d866c31b3c5 | 526 | } |
AnnaBridge | 172:7d866c31b3c5 | 527 | |
AnnaBridge | 172:7d866c31b3c5 | 528 | /** |
AnnaBridge | 172:7d866c31b3c5 | 529 | * @brief Repeat Control OUT pipe |
AnnaBridge | 172:7d866c31b3c5 | 530 | * |
AnnaBridge | 172:7d866c31b3c5 | 531 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 532 | * |
AnnaBridge | 172:7d866c31b3c5 | 533 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 534 | * |
AnnaBridge | 172:7d866c31b3c5 | 535 | * @details This function processes the successive Control OUT transfer. |
AnnaBridge | 172:7d866c31b3c5 | 536 | * |
AnnaBridge | 172:7d866c31b3c5 | 537 | */ |
AnnaBridge | 172:7d866c31b3c5 | 538 | void USBD_CtrlOut(void) |
AnnaBridge | 172:7d866c31b3c5 | 539 | { |
AnnaBridge | 172:7d866c31b3c5 | 540 | uint32_t u32Size; |
AnnaBridge | 172:7d866c31b3c5 | 541 | uint32_t addr; |
AnnaBridge | 172:7d866c31b3c5 | 542 | |
AnnaBridge | 172:7d866c31b3c5 | 543 | if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit) { |
AnnaBridge | 172:7d866c31b3c5 | 544 | u32Size = USBD_GET_PAYLOAD_LEN(EP1); |
AnnaBridge | 172:7d866c31b3c5 | 545 | addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1); |
AnnaBridge | 172:7d866c31b3c5 | 546 | USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)addr, u32Size); |
AnnaBridge | 172:7d866c31b3c5 | 547 | g_usbd_CtrlOutPointer += u32Size; |
AnnaBridge | 172:7d866c31b3c5 | 548 | g_usbd_CtrlOutSize += u32Size; |
AnnaBridge | 172:7d866c31b3c5 | 549 | |
AnnaBridge | 172:7d866c31b3c5 | 550 | if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit) { |
AnnaBridge | 172:7d866c31b3c5 | 551 | USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize); |
AnnaBridge | 172:7d866c31b3c5 | 552 | } |
AnnaBridge | 172:7d866c31b3c5 | 553 | |
AnnaBridge | 172:7d866c31b3c5 | 554 | } |
AnnaBridge | 172:7d866c31b3c5 | 555 | } |
AnnaBridge | 172:7d866c31b3c5 | 556 | |
AnnaBridge | 172:7d866c31b3c5 | 557 | /** |
AnnaBridge | 172:7d866c31b3c5 | 558 | * @brief Reset software flags |
AnnaBridge | 172:7d866c31b3c5 | 559 | * |
AnnaBridge | 172:7d866c31b3c5 | 560 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 561 | * |
AnnaBridge | 172:7d866c31b3c5 | 562 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 563 | * |
AnnaBridge | 172:7d866c31b3c5 | 564 | * @details This function resets all variables for protocol and resets USB device address to 0. |
AnnaBridge | 172:7d866c31b3c5 | 565 | * |
AnnaBridge | 172:7d866c31b3c5 | 566 | */ |
AnnaBridge | 172:7d866c31b3c5 | 567 | void USBD_SwReset(void) |
AnnaBridge | 172:7d866c31b3c5 | 568 | { |
AnnaBridge | 172:7d866c31b3c5 | 569 | uint32_t i; |
AnnaBridge | 172:7d866c31b3c5 | 570 | |
AnnaBridge | 172:7d866c31b3c5 | 571 | /* Reset all variables for protocol */ |
AnnaBridge | 172:7d866c31b3c5 | 572 | g_usbd_CtrlInPointer = 0; |
AnnaBridge | 172:7d866c31b3c5 | 573 | g_usbd_CtrlInSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 574 | g_usbd_CtrlOutPointer = 0; |
AnnaBridge | 172:7d866c31b3c5 | 575 | g_usbd_CtrlOutSize = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 576 | g_usbd_CtrlOutSizeLimit = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 577 | g_u32EpStallLock = 0ul; |
AnnaBridge | 172:7d866c31b3c5 | 578 | memset(g_usbd_SetupPacket, 0, 8ul); |
AnnaBridge | 172:7d866c31b3c5 | 579 | |
AnnaBridge | 172:7d866c31b3c5 | 580 | /* Reset PID DATA0 */ |
AnnaBridge | 172:7d866c31b3c5 | 581 | for(i=0ul; i<USBD_MAX_EP; i++) { |
AnnaBridge | 172:7d866c31b3c5 | 582 | USBD->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 583 | } |
AnnaBridge | 172:7d866c31b3c5 | 584 | |
AnnaBridge | 172:7d866c31b3c5 | 585 | /* Reset USB device address */ |
AnnaBridge | 172:7d866c31b3c5 | 586 | USBD_SET_ADDR(0ul); |
AnnaBridge | 172:7d866c31b3c5 | 587 | } |
AnnaBridge | 172:7d866c31b3c5 | 588 | |
AnnaBridge | 172:7d866c31b3c5 | 589 | /** |
AnnaBridge | 172:7d866c31b3c5 | 590 | * @brief USBD Set Vendor Request |
AnnaBridge | 172:7d866c31b3c5 | 591 | * |
AnnaBridge | 172:7d866c31b3c5 | 592 | * @param[in] pfnVendorReq Vendor Request Callback Function |
AnnaBridge | 172:7d866c31b3c5 | 593 | * |
AnnaBridge | 172:7d866c31b3c5 | 594 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 595 | * |
AnnaBridge | 172:7d866c31b3c5 | 596 | * @details This function is used to set USBD vendor request callback function |
AnnaBridge | 172:7d866c31b3c5 | 597 | */ |
AnnaBridge | 172:7d866c31b3c5 | 598 | void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq) |
AnnaBridge | 172:7d866c31b3c5 | 599 | { |
AnnaBridge | 172:7d866c31b3c5 | 600 | g_usbd_pfnVendorRequest = pfnVendorReq; |
AnnaBridge | 172:7d866c31b3c5 | 601 | } |
AnnaBridge | 172:7d866c31b3c5 | 602 | |
AnnaBridge | 172:7d866c31b3c5 | 603 | /** |
AnnaBridge | 172:7d866c31b3c5 | 604 | * @brief The callback function which called when get SET CONFIGURATION request |
AnnaBridge | 172:7d866c31b3c5 | 605 | * |
AnnaBridge | 172:7d866c31b3c5 | 606 | * @param[in] pfnSetConfigCallback Callback function pointer for SET CONFIGURATION request |
AnnaBridge | 172:7d866c31b3c5 | 607 | * |
AnnaBridge | 172:7d866c31b3c5 | 608 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 609 | * |
AnnaBridge | 172:7d866c31b3c5 | 610 | * @details This function is used to set the callback function which will be called at SET CONFIGURATION request. |
AnnaBridge | 172:7d866c31b3c5 | 611 | */ |
AnnaBridge | 172:7d866c31b3c5 | 612 | void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback) |
AnnaBridge | 172:7d866c31b3c5 | 613 | { |
AnnaBridge | 172:7d866c31b3c5 | 614 | g_usbd_pfnSetConfigCallback = pfnSetConfigCallback; |
AnnaBridge | 172:7d866c31b3c5 | 615 | } |
AnnaBridge | 172:7d866c31b3c5 | 616 | |
AnnaBridge | 172:7d866c31b3c5 | 617 | |
AnnaBridge | 172:7d866c31b3c5 | 618 | /** |
AnnaBridge | 172:7d866c31b3c5 | 619 | * @brief EP stall lock function to avoid stall clear by USB SET FEATURE request. |
AnnaBridge | 172:7d866c31b3c5 | 620 | * |
AnnaBridge | 172:7d866c31b3c5 | 621 | * @param[in] u32EpBitmap Use bitmap to select which endpoints will be locked |
AnnaBridge | 172:7d866c31b3c5 | 622 | * |
AnnaBridge | 172:7d866c31b3c5 | 623 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 624 | * |
AnnaBridge | 172:7d866c31b3c5 | 625 | * @details This function is used to lock relative endpoint to avoid stall clear by SET FEATURE request. |
AnnaBridge | 172:7d866c31b3c5 | 626 | * If ep stall locked, user needs to reset USB device or re-configure device to clear it. |
AnnaBridge | 172:7d866c31b3c5 | 627 | */ |
AnnaBridge | 172:7d866c31b3c5 | 628 | void USBD_LockEpStall(uint32_t u32EpBitmap) |
AnnaBridge | 172:7d866c31b3c5 | 629 | { |
AnnaBridge | 172:7d866c31b3c5 | 630 | g_u32EpStallLock = u32EpBitmap; |
AnnaBridge | 172:7d866c31b3c5 | 631 | } |
AnnaBridge | 172:7d866c31b3c5 | 632 | |
AnnaBridge | 172:7d866c31b3c5 | 633 | |
AnnaBridge | 172:7d866c31b3c5 | 634 | /*@}*/ /* end of group M480_USBD_EXPORTED_FUNCTIONS */ |
AnnaBridge | 172:7d866c31b3c5 | 635 | |
AnnaBridge | 172:7d866c31b3c5 | 636 | /*@}*/ /* end of group M480_USBD_Driver */ |
AnnaBridge | 172:7d866c31b3c5 | 637 | |
AnnaBridge | 172:7d866c31b3c5 | 638 | /*@}*/ /* end of group M480_Device_Driver */ |
AnnaBridge | 172:7d866c31b3c5 | 639 | |
AnnaBridge | 172:7d866c31b3c5 | 640 | #ifdef __cplusplus |
AnnaBridge | 172:7d866c31b3c5 | 641 | } |
AnnaBridge | 172:7d866c31b3c5 | 642 | #endif |
AnnaBridge | 172:7d866c31b3c5 | 643 | |
AnnaBridge | 172:7d866c31b3c5 | 644 | /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ |