@@ -35,6 +35,7 @@
#include <unistd.h>
#include <linux/media.h>
+#include <linux/kdev_t.h>
#include <linux/videodev2.h>
#include "mediactl.h"
@@ -45,6 +46,7 @@
* Graph access
*/
+
struct media_pad *media_entity_remote_source(struct media_pad *pad)
{
unsigned int i;
@@ -87,6 +89,28 @@ struct media_entity *media_get_entity_by_name(struct media_device *media,
return NULL;
}
+struct media_entity *media_get_entity_by_devname(struct media_device *media,
+ const char *devname, size_t length)
+{
+ unsigned int i;
+
+ /* A match is impossible if the entity devname is longer than the maximum
+ * size we can get from the kernel.
+ */
+ if (length >= FIELD_SIZEOF(struct media_entity, devname))
+ return NULL;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ if (strncmp(entity->devname, devname, length) == 0 &&
+ entity->devname[length] == '\0')
+ return entity;
+ }
+
+ return NULL;
+}
+
struct media_entity *media_get_entity_by_id(struct media_device *media,
__u32 id)
{
@@ -145,6 +169,11 @@ const char *media_entity_get_devname(struct media_entity *entity)
return entity->devname[0] ? entity->devname : NULL;
}
+const char *media_entity_get_name(struct media_entity *entity)
+{
+ return entity->info.name ? entity->info.name : NULL;
+}
+
struct media_entity *media_get_default_entity(struct media_device *media,
unsigned int type)
{
@@ -177,6 +206,152 @@ const struct media_entity_desc *media_entity_get_info(struct media_entity *entit
return &entity->info;
}
+int media_get_link_by_sink_pad(struct media_device *media,
+ struct media_pad *pad,
+ struct media_link **link)
+{
+ struct media_link *cur_link = NULL;
+ int i, j;
+
+ if (pad == NULL || link == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ for (j = 0; j < media->entities[i].num_links; ++j) {
+ cur_link = &media->entities[i].links[j];
+ if ((cur_link->flags & MEDIA_LNK_FL_ENABLED) &&
+ /* check if cur_link's sink entity matches the pad parent entity */
+ (cur_link->sink->entity->info.id == pad->entity->info.id) &&
+ /* check if cur_link's sink pad id matches */
+ (cur_link->sink->index == pad->index)) {
+ *link = cur_link;
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+int media_get_link_by_source_pad(struct media_entity *entity,
+ struct media_pad *pad,
+ struct media_link **link)
+{
+ int i;
+
+ if (entity == NULL || pad == NULL || link == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < entity->num_links; ++i) {
+ if ((entity->links[i].flags & MEDIA_LNK_FL_ENABLED) &&
+ (entity->links[i].source->index == pad->index)) {
+ *link = &entity->links[i];
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+int media_get_pads_by_entity(struct media_entity *entity, unsigned int type,
+ struct media_pad **pads, int *num_pads)
+{
+ struct media_pad *entity_pads;
+ int cnt_pads, i;
+
+ if (entity == NULL || pads == NULL || num_pads == NULL)
+ return -EINVAL;
+
+ entity_pads = malloc(sizeof(*entity_pads));
+ cnt_pads = 0;
+
+ for (i = 0; i < entity->info.pads; ++i) {
+ if (entity->pads[i].flags & type) {
+ entity_pads = realloc(entity_pads, (i + 1) *
+ sizeof(*entity_pads));
+ entity_pads[cnt_pads++] = entity->pads[i];
+ }
+ }
+
+ if (cnt_pads == 0)
+ free(entity_pads);
+
+ *pads = entity_pads;
+ *num_pads = cnt_pads;
+
+ return 0;
+}
+
+int media_get_busy_pads_by_entity(struct media_device *media,
+ struct media_entity *entity,
+ unsigned int type,
+ struct media_pad **busy_pads,
+ int *num_busy_pads)
+{
+ struct media_pad *bpads, *pads;
+ struct media_link *link;
+ int cnt_bpads = 0, num_pads, i, ret;
+
+ if (entity == NULL || busy_pads == NULL || num_busy_pads == NULL ||
+ (type == MEDIA_PAD_FL_SINK && media == NULL))
+ return -EINVAL;
+
+ ret = media_get_pads_by_entity(entity, type, &pads, &num_pads);
+ if (ret < 0)
+ return -EINVAL;
+
+ if (num_pads == 0)
+ goto done;
+
+ bpads = malloc(sizeof(*pads));
+ if (bpads == NULL)
+ goto error_ret;
+
+ for (i = 0; i < num_pads; ++i) {
+ if (type == MEDIA_PAD_FL_SINK)
+ ret = media_get_link_by_sink_pad(media, &pads[i], &link);
+ else
+ ret = media_get_link_by_source_pad(entity, &pads[i], &link);
+ if (ret == 0) {
+ bpads = realloc(bpads, (i + 1) *
+ sizeof(*bpads));
+ bpads[cnt_bpads++] = pads[i];
+ }
+ }
+ if (num_pads > 0)
+ free(pads);
+
+ if (cnt_bpads == 0)
+ free(bpads);
+
+done:
+ *busy_pads = bpads;
+ *num_busy_pads = cnt_bpads;
+
+ return 0;
+
+error_ret:
+ return -EINVAL;
+}
+
+int media_get_pad_by_index(struct media_pad *pads, int num_pads,
+ int index, struct media_pad *out_pad)
+{
+ int i;
+
+ if (pads == NULL || out_pad == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < num_pads; ++i) {
+ if (pads[i].index == index) {
+ *out_pad = pads[i];
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
/* -----------------------------------------------------------------------------
* Open/close
*/
@@ -1001,3 +1176,12 @@ struct media_entity *media_config_get_entity_by_cid(struct media_device *media,
return NULL;
}
+
+/* -----------------------------------------------------------------------------
+ * Media entity access
+ */
+
+int media_entity_get_fd(struct media_entity *entity)
+{
+ return entity->fd;
+}
@@ -23,6 +23,7 @@
#define __MEDIA_H__
#include <linux/media.h>
+#include <sys/types.h>
struct media_link {
struct media_pad *source;
@@ -231,6 +232,16 @@ const struct media_link *media_entity_get_link(struct media_entity *entity,
const char *media_entity_get_devname(struct media_entity *entity);
/**
+ * @brief Get the name for an entity
+ * @param entity - media entity.
+ *
+ * This function returns the name of the entity.
+ *
+ * @return A pointer to the string with entity name
+ */
+const char *media_entity_get_name(struct media_entity *entity);
+
+/**
* @brief Get the type of an entity.
* @param entity - the entity.
*
@@ -255,6 +266,19 @@ struct media_entity *media_get_entity_by_name(struct media_device *media,
const char *name, size_t length);
/**
+ * @brief Find an entity by the corresponding device node name.
+ * @param media - media device.
+ * @param devname - device node name.
+ * @param length - size of @a devname.
+ *
+ * Search for an entity with a device node name equal to @a devname.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *media_get_entity_by_devname(struct media_device *media,
+ const char *devname, size_t length);
+
+/**
* @brief Find an entity by its ID.
* @param media - media device.
* @param id - entity ID.
@@ -450,4 +474,112 @@ struct media_entity *media_config_get_entity_by_cid(
struct media_device *media,
int cid);
+/**
+ * @brief Get entity's pads of a given type
+ * @param entity - media entity
+ * @param type - pad type (MEDIA_PAD_FL_SINK or MEDIA_PAD_FL_SOURCE)
+ * @param pads - array of matching pads
+ * @param num_pads - number of matching pads
+ *
+ * Get only sink or source pads for an entity. The returned pads
+ * array has to be freed by the caller.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_get_pads_by_entity(struct media_entity *entity,
+ unsigned int type,
+ struct media_pad **pads,
+ int *num_pads);
+/**
+ * @brief Get occupied entity's pads of a given type
+ * @param media - media device
+ * @param entity - media entity
+ * @param type - pad type (MEDIA_PAD_FL_SINK or MEDIA_PAD_FL_SOURCE)
+ * @param busy_pads - array of matching pads
+ * @param num_busy_pads - number of matching pads
+ *
+ * Get only sink or source pads for an entity, with active links.
+ * The returned pads array has to be freed by the caller.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_get_busy_pads_by_entity(struct media_device *media,
+ struct media_entity *entity,
+ unsigned int type,
+ struct media_pad **busy_pads,
+ int *num_busy_pads);
+
+/**
+ * @brief Get link for sink pad
+ * @param media - media device
+ * @param pad - pad to search the link for
+ * @param link - matching link
+ *
+ * Get the link connected to the entity's sink pad.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_get_link_by_sink_pad(struct media_device *media,
+ struct media_pad *pad,
+ struct media_link **link);
+
+/**
+ * @brief Get link for source pad
+ * @param entity - media entity
+ * @param pad - pad to search the link for
+ * @param link - matching link
+ *
+ * Get the link connected to the entity's source pad.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_get_link_by_source_pad(struct media_entity *entity,
+ struct media_pad *pad,
+ struct media_link **link);
+
+/**
+ * @brief Get pad with given index
+ * @param pads - array of pads
+ * @param num_pads - number of pads in the array
+ * @param index - index of a pad to search for
+ * @param out_pad - matching pad
+ *
+ * Get pad with given index from the given pads array.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_get_pad_by_index(struct media_pad *pads, int num_pads,
+ int index, struct media_pad *out_pad);
+
+/**
+ * @brief Get source pad of the pipeline entity
+ * @param entity - media entity
+ *
+ * This function returns the source pad of the entity.
+ *
+ * @return entity source pad, or NULL if the entity is not linked.
+ */
+int media_entity_get_src_pad_index(struct media_entity *entity);
+
+/**
+ * @brief Get sink pad of the pipeline entity
+ * @param entity - media entity
+ *
+ * This function returns the sink pad of the entity.
+ *
+ * @return entity sink pad, or NULL if the entity is not linked
+ */
+int media_entity_get_sink_pad_index(struct media_entity *entity);
+
+/**
+ * @brief Get file descriptor of the entity
+ * @param entity - media entity
+ *
+ * This function gets the file descriptor of the opened
+ * video device node related to the entity.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_entity_get_fd(struct media_entity *entity);
+
#endif