USBDevice for STM support

Dependents:   Nucleo_Usb_JoyMouse Nucleo_usbmouse ELEC350_1-referral-2018-usb-hid USBJoystick_HelloWorld2_wip ... more

This library contains all mbed usb device library (mbed-os\features\unsupported\USBDevice).

Committer:
frq08711@LMECWL0871.LME.ST.COM
Date:
Thu Dec 15 17:40:59 2016 +0100
Revision:
1:2a3ae13b45ef
copy of git hub directory unsupported/USBDevice

Who changed what in which revision?

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