I changed one line of code in the file with path name: USBDeviceHT/targets/TARGET_Maxim

Fork of USBDeviceHT by Helmut Tschemernjak

Committer:
Helmut64
Date:
Mon Feb 05 10:22:57 2018 +0000
Revision:
0:a3ea811f80f2
Inital checkin after copied from mbed.

Who changed what in which revision?

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