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 routing and streams support
Author:  Tomi Valkeinen <[email protected]>
Date:    Tue Aug 8 09:19:21 2023 +0300

Add support to get and set subdev routes and to get and set
configurations per stream.

Based on work from Jacopo Mondi <[email protected]> and
Niklas Söderlund <[email protected]>.

Signed-off-by: Tomi Valkeinen <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>

 utils/common/v4l2-info.h           |   6 +
 utils/v4l2-ctl/v4l2-ctl-subdev.cpp | 308 ++++++++++++++++++++++++++++++++-----
 utils/v4l2-ctl/v4l2-ctl.cpp        |   2 +
 utils/v4l2-ctl/v4l2-ctl.h          |   2 +
 4 files changed, 282 insertions(+), 36 deletions(-)

---

http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=67988a0050d00018fdc2473f58a86ecba23ee18c
diff --git a/utils/common/v4l2-info.h b/utils/common/v4l2-info.h
index 4a9aa3e831e3..6de5654c53b2 100644
--- a/utils/common/v4l2-info.h
+++ b/utils/common/v4l2-info.h
@@ -11,6 +11,12 @@
 #include <linux/videodev2.h>
 #include <linux/v4l2-subdev.h>
 
+/*
+ * The max value comes from a check in the kernel source code
+ * drivers/media/v4l2-core/v4l2-ioctl.c check_array_args()
+ */
+#define NUM_ROUTES_MAX 256
+
 struct flag_def {
        unsigned flag;
        const char *str;
diff --git a/utils/v4l2-ctl/v4l2-ctl-subdev.cpp 
b/utils/v4l2-ctl/v4l2-ctl-subdev.cpp
index 22fd90526a6f..d906b72da396 100644
--- a/utils/v4l2-ctl/v4l2-ctl-subdev.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-subdev.cpp
@@ -1,5 +1,7 @@
 #include "v4l2-ctl.h"
 
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
 struct mbus_name {
        const char *name;
        __u32 code;
@@ -19,46 +21,56 @@ static const struct mbus_name mbus_names[] = {
 #define SelectionFlags                 (1L<<4)
 
 static __u32 list_mbus_codes_pad;
+static __u32 list_mbus_codes_stream = 0;
 static __u32 get_fmt_pad;
+static __u32 get_fmt_stream = 0;
 static __u32 get_sel_pad;
+static __u32 get_sel_stream = 0;
 static __u32 get_fps_pad;
+static __u32 get_fps_stream = 0;
 static int get_sel_target = -1;
 static unsigned int set_selection;
 static struct v4l2_subdev_selection vsel;
 static unsigned int set_fmt;
 static __u32 set_fmt_pad;
+static __u32 set_fmt_stream = 0;
 static struct v4l2_mbus_framefmt ffmt;
 static struct v4l2_subdev_frame_size_enum frmsize;
 static struct v4l2_subdev_frame_interval_enum frmival;
 static __u32 set_fps_pad;
+static __u32 set_fps_stream = 0;
 static double set_fps;
+static struct v4l2_subdev_routing routing;
+static struct v4l2_subdev_route routes[NUM_ROUTES_MAX];
 
 void subdev_usage()
 {
        printf("\nSub-Device options:\n"
               "Note: all parameters below (pad, code, etc.) are optional 
unless otherwise noted and default to 0\n"
-              "  --list-subdev-mbus-codes <pad>\n"
-              "                      display supported mediabus codes for this 
pad\n"
+              "  --list-subdev-mbus-codes pad=<pad>,stream=<stream>\n"
+              "                      display supported mediabus codes for this 
pad and stream\n"
               "                      [VIDIOC_SUBDEV_ENUM_MBUS_CODE]\n"
-              "  --list-subdev-framesizes pad=<pad>,code=<code>\n"
-              "                     list supported framesizes for this pad and 
code\n"
+              "  --list-subdev-framesizes 
pad=<pad>,stream=<stream>,code=<code>\n"
+              "                     list supported framesizes for this pad, 
stream and code\n"
               "                     [VIDIOC_SUBDEV_ENUM_FRAME_SIZE]\n"
               "                     <code> is the value of the mediabus code\n"
-              "  --list-subdev-frameintervals 
pad=<pad>,width=<w>,height=<h>,code=<code>\n"
-              "                     list supported frame intervals for this 
pad and code and\n"
+              "  --list-subdev-frameintervals 
pad=<pad>,stream=<stream>,width=<w>,height=<h>,code=<code>\n"
+              "                     list supported frame intervals for this 
pad, stream, code and\n"
               "                     the given width and height 
[VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL]\n"
               "                     <code> is the value of the mediabus code\n"
-              "  --get-subdev-fmt [<pad>]\n"
-              "                     query the frame format for the given pad 
[VIDIOC_SUBDEV_G_FMT]\n"
-              "  --get-subdev-selection pad=<pad>,target=<target>\n"
+              "  --get-subdev-fmt pad=<pad>,stream=<stream>\n"
+              "                     query the frame format for the given pad 
and stream [VIDIOC_SUBDEV_G_FMT]\n"
+              "  --get-subdev-selection 
pad=<pad>,stream=<stream>,target=<target>\n"
               "                     query the frame selection rectangle 
[VIDIOC_SUBDEV_G_SELECTION]\n"
               "                     See --set-subdev-selection command for the 
valid <target> values.\n"
-              "  --get-subdev-fps [<pad>]\n"
+              "  --get-subdev-fps pad=<pad>,stream=<stream>\n"
               "                     query the frame rate 
[VIDIOC_SUBDEV_G_FRAME_INTERVAL]\n"
               "  --set-subdev-fmt   (for testing only, otherwise use 
media-ctl)\n"
-              "  --try-subdev-fmt 
pad=<pad>,width=<w>,height=<h>,code=<code>,field=<f>,colorspace=<c>,\n"
+              "  --try-subdev-fmt 
pad=<pad>,stream=<stream>,width=<w>,height=<h>,code=<code>,field=<f>,colorspace=<c>,\n"
               "                   
xfer=<xf>,ycbcr=<y>,hsv=<hsv>,quantization=<q>\n"
-              "                     set the frame format 
[VIDIOC_SUBDEV_S_FMT]\n"
+              "                     set the frame format for the given pad and 
stream [VIDIOC_SUBDEV_S_FMT]\n"
+              "                     <pad> the pad to get the format from\n"
+              "                     <stream> the stream to get the format\n"
               "                     <code> is the value of the mediabus code\n"
               "                     <f> can be one of the following field 
layouts:\n"
               "                       any, none, top, bottom, interlaced, 
seq_tb, seq_bt,\n"
@@ -75,31 +87,74 @@ void subdev_usage()
               "                     <q> can be one of the following 
quantization methods:\n"
               "                       default, full-range, lim-range\n"
               "  --set-subdev-selection (for testing only, otherwise use 
media-ctl)\n"
-              "  --try-subdev-selection 
pad=<pad>,target=<target>,flags=<flags>,\n"
+              "  --try-subdev-selection 
pad=<pad>,stream=<stream>,target=<target>,flags=<flags>,\n"
               "                         
top=<x>,left=<y>,width=<w>,height=<h>\n"
               "                     set the video capture selection rectangle 
[VIDIOC_SUBDEV_S_SELECTION]\n"
               "                     
target=crop|crop_bounds|crop_default|compose|compose_bounds|\n"
               "                            
compose_default|compose_padded|native_size\n"
               "                     flags=le|ge|keep-config\n"
-              "  --set-subdev-fps pad=<pad>,fps=<fps> (for testing only, 
otherwise use media-ctl)\n"
+              "  --set-subdev-fps pad=<pad>,stream=<stream>,fps=<fps> (for 
testing only, otherwise use media-ctl)\n"
               "                     set the frame rate 
[VIDIOC_SUBDEV_S_FRAME_INTERVAL]\n"
+              "  --get-routing      Print the route topology\n"
+              "  --set-routing <routes>\n"
+              "                     Comma-separated list of route descriptors 
to setup\n"
+              "\n"
+              "Routes are defined as\n"
+              "        routes          = route { ',' route } ;\n"
+              "        route           = sink '->' source '[' flags ']' ;\n"
+              "        sink            = sink-pad '/' sink-stream ;\n"
+              "        source          = source-pad '/' source-stream ;\n"
+              "\n"
+              "where\n"
+              "        sink-pad        = Pad numeric identifier for sink\n"
+              "        sink-stream     = Stream numeric identifier for sink\n"
+              "        source-pad      = Pad numeric identifier for source\n"
+              "        source-stream   = Stream numeric identifier for 
source\n"
+              "        flags           = Route flags (0: inactive, 1: 
active)\n"
               );
 }
 
 void subdev_cmd(int ch, char *optarg)
 {
        char *value, *subs;
+       char *endp;
 
        switch (ch) {
        case OptListSubDevMBusCodes:
-               if (optarg)
-                       list_mbus_codes_pad = strtoul(optarg, nullptr, 0);
+               if (optarg) {
+                       /* Legacy pad-only parsing */
+                       list_mbus_codes_pad = strtoul(optarg, &endp, 0);
+                       if (*endp == 0)
+                               break;
+               }
+
+               subs = optarg;
+               while (subs && *subs != '\0') {
+                       static constexpr const char *subopts[] = {
+                               "pad",
+                               "stream",
+                               nullptr
+                       };
+
+                       switch (parse_subopt(&subs, subopts, &value)) {
+                       case 0:
+                               list_mbus_codes_pad = strtoul(value, nullptr, 
0);
+                               break;
+                       case 1:
+                               list_mbus_codes_stream = strtoul(value, 
nullptr, 0);
+                               break;
+                       default:
+                               subdev_usage();
+                               std::exit(EXIT_FAILURE);
+                       }
+               }
                break;
        case OptListSubDevFrameSizes:
                subs = optarg;
                while (*subs != '\0') {
                        static constexpr const char *subopts[] = {
                                "pad",
+                               "stream",
                                "code",
                                nullptr
                        };
@@ -109,6 +164,9 @@ void subdev_cmd(int ch, char *optarg)
                                frmsize.pad = strtoul(value, nullptr, 0);
                                break;
                        case 1:
+                               frmsize.stream = strtoul(value, nullptr, 0);
+                               break;
+                       case 2:
                                frmsize.code = strtoul(value, nullptr, 0);
                                break;
                        default:
@@ -122,6 +180,7 @@ void subdev_cmd(int ch, char *optarg)
                while (*subs != '\0') {
                        static constexpr const char *subopts[] = {
                                "pad",
+                               "stream",
                                "code",
                                "width",
                                "height",
@@ -133,12 +192,15 @@ void subdev_cmd(int ch, char *optarg)
                                frmival.pad = strtoul(value, nullptr, 0);
                                break;
                        case 1:
-                               frmival.code = strtoul(value, nullptr, 0);
+                               frmival.stream = strtoul(value, nullptr, 0);
                                break;
                        case 2:
-                               frmival.width = strtoul(value, nullptr, 0);
+                               frmival.code = strtoul(value, nullptr, 0);
                                break;
                        case 3:
+                               frmival.width = strtoul(value, nullptr, 0);
+                               break;
+                       case 4:
                                frmival.height = strtoul(value, nullptr, 0);
                                break;
                        default:
@@ -148,14 +210,40 @@ void subdev_cmd(int ch, char *optarg)
                }
                break;
        case OptGetSubDevFormat:
-               if (optarg)
-                       get_fmt_pad = strtoul(optarg, nullptr, 0);
+               if (optarg) {
+                       /* Legacy pad-only parsing */
+                       get_fmt_pad = strtoul(optarg, &endp, 0);
+                       if (*endp == 0)
+                               break;
+               }
+
+               subs = optarg;
+               while (subs && *subs != '\0') {
+                       static constexpr const char *subopts[] = {
+                               "pad",
+                               "stream",
+                               nullptr
+                       };
+
+                       switch (parse_subopt(&subs, subopts, &value)) {
+                       case 0:
+                               get_fmt_pad = strtoul(value, nullptr, 0);
+                               break;
+                       case 1:
+                               get_fmt_stream = strtoul(value, nullptr, 0);
+                               break;
+                       default:
+                               subdev_usage();
+                               std::exit(EXIT_FAILURE);
+                       }
+               }
                break;
        case OptGetSubDevSelection:
                subs = optarg;
                while (*subs != '\0') {
                        static constexpr const char *subopts[] = {
                                "pad",
+                               "stream",
                                "target",
                                nullptr
                        };
@@ -166,6 +254,9 @@ void subdev_cmd(int ch, char *optarg)
                                get_sel_pad = strtoul(value, nullptr, 0);
                                break;
                        case 1:
+                               get_sel_stream = strtoul(value, nullptr, 0);
+                               break;
+                       case 2:
                                if (parse_selection_target(value, target)) {
                                        fprintf(stderr, "Unknown selection 
target\n");
                                        subdev_usage();
@@ -180,8 +271,33 @@ void subdev_cmd(int ch, char *optarg)
                }
                break;
        case OptGetSubDevFPS:
-               if (optarg)
-                       get_fps_pad = strtoul(optarg, nullptr, 0);
+               if (optarg) {
+                       /* Legacy pad-only parsing */
+                       get_fps_pad = strtoul(optarg, &endp, 0);
+                       if (*endp == 0)
+                               break;
+               }
+
+               subs = optarg;
+               while (subs && *subs != '\0') {
+                       static constexpr const char *subopts[] = {
+                               "pad",
+                               "stream",
+                               nullptr
+                       };
+
+                       switch (parse_subopt(&subs, subopts, &value)) {
+                       case 0:
+                               get_fps_pad = strtoul(value, nullptr, 0);
+                               break;
+                       case 1:
+                               get_fps_stream = strtoul(value, nullptr, 0);
+                               break;
+                       default:
+                               subdev_usage();
+                               std::exit(EXIT_FAILURE);
+                       }
+               }
                break;
        case OptSetSubDevFormat:
        case OptTrySubDevFormat:
@@ -199,6 +315,7 @@ void subdev_cmd(int ch, char *optarg)
                                "quantization",
                                "xfer",
                                "pad",
+                               "stream",
                                nullptr
                        };
 
@@ -245,6 +362,9 @@ void subdev_cmd(int ch, char *optarg)
                        case 9:
                                set_fmt_pad = strtoul(value, nullptr, 0);
                                break;
+                       case 10:
+                               set_fmt_stream = strtoul(value, nullptr, 0);
+                               break;
                        default:
                                fprintf(stderr, "Unknown option\n");
                                subdev_usage();
@@ -265,6 +385,7 @@ void subdev_cmd(int ch, char *optarg)
                                "width",
                                "height",
                                "pad",
+                               "stream",
                                nullptr
                        };
 
@@ -299,6 +420,9 @@ void subdev_cmd(int ch, char *optarg)
                        case 6:
                                vsel.pad = strtoul(value, nullptr, 0);
                                break;
+                       case 7:
+                               vsel.stream = strtoul(value, nullptr, 0);
+                               break;
                        default:
                                fprintf(stderr, "Unknown option\n");
                                subdev_usage();
@@ -312,6 +436,7 @@ void subdev_cmd(int ch, char *optarg)
                while (*subs != '\0') {
                        static constexpr const char *subopts[] = {
                                "pad",
+                               "stream",
                                "fps",
                                nullptr
                        };
@@ -321,6 +446,9 @@ void subdev_cmd(int ch, char *optarg)
                                set_fps_pad = strtoul(value, nullptr, 0);
                                break;
                        case 1:
+                               set_fps_stream = strtoul(value, nullptr, 0);
+                               break;
+                       case 2:
                                set_fps = strtod(value, nullptr);
                                break;
                        default:
@@ -330,6 +458,47 @@ void subdev_cmd(int ch, char *optarg)
                        }
                }
                break;
+       case OptSetRouting: {
+               struct v4l2_subdev_route *r;
+               char *end, *ref, *tok;
+               unsigned int flags;
+
+               memset(&routing, 0, sizeof(routing));
+               memset(routes, 0, sizeof(routes[0]) * NUM_ROUTES_MAX);
+               routing.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               routing.num_routes = 0;
+               routing.routes = (__u64)routes;
+
+               if (!optarg)
+                       break;
+
+               r = (v4l2_subdev_route *)routing.routes;
+               ref = end = strdup(optarg);
+               while ((tok = strsep(&end, ",")) != NULL) {
+                       if (sscanf(tok, "%u/%u -> %u/%u [%u]",
+                                  &r->sink_pad, &r->sink_stream,
+                                  &r->source_pad, &r->source_stream,
+                                  &flags) != 5) {
+                               free(ref);
+                               fprintf(stderr, "Invalid route information 
specified\n");
+                               subdev_usage();
+                               std::exit(EXIT_FAILURE);
+                       }
+
+                       if (flags & ~(V4L2_SUBDEV_ROUTE_FL_ACTIVE)) {
+                               fprintf(stderr, "Invalid route flags specified: 
%#x\n", flags);
+                               subdev_usage();
+                               std::exit(EXIT_FAILURE);
+                       }
+
+                       r->flags = flags;
+
+                       r++;
+                       routing.num_routes++;
+               }
+               free(ref);
+               break;
+       }
        default:
                break;
        }
@@ -395,6 +564,7 @@ void subdev_set(cv4l_fd &_fd)
 
                memset(&fmt, 0, sizeof(fmt));
                fmt.pad = set_fmt_pad;
+               fmt.stream = set_fmt_stream;
                fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
                if (doioctl(fd, VIDIOC_SUBDEV_G_FMT, &fmt) == 0) {
@@ -431,7 +601,7 @@ void subdev_set(cv4l_fd &_fd)
                        else
                                fmt.which = V4L2_SUBDEV_FORMAT_TRY;
 
-                       printf("ioctl: VIDIOC_SUBDEV_S_FMT (pad=%u)\n", 
fmt.pad);
+                       printf("ioctl: VIDIOC_SUBDEV_S_FMT 
(pad=%u,stream=%u)\n", fmt.pad, fmt.stream);
                        ret = doioctl(fd, VIDIOC_SUBDEV_S_FMT, &fmt);
                        if (ret == 0 && (verbose || 
!options[OptSetSubDevFormat]))
                                print_framefmt(fmt.format);
@@ -442,6 +612,7 @@ void subdev_set(cv4l_fd &_fd)
 
                memset(&sel, 0, sizeof(sel));
                sel.pad = vsel.pad;
+               sel.stream = vsel.stream;
                sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                sel.target = vsel.target;
 
@@ -462,7 +633,7 @@ void subdev_set(cv4l_fd &_fd)
                        else
                                sel.which = V4L2_SUBDEV_FORMAT_TRY;
 
-                       printf("ioctl: VIDIOC_SUBDEV_S_SELECTION (pad=%u)\n", 
sel.pad);
+                       printf("ioctl: VIDIOC_SUBDEV_S_SELECTION 
(pad=%u,stream=%u)\n", sel.pad, sel.stream);
                        int ret = doioctl(fd, VIDIOC_SUBDEV_S_SELECTION, &sel);
                        if (ret == 0 && (verbose || 
!options[OptSetSubDevSelection]))
                                print_subdev_selection(sel);
@@ -473,6 +644,7 @@ void subdev_set(cv4l_fd &_fd)
 
                memset(&fival, 0, sizeof(fival));
                fival.pad = set_fps_pad;
+               fival.stream = set_fps_stream;
 
                if (set_fps <= 0) {
                        fprintf(stderr, "invalid fps %f\n", set_fps);
@@ -483,7 +655,7 @@ void subdev_set(cv4l_fd &_fd)
                fival.interval.denominator = static_cast<uint32_t>(set_fps * 
fival.interval.numerator);
                printf("Note: --set-subdev-fps is only for testing.\n"
                       "Normally media-ctl is used to configure the video 
pipeline.\n");
-               printf("ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL (pad=%u)\n", 
fival.pad);
+               printf("ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL 
(pad=%u,stream=%u)\n", fival.pad, fival.stream);
                if (doioctl(fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &fival) == 0) {
                        if (!fival.interval.denominator || 
!fival.interval.numerator)
                                printf("\tFrames per second: invalid (%d/%d)\n",
@@ -494,6 +666,55 @@ void subdev_set(cv4l_fd &_fd)
                                        fival.interval.denominator, 
fival.interval.numerator);
                }
        }
+       if (options[OptSetRouting]) {
+               if (doioctl(fd, VIDIOC_SUBDEV_S_ROUTING, &routing) == 0)
+                       printf("Routing set\n");
+       }
+}
+
+struct flag_name {
+       __u32 flag;
+       const char *name;
+};
+
+static void print_flags(const struct flag_name *flag_names, unsigned int 
num_entries, __u32 flags)
+{
+       bool first = true;
+       unsigned int i;
+
+       for (i = 0; i < num_entries; i++) {
+               if (!(flags & flag_names[i].flag))
+                       continue;
+               if (!first)
+                       printf(",");
+               printf("%s", flag_names[i].name);
+               flags &= ~flag_names[i].flag;
+               first = false;
+       }
+
+       if (flags) {
+               if (!first)
+                       printf(",");
+               printf("0x%x", flags);
+       }
+}
+
+static void print_routes(const struct v4l2_subdev_routing *r)
+{
+       unsigned int i;
+       struct v4l2_subdev_route *routes = (struct v4l2_subdev_route 
*)r->routes;
+
+       static const struct flag_name route_flags[] = {
+               { V4L2_SUBDEV_ROUTE_FL_ACTIVE, "ACTIVE" },
+       };
+
+       for (i = 0; i < r->num_routes; i++) {
+               printf("%u/%u -> %u/%u [",
+                      routes[i].sink_pad, routes[i].sink_stream,
+                      routes[i].source_pad, routes[i].source_stream);
+               print_flags(route_flags, ARRAY_SIZE(route_flags), 
routes[i].flags);
+               printf("]\n");
+       }
 }
 
 void subdev_get(cv4l_fd &_fd)
@@ -506,8 +727,9 @@ void subdev_get(cv4l_fd &_fd)
                memset(&fmt, 0, sizeof(fmt));
                fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                fmt.pad = get_fmt_pad;
+               fmt.stream = get_fmt_stream;
 
-               printf("ioctl: VIDIOC_SUBDEV_G_FMT (pad=%u)\n", fmt.pad);
+               printf("ioctl: VIDIOC_SUBDEV_G_FMT (pad=%u,stream=%u)\n", 
fmt.pad, fmt.stream);
                if (doioctl(fd, VIDIOC_SUBDEV_G_FMT, &fmt) == 0)
                        print_framefmt(fmt.format);
        }
@@ -519,8 +741,9 @@ void subdev_get(cv4l_fd &_fd)
                memset(&sel, 0, sizeof(sel));
                sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                sel.pad = get_sel_pad;
+               sel.stream = get_sel_stream;
 
-               printf("ioctl: VIDIOC_SUBDEV_G_SELECTION (pad=%u)\n", sel.pad);
+               printf("ioctl: VIDIOC_SUBDEV_G_SELECTION (pad=%u,stream=%u)\n", 
sel.pad, sel.stream);
                if (options[OptAll] || get_sel_target == -1) {
                        while (valid_seltarget_at_idx(idx)) {
                                sel.target = seltarget_at_idx(idx);
@@ -539,8 +762,9 @@ void subdev_get(cv4l_fd &_fd)
 
                memset(&fival, 0, sizeof(fival));
                fival.pad = get_fps_pad;
+               fival.stream = get_fps_stream;
 
-               printf("ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL (pad=%u)\n", 
fival.pad);
+               printf("ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL 
(pad=%u,stream=%u)\n", fival.pad, fival.stream);
                if (doioctl(fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &fival) == 0) {
                        if (!fival.interval.denominator || 
!fival.interval.numerator)
                                printf("\tFrames per second: invalid (%d/%d)\n",
@@ -551,6 +775,17 @@ void subdev_get(cv4l_fd &_fd)
                                        fival.interval.denominator, 
fival.interval.numerator);
                }
        }
+
+       if (options[OptGetRouting]) {
+               memset(&routing, 0, sizeof(routing));
+               memset(routes, 0, sizeof(routes[0]) * NUM_ROUTES_MAX);
+               routing.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               routing.num_routes = NUM_ROUTES_MAX;
+               routing.routes = (__u64)routes;
+
+               if (doioctl(fd, VIDIOC_SUBDEV_G_ROUTING, &routing) == 0)
+                       print_routes(&routing);
+       }
 }
 
 static void print_mbus_code(__u32 code)
@@ -567,11 +802,12 @@ static void print_mbus_code(__u32 code)
                printf("\t0x%04x", code);
 }
 
-static void print_mbus_codes(int fd, __u32 pad)
+static void print_mbus_codes(int fd, __u32 pad, __u32 stream)
 {
        struct v4l2_subdev_mbus_code_enum mbus_code = {};
 
        mbus_code.pad = pad;
+       mbus_code.stream = stream;
        mbus_code.which = V4L2_SUBDEV_FORMAT_TRY;
 
        for (;;) {
@@ -624,13 +860,13 @@ void subdev_list(cv4l_fd &_fd)
        int fd = _fd.g_fd();
 
        if (options[OptListSubDevMBusCodes]) {
-               printf("ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=%u)\n",
-                      list_mbus_codes_pad);
-               print_mbus_codes(fd, list_mbus_codes_pad);
+               printf("ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE 
(pad=%u,stream=%u)\n",
+                      list_mbus_codes_pad, list_mbus_codes_stream);
+               print_mbus_codes(fd, list_mbus_codes_pad, 
list_mbus_codes_stream);
        }
        if (options[OptListSubDevFrameSizes]) {
-               printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=%u)\n",
-                      frmsize.pad);
+               printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE 
(pad=%u,stream=%u)\n",
+                      frmsize.pad, frmsize.stream);
                frmsize.index = 0;
                frmsize.which = V4L2_SUBDEV_FORMAT_TRY;
                while (test_ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &frmsize) 
>= 0) {
@@ -639,8 +875,8 @@ void subdev_list(cv4l_fd &_fd)
                }
        }
        if (options[OptListSubDevFrameIntervals]) {
-               printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=%u)\n",
-                      frmival.pad);
+               printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL 
(pad=%u,stream=%u)\n",
+                      frmival.pad, frmival.stream);
                frmival.index = 0;
                frmival.which = V4L2_SUBDEV_FORMAT_TRY;
                while (test_ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, 
&frmival) >= 0) {
diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
index 8585278f7f3d..52974b400c38 100644
--- a/utils/v4l2-ctl/v4l2-ctl.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl.cpp
@@ -64,6 +64,8 @@ static struct option long_options[] = {
        {"get-fmt-video-out", no_argument, nullptr, OptGetVideoOutFormat},
        {"set-fmt-video-out", required_argument, nullptr, OptSetVideoOutFormat},
        {"try-fmt-video-out", required_argument, nullptr, OptTryVideoOutFormat},
+       {"get-routing", no_argument, 0, OptGetRouting},
+       {"set-routing", required_argument, 0, OptSetRouting},
        {"help", no_argument, nullptr, OptHelp},
        {"help-tuner", no_argument, nullptr, OptHelpTuner},
        {"help-io", no_argument, nullptr, OptHelpIO},
diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h
index 8f2726eac07e..bf519c3ff93f 100644
--- a/utils/v4l2-ctl/v4l2-ctl.h
+++ b/utils/v4l2-ctl/v4l2-ctl.h
@@ -191,6 +191,8 @@ enum Option {
        OptInfoEdid,
        OptShowEdid,
        OptFixEdidChecksums,
+       OptGetRouting,
+       OptSetRouting,
        OptFreqSeek,
        OptEncoderCmd,
        OptTryEncoderCmd,

_______________________________________________
linuxtv-commits mailing list
[email protected]
https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to