aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2018-08-02 18:53:15 +0200
committerHans Verkuil <hverkuil@xs4all.nl>2018-11-21 16:25:47 +0100
commit9e3997b51d57108a23fdb33657be27b9acfd5a4d (patch)
treef089a7adfd0cb1e37d4f26fb8b6e82d9e0f9ba70
parent45a0c5565f164a29f5c72c1a808f97a8a8e0e595 (diff)
adds props APIprops
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r--utils/common/media-info.cpp117
-rw-r--r--utils/common/media-info.h3
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.cpp5
-rw-r--r--utils/v4l2-compliance/v4l2-test-media.cpp132
4 files changed, 252 insertions, 5 deletions
diff --git a/utils/common/media-info.cpp b/utils/common/media-info.cpp
index 8eacfe06..89e51d2e 100644
--- a/utils/common/media-info.cpp
+++ b/utils/common/media-info.cpp
@@ -234,6 +234,8 @@ int mi_get_media_fd(int fd)
static const flag_def entity_flags_def[] = {
{ MEDIA_ENT_FL_DEFAULT, "default" },
{ MEDIA_ENT_FL_CONNECTOR, "connector" },
+ { MEDIA_ENT_FL_PAD_IDX, "pad-idx" },
+ { MEDIA_ENT_FL_PROP_IDX, "prop-idx" },
{ 0, NULL }
};
@@ -373,6 +375,9 @@ static const flag_def pad_flags_def[] = {
{ MEDIA_PAD_FL_SINK, "Sink" },
{ MEDIA_PAD_FL_SOURCE, "Source" },
{ MEDIA_PAD_FL_MUST_CONNECT, "Must Connect" },
+ { MEDIA_PAD_FL_LINK_IDX, "link-idx" },
+ { MEDIA_PAD_FL_ENTITY_IDX, "entity-idx" },
+ { MEDIA_PAD_FL_PROP_IDX, "prop-idx" },
{ 0, NULL }
};
@@ -385,6 +390,8 @@ static const flag_def link_flags_def[] = {
{ MEDIA_LNK_FL_ENABLED, "Enabled" },
{ MEDIA_LNK_FL_IMMUTABLE, "Immutable" },
{ MEDIA_LNK_FL_DYNAMIC, "Dynamic" },
+ { MEDIA_LNK_FL_SOURCE_IDX, "source-idx" },
+ { MEDIA_LNK_FL_SINK_IDX, "sink-idx" },
{ 0, NULL }
};
@@ -404,6 +411,63 @@ std::string mi_linkflags2s(__u32 flags)
}
}
+static const flag_def prop_flags_def[] = {
+ { MEDIA_PROP_FL_PROP_IDX, "prop-idx" },
+ { 0, NULL }
+};
+
+std::string mi_propflags2s(__u32 flags)
+{
+ std::string s = flags2s(flags & ~MEDIA_PROP_FL_OWNER, prop_flags_def);
+
+ if (!s.empty())
+ s = ", " + s;
+ switch (flags & MEDIA_PROP_FL_OWNER) {
+ case MEDIA_PROP_FL_ENTITY:
+ return "Entity" + s;
+ case MEDIA_PROP_FL_PAD:
+ return "Pad" + s;
+ case MEDIA_PROP_FL_LINK:
+ return "Link" + s;
+ case MEDIA_PROP_FL_INTF:
+ return "Interface" + s;
+ case MEDIA_PROP_FL_PROP:
+ return "Property" + s;
+ default:
+ return "Unknown (" + num2s(flags) + ")" + s;
+ }
+}
+
+static void show_props(const media_v2_prop *props,
+ const media_v2_prop &prop, std::string prefix)
+{
+ if (!(prop.flags & MEDIA_PROP_FL_PROP_IDX))
+ return;
+ __u16 idx = prop.prop_idx;
+ while (props[idx].owner_id == prop.id) {
+ printf("%sProperty 0x%08x '%s'", prefix.c_str(), props[idx].id, props[idx].name);
+ switch (props[idx].type) {
+ case MEDIA_PROP_TYPE_U64:
+ printf(": 0x%016llx %llu\n", media_prop2u64(props + idx),
+ media_prop2u64(props + idx));
+ break;
+ case MEDIA_PROP_TYPE_S64:
+ printf(": 0x%016llx %lld\n", media_prop2s64(props + idx),
+ media_prop2s64(props + idx));
+ break;
+ case MEDIA_PROP_TYPE_STRING:
+ printf(": '%s'\n", media_prop2s(props + idx));
+ break;
+ case MEDIA_PROP_TYPE_GROUP:
+ printf(" {\n");
+ show_props(props, props[idx], prefix + "\t");
+ printf("%s}\n", prefix.c_str());
+ break;
+ }
+ idx++;
+ }
+}
+
static __u32 read_topology(int media_fd, __u32 major, __u32 minor,
__u32 media_version, bool *is_invalid)
{
@@ -411,19 +475,25 @@ static __u32 read_topology(int media_fd, __u32 major, __u32 minor,
unsigned i, j;
memset(&topology, 0, sizeof(topology));
- if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology))
+ if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) &&
+ ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY_OLD, &topology))
return 0;
media_v2_entity v2_ents[topology.num_entities];
media_v2_interface v2_ifaces[topology.num_interfaces];
media_v2_pad v2_pads[topology.num_pads];
media_v2_link v2_links[topology.num_links];
+ __u8 props[topology.num_props * sizeof(media_v2_prop) +
+ topology.props_payload_size];
+ media_v2_prop *v2_props = (media_v2_prop *)props;
topology.ptr_entities = (__u64)v2_ents;
topology.ptr_interfaces = (__u64)v2_ifaces;
topology.ptr_pads = (__u64)v2_pads;
topology.ptr_links = (__u64)v2_links;
- if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology))
+ topology.ptr_props = (__u64)v2_props;
+ if (ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) &&
+ ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY_OLD, &topology))
return 0;
for (i = 0; i < topology.num_interfaces; i++)
if (v2_ifaces[i].devnode.major == major &&
@@ -530,6 +600,49 @@ static __u32 read_topology(int media_fd, __u32 major, __u32 minor,
remote_ent->name, mi_linkflags2s(link.flags).c_str());
}
}
+
+ for (i = 0; i < topology.num_props; i++) {
+ media_v2_prop &prop = v2_props[i];
+ media_v2_entity *ent_ptr = NULL;
+ media_v2_pad *pad_ptr = NULL;
+
+ if (prop.owner_id == ent.id) {
+ ent_ptr = &ent;
+ } else {
+ for (unsigned j = 0; j < topology.num_pads; j++) {
+ if (prop.owner_id == v2_pads[j].id) {
+ pad_ptr = &v2_pads[j];
+ break;
+ }
+ }
+ if (pad_ptr && pad_ptr->entity_id != ent.id)
+ pad_ptr = NULL;
+ }
+ if (!ent_ptr && !pad_ptr)
+ continue;
+
+ printf("\tProperty 0x%08x '%s'", prop.id, prop.name);
+ if (pad_ptr)
+ printf(" (pad 0x%08x)", prop.owner_id);
+ switch (prop.type) {
+ case MEDIA_PROP_TYPE_U64:
+ printf(": 0x%016llx %llu\n", media_prop2u64(&prop),
+ media_prop2u64(&prop));
+ break;
+ case MEDIA_PROP_TYPE_S64:
+ printf(": 0x%016llx %lld\n", media_prop2s64(&prop),
+ media_prop2s64(&prop));
+ break;
+ case MEDIA_PROP_TYPE_STRING:
+ printf(": '%s'\n", media_prop2s(&prop));
+ break;
+ case MEDIA_PROP_TYPE_GROUP:
+ printf(" {\n");
+ show_props(v2_props, prop, "\t\t");
+ printf("\t}\n");
+ break;
+ }
+ }
return ent.id;
}
diff --git a/utils/common/media-info.h b/utils/common/media-info.h
index 97c3d382..5b5da9ab 100644
--- a/utils/common/media-info.h
+++ b/utils/common/media-info.h
@@ -71,6 +71,9 @@ std::string mi_padflags2s(__u32 flags);
/* Return link flags description */
std::string mi_linkflags2s(__u32 flags);
+/* Return property flags description */
+std::string mi_propflags2s(__u32 flags);
+
/*
* Show media controller information media_fd and (if >= 0) the
* corresponsing entity/interface information for the fd.
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
index 1fb51721..f8f747a0 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -830,11 +830,12 @@ void testNode(struct node &node, struct node &expbuf_node, media_type type,
printf("Media Controller ioctls:\n");
printf("\ttest MEDIA_IOC_G_TOPOLOGY: %s\n", ok(testMediaTopology(&node)));
if (node.topology)
- printf("\tEntities: %u Interfaces: %u Pads: %u Links: %u\n",
+ printf("\tEntities: %u Interfaces: %u Pads: %u Links: %u Properties: %u\n",
node.topology->num_entities,
node.topology->num_interfaces,
node.topology->num_pads,
- node.topology->num_links);
+ node.topology->num_links,
+ node.topology->num_props);
printf("\ttest MEDIA_IOC_ENUM_ENTITIES/LINKS: %s\n", ok(testMediaEnum(&node)));
printf("\ttest MEDIA_IOC_SETUP_LINK: %s\n", ok(testMediaSetupLink(&node)));
printf("\n");
diff --git a/utils/v4l2-compliance/v4l2-test-media.cpp b/utils/v4l2-compliance/v4l2-test-media.cpp
index ae5f0c8b..4af3ee86 100644
--- a/utils/v4l2-compliance/v4l2-test-media.cpp
+++ b/utils/v4l2-compliance/v4l2-test-media.cpp
@@ -79,12 +79,15 @@ static media_v2_pad *v2_pads;
static id_set v2_pads_set;
static media_v2_link *v2_links;
static id_set v2_links_set;
+static media_v2_prop *v2_props;
+static id_set v2_props_set;
static std::map<__u32, __u32> entity_num_pads;
static std::map<__u32, media_v2_entity *> v2_entity_map;
static std::set<std::string> v2_entity_names_set;
static std::map<__u32, media_v2_interface *> v2_iface_map;
static std::map<__u32, media_v2_pad *> v2_pad_map;
static std::set<__u64> v2_entity_pad_idx_set;
+static std::map<__u32, media_v2_prop *> v2_prop_map;
static unsigned num_data_links;
static int checkFunction(__u32 function, bool v2_api)
@@ -111,13 +114,25 @@ int testMediaTopology(struct node *node)
topology.ptr_interfaces = 0;
topology.ptr_pads = 0;
topology.ptr_links = 0;
+ fail_on_test(doioctl(node, MEDIA_IOC_G_TOPOLOGY_OLD, &topology));
+ fail_on_test(topology.ptr_props != ~0ULL);
+
+ memset(&topology, 0xff, sizeof(topology));
+ topology.ptr_entities = 0;
+ topology.ptr_interfaces = 0;
+ topology.ptr_pads = 0;
+ topology.ptr_links = 0;
+ topology.ptr_props = 0;
fail_on_test(doioctl(node, MEDIA_IOC_G_TOPOLOGY, &topology));
+
fail_on_test(!topology.num_entities);
fail_on_test(topology.topology_version == ~0ULL);
fail_on_test(topology.num_entities == ~0U);
fail_on_test(topology.num_interfaces == ~0U);
fail_on_test(topology.num_pads == ~0U);
fail_on_test(topology.num_links == ~0U);
+ fail_on_test(topology.num_props == ~0U);
+ fail_on_test(topology.props_payload_size == ~0U);
fail_on_test(topology.reserved1);
fail_on_test(topology.reserved2);
fail_on_test(topology.reserved3);
@@ -137,6 +152,10 @@ int testMediaTopology(struct node *node)
fail_on_test(topology.num_links &&
doioctl(node, MEDIA_IOC_G_TOPOLOGY, &topology) != EFAULT);
topology.ptr_links = 0;
+ topology.ptr_props = 4;
+ fail_on_test(topology.num_props &&
+ doioctl(node, MEDIA_IOC_G_TOPOLOGY, &topology) != EFAULT);
+ topology.ptr_props = 0;
v2_ents = new media_v2_entity[topology.num_entities];
memset(v2_ents, 0xff, topology.num_entities * sizeof(*v2_ents));
topology.ptr_entities = (__u64)v2_ents;
@@ -149,11 +168,18 @@ int testMediaTopology(struct node *node)
v2_links = new media_v2_link[topology.num_links];
memset(v2_links, 0xff, topology.num_links * sizeof(*v2_links));
topology.ptr_links = (__u64)v2_links;
+ __u8 *props = new __u8[topology.num_props * sizeof(media_v2_prop) +
+ topology.props_payload_size];
+ memset(props, 0xff, topology.num_props * sizeof(media_v2_prop) +
+ topology.props_payload_size);
+ v2_props = (media_v2_prop *)props;
+ topology.ptr_props = (__u64)v2_props;
fail_on_test(doioctl(node, MEDIA_IOC_G_TOPOLOGY, &topology));
fail_on_test(v2_ents != (media_v2_entity *)topology.ptr_entities);
fail_on_test(v2_ifaces != (media_v2_interface *)topology.ptr_interfaces);
fail_on_test(v2_pads != (media_v2_pad *)topology.ptr_pads);
fail_on_test(v2_links != (media_v2_link *)topology.ptr_links);
+ fail_on_test(v2_props != (media_v2_prop *)topology.ptr_props);
for (unsigned i = 0; i < topology.num_entities; i++) {
media_v2_entity &ent = v2_ents[i];
@@ -173,6 +199,10 @@ int testMediaTopology(struct node *node)
fail_on_test(v2_entity_names_set.find(ent.name) != v2_entity_names_set.end());
if (!MEDIA_V2_ENTITY_HAS_FLAGS(node->media_version))
fail_on_test(ent.flags);
+ if (ent.flags & MEDIA_ENT_FL_PAD_IDX)
+ fail_on_test(v2_pads[ent.pad_idx].entity_id != ent.id);
+ if (ent.flags & MEDIA_ENT_FL_PROP_IDX)
+ fail_on_test(v2_props[ent.prop_idx].owner_id != ent.id);
v2_entities_set.insert(ent.id);
v2_entity_names_set.insert(ent.name);
v2_entity_map[ent.id] = &ent;
@@ -194,7 +224,9 @@ int testMediaTopology(struct node *node)
fail_on_test(!iface.intf_type);
fail_on_test(iface.intf_type < MEDIA_INTF_T_DVB_BASE);
fail_on_test(iface.intf_type > MEDIA_INTF_T_V4L_BASE + 0xff);
- fail_on_test(iface.flags);
+ fail_on_test(iface.flags & ~MEDIA_INTF_FL_LINK_IDX);
+ if (iface.flags & MEDIA_INTF_FL_LINK_IDX)
+ fail_on_test(v2_links[iface.link_idx].source_id != iface.id);
fail_on_test(v2_interfaces_set.find(iface.id) != v2_interfaces_set.end());
v2_interfaces_set.insert(iface.id);
v2_iface_map[iface.id] = &iface;
@@ -228,6 +260,12 @@ int testMediaTopology(struct node *node)
} else {
fail_on_test(pad.index);
}
+ if (fl & MEDIA_PAD_FL_ENTITY_IDX)
+ fail_on_test(v2_ents[pad.entity_idx].id != pad.entity_id);
+ if (fl & MEDIA_PAD_FL_LINK_IDX)
+ fail_on_test(v2_links[pad.link_idx].source_id != pad.id);
+ if (fl & MEDIA_PAD_FL_PROP_IDX)
+ fail_on_test(v2_props[pad.prop_idx].owner_id != pad.id);
entity_num_pads[pad.entity_id]++;
v2_pad_map[pad.id] = &pad;
}
@@ -247,6 +285,10 @@ int testMediaTopology(struct node *node)
if (is_iface) {
fail_on_test(v2_interfaces_set.find(link.source_id) == v2_interfaces_set.end());
fail_on_test(v2_entities_set.find(link.sink_id) == v2_entities_set.end());
+ if (link.flags & MEDIA_LNK_FL_SOURCE_IDX)
+ fail_on_test(v2_ifaces[link.source_idx].id != link.source_id);
+ if (link.flags & MEDIA_LNK_FL_SINK_IDX)
+ fail_on_test(v2_ents[link.sink_idx].id != link.sink_id);
media_v2_interface &iface = *v2_iface_map[link.source_id];
dev_t dev = makedev(iface.devnode.major, iface.devnode.minor);
@@ -261,6 +303,10 @@ int testMediaTopology(struct node *node)
fail_on_test(v2_pads_set.find(link.source_id) == v2_pads_set.end());
fail_on_test(v2_pads_set.find(link.sink_id) == v2_pads_set.end());
fail_on_test(link.source_id == link.sink_id);
+ if (link.flags & MEDIA_LNK_FL_SOURCE_IDX)
+ fail_on_test(v2_pads[link.source_idx].id != link.source_id);
+ if (link.flags & MEDIA_LNK_FL_SINK_IDX)
+ fail_on_test(v2_pads[link.sink_idx].id != link.sink_id);
num_data_links++;
if (show_info)
printf("\t\tLink: 0x%08x (%s -> %s, %s)\n", link.id,
@@ -270,6 +316,90 @@ int testMediaTopology(struct node *node)
}
}
+ for (unsigned i = 0; i < topology.num_props; i++) {
+ media_v2_prop &prop = v2_props[i];
+
+ if (show_info) {
+ printf("\t\tProperty: 0x%08x '%s' (Owner: 0x%08x): ",
+ prop.id, prop.name, prop.owner_id);
+ switch (prop.type) {
+ case MEDIA_PROP_TYPE_GROUP:
+ printf("group\n");
+ break;
+ case MEDIA_PROP_TYPE_U64:
+ printf("0x%016llx %llu\n", media_prop2u64(&prop),
+ media_prop2u64(&prop));
+ break;
+ case MEDIA_PROP_TYPE_S64:
+ printf("0x%016llx %lld\n", media_prop2s64(&prop),
+ media_prop2s64(&prop));
+ break;
+ case MEDIA_PROP_TYPE_STRING:
+ printf("'%s'\n", media_prop2s(&prop));
+ break;
+ }
+ }
+ fail_on_test(check_0(prop.reserved, sizeof(prop.reserved)));
+ fail_on_test(!prop.id);
+ fail_on_test(!prop.owner_id);
+ fail_on_test(v2_entities_set.find(prop.owner_id) == v2_entities_set.end() &&
+ v2_pads_set.find(prop.owner_id) == v2_pads_set.end() &&
+ v2_props_set.find(prop.owner_id) == v2_props_set.end());
+ if (prop.payload_size)
+ fail_on_test(!prop.payload_offset);
+ else
+ fail_on_test(prop.payload_offset);
+ if (prop.type == MEDIA_PROP_TYPE_GROUP) {
+ if (prop.flags & MEDIA_PROP_FL_PROP_IDX)
+ fail_on_test(!prop.prop_idx);
+ else
+ fail_on_test(prop.prop_idx);
+ } else {
+ fail_on_test(prop.prop_idx);
+ fail_on_test(prop.flags & ~MEDIA_PROP_FL_OWNER);
+ }
+ if (prop.flags & MEDIA_PROP_FL_PROP_IDX)
+ fail_on_test(v2_props[prop.prop_idx].owner_id != prop.id);
+
+ switch (prop.flags & MEDIA_PROP_FL_OWNER) {
+ case MEDIA_PROP_FL_ENTITY:
+ fail_on_test(v2_ents[prop.owner_idx].id != prop.owner_id);
+ break;
+ case MEDIA_PROP_FL_PAD:
+ fail_on_test(v2_pads[prop.owner_idx].id != prop.owner_id);
+ break;
+ case MEDIA_PROP_FL_LINK:
+ fail_on_test(v2_links[prop.owner_idx].id != prop.owner_id);
+ break;
+ case MEDIA_PROP_FL_INTF:
+ fail_on_test(v2_ifaces[prop.owner_idx].id != prop.owner_id);
+ break;
+ case MEDIA_PROP_FL_PROP:
+ fail_on_test(v2_props[prop.owner_idx].id != prop.owner_id);
+ break;
+ default:
+ return fail("unknown property owner");
+ }
+
+ switch (prop.type) {
+ case MEDIA_PROP_TYPE_GROUP:
+ fail_on_test(prop.payload_size);
+ break;
+ case MEDIA_PROP_TYPE_U64:
+ case MEDIA_PROP_TYPE_S64:
+ fail_on_test(prop.payload_size != 8);
+ break;
+ case MEDIA_PROP_TYPE_STRING:
+ fail_on_test(!prop.payload_size);
+ break;
+ default:
+ return fail("unknown property type\n");
+ }
+ fail_on_test(v2_props_set.find(prop.id) != v2_props_set.end());
+ v2_props_set.insert(prop.id);
+ v2_prop_map[prop.id] = &prop;
+ }
+
for (unsigned i = 0; i < topology.num_entities; i++) {
media_v2_entity &ent = v2_ents[i];

Privacy Policy