USBDevice with Nucleo 32L476RG support
Dependents: ObCP_ENSMM_V2020_Test_Accelero
targets/TARGET_Silicon_Labs/src/em_usbd.c@72:14a22343c610, 2020-09-30 (annotated)
- Committer:
- jimbaud
- Date:
- Wed Sep 30 11:26:16 2020 +0000
- Revision:
- 72:14a22343c610
- Parent:
- 71:53949e6131f6
USBDevice with Nucleo 32L476RG support
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Kojto | 71:53949e6131f6 | 1 | /**************************************************************************//** |
Kojto | 71:53949e6131f6 | 2 | * @file em_usbd.c |
Kojto | 71:53949e6131f6 | 3 | * @brief USB protocol stack library, device API. |
Kojto | 71:53949e6131f6 | 4 | * @version 3.20.14 |
Kojto | 71:53949e6131f6 | 5 | ****************************************************************************** |
Kojto | 71:53949e6131f6 | 6 | * @section License |
Kojto | 71:53949e6131f6 | 7 | * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b> |
Kojto | 71:53949e6131f6 | 8 | ******************************************************************************* |
Kojto | 71:53949e6131f6 | 9 | * |
Kojto | 71:53949e6131f6 | 10 | * Licensed under the Apache License, Version 2.0 (the "License"); |
Kojto | 71:53949e6131f6 | 11 | * you may not use this file except in compliance with the License. |
Kojto | 71:53949e6131f6 | 12 | * You may obtain a copy of the License at |
Kojto | 71:53949e6131f6 | 13 | * |
Kojto | 71:53949e6131f6 | 14 | * http://www.apache.org/licenses/LICENSE-2.0 |
Kojto | 71:53949e6131f6 | 15 | * |
Kojto | 71:53949e6131f6 | 16 | * Unless required by applicable law or agreed to in writing, software |
Kojto | 71:53949e6131f6 | 17 | * distributed under the License is distributed on an "AS IS" BASIS, |
Kojto | 71:53949e6131f6 | 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Kojto | 71:53949e6131f6 | 19 | * See the License for the specific language governing permissions and |
Kojto | 71:53949e6131f6 | 20 | * limitations under the License. |
Kojto | 71:53949e6131f6 | 21 | * |
Kojto | 71:53949e6131f6 | 22 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 23 | |
Kojto | 71:53949e6131f6 | 24 | #include "em_device.h" |
Kojto | 71:53949e6131f6 | 25 | #if defined( USB_PRESENT ) && ( USB_COUNT == 1 ) |
Kojto | 71:53949e6131f6 | 26 | #include "em_usb.h" |
Kojto | 71:53949e6131f6 | 27 | #if defined( USB_DEVICE ) |
Kojto | 71:53949e6131f6 | 28 | |
Kojto | 71:53949e6131f6 | 29 | #include "em_cmu.h" |
Kojto | 71:53949e6131f6 | 30 | #include "em_usbtypes.h" |
Kojto | 71:53949e6131f6 | 31 | #include "em_usbhal.h" |
Kojto | 71:53949e6131f6 | 32 | #include "em_usbd.h" |
Kojto | 71:53949e6131f6 | 33 | |
Kojto | 71:53949e6131f6 | 34 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ |
Kojto | 71:53949e6131f6 | 35 | |
Kojto | 71:53949e6131f6 | 36 | static USBD_Device_TypeDef device; |
Kojto | 71:53949e6131f6 | 37 | USBD_Device_TypeDef *dev = &device; |
Kojto | 71:53949e6131f6 | 38 | |
Kojto | 71:53949e6131f6 | 39 | static uint32_t totalRxFifoSize = 0, totalTxFifoSize = 0; |
Kojto | 71:53949e6131f6 | 40 | static int numEps = 0; |
Kojto | 71:53949e6131f6 | 41 | static int txFifoNum = 1; |
Kojto | 71:53949e6131f6 | 42 | |
Kojto | 71:53949e6131f6 | 43 | static void USBD_ResetEndpoints(void); |
Kojto | 71:53949e6131f6 | 44 | extern USB_Status_TypeDef USBDHAL_ReconfigureFifos( uint32_t totalRxFifoSize, |
Kojto | 71:53949e6131f6 | 45 | uint32_t totalTxFifoSize ); |
Kojto | 71:53949e6131f6 | 46 | #ifndef __MBED__ |
Kojto | 71:53949e6131f6 | 47 | static const char *stateNames[] = |
Kojto | 71:53949e6131f6 | 48 | { |
Kojto | 71:53949e6131f6 | 49 | [ USBD_STATE_NONE ] = "NONE ", |
Kojto | 71:53949e6131f6 | 50 | [ USBD_STATE_ATTACHED ] = "ATTACHED ", |
Kojto | 71:53949e6131f6 | 51 | [ USBD_STATE_POWERED ] = "POWERED ", |
Kojto | 71:53949e6131f6 | 52 | [ USBD_STATE_DEFAULT ] = "DEFAULT ", |
Kojto | 71:53949e6131f6 | 53 | [ USBD_STATE_ADDRESSED ] = "ADDRESSED ", |
Kojto | 71:53949e6131f6 | 54 | [ USBD_STATE_CONFIGURED ] = "CONFIGURED", |
Kojto | 71:53949e6131f6 | 55 | [ USBD_STATE_SUSPENDED ] = "SUSPENDED ", |
Kojto | 71:53949e6131f6 | 56 | [ USBD_STATE_LASTMARKER ] = "UNDEFINED " |
Kojto | 71:53949e6131f6 | 57 | }; |
Kojto | 71:53949e6131f6 | 58 | #endif |
Kojto | 71:53949e6131f6 | 59 | |
Kojto | 71:53949e6131f6 | 60 | /** @endcond */ |
Kojto | 71:53949e6131f6 | 61 | |
Kojto | 71:53949e6131f6 | 62 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 63 | * @brief |
Kojto | 71:53949e6131f6 | 64 | * Abort all pending transfers. |
Kojto | 71:53949e6131f6 | 65 | * |
Kojto | 71:53949e6131f6 | 66 | * @details |
Kojto | 71:53949e6131f6 | 67 | * Aborts transfers for all endpoints currently in use. Pending |
Kojto | 71:53949e6131f6 | 68 | * transfers on the default endpoint (EP0) are not aborted. |
Kojto | 71:53949e6131f6 | 69 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 70 | void USBD_AbortAllTransfers( void ) |
Kojto | 71:53949e6131f6 | 71 | { |
Kojto | 71:53949e6131f6 | 72 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 73 | USBDHAL_AbortAllTransfers( USB_STATUS_EP_ABORTED ); |
Kojto | 71:53949e6131f6 | 74 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 75 | } |
Kojto | 71:53949e6131f6 | 76 | |
Kojto | 71:53949e6131f6 | 77 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 78 | * @brief |
Kojto | 71:53949e6131f6 | 79 | * Abort a pending transfer on a specific endpoint. |
Kojto | 71:53949e6131f6 | 80 | * |
Kojto | 71:53949e6131f6 | 81 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 82 | * The address of the endpoint to abort. |
Kojto | 71:53949e6131f6 | 83 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 84 | int USBD_AbortTransfer( int epAddr ) |
Kojto | 71:53949e6131f6 | 85 | { |
Kojto | 71:53949e6131f6 | 86 | USB_XferCompleteCb_TypeDef callback; |
Kojto | 71:53949e6131f6 | 87 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 88 | |
Kojto | 71:53949e6131f6 | 89 | if ( ep == NULL ) |
Kojto | 71:53949e6131f6 | 90 | { |
Kojto | 71:53949e6131f6 | 91 | DEBUG_USB_API_PUTS( "\nUSBD_AbortTransfer(), Illegal endpoint" ); |
Kojto | 71:53949e6131f6 | 92 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 93 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 94 | } |
Kojto | 71:53949e6131f6 | 95 | |
Kojto | 71:53949e6131f6 | 96 | if ( ep->num == 0 ) |
Kojto | 71:53949e6131f6 | 97 | { |
Kojto | 71:53949e6131f6 | 98 | DEBUG_USB_API_PUTS( "\nUSBD_AbortTransfer(), Illegal endpoint" ); |
Kojto | 71:53949e6131f6 | 99 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 100 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 101 | } |
Kojto | 71:53949e6131f6 | 102 | |
Kojto | 71:53949e6131f6 | 103 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 104 | if ( ep->state == D_EP_IDLE ) |
Kojto | 71:53949e6131f6 | 105 | { |
Kojto | 71:53949e6131f6 | 106 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 107 | return USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 108 | } |
Kojto | 71:53949e6131f6 | 109 | |
Kojto | 71:53949e6131f6 | 110 | USBD_AbortEp( ep ); |
Kojto | 71:53949e6131f6 | 111 | |
Kojto | 71:53949e6131f6 | 112 | ep->state = D_EP_IDLE; |
Kojto | 71:53949e6131f6 | 113 | if ( ep->xferCompleteCb ) |
Kojto | 71:53949e6131f6 | 114 | { |
Kojto | 71:53949e6131f6 | 115 | callback = ep->xferCompleteCb; |
Kojto | 71:53949e6131f6 | 116 | ep->xferCompleteCb = NULL; |
Kojto | 71:53949e6131f6 | 117 | |
Kojto | 71:53949e6131f6 | 118 | if ( ( dev->lastState == USBD_STATE_CONFIGURED ) && |
Kojto | 71:53949e6131f6 | 119 | ( dev->state == USBD_STATE_ADDRESSED ) ) |
Kojto | 71:53949e6131f6 | 120 | { |
Kojto | 71:53949e6131f6 | 121 | USBDHAL_DeactivateEp( ep ); |
Kojto | 71:53949e6131f6 | 122 | } |
Kojto | 71:53949e6131f6 | 123 | |
Kojto | 71:53949e6131f6 | 124 | DEBUG_TRACE_ABORT( USB_STATUS_EP_ABORTED ); |
Kojto | 71:53949e6131f6 | 125 | callback( USB_STATUS_EP_ABORTED, ep->xferred, ep->remaining ); |
Kojto | 71:53949e6131f6 | 126 | } |
Kojto | 71:53949e6131f6 | 127 | |
Kojto | 71:53949e6131f6 | 128 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 129 | return USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 130 | } |
Kojto | 71:53949e6131f6 | 131 | |
Kojto | 71:53949e6131f6 | 132 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 133 | * @brief |
Kojto | 71:53949e6131f6 | 134 | * Start USB device operation. |
Kojto | 71:53949e6131f6 | 135 | * |
Kojto | 71:53949e6131f6 | 136 | * @details |
Kojto | 71:53949e6131f6 | 137 | * Device operation is started by connecting a pullup resistor on the |
Kojto | 71:53949e6131f6 | 138 | * appropriate USB data line. |
Kojto | 71:53949e6131f6 | 139 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 140 | void USBD_Connect( void ) |
Kojto | 71:53949e6131f6 | 141 | { |
Kojto | 71:53949e6131f6 | 142 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 143 | USBDHAL_Connect(); |
Kojto | 71:53949e6131f6 | 144 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 145 | } |
Kojto | 71:53949e6131f6 | 146 | |
Kojto | 71:53949e6131f6 | 147 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 148 | * @brief |
Kojto | 71:53949e6131f6 | 149 | * Stop USB device operation. |
Kojto | 71:53949e6131f6 | 150 | * |
Kojto | 71:53949e6131f6 | 151 | * @details |
Kojto | 71:53949e6131f6 | 152 | * Device operation is stopped by disconnecting the pullup resistor from the |
Kojto | 71:53949e6131f6 | 153 | * appropriate USB data line. Often referred to as a "soft" disconnect. |
Kojto | 71:53949e6131f6 | 154 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 155 | void USBD_Disconnect( void ) |
Kojto | 71:53949e6131f6 | 156 | { |
Kojto | 71:53949e6131f6 | 157 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 158 | USBDHAL_Disconnect(); |
Kojto | 71:53949e6131f6 | 159 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 160 | } |
Kojto | 71:53949e6131f6 | 161 | |
Kojto | 71:53949e6131f6 | 162 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 163 | * @brief |
Kojto | 71:53949e6131f6 | 164 | * Check if an endpoint is busy doing a transfer. |
Kojto | 71:53949e6131f6 | 165 | * |
Kojto | 71:53949e6131f6 | 166 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 167 | * The address of the endpoint to check. |
Kojto | 71:53949e6131f6 | 168 | * |
Kojto | 71:53949e6131f6 | 169 | * @return |
Kojto | 71:53949e6131f6 | 170 | * True if endpoint is busy, false otherwise. |
Kojto | 71:53949e6131f6 | 171 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 172 | bool USBD_EpIsBusy( int epAddr ) |
Kojto | 71:53949e6131f6 | 173 | { |
Kojto | 71:53949e6131f6 | 174 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 175 | |
Kojto | 71:53949e6131f6 | 176 | if ( ep == NULL ) |
Kojto | 71:53949e6131f6 | 177 | { |
Kojto | 71:53949e6131f6 | 178 | DEBUG_USB_API_PUTS( "\nUSBD_EpIsBusy(), Illegal endpoint" ); |
Kojto | 71:53949e6131f6 | 179 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 180 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 181 | } |
Kojto | 71:53949e6131f6 | 182 | |
Kojto | 71:53949e6131f6 | 183 | if ( ep->state == D_EP_IDLE ) |
Kojto | 71:53949e6131f6 | 184 | return false; |
Kojto | 71:53949e6131f6 | 185 | |
Kojto | 71:53949e6131f6 | 186 | return true; |
Kojto | 71:53949e6131f6 | 187 | } |
Kojto | 71:53949e6131f6 | 188 | |
Kojto | 71:53949e6131f6 | 189 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 190 | * @brief |
Kojto | 71:53949e6131f6 | 191 | * Get current USB device state. |
Kojto | 71:53949e6131f6 | 192 | * |
Kojto | 71:53949e6131f6 | 193 | * @return |
Kojto | 71:53949e6131f6 | 194 | * Device USB state. See @ref USBD_State_TypeDef. |
Kojto | 71:53949e6131f6 | 195 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 196 | USBD_State_TypeDef USBD_GetUsbState( void ) |
Kojto | 71:53949e6131f6 | 197 | { |
Kojto | 71:53949e6131f6 | 198 | return dev->state; |
Kojto | 71:53949e6131f6 | 199 | } |
Kojto | 71:53949e6131f6 | 200 | |
Kojto | 71:53949e6131f6 | 201 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 202 | * @brief |
Kojto | 71:53949e6131f6 | 203 | * Get a string naming a device USB state. |
Kojto | 71:53949e6131f6 | 204 | * |
Kojto | 71:53949e6131f6 | 205 | * @param[in] state |
Kojto | 71:53949e6131f6 | 206 | * Device USB state. See @ref USBD_State_TypeDef. |
Kojto | 71:53949e6131f6 | 207 | * |
Kojto | 71:53949e6131f6 | 208 | * @return |
Kojto | 71:53949e6131f6 | 209 | * State name string pointer. |
Kojto | 71:53949e6131f6 | 210 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 211 | const char *USBD_GetUsbStateName( USBD_State_TypeDef state ) |
Kojto | 71:53949e6131f6 | 212 | { |
Kojto | 71:53949e6131f6 | 213 | if ( state > USBD_STATE_LASTMARKER ) |
Kojto | 71:53949e6131f6 | 214 | state = USBD_STATE_LASTMARKER; |
Kojto | 71:53949e6131f6 | 215 | |
Kojto | 71:53949e6131f6 | 216 | #ifndef __MBED__ |
Kojto | 71:53949e6131f6 | 217 | return stateNames[ state ]; |
Kojto | 71:53949e6131f6 | 218 | #else |
Kojto | 71:53949e6131f6 | 219 | return NULL; |
Kojto | 71:53949e6131f6 | 220 | #endif |
Kojto | 71:53949e6131f6 | 221 | } |
Kojto | 71:53949e6131f6 | 222 | |
Kojto | 71:53949e6131f6 | 223 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 224 | * @brief |
Kojto | 71:53949e6131f6 | 225 | * Initializes USB device hardware and internal protocol stack data structures, |
Kojto | 71:53949e6131f6 | 226 | * then connects the data-line (D+ or D-) pullup resistor to signal host that |
Kojto | 71:53949e6131f6 | 227 | * enumeration can begin. |
Kojto | 71:53949e6131f6 | 228 | * |
Kojto | 71:53949e6131f6 | 229 | * @note |
Kojto | 71:53949e6131f6 | 230 | * You may later use @ref USBD_Disconnect() and @ref USBD_Connect() to force |
Kojto | 71:53949e6131f6 | 231 | * reenumeration. |
Kojto | 71:53949e6131f6 | 232 | * |
Kojto | 71:53949e6131f6 | 233 | * @param[in] p |
Kojto | 71:53949e6131f6 | 234 | * Pointer to device initialization struct. See @ref USBD_Init_TypeDef. |
Kojto | 71:53949e6131f6 | 235 | * |
Kojto | 71:53949e6131f6 | 236 | * @return |
Kojto | 71:53949e6131f6 | 237 | * @ref USB_STATUS_OK on success, else an appropriate error code. |
Kojto | 71:53949e6131f6 | 238 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 239 | int USBD_Init( const USBD_Init_TypeDef *p ) |
Kojto | 71:53949e6131f6 | 240 | { |
Kojto | 71:53949e6131f6 | 241 | USBD_Ep_TypeDef *ep; |
Kojto | 71:53949e6131f6 | 242 | |
Kojto | 71:53949e6131f6 | 243 | #if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN ) |
Kojto | 71:53949e6131f6 | 244 | /* Devices supporting crystal-less USB can use HFRCO or HFXO as core clock. */ |
Kojto | 71:53949e6131f6 | 245 | /* All other devices must use HFXO as core clock. */ |
Kojto | 71:53949e6131f6 | 246 | if ( CMU_ClockSelectGet( cmuClock_HF ) != cmuSelect_HFXO ) |
Kojto | 71:53949e6131f6 | 247 | { |
Kojto | 71:53949e6131f6 | 248 | CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO ); |
Kojto | 71:53949e6131f6 | 249 | } |
Kojto | 71:53949e6131f6 | 250 | #endif |
Kojto | 71:53949e6131f6 | 251 | |
Kojto | 71:53949e6131f6 | 252 | #if !defined( CMU_OSCENCMD_USHFRCOEN ) |
Kojto | 71:53949e6131f6 | 253 | #if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO ) |
Kojto | 71:53949e6131f6 | 254 | CMU_OscillatorEnable(cmuOsc_LFXO, true, false); |
Kojto | 71:53949e6131f6 | 255 | #else |
Kojto | 71:53949e6131f6 | 256 | CMU_OscillatorEnable(cmuOsc_LFRCO, true, false); |
Kojto | 71:53949e6131f6 | 257 | #endif |
Kojto | 71:53949e6131f6 | 258 | |
Kojto | 71:53949e6131f6 | 259 | #else |
Kojto | 71:53949e6131f6 | 260 | CMU_ClockEnable(cmuClock_CORELE, true); |
Kojto | 71:53949e6131f6 | 261 | /* LFC clock is needed to detect USB suspend when LEMIDLE is activated. */ |
Kojto | 71:53949e6131f6 | 262 | #if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO ) |
Kojto | 71:53949e6131f6 | 263 | CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFXO); |
Kojto | 71:53949e6131f6 | 264 | #else |
Kojto | 71:53949e6131f6 | 265 | CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFRCO); |
Kojto | 71:53949e6131f6 | 266 | #endif |
Kojto | 71:53949e6131f6 | 267 | CMU_ClockEnable(cmuClock_USBLE, true); |
Kojto | 71:53949e6131f6 | 268 | #endif |
Kojto | 71:53949e6131f6 | 269 | |
Kojto | 71:53949e6131f6 | 270 | USBTIMER_Init(); |
Kojto | 71:53949e6131f6 | 271 | |
Kojto | 71:53949e6131f6 | 272 | memset( dev, 0, sizeof( USBD_Device_TypeDef ) ); |
Kojto | 71:53949e6131f6 | 273 | |
Kojto | 71:53949e6131f6 | 274 | dev->setup = dev->setupPkt; |
Kojto | 71:53949e6131f6 | 275 | dev->state = USBD_STATE_LASTMARKER; |
Kojto | 71:53949e6131f6 | 276 | dev->savedState = USBD_STATE_NONE; |
Kojto | 71:53949e6131f6 | 277 | dev->lastState = USBD_STATE_NONE; |
Kojto | 71:53949e6131f6 | 278 | dev->callbacks = p->callbacks; |
Kojto | 71:53949e6131f6 | 279 | dev->remoteWakeupEnabled = false; |
Kojto | 71:53949e6131f6 | 280 | |
Kojto | 71:53949e6131f6 | 281 | /* Initialize EP0 */ |
Kojto | 71:53949e6131f6 | 282 | |
Kojto | 71:53949e6131f6 | 283 | ep = &dev->ep[ 0 ]; |
Kojto | 71:53949e6131f6 | 284 | ep->in = false; |
Kojto | 71:53949e6131f6 | 285 | ep->buf = NULL; |
Kojto | 71:53949e6131f6 | 286 | ep->num = 0; |
Kojto | 71:53949e6131f6 | 287 | ep->mask = 1; |
Kojto | 71:53949e6131f6 | 288 | ep->addr = 0; |
Kojto | 71:53949e6131f6 | 289 | ep->type = USB_EPTYPE_CTRL; |
Kojto | 71:53949e6131f6 | 290 | ep->txFifoNum = 0; |
Kojto | 71:53949e6131f6 | 291 | |
Kojto | 71:53949e6131f6 | 292 | /* FIXME! */ |
Kojto | 71:53949e6131f6 | 293 | ep->packetSize = 64; |
Kojto | 71:53949e6131f6 | 294 | dev->ep0MpsCode = _USB_DOEP0CTL_MPS_64B; |
Kojto | 71:53949e6131f6 | 295 | |
Kojto | 71:53949e6131f6 | 296 | ep->remaining = 0; |
Kojto | 71:53949e6131f6 | 297 | ep->xferred = 0; |
Kojto | 71:53949e6131f6 | 298 | ep->state = D_EP_IDLE; |
Kojto | 71:53949e6131f6 | 299 | ep->xferCompleteCb = NULL; |
Kojto | 71:53949e6131f6 | 300 | ep->fifoSize = ep->packetSize / 4; |
Kojto | 71:53949e6131f6 | 301 | |
Kojto | 71:53949e6131f6 | 302 | totalTxFifoSize = ep->fifoSize * p->bufferingMultiplier[ 0 ]; |
Kojto | 71:53949e6131f6 | 303 | totalRxFifoSize = (ep->fifoSize + 1) * p->bufferingMultiplier[ 0 ]; |
Kojto | 71:53949e6131f6 | 304 | |
Kojto | 71:53949e6131f6 | 305 | /* Rx-FIFO size: SETUP packets : 4*n + 6 n=#CTRL EP's |
Kojto | 71:53949e6131f6 | 306 | * GOTNAK : 1 |
Kojto | 71:53949e6131f6 | 307 | * Status info : 2*n n=#OUT EP's (EP0 included) in HW |
Kojto | 71:53949e6131f6 | 308 | */ |
Kojto | 71:53949e6131f6 | 309 | totalRxFifoSize += 10 + 1 + ( 2 * (MAX_NUM_OUT_EPS + 1) ); |
Kojto | 71:53949e6131f6 | 310 | |
Kojto | 71:53949e6131f6 | 311 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 312 | |
Kojto | 71:53949e6131f6 | 313 | /* Enable USB clock */ |
Kojto | 71:53949e6131f6 | 314 | CMU->HFCORECLKEN0 |= CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC; |
Kojto | 71:53949e6131f6 | 315 | |
Kojto | 71:53949e6131f6 | 316 | #if defined( CMU_OSCENCMD_USHFRCOEN ) |
Kojto | 71:53949e6131f6 | 317 | CMU->USHFRCOCONF = CMU_USHFRCOCONF_BAND_48MHZ; |
Kojto | 71:53949e6131f6 | 318 | CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_USHFRCO ); |
Kojto | 71:53949e6131f6 | 319 | |
Kojto | 71:53949e6131f6 | 320 | /* Enable USHFRCO Clock Recovery mode. */ |
Kojto | 71:53949e6131f6 | 321 | CMU->USBCRCTRL |= CMU_USBCRCTRL_EN; |
Kojto | 71:53949e6131f6 | 322 | |
Kojto | 71:53949e6131f6 | 323 | /* Turn on Low Energy Mode (LEM) features. */ |
Kojto | 71:53949e6131f6 | 324 | USB->CTRL = USB_CTRL_LEMOSCCTRL_GATE |
Kojto | 71:53949e6131f6 | 325 | | USB_CTRL_LEMIDLEEN |
Kojto | 71:53949e6131f6 | 326 | | USB_CTRL_LEMPHYCTRL; |
Kojto | 71:53949e6131f6 | 327 | #else |
Kojto | 71:53949e6131f6 | 328 | CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_HFCLK ); |
Kojto | 71:53949e6131f6 | 329 | #endif |
Kojto | 71:53949e6131f6 | 330 | |
Kojto | 71:53949e6131f6 | 331 | USBHAL_DisableGlobalInt(); |
Kojto | 71:53949e6131f6 | 332 | |
Kojto | 71:53949e6131f6 | 333 | if ( USBDHAL_CoreInit( totalRxFifoSize, totalTxFifoSize ) == USB_STATUS_OK ) |
Kojto | 71:53949e6131f6 | 334 | { |
Kojto | 71:53949e6131f6 | 335 | USBDHAL_EnableUsbResetAndSuspendInt(); |
Kojto | 71:53949e6131f6 | 336 | USBHAL_EnableGlobalInt(); |
Kojto | 71:53949e6131f6 | 337 | NVIC_ClearPendingIRQ( USB_IRQn ); |
Kojto | 71:53949e6131f6 | 338 | NVIC_EnableIRQ( USB_IRQn ); |
Kojto | 71:53949e6131f6 | 339 | } |
Kojto | 71:53949e6131f6 | 340 | else |
Kojto | 71:53949e6131f6 | 341 | { |
Kojto | 71:53949e6131f6 | 342 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 343 | DEBUG_USB_API_PUTS( "\nUSBD_Init(), FIFO setup error" ); |
Kojto | 71:53949e6131f6 | 344 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 345 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 346 | } |
Kojto | 71:53949e6131f6 | 347 | |
Kojto | 71:53949e6131f6 | 348 | #if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF ) |
Kojto | 71:53949e6131f6 | 349 | if ( USBHAL_VbusIsOn() ) |
Kojto | 71:53949e6131f6 | 350 | { |
Kojto | 71:53949e6131f6 | 351 | USBD_SetUsbState( USBD_STATE_POWERED ); |
Kojto | 71:53949e6131f6 | 352 | } |
Kojto | 71:53949e6131f6 | 353 | else |
Kojto | 71:53949e6131f6 | 354 | #endif |
Kojto | 71:53949e6131f6 | 355 | { |
Kojto | 71:53949e6131f6 | 356 | USBD_SetUsbState( USBD_STATE_NONE ); |
Kojto | 71:53949e6131f6 | 357 | } |
Kojto | 71:53949e6131f6 | 358 | |
Kojto | 71:53949e6131f6 | 359 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 360 | return USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 361 | } |
Kojto | 71:53949e6131f6 | 362 | |
Kojto | 71:53949e6131f6 | 363 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 364 | * @brief |
Kojto | 71:53949e6131f6 | 365 | * Start a read (OUT) transfer on an endpoint. |
Kojto | 71:53949e6131f6 | 366 | * |
Kojto | 71:53949e6131f6 | 367 | * @note |
Kojto | 71:53949e6131f6 | 368 | * The transfer buffer length must be a multiple of 4 bytes in length and |
Kojto | 71:53949e6131f6 | 369 | * WORD (4 byte) aligned. When allocating the buffer, round buffer length up. |
Kojto | 71:53949e6131f6 | 370 | * If it is possible that the host will send more data than your device |
Kojto | 71:53949e6131f6 | 371 | * expects, round buffer size up to the next multiple of maxpacket size. |
Kojto | 71:53949e6131f6 | 372 | * |
Kojto | 71:53949e6131f6 | 373 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 374 | * Endpoint address. |
Kojto | 71:53949e6131f6 | 375 | * |
Kojto | 71:53949e6131f6 | 376 | * @param[in] data |
Kojto | 71:53949e6131f6 | 377 | * Pointer to transfer data buffer. |
Kojto | 71:53949e6131f6 | 378 | * |
Kojto | 71:53949e6131f6 | 379 | * @param[in] byteCount |
Kojto | 71:53949e6131f6 | 380 | * Transfer length. |
Kojto | 71:53949e6131f6 | 381 | * |
Kojto | 71:53949e6131f6 | 382 | * @param[in] callback |
Kojto | 71:53949e6131f6 | 383 | * Function to be called on transfer completion. Supply NULL if no callback |
Kojto | 71:53949e6131f6 | 384 | * is needed. See @ref USB_XferCompleteCb_TypeDef. |
Kojto | 71:53949e6131f6 | 385 | * |
Kojto | 71:53949e6131f6 | 386 | * @return |
Kojto | 71:53949e6131f6 | 387 | * @ref USB_STATUS_OK on success, else an appropriate error code. |
Kojto | 71:53949e6131f6 | 388 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 389 | int USBD_Read( int epAddr, void *data, int byteCount, |
Kojto | 71:53949e6131f6 | 390 | USB_XferCompleteCb_TypeDef callback ) |
Kojto | 71:53949e6131f6 | 391 | { |
Kojto | 71:53949e6131f6 | 392 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 393 | |
Kojto | 71:53949e6131f6 | 394 | USB_PRINTF("USBD: Read addr %x, data %p, size %d, cb 0x%lx\n", |
Kojto | 71:53949e6131f6 | 395 | epAddr, data, byteCount, (uint32_t)callback); |
Kojto | 71:53949e6131f6 | 396 | |
Kojto | 71:53949e6131f6 | 397 | if ( ep == NULL ) |
Kojto | 71:53949e6131f6 | 398 | { |
Kojto | 71:53949e6131f6 | 399 | DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal endpoint" ); |
Kojto | 71:53949e6131f6 | 400 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 401 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 402 | } |
Kojto | 71:53949e6131f6 | 403 | |
Kojto | 71:53949e6131f6 | 404 | if ( ( byteCount > MAX_XFER_LEN ) || |
Kojto | 71:53949e6131f6 | 405 | ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER ) ) |
Kojto | 71:53949e6131f6 | 406 | { |
Kojto | 71:53949e6131f6 | 407 | DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal transfer size" ); |
Kojto | 71:53949e6131f6 | 408 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 409 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 410 | } |
Kojto | 71:53949e6131f6 | 411 | |
Kojto | 71:53949e6131f6 | 412 | if ( (uint32_t)data & 3 ) |
Kojto | 71:53949e6131f6 | 413 | { |
Kojto | 71:53949e6131f6 | 414 | DEBUG_USB_API_PUTS( "\nUSBD_Read(), Misaligned data buffer" ); |
Kojto | 71:53949e6131f6 | 415 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 416 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 417 | } |
Kojto | 71:53949e6131f6 | 418 | |
Kojto | 71:53949e6131f6 | 419 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 420 | if ( USBDHAL_EpIsStalled( ep ) ) |
Kojto | 71:53949e6131f6 | 421 | { |
Kojto | 71:53949e6131f6 | 422 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 423 | DEBUG_USB_API_PUTS( "\nUSBD_Read(), Endpoint is halted" ); |
Kojto | 71:53949e6131f6 | 424 | return USB_STATUS_EP_STALLED; |
Kojto | 71:53949e6131f6 | 425 | } |
Kojto | 71:53949e6131f6 | 426 | |
Kojto | 71:53949e6131f6 | 427 | if ( ep->state != D_EP_IDLE ) |
Kojto | 71:53949e6131f6 | 428 | { |
Kojto | 71:53949e6131f6 | 429 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 430 | DEBUG_USB_API_PUTS( "\nUSBD_Read(), Endpoint is busy" ); |
Kojto | 71:53949e6131f6 | 431 | return USB_STATUS_EP_BUSY; |
Kojto | 71:53949e6131f6 | 432 | } |
Kojto | 71:53949e6131f6 | 433 | |
Kojto | 71:53949e6131f6 | 434 | if ( ( ep->num > 0 ) && ( USBD_GetUsbState() != USBD_STATE_CONFIGURED ) ) |
Kojto | 71:53949e6131f6 | 435 | { |
Kojto | 71:53949e6131f6 | 436 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 437 | DEBUG_USB_API_PUTS( "\nUSBD_Read(), Device not configured" ); |
Kojto | 71:53949e6131f6 | 438 | return USB_STATUS_DEVICE_UNCONFIGURED; |
Kojto | 71:53949e6131f6 | 439 | } |
Kojto | 71:53949e6131f6 | 440 | |
Kojto | 71:53949e6131f6 | 441 | ep->buf = (uint8_t*)data; |
Kojto | 71:53949e6131f6 | 442 | ep->remaining = byteCount; |
Kojto | 71:53949e6131f6 | 443 | ep->xferred = 0; |
Kojto | 71:53949e6131f6 | 444 | |
Kojto | 71:53949e6131f6 | 445 | if ( ep->num == 0 ) |
Kojto | 71:53949e6131f6 | 446 | { |
Kojto | 71:53949e6131f6 | 447 | ep->in = false; |
Kojto | 71:53949e6131f6 | 448 | } |
Kojto | 71:53949e6131f6 | 449 | else if ( ep->in != false ) |
Kojto | 71:53949e6131f6 | 450 | { |
Kojto | 71:53949e6131f6 | 451 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 452 | DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal EP direction" ); |
Kojto | 71:53949e6131f6 | 453 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 454 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 455 | } |
Kojto | 71:53949e6131f6 | 456 | |
Kojto | 71:53949e6131f6 | 457 | ep->state = D_EP_RECEIVING; |
Kojto | 71:53949e6131f6 | 458 | ep->xferCompleteCb = callback; |
Kojto | 71:53949e6131f6 | 459 | |
Kojto | 71:53949e6131f6 | 460 | USBD_ArmEp( ep ); |
Kojto | 71:53949e6131f6 | 461 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 462 | return USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 463 | } |
Kojto | 71:53949e6131f6 | 464 | |
Kojto | 71:53949e6131f6 | 465 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 466 | * @brief |
Kojto | 71:53949e6131f6 | 467 | * Perform a remote wakeup signalling sequence. |
Kojto | 71:53949e6131f6 | 468 | * |
Kojto | 71:53949e6131f6 | 469 | * @note |
Kojto | 71:53949e6131f6 | 470 | * It is the responsibility of the application to ensure that remote wakeup |
Kojto | 71:53949e6131f6 | 471 | * is not attempted before the device has been suspended for at least 5 |
Kojto | 71:53949e6131f6 | 472 | * miliseconds. This function should not be called from within an interrupt |
Kojto | 71:53949e6131f6 | 473 | * handler. |
Kojto | 71:53949e6131f6 | 474 | * |
Kojto | 71:53949e6131f6 | 475 | * @return |
Kojto | 71:53949e6131f6 | 476 | * @ref USB_STATUS_OK on success, else an appropriate error code. |
Kojto | 71:53949e6131f6 | 477 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 478 | int USBD_RemoteWakeup( void ) |
Kojto | 71:53949e6131f6 | 479 | { |
Kojto | 71:53949e6131f6 | 480 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 481 | |
Kojto | 71:53949e6131f6 | 482 | if ( ( dev->state != USBD_STATE_SUSPENDED ) || |
Kojto | 71:53949e6131f6 | 483 | ( dev->remoteWakeupEnabled == false ) ) |
Kojto | 71:53949e6131f6 | 484 | { |
Kojto | 71:53949e6131f6 | 485 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 486 | DEBUG_USB_API_PUTS( "\nUSBD_RemoteWakeup(), Illegal remote wakeup" ); |
Kojto | 71:53949e6131f6 | 487 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 488 | } |
Kojto | 71:53949e6131f6 | 489 | |
Kojto | 71:53949e6131f6 | 490 | USBDHAL_SetRemoteWakeup(); |
Kojto | 71:53949e6131f6 | 491 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 492 | USBTIMER_DelayMs( 10 ); |
Kojto | 71:53949e6131f6 | 493 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 494 | USBDHAL_ClearRemoteWakeup(); |
Kojto | 71:53949e6131f6 | 495 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 496 | return USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 497 | } |
Kojto | 71:53949e6131f6 | 498 | |
Kojto | 71:53949e6131f6 | 499 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 500 | * @brief |
Kojto | 71:53949e6131f6 | 501 | * Check if it is ok to enter energy mode EM2. |
Kojto | 71:53949e6131f6 | 502 | * |
Kojto | 71:53949e6131f6 | 503 | * @note |
Kojto | 71:53949e6131f6 | 504 | * Before entering EM2 both the USB hardware and the USB stack must be in a |
Kojto | 71:53949e6131f6 | 505 | * certain state, this function checks if all conditions for entering EM2 |
Kojto | 71:53949e6131f6 | 506 | * is met. |
Kojto | 71:53949e6131f6 | 507 | * Refer to the @ref usb_device_powersave section for more information. |
Kojto | 71:53949e6131f6 | 508 | * |
Kojto | 71:53949e6131f6 | 509 | * @return |
Kojto | 71:53949e6131f6 | 510 | * True if ok to enter EM2, false otherwise. |
Kojto | 71:53949e6131f6 | 511 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 512 | bool USBD_SafeToEnterEM2( void ) |
Kojto | 71:53949e6131f6 | 513 | { |
Kojto | 71:53949e6131f6 | 514 | #if ( USB_PWRSAVE_MODE ) |
Kojto | 71:53949e6131f6 | 515 | return USBD_poweredDown ? true : false; |
Kojto | 71:53949e6131f6 | 516 | #else |
Kojto | 71:53949e6131f6 | 517 | return false; |
Kojto | 71:53949e6131f6 | 518 | #endif |
Kojto | 71:53949e6131f6 | 519 | } |
Kojto | 71:53949e6131f6 | 520 | |
Kojto | 71:53949e6131f6 | 521 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ |
Kojto | 71:53949e6131f6 | 522 | |
Kojto | 71:53949e6131f6 | 523 | void USBD_SetUsbState( USBD_State_TypeDef newState ) |
Kojto | 71:53949e6131f6 | 524 | { |
Kojto | 71:53949e6131f6 | 525 | USBD_State_TypeDef currentState; |
Kojto | 71:53949e6131f6 | 526 | |
Kojto | 71:53949e6131f6 | 527 | currentState = dev->state; |
Kojto | 71:53949e6131f6 | 528 | if ( newState == USBD_STATE_SUSPENDED ) |
Kojto | 71:53949e6131f6 | 529 | { |
Kojto | 71:53949e6131f6 | 530 | dev->savedState = currentState; |
Kojto | 71:53949e6131f6 | 531 | } |
Kojto | 71:53949e6131f6 | 532 | |
Kojto | 71:53949e6131f6 | 533 | dev->lastState = dev->state; |
Kojto | 71:53949e6131f6 | 534 | dev->state = newState; |
Kojto | 71:53949e6131f6 | 535 | |
Kojto | 71:53949e6131f6 | 536 | if ( ( dev->callbacks->usbStateChange ) && |
Kojto | 71:53949e6131f6 | 537 | ( currentState != newState ) ) |
Kojto | 71:53949e6131f6 | 538 | { |
Kojto | 71:53949e6131f6 | 539 | /* When we transition to a state "lower" than CONFIGURED |
Kojto | 71:53949e6131f6 | 540 | * we must reset the endpoint data |
Kojto | 71:53949e6131f6 | 541 | */ |
Kojto | 71:53949e6131f6 | 542 | if ( (dev->lastState == USBD_STATE_CONFIGURED || |
Kojto | 71:53949e6131f6 | 543 | dev->lastState == USBD_STATE_SUSPENDED ) && |
Kojto | 71:53949e6131f6 | 544 | dev->state < USBD_STATE_CONFIGURED ) |
Kojto | 71:53949e6131f6 | 545 | { |
Kojto | 71:53949e6131f6 | 546 | USBD_ResetEndpoints(); |
Kojto | 71:53949e6131f6 | 547 | } |
Kojto | 71:53949e6131f6 | 548 | |
Kojto | 71:53949e6131f6 | 549 | dev->callbacks->usbStateChange( currentState, newState ); |
Kojto | 71:53949e6131f6 | 550 | } |
Kojto | 71:53949e6131f6 | 551 | } |
Kojto | 71:53949e6131f6 | 552 | |
Kojto | 71:53949e6131f6 | 553 | /** @endcond */ |
Kojto | 71:53949e6131f6 | 554 | |
Kojto | 71:53949e6131f6 | 555 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 556 | * @brief |
Kojto | 71:53949e6131f6 | 557 | * Set an endpoint in the stalled (halted) state. |
Kojto | 71:53949e6131f6 | 558 | * |
Kojto | 71:53949e6131f6 | 559 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 560 | * The address of the endpoint to stall. |
Kojto | 71:53949e6131f6 | 561 | * |
Kojto | 71:53949e6131f6 | 562 | * @return |
Kojto | 71:53949e6131f6 | 563 | * @ref USB_STATUS_OK on success, else an appropriate error code. |
Kojto | 71:53949e6131f6 | 564 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 565 | int USBD_StallEp( int epAddr ) |
Kojto | 71:53949e6131f6 | 566 | { |
Kojto | 71:53949e6131f6 | 567 | USB_Status_TypeDef retVal; |
Kojto | 71:53949e6131f6 | 568 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 569 | |
Kojto | 71:53949e6131f6 | 570 | if ( ep == NULL ) |
Kojto | 71:53949e6131f6 | 571 | { |
Kojto | 71:53949e6131f6 | 572 | DEBUG_USB_API_PUTS( "\nUSBD_StallEp(), Illegal request" ); |
Kojto | 71:53949e6131f6 | 573 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 574 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 575 | } |
Kojto | 71:53949e6131f6 | 576 | |
Kojto | 71:53949e6131f6 | 577 | if ( ep->num == 0 ) |
Kojto | 71:53949e6131f6 | 578 | { |
Kojto | 71:53949e6131f6 | 579 | DEBUG_USB_API_PUTS( "\nUSBD_StallEp(), Illegal endpoint" ); |
Kojto | 71:53949e6131f6 | 580 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 581 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 582 | } |
Kojto | 71:53949e6131f6 | 583 | |
Kojto | 71:53949e6131f6 | 584 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 585 | retVal = USBDHAL_StallEp( ep ); |
Kojto | 71:53949e6131f6 | 586 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 587 | |
Kojto | 71:53949e6131f6 | 588 | if ( retVal != USB_STATUS_OK ) |
Kojto | 71:53949e6131f6 | 589 | { |
Kojto | 71:53949e6131f6 | 590 | retVal = USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 591 | } |
Kojto | 71:53949e6131f6 | 592 | |
Kojto | 71:53949e6131f6 | 593 | return retVal; |
Kojto | 71:53949e6131f6 | 594 | } |
Kojto | 71:53949e6131f6 | 595 | |
Kojto | 71:53949e6131f6 | 596 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 597 | * @brief |
Kojto | 71:53949e6131f6 | 598 | * Stop USB device stack operation. |
Kojto | 71:53949e6131f6 | 599 | * |
Kojto | 71:53949e6131f6 | 600 | * @details |
Kojto | 71:53949e6131f6 | 601 | * The data-line pullup resistor is turned off, USB interrupts are disabled, |
Kojto | 71:53949e6131f6 | 602 | * and finally the USB pins are disabled. |
Kojto | 71:53949e6131f6 | 603 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 604 | void USBD_Stop( void ) |
Kojto | 71:53949e6131f6 | 605 | { |
Kojto | 71:53949e6131f6 | 606 | USBD_Disconnect(); |
Kojto | 71:53949e6131f6 | 607 | NVIC_DisableIRQ( USB_IRQn ); |
Kojto | 71:53949e6131f6 | 608 | USBHAL_DisableGlobalInt(); |
Kojto | 71:53949e6131f6 | 609 | USBHAL_DisableUsbInt(); |
Kojto | 71:53949e6131f6 | 610 | USBHAL_DisablePhyPins(); |
Kojto | 71:53949e6131f6 | 611 | USBD_SetUsbState( USBD_STATE_NONE ); |
Kojto | 71:53949e6131f6 | 612 | /* Turn off USB clocks. */ |
Kojto | 71:53949e6131f6 | 613 | CMU->HFCORECLKEN0 &= ~(CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC); |
Kojto | 71:53949e6131f6 | 614 | } |
Kojto | 71:53949e6131f6 | 615 | |
Kojto | 71:53949e6131f6 | 616 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 617 | * @brief |
Kojto | 71:53949e6131f6 | 618 | * Reset stall state on a stalled (halted) endpoint. |
Kojto | 71:53949e6131f6 | 619 | * |
Kojto | 71:53949e6131f6 | 620 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 621 | * The address of the endpoint to un-stall. |
Kojto | 71:53949e6131f6 | 622 | * |
Kojto | 71:53949e6131f6 | 623 | * @return |
Kojto | 71:53949e6131f6 | 624 | * @ref USB_STATUS_OK on success, else an appropriate error code. |
Kojto | 71:53949e6131f6 | 625 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 626 | int USBD_UnStallEp( int epAddr ) |
Kojto | 71:53949e6131f6 | 627 | { |
Kojto | 71:53949e6131f6 | 628 | USB_Status_TypeDef retVal; |
Kojto | 71:53949e6131f6 | 629 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 630 | |
Kojto | 71:53949e6131f6 | 631 | if ( ep == NULL ) |
Kojto | 71:53949e6131f6 | 632 | { |
Kojto | 71:53949e6131f6 | 633 | DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal request" ); |
Kojto | 71:53949e6131f6 | 634 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 635 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 636 | } |
Kojto | 71:53949e6131f6 | 637 | |
Kojto | 71:53949e6131f6 | 638 | if ( ep->num == 0 ) |
Kojto | 71:53949e6131f6 | 639 | { |
Kojto | 71:53949e6131f6 | 640 | DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal endpoint" ); |
Kojto | 71:53949e6131f6 | 641 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 642 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 643 | } |
Kojto | 71:53949e6131f6 | 644 | |
Kojto | 71:53949e6131f6 | 645 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 646 | retVal = USBDHAL_UnStallEp( ep ); |
Kojto | 71:53949e6131f6 | 647 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 648 | |
Kojto | 71:53949e6131f6 | 649 | if ( retVal != USB_STATUS_OK ) |
Kojto | 71:53949e6131f6 | 650 | { |
Kojto | 71:53949e6131f6 | 651 | retVal = USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 652 | } |
Kojto | 71:53949e6131f6 | 653 | |
Kojto | 71:53949e6131f6 | 654 | return retVal; |
Kojto | 71:53949e6131f6 | 655 | } |
Kojto | 71:53949e6131f6 | 656 | |
Kojto | 71:53949e6131f6 | 657 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 658 | * @brief |
Kojto | 71:53949e6131f6 | 659 | * Start a write (IN) transfer on an endpoint. |
Kojto | 71:53949e6131f6 | 660 | * |
Kojto | 71:53949e6131f6 | 661 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 662 | * Endpoint address. |
Kojto | 71:53949e6131f6 | 663 | * |
Kojto | 71:53949e6131f6 | 664 | * @param[in] data |
Kojto | 71:53949e6131f6 | 665 | * Pointer to transfer data buffer. This buffer must be WORD (4 byte) aligned. |
Kojto | 71:53949e6131f6 | 666 | * |
Kojto | 71:53949e6131f6 | 667 | * @param[in] byteCount |
Kojto | 71:53949e6131f6 | 668 | * Transfer length. |
Kojto | 71:53949e6131f6 | 669 | * |
Kojto | 71:53949e6131f6 | 670 | * @param[in] callback |
Kojto | 71:53949e6131f6 | 671 | * Function to be called on transfer completion. Supply NULL if no callback |
Kojto | 71:53949e6131f6 | 672 | * is needed. See @ref USB_XferCompleteCb_TypeDef. |
Kojto | 71:53949e6131f6 | 673 | * |
Kojto | 71:53949e6131f6 | 674 | * @return |
Kojto | 71:53949e6131f6 | 675 | * @ref USB_STATUS_OK on success, else an appropriate error code. |
Kojto | 71:53949e6131f6 | 676 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 677 | int USBD_Write( int epAddr, void *data, int byteCount, |
Kojto | 71:53949e6131f6 | 678 | USB_XferCompleteCb_TypeDef callback ) |
Kojto | 71:53949e6131f6 | 679 | { |
Kojto | 71:53949e6131f6 | 680 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 681 | |
Kojto | 71:53949e6131f6 | 682 | USB_PRINTF("USBD: Write addr %x, data %p, size %d, cb 0x%lx\n", |
Kojto | 71:53949e6131f6 | 683 | epAddr, data, byteCount, (uint32_t)callback); |
Kojto | 71:53949e6131f6 | 684 | |
Kojto | 71:53949e6131f6 | 685 | if ( ep == NULL ) |
Kojto | 71:53949e6131f6 | 686 | { |
Kojto | 71:53949e6131f6 | 687 | DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal endpoint" ); |
Kojto | 71:53949e6131f6 | 688 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 689 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 690 | } |
Kojto | 71:53949e6131f6 | 691 | |
Kojto | 71:53949e6131f6 | 692 | if ( ( byteCount > MAX_XFER_LEN ) || |
Kojto | 71:53949e6131f6 | 693 | ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER ) ) |
Kojto | 71:53949e6131f6 | 694 | { |
Kojto | 71:53949e6131f6 | 695 | DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal transfer size" ); |
Kojto | 71:53949e6131f6 | 696 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 697 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 698 | } |
Kojto | 71:53949e6131f6 | 699 | |
Kojto | 71:53949e6131f6 | 700 | if ( (uint32_t)data & 3 ) |
Kojto | 71:53949e6131f6 | 701 | { |
Kojto | 71:53949e6131f6 | 702 | DEBUG_USB_API_PUTS( "\nUSBD_Write(), Misaligned data buffer" ); |
Kojto | 71:53949e6131f6 | 703 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 704 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 705 | } |
Kojto | 71:53949e6131f6 | 706 | |
Kojto | 71:53949e6131f6 | 707 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 708 | if ( USBDHAL_EpIsStalled( ep ) ) |
Kojto | 71:53949e6131f6 | 709 | { |
Kojto | 71:53949e6131f6 | 710 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 711 | DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is halted" ); |
Kojto | 71:53949e6131f6 | 712 | return USB_STATUS_EP_STALLED; |
Kojto | 71:53949e6131f6 | 713 | } |
Kojto | 71:53949e6131f6 | 714 | |
Kojto | 71:53949e6131f6 | 715 | if ( ep->state != D_EP_IDLE ) |
Kojto | 71:53949e6131f6 | 716 | { |
Kojto | 71:53949e6131f6 | 717 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 718 | DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is busy" ); |
Kojto | 71:53949e6131f6 | 719 | return USB_STATUS_EP_BUSY; |
Kojto | 71:53949e6131f6 | 720 | } |
Kojto | 71:53949e6131f6 | 721 | |
Kojto | 71:53949e6131f6 | 722 | if ( ( ep->num > 0 ) && ( USBD_GetUsbState() != USBD_STATE_CONFIGURED ) ) |
Kojto | 71:53949e6131f6 | 723 | { |
Kojto | 71:53949e6131f6 | 724 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 725 | DEBUG_USB_API_PUTS( "\nUSBD_Write(), Device not configured" ); |
Kojto | 71:53949e6131f6 | 726 | return USB_STATUS_DEVICE_UNCONFIGURED; |
Kojto | 71:53949e6131f6 | 727 | } |
Kojto | 71:53949e6131f6 | 728 | |
Kojto | 71:53949e6131f6 | 729 | ep->buf = (uint8_t*)data; |
Kojto | 71:53949e6131f6 | 730 | ep->remaining = byteCount; |
Kojto | 71:53949e6131f6 | 731 | ep->xferred = 0; |
Kojto | 71:53949e6131f6 | 732 | |
Kojto | 71:53949e6131f6 | 733 | if ( ep->num == 0 ) |
Kojto | 71:53949e6131f6 | 734 | { |
Kojto | 71:53949e6131f6 | 735 | ep->in = true; |
Kojto | 71:53949e6131f6 | 736 | } |
Kojto | 71:53949e6131f6 | 737 | else if ( ep->in != true ) |
Kojto | 71:53949e6131f6 | 738 | { |
Kojto | 71:53949e6131f6 | 739 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 740 | DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal EP direction" ); |
Kojto | 71:53949e6131f6 | 741 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 742 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 743 | } |
Kojto | 71:53949e6131f6 | 744 | |
Kojto | 71:53949e6131f6 | 745 | ep->state = D_EP_TRANSMITTING; |
Kojto | 71:53949e6131f6 | 746 | ep->xferCompleteCb = callback; |
Kojto | 71:53949e6131f6 | 747 | |
Kojto | 71:53949e6131f6 | 748 | USBD_ArmEp( ep ); |
Kojto | 71:53949e6131f6 | 749 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 750 | return USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 751 | } |
Kojto | 71:53949e6131f6 | 752 | |
Kojto | 71:53949e6131f6 | 753 | int USBD_SetAddress(uint8_t addr) |
Kojto | 71:53949e6131f6 | 754 | { |
Kojto | 71:53949e6131f6 | 755 | int retVal = USB_STATUS_REQ_ERR; |
Kojto | 71:53949e6131f6 | 756 | |
Kojto | 71:53949e6131f6 | 757 | if ( dev->state == USBD_STATE_DEFAULT ) |
Kojto | 71:53949e6131f6 | 758 | { |
Kojto | 71:53949e6131f6 | 759 | if ( addr != 0 ) |
Kojto | 71:53949e6131f6 | 760 | { |
Kojto | 71:53949e6131f6 | 761 | USBD_SetUsbState( USBD_STATE_ADDRESSED ); |
Kojto | 71:53949e6131f6 | 762 | } |
Kojto | 71:53949e6131f6 | 763 | USBDHAL_SetAddr( addr ); |
Kojto | 71:53949e6131f6 | 764 | retVal = USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 765 | } |
Kojto | 71:53949e6131f6 | 766 | else if ( dev->state == USBD_STATE_ADDRESSED ) |
Kojto | 71:53949e6131f6 | 767 | { |
Kojto | 71:53949e6131f6 | 768 | if ( addr == 0 ) |
Kojto | 71:53949e6131f6 | 769 | { |
Kojto | 71:53949e6131f6 | 770 | USBD_SetUsbState( USBD_STATE_DEFAULT ); |
Kojto | 71:53949e6131f6 | 771 | } |
Kojto | 71:53949e6131f6 | 772 | USBDHAL_SetAddr( addr ); |
Kojto | 71:53949e6131f6 | 773 | retVal = USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 774 | } |
Kojto | 71:53949e6131f6 | 775 | |
Kojto | 71:53949e6131f6 | 776 | return retVal; |
Kojto | 71:53949e6131f6 | 777 | } |
Kojto | 71:53949e6131f6 | 778 | |
Kojto | 71:53949e6131f6 | 779 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 780 | * @brief |
Kojto | 71:53949e6131f6 | 781 | * Query the stall state of an endpoint |
Kojto | 71:53949e6131f6 | 782 | * |
Kojto | 71:53949e6131f6 | 783 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 784 | * The address of the endpoint to query. |
Kojto | 71:53949e6131f6 | 785 | * |
Kojto | 71:53949e6131f6 | 786 | * @return |
Kojto | 71:53949e6131f6 | 787 | * True if endpoint is stalled, false otherwise |
Kojto | 71:53949e6131f6 | 788 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 789 | int USBD_EpIsStalled(int epAddr) |
Kojto | 71:53949e6131f6 | 790 | { |
Kojto | 71:53949e6131f6 | 791 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 792 | |
Kojto | 71:53949e6131f6 | 793 | if( !ep ) |
Kojto | 71:53949e6131f6 | 794 | { |
Kojto | 71:53949e6131f6 | 795 | return false; |
Kojto | 71:53949e6131f6 | 796 | } |
Kojto | 71:53949e6131f6 | 797 | |
Kojto | 71:53949e6131f6 | 798 | return USBDHAL_EpIsStalled(ep); |
Kojto | 71:53949e6131f6 | 799 | } |
Kojto | 71:53949e6131f6 | 800 | |
Kojto | 71:53949e6131f6 | 801 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 802 | * @brief |
Kojto | 71:53949e6131f6 | 803 | * Reset (remove) all client endpoints |
Kojto | 71:53949e6131f6 | 804 | * |
Kojto | 71:53949e6131f6 | 805 | * @details |
Kojto | 71:53949e6131f6 | 806 | * Removes client endpoints, and resets the RX/TX fifos. No endpoints |
Kojto | 71:53949e6131f6 | 807 | * other than EP0 can be used until added with @ref USBD_AddEndpoint. |
Kojto | 71:53949e6131f6 | 808 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 809 | static void USBD_ResetEndpoints(void) |
Kojto | 71:53949e6131f6 | 810 | { |
Kojto | 71:53949e6131f6 | 811 | USBD_Ep_TypeDef *ep = &dev->ep[0]; |
Kojto | 71:53949e6131f6 | 812 | |
Kojto | 71:53949e6131f6 | 813 | numEps = 0; |
Kojto | 71:53949e6131f6 | 814 | txFifoNum = 1; |
Kojto | 71:53949e6131f6 | 815 | |
Kojto | 71:53949e6131f6 | 816 | totalTxFifoSize = ep->fifoSize * 1; |
Kojto | 71:53949e6131f6 | 817 | totalRxFifoSize = (ep->fifoSize + 1) * 1; |
Kojto | 71:53949e6131f6 | 818 | totalRxFifoSize += 10 + 1 + ( 2 * (MAX_NUM_OUT_EPS + 1) ); |
Kojto | 71:53949e6131f6 | 819 | } |
Kojto | 71:53949e6131f6 | 820 | |
Kojto | 71:53949e6131f6 | 821 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 822 | * @brief |
Kojto | 71:53949e6131f6 | 823 | * Add a new endpoint |
Kojto | 71:53949e6131f6 | 824 | * |
Kojto | 71:53949e6131f6 | 825 | * @param[in] epAddr |
Kojto | 71:53949e6131f6 | 826 | * Endpoint address |
Kojto | 71:53949e6131f6 | 827 | * |
Kojto | 71:53949e6131f6 | 828 | * @param[in] transferType |
Kojto | 71:53949e6131f6 | 829 | * Endpoint type, one of @ref USB_EPTYPE_BULK, @ref USB_EPTYPE_INTR or |
Kojto | 71:53949e6131f6 | 830 | * @ref USB_EPTYPE_ISOC. |
Kojto | 71:53949e6131f6 | 831 | * |
Kojto | 71:53949e6131f6 | 832 | * @param[in] maxPacketSize |
Kojto | 71:53949e6131f6 | 833 | * Maximum packet size of the new endpoint, in bytes |
Kojto | 71:53949e6131f6 | 834 | * |
Kojto | 71:53949e6131f6 | 835 | * @param[in] bufferMult |
Kojto | 71:53949e6131f6 | 836 | * FIFO buffer size multiplier |
Kojto | 71:53949e6131f6 | 837 | * |
Kojto | 71:53949e6131f6 | 838 | * @return |
Kojto | 71:53949e6131f6 | 839 | * @ref USB_STATUS_OK on success, else an appropriate error code. |
Kojto | 71:53949e6131f6 | 840 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 841 | int USBD_AddEndpoint(int epAddr, int transferType, |
Kojto | 71:53949e6131f6 | 842 | int maxPacketSize, int bufferMult) |
Kojto | 71:53949e6131f6 | 843 | { |
Kojto | 71:53949e6131f6 | 844 | USBD_Ep_TypeDef *ep; |
Kojto | 71:53949e6131f6 | 845 | |
Kojto | 71:53949e6131f6 | 846 | numEps++; |
Kojto | 71:53949e6131f6 | 847 | |
Kojto | 71:53949e6131f6 | 848 | ep = &dev->ep[ numEps ]; |
Kojto | 71:53949e6131f6 | 849 | ep->in = ( epAddr & USB_SETUP_DIR_MASK ) != 0; |
Kojto | 71:53949e6131f6 | 850 | ep->buf = NULL; |
Kojto | 71:53949e6131f6 | 851 | ep->addr = epAddr; |
Kojto | 71:53949e6131f6 | 852 | ep->num = ep->addr & USB_EPNUM_MASK; |
Kojto | 71:53949e6131f6 | 853 | ep->mask = 1 << ep->num; |
Kojto | 71:53949e6131f6 | 854 | ep->type = transferType; |
Kojto | 71:53949e6131f6 | 855 | ep->packetSize = maxPacketSize; |
Kojto | 71:53949e6131f6 | 856 | ep->remaining = 0; |
Kojto | 71:53949e6131f6 | 857 | ep->xferred = 0; |
Kojto | 71:53949e6131f6 | 858 | ep->state = D_EP_IDLE; |
Kojto | 71:53949e6131f6 | 859 | ep->xferCompleteCb = NULL; |
Kojto | 71:53949e6131f6 | 860 | |
Kojto | 71:53949e6131f6 | 861 | if ( ep->in ) |
Kojto | 71:53949e6131f6 | 862 | { |
Kojto | 71:53949e6131f6 | 863 | ep->txFifoNum = txFifoNum++; |
Kojto | 71:53949e6131f6 | 864 | ep->fifoSize = ( ( ep->packetSize + 3 ) / 4 ) * bufferMult; |
Kojto | 71:53949e6131f6 | 865 | dev->inEpAddr2EpIndex[ ep->num ] = numEps; |
Kojto | 71:53949e6131f6 | 866 | totalTxFifoSize += ep->fifoSize; |
Kojto | 71:53949e6131f6 | 867 | |
Kojto | 71:53949e6131f6 | 868 | if ( ep->num > MAX_NUM_IN_EPS ) |
Kojto | 71:53949e6131f6 | 869 | { |
Kojto | 71:53949e6131f6 | 870 | DEBUG_USB_API_PUTS( "\nUSBD_AddEndpoint(), Illegal IN EP address" ); |
Kojto | 71:53949e6131f6 | 871 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 872 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 873 | } |
Kojto | 71:53949e6131f6 | 874 | } |
Kojto | 71:53949e6131f6 | 875 | else |
Kojto | 71:53949e6131f6 | 876 | { |
Kojto | 71:53949e6131f6 | 877 | ep->fifoSize = ( ( ( ep->packetSize + 3 ) / 4 ) + 1 ) * bufferMult; |
Kojto | 71:53949e6131f6 | 878 | dev->outEpAddr2EpIndex[ ep->num ] = numEps; |
Kojto | 71:53949e6131f6 | 879 | totalRxFifoSize += ep->fifoSize; |
Kojto | 71:53949e6131f6 | 880 | |
Kojto | 71:53949e6131f6 | 881 | if ( ep->num > MAX_NUM_OUT_EPS ) |
Kojto | 71:53949e6131f6 | 882 | { |
Kojto | 71:53949e6131f6 | 883 | DEBUG_USB_API_PUTS( "\nUSBD_AddEndpoint(), Illegal OUT EP address" ); |
Kojto | 71:53949e6131f6 | 884 | EFM_ASSERT( false ); |
Kojto | 71:53949e6131f6 | 885 | return USB_STATUS_ILLEGAL; |
Kojto | 71:53949e6131f6 | 886 | } |
Kojto | 71:53949e6131f6 | 887 | } |
Kojto | 71:53949e6131f6 | 888 | |
Kojto | 71:53949e6131f6 | 889 | USB_PRINTF("USBD: Added endpoint %d to slot %d, in %d, addr 0x%x, type %d, ps %d, fifo %ld (total tx %ld, rx %ld)\n", |
Kojto | 71:53949e6131f6 | 890 | ep->num, numEps, ep->in, ep->addr, ep->type, ep->packetSize, ep->fifoSize, |
Kojto | 71:53949e6131f6 | 891 | totalTxFifoSize, totalRxFifoSize); |
Kojto | 71:53949e6131f6 | 892 | |
Kojto | 71:53949e6131f6 | 893 | INT_Disable(); |
Kojto | 71:53949e6131f6 | 894 | #if defined( CMU_OSCENCMD_USHFRCOEN ) |
Kojto | 71:53949e6131f6 | 895 | /* Happy Gecko workaround: disable LEM GATE mode if using ISOC endpoints. */ |
Kojto | 71:53949e6131f6 | 896 | if ( transferType == USB_EPTYPE_ISOC ) |
Kojto | 71:53949e6131f6 | 897 | { |
Kojto | 71:53949e6131f6 | 898 | USB->CTRL = (USB->CTRL & ~_USB_CTRL_LEMOSCCTRL_MASK) | USB_CTRL_LEMOSCCTRL_NONE; |
Kojto | 71:53949e6131f6 | 899 | } |
Kojto | 71:53949e6131f6 | 900 | #endif |
Kojto | 71:53949e6131f6 | 901 | |
Kojto | 71:53949e6131f6 | 902 | int ret = USBDHAL_ReconfigureFifos(totalRxFifoSize, totalTxFifoSize); |
Kojto | 71:53949e6131f6 | 903 | INT_Enable(); |
Kojto | 71:53949e6131f6 | 904 | |
Kojto | 71:53949e6131f6 | 905 | if( ret != USB_STATUS_OK ) { |
Kojto | 71:53949e6131f6 | 906 | return ret; |
Kojto | 71:53949e6131f6 | 907 | } |
Kojto | 71:53949e6131f6 | 908 | |
Kojto | 71:53949e6131f6 | 909 | USBDHAL_ActivateEp(ep, false); |
Kojto | 71:53949e6131f6 | 910 | |
Kojto | 71:53949e6131f6 | 911 | return USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 912 | } |
Kojto | 71:53949e6131f6 | 913 | |
Kojto | 71:53949e6131f6 | 914 | |
Kojto | 71:53949e6131f6 | 915 | /***************************************************************************//** |
Kojto | 71:53949e6131f6 | 916 | * @brief |
Kojto | 71:53949e6131f6 | 917 | * Set an endpoint0 in the stalled (halted) state. |
Kojto | 71:53949e6131f6 | 918 | * |
Kojto | 71:53949e6131f6 | 919 | * @details |
Kojto | 71:53949e6131f6 | 920 | * Temporarily stalls endpoint 0. Used to signal a failure to respond to |
Kojto | 71:53949e6131f6 | 921 | * the host's setup packet. |
Kojto | 71:53949e6131f6 | 922 | ******************************************************************************/ |
Kojto | 71:53949e6131f6 | 923 | void USBD_StallEp0() |
Kojto | 71:53949e6131f6 | 924 | { |
Kojto | 71:53949e6131f6 | 925 | int const epAddr = 0; |
Kojto | 71:53949e6131f6 | 926 | USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); |
Kojto | 71:53949e6131f6 | 927 | ep->in = true; |
Kojto | 71:53949e6131f6 | 928 | USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ |
Kojto | 71:53949e6131f6 | 929 | ep->in = false; /* OUT for next SETUP */ |
Kojto | 71:53949e6131f6 | 930 | USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ |
Kojto | 71:53949e6131f6 | 931 | #if !defined( USB_DOEP0INT_STUPPKTRCVD ) |
Kojto | 71:53949e6131f6 | 932 | USBDHAL_ReenableEp0Setup( dev ); /* Prepare for next SETUP pkt. */ |
Kojto | 71:53949e6131f6 | 933 | #else |
Kojto | 71:53949e6131f6 | 934 | USBDHAL_StartEp0Setup( dev ); |
Kojto | 71:53949e6131f6 | 935 | #endif |
Kojto | 71:53949e6131f6 | 936 | ep->state = D_EP_IDLE; |
Kojto | 71:53949e6131f6 | 937 | } |
Kojto | 71:53949e6131f6 | 938 | |
Kojto | 71:53949e6131f6 | 939 | /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************//** |
Kojto | 71:53949e6131f6 | 940 | * @{ |
Kojto | 71:53949e6131f6 | 941 | |
Kojto | 71:53949e6131f6 | 942 | @page usb_device USB device stack library |
Kojto | 71:53949e6131f6 | 943 | |
Kojto | 71:53949e6131f6 | 944 | The source files for the USB device stack resides in the usb directory |
Kojto | 71:53949e6131f6 | 945 | and follows the naming convention: em_usbd<em>nnn</em>.c/h. |
Kojto | 71:53949e6131f6 | 946 | |
Kojto | 71:53949e6131f6 | 947 | @li @ref usb_device_intro |
Kojto | 71:53949e6131f6 | 948 | @li @ref usb_device_api |
Kojto | 71:53949e6131f6 | 949 | @li @ref usb_device_conf |
Kojto | 71:53949e6131f6 | 950 | @li @ref usb_device_powersave |
Kojto | 71:53949e6131f6 | 951 | @li @ref usb_device_example1 |
Kojto | 71:53949e6131f6 | 952 | |
Kojto | 71:53949e6131f6 | 953 | |
Kojto | 71:53949e6131f6 | 954 | @n @section usb_device_intro Introduction |
Kojto | 71:53949e6131f6 | 955 | |
Kojto | 71:53949e6131f6 | 956 | The USB device protocol stack provides an API which makes it possible to |
Kojto | 71:53949e6131f6 | 957 | create USB devices with a minimum of effort. The device stack supports control, |
Kojto | 71:53949e6131f6 | 958 | bulk and interrupt transfers. |
Kojto | 71:53949e6131f6 | 959 | |
Kojto | 71:53949e6131f6 | 960 | The stack is highly configurable to suit various needs, it does also contain |
Kojto | 71:53949e6131f6 | 961 | useful debugging features together with several demonstration projects to |
Kojto | 71:53949e6131f6 | 962 | get you started fast. |
Kojto | 71:53949e6131f6 | 963 | |
Kojto | 71:53949e6131f6 | 964 | We recommend that you read through this documentation, then proceed to build |
Kojto | 71:53949e6131f6 | 965 | and test a few example projects before you start designing your own device. |
Kojto | 71:53949e6131f6 | 966 | |
Kojto | 71:53949e6131f6 | 967 | @n @section usb_device_api The device stack API |
Kojto | 71:53949e6131f6 | 968 | |
Kojto | 71:53949e6131f6 | 969 | This section contains brief descriptions of the functions in the API. You will |
Kojto | 71:53949e6131f6 | 970 | find detailed information on input and output parameters and return values by |
Kojto | 71:53949e6131f6 | 971 | clicking on the hyperlinked function names. It is also a good idea to study |
Kojto | 71:53949e6131f6 | 972 | the code in the USB demonstration projects. |
Kojto | 71:53949e6131f6 | 973 | |
Kojto | 71:53949e6131f6 | 974 | Your application code must include one header file: @em em_usb.h. |
Kojto | 71:53949e6131f6 | 975 | |
Kojto | 71:53949e6131f6 | 976 | All functions defined in the API can be called from within interrupt handlers. |
Kojto | 71:53949e6131f6 | 977 | |
Kojto | 71:53949e6131f6 | 978 | The USB stack use a hardware timer to keep track of time. TIMER0 is the |
Kojto | 71:53949e6131f6 | 979 | default choice, refer to @ref usb_device_conf for other possibilities. |
Kojto | 71:53949e6131f6 | 980 | Your application must not use the selected timer. |
Kojto | 71:53949e6131f6 | 981 | |
Kojto | 71:53949e6131f6 | 982 | <b>Pitfalls:</b>@n |
Kojto | 71:53949e6131f6 | 983 | The USB peripheral will fill your receive buffers in quantities of WORD's |
Kojto | 71:53949e6131f6 | 984 | (4 bytes). Transmit and receive buffers must be WORD aligned, in |
Kojto | 71:53949e6131f6 | 985 | addition when allocating storage for receive buffers, round size up to |
Kojto | 71:53949e6131f6 | 986 | next WORD boundary. If it is possible that the host will send more data |
Kojto | 71:53949e6131f6 | 987 | than your device expects, round buffer size up to the next multiple of |
Kojto | 71:53949e6131f6 | 988 | maxpacket size for the relevant endpoint to avoid data corruption. |
Kojto | 71:53949e6131f6 | 989 | |
Kojto | 71:53949e6131f6 | 990 | Transmit buffers passed to @htmlonly USBD_Write() @endhtmlonly must be |
Kojto | 71:53949e6131f6 | 991 | statically allocated because @htmlonly USBD_Write() @endhtmlonly only |
Kojto | 71:53949e6131f6 | 992 | initiates the transfer. When the host decide to actually perform the |
Kojto | 71:53949e6131f6 | 993 | transfer, your data must be available. |
Kojto | 71:53949e6131f6 | 994 | |
Kojto | 71:53949e6131f6 | 995 | @n @ref USBD_Init() @n |
Kojto | 71:53949e6131f6 | 996 | This function is called to register your device and all its properties with |
Kojto | 71:53949e6131f6 | 997 | the device stack. The application must fill in a @ref USBD_Init_TypeDef |
Kojto | 71:53949e6131f6 | 998 | structure prior to calling. Refer to @ref DeviceInitCallbacks for the |
Kojto | 71:53949e6131f6 | 999 | optional callback functions defined within this structure. When this |
Kojto | 71:53949e6131f6 | 1000 | function has been called your device is ready to be enumerated by the USB |
Kojto | 71:53949e6131f6 | 1001 | host. |
Kojto | 71:53949e6131f6 | 1002 | |
Kojto | 71:53949e6131f6 | 1003 | @ref USBD_Read(), @ref USBD_Write() @n |
Kojto | 71:53949e6131f6 | 1004 | These functions initiate data transfers. |
Kojto | 71:53949e6131f6 | 1005 | @n @htmlonly USBD_Read() @endhtmlonly initiate a transfer of data @em |
Kojto | 71:53949e6131f6 | 1006 | from host @em to device (an @em OUT transfer in USB terminology). |
Kojto | 71:53949e6131f6 | 1007 | @n @htmlonly USBD_Write() @endhtmlonly initiate a transfer of data @em from |
Kojto | 71:53949e6131f6 | 1008 | device @em to host (an @em IN transfer). |
Kojto | 71:53949e6131f6 | 1009 | |
Kojto | 71:53949e6131f6 | 1010 | When the USB host actually performs the transfer, your application will be |
Kojto | 71:53949e6131f6 | 1011 | notified by means of a callback function which you provide (optionally). |
Kojto | 71:53949e6131f6 | 1012 | Refer to @ref TransferCallback for details of the callback functionality. |
Kojto | 71:53949e6131f6 | 1013 | |
Kojto | 71:53949e6131f6 | 1014 | @ref USBD_AbortTransfer(), @ref USBD_AbortAllTransfers() @n |
Kojto | 71:53949e6131f6 | 1015 | These functions terminate transfers that are initiated, but has not yet |
Kojto | 71:53949e6131f6 | 1016 | taken place. If a transfer is initiated with @htmlonly USBD_Read() |
Kojto | 71:53949e6131f6 | 1017 | or USBD_Write(), @endhtmlonly but the USB host never actually peform |
Kojto | 71:53949e6131f6 | 1018 | the transfers, these functions will deactivate the transfer setup to make |
Kojto | 71:53949e6131f6 | 1019 | the USB device endpoint hardware ready for new (and potentially) different |
Kojto | 71:53949e6131f6 | 1020 | transfers. |
Kojto | 71:53949e6131f6 | 1021 | |
Kojto | 71:53949e6131f6 | 1022 | @ref USBD_Connect(), @ref USBD_Disconnect() @n |
Kojto | 71:53949e6131f6 | 1023 | These functions turns the data-line (D+ or D-) pullup on or off. They can be |
Kojto | 71:53949e6131f6 | 1024 | used to force reenumeration. It's good practice to delay at least one second |
Kojto | 71:53949e6131f6 | 1025 | between @htmlonly USBD_Disconnect() and USBD_Connect() @endhtmlonly |
Kojto | 71:53949e6131f6 | 1026 | to allow the USB host to unload the currently active device driver. |
Kojto | 71:53949e6131f6 | 1027 | |
Kojto | 71:53949e6131f6 | 1028 | @ref USBD_EpIsBusy() @n |
Kojto | 71:53949e6131f6 | 1029 | Check if an endpoint is busy. |
Kojto | 71:53949e6131f6 | 1030 | |
Kojto | 71:53949e6131f6 | 1031 | @ref USBD_StallEp(), @ref USBD_UnStallEp() @n |
Kojto | 71:53949e6131f6 | 1032 | These functions stalls or un-stalls an endpoint. This functionality may not |
Kojto | 71:53949e6131f6 | 1033 | be needed by your application, but the USB device stack use them in response |
Kojto | 71:53949e6131f6 | 1034 | to standard setup commands SET_FEATURE and CLEAR_FEATURE. They may be useful |
Kojto | 71:53949e6131f6 | 1035 | when implementing some USB classes, e.g. a mass storage device use them |
Kojto | 71:53949e6131f6 | 1036 | extensively. |
Kojto | 71:53949e6131f6 | 1037 | |
Kojto | 71:53949e6131f6 | 1038 | @ref USBD_RemoteWakeup() @n |
Kojto | 71:53949e6131f6 | 1039 | Used in SUSPENDED state (see @ref USB_Status_TypeDef) to signal resume to |
Kojto | 71:53949e6131f6 | 1040 | host. It's the applications responsibility to adhere to the USB standard |
Kojto | 71:53949e6131f6 | 1041 | which states that a device can not signal resume before it has been |
Kojto | 71:53949e6131f6 | 1042 | SUSPENDED for at least 5 ms. The function will also check the configuration |
Kojto | 71:53949e6131f6 | 1043 | descriptor defined by the application to see if it is legal for the device |
Kojto | 71:53949e6131f6 | 1044 | to signal resume. |
Kojto | 71:53949e6131f6 | 1045 | |
Kojto | 71:53949e6131f6 | 1046 | @ref USBD_GetUsbState() @n |
Kojto | 71:53949e6131f6 | 1047 | Returns the device USB state (see @ref USBD_State_TypeDef). Refer to |
Kojto | 71:53949e6131f6 | 1048 | Figure 9-1. "Device State Diagram" in the USB revision 2.0 specification. |
Kojto | 71:53949e6131f6 | 1049 | |
Kojto | 71:53949e6131f6 | 1050 | @ref USBD_GetUsbStateName() @n |
Kojto | 71:53949e6131f6 | 1051 | Returns a text string naming a given USB device state. |
Kojto | 71:53949e6131f6 | 1052 | |
Kojto | 71:53949e6131f6 | 1053 | @ref USBD_SafeToEnterEM2() @n |
Kojto | 71:53949e6131f6 | 1054 | Check if it is ok to enter energy mode EM2. Refer to the |
Kojto | 71:53949e6131f6 | 1055 | @ref usb_device_powersave section for more information. |
Kojto | 71:53949e6131f6 | 1056 | |
Kojto | 71:53949e6131f6 | 1057 | @n @anchor TransferCallback <b>The transfer complete callback function:</b> @n |
Kojto | 71:53949e6131f6 | 1058 | @n USB_XferCompleteCb_TypeDef() is called when a transfer completes. It is |
Kojto | 71:53949e6131f6 | 1059 | called with three parameters, the status of the transfer, the number of |
Kojto | 71:53949e6131f6 | 1060 | bytes transferred and the number of bytes remaining. It may not always be |
Kojto | 71:53949e6131f6 | 1061 | needed to have a callback on transfer completion, but you should keep in |
Kojto | 71:53949e6131f6 | 1062 | mind that a transfer may be aborted when you least expect it. A transfer |
Kojto | 71:53949e6131f6 | 1063 | will be aborted if host stalls the endpoint, if host resets your device, if |
Kojto | 71:53949e6131f6 | 1064 | host unconfigures your device or if you unplug your device cable and the |
Kojto | 71:53949e6131f6 | 1065 | device is selfpowered. |
Kojto | 71:53949e6131f6 | 1066 | @htmlonly USB_XferCompleteCb_TypeDef() @endhtmlonly is also called if your |
Kojto | 71:53949e6131f6 | 1067 | application use @htmlonly USBD_AbortTransfer() or USBD_AbortAllTransfers() |
Kojto | 71:53949e6131f6 | 1068 | @endhtmlonly calls. |
Kojto | 71:53949e6131f6 | 1069 | @note This callback is called from within an interrupt handler with |
Kojto | 71:53949e6131f6 | 1070 | interrupts disabled. |
Kojto | 71:53949e6131f6 | 1071 | |
Kojto | 71:53949e6131f6 | 1072 | @n @anchor DeviceInitCallbacks <b>Optional callbacks passed to the stack via |
Kojto | 71:53949e6131f6 | 1073 | the @ref USBD_Init() function:</b> @n |
Kojto | 71:53949e6131f6 | 1074 | @n These callbacks are all optional, and it is up to the application |
Kojto | 71:53949e6131f6 | 1075 | programmer to decide if the application needs the functionality they |
Kojto | 71:53949e6131f6 | 1076 | provide. |
Kojto | 71:53949e6131f6 | 1077 | @note These callbacks are all called from within an interrupt handler |
Kojto | 71:53949e6131f6 | 1078 | with interrupts disabled. |
Kojto | 71:53949e6131f6 | 1079 | |
Kojto | 71:53949e6131f6 | 1080 | USBD_UsbResetCb_TypeDef() is called each time reset signalling is sensed on |
Kojto | 71:53949e6131f6 | 1081 | the USB wire. |
Kojto | 71:53949e6131f6 | 1082 | |
Kojto | 71:53949e6131f6 | 1083 | @n USBD_SofIntCb_TypeDef() is called with framenumber as a parameter on |
Kojto | 71:53949e6131f6 | 1084 | each SOF interrupt. |
Kojto | 71:53949e6131f6 | 1085 | |
Kojto | 71:53949e6131f6 | 1086 | @n USBD_DeviceStateChangeCb_TypeDef() is called whenever the device state |
Kojto | 71:53949e6131f6 | 1087 | change. Useful for detecting e.g. SUSPENDED state change in order to reduce |
Kojto | 71:53949e6131f6 | 1088 | current consumption of buspowered devices. The USB HID keyboard example |
Kojto | 71:53949e6131f6 | 1089 | project has a good example on how to use this callback. |
Kojto | 71:53949e6131f6 | 1090 | |
Kojto | 71:53949e6131f6 | 1091 | @n USBD_IsSelfPoweredCb_TypeDef() is called by the device stack when host |
Kojto | 71:53949e6131f6 | 1092 | queries the device with a standard setup GET_STATUS command to check if the |
Kojto | 71:53949e6131f6 | 1093 | device is currently selfpowered or buspowered. This feature is only |
Kojto | 71:53949e6131f6 | 1094 | applicable on selfpowered devices which also works when only buspower is |
Kojto | 71:53949e6131f6 | 1095 | available. |
Kojto | 71:53949e6131f6 | 1096 | |
Kojto | 71:53949e6131f6 | 1097 | @n USBD_SetupCmdCb_TypeDef() is called each time a setup command is |
Kojto | 71:53949e6131f6 | 1098 | received from host. Use this callback to override or extend the default |
Kojto | 71:53949e6131f6 | 1099 | handling of standard setup commands, and to implement class or vendor |
Kojto | 71:53949e6131f6 | 1100 | specific setup commands. The USB HID keyboard example project has a good |
Kojto | 71:53949e6131f6 | 1101 | example on how to use this callback. |
Kojto | 71:53949e6131f6 | 1102 | |
Kojto | 71:53949e6131f6 | 1103 | @n <b>Utility functions:</b> @n |
Kojto | 71:53949e6131f6 | 1104 | @n USB_PUTCHAR() Transmit a single char on the debug serial port. |
Kojto | 71:53949e6131f6 | 1105 | @n @n USB_PUTS() Transmit a zero terminated string on the debug serial port. |
Kojto | 71:53949e6131f6 | 1106 | @n @n USB_PRINTF() Transmit "printf" formated data on the debug serial port. |
Kojto | 71:53949e6131f6 | 1107 | @n @n USB_GetErrorMsgString() Return an error message string for a given |
Kojto | 71:53949e6131f6 | 1108 | error code. |
Kojto | 71:53949e6131f6 | 1109 | @n @n USB_PrintErrorMsgString() Format and print a text string given an |
Kojto | 71:53949e6131f6 | 1110 | error code, prepends an optional user supplied leader string. |
Kojto | 71:53949e6131f6 | 1111 | @n @n USBTIMER_DelayMs() Active wait millisecond delay function. Can also be |
Kojto | 71:53949e6131f6 | 1112 | used inside interrupt handlers. |
Kojto | 71:53949e6131f6 | 1113 | @n @n USBTIMER_DelayUs() Active wait microsecond delay function. Can also be |
Kojto | 71:53949e6131f6 | 1114 | used inside interrupt handlers. |
Kojto | 71:53949e6131f6 | 1115 | @n @n USBTIMER_Init() Initialize the timer system. Called by @htmlonly |
Kojto | 71:53949e6131f6 | 1116 | USBD_Init(), @endhtmlonly but your application must call it again to |
Kojto | 71:53949e6131f6 | 1117 | reinitialize whenever you change the HFPERCLK frequency. |
Kojto | 71:53949e6131f6 | 1118 | @n @n USBTIMER_Start() Start a timer. You can configure the USB device stack |
Kojto | 71:53949e6131f6 | 1119 | to provide any number of timers. The timers have 1 ms resolution, your |
Kojto | 71:53949e6131f6 | 1120 | application is notified of timeout by means of a callback. |
Kojto | 71:53949e6131f6 | 1121 | @n @n USBTIMER_Stop() Stop a timer. |
Kojto | 71:53949e6131f6 | 1122 | |
Kojto | 71:53949e6131f6 | 1123 | @n @section usb_device_conf Configuring the device stack |
Kojto | 71:53949e6131f6 | 1124 | |
Kojto | 71:53949e6131f6 | 1125 | Your application must provide a header file named @em usbconfig.h. This file |
Kojto | 71:53949e6131f6 | 1126 | must contain the following \#define's:@n @n |
Kojto | 71:53949e6131f6 | 1127 | @verbatim |
Kojto | 71:53949e6131f6 | 1128 | #define USB_DEVICE // Compile the stack for device mode. |
Kojto | 71:53949e6131f6 | 1129 | #define NUM_EP_USED n // Your application use 'n' endpoints in |
Kojto | 71:53949e6131f6 | 1130 | // addition to endpoint 0. @endverbatim |
Kojto | 71:53949e6131f6 | 1131 | |
Kojto | 71:53949e6131f6 | 1132 | @n @em usbconfig.h may define the following items: @n @n |
Kojto | 71:53949e6131f6 | 1133 | @verbatim |
Kojto | 71:53949e6131f6 | 1134 | #define NUM_APP_TIMERS n // Your application needs 'n' timers |
Kojto | 71:53949e6131f6 | 1135 | |
Kojto | 71:53949e6131f6 | 1136 | #define DEBUG_USB_API // Turn on API debug diagnostics. |
Kojto | 71:53949e6131f6 | 1137 | |
Kojto | 71:53949e6131f6 | 1138 | // Some utility functions in the API needs printf. These |
Kojto | 71:53949e6131f6 | 1139 | // functions have "print" in their name. This macro enables |
Kojto | 71:53949e6131f6 | 1140 | // these functions. |
Kojto | 71:53949e6131f6 | 1141 | #define USB_USE_PRINTF // Enable utility print functions. |
Kojto | 71:53949e6131f6 | 1142 | |
Kojto | 71:53949e6131f6 | 1143 | // Define a function for transmitting a single char on the serial port. |
Kojto | 71:53949e6131f6 | 1144 | extern int RETARGET_WriteChar(char c); |
Kojto | 71:53949e6131f6 | 1145 | #define USER_PUTCHAR RETARGET_WriteChar |
Kojto | 71:53949e6131f6 | 1146 | |
Kojto | 71:53949e6131f6 | 1147 | #define USB_TIMER USB_TIMERn // Select which hardware timer the USB stack |
Kojto | 71:53949e6131f6 | 1148 | // is allowed to use. Valid values are n=0,1,2... |
Kojto | 71:53949e6131f6 | 1149 | // corresponding to TIMER0, TIMER1, ... |
Kojto | 71:53949e6131f6 | 1150 | // If not specified, TIMER0 is used |
Kojto | 71:53949e6131f6 | 1151 | |
Kojto | 71:53949e6131f6 | 1152 | #define USB_VBUS_SWITCH_NOT_PRESENT // Hardware does not have a VBUS switch |
Kojto | 71:53949e6131f6 | 1153 | |
Kojto | 71:53949e6131f6 | 1154 | #define USB_CORECLK_HFRCO // Devices supporting crystal-less USB can use |
Kojto | 71:53949e6131f6 | 1155 | // HFRCO as core clock, default is HFXO |
Kojto | 71:53949e6131f6 | 1156 | @endverbatim |
Kojto | 71:53949e6131f6 | 1157 | |
Kojto | 71:53949e6131f6 | 1158 | @n You are strongly encouraged to start application development with DEBUG_USB_API |
Kojto | 71:53949e6131f6 | 1159 | turned on. When DEBUG_USB_API is turned on and USER_PUTCHAR is defined, useful |
Kojto | 71:53949e6131f6 | 1160 | debugging information will be output on the development kit serial port. |
Kojto | 71:53949e6131f6 | 1161 | Compiling with the DEBUG_EFM_USER flag will also enable all asserts |
Kojto | 71:53949e6131f6 | 1162 | in both @em emlib and in the USB stack. If asserts are enabled and |
Kojto | 71:53949e6131f6 | 1163 | USER_PUTCHAR defined, assert texts will be output on the serial port. |
Kojto | 71:53949e6131f6 | 1164 | |
Kojto | 71:53949e6131f6 | 1165 | You application must include @em retargetserial.c if DEBUG_USB_API is defined |
Kojto | 71:53949e6131f6 | 1166 | and @em retargetio.c if USB_USE_PRINTF is defined. |
Kojto | 71:53949e6131f6 | 1167 | These files reside in the @em drivers |
Kojto | 71:53949e6131f6 | 1168 | directory in the software package for your development board. Refer to |
Kojto | 71:53949e6131f6 | 1169 | @ref usb_device_powersave for energy-saving mode configurations. |
Kojto | 71:53949e6131f6 | 1170 | |
Kojto | 71:53949e6131f6 | 1171 | @n @section usb_device_powersave Energy-saving modes |
Kojto | 71:53949e6131f6 | 1172 | |
Kojto | 71:53949e6131f6 | 1173 | The device stack provides two energy saving levels. The first level is to |
Kojto | 71:53949e6131f6 | 1174 | set the USB peripheral in energy saving mode, the next level is to enter |
Kojto | 71:53949e6131f6 | 1175 | Energy Mode 2 (EM2). These energy saving modes can be applied when the device |
Kojto | 71:53949e6131f6 | 1176 | is suspended by the USB host, or when when the device is not connected to a |
Kojto | 71:53949e6131f6 | 1177 | USB host. |
Kojto | 71:53949e6131f6 | 1178 | In addition to this an application can use energy modes EM1 and EM2. There |
Kojto | 71:53949e6131f6 | 1179 | are no restrictions on when EM1 can be entered, EM2 can only be entered |
Kojto | 71:53949e6131f6 | 1180 | when the USB device is suspended or detached from host. |
Kojto | 71:53949e6131f6 | 1181 | |
Kojto | 71:53949e6131f6 | 1182 | Energy-saving modes are selected with a \#define in @em usbconfig.h, default |
Kojto | 71:53949e6131f6 | 1183 | selection is to not use any energy saving modes.@n @n |
Kojto | 71:53949e6131f6 | 1184 | @verbatim |
Kojto | 71:53949e6131f6 | 1185 | #define USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ENTEREM2)@endverbatim |
Kojto | 71:53949e6131f6 | 1186 | |
Kojto | 71:53949e6131f6 | 1187 | There are three flags available, the flags can be or'ed together as shown above. |
Kojto | 71:53949e6131f6 | 1188 | |
Kojto | 71:53949e6131f6 | 1189 | <b>\#define USB_PWRSAVE_MODE_ONSUSPEND</b>@n Set USB peripheral in low power |
Kojto | 71:53949e6131f6 | 1190 | mode on suspend. |
Kojto | 71:53949e6131f6 | 1191 | |
Kojto | 71:53949e6131f6 | 1192 | <b>\#define USB_PWRSAVE_MODE_ONVBUSOFF</b>@n Set USB peripheral in low power |
Kojto | 71:53949e6131f6 | 1193 | mode when not attached to a host. This mode assumes that the internal voltage |
Kojto | 71:53949e6131f6 | 1194 | regulator is used and that the VREGI pin of the chip is connected to VBUS. |
Kojto | 71:53949e6131f6 | 1195 | This option can not be used with bus-powered devices. |
Kojto | 71:53949e6131f6 | 1196 | |
Kojto | 71:53949e6131f6 | 1197 | <b>\#define USB_PWRSAVE_MODE_ENTEREM2</b>@n Enter EM2 when USB peripheral is |
Kojto | 71:53949e6131f6 | 1198 | in low power mode. |
Kojto | 71:53949e6131f6 | 1199 | |
Kojto | 71:53949e6131f6 | 1200 | When the USB peripheral is set in low power mode, it must be clocked by a 32kHz |
Kojto | 71:53949e6131f6 | 1201 | clock. Both LFXO and LFRCO can be used, but only LFXO guarantee USB specification |
Kojto | 71:53949e6131f6 | 1202 | compliance. Selection is done with a \#define in @em usbconfig.h.@n @n |
Kojto | 71:53949e6131f6 | 1203 | @verbatim |
Kojto | 71:53949e6131f6 | 1204 | #define USB_USBC_32kHz_CLK USB_USBC_32kHz_CLK_LFXO @endverbatim |
Kojto | 71:53949e6131f6 | 1205 | Two flags are available, <b>USB_USBC_32kHz_CLK_LFXO</b> and |
Kojto | 71:53949e6131f6 | 1206 | <b>USB_USBC_32kHz_CLK_LFRCO</b>. <b>USB_USBC_32kHz_CLK_LFXO</b> is selected |
Kojto | 71:53949e6131f6 | 1207 | by default. |
Kojto | 71:53949e6131f6 | 1208 | |
Kojto | 71:53949e6131f6 | 1209 | The USB HID keyboard and Mass Storage device example projects demonstrate |
Kojto | 71:53949e6131f6 | 1210 | different energy-saving modes. |
Kojto | 71:53949e6131f6 | 1211 | |
Kojto | 71:53949e6131f6 | 1212 | <b>Example 1:</b> |
Kojto | 71:53949e6131f6 | 1213 | Leave all energy saving to the stack, the device enters EM2 on suspend and |
Kojto | 71:53949e6131f6 | 1214 | when detached from host. @n |
Kojto | 71:53949e6131f6 | 1215 | @verbatim |
Kojto | 71:53949e6131f6 | 1216 | In usbconfig.h: |
Kojto | 71:53949e6131f6 | 1217 | |
Kojto | 71:53949e6131f6 | 1218 | #define USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ONVBUSOFF | USB_PWRSAVE_MODE_ENTEREM2) |
Kojto | 71:53949e6131f6 | 1219 | @endverbatim |
Kojto | 71:53949e6131f6 | 1220 | |
Kojto | 71:53949e6131f6 | 1221 | @n <b>Example 2:</b> |
Kojto | 71:53949e6131f6 | 1222 | Let the stack control energy saving in the USB periheral but let your |
Kojto | 71:53949e6131f6 | 1223 | application control energy modes EM1 and EM2. @n |
Kojto | 71:53949e6131f6 | 1224 | @verbatim |
Kojto | 71:53949e6131f6 | 1225 | In usbconfig.h: |
Kojto | 71:53949e6131f6 | 1226 | |
Kojto | 71:53949e6131f6 | 1227 | #define USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ONVBUSOFF) |
Kojto | 71:53949e6131f6 | 1228 | |
Kojto | 71:53949e6131f6 | 1229 | In application code: |
Kojto | 71:53949e6131f6 | 1230 | |
Kojto | 71:53949e6131f6 | 1231 | if ( USBD_SafeToEnterEM2() ) |
Kojto | 71:53949e6131f6 | 1232 | EMU_EnterEM2(true); |
Kojto | 71:53949e6131f6 | 1233 | else |
Kojto | 71:53949e6131f6 | 1234 | EMU_EnterEM1(); @endverbatim |
Kojto | 71:53949e6131f6 | 1235 | |
Kojto | 71:53949e6131f6 | 1236 | @n @section usb_device_example1 Vendor unique device example application |
Kojto | 71:53949e6131f6 | 1237 | |
Kojto | 71:53949e6131f6 | 1238 | This example represents the most simple USB device imaginable. It's purpose |
Kojto | 71:53949e6131f6 | 1239 | is to turn user LED's on or off under control of vendor unique setup commands. |
Kojto | 71:53949e6131f6 | 1240 | The device will rely on @em libusb device driver on the host, a host |
Kojto | 71:53949e6131f6 | 1241 | application @em EFM32-LedApp.exe is bundled with the example. |
Kojto | 71:53949e6131f6 | 1242 | |
Kojto | 71:53949e6131f6 | 1243 | The main() is really simple ! @n @n |
Kojto | 71:53949e6131f6 | 1244 | @verbatim |
Kojto | 71:53949e6131f6 | 1245 | #include "em_usb.h" |
Kojto | 71:53949e6131f6 | 1246 | |
Kojto | 71:53949e6131f6 | 1247 | #include "descriptors.h" |
Kojto | 71:53949e6131f6 | 1248 | |
Kojto | 71:53949e6131f6 | 1249 | int main( void ) |
Kojto | 71:53949e6131f6 | 1250 | { |
Kojto | 71:53949e6131f6 | 1251 | BSP_Init(BSP_INIT_DEFAULT); // Initialize DK board register access |
Kojto | 71:53949e6131f6 | 1252 | CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO ); |
Kojto | 71:53949e6131f6 | 1253 | BSP_LedsSet(0); // Turn off all LED's |
Kojto | 71:53949e6131f6 | 1254 | |
Kojto | 71:53949e6131f6 | 1255 | ConsoleDebugInit(); // Initialize UART for debug diagnostics |
Kojto | 71:53949e6131f6 | 1256 | |
Kojto | 71:53949e6131f6 | 1257 | USB_PUTS( "\nEFM32 USB LED Vendor Unique Device example\n" ); |
Kojto | 71:53949e6131f6 | 1258 | |
Kojto | 71:53949e6131f6 | 1259 | USBD_Init( &initstruct ); // GO ! |
Kojto | 71:53949e6131f6 | 1260 | |
Kojto | 71:53949e6131f6 | 1261 | //When using a debugger it is pratical to uncomment the following three |
Kojto | 71:53949e6131f6 | 1262 | //lines to force host to re-enumerate the device. |
Kojto | 71:53949e6131f6 | 1263 | |
Kojto | 71:53949e6131f6 | 1264 | //USBD_Disconnect(); |
Kojto | 71:53949e6131f6 | 1265 | //USBTIMER_DelayMs( 1000 ); |
Kojto | 71:53949e6131f6 | 1266 | //USBD_Connect(); |
Kojto | 71:53949e6131f6 | 1267 | |
Kojto | 71:53949e6131f6 | 1268 | for (;;) {} |
Kojto | 71:53949e6131f6 | 1269 | } @endverbatim |
Kojto | 71:53949e6131f6 | 1270 | |
Kojto | 71:53949e6131f6 | 1271 | @n Configure the device stack in <em>usbconfig.h</em>: @n @n |
Kojto | 71:53949e6131f6 | 1272 | @verbatim |
Kojto | 71:53949e6131f6 | 1273 | #define USB_DEVICE // Compile stack for device mode. |
Kojto | 71:53949e6131f6 | 1274 | |
Kojto | 71:53949e6131f6 | 1275 | // ************************************************************************** |
Kojto | 71:53949e6131f6 | 1276 | ** ** |
Kojto | 71:53949e6131f6 | 1277 | ** Specify number of endpoints used (in addition to EP0). ** |
Kojto | 71:53949e6131f6 | 1278 | ** ** |
Kojto | 71:53949e6131f6 | 1279 | ***************************************************************************** |
Kojto | 71:53949e6131f6 | 1280 | #define NUM_EP_USED 0 // EP0 is the only endpoint used. |
Kojto | 71:53949e6131f6 | 1281 | |
Kojto | 71:53949e6131f6 | 1282 | // ************************************************************************** |
Kojto | 71:53949e6131f6 | 1283 | ** ** |
Kojto | 71:53949e6131f6 | 1284 | ** Configure serial port debug output. ** |
Kojto | 71:53949e6131f6 | 1285 | ** ** |
Kojto | 71:53949e6131f6 | 1286 | ***************************************************************************** |
Kojto | 71:53949e6131f6 | 1287 | // Prototype a function for transmitting a single char on the serial port. |
Kojto | 71:53949e6131f6 | 1288 | extern int RETARGET_WriteChar(char c); |
Kojto | 71:53949e6131f6 | 1289 | #define USER_PUTCHAR RETARGET_WriteChar |
Kojto | 71:53949e6131f6 | 1290 | |
Kojto | 71:53949e6131f6 | 1291 | // Enable debug diagnostics from API functions (illegal input params etc.) |
Kojto | 71:53949e6131f6 | 1292 | #define DEBUG_USB_API @endverbatim |
Kojto | 71:53949e6131f6 | 1293 | |
Kojto | 71:53949e6131f6 | 1294 | @n Define device properties and fill in USB initstruct in |
Kojto | 71:53949e6131f6 | 1295 | <em>descriptors.h</em>: @n @n |
Kojto | 71:53949e6131f6 | 1296 | @verbatim |
Kojto | 71:53949e6131f6 | 1297 | EFM32_ALIGN(4) |
Kojto | 71:53949e6131f6 | 1298 | static const USB_DeviceDescriptor_TypeDef deviceDesc __attribute__ ((aligned(4))) = |
Kojto | 71:53949e6131f6 | 1299 | { |
Kojto | 71:53949e6131f6 | 1300 | .bLength = USB_DEVICE_DESCSIZE, |
Kojto | 71:53949e6131f6 | 1301 | .bDescriptorType = USB_DEVICE_DESCRIPTOR, |
Kojto | 71:53949e6131f6 | 1302 | .bcdUSB = 0x0200, |
Kojto | 71:53949e6131f6 | 1303 | .bDeviceClass = 0xFF, |
Kojto | 71:53949e6131f6 | 1304 | .bDeviceSubClass = 0, |
Kojto | 71:53949e6131f6 | 1305 | .bDeviceProtocol = 0, |
Kojto | 71:53949e6131f6 | 1306 | .bMaxPacketSize0 = USB_FS_CTRL_EP_MAXSIZE, |
Kojto | 71:53949e6131f6 | 1307 | .idVendor = 0x10C4, |
Kojto | 71:53949e6131f6 | 1308 | .idProduct = 0x0001, |
Kojto | 71:53949e6131f6 | 1309 | .bcdDevice = 0x0000, |
Kojto | 71:53949e6131f6 | 1310 | .iManufacturer = 1, |
Kojto | 71:53949e6131f6 | 1311 | .iProduct = 2, |
Kojto | 71:53949e6131f6 | 1312 | .iSerialNumber = 3, |
Kojto | 71:53949e6131f6 | 1313 | .bNumConfigurations = 1 |
Kojto | 71:53949e6131f6 | 1314 | }; |
Kojto | 71:53949e6131f6 | 1315 | |
Kojto | 71:53949e6131f6 | 1316 | EFM32_ALIGN(4) |
Kojto | 71:53949e6131f6 | 1317 | static const uint8_t configDesc[] __attribute__ ((aligned(4)))= |
Kojto | 71:53949e6131f6 | 1318 | { |
Kojto | 71:53949e6131f6 | 1319 | // *** Configuration descriptor *** |
Kojto | 71:53949e6131f6 | 1320 | USB_CONFIG_DESCSIZE, // bLength |
Kojto | 71:53949e6131f6 | 1321 | USB_CONFIG_DESCRIPTOR, // bDescriptorType |
Kojto | 71:53949e6131f6 | 1322 | USB_CONFIG_DESCSIZE + // wTotalLength (LSB) |
Kojto | 71:53949e6131f6 | 1323 | USB_INTERFACE_DESCSIZE, |
Kojto | 71:53949e6131f6 | 1324 | (USB_CONFIG_DESCSIZE + // wTotalLength (MSB) |
Kojto | 71:53949e6131f6 | 1325 | USB_INTERFACE_DESCSIZE)>>8, |
Kojto | 71:53949e6131f6 | 1326 | 1, // bNumInterfaces |
Kojto | 71:53949e6131f6 | 1327 | 1, // bConfigurationValue |
Kojto | 71:53949e6131f6 | 1328 | 0, // iConfiguration |
Kojto | 71:53949e6131f6 | 1329 | CONFIG_DESC_BM_RESERVED_D7 | // bmAttrib: Self powered |
Kojto | 71:53949e6131f6 | 1330 | CONFIG_DESC_BM_SELFPOWERED, |
Kojto | 71:53949e6131f6 | 1331 | CONFIG_DESC_MAXPOWER_mA( 100 ), // bMaxPower: 100 mA |
Kojto | 71:53949e6131f6 | 1332 | |
Kojto | 71:53949e6131f6 | 1333 | // *** Interface descriptor *** |
Kojto | 71:53949e6131f6 | 1334 | USB_INTERFACE_DESCSIZE, // bLength |
Kojto | 71:53949e6131f6 | 1335 | USB_INTERFACE_DESCRIPTOR, // bDescriptorType |
Kojto | 71:53949e6131f6 | 1336 | 0, // bInterfaceNumber |
Kojto | 71:53949e6131f6 | 1337 | 0, // bAlternateSetting |
Kojto | 71:53949e6131f6 | 1338 | NUM_EP_USED, // bNumEndpoints |
Kojto | 71:53949e6131f6 | 1339 | 0xFF, // bInterfaceClass |
Kojto | 71:53949e6131f6 | 1340 | 0, // bInterfaceSubClass |
Kojto | 71:53949e6131f6 | 1341 | 0, // bInterfaceProtocol |
Kojto | 71:53949e6131f6 | 1342 | 0, // iInterface |
Kojto | 71:53949e6131f6 | 1343 | }; |
Kojto | 71:53949e6131f6 | 1344 | |
Kojto | 71:53949e6131f6 | 1345 | STATIC_CONST_STRING_DESC_LANGID( langID, 0x04, 0x09 ); |
Kojto | 71:53949e6131f6 | 1346 | STATIC_CONST_STRING_DESC( iManufacturer, 'E','n','e','r','g','y',' ', \ |
Kojto | 71:53949e6131f6 | 1347 | 'M','i','c','r','o',' ','A','S' ); |
Kojto | 71:53949e6131f6 | 1348 | STATIC_CONST_STRING_DESC( iProduct , 'V','e','n','d','o','r',' ', \ |
Kojto | 71:53949e6131f6 | 1349 | 'U','n','i','q','u','e',' ', \ |
Kojto | 71:53949e6131f6 | 1350 | 'L','E','D',' ', \ |
Kojto | 71:53949e6131f6 | 1351 | 'D','e','v','i','c','e' ); |
Kojto | 71:53949e6131f6 | 1352 | STATIC_CONST_STRING_DESC( iSerialNumber, '0','0','0','0','0','0', \ |
Kojto | 71:53949e6131f6 | 1353 | '0','0','1','2','3','4' ); |
Kojto | 71:53949e6131f6 | 1354 | |
Kojto | 71:53949e6131f6 | 1355 | static const void * const strings[] = |
Kojto | 71:53949e6131f6 | 1356 | { |
Kojto | 71:53949e6131f6 | 1357 | &langID, |
Kojto | 71:53949e6131f6 | 1358 | &iManufacturer, |
Kojto | 71:53949e6131f6 | 1359 | &iProduct, |
Kojto | 71:53949e6131f6 | 1360 | &iSerialNumber |
Kojto | 71:53949e6131f6 | 1361 | }; |
Kojto | 71:53949e6131f6 | 1362 | |
Kojto | 71:53949e6131f6 | 1363 | // Endpoint buffer sizes |
Kojto | 71:53949e6131f6 | 1364 | // 1 = single buffer, 2 = double buffering, 3 = tripple buffering ... |
Kojto | 71:53949e6131f6 | 1365 | static const uint8_t bufferingMultiplier[ NUM_EP_USED + 1 ] = { 1 }; |
Kojto | 71:53949e6131f6 | 1366 | |
Kojto | 71:53949e6131f6 | 1367 | static const USBD_Callbacks_TypeDef callbacks = |
Kojto | 71:53949e6131f6 | 1368 | { |
Kojto | 71:53949e6131f6 | 1369 | .usbReset = NULL, |
Kojto | 71:53949e6131f6 | 1370 | .usbStateChange = NULL, |
Kojto | 71:53949e6131f6 | 1371 | .setupCmd = SetupCmd, |
Kojto | 71:53949e6131f6 | 1372 | .isSelfPowered = NULL, |
Kojto | 71:53949e6131f6 | 1373 | .sofInt = NULL |
Kojto | 71:53949e6131f6 | 1374 | }; |
Kojto | 71:53949e6131f6 | 1375 | |
Kojto | 71:53949e6131f6 | 1376 | static const USBD_Init_TypeDef initstruct = |
Kojto | 71:53949e6131f6 | 1377 | { |
Kojto | 71:53949e6131f6 | 1378 | .deviceDescriptor = &deviceDesc, |
Kojto | 71:53949e6131f6 | 1379 | .configDescriptor = configDesc, |
Kojto | 71:53949e6131f6 | 1380 | .stringDescriptors = strings, |
Kojto | 71:53949e6131f6 | 1381 | .numberOfStrings = sizeof(strings)/sizeof(void*), |
Kojto | 71:53949e6131f6 | 1382 | .callbacks = &callbacks, |
Kojto | 71:53949e6131f6 | 1383 | .bufferingMultiplier = bufferingMultiplier |
Kojto | 71:53949e6131f6 | 1384 | }; @endverbatim |
Kojto | 71:53949e6131f6 | 1385 | |
Kojto | 71:53949e6131f6 | 1386 | @n Now we have to implement vendor unique USB setup commands to control the |
Kojto | 71:53949e6131f6 | 1387 | LED's (see callbacks variable above). Notice that the buffer variable below is |
Kojto | 71:53949e6131f6 | 1388 | statically allocated because @htmlonly USBD_Write() @endhtmlonly only |
Kojto | 71:53949e6131f6 | 1389 | initiates the transfer. When the host actually performs the transfer, the |
Kojto | 71:53949e6131f6 | 1390 | SetupCmd() function will have returned ! @n @n |
Kojto | 71:53949e6131f6 | 1391 | |
Kojto | 71:53949e6131f6 | 1392 | @verbatim |
Kojto | 71:53949e6131f6 | 1393 | #define VND_GET_LEDS 0x10 |
Kojto | 71:53949e6131f6 | 1394 | #define VND_SET_LED 0x11 |
Kojto | 71:53949e6131f6 | 1395 | |
Kojto | 71:53949e6131f6 | 1396 | static int SetupCmd( const USB_Setup_TypeDef *setup ) |
Kojto | 71:53949e6131f6 | 1397 | { |
Kojto | 71:53949e6131f6 | 1398 | int retVal; |
Kojto | 71:53949e6131f6 | 1399 | uint16_t leds; |
Kojto | 71:53949e6131f6 | 1400 | static uint32_t buffer; |
Kojto | 71:53949e6131f6 | 1401 | uint8_t *pBuffer = (uint8_t*)&buffer; |
Kojto | 71:53949e6131f6 | 1402 | |
Kojto | 71:53949e6131f6 | 1403 | retVal = USB_STATUS_REQ_UNHANDLED; |
Kojto | 71:53949e6131f6 | 1404 | |
Kojto | 71:53949e6131f6 | 1405 | if ( setup->Type == USB_SETUP_TYPE_VENDOR ) |
Kojto | 71:53949e6131f6 | 1406 | { |
Kojto | 71:53949e6131f6 | 1407 | switch ( setup->bRequest ) |
Kojto | 71:53949e6131f6 | 1408 | { |
Kojto | 71:53949e6131f6 | 1409 | case VND_GET_LEDS: |
Kojto | 71:53949e6131f6 | 1410 | // ******************** |
Kojto | 71:53949e6131f6 | 1411 | *pBuffer = BSP_LedsGet() & 0x1F; |
Kojto | 71:53949e6131f6 | 1412 | retVal = USBD_Write( 0, pBuffer, setup->wLength, NULL ); |
Kojto | 71:53949e6131f6 | 1413 | break; |
Kojto | 71:53949e6131f6 | 1414 | |
Kojto | 71:53949e6131f6 | 1415 | case VND_SET_LED: |
Kojto | 71:53949e6131f6 | 1416 | // ******************** |
Kojto | 71:53949e6131f6 | 1417 | leds = DVK_getLEDs() & 0x1F; |
Kojto | 71:53949e6131f6 | 1418 | if ( setup->wValue ) |
Kojto | 71:53949e6131f6 | 1419 | { |
Kojto | 71:53949e6131f6 | 1420 | leds |= LED0 << setup->wIndex; |
Kojto | 71:53949e6131f6 | 1421 | } |
Kojto | 71:53949e6131f6 | 1422 | else |
Kojto | 71:53949e6131f6 | 1423 | { |
Kojto | 71:53949e6131f6 | 1424 | leds &= ~( LED0 << setup->wIndex ); |
Kojto | 71:53949e6131f6 | 1425 | } |
Kojto | 71:53949e6131f6 | 1426 | BSP_LedsSet( leds ); |
Kojto | 71:53949e6131f6 | 1427 | retVal = USB_STATUS_OK; |
Kojto | 71:53949e6131f6 | 1428 | break; |
Kojto | 71:53949e6131f6 | 1429 | } |
Kojto | 71:53949e6131f6 | 1430 | } |
Kojto | 71:53949e6131f6 | 1431 | |
Kojto | 71:53949e6131f6 | 1432 | return retVal; |
Kojto | 71:53949e6131f6 | 1433 | }@endverbatim |
Kojto | 71:53949e6131f6 | 1434 | |
Kojto | 71:53949e6131f6 | 1435 | * @}**************************************************************************/ |
Kojto | 71:53949e6131f6 | 1436 | |
Kojto | 71:53949e6131f6 | 1437 | #endif /* defined( USB_DEVICE ) */ |
Kojto | 71:53949e6131f6 | 1438 | #endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */ |