From b7284bb0be49441805ae7db0fc419ab7ee882bff Mon Sep 17 00:00:00 2001 From: Ramakrishnan Muthukrishnan Date: Thu, 19 Jun 2014 14:22:57 -0300 Subject: [media] media: v4l2-core: remove the use of V4L2_FL_USE_FH_PRIO flag Since all the drivers that use `struct v4l2_fh' use the core priority checking instead of doing it themselves, this flag can be removed. This patch removes the usage of the flag from v4l2-core. Signed-off-by: Ramakrishnan Muthukrishnan Reviewed-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 16bffd851bf9..8d4a25d62e47 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2190,7 +2190,6 @@ static long __video_do_ioctl(struct file *file, const struct v4l2_ioctl_info *info; void *fh = file->private_data; struct v4l2_fh *vfh = NULL; - int use_fh_prio = 0; int debug = vfd->debug; long ret = -ENOTTY; @@ -2200,10 +2199,8 @@ static long __video_do_ioctl(struct file *file, return ret; } - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) vfh = file->private_data; - use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); - } if (v4l2_is_known_ioctl(cmd)) { info = &v4l2_ioctls[_IOC_NR(cmd)]; @@ -2212,7 +2209,7 @@ static long __video_do_ioctl(struct file *file, !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler)) goto done; - if (use_fh_prio && (info->flags & INFO_FL_PRIO)) { + if (vfh && (info->flags & INFO_FL_PRIO)) { ret = v4l2_prio_check(vfd->prio, vfh->prio); if (ret) goto done; @@ -2237,7 +2234,7 @@ static long __video_do_ioctl(struct file *file, ret = -ENOTTY; } else { ret = ops->vidioc_default(file, fh, - use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, + vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, cmd, arg); } -- cgit v1.2.3 From e6bee3685e732df82f48698254a36754cf15f0b0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 10 Jun 2014 04:22:06 -0300 Subject: [media] v4l2: integrate support for VIDIOC_QUERY_EXT_CTRL Add the v4l2 core plumbing for the new VIDIOC_QUERY_EXT_CTRL ioctl. Signed-off-by: Hans Verkuil Reviewed-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 2 ++ drivers/media/v4l2-core/v4l2-ioctl.c | 33 +++++++++++++++++++++++++++++++++ drivers/media/v4l2-core/v4l2-subdev.c | 3 +++ include/media/v4l2-ioctl.h | 2 ++ 4 files changed, 40 insertions(+) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 35698aa377f5..1cfdbdd034bc 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -575,6 +575,8 @@ static void determine_valid_ioctls(struct video_device *vdev) be valid if the filehandle passed the control handler. */ if (vdev->ctrl_handler || ops->vidioc_queryctrl) set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls); + if (vdev->ctrl_handler || ops->vidioc_query_ext_ctrl) + set_bit(_IOC_NR(VIDIOC_QUERY_EXT_CTRL), valid_ioctls); if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls) set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls); if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8d4a25d62e47..c38a6208d2cd 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -525,6 +525,21 @@ static void v4l_print_queryctrl(const void *arg, bool write_only) p->step, p->default_value, p->flags); } +static void v4l_print_query_ext_ctrl(const void *arg, bool write_only) +{ + const struct v4l2_query_ext_ctrl *p = arg; + + pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, " + "step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, " + "nr_of_dims=%u, dims=%u,%u,%u,%u,%u,%u,%u,%u\n", + p->id, p->type, (int)sizeof(p->name), p->name, + p->minimum, p->maximum, + p->step, p->default_value, p->flags, + p->elem_size, p->elems, p->nr_of_dims, + p->dims[0], p->dims[1], p->dims[2], p->dims[3], + p->dims[4], p->dims[5], p->dims[6], p->dims[7]); +} + static void v4l_print_querymenu(const void *arg, bool write_only) { const struct v4l2_querymenu *p = arg; @@ -1561,6 +1576,23 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, return -ENOTTY; } +static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_query_ext_ctrl *p = arg; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + + if (vfh && vfh->ctrl_handler) + return v4l2_query_ext_ctrl(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_query_ext_ctrl(vfd->ctrl_handler, p); + if (ops->vidioc_query_ext_ctrl) + return ops->vidioc_query_ext_ctrl(file, fh, p); + return -ENOTTY; +} + static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -2121,6 +2153,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)), IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0), IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)), + IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 058c1a6e8392..b984f33de7f4 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -139,6 +139,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_QUERYCTRL: return v4l2_queryctrl(vfh->ctrl_handler, arg); + case VIDIOC_QUERY_EXT_CTRL: + return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg); + case VIDIOC_QUERYMENU: return v4l2_querymenu(vfh->ctrl_handler, arg); diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 50cf7c110a70..53605f0f9903 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -158,6 +158,8 @@ struct v4l2_ioctl_ops { /* Control handling */ int (*vidioc_queryctrl) (struct file *file, void *fh, struct v4l2_queryctrl *a); + int (*vidioc_query_ext_ctrl) (struct file *file, void *fh, + struct v4l2_query_ext_ctrl *a); int (*vidioc_g_ctrl) (struct file *file, void *fh, struct v4l2_control *a); int (*vidioc_s_ctrl) (struct file *file, void *fh, -- cgit v1.2.3 From 0176077a813933a547b7a913377a87d615b7c108 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 27 Apr 2014 03:22:17 -0300 Subject: [media] v4l2-ctrls: create type_ops Since compound controls can have non-standard types we need to be able to do type-specific checks etc. In order to make that easy type operations are added. There are four operations: - equal: check if two values are equal - init: initialize a value - log: log the value - validate: validate a new value The v4l2_ctrl struct adds p_new and p_cur unions at the end of the struct. This union provides a standard way of accessing control types through a pointer, which greatly simplifies internal control processing. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 273 ++++++++++++++++++++++------------- drivers/media/v4l2-core/v4l2-ioctl.c | 5 +- include/media/v4l2-ctrls.h | 37 +++++ 3 files changed, 212 insertions(+), 103 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index d5cd1aab970b..09e2c3a2c5c2 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1161,6 +1161,149 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes) v4l2_event_queue_fh(sev->fh, &ev); } +static bool std_equal(const struct v4l2_ctrl *ctrl, + union v4l2_ctrl_ptr ptr1, + union v4l2_ctrl_ptr ptr2) +{ + switch (ctrl->type) { + case V4L2_CTRL_TYPE_BUTTON: + return false; + case V4L2_CTRL_TYPE_STRING: + /* strings are always 0-terminated */ + return !strcmp(ptr1.p_char, ptr2.p_char); + case V4L2_CTRL_TYPE_INTEGER64: + return *ptr1.p_s64 == *ptr2.p_s64; + default: + if (ctrl->is_ptr) + return !memcmp(ptr1.p, ptr2.p, ctrl->elem_size); + return *ptr1.p_s32 == *ptr2.p_s32; + } +} + +static void std_init(const struct v4l2_ctrl *ctrl, + union v4l2_ctrl_ptr ptr) +{ + switch (ctrl->type) { + case V4L2_CTRL_TYPE_STRING: + memset(ptr.p_char, ' ', ctrl->minimum); + ptr.p_char[ctrl->minimum] = '\0'; + break; + case V4L2_CTRL_TYPE_INTEGER64: + *ptr.p_s64 = ctrl->default_value; + break; + case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_INTEGER_MENU: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_BITMASK: + case V4L2_CTRL_TYPE_BOOLEAN: + *ptr.p_s32 = ctrl->default_value; + break; + default: + break; + } +} + +static void std_log(const struct v4l2_ctrl *ctrl) +{ + union v4l2_ctrl_ptr ptr = ctrl->p_cur; + + switch (ctrl->type) { + case V4L2_CTRL_TYPE_INTEGER: + pr_cont("%d", *ptr.p_s32); + break; + case V4L2_CTRL_TYPE_BOOLEAN: + pr_cont("%s", *ptr.p_s32 ? "true" : "false"); + break; + case V4L2_CTRL_TYPE_MENU: + pr_cont("%s", ctrl->qmenu[*ptr.p_s32]); + break; + case V4L2_CTRL_TYPE_INTEGER_MENU: + pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]); + break; + case V4L2_CTRL_TYPE_BITMASK: + pr_cont("0x%08x", *ptr.p_s32); + break; + case V4L2_CTRL_TYPE_INTEGER64: + pr_cont("%lld", *ptr.p_s64); + break; + case V4L2_CTRL_TYPE_STRING: + pr_cont("%s", ptr.p_char); + break; + default: + pr_cont("unknown type %d", ctrl->type); + break; + } +} + +/* Round towards the closest legal value */ +#define ROUND_TO_RANGE(val, offset_type, ctrl) \ +({ \ + offset_type offset; \ + val += (ctrl)->step / 2; \ + val = clamp_t(typeof(val), val, \ + (ctrl)->minimum, (ctrl)->maximum); \ + offset = (val) - (ctrl)->minimum; \ + offset = (ctrl)->step * (offset / (ctrl)->step); \ + val = (ctrl)->minimum + offset; \ + 0; \ +}) + +/* Validate a new control */ +static int std_validate(const struct v4l2_ctrl *ctrl, + union v4l2_ctrl_ptr ptr) +{ + size_t len; + + switch (ctrl->type) { + case V4L2_CTRL_TYPE_INTEGER: + return ROUND_TO_RANGE(*ptr.p_s32, u32, ctrl); + case V4L2_CTRL_TYPE_INTEGER64: + return ROUND_TO_RANGE(*ptr.p_s64, u64, ctrl); + + case V4L2_CTRL_TYPE_BOOLEAN: + *ptr.p_s32 = !!*ptr.p_s32; + return 0; + + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER_MENU: + if (*ptr.p_s32 < ctrl->minimum || *ptr.p_s32 > ctrl->maximum) + return -ERANGE; + if (ctrl->menu_skip_mask & (1 << *ptr.p_s32)) + return -EINVAL; + if (ctrl->type == V4L2_CTRL_TYPE_MENU && + ctrl->qmenu[*ptr.p_s32][0] == '\0') + return -EINVAL; + return 0; + + case V4L2_CTRL_TYPE_BITMASK: + *ptr.p_s32 &= ctrl->maximum; + return 0; + + case V4L2_CTRL_TYPE_BUTTON: + case V4L2_CTRL_TYPE_CTRL_CLASS: + *ptr.p_s32 = 0; + return 0; + + case V4L2_CTRL_TYPE_STRING: + len = strlen(ptr.p_char); + if (len < ctrl->minimum) + return -ERANGE; + if ((len - ctrl->minimum) % ctrl->step) + return -ERANGE; + return 0; + + default: + return -EINVAL; + } +} + +static const struct v4l2_ctrl_type_ops std_type_ops = { + .equal = std_equal, + .init = std_init, + .log = std_log, + .validate = std_validate, +}; + /* Helper function: copy the current control value back to the caller */ static int cur_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) @@ -1344,21 +1487,7 @@ static int cluster_changed(struct v4l2_ctrl *master) if (ctrl == NULL) continue; - switch (ctrl->type) { - case V4L2_CTRL_TYPE_BUTTON: - /* Button controls are always 'different' */ - return 1; - case V4L2_CTRL_TYPE_STRING: - /* strings are always 0-terminated */ - diff = strcmp(ctrl->string, ctrl->cur.string); - break; - case V4L2_CTRL_TYPE_INTEGER64: - diff = ctrl->val64 != ctrl->cur.val64; - break; - default: - diff = ctrl->val != ctrl->cur.val; - break; - } + diff = !ctrl->type_ops->equal(ctrl, ctrl->p_cur, ctrl->p_new); } return diff; } @@ -1399,65 +1528,30 @@ static int check_range(enum v4l2_ctrl_type type, } } -/* Round towards the closest legal value */ -#define ROUND_TO_RANGE(val, offset_type, ctrl) \ -({ \ - offset_type offset; \ - val += (ctrl)->step / 2; \ - val = clamp_t(typeof(val), val, \ - (ctrl)->minimum, (ctrl)->maximum); \ - offset = (val) - (ctrl)->minimum; \ - offset = (ctrl)->step * (offset / (ctrl)->step); \ - val = (ctrl)->minimum + offset; \ - 0; \ -}) - /* Validate a new control */ static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) { - size_t len; + union v4l2_ctrl_ptr ptr; switch (ctrl->type) { case V4L2_CTRL_TYPE_INTEGER: - return ROUND_TO_RANGE(*(s32 *)&c->value, u32, ctrl); - case V4L2_CTRL_TYPE_INTEGER64: - return ROUND_TO_RANGE(*(s64 *)&c->value64, u64, ctrl); - - case V4L2_CTRL_TYPE_BOOLEAN: - c->value = !!c->value; - return 0; - - case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER_MENU: - if (c->value < ctrl->minimum || c->value > ctrl->maximum) - return -ERANGE; - if (ctrl->menu_skip_mask & (1 << c->value)) - return -EINVAL; - if (ctrl->type == V4L2_CTRL_TYPE_MENU && - ctrl->qmenu[c->value][0] == '\0') - return -EINVAL; - return 0; - + case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_BITMASK: - c->value &= ctrl->maximum; - return 0; - + case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_BUTTON: case V4L2_CTRL_TYPE_CTRL_CLASS: - c->value = 0; - return 0; + ptr.p_s32 = &c->value; + return ctrl->type_ops->validate(ctrl, ptr); - case V4L2_CTRL_TYPE_STRING: - len = strlen(c->string); - if (len < ctrl->minimum) - return -ERANGE; - if ((len - ctrl->minimum) % ctrl->step) - return -ERANGE; - return 0; + case V4L2_CTRL_TYPE_INTEGER64: + ptr.p_s64 = &c->value64; + return ctrl->type_ops->validate(ctrl, ptr); default: - return -EINVAL; + ptr.p = c->ptr; + return ctrl->type_ops->validate(ctrl, ptr); } } @@ -1674,6 +1768,7 @@ unlock: /* Add a new control */ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, + const struct v4l2_ctrl_type_ops *type_ops, u32 id, const char *name, enum v4l2_ctrl_type type, s64 min, s64 max, u64 step, s64 def, u32 elem_size, @@ -1731,6 +1826,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, INIT_LIST_HEAD(&ctrl->ev_subs); ctrl->handler = hdl; ctrl->ops = ops; + ctrl->type_ops = type_ops ? type_ops : &std_type_ops; ctrl->id = id; ctrl->name = name; ctrl->type = type; @@ -1751,16 +1847,16 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, ctrl->cur.val = ctrl->val = def; data = &ctrl->cur + 1; - if (ctrl->is_string) { - ctrl->string = data; - ctrl->cur.string = data + elem_size; - - if (ctrl->minimum) - memset(ctrl->cur.string, ' ', ctrl->minimum); - } else if (ctrl->is_ptr) { - ctrl->p = data; - ctrl->cur.p = data + elem_size; + if (ctrl->is_ptr) { + ctrl->p = ctrl->p_new.p = data; + ctrl->p_cur.p = data + elem_size; + } else { + ctrl->p_new.p = &ctrl->val; + ctrl->p_cur.p = &ctrl->cur.val; } + ctrl->type_ops->init(ctrl, ctrl->p_cur); + ctrl->type_ops->init(ctrl, ctrl->p_new); + if (handler_new_ref(hdl, ctrl)) { kfree(ctrl); return NULL; @@ -1804,7 +1900,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, return NULL; } - ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, + ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name, type, min, max, is_menu ? cfg->menu_skip_mask : step, def, cfg->elem_size, @@ -1831,7 +1927,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, handler_set_err(hdl, -EINVAL); return NULL; } - return v4l2_ctrl_new(hdl, ops, id, name, type, + return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, min, max, step, def, 0, flags, NULL, NULL, NULL); } @@ -1864,7 +1960,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, handler_set_err(hdl, -EINVAL); return NULL; } - return v4l2_ctrl_new(hdl, ops, id, name, type, + return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 0, max, mask, def, 0, flags, qmenu, qmenu_int, NULL); } @@ -1896,7 +1992,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, handler_set_err(hdl, -EINVAL); return NULL; } - return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def, + return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, + 0, max, mask, def, 0, flags, qmenu, NULL, NULL); } @@ -1920,7 +2017,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, handler_set_err(hdl, -EINVAL); return NULL; } - return v4l2_ctrl_new(hdl, ops, id, name, type, + return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 0, max, 0, def, 0, flags, NULL, qmenu_int, NULL); } @@ -2104,32 +2201,8 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl, pr_info("%s%s%s: ", prefix, colon, ctrl->name); - switch (ctrl->type) { - case V4L2_CTRL_TYPE_INTEGER: - pr_cont("%d", ctrl->cur.val); - break; - case V4L2_CTRL_TYPE_BOOLEAN: - pr_cont("%s", ctrl->cur.val ? "true" : "false"); - break; - case V4L2_CTRL_TYPE_MENU: - pr_cont("%s", ctrl->qmenu[ctrl->cur.val]); - break; - case V4L2_CTRL_TYPE_INTEGER_MENU: - pr_cont("%lld", ctrl->qmenu_int[ctrl->cur.val]); - break; - case V4L2_CTRL_TYPE_BITMASK: - pr_cont("0x%08x", ctrl->cur.val); - break; - case V4L2_CTRL_TYPE_INTEGER64: - pr_cont("%lld", ctrl->cur.val64); - break; - case V4L2_CTRL_TYPE_STRING: - pr_cont("%s", ctrl->cur.string); - break; - default: - pr_cont("unknown type %d", ctrl->type); - break; - } + ctrl->type_ops->log(ctrl); + if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_GRABBED | V4L2_CTRL_FLAG_VOLATILE)) { diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index c38a6208d2cd..96bc117f66b2 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -531,13 +531,12 @@ static void v4l_print_query_ext_ctrl(const void *arg, bool write_only) pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, " "step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, " - "nr_of_dims=%u, dims=%u,%u,%u,%u,%u,%u,%u,%u\n", + "nr_of_dims=%u, dims=%u,%u,%u,%u\n", p->id, p->type, (int)sizeof(p->name), p->name, p->minimum, p->maximum, p->step, p->default_value, p->flags, p->elem_size, p->elems, p->nr_of_dims, - p->dims[0], p->dims[1], p->dims[2], p->dims[3], - p->dims[4], p->dims[5], p->dims[6], p->dims[7]); + p->dims[0], p->dims[1], p->dims[2], p->dims[3]); } static void v4l_print_querymenu(const void *arg, bool write_only) diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 9024daebdf3b..ddd9fdf1ac1a 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -36,6 +36,19 @@ struct v4l2_subscribed_event; struct v4l2_fh; struct poll_table_struct; +/** union v4l2_ctrl_ptr - A pointer to a control value. + * @p_s32: Pointer to a 32-bit signed value. + * @p_s64: Pointer to a 64-bit signed value. + * @p_char: Pointer to a string. + * @p: Pointer to a compound value. + */ +union v4l2_ctrl_ptr { + s32 *p_s32; + s64 *p_s64; + char *p_char; + void *p; +}; + /** struct v4l2_ctrl_ops - The control operations that the driver has to provide. * @g_volatile_ctrl: Get a new value for this control. Generally only relevant * for volatile (and usually read-only) controls such as a control @@ -54,6 +67,23 @@ struct v4l2_ctrl_ops { int (*s_ctrl)(struct v4l2_ctrl *ctrl); }; +/** struct v4l2_ctrl_type_ops - The control type operations that the driver has to provide. + * @equal: return true if both values are equal. + * @init: initialize the value. + * @log: log the value. + * @validate: validate the value. Return 0 on success and a negative value otherwise. + */ +struct v4l2_ctrl_type_ops { + bool (*equal)(const struct v4l2_ctrl *ctrl, + union v4l2_ctrl_ptr ptr1, + union v4l2_ctrl_ptr ptr2); + void (*init)(const struct v4l2_ctrl *ctrl, + union v4l2_ctrl_ptr ptr); + void (*log)(const struct v4l2_ctrl *ctrl); + int (*validate)(const struct v4l2_ctrl *ctrl, + union v4l2_ctrl_ptr ptr); +}; + typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); /** struct v4l2_ctrl - The control structure. @@ -89,6 +119,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); * value, then the whole cluster is in manual mode. Drivers should * never set this flag directly. * @ops: The control ops. + * @type_ops: The control type ops. * @id: The control ID. * @name: The control name. * @type: The control type. @@ -137,6 +168,7 @@ struct v4l2_ctrl { unsigned int manual_mode_value:8; const struct v4l2_ctrl_ops *ops; + const struct v4l2_ctrl_type_ops *type_ops; u32 id; const char *name; enum v4l2_ctrl_type type; @@ -164,6 +196,9 @@ struct v4l2_ctrl { char *string; void *p; } cur; + + union v4l2_ctrl_ptr p_new; + union v4l2_ctrl_ptr p_cur; }; /** struct v4l2_ctrl_ref - The control reference. @@ -217,6 +252,7 @@ struct v4l2_ctrl_handler { /** struct v4l2_ctrl_config - Control configuration structure. * @ops: The control ops. + * @type_ops: The control type ops. Only needed for compound controls. * @id: The control ID. * @name: The control name. * @type: The control type. @@ -241,6 +277,7 @@ struct v4l2_ctrl_handler { */ struct v4l2_ctrl_config { const struct v4l2_ctrl_ops *ops; + const struct v4l2_ctrl_type_ops *type_ops; u32 id; const char *name; enum v4l2_ctrl_type type; -- cgit v1.2.3 From d52e23813672c3c72f92e7b39c7408d4b9a40a96 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 27 May 2014 09:41:05 -0300 Subject: [media] v4l: Support extending the v4l2_pix_format structure The v4l2_pix_format structure has no reserved field. It is embedded in the v4l2_framebuffer structure which has no reserved fields either, and in the v4l2_format structure which has reserved fields that were not previously required to be zeroed out by applications. To allow extending v4l2_pix_format, inline it in the v4l2_framebuffer structure, and use the priv field as a magic value to indicate that the application has set all v4l2_pix_format extended fields and zeroed all reserved fields following the v4l2_pix_format field in the v4l2_format structure. The availability of this API extension is reported to userspace through the new V4L2_CAP_EXT_PIX_FORMAT capability flag. Just checking that the priv field is still set to the magic value at [GS]_FMT return wouldn't be enough, as older kernels don't zero the priv field on return. To simplify the internal API towards drivers zero the extended fields and set the priv field to the magic value for applications not aware of the extensions. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/Makefile | 2 +- Documentation/DocBook/media/v4l/pixfmt.xml | 25 ++++++++- Documentation/DocBook/media/v4l/v4l2.xml | 8 +++ Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml | 12 ++-- .../DocBook/media/v4l/vidioc-querycap.xml | 6 ++ drivers/media/parport/bw-qcam.c | 2 - drivers/media/pci/cx18/cx18-ioctl.c | 1 - drivers/media/pci/cx25821/cx25821-video.c | 3 - drivers/media/pci/ivtv/ivtv-ioctl.c | 3 - drivers/media/pci/meye/meye.c | 2 - drivers/media/pci/saa7134/saa7134-empress.c | 3 - drivers/media/pci/saa7134/saa7134-video.c | 2 - drivers/media/pci/sta2x11/sta2x11_vip.c | 1 - drivers/media/platform/coda.c | 2 - drivers/media/platform/davinci/vpif_display.c | 1 - drivers/media/platform/mem2mem_testdev.c | 1 - drivers/media/platform/omap/omap_vout.c | 2 - drivers/media/platform/sh_veu.c | 2 - drivers/media/platform/vino.c | 5 -- drivers/media/platform/vivi.c | 1 - drivers/media/usb/cx231xx/cx231xx-417.c | 2 - drivers/media/usb/cx231xx/cx231xx-video.c | 2 - drivers/media/usb/gspca/gspca.c | 8 +-- drivers/media/usb/hdpvr/hdpvr-video.c | 1 - drivers/media/usb/stkwebcam/stk-webcam.c | 2 - drivers/media/usb/tlg2300/pd-video.c | 1 - drivers/media/usb/tm6000/tm6000-video.c | 2 - drivers/media/usb/zr364xx/zr364xx.c | 3 - drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 19 +++++-- drivers/media/v4l2-core/v4l2-ioctl.c | 65 ++++++++++++++++++++-- include/uapi/linux/videodev2.h | 15 ++++- 31 files changed, 134 insertions(+), 70 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile index 639e74857968..df2962d9e11e 100644 --- a/Documentation/DocBook/media/Makefile +++ b/Documentation/DocBook/media/Makefile @@ -174,7 +174,7 @@ FILENAME = \ DOCUMENTED = \ -e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1v4l2_mpeg_cx2341x_video_\2<\/link>/g" \ -e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1\3<\/link>/g" \ - -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /\1<\/link> /g" \ + -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\)\(\s\+v4l2_fourcc\)/\1<\/link>\2/g" \ -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \ -e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g" diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index 91dcbc84f3f8..bb36b3829cf9 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -112,9 +112,28 @@ see . __u32 priv - Reserved for custom (driver defined) additional -information about formats. When not used drivers and applications must -set this field to zero. + This field indicates whether the remaining fields of the +v4l2_pix_format structure, also called the extended +fields, are valid. When set to V4L2_PIX_FMT_PRIV_MAGIC, it +indicates that the extended fields have been correctly initialized. When set to +any other value it indicates that the extended fields contain undefined values. + +Applications that wish to use the pixel format extended fields must first +ensure that the feature is supported by querying the device for the +V4L2_CAP_EXT_PIX_FORMAT +capability. If the capability isn't set the pixel format extended fields are not +supported and using the extended fields will lead to undefined results. +To use the extended fields, applications must set the +priv field to +V4L2_PIX_FMT_PRIV_MAGIC, initialize all the extended fields +and zero the unused bytes of the v4l2_format +raw_data field. +When the priv field isn't set to +V4L2_PIX_FMT_PRIV_MAGIC drivers must act as if all the +extended fields were set to zero. On return drivers must set the +priv field to +V4L2_PIX_FMT_PRIV_MAGIC and all the extended fields to +applicable values. diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index b445161b912c..d0a48bebfa52 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -151,6 +151,14 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.xml), along with the possible impact on existing drivers and applications. --> + + 3.16 + 2014-05-27 + lp + Extended &v4l2-pix-format;. + + + 3.15 2014-02-03 diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml index 7c63815e7afd..20460730b02c 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml @@ -152,13 +152,10 @@ a valid base address, so applications can find the corresponding Linux framebuffer device (see ). - &v4l2-pix-format; + struct fmt - Layout of the frame buffer. The -v4l2_pix_format structure is defined in , for clarification the fields and acceptable values - are listed below: + Layout of the frame buffer. @@ -276,9 +273,8 @@ see . __u32 priv - Reserved for additional information about custom -(driver defined) formats. When not used drivers and applications must -set this field to zero. + Reserved. Drivers and applications must set this field to +zero. diff --git a/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/Documentation/DocBook/media/v4l/vidioc-querycap.xml index 370d49d6fb64..d0c5e604f014 100644 --- a/Documentation/DocBook/media/v4l/vidioc-querycap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-querycap.xml @@ -300,6 +300,12 @@ modulator programming see 0x00100000 The device supports the SDR Capture interface. + + + V4L2_CAP_EXT_PIX_FORMAT + 0x00200000 + The device supports the &v4l2-pix-format; extended +fields. V4L2_CAP_READWRITE diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c index 3c5dac4c1eab..67b9da1dc43f 100644 --- a/drivers/media/parport/bw-qcam.c +++ b/drivers/media/parport/bw-qcam.c @@ -759,7 +759,6 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f pix->sizeimage = pix->width * pix->height; /* Just a guess */ pix->colorspace = V4L2_COLORSPACE_SRGB; - pix->priv = 0; return 0; } @@ -785,7 +784,6 @@ static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format pix->sizeimage = pix->width * pix->height; /* Just a guess */ pix->colorspace = V4L2_COLORSPACE_SRGB; - pix->priv = 0; return 0; } diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index fefb2cd35838..6f2b59042b73 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -156,7 +156,6 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh, pixfmt->height = cx->cxhdl.height; pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; pixfmt->field = V4L2_FIELD_INTERLACED; - pixfmt->priv = 0; if (id->type == CX18_ENC_STREAM_TYPE_YUV) { pixfmt->pixelformat = s->pixelformat; pixfmt->sizeimage = s->vb_bytes_per_frame; diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 8d2f1abeef77..3a419f134584 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3; f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } @@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } @@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv, f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index b3667a00db3a..3e0cb77d5930 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -351,7 +351,6 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f pixfmt->height = itv->cxhdl.height; pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; pixfmt->field = V4L2_FIELD_INTERLACED; - pixfmt->priv = 0; if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { pixfmt->pixelformat = V4L2_PIX_FMT_HM12; /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ @@ -418,7 +417,6 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f pixfmt->height = itv->main_rect.height; pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; pixfmt->field = V4L2_FIELD_INTERLACED; - pixfmt->priv = 0; if (id->type == IVTV_DEC_STREAM_TYPE_YUV) { switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { case IVTV_YUV_MODE_INTERLACED: @@ -1384,7 +1382,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) fb->fmt.bytesperline = fb->fmt.width; fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; fb->fmt.field = V4L2_FIELD_INTERLACED; - fb->fmt.priv = 0; if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8) fb->fmt.bytesperline *= 2; if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 || diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 1a77f8dfafa5..aeae54708811 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; - f->fmt.pix.priv = 0; return 0; } @@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 5526ed5444fb..ef39261c1f20 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -130,7 +130,6 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; f->fmt.pix.bytesperline = 0; - f->fmt.pix.priv = 0; return 0; } @@ -148,7 +147,6 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; f->fmt.pix.bytesperline = 0; - f->fmt.pix.priv = 0; return 0; } @@ -166,7 +164,6 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; f->fmt.pix.bytesperline = 0; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index d37599980768..0cfa2ca6a32a 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1235,7 +1235,6 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } @@ -1315,7 +1314,6 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index f2d8c70d35f5..365bd21301ba 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -640,7 +640,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.width * 2 * f->fmt.pix.height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index b1783791d426..54886606ed68 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -613,8 +613,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec, BUG(); } - f->fmt.pix.priv = 0; - return 0; } diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 877b46e8b2e4..0bd6dcb13cbc 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -648,7 +648,6 @@ static int vpif_try_fmt_vid_out(struct file *file, void *priv, pixfmt->width = common->fmt.fmt.pix.width; pixfmt->height = common->fmt.fmt.pix.height; pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2; - pixfmt->priv = 0; return 0; } diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index 0714070ed7fa..c1b03cfd6ded 100644 --- a/drivers/media/platform/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c @@ -532,7 +532,6 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 9a726eacb29b..2d177fa58471 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -165,7 +165,6 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix) pix->pixelformat = omap_formats[ifmt].pixelformat; pix->field = V4L2_FIELD_ANY; - pix->priv = 0; switch (pix->pixelformat) { case V4L2_PIX_FMT_YUYV: @@ -1896,7 +1895,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) pix->field = V4L2_FIELD_ANY; pix->bytesperline = pix->width * 2; pix->sizeimage = pix->bytesperline * pix->height; - pix->priv = 0; pix->colorspace = V4L2_COLORSPACE_JPEG; vout->bpp = RGB565_BPP; diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 744e43b480bc..8dc279d4d561 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -425,7 +425,6 @@ static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f) pix->bytesperline = vfmt->bytesperline; pix->sizeimage = vfmt->bytesperline * pix->height * vfmt->fmt->depth / vfmt->fmt->ydepth; - pix->priv = 0; dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__, f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat); @@ -473,7 +472,6 @@ static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt pix->pixelformat = fmt->fourcc; pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat); - pix->priv = 0; pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage); diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c index 470d35336119..91d44ea16f27 100644 --- a/drivers/media/platform/vino.c +++ b/drivers/media/platform/vino.c @@ -3147,7 +3147,6 @@ static int vino_try_fmt_vid_cap(struct file *file, void *__fh, pf->colorspace = vino_data_formats[tempvcs.data_format].colorspace; - pf->priv = 0; return 0; } @@ -3175,8 +3174,6 @@ static int vino_g_fmt_vid_cap(struct file *file, void *__fh, pf->colorspace = vino_data_formats[vcs->data_format].colorspace; - pf->priv = 0; - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } @@ -3219,8 +3216,6 @@ static int vino_s_fmt_vid_cap(struct file *file, void *__fh, pf->colorspace = vino_data_formats[vcs->data_format].colorspace; - pf->priv = 0; - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c index 7542b5dd9910..80333714ffa7 100644 --- a/drivers/media/platform/vivi.c +++ b/drivers/media/platform/vivi.c @@ -1014,7 +1014,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; else f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index f0400e260eb7..459bb0e98971 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1563,7 +1563,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = dev->ts1.width; f->fmt.pix.height = dev->ts1.height; f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.priv = 0; dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n", dev->ts1.width, dev->ts1.height); dprintk(3, "exit vidioc_g_fmt_vid_cap()\n"); @@ -1582,7 +1581,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = mpeglines * mpeglinesize; f->fmt.pix.field = V4L2_FIELD_INTERLACED; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n", dev->ts1.width, dev->ts1.height); dprintk(3, "exit vidioc_try_fmt_vid_cap()\n"); diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index ae31ca2fc9a1..3b3ada6562ca 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -885,7 +885,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.priv = 0; return 0; } @@ -930,7 +929,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 42d223239206..e8cf23c91cef 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1109,8 +1109,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct gspca_dev *gspca_dev = video_drvdata(file); fmt->fmt.pix = gspca_dev->pixfmt; - /* some drivers use priv internally, zero it before giving it to - userspace */ + /* some drivers use priv internally, zero it before giving it back to + the core */ fmt->fmt.pix.priv = 0; return 0; } @@ -1146,8 +1146,8 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, fmt->fmt.pix.height = h; gspca_dev->sd_desc->try_fmt(gspca_dev, fmt); } - /* some drivers use priv internally, zero it before giving it to - userspace */ + /* some drivers use priv internally, zero it before giving it back to + the core */ fmt->fmt.pix.priv = 0; return mode; /* used when s_fmt */ } diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index dca4b65053aa..4b7653fd4b0b 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -1022,7 +1022,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = dev->bulk_in_size; f->fmt.pix.bytesperline = 0; - f->fmt.pix.priv = 0; if (f->fmt.pix.width == 720) { /* SDTV formats */ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index d76860b6a0b8..3588dc38db87 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -923,7 +923,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp, pix_format->bytesperline = 2 * pix_format->width; pix_format->sizeimage = pix_format->bytesperline * pix_format->height; - pix_format->priv = 0; return 0; } @@ -967,7 +966,6 @@ static int stk_try_fmt_vid_cap(struct file *filp, fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width; fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline * fmtd->fmt.pix.height; - fmtd->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c index 8df668d06552..8cd7f02fcf9f 100644 --- a/drivers/media/usb/tlg2300/pd-video.c +++ b/drivers/media/usb/tlg2300/pd-video.c @@ -1321,7 +1321,6 @@ static void init_video_context(struct running_context *context) .bytesperline = 720 * 2, .sizeimage = 720 * 576 * 2, .colorspace = V4L2_COLORSPACE_SMPTE170M, - .priv = 0 }; } diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index 9bde0642ffd1..793577fc4633 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -918,7 +918,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, (f->fmt.pix.width * fh->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - f->fmt.pix.priv = 0; return 0; } @@ -959,7 +958,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width &= ~0x01; f->fmt.pix.field = field; - f->fmt.pix.priv = 0; f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 3b80579a82c5..5c006277b8b1 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -806,7 +806,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - f->fmt.pix.priv = 0; DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), f->fmt.pix.field); @@ -829,7 +828,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - f->fmt.pix.priv = 0; return 0; } @@ -866,7 +864,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - f->fmt.pix.priv = 0; cam->vb_vidq.field = f->fmt.pix.field; if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 7e2411c36419..cca6c2f76b3a 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -540,7 +540,16 @@ struct v4l2_framebuffer32 { __u32 capability; __u32 flags; compat_caddr_t base; - struct v4l2_pix_format fmt; + struct { + __u32 width; + __u32 height; + __u32 pixelformat; + __u32 field; + __u32 bytesperline; + __u32 sizeimage; + __u32 colorspace; + __u32 priv; + } fmt; }; static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) @@ -550,10 +559,10 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || get_user(tmp, &up->base) || get_user(kp->capability, &up->capability) || - get_user(kp->flags, &up->flags)) + get_user(kp->flags, &up->flags) || + copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt))) return -EFAULT; kp->base = compat_ptr(tmp); - get_v4l2_pix_format(&kp->fmt, &up->fmt); return 0; } @@ -564,9 +573,9 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || put_user(tmp, &up->base) || put_user(kp->capability, &up->capability) || - put_user(kp->flags, &up->flags)) + put_user(kp->flags, &up->flags) || + copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt))) return -EFAULT; - put_v4l2_pix_format(&kp->fmt, &up->fmt); return 0; } diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 96bc117f66b2..2e630005676f 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -973,13 +973,48 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type) return -EINVAL; } +static void v4l_sanitize_format(struct v4l2_format *fmt) +{ + unsigned int offset; + + /* + * The v4l2_pix_format structure has been extended with fields that were + * not previously required to be set to zero by applications. The priv + * field, when set to a magic value, indicates the the extended fields + * are valid. Otherwise they will contain undefined values. To simplify + * the API towards drivers zero the extended fields and set the priv + * field to the magic value when the extended pixel format structure + * isn't used by applications. + */ + + if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return; + + if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC) + return; + + fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + + offset = offsetof(struct v4l2_pix_format, priv) + + sizeof(fmt->fmt.pix.priv); + memset(((void *)&fmt->fmt.pix) + offset, 0, + sizeof(fmt->fmt.pix) - offset); +} + static int v4l_querycap(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_capability *cap = (struct v4l2_capability *)arg; + int ret; cap->version = LINUX_VERSION_CODE; - return ops->vidioc_querycap(file, fh, cap); + + ret = ops->vidioc_querycap(file, fh, cap); + + cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; + + return ret; } static int v4l_s_input(const struct v4l2_ioctl_ops *ops, @@ -1103,12 +1138,17 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; bool is_rx = vfd->vfl_dir != VFL_DIR_TX; bool is_tx = vfd->vfl_dir != VFL_DIR_RX; + int ret; + + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) break; - return ops->vidioc_g_fmt_vid_cap(file, fh, arg); + ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane)) break; @@ -1128,7 +1168,9 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out)) break; - return ops->vidioc_g_fmt_vid_out(file, fh, arg); + ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane)) break; @@ -1163,6 +1205,8 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, bool is_rx = vfd->vfl_dir != VFL_DIR_TX; bool is_tx = vfd->vfl_dir != VFL_DIR_RX; + v4l_sanitize_format(p); + switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap)) @@ -1233,6 +1277,8 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, bool is_rx = vfd->vfl_dir != VFL_DIR_TX; bool is_tx = vfd->vfl_dir != VFL_DIR_RX; + v4l_sanitize_format(p); + switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap)) @@ -1516,7 +1562,18 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, struct v4l2_create_buffers *create = arg; int ret = check_fmt(file, create->format.type); - return ret ? ret : ops->vidioc_create_bufs(file, fh, create); + if (ret) + return ret; + + v4l_sanitize_format(&create->format); + + ret = ops->vidioc_create_bufs(file, fh, create); + + if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || + create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + + return ret; } static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index a498d8b58679..eb3bdd33816b 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -268,6 +268,7 @@ struct v4l2_capability { #define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator */ #define V4L2_CAP_SDR_CAPTURE 0x00100000 /* Is a SDR capture device */ +#define V4L2_CAP_EXT_PIX_FORMAT 0x00200000 /* Supports the extended pixel format */ #define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ @@ -448,6 +449,9 @@ struct v4l2_pix_format { #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ #define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */ +/* priv field value to indicates that subsequent fields are valid. */ +#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe + /* * F O R M A T E N U M E R A T I O N */ @@ -752,7 +756,16 @@ struct v4l2_framebuffer { /* FIXME: in theory we should pass something like PCI device + memory * region + offset instead of some physical address */ void *base; - struct v4l2_pix_format fmt; + struct { + __u32 width; + __u32 height; + __u32 pixelformat; + __u32 field; /* enum v4l2_field */ + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + __u32 colorspace; /* enum v4l2_colorspace */ + __u32 priv; /* reserved field, set to 0 */ + } fmt; }; /* Flags for the 'capability' field. Read only */ #define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 -- cgit v1.2.3 From c96fd46afb34a554406bce9784126b96ad09091e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 27 May 2014 10:12:43 -0300 Subject: [media] v4l: Add premultiplied alpha flag for pixel formats When set, the new V4L2_PIX_FMT_FLAG_PREMUL_ALPHA flag indicates that the pixel values are premultiplied by the alpha channel value. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/pixfmt.xml | 31 +++++++++++++++++++++++++++++- Documentation/DocBook/media/v4l/v4l2.xml | 2 +- drivers/media/v4l2-core/v4l2-ioctl.c | 5 +++-- include/uapi/linux/videodev2.h | 8 +++++++- 4 files changed, 41 insertions(+), 5 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index bb36b3829cf9..87ce7f3e7178 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -135,6 +135,12 @@ extended fields were set to zero. On return drivers must set the V4L2_PIX_FMT_PRIV_MAGIC and all the extended fields to applicable values. + + __u32 + flags + Flags set by the application or driver, see . + @@ -220,9 +226,15 @@ codes can be used. and the number of valid entries in the plane_fmt array. + + __u8 + flags + Flags set by the application or driver, see . + __u8 - reserved[11] + reserved[10] Reserved for future extensions. Should be zeroed by the application. @@ -1079,4 +1091,21 @@ concatenated to form the JPEG stream. + + + Format Flags + + &cs-def; + + + V4L2_PIX_FMT_FLAG_PREMUL_ALPHA + 0x00000001 + The color values are premultiplied by the alpha channel +value. For example, if a light blue pixel with 50% transparency was described by +RGBA values (128, 192, 255, 128), the same pixel described with premultiplied +colors would be described by RGBA values (64, 96, 128, 128) + + + +
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index d0a48bebfa52..f2f81f06a17b 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -155,7 +155,7 @@ applications. --> 3.16 2014-05-27 lp - Extended &v4l2-pix-format;. + Extended &v4l2-pix-format;. Added format flags.
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 2e630005676f..e0bafda89e13 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -256,7 +256,8 @@ static void v4l_print_format(const void *arg, bool write_only) pix = &p->fmt.pix; pr_cont(", width=%u, height=%u, " "pixelformat=%c%c%c%c, field=%s, " - "bytesperline=%u, sizeimage=%u, colorspace=%d\n", + "bytesperline=%u, sizeimage=%u, colorspace=%d, " + "flags %u\n", pix->width, pix->height, (pix->pixelformat & 0xff), (pix->pixelformat >> 8) & 0xff, @@ -264,7 +265,7 @@ static void v4l_print_format(const void *arg, bool write_only) (pix->pixelformat >> 24) & 0xff, prt_names(pix->field, v4l2_field_names), pix->bytesperline, pix->sizeimage, - pix->colorspace); + pix->colorspace, pix->flags); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index eb3bdd33816b..b73e8cda7192 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -288,6 +288,7 @@ struct v4l2_pix_format { __u32 sizeimage; __u32 colorspace; /* enum v4l2_colorspace */ __u32 priv; /* private data, depends on pixelformat */ + __u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */ }; /* Pixel format FOURCC depth Description */ @@ -452,6 +453,9 @@ struct v4l2_pix_format { /* priv field value to indicates that subsequent fields are valid. */ #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe +/* Flags */ +#define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA 0x00000001 + /* * F O R M A T E N U M E R A T I O N */ @@ -1754,6 +1758,7 @@ struct v4l2_plane_pix_format { * @colorspace: enum v4l2_colorspace; supplemental to pixelformat * @plane_fmt: per-plane information * @num_planes: number of planes for this format + * @flags: format flags (V4L2_PIX_FMT_FLAG_*) */ struct v4l2_pix_format_mplane { __u32 width; @@ -1764,7 +1769,8 @@ struct v4l2_pix_format_mplane { struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES]; __u8 num_planes; - __u8 reserved[11]; + __u8 flags; + __u8 reserved[10]; } __attribute__ ((packed)); /** -- cgit v1.2.3 From ce71bbc91e2440a399f2f96b96cfbf263a6629c1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 12 Jul 2014 07:54:26 -0300 Subject: [media] v4l2-ioctl.c: check vfl_type in ENUM_FMT The other format ioctls (g/s/try_fmt) all check if the passed buffer type makes sense for the device node's vfl_type. E.g. it makes no sense for a VBI buffer type to be passed through a video node instead of a vbi node. But this check was missing in ENUM_FMT which can cause a problem if you have both video and sdr device nodes. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index e0bafda89e13..cd9e94c37808 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1098,32 +1098,34 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, { struct v4l2_fmtdesc *p = arg; struct video_device *vfd = video_devdata(file); + bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; + bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; bool is_rx = vfd->vfl_dir != VFL_DIR_TX; bool is_tx = vfd->vfl_dir != VFL_DIR_RX; switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap)) break; return ops->vidioc_enum_fmt_vid_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap_mplane)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane)) break; return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_overlay)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay)) break; return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out)) break; return ops->vidioc_enum_fmt_vid_out(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane)) break; return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); case V4L2_BUF_TYPE_SDR_CAPTURE: - if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap)) + if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap)) break; return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg); } -- cgit v1.2.3 From a7f404af8a435b940055a04be19a3304da93a76d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 Jul 2014 07:01:39 -0300 Subject: [media] v4l2-ioctl.c: fix enum_freq_bands handling If the driver supports enum_freq_bands, but only for certain device nodes, then it may return -ENOTTY. But in that case the code should fall into the fall-back case where the current tuner/modulator range is returned. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index cd9e94c37808..aef588cf6d44 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2042,8 +2042,11 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, if (type != p->type) return -EINVAL; } - if (ops->vidioc_enum_freq_bands) - return ops->vidioc_enum_freq_bands(file, fh, p); + if (ops->vidioc_enum_freq_bands) { + err = ops->vidioc_enum_freq_bands(file, fh, p); + if (err != -ENOTTY) + return err; + } if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) { struct v4l2_tuner t = { .index = p->tuner, -- cgit v1.2.3 From f9402a94e7ca0df34e7dc17d763bb49afbd89c3a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 14 Mar 2014 11:52:38 -0300 Subject: [media] v4l2-ioctl: remove pointless INFO_FL_CLEAR The edid field is the last field of the struct, so there is nothing to clear. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index aef588cf6d44..e8296bae9fe6 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2164,8 +2164,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0), IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), - IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_CLEAR(v4l2_edid, edid)), - IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_edid, edid)), + IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, 0), + IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0), IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), -- cgit v1.2.3 From 865c4642e3750a257e4e199c2eb60495fd66f530 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Mar 2014 09:51:34 -0300 Subject: [media] v4l2-ioctl: clear reserved field of G/S_SELECTION Be sure that the reserved fields are cleared. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index e8296bae9fe6..dca8ca9ad48e 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2178,8 +2178,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)), IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)), IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO), - IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0), - IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)), + IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)), IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0), IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0), -- cgit v1.2.3 From 9409945c7ff7ba39727df8ede2551bd22e76b58b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Jun 2014 04:31:06 -0300 Subject: [media] v4l2-ioctl: call g_selection before calling cropcap If the vidioc_cropcap op is implemented by the driver then the v4l2 core will call that directly. If g_selection is available, then the core cropcap implementation uses g_selection to fill in the bounds and defrect and it sets the pixelaspect to 1x1. But if both are available, then I would like to use g_selection to fill in defrect and bounds before calling cropcap. That way the driver's cropcap implementation doesn't have to set defrect or bounds. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 48 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index dca8ca9ad48e..46f45f087a83 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1842,37 +1842,41 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_cropcap *p = arg; - struct v4l2_selection s = { .type = p->type }; - int ret; - if (ops->vidioc_cropcap) - return ops->vidioc_cropcap(file, fh, p); + if (ops->vidioc_g_selection) { + struct v4l2_selection s = { .type = p->type }; + int ret; - /* obtaining bounds */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; - else - s.target = V4L2_SEL_TGT_CROP_BOUNDS; + /* obtaining bounds */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; + else + s.target = V4L2_SEL_TGT_CROP_BOUNDS; - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - return ret; - p->bounds = s.r; + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->bounds = s.r; - /* obtaining defrect */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; - else - s.target = V4L2_SEL_TGT_CROP_DEFAULT; + /* obtaining defrect */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; + else + s.target = V4L2_SEL_TGT_CROP_DEFAULT; - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - return ret; - p->defrect = s.r; + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->defrect = s.r; + } /* setting trivial pixelaspect */ p->pixelaspect.numerator = 1; p->pixelaspect.denominator = 1; + + if (ops->vidioc_cropcap) + return ops->vidioc_cropcap(file, fh, p); + return 0; } -- cgit v1.2.3 From e5ce558a6157e49374ba762471b77ce89ada4df0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 17 Jul 2014 18:45:45 -0300 Subject: [media] v4l2-ioctl: clips, clipcount and bitmap should not be zeroed Otherwise you cannot get the current clip and bitmap information from an overlay. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 46f45f087a83..e620387b29ca 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1145,6 +1145,30 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + /* + * fmt can't be cleared for these overlay types due to the 'clips' + * 'clipcount' and 'bitmap' pointers in struct v4l2_window. + * Those are provided by the user. So handle these two overlay types + * first, and then just do a simple memset for the other types. + */ + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: { + struct v4l2_clip *clips = p->fmt.win.clips; + u32 clipcount = p->fmt.win.clipcount; + void *bitmap = p->fmt.win.bitmap; + + memset(&p->fmt, 0, sizeof(p->fmt)); + p->fmt.win.clips = clips; + p->fmt.win.clipcount = clipcount; + p->fmt.win.bitmap = bitmap; + break; + } + default: + memset(&p->fmt, 0, sizeof(p->fmt)); + break; + } + switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) @@ -2140,7 +2164,7 @@ struct v4l2_ioctl_info { static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), - IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)), + IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0), IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE), IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)), -- cgit v1.2.3 From 796a2bd25b4fc3c4a1d6f04373ef2af1e12489b5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 21 Jul 2014 04:14:46 -0300 Subject: [media] v4l2-ioctl: set V4L2_CAP_EXT_PIX_FORMAT for device_caps V4L2_CAP_EXT_PIX_FORMAT is set for capabilities, but it needs to be set for device_caps as well: device_caps should report all caps relevant to the device node, and this is one of them. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index e620387b29ca..00ceedf16bb7 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1014,6 +1014,7 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops, ret = ops->vidioc_querycap(file, fh, cap); cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; + cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT; return ret; } -- cgit v1.2.3 From 48f2650a87ae462598cf0a3b4b34ee5f52c34869 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 21 Jul 2014 07:50:39 -0300 Subject: [media] v4l2-ioctl: don't set PRIV_MAGIC unconditionally in g_fmt() Regression fix: V4L2_PIX_FMT_PRIV_MAGIC should only be set for the VIDEO_CAPTURE and VIDEO_OUTPUT buffer types, and not for any others. In the case of the win format this overwrote a pointer value that is passed in from userspace. Just set it for V4L2_BUF_TYPE_VIDEO_CAPTURE and OUTPUT only. Set it before the callback is called, just as is done for try/s_fmt, and again afterwards in case the driver zeroed it. The latter was missing in try/s_fmt, so add it there as well. Currently it is quite likely that drivers clear priv (that was needed for a long time), so it makes sense to set it twice. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 00ceedf16bb7..d15e16737eef 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1144,8 +1144,6 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, bool is_tx = vfd->vfl_dir != VFL_DIR_RX; int ret; - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - /* * fmt can't be cleared for these overlay types due to the 'clips' * 'clipcount' and 'bitmap' pointers in struct v4l2_window. @@ -1174,7 +1172,9 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) break; + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); + /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; return ret; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: @@ -1196,7 +1196,9 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out)) break; + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); + /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; return ret; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: @@ -1232,6 +1234,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; bool is_rx = vfd->vfl_dir != VFL_DIR_TX; bool is_tx = vfd->vfl_dir != VFL_DIR_RX; + int ret; v4l_sanitize_format(p); @@ -1240,7 +1243,10 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap)) break; CLEAR_AFTER_FIELD(p, fmt.pix); - return ops->vidioc_s_fmt_vid_cap(file, fh, arg); + ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane)) break; @@ -1265,7 +1271,10 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out)) break; CLEAR_AFTER_FIELD(p, fmt.pix); - return ops->vidioc_s_fmt_vid_out(file, fh, arg); + ret = ops->vidioc_s_fmt_vid_out(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane)) break; @@ -1304,6 +1313,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; bool is_rx = vfd->vfl_dir != VFL_DIR_TX; bool is_tx = vfd->vfl_dir != VFL_DIR_RX; + int ret; v4l_sanitize_format(p); @@ -1312,7 +1322,10 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap)) break; CLEAR_AFTER_FIELD(p, fmt.pix); - return ops->vidioc_try_fmt_vid_cap(file, fh, arg); + ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane)) break; @@ -1337,7 +1350,10 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out)) break; CLEAR_AFTER_FIELD(p, fmt.pix); - return ops->vidioc_try_fmt_vid_out(file, fh, arg); + ret = ops->vidioc_try_fmt_vid_out(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane)) break; -- cgit v1.2.3