2 * Media controller interface library
4 * Copyright (C) 2010-2011 Ideas on board SPRL
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published
10 * by the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/ioctl.h>
26 #include <sys/types.h>
35 #include <linux/videodev2.h>
36 #include <linux/media.h>
41 struct media_pad *media_entity_remote_source(struct media_pad *pad)
45 if (!(pad->flags & MEDIA_PAD_FL_SINK))
48 for (i = 0; i < pad->entity->num_links; ++i) {
49 struct media_link *link = &pad->entity->links[i];
51 if (!(link->flags & MEDIA_LNK_FL_ENABLED))
54 if (link->sink == pad)
61 struct media_entity *media_get_entity_by_name(struct media_device *media,
62 const char *name, size_t length)
66 /* A match is impossible if the entity name is longer than the maximum
67 * size we can get from the kernel.
69 if (length >= FIELD_SIZEOF(struct media_entity_desc, name))
72 for (i = 0; i < media->entities_count; ++i) {
73 struct media_entity *entity = &media->entities[i];
75 if (strncmp(entity->info.name, name, length) == 0 &&
76 entity->info.name[length] == '\0')
83 struct media_entity *media_get_entity_by_id(struct media_device *media,
88 for (i = 0; i < media->entities_count; ++i) {
89 struct media_entity *entity = &media->entities[i];
91 if (entity->info.id == id)
98 int media_setup_link(struct media_device *media,
99 struct media_pad *source,
100 struct media_pad *sink,
103 struct media_link *link;
104 struct media_link_desc ulink;
108 for (i = 0; i < source->entity->num_links; i++) {
109 link = &source->entity->links[i];
111 if (link->source->entity == source->entity &&
112 link->source->index == source->index &&
113 link->sink->entity == sink->entity &&
114 link->sink->index == sink->index)
118 if (i == source->entity->num_links) {
119 media_dbg(media, "%s: Link not found\n", __func__);
124 ulink.source.entity = source->entity->info.id;
125 ulink.source.index = source->index;
126 ulink.source.flags = MEDIA_PAD_FL_SOURCE;
129 ulink.sink.entity = sink->entity->info.id;
130 ulink.sink.index = sink->index;
131 ulink.sink.flags = MEDIA_PAD_FL_SINK;
133 ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
135 ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
137 media_dbg(media, "%s: Unable to setup link (%s)\n",
138 __func__, strerror(errno));
142 link->flags = ulink.flags;
143 link->twin->flags = ulink.flags;
147 int media_reset_links(struct media_device *media)
152 for (i = 0; i < media->entities_count; ++i) {
153 struct media_entity *entity = &media->entities[i];
155 for (j = 0; j < entity->num_links; j++) {
156 struct media_link *link = &entity->links[j];
158 if (link->flags & MEDIA_LNK_FL_IMMUTABLE ||
159 link->source->entity != entity)
162 ret = media_setup_link(media, link->source, link->sink,
163 link->flags & ~MEDIA_LNK_FL_ENABLED);
172 static struct media_link *media_entity_add_link(struct media_entity *entity)
174 if (entity->num_links >= entity->max_links) {
175 struct media_link *links = entity->links;
176 unsigned int max_links = entity->max_links * 2;
179 links = realloc(links, max_links * sizeof *links);
183 for (i = 0; i < entity->num_links; ++i)
184 links[i].twin->twin = &links[i];
186 entity->max_links = max_links;
187 entity->links = links;
190 return &entity->links[entity->num_links++];
193 static int media_enum_links(struct media_device *media)
198 for (id = 1; id <= media->entities_count; id++) {
199 struct media_entity *entity = &media->entities[id - 1];
200 struct media_links_enum links;
203 links.entity = entity->info.id;
204 links.pads = malloc(entity->info.pads * sizeof(struct media_pad_desc));
205 links.links = malloc(entity->info.links * sizeof(struct media_link_desc));
207 if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
209 "%s: Unable to enumerate pads and links (%s).\n",
210 __func__, strerror(errno));
216 for (i = 0; i < entity->info.pads; ++i) {
217 entity->pads[i].entity = entity;
218 entity->pads[i].index = links.pads[i].index;
219 entity->pads[i].flags = links.pads[i].flags;
222 for (i = 0; i < entity->info.links; ++i) {
223 struct media_link_desc *link = &links.links[i];
224 struct media_link *fwdlink;
225 struct media_link *backlink;
226 struct media_entity *source;
227 struct media_entity *sink;
229 source = media_get_entity_by_id(media, link->source.entity);
230 sink = media_get_entity_by_id(media, link->sink.entity);
232 if (source == NULL || sink == NULL) {
234 "WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
235 id, i, link->source.entity,
241 fwdlink = media_entity_add_link(source);
242 fwdlink->source = &source->pads[link->source.index];
243 fwdlink->sink = &sink->pads[link->sink.index];
244 fwdlink->flags = link->flags;
246 backlink = media_entity_add_link(sink);
247 backlink->source = &source->pads[link->source.index];
248 backlink->sink = &sink->pads[link->sink.index];
249 backlink->flags = link->flags;
251 fwdlink->twin = backlink;
252 backlink->twin = fwdlink;
267 static inline int media_udev_open(struct udev **udev)
275 static inline void media_udev_close(struct udev *udev)
281 static int media_get_devname_udev(struct udev *udev,
282 struct media_entity *entity)
284 struct udev_device *device;
292 devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
293 media_dbg(entity->media, "looking up device: %u:%u\n",
294 major(devnum), minor(devnum));
295 device = udev_device_new_from_devnum(udev, 'c', devnum);
297 p = udev_device_get_devnode(device);
299 strncpy(entity->devname, p, sizeof(entity->devname));
300 entity->devname[sizeof(entity->devname) - 1] = '\0';
305 udev_device_unref(device);
310 #else /* HAVE_LIBUDEV */
314 static inline int media_udev_open(struct udev **udev) { return 0; }
316 static inline void media_udev_close(struct udev *udev) { }
318 static inline int media_get_devname_udev(struct udev *udev,
319 struct media_entity *entity)
324 #endif /* HAVE_LIBUDEV */
326 static int media_get_devname_sysfs(struct media_entity *entity)
335 sprintf(sysname, "/sys/dev/char/%u:%u", entity->info.v4l.major,
336 entity->info.v4l.minor);
337 ret = readlink(sysname, target, sizeof(target));
342 p = strrchr(target, '/');
346 sprintf(devname, "/dev/%s", p + 1);
347 ret = stat(devname, &devstat);
351 /* Sanity check: udev might have reordered the device nodes.
352 * Make sure the major/minor match. We should really use
355 if (major(devstat.st_rdev) == entity->info.v4l.major &&
356 minor(devstat.st_rdev) == entity->info.v4l.minor)
357 strcpy(entity->devname, devname);
362 static int media_enum_entities(struct media_device *media)
364 struct media_entity *entity;
370 ret = media_udev_open(&udev);
372 media_dbg(media, "Can't get udev context\n");
374 for (id = 0, ret = 0; ; id = entity->info.id) {
375 size = (media->entities_count + 1) * sizeof(*media->entities);
376 media->entities = realloc(media->entities, size);
378 entity = &media->entities[media->entities_count];
379 memset(entity, 0, sizeof(*entity));
381 entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
382 entity->media = media;
384 ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
386 ret = errno != EINVAL ? -errno : 0;
390 /* Number of links (for outbound links) plus number of pads (for
391 * inbound links) is a good safe initial estimate of the total
394 entity->max_links = entity->info.pads + entity->info.links;
396 entity->pads = malloc(entity->info.pads * sizeof(*entity->pads));
397 entity->links = malloc(entity->max_links * sizeof(*entity->links));
398 if (entity->pads == NULL || entity->links == NULL) {
403 media->entities_count++;
405 /* Find the corresponding device name. */
406 if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE &&
407 media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
410 /* Try to get the device name via udev */
411 if (!media_get_devname_udev(udev, entity))
414 /* Fall back to get the device name via sysfs */
415 media_get_devname_sysfs(entity);
418 media_udev_close(udev);
422 static void media_debug_default(void *ptr, ...)
426 void media_debug_set_handler(struct media_device *media,
427 void (*debug_handler)(void *, ...),
431 media->debug_handler = debug_handler;
432 media->debug_priv = debug_priv;
434 media->debug_handler = media_debug_default;
435 media->debug_priv = NULL;
439 struct media_device *media_open_debug(
440 const char *name, void (*debug_handler)(void *, ...),
443 struct media_device *media;
446 media = calloc(1, sizeof(*media));
450 media_debug_set_handler(media, debug_handler, debug_priv);
452 media_dbg(media, "Opening media device %s\n", name);
454 media->fd = open(name, O_RDWR);
457 media_dbg(media, "%s: Can't open media device %s\n",
462 ret = ioctl(media->fd, MEDIA_IOC_DEVICE_INFO, &media->info);
464 media_dbg(media, "%s: Unable to retrieve media device "
465 "information for device %s (%s)\n", __func__,
466 name, strerror(errno));
471 media_dbg(media, "Enumerating entities\n");
473 ret = media_enum_entities(media);
477 "%s: Unable to enumerate entities for device %s (%s)\n",
478 __func__, name, strerror(-ret));
483 media_dbg(media, "Found %u entities\n", media->entities_count);
484 media_dbg(media, "Enumerating pads and links\n");
486 ret = media_enum_links(media);
489 "%s: Unable to enumerate pads and linksfor device %s\n",
498 struct media_device *media_open(const char *name)
500 return media_open_debug(name, NULL, NULL);
503 void media_close(struct media_device *media)
510 for (i = 0; i < media->entities_count; ++i) {
511 struct media_entity *entity = &media->entities[i];
515 if (entity->fd != -1)
519 free(media->entities);
523 struct media_pad *media_parse_pad(struct media_device *media,
524 const char *p, char **endp)
526 unsigned int entity_id, pad;
527 struct media_entity *entity;
530 for (; isspace(*p); ++p);
533 for (end = (char *)p + 1; *end && *end != '"'; ++end);
537 entity = media_get_entity_by_name(media, p + 1, end - p - 1);
543 entity_id = strtoul(p, &end, 10);
544 entity = media_get_entity_by_id(media, entity_id);
548 for (; isspace(*end); ++end);
552 for (p = end + 1; isspace(*p); ++p);
554 pad = strtoul(p, &end, 10);
555 for (p = end; isspace(*p); ++p);
557 if (pad >= entity->info.pads)
560 for (p = end; isspace(*p); ++p);
564 return &entity->pads[pad];
567 struct media_link *media_parse_link(struct media_device *media,
568 const char *p, char **endp)
570 struct media_link *link;
571 struct media_pad *source;
572 struct media_pad *sink;
576 source = media_parse_pad(media, p, &end);
580 if (end[0] != '-' || end[1] != '>')
584 sink = media_parse_pad(media, p, &end);
590 for (i = 0; i < source->entity->num_links; i++) {
591 link = &source->entity->links[i];
593 if (link->source == source && link->sink == sink)
600 int media_parse_setup_link(struct media_device *media,
601 const char *p, char **endp)
603 struct media_link *link;
607 link = media_parse_link(media, p, &end);
610 "%s: Unable to parse link\n", __func__);
616 media_dbg(media, "Unable to parse link flags\n");
620 flags = strtoul(p, &end, 10);
621 for (p = end; isspace(*p); p++);
623 media_dbg(media, "Unable to parse link flags\n");
627 for (; isspace(*p); p++);
631 "Setting up link %u:%u -> %u:%u [%u]\n",
632 link->source->entity->info.id, link->source->index,
633 link->sink->entity->info.id, link->sink->index,
636 return media_setup_link(media, link->source, link->sink, flags);
639 int media_parse_setup_links(struct media_device *media, const char *p)
645 ret = media_parse_setup_link(media, p, &end);
650 } while (*end == ',');
652 return *end ? -EINVAL : 0;