aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-04-08 11:59:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-07 15:28:35 -0400
commitc53c2549333b340e2662dc64ec81323476b69a97 (patch)
tree4bd55780eba1302caaf7359631b996043dc1082f /drivers
parenta22d85fea89744fad2cb215da1fe0c1ce226a613 (diff)
[media] v4l2-event: Add v4l2_subscribed_event_ops
Just like with ctrl events, drivers may want to get called back on listener add / remove for other event types too. Rather then special casing all of this in subscribe / unsubscribe event it is better to use ops for this. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c2
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c2
-rw-r--r--drivers/media/video/omap3isp/ispstat.c2
-rw-r--r--drivers/media/video/v4l2-ctrls.c2
-rw-r--r--drivers/media/video/v4l2-event.c54
-rw-r--r--drivers/usb/gadget/uvc_v4l2.c2
6 files changed, 48 insertions, 16 deletions
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index a151271f60e1..a7730fd4827f 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1469,7 +1469,7 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti
1469 case V4L2_EVENT_VSYNC: 1469 case V4L2_EVENT_VSYNC:
1470 case V4L2_EVENT_EOS: 1470 case V4L2_EVENT_EOS:
1471 case V4L2_EVENT_CTRL: 1471 case V4L2_EVENT_CTRL:
1472 return v4l2_event_subscribe(fh, sub, 0); 1472 return v4l2_event_subscribe(fh, sub, 0, NULL);
1473 default: 1473 default:
1474 return -EINVAL; 1474 return -EINVAL;
1475 } 1475 }
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index eaabc27f0fa2..1f3c16d8f0b4 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -1703,7 +1703,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1703 if (sub->id != 0) 1703 if (sub->id != 0)
1704 return -EINVAL; 1704 return -EINVAL;
1705 1705
1706 return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS); 1706 return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS, NULL);
1707} 1707}
1708 1708
1709static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, 1709static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c
index 11871ecc6d25..b8640be692f1 100644
--- a/drivers/media/video/omap3isp/ispstat.c
+++ b/drivers/media/video/omap3isp/ispstat.c
@@ -1032,7 +1032,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
1032 if (sub->type != stat->event_type) 1032 if (sub->type != stat->event_type)
1033 return -EINVAL; 1033 return -EINVAL;
1034 1034
1035 return v4l2_event_subscribe(fh, sub, STAT_NEVENTS); 1035 return v4l2_event_subscribe(fh, sub, STAT_NEVENTS, NULL);
1036} 1036}
1037 1037
1038int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, 1038int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index c93a9796f1fb..91b197819fc2 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -2468,7 +2468,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
2468 struct v4l2_event_subscription *sub) 2468 struct v4l2_event_subscription *sub)
2469{ 2469{
2470 if (sub->type == V4L2_EVENT_CTRL) 2470 if (sub->type == V4L2_EVENT_CTRL)
2471 return v4l2_event_subscribe(fh, sub, 0); 2471 return v4l2_event_subscribe(fh, sub, 0, NULL);
2472 return -EINVAL; 2472 return -EINVAL;
2473} 2473}
2474EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); 2474EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c
index c26ad9637143..0ba2dfa86d07 100644
--- a/drivers/media/video/v4l2-event.c
+++ b/drivers/media/video/v4l2-event.c
@@ -120,6 +120,14 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
120 if (sev == NULL) 120 if (sev == NULL)
121 return; 121 return;
122 122
123 /*
124 * If the event has been added to the fh->subscribed list, but its
125 * add op has not completed yet elems will be 0, treat this as
126 * not being subscribed.
127 */
128 if (!sev->elems)
129 return;
130
123 /* Increase event sequence number on fh. */ 131 /* Increase event sequence number on fh. */
124 fh->sequence++; 132 fh->sequence++;
125 133
@@ -132,14 +140,14 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
132 sev->first = sev_pos(sev, 1); 140 sev->first = sev_pos(sev, 1);
133 fh->navailable--; 141 fh->navailable--;
134 if (sev->elems == 1) { 142 if (sev->elems == 1) {
135 if (sev->replace) { 143 if (sev->ops && sev->ops->replace) {
136 sev->replace(&kev->event, ev); 144 sev->ops->replace(&kev->event, ev);
137 copy_payload = false; 145 copy_payload = false;
138 } 146 }
139 } else if (sev->merge) { 147 } else if (sev->ops && sev->ops->merge) {
140 struct v4l2_kevent *second_oldest = 148 struct v4l2_kevent *second_oldest =
141 sev->events + sev_pos(sev, 0); 149 sev->events + sev_pos(sev, 0);
142 sev->merge(&kev->event, &second_oldest->event); 150 sev->ops->merge(&kev->event, &second_oldest->event);
143 } 151 }
144 } 152 }
145 153
@@ -208,8 +216,14 @@ static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new)
208 new->u.ctrl.changes |= old->u.ctrl.changes; 216 new->u.ctrl.changes |= old->u.ctrl.changes;
209} 217}
210 218
219static const struct v4l2_subscribed_event_ops ctrl_ops = {
220 .replace = ctrls_replace,
221 .merge = ctrls_merge,
222};
223
211int v4l2_event_subscribe(struct v4l2_fh *fh, 224int v4l2_event_subscribe(struct v4l2_fh *fh,
212 struct v4l2_event_subscription *sub, unsigned elems) 225 struct v4l2_event_subscription *sub, unsigned elems,
226 const struct v4l2_subscribed_event_ops *ops)
213{ 227{
214 struct v4l2_subscribed_event *sev, *found_ev; 228 struct v4l2_subscribed_event *sev, *found_ev;
215 struct v4l2_ctrl *ctrl = NULL; 229 struct v4l2_ctrl *ctrl = NULL;
@@ -236,10 +250,9 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
236 sev->id = sub->id; 250 sev->id = sub->id;
237 sev->flags = sub->flags; 251 sev->flags = sub->flags;
238 sev->fh = fh; 252 sev->fh = fh;
239 sev->elems = elems; 253 sev->ops = ops;
240 if (ctrl) { 254 if (ctrl) {
241 sev->replace = ctrls_replace; 255 sev->ops = &ctrl_ops;
242 sev->merge = ctrls_merge;
243 } 256 }
244 257
245 spin_lock_irqsave(&fh->vdev->fh_lock, flags); 258 spin_lock_irqsave(&fh->vdev->fh_lock, flags);
@@ -248,12 +261,27 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
248 list_add(&sev->list, &fh->subscribed); 261 list_add(&sev->list, &fh->subscribed);
249 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); 262 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
250 263
251 /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */ 264 if (found_ev) {
252 if (found_ev)
253 kfree(sev); 265 kfree(sev);
254 else if (ctrl) 266 return 0; /* Already listening */
267 }
268
269 if (sev->ops && sev->ops->add) {
270 int ret = sev->ops->add(sev);
271 if (ret) {
272 sev->ops = NULL;
273 v4l2_event_unsubscribe(fh, sub);
274 return ret;
275 }
276 }
277
278 /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
279 if (ctrl)
255 v4l2_ctrl_add_event(ctrl, sev); 280 v4l2_ctrl_add_event(ctrl, sev);
256 281
282 /* Mark as ready for use */
283 sev->elems = elems;
284
257 return 0; 285 return 0;
258} 286}
259EXPORT_SYMBOL_GPL(v4l2_event_subscribe); 287EXPORT_SYMBOL_GPL(v4l2_event_subscribe);
@@ -306,6 +334,10 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
306 } 334 }
307 335
308 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); 336 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
337
338 if (sev && sev->ops && sev->ops->del)
339 sev->ops->del(sev);
340
309 if (sev && sev->type == V4L2_EVENT_CTRL) { 341 if (sev && sev->type == V4L2_EVENT_CTRL) {
310 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id); 342 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id);
311 343
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c
index f6e083b50191..90db5fe9c56e 100644
--- a/drivers/usb/gadget/uvc_v4l2.c
+++ b/drivers/usb/gadget/uvc_v4l2.c
@@ -296,7 +296,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
296 if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) 296 if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
297 return -EINVAL; 297 return -EINVAL;
298 298
299 return v4l2_event_subscribe(&handle->vfh, arg, 2); 299 return v4l2_event_subscribe(&handle->vfh, arg, 2, NULL);
300 } 300 }
301 301
302 case VIDIOC_UNSUBSCRIBE_EVENT: 302 case VIDIOC_UNSUBSCRIBE_EVENT: