A copy of the mbed USBDevice with USBSerial library

Dependents:   STM32L0_LoRa Smartage STM32L0_LoRa Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Sun Feb 24 14:52:33 2019 +0100
Revision:
8:961423d1da74
Parent:
0:a3ea811f80f2
Added sleep manager support to avoids sleeps while a USB CDC
connection is active

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Helmut64 0:a3ea811f80f2 1 /* Copyright 2015 Silicon Labs, http://www.silabs.com
Helmut64 0:a3ea811f80f2 2 *
Helmut64 0:a3ea811f80f2 3 * Licensed under the Apache License, Version 2.0 (the "License");
Helmut64 0:a3ea811f80f2 4 * you may not use this file except in compliance with the License.
Helmut64 0:a3ea811f80f2 5 * You may obtain a copy of the License at
Helmut64 0:a3ea811f80f2 6 *
Helmut64 0:a3ea811f80f2 7 * http://www.apache.org/licenses/LICENSE-2.0
Helmut64 0:a3ea811f80f2 8 *
Helmut64 0:a3ea811f80f2 9 * Unless required by applicable law or agreed to in writing, software
Helmut64 0:a3ea811f80f2 10 * distributed under the License is distributed on an "AS IS" BASIS,
Helmut64 0:a3ea811f80f2 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Helmut64 0:a3ea811f80f2 12 * See the License for the specific language governing permissions and
Helmut64 0:a3ea811f80f2 13 * limitations under the License.
Helmut64 0:a3ea811f80f2 14 */
Helmut64 0:a3ea811f80f2 15
Helmut64 0:a3ea811f80f2 16 #if defined TARGET_EFM32GG_STK3700 || \
Helmut64 0:a3ea811f80f2 17 defined TARGET_EFM32LG_STK3600 || \
Helmut64 0:a3ea811f80f2 18 defined TARGET_EFM32WG_STK3800 || \
Helmut64 0:a3ea811f80f2 19 defined TARGET_EFM32HG_STK3400
Helmut64 0:a3ea811f80f2 20
Helmut64 0:a3ea811f80f2 21 #include "USBHAL.h"
Helmut64 0:a3ea811f80f2 22 #include "em_usb.h"
Helmut64 0:a3ea811f80f2 23 #include "em_usbtypes.h"
Helmut64 0:a3ea811f80f2 24 #include "em_usbhal.h"
Helmut64 0:a3ea811f80f2 25 #include "em_usbd.h"
Helmut64 0:a3ea811f80f2 26 #include "mbed_sleep.h"
Helmut64 0:a3ea811f80f2 27
Helmut64 0:a3ea811f80f2 28 enum USBISRCommand {
Helmut64 0:a3ea811f80f2 29 CMD_HANDLED = 0,
Helmut64 0:a3ea811f80f2 30 CMD_EP0SETUP,
Helmut64 0:a3ea811f80f2 31 CMD_EP0IN,
Helmut64 0:a3ea811f80f2 32 CMD_EP0OUT,
Helmut64 0:a3ea811f80f2 33 CMD_EP_XFER_COMPLETED,
Helmut64 0:a3ea811f80f2 34 CMD_SOF,
Helmut64 0:a3ea811f80f2 35 CMD_BUSRESET,
Helmut64 0:a3ea811f80f2 36 CMD_SUSPEND_STATE_CHANGED,
Helmut64 0:a3ea811f80f2 37 CMD_ENUM_END_MARKER
Helmut64 0:a3ea811f80f2 38 };
Helmut64 0:a3ea811f80f2 39
Helmut64 0:a3ea811f80f2 40 enum IEPStatus {
Helmut64 0:a3ea811f80f2 41 NOT_CONFIGURED = 0,
Helmut64 0:a3ea811f80f2 42 IDLE = 1,
Helmut64 0:a3ea811f80f2 43 READ_PENDING = 2,
Helmut64 0:a3ea811f80f2 44 WRITE_PENDING = 3,
Helmut64 0:a3ea811f80f2 45 READ_COMPLETE = 4,
Helmut64 0:a3ea811f80f2 46 WRITE_COMPLETE = 5,
Helmut64 0:a3ea811f80f2 47 FAILED_INVALID = 6,
Helmut64 0:a3ea811f80f2 48 FAILED_STALLED = 7
Helmut64 0:a3ea811f80f2 49 };
Helmut64 0:a3ea811f80f2 50
Helmut64 0:a3ea811f80f2 51 typedef struct {
Helmut64 0:a3ea811f80f2 52 IEPStatus status;
Helmut64 0:a3ea811f80f2 53 uint32_t byte_count;
Helmut64 0:a3ea811f80f2 54 uint32_t max_packet;
Helmut64 0:a3ea811f80f2 55 USB_XferCompleteCb_TypeDef intern_cb;
Helmut64 0:a3ea811f80f2 56 uint8_t *data_buf;
Helmut64 0:a3ea811f80f2 57 } ep_state_t;
Helmut64 0:a3ea811f80f2 58
Helmut64 0:a3ea811f80f2 59 USBHAL * USBHAL::instance;
Helmut64 0:a3ea811f80f2 60 static uint8_t ep0setupdata[8];
Helmut64 0:a3ea811f80f2 61 static ep_state_t ep_state[NUMBER_OF_ENDPOINTS];
Helmut64 0:a3ea811f80f2 62 #ifdef USB_USE_DYNAMIC_MEMORY
Helmut64 0:a3ea811f80f2 63 static uint8_t ep0in_data_buf[MAX_PACKET_SIZE_EP0] __attribute__ ((aligned (4)));
Helmut64 0:a3ea811f80f2 64 static uint8_t ep0out_data_buf[MAX_PACKET_SIZE_EP0]; // FIXME: does this need to be this big?
Helmut64 0:a3ea811f80f2 65 #else
Helmut64 0:a3ea811f80f2 66 static uint8_t ep_data_buf[NUMBER_OF_ENDPOINTS][64] __attribute__ ((aligned (4)));
Helmut64 0:a3ea811f80f2 67 #endif
Helmut64 0:a3ea811f80f2 68
Helmut64 0:a3ea811f80f2 69 static void run_cmd(USBISRCommand cmd, uint32_t param);
Helmut64 0:a3ea811f80f2 70 static void (*isrptr)() = NULL;
Helmut64 0:a3ea811f80f2 71 static USBISRCommand usb_isrcmd = CMD_HANDLED;
Helmut64 0:a3ea811f80f2 72 static uint32_t usb_isrcmd_param = 0;
Helmut64 0:a3ea811f80f2 73
Helmut64 0:a3ea811f80f2 74 extern "C" void usbhal_allow_em2(bool allow_em2);
Helmut64 0:a3ea811f80f2 75
Helmut64 0:a3ea811f80f2 76 #ifdef DEBUG_USB_API
Helmut64 0:a3ea811f80f2 77 #define TRACE(fmt,...) printf("USB: %s: " fmt "\n", __func__, __VA_ARGS__);
Helmut64 0:a3ea811f80f2 78 #define TRACE_FUNC_IN printf("USB: > %s\n",__func__);
Helmut64 0:a3ea811f80f2 79 #define TRACE_FUNC_IN_P(fmt, ...) printf("USB: > %s: " fmt "\n", __func__, __VA_ARGS__);
Helmut64 0:a3ea811f80f2 80 #else
Helmut64 0:a3ea811f80f2 81 #define TRACE(fmt,...)
Helmut64 0:a3ea811f80f2 82 #define TRACE_FUNC_IN
Helmut64 0:a3ea811f80f2 83 #define TRACE_FUNC_IN_P(fmt, ...)
Helmut64 0:a3ea811f80f2 84 #endif
Helmut64 0:a3ea811f80f2 85
Helmut64 0:a3ea811f80f2 86 static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize);
Helmut64 0:a3ea811f80f2 87
Helmut64 0:a3ea811f80f2 88 static int usbhal_xfer_complete_cb(uint8_t epaddr, USB_Status_TypeDef status,
Helmut64 0:a3ea811f80f2 89 uint32_t xferred, uint32_t remaining);
Helmut64 0:a3ea811f80f2 90 static void usbhal_free_buffers(void);
Helmut64 0:a3ea811f80f2 91
Helmut64 0:a3ea811f80f2 92 /* Internal EP transfer complete callbacks */
Helmut64 0:a3ea811f80f2 93 #define EPCB(n) static int usbhal_xfer_complete_cb_##n(USB_Status_TypeDef status, \
Helmut64 0:a3ea811f80f2 94 uint32_t xferred, uint32_t remaining) { \
Helmut64 0:a3ea811f80f2 95 return usbhal_xfer_complete_cb(n, status, xferred, remaining); \
Helmut64 0:a3ea811f80f2 96 }
Helmut64 0:a3ea811f80f2 97 /* ------^ */
Helmut64 0:a3ea811f80f2 98 EPCB(EP0OUT)
Helmut64 0:a3ea811f80f2 99 EPCB(EP0IN)
Helmut64 0:a3ea811f80f2 100 EPCB(EP1OUT)
Helmut64 0:a3ea811f80f2 101 EPCB(EP1IN)
Helmut64 0:a3ea811f80f2 102 EPCB(EP2OUT)
Helmut64 0:a3ea811f80f2 103 EPCB(EP2IN)
Helmut64 0:a3ea811f80f2 104 EPCB(EP3OUT)
Helmut64 0:a3ea811f80f2 105 EPCB(EP3IN)
Helmut64 0:a3ea811f80f2 106 #ifndef TARGET_EFM32HG_STK3400
Helmut64 0:a3ea811f80f2 107 EPCB(EP4OUT)
Helmut64 0:a3ea811f80f2 108 EPCB(EP4IN)
Helmut64 0:a3ea811f80f2 109 EPCB(EP5OUT)
Helmut64 0:a3ea811f80f2 110 EPCB(EP5IN)
Helmut64 0:a3ea811f80f2 111 EPCB(EP6OUT)
Helmut64 0:a3ea811f80f2 112 EPCB(EP6IN)
Helmut64 0:a3ea811f80f2 113 #endif
Helmut64 0:a3ea811f80f2 114
Helmut64 0:a3ea811f80f2 115 static inline bool is_aligned(const void *pointer, size_t byte_count)
Helmut64 0:a3ea811f80f2 116 {
Helmut64 0:a3ea811f80f2 117 return ((uintptr_t)pointer % byte_count == 0);
Helmut64 0:a3ea811f80f2 118 }
Helmut64 0:a3ea811f80f2 119
Helmut64 0:a3ea811f80f2 120 USBHAL::USBHAL(void)
Helmut64 0:a3ea811f80f2 121 {
Helmut64 0:a3ea811f80f2 122 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 123
Helmut64 0:a3ea811f80f2 124 isrptr = &USBHAL::_usbisr;
Helmut64 0:a3ea811f80f2 125
Helmut64 0:a3ea811f80f2 126 if (instance) {
Helmut64 0:a3ea811f80f2 127 TRACE("Assert self failed! instance=%p", instance);
Helmut64 0:a3ea811f80f2 128 abort();
Helmut64 0:a3ea811f80f2 129 }
Helmut64 0:a3ea811f80f2 130 instance = this;
Helmut64 0:a3ea811f80f2 131
Helmut64 0:a3ea811f80f2 132 // When USB is active, we can't go below EM1. This block may
Helmut64 0:a3ea811f80f2 133 // be dynamically removed/reinstated to allow deeper sleep.
Helmut64 0:a3ea811f80f2 134 usbhal_allow_em2(false);
Helmut64 0:a3ea811f80f2 135
Helmut64 0:a3ea811f80f2 136 epCallback[EP0OUT] = NULL;
Helmut64 0:a3ea811f80f2 137 epCallback[EP0IN ] = NULL;
Helmut64 0:a3ea811f80f2 138 epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback;
Helmut64 0:a3ea811f80f2 139 epCallback[EP1IN ] = &USBHAL::EP1_IN_callback;
Helmut64 0:a3ea811f80f2 140 epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback;
Helmut64 0:a3ea811f80f2 141 epCallback[EP2IN ] = &USBHAL::EP2_IN_callback;
Helmut64 0:a3ea811f80f2 142 epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback;
Helmut64 0:a3ea811f80f2 143 epCallback[EP3IN ] = &USBHAL::EP3_IN_callback;
Helmut64 0:a3ea811f80f2 144 #ifndef TARGET_EFM32HG_STK3400
Helmut64 0:a3ea811f80f2 145 epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback;
Helmut64 0:a3ea811f80f2 146 epCallback[EP4IN ] = &USBHAL::EP4_IN_callback;
Helmut64 0:a3ea811f80f2 147 epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback;
Helmut64 0:a3ea811f80f2 148 epCallback[EP5IN ] = &USBHAL::EP5_IN_callback;
Helmut64 0:a3ea811f80f2 149 epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback;
Helmut64 0:a3ea811f80f2 150 epCallback[EP6IN ] = &USBHAL::EP6_IN_callback;
Helmut64 0:a3ea811f80f2 151 #endif
Helmut64 0:a3ea811f80f2 152
Helmut64 0:a3ea811f80f2 153 memset(ep_state, 0, sizeof(ep_state));
Helmut64 0:a3ea811f80f2 154
Helmut64 0:a3ea811f80f2 155 ep_state[EP0OUT].intern_cb = usbhal_xfer_complete_cb_EP0OUT;
Helmut64 0:a3ea811f80f2 156 ep_state[EP0IN ].intern_cb = usbhal_xfer_complete_cb_EP0IN;
Helmut64 0:a3ea811f80f2 157 ep_state[EP1OUT].intern_cb = usbhal_xfer_complete_cb_EP1OUT;
Helmut64 0:a3ea811f80f2 158 ep_state[EP1IN ].intern_cb = usbhal_xfer_complete_cb_EP1IN;
Helmut64 0:a3ea811f80f2 159 ep_state[EP2OUT].intern_cb = usbhal_xfer_complete_cb_EP2OUT;
Helmut64 0:a3ea811f80f2 160 ep_state[EP2IN ].intern_cb = usbhal_xfer_complete_cb_EP2IN;
Helmut64 0:a3ea811f80f2 161 ep_state[EP3OUT].intern_cb = usbhal_xfer_complete_cb_EP3OUT;
Helmut64 0:a3ea811f80f2 162 ep_state[EP3IN ].intern_cb = usbhal_xfer_complete_cb_EP3IN;
Helmut64 0:a3ea811f80f2 163 #ifndef TARGET_EFM32HG_STK3400
Helmut64 0:a3ea811f80f2 164 ep_state[EP4OUT].intern_cb = usbhal_xfer_complete_cb_EP4OUT;
Helmut64 0:a3ea811f80f2 165 ep_state[EP4IN ].intern_cb = usbhal_xfer_complete_cb_EP4IN;
Helmut64 0:a3ea811f80f2 166 ep_state[EP5OUT].intern_cb = usbhal_xfer_complete_cb_EP5OUT;
Helmut64 0:a3ea811f80f2 167 ep_state[EP5IN ].intern_cb = usbhal_xfer_complete_cb_EP5IN;
Helmut64 0:a3ea811f80f2 168 ep_state[EP6OUT].intern_cb = usbhal_xfer_complete_cb_EP6OUT;
Helmut64 0:a3ea811f80f2 169 ep_state[EP6IN ].intern_cb = usbhal_xfer_complete_cb_EP6IN;
Helmut64 0:a3ea811f80f2 170 #endif
Helmut64 0:a3ea811f80f2 171
Helmut64 0:a3ea811f80f2 172 #ifdef USB_USE_DYNAMIC_MEMORY
Helmut64 0:a3ea811f80f2 173 ep_state[EP0OUT].data_buf = ep0out_data_buf;
Helmut64 0:a3ea811f80f2 174 ep_state[EP0IN].data_buf = ep0in_data_buf;
Helmut64 0:a3ea811f80f2 175 #else
Helmut64 0:a3ea811f80f2 176 for (int i=0 ; i<NUMBER_OF_ENDPOINTS ; i++) {
Helmut64 0:a3ea811f80f2 177 ep_state[i].data_buf = ep_data_buf[i];
Helmut64 0:a3ea811f80f2 178 }
Helmut64 0:a3ea811f80f2 179 #endif
Helmut64 0:a3ea811f80f2 180 }
Helmut64 0:a3ea811f80f2 181
Helmut64 0:a3ea811f80f2 182 USBHAL::~USBHAL(void)
Helmut64 0:a3ea811f80f2 183 {
Helmut64 0:a3ea811f80f2 184 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 185 USBD_AbortAllTransfers();
Helmut64 0:a3ea811f80f2 186 USBD_Disconnect();
Helmut64 0:a3ea811f80f2 187 usbhal_free_buffers();
Helmut64 0:a3ea811f80f2 188
Helmut64 0:a3ea811f80f2 189 usbhal_allow_em2(true);
Helmut64 0:a3ea811f80f2 190 }
Helmut64 0:a3ea811f80f2 191
Helmut64 0:a3ea811f80f2 192 extern "C" void usbhal_allow_em2(bool allow_em2)
Helmut64 0:a3ea811f80f2 193 {
Helmut64 0:a3ea811f80f2 194 static bool blocked = false;
Helmut64 0:a3ea811f80f2 195 if (allow_em2 && blocked) {
Helmut64 0:a3ea811f80f2 196 sleep_manager_unlock_deep_sleep();
Helmut64 0:a3ea811f80f2 197 blocked = false;
Helmut64 0:a3ea811f80f2 198 } else if (!blocked) {
Helmut64 0:a3ea811f80f2 199 sleep_manager_lock_deep_sleep();
Helmut64 0:a3ea811f80f2 200 blocked = true;
Helmut64 0:a3ea811f80f2 201 }
Helmut64 0:a3ea811f80f2 202 }
Helmut64 0:a3ea811f80f2 203
Helmut64 0:a3ea811f80f2 204 static void usbhal_reset_cb(void)
Helmut64 0:a3ea811f80f2 205 {
Helmut64 0:a3ea811f80f2 206 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 207 run_cmd(CMD_BUSRESET, 0);
Helmut64 0:a3ea811f80f2 208 }
Helmut64 0:a3ea811f80f2 209
Helmut64 0:a3ea811f80f2 210 #ifdef DEBUG_USB_API
Helmut64 0:a3ea811f80f2 211 static const char *usbstate[] = { "NONE", "ATTACHED", "POWERED", "DEFAULT",
Helmut64 0:a3ea811f80f2 212 "ADDRESSED", "CONFIGURED", "SUSPENDED", "???" };
Helmut64 0:a3ea811f80f2 213 #endif
Helmut64 0:a3ea811f80f2 214
Helmut64 0:a3ea811f80f2 215 static void usbhal_state_change_cb(USBD_State_TypeDef oldState,
Helmut64 0:a3ea811f80f2 216 USBD_State_TypeDef newState)
Helmut64 0:a3ea811f80f2 217 {
Helmut64 0:a3ea811f80f2 218 TRACE("state changed %s -> %s", usbstate[oldState], usbstate[newState]);
Helmut64 0:a3ea811f80f2 219
Helmut64 0:a3ea811f80f2 220 if (oldState == USBD_STATE_SUSPENDED) {
Helmut64 0:a3ea811f80f2 221 run_cmd(CMD_SUSPEND_STATE_CHANGED, 0);
Helmut64 0:a3ea811f80f2 222 }
Helmut64 0:a3ea811f80f2 223
Helmut64 0:a3ea811f80f2 224 if (newState == USBD_STATE_SUSPENDED) {
Helmut64 0:a3ea811f80f2 225 run_cmd(CMD_SUSPEND_STATE_CHANGED, 1);
Helmut64 0:a3ea811f80f2 226 }
Helmut64 0:a3ea811f80f2 227
Helmut64 0:a3ea811f80f2 228 // Should call connectStateChanged from here as well but there is
Helmut64 0:a3ea811f80f2 229 // no documentation on when to actually do so. (And the implementation
Helmut64 0:a3ea811f80f2 230 // in USBDevice.cpp is a stub)
Helmut64 0:a3ea811f80f2 231
Helmut64 0:a3ea811f80f2 232 // HACK! Since connectStateChanged is not used, indicate the loss
Helmut64 0:a3ea811f80f2 233 // off connection by reporting a bus reset. This causes USBDevice
Helmut64 0:a3ea811f80f2 234 // to realise that at least it's not in CONFIGURED anymore, and
Helmut64 0:a3ea811f80f2 235 // stop trying to read/write in a busyloop.
Helmut64 0:a3ea811f80f2 236 if (newState == USBD_STATE_NONE) {
Helmut64 0:a3ea811f80f2 237 run_cmd(CMD_BUSRESET, 0);
Helmut64 0:a3ea811f80f2 238 }
Helmut64 0:a3ea811f80f2 239 }
Helmut64 0:a3ea811f80f2 240
Helmut64 0:a3ea811f80f2 241 static int usbhal_setupcmd_cb(const USB_Setup_TypeDef *setup)
Helmut64 0:a3ea811f80f2 242 {
Helmut64 0:a3ea811f80f2 243 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 244 if (!setup) {
Helmut64 0:a3ea811f80f2 245 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 246 return USB_STATUS_REQ_ERR;
Helmut64 0:a3ea811f80f2 247 }
Helmut64 0:a3ea811f80f2 248
Helmut64 0:a3ea811f80f2 249 memcpy(ep0setupdata, setup, 8);
Helmut64 0:a3ea811f80f2 250 run_cmd(CMD_EP0SETUP, 0);
Helmut64 0:a3ea811f80f2 251
Helmut64 0:a3ea811f80f2 252 return USB_STATUS_OK;
Helmut64 0:a3ea811f80f2 253 }
Helmut64 0:a3ea811f80f2 254
Helmut64 0:a3ea811f80f2 255 static void usbhal_sof_cb(uint16_t frameNum)
Helmut64 0:a3ea811f80f2 256 {
Helmut64 0:a3ea811f80f2 257 run_cmd(CMD_SOF, frameNum);
Helmut64 0:a3ea811f80f2 258 }
Helmut64 0:a3ea811f80f2 259
Helmut64 0:a3ea811f80f2 260 static void usbhal_free_buffers(void)
Helmut64 0:a3ea811f80f2 261 {
Helmut64 0:a3ea811f80f2 262 #ifdef USB_USE_DYNAMIC_MEMORY
Helmut64 0:a3ea811f80f2 263 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 264
Helmut64 0:a3ea811f80f2 265 for (int i=EP1OUT ; i<NUMBER_OF_ENDPOINTS ; i++ ) {
Helmut64 0:a3ea811f80f2 266 if (ep_state[i].data_buf) {
Helmut64 0:a3ea811f80f2 267 free(ep_state[i].data_buf);
Helmut64 0:a3ea811f80f2 268 ep_state[i].data_buf = NULL;
Helmut64 0:a3ea811f80f2 269 }
Helmut64 0:a3ea811f80f2 270 }
Helmut64 0:a3ea811f80f2 271 #endif
Helmut64 0:a3ea811f80f2 272 }
Helmut64 0:a3ea811f80f2 273
Helmut64 0:a3ea811f80f2 274 void USBHAL::connect(void)
Helmut64 0:a3ea811f80f2 275 {
Helmut64 0:a3ea811f80f2 276 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 277
Helmut64 0:a3ea811f80f2 278 // Init datastructures must be static - driver will use these even after the init function exits!
Helmut64 0:a3ea811f80f2 279
Helmut64 0:a3ea811f80f2 280 static const uint8_t buffer_multiplier[] = { 1 }; // Mult 1 for control EP
Helmut64 0:a3ea811f80f2 281 static const USBD_Callbacks_TypeDef usbd_callbacks = {
Helmut64 0:a3ea811f80f2 282 .usbReset = usbhal_reset_cb,
Helmut64 0:a3ea811f80f2 283 .usbStateChange = usbhal_state_change_cb,
Helmut64 0:a3ea811f80f2 284 .setupCmd = usbhal_setupcmd_cb,
Helmut64 0:a3ea811f80f2 285 .isSelfPowered = NULL,
Helmut64 0:a3ea811f80f2 286 .sofInt = usbhal_sof_cb
Helmut64 0:a3ea811f80f2 287 };
Helmut64 0:a3ea811f80f2 288
Helmut64 0:a3ea811f80f2 289 USBD_Init_TypeDef initdata = {
Helmut64 0:a3ea811f80f2 290 .deviceDescriptor = NULL,
Helmut64 0:a3ea811f80f2 291 .configDescriptor = NULL,
Helmut64 0:a3ea811f80f2 292 .stringDescriptors = NULL,
Helmut64 0:a3ea811f80f2 293 .numberOfStrings = 0,
Helmut64 0:a3ea811f80f2 294 .bufferingMultiplier = buffer_multiplier,
Helmut64 0:a3ea811f80f2 295 .callbacks = &usbd_callbacks,
Helmut64 0:a3ea811f80f2 296 .reserved = 0
Helmut64 0:a3ea811f80f2 297 };
Helmut64 0:a3ea811f80f2 298
Helmut64 0:a3ea811f80f2 299 int ret = USBD_Init(&initdata);
Helmut64 0:a3ea811f80f2 300
Helmut64 0:a3ea811f80f2 301 TRACE("init = %d, devicedesc = %lx, configdesc = %lx", ret,
Helmut64 0:a3ea811f80f2 302 (uint32_t) initdata.deviceDescriptor,
Helmut64 0:a3ea811f80f2 303 (uint32_t) initdata.configDescriptor);
Helmut64 0:a3ea811f80f2 304
Helmut64 0:a3ea811f80f2 305 EFM_ASSERT(ret == USB_STATUS_OK);
Helmut64 0:a3ea811f80f2 306 }
Helmut64 0:a3ea811f80f2 307
Helmut64 0:a3ea811f80f2 308 void USBHAL::disconnect(void)
Helmut64 0:a3ea811f80f2 309 {
Helmut64 0:a3ea811f80f2 310 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 311 USBD_Disconnect();
Helmut64 0:a3ea811f80f2 312 }
Helmut64 0:a3ea811f80f2 313
Helmut64 0:a3ea811f80f2 314 void USBHAL::configureDevice(void)
Helmut64 0:a3ea811f80f2 315 {
Helmut64 0:a3ea811f80f2 316 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 317 USBD_SetUsbState(USBD_STATE_CONFIGURED);
Helmut64 0:a3ea811f80f2 318 }
Helmut64 0:a3ea811f80f2 319
Helmut64 0:a3ea811f80f2 320 void USBHAL::unconfigureDevice(void)
Helmut64 0:a3ea811f80f2 321 {
Helmut64 0:a3ea811f80f2 322 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 323 USBD_SetUsbState(USBD_STATE_DEFAULT);
Helmut64 0:a3ea811f80f2 324 usbhal_free_buffers();
Helmut64 0:a3ea811f80f2 325 }
Helmut64 0:a3ea811f80f2 326
Helmut64 0:a3ea811f80f2 327 void USBHAL::setAddress(uint8_t address)
Helmut64 0:a3ea811f80f2 328 {
Helmut64 0:a3ea811f80f2 329 TRACE_FUNC_IN_P("addr 0x%x", (unsigned)address);
Helmut64 0:a3ea811f80f2 330 USBD_SetAddress(address);
Helmut64 0:a3ea811f80f2 331 }
Helmut64 0:a3ea811f80f2 332
Helmut64 0:a3ea811f80f2 333 void USBHAL::remoteWakeup(void)
Helmut64 0:a3ea811f80f2 334 {
Helmut64 0:a3ea811f80f2 335 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 336 USBD_RemoteWakeup();
Helmut64 0:a3ea811f80f2 337 }
Helmut64 0:a3ea811f80f2 338
Helmut64 0:a3ea811f80f2 339 void USBHAL::EP0setup(uint8_t *buffer)
Helmut64 0:a3ea811f80f2 340 {
Helmut64 0:a3ea811f80f2 341 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 342 EFM_ASSERT(buffer);
Helmut64 0:a3ea811f80f2 343 if (buffer) {
Helmut64 0:a3ea811f80f2 344 memcpy(buffer, ep0setupdata, 8);
Helmut64 0:a3ea811f80f2 345 }
Helmut64 0:a3ea811f80f2 346 }
Helmut64 0:a3ea811f80f2 347
Helmut64 0:a3ea811f80f2 348 void USBHAL::EP0read(void)
Helmut64 0:a3ea811f80f2 349 {
Helmut64 0:a3ea811f80f2 350 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 351 (void)internEndpointRead(0, MAX_PACKET_SIZE_EP0);
Helmut64 0:a3ea811f80f2 352 }
Helmut64 0:a3ea811f80f2 353
Helmut64 0:a3ea811f80f2 354 void USBHAL::EP0readStage(void)
Helmut64 0:a3ea811f80f2 355 {
Helmut64 0:a3ea811f80f2 356 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 357 // Not needed
Helmut64 0:a3ea811f80f2 358 }
Helmut64 0:a3ea811f80f2 359
Helmut64 0:a3ea811f80f2 360 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
Helmut64 0:a3ea811f80f2 361 {
Helmut64 0:a3ea811f80f2 362 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 363 EFM_ASSERT(buffer);
Helmut64 0:a3ea811f80f2 364
Helmut64 0:a3ea811f80f2 365 uint32_t read = 0;
Helmut64 0:a3ea811f80f2 366 endpointReadResult(0, buffer, &read);
Helmut64 0:a3ea811f80f2 367 return read;
Helmut64 0:a3ea811f80f2 368 }
Helmut64 0:a3ea811f80f2 369
Helmut64 0:a3ea811f80f2 370 static int usbhal_xfer_complete_cb(uint8_t ep, USB_Status_TypeDef status,
Helmut64 0:a3ea811f80f2 371 uint32_t xferred, uint32_t remaining)
Helmut64 0:a3ea811f80f2 372 {
Helmut64 0:a3ea811f80f2 373 TRACE_FUNC_IN_P("ep 0x%x, status %u, xferred %lu, rem %lu",
Helmut64 0:a3ea811f80f2 374 ep, status, xferred, remaining);
Helmut64 0:a3ea811f80f2 375
Helmut64 0:a3ea811f80f2 376 if (ep >= NUMBER_OF_ENDPOINTS) {
Helmut64 0:a3ea811f80f2 377 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 378 return USB_STATUS_REQ_ERR;
Helmut64 0:a3ea811f80f2 379 }
Helmut64 0:a3ea811f80f2 380
Helmut64 0:a3ea811f80f2 381 switch (ep) {
Helmut64 0:a3ea811f80f2 382 case EP0OUT:
Helmut64 0:a3ea811f80f2 383 if (ep_state[EP0OUT].status == READ_PENDING) {
Helmut64 0:a3ea811f80f2 384 ep_state[EP0OUT].status = READ_COMPLETE;
Helmut64 0:a3ea811f80f2 385 ep_state[EP0OUT].byte_count = xferred;
Helmut64 0:a3ea811f80f2 386 // drop zlp
Helmut64 0:a3ea811f80f2 387 if (xferred == 0) {
Helmut64 0:a3ea811f80f2 388 break;
Helmut64 0:a3ea811f80f2 389 }
Helmut64 0:a3ea811f80f2 390 }
Helmut64 0:a3ea811f80f2 391 run_cmd(CMD_EP0OUT, 0);
Helmut64 0:a3ea811f80f2 392 break;
Helmut64 0:a3ea811f80f2 393
Helmut64 0:a3ea811f80f2 394 case EP0IN:
Helmut64 0:a3ea811f80f2 395 run_cmd(CMD_EP0IN, 0);
Helmut64 0:a3ea811f80f2 396 break;
Helmut64 0:a3ea811f80f2 397
Helmut64 0:a3ea811f80f2 398 default:
Helmut64 0:a3ea811f80f2 399 bool write = ep & 1;
Helmut64 0:a3ea811f80f2 400
Helmut64 0:a3ea811f80f2 401 if (status == USB_STATUS_OK) {
Helmut64 0:a3ea811f80f2 402 if (!write && ep_state[ep].status == READ_PENDING) {
Helmut64 0:a3ea811f80f2 403 ep_state[ep].status = READ_COMPLETE;
Helmut64 0:a3ea811f80f2 404 ep_state[ep].byte_count = xferred;
Helmut64 0:a3ea811f80f2 405 } else if (write && ep_state[ep].status == WRITE_PENDING) {
Helmut64 0:a3ea811f80f2 406 ep_state[ep].status = WRITE_COMPLETE;
Helmut64 0:a3ea811f80f2 407 } else {
Helmut64 0:a3ea811f80f2 408 ep_state[ep].status = FAILED_INVALID;
Helmut64 0:a3ea811f80f2 409 }
Helmut64 0:a3ea811f80f2 410 } else {
Helmut64 0:a3ea811f80f2 411 ep_state[ep].status = FAILED_INVALID;
Helmut64 0:a3ea811f80f2 412 }
Helmut64 0:a3ea811f80f2 413
Helmut64 0:a3ea811f80f2 414 if (ep_state[ep].status != FAILED_INVALID) {
Helmut64 0:a3ea811f80f2 415 run_cmd(CMD_EP_XFER_COMPLETED, ep);
Helmut64 0:a3ea811f80f2 416 }
Helmut64 0:a3ea811f80f2 417 break;
Helmut64 0:a3ea811f80f2 418 }
Helmut64 0:a3ea811f80f2 419
Helmut64 0:a3ea811f80f2 420 return USB_STATUS_OK;
Helmut64 0:a3ea811f80f2 421 }
Helmut64 0:a3ea811f80f2 422
Helmut64 0:a3ea811f80f2 423 void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
Helmut64 0:a3ea811f80f2 424 {
Helmut64 0:a3ea811f80f2 425 //TRACE_FUNC_IN_P("buffer %lx, size %lu", (uint32_t) buffer, size);
Helmut64 0:a3ea811f80f2 426
Helmut64 0:a3ea811f80f2 427 int ret;
Helmut64 0:a3ea811f80f2 428 USB_XferCompleteCb_TypeDef cb = ep_state[EP0IN].intern_cb;
Helmut64 0:a3ea811f80f2 429
Helmut64 0:a3ea811f80f2 430 EFM_ASSERT((buffer != NULL) || (size == 0));
Helmut64 0:a3ea811f80f2 431 EFM_ASSERT(size <= MAX_PACKET_SIZE_EP0);
Helmut64 0:a3ea811f80f2 432
Helmut64 0:a3ea811f80f2 433 if (!buffer || size == 0) {
Helmut64 0:a3ea811f80f2 434 // No callback after writing EP0 ZLP
Helmut64 0:a3ea811f80f2 435 cb = NULL;
Helmut64 0:a3ea811f80f2 436 }
Helmut64 0:a3ea811f80f2 437
Helmut64 0:a3ea811f80f2 438 if (buffer && !is_aligned(buffer,4)) {
Helmut64 0:a3ea811f80f2 439 // Copy unaligned data to write-buffer before USBD_Write
Helmut64 0:a3ea811f80f2 440 memcpy(ep_state[EP0IN].data_buf, buffer, size);
Helmut64 0:a3ea811f80f2 441 ret = USBD_Write(0, ep_state[EP0IN].data_buf, size, cb);
Helmut64 0:a3ea811f80f2 442 } else {
Helmut64 0:a3ea811f80f2 443 ret = USBD_Write(0, buffer, size, cb);
Helmut64 0:a3ea811f80f2 444 }
Helmut64 0:a3ea811f80f2 445
Helmut64 0:a3ea811f80f2 446 if (ret != USB_STATUS_OK) {
Helmut64 0:a3ea811f80f2 447 TRACE("FAILED - ret %d", ret);
Helmut64 0:a3ea811f80f2 448 }
Helmut64 0:a3ea811f80f2 449 }
Helmut64 0:a3ea811f80f2 450
Helmut64 0:a3ea811f80f2 451 void USBHAL::EP0stall(void)
Helmut64 0:a3ea811f80f2 452 {
Helmut64 0:a3ea811f80f2 453 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 454 USBD_StallEp0();
Helmut64 0:a3ea811f80f2 455 }
Helmut64 0:a3ea811f80f2 456
Helmut64 0:a3ea811f80f2 457 static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize)
Helmut64 0:a3ea811f80f2 458 {
Helmut64 0:a3ea811f80f2 459 //TRACE_FUNC_IN_P("endpoint 0x%x, size %ld, cb %d", (unsigned)ep, maxSize, useCallback);
Helmut64 0:a3ea811f80f2 460
Helmut64 0:a3ea811f80f2 461 if (ep >= NUMBER_OF_ENDPOINTS) {
Helmut64 0:a3ea811f80f2 462 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 463 return EP_INVALID;
Helmut64 0:a3ea811f80f2 464 }
Helmut64 0:a3ea811f80f2 465
Helmut64 0:a3ea811f80f2 466 ep_state[ep].status = READ_PENDING;
Helmut64 0:a3ea811f80f2 467
Helmut64 0:a3ea811f80f2 468 int ret = USBD_Read(USB_EP_TO_ADDR(ep), ep_state[ep].data_buf, maxSize,
Helmut64 0:a3ea811f80f2 469 ep_state[ep].intern_cb);
Helmut64 0:a3ea811f80f2 470
Helmut64 0:a3ea811f80f2 471 if (ret == USB_STATUS_OK) {
Helmut64 0:a3ea811f80f2 472 return EP_PENDING;
Helmut64 0:a3ea811f80f2 473 } else {
Helmut64 0:a3ea811f80f2 474 TRACE("FAILED - ret %d", ret);
Helmut64 0:a3ea811f80f2 475
Helmut64 0:a3ea811f80f2 476 if (ret == USB_STATUS_EP_STALLED) {
Helmut64 0:a3ea811f80f2 477 return EP_STALLED;
Helmut64 0:a3ea811f80f2 478 } else {
Helmut64 0:a3ea811f80f2 479 return EP_INVALID;
Helmut64 0:a3ea811f80f2 480 }
Helmut64 0:a3ea811f80f2 481 }
Helmut64 0:a3ea811f80f2 482 }
Helmut64 0:a3ea811f80f2 483
Helmut64 0:a3ea811f80f2 484 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
Helmut64 0:a3ea811f80f2 485 {
Helmut64 0:a3ea811f80f2 486 return internEndpointRead(endpoint, maximumSize);
Helmut64 0:a3ea811f80f2 487 }
Helmut64 0:a3ea811f80f2 488
Helmut64 0:a3ea811f80f2 489 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead)
Helmut64 0:a3ea811f80f2 490 {
Helmut64 0:a3ea811f80f2 491 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 492
Helmut64 0:a3ea811f80f2 493 if (endpoint >= NUMBER_OF_ENDPOINTS) {
Helmut64 0:a3ea811f80f2 494 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 495 return EP_INVALID;
Helmut64 0:a3ea811f80f2 496 }
Helmut64 0:a3ea811f80f2 497
Helmut64 0:a3ea811f80f2 498 EFM_ASSERT(data);
Helmut64 0:a3ea811f80f2 499 EFM_ASSERT(bytesRead);
Helmut64 0:a3ea811f80f2 500 if (!data || !bytesRead) {
Helmut64 0:a3ea811f80f2 501 return EP_INVALID;
Helmut64 0:a3ea811f80f2 502 }
Helmut64 0:a3ea811f80f2 503
Helmut64 0:a3ea811f80f2 504 switch (ep_state[endpoint].status) {
Helmut64 0:a3ea811f80f2 505 case READ_PENDING:
Helmut64 0:a3ea811f80f2 506 return EP_PENDING;
Helmut64 0:a3ea811f80f2 507
Helmut64 0:a3ea811f80f2 508 case READ_COMPLETE:
Helmut64 0:a3ea811f80f2 509 memcpy(data, ep_state[endpoint].data_buf, ep_state[endpoint].byte_count);
Helmut64 0:a3ea811f80f2 510 *bytesRead = ep_state[endpoint].byte_count;
Helmut64 0:a3ea811f80f2 511 ep_state[endpoint].status = IDLE;
Helmut64 0:a3ea811f80f2 512 return EP_COMPLETED;
Helmut64 0:a3ea811f80f2 513
Helmut64 0:a3ea811f80f2 514 case FAILED_STALLED:
Helmut64 0:a3ea811f80f2 515 ep_state[endpoint].status = IDLE;
Helmut64 0:a3ea811f80f2 516 return EP_STALLED;
Helmut64 0:a3ea811f80f2 517
Helmut64 0:a3ea811f80f2 518 default:
Helmut64 0:a3ea811f80f2 519 ep_state[endpoint].status = IDLE;
Helmut64 0:a3ea811f80f2 520 return EP_INVALID;
Helmut64 0:a3ea811f80f2 521 }
Helmut64 0:a3ea811f80f2 522 }
Helmut64 0:a3ea811f80f2 523
Helmut64 0:a3ea811f80f2 524 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
Helmut64 0:a3ea811f80f2 525 {
Helmut64 0:a3ea811f80f2 526 TRACE_FUNC_IN_P("endpoint 0x%x, data 0x%lx, size %lu", (unsigned )endpoint, (uint32_t)data, size);
Helmut64 0:a3ea811f80f2 527
Helmut64 0:a3ea811f80f2 528 EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
Helmut64 0:a3ea811f80f2 529 EFM_ASSERT(endpoint > EP0IN);
Helmut64 0:a3ea811f80f2 530 EFM_ASSERT(size <= ep_state[endpoint].max_packet);
Helmut64 0:a3ea811f80f2 531 EFM_ASSERT(data);
Helmut64 0:a3ea811f80f2 532
Helmut64 0:a3ea811f80f2 533 uint8_t ep = USB_EP_TO_INDEX(endpoint);
Helmut64 0:a3ea811f80f2 534
Helmut64 0:a3ea811f80f2 535 if (endpoint >= NUMBER_OF_ENDPOINTS || endpoint <= EP0IN) {
Helmut64 0:a3ea811f80f2 536 return EP_INVALID;
Helmut64 0:a3ea811f80f2 537 }
Helmut64 0:a3ea811f80f2 538
Helmut64 0:a3ea811f80f2 539 if (size > ep_state[endpoint].max_packet) {
Helmut64 0:a3ea811f80f2 540 return EP_INVALID;
Helmut64 0:a3ea811f80f2 541 }
Helmut64 0:a3ea811f80f2 542
Helmut64 0:a3ea811f80f2 543 if (!data) {
Helmut64 0:a3ea811f80f2 544 return EP_INVALID;
Helmut64 0:a3ea811f80f2 545 }
Helmut64 0:a3ea811f80f2 546
Helmut64 0:a3ea811f80f2 547 memcpy(ep_state[ep].data_buf, data, size);
Helmut64 0:a3ea811f80f2 548
Helmut64 0:a3ea811f80f2 549 ep_state[ep].status = WRITE_PENDING;
Helmut64 0:a3ea811f80f2 550 int ret = USBD_Write(USB_EP_TO_ADDR(endpoint), ep_state[ep].data_buf, size, ep_state[ep].intern_cb);
Helmut64 0:a3ea811f80f2 551
Helmut64 0:a3ea811f80f2 552 if (ret == USB_STATUS_EP_STALLED) {
Helmut64 0:a3ea811f80f2 553 ep_state[ep].status = IDLE;
Helmut64 0:a3ea811f80f2 554 return EP_STALLED;
Helmut64 0:a3ea811f80f2 555 } else if (ret != USB_STATUS_OK) {
Helmut64 0:a3ea811f80f2 556 ep_state[ep].status = IDLE;
Helmut64 0:a3ea811f80f2 557 return EP_INVALID;
Helmut64 0:a3ea811f80f2 558 }
Helmut64 0:a3ea811f80f2 559
Helmut64 0:a3ea811f80f2 560 return EP_PENDING;
Helmut64 0:a3ea811f80f2 561 }
Helmut64 0:a3ea811f80f2 562
Helmut64 0:a3ea811f80f2 563 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
Helmut64 0:a3ea811f80f2 564 {
Helmut64 0:a3ea811f80f2 565 if (endpoint >= NUMBER_OF_ENDPOINTS) {
Helmut64 0:a3ea811f80f2 566 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 567 return EP_INVALID;
Helmut64 0:a3ea811f80f2 568 }
Helmut64 0:a3ea811f80f2 569
Helmut64 0:a3ea811f80f2 570 switch (ep_state[endpoint].status) {
Helmut64 0:a3ea811f80f2 571 case WRITE_PENDING:
Helmut64 0:a3ea811f80f2 572 return EP_PENDING;
Helmut64 0:a3ea811f80f2 573
Helmut64 0:a3ea811f80f2 574 case WRITE_COMPLETE:
Helmut64 0:a3ea811f80f2 575 ep_state[endpoint].status = IDLE;
Helmut64 0:a3ea811f80f2 576 return EP_COMPLETED;
Helmut64 0:a3ea811f80f2 577
Helmut64 0:a3ea811f80f2 578 case FAILED_STALLED:
Helmut64 0:a3ea811f80f2 579 ep_state[endpoint].status = IDLE;
Helmut64 0:a3ea811f80f2 580 return EP_STALLED;
Helmut64 0:a3ea811f80f2 581
Helmut64 0:a3ea811f80f2 582 default:
Helmut64 0:a3ea811f80f2 583 ep_state[endpoint].status = IDLE;
Helmut64 0:a3ea811f80f2 584 return EP_INVALID;
Helmut64 0:a3ea811f80f2 585 }
Helmut64 0:a3ea811f80f2 586 }
Helmut64 0:a3ea811f80f2 587
Helmut64 0:a3ea811f80f2 588 void USBHAL::stallEndpoint(uint8_t endpoint)
Helmut64 0:a3ea811f80f2 589 {
Helmut64 0:a3ea811f80f2 590 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 591
Helmut64 0:a3ea811f80f2 592 EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
Helmut64 0:a3ea811f80f2 593 EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
Helmut64 0:a3ea811f80f2 594
Helmut64 0:a3ea811f80f2 595 USBD_StallEp(USB_EP_TO_ADDR(endpoint));
Helmut64 0:a3ea811f80f2 596 }
Helmut64 0:a3ea811f80f2 597
Helmut64 0:a3ea811f80f2 598 void USBHAL::unstallEndpoint(uint8_t endpoint)
Helmut64 0:a3ea811f80f2 599 {
Helmut64 0:a3ea811f80f2 600 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 601
Helmut64 0:a3ea811f80f2 602 EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
Helmut64 0:a3ea811f80f2 603 EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
Helmut64 0:a3ea811f80f2 604
Helmut64 0:a3ea811f80f2 605 USBD_UnStallEp(USB_EP_TO_ADDR(endpoint));
Helmut64 0:a3ea811f80f2 606 }
Helmut64 0:a3ea811f80f2 607
Helmut64 0:a3ea811f80f2 608 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
Helmut64 0:a3ea811f80f2 609 {
Helmut64 0:a3ea811f80f2 610 TRACE_FUNC_IN_P("endpoint %d, packetsize %ld, options 0x%lx", endpoint,
Helmut64 0:a3ea811f80f2 611 maxPacket, options);
Helmut64 0:a3ea811f80f2 612
Helmut64 0:a3ea811f80f2 613 int mult = 1; // RX/TX buffer size multiplier
Helmut64 0:a3ea811f80f2 614 int type = USB_EPTYPE_INTR;
Helmut64 0:a3ea811f80f2 615
Helmut64 0:a3ea811f80f2 616 if (endpoint >= NUMBER_OF_ENDPOINTS) {
Helmut64 0:a3ea811f80f2 617 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 618 return false;
Helmut64 0:a3ea811f80f2 619 }
Helmut64 0:a3ea811f80f2 620
Helmut64 0:a3ea811f80f2 621 if (endpoint == EP0IN || endpoint == EP0OUT) {
Helmut64 0:a3ea811f80f2 622 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 623 return false;
Helmut64 0:a3ea811f80f2 624 }
Helmut64 0:a3ea811f80f2 625
Helmut64 0:a3ea811f80f2 626 ep_state[endpoint].max_packet = 0;
Helmut64 0:a3ea811f80f2 627
Helmut64 0:a3ea811f80f2 628 if (endpoint == EPISO_OUT || endpoint == EPISO_IN) {
Helmut64 0:a3ea811f80f2 629 if (maxPacket > MAX_PACKET_SIZE_EPISO) {
Helmut64 0:a3ea811f80f2 630 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 631 return false;
Helmut64 0:a3ea811f80f2 632 }
Helmut64 0:a3ea811f80f2 633 } else if ((maxPacket > MAX_PACKET_SIZE_EPBULK) || (maxPacket > MAX_PACKET_SIZE_EPINT)) {
Helmut64 0:a3ea811f80f2 634 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 635 return false;
Helmut64 0:a3ea811f80f2 636 }
Helmut64 0:a3ea811f80f2 637
Helmut64 0:a3ea811f80f2 638 // USBDevice performs a read right after creating the endpoints,
Helmut64 0:a3ea811f80f2 639 // before calling configureDevice. The read will fail since
Helmut64 0:a3ea811f80f2 640 // at that point the device state is still ADDRESSED. Workaround
Helmut64 0:a3ea811f80f2 641 // is to force configured state here.
Helmut64 0:a3ea811f80f2 642 //
Helmut64 0:a3ea811f80f2 643 // This relies on USBDevice to not call realiseEndpoint unless
Helmut64 0:a3ea811f80f2 644 // it is transitioning to the CONFIGURED state.
Helmut64 0:a3ea811f80f2 645 USBD_SetUsbState(USBD_STATE_CONFIGURED);
Helmut64 0:a3ea811f80f2 646
Helmut64 0:a3ea811f80f2 647 // Why doesn't this function have a type param? This is silly...
Helmut64 0:a3ea811f80f2 648 switch (endpoint) {
Helmut64 0:a3ea811f80f2 649 case EPBULK_OUT:
Helmut64 0:a3ea811f80f2 650 case EPBULK_IN:
Helmut64 0:a3ea811f80f2 651 type = USB_EPTYPE_BULK;
Helmut64 0:a3ea811f80f2 652 mult = 2;
Helmut64 0:a3ea811f80f2 653 break;
Helmut64 0:a3ea811f80f2 654 case EPINT_OUT:
Helmut64 0:a3ea811f80f2 655 case EPINT_IN:
Helmut64 0:a3ea811f80f2 656 type = USB_EPTYPE_INTR;
Helmut64 0:a3ea811f80f2 657 mult = 1;
Helmut64 0:a3ea811f80f2 658 break;
Helmut64 0:a3ea811f80f2 659 case EPISO_OUT:
Helmut64 0:a3ea811f80f2 660 case EPISO_IN:
Helmut64 0:a3ea811f80f2 661 type = USB_EPTYPE_ISOC;
Helmut64 0:a3ea811f80f2 662 mult = 2; // ?
Helmut64 0:a3ea811f80f2 663 break;
Helmut64 0:a3ea811f80f2 664 }
Helmut64 0:a3ea811f80f2 665
Helmut64 0:a3ea811f80f2 666 // Some options force the endpoint to a specific type
Helmut64 0:a3ea811f80f2 667 if( options & ISOCHRONOUS ) {
Helmut64 0:a3ea811f80f2 668 type = USB_EPTYPE_ISOC;
Helmut64 0:a3ea811f80f2 669 mult = 2; // ?
Helmut64 0:a3ea811f80f2 670 } else if ( options & RATE_FEEDBACK_MODE ) {
Helmut64 0:a3ea811f80f2 671 // No support for whatever rate feedback is, but for interrupt only
Helmut64 0:a3ea811f80f2 672 type = USB_EPTYPE_INTR;
Helmut64 0:a3ea811f80f2 673 mult = 1;
Helmut64 0:a3ea811f80f2 674 }
Helmut64 0:a3ea811f80f2 675
Helmut64 0:a3ea811f80f2 676 #ifdef USB_USE_DYNAMIC_MEMORY
Helmut64 0:a3ea811f80f2 677 if (ep_state[endpoint].data_buf) {
Helmut64 0:a3ea811f80f2 678 free(ep_state[endpoint].data_buf);
Helmut64 0:a3ea811f80f2 679 }
Helmut64 0:a3ea811f80f2 680
Helmut64 0:a3ea811f80f2 681 ep_state[endpoint].data_buf = (uint8_t *)malloc(maxPacket);
Helmut64 0:a3ea811f80f2 682
Helmut64 0:a3ea811f80f2 683 if (!ep_state[endpoint].data_buf) {
Helmut64 0:a3ea811f80f2 684 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 685 return false;
Helmut64 0:a3ea811f80f2 686 }
Helmut64 0:a3ea811f80f2 687 #endif
Helmut64 0:a3ea811f80f2 688
Helmut64 0:a3ea811f80f2 689 int ret = USBD_AddEndpoint(USB_EP_TO_ADDR(endpoint), type, maxPacket, mult);
Helmut64 0:a3ea811f80f2 690
Helmut64 0:a3ea811f80f2 691 if (ret == USB_STATUS_OK) {
Helmut64 0:a3ea811f80f2 692 ep_state[endpoint].status = IDLE;
Helmut64 0:a3ea811f80f2 693 ep_state[endpoint].max_packet = maxPacket;
Helmut64 0:a3ea811f80f2 694 return true;
Helmut64 0:a3ea811f80f2 695 } else {
Helmut64 0:a3ea811f80f2 696 return false;
Helmut64 0:a3ea811f80f2 697 }
Helmut64 0:a3ea811f80f2 698 }
Helmut64 0:a3ea811f80f2 699
Helmut64 0:a3ea811f80f2 700 bool USBHAL::getEndpointStallState(unsigned char endpoint)
Helmut64 0:a3ea811f80f2 701 {
Helmut64 0:a3ea811f80f2 702 TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 703 if (endpoint >= NUMBER_OF_ENDPOINTS) {
Helmut64 0:a3ea811f80f2 704 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 705 return false;
Helmut64 0:a3ea811f80f2 706 }
Helmut64 0:a3ea811f80f2 707 return USBD_EpIsStalled(USB_EP_TO_ADDR(endpoint));
Helmut64 0:a3ea811f80f2 708 }
Helmut64 0:a3ea811f80f2 709
Helmut64 0:a3ea811f80f2 710 static void run_cmd(USBISRCommand cmd, uint32_t param)
Helmut64 0:a3ea811f80f2 711 {
Helmut64 0:a3ea811f80f2 712 if (usb_isrcmd != CMD_HANDLED || cmd >= CMD_ENUM_END_MARKER) {
Helmut64 0:a3ea811f80f2 713 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 714 abort();
Helmut64 0:a3ea811f80f2 715 }
Helmut64 0:a3ea811f80f2 716
Helmut64 0:a3ea811f80f2 717 usb_isrcmd = cmd;
Helmut64 0:a3ea811f80f2 718 usb_isrcmd_param = param;
Helmut64 0:a3ea811f80f2 719 isrptr();
Helmut64 0:a3ea811f80f2 720 }
Helmut64 0:a3ea811f80f2 721
Helmut64 0:a3ea811f80f2 722 void USBHAL::_usbisr(void)
Helmut64 0:a3ea811f80f2 723 {
Helmut64 0:a3ea811f80f2 724 EFM_ASSERT(instance);
Helmut64 0:a3ea811f80f2 725 instance->usbisr();
Helmut64 0:a3ea811f80f2 726 }
Helmut64 0:a3ea811f80f2 727
Helmut64 0:a3ea811f80f2 728 void USBHAL::usbisr(void)
Helmut64 0:a3ea811f80f2 729 {
Helmut64 0:a3ea811f80f2 730 //TRACE_FUNC_IN;
Helmut64 0:a3ea811f80f2 731
Helmut64 0:a3ea811f80f2 732 // This "ISR" is used just to route callbacks from SiL USB driver
Helmut64 0:a3ea811f80f2 733 // callback context (which can not call protected/private USBHAL
Helmut64 0:a3ea811f80f2 734 // methods), to the actual USBHAL.
Helmut64 0:a3ea811f80f2 735
Helmut64 0:a3ea811f80f2 736 EFM_ASSERT(usb_isrcmd != CMD_HANDLED);
Helmut64 0:a3ea811f80f2 737 switch (usb_isrcmd) {
Helmut64 0:a3ea811f80f2 738 case CMD_EP0SETUP:
Helmut64 0:a3ea811f80f2 739 this->EP0setupCallback();
Helmut64 0:a3ea811f80f2 740 break;
Helmut64 0:a3ea811f80f2 741 case CMD_EP0IN:
Helmut64 0:a3ea811f80f2 742 this->EP0in();
Helmut64 0:a3ea811f80f2 743 break;
Helmut64 0:a3ea811f80f2 744 case CMD_EP0OUT:
Helmut64 0:a3ea811f80f2 745 this->EP0out();
Helmut64 0:a3ea811f80f2 746 break;
Helmut64 0:a3ea811f80f2 747 case CMD_BUSRESET:
Helmut64 0:a3ea811f80f2 748 this->busReset();
Helmut64 0:a3ea811f80f2 749 break;
Helmut64 0:a3ea811f80f2 750 case CMD_EP_XFER_COMPLETED:
Helmut64 0:a3ea811f80f2 751 if (epCallback[usb_isrcmd_param] && instance) {
Helmut64 0:a3ea811f80f2 752 (instance->*(epCallback[usb_isrcmd_param]))();
Helmut64 0:a3ea811f80f2 753 }
Helmut64 0:a3ea811f80f2 754 break;
Helmut64 0:a3ea811f80f2 755 case CMD_SOF:
Helmut64 0:a3ea811f80f2 756 this->SOF(usb_isrcmd_param);
Helmut64 0:a3ea811f80f2 757 break;
Helmut64 0:a3ea811f80f2 758 case CMD_SUSPEND_STATE_CHANGED:
Helmut64 0:a3ea811f80f2 759 this->suspendStateChanged(usb_isrcmd_param);
Helmut64 0:a3ea811f80f2 760 break;
Helmut64 0:a3ea811f80f2 761 default:
Helmut64 0:a3ea811f80f2 762 EFM_ASSERT(false);
Helmut64 0:a3ea811f80f2 763 break;
Helmut64 0:a3ea811f80f2 764 }
Helmut64 0:a3ea811f80f2 765 usb_isrcmd = CMD_HANDLED;
Helmut64 0:a3ea811f80f2 766 }
Helmut64 0:a3ea811f80f2 767 #endif
Helmut64 0:a3ea811f80f2 768
Helmut64 0:a3ea811f80f2 769 // End of file