libmediatext is a helper library for converting configurations (Media controller links, V4L2 controls and V4L2 sub-device media bus formats and selections) from text-based form into IOCTLs. libmediatext depends on libv4l2subdev and libmediactl. Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> Signed-off-by: Teemu Tuominen <teemu.tuominen@xxxxxxxxx> --- libmediatext.pc.in | 10 ++ utils/media-ctl/Makefile.am | 10 +- utils/media-ctl/libmediatext.pc.in | 10 ++ utils/media-ctl/mediatext-test.c | 65 ++++++++++++ utils/media-ctl/mediatext.c | 210 +++++++++++++++++++++++++++++++++++++ utils/media-ctl/mediatext.h | 29 +++++ 6 files changed, 332 insertions(+), 2 deletions(-) create mode 100644 libmediatext.pc.in create mode 100644 utils/media-ctl/libmediatext.pc.in create mode 100644 utils/media-ctl/mediatext-test.c create mode 100644 utils/media-ctl/mediatext.c create mode 100644 utils/media-ctl/mediatext.h diff --git a/libmediatext.pc.in b/libmediatext.pc.in new file mode 100644 index 0000000..6aa6353 --- /dev/null +++ b/libmediatext.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libmediatext +Description: Media controller and V4L2 text-based configuration library +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lmediatext diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am index a3931fb..3e883e0 100644 --- a/utils/media-ctl/Makefile.am +++ b/utils/media-ctl/Makefile.am @@ -1,4 +1,4 @@ -noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la +noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la libmediatext.la libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS) @@ -9,9 +9,15 @@ libv4l2subdev_la_LIBADD = libmediactl.la libv4l2subdev_la_CFLAGS = -static libv4l2subdev_la_LDFLAGS = -static +libmediatext_la_SOURCES = mediatext.c +libmediatext_la_CFLAGS = -static $(LIBUDEV_CFLAGS) +libmediatext_la_LDFLAGS = -static $(LIBUDEV_LIBS) + mediactl_includedir=$(includedir)/mediactl noinst_HEADERS = mediactl.h v4l2subdev.h -bin_PROGRAMS = media-ctl +bin_PROGRAMS = media-ctl mediatext-test media_ctl_SOURCES = media-ctl.c options.c options.h tools.h media_ctl_LDADD = libmediactl.la libv4l2subdev.la +mediatext_test_SOURCES = mediatext-test.c +mediatext_test_LDADD = libmediatext.la libmediactl.la libv4l2subdev.la diff --git a/utils/media-ctl/libmediatext.pc.in b/utils/media-ctl/libmediatext.pc.in new file mode 100644 index 0000000..6aa6353 --- /dev/null +++ b/utils/media-ctl/libmediatext.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libmediatext +Description: Media controller and V4L2 text-based configuration library +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lmediatext diff --git a/utils/media-ctl/mediatext-test.c b/utils/media-ctl/mediatext-test.c new file mode 100644 index 0000000..296b8c0 --- /dev/null +++ b/utils/media-ctl/mediatext-test.c @@ -0,0 +1,65 @@ +/* + * libmediatext test program + * + * Copyright (C) 2013 Intel Corporation + * + * Contact: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "mediactl.h" +#include "mediatext.h" + +int main(int argc, char *argv[]) +{ + struct media_device *device; + int rval; + + if (argc != 3) { + fprintf(stderr, "usage: %s <media device> <string>\n\n", argv[0]); + fprintf(stderr, "\tstring := [ v4l2-ctrl |�v4l2-mbus | link-reset | link-conf]\n\n"); + fprintf(stderr, "\tv4l2-ctrl := \"entity\" ctrl_type ctrl_id ctrl_value\n"); + fprintf(stderr, "\tctrl_type := [ int | int64 | bitmask ]\n"); + fprintf(stderr, "\tctrl_value := [ %%d | %%PRId64 | bitmask_value ]\n"); + fprintf(stderr, "\tbitmask_value := b<binary_number>\n\n"); + fprintf(stderr, "\tv4l2-mbus := \n"); + fprintf(stderr, "\tlink-conf := \"entity\":pad -> \"entity\":pad[link-flags]\n"); + return EXIT_FAILURE; + } + + device = media_device_new(argv[1]); + if (!device) + return EXIT_FAILURE; + + media_debug_set_handler(device, (void (*)(void *, ...))fprintf, stdout); + + rval = media_device_enumerate(device); + if (rval) + return EXIT_FAILURE; + + rval = mediatext_parse(device, argv[2]); + if (rval) { + fprintf(stderr, "bad string %s (%s)\n", argv[2], strerror(-rval)); + return EXIT_FAILURE; + } + + media_device_unref(device); + + return EXIT_SUCCESS; +} diff --git a/utils/media-ctl/mediatext.c b/utils/media-ctl/mediatext.c new file mode 100644 index 0000000..ce0ee42 --- /dev/null +++ b/utils/media-ctl/mediatext.c @@ -0,0 +1,210 @@ +/* + * Media controller text-based configuration library + * + * Copyright (C) 2013 Intel Corporation + * + * Contact: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/ioctl.h> + +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include <linux/types.h> + +#include "mediactl.h" +#include "mediactl-priv.h" +#include "tools.h" +#include "v4l2subdev.h" + +struct parser { + char *prefix; + int (*parse)(struct media_device *media, const struct parser *p, + char *string); + struct parser *next; + bool no_args; +}; + +static int parse(struct media_device *media, const struct parser *p, char *string) +{ + for (; p->prefix; p++) { + size_t len = strlen(p->prefix); + + if (strncmp(p->prefix, string, len)) + continue; + + string += len; + + for (; isspace(*string); string++); + + if (p->no_args) + return p->parse(media, p->next, NULL); + + if (strlen(string) == 0) + return -ENOEXEC; + + return p->parse(media, p->next, string); + } + + return -ENOENT; +} + +struct ctrl_type { + uint32_t type; + char *str; +} ctrltypes[] = { + { V4L2_CTRL_TYPE_INTEGER, "int" }, + { V4L2_CTRL_TYPE_MENU, "menu" }, + { V4L2_CTRL_TYPE_INTEGER_MENU, "intmenu" }, + { V4L2_CTRL_TYPE_BITMASK, "bitmask" }, + { V4L2_CTRL_TYPE_INTEGER64, "int64" }, +}; + +/* adapted from yavta.c */ +static int parse_v4l2_ctrl(struct media_device *media, const struct parser *p, + char *string) +{ + struct v4l2_ext_control ctrl = { 0 }; + struct v4l2_ext_controls ctrls = { .count = 1, + .controls = &ctrl }; + int64_t val; + int rval; + struct media_entity *entity; + struct ctrl_type *ctype; + unsigned int i; + + entity = media_parse_entity(media, string, &string); + if (!entity) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(ctrltypes); i++) + if (!strncmp(string, ctrltypes[i].str, + strlen(ctrltypes[i].str))) + break; + + if (i == ARRAY_SIZE(ctrltypes)) + return -ENOENT; + + ctype = &ctrltypes[i]; + + string += strlen(ctrltypes[i].str); + for (; isspace(*string); string++); + rval = sscanf(string, "0x%" PRIx32, &ctrl.id); + if (rval <= 0) + return -EINVAL; + + for (; !isspace(*string) && *string; string++); + for (; isspace(*string); string++); + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(ctrl.id); + + switch (ctype->type) { + case V4L2_CTRL_TYPE_BITMASK: + if (*string++ != 'b') + return -EINVAL; + while (*string == '1' || *string == '0') { + val <<= 1; + if (*string == '1') + val++; + string++; + } + break; + default: + rval = sscanf(string, "%" PRId64, &val); + break; + } + if (rval <= 0) + return -EINVAL; + + media_dbg(media, "Setting control 0x%8.8x (type %s), value %" PRId64 "\n", + ctrl.id, ctype->str, val); + + if (ctype->type == V4L2_CTRL_TYPE_INTEGER64) + ctrl.value64 = val; + else + ctrl.value = val; + + rval = v4l2_subdev_open(entity); + if (rval < 0) + return rval; + + rval = ioctl(entity->fd, VIDIOC_S_EXT_CTRLS, &ctrls); + if (ctype->type != V4L2_CTRL_TYPE_INTEGER64) { + if (rval != -1) { + ctrl.value64 = ctrl.value; + } else if (ctype->type != V4L2_CTRL_TYPE_STRING && + (errno == EINVAL || errno == ENOTTY)) { + struct v4l2_control old = { .id = ctrl.id, + .value = val }; + + rval = ioctl(entity->fd, VIDIOC_S_CTRL, &old); + if (rval != -1) { + ctrl.value64 = old.value; + } + } + } + if (rval == -1) { + media_dbg(media, + "Failed setting control 0x8.8x: %s (%d) to value %" + PRId64 "\n", ctrl.id, strerror(errno), errno, val);; + return -errno; + } + + if (val != ctrl.value64) + media_dbg(media, "Asking for %" PRId64 ", got %" PRId64 "\n", + val, ctrl.value64); + + return 0; +} + +static int parse_v4l2_mbus(struct media_device *media, const struct parser *p, + char *string) +{ + media_dbg(media, "Media bus format setup: %s\n", string); + return v4l2_subdev_parse_setup_formats(media, string); +} + +static int parse_link_reset(struct media_device *media, const struct parser *p, + char *string) +{ + media_dbg(media, "Resetting links\n"); + return media_reset_links(media); +} + +static int parse_link_conf(struct media_device *media, const struct parser *p, + char *string) +{ + media_dbg(media, "Configuring links: %s\n", string); + return media_parse_setup_links(media, string); +} + +static const struct parser parsers[] = { + { "v4l2-ctrl", parse_v4l2_ctrl }, + { "v4l2-mbus", parse_v4l2_mbus }, + { "link-reset", parse_link_reset, NULL, true }, + { "link-conf", parse_link_conf }, + { 0 } +}; + +int mediatext_parse(struct media_device *media, char *string) +{ + return parse(media, parsers, string); +} diff --git a/utils/media-ctl/mediatext.h b/utils/media-ctl/mediatext.h new file mode 100644 index 0000000..f2f80fe --- /dev/null +++ b/utils/media-ctl/mediatext.h @@ -0,0 +1,29 @@ +/* + * Media controller text-based configuration library + * + * Copyright (C) 2013 Intel Corporation + * + * Contact: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __MEDIATEXT_H__ +#define __MEDIATEXT_H__ + +struct media_device; + +int mediatext_parse(struct media_device *device, char *string); + +#endif /* __MEDIATEXT_H__ */ -- 2.1.0.231.g7484e3b -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html