Fall back to regular S_CTRL / G_CTRL if extended controls aren't available. Also don't try to get value for classes. Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxx> --- yavta.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 100 insertions(+), 30 deletions(-) diff --git a/yavta.c b/yavta.c index af6f3be..d3a4a0e 100644 --- a/yavta.c +++ b/yavta.c @@ -230,40 +230,104 @@ static void video_close(struct device *dev) close(dev->fd); } -static void uvc_get_control(struct device *dev, unsigned int id) +static unsigned int get_control_type(struct device *dev, unsigned int id) { - struct v4l2_control ctrl; + struct v4l2_queryctrl query; int ret; + memset(&query, 0, sizeof(query)); + + query.id = id; + ret = ioctl(dev->fd, VIDIOC_QUERYCTRL, &query); + if (ret == -1) + return V4L2_CTRL_TYPE_INTEGER; + + return query.type; +} + +static int get_control(struct device *dev, unsigned int id, int type, + int64_t *val) +{ + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + int ret; + + memset(&ctrls, 0, sizeof(ctrls)); + memset(&ctrl, 0, sizeof(ctrl)); + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id); + ctrls.count = 1; + ctrls.controls = &ctrl; + ctrl.id = id; - ret = ioctl(dev->fd, VIDIOC_G_CTRL, &ctrl); - if (ret < 0) { - printf("unable to get control: %s (%d).\n", - strerror(errno), errno); - return; + ret = ioctl(dev->fd, VIDIOC_G_EXT_CTRLS, &ctrls); + if (ret != -1) { + if (type == V4L2_CTRL_TYPE_INTEGER64) + *val = ctrl.value64; + else + *val = ctrl.value; + return 0; + } + if (errno == EINVAL || errno == ENOTTY) { + struct v4l2_control old; + + old.id = id; + ret = ioctl(dev->fd, VIDIOC_G_CTRL, &old); + if (ret != -1) { + *val = old.value; + return 0; + } } - printf("Control 0x%08x value %u\n", id, ctrl.value); + printf("unable to get control 0x%8.8x: %s (%d).\n", + id, strerror(errno), errno); + return -1; } -static void uvc_set_control(struct device *dev, unsigned int id, int value) +static void set_control(struct device *dev, unsigned int id, int type, + int64_t val) { - struct v4l2_control ctrl; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + int is_64 = type == V4L2_CTRL_TYPE_INTEGER64; + int64_t old_val = val; int ret; + + memset(&ctrls, 0, sizeof(ctrls)); + memset(&ctrl, 0, sizeof(ctrl)); + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id); + ctrls.count = 1; + ctrls.controls = &ctrl; ctrl.id = id; - ctrl.value = value; + if (is_64) + ctrl.value64 = val; + else + ctrl.value = val; - ret = ioctl(dev->fd, VIDIOC_S_CTRL, &ctrl); - if (ret < 0) { - printf("unable to set control: %s (%d).\n", - strerror(errno), errno); + ret = ioctl(dev->fd, VIDIOC_S_EXT_CTRLS, &ctrls); + if (ret != -1) { + if (is_64) + val = ctrl.value64; + else + val = ctrl.value; + } else if (errno == EINVAL || errno == ENOTTY) { + struct v4l2_control old; + + old.id = id; + ret = ioctl(dev->fd, VIDIOC_S_CTRL, &old); + if (ret != -1) + val = old.value; + } + if (ret == -1) { + printf("unable to set control 0x%8.8x: %s (%d).\n", + id, strerror(errno), errno); return; } - - printf("Control 0x%08x set to %u, is %u\n", id, value, - ctrl.value); + + printf("Control 0x%08x set to %lld, is %lld\n", id, old_val, val); } static int video_get_format(struct device *dev) @@ -567,9 +631,9 @@ static void video_query_menu(struct device *dev, struct v4l2_queryctrl *query) static void video_list_controls(struct device *dev) { struct v4l2_queryctrl query; - struct v4l2_control ctrl; unsigned int nctrls = 0; - char value[12]; + char value[24]; + int64_t val64; int ret; #ifndef V4L2_CTRL_FLAG_NEXT_CTRL @@ -589,18 +653,17 @@ static void video_list_controls(struct device *dev) if (query.flags & V4L2_CTRL_FLAG_DISABLED) continue; - ctrl.id = query.id; - ret = ioctl(dev->fd, VIDIOC_G_CTRL, &ctrl); - if (ret < 0) - strcpy(value, "n/a"); - else - sprintf(value, "%d", ctrl.value); - if (query.type == V4L2_CTRL_TYPE_CTRL_CLASS) { printf("--- %s (class 0x%08x) ---\n", query.name, query.id); continue; } + ret = get_control(dev, query.id, query.type, &val64); + if (ret < 0) + strcpy(value, "n/a"); + else + sprintf(value, "%lld", val64); + printf("control 0x%08x `%s' min %d max %d step %d default %d current %s.\n", query.id, query.name, query.minimum, query.maximum, query.step, query.default_value, value); @@ -1401,10 +1464,17 @@ int main(int argc, char *argv[]) dev.memtype = memtype; - if (do_get_control) - uvc_get_control(&dev, ctrl_name); + if (do_get_control) { + int64_t val; + ret = get_control(&dev, ctrl_name, + get_control_type(&dev, ctrl_name), &val); + if (ret >= 0) + printf("Control 0x%08x value %lld\n", ctrl_name, val); + } + if (do_set_control) - uvc_set_control(&dev, ctrl_name, ctrl_value); + set_control(&dev, ctrl_name, get_control_type(&dev, ctrl_name), + ctrl_value); if (do_list_controls) video_list_controls(&dev); -- 1.7.2.5 -- 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