12#if defined(STM32F4) && defined(HAL_PCD_MODULE_ENABLED)
14#include <usbd_cdc_if.h>
18Stm32F4UsbVcp::CallbackList* Stm32F4UsbVcp::m_callbackList =
nullptr;
19Stm32F4UsbVcp::Stm32F4UsbVcp(USBD_HandleTypeDef& usbHandle, uint8_t usbRxCache[],
size_t usbRxCacheSize):
20 m_handle(&usbHandle), m_usbRxCache(usbRxCache), m_usbRxCacheSize(usbRxCacheSize)
22 m_listMember.member =
this;
23 m_listMember.next =
nullptr;
25 if (m_callbackList ==
nullptr)
27 m_callbackList =&m_listMember;
31 CallbackList* curr = m_callbackList;
32 while (curr->next !=
nullptr)
36 curr->next = &m_listMember;
40void Stm32F4UsbVcp::init()
42 m_interfaceCallbackClass = USBD_CDC;
45 m_interfaceCallbackClass.Init = cdcInitCallback;
46 m_interfaceCallbackClass.DeInit = cdcDeInitCallback;
47 m_interfaceCallbackClass.DataIn = cdcTxCallback;
48 m_interfaceCallbackClass.DataOut = cdcRxCallback;
49 reinterpret_cast<USBD_CDC_ItfTypeDef *
>(m_handle->pUserData)->Control = cdcControlCallback;
52 if (USBD_Stop(m_handle) != USBD_OK)
54 onError(Error(kSemfClassId,
static_cast<uint8_t
>(ErrorCode::Init_Stop)));
56 if (USBD_DeInit(m_handle) != USBD_OK)
58 onError(Error(kSemfClassId,
static_cast<uint8_t
>(ErrorCode::Init_Deinit)));
60 if (USBD_Init(m_handle, &FS_Desc, DEVICE_FS) != USBD_OK)
62 onError(Error(kSemfClassId,
static_cast<uint8_t
>(ErrorCode::Init_Init)));
64 if (USBD_RegisterClass(m_handle, &m_interfaceCallbackClass) != USBD_OK)
66 onError(Error(kSemfClassId,
static_cast<uint8_t
>(ErrorCode::Init_RegisterClass)));
68 if (USBD_CDC_RegisterInterface(m_handle, &USBD_Interface_fops_FS) != USBD_OK)
70 onError(Error(kSemfClassId,
static_cast<uint8_t
>(ErrorCode::Init_RegisterInterface)));
72 if (USBD_Start(m_handle) != USBD_OK)
74 onError(Error(kSemfClassId,
static_cast<uint8_t
>(ErrorCode::Init_Start)));
78void Stm32F4UsbVcp::deinit()
83void Stm32F4UsbVcp::stopRead()
88void Stm32F4UsbVcp::stopWrite()
94void Stm32F4UsbVcp::setFormat(uint8_t bits, WireMode wire, Parity par, StopBits stop, FlowControl flow)
100void Stm32F4UsbVcp::setBaud(uint32_t baud)
106uint8_t Stm32F4UsbVcp::cdcInitCallback(USBD_HandleTypeDef* usb, uint8_t cfgidx)
109 USBD_CDC_HandleTypeDef *hcdc;
111 if (usb->dev_speed == USBD_SPEED_HIGH)
114 USBD_LL_OpenEP(usb, CDC_IN_EP, USBD_EP_TYPE_BULK,
115 CDC_DATA_HS_IN_PACKET_SIZE);
117 usb->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
120 USBD_LL_OpenEP(usb, CDC_OUT_EP, USBD_EP_TYPE_BULK,
121 CDC_DATA_HS_OUT_PACKET_SIZE);
123 usb->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
128 USBD_LL_OpenEP(usb, CDC_IN_EP, USBD_EP_TYPE_BULK,
129 CDC_DATA_FS_IN_PACKET_SIZE);
131 usb->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
134 USBD_LL_OpenEP(usb, CDC_OUT_EP, USBD_EP_TYPE_BULK,
135 CDC_DATA_FS_OUT_PACKET_SIZE);
137 usb->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
140 USBD_LL_OpenEP(usb, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
141 usb->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;
143 for(
auto i = m_callbackList; i !=
nullptr; i = i->next)
145 if (i->member->m_handle == usb)
147 usb->pClassData =
reinterpret_cast<void*
>(&i->member->m_cdcHandle);
148 USBD_CDC_SetRxBuffer(i->member->m_handle, i->member->m_usbRxCache);
153 if (usb->pClassData == NULL)
159 hcdc =
reinterpret_cast<USBD_CDC_HandleTypeDef*
>(usb->pClassData);
162 reinterpret_cast<USBD_CDC_ItfTypeDef *
>(usb->pUserData)->Init();
164 CallbackList* curr = m_callbackList;
165 while(curr !=
nullptr)
167 curr->member->cdcInit(usb);
175 if (usb->dev_speed == USBD_SPEED_HIGH)
178 USBD_LL_PrepareReceive(usb, CDC_OUT_EP, hcdc->RxBuffer,
179 CDC_DATA_HS_OUT_PACKET_SIZE);
184 USBD_LL_PrepareReceive(usb, CDC_OUT_EP, hcdc->RxBuffer,
185 CDC_DATA_FS_OUT_PACKET_SIZE);
191uint8_t Stm32F4UsbVcp::cdcDeInitCallback(USBD_HandleTypeDef *usb, uint8_t cfgidx)
194 USBD_LL_CloseEP(usb, CDC_IN_EP);
195 usb->ep_in[CDC_IN_EP & 0xFU].is_used = 0U;
198 USBD_LL_CloseEP(usb, CDC_OUT_EP);
199 usb->ep_out[CDC_OUT_EP & 0xFU].is_used = 0U;
202 USBD_LL_CloseEP(usb, CDC_CMD_EP);
203 usb->ep_in[CDC_CMD_EP & 0xFU].is_used = 0U;
206 if(usb->pClassData != NULL)
208 (
reinterpret_cast<USBD_CDC_ItfTypeDef*
>(usb->pUserData))->DeInit();
209 usb->pClassData = NULL;
215uint8_t Stm32F4UsbVcp::cdcTxCallback(USBD_HandleTypeDef* usb, uint8_t epnum)
217 uint8_t retVal = USBD_CDC.DataIn(usb, epnum);
218 if ( (retVal == USBD_OK) &&
219 ((
reinterpret_cast<USBD_CDC_HandleTypeDef*
>(usb->pClassData))->TxState == 0U)
222 CallbackList* curr = m_callbackList;
223 while(curr !=
nullptr)
225 curr->member->cdcTx(usb);
232uint8_t Stm32F4UsbVcp::cdcRxCallback(USBD_HandleTypeDef* usb, uint8_t epnum)
234 CallbackList* curr = m_callbackList;
235 while(curr !=
nullptr)
237 curr->member->cdcRx(usb, epnum);
244int8_t Stm32F4UsbVcp::cdcControlCallback(uint8_t cmd, uint8_t pbuf[], uint16_t size)
246 CallbackList* curr = m_callbackList;
247 while(curr !=
nullptr)
249 curr->member->cdcControl(cmd, pbuf, size);
255void Stm32F4UsbVcp::cdcInit(USBD_HandleTypeDef* usb)
259 m_usbRxCacheWritePos = 0;
260 m_usbRxCacheReadPos = 0;
264void Stm32F4UsbVcp::cdcTx(USBD_HandleTypeDef* usb)
272void Stm32F4UsbVcp::cdcRx(USBD_HandleTypeDef* usb, uint8_t epnum)
276 size_t numOfRxData = USBD_LL_GetRxDataSize(usb, epnum);
279 memcpy(&m_rxData[m_rxDataAvailable], &m_usbRxCache[m_usbRxCacheReadPos],
280 std::min(numOfRxData, m_rxDataSize - m_rxDataAvailable));
281 m_usbRxCacheReadPos += std::min(numOfRxData, m_rxDataSize - m_rxDataAvailable);
282 m_usbRxCacheWritePos += numOfRxData;
283 m_rxDataAvailable += std::min(numOfRxData, m_rxDataSize);
284 if (m_rxDataAvailable == m_rxDataSize)
289 if(usb->dev_speed == USBD_SPEED_HIGH)
291 if (m_usbRxCacheSize < (m_usbRxCacheWritePos + CDC_DATA_HS_OUT_PACKET_SIZE))
293 m_usbRxCacheWritePos = 0;
294 m_usbRxCacheReadPos = 0;
299 if (m_usbRxCacheSize < (m_usbRxCacheWritePos + CDC_DATA_FS_OUT_PACKET_SIZE))
301 m_usbRxCacheWritePos = 0;
302 m_usbRxCacheReadPos = 0;
306 USBD_CDC_SetRxBuffer(m_handle, &m_usbRxCache[m_usbRxCacheWritePos]);
307 USBD_CDC_ReceivePacket(usb);
311void Stm32F4UsbVcp::cdcControl(uint8_t cmd, uint8_t pbuf[], uint16_t size)
315 case CDC_SEND_ENCAPSULATED_COMMAND:
317 case CDC_GET_ENCAPSULATED_RESPONSE:
319 case CDC_SET_COMM_FEATURE:
321 case CDC_GET_COMM_FEATURE:
323 case CDC_CLEAR_COMM_FEATURE:
325 case CDC_SET_LINE_CODING:
326 m_lineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\
327 (pbuf[2] << 16) | (pbuf[3] << 24));
328 m_lineCoding.format = pbuf[4];
329 m_lineCoding.paritytype = pbuf[5];
330 m_lineCoding.datatype = pbuf[6];
332 case CDC_GET_LINE_CODING:
333 pbuf[0] = (uint8_t)(m_lineCoding.bitrate);
334 pbuf[1] = (uint8_t)(m_lineCoding.bitrate >> 8);
335 pbuf[2] = (uint8_t)(m_lineCoding.bitrate >> 16);
336 pbuf[3] = (uint8_t)(m_lineCoding.bitrate >> 24);
337 pbuf[4] = m_lineCoding.format;
338 pbuf[5] = m_lineCoding.paritytype;
339 pbuf[6] = m_lineCoding.datatype;
341 case CDC_SET_CONTROL_LINE_STATE:
350void Stm32F4UsbVcp::writeHardware(
const uint8_t data[],
size_t size)
353 if (m_handle->dev_state == USBD_STATE_CONFIGURED)
355 if (CDC_Transmit_FS(
const_cast<uint8_t*
>(data), size) != USBD_OK)
368void Stm32F4UsbVcp::readHardware(uint8_t data[],
size_t size)
372 m_rxDataAvailable = 0;
374 if (m_usbRxCacheWritePos > m_usbRxCacheReadPos)
376 memcpy(m_rxData, &m_usbRxCache[m_usbRxCacheReadPos],
377 std::min(m_usbRxCacheWritePos - m_usbRxCacheReadPos, m_rxDataSize));
378 m_rxDataAvailable = std::min(m_usbRxCacheWritePos - m_usbRxCacheReadPos, m_rxDataSize);
379 m_usbRxCacheReadPos += std::min(m_usbRxCacheWritePos - m_usbRxCacheReadPos, m_rxDataSize);
381 if (m_rxDataAvailable == m_rxDataSize)
385 if (m_usbRxCacheWritePos <= m_usbRxCacheReadPos)
387 m_usbRxCacheWritePos = 0;
388 m_usbRxCacheReadPos = 0;
389 USBD_CDC_SetRxBuffer(m_handle, m_usbRxCache);