diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2018-08-02 18:53:15 +0200 |
---|---|---|
committer | Hans Verkuil <hverkuil@xs4all.nl> | 2018-11-21 16:25:47 +0100 |
commit | 9e3997b51d57108a23fdb33657be27b9acfd5a4d (patch) | |
tree | f089a7adfd0cb1e37d4f26fb8b6e82d9e0f9ba70 | |
parent | 45a0c5565f164a29f5c72c1a808f97a8a8e0e595 (diff) |
adds props APIprops
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r-- | utils/common/media-info.cpp | 117 | ||||
-rw-r--r-- | utils/common/media-info.h | 3 | ||||
-rw-r--r-- | utils/v4l2-compliance/v4l2-compliance.cpp | 5 | ||||
-rw-r--r-- | utils/v4l2-compliance/v4l2-test-media.cpp | 132 |
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] = ∝ + } + for (unsigned i = 0; i < topology.num_entities; i++) { media_v2_entity &ent = v2_ents[i]; |