USBDevice with Nucleo 32L476RG support

Dependents:   ObCP_ENSMM_V2020_Test_Accelero

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?

UserRevisionLine numberNew 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 ) */