Skip to content

Commit

Permalink
Add support for transmitting stdout over USB
Browse files Browse the repository at this point in the history
Adds support for transmitting stdout messages over USB.

Signed-off-by: Nate Karstens <[email protected]>
  • Loading branch information
nkarstens committed Feb 10, 2024
1 parent e77e5c7 commit f3115c7
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 4 deletions.
42 changes: 38 additions & 4 deletions bricks/_common_stm32/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <contiki.h>

#include <pbdrv/config.h>
#include <pbdrv/usb.h>
#include <pbio/main.h>
#include <pbsys/bluetooth.h>

Expand Down Expand Up @@ -128,9 +129,40 @@ int mp_hal_stdin_rx_chr(void) {

// Send string of given length
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
uint32_t size;
pbio_error_t err;

#if PBDRV_CONFIG_USB

const char *usb_ptr = str;
mp_uint_t usb_len = len;

while (usb_len) {
size = usb_len;
err = pbdrv_usb_stdout_tx((const uint8_t *)usb_ptr, &size);

if (err == PBIO_SUCCESS) {
usb_ptr += size;
usb_len -= size;
continue;
}

if (err != PBIO_ERROR_AGAIN) {
// Ignoring error for now. This means
// stdout lost if USB is disconnected.
break;
}

if (usb_len) {
MICROPY_EVENT_POLL_HOOK
}
}

#endif // PBDRV_CONFIG_USB

while (len) {
uint32_t size = len;
pbio_error_t err = pbsys_bluetooth_tx((const uint8_t *)str, &size);
size = len;
err = pbsys_bluetooth_tx((const uint8_t *)str, &size);

if (err == PBIO_SUCCESS) {
str += size;
Expand All @@ -144,12 +176,14 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
return;
}

MICROPY_EVENT_POLL_HOOK
if (len) {
MICROPY_EVENT_POLL_HOOK
}
}
}

void mp_hal_stdout_tx_flush(void) {
while (!pbsys_bluetooth_tx_is_idle()) {
while (!pbsys_bluetooth_tx_is_idle() && !pbdrv_usb_stdout_tx_is_idle()) {
MICROPY_EVENT_POLL_HOOK
}
}
Expand Down
62 changes: 62 additions & 0 deletions lib/pbio/drv/usb/usb_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@
PROCESS(pbdrv_usb_process, "USB");

static uint8_t usb_in_buf[USBD_PYBRICKS_MAX_PACKET_SIZE];
static uint8_t usb_out_buf[USBD_PYBRICKS_MAX_PACKET_SIZE];
static uint8_t usb_stdout_buf[USBD_PYBRICKS_MAX_PACKET_SIZE];
static volatile uint32_t usb_in_sz;
static volatile uint32_t usb_out_sz;
static volatile uint32_t usb_stdout_sz;

static USBD_HandleTypeDef husbd;
static PCD_HandleTypeDef hpcd;
Expand Down Expand Up @@ -130,6 +134,53 @@ void pbdrv_usb_stm32_handle_vbus_irq(bool active) {
process_poll(&pbdrv_usb_process);
}

/**
* Queues data to be transmitted via USB.
* @param data [in] The data to be sent.
* @param size [in, out] The size of @p data in bytes. After return, @p size
* contains the number of bytes actually written.
* @return ::PBIO_SUCCESS if @p data was queued, ::PBIO_ERROR_AGAIN
* if @p data could not be queued at this time (e.g. buffer
* is full), ::PBIO_ERROR_INVALID_OP if there is not an
* active USB connection or ::PBIO_ERROR_NOT_SUPPORTED
* if this platform does not support USB.
*/
pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size) {
uint8_t *ptr = usb_stdout_buf;
uint32_t ptr_len = sizeof(usb_stdout_buf);

// TODO: return PBIO_ERROR_INVALID_OP if not connected

if (usb_stdout_sz) {
return PBIO_ERROR_AGAIN;
}

*ptr = USBD_PYBRICKS_MSG_EVENT;
ptr++;
ptr_len--;

*ptr = PBIO_PYBRICKS_EVENT_WRITE_STDOUT;
ptr++;
ptr_len--;

*size = MIN(*size, ptr_len);
memcpy(ptr, data, *size);

usb_stdout_sz = 1 + 1 + *size;

process_poll(&pbdrv_usb_process);

return PBIO_SUCCESS;
}

/**
* Indicates if there is stdout data waiting to be transmitted over USB.
* @retval false if stdout data is currently being transmitted.
*/
bool pbdrv_usb_stdout_tx_is_idle(void) {
return usb_stdout_sz == 0;
}

/**
* @brief Pybricks_Itf_Init
* Initializes the Pybricks media low layer
Expand All @@ -139,6 +190,8 @@ void pbdrv_usb_stm32_handle_vbus_irq(bool active) {
static USBD_StatusTypeDef Pybricks_Itf_Init(void) {
USBD_Pybricks_SetRxBuffer(&husbd, usb_in_buf);
usb_in_sz = 0;
usb_out_sz = 0;
usb_stdout_sz = 0;

return USBD_OK;
}
Expand Down Expand Up @@ -185,6 +238,7 @@ static USBD_StatusTypeDef Pybricks_Itf_Receive(uint8_t *Buf, uint32_t *Len) {
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static USBD_StatusTypeDef Pybricks_Itf_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum) {
usb_out_sz = 0;
process_poll(&pbdrv_usb_process);
return USBD_OK;
}
Expand Down Expand Up @@ -281,6 +335,14 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
// Prepare to receive the next packet
USBD_Pybricks_ReceivePacket(&husbd);
}

if (!usb_out_sz && usb_stdout_sz) {
memcpy(usb_out_buf, usb_stdout_buf, usb_stdout_sz);
usb_out_sz = usb_stdout_sz;
usb_stdout_sz = 0;

USBD_Pybricks_TransmitPacket(&husbd, usb_out_buf, usb_out_sz);
}
}

PROCESS_END();
Expand Down
21 changes: 21 additions & 0 deletions lib/pbio/include/pbdrv/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <stdbool.h>

#include <pbdrv/config.h>
#include <pbio/error.h>

/**
* Indicates battery charging capabilites that were detected on a USB port.
Expand Down Expand Up @@ -43,6 +44,18 @@ pbdrv_usb_bcd_t pbdrv_usb_get_bcd(void);
*/
bool pbdrv_usb_get_vbus_status(void);

/**
* Transmits the given buffer over the USB stdout stream.
* @return The result of the operation.
*/
pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size);

/**
* Indicates if the USB stdout stream is idle.
* @return true if the USB stdout stream is idle.
*/
bool pbdrv_usb_stdout_tx_is_idle(void);

#else // PBDRV_CONFIG_USB

static inline pbdrv_usb_bcd_t pbdrv_usb_get_bcd(void) {
Expand All @@ -53,6 +66,14 @@ static inline bool pbdrv_usb_get_vbus_status(void) {
return false;
}

static inline pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size) {
return PBIO_SUCCESS;
}

static inline bool pbdrv_usb_stdout_tx_is_idle(void) {
return true;
}

#endif // PBDRV_CONFIG_USB

#endif // _PBDRV_USB_H_
Expand Down

0 comments on commit f3115c7

Please sign in to comment.