From: Hans Verkuil <hans.verkuil@xxxxxxxxx> The current control event is not able to handle the 64-bit ranges or the config_store. Add a new extended event that is able to handle this. Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> --- drivers/media/v4l2-core/v4l2-ctrls.c | 61 ++++++++++++++++++++++++++++++------ include/uapi/linux/videodev2.h | 19 ++++++++++- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 8d6711e..0014324 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1091,8 +1091,10 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change ev->u.ctrl.flags = ctrl->flags; if (ctrl->is_ptr) ev->u.ctrl.value64 = 0; - else + else if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) ev->u.ctrl.value64 = *ctrl->cur.p_s64; + else + ev->u.ctrl.value = *ctrl->cur.p_s32; ev->u.ctrl.minimum = ctrl->minimum; ev->u.ctrl.maximum = ctrl->maximum; if (ctrl->type == V4L2_CTRL_TYPE_MENU @@ -1103,19 +1105,48 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change ev->u.ctrl.default_value = ctrl->default_value; } +static void fill_event64(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes) +{ + memset(ev->reserved, 0, sizeof(ev->reserved)); + ev->type = V4L2_EVENT_CTRL64; + ev->id = ctrl->id; + ev->u.ctrl64.changes = changes; + ev->u.ctrl64.type = ctrl->type; + ev->u.ctrl64.config_store = ctrl->cur_store; + ev->u.ctrl64.flags = ctrl->flags; + if (ctrl->is_ptr) + ev->u.ctrl64.value64 = 0; + else if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) + ev->u.ctrl64.value64 = *ctrl->cur.p_s64; + else + ev->u.ctrl64.value = *ctrl->cur.p_s32; + ev->u.ctrl64.minimum = ctrl->minimum; + ev->u.ctrl64.maximum = ctrl->maximum; + if (ctrl->type == V4L2_CTRL_TYPE_MENU + || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU) + ev->u.ctrl64.step = 1; + else + ev->u.ctrl64.step = ctrl->step; + ev->u.ctrl64.default_value = ctrl->default_value; +} + static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes) { struct v4l2_event ev; + struct v4l2_event ev64; struct v4l2_subscribed_event *sev; if (list_empty(&ctrl->ev_subs)) return; fill_event(&ev, ctrl, changes); + fill_event64(&ev64, ctrl, changes); list_for_each_entry(sev, &ctrl->ev_subs, node) if (sev->fh != fh || - (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)) + (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)) { v4l2_event_queue_fh(sev->fh, &ev); + v4l2_event_queue_fh(sev->fh, &ev64); + } } static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx, @@ -3239,13 +3270,23 @@ int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, ctrl->maximum = max; ctrl->step = step; ctrl->default_value = def; - c.value = *ctrl->cur.p_s32; - if (validate_new(ctrl, &c)) - c.value = def; - if (c.value != *ctrl->cur.p_s32) - ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE); - else - send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); + if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) { + c.value64 = *ctrl->cur.p_s64; + if (validate_new(ctrl, &c)) + c.value64 = def; + if (c.value64 != *ctrl->cur.p_s64) + ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE); + else + send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); + } else { + c.value = *ctrl->cur.p_s32; + if (validate_new(ctrl, &c)) + c.value = def; + if (c.value != *ctrl->cur.p_s32) + ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE); + else + send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); + } v4l2_ctrl_unlock(ctrl); return ret; } @@ -3324,7 +3365,7 @@ EXPORT_SYMBOL(v4l2_ctrl_log_status); int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { - if (sub->type == V4L2_EVENT_CTRL) + if (sub->type == V4L2_EVENT_CTRL || sub->type == V4L2_EVENT_CTRL64) return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); return -EINVAL; } diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 78aba44..afa335d 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1773,6 +1773,7 @@ struct v4l2_streamparm { #define V4L2_EVENT_EOS 2 #define V4L2_EVENT_CTRL 3 #define V4L2_EVENT_FRAME_SYNC 4 +#define V4L2_EVENT_CTRL64 5 #define V4L2_EVENT_PRIVATE_START 0x08000000 /* Payload for V4L2_EVENT_VSYNC */ @@ -1781,7 +1782,7 @@ struct v4l2_event_vsync { __u8 field; } __attribute__ ((packed)); -/* Payload for V4L2_EVENT_CTRL */ +/* Payload for V4L2_EVENT_CTRL/V4L2_EVENT_CTRL64 */ #define V4L2_EVENT_CTRL_CH_VALUE (1 << 0) #define V4L2_EVENT_CTRL_CH_FLAGS (1 << 1) #define V4L2_EVENT_CTRL_CH_RANGE (1 << 2) @@ -1800,6 +1801,21 @@ struct v4l2_event_ctrl { __s32 default_value; }; +struct v4l2_event_ctrl64 { + __u32 changes; + __u32 type; + union { + __s32 value; + __s64 value64; + }; + __u32 flags; + __u32 config_store; + __s64 minimum; + __s64 maximum; + __u64 step; + __s64 default_value; +}; + struct v4l2_event_frame_sync { __u32 frame_sequence; }; @@ -1809,6 +1825,7 @@ struct v4l2_event { union { struct v4l2_event_vsync vsync; struct v4l2_event_ctrl ctrl; + struct v4l2_event_ctrl64 ctrl64; struct v4l2_event_frame_sync frame_sync; __u8 data[64]; } u; -- 1.8.5.2 -- 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