Hi Laurent,

On Wed, Feb 20, 2019 at 02:51:19PM +0200, Laurent Pinchart wrote:
> Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> ---
>  yavta.c | 154 ++++++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 115 insertions(+), 39 deletions(-)
> 
> diff --git a/yavta.c b/yavta.c
> index eb50d592736f..6428c22f88d7 100644
> --- a/yavta.c
> +++ b/yavta.c
> @@ -529,6 +529,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));
> @@ -540,34 +541,32 @@ 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) {

This breaks string controls for kernels that don't have
V4L2_CTRL_FLAG_HAS_PAYLOAD. As you still support kernels that have no
V4L2_CTRL_FLAG_NEXT_CTRL, how about checking for string type specifically?

> +             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)
> +             free(ctrl->ptr);
>  
> -             old.id = query->id;
> -             ret = ioctl(dev->fd, VIDIOC_G_CTRL, &old);
> -             if (ret != -1) {
> -                     ctrl->value = old.value;
> -                     return 0;
> -             }
> -     }
> +     if (query->flags & V4L2_CTRL_FLAG_HAS_PAYLOAD ||
> +         query->type == V4L2_CTRL_TYPE_INTEGER64 ||
> +         (errno != EINVAL && errno != ENOTTY))
> +             return -errno;
>  
> -     printf("unable to get control 0x%8.8x: %s (%d).\n",
> -             query->id, strerror(errno), errno);
> -     return -1;
> +     old.id = query->id;
> +     ret = ioctl(dev->fd, VIDIOC_G_CTRL, &old);
> +     if (ret < 0)
> +             return -errno;
> +
> +     ctrl->value = old.value;
> +     return 0;
>  }
>  
>  static void set_control(struct device *dev, unsigned int id,
> @@ -1170,7 +1169,7 @@ static int video_for_each_control(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 = query_control(dev, id, &query);
> @@ -1215,13 +1214,76 @@ 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("{");

A space would be nice after the opening brace, also before the closing one.

> +
> +     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);

A cast to unsigned here?

> +                     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");

How about printing the unsupported type?

> +             break;
> +     }
> +}
> +
>  static int video_print_control(struct device *dev,
>                              const struct v4l2_query_ext_ctrl *query,
>                              bool full)
>  {
>       struct v4l2_ext_control ctrl;
> -     char sval[24];
> -     char *current = sval;
> +     unsigned int i;
>       int ret;
>  
>       if (query->flags & V4L2_CTRL_FLAG_DISABLED)
> @@ -1232,25 +1294,39 @@ static int video_print_control(struct device *dev,
>               return 0;
>       }
>  
> -     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_STRING)
> -             free(ctrl.string);
> +     if (query->type == V4L2_CTRL_TYPE_BUTTON) {
> +             /* Button controls have no current value. */
> +             printf("\n");
> +             return 1;
> +     }
> +
> +     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->flags & V4L2_CTRL_FLAG_HAS_PAYLOAD)
> +             free(ctrl.ptr);
>  
>       if (!full)
>               return 1;

-- 
Regards,

Sakari Ailus

Reply via email to