This is an automated email from the ASF dual-hosted git repository.

GUIDINGLI pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 3b993dfbb61d1d57325014079fc01e638202ae43
Author: fangpeina <[email protected]>
AuthorDate: Fri Aug 21 17:11:50 2026 +0800

    system/fastboot: Add serial (UART) transport backend.
    
    Add a serial transport alongside the existing USB and TCP backends.
    The serial backend reuses the TCP v1 wire framing (FB01 handshake
    plus an 8-byte big-endian length prefix) so the host side needs no
    new tool: socat bridges the UART to a TCP socket and the standard
    fastboot tool connects via tcp:.
    
    The serial port path is configured at build time through Kconfig
    SYSTEM_FASTBOOTD_SERIAL_PORT.
    
    Signed-off-by: fangpeina <[email protected]>
---
 system/fastboot/Kconfig    |  19 ++++-
 system/fastboot/fastboot.c | 204 ++++++++++++++++++++++++++++++++-------------
 2 files changed, 161 insertions(+), 62 deletions(-)

diff --git a/system/fastboot/Kconfig b/system/fastboot/Kconfig
index 093640115..966027376 100644
--- a/system/fastboot/Kconfig
+++ b/system/fastboot/Kconfig
@@ -6,12 +6,13 @@
 menuconfig SYSTEM_FASTBOOTD
        bool "fastbootd"
        default n
-       depends on USBFASTBOOT || (NET_TCP && NET_TCPBACKLOG)
+       depends on USBFASTBOOT || (NET_TCP && NET_TCPBACKLOG) || SERIAL
        ---help---
                Fastboot daemon supporting multiple transports concurrently.
-               Enable at least one transport (USB, TCP).
+               Enable at least one transport (USB, TCP, Serial).
                The USB transport depends on USBFASTBOOT.
                The TCP network transport depends on NET_TCP and NET_TCPBACKLOG.
+               The Serial transport depends on SERIAL.
                Each transport can be individually disabled via
                SYSTEM_FASTBOOTD_USB / SYSTEM_FASTBOOTD_TCP below.
 
@@ -71,4 +72,18 @@ config SYSTEM_FASTBOOTD_NET_INIT
        ---help---
                This option enables/disables all network initialization in 
fastboot server.
 
+config SYSTEM_FASTBOOTD_SERIAL
+       bool "Fastboot serial transport"
+       default n
+       depends on SERIAL
+       ---help---
+               Enable serial (UART) transport for fastboot daemon.
+               Reuses TCP v1 wire framing (FB01 handshake + 8-byte length 
prefix).
+               The host side can use socat to bridge the UART to a TCP socket.
+
+config SYSTEM_FASTBOOTD_SERIAL_PORT
+       string "Serial device path"
+       default "/dev/ttyS1"
+       depends on SYSTEM_FASTBOOTD_SERIAL
+
 endif # SYSTEM_FASTBOOTD
diff --git a/system/fastboot/fastboot.c b/system/fastboot/fastboot.c
index 15115ebf2..d65541967 100644
--- a/system/fastboot/fastboot.c
+++ b/system/fastboot/fastboot.c
@@ -39,6 +39,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <syslog.h>
+#include <termios.h>
 #include <unistd.h>
 
 #include <netinet/in.h>
