Skip to content

Commit bce2757

Browse files
committed
pbio/sys/host: Duplicate stdout to ble and usb.
Also change the signature of pbsys_bluetooth_tx and pbdrv_usb_stdout_tx to return PBIO_SUCCESS upon completion (not partial completion) and PBIO_ERROR_AGAIN for zero or partial transfers, which makes more sense with our other protothreads.
1 parent 2fb2f0b commit bce2757

File tree

5 files changed

+69
-29
lines changed

5 files changed

+69
-29
lines changed

bricks/_common_stm32/mphalport.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,24 +65,10 @@ int mp_hal_stdin_rx_chr(void) {
6565

6666
// Send string of given length
6767
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
68-
while (len) {
69-
uint32_t size = len;
70-
pbio_error_t err = pbsys_host_tx((const uint8_t *)str, &size);
71-
72-
if (err == PBIO_SUCCESS) {
73-
str += size;
74-
len -= size;
75-
continue;
76-
}
77-
68+
while (pbsys_host_tx((const uint8_t *)str, len) == PBIO_ERROR_AGAIN) {
7869
MICROPY_EVENT_POLL_HOOK
79-
80-
if (err != PBIO_ERROR_AGAIN) {
81-
// Ignoring error for now. This means stdout lost if Bluetooth is
82-
// disconnected.
83-
return;
84-
}
8570
}
71+
// Not raising the error. This means stdout lost if host is not connected.
8672
}
8773

8874
void mp_hal_stdout_tx_flush(void) {

lib/pbio/drv/usb/usb_stm32.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,20 +191,22 @@ void pbdrv_usb_stm32_handle_vbus_irq(bool active) {
191191
* @param data [in] The data to be sent.
192192
* @param size [in, out] The size of @p data in bytes. After return, @p size
193193
* contains the number of bytes actually written.
194-
* @return ::PBIO_SUCCESS if @p data was queued, ::PBIO_ERROR_AGAIN
195-
* if @p data could not be queued at this time (e.g. buffer
194+
* @return ::PBIO_SUCCESS if all @p data was queued, ::PBIO_ERROR_AGAIN
195+
* if not all @p data could not be queued at this time (e.g. buffer
196196
* is full), ::PBIO_ERROR_INVALID_OP if there is not an
197197
* active USB connection or ::PBIO_ERROR_NOT_SUPPORTED
198198
* if this platform does not support USB.
199199
*/
200200
pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size) {
201201
uint8_t *ptr = usb_stdout_buf;
202202
uint32_t ptr_len = sizeof(usb_stdout_buf);
203+
uint32_t full_size = *size;
203204

204205
if (!pbdrv_usb_stdout_is_awaitable()) {
205206
return PBIO_ERROR_INVALID_OP;
206207
}
207208
if (usb_stdout_sz) {
209+
*size = 0;
208210
return PBIO_ERROR_AGAIN;
209211
}
210212

@@ -214,14 +216,14 @@ pbio_error_t pbdrv_usb_stdout_tx(const uint8_t *data, uint32_t *size) {
214216
*ptr++ = PBIO_PYBRICKS_EVENT_WRITE_STDOUT;
215217
ptr_len--;
216218

217-
*size = MIN(*size, ptr_len);
219+
*size = MIN(full_size, ptr_len);
218220
memcpy(ptr, data, *size);
219221

220222
usb_stdout_sz = 1 + 1 + *size;
221223

222224
process_poll(&pbdrv_usb_process);
223225

224-
return PBIO_SUCCESS;
226+
return *size == full_size ? PBIO_SUCCESS : PBIO_ERROR_AGAIN;
225227
}
226228

227229
/**

lib/pbio/include/pbsys/host.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ uint32_t pbsys_host_rx_get_available(void);
3232
uint32_t pbsys_host_rx_get_free(void);
3333
void pbsys_host_rx_write(const uint8_t *data, uint32_t size);
3434
pbio_error_t pbsys_host_rx(uint8_t *data, uint32_t *size);
35-
pbio_error_t pbsys_host_tx(const uint8_t *data, uint32_t *size);
35+
pbio_error_t pbsys_host_tx(const uint8_t *data, uint32_t size);
3636
bool pbsys_host_tx_is_idle(void);
3737

3838
#else // PBSYS_CONFIG_HOST
@@ -47,7 +47,7 @@ bool pbsys_host_tx_is_idle(void);
4747
static inline pbio_error_t pbsys_host_rx(uint8_t *data, uint32_t *size) {
4848
return PBIO_ERROR_NOT_SUPPORTED;
4949
}
50-
static inline pbio_error_t pbsys_host_tx(const uint8_t *data, uint32_t *size) {
50+
static inline pbio_error_t pbsys_host_tx(const uint8_t *data, uint32_t size) {
5151
return PBIO_ERROR_NOT_SUPPORTED;
5252
}
5353
static inline bool pbsys_host_tx_is_idle(void) {

lib/pbio/sys/bluetooth.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,17 @@ void pbsys_bluetooth_rx_flush(void) {
153153
* @param data [in] The data to be sent.
154154
* @param size [in, out] The size of @p data in bytes. After return, @p size
155155
* contains the number of bytes actually written.
156-
* @return ::PBIO_SUCCESS if @p data was queued, ::PBIO_ERROR_AGAIN
157-
* if @p data could not be queued at this time (e.g. buffer
158-
* is full), ::PBIO_ERROR_INVALID_OP if there is not an
156+
* @return ::PBIO_SUCCESS if all @p data was queued,
157+
* ::PBIO_ERROR_AGAIN if not all @p data could not be
158+
* queued at this time (e.g. buffer is full),
159+
* ::PBIO_ERROR_INVALID_OP if there is not an
159160
* active Bluetooth connection or ::PBIO_ERROR_NOT_SUPPORTED
160161
* if this platform does not support Bluetooth.
161162
*/
162163
pbio_error_t pbsys_bluetooth_tx(const uint8_t *data, uint32_t *size) {
164+
165+
uint32_t full_size = *size;
166+
163167
// make sure we have a Bluetooth connection
164168
if (!pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_PYBRICKS)) {
165169
return PBIO_ERROR_INVALID_OP;
@@ -176,15 +180,15 @@ pbio_error_t pbsys_bluetooth_tx(const uint8_t *data, uint32_t *size) {
176180
stdout_msg.is_queued = true;
177181
}
178182

179-
if ((*size = lwrb_write(&stdout_ring_buf, data, *size)) == 0) {
183+
if ((*size = lwrb_write(&stdout_ring_buf, data, full_size)) == 0) {
180184
return PBIO_ERROR_AGAIN;
181185
}
182186

183187
// poke the process to start tx soon-ish. This way, we can accumulate up to
184188
// MAX_CHAR_SIZE bytes before actually transmitting
185189
pbsys_bluetooth_process_poll();
186190

187-
return PBIO_SUCCESS;
191+
return *size == full_size ? PBIO_SUCCESS : PBIO_ERROR_AGAIN;
188192
}
189193

190194
/**

lib/pbio/sys/host.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#if PBSYS_CONFIG_HOST
77

8+
#include <pbdrv/usb.h>
9+
810
#include <pbsys/host.h>
911

1012
#include "bluetooth.h"
@@ -37,8 +39,54 @@ pbio_error_t pbsys_host_rx(uint8_t *data, uint32_t *size) {
3739
return pbsys_bluetooth_rx(data, size);
3840
}
3941

40-
pbio_error_t pbsys_host_tx(const uint8_t *data, uint32_t *size) {
41-
return pbsys_bluetooth_tx(data, size);
42+
/**
43+
* Transmits data over Bluetooth and USB.
44+
*
45+
* Should be called in a loop with the same arguments until it no longer
46+
* returns ::PBIO_ERROR_AGAIN.
47+
*
48+
* @param data [in] The data to transmit.
49+
* @param size [in] The size of the data to transmit.
50+
* @return ::PBIO_ERROR_AGAIN if the data is still being transmitted
51+
* ::PBIO_SUCCESS if complete or failed.
52+
*/
53+
pbio_error_t pbsys_host_tx(const uint8_t *data, uint32_t size) {
54+
55+
static bool transmitting = false;
56+
static uint32_t tx_done_ble;
57+
static uint32_t tx_done_usb;
58+
59+
if (!transmitting) {
60+
tx_done_ble = 0;
61+
tx_done_usb = 0;
62+
transmitting = true;
63+
}
64+
65+
pbio_error_t err_ble = PBIO_SUCCESS;
66+
pbio_error_t err_usb = PBIO_SUCCESS;
67+
uint32_t size_now;
68+
69+
if (tx_done_ble < size) {
70+
size_now = size - tx_done_ble;
71+
err_ble = pbsys_bluetooth_tx(data + tx_done_ble, &size_now);
72+
tx_done_ble += size_now;
73+
}
74+
75+
if (tx_done_usb < size) {
76+
size_now = size - tx_done_usb;
77+
err_usb = pbdrv_usb_stdout_tx(data + tx_done_usb, &size_now);
78+
tx_done_usb += size_now;
79+
}
80+
81+
// Keep waiting as long as at least has not completed or errored.
82+
if (err_ble == PBIO_ERROR_AGAIN || err_usb == PBIO_ERROR_AGAIN) {
83+
return PBIO_ERROR_AGAIN;
84+
}
85+
86+
// Both of them are either complete or failed. The caller of this function
87+
// does not currently raise errors, so we just return success.
88+
transmitting = false;
89+
return PBIO_SUCCESS;
4290
}
4391

4492
bool pbsys_host_tx_is_idle(void) {

0 commit comments

Comments
 (0)