diff options
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 3 | ||||
-rw-r--r-- | drivers/media/video/v4l2-ctrls.c | 41 | ||||
-rw-r--r-- | drivers/media/video/v4l2-event.c | 39 | ||||
-rw-r--r-- | include/media/v4l2-ctrls.h | 7 |
4 files changed, 39 insertions, 51 deletions
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index a7730fd4827f..70cd802c9ca8 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -1468,8 +1468,9 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti | |||
1468 | switch (sub->type) { | 1468 | switch (sub->type) { |
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: | ||
1472 | return v4l2_event_subscribe(fh, sub, 0, NULL); | 1471 | return v4l2_event_subscribe(fh, sub, 0, NULL); |
1472 | case V4L2_EVENT_CTRL: | ||
1473 | return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); | ||
1473 | default: | 1474 | default: |
1474 | return -EINVAL; | 1475 | return -EINVAL; |
1475 | } | 1476 | } |
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 91b197819fc2..ae544d870d7d 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c | |||
@@ -2424,9 +2424,13 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) | |||
2424 | } | 2424 | } |
2425 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); | 2425 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); |
2426 | 2426 | ||
2427 | void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, | 2427 | static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev) |
2428 | struct v4l2_subscribed_event *sev) | ||
2429 | { | 2428 | { |
2429 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); | ||
2430 | |||
2431 | if (ctrl == NULL) | ||
2432 | return -EINVAL; | ||
2433 | |||
2430 | v4l2_ctrl_lock(ctrl); | 2434 | v4l2_ctrl_lock(ctrl); |
2431 | list_add_tail(&sev->node, &ctrl->ev_subs); | 2435 | list_add_tail(&sev->node, &ctrl->ev_subs); |
2432 | if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && | 2436 | if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && |
@@ -2440,17 +2444,40 @@ void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, | |||
2440 | v4l2_event_queue_fh(sev->fh, &ev); | 2444 | v4l2_event_queue_fh(sev->fh, &ev); |
2441 | } | 2445 | } |
2442 | v4l2_ctrl_unlock(ctrl); | 2446 | v4l2_ctrl_unlock(ctrl); |
2447 | return 0; | ||
2443 | } | 2448 | } |
2444 | EXPORT_SYMBOL(v4l2_ctrl_add_event); | ||
2445 | 2449 | ||
2446 | void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, | 2450 | static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev) |
2447 | struct v4l2_subscribed_event *sev) | ||
2448 | { | 2451 | { |
2452 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); | ||
2453 | |||
2449 | v4l2_ctrl_lock(ctrl); | 2454 | v4l2_ctrl_lock(ctrl); |
2450 | list_del(&sev->node); | 2455 | list_del(&sev->node); |
2451 | v4l2_ctrl_unlock(ctrl); | 2456 | v4l2_ctrl_unlock(ctrl); |
2452 | } | 2457 | } |
2453 | EXPORT_SYMBOL(v4l2_ctrl_del_event); | 2458 | |
2459 | void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new) | ||
2460 | { | ||
2461 | u32 old_changes = old->u.ctrl.changes; | ||
2462 | |||
2463 | old->u.ctrl = new->u.ctrl; | ||
2464 | old->u.ctrl.changes |= old_changes; | ||
2465 | } | ||
2466 | EXPORT_SYMBOL(v4l2_ctrl_replace); | ||
2467 | |||
2468 | void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new) | ||
2469 | { | ||
2470 | new->u.ctrl.changes |= old->u.ctrl.changes; | ||
2471 | } | ||
2472 | EXPORT_SYMBOL(v4l2_ctrl_merge); | ||
2473 | |||
2474 | const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = { | ||
2475 | .add = v4l2_ctrl_add_event, | ||
2476 | .del = v4l2_ctrl_del_event, | ||
2477 | .replace = v4l2_ctrl_replace, | ||
2478 | .merge = v4l2_ctrl_merge, | ||
2479 | }; | ||
2480 | EXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops); | ||
2454 | 2481 | ||
2455 | int v4l2_ctrl_log_status(struct file *file, void *fh) | 2482 | int v4l2_ctrl_log_status(struct file *file, void *fh) |
2456 | { | 2483 | { |
@@ -2468,7 +2495,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, | |||
2468 | struct v4l2_event_subscription *sub) | 2495 | struct v4l2_event_subscription *sub) |
2469 | { | 2496 | { |
2470 | if (sub->type == V4L2_EVENT_CTRL) | 2497 | if (sub->type == V4L2_EVENT_CTRL) |
2471 | return v4l2_event_subscribe(fh, sub, 0, NULL); | 2498 | return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); |
2472 | return -EINVAL; | 2499 | return -EINVAL; |
2473 | } | 2500 | } |
2474 | EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); | 2501 | EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); |
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 0ba2dfa86d07..60b4e2e9c874 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <media/v4l2-dev.h> | 25 | #include <media/v4l2-dev.h> |
26 | #include <media/v4l2-fh.h> | 26 | #include <media/v4l2-fh.h> |
27 | #include <media/v4l2-event.h> | 27 | #include <media/v4l2-event.h> |
28 | #include <media/v4l2-ctrls.h> | ||
29 | 28 | ||
30 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
@@ -203,30 +202,11 @@ int v4l2_event_pending(struct v4l2_fh *fh) | |||
203 | } | 202 | } |
204 | EXPORT_SYMBOL_GPL(v4l2_event_pending); | 203 | EXPORT_SYMBOL_GPL(v4l2_event_pending); |
205 | 204 | ||
206 | static void ctrls_replace(struct v4l2_event *old, const struct v4l2_event *new) | ||
207 | { | ||
208 | u32 old_changes = old->u.ctrl.changes; | ||
209 | |||
210 | old->u.ctrl = new->u.ctrl; | ||
211 | old->u.ctrl.changes |= old_changes; | ||
212 | } | ||
213 | |||
214 | static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new) | ||
215 | { | ||
216 | new->u.ctrl.changes |= old->u.ctrl.changes; | ||
217 | } | ||
218 | |||
219 | static const struct v4l2_subscribed_event_ops ctrl_ops = { | ||
220 | .replace = ctrls_replace, | ||
221 | .merge = ctrls_merge, | ||
222 | }; | ||
223 | |||
224 | int v4l2_event_subscribe(struct v4l2_fh *fh, | 205 | int v4l2_event_subscribe(struct v4l2_fh *fh, |
225 | struct v4l2_event_subscription *sub, unsigned elems, | 206 | struct v4l2_event_subscription *sub, unsigned elems, |
226 | const struct v4l2_subscribed_event_ops *ops) | 207 | const struct v4l2_subscribed_event_ops *ops) |
227 | { | 208 | { |
228 | struct v4l2_subscribed_event *sev, *found_ev; | 209 | struct v4l2_subscribed_event *sev, *found_ev; |
229 | struct v4l2_ctrl *ctrl = NULL; | ||
230 | unsigned long flags; | 210 | unsigned long flags; |
231 | unsigned i; | 211 | unsigned i; |
232 | 212 | ||
@@ -235,11 +215,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, | |||
235 | 215 | ||
236 | if (elems < 1) | 216 | if (elems < 1) |
237 | elems = 1; | 217 | elems = 1; |
238 | if (sub->type == V4L2_EVENT_CTRL) { | ||
239 | ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id); | ||
240 | if (ctrl == NULL) | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | 218 | ||
244 | sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL); | 219 | sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL); |
245 | if (!sev) | 220 | if (!sev) |
@@ -251,9 +226,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, | |||
251 | sev->flags = sub->flags; | 226 | sev->flags = sub->flags; |
252 | sev->fh = fh; | 227 | sev->fh = fh; |
253 | sev->ops = ops; | 228 | sev->ops = ops; |
254 | if (ctrl) { | ||
255 | sev->ops = &ctrl_ops; | ||
256 | } | ||
257 | 229 | ||
258 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | 230 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); |
259 | found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); | 231 | found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); |
@@ -275,10 +247,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, | |||
275 | } | 247 | } |
276 | } | 248 | } |
277 | 249 | ||
278 | /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */ | ||
279 | if (ctrl) | ||
280 | v4l2_ctrl_add_event(ctrl, sev); | ||
281 | |||
282 | /* Mark as ready for use */ | 250 | /* Mark as ready for use */ |
283 | sev->elems = elems; | 251 | sev->elems = elems; |
284 | 252 | ||
@@ -338,13 +306,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, | |||
338 | if (sev && sev->ops && sev->ops->del) | 306 | if (sev && sev->ops && sev->ops->del) |
339 | sev->ops->del(sev); | 307 | sev->ops->del(sev); |
340 | 308 | ||
341 | if (sev && sev->type == V4L2_EVENT_CTRL) { | ||
342 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id); | ||
343 | |||
344 | if (ctrl) | ||
345 | v4l2_ctrl_del_event(ctrl, sev); | ||
346 | } | ||
347 | |||
348 | kfree(sev); | 309 | kfree(sev); |
349 | 310 | ||
350 | return 0; | 311 | return 0; |
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 8920f8210eab..c6f6b4c2c5f2 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h | |||
@@ -491,10 +491,9 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl); | |||
491 | int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val); | 491 | int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val); |
492 | 492 | ||
493 | /* Internal helper functions that deal with control events. */ | 493 | /* Internal helper functions that deal with control events. */ |
494 | void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, | 494 | extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops; |
495 | struct v4l2_subscribed_event *sev); | 495 | void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new); |
496 | void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, | 496 | void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new); |
497 | struct v4l2_subscribed_event *sev); | ||
498 | 497 | ||
499 | struct file; | 498 | struct file; |
500 | /* Can be used as a vidioc_log_status function that just dumps all controls | 499 | /* Can be used as a vidioc_log_status function that just dumps all controls |