aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-07 15:53:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-15 07:43:06 -0400
commit6e6d76cdc541e28bf4f609141d76c488c6c0d263 (patch)
tree479d1c19b79849098e35b6e2f604794541f0fe0b
parent69ecdbac144147a80747914d9b6ea3472e2d93e7 (diff)
[media] v4l2-event: fix regression with initial event handling
If the V4L2_EVENT_SUB_FL_SEND_INITIAL was set, then the application expects to receive an initial event of the initial value of the control. However, commit c53c2549333b340e2662dc64ec81323476b69a97 that added the new v4l2_subscribed_event_ops introduced a regression: while the code still queued that initial event the __v4l2_event_queue_fh() function was modified to ignore such requests if sev->elems was 0 (meaning that the event subscription wasn't finished yet). And sev->elems was only set to a non-zero value after the add operation returned. This patch fixes this by passing the elems value to the add function. Then the add function can set it before queuing the initial event. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c5
-rw-r--r--drivers/media/video/v4l2-ctrls.c5
-rw-r--r--drivers/media/video/v4l2-event.c2
-rw-r--r--include/media/v4l2-event.h2
4 files changed, 10 insertions, 4 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 28363b72ff8a..f3bd66c500b6 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1250,7 +1250,7 @@ static void uvc_ctrl_send_events(struct uvc_fh *handle,
1250 } 1250 }
1251} 1251}
1252 1252
1253static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev) 1253static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
1254{ 1254{
1255 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); 1255 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
1256 struct uvc_control_mapping *mapping; 1256 struct uvc_control_mapping *mapping;
@@ -1278,6 +1278,9 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev)
1278 1278
1279 uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, 1279 uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val,
1280 changes); 1280 changes);
1281 /* Mark the queue as active, allowing this initial
1282 event to be accepted. */
1283 sev->elems = elems;
1281 v4l2_event_queue_fh(sev->fh, &ev); 1284 v4l2_event_queue_fh(sev->fh, &ev);
1282 } 1285 }
1283 1286
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index a5fbace4c059..9abd9abd4502 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -2559,7 +2559,7 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
2559} 2559}
2560EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); 2560EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
2561 2561
2562static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev) 2562static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
2563{ 2563{
2564 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); 2564 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
2565 2565
@@ -2576,6 +2576,9 @@ static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev)
2576 if (!(ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)) 2576 if (!(ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY))
2577 changes |= V4L2_EVENT_CTRL_CH_VALUE; 2577 changes |= V4L2_EVENT_CTRL_CH_VALUE;
2578 fill_event(&ev, ctrl, changes); 2578 fill_event(&ev, ctrl, changes);
2579 /* Mark the queue as active, allowing this initial
2580 event to be accepted. */
2581 sev->elems = elems;
2579 v4l2_event_queue_fh(sev->fh, &ev); 2582 v4l2_event_queue_fh(sev->fh, &ev);
2580 } 2583 }
2581 v4l2_ctrl_unlock(ctrl); 2584 v4l2_ctrl_unlock(ctrl);
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c
index 60b4e2e9c874..ef2a33c94045 100644
--- a/drivers/media/video/v4l2-event.c
+++ b/drivers/media/video/v4l2-event.c
@@ -239,7 +239,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
239 } 239 }
240 240
241 if (sev->ops && sev->ops->add) { 241 if (sev->ops && sev->ops->add) {
242 int ret = sev->ops->add(sev); 242 int ret = sev->ops->add(sev, elems);
243 if (ret) { 243 if (ret) {
244 sev->ops = NULL; 244 sev->ops = NULL;
245 v4l2_event_unsubscribe(fh, sub); 245 v4l2_event_unsubscribe(fh, sub);
diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h
index 88fa9a1e0df3..2885a810a128 100644
--- a/include/media/v4l2-event.h
+++ b/include/media/v4l2-event.h
@@ -85,7 +85,7 @@ struct v4l2_kevent {
85 * @merge: Optional callback that can merge event 'old' into event 'new'. 85 * @merge: Optional callback that can merge event 'old' into event 'new'.
86 */ 86 */
87struct v4l2_subscribed_event_ops { 87struct v4l2_subscribed_event_ops {
88 int (*add)(struct v4l2_subscribed_event *sev); 88 int (*add)(struct v4l2_subscribed_event *sev, unsigned elems);
89 void (*del)(struct v4l2_subscribed_event *sev); 89 void (*del)(struct v4l2_subscribed_event *sev);
90 void (*replace)(struct v4l2_event *old, const struct v4l2_event *new); 90 void (*replace)(struct v4l2_event *old, const struct v4l2_event *new);
91 void (*merge)(const struct v4l2_event *old, struct v4l2_event *new); 91 void (*merge)(const struct v4l2_event *old, struct v4l2_event *new);