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: show media/entity info if available
Author:  Hans Verkuil <hans.verk...@cisco.com>
Date:    Fri Feb 2 12:24:43 2018 +0100

If a media device is detected, then show the media and entity info
if the -D option is given.

Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>

 utils/v4l2-ctl/v4l2-ctl.cpp | 231 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 224 insertions(+), 7 deletions(-)

---

http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=65e7b2a4076845d3932b88cb9c76f1fa4b78c32c
diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
index 0a0ca8e4658b..02baf48cc9df 100644
--- a/utils/v4l2-ctl/v4l2-ctl.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl.cpp
@@ -33,9 +33,12 @@
 #include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
+#include <sys/sysmacros.h>
 #include <dirent.h>
 #include <math.h>
 
+#include <linux/media.h>
+
 #include "v4l2-ctl.h"
 
 #ifdef HAVE_SYS_KLOG_H
@@ -1222,6 +1225,42 @@ __u32 find_pixel_format(int fd, unsigned index, bool 
output, bool mplane)
        return fmt.pixelformat;
 }
 
+static int get_media_fd(int fd)
+{
+       struct stat sb;
+       int media_fd = -1;
+
+       if (fstat(fd, &sb) == -1) {
+               fprintf(stderr, "failed to stat file\n");
+               exit(1);
+       }
+
+       char media_path[100];
+       if (snprintf(media_path, sizeof(media_path), 
"/sys/dev/char/%d:%d/device",
+                    major(sb.st_rdev), minor(sb.st_rdev)) == -1) {
+               fprintf(stderr, "failed to create media file path\n");
+               exit(1);
+       }
+       DIR *dp;
+       struct dirent *ep;
+       dp = opendir(media_path);
+       if (dp == NULL) {
+               perror("Couldn't open the directory");
+               exit(1);
+       }
+       media_path[0] = 0;
+       while ((ep = readdir(dp))) {
+               if (!memcmp(ep->d_name, "media", 5) && isdigit(ep->d_name[5])) {
+                       if (snprintf(media_path, sizeof(media_path),
+                                    "/dev/%s", ep->d_name) >= 0)
+                               media_fd = open(media_path, O_RDWR);
+                       break;
+               }
+       }
+       closedir(dp);
+       return media_fd;
+}
+
 static bool is_subdevice(int fd)
 {
        struct stat sb;
@@ -1275,12 +1314,172 @@ static bool is_subdevice(int fd)
        exit(1);
 }
 
