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-compliance: add initial support for v4l-subdevX devices
Author:  Hans Verkuil <hans.verk...@cisco.com>
Date:    Fri Feb 2 13:29:41 2018 +0100

Still to do: write subdev-specific tests.

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

 utils/v4l2-compliance/v4l2-compliance.cpp | 335 ++++++++++++++++++++++++++++--
 utils/v4l2-compliance/v4l2-compliance.h   |   1 +
 2 files changed, 317 insertions(+), 19 deletions(-)

---

http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=3f86d8e1fb39759cefea7840c888c474ea0ffeea
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp 
b/utils/v4l2-compliance/v4l2-compliance.cpp
index 7749e7741374..ce7ac660a8ce 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -26,15 +26,20 @@
 #include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include <ctype.h>
 #include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
+#include <sys/sysmacros.h>
+#include <dirent.h>
 #include <math.h>
 #include <sys/utsname.h>
 #include <signal.h>
 #include <vector>
 
+#include <linux/media.h>
+
 #include "v4l2-compliance.h"
 #ifndef ANDROID
 #include "version.h"
@@ -60,6 +65,7 @@ enum Option {
        OptSetSWRadioDevice = 'S',
        OptSetTouchDevice = 't',
        OptTrace = 'T',
+       OptSetSubDevDevice = 'u',
        OptVerbose = 'v',
        OptSetVbiDevice = 'V',
        OptUseWrapper = 'w',
@@ -75,6 +81,7 @@ static int tests_total, tests_ok;
 bool show_info;
 bool show_warnings = true;
 int kernel_version;
+int media_fd = -1;
 unsigned warnings;
 
 static unsigned color_component;
@@ -108,6 +115,7 @@ static struct option long_options[] = {
        {"radio-device", required_argument, 0, OptSetRadioDevice},
        {"vbi-device", required_argument, 0, OptSetVbiDevice},
        {"sdr-device", required_argument, 0, OptSetSWRadioDevice},
+       {"subdev-device", required_argument, 0, OptSetSubDevDevice},
        {"expbuf-device", required_argument, 0, OptSetExpBufDevice},
        {"touch-device", required_argument, 0, OptSetTouchDevice},
        {"help", no_argument, 0, OptHelp},
@@ -142,6 +150,9 @@ static void usage(void)
        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("  -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("  -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");
@@ -712,6 +723,234 @@ static int parse_subopt(char **subs, const char * const 
*subopts, char **value)
        return opt;
 }
 
+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;
+}
+
+typedef struct {
+       unsigned flag;
+       const char *str;
+} flag_def;
+
+static std::string num2s(unsigned num)
+{
+       char buf[10];
+
+       sprintf(buf, "%08x", num);
+       return buf;
+}
+
+static std::string flags2s(unsigned val, const flag_def *def)
+{
+       std::string s;
+
+       while (def->flag) {
+               if (val & def->flag) {
+                       if (s.length()) s += ", ";
+                       s += def->str;
+                       val &= ~def->flag;
+               }
+               def++;
+       }
+       if (val) {
+               if (s.length()) s += ", ";
+               s += num2s(val);
+       }
+       return s;
+}
+
+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;
@@ -726,6 +965,8 @@ int main(int argc, char **argv)
        struct node sdr_node2;
        struct node touch_node;
        struct node touch_node2;
+       struct node subdev_node;
+       struct node subdev_node2;
        struct node expbuf_node;
 
        /* command args */
@@ -736,6 +977,7 @@ int main(int argc, char **argv)
        const char *radio_device = NULL;        /* -r device */
        const char *sdr_device = NULL;          /* -S device */
        const char *touch_device = NULL;        /* -t device */
+       const char *subdev_device = NULL;       /* -u device */
        const char *expbuf_device = NULL;       /* --expbuf-device device */
        struct v4l2_capability vcap;            /* list_cap */
        unsigned frame_count = 60;
@@ -813,6 +1055,15 @@ int main(int argc, char **argv)
                                touch_device = newdev;
                        }
                        break;
+               case OptSetSubDevDevice:
+                       subdev_device = optarg;
+                       if (subdev_device[0] >= '0' && subdev_device[0] <= '9' 
&& strlen(subdev_device) <= 3) {
+                               static char newdev[20];
+
+                               sprintf(newdev, "/dev/v4l-subdev%s", 
subdev_device);
+                               subdev_device = newdev;
+                       }
+                       break;
                case OptSetExpBufDevice:
                        expbuf_device = optarg;
                        if (expbuf_device[0] >= '0' && expbuf_device[0] <= '9' 
&& strlen(expbuf_device) <= 3) {
@@ -903,7 +1154,7 @@ int main(int argc, char **argv)
                kernel_version = v3;
 
        if (!video_device && !vbi_device && !radio_device &&
-           !sdr_device && !touch_device)
+           !sdr_device && !touch_device && !subdev_device)
                video_device = "/dev/video0";
 
        if (video_device) {
@@ -961,6 +1212,17 @@ int main(int argc, char **argv)
                }
        }
 
+       if (subdev_device) {
+               subdev_node.s_trace(options[OptTrace]);
+               subdev_node.s_direct(true);
+               fd = subdev_node.subdev_open(subdev_device, false);
+               if (fd < 0) {
+                       fprintf(stderr, "Failed to open %s: %s\n", 
subdev_device,
+                               strerror(errno));
+                       exit(1);
+               }
+       }
+
        if (expbuf_device) {
                expbuf_node.s_trace(options[OptTrace]);
                expbuf_node.s_direct(true);
@@ -992,10 +1254,16 @@ int main(int argc, char **argv)
                node = touch_node;
                device = touch_device;
                node.is_touch = true;
+       } else if (subdev_node.g_fd() >= 0) {
+               node = subdev_node;
+               device = subdev_device;
        }
        node.device = device;
 
