diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-08-03 10:55:50 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2014-03-10 19:54:04 +0100 |
commit | c4aee27b34a92f1774dbb41f255b79f46e1bdf06 (patch) | |
tree | edd2b461e5cdcc0534355cc12512fad7023219e2 | |
parent | 5d751cc0b289282d354f7701a1ff896cc0778be8 (diff) |
Add support for emulated devices
Emulated media devices are backed by real hardware devices for the
functions they provide, but have no kernel media device counterpart.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
-rw-r--r-- | src/mediactl.c | 85 | ||||
-rw-r--r-- | src/mediactl.h | 52 |
2 files changed, 133 insertions, 4 deletions
diff --git a/src/mediactl.c b/src/mediactl.c index 4da334a..5daecb6 100644 --- a/src/mediactl.c +++ b/src/mediactl.c @@ -637,7 +637,7 @@ void media_debug_set_handler(struct media_device *media, } } -struct media_device *media_device_new(const char *devnode) +static struct media_device *__media_device_new(void) { struct media_device *media; int ret; @@ -651,6 +651,18 @@ struct media_device *media_device_new(const char *devnode) media_debug_set_handler(media, NULL, NULL); + return media; +} + +struct media_device *media_device_new(const char *devnode) +{ + struct media_device *media; + int ret; + + media = __media_device_new(); + if (media == NULL) + return NULL; + media->devnode = strdup(devnode); if (media->devnode == NULL) { media_device_unref(media); @@ -660,6 +672,19 @@ struct media_device *media_device_new(const char *devnode) return media; } +struct media_device *media_device_new_emulated(struct media_device_info *info) +{ + struct media_device *media; + + media = __media_device_new(); + if (media == NULL) + return NULL; + + media->info = *info; + + return media; +} + struct media_device *media_device_ref(struct media_device *media) { media->refcount++; @@ -688,9 +713,61 @@ void media_device_unref(struct media_device *media) free(media); } -/* ----------------------------------------------------------------------------- - * Parsing - */ +int media_device_add_entity(struct media_device *media, + const struct media_entity_desc *desc, + const char *devnode) +{ + struct media_entity **defent; + struct media_entity *entity; + unsigned int size; + + size = (media->entities_count + 1) * sizeof(*media->entities); + entity = realloc(media->entities, size); + if (entity == NULL) + return -ENOMEM; + + media->entities = entity; + media->entities_count++; + + entity = &media->entities[media->entities_count - 1]; + memset(entity, 0, sizeof *entity); + + entity->fd = -1; + entity->media = media; + strncpy(entity->devname, devnode, sizeof entity->devname); + entity->devname[sizeof entity->devname - 1] = '\0'; + + entity->info.id = 0; + entity->info.type = desc->type; + entity->info.flags = 0; + memcpy(entity->info.name, desc->name, sizeof entity->info.name); + + switch (entity->info.type) { + case MEDIA_ENT_T_DEVNODE_V4L: + defent = &media->def.v4l; + entity->info.v4l = desc->v4l; + break; + case MEDIA_ENT_T_DEVNODE_FB: + defent = &media->def.fb; + entity->info.fb = desc->fb; + break; + case MEDIA_ENT_T_DEVNODE_ALSA: + defent = &media->def.alsa; + entity->info.alsa = desc->alsa; + break; + case MEDIA_ENT_T_DEVNODE_DVB: + defent = &media->def.dvb; + entity->info.dvb = desc->dvb; + break; + } + + if (desc->flags & MEDIA_ENT_FL_DEFAULT) { + entity->info.flags |= MEDIA_ENT_FL_DEFAULT; + *defent = entity; + } + + return 0; +} struct media_pad *media_parse_pad(struct media_device *media, const char *p, char **endp) diff --git a/src/mediactl.h b/src/mediactl.h index b74be0b..e34ae81 100644 --- a/src/mediactl.h +++ b/src/mediactl.h @@ -60,6 +60,22 @@ struct media_entity; struct media_device *media_device_new(const char *devnode); /** + * @brief Create a new emulated media device. + * @param info - device information. + * + * Emulated media devices are userspace-only objects not backed by a kernel + * media device. They are created for ALSA and V4L2 devices that are not + * associated with a media controller device. + * + * Only device query functions are available for media devices. Enumerating or + * setting up links is invalid. + * + * @return A pointer to the new media device or NULL if memory cannot be + * allocated. + */ +struct media_device *media_device_new_emulated(struct media_device_info *info); + +/** * @brief Take a reference to the device. * @param media - device instance. * @@ -81,6 +97,42 @@ struct media_device *media_device_ref(struct media_device *media); void media_device_unref(struct media_device *media); /** + * @brief Add an entity to an existing media device + * @param media - device instance. + * @param desc - description of the entity to be added + * @param devnode - device node corresponding to the entity + * + * Entities are usually created and added to media devices automatically when + * the media device is enumerated through the media controller API. However, + * when an emulated media device (thus not backed with a kernel-side media + * controller device) is created, entities need to be manually added. + * + * Entities can also be manually added to a successfully enumerated media device + * to group several functions provided by separate kernel devices. The most + * common use case is to group the audio and video functions of a USB webcam in + * a single media device. Those functions are exposed through separate USB + * interfaces and handled through unrelated kernel drivers, they must thus be + * manually added to the same media device. + * + * This function adds a new entity to the given media device and initializes it + * from the given entity description and device node name. Only the following + * fields of the description are copied over to the new entity: + * + * - type + * - flags (MEDIA_ENT_FL_DEFAULT only) + * - name + * - v4l, fb, alsa or dvb (depending on the device type) + * + * All other fields of the newly created entity id are initialized to 0, + * including the entity ID. + * + * @return Zero on success or -ENOMEM if memory cannot be allocated. + */ +int media_device_add_entity(struct media_device *media, + const struct media_entity_desc *desc, + const char *devnode); + +/** * @brief Set a handler for debug messages. * @param media - device instance. * @param debug_handler - debug message handler |