+static const flag_def entity_flags_def[] = {
+       { MEDIA_ENT_FL_DEFAULT, "default" },
+       { MEDIA_ENT_FL_CONNECTOR, "connector" },
+       { 0, NULL }
+};
+
+static std::string entflags2s(__u32 flags)
+{
+       return flags2s(flags, entity_flags_def);
+}
+
+static const flag_def entity_types_def[] = {
+       { MEDIA_ENT_F_UNKNOWN, "Unknown" },
+       { MEDIA_ENT_F_DTV_DEMOD, "Digital TV Demodulator" },
+       { MEDIA_ENT_F_TS_DEMUX, "Transport Stream Demuxer" },
+       { MEDIA_ENT_F_DTV_CA, "Digital TV Conditional Access" },
+       { MEDIA_ENT_F_DTV_NET_DECAP, "Digital TV Network ULE/MLE 
Desencapsulation" },
+       { MEDIA_ENT_F_IO_DTV, "Digital TV I/O" },
+       { MEDIA_ENT_F_IO_VBI, "VBI I/O" },
+       { MEDIA_ENT_F_IO_SWRADIO, "Software Radio I/O" },
+       { MEDIA_ENT_F_IF_VID_DECODER, "IF-PLL Video Decoder" },
+       { MEDIA_ENT_F_IF_AUD_DECODER, "IF-PLL Audio Decoder" },
+       { MEDIA_ENT_F_AUDIO_CAPTURE, "Audio Capture" },
+       { MEDIA_ENT_F_AUDIO_PLAYBACK, "Audio Playback" },
+       { MEDIA_ENT_F_AUDIO_MIXER, "Audio Mixer" },
+       { MEDIA_ENT_F_PROC_VIDEO_COMPOSER, "Video Composer" },
+       { MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER, "Video Pixel Formatter" },
+       { MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, "Video Pixel Encoding 
Converter" },
+       { MEDIA_ENT_F_PROC_VIDEO_LUT, "Video Look-Up Table" },
+       { MEDIA_ENT_F_PROC_VIDEO_SCALER, "Video Scaler" },
+       { MEDIA_ENT_F_PROC_VIDEO_STATISTICS, "Video Statistics" },
+       { MEDIA_ENT_F_VID_MUX, "Video Muxer" },
+       { MEDIA_ENT_F_VID_IF_BRIDGE, "Video Interface Bridge" },
+
+       { MEDIA_ENT_F_IO_V4L, "V4L2 I/O" },
+       { MEDIA_ENT_F_CAM_SENSOR, "Camera Sensor" },
+       { MEDIA_ENT_F_FLASH, "Flash Controller" },
+       { MEDIA_ENT_F_LENS, "Lens Controller" },
+       { MEDIA_ENT_F_ATV_DECODER, "Analog Video Decoder" },
+       { MEDIA_ENT_F_TUNER, "Tuner" },
+       { MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN, "Unknown" },
+       { 0, NULL }
+};
+
+static std::string enttype2s(__u32 type)
+{
+       for (unsigned i = 0; entity_types_def[i].str; i++)
+               if (type == entity_types_def[i].flag)
+                       return entity_types_def[i].str;
+       return "Unknown (" + num2s(type) + ")";
+}
+
+static const flag_def pad_flags_def[] = {
+       { MEDIA_PAD_FL_SINK, "Sink" },
+       { MEDIA_PAD_FL_SOURCE, "Source" },
+       { MEDIA_PAD_FL_MUST_CONNECT, "Must Connect" },
+       { 0, NULL }
+};
+
+static std::string padflags2s(__u32 flags)
+{
+       return flags2s(flags, pad_flags_def);
+}
+
+static const flag_def link_flags_def[] = {
+       { MEDIA_LNK_FL_ENABLED, "Enabled" },
+       { MEDIA_LNK_FL_IMMUTABLE, "Immutable" },
+       { MEDIA_LNK_FL_DYNAMIC, "Dynamic" },
+       { 0, NULL }
+};
+
+static std::string linkflags2s(__u32 flags)
+{
+       switch (flags & MEDIA_LNK_FL_LINK_TYPE) {
+       case MEDIA_LNK_FL_DATA_LINK:
+               return "Data " + flags2s(flags, link_flags_def);
+       case MEDIA_LNK_FL_INTERFACE_LINK:
+               return "Interface " + flags2s(flags, link_flags_def);
+       default:
+               return "Unknown " + flags2s(flags, link_flags_def);
+       }
+}
+
+static void mdev_info(int fd, int media_fd)
+{
+       struct media_device_info mdinfo;
+       struct stat sb;
+
+       if (fstat(fd, &sb) == -1) {
+               fprintf(stderr, "failed to stat file\n");
+               exit(1);
+       }
+
+       if (ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &mdinfo))
+               return;
+
+       struct media_entity_desc ent;
+       bool found = false;
+
+       printf("Media Driver Info:\n");
+       printf("\tDriver name      : %s\n", mdinfo.driver);
+       printf("\tModel            : %s\n", mdinfo.model);
+       printf("\tSerial           : %s\n", mdinfo.serial);
+       printf("\tBus info         : %s\n", mdinfo.bus_info);
+       printf("\tMedia version    : %d.%d.%d\n",
+              mdinfo.media_version >> 16,
+              (mdinfo.media_version >> 8) & 0xff,
+              mdinfo.media_version & 0xff);
+       printf("\tHardware revision: 0x%08x, %d\n",
+              mdinfo.hw_revision, mdinfo.hw_revision);
+       printf("\tDriver version   : %d.%d.%d\n",
+              mdinfo.driver_version >> 16,
+              (mdinfo.driver_version >> 8) & 0xff,
+              mdinfo.driver_version & 0xff);
+
+       memset(&ent, 0, sizeof(ent));
+       ent.id = MEDIA_ENT_ID_FLAG_NEXT;
+       while (!ioctl(media_fd, MEDIA_IOC_ENUM_ENTITIES, &ent)) {
+               if (ent.dev.major == major(sb.st_rdev) &&
+                   ent.dev.minor == minor(sb.st_rdev)) {
+                       found = true;
+                       break;
+               }
+               ent.id |= MEDIA_ENT_ID_FLAG_NEXT;
+       }
+       if (!found)
+               return;
+
+       printf("Entity Info:\n");
+       printf("\tID   : %u\n", ent.id);
+       printf("\tName : %s\n", ent.name);
+       printf("\tType : %s\n", enttype2s(ent.type).c_str());
+       printf("\tFlags: %s\n", entflags2s(ent.flags).c_str());
+       if (ent.flags & MEDIA_ENT_FL_DEFAULT) {
+               printf("\tMajor: %u\n", ent.dev.major);
+               printf("\tMinor: %u\n", ent.dev.minor);
+       }
+
+       struct media_links_enum links_enum;
+       struct media_pad_desc pads[ent.pads];
+       struct media_link_desc links[ent.links];
+
+       memset(&links_enum, 0, sizeof(links_enum));
+       links_enum.entity = ent.id;
+       links_enum.pads = pads;
+       links_enum.links = links;
+       if (ioctl(media_fd, MEDIA_IOC_ENUM_LINKS, &links_enum))
+               return;
+
+       for (unsigned i = 0; i < ent.pads; i++)
+               printf("\tPad %u: %s\n", pads[i].index,
+                      padflags2s(pads[i].flags).c_str());
+       for (unsigned i = 0; i < ent.links; i++)
+               printf("\tLinks %u->%u: %s\n",
+                      links[i].source.entity,
+                      links[i].sink.entity,
+                      linkflags2s(links[i].flags).c_str());
+}
+
 int main(int argc, char **argv)
 {
        int i;
-
        int fd = -1;
        int out_fd = -1;
+       int media_fd = -1;
+       bool is_subdev = false;
 
        /* command args */
        int ch;
@@ -1440,14 +1639,26 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       if ((fd = test_open(device, O_RDWR)) < 0) {
+       if ((fd = open(device, O_RDWR)) < 0) {
                fprintf(stderr, "Failed to open %s: %s\n", device,
                        strerror(errno));
                exit(1);
        }
-
        verbose = options[OptVerbose];
-       if (!is_subdevice(fd) && doioctl(fd, VIDIOC_QUERYCAP, &vcap)) {
+       is_subdev = is_subdevice(fd);
+       if (is_subdev)
+               options[OptUseWrapper] = 0;
+
+       if (options[OptUseWrapper]) {
+               close(fd);
+               if ((fd = test_open(device, O_RDWR)) < 0) {
+                       fprintf(stderr, "Failed to open %s: %s\n", device,
+                               strerror(errno));
+                       exit(1);
+               }
+       }
+
+       if (!is_subdev && doioctl(fd, VIDIOC_QUERYCAP, &vcap)) {
                fprintf(stderr, "%s: not a v4l2 node\n", device);
                exit(1);
        }
@@ -1455,6 +1666,8 @@ int main(int argc, char **argv)
        if (capabilities & V4L2_CAP_DEVICE_CAPS)
                capabilities = vcap.device_caps;
 
+       media_fd = get_media_fd(fd);
+
        priv_magic = (capabilities & V4L2_CAP_EXT_PIX_FORMAT) ?
                        V4L2_PIX_FMT_PRIV_MAGIC : 0;
        is_multiplanar = capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
@@ -1533,9 +1746,9 @@ int main(int argc, char **argv)
 
        /* Information Opts */
 
-       if (options[OptGetDriverInfo]) {
-               printf("Driver Info (%susing libv4l2):\n",
-                               options[OptUseWrapper] ? "" : "not ");
+       if (!is_subdev && options[OptGetDriverInfo]) {
+               printf("Driver Info%s:\n",
+                               options[OptUseWrapper] ? " (using libv4l2)" : 
"");
                printf("\tDriver name   : %s\n", vcap.driver);
                printf("\tCard type     : %s\n", vcap.card);
                printf("\tBus info      : %s\n", vcap.bus_info);
@@ -1550,6 +1763,8 @@ int main(int argc, char **argv)
                        printf("%s", cap2s(vcap.device_caps).c_str());
                }
        }
+       if (options[OptGetDriverInfo] && media_fd >= 0)
+               mdev_info(fd, media_fd);
 
        /* Set options */
 
@@ -1662,6 +1877,8 @@ int main(int argc, char **argv)
        test_close(fd);
        if (out_device)
                test_close(out_fd);
+       if (media_fd >= 0)
+               close(media_fd);
 
        // --all sets --silent to avoid ioctl errors to be shown when an ioctl
        // is not implemented by the driver. Which is fine, but we shouldn't

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to