-       doioctl(&node, VIDIOC_QUERYCAP, &vcap);
+       if (node.is_subdev())
+               memset(&vcap, 0, sizeof(vcap));
+       else
+               doioctl(&node, VIDIOC_QUERYCAP, &vcap);
        if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
                         V4L2_CAP_VIDEO_CAPTURE_MPLANE | 
V4L2_CAP_SLICED_VBI_CAPTURE))
                node.has_inputs = true;
@@ -1033,29 +1301,37 @@ int main(int argc, char **argv)
        if (kernel_version)
                printf("Running on 2.6.%d\n", kernel_version);
 
-       printf("\nDriver Info:\n");
-       printf("\tDriver name   : %s\n", vcap.driver);
-       printf("\tCard type     : %s\n", vcap.card);
-       printf("\tBus info      : %s\n", vcap.bus_info);
-       printf("\tDriver version: %d.%d.%d\n",
-                       vcap.version >> 16,
-                       (vcap.version >> 8) & 0xff,
-                       vcap.version & 0xff);
-       printf("\tCapabilities  : 0x%08X\n", vcap.capabilities);
-       printf("%s", cap2s(vcap.capabilities).c_str());
-       if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) {
-               printf("\tDevice Caps   : 0x%08X\n", vcap.device_caps);
-               printf("%s", cap2s(vcap.device_caps).c_str());
+       media_fd = get_media_fd(node.g_fd());
+
+       if (!node.is_subdev()) {
+               printf("\nDriver Info:\n");
+               printf("\tDriver name   : %s\n", vcap.driver);
+               printf("\tCard type     : %s\n", vcap.card);
+               printf("\tBus info      : %s\n", vcap.bus_info);
+               printf("\tDriver version: %d.%d.%d\n",
+                      vcap.version >> 16,
+                      (vcap.version >> 8) & 0xff,
+                      vcap.version & 0xff);
+               printf("\tCapabilities  : 0x%08X\n", vcap.capabilities);
+               printf("%s", cap2s(vcap.capabilities).c_str());
+               if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) {
+                       printf("\tDevice Caps   : 0x%08X\n", vcap.device_caps);
+                       printf("%s", cap2s(vcap.device_caps).c_str());
+               }
        }
+       if (media_fd >= 0)
+               mdev_info(node.g_fd(), media_fd);
 
        printf("\nCompliance test for device %s%s:\n\n",
                        device, direct ? "" : " (using libv4l2)");
 
        /* Required ioctls */
 
-       printf("Required ioctls:\n");
-       printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&node)));
-       printf("\n");
+       if (!node.is_subdev()) {
+               printf("Required ioctls:\n");
+               printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&node)));
+               printf("\n");
+       }
 
        /* Multiple opens */
 
@@ -1104,6 +1380,24 @@ int main(int argc, char **argv)
                        node.node2 = &sdr_node2;
                }
        }
+       if (touch_device) {
+               touch_node2 = node;
+               printf("\ttest second touch open: %s\n",
+                               ok(touch_node2.open(touch_device, false) >= 0 ? 
0 : errno));
+               if (touch_node2.g_fd() >= 0) {
+                       printf("\ttest VIDIOC_QUERYCAP: %s\n", 
ok(testCap(&touch_node2)));
+                       printf("\ttest VIDIOC_G/S_PRIORITY: %s\n",
+                                       ok(testPrio(&node, &touch_node2)));
+                       node.node2 = &touch_node2;
+               }
+       }
+       if (subdev_device) {
+               subdev_node2 = node;
+               printf("\ttest second subdev open: %s\n",
+                               ok(subdev_node2.subdev_open(subdev_device, 
false) >= 0 ? 0 : errno));
+               if (subdev_node2.g_fd() >= 0)
+                       node.node2 = &subdev_node2;
+       }
        printf("\ttest for unlimited opens: %s\n",
                ok(testUnlimitedOpens(&node)));
        printf("\n");
@@ -1116,7 +1410,8 @@ int main(int argc, char **argv)
        /* Debug ioctls */
 
        printf("Debug ioctls:\n");
-       printf("\ttest VIDIOC_DBG_G/S_REGISTER: %s\n", ok(testRegister(&node)));
+       if (!node.is_subdev())
+               printf("\ttest VIDIOC_DBG_G/S_REGISTER: %s\n", 
ok(testRegister(&node)));
        printf("\ttest VIDIOC_LOG_STATUS: %s\n", ok(testLogStatus(&node)));
        printf("\n");
 
@@ -1320,6 +1615,8 @@ int main(int argc, char **argv)
                node.node2->close();
        if (expbuf_device)
                expbuf_node.close();
+       if (media_fd >= 0)
+               close(media_fd);
        printf("Total: %d, Succeeded: %d, Failed: %d, Warnings: %d\n",
                        tests_total, tests_ok, tests_total - tests_ok, 
warnings);
        if (!strcmp((const char *)vcap.driver, "vivid") && tests_total - 
tests_ok > 19) {
diff --git a/utils/v4l2-compliance/v4l2-compliance.h 
b/utils/v4l2-compliance/v4l2-compliance.h
index 53ea5d5e6987..3dd831428fab 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -48,6 +48,7 @@
 extern bool show_info;
 extern bool show_warnings;
 extern int kernel_version;
+extern int media_fd;
 extern unsigned warnings;
 
 struct test_query_ext_ctrl: v4l2_query_ext_ctrl {

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

Reply via email to