Version of USBDevice that works for KL25Z on Mbed OS2.
Fork of USBDevice by
targets/TARGET_STM/USBHAL_STM32.cpp
- Committer:
- jeffmajeff
- Date:
- 2017-08-29
- Revision:
- 72:d236bae8866e
- Parent:
- 71:53949e6131f6
File content as of revision 72:d236bae8866e:
/* Copyright (c) 2010-2011 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* TARGET NOT STM does not support this HAL */ #ifndef TARGET_STM #define USBSTM_HAL_UNSUPPORTED #endif /* F4 famlily wihtout USB_STM_HAL use another HAL*/ #if defined(TARGET_STM) && defined(TARGET_STM32F4) && !defined(USB_STM_HAL) #define USBSTM_HAL_UNSUPPORTED #endif #ifndef USBSTM_HAL_UNSUPPORTED #include "USBHAL.h" #include "pinmap.h" /* mbed endpoint definition to hal definition */ #define EP_ADDR(ep) (((ep) >> 1)|((ep) & 1) << 7) /* from hal definition to mbed definition */ #define ADDR_EPIN(ep) (((ep) << 1) | 1) #define ADDR_EPOUT(ep) (((ep) << 1)) /* id to detect if rx buffer is used or not */ #include "USBHAL_STM_TARGET.h" /* this call at device reception completion on a Out Enpoint */ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; uint8_t endpoint = ADDR_EPOUT(epnum); priv->epComplete[endpoint] = 1; /* -2 endpoint 0 In out are not in call back list */ if (epnum) { bool (USBHAL::*func)(void) = priv->epCallback[endpoint-2]; (obj->*func)(); } else { void (USBHAL::*func)(void) = priv->ep0_out; (obj->*func)(); } } /* this is call at device transmission completion on In endpoint */ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; uint8_t endpoint = ADDR_EPIN(epnum); priv->epComplete[endpoint] = 1; /* -2 endpoint 0 In out are not in call back list */ if (epnum) { bool (USBHAL::*func)(void) = priv->epCallback[endpoint-2]; (obj->*func)(); } else { void (USBHAL::*func)(void) = priv->ep0_in; (obj->*func)(); } } /* This is call at device set up reception */ void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; void (USBHAL::*func)(void)=priv->ep0_setup; void (USBHAL::*func1)(void)=priv->ep0_read; (obj->*func)(); (obj->*func1)(); } void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; void (USBHAL::*func)(unsigned int suspended) = priv->suspend_change; (obj->*func)(1); } void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; void (USBHAL::*func)(unsigned int suspended) = priv->suspend_change; (obj->*func)(0); } void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; void (USBHAL::*func)(unsigned int suspended) = priv->connect_change; (obj->*func)(1); } void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; void (USBHAL::*func)(unsigned int suspended) = priv->connect_change; (obj->*func)(0); } void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; unsigned int i; for(i=0;i<hpcd->Init.dev_endpoints;i++) { priv->epComplete[2*i]=0; HAL_PCD_EP_Close(hpcd,EP_ADDR(2*i)); HAL_PCD_EP_Flush(hpcd,EP_ADDR(2*i)); priv->epComplete[2*i+1]=0; HAL_PCD_EP_Close(hpcd,EP_ADDR(2*i+1)); HAL_PCD_EP_Flush(hpcd,EP_ADDR(2*i+1)); } void (USBHAL::*func)(void)=priv->bus_reset; bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) = priv->ep_realise; (obj->*func)(); (obj->*ep_realise)(EP0IN, MAX_PACKET_SIZE_EP0,0); (obj->*ep_realise)(EP0OUT, MAX_PACKET_SIZE_EP0,0); } /* hal pcd handler , used for STM32 HAL PCD Layer */ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { return 0; } USBHAL::~USBHAL(void) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); HAL_PCD_DeInit(&hpcd); delete HALPriv; } void USBHAL::connect(void) { NVIC_EnableIRQ(USBHAL_IRQn); } void USBHAL::disconnect(void) { NVIC_DisableIRQ(USBHAL_IRQn); } void USBHAL::configureDevice(void) { // Not needed } void USBHAL::unconfigureDevice(void) { // Not needed } void USBHAL::setAddress(uint8_t address) { HAL_PCD_SetAddress(&hpcd, address); EP0write(0, 0); } bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { uint32_t epIndex = EP_ADDR(endpoint); uint32_t type; uint32_t len; HAL_StatusTypeDef ret; switch (endpoint) { case EP0IN: case EP0OUT: type = 0; break; case EPISO_IN: case EPISO_OUT: type = 1; break; case EPBULK_IN: case EPBULK_OUT: type = 2; break; case EPINT_IN: case EPINT_OUT: type = 3; break; } if (maxPacket > MAXTRANSFER_SIZE) return false; if (epIndex & 0x80) { len = HAL_PCDEx_GetTxFiFo(&hpcd,epIndex & 0x7f); MBED_ASSERT(len >= maxPacket); } ret = HAL_PCD_EP_Open(&hpcd, epIndex, maxPacket, type); MBED_ASSERT(ret!=HAL_BUSY); return (ret == HAL_OK) ? true:false; } // read setup packet void USBHAL::EP0setup(uint8_t *buffer) { memcpy(buffer, hpcd.Setup, MAX_PACKET_SIZE_SETUP); memset(hpcd.Setup,0,MAX_PACKET_SIZE_SETUP); } void USBHAL::EP0readStage(void) { } void USBHAL::EP0read(void) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)hpcd.pData; uint32_t epIndex = EP_ADDR(EP0OUT); uint8_t *pBuf = (uint8_t *)HALPriv->pBufRx0; HAL_StatusTypeDef ret; HALPriv->epComplete[EP0OUT] = 2; ret = HAL_PCD_EP_Receive(&hpcd, epIndex, pBuf, MAX_PACKET_SIZE_EP0 ); MBED_ASSERT(ret!=HAL_BUSY); } uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)hpcd.pData; uint32_t length = (uint32_t) HAL_PCD_EP_GetRxCount(&hpcd, 0); HALPriv->epComplete[EP0OUT] = 0; if (length) { uint8_t *buff = (uint8_t *)HALPriv->pBufRx0; memcpy(buffer, buff, length); } return length; } void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { /* check that endpoint maximum size is not exceeding TX fifo */ MBED_ASSERT(hpcd.IN_ep[0].maxpacket >= size); endpointWrite(EP0IN, buffer, size); } void USBHAL::EP0getWriteResult(void) { } void USBHAL::EP0stall(void) { stallEndpoint(EP0IN); } EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); uint32_t epIndex = EP_ADDR(endpoint); uint8_t* pBuf = (uint8_t *)HALPriv->pBufRx; HAL_StatusTypeDef ret; // clean reception end flag before requesting reception HALPriv->epComplete[endpoint] = 2; ret = HAL_PCD_EP_Receive(&hpcd, epIndex, pBuf, maximumSize); MBED_ASSERT(ret!=HAL_BUSY); return EP_PENDING; } EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); if (HALPriv->epComplete[endpoint]==0) { /* no reception possible !!! */ bytesRead = 0; return EP_COMPLETED; }else if ((HALPriv->epComplete[endpoint]!=1)) return EP_PENDING; uint32_t epIndex = EP_ADDR(endpoint); uint8_t *buff = (uint8_t *)HALPriv->pBufRx; uint32_t length = (uint32_t) HAL_PCD_EP_GetRxCount(&hpcd, epIndex); memcpy(buffer, buff, length); *bytesRead = length; HALPriv->epComplete[endpoint]= 0; return EP_COMPLETED; } EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); uint32_t epIndex = EP_ADDR(endpoint); HAL_StatusTypeDef ret; // clean transmission end flag before requesting transmission HALPriv->epComplete[endpoint] = 2; ret = HAL_PCD_EP_Transmit(&hpcd, epIndex, data, size); MBED_ASSERT(ret!=HAL_BUSY); // update the status if (ret != HAL_OK) return EP_INVALID; // fix me return is too simple return EP_PENDING; } EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); if (HALPriv->epComplete[endpoint] == 1) return EP_COMPLETED; return EP_PENDING; } void USBHAL::stallEndpoint(uint8_t endpoint) { USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); HAL_StatusTypeDef ret; HALPriv->epComplete[endpoint] = 0; ret = HAL_PCD_EP_SetStall(&hpcd, EP_ADDR(endpoint)); MBED_ASSERT(ret!=HAL_BUSY); } void USBHAL::unstallEndpoint(uint8_t endpoint) { HAL_StatusTypeDef ret; ret = HAL_PCD_EP_ClrStall(&hpcd, EP_ADDR(endpoint)); MBED_ASSERT(ret!=HAL_BUSY); } bool USBHAL::getEndpointStallState(uint8_t endpoint) { return false; } void USBHAL::remoteWakeup(void) { } void USBHAL::_usbisr(void) { instance->usbisr(); } void USBHAL::usbisr(void) { HAL_PCD_IRQHandler(&instance->hpcd); } #endif