USBDevice for STM support
Dependents: DISCO-F429ZI_LCDTS_demo_richard
Fork of USBDEVICE by
USBDevice/TARGET_Silicon_Labs/src/em_usbd.c@6:5a6efd08d588, 2017-06-27 (annotated)
- Committer:
- pierrebizouard
- Date:
- Tue Jun 27 13:11:46 2017 +0000
- Revision:
- 6:5a6efd08d588
- Parent:
- 1:2a3ae13b45ef
fixup in definition
Who changed what in which revision?
User | Revision | Line number | New 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 ) */ |