From 1fd84a5fba5b64a2c8731c979972d9da591eafef Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 25 May 2009 20:59:10 +0200 Subject: [PATCH] libv4l: Fix a few small issues with V4L2_CTRL_FLAG_NEXT_CTRL handling From: Hans de Goede libv4l: Fix a few small issues with V4L2_CTRL_FLAG_NEXT_CTRL handling Priority: normal Signed-off-by: Hans de Goede --- lib/libv4lconvert/control/libv4lcontrol-priv.h | 5 +++- lib/libv4lconvert/control/libv4lcontrol.c | 39 +++++++++++++++++++------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/libv4lconvert/control/libv4lcontrol-priv.h b/lib/libv4lconvert/control/libv4lcontrol-priv.h index 14e4fe8..14481a9 100644 --- a/lib/libv4lconvert/control/libv4lcontrol-priv.h +++ b/lib/libv4lconvert/control/libv4lcontrol-priv.h @@ -24,9 +24,12 @@ #define V4LCONTROL_SHM_SIZE 4096 +#define V4LCONTROL_SUPPORTS_NEXT_CTRL 0x01 + struct v4lcontrol_data { int fd; /* Device fd */ - int flags; /* Special flags for this device */ + int flags; /* Flags for this device */ + int priv_flags; /* Internal use only flags */ int controls; /* Which controls to use for this device */ unsigned int *shm_values; /* shared memory control value store */ unsigned int old_values[V4LCONTROL_COUNT]; /* for controls_changed() */ diff --git a/lib/libv4lconvert/control/libv4lcontrol.c b/lib/libv4lconvert/control/libv4lcontrol.c index edf8648..3f57afb 100644 --- a/lib/libv4lconvert/control/libv4lcontrol.c +++ b/lib/libv4lconvert/control/libv4lcontrol.c @@ -223,6 +223,10 @@ struct v4lcontrol_data *v4lcontrol_create(int fd, int always_needs_conversion) if ((s = getenv("LIBV4LCONTROL_FLAGS"))) data->flags = strtol(s, NULL, 0); + ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL; + if (syscall(SYS_ioctl, data->fd, VIDIOC_QUERYCTRL, &ctrl) == 0) + data->priv_flags |= V4LCONTROL_SUPPORTS_NEXT_CTRL; + /* If the device always needs conversion, we can add fake controls at no cost (no cost when not activated by the user that is) */ if (always_needs_conversion || v4lcontrol_needs_conversion(data)) { @@ -350,6 +354,17 @@ static const struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = { }, }; +static void v4lcontrol_copy_queryctrl(struct v4lcontrol_data *data, + struct v4l2_queryctrl *ctrl, int i) +{ + memcpy(ctrl, &fake_controls[i], sizeof(struct v4l2_queryctrl)); + + /* Hmm, not pretty */ + if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE && + (data->flags & V4LCONTROL_WANTS_WB)) + ctrl->default_value = 1; +} + int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data *data, void *arg) { int i; @@ -361,28 +376,32 @@ int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data *data, void *arg) for (i = 0; i < V4LCONTROL_COUNT; i++) if ((data->controls & (1 << i)) && ctrl->id == fake_controls[i].id) { - memcpy(ctrl, &fake_controls[i], sizeof(struct v4l2_queryctrl)); - /* Hmm, not pretty */ - if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE && - (data->flags & V4LCONTROL_WANTS_WB)) - ctrl->default_value = 1; - + v4lcontrol_copy_queryctrl(data, ctrl, i); return 0; } /* find out what the kernel driver would respond. */ retval = syscall(SYS_ioctl, data->fd, VIDIOC_QUERYCTRL, arg); - /* if any of our controls have an id > orig_id but less than - ctrl->id then return that control instead. */ - if (orig_id & V4L2_CTRL_FLAG_NEXT_CTRL) + if ((data->priv_flags & V4LCONTROL_SUPPORTS_NEXT_CTRL) && + (orig_id & V4L2_CTRL_FLAG_NEXT_CTRL)) { + /* If the hardware has no more controls check if we still have any + fake controls with a higher id then the hardware's highest */ + if (retval) + ctrl->id = V4L2_CTRL_FLAG_NEXT_CTRL; + + /* If any of our controls have an id > orig_id but less than + ctrl->id then return that control instead. Note we do not + break when we have a match, but keep iterating, so that + we end up with the fake ctrl with the lowest CID > orig_id. */ for (i = 0; i < V4LCONTROL_COUNT; i++) if ((data->controls & (1 << i)) && (fake_controls[i].id > (orig_id & ~V4L2_CTRL_FLAG_NEXT_CTRL)) && (fake_controls[i].id <= ctrl->id)) { - memcpy(ctrl, &fake_controls[i], sizeof(struct v4l2_queryctrl)); + v4lcontrol_copy_queryctrl(data, ctrl, i); retval = 0; } + } return retval; } -- 2.7.4