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

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

commit 11cf4211abe7890b544287358b79a8c385b7ed46
Author: wangjianyu3 <[email protected]>
AuthorDate: Thu Jun 19 21:48:39 2025 +0800

    system/fastboot: enable usb and tcp the same time
    
    Add support for enabling USB and TCP transport at the same time.
    
    Signed-off-by: wangjianyu3 <[email protected]>
---
 system/fastboot/fastboot.c | 243 ++++++++++++++++++++++++++-------------------
 1 file changed, 143 insertions(+), 100 deletions(-)

diff --git a/system/fastboot/fastboot.c b/system/fastboot/fastboot.c
index c5afbb9a9..569d5c961 100644
--- a/system/fastboot/fastboot.c
+++ b/system/fastboot/fastboot.c
@@ -231,10 +231,11 @@ static ssize_t fastboot_usbdev_read(FAR struct 
fastboot_ctx_s *ctx,
                                     FAR void *buf, size_t len);
 static int     fastboot_usbdev_write(FAR struct fastboot_ctx_s *ctx,
                                      FAR const void *buf, size_t len);
-#elif defined(CONFIG_NET_TCP)
+#endif
 
 /* TCP transport */
 
+#ifdef CONFIG_NET_TCP
 static int     fastboot_tcp_initialize(FAR struct fastboot_ctx_s *ctx);
 static void    fastboot_tcp_deinit(FAR struct fastboot_ctx_s *ctx);
 static ssize_t fastboot_tcp_read(FAR struct fastboot_ctx_s *ctx,
@@ -275,23 +276,25 @@ static const struct memory_region_s g_memory_region[] =
 };
 #endif
 
-#ifdef CONFIG_USBFASTBOOT
-static const struct fastboot_transport_ops_s g_tran_ops_usb =
+static const struct fastboot_transport_ops_s g_tran_ops[] =
 {
-  .init    = fastboot_usbdev_initialize,
-  .deinit  = fastboot_usbdev_deinit,
-  .read    = fastboot_usbdev_read,
-  .write   = fastboot_usbdev_write,
-};
-#elif defined(CONFIG_NET_TCP)
-static const struct fastboot_transport_ops_s g_tran_ops_tcp =
-{
-  .init    = fastboot_tcp_initialize,
-  .deinit  = fastboot_tcp_deinit,
-  .read    = fastboot_tcp_read,
-  .write   = fastboot_tcp_write,
-};
+#ifdef CONFIG_USBFASTBOOT
+  {
+    .init    = fastboot_usbdev_initialize,
+    .deinit  = fastboot_usbdev_deinit,
+    .read    = fastboot_usbdev_read,
+    .write   = fastboot_usbdev_write,
+  },
+#endif
+#ifdef CONFIG_NET_TCP
+  {
+    .init    = fastboot_tcp_initialize,
+    .deinit  = fastboot_tcp_deinit,
+    .read    = fastboot_tcp_read,
+    .write   = fastboot_tcp_write,
+  },
 #endif
+};
 
 /****************************************************************************
  * Private Functions
@@ -660,6 +663,11 @@ static void fastboot_download(FAR struct fastboot_ctx_s 
*ctx,
       ssize_t r = ctx->ops->read(ctx, download, len);
       if (r < 0)
         {
+          if (errno == EAGAIN)
+            {
+              continue;
+            }
+
           ctx->download_size = 0;
           fb_err("fastboot_download usb read error\n");
           return;
@@ -978,28 +986,34 @@ static void fastboot_oem(FAR struct fastboot_ctx_s *ctx, 
FAR const char *arg)
     }
 }
 
-static void fastboot_command_loop(FAR struct fastboot_ctx_s *ctx)
+static void fastboot_command_loop(FAR struct fastboot_ctx_s *ctx,
+                                  size_t nctx)
 {
-  struct epoll_event ev[1];
+  FAR struct fastboot_ctx_s *c;
+  struct epoll_event ev[nctx];
   int epfd;
+  int n;
 
-  if (ctx->left > 0)
+  epfd = epoll_create(1);
+  if (epfd < 0)
     {
-      epfd = epoll_create(1);
-      if (epfd < 0)
-        {
-          fb_err("open epoll failed %d", errno);
-          return;
-        }
+      fb_err("open epoll failed %d", errno);
+      return;
+    }
 
-      ev[0].events = EPOLLIN;
-      ev[0].data.ptr = ctx;
-      if (epoll_ctl(epfd, EPOLL_CTL_ADD, ctx->tran_fd[0], &ev[0]) < 0)
+  for (c = ctx, n = nctx; n-- > 0; c++)
+    {
+      ev[n].events = EPOLLIN;
+      ev[n].data.ptr = c;
+      if (epoll_ctl(epfd, EPOLL_CTL_ADD, c->tran_fd[0], &ev[n]) < 0)
         {
-          fb_err("err add poll %d", ctx->tran_fd[0]);
+          fb_err("err add poll %d", c->tran_fd[0]);
           return;
         }
+    }
 
+  if (ctx->left > 0)
+    {
       if (epoll_wait(epfd, ev, nitems(ev), ctx->left) <= 0)
         {
           return;
@@ -1008,7 +1022,10 @@ static void fastboot_command_loop(FAR struct 
fastboot_ctx_s *ctx)
 
   /* Reinitialize for storing TCP transport remaining data size. */
 
-  ctx->left = 0;
+  for (c = ctx, n = nctx; n-- > 0; c++)
+    {
+      c->left = 0;
+    }
 
   while (1)
     {
@@ -1016,27 +1033,32 @@ static void fastboot_command_loop(FAR struct 
fastboot_ctx_s *ctx)
       size_t ncmds = nitems(g_fast_cmd);
       size_t index;
 
-      ssize_t r = ctx->ops->read(ctx, buffer, FASTBOOT_MSG_LEN);
-      if (r < 0)
+      n = epoll_wait(epfd, ev, nitems(ev), -1);
+      for (n--; n >= 0; )
         {
-          fb_err("fastboot transport read() %zd\n", r);
-          continue;
-        }
+          c = (FAR struct fastboot_ctx_s *)ev[n].data.ptr;
+          ssize_t r = c->ops->read(c, buffer, FASTBOOT_MSG_LEN);
+          if (r <= 0)
+            {
+              n--;
+              continue;
+            }
 
-      buffer[r] = '\0';
-      for (index = 0; index < ncmds; index++)
-        {
-          size_t len = strlen(g_fast_cmd[index].prefix);
-          if (memcmp(buffer, g_fast_cmd[index].prefix, len) == 0)
+          buffer[r] = '\0';
+          for (index = 0; index < ncmds; index++)
             {
-              g_fast_cmd[index].handle(ctx, buffer + len);
-              break;
+              size_t len = strlen(g_fast_cmd[index].prefix);
+              if (memcmp(buffer, g_fast_cmd[index].prefix, len) == 0)
+                {
+                  g_fast_cmd[index].handle(c, buffer + len);
+                  break;
+                }
             }
-        }
 
-      if (index == ncmds)
-        {
-          fastboot_fail(ctx, "Unknown command");
+          if (index == ncmds)
+            {
+              fastboot_fail(c, "Unknown command");
+            }
         }
     }
 }
@@ -1062,25 +1084,33 @@ static void fastboot_publish(FAR struct fastboot_ctx_s 
*ctx,
   ctx->varlist = var;
 }
 
-static void fastboot_create_publish(FAR struct fastboot_ctx_s *ctx)
+static void fastboot_create_publish(FAR struct fastboot_ctx_s *ctx,
+                                    size_t nctx)
 {
-  fastboot_publish(ctx, "product", "NuttX", 0);
-  fastboot_publish(ctx, "kernel", "NuttX", 0);
-  fastboot_publish(ctx, "version", CONFIG_VERSION_STRING, 0);
-  fastboot_publish(ctx, "slot-count", "1", 0);
-  fastboot_publish(ctx, "max-download-size", NULL,
-                   CONFIG_SYSTEM_FASTBOOTD_DOWNLOAD_MAX);
+  for (; nctx-- > 0; ctx++)
+    {
+      fastboot_publish(ctx, "product", "NuttX", 0);
+      fastboot_publish(ctx, "kernel", "NuttX", 0);
+      fastboot_publish(ctx, "version", CONFIG_VERSION_STRING, 0);
+      fastboot_publish(ctx, "slot-count", "1", 0);
+      fastboot_publish(ctx, "max-download-size", NULL,
+                       CONFIG_SYSTEM_FASTBOOTD_DOWNLOAD_MAX);
+    }
 }
 
-static void fastboot_free_publish(FAR struct fastboot_ctx_s *ctx)
+static void fastboot_free_publish(FAR struct fastboot_ctx_s *ctx,
+                                  size_t nctx)
 {
   FAR struct fastboot_var_s *next;
 
-  while (ctx->varlist)
+  for (; nctx-- > 0; ctx++)
     {
-      next = ctx->varlist->next;
-      free(ctx->varlist);
-      ctx->varlist = next;
+      while (ctx->varlist)
+        {
+          next = ctx->varlist->next;
+          free(ctx->varlist);
+          ctx->varlist = next;
+        }
     }
 }
 
@@ -1149,15 +1179,15 @@ static int fastboot_usbdev_initialize(FAR struct 
fastboot_ctx_s *ctx)
     }
 #endif /* SYSTEM_FASTBOOTD_USB_BOARDCTL */
 
-  ctx->tran_fd[0]  =
-      fastboot_open_usb(FASTBOOT_EP_BULKOUT_IDX, O_RDONLY | O_CLOEXEC);
+  ctx->tran_fd[0]  = fastboot_open_usb(FASTBOOT_EP_BULKOUT_IDX,
+                                       O_RDONLY | O_CLOEXEC | O_NONBLOCK);
   if (ctx->tran_fd[0] < 0)
     {
       return ctx->tran_fd[0];
     }
 
-  ctx->tran_fd[1] =
-      fastboot_open_usb(FASTBOOT_EP_BULKIN_IDX, O_WRONLY | O_CLOEXEC);
+  ctx->tran_fd[1] = fastboot_open_usb(FASTBOOT_EP_BULKIN_IDX,
+                                      O_WRONLY | O_CLOEXEC | O_NONBLOCK);
   if (ctx->tran_fd[1] < 0)
     {
       close(ctx->tran_fd[0]);
@@ -1190,13 +1220,15 @@ static int fastboot_usbdev_write(FAR struct 
fastboot_ctx_s *ctx,
 {
   return fastboot_write(ctx->tran_fd[1], buf, len);
 }
+#endif
 
-#elif defined(CONFIG_NET_TCP)
+#ifdef CONFIG_NET_TCP
 static int fastboot_tcp_initialize(FAR struct fastboot_ctx_s *ctx)
 {
   struct sockaddr_in addr;
 
-  ctx->tran_fd[0] = socket(AF_INET, SOCK_STREAM, 0);
+  ctx->tran_fd[0] = socket(AF_INET, SOCK_STREAM,
+                           SOCK_CLOEXEC | SOCK_NONBLOCK);
   if (ctx->tran_fd[0] < 0)
     {
       fb_err("create socket failed %d", errno);
@@ -1357,36 +1389,54 @@ static int fastboot_tcp_write(FAR struct fastboot_ctx_s 
*ctx,
 }
 #endif
 
-static int fastboot_context_initialize(FAR struct fastboot_ctx_s *ctx)
+static int fastboot_context_initialize(FAR struct fastboot_ctx_s *ctx,
+                                       size_t nctx)
 {
-  ctx->download_max    = CONFIG_SYSTEM_FASTBOOTD_DOWNLOAD_MAX;
-  ctx->download_offset = 0;
-  ctx->download_size   = 0;
-  ctx->flash_fd        = -1;
-  ctx->total_imgsize   = 0;
-  ctx->varlist         = NULL;
-  ctx->left            = 0;
-#ifdef CONFIG_USBFASTBOOT
-  ctx->ops             = &g_tran_ops_usb;
-#elif defined(CONFIG_NET_TCP)
-  ctx->ops             = &g_tran_ops_tcp;
-#endif
-  ctx->tran_fd[0]      = -1;
-  ctx->tran_fd[1]      = -1;
+  int ret;
 
-  ctx->download_buffer = malloc(CONFIG_SYSTEM_FASTBOOTD_DOWNLOAD_MAX);
-  if (ctx->download_buffer == NULL)
-    {
-      fb_err("ERROR: Could not allocate the memory.\n");
-      return -errno;
+  for (; nctx-- > 0; ctx++)
+    {
+      ctx->download_max    = CONFIG_SYSTEM_FASTBOOTD_DOWNLOAD_MAX;
+      ctx->download_offset = 0;
+      ctx->download_size   = 0;
+      ctx->flash_fd        = -1;
+      ctx->total_imgsize   = 0;
+      ctx->varlist         = NULL;
+      ctx->left            = ctx[0].left;
+      ctx->ops             = &g_tran_ops[nctx];
+      ctx->tran_fd[0]      = -1;
+      ctx->tran_fd[1]      = -1;
+
+      ctx->download_buffer = malloc(CONFIG_SYSTEM_FASTBOOTD_DOWNLOAD_MAX);
+      if (ctx->download_buffer == NULL)
+        {
+          fb_err("ERROR: Could not allocate the memory.\n");
+          continue;
+        }
+
+      ret = ctx->ops->init(ctx);
+      if (ret < 0)
+        {
+          free(ctx->download_buffer);
+          ctx->download_buffer = NULL;
+          ctx->ops->deinit(ctx);
+        }
     }
 
   return 0;
 }
 
-static void fastboot_context_deinit(FAR struct fastboot_ctx_s *ctx)
+static void fastboot_context_deinit(FAR struct fastboot_ctx_s *ctx,
+                                    size_t nctx)
 {
-  free(ctx->download_buffer);
+  for (; nctx-- > 0; ctx++)
+    {
+      if (ctx->download_buffer)
+        {
+          ctx->ops->deinit(ctx);
+          free(ctx->download_buffer);
+        }
+    }
 }
 
 /****************************************************************************
@@ -1395,15 +1445,9 @@ static void fastboot_context_deinit(FAR struct 
fastboot_ctx_s *ctx)
 
 int main(int argc, FAR char **argv)
 {
-  struct fastboot_ctx_s context;
+  struct fastboot_ctx_s context[nitems(g_tran_ops)];
   int ret;
 
-  ret = fastboot_context_initialize(&context);
-  if (ret < 0)
-    {
-      return ret;
-    }
-
   if (argc > 1)
     {
       if (strcmp(argv[1], "-h") == 0)
@@ -1414,23 +1458,22 @@ int main(int argc, FAR char **argv)
           return 0;
         }
 
-      if (sscanf(argv[1], "%" SCNu64 , &context.left) != 1)
+      if (sscanf(argv[1], "%" SCNu64 , &context[0].left) != 1)
         {
           return -EINVAL;
         }
     }
 
-  ret = context.ops->init(&context);
+  ret = fastboot_context_initialize(context, nitems(context));
   if (ret < 0)
     {
       return ret;
     }
 
-  fastboot_create_publish(&context);
-  fastboot_command_loop(&context);
-  fastboot_free_publish(&context);
-  context.ops->deinit(&context);
-  fastboot_context_deinit(&context);
+  fastboot_create_publish(context, nitems(context));
+  fastboot_command_loop(context, nitems(context));
+  fastboot_free_publish(context, nitems(context));
+  fastboot_context_deinit(context, nitems(context));
 
   return ret;
 }

Reply via email to