aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.1.in56
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.cpp134
2 files changed, 161 insertions, 29 deletions
diff --git a/utils/v4l2-compliance/v4l2-compliance.1.in b/utils/v4l2-compliance/v4l2-compliance.1.in
index a0563a1..9533e39 100644
--- a/utils/v4l2-compliance/v4l2-compliance.1.in
+++ b/utils/v4l2-compliance/v4l2-compliance.1.in
@@ -3,9 +3,7 @@
v4l2-compliance - An application to test video4linux drivers
.SH SYNOPSIS
.B v4l2-compliance
-[\fI-h\fR] [\fI-d <dev>\fR] [\fI-r <dev>\fR] [\fI-V <dev>\fR] [\fI-S <dev>\fR] [\fI-e <dev>\fR]
-[\fI-s <count>\fR] [\fI-f\fR] [\fI-a\fR] [\fI-c color=<color>,skip=<skip>,perc=<perc>\fR]
-[\fI-n\fR] [\fI-T\fR] [\fI-v\fR] [\fI-w\fR]
+[\fI-h\fR] [\fI-d <dev>\fR] [many other options]
.SH DESCRIPTION
The v4l2-compliance tool is used to test video4linux devices, either video, vbi, radio
or swradio, both input and output. It attempts to test almost all aspects of a V4L2 device
@@ -54,35 +52,59 @@ very good shape!
.SH OPTIONS
.TP
\fB\-d\fR, \fB\-\-device\fR \fI<dev>\fR
-Use device <dev> as the video device. If <dev> is a number, then /dev/video<dev> is used.
+Use device \fI<dev>\fR as the video device. If \fI<dev>\fR is a number, 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\-\-vbi\-device\fR \fI<dev>\fR
-Use device <dev> as the vbi device. If <dev> is a number, then /dev/vbi<dev> is used.
+Use device \fI<dev>\fR as the vbi device. If \fI<dev>\fR is a number, then /dev/vbi\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\-r\fR, \fB\-\-radio\-device\fR \fI<dev>\fR
-Use device <dev> as the radio device. If <dev> is a number, then /dev/radio<dev> is used.
+Use device \fI<dev>\fR as the radio device. If \fI<dev>\fR is a number, then /dev/radio\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\-S\fR, \fB\-\-sdr\-device\fR \fI<dev>\fR
-Use device <dev> as the SDR device. If <dev> is a number, then /dev/swradio<dev> is used.
+Use device \fI<dev>\fR as the SDR device. If \fI<dev>\fR is a number, then /dev/swradio\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\-t\fR, \fB\-\-touch\-device\fR \fI<dev>\fR
-Use device <dev> as the touch device. If <dev> is a number, then /dev/v4l-touch<dev> is used.
+Use device \fI<dev>\fR as the touch device. If \fI<dev>\fR is a number, then /dev/v4l-touch\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\-u\fR, \fB\-\-subdev\-device\fR \fI<dev>\fR
-Use device <dev> as the v4l-subdevX device. If <dev> is a number, then /dev/v4l-subdev<dev> is used.
+Use device \fI<dev>\fR as the v4l-subdevX device. If \fI<dev>\fR is a number, then /dev/v4l-subdev\fI<dev>\fR is used.
+Otherwise if \fB-z\fR was specified earlier, then \fI<dev>\fR is the entity name
+\fB\-e\fR, \fB\-\-exp\-buf\-device\fR \fI<dev>\fR
+Use device \fI<dev>\fR as the video device used to export DMABUFfers for doing DMABUF
+streaming tests. If \fI<dev>\fR is a number, 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.
+If this option is not specified, then the DMABUF streaming tests will be skipped.
+.TP
+\fB-z\fR, \fB--media-bus-info\fR \fI<bus-info>\fR
+Find the media device with the given bus info string. If set, then
+the options above can use the entity name or interface ID to refer to the
+device nodes. Example: v4l2-compliance -z platform:vivid-000 -d vivid-000-vid-cap
.TP
\fB\-m\fR, \fB\-\-media\-device\fR \fI<dev>\fR
-Use device <dev> as the media controller device. Besides this device it also tests
-all interfaces it finds. If <dev> starts with a digit, then /dev/media<dev> is used.
+Use device \fI<dev>\fR as the media controller device. Besides this device it also tests
+all interfaces it finds. If \fI<dev>\fR starts with a digit, then /dev/media\fI<dev>\fR is used.
.TP
\fB\-M\fR, \fB\-\-media\-device\-only\fR \fI<dev>\fR
-Use device <dev> as the media controller device. Only test this device, don't walk
-over all the interfaces. If <dev> starts with a digit, then /dev/media<dev> is used.
+Use device \fI<dev>\fR as the media controller device. Only test this device, don't walk
+over all the interfaces. If \fI<dev>\fR starts with a digit, then /dev/media\fI<dev>\fR is used.
.TP
-\fB\-e\fR, \fB\-\-exp\-buf\-device\fR \fI<dev>\fR
-Use device <dev> as the video device used to export DMABUFfers for doing DMABUF
-streaming tests. If <dev> is a number, then /dev/video<dev> is used. If this option
-is not specified, then the DMABUF streaming tests will be skipped.
.TP
\fB\-\-stream\-from\fR \fI[<pixelformat>=]<file>\fR, \fB\-\-stream\-from\-hdr\fR \fI[<pixelformat>=]<file>\fR
Use the contents of the file to fill in output buffers.
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
index 60ee2fe..a4f8775 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -72,6 +72,7 @@ enum Option {
OptSetVbiDevice = 'V',
OptUseWrapper = 'w',
OptExitOnWarn = 'W',
+ OptMediaBusInfo = 'z',
OptStreamFrom = 128,
OptStreamFromHdr,
OptLast = 256
@@ -129,6 +130,7 @@ static struct option long_options[] = {
{"touch-device", required_argument, 0, OptSetTouchDevice},
{"media-device", required_argument, 0, OptSetMediaDevice},
{"media-device-only", required_argument, 0, OptSetMediaDeviceOnly},
+ {"media-bus-info", required_argument, 0, OptMediaBusInfo},
{"help", no_argument, 0, OptHelp},
{"verbose", no_argument, 0, OptVerbose},
{"no-warnings", no_argument, 0, OptNoWarnings},
@@ -153,21 +155,37 @@ static void usage(void)
printf("Common options:\n");
printf(" -d, --device <dev> Use device <dev> as the video device.\n");
printf(" If <dev> starts with a digit, then /dev/video<dev> is used.\n");
+ printf(" Otherwise if -z was specified earlier, then <dev> is the entity name\n");
+ printf(" or interface ID (if prefixed with 0x) as found in the topology of the\n");
+ printf(" media device with the bus info string as specified by the -z option.\n");
printf(" -V, --vbi-device <dev>\n");
printf(" Use device <dev> as the vbi device.\n");
printf(" If <dev> starts with a digit, then /dev/vbi<dev> is used.\n");
+ printf(" See the -d description of how <dev> is used in combination with -z.\n");
printf(" -r, --radio-device <dev>\n");
printf(" Use device <dev> as the radio device.\n");
printf(" If <dev> starts with a digit, then /dev/radio<dev> is used.\n");
+ printf(" See the -d description of how <dev> is used in combination with -z.\n");
printf(" -S, --sdr-device <dev>\n");
printf(" Use device <dev> as the SDR device.\n");
printf(" If <dev> starts with a digit, then /dev/swradio<dev> is used.\n");
+ printf(" See the -d description of how <dev> is used in combination with -z.\n");
printf(" -t, --touch-device <dev>\n");
printf(" Use device <dev> as the touch device.\n");
printf(" If <dev> starts with a digit, then /dev/v4l-touch<dev> is used.\n");
+ printf(" See the -d description of how <dev> is used in combination with -z.\n");
printf(" -u, --subdev-device <dev>\n");
printf(" Use device <dev> as the v4l-subdev device.\n");
printf(" If <dev> starts with a digit, then /dev/v4l-subdev<dev> is used.\n");
+ printf(" See the -d description of how <dev> is used in combination with -z.\n");
+ printf(" -e, --expbuf-device <dev>\n");
+ printf(" Use video device <dev> to obtain DMABUF handles.\n");
+ printf(" If <dev> starts with a digit, then /dev/video<dev> is used.\n");
+ printf(" See the -d description of how <dev> is used in combination with -z.\n");
+ printf(" -z, --media-bus-info <bus-info>\n");
+ printf(" Find the media device with the given bus info string. If set, then\n");
+ printf(" the options above can use the entity name or interface ID to refer\n");
+ printf(" to the device nodes.\n");
printf(" -m, --media-device <dev>\n");
printf(" Use device <dev> as the media controller device. Besides this\n");
printf(" device it also tests all interfaces it finds.\n");
@@ -176,10 +194,6 @@ static void usage(void)
printf(" Use device <dev> as the media controller device. Only test this\n");
printf(" device, don't walk over all the interfaces.\n");
printf(" If <dev> starts with a digit, then /dev/media<dev> is used.\n");
- printf(" -e, --expbuf-device <dev>\n");
- printf(" Use device <dev> to obtain DMABUF handles.\n");
- printf(" If <dev> starts with a digit, then /dev/video<dev> is used.\n");
- printf(" only /dev/videoX devices are supported.\n");
printf(" -s, --streaming <count>\n");
printf(" Enable the streaming tests. Set <count> to the number of\n");
printf(" frames to stream (default 60). Requires a valid input/output\n");
@@ -769,7 +783,39 @@ static int parse_subopt(char **subs, const char * const *subopts, char **value)
return opt;
}
-static const char *make_devname(const char *device, const char *devname)
+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];
@@ -777,6 +823,66 @@ static const char *make_devname(const char *device, const char *devname)
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;
}
@@ -1298,6 +1404,7 @@ int main(int argc, char **argv)
struct node node;
media_type type = MEDIA_TYPE_UNKNOWN;
struct node expbuf_node;
+ std::string media_bus_info;
/* command args */
int ch;
@@ -1364,28 +1471,31 @@ int main(int argc, char **argv)
usage();
return 0;
case OptSetDevice:
- device = make_devname(optarg, "video");
+ device = make_devname(optarg, "video", media_bus_info);
break;
case OptSetVbiDevice:
- device = make_devname(optarg, "vbi");
+ device = make_devname(optarg, "vbi", media_bus_info);
break;
case OptSetRadioDevice:
- device = make_devname(optarg, "radio");
+ device = make_devname(optarg, "radio", media_bus_info);
break;
case OptSetSWRadioDevice:
- device = make_devname(optarg, "swradio");
+ device = make_devname(optarg, "swradio", media_bus_info);
break;
case OptSetTouchDevice:
- device = make_devname(optarg, "v4l-touch");
+ device = make_devname(optarg, "v4l-touch", media_bus_info);
break;
case OptSetSubDevDevice:
- device = make_devname(optarg, "v4l-subdev");
+ device = make_devname(optarg, "v4l-subdev", media_bus_info);
break;
case OptSetMediaDevice:
case OptSetMediaDeviceOnly:
- device = make_devname(optarg, "media");
+ device = make_devname(optarg, "media", media_bus_info);
type = MEDIA_TYPE_MEDIA;
break;
+ case OptMediaBusInfo:
+ media_bus_info = optarg;
+ break;
case OptSetExpBufDevice:
expbuf_device = optarg;
if (expbuf_device[0] >= '0' && expbuf_device[0] <= '9' && strlen(expbuf_device) <= 3) {

Privacy Policy