aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/media-device.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2009-12-09 06:40:01 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-22 03:53:14 -0400
commit1651333b09743887bc2dd3d158a11853a2be3fe7 (patch)
tree965dd31e8fbd0c866bbcd47b86baccc238101ef7 /drivers/media/media-device.c
parent140d88165c25137e871f9559e67986ed89251105 (diff)
[media] media: Entities, pads and links enumeration
Create the following two ioctls and implement them at the media device level to enumerate entities, pads and links. - MEDIA_IOC_ENUM_ENTITIES: Enumerate entities and their properties - MEDIA_IOC_ENUM_LINKS: Enumerate all pads and links for a given entity Entity IDs can be non-contiguous. Userspace applications should enumerate entities using the MEDIA_ENT_ID_FLAG_NEXT flag. When the flag is set in the entity ID, the MEDIA_IOC_ENUM_ENTITIES will return the next entity with an ID bigger than the requested one. Only forward links that originate at one of the entity's source pads are returned during the enumeration process. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi> Acked-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/media-device.c')
-rw-r--r--drivers/media/media-device.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 92e0d4eb84b8..648a9d892ac1 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -61,6 +61,117 @@ static int media_device_get_info(struct media_device *dev,
61 return copy_to_user(__info, &info, sizeof(*__info)); 61 return copy_to_user(__info, &info, sizeof(*__info));
62} 62}
63 63
64static struct media_entity *find_entity(struct media_device *mdev, u32 id)
65{
66 struct media_entity *entity;
67 int next = id & MEDIA_ENT_ID_FLAG_NEXT;
68
69 id &= ~MEDIA_ENT_ID_FLAG_NEXT;
70
71 spin_lock(&mdev->lock);
72
73 media_device_for_each_entity(entity, mdev) {
74 if ((entity->id == id && !next) ||
75 (entity->id > id && next)) {
76 spin_unlock(&mdev->lock);
77 return entity;
78 }
79 }
80
81 spin_unlock(&mdev->lock);
82
83 return NULL;
84}
85
86static long media_device_enum_entities(struct media_device *mdev,
87 struct media_entity_desc __user *uent)
88{
89 struct media_entity *ent;
90 struct media_entity_desc u_ent;
91
92 if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id)))
93 return -EFAULT;
94
95 ent = find_entity(mdev, u_ent.id);
96
97 if (ent == NULL)
98 return -EINVAL;
99
100 u_ent.id = ent->id;
101 u_ent.name[0] = '\0';
102 if (ent->name)
103 strlcpy(u_ent.name, ent->name, sizeof(u_ent.name));
104 u_ent.type = ent->type;
105 u_ent.revision = ent->revision;
106 u_ent.flags = ent->flags;
107 u_ent.group_id = ent->group_id;
108 u_ent.pads = ent->num_pads;
109 u_ent.links = ent->num_links - ent->num_backlinks;
110 u_ent.v4l.major = ent->v4l.major;
111 u_ent.v4l.minor = ent->v4l.minor;
112 if (copy_to_user(uent, &u_ent, sizeof(u_ent)))
113 return -EFAULT;
114 return 0;
115}
116
117static void media_device_kpad_to_upad(const struct media_pad *kpad,
118 struct media_pad_desc *upad)
119{
120 upad->entity = kpad->entity->id;
121 upad->index = kpad->index;
122 upad->flags = kpad->flags;
123}
124
125static long media_device_enum_links(struct media_device *mdev,
126 struct media_links_enum __user *ulinks)
127{
128 struct media_entity *entity;
129 struct media_links_enum links;
130
131 if (copy_from_user(&links, ulinks, sizeof(links)))
132 return -EFAULT;
133
134 entity = find_entity(mdev, links.entity);
135 if (entity == NULL)
136 return -EINVAL;
137
138 if (links.pads) {
139 unsigned int p;
140
141 for (p = 0; p < entity->num_pads; p++) {
142 struct media_pad_desc pad;
143 media_device_kpad_to_upad(&entity->pads[p], &pad);
144 if (copy_to_user(&links.pads[p], &pad, sizeof(pad)))
145 return -EFAULT;
146 }
147 }
148
149 if (links.links) {
150 struct media_link_desc __user *ulink;
151 unsigned int l;
152
153 for (l = 0, ulink = links.links; l < entity->num_links; l++) {
154 struct media_link_desc link;
155
156 /* Ignore backlinks. */
157 if (entity->links[l].source->entity != entity)
158 continue;
159
160 media_device_kpad_to_upad(entity->links[l].source,
161 &link.source);
162 media_device_kpad_to_upad(entity->links[l].sink,
163 &link.sink);
164 link.flags = entity->links[l].flags;
165 if (copy_to_user(ulink, &link, sizeof(*ulink)))
166 return -EFAULT;
167 ulink++;
168 }
169 }
170 if (copy_to_user(ulinks, &links, sizeof(*ulinks)))
171 return -EFAULT;
172 return 0;
173}
174
64static long media_device_ioctl(struct file *filp, unsigned int cmd, 175static long media_device_ioctl(struct file *filp, unsigned int cmd,
65 unsigned long arg) 176 unsigned long arg)
66{ 177{
@@ -74,6 +185,18 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
74 (struct media_device_info __user *)arg); 185 (struct media_device_info __user *)arg);
75 break; 186 break;
76 187
188 case MEDIA_IOC_ENUM_ENTITIES:
189 ret = media_device_enum_entities(dev,
190 (struct media_entity_desc __user *)arg);
191 break;
192
193 case MEDIA_IOC_ENUM_LINKS:
194 mutex_lock(&dev->graph_mutex);
195 ret = media_device_enum_links(dev,
196 (struct media_links_enum __user *)arg);
197 mutex_unlock(&dev->graph_mutex);
198 break;
199
77 default: 200 default:
78 ret = -ENOIOCTLCMD; 201 ret = -ENOIOCTLCMD;
79 } 202 }