summaryrefslogtreecommitdiffstats
path: root/drivers/media/media-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/media-device.c')
-rw-r--r--drivers/media/media-device.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 648a9d892ac1..16b70b4412f7 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -172,6 +172,44 @@ static long media_device_enum_links(struct media_device *mdev,
return 0;
}
+static long media_device_setup_link(struct media_device *mdev,
+ struct media_link_desc __user *_ulink)
+{
+ struct media_link *link = NULL;
+ struct media_link_desc ulink;
+ struct media_entity *source;
+ struct media_entity *sink;
+ int ret;
+
+ if (copy_from_user(&ulink, _ulink, sizeof(ulink)))
+ return -EFAULT;
+
+ /* Find the source and sink entities and link.
+ */
+ source = find_entity(mdev, ulink.source.entity);
+ sink = find_entity(mdev, ulink.sink.entity);
+
+ if (source == NULL || sink == NULL)
+ return -EINVAL;
+
+ if (ulink.source.index >= source->num_pads ||
+ ulink.sink.index >= sink->num_pads)
+ return -EINVAL;
+
+ link = media_entity_find_link(&source->pads[ulink.source.index],
+ &sink->pads[ulink.sink.index]);
+ if (link == NULL)
+ return -EINVAL;
+
+ /* Setup the link on both entities. */
+ ret = __media_entity_setup_link(link, ulink.flags);
+
+ if (copy_to_user(_ulink, &ulink, sizeof(ulink)))
+ return -EFAULT;
+
+ return ret;
+}
+
static long media_device_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -197,6 +235,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
mutex_unlock(&dev->graph_mutex);
break;
+ case MEDIA_IOC_SETUP_LINK:
+ mutex_lock(&dev->graph_mutex);
+ ret = media_device_setup_link(dev,
+ (struct media_link_desc __user *)arg);
+ mutex_unlock(&dev->graph_mutex);
+ break;
+
default:
ret = -ENOIOCTLCMD;
}