/* * Legacy defines from linux/media.h. This is the only place we need this * so we just define it here. The media.h header doesn't expose it to the * kernel to prevent it from being used by drivers, but here (and only here!) * we need it to handle the legacy behavior.
*/ #define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff #define MEDIA_ENT_T_DEVNODE_UNKNOWN (MEDIA_ENT_F_OLD_BASE | \
MEDIA_ENT_SUBTYPE_MASK)
/* ----------------------------------------------------------------------------- * Userspace API
*/
/* * Workaround for a bug at media-ctl <= v1.10 that makes it to * do the wrong thing if the entity function doesn't belong to * either MEDIA_ENT_F_OLD_BASE or MEDIA_ENT_F_OLD_SUBDEV_BASE * Ranges. * * Non-subdevices are expected to be at the MEDIA_ENT_F_OLD_BASE, * or, otherwise, will be silently ignored by media-ctl when * printing the graphviz diagram. So, map them into the devnode * old range.
*/ if (ent->function < MEDIA_ENT_F_OLD_BASE ||
ent->function > MEDIA_ENT_F_TUNER) { if (is_media_entity_v4l2_subdev(ent))
entd->type = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; elseif (ent->function != MEDIA_ENT_F_IO_V4L)
entd->type = MEDIA_ENT_T_DEVNODE_UNKNOWN;
}
/* Get entities and number of entities */
i = 0;
uentity = media_get_uptr(topo->ptr_entities);
media_device_for_each_entity(entity, mdev) {
i++; if (ret || !uentity) continue;
if (i > topo->num_entities) {
ret = -ENOSPC; continue;
}
/* Copy fields to userspace struct if not error */
memset(&kentity, 0, sizeof(kentity));
kentity.id = entity->graph_obj.id;
kentity.function = entity->function;
kentity.flags = entity->flags;
strscpy(kentity.name, entity->name, sizeof(kentity.name));
if (copy_to_user(uentity, &kentity, sizeof(kentity)))
ret = -EFAULT;
uentity++;
}
topo->num_entities = i;
topo->reserved1 = 0;
/* Get interfaces and number of interfaces */
i = 0;
uintf = media_get_uptr(topo->ptr_interfaces);
media_device_for_each_intf(intf, mdev) {
i++; if (ret || !uintf) continue;
if (i > topo->num_interfaces) {
ret = -ENOSPC; continue;
}
if (copy_to_user(uintf, &kintf, sizeof(kintf)))
ret = -EFAULT;
uintf++;
}
topo->num_interfaces = i;
topo->reserved2 = 0;
/* Get pads and number of pads */
i = 0;
upad = media_get_uptr(topo->ptr_pads);
media_device_for_each_pad(pad, mdev) {
i++; if (ret || !upad) continue;
if (i > topo->num_pads) {
ret = -ENOSPC; continue;
}
memset(&kpad, 0, sizeof(kpad));
/* Copy pad fields to userspace struct */
kpad.id = pad->graph_obj.id;
kpad.entity_id = pad->entity->graph_obj.id;
kpad.flags = pad->flags;
kpad.index = pad->index;
if (copy_to_user(upad, &kpad, sizeof(kpad)))
ret = -EFAULT;
upad++;
}
topo->num_pads = i;
topo->reserved3 = 0;
/* Get links and number of links */
i = 0;
ulink = media_get_uptr(topo->ptr_links);
media_device_for_each_link(link, mdev) { if (link->is_backlink) continue;
i++;
if (ret || !ulink) continue;
if (i > topo->num_links) {
ret = -ENOSPC; continue;
}
memset(&klink, 0, sizeof(klink));
/* Copy link fields to userspace struct */
klink.id = link->graph_obj.id;
klink.source_id = link->gobj0->id;
klink.sink_id = link->gobj1->id;
klink.flags = link->flags;
if (copy_to_user(ulink, &klink, sizeof(klink)))
ret = -EFAULT;
ulink++;
}
topo->num_links = i;
topo->reserved4 = 0;
/* Remove all interface links pointing to this entity */
list_for_each_entry(intf, &mdev->interfaces, graph_obj.list) {
list_for_each_entry_safe(link, tmp, &intf->links, list) { if (link->entity == entity)
__media_remove_intf_link(link);
}
}
/* Remove all data links that belong to this entity */
__media_entity_remove_links(entity);
/* Remove all pads that belong to this entity */
media_entity_for_each_pad(entity, iter)
media_gobj_destroy(&iter->graph_obj);
/* Remove the entity */
media_gobj_destroy(&entity->graph_obj);
/* invoke entity_notify callbacks to handle entity removal?? */
}
int __must_check media_device_register_entity(struct media_device *mdev, struct media_entity *entity)
{ struct media_entity_notify *notify, *next; struct media_pad *iter; int ret;
if (entity->function == MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN ||
entity->function == MEDIA_ENT_F_UNKNOWN)
dev_warn(mdev->dev, "Entity type for entity %s was not initialized!\n",
entity->name);
/* Warn if we apparently re-register an entity */
WARN_ON(entity->graph_obj.mdev != NULL);
entity->graph_obj.mdev = mdev;
INIT_LIST_HEAD(&entity->links);
entity->num_links = 0;
entity->num_backlinks = 0;
ret = ida_alloc_min(&mdev->entity_internal_idx, 1, GFP_KERNEL); if (ret < 0) return ret;
entity->internal_idx = ret;
if (mdev->entity_internal_idx_max
>= mdev->pm_count_walk.ent_enum.idx_max) { struct media_graph new = { .top = 0 };
/* * Initialise the new graph walk before cleaning up * the old one in order not to spoil the graph walk * object of the media device if graph walk init fails.
*/
ret = media_graph_walk_init(&new, mdev); if (ret) {
__media_device_unregister_entity(entity);
mutex_unlock(&mdev->graph_mutex); return ret;
}
media_graph_walk_cleanup(&mdev->pm_count_walk);
mdev->pm_count_walk = new;
}
mutex_unlock(&mdev->graph_mutex);
/* * Note: Should be called with mdev->lock held.
*/ staticvoid __media_device_unregister_entity_notify(struct media_device *mdev, struct media_entity_notify *nptr)
{
list_del(&nptr->list);
}
/* Check if mdev was ever registered at all */ if (!media_devnode_is_registered(mdev->devnode)) {
mutex_unlock(&mdev->graph_mutex); return;
}
/* Clear the devnode register bit to avoid races with media dev open */
media_devnode_unregister_prepare(mdev->devnode);
/* Remove all entities from the media device */
list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
__media_device_unregister_entity(entity);
/* Remove all entity_notify callbacks from the media device */
list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list)
__media_device_unregister_entity_notify(mdev, notify);
/* Remove all interfaces from the media device */
list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
graph_obj.list) { /* * Unlink the interface, but don't free it here; the * module which created it is responsible for freeing * it
*/
__media_remove_intf_links(intf);
media_gobj_destroy(&intf->graph_obj);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.