Find the major and minor numbers of the device. Check if the
file /dev/dev/char/major:minor/uevent contains "DEVNAME=v4l-subdev".
If so, the device is a sub-device.

Signed-off-by: Harald Dankworth <harda...@cisco.com>
Reviewed-by: Hans Verkuil <hansv...@cisco.com>
---
 utils/v4l2-ctl/v4l2-ctl.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
index 5c67bf0..e02dc75 100644
--- a/utils/v4l2-ctl/v4l2-ctl.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl.cpp
@@ -46,6 +46,7 @@
 #include <vector>
 #include <map>
 #include <algorithm>
+#include <fstream>
 
 char options[OptLast];
 
@@ -1142,6 +1143,59 @@ __u32 find_pixel_format(int fd, unsigned index, bool 
output, bool mplane)
        return fmt.pixelformat;
 }
 
+static bool is_subdevice(int fd)
+{
+       struct stat sb;
+       if (fstat(fd, &sb) == -1) {
+               fprintf(stderr, "failed to stat file\n");
+               exit(1);
+       }
+
+       char uevent_path[100];
+       if (snprintf(uevent_path, sizeof(uevent_path), 
"/sys/dev/char/%d:%d/uevent",
+                    major(sb.st_rdev), minor(sb.st_rdev)) == -1) {
+               fprintf(stderr, "failed to create uevent file path\n");
+               exit(1);
+       }
+
+       std::ifstream uevent_file(uevent_path);
+       if (uevent_file.fail()) {
+               fprintf(stderr, "failed to open %s\n", uevent_path);
+               exit(1);
+       }
+
+       std::string line;
+
+       while (std::getline(uevent_file, line)) {
+               if (line.compare(0, 8, "DEVNAME="))
+                       continue;
+
+               static const char * devnames[] = {
+                       "v4l-subdev",
+                       "video",
+                       "vbi",
+                       "radio",
+                       "swradio",
+                       "v4l-touch",
+                       NULL
+               };
+
+               for (size_t i = 0; devnames[i]; i++) {
+                       size_t len = strlen(devnames[i]);
+
+                       if (!line.compare(8, len, devnames[i]) && 
isdigit(line[8+len])) {
+                               uevent_file.close();
+                               return i == 0;
+                       }
+               }
+       }
+
+       uevent_file.close();
+
+       fprintf(stderr, "unknown device name\n");
+       exit(1);
+}
+
 int main(int argc, char **argv)
 {
        int i;
@@ -1310,7 +1364,7 @@ int main(int argc, char **argv)
        }
 
        verbose = options[OptVerbose];
-       if (doioctl(fd, VIDIOC_QUERYCAP, &vcap)) {
+       if (!is_subdevice(fd) && doioctl(fd, VIDIOC_QUERYCAP, &vcap)) {
                fprintf(stderr, "%s: not a v4l2 node\n", device);
                exit(1);
        }
-- 
2.7.4

Reply via email to