@@ -155,10 +156,10 @@ struct fastboot_ctx_s
 {
   /* Transport file descriptors
    *
-   * | idx |    USB   |      TCP      | poll |
-   * |-----|----------|---------------|------|
-   * |   0 |usbdev in |TCP socket     |  Y   |
-   * |   1 |usbdev out|accepted socket|  N   |
+   * | idx |    USB   |      TCP      |  Serial  | poll |
+   * |-----|----------|---------------|----------|------|
+   * |   0 |usbdev in |TCP socket     |serial fd |  Y   |
+   * |   1 |usbdev out|accepted socket|serial fd |  N   |
    */
 
   int tran_fd[2];
@@ -253,6 +254,17 @@ static int     fastboot_tcp_write(FAR struct 
fastboot_ctx_s *ctx,
                                   FAR const void *buf, size_t len);
 #endif
 
+/* Serial transport */
+
+#ifdef CONFIG_SYSTEM_FASTBOOTD_SERIAL
+static int     fastboot_serial_initialize(FAR struct fastboot_ctx_s *ctx);
+static void    fastboot_serial_deinit(FAR struct fastboot_ctx_s *ctx);
+static ssize_t fastboot_serial_read(FAR struct fastboot_ctx_s *ctx,
+                                    FAR void *buf, size_t len);
+static int     fastboot_serial_write(FAR struct fastboot_ctx_s *ctx,
+                                     FAR const void *buf, size_t len);
+#endif
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -306,6 +318,14 @@ static const struct fastboot_transport_ops_s g_tran_ops[] =
     .write   = fastboot_tcp_write,
   },
 #endif
