From: Hans Verkuil <hans.verkuil@xxxxxxxxx> Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> --- drivers/media/v4l2-core/v4l2-ctrls.c | 60 ++++++++++++++++---------- drivers/media/v4l2-core/v4l2-dev.c | 1 + drivers/media/v4l2-core/v4l2-ioctl.c | 81 ++++++++++++++++++++++++++++++----- drivers/media/v4l2-core/v4l2-subdev.c | 63 ++++++++++++++++++++++++--- include/media/v4l2-ctrls.h | 8 ++-- include/media/v4l2-fh.h | 1 + include/uapi/linux/videodev2.h | 19 +++++++- 7 files changed, 189 insertions(+), 44 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 43fb3c2..d262e2e 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -2715,9 +2715,13 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr EXPORT_SYMBOL(v4l2_query_ext_ctrl); /* Implement VIDIOC_QUERYCTRL */ -int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) +int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, + unsigned request, struct v4l2_queryctrl *qc) { - struct v4l2_query_ext_ctrl qec = { qc->id }; + struct v4l2_query_ext_ctrl qec = { + .id = qc->id, + .request = request, + }; int rc; rc = v4l2_query_ext_ctrl(hdl, &qec); @@ -2755,7 +2759,7 @@ int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { if (qc->id & (V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND)) return -EINVAL; - return v4l2_queryctrl(sd->ctrl_handler, qc); + return v4l2_queryctrl(sd->ctrl_handler, 0, qc); } EXPORT_SYMBOL(v4l2_subdev_queryctrl); @@ -3058,7 +3062,8 @@ int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls); /* Helper function to get a single control */ -static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) +static int get_ctrl(struct v4l2_ctrl *ctrl, + unsigned request, struct v4l2_ext_control *c) { struct v4l2_ctrl *master = ctrl->cluster[0]; int ret = 0; @@ -3076,11 +3081,17 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) v4l2_ctrl_lock(master); /* g_volatile_ctrl will update the current control values */ - if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { + if (request == 0 && (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)) { for (i = 0; i < master->ncontrols; i++) cur_to_new(master->cluster[i]); ret = call_op(master, g_volatile_ctrl); new_to_user(c, ctrl); + } else if (request) { + ctrl->request = get_request(ctrl, request); + if (ctrl->request) + ptr_to_user(c, ctrl, ctrl->request->ptr); + else + ret = -EINVAL; } else { cur_to_user(c, ctrl); } @@ -3088,7 +3099,8 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) return ret; } -int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) +int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, + unsigned request, struct v4l2_control *control) { struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); struct v4l2_ext_control c; @@ -3096,7 +3108,7 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) if (ctrl == NULL || !ctrl->is_int) return -EINVAL; - ret = get_ctrl(ctrl, &c); + ret = get_ctrl(ctrl, request, &c); control->value = c.value; return ret; } @@ -3104,7 +3116,7 @@ EXPORT_SYMBOL(v4l2_g_ctrl); int v4l2_subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control) { - return v4l2_g_ctrl(sd->ctrl_handler, control); + return v4l2_g_ctrl(sd->ctrl_handler, 0, control); } EXPORT_SYMBOL(v4l2_subdev_g_ctrl); @@ -3115,7 +3127,7 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) /* It's a driver bug if this happens. */ WARN_ON(!ctrl->is_int); c.value = 0; - get_ctrl(ctrl, &c); + get_ctrl(ctrl, 0, &c); return c.value; } EXPORT_SYMBOL(v4l2_ctrl_g_ctrl); @@ -3127,7 +3139,7 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl) /* It's a driver bug if this happens. */ WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64); c.value = 0; - get_ctrl(ctrl, &c); + get_ctrl(ctrl, 0, &c); return c.value; } EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); @@ -3384,7 +3396,8 @@ int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); /* Helper function for VIDIOC_S_CTRL compatibility */ -static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) +static int set_ctrl(struct v4l2_fh *fh, unsigned request, + struct v4l2_ctrl *ctrl, u32 ch_flags) { struct v4l2_ctrl *master = ctrl->cluster[0]; int ret; @@ -3404,23 +3417,24 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) /* For autoclusters with volatiles that are switched from auto to manual mode we have to update the current volatile values since those will become the initial manual values after such a switch. */ - if (master->is_auto && master->has_volatiles && ctrl == master && + if (request == 0 && + master->is_auto && master->has_volatiles && ctrl == master && !is_cur_manual(master) && ctrl->val == master->manual_mode_value) update_from_auto_cluster(master); ctrl->is_new = 1; - return try_or_set_cluster(fh, master, 0, true, ch_flags); + return try_or_set_cluster(fh, master, request, true, ch_flags); } /* Helper function for VIDIOC_S_CTRL compatibility */ -static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, - struct v4l2_ext_control *c) +static int set_ctrl_lock(struct v4l2_fh *fh, unsigned request, + struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) { int ret; v4l2_ctrl_lock(ctrl); user_to_new(c, ctrl); - ret = set_ctrl(fh, ctrl, 0); + ret = set_ctrl(fh, request, ctrl, 0); if (!ret) cur_to_user(c, ctrl); v4l2_ctrl_unlock(ctrl); @@ -3428,7 +3442,7 @@ static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, } int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, - struct v4l2_control *control) + unsigned request, struct v4l2_control *control) { struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); struct v4l2_ext_control c = { control->id }; @@ -3441,7 +3455,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, return -EACCES; c.value = control->value; - ret = set_ctrl_lock(fh, ctrl, &c); + ret = set_ctrl_lock(fh, request, ctrl, &c); control->value = c.value; return ret; } @@ -3449,7 +3463,7 @@ EXPORT_SYMBOL(v4l2_s_ctrl); int v4l2_subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control) { - return v4l2_s_ctrl(NULL, sd->ctrl_handler, control); + return v4l2_s_ctrl(NULL, sd->ctrl_handler, 0, control); } EXPORT_SYMBOL(v4l2_subdev_s_ctrl); @@ -3460,7 +3474,7 @@ int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) /* It's a driver bug if this happens. */ WARN_ON(!ctrl->is_int); ctrl->val = val; - return set_ctrl(NULL, ctrl, 0); + return set_ctrl(NULL, 0, ctrl, 0); } EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl); @@ -3471,7 +3485,7 @@ int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val) /* It's a driver bug if this happens. */ WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64); *ctrl->p_new.p_s64 = val; - return set_ctrl(NULL, ctrl, 0); + return set_ctrl(NULL, 0, ctrl, 0); } EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64); @@ -3482,7 +3496,7 @@ int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s) /* It's a driver bug if this happens. */ WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING); strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); - return set_ctrl(NULL, ctrl, 0); + return set_ctrl(NULL, 0, ctrl, 0); } EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); @@ -3668,7 +3682,7 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, else changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32; if (changed) - ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); + ret = set_ctrl(NULL, 0, ctrl, V4L2_EVENT_CTRL_CH_RANGE); else send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); return ret; diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 71a1b93..ff206f1 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -558,6 +558,7 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency); SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency); SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status); + set_bit(_IOC_NR(VIDIOC_REQUEST_CMD), valid_ioctls); #ifdef CONFIG_VIDEO_ADV_DEBUG set_bit(_IOC_NR(VIDIOC_DBG_G_CHIP_INFO), valid_ioctls); set_bit(_IOC_NR(VIDIOC_DBG_G_REGISTER), valid_ioctls); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index a16af7f..51830c2 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -653,6 +653,14 @@ static void v4l_print_decoder_cmd(const void *arg, bool write_only) pr_info("pts=%llu\n", p->stop.pts); } +static void v4l_print_request_cmd(const void *arg, bool write_only) +{ + const struct v4l2_request_cmd *p = arg; + + pr_cont("cmd=%u, request=%u, flags=0x%x\n", + p->cmd, p->request, p->flags); +} + static void v4l_print_dbg_chip_info(const void *arg, bool write_only) { const struct v4l2_dbg_chip_info *p = arg; @@ -1681,9 +1689,9 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; if (vfh && vfh->ctrl_handler) - return v4l2_queryctrl(vfh->ctrl_handler, p); + return v4l2_queryctrl(vfh->ctrl_handler, vfh->request, p); if (vfd->ctrl_handler) - return v4l2_queryctrl(vfd->ctrl_handler, p); + return v4l2_queryctrl(vfd->ctrl_handler, 0, p); if (ops->vidioc_queryctrl) return ops->vidioc_queryctrl(file, fh, p); return -ENOTTY; @@ -1697,8 +1705,11 @@ static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops, struct v4l2_fh *vfh = test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; - if (vfh && vfh->ctrl_handler) + if (vfh && vfh->ctrl_handler) { + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_query_ext_ctrl(vfh->ctrl_handler, p); + } if (vfd->ctrl_handler) return v4l2_query_ext_ctrl(vfd->ctrl_handler, p); if (p->request) @@ -1736,9 +1747,9 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, struct v4l2_ext_control ctrl; if (vfh && vfh->ctrl_handler) - return v4l2_g_ctrl(vfh->ctrl_handler, p); + return v4l2_g_ctrl(vfh->ctrl_handler, vfh->request, p); if (vfd->ctrl_handler) - return v4l2_g_ctrl(vfd->ctrl_handler, p); + return v4l2_g_ctrl(vfd->ctrl_handler, 0, p); if (ops->vidioc_g_ctrl) return ops->vidioc_g_ctrl(file, fh, p); if (ops->vidioc_g_ext_ctrls == NULL) @@ -1770,9 +1781,9 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, struct v4l2_ext_control ctrl; if (vfh && vfh->ctrl_handler) - return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); + return v4l2_s_ctrl(vfh, vfh->ctrl_handler, vfh->request, p); if (vfd->ctrl_handler) - return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); + return v4l2_s_ctrl(NULL, vfd->ctrl_handler, 0, p); if (ops->vidioc_s_ctrl) return ops->vidioc_s_ctrl(file, fh, p); if (ops->vidioc_s_ext_ctrls == NULL) @@ -1797,8 +1808,11 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; p->error_idx = p->count; - if (vfh && vfh->ctrl_handler) + if (vfh && vfh->ctrl_handler) { + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_g_ext_ctrls(vfh->ctrl_handler, p); + } if (vfd->ctrl_handler) return v4l2_g_ext_ctrls(vfd->ctrl_handler, p); if (ops->vidioc_g_ext_ctrls == NULL) @@ -1818,8 +1832,11 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; p->error_idx = p->count; - if (vfh && vfh->ctrl_handler) + if (vfh && vfh->ctrl_handler) { + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); + } if (vfd->ctrl_handler) return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); if (ops->vidioc_s_ext_ctrls == NULL) @@ -1839,8 +1856,11 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; p->error_idx = p->count; - if (vfh && vfh->ctrl_handler) + if (vfh && vfh->ctrl_handler) { + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_try_ext_ctrls(vfh->ctrl_handler, p); + } if (vfd->ctrl_handler) return v4l2_try_ext_ctrls(vfd->ctrl_handler, p); if (ops->vidioc_try_ext_ctrls == NULL) @@ -1942,6 +1962,46 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, return 0; } +static int v4l_request_cmd(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_request_cmd *p = arg; + struct video_device *vfd; + struct v4l2_fh *vfh; + int ret; + + vfd = video_devdata(file); + if (!test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) + return -ENOTTY; + vfh = file->private_data; + if (vfh->ctrl_handler == NULL) + return -ENOTTY; + ret = v4l2_prio_check(vfd->prio, vfh->prio); + if (ret) + return ret; + if (p->request > USHRT_MAX) + return -EINVAL; + switch (p->cmd) { + case V4L2_REQ_CMD_BEGIN: + if (vfh->request) + return -EBUSY; + if (p->request == 0) + return -EINVAL; + vfh->request = p->request; + break; + case V4L2_REQ_CMD_END: + vfh->request = 0; + break; + case V4L2_REQ_CMD_DELETE: + return v4l2_ctrl_delete_request(vfh->ctrl_handler, p->request); + case V4L2_REQ_CMD_APPLY: + return v4l2_ctrl_apply_request(vfh->ctrl_handler, p->request); + default: + return -EINVAL; + } + return 0; +} + static int v4l_log_status(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -2282,6 +2342,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { 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)), + IOCTL_INFO_FNC(VIDIOC_REQUEST_CMD, v4l_request_cmd, v4l_print_request_cmd, 0), }; #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 6359606..cabbddc 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -188,28 +188,48 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) switch (cmd) { case VIDIOC_QUERYCTRL: - return v4l2_queryctrl(vfh->ctrl_handler, arg); + return v4l2_queryctrl(vfh->ctrl_handler, vfh->request, arg); - case VIDIOC_QUERY_EXT_CTRL: + case VIDIOC_QUERY_EXT_CTRL: { + struct v4l2_query_ext_ctrl *p = arg; + + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg); + } case VIDIOC_QUERYMENU: return v4l2_querymenu(vfh->ctrl_handler, arg); case VIDIOC_G_CTRL: - return v4l2_g_ctrl(vfh->ctrl_handler, arg); + return v4l2_g_ctrl(vfh->ctrl_handler, vfh->request, arg); case VIDIOC_S_CTRL: - return v4l2_s_ctrl(vfh, vfh->ctrl_handler, arg); + return v4l2_s_ctrl(vfh, vfh->ctrl_handler, vfh->request, arg); - case VIDIOC_G_EXT_CTRLS: + case VIDIOC_G_EXT_CTRLS: { + struct v4l2_ext_controls *p = arg; + + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg); + } - case VIDIOC_S_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: { + struct v4l2_ext_controls *p = arg; + + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg); + } - case VIDIOC_TRY_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: { + struct v4l2_ext_controls *p = arg; + + if (vfh->request && p->request == 0) + p->request = vfh->request; return v4l2_try_ext_ctrls(vfh->ctrl_handler, arg); + } case VIDIOC_DQEVENT: if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) @@ -223,6 +243,35 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_UNSUBSCRIBE_EVENT: return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg); + case VIDIOC_REQUEST_CMD: { + struct v4l2_request_cmd *p = arg; + + if (p->request > USHRT_MAX) + return -EINVAL; + + switch (p->cmd) { + case V4L2_REQ_CMD_BEGIN: + if (vfh->request) + return -EBUSY; + if (p->request == 0) + return -EINVAL; + vfh->request = p->request; + break; + case V4L2_REQ_CMD_END: + vfh->request = 0; + break; + case V4L2_REQ_CMD_DELETE: + return v4l2_ctrl_delete_request(vfh->ctrl_handler, + p->request); + case V4L2_REQ_CMD_APPLY: + return v4l2_ctrl_apply_request(vfh->ctrl_handler, + p->request); + default: + return -EINVAL; + } + return 0; + } + #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: { diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 324db6d..efba887 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -830,12 +830,14 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */ -int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc); +int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, + unsigned request, struct v4l2_queryctrl *qc); int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc); int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm); -int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl); +int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, + unsigned request, struct v4l2_control *ctrl); int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, - struct v4l2_control *ctrl); + unsigned request, struct v4l2_control *ctrl); int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c); int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c); int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h index 8035167..652202f 100644 --- a/include/media/v4l2-fh.h +++ b/include/media/v4l2-fh.h @@ -45,6 +45,7 @@ struct v4l2_fh { struct list_head available; /* Dequeueable event */ unsigned int navailable; u32 sequence; + u16 request; #if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) struct v4l2_m2m_ctx *m2m_ctx; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 7f2b548..98a7717 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -2085,6 +2085,21 @@ struct v4l2_create_buffers { __u32 reserved[8]; }; +#define V4L2_REQ_CMD_BEGIN (0) +#define V4L2_REQ_CMD_END (1) +#define V4L2_REQ_CMD_DELETE (2) +#define V4L2_REQ_CMD_APPLY (3) + +struct v4l2_request_cmd { + __u32 cmd; + __u16 request; + __u16 flags; + union { + struct { + __u32 data[8]; + } raw; + }; +}; /* * I O C T L C O D E S F O R V I D E O D E V I C E S * @@ -2197,8 +2212,10 @@ struct v4l2_create_buffers { #define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) +#define VIDIOC_REQUEST_CMD _IOWR('V', 104, struct v4l2_request_cmd) + /* Reminder: when adding new ioctls please add support for them to - drivers/media/video/v4l2-compat-ioctl32.c as well! */ + drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */ #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ -- 2.1.4 -- 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