mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
<>
Date:
Fri Oct 28 11:17:30 2016 +0100
Revision:
149:156823d33999
Child:
154:37f96f9d4de2
This updates the lib to the mbed lib v128

NOTE: This release includes a restructuring of the file and directory locations and thus some
include paths in your code may need updating accordingly.

Who changed what in which revision?

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