+#ifdef CONFIG_SYSTEM_FASTBOOTD_SERIAL
+  {
+    .init    = fastboot_serial_initialize,
+    .deinit  = fastboot_serial_deinit,
+    .read    = fastboot_serial_read,
+    .write   = fastboot_serial_write,
+  },
+#endif
 };
 
 /****************************************************************************
@@ -1301,62 +1321,7 @@ static int fastboot_usbdev_write(FAR struct 
fastboot_ctx_s *ctx,
 }
 #endif
 
-#ifdef CONFIG_SYSTEM_FASTBOOTD_TCP
-static int fastboot_tcp_initialize(FAR struct fastboot_ctx_s *ctx)
-{
-  struct sockaddr_in addr;
-
-#ifdef CONFIG_SYSTEM_FASTBOOTD_NET_INIT
-  /* Bring up the network */
-
-  netinit_bringup();
-#endif
-
-  ctx->tran_fd[0] = socket(AF_INET,
-                           SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
-                           0);
-  if (ctx->tran_fd[0] < 0)
-    {
-      fb_err("create socket failed %d", errno);
-      return -errno;
-    }
-
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = htonl(INADDR_ANY);
-  addr.sin_port = htons(FASTBOOT_TCP_PORT);
-  if (bind(ctx->tran_fd[0], (struct sockaddr *) &addr, sizeof(addr)) < 0)
-    {
-      fb_err("bind() failed %d", errno);
-      goto error;
-    }
-
-  if (listen(ctx->tran_fd[0], 1) < 0)
-    {
-      fb_err("listen() failed %d", errno);
-      goto error;
-    }
-
-  return 0;
-error:
-  close(ctx->tran_fd[0]);
-  ctx->tran_fd[0] = -1;
-  return -errno;
-}
-
-static void fastboot_tcp_disconn(FAR struct fastboot_ctx_s *ctx)
-{
-  close(ctx->tran_fd[1]);
-  ctx->tran_fd[1] = -1;
-}
-
-static void fastboot_tcp_deinit(FAR struct fastboot_ctx_s *ctx)
-{
-  fastboot_tcp_disconn(ctx);
-  close(ctx->tran_fd[0]);
-  ctx->tran_fd[0] = -1;
-}
-
+#if defined(CONFIG_SYSTEM_FASTBOOTD_TCP) || 
defined(CONFIG_SYSTEM_FASTBOOTD_SERIAL)
 static ssize_t fastboot_read_all(int fd, FAR void *buf, size_t len)
 {
   size_t total = 0;
@@ -1449,6 +1414,63 @@ static ssize_t fastboot_framed_read(FAR struct 
fastboot_ctx_s *ctx,
   ctx->left -= nread;
   return nread;
 }
+#endif
+
+#ifdef CONFIG_SYSTEM_FASTBOOTD_TCP
+static int fastboot_tcp_initialize(FAR struct fastboot_ctx_s *ctx)
+{
+  struct sockaddr_in addr;
+
+#ifdef CONFIG_SYSTEM_FASTBOOTD_NET_INIT
+  /* Bring up the network */
+
+  netinit_bringup();
+#endif
+
+  ctx->tran_fd[0] = socket(AF_INET,
+                           SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
+                           0);
+  if (ctx->tran_fd[0] < 0)
+    {
+      fb_err("create socket failed %d", errno);
+      return -errno;
+    }
+
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = htonl(INADDR_ANY);
+  addr.sin_port = htons(FASTBOOT_TCP_PORT);
+  if (bind(ctx->tran_fd[0], (struct sockaddr *) &addr, sizeof(addr)) < 0)
+    {
+      fb_err("bind() failed %d", errno);
+      goto error;
+    }
+
+  if (listen(ctx->tran_fd[0], 1) < 0)
+    {
+      fb_err("listen() failed %d", errno);
+      goto error;
+    }
+
+  return 0;
+error:
+  close(ctx->tran_fd[0]);
+  ctx->tran_fd[0] = -1;
+  return -errno;
+}
+
+static void fastboot_tcp_disconn(FAR struct fastboot_ctx_s *ctx)
+{
+  close(ctx->tran_fd[1]);
+  ctx->tran_fd[1] = -1;
+}
+
+static void fastboot_tcp_deinit(FAR struct fastboot_ctx_s *ctx)
+{
+  fastboot_tcp_disconn(ctx);
+  close(ctx->tran_fd[0]);
+  ctx->tran_fd[0] = -1;
+}
 
 static ssize_t fastboot_tcp_read(FAR struct fastboot_ctx_s *ctx,
                                  FAR void *buf, size_t len)
@@ -1491,6 +1513,68 @@ static int fastboot_tcp_write(FAR struct fastboot_ctx_s 
*ctx,
 }
 #endif
 
+#ifdef CONFIG_SYSTEM_FASTBOOTD_SERIAL
+static int fastboot_serial_initialize(FAR struct fastboot_ctx_s *ctx)
+{
+  int fd;
+
+  fd = open(CONFIG_SYSTEM_FASTBOOTD_SERIAL_PORT,
+            O_RDWR | O_CLOEXEC | O_NONBLOCK);
+  if (fd < 0)
+    {
+      fb_err("serial: open %s failed %d\n",
+             CONFIG_SYSTEM_FASTBOOTD_SERIAL_PORT, errno);
+      return -errno;
+    }
+
+#ifdef CONFIG_SERIAL_TERMIOS
+  struct termios tio;
+
+  if (tcgetattr(fd, &tio) == 0)
+    {
+      cfmakeraw(&tio);
+      tcsetattr(fd, TCSANOW, &tio);
+    }
+#endif
+
+  ctx->tran_fd[0] = fd;
+  ctx->tran_fd[1] = fd;
+  fb_info("serial: opened %s\n", CONFIG_SYSTEM_FASTBOOTD_SERIAL_PORT);
+  return 0;
+}
+
+static void fastboot_serial_deinit(FAR struct fastboot_ctx_s *ctx)
+{
+  if (ctx->tran_fd[0] >= 0)
+    {
+      close(ctx->tran_fd[0]);
+      ctx->tran_fd[0] = -1;
+      ctx->tran_fd[1] = -1;
+    }
+}
+
+static ssize_t fastboot_serial_read(FAR struct fastboot_ctx_s *ctx,
+                                    FAR void *buf, size_t len)
+{
+  return fastboot_framed_read(ctx, ctx->tran_fd[0], buf, len, true);
+}
+
+static int fastboot_serial_write(FAR struct fastboot_ctx_s *ctx,
+                                 FAR const void *buf, size_t len)
+{
+  uint64_t data_size = htobe64(len);
+  int ret;
+
+  ret = fastboot_write(ctx->tran_fd[0], &data_size, sizeof(data_size));
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return fastboot_write(ctx->tran_fd[0], buf, len);
+}
+#endif
+
 static int fastboot_context_initialize(FAR struct fastboot_ctx_s *ctx,
                                        size_t nctx)
 {

Reply via email to