* [media-ctl PATCH 1/7] Rename files to match the names of the libraries
2011-10-07 15:34 [media-ctl PATCH 0/7] Move functionality to libraries, debug changes Sakari Ailus
@ 2011-10-07 15:38 ` Sakari Ailus
2011-10-08 11:53 ` Laurent Pinchart
2011-10-07 15:38 ` [media-ctl PATCH 2/7] Move link parsing from main.c to media.c, making it part of libmediactl Sakari Ailus
` (5 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Sakari Ailus @ 2011-10-07 15:38 UTC (permalink / raw)
To: linux-media; +Cc: laurent.pinchart
Rename media.* to mediactl.* and subdev.* v4l2subdev.*.
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
src/Makefile.am | 6 +-
src/main.c | 4 +-
src/media.c | 475 ------------------------------------------------------
src/media.h | 161 ------------------
src/mediactl.c | 475 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/mediactl.h | 161 ++++++++++++++++++
src/subdev.c | 188 ---------------------
src/subdev.h | 162 -------------------
src/v4l2subdev.c | 188 +++++++++++++++++++++
src/v4l2subdev.h | 162 +++++++++++++++++++
10 files changed, 991 insertions(+), 991 deletions(-)
delete mode 100644 src/media.c
delete mode 100644 src/media.h
create mode 100644 src/mediactl.c
create mode 100644 src/mediactl.h
delete mode 100644 src/subdev.c
delete mode 100644 src/subdev.h
create mode 100644 src/v4l2subdev.c
create mode 100644 src/v4l2subdev.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 52628d2..2583464 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,8 +1,8 @@
lib_LTLIBRARIES = libmediactl.la libv4l2subdev.la
-libmediactl_la_SOURCES = media.c
-libv4l2subdev_la_SOURCES = subdev.c
+libmediactl_la_SOURCES = mediactl.c
+libv4l2subdev_la_SOURCES = v4l2subdev.c
mediactl_includedir=$(includedir)/mediactl
-mediactl_include_HEADERS = media.h subdev.h
+mediactl_include_HEADERS = mediactl.h v4l2subdev.h
bin_PROGRAMS = media-ctl
media_ctl_CFLAGS = $(LIBUDEV_CFLAGS)
diff --git a/src/main.c b/src/main.c
index b9b9150..55a6e2d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -36,9 +36,9 @@
#include <linux/v4l2-subdev.h>
#include <linux/videodev2.h>
-#include "media.h"
+#include "mediactl.h"
#include "options.h"
-#include "subdev.h"
+#include "v4l2subdev.h"
#include "tools.h"
/* -----------------------------------------------------------------------------
diff --git a/src/media.c b/src/media.c
deleted file mode 100644
index f443d0c..0000000
--- a/src/media.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Media controller test application
- *
- * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- */
-
-#include "config.h"
-
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <linux/videodev2.h>
-#include <linux/media.h>
-
-#include "media.h"
-#include "tools.h"
-
-struct media_pad *media_entity_remote_source(struct media_pad *pad)
-{
- unsigned int i;
-
- if (!(pad->flags & MEDIA_PAD_FL_SINK))
- return NULL;
-
- for (i = 0; i < pad->entity->num_links; ++i) {
- struct media_link *link = &pad->entity->links[i];
-
- if (!(link->flags & MEDIA_LNK_FL_ENABLED))
- continue;
-
- if (link->sink == pad)
- return link->source;
- }
-
- return NULL;
-}
-
-struct media_entity *media_get_entity_by_name(struct media_device *media,
- const char *name, size_t length)
-{
- unsigned int i;
-
- for (i = 0; i < media->entities_count; ++i) {
- struct media_entity *entity = &media->entities[i];
-
- if (strncmp(entity->info.name, name, length) == 0)
- return entity;
- }
-
- return NULL;
-}
-
-struct media_entity *media_get_entity_by_id(struct media_device *media,
- __u32 id)
-{
- unsigned int i;
-
- for (i = 0; i < media->entities_count; ++i) {
- struct media_entity *entity = &media->entities[i];
-
- if (entity->info.id == id)
- return entity;
- }
-
- return NULL;
-}
-
-int media_setup_link(struct media_device *media,
- struct media_pad *source,
- struct media_pad *sink,
- __u32 flags)
-{
- struct media_link *link;
- struct media_link_desc ulink;
- unsigned int i;
- int ret;
-
- for (i = 0; i < source->entity->num_links; i++) {
- link = &source->entity->links[i];
-
- if (link->source->entity == source->entity &&
- link->source->index == source->index &&
- link->sink->entity == sink->entity &&
- link->sink->index == sink->index)
- break;
- }
-
- if (i == source->entity->num_links) {
- printf("%s: Link not found\n", __func__);
- return -EINVAL;
- }
-
- /* source pad */
- ulink.source.entity = source->entity->info.id;
- ulink.source.index = source->index;
- ulink.source.flags = MEDIA_PAD_FL_SOURCE;
-
- /* sink pad */
- ulink.sink.entity = sink->entity->info.id;
- ulink.sink.index = sink->index;
- ulink.sink.flags = MEDIA_PAD_FL_SINK;
-
- ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
-
- ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
- if (ret < 0) {
- printf("%s: Unable to setup link (%s)\n", __func__,
- strerror(errno));
- return ret;
- }
-
- link->flags = ulink.flags;
- link->twin->flags = ulink.flags;
- return 0;
-}
-
-int media_reset_links(struct media_device *media)
-{
- unsigned int i, j;
- int ret;
-
- for (i = 0; i < media->entities_count; ++i) {
- struct media_entity *entity = &media->entities[i];
-
- for (j = 0; j < entity->num_links; j++) {
- struct media_link *link = &entity->links[j];
-
- if (link->flags & MEDIA_LNK_FL_IMMUTABLE ||
- link->source->entity != entity)
- continue;
-
- ret = media_setup_link(media, link->source, link->sink,
- link->flags & ~MEDIA_LNK_FL_ENABLED);
- if (ret < 0)
- return ret;
- }
- }
-
- return 0;
-}
-
-static struct media_link *media_entity_add_link(struct media_entity *entity)
-{
- if (entity->num_links >= entity->max_links) {
- struct media_link *links = entity->links;
- unsigned int max_links = entity->max_links * 2;
- unsigned int i;
-
- links = realloc(links, max_links * sizeof *links);
- if (links == NULL)
- return NULL;
-
- for (i = 0; i < entity->num_links; ++i)
- links[i].twin->twin = &links[i];
-
- entity->max_links = max_links;
- entity->links = links;
- }
-
- return &entity->links[entity->num_links++];
-}
-
-static int media_enum_links(struct media_device *media)
-{
- __u32 id;
- int ret = 0;
-
- for (id = 1; id <= media->entities_count; id++) {
- struct media_entity *entity = &media->entities[id - 1];
- struct media_links_enum links;
- unsigned int i;
-
- links.entity = entity->info.id;
- links.pads = malloc(entity->info.pads * sizeof(struct media_pad_desc));
- links.links = malloc(entity->info.links * sizeof(struct media_link_desc));
-
- if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
- printf("%s: Unable to enumerate pads and links (%s).\n",
- __func__, strerror(errno));
- free(links.pads);
- free(links.links);
- return -errno;
- }
-
- for (i = 0; i < entity->info.pads; ++i) {
- entity->pads[i].entity = entity;
- entity->pads[i].index = links.pads[i].index;
- entity->pads[i].flags = links.pads[i].flags;
- }
-
- for (i = 0; i < entity->info.links; ++i) {
- struct media_link_desc *link = &links.links[i];
- struct media_link *fwdlink;
- struct media_link *backlink;
- struct media_entity *source;
- struct media_entity *sink;
-
- source = media_get_entity_by_id(media, link->source.entity);
- sink = media_get_entity_by_id(media, link->sink.entity);
-
- if (source == NULL || sink == NULL) {
- printf("WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
- id, i, link->source.entity, link->source.index,
- link->sink.entity, link->sink.index);
- ret = -EINVAL;
- } else {
- fwdlink = media_entity_add_link(source);
- fwdlink->source = &source->pads[link->source.index];
- fwdlink->sink = &sink->pads[link->sink.index];
- fwdlink->flags = link->flags;
-
- backlink = media_entity_add_link(sink);
- backlink->source = &source->pads[link->source.index];
- backlink->sink = &sink->pads[link->sink.index];
- backlink->flags = link->flags;
-
- fwdlink->twin = backlink;
- backlink->twin = fwdlink;
- }
- }
-
- free(links.pads);
- free(links.links);
- }
-
- return ret;
-}
-
-#ifdef HAVE_LIBUDEV
-
-#include <libudev.h>
-
-static inline int media_udev_open(struct udev **udev)
-{
- *udev = udev_new();
- if (*udev == NULL)
- return -ENOMEM;
- return 0;
-}
-
-static inline void media_udev_close(struct udev *udev)
-{
- if (udev != NULL)
- udev_unref(udev);
-}
-
-static int media_get_devname_udev(struct udev *udev,
- struct media_entity *entity, int verbose)
-{
- struct udev_device *device;
- dev_t devnum;
- const char *p;
- int ret = -ENODEV;
-
- if (udev == NULL)
- return -EINVAL;
-
- devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
- if (verbose)
- printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
- device = udev_device_new_from_devnum(udev, 'c', devnum);
- if (device) {
- p = udev_device_get_devnode(device);
- if (p) {
- strncpy(entity->devname, p, sizeof(entity->devname));
- entity->devname[sizeof(entity->devname) - 1] = '\0';
- }
- ret = 0;
- }
-
- udev_device_unref(device);
-
- return ret;
-}
-
-#else /* HAVE_LIBUDEV */
-
-struct udev;
-
-static inline int media_udev_open(struct udev **udev) { return 0; }
-
-static inline void media_udev_close(struct udev *udev) { }
-
-static inline int media_get_devname_udev(struct udev *udev,
- struct media_entity *entity, int verbose)
-{
- return -ENOTSUP;
-}
-
-#endif /* HAVE_LIBUDEV */
-
-static int media_get_devname_sysfs(struct media_entity *entity)
-{
- struct stat devstat;
- char devname[32];
- char sysname[32];
- char target[1024];
- char *p;
- int ret;
-
- sprintf(sysname, "/sys/dev/char/%u:%u", entity->info.v4l.major,
- entity->info.v4l.minor);
- ret = readlink(sysname, target, sizeof(target));
- if (ret < 0)
- return -errno;
-
- target[ret] = '\0';
- p = strrchr(target, '/');
- if (p == NULL)
- return -EINVAL;
-
- sprintf(devname, "/dev/%s", p + 1);
- ret = stat(devname, &devstat);
- if (ret < 0)
- return -errno;
-
- /* Sanity check: udev might have reordered the device nodes.
- * Make sure the major/minor match. We should really use
- * libudev.
- */
- if (major(devstat.st_rdev) == entity->info.v4l.major &&
- minor(devstat.st_rdev) == entity->info.v4l.minor)
- strcpy(entity->devname, devname);
-
- return 0;
-}
-
-static int media_enum_entities(struct media_device *media, int verbose)
-{
- struct media_entity *entity;
- struct udev *udev;
- unsigned int size;
- __u32 id;
- int ret;
-
- ret = media_udev_open(&udev);
- if (ret < 0)
- printf("%s: Can't get udev context\n", __func__);
-
- for (id = 0, ret = 0; ; id = entity->info.id) {
- size = (media->entities_count + 1) * sizeof(*media->entities);
- media->entities = realloc(media->entities, size);
-
- entity = &media->entities[media->entities_count];
- memset(entity, 0, sizeof(*entity));
- entity->fd = -1;
- entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
-
- ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
- if (ret < 0) {
- ret = errno != EINVAL ? -errno : 0;
- break;
- }
-
- /* Number of links (for outbound links) plus number of pads (for
- * inbound links) is a good safe initial estimate of the total
- * number of links.
- */
- entity->max_links = entity->info.pads + entity->info.links;
-
- entity->pads = malloc(entity->info.pads * sizeof(*entity->pads));
- entity->links = malloc(entity->max_links * sizeof(*entity->links));
- if (entity->pads == NULL || entity->links == NULL) {
- ret = -ENOMEM;
- break;
- }
-
- media->entities_count++;
-
- /* Find the corresponding device name. */
- if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE &&
- media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
- continue;
-
- /* Try to get the device name via udev */
- if (!media_get_devname_udev(udev, entity, verbose))
- continue;
-
- /* Fall back to get the device name via sysfs */
- media_get_devname_sysfs(entity);
- }
-
- media_udev_close(udev);
- return ret;
-}
-
-struct media_device *media_open(const char *name, int verbose)
-{
- struct media_device *media;
- int ret;
-
- media = calloc(1, sizeof(*media));
- if (media == NULL) {
- printf("%s: unable to allocate memory\n", __func__);
- return NULL;
- }
-
- if (verbose)
- printf("Opening media device %s\n", name);
- media->fd = open(name, O_RDWR);
- if (media->fd < 0) {
- media_close(media);
- printf("%s: Can't open media device %s\n", __func__, name);
- return NULL;
- }
-
- if (verbose)
- printf("Enumerating entities\n");
-
- ret = media_enum_entities(media, verbose);
-
- if (ret < 0) {
- printf("%s: Unable to enumerate entities for device %s (%s)\n",
- __func__, name, strerror(-ret));
- media_close(media);
- return NULL;
- }
-
- if (verbose) {
- printf("Found %u entities\n", media->entities_count);
- printf("Enumerating pads and links\n");
- }
-
- ret = media_enum_links(media);
- if (ret < 0) {
- printf("%s: Unable to enumerate pads and linksfor device %s\n",
- __func__, name);
- media_close(media);
- return NULL;
- }
-
- return media;
-}
-
-void media_close(struct media_device *media)
-{
- unsigned int i;
-
- if (media->fd != -1)
- close(media->fd);
-
- for (i = 0; i < media->entities_count; ++i) {
- struct media_entity *entity = &media->entities[i];
-
- free(entity->pads);
- free(entity->links);
- if (entity->fd != -1)
- close(entity->fd);
- }
-
- free(media->entities);
- free(media);
-}
-
diff --git a/src/media.h b/src/media.h
deleted file mode 100644
index b91a2ac..0000000
--- a/src/media.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Media controller test application
- *
- * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- */
-
-#ifndef __MEDIA_H__
-#define __MEDIA_H__
-
-#include <linux/media.h>
-
-struct media_link {
- struct media_pad *source;
- struct media_pad *sink;
- struct media_link *twin;
- __u32 flags;
- __u32 padding[3];
-};
-
-struct media_pad {
- struct media_entity *entity;
- __u32 index;
- __u32 flags;
- __u32 padding[3];
-};
-
-struct media_entity {
- struct media_entity_desc info;
- struct media_pad *pads;
- struct media_link *links;
- unsigned int max_links;
- unsigned int num_links;
-
- char devname[32];
- int fd;
- __u32 padding[6];
-};
-
-struct media_device {
- int fd;
- struct media_entity *entities;
- unsigned int entities_count;
- __u32 padding[6];
-};
-
-/**
- * @brief Open a media device.
- * @param name - name (including path) of the device node.
- * @param verbose - whether to print verbose information on the standard output.
- *
- * Open the media device referenced by @a name and enumerate entities, pads and
- * links.
- *
- * @return A pointer to a newly allocated media_device structure instance on
- * success and NULL on failure. The returned pointer must be freed with
- * media_close when the device isn't needed anymore.
- */
-struct media_device *media_open(const char *name, int verbose);
-
-/**
- * @brief Close a media device.
- * @param media - device instance.
- *
- * Close the @a media device instance and free allocated resources. Access to the
- * device instance is forbidden after this function returns.
- */
-void media_close(struct media_device *media);
-
-/**
- * @brief Locate the pad at the other end of a link.
- * @param pad - sink pad at one end of the link.
- *
- * Locate the source pad connected to @a pad through an enabled link. As only one
- * link connected to a sink pad can be enabled at a time, the connected source
- * pad is guaranteed to be unique.
- *
- * @return A pointer to the connected source pad, or NULL if all links connected
- * to @a pad are disabled. Return NULL also if @a pad is not a sink pad.
- */
-struct media_pad *media_entity_remote_source(struct media_pad *pad);
-
-/**
- * @brief Get the type of an entity.
- * @param entity - the entity.
- *
- * @return The type of @a entity.
- */
-static inline unsigned int media_entity_type(struct media_entity *entity)
-{
- return entity->info.type & MEDIA_ENT_TYPE_MASK;
-}
-
-/**
- * @brief Find an entity by its name.
- * @param media - media device.
- * @param name - entity name.
- * @param length - size of @a name.
- *
- * Search for an entity with a name equal to @a name.
- *
- * @return A pointer to the entity if found, or NULL otherwise.
- */
-struct media_entity *media_get_entity_by_name(struct media_device *media,
- const char *name, size_t length);
-
-/**
- * @brief Find an entity by its ID.
- * @param media - media device.
- * @param id - entity ID.
- *
- * Search for an entity with an ID equal to @a id.
- *
- * @return A pointer to the entity if found, or NULL otherwise.
- */
-struct media_entity *media_get_entity_by_id(struct media_device *media,
- __u32 id);
-
-/**
- * @brief Configure a link.
- * @param media - media device.
- * @param source - source pad at the link origin.
- * @param sink - sink pad at the link target.
- * @param flags - configuration flags.
- *
- * Locate the link between @a source and @a sink, and configure it by applying
- * the new @a flags.
- *
- * Only the MEDIA_LINK_FLAG_ENABLED flag is writable.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int media_setup_link(struct media_device *media,
- struct media_pad *source, struct media_pad *sink,
- __u32 flags);
-
-/**
- * @brief Reset all links to the disabled state.
- * @param media - media device.
- *
- * Disable all links in the media device. This function is usually used after
- * opening a media device to reset all links to a known state.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int media_reset_links(struct media_device *media);
-
-#endif
-
diff --git a/src/mediactl.c b/src/mediactl.c
new file mode 100644
index 0000000..5c710c9
--- /dev/null
+++ b/src/mediactl.c
@@ -0,0 +1,475 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include "config.h"
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <linux/videodev2.h>
+#include <linux/media.h>
+
+#include "mediactl.h"
+#include "tools.h"
+
+struct media_pad *media_entity_remote_source(struct media_pad *pad)
+{
+ unsigned int i;
+
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ return NULL;
+
+ for (i = 0; i < pad->entity->num_links; ++i) {
+ struct media_link *link = &pad->entity->links[i];
+
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+ continue;
+
+ if (link->sink == pad)
+ return link->source;
+ }
+
+ return NULL;
+}
+
+struct media_entity *media_get_entity_by_name(struct media_device *media,
+ const char *name, size_t length)
+{
+ unsigned int i;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ if (strncmp(entity->info.name, name, length) == 0)
+ return entity;
+ }
+
+ return NULL;
+}
+
+struct media_entity *media_get_entity_by_id(struct media_device *media,
+ __u32 id)
+{
+ unsigned int i;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ if (entity->info.id == id)
+ return entity;
+ }
+
+ return NULL;
+}
+
+int media_setup_link(struct media_device *media,
+ struct media_pad *source,
+ struct media_pad *sink,
+ __u32 flags)
+{
+ struct media_link *link;
+ struct media_link_desc ulink;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source->entity == source->entity &&
+ link->source->index == source->index &&
+ link->sink->entity == sink->entity &&
+ link->sink->index == sink->index)
+ break;
+ }
+
+ if (i == source->entity->num_links) {
+ printf("%s: Link not found\n", __func__);
+ return -EINVAL;
+ }
+
+ /* source pad */
+ ulink.source.entity = source->entity->info.id;
+ ulink.source.index = source->index;
+ ulink.source.flags = MEDIA_PAD_FL_SOURCE;
+
+ /* sink pad */
+ ulink.sink.entity = sink->entity->info.id;
+ ulink.sink.index = sink->index;
+ ulink.sink.flags = MEDIA_PAD_FL_SINK;
+
+ ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
+
+ ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
+ if (ret < 0) {
+ printf("%s: Unable to setup link (%s)\n", __func__,
+ strerror(errno));
+ return ret;
+ }
+
+ link->flags = ulink.flags;
+ link->twin->flags = ulink.flags;
+ return 0;
+}
+
+int media_reset_links(struct media_device *media)
+{
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ for (j = 0; j < entity->num_links; j++) {
+ struct media_link *link = &entity->links[j];
+
+ if (link->flags & MEDIA_LNK_FL_IMMUTABLE ||
+ link->source->entity != entity)
+ continue;
+
+ ret = media_setup_link(media, link->source, link->sink,
+ link->flags & ~MEDIA_LNK_FL_ENABLED);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static struct media_link *media_entity_add_link(struct media_entity *entity)
+{
+ if (entity->num_links >= entity->max_links) {
+ struct media_link *links = entity->links;
+ unsigned int max_links = entity->max_links * 2;
+ unsigned int i;
+
+ links = realloc(links, max_links * sizeof *links);
+ if (links == NULL)
+ return NULL;
+
+ for (i = 0; i < entity->num_links; ++i)
+ links[i].twin->twin = &links[i];
+
+ entity->max_links = max_links;
+ entity->links = links;
+ }
+
+ return &entity->links[entity->num_links++];
+}
+
+static int media_enum_links(struct media_device *media)
+{
+ __u32 id;
+ int ret = 0;
+
+ for (id = 1; id <= media->entities_count; id++) {
+ struct media_entity *entity = &media->entities[id - 1];
+ struct media_links_enum links;
+ unsigned int i;
+
+ links.entity = entity->info.id;
+ links.pads = malloc(entity->info.pads * sizeof(struct media_pad_desc));
+ links.links = malloc(entity->info.links * sizeof(struct media_link_desc));
+
+ if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
+ printf("%s: Unable to enumerate pads and links (%s).\n",
+ __func__, strerror(errno));
+ free(links.pads);
+ free(links.links);
+ return -errno;
+ }
+
+ for (i = 0; i < entity->info.pads; ++i) {
+ entity->pads[i].entity = entity;
+ entity->pads[i].index = links.pads[i].index;
+ entity->pads[i].flags = links.pads[i].flags;
+ }
+
+ for (i = 0; i < entity->info.links; ++i) {
+ struct media_link_desc *link = &links.links[i];
+ struct media_link *fwdlink;
+ struct media_link *backlink;
+ struct media_entity *source;
+ struct media_entity *sink;
+
+ source = media_get_entity_by_id(media, link->source.entity);
+ sink = media_get_entity_by_id(media, link->sink.entity);
+
+ if (source == NULL || sink == NULL) {
+ printf("WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
+ id, i, link->source.entity, link->source.index,
+ link->sink.entity, link->sink.index);
+ ret = -EINVAL;
+ } else {
+ fwdlink = media_entity_add_link(source);
+ fwdlink->source = &source->pads[link->source.index];
+ fwdlink->sink = &sink->pads[link->sink.index];
+ fwdlink->flags = link->flags;
+
+ backlink = media_entity_add_link(sink);
+ backlink->source = &source->pads[link->source.index];
+ backlink->sink = &sink->pads[link->sink.index];
+ backlink->flags = link->flags;
+
+ fwdlink->twin = backlink;
+ backlink->twin = fwdlink;
+ }
+ }
+
+ free(links.pads);
+ free(links.links);
+ }
+
+ return ret;
+}
+
+#ifdef HAVE_LIBUDEV
+
+#include <libudev.h>
+
+static inline int media_udev_open(struct udev **udev)
+{
+ *udev = udev_new();
+ if (*udev == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void media_udev_close(struct udev *udev)
+{
+ if (udev != NULL)
+ udev_unref(udev);
+}
+
+static int media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity, int verbose)
+{
+ struct udev_device *device;
+ dev_t devnum;
+ const char *p;
+ int ret = -ENODEV;
+
+ if (udev == NULL)
+ return -EINVAL;
+
+ devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
+ if (verbose)
+ printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
+ device = udev_device_new_from_devnum(udev, 'c', devnum);
+ if (device) {
+ p = udev_device_get_devnode(device);
+ if (p) {
+ strncpy(entity->devname, p, sizeof(entity->devname));
+ entity->devname[sizeof(entity->devname) - 1] = '\0';
+ }
+ ret = 0;
+ }
+
+ udev_device_unref(device);
+
+ return ret;
+}
+
+#else /* HAVE_LIBUDEV */
+
+struct udev;
+
+static inline int media_udev_open(struct udev **udev) { return 0; }
+
+static inline void media_udev_close(struct udev *udev) { }
+
+static inline int media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity, int verbose)
+{
+ return -ENOTSUP;
+}
+
+#endif /* HAVE_LIBUDEV */
+
+static int media_get_devname_sysfs(struct media_entity *entity)
+{
+ struct stat devstat;
+ char devname[32];
+ char sysname[32];
+ char target[1024];
+ char *p;
+ int ret;
+
+ sprintf(sysname, "/sys/dev/char/%u:%u", entity->info.v4l.major,
+ entity->info.v4l.minor);
+ ret = readlink(sysname, target, sizeof(target));
+ if (ret < 0)
+ return -errno;
+
+ target[ret] = '\0';
+ p = strrchr(target, '/');
+ if (p == NULL)
+ return -EINVAL;
+
+ sprintf(devname, "/dev/%s", p + 1);
+ ret = stat(devname, &devstat);
+ if (ret < 0)
+ return -errno;
+
+ /* Sanity check: udev might have reordered the device nodes.
+ * Make sure the major/minor match. We should really use
+ * libudev.
+ */
+ if (major(devstat.st_rdev) == entity->info.v4l.major &&
+ minor(devstat.st_rdev) == entity->info.v4l.minor)
+ strcpy(entity->devname, devname);
+
+ return 0;
+}
+
+static int media_enum_entities(struct media_device *media, int verbose)
+{
+ struct media_entity *entity;
+ struct udev *udev;
+ unsigned int size;
+ __u32 id;
+ int ret;
+
+ ret = media_udev_open(&udev);
+ if (ret < 0)
+ printf("%s: Can't get udev context\n", __func__);
+
+ for (id = 0, ret = 0; ; id = entity->info.id) {
+ size = (media->entities_count + 1) * sizeof(*media->entities);
+ media->entities = realloc(media->entities, size);
+
+ entity = &media->entities[media->entities_count];
+ memset(entity, 0, sizeof(*entity));
+ entity->fd = -1;
+ entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+
+ ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
+ if (ret < 0) {
+ ret = errno != EINVAL ? -errno : 0;
+ break;
+ }
+
+ /* Number of links (for outbound links) plus number of pads (for
+ * inbound links) is a good safe initial estimate of the total
+ * number of links.
+ */
+ entity->max_links = entity->info.pads + entity->info.links;
+
+ entity->pads = malloc(entity->info.pads * sizeof(*entity->pads));
+ entity->links = malloc(entity->max_links * sizeof(*entity->links));
+ if (entity->pads == NULL || entity->links == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ media->entities_count++;
+
+ /* Find the corresponding device name. */
+ if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE &&
+ media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ continue;
+
+ /* Try to get the device name via udev */
+ if (!media_get_devname_udev(udev, entity, verbose))
+ continue;
+
+ /* Fall back to get the device name via sysfs */
+ media_get_devname_sysfs(entity);
+ }
+
+ media_udev_close(udev);
+ return ret;
+}
+
+struct media_device *media_open(const char *name, int verbose)
+{
+ struct media_device *media;
+ int ret;
+
+ media = calloc(1, sizeof(*media));
+ if (media == NULL) {
+ printf("%s: unable to allocate memory\n", __func__);
+ return NULL;
+ }
+
+ if (verbose)
+ printf("Opening media device %s\n", name);
+ media->fd = open(name, O_RDWR);
+ if (media->fd < 0) {
+ media_close(media);
+ printf("%s: Can't open media device %s\n", __func__, name);
+ return NULL;
+ }
+
+ if (verbose)
+ printf("Enumerating entities\n");
+
+ ret = media_enum_entities(media, verbose);
+
+ if (ret < 0) {
+ printf("%s: Unable to enumerate entities for device %s (%s)\n",
+ __func__, name, strerror(-ret));
+ media_close(media);
+ return NULL;
+ }
+
+ if (verbose) {
+ printf("Found %u entities\n", media->entities_count);
+ printf("Enumerating pads and links\n");
+ }
+
+ ret = media_enum_links(media);
+ if (ret < 0) {
+ printf("%s: Unable to enumerate pads and linksfor device %s\n",
+ __func__, name);
+ media_close(media);
+ return NULL;
+ }
+
+ return media;
+}
+
+void media_close(struct media_device *media)
+{
+ unsigned int i;
+
+ if (media->fd != -1)
+ close(media->fd);
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ free(entity->pads);
+ free(entity->links);
+ if (entity->fd != -1)
+ close(entity->fd);
+ }
+
+ free(media->entities);
+ free(media);
+}
+
diff --git a/src/mediactl.h b/src/mediactl.h
new file mode 100644
index 0000000..b91a2ac
--- /dev/null
+++ b/src/mediactl.h
@@ -0,0 +1,161 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#ifndef __MEDIA_H__
+#define __MEDIA_H__
+
+#include <linux/media.h>
+
+struct media_link {
+ struct media_pad *source;
+ struct media_pad *sink;
+ struct media_link *twin;
+ __u32 flags;
+ __u32 padding[3];
+};
+
+struct media_pad {
+ struct media_entity *entity;
+ __u32 index;
+ __u32 flags;
+ __u32 padding[3];
+};
+
+struct media_entity {
+ struct media_entity_desc info;
+ struct media_pad *pads;
+ struct media_link *links;
+ unsigned int max_links;
+ unsigned int num_links;
+
+ char devname[32];
+ int fd;
+ __u32 padding[6];
+};
+
+struct media_device {
+ int fd;
+ struct media_entity *entities;
+ unsigned int entities_count;
+ __u32 padding[6];
+};
+
+/**
+ * @brief Open a media device.
+ * @param name - name (including path) of the device node.
+ * @param verbose - whether to print verbose information on the standard output.
+ *
+ * Open the media device referenced by @a name and enumerate entities, pads and
+ * links.
+ *
+ * @return A pointer to a newly allocated media_device structure instance on
+ * success and NULL on failure. The returned pointer must be freed with
+ * media_close when the device isn't needed anymore.
+ */
+struct media_device *media_open(const char *name, int verbose);
+
+/**
+ * @brief Close a media device.
+ * @param media - device instance.
+ *
+ * Close the @a media device instance and free allocated resources. Access to the
+ * device instance is forbidden after this function returns.
+ */
+void media_close(struct media_device *media);
+
+/**
+ * @brief Locate the pad at the other end of a link.
+ * @param pad - sink pad at one end of the link.
+ *
+ * Locate the source pad connected to @a pad through an enabled link. As only one
+ * link connected to a sink pad can be enabled at a time, the connected source
+ * pad is guaranteed to be unique.
+ *
+ * @return A pointer to the connected source pad, or NULL if all links connected
+ * to @a pad are disabled. Return NULL also if @a pad is not a sink pad.
+ */
+struct media_pad *media_entity_remote_source(struct media_pad *pad);
+
+/**
+ * @brief Get the type of an entity.
+ * @param entity - the entity.
+ *
+ * @return The type of @a entity.
+ */
+static inline unsigned int media_entity_type(struct media_entity *entity)
+{
+ return entity->info.type & MEDIA_ENT_TYPE_MASK;
+}
+
+/**
+ * @brief Find an entity by its name.
+ * @param media - media device.
+ * @param name - entity name.
+ * @param length - size of @a name.
+ *
+ * Search for an entity with a name equal to @a name.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *media_get_entity_by_name(struct media_device *media,
+ const char *name, size_t length);
+
+/**
+ * @brief Find an entity by its ID.
+ * @param media - media device.
+ * @param id - entity ID.
+ *
+ * Search for an entity with an ID equal to @a id.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *media_get_entity_by_id(struct media_device *media,
+ __u32 id);
+
+/**
+ * @brief Configure a link.
+ * @param media - media device.
+ * @param source - source pad at the link origin.
+ * @param sink - sink pad at the link target.
+ * @param flags - configuration flags.
+ *
+ * Locate the link between @a source and @a sink, and configure it by applying
+ * the new @a flags.
+ *
+ * Only the MEDIA_LINK_FLAG_ENABLED flag is writable.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_setup_link(struct media_device *media,
+ struct media_pad *source, struct media_pad *sink,
+ __u32 flags);
+
+/**
+ * @brief Reset all links to the disabled state.
+ * @param media - media device.
+ *
+ * Disable all links in the media device. This function is usually used after
+ * opening a media device to reset all links to a known state.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_reset_links(struct media_device *media);
+
+#endif
+
diff --git a/src/subdev.c b/src/subdev.c
deleted file mode 100644
index f8ccfe3..0000000
--- a/src/subdev.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Media controller test application
- *
- * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- */
-
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <linux/v4l2-subdev.h>
-
-#include "media.h"
-#include "subdev.h"
-#include "tools.h"
-
-int v4l2_subdev_open(struct media_entity *entity)
-{
- if (entity->fd != -1)
- return 0;
-
- entity->fd = open(entity->devname, O_RDWR);
- if (entity->fd == -1) {
- printf("%s: Failed to open subdev device node %s\n", __func__,
- entity->devname);
- return -errno;
- }
-
- return 0;
-}
-
-void v4l2_subdev_close(struct media_entity *entity)
-{
- close(entity->fd);
- entity->fd = -1;
-}
-
-int v4l2_subdev_get_format(struct media_entity *entity,
- struct v4l2_mbus_framefmt *format, unsigned int pad,
- enum v4l2_subdev_format_whence which)
-{
- struct v4l2_subdev_format fmt;
- int ret;
-
- ret = v4l2_subdev_open(entity);
- if (ret < 0)
- return ret;
-
- memset(&fmt, 0, sizeof(fmt));
- fmt.pad = pad;
- fmt.which = which;
-
- ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FMT, &fmt);
- if (ret < 0)
- return -errno;
-
- *format = fmt.format;
- return 0;
-}
-
-int v4l2_subdev_set_format(struct media_entity *entity,
- struct v4l2_mbus_framefmt *format, unsigned int pad,
- enum v4l2_subdev_format_whence which)
-{
- struct v4l2_subdev_format fmt;
- int ret;
-
- ret = v4l2_subdev_open(entity);
- if (ret < 0)
- return ret;
-
- memset(&fmt, 0, sizeof(fmt));
- fmt.pad = pad;
- fmt.which = which;
- fmt.format = *format;
-
- ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FMT, &fmt);
- if (ret < 0)
- return -errno;
-
- *format = fmt.format;
- return 0;
-}
-
-int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
- unsigned int pad, enum v4l2_subdev_format_whence which)
-{
- struct v4l2_subdev_crop crop;
- int ret;
-
- ret = v4l2_subdev_open(entity);
- if (ret < 0)
- return ret;
-
- memset(&crop, 0, sizeof(crop));
- crop.pad = pad;
- crop.which = which;
-
- ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_CROP, &crop);
- if (ret < 0)
- return -errno;
-
- *rect = crop.rect;
- return 0;
-}
-
-int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
- unsigned int pad, enum v4l2_subdev_format_whence which)
-{
- struct v4l2_subdev_crop crop;
- int ret;
-
- ret = v4l2_subdev_open(entity);
- if (ret < 0)
- return ret;
-
- memset(&crop, 0, sizeof(crop));
- crop.pad = pad;
- crop.which = which;
- crop.rect = *rect;
-
- ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CROP, &crop);
- if (ret < 0)
- return -errno;
-
- *rect = crop.rect;
- return 0;
-}
-
-int v4l2_subdev_get_frame_interval(struct media_entity *entity,
- struct v4l2_fract *interval)
-{
- struct v4l2_subdev_frame_interval ival;
- int ret;
-
- ret = v4l2_subdev_open(entity);
- if (ret < 0)
- return ret;
-
- memset(&ival, 0, sizeof(ival));
-
- ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival);
- if (ret < 0)
- return -errno;
-
- *interval = ival.interval;
- return 0;
-}
-
-int v4l2_subdev_set_frame_interval(struct media_entity *entity,
- struct v4l2_fract *interval)
-{
- struct v4l2_subdev_frame_interval ival;
- int ret;
-
- ret = v4l2_subdev_open(entity);
- if (ret < 0)
- return ret;
-
- memset(&ival, 0, sizeof(ival));
- ival.interval = *interval;
-
- ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
- if (ret < 0)
- return -errno;
-
- *interval = ival.interval;
- return 0;
-}
diff --git a/src/subdev.h b/src/subdev.h
deleted file mode 100644
index b5772e0..0000000
--- a/src/subdev.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Media controller test application
- *
- * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- */
-
-#ifndef __SUBDEV_H__
-#define __SUBDEV_H__
-
-#include <linux/v4l2-subdev.h>
-
-struct media_entity;
-
-/**
- * @brief Open a sub-device.
- * @param entity - sub-device media entity.
- *
- * Open the V4L2 subdev device node associated with @a entity. The file
- * descriptor is stored in the media_entity structure.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int v4l2_subdev_open(struct media_entity *entity);
-
-/**
- * @brief Close a sub-device.
- * @param entity - sub-device media entity.
- *
- * Close the V4L2 subdev device node associated with the @a entity and opened by
- * a previous call to v4l2_subdev_open() (either explicit or implicit).
- */
-void v4l2_subdev_close(struct media_entity *entity);
-
-/**
- * @brief Retrieve the format on a pad.
- * @param entity - subdev-device media entity.
- * @param format - format to be filled.
- * @param pad - pad number.
- * @param which - identifier of the format to get.
- *
- * Retrieve the current format on the @a entity @a pad and store it in the
- * @a format structure.
- *
- * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try format stored
- * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the current
- * active format.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int v4l2_subdev_get_format(struct media_entity *entity,
- struct v4l2_mbus_framefmt *format, unsigned int pad,
- enum v4l2_subdev_format_whence which);
-
-/**
- * @brief Set the format on a pad.
- * @param entity - subdev-device media entity.
- * @param format - format.
- * @param pad - pad number.
- * @param which - identifier of the format to set.
- *
- * Set the format on the @a entity @a pad to @a format. The driver is allowed to
- * modify the requested format, in which case @a format is updated with the
- * modifications.
- *
- * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try format stored in the
- * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the device with an
- * active format.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int v4l2_subdev_set_format(struct media_entity *entity,
- struct v4l2_mbus_framefmt *format, unsigned int pad,
- enum v4l2_subdev_format_whence which);
-
-/**
- * @brief Retrieve the crop rectangle on a pad.
- * @param entity - subdev-device media entity.
- * @param rect - crop rectangle to be filled.
- * @param pad - pad number.
- * @param which - identifier of the format to get.
- *
- * Retrieve the current crop rectangleon the @a entity @a pad and store it in
- * the @a rect structure.
- *
- * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try crop rectangle
- * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the
- * current active crop rectangle.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
- unsigned int pad, enum v4l2_subdev_format_whence which);
-
-/**
- * @brief Set the crop rectangle on a pad.
- * @param entity - subdev-device media entity.
- * @param rect - crop rectangle.
- * @param pad - pad number.
- * @param which - identifier of the format to set.
- *
- * Set the crop rectangle on the @a entity @a pad to @a rect. The driver is
- * allowed to modify the requested rectangle, in which case @a rect is updated
- * with the modifications.
- *
- * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try crop rectangle
- * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the
- * device with an active crop rectangle.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
- unsigned int pad, enum v4l2_subdev_format_whence which);
-
-/**
- * @brief Retrieve the frame interval on a sub-device.
- * @param entity - subdev-device media entity.
- * @param interval - frame interval to be filled.
- *
- * Retrieve the current frame interval on subdev @a entity and store it in the
- * @a interval structure.
- *
- * Frame interval retrieving is usually supported only on devices at the
- * beginning of video pipelines, such as sensors.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-
-int v4l2_subdev_get_frame_interval(struct media_entity *entity,
- struct v4l2_fract *interval);
-
-/**
- * @brief Set the frame interval on a sub-device.
- * @param entity - subdev-device media entity.
- * @param interval - frame interval.
- *
- * Set the frame interval on subdev @a entity to @a interval. The driver is
- * allowed to modify the requested frame interval, in which case @a interval is
- * updated with the modifications.
- *
- * Frame interval setting is usually supported only on devices at the beginning
- * of video pipelines, such as sensors.
- *
- * @return 0 on success, or a negative error code on failure.
- */
-int v4l2_subdev_set_frame_interval(struct media_entity *entity,
- struct v4l2_fract *interval);
-
-#endif
-
diff --git a/src/v4l2subdev.c b/src/v4l2subdev.c
new file mode 100644
index 0000000..785209b
--- /dev/null
+++ b/src/v4l2subdev.c
@@ -0,0 +1,188 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <linux/v4l2-subdev.h>
+
+#include "mediactl.h"
+#include "v4l2subdev.h"
+#include "tools.h"
+
+int v4l2_subdev_open(struct media_entity *entity)
+{
+ if (entity->fd != -1)
+ return 0;
+
+ entity->fd = open(entity->devname, O_RDWR);
+ if (entity->fd == -1) {
+ printf("%s: Failed to open subdev device node %s\n", __func__,
+ entity->devname);
+ return -errno;
+ }
+
+ return 0;
+}
+
+void v4l2_subdev_close(struct media_entity *entity)
+{
+ close(entity->fd);
+ entity->fd = -1;
+}
+
+int v4l2_subdev_get_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_format fmt;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.pad = pad;
+ fmt.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FMT, &fmt);
+ if (ret < 0)
+ return -errno;
+
+ *format = fmt.format;
+ return 0;
+}
+
+int v4l2_subdev_set_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_format fmt;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.pad = pad;
+ fmt.which = which;
+ fmt.format = *format;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FMT, &fmt);
+ if (ret < 0)
+ return -errno;
+
+ *format = fmt.format;
+ return 0;
+}
+
+int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_crop crop;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&crop, 0, sizeof(crop));
+ crop.pad = pad;
+ crop.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_CROP, &crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = crop.rect;
+ return 0;
+}
+
+int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_crop crop;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&crop, 0, sizeof(crop));
+ crop.pad = pad;
+ crop.which = which;
+ crop.rect = *rect;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CROP, &crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = crop.rect;
+ return 0;
+}
+
+int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ struct v4l2_subdev_frame_interval ival;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&ival, 0, sizeof(ival));
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival);
+ if (ret < 0)
+ return -errno;
+
+ *interval = ival.interval;
+ return 0;
+}
+
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ struct v4l2_subdev_frame_interval ival;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&ival, 0, sizeof(ival));
+ ival.interval = *interval;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
+ if (ret < 0)
+ return -errno;
+
+ *interval = ival.interval;
+ return 0;
+}
diff --git a/src/v4l2subdev.h b/src/v4l2subdev.h
new file mode 100644
index 0000000..b5772e0
--- /dev/null
+++ b/src/v4l2subdev.h
@@ -0,0 +1,162 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#ifndef __SUBDEV_H__
+#define __SUBDEV_H__
+
+#include <linux/v4l2-subdev.h>
+
+struct media_entity;
+
+/**
+ * @brief Open a sub-device.
+ * @param entity - sub-device media entity.
+ *
+ * Open the V4L2 subdev device node associated with @a entity. The file
+ * descriptor is stored in the media_entity structure.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_open(struct media_entity *entity);
+
+/**
+ * @brief Close a sub-device.
+ * @param entity - sub-device media entity.
+ *
+ * Close the V4L2 subdev device node associated with the @a entity and opened by
+ * a previous call to v4l2_subdev_open() (either explicit or implicit).
+ */
+void v4l2_subdev_close(struct media_entity *entity);
+
+/**
+ * @brief Retrieve the format on a pad.
+ * @param entity - subdev-device media entity.
+ * @param format - format to be filled.
+ * @param pad - pad number.
+ * @param which - identifier of the format to get.
+ *
+ * Retrieve the current format on the @a entity @a pad and store it in the
+ * @a format structure.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try format stored
+ * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the current
+ * active format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Set the format on a pad.
+ * @param entity - subdev-device media entity.
+ * @param format - format.
+ * @param pad - pad number.
+ * @param which - identifier of the format to set.
+ *
+ * Set the format on the @a entity @a pad to @a format. The driver is allowed to
+ * modify the requested format, in which case @a format is updated with the
+ * modifications.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try format stored in the
+ * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the device with an
+ * active format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Retrieve the crop rectangle on a pad.
+ * @param entity - subdev-device media entity.
+ * @param rect - crop rectangle to be filled.
+ * @param pad - pad number.
+ * @param which - identifier of the format to get.
+ *
+ * Retrieve the current crop rectangleon the @a entity @a pad and store it in
+ * the @a rect structure.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try crop rectangle
+ * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the
+ * current active crop rectangle.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Set the crop rectangle on a pad.
+ * @param entity - subdev-device media entity.
+ * @param rect - crop rectangle.
+ * @param pad - pad number.
+ * @param which - identifier of the format to set.
+ *
+ * Set the crop rectangle on the @a entity @a pad to @a rect. The driver is
+ * allowed to modify the requested rectangle, in which case @a rect is updated
+ * with the modifications.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try crop rectangle
+ * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the
+ * device with an active crop rectangle.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Retrieve the frame interval on a sub-device.
+ * @param entity - subdev-device media entity.
+ * @param interval - frame interval to be filled.
+ *
+ * Retrieve the current frame interval on subdev @a entity and store it in the
+ * @a interval structure.
+ *
+ * Frame interval retrieving is usually supported only on devices at the
+ * beginning of video pipelines, such as sensors.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+
+int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval);
+
+/**
+ * @brief Set the frame interval on a sub-device.
+ * @param entity - subdev-device media entity.
+ * @param interval - frame interval.
+ *
+ * Set the frame interval on subdev @a entity to @a interval. The driver is
+ * allowed to modify the requested frame interval, in which case @a interval is
+ * updated with the modifications.
+ *
+ * Frame interval setting is usually supported only on devices at the beginning
+ * of video pipelines, such as sensors.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval);
+
+#endif
+
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread* [media-ctl PATCH 2/7] Move link parsing from main.c to media.c, making it part of libmediactl
2011-10-07 15:34 [media-ctl PATCH 0/7] Move functionality to libraries, debug changes Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 1/7] Rename files to match the names of the libraries Sakari Ailus
@ 2011-10-07 15:38 ` Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 3/7] Move V4L2 subdev format parsing from main.c to subdev.c Sakari Ailus
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Sakari Ailus @ 2011-10-07 15:38 UTC (permalink / raw)
To: linux-media; +Cc: laurent.pinchart
This makes it possible to benefit from the link parsing code anywhere the
library is being used.
dprintf macro will later be replaced with proper debug support.
Also fix a case where -1 was returned on error and the user was expected to
check the value of errno. Negative error codes are now returned
consistently.
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
src/main.c | 139 +---------------------------------------------
src/mediactl.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
src/mediactl.h | 57 +++++++++++++++++++-
3 files changed, 212 insertions(+), 151 deletions(-)
diff --git a/src/main.c b/src/main.c
index 55a6e2d..02cdecd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -335,137 +335,6 @@ void media_print_topology(struct media_device *media, int dot)
}
/* -----------------------------------------------------------------------------
- * Links setup
- */
-
-static struct media_pad *parse_pad(struct media_device *media, const char *p, char **endp)
-{
- unsigned int entity_id, pad;
- struct media_entity *entity;
- char *end;
-
- for (; isspace(*p); ++p);
-
- if (*p == '"') {
- for (end = (char *)p + 1; *end && *end != '"'; ++end);
- if (*end != '"')
- return NULL;
-
- entity = media_get_entity_by_name(media, p + 1, end - p - 1);
- if (entity == NULL)
- return NULL;
-
- ++end;
- } else {
- entity_id = strtoul(p, &end, 10);
- entity = media_get_entity_by_id(media, entity_id);
- if (entity == NULL)
- return NULL;
- }
- for (; isspace(*end); ++end);
-
- if (*end != ':')
- return NULL;
- for (p = end + 1; isspace(*p); ++p);
-
- pad = strtoul(p, &end, 10);
- for (p = end; isspace(*p); ++p);
-
- if (pad >= entity->info.pads)
- return NULL;
-
- for (p = end; isspace(*p); ++p);
- if (endp)
- *endp = (char *)p;
-
- return &entity->pads[pad];
-}
-
-static struct media_link *parse_link(struct media_device *media, const char *p, char **endp)
-{
- struct media_link *link;
- struct media_pad *source;
- struct media_pad *sink;
- unsigned int i;
- char *end;
-
- source = parse_pad(media, p, &end);
- if (source == NULL)
- return NULL;
-
- if (end[0] != '-' || end[1] != '>')
- return NULL;
- p = end + 2;
-
- sink = parse_pad(media, p, &end);
- if (sink == NULL)
- return NULL;
-
- *endp = end;
-
- for (i = 0; i < source->entity->num_links; i++) {
- link = &source->entity->links[i];
-
- if (link->source == source && link->sink == sink)
- return link;
- }
-
- return NULL;
-}
-
-static int setup_link(struct media_device *media, const char *p, char **endp)
-{
- struct media_link *link;
- __u32 flags;
- char *end;
-
- link = parse_link(media, p, &end);
- if (link == NULL) {
- printf("Unable to parse link\n");
- return -EINVAL;
- }
-
- p = end;
- if (*p++ != '[') {
- printf("Unable to parse link flags\n");
- return -EINVAL;
- }
-
- flags = strtoul(p, &end, 10);
- for (p = end; isspace(*p); p++);
- if (*p++ != ']') {
- printf("Unable to parse link flags\n");
- return -EINVAL;
- }
-
- for (; isspace(*p); p++);
- *endp = (char *)p;
-
- printf("Setting up link %u:%u -> %u:%u [%u]\n",
- link->source->entity->info.id, link->source->index,
- link->sink->entity->info.id, link->sink->index,
- flags);
-
- return media_setup_link(media, link->source, link->sink, flags);
-}
-
-static int setup_links(struct media_device *media, const char *p)
-{
- char *end;
- int ret;
-
- do {
- ret = setup_link(media, p, &end);
- if (ret < 0)
- return ret;
-
- p = end + 1;
- } while (*end == ',');
-
- return *end ? -EINVAL : 0;
-}
-
-/* -----------------------------------------------------------------------------
* Formats setup
*/
@@ -558,7 +427,7 @@ static struct media_pad *parse_pad_format(struct media_device *media,
for (; isspace(*p); ++p);
- pad = parse_pad(media, p, &end);
+ pad = media_parse_pad(media, p, &end);
if (pad == NULL)
return NULL;
@@ -775,7 +644,7 @@ int main(int argc, char **argv)
if (media_opts.pad) {
struct media_pad *pad;
- pad = parse_pad(media, media_opts.pad, NULL);
+ pad = media_parse_pad(media, media_opts.pad, NULL);
if (pad == NULL) {
printf("Pad '%s' not found\n", media_opts.pad);
goto out;
@@ -797,7 +666,7 @@ int main(int argc, char **argv)
}
if (media_opts.links)
- setup_links(media, media_opts.links);
+ media_parse_setup_links(media, media_opts.links);
if (media_opts.formats)
setup_formats(media, media_opts.formats);
@@ -814,7 +683,7 @@ int main(int argc, char **argv)
if (buffer[0] == '\n')
break;
- setup_link(media, buffer, &end);
+ media_parse_setup_link(media, buffer, &end);
}
}
diff --git a/src/mediactl.c b/src/mediactl.c
index 5c710c9..dc5b022 100644
--- a/src/mediactl.c
+++ b/src/mediactl.c
@@ -36,6 +36,12 @@
#include "mediactl.h"
#include "tools.h"
+#ifdef DEBUG
+#define dprintf(...) printf(__VA_ARGS__)
+#else
+#define dprintf(...)
+#endif
+
struct media_pad *media_entity_remote_source(struct media_pad *pad)
{
unsigned int i;
@@ -107,8 +113,8 @@ int media_setup_link(struct media_device *media,
}
if (i == source->entity->num_links) {
- printf("%s: Link not found\n", __func__);
- return -EINVAL;
+ dprintf("%s: Link not found\n", __func__);
+ return -ENOENT;
}
/* source pad */
@@ -124,10 +130,10 @@ int media_setup_link(struct media_device *media,
ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
- if (ret < 0) {
- printf("%s: Unable to setup link (%s)\n", __func__,
+ if (ret == -1) {
+ dprintf("%s: Unable to setup link (%s)\n", __func__,
strerror(errno));
- return ret;
+ return -errno;
}
link->flags = ulink.flags;
@@ -196,7 +202,7 @@ static int media_enum_links(struct media_device *media)
links.links = malloc(entity->info.links * sizeof(struct media_link_desc));
if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
- printf("%s: Unable to enumerate pads and links (%s).\n",
+ dprintf("%s: Unable to enumerate pads and links (%s).\n",
__func__, strerror(errno));
free(links.pads);
free(links.links);
@@ -220,7 +226,7 @@ static int media_enum_links(struct media_device *media)
sink = media_get_entity_by_id(media, link->sink.entity);
if (source == NULL || sink == NULL) {
- printf("WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
+ dprintf("WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
id, i, link->source.entity, link->source.index,
link->sink.entity, link->sink.index);
ret = -EINVAL;
@@ -412,39 +418,40 @@ struct media_device *media_open(const char *name, int verbose)
media = calloc(1, sizeof(*media));
if (media == NULL) {
- printf("%s: unable to allocate memory\n", __func__);
+ dprintf("%s: unable to allocate memory\n", __func__);
return NULL;
}
if (verbose)
- printf("Opening media device %s\n", name);
+ dprintf("Opening media device %s\n", name);
+
media->fd = open(name, O_RDWR);
if (media->fd < 0) {
media_close(media);
- printf("%s: Can't open media device %s\n", __func__, name);
+ dprintf("%s: Can't open media device %s\n", __func__, name);
return NULL;
}
if (verbose)
- printf("Enumerating entities\n");
+ dprintf("Enumerating entities\n");
ret = media_enum_entities(media, verbose);
if (ret < 0) {
- printf("%s: Unable to enumerate entities for device %s (%s)\n",
+ dprintf("%s: Unable to enumerate entities for device %s (%s)\n",
__func__, name, strerror(-ret));
media_close(media);
return NULL;
}
if (verbose) {
- printf("Found %u entities\n", media->entities_count);
- printf("Enumerating pads and links\n");
+ dprintf("Found %u entities\n", media->entities_count);
+ dprintf("Enumerating pads and links\n");
}
ret = media_enum_links(media);
if (ret < 0) {
- printf("%s: Unable to enumerate pads and linksfor device %s\n",
+ dprintf("%s: Unable to enumerate pads and linksfor device %s\n",
__func__, name);
media_close(media);
return NULL;
@@ -473,3 +480,133 @@ void media_close(struct media_device *media)
free(media);
}
+struct media_pad *media_parse_pad(struct media_device *media,
+ const char *p, char **endp)
+{
+ unsigned int entity_id, pad;
+ struct media_entity *entity;
+ char *end;
+
+ for (; isspace(*p); ++p);
+
+ if (*p == '"') {
+ for (end = (char *)p + 1; *end && *end != '"'; ++end);
+ if (*end != '"')
+ return NULL;
+
+ entity = media_get_entity_by_name(media, p + 1, end - p - 1);
+ if (entity == NULL)
+ return NULL;
+
+ ++end;
+ } else {
+ entity_id = strtoul(p, &end, 10);
+ entity = media_get_entity_by_id(media, entity_id);
+ if (entity == NULL)
+ return NULL;
+ }
+ for (; isspace(*end); ++end);
+
+ if (*end != ':')
+ return NULL;
+ for (p = end + 1; isspace(*p); ++p);
+
+ pad = strtoul(p, &end, 10);
+ for (p = end; isspace(*p); ++p);
+
+ if (pad >= entity->info.pads)
+ return NULL;
+
+ for (p = end; isspace(*p); ++p);
+ if (endp)
+ *endp = (char *)p;
+
+ return &entity->pads[pad];
+}
+
+struct media_link *media_parse_link(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct media_link *link;
+ struct media_pad *source;
+ struct media_pad *sink;
+ unsigned int i;
+ char *end;
+
+ source = media_parse_pad(media, p, &end);
+ if (source == NULL)
+ return NULL;
+
+ if (end[0] != '-' || end[1] != '>')
+ return NULL;
+ p = end + 2;
+
+ sink = media_parse_pad(media, p, &end);
+ if (sink == NULL)
+ return NULL;
+
+ *endp = end;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source == source && link->sink == sink)
+ return link;
+ }
+
+ return NULL;
+}
+
+int media_parse_setup_link(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct media_link *link;
+ __u32 flags;
+ char *end;
+
+ link = media_parse_link(media, p, &end);
+ if (link == NULL) {
+ dprintf("Unable to parse link\n");
+ return -EINVAL;
+ }
+
+ p = end;
+ if (*p++ != '[') {
+ dprintf("Unable to parse link flags\n");
+ return -EINVAL;
+ }
+
+ flags = strtoul(p, &end, 10);
+ for (p = end; isspace(*p); p++);
+ if (*p++ != ']') {
+ dprintf("Unable to parse link flags\n");
+ return -EINVAL;
+ }
+
+ for (; isspace(*p); p++);
+ *endp = (char *)p;
+
+ dprintf("Setting up link %u:%u -> %u:%u [%u]\n",
+ link->source->entity->info.id, link->source->index,
+ link->sink->entity->info.id, link->sink->index,
+ flags);
+
+ return media_setup_link(media, link->source, link->sink, flags);
+}
+
+int media_parse_setup_links(struct media_device *media, const char *p)
+{
+ char *end;
+ int ret;
+
+ do {
+ ret = media_parse_setup_link(media, p, &end);
+ if (ret < 0)
+ return ret;
+
+ p = end + 1;
+ } while (*end == ',');
+
+ return *end ? -EINVAL : 0;
+}
+
diff --git a/src/mediactl.h b/src/mediactl.h
index b91a2ac..5627cd7 100644
--- a/src/mediactl.h
+++ b/src/mediactl.h
@@ -140,7 +140,9 @@ struct media_entity *media_get_entity_by_id(struct media_device *media,
*
* Only the MEDIA_LINK_FLAG_ENABLED flag is writable.
*
- * @return 0 on success, or a negative error code on failure.
+ * @return 0 on success, -1 on failure:
+ * -ENOENT: link not found
+ * - other error codes returned by MEDIA_IOC_SETUP_LINK
*/
int media_setup_link(struct media_device *media,
struct media_pad *source, struct media_pad *sink,
@@ -157,5 +159,58 @@ int media_setup_link(struct media_device *media,
*/
int media_reset_links(struct media_device *media);
+/**
+ * @brief Parse string to a pad on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string where parsing ended
+ *
+ * Parse NULL terminated string describing a pad and return its struct
+ * media_pad instance.
+ *
+ * @return Pointer to struct media_pad on success, NULL on failure.
+ */
+struct media_pad *media_parse_pad(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to a link on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to p where parsing ended
+ *
+ * Parse NULL terminated string p describing a link and return its struct
+ * media_link instance.
+ *
+ * @return Pointer to struct media_link on success, NULL on failure.
+ */
+struct media_link *media_parse_link(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to a link on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing a link and its configuration
+ * and configure the link.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_parse_setup_link(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to link(s) on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing link(s) separated by
+ * commas (,) and configure the link(s).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_parse_setup_links(struct media_device *media, const char *p);
+
#endif
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread* [media-ctl PATCH 3/7] Move V4L2 subdev format parsing from main.c to subdev.c
2011-10-07 15:34 [media-ctl PATCH 0/7] Move functionality to libraries, debug changes Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 1/7] Rename files to match the names of the libraries Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 2/7] Move link parsing from main.c to media.c, making it part of libmediactl Sakari Ailus
@ 2011-10-07 15:38 ` Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 4/7] libv4l2subdev and libmediactl are not test programs Sakari Ailus
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Sakari Ailus @ 2011-10-07 15:38 UTC (permalink / raw)
To: linux-media; +Cc: laurent.pinchart
This makes format parsing a part of the libv4l2subdev and thus available on
all who use the library.
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
src/main.c | 340 +-----------------------------------------------------
src/v4l2subdev.c | 343 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/v4l2subdev.h | 37 ++++++
3 files changed, 382 insertions(+), 338 deletions(-)
diff --git a/src/main.c b/src/main.c
index 02cdecd..0d68ff6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -45,61 +45,6 @@
* Printing
*/
-static struct {
- const char *name;
- enum v4l2_mbus_pixelcode code;
-} mbus_formats[] = {
- { "Y8", V4L2_MBUS_FMT_Y8_1X8},
- { "Y10", V4L2_MBUS_FMT_Y10_1X10 },
- { "Y12", V4L2_MBUS_FMT_Y12_1X12 },
- { "YUYV", V4L2_MBUS_FMT_YUYV8_1X16 },
- { "UYVY", V4L2_MBUS_FMT_UYVY8_1X16 },
- { "SBGGR8", V4L2_MBUS_FMT_SBGGR8_1X8 },
- { "SGBRG8", V4L2_MBUS_FMT_SGBRG8_1X8 },
- { "SGRBG8", V4L2_MBUS_FMT_SGRBG8_1X8 },
- { "SRGGB8", V4L2_MBUS_FMT_SRGGB8_1X8 },
- { "SBGGR10", V4L2_MBUS_FMT_SBGGR10_1X10 },
- { "SGBRG10", V4L2_MBUS_FMT_SGBRG10_1X10 },
- { "SGRBG10", V4L2_MBUS_FMT_SGRBG10_1X10 },
- { "SRGGB10", V4L2_MBUS_FMT_SRGGB10_1X10 },
- { "SBGGR10_DPCM8", V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 },
- { "SGBRG10_DPCM8", V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 },
- { "SGRBG10_DPCM8", V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 },
- { "SRGGB10_DPCM8", V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 },
- { "SBGGR12", V4L2_MBUS_FMT_SBGGR12_1X12 },
- { "SGBRG12", V4L2_MBUS_FMT_SGBRG12_1X12 },
- { "SGRBG12", V4L2_MBUS_FMT_SGRBG12_1X12 },
- { "SRGGB12", V4L2_MBUS_FMT_SRGGB12_1X12 },
-};
-
-static const char *pixelcode_to_string(enum v4l2_mbus_pixelcode code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
- if (mbus_formats[i].code == code)
- return mbus_formats[i].name;
- }
-
- return "unknown";
-}
-
-static enum v4l2_mbus_pixelcode string_to_pixelcode(const char *string,
- unsigned int length)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
- if (strncmp(mbus_formats[i].name, string, length) == 0)
- break;
- }
-
- if (i == ARRAY_SIZE(mbus_formats))
- return (enum v4l2_mbus_pixelcode)-1;
-
- return mbus_formats[i].code;
-}
-
static void v4l2_subdev_print_format(struct media_entity *entity,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
@@ -111,7 +56,7 @@ static void v4l2_subdev_print_format(struct media_entity *entity,
if (ret != 0)
return;
- printf("[%s %ux%u", pixelcode_to_string(format.code),
+ printf("[%s %ux%u", v4l2_subdev_pixelcode_to_string(format.code),
format.width, format.height);
ret = v4l2_subdev_get_crop(entity, &rect, pad, which);
@@ -334,287 +279,6 @@ void media_print_topology(struct media_device *media, int dot)
media_print_topology_text(media);
}
-/* -----------------------------------------------------------------------------
- * Formats setup
- */
-
-static int parse_format(struct v4l2_mbus_framefmt *format, const char *p, char **endp)
-{
- enum v4l2_mbus_pixelcode code;
- unsigned int width, height;
- char *end;
-
- for (; isspace(*p); ++p);
- for (end = (char *)p; !isspace(*end) && *end != '\0'; ++end);
-
- code = string_to_pixelcode(p, end - p);
- if (code == (enum v4l2_mbus_pixelcode)-1)
- return -EINVAL;
-
- for (p = end; isspace(*p); ++p);
- width = strtoul(p, &end, 10);
- if (*end != 'x')
- return -EINVAL;
-
- p = end + 1;
- height = strtoul(p, &end, 10);
- *endp = end;
-
- memset(format, 0, sizeof(*format));
- format->width = width;
- format->height = height;
- format->code = code;
-
- return 0;
-}
-
-static int parse_crop(struct v4l2_rect *crop, const char *p, char **endp)
-{
- char *end;
-
- if (*p++ != '(')
- return -EINVAL;
-
- crop->left = strtoul(p, &end, 10);
- if (*end != ',')
- return -EINVAL;
-
- p = end + 1;
- crop->top = strtoul(p, &end, 10);
- if (*end++ != ')')
- return -EINVAL;
- if (*end != '/')
- return -EINVAL;
-
- p = end + 1;
- crop->width = strtoul(p, &end, 10);
- if (*end != 'x')
- return -EINVAL;
-
- p = end + 1;
- crop->height = strtoul(p, &end, 10);
- *endp = end;
-
- return 0;
-}
-
-static int parse_frame_interval(struct v4l2_fract *interval, const char *p, char **endp)
-{
- char *end;
-
- for (; isspace(*p); ++p);
-
- interval->numerator = strtoul(p, &end, 10);
-
- for (p = end; isspace(*p); ++p);
- if (*p++ != '/')
- return -EINVAL;
-
- for (; isspace(*p); ++p);
- interval->denominator = strtoul(p, &end, 10);
-
- *endp = end;
- return 0;
-}
-
-static struct media_pad *parse_pad_format(struct media_device *media,
- struct v4l2_mbus_framefmt *format, struct v4l2_rect *crop,
- struct v4l2_fract *interval, const char *p, char **endp)
-{
- struct media_pad *pad;
- char *end;
- int ret;
-
- for (; isspace(*p); ++p);
-
- pad = media_parse_pad(media, p, &end);
- if (pad == NULL)
- return NULL;
-
- for (p = end; isspace(*p); ++p);
- if (*p++ != '[')
- return NULL;
-
- for (; isspace(*p); ++p);
-
- if (isalnum(*p)) {
- ret = parse_format(format, p, &end);
- if (ret < 0)
- return NULL;
-
- for (p = end; isspace(*p); p++);
- }
-
- if (*p == '(') {
- ret = parse_crop(crop, p, &end);
- if (ret < 0)
- return NULL;
-
- for (p = end; isspace(*p); p++);
- }
-
- if (*p == '@') {
- ret = parse_frame_interval(interval, ++p, &end);
- if (ret < 0)
- return NULL;
-
- for (p = end; isspace(*p); p++);
- }
-
- if (*p != ']')
- return NULL;
-
- *endp = (char *)p + 1;
- return pad;
-}
-
-static int set_format(struct media_pad *pad, struct v4l2_mbus_framefmt *format)
-{
- int ret;
-
- if (format->width == 0 || format->height == 0)
- return 0;
-
- printf("Setting up format %s %ux%u on pad %s/%u\n",
- pixelcode_to_string(format->code), format->width, format->height,
- pad->entity->info.name, pad->index);
-
- ret = v4l2_subdev_set_format(pad->entity, format, pad->index,
- V4L2_SUBDEV_FORMAT_ACTIVE);
- if (ret < 0) {
- printf("Unable to set format: %s (%d)\n", strerror(-ret), ret);
- return ret;
- }
-
- printf("Format set: %s %ux%u\n",
- pixelcode_to_string(format->code), format->width, format->height);
-
- return 0;
-}
-
-static int set_crop(struct media_pad *pad, struct v4l2_rect *crop)
-{
- int ret;
-
- if (crop->left == -1 || crop->top == -1)
- return 0;
-
- printf("Setting up crop rectangle (%u,%u)/%ux%u on pad %s/%u\n",
- crop->left, crop->top, crop->width, crop->height,
- pad->entity->info.name, pad->index);
-
- ret = v4l2_subdev_set_crop(pad->entity, crop, pad->index,
- V4L2_SUBDEV_FORMAT_ACTIVE);
- if (ret < 0) {
- printf("Unable to set crop rectangle: %s (%d)\n", strerror(-ret), ret);
- return ret;
- }
-
- printf("Crop rectangle set: (%u,%u)/%ux%u\n",
- crop->left, crop->top, crop->width, crop->height);
-
- return 0;
-}
-
-static int set_frame_interval(struct media_entity *entity, struct v4l2_fract *interval)
-{
- int ret;
-
- if (interval->numerator == 0)
- return 0;
-
- printf("Setting up frame interval %u/%u on entity %s\n",
- interval->numerator, interval->denominator, entity->info.name);
-
- ret = v4l2_subdev_set_frame_interval(entity, interval);
- if (ret < 0) {
- printf("Unable to set frame interval: %s (%d)", strerror(-ret), ret);
- return ret;
- }
-
- printf("Frame interval set: %u/%u\n",
- interval->numerator, interval->denominator);
-
- return 0;
-}
-
-
-static int setup_format(struct media_device *media, const char *p, char **endp)
-{
- struct v4l2_mbus_framefmt format = { 0, 0, 0 };
- struct media_pad *pad;
- struct v4l2_rect crop = { -1, -1, -1, -1 };
- struct v4l2_fract interval = { 0, 0 };
- unsigned int i;
- char *end;
- int ret;
-
- pad = parse_pad_format(media, &format, &crop, &interval, p, &end);
- if (pad == NULL) {
- printf("Unable to parse format\n");
- return -EINVAL;
- }
-
- if (pad->flags & MEDIA_PAD_FL_SOURCE) {
- ret = set_crop(pad, &crop);
- if (ret < 0)
- return ret;
- }
-
- ret = set_format(pad, &format);
- if (ret < 0)
- return ret;
-
- if (pad->flags & MEDIA_PAD_FL_SINK) {
- ret = set_crop(pad, &crop);
- if (ret < 0)
- return ret;
- }
-
- ret = set_frame_interval(pad->entity, &interval);
- if (ret < 0)
- return ret;
-
-
- /* If the pad is an output pad, automatically set the same format on
- * the remote subdev input pads, if any.
- */
- if (pad->flags & MEDIA_PAD_FL_SOURCE) {
- for (i = 0; i < pad->entity->num_links; ++i) {
- struct media_link *link = &pad->entity->links[i];
- struct v4l2_mbus_framefmt remote_format;
-
- if (!(link->flags & MEDIA_LNK_FL_ENABLED))
- continue;
-
- if (link->source == pad &&
- link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) {
- remote_format = format;
- set_format(link->sink, &remote_format);
- }
- }
- }
-
- *endp = end;
- return 0;
-}
-
-static int setup_formats(struct media_device *media, const char *p)
-{
- char *end;
- int ret;
-
- do {
- ret = setup_format(media, p, &end);
- if (ret < 0)
- return ret;
-
- p = end + 1;
- } while (*end == ',');
-
- return *end ? -EINVAL : 0;
-}
-
int main(int argc, char **argv)
{
struct media_device *media;
@@ -669,7 +333,7 @@ int main(int argc, char **argv)
media_parse_setup_links(media, media_opts.links);
if (media_opts.formats)
- setup_formats(media, media_opts.formats);
+ v4l2_subdev_parse_setup_formats(media, media_opts.formats);
if (media_opts.interactive) {
while (1) {
diff --git a/src/v4l2subdev.c b/src/v4l2subdev.c
index 785209b..0b4793d 100644
--- a/src/v4l2subdev.c
+++ b/src/v4l2subdev.c
@@ -186,3 +186,346 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
*interval = ival.interval;
return 0;
}
+
+static int v4l2_subdev_parse_format(struct v4l2_mbus_framefmt *format,
+ const char *p, char **endp)
+{
+ enum v4l2_mbus_pixelcode code;
+ unsigned int width, height;
+ char *end;
+
+ for (; isspace(*p); ++p);
+ for (end = (char *)p; !isspace(*end) && *end != '\0'; ++end);
+
+ code = v4l2_subdev_string_to_pixelcode(p, end - p);
+ if (code == (enum v4l2_mbus_pixelcode)-1)
+ return -EINVAL;
+
+ for (p = end; isspace(*p); ++p);
+ width = strtoul(p, &end, 10);
+ if (*end != 'x')
+ return -EINVAL;
+
+ p = end + 1;
+ height = strtoul(p, &end, 10);
+ *endp = end;
+
+ memset(format, 0, sizeof(*format));
+ format->width = width;
+ format->height = height;
+ format->code = code;
+
+ return 0;
+}
+
+static int v4l2_subdev_parse_crop(
+ struct v4l2_rect *crop, const char *p, char **endp)
+{
+ char *end;
+
+ if (*p++ != '(')
+ return -EINVAL;
+
+ crop->left = strtoul(p, &end, 10);
+ if (*end != ',')
+ return -EINVAL;
+
+ p = end + 1;
+ crop->top = strtoul(p, &end, 10);
+ if (*end++ != ')')
+ return -EINVAL;
+ if (*end != '/')
+ return -EINVAL;
+
+ p = end + 1;
+ crop->width = strtoul(p, &end, 10);
+ if (*end != 'x')
+ return -EINVAL;
+
+ p = end + 1;
+ crop->height = strtoul(p, &end, 10);
+ *endp = end;
+
+ return 0;
+}
+
+static int v4l2_subdev_parse_frame_interval(struct v4l2_fract *interval,
+ const char *p, char **endp)
+{
+ char *end;
+
+ for (; isspace(*p); ++p);
+
+ interval->numerator = strtoul(p, &end, 10);
+
+ for (p = end; isspace(*p); ++p);
+ if (*p++ != '/')
+ return -EINVAL;
+
+ for (; isspace(*p); ++p);
+ interval->denominator = strtoul(p, &end, 10);
+
+ *endp = end;
+ return 0;
+}
+
+static struct media_pad *v4l2_subdev_parse_pad_format(
+ struct media_device *media, struct v4l2_mbus_framefmt *format,
+ struct v4l2_rect *crop, struct v4l2_fract *interval, const char *p,
+ char **endp)
+{
+ struct media_pad *pad;
+ char *end;
+ int ret;
+
+ for (; isspace(*p); ++p);
+
+ pad = media_parse_pad(media, p, &end);
+ if (pad == NULL)
+ return NULL;
+
+ for (p = end; isspace(*p); ++p);
+ if (*p++ != '[')
+ return NULL;
+
+ for (; isspace(*p); ++p);
+
+ if (isalnum(*p)) {
+ ret = v4l2_subdev_parse_format(format, p, &end);
+ if (ret < 0)
+ return NULL;
+
+ for (p = end; isspace(*p); p++);
+ }
+
+ if (*p == '(') {
+ ret = v4l2_subdev_parse_crop(crop, p, &end);
+ if (ret < 0)
+ return NULL;
+
+ for (p = end; isspace(*p); p++);
+ }
+
+ if (*p == '@') {
+ ret = v4l2_subdev_parse_frame_interval(interval, ++p, &end);
+ if (ret < 0)
+ return NULL;
+
+ for (p = end; isspace(*p); p++);
+ }
+
+ if (*p != ']')
+ return NULL;
+
+ *endp = (char *)p + 1;
+ return pad;
+}
+
+static int set_format(struct media_pad *pad,
+ struct v4l2_mbus_framefmt *format)
+{
+ int ret;
+
+ if (format->width == 0 || format->height == 0)
+ return 0;
+
+ printf("Setting up format %s %ux%u on pad %s/%u\n",
+ v4l2_subdev_pixelcode_to_string(format->code),
+ format->width, format->height,
+ pad->entity->info.name, pad->index);
+
+ ret = v4l2_subdev_set_format(pad->entity, format, pad->index,
+ V4L2_SUBDEV_FORMAT_ACTIVE);
+ if (ret < 0) {
+ printf("Unable to set format: %s (%d)\n", strerror(-ret), ret);
+ return ret;
+ }
+
+ printf("Format set: %s %ux%u\n",
+ v4l2_subdev_pixelcode_to_string(format->code),
+ format->width, format->height);
+
+ return 0;
+}
+
+static int set_crop(struct media_pad *pad, struct v4l2_rect *crop)
+{
+ int ret;
+
+ if (crop->left == -1 || crop->top == -1)
+ return 0;
+
+ printf("Setting up crop rectangle (%u,%u)/%ux%u on pad %s/%u\n",
+ crop->left, crop->top, crop->width, crop->height,
+ pad->entity->info.name, pad->index);
+
+ ret = v4l2_subdev_set_crop(pad->entity, crop, pad->index,
+ V4L2_SUBDEV_FORMAT_ACTIVE);
+ if (ret < 0) {
+ printf("Unable to set crop rectangle: %s (%d)\n", strerror(-ret), ret);
+ return ret;
+ }
+
+ printf("Crop rectangle set: (%u,%u)/%ux%u\n",
+ crop->left, crop->top, crop->width, crop->height);
+
+ return 0;
+}
+
+static int set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ int ret;
+
+ if (interval->numerator == 0)
+ return 0;
+
+ printf("Setting up frame interval %u/%u on entity %s\n",
+ interval->numerator, interval->denominator, entity->info.name);
+
+ ret = v4l2_subdev_set_frame_interval(entity, interval);
+ if (ret < 0) {
+ printf("Unable to set frame interval: %s (%d)", strerror(-ret), ret);
+ return ret;
+ }
+
+ printf("Frame interval set: %u/%u\n",
+ interval->numerator, interval->denominator);
+
+ return 0;
+}
+
+
+static int v4l2_subdev_parse_setup_format(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct v4l2_mbus_framefmt format = { 0, 0, 0 };
+ struct media_pad *pad;
+ struct v4l2_rect crop = { -1, -1, -1, -1 };
+ struct v4l2_fract interval = { 0, 0 };
+ unsigned int i;
+ char *end;
+ int ret;
+
+ pad = v4l2_subdev_parse_pad_format(media, &format, &crop, &interval,
+ p, &end);
+ if (pad == NULL) {
+ printf("Unable to parse format\n");
+ return -EINVAL;
+ }
+
+ if (pad->flags & MEDIA_PAD_FL_SOURCE) {
+ ret = set_crop(pad, &crop);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = set_format(pad, &format);
+ if (ret < 0)
+ return ret;
+
+ if (pad->flags & MEDIA_PAD_FL_SINK) {
+ ret = set_crop(pad, &crop);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = set_frame_interval(pad->entity, &interval);
+ if (ret < 0)
+ return ret;
+
+
+ /* If the pad is an output pad, automatically set the same format on
+ * the remote subdev input pads, if any.
+ */
+ if (pad->flags & MEDIA_PAD_FL_SOURCE) {
+ for (i = 0; i < pad->entity->num_links; ++i) {
+ struct media_link *link = &pad->entity->links[i];
+ struct v4l2_mbus_framefmt remote_format;
+
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+ continue;
+
+ if (link->source == pad &&
+ link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) {
+ remote_format = format;
+ set_format(link->sink, &remote_format);
+ }
+ }
+ }
+
+ *endp = end;
+ return 0;
+}
+
+int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p)
+{
+ char *end;
+ int ret;
+
+ do {
+ ret = v4l2_subdev_parse_setup_format(media, p, &end);
+ if (ret < 0)
+ return ret;
+
+ p = end + 1;
+ } while (*end == ',');
+
+ return *end ? -EINVAL : 0;
+}
+
+static struct {
+ const char *name;
+ enum v4l2_mbus_pixelcode code;
+} mbus_formats[] = {
+ { "Y8", V4L2_MBUS_FMT_Y8_1X8},
+ { "Y10", V4L2_MBUS_FMT_Y10_1X10 },
+ { "Y12", V4L2_MBUS_FMT_Y12_1X12 },
+ { "YUYV", V4L2_MBUS_FMT_YUYV8_1X16 },
+ { "UYVY", V4L2_MBUS_FMT_UYVY8_1X16 },
+ { "SBGGR8", V4L2_MBUS_FMT_SBGGR8_1X8 },
+ { "SGBRG8", V4L2_MBUS_FMT_SGBRG8_1X8 },
+ { "SGRBG8", V4L2_MBUS_FMT_SGRBG8_1X8 },
+ { "SRGGB8", V4L2_MBUS_FMT_SRGGB8_1X8 },
+ { "SBGGR10", V4L2_MBUS_FMT_SBGGR10_1X10 },
+ { "SGBRG10", V4L2_MBUS_FMT_SGBRG10_1X10 },
+ { "SGRBG10", V4L2_MBUS_FMT_SGRBG10_1X10 },
+ { "SRGGB10", V4L2_MBUS_FMT_SRGGB10_1X10 },
+ { "SBGGR10_DPCM8", V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 },
+ { "SGBRG10_DPCM8", V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 },
+ { "SGRBG10_DPCM8", V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 },
+ { "SRGGB10_DPCM8", V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 },
+ { "SBGGR12", V4L2_MBUS_FMT_SBGGR12_1X12 },
+ { "SGBRG12", V4L2_MBUS_FMT_SGBRG12_1X12 },
+ { "SGRBG12", V4L2_MBUS_FMT_SGRBG12_1X12 },
+ { "SRGGB12", V4L2_MBUS_FMT_SRGGB12_1X12 },
+};
+
+const char *v4l2_subdev_pixelcode_to_string(enum v4l2_mbus_pixelcode code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
+ if (mbus_formats[i].code == code)
+ return mbus_formats[i].name;
+ }
+
+ return "unknown";
+}
+
+enum v4l2_mbus_pixelcode v4l2_subdev_string_to_pixelcode(const char *string,
+ unsigned int length)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
+ if (strncmp(mbus_formats[i].name, string, length) == 0)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(mbus_formats))
+ return (enum v4l2_mbus_pixelcode)-1;
+
+ return mbus_formats[i].code;
+}
+
diff --git a/src/v4l2subdev.h b/src/v4l2subdev.h
index b5772e0..db85491 100644
--- a/src/v4l2subdev.h
+++ b/src/v4l2subdev.h
@@ -158,5 +158,42 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
int v4l2_subdev_set_frame_interval(struct media_entity *entity,
struct v4l2_fract *interval);
+/**
+ * @brief Parse a string and apply format, crop and frame interval settings.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string p where parsing ended (return)
+ *
+ * Parse string @a p and apply format, crop and frame interval settings to a
+ * subdev pad specified in @a p. @a endp will be written a pointer where
+ * parsing of @a p ended.
+ *
+ * Format strings are separeted by commas (,).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p);
+
+/**
+ * @brief Convert media bus pixel code to string.
+ * @param code - input string
+ *
+ * Convert media bus pixel code @a code to a human-readable string.
+ *
+ * @return A pointer to a string on success, NULL on failure.
+ */
+const char *v4l2_subdev_pixelcode_to_string(enum v4l2_mbus_pixelcode code);
+
+/**
+ * @brief Parse string to media bus pixel code.
+ * @param string - input string
+ * @param lenght - length of the string
+ *
+ * Parse human readable string @a string to an media bus pixel code.
+ *
+ * @return media bus pixelcode on success, -1 on failure.
+ */
+enum v4l2_mbus_pixelcode v4l2_subdev_string_to_pixelcode(const char *string,
+ unsigned int length);
#endif
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread* [media-ctl PATCH 4/7] libv4l2subdev and libmediactl are not test programs
2011-10-07 15:34 [media-ctl PATCH 0/7] Move functionality to libraries, debug changes Sakari Ailus
` (2 preceding siblings ...)
2011-10-07 15:38 ` [media-ctl PATCH 3/7] Move V4L2 subdev format parsing from main.c to subdev.c Sakari Ailus
@ 2011-10-07 15:38 ` Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 5/7] Add link to media_device from the media_entity Sakari Ailus
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Sakari Ailus @ 2011-10-07 15:38 UTC (permalink / raw)
To: linux-media; +Cc: laurent.pinchart
Call the libraries libraries rather than test programs.
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
src/mediactl.c | 2 +-
src/mediactl.h | 2 +-
src/v4l2subdev.c | 2 +-
src/v4l2subdev.h | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/mediactl.c b/src/mediactl.c
index dc5b022..a03c19a 100644
--- a/src/mediactl.c
+++ b/src/mediactl.c
@@ -1,5 +1,5 @@
/*
- * Media controller test application
+ * Media controller interface library
*
* Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
*
diff --git a/src/mediactl.h b/src/mediactl.h
index 5627cd7..9ebad9f 100644
--- a/src/mediactl.h
+++ b/src/mediactl.h
@@ -1,5 +1,5 @@
/*
- * Media controller test application
+ * Media controller interface library
*
* Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
*
diff --git a/src/v4l2subdev.c b/src/v4l2subdev.c
index 0b4793d..80365e6 100644
--- a/src/v4l2subdev.c
+++ b/src/v4l2subdev.c
@@ -1,5 +1,5 @@
/*
- * Media controller test application
+ * V4L2 subdev interface library
*
* Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
*
diff --git a/src/v4l2subdev.h b/src/v4l2subdev.h
index db85491..d9ab692 100644
--- a/src/v4l2subdev.h
+++ b/src/v4l2subdev.h
@@ -1,5 +1,5 @@
/*
- * Media controller test application
+ * V4L2 subdev interface library
*
* Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
*
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread* [media-ctl PATCH 5/7] Add link to media_device from the media_entity
2011-10-07 15:34 [media-ctl PATCH 0/7] Move functionality to libraries, debug changes Sakari Ailus
` (3 preceding siblings ...)
2011-10-07 15:38 ` [media-ctl PATCH 4/7] libv4l2subdev and libmediactl are not test programs Sakari Ailus
@ 2011-10-07 15:38 ` Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 6/7] Add debugging handler Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 7/7] Remove extra verbosity Sakari Ailus
6 siblings, 0 replies; 10+ messages in thread
From: Sakari Ailus @ 2011-10-07 15:38 UTC (permalink / raw)
To: linux-media; +Cc: laurent.pinchart
This makes it possible to obtain the media device an entity belongs to.
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
src/mediactl.c | 1 +
src/mediactl.h | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/mediactl.c b/src/mediactl.c
index a03c19a..8cc338d 100644
--- a/src/mediactl.c
+++ b/src/mediactl.c
@@ -372,6 +372,7 @@ static int media_enum_entities(struct media_device *media, int verbose)
memset(entity, 0, sizeof(*entity));
entity->fd = -1;
entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+ entity->media = media;
ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
if (ret < 0) {
diff --git a/src/mediactl.h b/src/mediactl.h
index 9ebad9f..98b47fd 100644
--- a/src/mediactl.h
+++ b/src/mediactl.h
@@ -38,6 +38,7 @@ struct media_pad {
};
struct media_entity {
+ struct media_device *media;
struct media_entity_desc info;
struct media_pad *pads;
struct media_link *links;
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread* [media-ctl PATCH 6/7] Add debugging handler
2011-10-07 15:34 [media-ctl PATCH 0/7] Move functionality to libraries, debug changes Sakari Ailus
` (4 preceding siblings ...)
2011-10-07 15:38 ` [media-ctl PATCH 5/7] Add link to media_device from the media_entity Sakari Ailus
@ 2011-10-07 15:38 ` Sakari Ailus
2011-10-07 15:38 ` [media-ctl PATCH 7/7] Remove extra verbosity Sakari Ailus
6 siblings, 0 replies; 10+ messages in thread
From: Sakari Ailus @ 2011-10-07 15:38 UTC (permalink / raw)
To: linux-media; +Cc: laurent.pinchart
Add debugging handler to media_device that may be used to redirect all debug
formatting to user-supplied function. fprintf will do, and that's what
media-ctl test program will use.
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
src/main.c | 3 +-
src/mediactl.c | 105 +++++++++++++++++++++++++++++++++---------------------
src/mediactl.h | 41 +++++++++++++++++++++
src/v4l2subdev.c | 57 ++++++++++++++++++-----------
4 files changed, 142 insertions(+), 64 deletions(-)
diff --git a/src/main.c b/src/main.c
index 0d68ff6..40ab13e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -288,7 +288,8 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
/* Open the media device and enumerate entities, pads and links. */
- media = media_open(media_opts.devname, media_opts.verbose);
+ media = media_open_debug(media_opts.devname, media_opts.verbose,
+ (void (*)(void *, ...))fprintf, stdout);
if (media == NULL)
goto out;
diff --git a/src/mediactl.c b/src/mediactl.c
index 8cc338d..43d1b6a 100644
--- a/src/mediactl.c
+++ b/src/mediactl.c
@@ -36,12 +36,6 @@
#include "mediactl.h"
#include "tools.h"
-#ifdef DEBUG
-#define dprintf(...) printf(__VA_ARGS__)
-#else
-#define dprintf(...)
-#endif
-
struct media_pad *media_entity_remote_source(struct media_pad *pad)
{
unsigned int i;
@@ -113,7 +107,7 @@ int media_setup_link(struct media_device *media,
}
if (i == source->entity->num_links) {
- dprintf("%s: Link not found\n", __func__);
+ media_dbg(media, "%s: Link not found\n", __func__);
return -ENOENT;
}
@@ -131,8 +125,8 @@ int media_setup_link(struct media_device *media,
ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
if (ret == -1) {
- dprintf("%s: Unable to setup link (%s)\n", __func__,
- strerror(errno));
+ media_dbg(media, "%s: Unable to setup link (%s)\n",
+ __func__, strerror(errno));
return -errno;
}
@@ -202,8 +196,9 @@ static int media_enum_links(struct media_device *media)
links.links = malloc(entity->info.links * sizeof(struct media_link_desc));
if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
- dprintf("%s: Unable to enumerate pads and links (%s).\n",
- __func__, strerror(errno));
+ media_dbg(media,
+ "%s: Unable to enumerate pads and links (%s).\n",
+ __func__, strerror(errno));
free(links.pads);
free(links.links);
return -errno;
@@ -226,9 +221,12 @@ static int media_enum_links(struct media_device *media)
sink = media_get_entity_by_id(media, link->sink.entity);
if (source == NULL || sink == NULL) {
- dprintf("WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
- id, i, link->source.entity, link->source.index,
- link->sink.entity, link->sink.index);
+ media_dbg(media,
+ "WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
+ id, i, link->source.entity,
+ link->source.index,
+ link->sink.entity,
+ link->sink.index);
ret = -EINVAL;
} else {
fwdlink = media_entity_add_link(source);
@@ -284,7 +282,8 @@ static int media_get_devname_udev(struct udev *udev,
devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
if (verbose)
- printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
+ media_dbg(entity->media, "looking up device: %u:%u\n",
+ major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
if (device) {
p = udev_device_get_devnode(device);
@@ -362,7 +361,7 @@ static int media_enum_entities(struct media_device *media, int verbose)
ret = media_udev_open(&udev);
if (ret < 0)
- printf("%s: Can't get udev context\n", __func__);
+ media_dbg(media, "Can't get udev context\n");
for (id = 0, ret = 0; ; id = entity->info.id) {
size = (media->entities_count + 1) * sizeof(*media->entities);
@@ -412,48 +411,66 @@ static int media_enum_entities(struct media_device *media, int verbose)
return ret;
}
-struct media_device *media_open(const char *name, int verbose)
+static void media_debug_default(void *ptr, ...)
+{
+}
+
+void media_debug_set_handler(struct media_device *media,
+ void (*debug_handler)(void *, ...),
+ void *debug_priv)
+{
+ if (debug_handler) {
+ media->debug_handler = debug_handler;
+ media->debug_priv = debug_priv;
+ } else {
+ media->debug_handler = media_debug_default;
+ media->debug_priv = NULL;
+ }
+}
+
+struct media_device *media_open_debug(
+ const char *name, int verbose, void (*debug_handler)(void *, ...),
+ void *debug_priv)
{
struct media_device *media;
int ret;
media = calloc(1, sizeof(*media));
- if (media == NULL) {
- dprintf("%s: unable to allocate memory\n", __func__);
+ if (media == NULL)
return NULL;
- }
- if (verbose)
- dprintf("Opening media device %s\n", name);
+ media_debug_set_handler(media, debug_handler, debug_priv);
+
+ media_dbg(media, "Opening media device %s\n", name);
media->fd = open(name, O_RDWR);
if (media->fd < 0) {
media_close(media);
- dprintf("%s: Can't open media device %s\n", __func__, name);
+ media_dbg(media, "%s: Can't open media device %s\n",
+ __func__, name);
return NULL;
}
- if (verbose)
- dprintf("Enumerating entities\n");
+ media_dbg(media, "Enumerating entities\n");
ret = media_enum_entities(media, verbose);
if (ret < 0) {
- dprintf("%s: Unable to enumerate entities for device %s (%s)\n",
- __func__, name, strerror(-ret));
+ media_dbg(media,
+ "%s: Unable to enumerate entities for device %s (%s)\n",
+ __func__, name, strerror(-ret));
media_close(media);
return NULL;
}
- if (verbose) {
- dprintf("Found %u entities\n", media->entities_count);
- dprintf("Enumerating pads and links\n");
- }
+ media_dbg(media, "Found %u entities\n", media->entities_count);
+ media_dbg(media, "Enumerating pads and links\n");
ret = media_enum_links(media);
if (ret < 0) {
- dprintf("%s: Unable to enumerate pads and linksfor device %s\n",
- __func__, name);
+ media_dbg(media,
+ "%s: Unable to enumerate pads and linksfor device %s\n",
+ __func__, name);
media_close(media);
return NULL;
}
@@ -461,6 +478,11 @@ struct media_device *media_open(const char *name, int verbose)
return media;
}
+struct media_device *media_open(const char *name, int verbose)
+{
+ return media_open_debug(name, verbose, NULL, NULL);
+}
+
void media_close(struct media_device *media)
{
unsigned int i;
@@ -567,30 +589,32 @@ int media_parse_setup_link(struct media_device *media,
link = media_parse_link(media, p, &end);
if (link == NULL) {
- dprintf("Unable to parse link\n");
+ media_dbg(media,
+ "%s: Unable to parse link\n", __func__);
return -EINVAL;
}
p = end;
if (*p++ != '[') {
- dprintf("Unable to parse link flags\n");
+ media_dbg(media, "Unable to parse link flags\n");
return -EINVAL;
}
flags = strtoul(p, &end, 10);
for (p = end; isspace(*p); p++);
if (*p++ != ']') {
- dprintf("Unable to parse link flags\n");
+ media_dbg(media, "Unable to parse link flags\n");
return -EINVAL;
}
for (; isspace(*p); p++);
*endp = (char *)p;
- dprintf("Setting up link %u:%u -> %u:%u [%u]\n",
- link->source->entity->info.id, link->source->index,
- link->sink->entity->info.id, link->sink->index,
- flags);
+ media_dbg(media,
+ "Setting up link %u:%u -> %u:%u [%u]\n",
+ link->source->entity->info.id, link->source->index,
+ link->sink->entity->info.id, link->sink->index,
+ flags);
return media_setup_link(media, link->source, link->sink, flags);
}
@@ -610,4 +634,3 @@ int media_parse_setup_links(struct media_device *media, const char *p)
return *end ? -EINVAL : 0;
}
-
diff --git a/src/mediactl.h b/src/mediactl.h
index 98b47fd..c6bf723 100644
--- a/src/mediactl.h
+++ b/src/mediactl.h
@@ -54,9 +54,50 @@ struct media_device {
int fd;
struct media_entity *entities;
unsigned int entities_count;
+ void (*debug_handler)(void *, ...);
+ void *debug_priv;
__u32 padding[6];
};
+#define media_dbg(media, ...) \
+ (media)->debug_handler((media)->debug_priv, __VA_ARGS__)
+
+/**
+ * @brief Set a handler for debug messages.
+ * @param media - device instance.
+ * @param debug_handler - debug message handler
+ * @param debug_priv - first argument to debug message handler
+ *
+ * Set a handler for debug messages that will be called whenever
+ * debugging information is to be printed. The handler expects an
+ * fprintf-like function.
+ */
+void media_debug_set_handler(
+ struct media_device *media, void (*debug_handler)(void *, ...),
+ void *debug_priv);
+
+/**
+ * @brief Open a media device with debugging enabled.
+ * @param name - name (including path) of the device node.
+ * @param verbose - whether to print verbose information on the standard output.
+ * @param debug_handler - debug message handler
+ * @param debug_priv - first argument to debug message handler
+ *
+ * Open the media device referenced by @a name and enumerate entities, pads and
+ * links.
+ *
+ * Calling media_open_debug() instead of media_open() is equivalent to
+ * media_open() and media_debug_set_handler() except that debugging is
+ * also enabled during media_open().
+ *
+ * @return A pointer to a newly allocated media_device structure instance on
+ * success and NULL on failure. The returned pointer must be freed with
+ * media_close when the device isn't needed anymore.
+ */
+struct media_device *media_open_debug(
+ const char *name, int verbose, void (*debug_handler)(void *, ...),
+ void *debug_priv);
+
/**
* @brief Open a media device.
* @param name - name (including path) of the device node.
diff --git a/src/v4l2subdev.c b/src/v4l2subdev.c
index 80365e6..5759948 100644
--- a/src/v4l2subdev.c
+++ b/src/v4l2subdev.c
@@ -40,8 +40,9 @@ int v4l2_subdev_open(struct media_entity *entity)
entity->fd = open(entity->devname, O_RDWR);
if (entity->fd == -1) {
- printf("%s: Failed to open subdev device node %s\n", __func__,
- entity->devname);
+ media_dbg(entity->media,
+ "%s: Failed to open subdev device node %s\n", __func__,
+ entity->devname);
return -errno;
}
@@ -329,21 +330,25 @@ static int set_format(struct media_pad *pad,
if (format->width == 0 || format->height == 0)
return 0;
- printf("Setting up format %s %ux%u on pad %s/%u\n",
- v4l2_subdev_pixelcode_to_string(format->code),
- format->width, format->height,
- pad->entity->info.name, pad->index);
+ media_dbg(pad->entity->media,
+ "Setting up format %s %ux%u on pad %s/%u\n",
+ v4l2_subdev_pixelcode_to_string(format->code),
+ format->width, format->height,
+ pad->entity->info.name, pad->index);
ret = v4l2_subdev_set_format(pad->entity, format, pad->index,
V4L2_SUBDEV_FORMAT_ACTIVE);
if (ret < 0) {
- printf("Unable to set format: %s (%d)\n", strerror(-ret), ret);
+ media_dbg(pad->entity->media,
+ "Unable to set format: %s (%d)\n",
+ strerror(-ret), ret);
return ret;
}
- printf("Format set: %s %ux%u\n",
- v4l2_subdev_pixelcode_to_string(format->code),
- format->width, format->height);
+ media_dbg(pad->entity->media,
+ "Format set: %s %ux%u\n",
+ v4l2_subdev_pixelcode_to_string(format->code),
+ format->width, format->height);
return 0;
}
@@ -355,19 +360,23 @@ static int set_crop(struct media_pad *pad, struct v4l2_rect *crop)
if (crop->left == -1 || crop->top == -1)
return 0;
- printf("Setting up crop rectangle (%u,%u)/%ux%u on pad %s/%u\n",
- crop->left, crop->top, crop->width, crop->height,
- pad->entity->info.name, pad->index);
+ media_dbg(pad->entity->media,
+ "Setting up crop rectangle (%u,%u)/%ux%u on pad %s/%u\n",
+ crop->left, crop->top, crop->width, crop->height,
+ pad->entity->info.name, pad->index);
ret = v4l2_subdev_set_crop(pad->entity, crop, pad->index,
V4L2_SUBDEV_FORMAT_ACTIVE);
if (ret < 0) {
- printf("Unable to set crop rectangle: %s (%d)\n", strerror(-ret), ret);
+ media_dbg(pad->entity->media,
+ "Unable to set crop rectangle: %s (%d)\n",
+ strerror(-ret), ret);
return ret;
}
- printf("Crop rectangle set: (%u,%u)/%ux%u\n",
- crop->left, crop->top, crop->width, crop->height);
+ media_dbg(pad->entity->media,
+ "Crop rectangle set: (%u,%u)/%ux%u\n",
+ crop->left, crop->top, crop->width, crop->height);
return 0;
}
@@ -380,17 +389,21 @@ static int set_frame_interval(struct media_entity *entity,
if (interval->numerator == 0)
return 0;
- printf("Setting up frame interval %u/%u on entity %s\n",
- interval->numerator, interval->denominator, entity->info.name);
+ media_dbg(entity->media,
+ "Setting up frame interval %u/%u on entity %s\n",
+ interval->numerator, interval->denominator,
+ entity->info.name);
ret = v4l2_subdev_set_frame_interval(entity, interval);
if (ret < 0) {
- printf("Unable to set frame interval: %s (%d)", strerror(-ret), ret);
+ media_dbg(entity->media,
+ "Unable to set frame interval: %s (%d)",
+ strerror(-ret), ret);
return ret;
}
- printf("Frame interval set: %u/%u\n",
- interval->numerator, interval->denominator);
+ media_dbg(entity->media, "Frame interval set: %u/%u\n",
+ interval->numerator, interval->denominator);
return 0;
}
@@ -410,7 +423,7 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media,
pad = v4l2_subdev_parse_pad_format(media, &format, &crop, &interval,
p, &end);
if (pad == NULL) {
- printf("Unable to parse format\n");
+ media_dbg(media, "Unable to parse format\n");
return -EINVAL;
}
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread* [media-ctl PATCH 7/7] Remove extra verbosity
2011-10-07 15:34 [media-ctl PATCH 0/7] Move functionality to libraries, debug changes Sakari Ailus
` (5 preceding siblings ...)
2011-10-07 15:38 ` [media-ctl PATCH 6/7] Add debugging handler Sakari Ailus
@ 2011-10-07 15:38 ` Sakari Ailus
6 siblings, 0 replies; 10+ messages in thread
From: Sakari Ailus @ 2011-10-07 15:38 UTC (permalink / raw)
To: linux-media; +Cc: laurent.pinchart
Remove extra verbosity by default; "-v" option brings back what used to be
there. The error messages are now being printed by main.c with the possibly
helpful error code attached.
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
src/main.c | 48 ++++++++++++++++++++++++++++++++++++++----------
src/mediactl.c | 21 ++++++++++-----------
src/mediactl.h | 6 ++----
3 files changed, 50 insertions(+), 25 deletions(-)
diff --git a/src/main.c b/src/main.c
index 40ab13e..57bbc16 100644
--- a/src/main.c
+++ b/src/main.c
@@ -288,10 +288,16 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
/* Open the media device and enumerate entities, pads and links. */
- media = media_open_debug(media_opts.devname, media_opts.verbose,
- (void (*)(void *, ...))fprintf, stdout);
- if (media == NULL)
+ if (media_opts.verbose)
+ media = media_open_debug(
+ media_opts.devname,
+ (void (*)(void *, ...))fprintf, stdout);
+ else
+ media = media_open(media_opts.devname);
+ if (media == NULL) {
+ printf("Failed to open %s\n", media_opts.devname);
goto out;
+ }
if (media_opts.entity) {
struct media_entity *entity;
@@ -326,15 +332,34 @@ int main(int argc, char **argv)
}
if (media_opts.reset) {
- printf("Resetting all links to inactive\n");
- media_reset_links(media);
+ if (media_opts.verbose)
+ printf("Resetting all links to inactive\n");
+ ret = media_reset_links(media);
+ if (ret) {
+ printf("Unable to reset links: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto out;
+ }
}
- if (media_opts.links)
- media_parse_setup_links(media, media_opts.links);
+ if (media_opts.links) {
+ ret = media_parse_setup_links(media, media_opts.links);
+ if (ret) {
+ printf("Unable to parse link: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto out;
+ }
+ }
- if (media_opts.formats)
- v4l2_subdev_parse_setup_formats(media, media_opts.formats);
+ if (media_opts.formats) {
+ ret = v4l2_subdev_parse_setup_formats(media,
+ media_opts.formats);
+ if (ret) {
+ printf("Unable to parse format: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto out;
+ }
+ }
if (media_opts.interactive) {
while (1) {
@@ -348,7 +373,10 @@ int main(int argc, char **argv)
if (buffer[0] == '\n')
break;
- media_parse_setup_link(media, buffer, &end);
+ ret = media_parse_setup_link(media, buffer, &end);
+ if (ret)
+ printf("Unable to parse link: %s (%d)\n",
+ strerror(-ret), -ret);
}
}
diff --git a/src/mediactl.c b/src/mediactl.c
index 43d1b6a..b9c2a10 100644
--- a/src/mediactl.c
+++ b/src/mediactl.c
@@ -270,7 +270,7 @@ static inline void media_udev_close(struct udev *udev)
}
static int media_get_devname_udev(struct udev *udev,
- struct media_entity *entity, int verbose)
+ struct media_entity *entity)
{
struct udev_device *device;
dev_t devnum;
@@ -281,9 +281,8 @@ static int media_get_devname_udev(struct udev *udev,
return -EINVAL;
devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
- if (verbose)
- media_dbg(entity->media, "looking up device: %u:%u\n",
- major(devnum), minor(devnum));
+ media_dbg(entity->media, "looking up device: %u:%u\n",
+ major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
if (device) {
p = udev_device_get_devnode(device);
@@ -308,7 +307,7 @@ static inline int media_udev_open(struct udev **udev) { return 0; }
static inline void media_udev_close(struct udev *udev) { }
static inline int media_get_devname_udev(struct udev *udev,
- struct media_entity *entity, int verbose)
+ struct media_entity *entity)
{
return -ENOTSUP;
}
@@ -351,7 +350,7 @@ static int media_get_devname_sysfs(struct media_entity *entity)
return 0;
}
-static int media_enum_entities(struct media_device *media, int verbose)
+static int media_enum_entities(struct media_device *media)
{
struct media_entity *entity;
struct udev *udev;
@@ -400,7 +399,7 @@ static int media_enum_entities(struct media_device *media, int verbose)
continue;
/* Try to get the device name via udev */
- if (!media_get_devname_udev(udev, entity, verbose))
+ if (!media_get_devname_udev(udev, entity))
continue;
/* Fall back to get the device name via sysfs */
@@ -429,7 +428,7 @@ void media_debug_set_handler(struct media_device *media,
}
struct media_device *media_open_debug(
- const char *name, int verbose, void (*debug_handler)(void *, ...),
+ const char *name, void (*debug_handler)(void *, ...),
void *debug_priv)
{
struct media_device *media;
@@ -453,7 +452,7 @@ struct media_device *media_open_debug(
media_dbg(media, "Enumerating entities\n");
- ret = media_enum_entities(media, verbose);
+ ret = media_enum_entities(media);
if (ret < 0) {
media_dbg(media,
@@ -478,9 +477,9 @@ struct media_device *media_open_debug(
return media;
}
-struct media_device *media_open(const char *name, int verbose)
+struct media_device *media_open(const char *name)
{
- return media_open_debug(name, verbose, NULL, NULL);
+ return media_open_debug(name, NULL, NULL);
}
void media_close(struct media_device *media)
diff --git a/src/mediactl.h b/src/mediactl.h
index c6bf723..5fdd078 100644
--- a/src/mediactl.h
+++ b/src/mediactl.h
@@ -79,7 +79,6 @@ void media_debug_set_handler(
/**
* @brief Open a media device with debugging enabled.
* @param name - name (including path) of the device node.
- * @param verbose - whether to print verbose information on the standard output.
* @param debug_handler - debug message handler
* @param debug_priv - first argument to debug message handler
*
@@ -95,13 +94,12 @@ void media_debug_set_handler(
* media_close when the device isn't needed anymore.
*/
struct media_device *media_open_debug(
- const char *name, int verbose, void (*debug_handler)(void *, ...),
+ const char *name, void (*debug_handler)(void *, ...),
void *debug_priv);
/**
* @brief Open a media device.
* @param name - name (including path) of the device node.
- * @param verbose - whether to print verbose information on the standard output.
*
* Open the media device referenced by @a name and enumerate entities, pads and
* links.
@@ -110,7 +108,7 @@ struct media_device *media_open_debug(
* success and NULL on failure. The returned pointer must be freed with
* media_close when the device isn't needed anymore.
*/
-struct media_device *media_open(const char *name, int verbose);
+struct media_device *media_open(const char *name);
/**
* @brief Close a media device.
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread