Hi Sakari,

On Wed, Feb 20, 2019 at 04:06:43PM +0200, Sakari Ailus wrote:
> 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?

Nasty one :-( I'll do so.

> > +           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.

Isn't that a matter of taste ? :-)

> > +
> > +   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?

Does your compiler warn ?

> > +                   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?

Good idea.

> > +           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,

Laurent Pinchart

Reply via email to