aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2019-02-01 13:29:26 (GMT)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2019-02-01 13:47:01 (GMT)
commit73b8d3eb769241f7f81e67b73a9ce6e6c167baeb (patch)
tree9676088d7381dc545608629309182028112c3445
parent2e1badeca2646c88e4e1f1a54e922b53ea62111c (diff)
v4l2-ctl: add -z option to make it possible to use entity names
The -z option refers to a media device by bus_info, and if this is known, then device nodes can be found with G_TOPOLOGY and the name of the entity associated with the interface link or the interface ID. This uniquely identifies a device node, independently of how it is named. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-common.cpp13
-rw-r--r--utils/v4l2-ctl/v4l2-ctl.1.in19
-rw-r--r--utils/v4l2-ctl/v4l2-ctl.cpp132
-rw-r--r--utils/v4l2-ctl/v4l2-ctl.h1
4 files changed, 142 insertions, 23 deletions
diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp b/utils/v4l2-ctl/v4l2-ctl-common.cpp
index c660d15..11fe602 100644
--- a/utils/v4l2-ctl/v4l2-ctl-common.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp
@@ -65,11 +65,24 @@ void common_usage(void)
" -D, --info show driver info [VIDIOC_QUERYCAP]\n"
" -d, --device <dev> use device <dev> instead of /dev/video0\n"
" if <dev> starts with a digit, then /dev/video<dev> is used\n"
+ " Otherwise if -z was specified earlier, then <dev> is the entity name\n"
+ " or interface ID (if prefixed with 0x) as found in the topology of the\n"
+ " media device with the bus info string as specified by the -z option.\n"
" -e, --out-device <dev> use device <dev> for output streams instead of the\n"
" default device as set with --device\n"
" if <dev> starts with a digit, then /dev/video<dev> is used\n"
+ " Otherwise if -z was specified earlier, then <dev> is the entity name\n"
+ " or interface ID (if prefixed with 0x) as found in the topology of the\n"
+ " media device with the bus info string as specified by the -z option.\n"
" -E, --export-device <dev> use device <dev> for exporting DMA buffers\n"
" if <dev> starts with a digit, then /dev/video<dev> is used\n"
+ " Otherwise if -z was specified earlier, then <dev> is the entity name\n"
+ " or interface ID (if prefixed with 0x) as found in the topology of the\n"
+ " media device with the bus info string as specified by the -z option.\n"
+ " -z, --media-bus-info <bus-info>\n"
+ " find the media device with the given bus info string. If set, then\n"
+ " -d, -e and -E options can use the entity name or interface ID to refer\n"
+ " to the device nodes.\n"
" -h, --help display this help message\n"
" --help-all all options\n"
" --help-io input/output options\n"
diff --git a/utils/v4l2-ctl/v4l2-ctl.1.in b/utils/v4l2-ctl/v4l2-ctl.1.in
index 132f513..f37d6e3 100644
--- a/utils/v4l2-ctl/v4l2-ctl.1.in
+++ b/utils/v4l2-ctl/v4l2-ctl.1.in
@@ -12,7 +12,11 @@ devices covering the full V4L2 API.
.SH OPTIONS
.TP
\fB\-d\fR, \fB\-\-device\fR \fI<dev>\fR
-Use device <dev> as the V4L2 device. If <dev> is a number, then /dev/video<dev> is used.
+Use device \fI<dev>\fR as the V4L2 device.
+if \fI<dev>\fR starts with a digit, then /dev/video\fI<dev>\fR is used
+Otherwise if \fB-z\fR was specified earlier, then \fI<dev>\fR is the entity name
+or interface ID (if prefixed with 0x) as found in the topology of the media device
+with the bus info string as specified by the \fB-z\fR option.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
Turn on verbose reporting.
@@ -86,12 +90,23 @@ Show driver info [VIDIOC_QUERYCAP].
.TP
\fB-e\fR, \fB--out-device\fR \fI<dev>\fR
Use device \fI<dev>\fR for output streams instead of the
-default device as set with --device. If \fI<dev>\fR starts
+default device as set with \fB--device\fR. If \fI<dev>\fR starts
with a digit, then /dev/video\fI<dev>\fR is used.
+Otherwise if \fB-z\fR was specified earlier, then \fI<dev>\fR is the entity name
+or interface ID (if prefixed with 0x) as found in the topology of the media device
+with the bus info string as specified by the \fB-z\fR option.
.TP
\fB-E\fR, \fB--export-device\fR \fI<dev>\fR
Use device \fI<dev>\fR for exporting DMA buffers.
If \fI<dev>\fR starts with a digit, then /dev/video\fI<dev>\fR is used.
+Otherwise if \fB-z\fR was specified earlier, then \fI<dev>\fR is the entity name
+or interface ID (if prefixed with 0x) as found in the topology of the media device
+with the bus info string as specified by the \fB-z\fR option.
+.TP
+\fB-z\fR, \fB--media-bus-info\fR \fI<bus-info>\fR
+Find the media device with the given \fI<bus-info>\fR string. If set, then
+\fB-d\fR, \fB-e\fR and \fB-E\fR options can use the entity name or interface ID
+to refer to the device nodes. Example: v4l2-ctl -z platform:vivid-000 -d vivid-000-vid-cap
.TP
\fB-k\fR, \fB--concise\fR
Be more concise if possible.
diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
index fc19798..057b08e 100644
--- a/utils/v4l2-ctl/v4l2-ctl.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl.cpp
@@ -73,6 +73,7 @@ static struct option long_options[] = {
{"device", required_argument, 0, OptSetDevice},
{"out-device", required_argument, 0, OptSetOutDevice},
{"export-device", required_argument, 0, OptSetExportDevice},
+ {"media-bus-info", required_argument, 0, OptMediaBusInfo},
{"get-fmt-video", no_argument, 0, OptGetVideoFormat},
{"set-fmt-video", required_argument, 0, OptSetVideoFormat},
{"try-fmt-video", required_argument, 0, OptTryVideoFormat},
@@ -947,6 +948,109 @@ __u32 find_pixel_format(int fd, unsigned index, bool output, bool mplane)
return fmt.pixelformat;
}
+static int open_media_bus_info(const std::string &bus_info)
+{
+ DIR *dp;
+ struct dirent *ep;
+
+ dp = opendir("/dev");
+ if (dp == NULL)
+ return -1;
+
+ while ((ep = readdir(dp))) {
+ const char *name = ep->d_name;
+
+ if (!memcmp(name, "media", 5) && isdigit(name[5])) {
+ struct media_device_info mdi;
+ std::string devname = std::string("/dev/") + name;
+
+ int fd = open(devname.c_str(), O_RDWR);
+ if (fd < 0)
+ continue;
+ if (!ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi) &&
+ bus_info == mdi.bus_info) {
+ closedir(dp);
+ return fd;
+ }
+ close(fd);
+ }
+ }
+ closedir(dp);
+ return -1;
+}
+
+static const char *make_devname(const char *device, const char *devname,
+ const std::string &media_bus_info)
+{
+ if (device[0] >= '0' && device[0] <= '9' && strlen(device) <= 3) {
+ static char newdev[32];
+
+ sprintf(newdev, "/dev/%s%s", devname, device);
+ return newdev;
+ }
+ if (media_bus_info.empty())
+ return device;
+ int media_fd = open_media_bus_info(media_bus_info);
+ if (media_fd < 0)
+ return device;
+
+ media_v2_topology topology;
+ memset(&topology, 0, sizeof(topology));
+ if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology)) {
+ close(media_fd);
+ return device;
+ }
+
+ media_v2_entity *ents = new media_v2_entity[topology.num_entities];
+ topology.ptr_entities = (__u64)ents;
+ media_v2_link *links = new media_v2_link[topology.num_links];
+ topology.ptr_links = (__u64)links;
+ media_v2_interface *ifaces = new media_v2_interface[topology.num_interfaces];
+ topology.ptr_interfaces = (__u64)ifaces;
+
+ unsigned i, ent_id, iface_id = 0;
+
+ if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology))
+ goto err;
+
+ if (device[0] == '0' && device[1] == 'x')
+ iface_id = strtoul(device, NULL, 16);
+
+ if (!iface_id) {
+ for (i = 0; i < topology.num_entities; i++)
+ if (!strcmp(ents[i].name, device))
+ break;
+ if (i >= topology.num_entities)
+ goto err;
+ ent_id = ents[i].id;
+ for (i = 0; i < topology.num_links; i++)
+ if (links[i].sink_id == ent_id &&
+ (links[i].flags & MEDIA_LNK_FL_LINK_TYPE) ==
+ MEDIA_LNK_FL_INTERFACE_LINK)
+ break;
+ if (i >= topology.num_links)
+ goto err;
+ iface_id = links[i].source_id;
+ }
+ for (i = 0; i < topology.num_interfaces; i++)
+ if (ifaces[i].id == iface_id)
+ break;
+ if (i >= topology.num_interfaces)
+ goto err;
+
+ static char newdev[32];
+ sprintf(newdev, "/dev/char/%d:%d",
+ ifaces[i].devnode.major, ifaces[i].devnode.minor);
+ device = newdev;
+
+err:
+ delete [] ents;
+ delete [] links;
+ delete [] ifaces;
+ close(media_fd);
+ return device;
+}
+
int main(int argc, char **argv)
{
int i;
@@ -958,6 +1062,7 @@ int main(int argc, char **argv)
int exp_fd = -1;
int media_fd = -1;
bool is_subdev = false;
+ std::string media_bus_info;
/* command args */
int ch;
@@ -1062,31 +1167,16 @@ int main(int argc, char **argv)
usage_all();
return 0;
case OptSetDevice:
- device = optarg;
- if (device[0] >= '0' && device[0] <= '9' && strlen(device) <= 3) {
- static char newdev[20];
-
- sprintf(newdev, "/dev/video%s", device);
- device = newdev;
- }
+ device = make_devname(optarg, "video", media_bus_info);
break;
case OptSetOutDevice:
- out_device = optarg;
- if (out_device[0] >= '0' && out_device[0] <= '9' && strlen(out_device) <= 3) {
- static char newdev[20];
-
- sprintf(newdev, "/dev/video%s", out_device);
- out_device = newdev;
- }
+ out_device = make_devname(optarg, "video", media_bus_info);
break;
case OptSetExportDevice:
- export_device = optarg;
- if (export_device[0] >= '0' && export_device[0] <= '9' && strlen(export_device) <= 3) {
- static char newdev[20];
-
- sprintf(newdev, "/dev/video%s", export_device);
- export_device = newdev;
- }
+ export_device = make_devname(optarg, "video", media_bus_info);
+ break;
+ case OptMediaBusInfo:
+ media_bus_info = optarg;
break;
case OptWaitForEvent:
wait_for_event = parse_event(optarg, &wait_event_id);
diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h
index 739dc5a..ef565d5 100644
--- a/utils/v4l2-ctl/v4l2-ctl.h
+++ b/utils/v4l2-ctl/v4l2-ctl.h
@@ -82,6 +82,7 @@ enum Option {
OptUseWrapper = 'w',
OptGetVideoOutFormat = 'X',
OptSetVideoOutFormat = 'x',
+ OptMediaBusInfo = 'z',
OptGetSlicedVbiOutFormat = 128,
OptGetOverlayFormat,

Privacy Policy