Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx> --- utils/v4l2-ctl/Android.mk | 2 +- utils/v4l2-ctl/Makefile.am | 2 +- utils/v4l2-ctl/v4l2-ctl-routing.cpp | 154 ++++++++++++++++++++++++++++++++++++ utils/v4l2-ctl/v4l2-ctl.cpp | 10 +++ utils/v4l2-ctl/v4l2-ctl.h | 9 +++ 5 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 utils/v4l2-ctl/v4l2-ctl-routing.cpp diff --git a/utils/v4l2-ctl/Android.mk b/utils/v4l2-ctl/Android.mk index 707895026f88962d..f83347e04ff477c7 100644 --- a/utils/v4l2-ctl/Android.mk +++ b/utils/v4l2-ctl/Android.mk @@ -21,5 +21,5 @@ LOCAL_SRC_FILES := \ v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \ v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \ v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp v4l2-ctl-modes.cpp \ - v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c + v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c v4l2-ctl-routing.cpp include $(BUILD_EXECUTABLE) diff --git a/utils/v4l2-ctl/Makefile.am b/utils/v4l2-ctl/Makefile.am index cae4e747a0afa047..69bf466e89bbf72e 100644 --- a/utils/v4l2-ctl/Makefile.am +++ b/utils/v4l2-ctl/Makefile.am @@ -6,7 +6,7 @@ v4l2_ctl_SOURCES = v4l2-ctl.cpp v4l2-ctl.h v4l2-ctl-common.cpp v4l2-ctl-tuner.cp v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \ v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \ v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp v4l2-ctl-modes.cpp \ - v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c v4l2-ctl-meta.cpp + v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c v4l2-ctl-meta.cpp v4l2-ctl-routing.cpp v4l2_ctl_CPPFLAGS = -I$(top_srcdir)/utils/common if WITH_LIBV4L diff --git a/utils/v4l2-ctl/v4l2-ctl-routing.cpp b/utils/v4l2-ctl/v4l2-ctl-routing.cpp new file mode 100644 index 0000000000000000..55a2e44949785015 --- /dev/null +++ b/utils/v4l2-ctl/v4l2-ctl-routing.cpp @@ -0,0 +1,154 @@ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <sys/ioctl.h> + +#include "v4l2-ctl.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 + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +struct v4l2_subdev_routing routing; +struct v4l2_subdev_route routes[NUM_ROUTES_MAX]; + +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; + + static const struct flag_name route_flags[] = { + { V4L2_SUBDEV_ROUTE_FL_ACTIVE, "ENABLED" }, + { V4L2_SUBDEV_ROUTE_FL_IMMUTABLE, "IMMUTABLE" }, + }; + + for (i = 0; i < r->num_routes; i++) { + printf("%d/%d -> %d/%d [", + r->routes[i].sink_pad, r->routes[i].sink_stream, + r->routes[i].source_pad, r->routes[i].source_stream); + print_flags(route_flags, ARRAY_SIZE(route_flags), r->routes[i].flags); + printf("]\n"); + } +} + +void routing_usage(void) +{ + printf("\nRoute options:\n" + " --get-routing Print the route topology\n" + " --set-routing routes 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 the fields are\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 routing_cmd(int ch, char *optarg) +{ + struct v4l2_subdev_route *r; + char *end, *ref, *tok; + unsigned int flags; + + switch (ch) { + case OptSetRouting: + memset(&routing, 0, sizeof(routing)); + memset(routes, 0, sizeof(routes[0]) * NUM_ROUTES_MAX); + routing.num_routes = 0; + routing.routes = routes; + + if (!optarg) + break; + + r = 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 || (flags != 0 && flags != 1)) { + free(ref); + fprintf(stderr, "Invalid route information specified\n"); + routing_usage(); + exit(1); + } + + if (flags == 1) + r->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE; + + r++; + routing.num_routes++; + } + free(ref); + + break; + } +} + +void routing_set(int fd) +{ + if (options[OptSetRouting]) { + if (doioctl(fd, VIDIOC_SUBDEV_S_ROUTING, &routing) == 0) + printf("Routing set\n"); + } +} + +void routing_get(int fd) +{ + if (options[OptGetRouting]) { + memset(&routing, 0, sizeof(routing)); + memset(routes, 0, sizeof(routes[0]) * NUM_ROUTES_MAX); + routing.num_routes = NUM_ROUTES_MAX; + routing.routes = routes; + + if (doioctl(fd, VIDIOC_SUBDEV_G_ROUTING, &routing) == 0) + print_routes(&routing); + } +} diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp index e02dc7563e50bd1d..718d5d175fd86364 100644 --- a/utils/v4l2-ctl/v4l2-ctl.cpp +++ b/utils/v4l2-ctl/v4l2-ctl.cpp @@ -87,6 +87,7 @@ static struct option long_options[] = { {"help-misc", no_argument, 0, OptHelpMisc}, {"help-streaming", no_argument, 0, OptHelpStreaming}, {"help-edid", no_argument, 0, OptHelpEdid}, + {"help-routing", no_argument, 0, OptHelpRouting}, {"help-all", no_argument, 0, OptHelpAll}, #ifndef NO_LIBV4L2 {"wrapper", no_argument, 0, OptUseWrapper}, @@ -210,6 +211,8 @@ static struct option long_options[] = { {"get-edid", optional_argument, 0, OptGetEdid}, {"info-edid", optional_argument, 0, OptInfoEdid}, {"fix-edid-checksums", no_argument, 0, OptFixEdidChecksums}, + {"set-routing", required_argument, 0, OptSetRouting}, + {"get-routing", no_argument, 0, OptGetRouting}, {"tuner-index", required_argument, 0, OptTunerIndex}, {"list-buffers", no_argument, 0, OptListBuffers}, {"list-buffers-out", no_argument, 0, OptListBuffersOut}, @@ -271,6 +274,7 @@ static void usage_all(void) misc_usage(); streaming_usage(); edid_usage(); + routing_usage(); } static int test_open(const char *file, int oflag) @@ -1286,6 +1290,9 @@ int main(int argc, char **argv) case OptHelpEdid: edid_usage(); return 0; + case OptHelpRouting: + routing_usage(); + return 0; case OptHelpAll: usage_all(); return 0; @@ -1345,6 +1352,7 @@ int main(int argc, char **argv) misc_cmd(ch, optarg); streaming_cmd(ch, optarg); edid_cmd(ch, optarg); + routing_cmd(ch, optarg); break; } } @@ -1484,6 +1492,7 @@ int main(int argc, char **argv) streaming_set(fd, out_fd); misc_set(fd); edid_set(fd); + routing_set(fd); /* Get options */ @@ -1500,6 +1509,7 @@ int main(int argc, char **argv) selection_get(fd); misc_get(fd); edid_get(fd); + routing_get(fd); /* List options */ diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h index 3b56d8a6cd6c3852..f1051ec61695b106 100644 --- a/utils/v4l2-ctl/v4l2-ctl.h +++ b/utils/v4l2-ctl/v4l2-ctl.h @@ -157,6 +157,8 @@ enum Option { OptGetEdid, OptInfoEdid, OptFixEdidChecksums, + OptSetRouting, + OptGetRouting, OptFreqSeek, OptEncoderCmd, OptTryEncoderCmd, @@ -215,6 +217,7 @@ enum Option { OptHelpMisc, OptHelpStreaming, OptHelpEdid, + OptHelpRouting, OptHelpAll, OptLast = 512 }; @@ -371,6 +374,12 @@ void edid_cmd(int ch, char *optarg); void edid_set(int fd); void edid_get(int fd); +// v4l2-ctl-routing.cpp +void routing_usage(void); +void routing_cmd(int ch, char *optarg); +void routing_set(int fd); +void routing_get(int fd); + /* v4l2-ctl-modes.cpp */ bool calc_cvt_modeline(int image_width, int image_height, int refresh_rate, int reduced_blanking, -- 2.14.2