diff options
author | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-05-25 20:59:10 +0200 |
---|---|---|
committer | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-05-25 20:59:10 +0200 |
commit | 7b1960c67fb907d4885734c31a41898a9fe6dfa7 (patch) | |
tree | 08a71b25fb926793b7575e70421f58b28ace41aa | |
parent | 2ffc360be1c38ab86399d6d574ee7cc0671c03d6 (diff) | |
download | mediapointer-dvb-s2-7b1960c67fb907d4885734c31a41898a9fe6dfa7.tar.gz mediapointer-dvb-s2-7b1960c67fb907d4885734c31a41898a9fe6dfa7.tar.bz2 |
libv4l: Fix a few small issues with V4L2_CTRL_FLAG_NEXT_CTRL handling
From: Hans de Goede <hdegoede@redhat.com>
libv4l: Fix a few small issues with V4L2_CTRL_FLAG_NEXT_CTRL handling
Priority: normal
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h | 5 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 39 |
2 files changed, 33 insertions, 11 deletions
diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h index 14e4fe838..14481a9a2 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h +++ b/v4l2-apps/libv4l/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/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index edf86483d..3f57afb72 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/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; } |