From 67cc5f8c2cdc361204cb5d71fc4a48c344fe95f1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 30 Jul 2012 16:40:42 +0200 Subject: Initial version of the libmediadev library Signed-off-by: Laurent Pinchart --- main.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 main.c (limited to 'main.c') diff --git a/main.c b/main.c new file mode 100644 index 0000000..2fc63d0 --- /dev/null +++ b/main.c @@ -0,0 +1,289 @@ +/* + * Media device discovery library + * + * Copyright (C) 2012 Ideas on board SPRL + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include + +#include "media-enumerate.h" + +/* ----------------------------------------------------------------------------- + * Topology printing - copied from mediactl + */ + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +static void v4l2_subdev_print_format(struct media_entity *entity, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + struct v4l2_mbus_framefmt format; + struct v4l2_rect rect; + int ret; + + ret = v4l2_subdev_get_format(entity, &format, pad, which); + if (ret != 0) + return; + + printf("\t\t[fmt:%s/%ux%u", + v4l2_subdev_pixelcode_to_string(format.code), + format.width, format.height); + + ret = v4l2_subdev_get_selection(entity, &rect, pad, + V4L2_SEL_TGT_CROP_BOUNDS, + which); + if (ret == 0) + printf("\n\t\t crop.bounds:(%u,%u)/%ux%u", rect.left, rect.top, + rect.width, rect.height); + + ret = v4l2_subdev_get_selection(entity, &rect, pad, + V4L2_SEL_TGT_CROP, + which); + if (ret == 0) + printf("\n\t\t crop:(%u,%u)/%ux%u", rect.left, rect.top, + rect.width, rect.height); + + ret = v4l2_subdev_get_selection(entity, &rect, pad, + V4L2_SEL_TGT_COMPOSE_BOUNDS, + which); + if (ret == 0) + printf("\n\t\t compose.bounds:(%u,%u)/%ux%u", + rect.left, rect.top, rect.width, rect.height); + + ret = v4l2_subdev_get_selection(entity, &rect, pad, + V4L2_SEL_TGT_COMPOSE, + which); + if (ret == 0) + printf("\n\t\t compose:(%u,%u)/%ux%u", + rect.left, rect.top, rect.width, rect.height); + + printf("]\n"); +} + +static const char *media_entity_type_to_string(unsigned type) +{ + static const struct { + __u32 type; + const char *name; + } types[] = { + { MEDIA_ENT_T_DEVNODE, "Node" }, + { MEDIA_ENT_T_V4L2_SUBDEV, "V4L2 subdev" }, + }; + + unsigned int i; + + type &= MEDIA_ENT_TYPE_MASK; + + for (i = 0; i < ARRAY_SIZE(types); i++) { + if (types[i].type == type) + return types[i].name; + } + + return "Unknown"; +} + +static const char *media_entity_subtype_to_string(unsigned type) +{ + static const char *node_types[] = { + "Unknown", + "V4L", + "FB", + "ALSA", + "DVB", + }; + static const char *subdev_types[] = { + "Unknown", + "Sensor", + "Flash", + "Lens", + }; + + unsigned int subtype = type & MEDIA_ENT_SUBTYPE_MASK; + + switch (type & MEDIA_ENT_TYPE_MASK) { + case MEDIA_ENT_T_DEVNODE: + if (subtype >= ARRAY_SIZE(node_types)) + subtype = 0; + return node_types[subtype]; + + case MEDIA_ENT_T_V4L2_SUBDEV: + if (subtype >= ARRAY_SIZE(subdev_types)) + subtype = 0; + return subdev_types[subtype]; + default: + return node_types[0]; + } +} + +static const char *media_pad_type_to_string(unsigned flag) +{ + static const struct { + __u32 flag; + const char *name; + } flags[] = { + { MEDIA_PAD_FL_SINK, "Sink" }, + { MEDIA_PAD_FL_SOURCE, "Source" }, + }; + + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(flags); i++) { + if (flags[i].flag & flag) + return flags[i].name; + } + + return "Unknown"; +} + +static void media_print_topology_text(struct media_device *media) +{ + static const struct { + __u32 flag; + char *name; + } link_flags[] = { + { MEDIA_LNK_FL_ENABLED, "ENABLED" }, + { MEDIA_LNK_FL_IMMUTABLE, "IMMUTABLE" }, + { MEDIA_LNK_FL_DYNAMIC, "DYNAMIC" }, + }; + + struct media_entity *entities = media_get_entities(media); + unsigned int nents = media_get_entities_count(media); + unsigned int i, j, k; + unsigned int padding; + + printf("Device topology\n"); + + for (i = 0; i < nents; ++i) { + struct media_entity *entity = &entities[i]; + + padding = printf("- entity %u: ", entity->info.id); + printf("%s (%u pad%s, %u link%s)\n", entity->info.name, + entity->info.pads, entity->info.pads > 1 ? "s" : "", + entity->num_links, entity->num_links > 1 ? "s" : ""); + printf("%*ctype %s subtype %s flags %x\n", padding, ' ', + media_entity_type_to_string(entity->info.type), + media_entity_subtype_to_string(entity->info.type), + entity->info.flags); + if (entity->devname[0]) + printf("%*cdevice node name %s\n", padding, ' ', entity->devname); + + for (j = 0; j < entity->info.pads; j++) { + struct media_pad *pad = &entity->pads[j]; + + printf("\tpad%u: %s\n", j, media_pad_type_to_string(pad->flags)); + + if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV) + v4l2_subdev_print_format(entity, j, V4L2_SUBDEV_FORMAT_ACTIVE); + + for (k = 0; k < entity->num_links; k++) { + struct media_link *link = &entity->links[k]; + struct media_pad *source = link->source; + struct media_pad *sink = link->sink; + bool first = true; + unsigned int i; + + if (source->entity == entity && source->index == j) + printf("\t\t-> \"%s\":%u [", + sink->entity->info.name, sink->index); + else if (sink->entity == entity && sink->index == j) + printf("\t\t<- \"%s\":%u [", + source->entity->info.name, source->index); + else + continue; + + for (i = 0; i < ARRAY_SIZE(link_flags); i++) { + if (!(link->flags & link_flags[i].flag)) + continue; + if (!first) + printf(","); + printf("%s", link_flags[i].name); + first = false; + } + + printf("]\n"); + } + } + printf("\n"); + } +} + +/* ----------------------------------------------------------------------------- + * Printing + */ + +int main(int argc, char *argv[]) +{ + struct media_enumerate *media_enum; + struct media_device **devices; + unsigned int n_devs; + unsigned int i; + int ret; + + media_enum = media_enumerate_new(); + if (media_enum == NULL) { + printf("Unable to create enumeration context\n"); + return EXIT_FAILURE; + } + + ret = media_enumerate_scan(media_enum); + if (ret < 0) { + goto done; + printf("Unable to enumerate media devices (%d)\n", ret); + } + + n_devs = media_enumerate_get_devices_count(media_enum); + if (n_devs == 0) { + printf("No devices found\n"); + goto done; + } + + devices = media_enumerate_get_devices(media_enum); + for (i = 0; i < n_devs; ++i) { + const struct media_device_info *info = media_get_info(devices[i]); + + printf("Media controller API version %u.%u.%u\n\n", + (info->media_version << 16) & 0xff, + (info->media_version << 8) & 0xff, + (info->media_version << 0) & 0xff); + printf("Media device information\n" + "------------------------\n" + "driver %s\n" + "model %s\n" + "serial %s\n" + "bus info %s\n" + "hw revision 0x%x\n" + "driver version %u.%u.%u\n\n", + info->driver, info->model, + info->serial, info->bus_info, + info->hw_revision, + (info->driver_version << 16) & 0xff, + (info->driver_version << 8) & 0xff, + (info->driver_version << 0) & 0xff); + + media_print_topology_text(devices[i]); + } + +done: + media_enumerate_unref(media_enum); + return EXIT_SUCCESS; +} -- cgit v1.2.3