|
| 1 | +/* Copyright (c) 2010-2011 mbed.org, MIT License |
| 2 | +* |
| 3 | +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
| 4 | +* and associated documentation files (the "Software"), to deal in the Software without |
| 5 | +* restriction, including without limitation the rights to use, copy, modify, merge, publish, |
| 6 | +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the |
| 7 | +* Software is furnished to do so, subject to the following conditions: |
| 8 | +* |
| 9 | +* The above copyright notice and this permission notice shall be included in all copies or |
| 10 | +* substantial portions of the Software. |
| 11 | +* |
| 12 | +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
| 13 | +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 14 | +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| 15 | +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 16 | +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 17 | +*/ |
| 18 | +#if (defined (USB_STM_HAL) && defined(TARGET_STM32F4)) \ |
| 19 | +|| defined(TARGET_STM32F2) || defined (TARGET_STM32F7) || defined (TARGET_STM32F3) || defined (TARGET_STM32L4) |
| 20 | + |
| 21 | +#include "USBHAL.h" |
| 22 | +#include "pinmap.h" |
| 23 | +/* mbed endpoint definition to hal definition */ |
| 24 | +#define EP_ADDR(ep) (((ep) >> 1)|((ep) & 1) << 7) |
| 25 | +/* from hal definition to mbed definition */ |
| 26 | +#define ADDR_EPIN(ep) (((ep) << 1) | 1) |
| 27 | +#define ADDR_EPOUT(ep) (((ep) << 1)) |
| 28 | +/* id to detect if rx buffer is used or not */ |
| 29 | + |
| 30 | +#include "USBHAL_STM_TARGET.h" |
| 31 | + |
| 32 | + |
| 33 | +/* this call at device reception completion on a Out Enpoint */ |
| 34 | +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) |
| 35 | +{ |
| 36 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 37 | + USBHAL *obj= priv->inst; |
| 38 | + uint8_t endpoint = ADDR_EPOUT(epnum); |
| 39 | + priv->epComplete[endpoint] = 1; |
| 40 | + /* -2 endpoint 0 In out are not in call back list */ |
| 41 | + if (epnum) { |
| 42 | + bool (USBHAL::*func)(void) = priv->epCallback[endpoint-2]; |
| 43 | + (obj->*func)(); |
| 44 | + } else { |
| 45 | + void (USBHAL::*func)(void) = priv->ep0_out; |
| 46 | + (obj->*func)(); |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +/* this is call at device transmission completion on In endpoint */ |
| 51 | +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) |
| 52 | +{ |
| 53 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 54 | + USBHAL *obj= priv->inst; |
| 55 | + uint8_t endpoint = ADDR_EPIN(epnum); |
| 56 | + priv->epComplete[endpoint] = 1; |
| 57 | + /* -2 endpoint 0 In out are not in call back list */ |
| 58 | + if (epnum) { |
| 59 | + bool (USBHAL::*func)(void) = priv->epCallback[endpoint-2]; |
| 60 | + (obj->*func)(); |
| 61 | + } else { |
| 62 | + void (USBHAL::*func)(void) = priv->ep0_in; |
| 63 | + (obj->*func)(); |
| 64 | + } |
| 65 | +} |
| 66 | +/* This is call at device set up reception */ |
| 67 | +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) |
| 68 | +{ |
| 69 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 70 | + USBHAL *obj= priv->inst; |
| 71 | + void (USBHAL::*func)(void)=priv->ep0_setup; |
| 72 | + void (USBHAL::*func1)(void)=priv->ep0_read; |
| 73 | + (obj->*func)(); |
| 74 | + (obj->*func1)(); |
| 75 | +} |
| 76 | + |
| 77 | +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) |
| 78 | +{ |
| 79 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 80 | + USBHAL *obj= priv->inst; |
| 81 | + void (USBHAL::*func)(unsigned int suspended) = priv->suspend_change; |
| 82 | + (obj->*func)(1); |
| 83 | +} |
| 84 | + |
| 85 | +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) |
| 86 | +{ |
| 87 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 88 | + USBHAL *obj= priv->inst; |
| 89 | + void (USBHAL::*func)(unsigned int suspended) = priv->suspend_change; |
| 90 | + (obj->*func)(0); |
| 91 | +} |
| 92 | + |
| 93 | +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) |
| 94 | +{ |
| 95 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 96 | + USBHAL *obj= priv->inst; |
| 97 | + void (USBHAL::*func)(unsigned int suspended) = priv->connect_change; |
| 98 | + (obj->*func)(1); |
| 99 | +} |
| 100 | + |
| 101 | +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) |
| 102 | +{ |
| 103 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 104 | + USBHAL *obj= priv->inst; |
| 105 | + void (USBHAL::*func)(unsigned int suspended) = priv->connect_change; |
| 106 | + (obj->*func)(0); |
| 107 | +} |
| 108 | + |
| 109 | +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) |
| 110 | +{ |
| 111 | + USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); |
| 112 | + USBHAL *obj= priv->inst; |
| 113 | + unsigned int i; |
| 114 | + for(i=0;i<hpcd->Init.dev_endpoints;i++) { |
| 115 | + priv->epComplete[2*i]=0; |
| 116 | + HAL_PCD_EP_Close(hpcd,EP_ADDR(2*i)); |
| 117 | + HAL_PCD_EP_Flush(hpcd,EP_ADDR(2*i)); |
| 118 | + priv->epComplete[2*i+1]=0; |
| 119 | + HAL_PCD_EP_Close(hpcd,EP_ADDR(2*i+1)); |
| 120 | + HAL_PCD_EP_Flush(hpcd,EP_ADDR(2*i+1)); |
| 121 | + |
| 122 | + } |
| 123 | + void (USBHAL::*func)(void)=priv->bus_reset; |
| 124 | + bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) = priv->ep_realise; |
| 125 | + (obj->*func)(); |
| 126 | + (obj->*ep_realise)(EP0IN, MAX_PACKET_SIZE_EP0,0); |
| 127 | + (obj->*ep_realise)(EP0OUT, MAX_PACKET_SIZE_EP0,0); |
| 128 | +} |
| 129 | + |
| 130 | + |
| 131 | +/* hal pcd handler , used for STM32 HAL PCD Layer */ |
| 132 | + |
| 133 | +uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { |
| 134 | + return 0; |
| 135 | +} |
| 136 | + |
| 137 | +USBHAL::~USBHAL(void) { |
| 138 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); |
| 139 | + HAL_PCD_DeInit(&hpcd); |
| 140 | + delete HALPriv; |
| 141 | +} |
| 142 | + |
| 143 | +void USBHAL::connect(void) { |
| 144 | + NVIC_EnableIRQ(USBHAL_IRQn); |
| 145 | +} |
| 146 | + |
| 147 | +void USBHAL::disconnect(void) { |
| 148 | + NVIC_DisableIRQ(USBHAL_IRQn); |
| 149 | +} |
| 150 | + |
| 151 | +void USBHAL::configureDevice(void) { |
| 152 | + // Not needed |
| 153 | +} |
| 154 | + |
| 155 | +void USBHAL::unconfigureDevice(void) { |
| 156 | + // Not needed |
| 157 | +} |
| 158 | + |
| 159 | +void USBHAL::setAddress(uint8_t address) { |
| 160 | + HAL_PCD_SetAddress(&hpcd, address); |
| 161 | + EP0write(0, 0); |
| 162 | +} |
| 163 | + |
| 164 | +bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { |
| 165 | + uint32_t epIndex = EP_ADDR(endpoint); |
| 166 | + uint32_t type; |
| 167 | + uint32_t len; |
| 168 | + HAL_StatusTypeDef ret; |
| 169 | + switch (endpoint) { |
| 170 | + case EP0IN: |
| 171 | + case EP0OUT: |
| 172 | + type = 0; |
| 173 | + break; |
| 174 | + case EPISO_IN: |
| 175 | + case EPISO_OUT: |
| 176 | + type = 1; |
| 177 | + break; |
| 178 | + case EPBULK_IN: |
| 179 | + case EPBULK_OUT: |
| 180 | + type = 2; |
| 181 | + break; |
| 182 | + case EPINT_IN: |
| 183 | + case EPINT_OUT: |
| 184 | + type = 3; |
| 185 | + break; |
| 186 | + } |
| 187 | + if (maxPacket > MAXTRANSFER_SIZE) return false; |
| 188 | + if (epIndex & 0x80) { |
| 189 | + len = HAL_PCDEx_GetTxFiFo(&hpcd,epIndex & 0x7f); |
| 190 | + MBED_ASSERT(len >= maxPacket); |
| 191 | + } |
| 192 | + ret = HAL_PCD_EP_Open(&hpcd, epIndex, maxPacket, type); |
| 193 | + MBED_ASSERT(ret!=HAL_BUSY); |
| 194 | + return (ret == HAL_OK) ? true:false; |
| 195 | +} |
| 196 | + |
| 197 | +// read setup packet |
| 198 | +void USBHAL::EP0setup(uint8_t *buffer) { |
| 199 | + memcpy(buffer, hpcd.Setup, MAX_PACKET_SIZE_SETUP); |
| 200 | + memset(hpcd.Setup,0,MAX_PACKET_SIZE_SETUP); |
| 201 | +} |
| 202 | + |
| 203 | +void USBHAL::EP0readStage(void) { |
| 204 | +} |
| 205 | + |
| 206 | +void USBHAL::EP0read(void) { |
| 207 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)hpcd.pData; |
| 208 | + uint32_t epIndex = EP_ADDR(EP0OUT); |
| 209 | + uint8_t *pBuf = (uint8_t *)HALPriv->pBufRx0; |
| 210 | + HAL_StatusTypeDef ret; |
| 211 | + HALPriv->epComplete[EP0OUT] = 2; |
| 212 | + ret = HAL_PCD_EP_Receive(&hpcd, epIndex, pBuf, MAX_PACKET_SIZE_EP0 ); |
| 213 | + MBED_ASSERT(ret!=HAL_BUSY); |
| 214 | + |
| 215 | +} |
| 216 | + |
| 217 | +uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { |
| 218 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)hpcd.pData; |
| 219 | + uint32_t length = (uint32_t) HAL_PCD_EP_GetRxCount(&hpcd, 0); |
| 220 | + HALPriv->epComplete[EP0OUT] = 0; |
| 221 | + if (length) { |
| 222 | + uint8_t *buff = (uint8_t *)HALPriv->pBufRx0; |
| 223 | + memcpy(buffer, buff, length); |
| 224 | + } |
| 225 | + return length; |
| 226 | +} |
| 227 | + |
| 228 | +void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { |
| 229 | + /* check that endpoint maximum size is not exceeding TX fifo */ |
| 230 | + MBED_ASSERT(hpcd.IN_ep[0].maxpacket >= size); |
| 231 | + endpointWrite(EP0IN, buffer, size); |
| 232 | +} |
| 233 | + |
| 234 | +void USBHAL::EP0getWriteResult(void) { |
| 235 | + |
| 236 | +} |
| 237 | + |
| 238 | +void USBHAL::EP0stall(void) { |
| 239 | + stallEndpoint(EP0IN); |
| 240 | +} |
| 241 | + |
| 242 | +EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { |
| 243 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); |
| 244 | + uint32_t epIndex = EP_ADDR(endpoint); |
| 245 | + uint8_t* pBuf = (uint8_t *)HALPriv->pBufRx; |
| 246 | + HAL_StatusTypeDef ret; |
| 247 | + // clean reception end flag before requesting reception |
| 248 | + HALPriv->epComplete[endpoint] = 2; |
| 249 | + ret = HAL_PCD_EP_Receive(&hpcd, epIndex, pBuf, maximumSize); |
| 250 | + MBED_ASSERT(ret!=HAL_BUSY); |
| 251 | + return EP_PENDING; |
| 252 | +} |
| 253 | + |
| 254 | +EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { |
| 255 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); |
| 256 | + if (HALPriv->epComplete[endpoint]==0) { |
| 257 | + /* no reception possible !!! */ |
| 258 | + bytesRead = 0; |
| 259 | + return EP_COMPLETED; |
| 260 | + }else if ((HALPriv->epComplete[endpoint]!=1)) |
| 261 | + return EP_PENDING; |
| 262 | + uint32_t epIndex = EP_ADDR(endpoint); |
| 263 | + uint8_t *buff = (uint8_t *)HALPriv->pBufRx; |
| 264 | + uint32_t length = (uint32_t) HAL_PCD_EP_GetRxCount(&hpcd, epIndex); |
| 265 | + memcpy(buffer, buff, length); |
| 266 | + *bytesRead = length; |
| 267 | + HALPriv->epComplete[endpoint]= 0; |
| 268 | + return EP_COMPLETED; |
| 269 | +} |
| 270 | + |
| 271 | +EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { |
| 272 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); |
| 273 | + uint32_t epIndex = EP_ADDR(endpoint); |
| 274 | + HAL_StatusTypeDef ret; |
| 275 | + // clean transmission end flag before requesting transmission |
| 276 | + HALPriv->epComplete[endpoint] = 2; |
| 277 | + ret = HAL_PCD_EP_Transmit(&hpcd, epIndex, data, size); |
| 278 | + MBED_ASSERT(ret!=HAL_BUSY); |
| 279 | + // update the status |
| 280 | + if (ret != HAL_OK) return EP_INVALID; |
| 281 | + // fix me return is too simple |
| 282 | + return EP_PENDING; |
| 283 | +} |
| 284 | + |
| 285 | +EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { |
| 286 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); |
| 287 | + if (HALPriv->epComplete[endpoint] == 1) |
| 288 | + return EP_COMPLETED; |
| 289 | + return EP_PENDING; |
| 290 | +} |
| 291 | + |
| 292 | +void USBHAL::stallEndpoint(uint8_t endpoint) { |
| 293 | + USBHAL_Private_t *HALPriv = (USBHAL_Private_t *)(hpcd.pData); |
| 294 | + HAL_StatusTypeDef ret; |
| 295 | + HALPriv->epComplete[endpoint] = 0; |
| 296 | + ret = HAL_PCD_EP_SetStall(&hpcd, EP_ADDR(endpoint)); |
| 297 | + MBED_ASSERT(ret!=HAL_BUSY); |
| 298 | +} |
| 299 | + |
| 300 | +void USBHAL::unstallEndpoint(uint8_t endpoint) { |
| 301 | + HAL_StatusTypeDef ret; |
| 302 | + ret = HAL_PCD_EP_ClrStall(&hpcd, EP_ADDR(endpoint)); |
| 303 | + MBED_ASSERT(ret!=HAL_BUSY); |
| 304 | + |
| 305 | +} |
| 306 | + |
| 307 | +bool USBHAL::getEndpointStallState(uint8_t endpoint) { |
| 308 | + return false; |
| 309 | +} |
| 310 | + |
| 311 | +void USBHAL::remoteWakeup(void) { |
| 312 | +} |
| 313 | + |
| 314 | + |
| 315 | +void USBHAL::_usbisr(void) { |
| 316 | + instance->usbisr(); |
| 317 | +} |
| 318 | + |
| 319 | + |
| 320 | +void USBHAL::usbisr(void) { |
| 321 | + |
| 322 | + HAL_PCD_IRQHandler(&instance->hpcd); |
| 323 | +} |
| 324 | +#endif |
| 325 | + |
0 commit comments