[PATCH 2/4] Implement compound control get support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
---
 yavta.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 116 insertions(+), 42 deletions(-)

diff --git a/yavta.c b/yavta.c
index af565245f87b..360c53fc77c5 100644
--- a/yavta.c
+++ b/yavta.c
@@ -438,12 +438,14 @@ static int query_control(struct device *dev, unsigned int id,
 	query->id = id;
 
 	ret = ioctl(dev->fd, VIDIOC_QUERY_EXT_CTRL, query);
-	if (ret < 0 && errno != EINVAL)
+	if (!ret || errno == EINVAL)
+		return ret;
+
+	if (errno != ENOTTY) {
 		printf("unable to query control 0x%8.8x: %s (%d).\n",
 		       id, strerror(errno), errno);
-
-	if (!ret || errno != ENOTTY)
 		return ret;
+	}
 
 	/*
 	 * If VIDIOC_QUERY_EXT_CTRL isn't available emulate it using
@@ -478,6 +480,7 @@ static int get_control(struct device *dev,
 		       struct v4l2_ext_control *ctrl)
 {
 	struct v4l2_ext_controls ctrls;
+	struct v4l2_control old;
 	int ret;
 
 	memset(&ctrls, 0, sizeof(ctrls));
@@ -489,34 +492,28 @@ static int get_control(struct device *dev,
 
 	ctrl->id = query->id;
 
-	if (query->type == V4L2_CTRL_TYPE_STRING) {
-		ctrl->string = malloc(query->maximum + 1);
-		if (ctrl->string == NULL)
+	if (query->flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) {
+		ctrl->size = query->elems * query->elem_size;
+		ctrl->ptr = malloc(ctrl->size);
+		if (ctrl->ptr == NULL)
 			return -ENOMEM;
-
-		ctrl->size = query->maximum + 1;
 	}
 
 	ret = ioctl(dev->fd, VIDIOC_G_EXT_CTRLS, &ctrls);
 	if (ret != -1)
 		return 0;
 
-	if (query->type != V4L2_CTRL_TYPE_INTEGER64 &&
-	    query->type != V4L2_CTRL_TYPE_STRING &&
-	    (errno == EINVAL || errno == ENOTTY)) {
-		struct v4l2_control old;
+	if (query->flags & V4L2_CTRL_FLAG_HAS_PAYLOAD ||
+	    query->type == V4L2_CTRL_TYPE_INTEGER64 ||
+	    (errno != EINVAL && errno != ENOTTY))
+		return -1;
 
-		old.id = query->id;
-		ret = ioctl(dev->fd, VIDIOC_G_CTRL, &old);
-		if (ret != -1) {
-			ctrl->value = old.value;
-			return 0;
-		}
-	}
+	old.id = query->id;
+	ret = ioctl(dev->fd, VIDIOC_G_CTRL, &old);
+	if (ret != -1)
+		ctrl->value = old.value;
 
-	printf("unable to get control 0x%8.8x: %s (%d).\n",
-		query->id, strerror(errno), errno);
-	return -1;
+	return ret;
 }
 
 static void set_control(struct device *dev, unsigned int id,
@@ -1111,12 +1108,75 @@ static void video_query_menu(struct device *dev,
 	};
 }
 
+static void video_print_control_array(const struct v4l2_query_ext_ctrl *query,
+				      struct v4l2_ext_control *ctrl)
+{
+	unsigned int i;
+
+	printf("{");
+
+	for (i = 0; i < query->elems; ++i) {
+		switch (query->type) {
+		case V4L2_CTRL_TYPE_U8:
+			printf("%u", ctrl->p_u8[i]);
+			break;
+		case V4L2_CTRL_TYPE_U16:
+			printf("%u", ctrl->p_u16[i]);
+			break;
+		case V4L2_CTRL_TYPE_U32:
+			printf("%u", ctrl->p_u32[i]);
+			break;
+		}
+
+		if (i != query->elems - 1)
+			printf(", ");
+	}
+
+	printf("}");
+}
+
+static void video_print_control_value(const struct v4l2_query_ext_ctrl *query,
+				      struct v4l2_ext_control *ctrl)
+{
+	if (query->nr_of_dims == 0) {
+		switch (query->type) {
+		case V4L2_CTRL_TYPE_INTEGER:
+		case V4L2_CTRL_TYPE_BOOLEAN:
+		case V4L2_CTRL_TYPE_MENU:
+		case V4L2_CTRL_TYPE_INTEGER_MENU:
+			printf("%d", ctrl->value);
+			break;
+		case V4L2_CTRL_TYPE_BITMASK:
+			printf("0x%08x", ctrl->value);
+			break;
+		case V4L2_CTRL_TYPE_INTEGER64:
+			printf("%lld", ctrl->value64);
+			break;
+		case V4L2_CTRL_TYPE_STRING:
+			printf("%s", ctrl->string);
+			break;
+		}
+
+		return;
+	}
+
+	switch (query->type) {
+	case V4L2_CTRL_TYPE_U8:
+	case V4L2_CTRL_TYPE_U16:
+	case V4L2_CTRL_TYPE_U32:
+		video_print_control_array(query, ctrl);
+		break;
+	default:
+		printf("unsupported");
+		break;
+	}
+}
+
 static int video_print_control(struct device *dev, unsigned int id, bool full)
 {
 	struct v4l2_ext_control ctrl;
 	struct v4l2_query_ext_ctrl query;
-	char sval[24];
-	char *current = sval;
+	unsigned int i;
 	int ret;
 
 	ret = query_control(dev, id, &query);
@@ -1131,25 +1191,39 @@ static int video_print_control(struct device *dev, unsigned int id, bool full)
 		return query.id;
 	}
 
-	ret = get_control(dev, &query, &ctrl);
-	if (ret < 0)
-		strcpy(sval, "n/a");
-	else if (query.type == V4L2_CTRL_TYPE_INTEGER64)
-		sprintf(sval, "%lld", ctrl.value64);
-	else if (query.type == V4L2_CTRL_TYPE_STRING)
-		current = ctrl.string;
-	else
-		sprintf(sval, "%d", ctrl.value);
-
-	if (full)
-		printf("control 0x%08x `%s' min %lld max %lld step %lld default %lld current %s.\n",
+	if (full) {
+		printf("control 0x%08x `%s' min %lld max %lld step %lld default %lld ",
 			query.id, query.name, query.minimum, query.maximum,
-			query.step, query.default_value, current);
-	else
-		printf("control 0x%08x current %s.\n", query.id, current);
+			query.step, query.default_value);
+		if (query.nr_of_dims) {
+			for (i = 0; i < query.nr_of_dims; ++i)
+				printf("[%u]", query.dims[i]);
+			printf(" ");
+		}
+	} else {
+		printf("control 0x%08x ", query.id);
+	}
+
+	if (query.type == V4L2_CTRL_TYPE_BUTTON) {
+		/* Button controls have no current value. */
+		printf("\n");
+		return query.id;
+	}
+
+	printf("current ");
+
+	ret = get_control(dev, &query, &ctrl);
+	if (ret < 0) {
+		printf("n/a\n");
+		printf("unable to get control 0x%8.8x: %s (%d).\n",
+			query.id, strerror(errno), errno);
+	} else {
+		video_print_control_value(&query, &ctrl);
+		printf("\n");
+	}
 
-	if (query.type == V4L2_CTRL_TYPE_STRING)
-		free(ctrl.string);
+	if ((query.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) && ctrl.ptr)
+		free(ctrl.ptr);
 
 	if (!full)
 		return query.id;
@@ -1175,7 +1249,7 @@ static void video_list_controls(struct device *dev)
 #else
 	id = 0;
 	while (1) {
-		id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+		id |= V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
 #endif
 
 		ret = video_print_control(dev, id, true);
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux