xiaoxiang781216 commented on code in PR #18745:
URL: https://github.com/apache/nuttx/pull/18745#discussion_r3093039527


##########
arch/sim/src/sim/posix/sim_host_v4l2.c:
##########
@@ -84,27 +88,239 @@ static int host_video_ioctl(int fd, int request, void *arg)
   return r;
 }
 
+static bool host_video_is_capture_device(const char *host_video_dev_path)
+{
+  struct v4l2_capability cap;
+  int fd;
+  bool available = false;
+
+  fd = open(host_video_dev_path, O_RDWR | O_NONBLOCK);
+  if (fd < 0)
+    {
+      fd = open(host_video_dev_path, O_RDONLY | O_NONBLOCK);
+      if (fd < 0)
+        {
+          return false;
+        }
+    }
+
+  memset(&cap, 0, sizeof(cap));
+  if (host_video_ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0)
+    {
+      uint32_t capabilities = cap.device_caps != 0 ? cap.device_caps :
+                              cap.capabilities;
+
+      if ((capabilities & V4L2_CAP_VIDEO_CAPTURE) != 0)
+        {
+          available = true;
+        }
+    }
+
+  close(fd);
+  return available;
+}
+
+static int host_video_get_device_path_by_index(const char *dirpath,
+                                               int index,
+                                               char *devpath,
+                                               size_t devpathlen)
+{
+  DIR *dir;
+  struct dirent *entry;
+  int count = 0;
+
+  dir = opendir(dirpath);
+  if (dir == NULL)
+    {
+      return -errno;
+    }
+
+  while ((entry = readdir(dir)) != NULL)
+    {
+      char path[PATH_MAX];
+
+      if (strncmp(entry->d_name, "video", 5) != 0)
+        {
+          continue;
+        }
+
+      if (snprintf(path, sizeof(path), "/dev/%s", entry->d_name) >=
+          (int)sizeof(path))
+        {
+          continue;
+        }
+
+      if (!host_video_is_capture_device(path))
+        {
+          continue;
+        }
+
+      if (count == index)
+        {
+          if (snprintf(devpath, devpathlen, "%s", path) >= devpathlen)
+            {
+              closedir(dir);
+              return -ENAMETOOLONG;
+            }
+
+          closedir(dir);
+          return 0;
+        }
+
+      count++;
+    }
+
+  closedir(dir);
+  return -ENODEV;
+}
+
+static int host_video_count_devices_in_dir(const char *dirpath)
+{
+  DIR *dir;
+  struct dirent *entry;
+  int count = 0;
+
+  dir = opendir(dirpath);
+  if (dir == NULL)
+    {
+      return -errno;
+    }
+
+  while ((entry = readdir(dir)) != NULL)
+    {
+      char devpath[PATH_MAX];
+
+      if (strncmp(entry->d_name, "video", 5) != 0)
+        {
+          continue;
+        }
+
+      if (snprintf(devpath, sizeof(devpath), "/dev/%s", entry->d_name) >=
+          (int)sizeof(devpath))
+        {
+          continue;
+        }
+
+      if (host_video_is_capture_device(devpath))
+        {
+          count++;
+        }
+    }
+
+  closedir(dir);
+  return count;
+}
+
+static int host_video_resolve_device_path(const char *host_video_dev_path,
+                                          char *resolved_path,
+                                          size_t resolved_path_len)
+{
+  const char *name;
+  char *endptr;
+  long index;
+  int ret;
+
+  name = strrchr(host_video_dev_path, '/');
+  name = name != NULL ? name + 1 : host_video_dev_path;
+
+  if (strncmp(name, "video", 5) != 0)
+    {
+      if (snprintf(resolved_path, resolved_path_len, "%s",
+                   host_video_dev_path) >= (int)resolved_path_len)
+        {
+          return -ENAMETOOLONG;
+        }
+
+      return 0;
+    }
+
+  index = strtol(name + 5, &endptr, 10);
+  if (endptr == name + 5 || *endptr != '\0' || index < 0 ||
+      index > INT_MAX)
+    {
+      return -EINVAL;
+    }
+
+  ret = host_video_get_device_path_by_index("/sys/class/video4linux", index,
+                                            resolved_path,
+                                            resolved_path_len);
+  if (ret == -ENOENT || ret == -ENODEV || ret == -EINVAL)
+    {
+      ret = host_video_get_device_path_by_index("/dev", index,
+                                                resolved_path,
+                                                resolved_path_len);
+    }
+
+  if (ret < 0)
+    {
+      WARN("failed to resolve %s to host capture device: %d",
+           host_video_dev_path, ret);
+    }
+
+  return ret;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
+int host_video_get_device_count(void)
+{
+  int count;
+
+  count = host_video_count_devices_in_dir("/sys/class/video4linux");
+  if (count >= 0)
+    {
+      return count;
+    }
+
+  count = host_video_count_devices_in_dir("/dev");
+  if (count >= 0)
+    {
+      return count;
+    }
+
+  return 0;
+}
+
 bool host_video_is_available(const char *host_video_dev_path)
 {
-  return access(host_video_dev_path, F_OK) == 0;
+  char resolved_path[PATH_MAX];
+  int ret;
+
+  ret = host_video_resolve_device_path(host_video_dev_path, resolved_path,
+                                       sizeof(resolved_path));
+  if (ret < 0)
+    {
+      return false;
+    }
+
+  return host_video_is_capture_device(resolved_path);
 }
 
 struct host_video_dev_s *host_video_init(const char *host_video_dev_path)
 {
   int fd;
+  int ret;
+  char resolved_path[PATH_MAX];
   struct host_video_dev_s *vdev;
 
-  fd = open(host_video_dev_path, O_RDWR | O_NONBLOCK);
-  if (fd < 0)
+  ret = host_video_resolve_device_path(host_video_dev_path, resolved_path,

Review Comment:
   why not call open with host_video_dev_path directly



##########
arch/sim/src/sim/posix/sim_host_v4l2.c:
##########
@@ -84,27 +88,239 @@ static int host_video_ioctl(int fd, int request, void *arg)
   return r;
 }
 
+static bool host_video_is_capture_device(const char *host_video_dev_path)
+{
+  struct v4l2_capability cap;
+  int fd;
+  bool available = false;
+
+  fd = open(host_video_dev_path, O_RDWR | O_NONBLOCK);
+  if (fd < 0)
+    {
+      fd = open(host_video_dev_path, O_RDONLY | O_NONBLOCK);
+      if (fd < 0)
+        {
+          return false;
+        }
+    }
+
+  memset(&cap, 0, sizeof(cap));
+  if (host_video_ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0)
+    {
+      uint32_t capabilities = cap.device_caps != 0 ? cap.device_caps :
+                              cap.capabilities;
+
+      if ((capabilities & V4L2_CAP_VIDEO_CAPTURE) != 0)
+        {
+          available = true;
+        }
+    }
+
+  close(fd);
+  return available;
+}
+
+static int host_video_get_device_path_by_index(const char *dirpath,
+                                               int index,
+                                               char *devpath,
+                                               size_t devpathlen)
+{
+  DIR *dir;
+  struct dirent *entry;
+  int count = 0;
+
+  dir = opendir(dirpath);
+  if (dir == NULL)
+    {
+      return -errno;
+    }
+
+  while ((entry = readdir(dir)) != NULL)
+    {
+      char path[PATH_MAX];

Review Comment:
   remove format to devpath directly



##########
arch/sim/src/sim/posix/sim_host_v4l2.c:
##########
@@ -84,27 +88,239 @@ static int host_video_ioctl(int fd, int request, void *arg)
   return r;
 }
 
+static bool host_video_is_capture_device(const char *host_video_dev_path)
+{
+  struct v4l2_capability cap;
+  int fd;
+  bool available = false;
+
+  fd = open(host_video_dev_path, O_RDWR | O_NONBLOCK);
+  if (fd < 0)
+    {
+      fd = open(host_video_dev_path, O_RDONLY | O_NONBLOCK);
+      if (fd < 0)
+        {
+          return false;
+        }
+    }
+
+  memset(&cap, 0, sizeof(cap));
+  if (host_video_ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0)
+    {
+      uint32_t capabilities = cap.device_caps != 0 ? cap.device_caps :
+                              cap.capabilities;
+
+      if ((capabilities & V4L2_CAP_VIDEO_CAPTURE) != 0)
+        {
+          available = true;
+        }
+    }
+
+  close(fd);
+  return available;
+}
+
+static int host_video_get_device_path_by_index(const char *dirpath,
+                                               int index,
+                                               char *devpath,
+                                               size_t devpathlen)
+{
+  DIR *dir;
+  struct dirent *entry;
+  int count = 0;
+
+  dir = opendir(dirpath);
+  if (dir == NULL)
+    {
+      return -errno;
+    }
+
+  while ((entry = readdir(dir)) != NULL)
+    {
+      char path[PATH_MAX];
+
+      if (strncmp(entry->d_name, "video", 5) != 0)
+        {
+          continue;
+        }
+
+      if (snprintf(path, sizeof(path), "/dev/%s", entry->d_name) >=
+          (int)sizeof(path))
+        {
+          continue;
+        }
+
+      if (!host_video_is_capture_device(path))
+        {
+          continue;
+        }
+
+      if (count == index)
+        {
+          if (snprintf(devpath, devpathlen, "%s", path) >= devpathlen)
+            {
+              closedir(dir);
+              return -ENAMETOOLONG;
+            }
+
+          closedir(dir);
+          return 0;
+        }
+
+      count++;
+    }
+
+  closedir(dir);
+  return -ENODEV;
+}
+
+static int host_video_count_devices_in_dir(const char *dirpath)
+{
+  DIR *dir;
+  struct dirent *entry;
+  int count = 0;
+
+  dir = opendir(dirpath);

Review Comment:
   call host_video_get_device_path_by_index unitl fail to get the count



##########
arch/sim/src/sim/posix/sim_host_v4l2.c:
##########
@@ -84,27 +88,239 @@ static int host_video_ioctl(int fd, int request, void *arg)
   return r;
 }
 
+static bool host_video_is_capture_device(const char *host_video_dev_path)
+{
+  struct v4l2_capability cap;
+  int fd;
+  bool available = false;
+
+  fd = open(host_video_dev_path, O_RDWR | O_NONBLOCK);
+  if (fd < 0)
+    {
+      fd = open(host_video_dev_path, O_RDONLY | O_NONBLOCK);
+      if (fd < 0)
+        {
+          return false;
+        }
+    }
+
+  memset(&cap, 0, sizeof(cap));
+  if (host_video_ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0)
+    {
+      uint32_t capabilities = cap.device_caps != 0 ? cap.device_caps :
+                              cap.capabilities;
+
+      if ((capabilities & V4L2_CAP_VIDEO_CAPTURE) != 0)
+        {
+          available = true;
+        }
+    }
+
+  close(fd);
+  return available;
+}
+
+static int host_video_get_device_path_by_index(const char *dirpath,
+                                               int index,
+                                               char *devpath,
+                                               size_t devpathlen)
+{
+  DIR *dir;
+  struct dirent *entry;
+  int count = 0;
+
+  dir = opendir(dirpath);
+  if (dir == NULL)
+    {
+      return -errno;
+    }
+
+  while ((entry = readdir(dir)) != NULL)
+    {
+      char path[PATH_MAX];
+
+      if (strncmp(entry->d_name, "video", 5) != 0)
+        {
+          continue;
+        }
+
+      if (snprintf(path, sizeof(path), "/dev/%s", entry->d_name) >=
+          (int)sizeof(path))
+        {
+          continue;
+        }
+
+      if (!host_video_is_capture_device(path))
+        {
+          continue;
+        }
+
+      if (count == index)
+        {
+          if (snprintf(devpath, devpathlen, "%s", path) >= devpathlen)
+            {
+              closedir(dir);
+              return -ENAMETOOLONG;
+            }
+
+          closedir(dir);
+          return 0;
+        }
+
+      count++;
+    }
+
+  closedir(dir);
+  return -ENODEV;
+}
+
+static int host_video_count_devices_in_dir(const char *dirpath)
+{
+  DIR *dir;
+  struct dirent *entry;
+  int count = 0;
+
+  dir = opendir(dirpath);
+  if (dir == NULL)
+    {
+      return -errno;
+    }
+
+  while ((entry = readdir(dir)) != NULL)
+    {
+      char devpath[PATH_MAX];
+
+      if (strncmp(entry->d_name, "video", 5) != 0)
+        {
+          continue;
+        }
+
+      if (snprintf(devpath, sizeof(devpath), "/dev/%s", entry->d_name) >=
+          (int)sizeof(devpath))
+        {
+          continue;
+        }
+
+      if (host_video_is_capture_device(devpath))
+        {
+          count++;
+        }
+    }
+
+  closedir(dir);
+  return count;
+}
+
+static int host_video_resolve_device_path(const char *host_video_dev_path,
+                                          char *resolved_path,
+                                          size_t resolved_path_len)
+{
+  const char *name;
+  char *endptr;
+  long index;
+  int ret;
+
+  name = strrchr(host_video_dev_path, '/');
+  name = name != NULL ? name + 1 : host_video_dev_path;
+
+  if (strncmp(name, "video", 5) != 0)
+    {
+      if (snprintf(resolved_path, resolved_path_len, "%s",
+                   host_video_dev_path) >= (int)resolved_path_len)
+        {
+          return -ENAMETOOLONG;
+        }
+
+      return 0;
+    }
+
+  index = strtol(name + 5, &endptr, 10);
+  if (endptr == name + 5 || *endptr != '\0' || index < 0 ||
+      index > INT_MAX)
+    {
+      return -EINVAL;
+    }
+
+  ret = host_video_get_device_path_by_index("/sys/class/video4linux", index,
+                                            resolved_path,
+                                            resolved_path_len);
+  if (ret == -ENOENT || ret == -ENODEV || ret == -EINVAL)
+    {
+      ret = host_video_get_device_path_by_index("/dev", index,
+                                                resolved_path,
+                                                resolved_path_len);
+    }
+
+  if (ret < 0)
+    {
+      WARN("failed to resolve %s to host capture device: %d",
+           host_video_dev_path, ret);
+    }
+
+  return ret;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
+int host_video_get_device_count(void)
+{
+  int count;
+
+  count = host_video_count_devices_in_dir("/sys/class/video4linux");
+  if (count >= 0)
+    {
+      return count;
+    }
+
+  count = host_video_count_devices_in_dir("/dev");
+  if (count >= 0)
+    {
+      return count;
+    }
+
+  return 0;
+}
+
 bool host_video_is_available(const char *host_video_dev_path)
 {
-  return access(host_video_dev_path, F_OK) == 0;
+  char resolved_path[PATH_MAX];
+  int ret;
+
+  ret = host_video_resolve_device_path(host_video_dev_path, resolved_path,

Review Comment:
   why not call host_video_is_capture_device directly



##########
arch/sim/src/sim/sim_camera.c:
##########
@@ -38,24 +44,40 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define SIM_CAMERA_PERIOD    MSEC2TICK(CONFIG_SIM_LOOP_INTERVAL)
+#define SIM_CAMERA_PERIOD USEC2TICK(1000000 / 30)

Review Comment:
   why change



##########
arch/sim/src/sim/posix/sim_host_v4l2.c:
##########
@@ -114,6 +330,7 @@ struct host_video_dev_s *host_video_init(const char 
*host_video_dev_path)
     }
 
   vdev->fd = fd;
+  (void)snprintf(vdev->path, sizeof(vdev->path), "%s", resolved_path);

Review Comment:
   strlcpy



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to