This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:
Subject: v4l2-ctl: add -z option to make it possible to use entity names Author: Hans Verkuil <hverkuil-ci...@xs4all.nl> Date: Fri Feb 1 14:29:26 2019 +0100 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-ci...@xs4all.nl> utils/v4l2-ctl/v4l2-ctl-common.cpp | 13 ++++ utils/v4l2-ctl/v4l2-ctl.1.in | 19 +++++- utils/v4l2-ctl/v4l2-ctl.cpp | 132 +++++++++++++++++++++++++++++++------ utils/v4l2-ctl/v4l2-ctl.h | 1 + 4 files changed, 142 insertions(+), 23 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=73b8d3eb769241f7f81e67b73a9ce6e6c167baeb diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp b/utils/v4l2-ctl/v4l2-ctl-common.cpp index c660d15f22fc..11fe602ebc7f 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 132f51346db2..f37d6e3d3cf4 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 fc19798c06f3..057b08e34136 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 739dc5a9fed2..ef565d5a652f 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, _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits