USB device stack

Dependents:   USBMSD_step1 USBMSD_step1_5 picossd_step1_2cs

Committer:
Kojto
Date:
Thu Jul 27 12:14:04 2017 +0100
Revision:
71:53949e6131f6
Update libraries

Fixes the previous commmit, as some devices were not copied. USBDevice contains
now targets directory with all targets implementations

Who changed what in which revision?

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