This tool allows to find a device by driver name,
this is useful for scripts to be written in a generic way.

Usage:

v4l2-get-device -d uvcvideo -c V4L2_CAP_VIDEO_CAPTURE
/dev/video0
/dev/video2

Signed-off-by: Ezequiel Garcia <ezequ...@collabora.com>
---
 configure.ac                            |   1 +
 utils/Makefile.am                       |   1 +
 utils/v4l2-get-device/.gitignore        |   1 +
 utils/v4l2-get-device/Makefile.am       |   4 +
 utils/v4l2-get-device/v4l2-get-device.c | 147 ++++++++++++++++++++++++
 v4l-utils.spec.in                       |   1 +
 6 files changed, 155 insertions(+)
 create mode 100644 utils/v4l2-get-device/.gitignore
 create mode 100644 utils/v4l2-get-device/Makefile.am
 create mode 100644 utils/v4l2-get-device/v4l2-get-device.c

diff --git a/configure.ac b/configure.ac
index 5cc34c248fbf..918cb59704b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,7 @@ AC_CONFIG_FILES([Makefile
        utils/v4l2-compliance/Makefile
        utils/v4l2-ctl/Makefile
        utils/v4l2-dbg/Makefile
+       utils/v4l2-get-device/Makefile
        utils/v4l2-sysfs-path/Makefile
        utils/qv4l2/Makefile
        utils/cec-ctl/Makefile
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 2d5070288c13..2b2b27107d13 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -9,6 +9,7 @@ SUBDIRS = \
        v4l2-compliance \
        v4l2-ctl \
        v4l2-dbg \
+       v4l2-get-device \
        v4l2-sysfs-path \
        cec-ctl \
        cec-compliance \
diff --git a/utils/v4l2-get-device/.gitignore b/utils/v4l2-get-device/.gitignore
new file mode 100644
index 000000000000..b222144c9f4e
--- /dev/null
+++ b/utils/v4l2-get-device/.gitignore
@@ -0,0 +1 @@
+v4l2-get-device
diff --git a/utils/v4l2-get-device/Makefile.am 
b/utils/v4l2-get-device/Makefile.am
new file mode 100644
index 000000000000..2e5a6e0ba32f
--- /dev/null
+++ b/utils/v4l2-get-device/Makefile.am
@@ -0,0 +1,4 @@
+bin_PROGRAMS = v4l2-get-device
+v4l2_get_device_SOURCES = v4l2-get-device.c
+v4l2_get_device_LDADD = ../libmedia_dev/libmedia_dev.la
+v4l2_get_device_LDFLAGS = $(ARGP_LIBS)
diff --git a/utils/v4l2-get-device/v4l2-get-device.c 
b/utils/v4l2-get-device/v4l2-get-device.c
new file mode 100644
index 000000000000..f9cc323b7057
--- /dev/null
+++ b/utils/v4l2-get-device/v4l2-get-device.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2018 Collabora, Ltd.
+ *
+ * Based on v4l2-sysfs-path by Mauro Carvalho Chehab:
+ *
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <argp.h>
+#include <config.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/unistd.h>
+
+#include <linux/videodev2.h>
+
+#include "../libmedia_dev/get_media_devices.h"
+
+const char *argp_program_version = "v4l2-get-device " V4L_UTILS_VERSION;
+const char *argp_program_bug_address = "Ezequiel Garcia 
<ezequ...@collabora.com>";
+
+struct args {
+       const char *driver;
+       unsigned int device_caps;
+};
+
+static const struct argp_option options[] = {
+       {"driver", 'd', "DRIVER", 0, "device driver name", 0},
+       {"v4l2-device-caps", 'c', "CAPS", 0, "v4l2 device capabilities", 0},
+       { 0 }
+};
+
+static unsigned int parse_capabilities(const char *arg)
+{
+       char *s, *str = strdup(arg);
+       unsigned int caps = 0;
+
+       s = strtok (str,",");
+       while (s != NULL) {
+               if (!strcmp(s, "V4L2_CAP_VIDEO_CAPTURE"))
+                       caps |= V4L2_CAP_VIDEO_CAPTURE;
+               else if (!strcmp(s, "V4L2_CAP_VIDEO_OUTPUT"))
+                       caps |= V4L2_CAP_VIDEO_OUTPUT;
+               else if (!strcmp(s, "V4L2_CAP_VIDEO_OVERLAY"))
+                       caps |= V4L2_CAP_VIDEO_OVERLAY;
+               else if (!strcmp(s, "V4L2_CAP_VBI_CAPTURE"))
+                       caps |= V4L2_CAP_VBI_CAPTURE;
+               else if (!strcmp(s, "V4L2_CAP_VBI_OUTPUT"))
+                       caps |= V4L2_CAP_VBI_OUTPUT;
+               s = strtok (NULL, ",");
+       }
+       free(str);
+       return caps;
+}
+
+static error_t parse_opt(int k, char *arg, struct argp_state *state)
+{
+       struct args *args = state->input;
+
+       switch (k) {
+       case 'd':
+               args->driver = arg;
+               break;
+       case 'c':
+               args->device_caps = parse_capabilities(arg);
+               break;
+       default:
+               return ARGP_ERR_UNKNOWN;
+       }
+       return 0;
+}
+
+static struct argp argp = {
+       .options = options,
+       .parser = parse_opt,
+};
+
+int main(int argc, char *argv[])
+{
+       const char *vid;
+       struct args args;
+       void *md;
+
+       args.driver = NULL;
+       args.device_caps = 0;
+       argp_parse(&argp, argc, argv, 0, 0, &args);
+
+       md = discover_media_devices();
+
+       vid = NULL;
+       do {
+               struct v4l2_capability cap;
+               char devnode[64];
+               int ret;
+               int fd;
+
+               vid = get_associated_device(md, vid, MEDIA_V4L_VIDEO,
+                                           NULL, NONE);
+               if (!vid)
+                       break;
+               snprintf(devnode, 64, "/dev/%s", vid);
+               fd = open(devnode, O_RDWR);
+               if (fd < 0)
+                       continue;
+
+               memset(&cap, 0, sizeof cap);
+               ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+               if (ret) {
+                       close(fd);
+                       continue;
+               }
+               close(fd);
+
+               if (strncmp(args.driver, (char *)cap.driver, 
sizeof(cap.driver)))
+                       continue;
+               if (args.device_caps && (args.device_caps & cap.device_caps) != 
args.device_caps)
+                       continue;
+               fprintf(stdout, "%s\n", devnode);
+       } while (vid);
+       free_media_devices(md);
+       return 0;
+}
diff --git a/v4l-utils.spec.in b/v4l-utils.spec.in
index 67bdca57ae92..ab15286b039b 100644
--- a/v4l-utils.spec.in
+++ b/v4l-utils.spec.in
@@ -159,6 +159,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null 
|| :
 %{_bindir}/ivtv-ctl
 %{_bindir}/v4l2-ctl
 %{_bindir}/v4l2-sysfs-path
+%{_bindir}/v4l2-get-device
 %{_mandir}/man1/ir-keytable.1*
 %{_mandir}/man1/ir-ctl.1*
 
-- 
2.19.1

Reply via email to