diff options
author | Nikolay Minaylov <nm29719@gmail.com> | 2021-11-04 22:33:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-04 22:33:28 +0300 |
commit | f8d3cc251c1d8d8a56c50208de78396c80ec6de1 (patch) | |
tree | 3961260df438c68157dc19c6609232a3c1c9966c /firmware | |
parent | 3225f408708fafde07d942645c6e739f1c399db4 (diff) |
[FL-1984, FL-2004, FL-2010] USB CDC Fixes (#801)
* [FL-1984, FL-2004] USB-UART Fixes, test with high timer task priority
* added forgotten file
* switch from EventFlags to ThreadFlags
* [FL-1984, FL-2010] USB-UART and furi-hal-vcp rework
* Scripts: modernize string formatting.
Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/targets/f6/furi-hal/furi-hal-console.h | 6 | ||||
-rw-r--r-- | firmware/targets/f6/furi-hal/furi-hal-uart.h | 6 | ||||
-rw-r--r-- | firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c | 16 | ||||
-rw-r--r-- | firmware/targets/f6/furi-hal/furi-hal-vcp.c | 193 | ||||
-rw-r--r-- | firmware/targets/f7/furi-hal/furi-hal-console.h | 6 | ||||
-rw-r--r-- | firmware/targets/f7/furi-hal/furi-hal-uart.c | 4 | ||||
-rw-r--r-- | firmware/targets/f7/furi-hal/furi-hal-uart.h | 6 | ||||
-rw-r--r-- | firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c | 16 | ||||
-rw-r--r-- | firmware/targets/f7/furi-hal/furi-hal-vcp.c | 193 |
9 files changed, 272 insertions, 174 deletions
diff --git a/firmware/targets/f6/furi-hal/furi-hal-console.h b/firmware/targets/f6/furi-hal/furi-hal-console.h index 4c10d81e..637c17f6 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-console.h +++ b/firmware/targets/f6/furi-hal/furi-hal-console.h @@ -7,12 +7,6 @@ extern "C" { #endif -typedef enum { - UartIrqEventRXNE, - UartIrqEventIDLE, - //TODO: more events -} UartIrqEvent; - void furi_hal_console_init(); void furi_hal_console_enable(); diff --git a/firmware/targets/f6/furi-hal/furi-hal-uart.h b/firmware/targets/f6/furi-hal/furi-hal-uart.h index 6be156b7..731a12a2 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-uart.h +++ b/firmware/targets/f6/furi-hal/furi-hal-uart.h @@ -2,7 +2,6 @@ #include <stddef.h> #include <stdint.h> -#include "furi-hal-console.h" #ifdef __cplusplus extern "C" { @@ -13,6 +12,11 @@ typedef enum { FuriHalUartIdLPUART1, } FuriHalUartId; +typedef enum { + UartIrqEventRXNE, + UartIrqEventIDLE, + //TODO: more events +} UartIrqEvent; void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud); diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c index 9386b100..dd82cf16 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c +++ b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c @@ -7,12 +7,12 @@ #include "usb_cdc.h" #define CDC0_RXD_EP 0x01 -#define CDC0_TXD_EP 0x81 -#define CDC0_NTF_EP 0x82 +#define CDC0_TXD_EP 0x82 +#define CDC0_NTF_EP 0x83 -#define CDC1_RXD_EP 0x03 -#define CDC1_TXD_EP 0x83 -#define CDC1_NTF_EP 0x84 +#define CDC1_RXD_EP 0x04 +#define CDC1_TXD_EP 0x85 +#define CDC1_NTF_EP 0x86 #define CDC_NTF_SZ 0x08 @@ -446,10 +446,12 @@ void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { } int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) { + int32_t len = 0; if (if_num == 0) - return usbd_ep_read(usb_dev, CDC0_RXD_EP, buf, max_len); + len = usbd_ep_read(usb_dev, CDC0_RXD_EP, buf, max_len); else - return usbd_ep_read(usb_dev, CDC1_RXD_EP, buf, max_len); + len = usbd_ep_read(usb_dev, CDC1_RXD_EP, buf, max_len); + return ((len < 0) ? 0 : len); } static void cdc_on_wakeup(usbd_device *dev) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-vcp.c b/firmware/targets/f6/furi-hal/furi-hal-vcp.c index b2f17842..b0b47f46 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-vcp.c +++ b/firmware/targets/f6/furi-hal/furi-hal-vcp.c @@ -3,18 +3,28 @@ #include <furi.h> #include <stream_buffer.h> -#define APP_RX_DATA_SIZE CDC_DATA_SZ -#define APP_TX_DATA_SIZE CDC_DATA_SZ -#define FURI_HAL_VCP_RX_BUFFER_SIZE (APP_RX_DATA_SIZE * 16) +#define USB_CDC_PKT_LEN CDC_DATA_SZ #define VCP_IF_NUM 0 +typedef enum { + VcpConnect, + VcpDisconnect, +} VcpEvent; + typedef struct { volatile bool connected; - StreamBufferHandle_t rx_stream; - volatile bool rx_stream_full; + uint8_t rx_buf[USB_CDC_PKT_LEN]; + uint8_t rx_buf_start; + uint8_t rx_buf_len; + + osMessageQueueId_t event_queue; + + osMutexId_t usb_mutex; + + osSemaphoreId_t tx_sem; + osSemaphoreId_t rx_sem; - osSemaphoreId_t tx_semaphore; } FuriHalVcp; static void vcp_on_cdc_tx_complete(); @@ -30,22 +40,21 @@ static CdcCallbacks cdc_cb = { NULL, }; -static FuriHalVcp* furi_hal_vcp = NULL; +static FuriHalVcp* vcp = NULL; static const uint8_t ascii_soh = 0x01; static const uint8_t ascii_eot = 0x04; -static uint8_t* vcp_rx_buf; - void furi_hal_vcp_init() { - furi_hal_vcp = furi_alloc(sizeof(FuriHalVcp)); - vcp_rx_buf = furi_alloc(APP_RX_DATA_SIZE); - furi_hal_vcp->connected = false; - - furi_hal_vcp->rx_stream = xStreamBufferCreate(FURI_HAL_VCP_RX_BUFFER_SIZE, 1); - furi_hal_vcp->rx_stream_full = false; + vcp = furi_alloc(sizeof(FuriHalVcp)); + vcp->connected = false; + + vcp->usb_mutex = osMutexNew(NULL); + + vcp->tx_sem = osSemaphoreNew(1, 1, NULL); + vcp->rx_sem = osSemaphoreNew(1, 0, NULL); - furi_hal_vcp->tx_semaphore = osSemaphoreNew(1, 1, NULL); + vcp->event_queue = osMessageQueueNew(8, sizeof(VcpEvent), NULL); furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); @@ -54,111 +63,149 @@ void furi_hal_vcp_init() { void furi_hal_vcp_enable() { furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); - furi_hal_vcp->connected = true; + VcpEvent evt = VcpConnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + vcp->connected = true; + osSemaphoreRelease(vcp->tx_sem); + osSemaphoreRelease(vcp->rx_sem); } void furi_hal_vcp_disable() { furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL); - furi_hal_vcp->connected = false; - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + VcpEvent evt = VcpDisconnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + vcp->connected = false; + osSemaphoreRelease(vcp->tx_sem); + osSemaphoreRelease(vcp->rx_sem); } -size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { - furi_assert(furi_hal_vcp); +size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { + furi_assert(vcp); + furi_assert(buffer); - size_t received = xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, portMAX_DELAY); + size_t rx_cnt = 0; - if(furi_hal_vcp->rx_stream_full - && xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { - furi_hal_vcp->rx_stream_full = false; + VcpEvent evt = VcpDisconnect; + + if (vcp->rx_buf_len > 0) { + size_t len = (vcp->rx_buf_len > size) ? (size) : (vcp->rx_buf_len); + memcpy(&buffer[rx_cnt], &vcp->rx_buf[vcp->rx_buf_start], len); + vcp->rx_buf_len -= len; + vcp->rx_buf_start += len; + rx_cnt += len; } - return received; + while (rx_cnt < size) { + if (osMessageQueueGet(vcp->event_queue, &evt, NULL, 0) == osOK) { + if (evt == VcpConnect) + buffer[rx_cnt] = ascii_soh; + else { + buffer[rx_cnt] = ascii_eot; + vcp->rx_buf_len = 0; + } + rx_cnt++; + return rx_cnt; + } + + if (osSemaphoreAcquire(vcp->rx_sem, timeout) == osErrorTimeout) + return rx_cnt; + + furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); + size_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->rx_buf, USB_CDC_PKT_LEN); + furi_check(osMutexRelease(vcp->usb_mutex) == osOK); + + vcp->rx_buf_len = len; + vcp->rx_buf_start = 0; + + if (vcp->rx_buf_len > (size - rx_cnt)) { + len = size - rx_cnt; + memcpy(&buffer[rx_cnt], vcp->rx_buf, len); + vcp->rx_buf_len -= len; + vcp->rx_buf_start += len; + } else { + memcpy(&buffer[rx_cnt], vcp->rx_buf, vcp->rx_buf_len); + vcp->rx_buf_len = 0; + } + rx_cnt += len; + } + return rx_cnt; } -size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { - furi_assert(furi_hal_vcp); - return xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, timeout); +size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { + furi_assert(vcp); + + return furi_hal_vcp_rx_with_timeout(buffer, size, portMAX_DELAY); } void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { - furi_assert(furi_hal_vcp); + furi_assert(vcp); - while (size > 0 && furi_hal_vcp->connected) { - furi_check(osSemaphoreAcquire(furi_hal_vcp->tx_semaphore, osWaitForever) == osOK); - if (!furi_hal_vcp->connected) + while (size > 0 && vcp->connected) { + furi_check(osSemaphoreAcquire(vcp->tx_sem, osWaitForever) == osOK); + if (!vcp->connected) break; size_t batch_size = size; - if (batch_size > APP_TX_DATA_SIZE) { - batch_size = APP_TX_DATA_SIZE; + if (batch_size > USB_CDC_PKT_LEN) { + batch_size = USB_CDC_PKT_LEN; } + furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); furi_hal_cdc_send(VCP_IF_NUM, (uint8_t*)buffer, batch_size); + furi_check(osMutexRelease(vcp->usb_mutex) == osOK); + size -= batch_size; buffer += batch_size; } } static void vcp_state_callback(uint8_t state) { - if (state == 1) - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); - else if (furi_hal_vcp->connected) { - furi_hal_vcp->connected = false; - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + if (state == 1) { + osSemaphoreRelease(vcp->rx_sem); + //osSemaphoreRelease(vcp->tx_sem); + } + else if (vcp->connected) { + vcp->connected = false; + osSemaphoreRelease(vcp->rx_sem); + VcpEvent evt = VcpDisconnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + //osSemaphoreRelease(vcp->tx_sem); } } static void vcp_on_cdc_control_line(uint8_t state) { - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; // bit 0: DTR state, bit 1: RTS state - // bool dtr = state & 0b01; bool dtr = state & 0b1; if (dtr) { - if (!furi_hal_vcp->connected) { - furi_hal_vcp->connected = true; - xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_soh, 1, &xHigherPriorityTaskWoken); // SOH - + if (!vcp->connected) { + vcp->connected = true; + VcpEvent evt = VcpConnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); } } else { - if (furi_hal_vcp->connected) { - xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_eot, 1, &xHigherPriorityTaskWoken); // EOT - furi_hal_vcp->connected = false; + if (vcp->connected) { + VcpEvent evt = VcpDisconnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + vcp->connected = false; } } - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); - - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + osSemaphoreRelease(vcp->tx_sem); + osSemaphoreRelease(vcp->rx_sem); } -static void vcp_on_cdc_rx() { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - uint16_t max_len = xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream); - if (max_len > 0) { - if (max_len > APP_RX_DATA_SIZE) - max_len = APP_RX_DATA_SIZE; - int32_t size = furi_hal_cdc_receive(VCP_IF_NUM, vcp_rx_buf, max_len); - - if (size > 0) { - size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, vcp_rx_buf, size, &xHigherPriorityTaskWoken); - furi_check(ret == size); - } - } else { - furi_hal_vcp->rx_stream_full = true; - }; - - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +static void vcp_on_cdc_rx() { + if (vcp->connected == false) + return; + osSemaphoreRelease(vcp->rx_sem); } static void vcp_on_cdc_tx_complete() { - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + osSemaphoreRelease(vcp->tx_sem); } bool furi_hal_vcp_is_connected(void) { - return furi_hal_vcp->connected; + return vcp->connected; } diff --git a/firmware/targets/f7/furi-hal/furi-hal-console.h b/firmware/targets/f7/furi-hal/furi-hal-console.h index 4c10d81e..637c17f6 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-console.h +++ b/firmware/targets/f7/furi-hal/furi-hal-console.h @@ -7,12 +7,6 @@ extern "C" { #endif -typedef enum { - UartIrqEventRXNE, - UartIrqEventIDLE, - //TODO: more events -} UartIrqEvent; - void furi_hal_console_init(); void furi_hal_console_enable(); diff --git a/firmware/targets/f7/furi-hal/furi-hal-uart.c b/firmware/targets/f7/furi-hal/furi-hal-uart.c index c6e74101..ff2d94a7 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-uart.c +++ b/firmware/targets/f7/furi-hal/furi-hal-uart.c @@ -182,6 +182,8 @@ void LPUART1_IRQHandler(void) { } else if (LL_LPUART_IsActiveFlag_IDLE(LPUART1)) { irq_cb[FuriHalUartIdLPUART1](UartIrqEventIDLE, 0); LL_LPUART_ClearFlag_IDLE(LPUART1); + } else if (LL_LPUART_IsActiveFlag_ORE(LPUART1)) { + LL_LPUART_ClearFlag_ORE(LPUART1); } //TODO: more events } @@ -193,5 +195,7 @@ void USART1_IRQHandler(void) { } else if (LL_USART_IsActiveFlag_IDLE(USART1)) { irq_cb[FuriHalUartIdUSART1](UartIrqEventIDLE, 0); LL_USART_ClearFlag_IDLE(USART1); + } else if (LL_USART_IsActiveFlag_ORE(USART1)) { + LL_USART_ClearFlag_ORE(USART1); } } diff --git a/firmware/targets/f7/furi-hal/furi-hal-uart.h b/firmware/targets/f7/furi-hal/furi-hal-uart.h index 6be156b7..731a12a2 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-uart.h +++ b/firmware/targets/f7/furi-hal/furi-hal-uart.h @@ -2,7 +2,6 @@ #include <stddef.h> #include <stdint.h> -#include "furi-hal-console.h" #ifdef __cplusplus extern "C" { @@ -13,6 +12,11 @@ typedef enum { FuriHalUartIdLPUART1, } FuriHalUartId; +typedef enum { + UartIrqEventRXNE, + UartIrqEventIDLE, + //TODO: more events +} UartIrqEvent; void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud); diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c index 9386b100..dd82cf16 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c +++ b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c @@ -7,12 +7,12 @@ #include "usb_cdc.h" #define CDC0_RXD_EP 0x01 -#define CDC0_TXD_EP 0x81 -#define CDC0_NTF_EP 0x82 +#define CDC0_TXD_EP 0x82 +#define CDC0_NTF_EP 0x83 -#define CDC1_RXD_EP 0x03 -#define CDC1_TXD_EP 0x83 -#define CDC1_NTF_EP 0x84 +#define CDC1_RXD_EP 0x04 +#define CDC1_TXD_EP 0x85 +#define CDC1_NTF_EP 0x86 #define CDC_NTF_SZ 0x08 @@ -446,10 +446,12 @@ void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { } int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) { + int32_t len = 0; if (if_num == 0) - return usbd_ep_read(usb_dev, CDC0_RXD_EP, buf, max_len); + len = usbd_ep_read(usb_dev, CDC0_RXD_EP, buf, max_len); else - return usbd_ep_read(usb_dev, CDC1_RXD_EP, buf, max_len); + len = usbd_ep_read(usb_dev, CDC1_RXD_EP, buf, max_len); + return ((len < 0) ? 0 : len); } static void cdc_on_wakeup(usbd_device *dev) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-vcp.c b/firmware/targets/f7/furi-hal/furi-hal-vcp.c index b2f17842..b0b47f46 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-vcp.c +++ b/firmware/targets/f7/furi-hal/furi-hal-vcp.c @@ -3,18 +3,28 @@ #include <furi.h> #include <stream_buffer.h> -#define APP_RX_DATA_SIZE CDC_DATA_SZ -#define APP_TX_DATA_SIZE CDC_DATA_SZ -#define FURI_HAL_VCP_RX_BUFFER_SIZE (APP_RX_DATA_SIZE * 16) +#define USB_CDC_PKT_LEN CDC_DATA_SZ #define VCP_IF_NUM 0 +typedef enum { + VcpConnect, + VcpDisconnect, +} VcpEvent; + typedef struct { volatile bool connected; - StreamBufferHandle_t rx_stream; - volatile bool rx_stream_full; + uint8_t rx_buf[USB_CDC_PKT_LEN]; + uint8_t rx_buf_start; + uint8_t rx_buf_len; + + osMessageQueueId_t event_queue; + + osMutexId_t usb_mutex; + + osSemaphoreId_t tx_sem; + osSemaphoreId_t rx_sem; - osSemaphoreId_t tx_semaphore; } FuriHalVcp; static void vcp_on_cdc_tx_complete(); @@ -30,22 +40,21 @@ static CdcCallbacks cdc_cb = { NULL, }; -static FuriHalVcp* furi_hal_vcp = NULL; +static FuriHalVcp* vcp = NULL; static const uint8_t ascii_soh = 0x01; static const uint8_t ascii_eot = 0x04; -static uint8_t* vcp_rx_buf; - void furi_hal_vcp_init() { - furi_hal_vcp = furi_alloc(sizeof(FuriHalVcp)); - vcp_rx_buf = furi_alloc(APP_RX_DATA_SIZE); - furi_hal_vcp->connected = false; - - furi_hal_vcp->rx_stream = xStreamBufferCreate(FURI_HAL_VCP_RX_BUFFER_SIZE, 1); - furi_hal_vcp->rx_stream_full = false; + vcp = furi_alloc(sizeof(FuriHalVcp)); + vcp->connected = false; + + vcp->usb_mutex = osMutexNew(NULL); + + vcp->tx_sem = osSemaphoreNew(1, 1, NULL); + vcp->rx_sem = osSemaphoreNew(1, 0, NULL); - furi_hal_vcp->tx_semaphore = osSemaphoreNew(1, 1, NULL); + vcp->event_queue = osMessageQueueNew(8, sizeof(VcpEvent), NULL); furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); @@ -54,111 +63,149 @@ void furi_hal_vcp_init() { void furi_hal_vcp_enable() { furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb); - furi_hal_vcp->connected = true; + VcpEvent evt = VcpConnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + vcp->connected = true; + osSemaphoreRelease(vcp->tx_sem); + osSemaphoreRelease(vcp->rx_sem); } void furi_hal_vcp_disable() { furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL); - furi_hal_vcp->connected = false; - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + VcpEvent evt = VcpDisconnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + vcp->connected = false; + osSemaphoreRelease(vcp->tx_sem); + osSemaphoreRelease(vcp->rx_sem); } -size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { - furi_assert(furi_hal_vcp); +size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { + furi_assert(vcp); + furi_assert(buffer); - size_t received = xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, portMAX_DELAY); + size_t rx_cnt = 0; - if(furi_hal_vcp->rx_stream_full - && xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { - furi_hal_vcp->rx_stream_full = false; + VcpEvent evt = VcpDisconnect; + + if (vcp->rx_buf_len > 0) { + size_t len = (vcp->rx_buf_len > size) ? (size) : (vcp->rx_buf_len); + memcpy(&buffer[rx_cnt], &vcp->rx_buf[vcp->rx_buf_start], len); + vcp->rx_buf_len -= len; + vcp->rx_buf_start += len; + rx_cnt += len; } - return received; + while (rx_cnt < size) { + if (osMessageQueueGet(vcp->event_queue, &evt, NULL, 0) == osOK) { + if (evt == VcpConnect) + buffer[rx_cnt] = ascii_soh; + else { + buffer[rx_cnt] = ascii_eot; + vcp->rx_buf_len = 0; + } + rx_cnt++; + return rx_cnt; + } + + if (osSemaphoreAcquire(vcp->rx_sem, timeout) == osErrorTimeout) + return rx_cnt; + + furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); + size_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->rx_buf, USB_CDC_PKT_LEN); + furi_check(osMutexRelease(vcp->usb_mutex) == osOK); + + vcp->rx_buf_len = len; + vcp->rx_buf_start = 0; + + if (vcp->rx_buf_len > (size - rx_cnt)) { + len = size - rx_cnt; + memcpy(&buffer[rx_cnt], vcp->rx_buf, len); + vcp->rx_buf_len -= len; + vcp->rx_buf_start += len; + } else { + memcpy(&buffer[rx_cnt], vcp->rx_buf, vcp->rx_buf_len); + vcp->rx_buf_len = 0; + } + rx_cnt += len; + } + return rx_cnt; } -size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { - furi_assert(furi_hal_vcp); - return xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, timeout); +size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { + furi_assert(vcp); + + return furi_hal_vcp_rx_with_timeout(buffer, size, portMAX_DELAY); } void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { - furi_assert(furi_hal_vcp); + furi_assert(vcp); - while (size > 0 && furi_hal_vcp->connected) { - furi_check(osSemaphoreAcquire(furi_hal_vcp->tx_semaphore, osWaitForever) == osOK); - if (!furi_hal_vcp->connected) + while (size > 0 && vcp->connected) { + furi_check(osSemaphoreAcquire(vcp->tx_sem, osWaitForever) == osOK); + if (!vcp->connected) break; size_t batch_size = size; - if (batch_size > APP_TX_DATA_SIZE) { - batch_size = APP_TX_DATA_SIZE; + if (batch_size > USB_CDC_PKT_LEN) { + batch_size = USB_CDC_PKT_LEN; } + furi_check(osMutexAcquire(vcp->usb_mutex, osWaitForever) == osOK); furi_hal_cdc_send(VCP_IF_NUM, (uint8_t*)buffer, batch_size); + furi_check(osMutexRelease(vcp->usb_mutex) == osOK); + size -= batch_size; buffer += batch_size; } } static void vcp_state_callback(uint8_t state) { - if (state == 1) - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); - else if (furi_hal_vcp->connected) { - furi_hal_vcp->connected = false; - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + if (state == 1) { + osSemaphoreRelease(vcp->rx_sem); + //osSemaphoreRelease(vcp->tx_sem); + } + else if (vcp->connected) { + vcp->connected = false; + osSemaphoreRelease(vcp->rx_sem); + VcpEvent evt = VcpDisconnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + //osSemaphoreRelease(vcp->tx_sem); } } static void vcp_on_cdc_control_line(uint8_t state) { - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; // bit 0: DTR state, bit 1: RTS state - // bool dtr = state & 0b01; bool dtr = state & 0b1; if (dtr) { - if (!furi_hal_vcp->connected) { - furi_hal_vcp->connected = true; - xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_soh, 1, &xHigherPriorityTaskWoken); // SOH - + if (!vcp->connected) { + vcp->connected = true; + VcpEvent evt = VcpConnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); } } else { - if (furi_hal_vcp->connected) { - xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_eot, 1, &xHigherPriorityTaskWoken); // EOT - furi_hal_vcp->connected = false; + if (vcp->connected) { + VcpEvent evt = VcpDisconnect; + osMessageQueuePut(vcp->event_queue, &evt, 0, 0); + vcp->connected = false; } } - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); - - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + osSemaphoreRelease(vcp->tx_sem); + osSemaphoreRelease(vcp->rx_sem); } -static void vcp_on_cdc_rx() { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - uint16_t max_len = xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream); - if (max_len > 0) { - if (max_len > APP_RX_DATA_SIZE) - max_len = APP_RX_DATA_SIZE; - int32_t size = furi_hal_cdc_receive(VCP_IF_NUM, vcp_rx_buf, max_len); - - if (size > 0) { - size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, vcp_rx_buf, size, &xHigherPriorityTaskWoken); - furi_check(ret == size); - } - } else { - furi_hal_vcp->rx_stream_full = true; - }; - - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +static void vcp_on_cdc_rx() { + if (vcp->connected == false) + return; + osSemaphoreRelease(vcp->rx_sem); } static void vcp_on_cdc_tx_complete() { - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + osSemaphoreRelease(vcp->tx_sem); } bool furi_hal_vcp_is_connected(void) { - return furi_hal_vcp->connected; + return vcp->connected; } |