From 5cb5a3879a4e638d650b9a7f469c6d5e6e36bec2 Mon Sep 17 00:00:00 2001 From: Aguru Morita Date: Sat, 21 Mar 2026 18:58:06 +0900 Subject: [PATCH 1/3] bricks: fix mp_hal_stdout_tx_strn() signature mismatch --- bricks/_common_stm32/mphalport.c | 14 +++++++++++--- bricks/ev3dev/ev3dev_mphal.c | 4 ++-- bricks/ev3rt/mphalport.c | 5 ++++- bricks/nxt/mphalport.c | 7 +++++-- bricks/primehub_spike-rt/mphalport.c | 12 ++++++++---- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/bricks/_common_stm32/mphalport.c b/bricks/_common_stm32/mphalport.c index d2a2fc30c..ae54727a0 100644 --- a/bricks/_common_stm32/mphalport.c +++ b/bricks/_common_stm32/mphalport.c @@ -88,13 +88,17 @@ 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) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + size_t org_len = len; + while (len--) { while (!(USART6->SR & USART_SR_TXE)) { MICROPY_VM_HOOK_LOOP } USART6->DR = *str++; } + + return org_len; } void mp_hal_stdout_tx_flush(void) { @@ -127,7 +131,9 @@ 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) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + size_t org_len = len; + while (len) { uint32_t size = len; pbio_error_t err = pbsys_bluetooth_tx((const uint8_t *)str, &size); @@ -141,11 +147,13 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { if (err != PBIO_ERROR_AGAIN) { // Ignoring error for now. This means stdout lost if Bluetooth is // disconnected. - return; + return org_len - len; } MICROPY_EVENT_POLL_HOOK } + + return org_len; } void mp_hal_stdout_tx_flush(void) { diff --git a/bricks/ev3dev/ev3dev_mphal.c b/bricks/ev3dev/ev3dev_mphal.c index 6dd1aa25a..c3fa7b5e5 100644 --- a/bricks/ev3dev/ev3dev_mphal.c +++ b/bricks/ev3dev/ev3dev_mphal.c @@ -109,11 +109,11 @@ int mp_hal_stdin_rx_chr(void) { return c; } -void mp_hal_stdout_tx_strn(const char *str, size_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { MP_THREAD_GIL_EXIT(); int ret = write(STDOUT_FILENO, str, len); MP_THREAD_GIL_ENTER(); - (void)ret; // to suppress compiler warning + return ret < 0 ? 0 : ret; } // cooked is same as uncooked because the terminal does some postprocessing diff --git a/bricks/ev3rt/mphalport.c b/bricks/ev3rt/mphalport.c index 7f1dfab2d..14602fe92 100644 --- a/bricks/ev3rt/mphalport.c +++ b/bricks/ev3rt/mphalport.c @@ -75,11 +75,14 @@ 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) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { uint32_t in_waiting; if (bluetooth_is_connected(&in_waiting)) { serial_wri_dat(EV3_SERIAL_BT, str, len); + return len; } + + return 0; } void mp_hal_stdout_tx_flush(void) { diff --git a/bricks/nxt/mphalport.c b/bricks/nxt/mphalport.c index dafb13453..369620cf8 100644 --- a/bricks/nxt/mphalport.c +++ b/bricks/nxt/mphalport.c @@ -85,17 +85,20 @@ 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) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { // Nothing to do if disconnected or empty data if (!nx_bt_stream_opened() || len == 0) { - return; + return 0; } + size_t org_len = len; nx_bt_stream_write((uint8_t *)str, len); while (!nx_bt_stream_data_written()) { MICROPY_EVENT_POLL_HOOK; } + + return org_len; } void mp_hal_stdout_tx_flush(void) { diff --git a/bricks/primehub_spike-rt/mphalport.c b/bricks/primehub_spike-rt/mphalport.c index 5f22f97d6..26104a81f 100644 --- a/bricks/primehub_spike-rt/mphalport.c +++ b/bricks/primehub_spike-rt/mphalport.c @@ -58,14 +58,14 @@ 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) { mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + size_t org_len = len; extern void tPutLogTarget_ePutLog_putChar(char c); while (len--) { tPutLogTarget_ePutLog_putChar(*str++); } // serial_wri_dat(TASK_PORTID, str, len) - return 0; + return org_len; } #else // !PYBRICKS_HUB_DEBUG @@ -94,7 +94,9 @@ 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) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + size_t org_len = len; + while (len) { uint32_t size = len; pbio_error_t err = pbsys_bluetooth_tx((const uint8_t *)str, &size); @@ -108,11 +110,13 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { if (err != PBIO_ERROR_AGAIN) { // Ignoring error for now. This means stdout lost if Bluetooth is // disconnected. - return; + return org_len - len; } MICROPY_EVENT_POLL_HOOK } + + return org_len; } #endif // PYBRICKS_HUB_DEBUG From 6064fa6fed5a56740ec97ee5a0cea09df3fe9d84 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 10:54:49 +0000 Subject: [PATCH 2/3] Initial plan From 2395918b5220d4678758f672bd7c7fedd7fc5af4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 10:57:37 +0000 Subject: [PATCH 3/3] Fix mp_hal_stdout_tx_strn(): use ssize_t, loop for partial writes, handle EINTR Co-authored-by: morita5840 <27051616+morita5840@users.noreply.github.com> Agent-Logs-Url: https://github.com/ETrobocon/pybricks-micropython/sessions/47be6172-8e95-4d8b-bd62-96efebdf1c34 --- bricks/ev3dev/ev3dev_mphal.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/bricks/ev3dev/ev3dev_mphal.c b/bricks/ev3dev/ev3dev_mphal.c index c3fa7b5e5..e4ac74983 100644 --- a/bricks/ev3dev/ev3dev_mphal.c +++ b/bricks/ev3dev/ev3dev_mphal.c @@ -110,10 +110,25 @@ int mp_hal_stdin_rx_chr(void) { } mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { - MP_THREAD_GIL_EXIT(); - int ret = write(STDOUT_FILENO, str, len); - MP_THREAD_GIL_ENTER(); - return ret < 0 ? 0 : ret; + size_t remaining = len; + while (remaining > 0) { + MP_THREAD_GIL_EXIT(); + ssize_t ret = write(STDOUT_FILENO, str, remaining); + MP_THREAD_GIL_ENTER(); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + return len - remaining; + } + /* Defensive check: POSIX guarantees ret <= remaining, but guard against non-compliant implementations. */ + if ((size_t)ret > remaining) { + return len; + } + str += ret; + remaining -= (size_t)ret; + } + return len; } // cooked is same as uncooked because the terminal does some postprocessing