PeterBee97 commented on code in PR #18745:
URL: https://github.com/apache/nuttx/pull/18745#discussion_r3099129308
##########
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:
Same reason as above. I wanted to map dev numbers without "holes".
--
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]