USB device stack
Dependents: blinky_max32630fthr FTHR_USB_serial FTHR_OLED HSP_RPC_GUI_3_0_1 ... more
Fork of USBDevice by
USBHAL_EFM32.cpp
00001 /* Copyright 2015 Silicon Labs, http://www.silabs.com 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 #if defined TARGET_EFM32GG_STK3700 || \ 00017 defined TARGET_EFM32LG_STK3600 || \ 00018 defined TARGET_EFM32WG_STK3800 || \ 00019 defined TARGET_EFM32HG_STK3400 00020 00021 #include "USBHAL.h" 00022 #include "em_usb.h" 00023 #include "em_usbtypes.h" 00024 #include "em_usbhal.h" 00025 #include "em_usbd.h" 00026 00027 #include "sleepmodes.h" 00028 00029 enum USBISRCommand { 00030 CMD_HANDLED = 0, 00031 CMD_EP0SETUP, 00032 CMD_EP0IN, 00033 CMD_EP0OUT, 00034 CMD_EP_XFER_COMPLETED, 00035 CMD_SOF, 00036 CMD_BUSRESET, 00037 CMD_SUSPEND_STATE_CHANGED, 00038 CMD_ENUM_END_MARKER 00039 }; 00040 00041 enum IEPStatus { 00042 NOT_CONFIGURED = 0, 00043 IDLE = 1, 00044 READ_PENDING = 2, 00045 WRITE_PENDING = 3, 00046 READ_COMPLETE = 4, 00047 WRITE_COMPLETE = 5, 00048 FAILED_INVALID = 6, 00049 FAILED_STALLED = 7 00050 }; 00051 00052 typedef struct { 00053 IEPStatus status; 00054 uint32_t byte_count; 00055 uint32_t max_packet; 00056 USB_XferCompleteCb_TypeDef intern_cb; 00057 uint8_t *data_buf; 00058 } ep_state_t; 00059 00060 USBHAL * USBHAL::instance; 00061 static uint8_t ep0setupdata[8]; 00062 static ep_state_t ep_state[NUMBER_OF_ENDPOINTS]; 00063 #ifdef USB_USE_DYNAMIC_MEMORY 00064 static uint8_t ep0in_data_buf[MAX_PACKET_SIZE_EP0] __attribute__ ((aligned (4))); 00065 static uint8_t ep0out_data_buf[MAX_PACKET_SIZE_EP0]; // FIXME: does this need to be this big? 00066 #else 00067 static uint8_t ep_data_buf[NUMBER_OF_ENDPOINTS][64] __attribute__ ((aligned (4))); 00068 #endif 00069 00070 static void run_cmd(USBISRCommand cmd, uint32_t param); 00071 static void (*isrptr)() = NULL; 00072 static USBISRCommand usb_isrcmd = CMD_HANDLED; 00073 static uint32_t usb_isrcmd_param = 0; 00074 00075 extern "C" void usbhal_allow_em2(bool allow_em2); 00076 00077 #ifdef DEBUG_USB_API 00078 #define TRACE(fmt,...) printf("USB: %s: " fmt "\n", __func__, __VA_ARGS__); 00079 #define TRACE_FUNC_IN printf("USB: > %s\n",__func__); 00080 #define TRACE_FUNC_IN_P(fmt, ...) printf("USB: > %s: " fmt "\n", __func__, __VA_ARGS__); 00081 #else 00082 #define TRACE(fmt,...) 00083 #define TRACE_FUNC_IN 00084 #define TRACE_FUNC_IN_P(fmt, ...) 00085 #endif 00086 00087 static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize); 00088 00089 static int usbhal_xfer_complete_cb(uint8_t epaddr, USB_Status_TypeDef status, 00090 uint32_t xferred, uint32_t remaining); 00091 static void usbhal_free_buffers(void); 00092 00093 /* Internal EP transfer complete callbacks */ 00094 #define EPCB(n) static int usbhal_xfer_complete_cb_##n(USB_Status_TypeDef status, \ 00095 uint32_t xferred, uint32_t remaining) { \ 00096 return usbhal_xfer_complete_cb(n, status, xferred, remaining); \ 00097 } 00098 /* ------^ */ 00099 EPCB(EP0OUT) 00100 EPCB(EP0IN) 00101 EPCB(EP1OUT) 00102 EPCB(EP1IN) 00103 EPCB(EP2OUT) 00104 EPCB(EP2IN) 00105 EPCB(EP3OUT) 00106 EPCB(EP3IN) 00107 #ifndef TARGET_EFM32HG_STK3400 00108 EPCB(EP4OUT) 00109 EPCB(EP4IN) 00110 EPCB(EP5OUT) 00111 EPCB(EP5IN) 00112 EPCB(EP6OUT) 00113 EPCB(EP6IN) 00114 #endif 00115 00116 static inline bool is_aligned(const void *pointer, size_t byte_count) 00117 { 00118 return ((uintptr_t)pointer % byte_count == 0); 00119 } 00120 00121 USBHAL::USBHAL(void) 00122 { 00123 TRACE_FUNC_IN; 00124 00125 isrptr = &USBHAL::_usbisr; 00126 00127 if (instance) { 00128 TRACE("Assert self failed! instance=%p", instance); 00129 abort(); 00130 } 00131 instance = this; 00132 00133 // When USB is active, we can't go below EM1. This block may 00134 // be dynamically removed/reinstated to allow deeper sleep. 00135 usbhal_allow_em2(false); 00136 00137 // When in suspend / Vbus off we can go to EM2, but never below 00138 // that as long as USB is being used. Despite the name the call here 00139 // blocks entering modes _below_ EM2, but allows EM2. 00140 blockSleepMode(EM2); 00141 00142 epCallback[EP0OUT] = NULL; 00143 epCallback[EP0IN ] = NULL; 00144 epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback; 00145 epCallback[EP1IN ] = &USBHAL::EP1_IN_callback; 00146 epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback; 00147 epCallback[EP2IN ] = &USBHAL::EP2_IN_callback; 00148 epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback; 00149 epCallback[EP3IN ] = &USBHAL::EP3_IN_callback; 00150 #ifndef TARGET_EFM32HG_STK3400 00151 epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback; 00152 epCallback[EP4IN ] = &USBHAL::EP4_IN_callback; 00153 epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback; 00154 epCallback[EP5IN ] = &USBHAL::EP5_IN_callback; 00155 epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback; 00156 epCallback[EP6IN ] = &USBHAL::EP6_IN_callback; 00157 #endif 00158 00159 memset(ep_state, 0, sizeof(ep_state)); 00160 00161 ep_state[EP0OUT].intern_cb = usbhal_xfer_complete_cb_EP0OUT; 00162 ep_state[EP0IN ].intern_cb = usbhal_xfer_complete_cb_EP0IN; 00163 ep_state[EP1OUT].intern_cb = usbhal_xfer_complete_cb_EP1OUT; 00164 ep_state[EP1IN ].intern_cb = usbhal_xfer_complete_cb_EP1IN; 00165 ep_state[EP2OUT].intern_cb = usbhal_xfer_complete_cb_EP2OUT; 00166 ep_state[EP2IN ].intern_cb = usbhal_xfer_complete_cb_EP2IN; 00167 ep_state[EP3OUT].intern_cb = usbhal_xfer_complete_cb_EP3OUT; 00168 ep_state[EP3IN ].intern_cb = usbhal_xfer_complete_cb_EP3IN; 00169 #ifndef TARGET_EFM32HG_STK3400 00170 ep_state[EP4OUT].intern_cb = usbhal_xfer_complete_cb_EP4OUT; 00171 ep_state[EP4IN ].intern_cb = usbhal_xfer_complete_cb_EP4IN; 00172 ep_state[EP5OUT].intern_cb = usbhal_xfer_complete_cb_EP5OUT; 00173 ep_state[EP5IN ].intern_cb = usbhal_xfer_complete_cb_EP5IN; 00174 ep_state[EP6OUT].intern_cb = usbhal_xfer_complete_cb_EP6OUT; 00175 ep_state[EP6IN ].intern_cb = usbhal_xfer_complete_cb_EP6IN; 00176 #endif 00177 00178 #ifdef USB_USE_DYNAMIC_MEMORY 00179 ep_state[EP0OUT].data_buf = ep0out_data_buf; 00180 ep_state[EP0IN].data_buf = ep0in_data_buf; 00181 #else 00182 for (int i=0 ; i<NUMBER_OF_ENDPOINTS ; i++) { 00183 ep_state[i].data_buf = ep_data_buf[i]; 00184 } 00185 #endif 00186 } 00187 00188 USBHAL::~USBHAL(void) 00189 { 00190 TRACE_FUNC_IN; 00191 USBD_AbortAllTransfers(); 00192 USBD_Disconnect(); 00193 usbhal_free_buffers(); 00194 00195 usbhal_allow_em2(true); 00196 unblockSleepMode(EM2); 00197 } 00198 00199 extern "C" void usbhal_allow_em2(bool allow_em2) 00200 { 00201 if (allow_em2) { 00202 // unblockSleepMode is safe to call even if we would unblock 00203 // an already unblocked mode, so no checks here. 00204 unblockSleepMode(EM1); 00205 } else { 00206 blockSleepMode(EM1); 00207 } 00208 } 00209 00210 static void usbhal_reset_cb(void) 00211 { 00212 TRACE_FUNC_IN; 00213 run_cmd(CMD_BUSRESET, 0); 00214 } 00215 00216 #ifdef DEBUG_USB_API 00217 static const char *usbstate[] = { "NONE", "ATTACHED", "POWERED", "DEFAULT", 00218 "ADDRESSED", "CONFIGURED", "SUSPENDED", "???" }; 00219 #endif 00220 00221 static void usbhal_state_change_cb(USBD_State_TypeDef oldState, 00222 USBD_State_TypeDef newState) 00223 { 00224 TRACE("state changed %s -> %s", usbstate[oldState], usbstate[newState]); 00225 00226 if (oldState == USBD_STATE_SUSPENDED) { 00227 run_cmd(CMD_SUSPEND_STATE_CHANGED, 0); 00228 } 00229 00230 if (newState == USBD_STATE_SUSPENDED) { 00231 run_cmd(CMD_SUSPEND_STATE_CHANGED, 1); 00232 } 00233 00234 // Should call connectStateChanged from here as well but there is 00235 // no documentation on when to actually do so. (And the implementation 00236 // in USBDevice.cpp is a stub) 00237 00238 // HACK! Since connectStateChanged is not used, indicate the loss 00239 // off connection by reporting a bus reset. This causes USBDevice 00240 // to realise that at least it's not in CONFIGURED anymore, and 00241 // stop trying to read/write in a busyloop. 00242 if (newState == USBD_STATE_NONE) { 00243 run_cmd(CMD_BUSRESET, 0); 00244 } 00245 } 00246 00247 static int usbhal_setupcmd_cb(const USB_Setup_TypeDef *setup) 00248 { 00249 TRACE_FUNC_IN; 00250 if (!setup) { 00251 EFM_ASSERT(false); 00252 return USB_STATUS_REQ_ERR; 00253 } 00254 00255 memcpy(ep0setupdata, setup, 8); 00256 run_cmd(CMD_EP0SETUP, 0); 00257 00258 return USB_STATUS_OK; 00259 } 00260 00261 static void usbhal_sof_cb(uint16_t frameNum) 00262 { 00263 run_cmd(CMD_SOF, frameNum); 00264 } 00265 00266 static void usbhal_free_buffers(void) 00267 { 00268 #ifdef USB_USE_DYNAMIC_MEMORY 00269 TRACE_FUNC_IN; 00270 00271 for (int i=EP1OUT ; i<NUMBER_OF_ENDPOINTS ; i++ ) { 00272 if (ep_state[i].data_buf) { 00273 free(ep_state[i].data_buf); 00274 ep_state[i].data_buf = NULL; 00275 } 00276 } 00277 #endif 00278 } 00279 00280 void USBHAL::connect(void) 00281 { 00282 TRACE_FUNC_IN; 00283 00284 // Init datastructures must be static - driver will use these even after the init function exits! 00285 00286 static const uint8_t buffer_multiplier[] = { 1 }; // Mult 1 for control EP 00287 static const USBD_Callbacks_TypeDef usbd_callbacks = { 00288 .usbReset = usbhal_reset_cb, 00289 .usbStateChange = usbhal_state_change_cb, 00290 .setupCmd = usbhal_setupcmd_cb, 00291 .isSelfPowered = NULL, 00292 .sofInt = usbhal_sof_cb 00293 }; 00294 00295 USBD_Init_TypeDef initdata = { 00296 .deviceDescriptor = NULL, 00297 .configDescriptor = NULL, 00298 .stringDescriptors = NULL, 00299 .numberOfStrings = 0, 00300 .bufferingMultiplier = buffer_multiplier, 00301 .callbacks = &usbd_callbacks, 00302 .reserved = 0 00303 }; 00304 00305 int ret = USBD_Init(&initdata); 00306 00307 TRACE("init = %d, devicedesc = %lx, configdesc = %lx", ret, 00308 (uint32_t) initdata.deviceDescriptor, 00309 (uint32_t) initdata.configDescriptor); 00310 00311 EFM_ASSERT(ret == USB_STATUS_OK); 00312 } 00313 00314 void USBHAL::disconnect(void) 00315 { 00316 TRACE_FUNC_IN; 00317 USBD_Disconnect(); 00318 } 00319 00320 void USBHAL::configureDevice(void) 00321 { 00322 TRACE_FUNC_IN; 00323 USBD_SetUsbState(USBD_STATE_CONFIGURED); 00324 } 00325 00326 void USBHAL::unconfigureDevice(void) 00327 { 00328 TRACE_FUNC_IN; 00329 USBD_SetUsbState(USBD_STATE_DEFAULT); 00330 usbhal_free_buffers(); 00331 } 00332 00333 void USBHAL::setAddress(uint8_t address) 00334 { 00335 TRACE_FUNC_IN_P("addr 0x%x", (unsigned)address); 00336 USBD_SetAddress(address); 00337 } 00338 00339 void USBHAL::remoteWakeup(void) 00340 { 00341 TRACE_FUNC_IN; 00342 USBD_RemoteWakeup(); 00343 } 00344 00345 void USBHAL::EP0setup(uint8_t *buffer) 00346 { 00347 TRACE_FUNC_IN; 00348 EFM_ASSERT(buffer); 00349 if (buffer) { 00350 memcpy(buffer, ep0setupdata, 8); 00351 } 00352 } 00353 00354 void USBHAL::EP0read(void) 00355 { 00356 TRACE_FUNC_IN; 00357 (void)internEndpointRead(0, MAX_PACKET_SIZE_EP0); 00358 } 00359 00360 void USBHAL::EP0readStage(void) 00361 { 00362 TRACE_FUNC_IN; 00363 // Not needed 00364 } 00365 00366 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) 00367 { 00368 TRACE_FUNC_IN; 00369 EFM_ASSERT(buffer); 00370 00371 uint32_t read = 0; 00372 endpointReadResult(0, buffer, &read); 00373 return read; 00374 } 00375 00376 static int usbhal_xfer_complete_cb(uint8_t ep, USB_Status_TypeDef status, 00377 uint32_t xferred, uint32_t remaining) 00378 { 00379 TRACE_FUNC_IN_P("ep 0x%x, status %u, xferred %lu, rem %lu", 00380 ep, status, xferred, remaining); 00381 00382 if (ep >= NUMBER_OF_ENDPOINTS) { 00383 EFM_ASSERT(false); 00384 return USB_STATUS_REQ_ERR; 00385 } 00386 00387 switch (ep) { 00388 case EP0OUT: 00389 if (ep_state[EP0OUT].status == READ_PENDING) { 00390 ep_state[EP0OUT].status = READ_COMPLETE; 00391 ep_state[EP0OUT].byte_count = xferred; 00392 // drop zlp 00393 if (xferred == 0) { 00394 break; 00395 } 00396 } 00397 run_cmd(CMD_EP0OUT, 0); 00398 break; 00399 00400 case EP0IN: 00401 run_cmd(CMD_EP0IN, 0); 00402 break; 00403 00404 default: 00405 bool write = ep & 1; 00406 00407 if (status == USB_STATUS_OK) { 00408 if (!write && ep_state[ep].status == READ_PENDING) { 00409 ep_state[ep].status = READ_COMPLETE; 00410 ep_state[ep].byte_count = xferred; 00411 } else if (write && ep_state[ep].status == WRITE_PENDING) { 00412 ep_state[ep].status = WRITE_COMPLETE; 00413 } else { 00414 ep_state[ep].status = FAILED_INVALID; 00415 } 00416 } else { 00417 ep_state[ep].status = FAILED_INVALID; 00418 } 00419 00420 if (ep_state[ep].status != FAILED_INVALID) { 00421 run_cmd(CMD_EP_XFER_COMPLETED, ep); 00422 } 00423 break; 00424 } 00425 00426 return USB_STATUS_OK; 00427 } 00428 00429 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) 00430 { 00431 //TRACE_FUNC_IN_P("buffer %lx, size %lu", (uint32_t) buffer, size); 00432 00433 int ret; 00434 USB_XferCompleteCb_TypeDef cb = ep_state[EP0IN].intern_cb; 00435 00436 EFM_ASSERT((buffer != NULL) || (size == 0)); 00437 EFM_ASSERT(size <= MAX_PACKET_SIZE_EP0); 00438 00439 if (!buffer || size == 0) { 00440 // No callback after writing EP0 ZLP 00441 cb = NULL; 00442 } 00443 00444 if (buffer && !is_aligned(buffer,4)) { 00445 // Copy unaligned data to write-buffer before USBD_Write 00446 memcpy(ep_state[EP0IN].data_buf, buffer, size); 00447 ret = USBD_Write(0, ep_state[EP0IN].data_buf, size, cb); 00448 } else { 00449 ret = USBD_Write(0, buffer, size, cb); 00450 } 00451 00452 if (ret != USB_STATUS_OK) { 00453 TRACE("FAILED - ret %d", ret); 00454 } 00455 } 00456 00457 void USBHAL::EP0stall(void) 00458 { 00459 TRACE_FUNC_IN; 00460 USBD_StallEp0(); 00461 } 00462 00463 static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize) 00464 { 00465 //TRACE_FUNC_IN_P("endpoint 0x%x, size %ld, cb %d", (unsigned)ep, maxSize, useCallback); 00466 00467 if (ep >= NUMBER_OF_ENDPOINTS) { 00468 EFM_ASSERT(false); 00469 return EP_INVALID; 00470 } 00471 00472 ep_state[ep].status = READ_PENDING; 00473 00474 int ret = USBD_Read(USB_EP_TO_ADDR(ep), ep_state[ep].data_buf, maxSize, 00475 ep_state[ep].intern_cb); 00476 00477 if (ret == USB_STATUS_OK) { 00478 return EP_PENDING; 00479 } else { 00480 TRACE("FAILED - ret %d", ret); 00481 00482 if (ret == USB_STATUS_EP_STALLED) { 00483 return EP_STALLED; 00484 } else { 00485 return EP_INVALID; 00486 } 00487 } 00488 } 00489 00490 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) 00491 { 00492 return internEndpointRead(endpoint, maximumSize); 00493 } 00494 00495 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) 00496 { 00497 TRACE_FUNC_IN; 00498 00499 if (endpoint >= NUMBER_OF_ENDPOINTS) { 00500 EFM_ASSERT(false); 00501 return EP_INVALID; 00502 } 00503 00504 EFM_ASSERT(data); 00505 EFM_ASSERT(bytesRead); 00506 if (!data || !bytesRead) { 00507 return EP_INVALID; 00508 } 00509 00510 switch (ep_state[endpoint].status) { 00511 case READ_PENDING: 00512 return EP_PENDING; 00513 00514 case READ_COMPLETE: 00515 memcpy(data, ep_state[endpoint].data_buf, ep_state[endpoint].byte_count); 00516 *bytesRead = ep_state[endpoint].byte_count; 00517 ep_state[endpoint].status = IDLE; 00518 return EP_COMPLETED; 00519 00520 case FAILED_STALLED: 00521 ep_state[endpoint].status = IDLE; 00522 return EP_STALLED; 00523 00524 default: 00525 ep_state[endpoint].status = IDLE; 00526 return EP_INVALID; 00527 } 00528 } 00529 00530 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) 00531 { 00532 TRACE_FUNC_IN_P("endpoint 0x%x, data 0x%lx, size %lu", (unsigned )endpoint, (uint32_t)data, size); 00533 00534 EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS); 00535 EFM_ASSERT(endpoint > EP0IN); 00536 EFM_ASSERT(size <= ep_state[endpoint].max_packet); 00537 EFM_ASSERT(data); 00538 00539 uint8_t ep = USB_EP_TO_INDEX(endpoint); 00540 00541 if (endpoint >= NUMBER_OF_ENDPOINTS || endpoint <= EP0IN) { 00542 return EP_INVALID; 00543 } 00544 00545 if (size > ep_state[endpoint].max_packet) { 00546 return EP_INVALID; 00547 } 00548 00549 if (!data) { 00550 return EP_INVALID; 00551 } 00552 00553 memcpy(ep_state[ep].data_buf, data, size); 00554 00555 ep_state[ep].status = WRITE_PENDING; 00556 int ret = USBD_Write(USB_EP_TO_ADDR(endpoint), ep_state[ep].data_buf, size, ep_state[ep].intern_cb); 00557 00558 if (ret == USB_STATUS_EP_STALLED) { 00559 ep_state[ep].status = IDLE; 00560 return EP_STALLED; 00561 } else if (ret != USB_STATUS_OK) { 00562 ep_state[ep].status = IDLE; 00563 return EP_INVALID; 00564 } 00565 00566 return EP_PENDING; 00567 } 00568 00569 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) 00570 { 00571 if (endpoint >= NUMBER_OF_ENDPOINTS) { 00572 EFM_ASSERT(false); 00573 return EP_INVALID; 00574 } 00575 00576 switch (ep_state[endpoint].status) { 00577 case WRITE_PENDING: 00578 return EP_PENDING; 00579 00580 case WRITE_COMPLETE: 00581 ep_state[endpoint].status = IDLE; 00582 return EP_COMPLETED; 00583 00584 case FAILED_STALLED: 00585 ep_state[endpoint].status = IDLE; 00586 return EP_STALLED; 00587 00588 default: 00589 ep_state[endpoint].status = IDLE; 00590 return EP_INVALID; 00591 } 00592 } 00593 00594 void USBHAL::stallEndpoint(uint8_t endpoint) 00595 { 00596 TRACE_FUNC_IN; 00597 00598 EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS); 00599 EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN)); 00600 00601 USBD_StallEp(USB_EP_TO_ADDR(endpoint)); 00602 } 00603 00604 void USBHAL::unstallEndpoint(uint8_t endpoint) 00605 { 00606 TRACE_FUNC_IN; 00607 00608 EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS); 00609 EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN)); 00610 00611 USBD_UnStallEp(USB_EP_TO_ADDR(endpoint)); 00612 } 00613 00614 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) 00615 { 00616 TRACE_FUNC_IN_P("endpoint %d, packetsize %ld, options 0x%lx", endpoint, 00617 maxPacket, options); 00618 00619 int mult = 1; // RX/TX buffer size multiplier 00620 int type = USB_EPTYPE_INTR; 00621 00622 if (endpoint >= NUMBER_OF_ENDPOINTS) { 00623 EFM_ASSERT(false); 00624 return false; 00625 } 00626 00627 if (endpoint == EP0IN || endpoint == EP0OUT) { 00628 EFM_ASSERT(false); 00629 return false; 00630 } 00631 00632 ep_state[endpoint].max_packet = 0; 00633 00634 if (endpoint == EPISO_OUT || endpoint == EPISO_IN) { 00635 if (maxPacket > MAX_PACKET_SIZE_EPISO) { 00636 EFM_ASSERT(false); 00637 return false; 00638 } 00639 } else if ((maxPacket > MAX_PACKET_SIZE_EPBULK) || (maxPacket > MAX_PACKET_SIZE_EPINT)) { 00640 EFM_ASSERT(false); 00641 return false; 00642 } 00643 00644 // USBDevice performs a read right after creating the endpoints, 00645 // before calling configureDevice. The read will fail since 00646 // at that point the device state is still ADDRESSED. Workaround 00647 // is to force configured state here. 00648 // 00649 // This relies on USBDevice to not call realiseEndpoint unless 00650 // it is transitioning to the CONFIGURED state. 00651 USBD_SetUsbState(USBD_STATE_CONFIGURED); 00652 00653 // Why doesn't this function have a type param? This is silly... 00654 switch (endpoint) { 00655 case EPBULK_OUT: 00656 case EPBULK_IN: 00657 type = USB_EPTYPE_BULK; 00658 mult = 2; 00659 break; 00660 case EPINT_OUT: 00661 case EPINT_IN: 00662 type = USB_EPTYPE_INTR; 00663 mult = 1; 00664 break; 00665 case EPISO_OUT: 00666 case EPISO_IN: 00667 type = USB_EPTYPE_ISOC; 00668 mult = 2; // ? 00669 break; 00670 } 00671 00672 // Some options force the endpoint to a specific type 00673 if( options & ISOCHRONOUS ) { 00674 type = USB_EPTYPE_ISOC; 00675 mult = 2; // ? 00676 } else if ( options & RATE_FEEDBACK_MODE ) { 00677 // No support for whatever rate feedback is, but for interrupt only 00678 type = USB_EPTYPE_INTR; 00679 mult = 1; 00680 } 00681 00682 #ifdef USB_USE_DYNAMIC_MEMORY 00683 if (ep_state[endpoint].data_buf) { 00684 free(ep_state[endpoint].data_buf); 00685 } 00686 00687 ep_state[endpoint].data_buf = (uint8_t *)malloc(maxPacket); 00688 00689 if (!ep_state[endpoint].data_buf) { 00690 EFM_ASSERT(false); 00691 return false; 00692 } 00693 #endif 00694 00695 int ret = USBD_AddEndpoint(USB_EP_TO_ADDR(endpoint), type, maxPacket, mult); 00696 00697 if (ret == USB_STATUS_OK) { 00698 ep_state[endpoint].status = IDLE; 00699 ep_state[endpoint].max_packet = maxPacket; 00700 return true; 00701 } else { 00702 return false; 00703 } 00704 } 00705 00706 bool USBHAL::getEndpointStallState(unsigned char endpoint) 00707 { 00708 TRACE_FUNC_IN; 00709 if (endpoint >= NUMBER_OF_ENDPOINTS) { 00710 EFM_ASSERT(false); 00711 return false; 00712 } 00713 return USBD_EpIsStalled(USB_EP_TO_ADDR(endpoint)); 00714 } 00715 00716 static void run_cmd(USBISRCommand cmd, uint32_t param) 00717 { 00718 if (usb_isrcmd != CMD_HANDLED || cmd >= CMD_ENUM_END_MARKER) { 00719 EFM_ASSERT(false); 00720 abort(); 00721 } 00722 00723 usb_isrcmd = cmd; 00724 usb_isrcmd_param = param; 00725 isrptr(); 00726 } 00727 00728 void USBHAL::_usbisr(void) 00729 { 00730 EFM_ASSERT(instance); 00731 instance->usbisr(); 00732 } 00733 00734 void USBHAL::usbisr(void) 00735 { 00736 //TRACE_FUNC_IN; 00737 00738 // This "ISR" is used just to route callbacks from SiL USB driver 00739 // callback context (which can not call protected/private USBHAL 00740 // methods), to the actual USBHAL. 00741 00742 EFM_ASSERT(usb_isrcmd != CMD_HANDLED); 00743 switch (usb_isrcmd) { 00744 case CMD_EP0SETUP: 00745 this->EP0setupCallback(); 00746 break; 00747 case CMD_EP0IN: 00748 this->EP0in(); 00749 break; 00750 case CMD_EP0OUT: 00751 this->EP0out(); 00752 break; 00753 case CMD_BUSRESET: 00754 this->busReset(); 00755 break; 00756 case CMD_EP_XFER_COMPLETED: 00757 if (epCallback[usb_isrcmd_param] && instance) { 00758 (instance->*(epCallback[usb_isrcmd_param]))(); 00759 } 00760 break; 00761 case CMD_SOF: 00762 this->SOF(usb_isrcmd_param); 00763 break; 00764 case CMD_SUSPEND_STATE_CHANGED: 00765 this->suspendStateChanged(usb_isrcmd_param); 00766 break; 00767 default: 00768 EFM_ASSERT(false); 00769 break; 00770 } 00771 usb_isrcmd = CMD_HANDLED; 00772 } 00773 #endif 00774 00775 // End of file
Generated on Wed Jul 13 2022 12:44:03 by 1.7.2