Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8309f47c authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] media-device: add support for MEDIA_IOC_G_TOPOLOGY ioctl



Add support for the new MEDIA_IOC_G_TOPOLOGY ioctl, according
with the RFC for the MC next generation.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 2521fdac
Loading
Loading
Loading
Loading
+158 −0
Original line number Diff line number Diff line
@@ -232,6 +232,156 @@ static long media_device_setup_link(struct media_device *mdev,
	return ret;
}

static long __media_device_get_topology(struct media_device *mdev,
				      struct media_v2_topology *topo)
{
	struct media_entity *entity;
	struct media_interface *intf;
	struct media_pad *pad;
	struct media_link *link;
	struct media_v2_entity uentity;
	struct media_v2_interface uintf;
	struct media_v2_pad upad;
	struct media_v2_link ulink;
	int ret = 0, i;

	topo->topology_version = mdev->topology_version;

	/* Get entities and number of entities */
	i = 0;
	media_device_for_each_entity(entity, mdev) {
		i++;

		if (ret || !topo->entities)
			continue;

		if (i > topo->num_entities) {
			ret = -ENOSPC;
			continue;
		}

		/* Copy fields to userspace struct if not error */
		memset(&uentity, 0, sizeof(uentity));
		uentity.id = entity->graph_obj.id;
		strncpy(uentity.name, entity->name,
			sizeof(uentity.name));

		if (copy_to_user(&topo->entities[i - 1], &uentity, sizeof(uentity)))
			ret = -EFAULT;
	}
	topo->num_entities = i;

	/* Get interfaces and number of interfaces */
	i = 0;
	media_device_for_each_intf(intf, mdev) {
		i++;

		if (ret || !topo->interfaces)
			continue;

		if (i > topo->num_interfaces) {
			ret = -ENOSPC;
			continue;
		}

		memset(&uintf, 0, sizeof(uintf));

		/* Copy intf fields to userspace struct */
		uintf.id = intf->graph_obj.id;
		uintf.intf_type = intf->type;
		uintf.flags = intf->flags;

		if (media_type(&intf->graph_obj) == MEDIA_GRAPH_INTF_DEVNODE) {
			struct media_intf_devnode *devnode;

			devnode = intf_to_devnode(intf);

			uintf.devnode.major = devnode->major;
			uintf.devnode.minor = devnode->minor;
		}

		if (copy_to_user(&topo->interfaces[i - 1], &uintf, sizeof(uintf)))
			ret = -EFAULT;
	}
	topo->num_interfaces = i;

	/* Get pads and number of pads */
	i = 0;
	media_device_for_each_pad(pad, mdev) {
		i++;

		if (ret || !topo->pads)
			continue;

		if (i > topo->num_pads) {
			ret = -ENOSPC;
			continue;
		}

		memset(&upad, 0, sizeof(upad));

		/* Copy pad fields to userspace struct */
		upad.id = pad->graph_obj.id;
		upad.entity_id = pad->entity->graph_obj.id;
		upad.flags = pad->flags;

		if (copy_to_user(&topo->pads[i - 1], &upad, sizeof(upad)))
			ret = -EFAULT;
	}
	topo->num_pads = i;

	/* Get links and number of links */
	i = 0;
	media_device_for_each_link(link, mdev) {
		i++;

		if (ret || !topo->links)
			continue;

		if (i > topo->num_links) {
			ret = -ENOSPC;
			continue;
		}

		memset(&ulink, 0, sizeof(ulink));

		/* Copy link fields to userspace struct */
		ulink.id = link->graph_obj.id;
		ulink.source_id = link->gobj0->id;
		ulink.sink_id = link->gobj1->id;
		ulink.flags = link->flags;

		if (media_type(link->gobj0) != MEDIA_GRAPH_PAD)
			ulink.flags |= MEDIA_LNK_FL_INTERFACE_LINK;

		if (copy_to_user(&topo->links[i - 1], &ulink, sizeof(ulink)))
			ret = -EFAULT;
	}
	topo->num_links = i;

	return ret;
}

static long media_device_get_topology(struct media_device *mdev,
				      struct media_v2_topology __user *utopo)
{
	struct media_v2_topology ktopo;
	int ret;

	ret = copy_from_user(&ktopo, utopo, sizeof(ktopo));

	if (ret < 0)
		return ret;

	ret = __media_device_get_topology(mdev, &ktopo);
	if (ret < 0)
		return ret;

	ret = copy_to_user(utopo, &ktopo, sizeof(*utopo));

	return ret;
}

static long media_device_ioctl(struct file *filp, unsigned int cmd,
			       unsigned long arg)
{
@@ -264,6 +414,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
		mutex_unlock(&dev->graph_mutex);
		break;

	case MEDIA_IOC_G_TOPOLOGY:
		mutex_lock(&dev->graph_mutex);
		ret = media_device_get_topology(dev,
				(struct media_v2_topology __user *)arg);
		mutex_unlock(&dev->graph_mutex);
		break;

	default:
		ret = -ENOIOCTLCMD;
	}
@@ -312,6 +469,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd,
	case MEDIA_IOC_DEVICE_INFO:
	case MEDIA_IOC_ENUM_ENTITIES:
	case MEDIA_IOC_SETUP_LINK:
	case MEDIA_IOC_G_TOPOLOGY:
		return media_device_ioctl(filp, cmd, arg);

	case MEDIA_IOC_ENUM_LINKS32: