boot_serial: support fragmentation for outgoing SMP packets
The mcumgr packet sent over serial should be fragmented into frames of
up to 127 bytes, including 2-bytes frame start header and 1-byte for
terminating newline [1], resulting in up to 124 bytes for the base64
encoded payload.
Current implementation doesn't fulfill above requirement and transmits
single frames, without considering their length. This change introduces
support for fragmenting as defined in 'SMP over console' specification.
[1] github.com/apache/mynewt-mcumgr/blob/master/transport/smp-console.md
Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c
index e346280..c9a9a37 100644
--- a/boot/boot_serial/src/boot_serial.c
+++ b/boot/boot_serial/src/boot_serial.c
@@ -83,6 +83,7 @@
#endif
#define BOOT_SERIAL_OUT_MAX (128 * BOOT_IMAGE_NUMBER)
+#define BOOT_SERIAL_FRAME_MTU 124 /* 127 - pkt start (2 bytes) and stop (1 byte) */
#ifdef __ZEPHYR__
/* base64 lib encodes data to null-terminated string */
@@ -758,9 +759,10 @@
boot_serial_output(void)
{
char *data;
- int len;
+ int len, out;
uint16_t crc;
uint16_t totlen;
+ char pkt_cont[2] = { SHELL_NLIP_DATA_START1, SHELL_NLIP_DATA_START2 };
char pkt_start[2] = { SHELL_NLIP_PKT_START1, SHELL_NLIP_PKT_START2 };
char buf[BOOT_SERIAL_OUT_MAX + sizeof(*bs_hdr) + sizeof(crc) + sizeof(totlen)];
char encoded_buf[BASE64_ENCODE_SIZE(sizeof(buf))];
@@ -786,8 +788,6 @@
#endif
crc = htons(crc);
- boot_uf->write(pkt_start, sizeof(pkt_start));
-
totlen = len + sizeof(*bs_hdr) + sizeof(crc);
totlen = htons(totlen);
@@ -810,8 +810,23 @@
#else
totlen = base64_encode(buf, totlen, encoded_buf, 1);
#endif
- boot_uf->write(encoded_buf, totlen);
- boot_uf->write("\n", 1);
+
+ out = 0;
+ while (out < totlen) {
+ if (out == 0) {
+ boot_uf->write(pkt_start, sizeof(pkt_start));
+ } else {
+ boot_uf->write(pkt_cont, sizeof(pkt_cont));
+ }
+
+ len = MIN(BOOT_SERIAL_FRAME_MTU, totlen - out);
+ boot_uf->write(&encoded_buf[out], len);
+
+ out += len;
+
+ boot_uf->write("\n", 1);
+ }
+
BOOT_LOG_INF("TX");
}