From 0f80c102cf9bad691fac3263d7020d4ba159c78d Mon Sep 17 00:00:00 2001
From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Date: Mon, 29 Apr 2024 08:57:22 +0200
Subject: [PATCH] v4l2-ctl: --list-devices --verbose will list current
 input/output

It can be handy to see what the current input or output name is of
a given v4l2 device: that often gives useful information to determine
which device to use. So if --verbose is added to --list-devices, then
it will report that information in parenthesis after the device name.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
 utils/v4l2-ctl/v4l2-ctl-common.cpp | 34 +++++++++++++++++++++++-------
 utils/v4l2-ctl/v4l2-ctl.cpp        |  4 ++--
 utils/v4l2-ctl/v4l2-ctl.h          |  4 ++--
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp b/utils/v4l2-ctl/v4l2-ctl-common.cpp
index 0370708b7..1f9cd0fb6 100644
--- a/utils/v4l2-ctl/v4l2-ctl-common.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp
@@ -286,6 +286,7 @@ static void list_devices()
 		int fd = open(file.c_str(), O_RDWR);
 		std::string bus_info;
 		std::string card;
+		std::string extra;
 
 		if (fd < 0)
 			continue;
@@ -305,8 +306,23 @@ static void list_devices()
 					card = mdi.driver;
 			}
 		} else {
+			unsigned idx;
+
 			bus_info = reinterpret_cast<const char *>(vcap.bus_info);
 			card = reinterpret_cast<const char *>(vcap.card);
+			if (!ioctl(fd, VIDIOC_G_INPUT, &idx)) {
+				struct v4l2_input in = {
+					.index = idx
+				};
+				if (!ioctl(fd, VIDIOC_ENUMINPUT, &in))
+					extra = std::string(" (input: ") + (const char *)in.name + ")";
+			} else if (!ioctl(fd, VIDIOC_G_OUTPUT, &idx)) {
+				struct v4l2_output out = {
+					.index = idx
+				};
+				if (!ioctl(fd, VIDIOC_ENUMOUTPUT, &out))
+					extra = std::string(" (output: ") + (const char *)out.name + ")";
+			}
 		}
 		close(fd);
 		if (err)
@@ -316,6 +332,8 @@ static void list_devices()
 		cards[bus_info] += "\t" + file;
 		if (!(links[file].empty()))
 			cards[bus_info] += " <- " + links[file];
+		if (verbose)
+			cards[bus_info] += extra;
 		cards[bus_info] += "\n";
 	}
 	for (const auto &card : cards) {
@@ -1037,7 +1055,7 @@ static bool parse_next_subopt(char **subs, char **value)
 	return true;
 }
 
-void common_cmd(const std::string &media_bus_info, int ch, char *optarg)
+void common_cmd(int ch, char *optarg)
 {
 	char *value, *subs;
 
@@ -1084,12 +1102,6 @@ void common_cmd(const std::string &media_bus_info, int ch, char *optarg)
 	case OptSetPriority:
 		prio = static_cast<enum v4l2_priority>(strtoul(optarg, nullptr, 0));
 		break;
-	case OptListDevices:
-		if (media_bus_info.empty())
-			list_devices();
-		else
-			list_media_devices(media_bus_info);
-		break;
 	}
 }
 
@@ -1356,8 +1368,14 @@ void common_get(cv4l_fd &_fd)
 	}
 }
 
-void common_list(cv4l_fd &fd)
+void common_list(const std::string &media_bus_info, cv4l_fd &fd)
 {
+	if (options[OptListDevices]) {
+		if (media_bus_info.empty())
+			list_devices();
+		else
+			list_media_devices(media_bus_info);
+	}
 	if (options[OptListCtrls] || options[OptListCtrlsMenus]) {
 		list_controls(fd.g_fd(), options[OptListCtrlsMenus]);
 	}
diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
index eb172654a..a64fa514b 100644
--- a/utils/v4l2-ctl/v4l2-ctl.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl.cpp
@@ -1276,7 +1276,7 @@ int main(int argc, char **argv)
 			common_usage();
 			return 1;
 		default:
-			common_cmd(media_bus_info, ch, optarg);
+			common_cmd(ch, optarg);
 			tuner_cmd(ch, optarg);
 			io_cmd(ch, optarg);
 			stds_cmd(ch, optarg);
@@ -1510,7 +1510,7 @@ int main(int argc, char **argv)
 
 	/* List options */
 
-	common_list(c_fd);
+	common_list(media_bus_info, c_fd);
 	io_list(c_fd);
 	stds_list(c_fd);
 	vidcap_list(c_fd);
diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h
index 1f66e4f1c..a1911e809 100644
--- a/utils/v4l2-ctl/v4l2-ctl.h
+++ b/utils/v4l2-ctl/v4l2-ctl.h
@@ -345,10 +345,10 @@ static inline bool subscribe_event(cv4l_fd &fd, __u32 type)
 
 // v4l2-ctl-common.cpp
 void common_usage(void);
-void common_cmd(const std::string &media_bus_info, int ch, char *optarg);
+void common_cmd(int ch, char *optarg);
 void common_set(cv4l_fd &fd);
 void common_get(cv4l_fd &fd);
-void common_list(cv4l_fd &fd);
+void common_list(const std::string &media_bus_info, cv4l_fd &fd);
 void common_process_controls(cv4l_fd &fd);
 void common_control_event(int fd, const struct v4l2_event *ev);
 int common_find_ctrl_id(const char *name);
-- 
GitLab