Skip to content

Commit 75cbbf5

Browse files
nkarstensdlech
authored andcommitted
pbdrv/usb: Add support for transmitting stdout over USB.
Add partial support for transmitting stdout messages over USB. TODO: Need to add implementation of subscribing to have this not enabled all of the time. Then this can be integrated with the mphal in MicroPython. Signed-off-by: Nate Karstens <[email protected]>
1 parent f7f670d commit 75cbbf5

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

lib/pbio/drv/usb/usb_stm32.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#if PBDRV_CONFIG_USB_STM32F4
99

10+
#include <string.h>
1011
#include <stdbool.h>
1112

1213
#include <contiki.h>
@@ -32,9 +33,11 @@ PROCESS(pbdrv_usb_process, "USB");
3233
static uint8_t usb_in_buf[USBD_PYBRICKS_MAX_PACKET_SIZE] __aligned(4);
3334
static uint8_t usb_response_buf[1 + sizeof(uint32_t)] __aligned(4);
3435
static uint8_t usb_status_buf[1 + PBSYS_STATUS_REPORT_SIZE] __aligned(4);
36+
static uint8_t usb_stdout_buf[USBD_PYBRICKS_MAX_PACKET_SIZE] __aligned(4);
3537
static volatile uint32_t usb_in_sz;
3638
static volatile uint32_t usb_response_sz;
3739
static volatile uint32_t usb_status_sz;
40+
static volatile uint32_t usb_stdout_sz;
3841
static volatile bool transmitting;
3942

4043
static USBD_HandleTypeDef husbd;
@@ -137,6 +140,52 @@ void pbdrv_usb_stm32_handle_vbus_irq(bool active) {
137140
process_poll(&pbdrv_usb_process);
138141
}
139142

143+
/**
144+
* Queues data to be transmitted via USB.
145+
* @param data [in] The data to be sent.
146+
* @param size [in, out] The size of @p data in bytes. After return, @p size
147+
* contains the number of bytes actually written.
148+
* @return ::PBIO_SUCCESS if @p data was queued, ::PBIO_ERROR_AGAIN
149+
* if @p data could not be queued at this time (e.g. buffer
150+
* is full), ::PBIO_ERROR_INVALID_OP if there is not an
151+
* active USB connection or ::PBIO_ERROR_NOT_SUPPORTED
152+
* if this platform does not support USB.
153+
*/
154+
pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size) {
155+
uint8_t *ptr = usb_stdout_buf;
156+
uint32_t ptr_len = sizeof(usb_stdout_buf);
157+
158+
// TODO: return PBIO_ERROR_INVALID_OP if app flag is not set. Also need a
159+
// timeout in case the app crashes and doesn't clear the flag on exit.
160+
161+
if (usb_stdout_sz) {
162+
return PBIO_ERROR_AGAIN;
163+
}
164+
165+
*ptr++ = USBD_PYBRICKS_IN_EP_MSG_EVENT;
166+
ptr_len--;
167+
168+
*ptr++ = PBIO_PYBRICKS_EVENT_WRITE_STDOUT;
169+
ptr_len--;
170+
171+
*size = MIN(*size, ptr_len);
172+
memcpy(ptr, data, *size);
173+
174+
usb_stdout_sz = 1 + 1 + *size;
175+
176+
process_poll(&pbdrv_usb_process);
177+
178+
return PBIO_SUCCESS;
179+
}
180+
181+
/**
182+
* Indicates if there is stdout data waiting to be transmitted over USB.
183+
* @retval false if stdout data is currently being transmitted.
184+
*/
185+
bool pbdrv_usb_stdout_tx_is_idle(void) {
186+
return usb_stdout_sz == 0;
187+
}
188+
140189
/**
141190
* @brief Pybricks_Itf_Init
142191
* Initializes the Pybricks media low layer
@@ -148,6 +197,7 @@ static USBD_StatusTypeDef Pybricks_Itf_Init(void) {
148197
usb_in_sz = 0;
149198
usb_response_sz = 0;
150199
usb_status_sz = 0;
200+
usb_stdout_sz = 0;
151201
transmitting = false;
152202

153203
return USBD_OK;
@@ -197,6 +247,8 @@ static USBD_StatusTypeDef Pybricks_Itf_TransmitCplt(uint8_t *Buf, uint32_t Len,
197247
usb_response_sz = 0;
198248
} else if (Buf == usb_status_buf) {
199249
usb_status_sz = 0;
250+
} else if (Buf == usb_stdout_buf) {
251+
usb_stdout_sz = 0;
200252
} else {
201253
ret = USBD_FAIL;
202254
}
@@ -314,7 +366,7 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
314366

315367
new_status_flags = pbsys_status_get_flags();
316368

317-
// Transmit. Give priority to response, then status updates.
369+
// Transmit. Give priority to response, then status updates, then stdout.
318370
if (usb_response_sz) {
319371
transmitting = true;
320372
USBD_Pybricks_TransmitPacket(&husbd, usb_response_buf, usb_response_sz);
@@ -329,6 +381,9 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
329381

330382
transmitting = true;
331383
USBD_Pybricks_TransmitPacket(&husbd, usb_status_buf, usb_status_sz);
384+
} else if (usb_stdout_sz) {
385+
transmitting = true;
386+
USBD_Pybricks_TransmitPacket(&husbd, usb_stdout_buf, usb_stdout_sz);
332387
}
333388
}
334389

lib/pbio/include/pbdrv/usb.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
#ifndef _PBDRV_USB_H_
1010
#define _PBDRV_USB_H_
1111

12+
#include <stdbool.h>
13+
1214
#include <pbdrv/config.h>
15+
#include <pbio/error.h>
1316

1417
/**
1518
* Indicates battery charging capabilites that were detected on a USB port.
@@ -37,12 +40,32 @@ typedef enum {
3740
*/
3841
pbdrv_usb_bcd_t pbdrv_usb_get_bcd(void);
3942

43+
/**
44+
* Transmits the given buffer over the USB stdout stream.
45+
* @return The result of the operation.
46+
*/
47+
pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size);
48+
49+
/**
50+
* Indicates if the USB stdout stream is idle.
51+
* @return true if the USB stdout stream is idle.
52+
*/
53+
bool pbdrv_usb_stdout_tx_is_idle(void);
54+
4055
#else // PBDRV_CONFIG_USB
4156

4257
static inline pbdrv_usb_bcd_t pbdrv_usb_get_bcd(void) {
4358
return PBDRV_USB_BCD_NONE;
4459
}
4560

61+
static inline pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size) {
62+
return PBIO_SUCCESS;
63+
}
64+
65+
static inline bool pbdrv_usb_stdout_tx_is_idle(void) {
66+
return true;
67+
}
68+
4669
#endif // PBDRV_CONFIG_USB
4770

4871
#endif // _PBDRV_USB_H_

0 commit comments

Comments
 (0)