===================================================================
@@ -10,7 +10,7 @@ stkwebcam-objs := stk-webcam.o stk-senso
omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
-videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o
+videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-mc.o
# V4L2 core modules
===================================================================
@@ -697,11 +697,11 @@ static int __devinit ivtv_init_struct1(s
v4l2_subdev_init(&itv->sd_encoder, NULL);
v4l2_subdev_init(&itv->sd_decoder, NULL);
strlcpy(itv->sd_encoder.name, "MPEG encoder", sizeof(itv->sd_encoder.name));
- v4l2_entity_prep(&itv->sd_encoder.entity, SD_ENC_NUM_INPUTS + SD_ENC_NUM_OUTPUTS,
- itv->sd_enc_links, itv->sd_enc_remote);
- v4l2_entity_prep(&itv->sd_decoder.entity, SD_DEC_NUM_INPUTS + SD_DEC_NUM_OUTPUTS,
- itv->sd_dec_links, itv->sd_dec_remote);
strlcpy(itv->sd_decoder.name, "MPEG decoder", sizeof(itv->sd_decoder.name));
+ v4l2_entity_init(&itv->sd_encoder.entity, SD_ENC_NUM_PADS,
+ itv->sd_encoder_pads, 0);
+ v4l2_entity_init(&itv->sd_decoder.entity, SD_DEC_NUM_PADS,
+ itv->sd_decoder_pads, 0);
err = v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_encoder);
if (err)
return err;
@@ -1020,7 +1020,7 @@ static int __devinit ivtv_probe(struct p
retval = v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_decoder);
if (retval)
goto free_io;
- v4l2_entity_connect(&itv->sd_encoder.entity, &itv->sd_decoder.entity, 0);
+ v4l2_entity_connect(&itv->sd_encoder.entity, 0, &itv->sd_decoder.entity, 0, 0);
}
else {
itv->dec_mem = itv->enc_mem;
===================================================================
@@ -321,6 +321,8 @@ struct ivtv_stream {
const char *name; /* name of the stream */
int type; /* stream type */
+ struct v4l2_entity_pad pad;
+
u32 id;
spinlock_t qlock; /* locks access to the queues */
unsigned long s_flags; /* status flags, see above */
@@ -615,18 +617,13 @@ struct ivtv {
struct v4l2_device v4l2_dev;
struct v4l2_subdev sd_gpio; /* GPIO sub-device */
- struct v4l2_entity_io sd_gpio_links;
- struct v4l2_mc_io sd_gpio_remote;
+ struct v4l2_entity_pad sd_gpio_pad;
struct v4l2_subdev sd_encoder; /* Bridge encoder sub-device */
-#define SD_ENC_NUM_INPUTS (10)
-#define SD_ENC_NUM_OUTPUTS (10)
- struct v4l2_entity_io sd_enc_links[SD_ENC_NUM_INPUTS + SD_ENC_NUM_OUTPUTS];
- struct v4l2_mc_io sd_enc_remote[SD_ENC_NUM_INPUTS + SD_ENC_NUM_OUTPUTS];
+#define SD_ENC_NUM_PADS 20 /* 10 inputs, 10 outputs */
+ struct v4l2_entity_pad sd_encoder_pads[SD_ENC_NUM_PADS];
struct v4l2_subdev sd_decoder; /* Bridge decoder sub-device */
-#define SD_DEC_NUM_INPUTS (10)
-#define SD_DEC_NUM_OUTPUTS (10)
- struct v4l2_entity_io sd_dec_links[SD_DEC_NUM_INPUTS + SD_DEC_NUM_OUTPUTS];
- struct v4l2_mc_io sd_dec_remote[SD_DEC_NUM_INPUTS + SD_DEC_NUM_OUTPUTS];
+#define SD_DEC_NUM_PADS 20 /* 10 inputs, 10 outputs */
+ struct v4l2_entity_pad sd_decoder_pads[SD_DEC_NUM_PADS];
u16 instance;
/* High-level state info */
@@ -653,8 +650,6 @@ struct ivtv {
/* Streams */
int stream_buf_size[IVTV_MAX_STREAMS]; /* stream buffer size */
struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* stream data */
- struct v4l2_entity_io stream_links[IVTV_MAX_STREAMS];
- struct v4l2_mc_io stream_remote[IVTV_MAX_STREAMS];
atomic_t capturing; /* count number of active capture streams */
atomic_t decoding; /* count number of active decoding streams */
===================================================================
@@ -374,8 +374,10 @@ int ivtv_gpio_init(struct ivtv *itv)
write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name);
- v4l2_entity_prep(&itv->sd_gpio.entity, 1, &itv->sd_gpio_links, &itv->sd_gpio_remote);
+ itv->sd_gpio_pad.type = V4L2_PAD_TYPE_OUTPUT;
+ v4l2_entity_init(&itv->sd_gpio.entity, 1, &itv->sd_gpio_pad, 0);
itv->sd_gpio.grp_id = IVTV_HW_GPIO;
- v4l2_entity_connect(&itv->sd_gpio.entity, &itv->sd_encoder.entity, 1);
+ v4l2_entity_connect(&itv->sd_gpio.entity, 0, &itv->sd_encoder.entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
}
===================================================================
@@ -170,21 +170,24 @@ int ivtv_i2c_register(struct ivtv *itv,
0, itv->card_i2c->radio);
if (sd) {
sd->grp_id = 1 << idx;
- v4l2_entity_connect(&sd->entity, &itv->sd_encoder.entity, 1);
+ v4l2_entity_connect(&sd->entity, 0, &itv->sd_encoder.entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
}
sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
adap, mod, type,
0, itv->card_i2c->demod);
if (sd) {
sd->grp_id = 1 << idx;
- v4l2_entity_connect(&sd->entity, &itv->sd_encoder.entity, 1);
+ v4l2_entity_connect(&sd->entity, 0, &itv->sd_encoder.entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
}
sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
adap, mod, type,
0, itv->card_i2c->tv);
if (sd) {
sd->grp_id = 1 << idx;
- v4l2_entity_connect(&sd->entity, &itv->sd_encoder.entity, 1);
+ v4l2_entity_connect(&sd->entity, 0, &itv->sd_encoder.entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
}
return sd ? 0 : -1;
}
@@ -193,15 +196,16 @@ int ivtv_i2c_register(struct ivtv *itv,
if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx]));
- v4l2_entity_connect(&sd->entity, &itv->sd_encoder.entity, 1);
} else {
sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
adap, mod, type, hw_addrs[idx], NULL);
- if (hw == IVTV_HW_SAA7127)
- v4l2_entity_connect(&itv->sd_decoder.entity, &sd->entity, 1);
- else
- v4l2_entity_connect(&sd->entity, &itv->sd_encoder.entity, 1);
}
+ if (hw == IVTV_HW_SAA7127)
+ v4l2_entity_connect(&itv->sd_decoder.entity, 0, &sd->entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
+ else
+ v4l2_entity_connect(&sd->entity, 0, &itv->sd_encoder.entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
if (sd)
sd->grp_id = 1 << idx;
return sd ? 0 : -1;
===================================================================
@@ -268,18 +268,20 @@ static int ivtv_reg_dev(struct ivtv *itv
s->vdev = NULL;
return -ENOMEM;
}
- if (type <= IVTV_ENC_STREAM_TYPE_RAD || type == IVTV_DEC_STREAM_TYPE_VBI)
- v4l2_entity_prep(&s->vdev->entity, 1,
- itv->stream_links + type, itv->stream_remote + type);
- else
- v4l2_entity_prep(&s->vdev->entity, 1,
- itv->stream_links + type, itv->stream_remote + type);
- if (type <= IVTV_ENC_STREAM_TYPE_RAD)
- v4l2_entity_connect(&itv->sd_encoder.entity, &s->vdev->entity, 1);
- else if (type == IVTV_DEC_STREAM_TYPE_VBI)
- v4l2_entity_connect(&itv->sd_decoder.entity, &s->vdev->entity, 1);
- else
- v4l2_entity_connect(&s->vdev->entity, &itv->sd_decoder.entity, 1);
+ v4l2_entity_init(&s->vdev->entity, 1, &s->pad, 0);
+ if (type <= IVTV_ENC_STREAM_TYPE_RAD) {
+ s->pad.type = V4L2_PAD_TYPE_INPUT;
+ v4l2_entity_connect(&itv->sd_encoder.entity, 0, &s->vdev->entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
+ } else if (type == IVTV_DEC_STREAM_TYPE_VBI) {
+ s->pad.type = V4L2_PAD_TYPE_INPUT;
+ v4l2_entity_connect(&itv->sd_decoder.entity, 0, &s->vdev->entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
+ } else {
+ s->pad.type = V4L2_PAD_TYPE_OUTPUT;
+ v4l2_entity_connect(&s->vdev->entity, 0, &itv->sd_decoder.entity, 0,
+ V4L2_LINK_FLAG_ACTIVE);
+ }
num = s->vdev->num;
===================================================================
@@ -764,7 +764,8 @@ static int msp_probe(struct i2c_client *
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &msp_ops);
- v4l2_entity_prep(&sd->entity, 1, &state->sd_output, &state->remote_input);
+ state->sd_pad.type = V4L2_PAD_TYPE_OUTPUT;
+ v4l2_entity_init(&sd->entity, 1, &state->sd_pad, 0);
state->v4l2_std = V4L2_STD_NTSC;
state->audmode = V4L2_TUNER_MODE_STEREO;
===================================================================
@@ -51,8 +51,7 @@ extern int msp_stereo_thresh;
struct msp_state {
struct v4l2_subdev sd;
- struct v4l2_entity_io sd_output;
- struct v4l2_mc_io remote_input;
+ struct v4l2_entity_pad sd_pad;
int rev1, rev2;
int ident;
u8 has_nicam;
===================================================================
@@ -74,8 +74,7 @@ I2C_CLIENT_INSMOD;
struct saa711x_state {
struct v4l2_subdev sd;
- struct v4l2_entity_io sd_output;
- struct v4l2_mc_io remote_input;
+ struct v4l2_entity_pad sd_pad;
v4l2_std_id std;
int input;
int output;
@@ -1604,7 +1603,8 @@ static int saa711x_probe(struct i2c_clie
return -ENOMEM;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
- v4l2_entity_prep(&sd->entity, 1, &state->sd_output, &state->remote_input);
+ state->sd_pad.type = V4L2_PAD_TYPE_OUTPUT;
+ v4l2_entity_init(&sd->entity, 1, &state->sd_pad, 0);
state->input = -1;
state->output = SAA7115_IPORT_ON;
state->enable = 1;
===================================================================
@@ -238,8 +238,7 @@ static struct i2c_reg_value saa7127_init
struct saa7127_state {
struct v4l2_subdev sd;
- struct v4l2_entity_io sd_input;
- struct v4l2_mc_io remote_output;
+ struct v4l2_entity_pad sd_pad;
v4l2_std_id std;
u32 ident;
enum saa7127_input_type input_type;
@@ -740,7 +739,8 @@ static int saa7127_probe(struct i2c_clie
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &saa7127_ops);
- v4l2_entity_prep(&sd->entity, 1, &state->sd_input, &state->remote_output);
+ state->sd_pad.type = V4L2_PAD_TYPE_OUTPUT;
+ v4l2_entity_init(&sd->entity, 1, &state->sd_pad, 0);
/* First test register 0: Bits 5-7 are a version ID (should be 0),
and bit 2 should also be 0.
===================================================================
@@ -80,8 +80,7 @@ struct tuner {
struct dvb_frontend fe;
struct i2c_client *i2c;
struct v4l2_subdev sd;
- struct v4l2_entity_io sd_output;
- struct v4l2_mc_io remote_input;
+ struct v4l2_entity_pad sd_pad;
struct list_head list;
unsigned int using_v4l2:1;
@@ -1041,7 +1040,8 @@ static int tuner_probe(struct i2c_client
if (NULL == t)
return -ENOMEM;
v4l2_i2c_subdev_init(&t->sd, client, &tuner_ops);
- v4l2_entity_prep(&t->sd.entity, 1, &t->sd_output, &t->remote_input);
+ t->sd_pad.type = V4L2_PAD_TYPE_OUTPUT;
+ v4l2_entity_init(&t->sd.entity, 1, &t->sd_pad, 0);
t->i2c = client;
t->name = "(tuner unset)";
t->type = UNSET;
===================================================================
@@ -107,14 +107,8 @@ static long mc_enum_entities(struct v4l2
strlcpy(mc_ent.descr, ent->descr, sizeof(mc_ent.descr));
mc_ent.type = ent->type;
mc_ent.subtype = ent->subtype;
- mc_ent.pads = ent->pads;
- mc_ent.total_possible_links = 0;
- if (ent->links) {
- int l;
-
- for (l = 0; l < ent->pads; l++)
- mc_ent.total_possible_links += ent->links[l].nr_of_remote_pads;
- }
+ mc_ent.pads = ent->num_pads;
+ mc_ent.links = ent->num_links;
mc_ent.v4l.major = ent->v4l.major;
mc_ent.v4l.minor = ent->v4l.minor;
if (copy_to_user(uent, &mc_ent, sizeof(mc_ent)))
@@ -122,12 +116,17 @@ static long mc_enum_entities(struct v4l2
return 0;
}
+static void mc_kpad_to_upad(const struct v4l2_entity_pad *kpad, struct v4l2_mc_pad *upad)
+{
+ upad->entity = kpad->entity->id;
+ upad->index = kpad - kpad->entity->pads;
+ upad->type = kpad->type;
+}
+
static long mc_enum_links(struct v4l2_device *v4l2_dev, struct v4l2_mc_ios __user *uios)
{
struct v4l2_entity *ent;
struct v4l2_mc_ios ios;
- u32 total_possible_links = 0;
- int l;
if (copy_from_user(&ios, uios, sizeof(ios)))
return -EFAULT;
@@ -135,31 +134,29 @@ static long mc_enum_links(struct v4l2_de
ent = find_entity(v4l2_dev, ios.entity);
if (ent == NULL)
return -EINVAL;
- if (ent->links) {
- for (l = 0; l < ent->pads; l++)
- total_possible_links += ent->links[l].nr_of_remote_pads;
- }
- if (ios.status) {
- int s = 0;
- for (l = 0; l < ent->pads; l++, s++) {
- struct v4l2_mc_io_status stat = { 0, 0 };
+ if (ios.pads) {
+ unsigned int p;
- if (ent->links)
- stat.nr_of_remote_pads = ent->links[l].nr_of_remote_pads;
- if (copy_to_user(uios->status + s, &stat, sizeof(stat)))
+ for (p = 0; p < ent->num_pads; p++) {
+ struct v4l2_mc_pad pad;
+ mc_kpad_to_upad(&ent->pads[p], &pad);
+ if (copy_to_user(&uios->pads[p], &pad, sizeof(pad)))
return -EFAULT;
}
}
- if (ios.remote_pads && total_possible_links) {
- int p = 0;
+ if (ios.links) {
+ unsigned int l;
+
+ for (l = 0; l < ent->num_links; l++) {
+ struct v4l2_mc_link link;
- for (l = 0; l < ent->pads; l++) {
- if (copy_to_user(uios->remote_pads + p, ent->links[l].remote_pads,
- ent->links[l].nr_of_remote_pads * sizeof(ent->links[l].remote_pads[0])))
+ mc_kpad_to_upad(ent->links[l].source, &link.source);
+ mc_kpad_to_upad(ent->links[l].sink, &link.sink);
+ link.flags = ent->links[l].flags;
+ if (copy_to_user(&uios->links[l], &link, sizeof(link)))
return -EFAULT;
- p += ent->links[l].nr_of_remote_pads;
}
}
if (copy_to_user(uios, &ios, sizeof(*uios)))
===================================================================
@@ -0,0 +1,118 @@
+/*
+ * V4L2 Media Controller support
+ *
+ * Copyright (C) 2009 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <media/v4l2-mc.h>
+
+/**
+ * v4l2_entity_init - Initialize a V4L2 entity
+ *
+ * @num_pads: Total number of input and output pads.
+ * @extra_links: Initial estimate of the number of extra links.
+ * @pads: Array of 'num_pads' pads.
+ *
+ * The total number of pads is an intrinsic property of entities known by the
+ * entity driver, while the total number of links depends on hardware design
+ * and is an extrinsic property unknown to the entity driver. However, in most
+ * use cases the entity driver can guess the number of links which can safely
+ * be assumed to be equal to or larger than the number of pads.
+ *
+ * For those reasons the links array can be preallocated based on the entity
+ * driver guess and will be reallocated later if extra links need to be
+ * created.
+ *
+ * This function allocates a links array with enough space to hold at least
+ * 'num_pads' + 'extra_links' elements. The v4l2_entity::max_links field will
+ * be set to the number of allocated elements.
+ *
+ * The pads array is managed by the entity driver and passed to
+ * v4l2_entity_init() where its pointer will be stored in the entity structure.
+ */
+int
+v4l2_entity_init(struct v4l2_entity *entity, u8 num_pads,
+ struct v4l2_entity_pad *pads, u8 extra_links)
+{
+ struct v4l2_entity_link *links;
+ unsigned int max_links = num_pads + extra_links;
+ unsigned int i;
+
+ links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL);
+ if (links == NULL)
+ return -ENOMEM;
+
+ entity->max_links = max_links;
+ entity->num_links = 0;
+ entity->num_pads = num_pads;
+ entity->pads = pads;
+ entity->links = links;
+
+ for (i = 0; i < num_pads; i++)
+ pads[i].entity = entity;
+
+ return 0;
+}
+EXPORT_SYMBOL(v4l2_entity_init);
+
+static struct
+v4l2_entity_link *v4l2_entity_add_link(struct v4l2_entity *entity)
+{
+ if (entity->num_links >= entity->max_links) {
+ struct v4l2_entity_link *links = entity->links;
+ unsigned int max_links = entity->max_links + 2;
+
+ links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL);
+ if (links == NULL)
+ return NULL;
+
+ entity->max_links = max_links;
+ entity->links = links;
+ }
+
+ return &entity->links[entity->num_links++];
+}
+
+int
+v4l2_entity_connect(struct v4l2_entity *source, u8 source_pad,
+ struct v4l2_entity *sink, u8 sink_pad, u32 flags)
+{
+ struct v4l2_entity_link *source_link;
+ struct v4l2_entity_link *sink_link;
+
+ BUG_ON(source == NULL || sink == NULL);
+ BUG_ON(source_pad >= source->num_pads);
+ BUG_ON(sink_pad >= sink->num_pads);
+
+ source_link = v4l2_entity_add_link(source);
+ sink_link = v4l2_entity_add_link(sink);
+ if (source_link == NULL || sink_link == NULL)
+ return -ENOMEM;
+
+ source_link->source = &source->pads[source_pad];
+ source_link->sink = &sink->pads[sink_pad];
+ source_link->flags = flags;
+ sink_link->source = &source->pads[source_pad];
+ sink_link->sink = &sink->pads[sink_pad];
+ sink_link->flags = flags;
+
+ return 0;
+}
+EXPORT_SYMBOL(v4l2_entity_connect);
+
===================================================================
@@ -1557,14 +1557,9 @@ struct v4l2_dbg_chip_ident {
#define V4L2_PAD_TYPE_INPUT 1
#define V4L2_PAD_TYPE_OUTPUT 2
-struct v4l2_mc_io {
+struct v4l2_mc_pad {
__u32 entity; /* entity ID */
- __u8 pad; /* pad index */
- __u8 active; /* link is active */
-};
-
-struct v4l2_mc_io_status {
- __u8 nr_of_remote_pads;
+ __u32 index; /* pad index */
__u32 type; /* pad type */
};
@@ -1575,7 +1570,7 @@ struct v4l2_mc_entity {
__u32 type;
__u32 subtype;
__u8 pads;
- __u32 total_possible_links;
+ __u32 links;
union {
/* Node specifications */
@@ -1595,17 +1590,21 @@ struct v4l2_mc_entity {
};
};
+#define V4L2_LINK_FLAG_ACTIVE (1 << 0)
+#define V4L2_LINK_FLAG_PERMANENT (1 << 1)
+
+struct v4l2_mc_link {
+ struct v4l2_mc_pad source;
+ struct v4l2_mc_pad sink;
+ __u32 flags;
+};
+
struct v4l2_mc_ios {
__u32 entity;
/* Should have enough room for pads elements */
- struct v4l2_mc_io_status *status;
+ struct v4l2_mc_pad *pads;
/* Should have enough room for total_possible_links elements */
- struct v4l2_mc_io *remote_pads;
-};
-
-struct v4l2_mc_link {
- struct v4l2_mc_io source;
- struct v4l2_mc_io sink;
+ struct v4l2_mc_link *links;
};
/*
===================================================================
@@ -3,23 +3,35 @@
#include <linux/list.h>
-struct v4l2_entity_io {
- u8 nr_of_remote_pads; /* number of remote pads */
- struct v4l2_mc_io *remote_pads; /* specify possible remote pads */
+struct v4l2_entity_link {
+ struct v4l2_entity_pad *source; /* Source pad */
+ struct v4l2_entity_pad *sink; /* Sink pad */
+ u32 flags; /* Link flags (V4L2_LINK_FLAG_*) */
+};
+
+struct v4l2_entity_pad {
+ struct v4l2_entity *entity; /* Entity this pad belongs to */
+ u32 type; /* Pad type (V4L2_PAD_TYPE_*) */
};
struct v4l2_entity {
struct list_head list;
- struct v4l2_device *parent;
- u32 id;
- const char *name;
- const char *descr;
- u32 type;
- u32 subtype;
- u8 pads;
- u8 num_pads;
- /* points to a v4l2_entity_io array of size num_pads links */
- struct v4l2_entity_io *links;
+ struct v4l2_device *parent; /* Media controller this entity belongs
+ * to */
+ u32 id; /* Entity ID, unique in the parent media
+ * controller context */
+ const char *name; /* Entity name */
+ const char *descr; /* Entity description, will be a string control */
+ u32 type; /* Entity type (V4L2_ENTITY_TYPE_*) */
+ u32 subtype; /* Entity subtype (type-specific) */
+
+ u8 num_pads; /* Number of input and output pads */
+ u8 num_links; /* Number of existing links, both active
+ * and inactive */
+ u8 max_links; /* Maximum number of links */
+
+ struct v4l2_entity_pad *pads; /* Array of pads (num_pads elements) */
+ struct v4l2_entity_link *links; /* Array of links (max_links elements) */
/* The entity's ioctl, accessible through the media controller */
long (*ioctl)(struct v4l2_entity *ent, unsigned int cmd, unsigned long arg);
@@ -42,35 +54,9 @@ struct v4l2_entity {
};
};
-static inline void v4l2_entity_prep(struct v4l2_entity *ent, u8 num_pads,
- struct v4l2_entity_io *links, struct v4l2_mc_io *remote_pads)
-{
- int i;
-
- ent->num_pads = num_pads;
- ent->links = links;
- for (i = 0; i < num_pads; i++) {
- links[i].nr_of_remote_pads = 1;
- links[i].remote_pads = remote_pads + i;
- }
-}
-
-static inline void v4l2_entity_connect(struct v4l2_entity *source,
- struct v4l2_entity *sink, int active)
-{
- int source_link, sink_link;
-
- if (source == NULL || sink == NULL || source->pads >= source->num_pads)
- return;
-
- source_link = source->pads++;
- sink_link = sink->pads++;
- source->links[source_link].remote_pads[0].entity = sink->id;
- source->links[source_link].remote_pads[0].pad = sink_link;
- source->links[source_link].remote_pads[0].active = active;
- sink->links[sink_link].remote_pads[0].entity = source->id;
- sink->links[sink_link].remote_pads[0].pad = source_link;
- sink->links[sink_link].remote_pads[0].active = active;
-}
+extern int v4l2_entity_init(struct v4l2_entity *entity, u8 num_pads,
+ struct v4l2_entity_pad *pads, u8 extra_links);
+extern int v4l2_entity_connect(struct v4l2_entity *source, u8 source_pad,
+ struct v4l2_entity *sink, u8 sink_pad, u32 flags);
#endif
===================================================================
@@ -170,9 +170,9 @@ static std::string entity2s(int fd, unsi
return ent.name;
}
-static std::string padtype2s(unsigned type)
+static std::string padtype2s(struct v4l2_mc_pad *pad)
{
- switch (type) {
+ switch (pad->type) {
case V4L2_PAD_TYPE_INPUT:
return "input";
case V4L2_PAD_TYPE_OUTPUT:
@@ -206,7 +206,7 @@ static void show_topology(int fd)
printf("\tType: %s\n", enttype2s(ent.type).c_str());
printf("\tSubtype: %s\n", subtype2s(ent.type, ent.subtype).c_str());
printf("\tPads: %d\n", ent.pads);
- printf("\tTotal Links: %d\n", ent.total_possible_links);
+ printf("\tLinks: %d\n", ent.links);
if (ent.type == V4L2_ENTITY_TYPE_NODE) {
/* Output node-specific properties */
@@ -232,37 +232,40 @@ static void show_topology(int fd)
}
ios.entity = ent.id;
- ios.status = (struct v4l2_mc_io_status *)
- malloc(ent.pads * sizeof(struct v4l2_mc_io_status));
- ios.remote_pads = (struct v4l2_mc_io *)
- malloc(ent.total_possible_links * sizeof(struct v4l2_mc_io));
+ ios.pads = (struct v4l2_mc_pad *)
+ malloc(ent.pads * sizeof(struct v4l2_mc_pad));
+ ios.links = (struct v4l2_mc_link *)
+ malloc(ent.links * sizeof(struct v4l2_mc_link));
if (ioctl(fd, VIDIOC_MC_ENUM_LINKS, &ios) >= 0) {
int i;
int p = 0;
for (i = 0; i < ent.pads; i++) {
+ struct v4l2_mc_pad *pad = &ios.pads[i];
int j;
- printf("\tPad %d (%s): ", i, padtype2s(ios.status[i].type).c_str());
- if (ios.status[i].nr_of_remote_pads == 1) {
- printf("%s/%d %s\n",
- entity2s(fd, ios.remote_pads[p].entity).c_str(),
- ios.remote_pads[p].pad,
- ios.status[i].active_pads == 1 ? "(active)" : "");
+ printf("\tPad %d (%s): ", i, padtype2s(pad).c_str());
+ for (j = 0; j < ent.links; j++) {
+ struct v4l2_mc_link *link = &ios.links[j];
+ struct v4l2_mc_pad *remote;
+
+ if (link->source.index == pad->index)
+ remote = &ios.pads[link->sink.index];
+ else if (link->sink.index == pad->index)
+ remote = &ios.pads[link->source.index];
+ else
+ continue;
+
+ printf("\t\t\t%s %s/%d %s\n",
+ remote->type == V4L2_PAD_TYPE_INPUT ? "->" : "<-",
+ entity2s(fd, remote->entity).c_str(),
+ remote->index,
+ link->flags & V4L2_LINK_FLAG_ACTIVE ? "(active)" : "");
}
- else {
- for (j = 0; j < ios.status[i].nr_of_remote_pads; j++) {
- printf("\t\t\t%s/%d %s\n",
- entity2s(fd, ios.remote_pads[p+j].entity).c_str(),
- ios.remote_pads[p+j].pad,
- (ios.status[i].active_pads & (1 << j)) ? "(active)" : "");
- }
- }
- p += ios.status[i].nr_of_remote_pads;
}
}
- free(ios.status);
- free(ios.remote_pads);
+ free(ios.pads);
+ free(ios.links);
printf("\n");
}
}
@@ -287,33 +290,25 @@ static void dot_topology(int fd)
printf("\tn%08x [label=\"%s\",shape=%s]\n", ent.id, ent.name,
ent.type == V4L2_ENTITY_TYPE_NODE ? "oval" : "box");
ios.entity = ent.id;
- ios.status = (struct v4l2_mc_io_status *)
- malloc(ent.pads * sizeof(struct v4l2_mc_io_status));
- ios.remote_pads = (struct v4l2_mc_io *)
- malloc(ent.total_possible_links * sizeof(struct v4l2_mc_io));
+ ios.pads = (struct v4l2_mc_pad *)
+ malloc(ent.pads * sizeof(struct v4l2_mc_pad));
+ ios.links = (struct v4l2_mc_link *)
+ malloc(ent.links * sizeof(struct v4l2_mc_link));
if (ioctl(fd, VIDIOC_MC_ENUM_LINKS, &ios) >= 0) {
int i;
- int p = 0;
- for (i = 0; i < ent.pads; i++) {
- int j;
-
- if (ios.status[i].type != V4L2_PAD_TYPE_OUTPUT) {
- p += ios.status[i].nr_of_remote_pads;
+ for (i = 0; i < ent.links; i++) {
+ if (ios.links[i].source.entity != ent.id)
continue;
- }
- for (j = 0; j < ios.status[i].nr_of_remote_pads; j++) {
- printf("\tn%08x -> n%08x ", ent.id, ios.remote_pads[p+j].entity);
- if (!(ios.status[i].active_pads & (1 << j)))
+ printf("\tn%08x -> n%08x ", ent.id, ios.links[i].sink.entity);
+ if (!(ios.links[i].flags & V4L2_LINK_FLAG_ACTIVE))
printf("[style=dashed]");
printf("\n");
- }
- p += ios.status[i].nr_of_remote_pads;
}
}
- free(ios.status);
- free(ios.remote_pads);
+ free(ios.pads);
+ free(ios.links);
}
printf("}\n");
}