* [PATCH 00/10] uvcvideo: Add support for control events (v2)
@ 2012-04-08 15:59 Hans de Goede
2012-04-08 15:59 ` [PATCH 01/10] media/radio: use v4l2_ctrl_subscribe_event where possible Hans de Goede
` (10 more replies)
0 siblings, 11 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List
Here is v2 of my uvcvideo ctrl events patchset. It hopefully addresses
all remarks you had wrt the previous version.
As discussed before this also contains some none uvcvideo changes, which
are necessary for the uvcvideo ctrl event support. Since these patches
have already been reviewed and they are a dependency of the further patches
in this set it is probably best for these patches to go upstream through
your tree too.
Regards,
Hans
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/10] media/radio: use v4l2_ctrl_subscribe_event where possible
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 02/10] v4l2-event: Add v4l2_subscribed_event_ops Hans de Goede
` (9 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/radio/radio-isa.c | 10 +---------
drivers/media/radio/radio-keene.c | 14 +-------------
2 files changed, 2 insertions(+), 22 deletions(-)
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 06f9063..1346046 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -150,14 +150,6 @@ static int radio_isa_log_status(struct file *file, void *priv)
return 0;
}
-static int radio_isa_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- if (sub->type == V4L2_EVENT_CTRL)
- return v4l2_event_subscribe(fh, sub, 0);
- return -EINVAL;
-}
-
static const struct v4l2_ctrl_ops radio_isa_ctrl_ops = {
.s_ctrl = radio_isa_s_ctrl,
};
@@ -177,7 +169,7 @@ static const struct v4l2_ioctl_ops radio_isa_ioctl_ops = {
.vidioc_g_frequency = radio_isa_g_frequency,
.vidioc_s_frequency = radio_isa_s_frequency,
.vidioc_log_status = radio_isa_log_status,
- .vidioc_subscribe_event = radio_isa_subscribe_event,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c
index 55bd1d2..e1c72b0 100644
--- a/drivers/media/radio/radio-keene.c
+++ b/drivers/media/radio/radio-keene.c
@@ -256,18 +256,6 @@ static int keene_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL;
}
-static int vidioc_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- switch (sub->type) {
- case V4L2_EVENT_CTRL:
- return v4l2_event_subscribe(fh, sub, 0);
- default:
- return -EINVAL;
- }
-}
-
-
/* File system interface */
static const struct v4l2_file_operations usb_keene_fops = {
.owner = THIS_MODULE,
@@ -288,7 +276,7 @@ static const struct v4l2_ioctl_ops usb_keene_ioctl_ops = {
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
.vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = vidioc_subscribe_event,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 02/10] v4l2-event: Add v4l2_subscribed_event_ops
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
2012-04-08 15:59 ` [PATCH 01/10] media/radio: use v4l2_ctrl_subscribe_event where possible Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 03/10] v4l2-ctrls: Use v4l2_subscribed_event_ops Hans de Goede
` (8 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
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>
---
Documentation/video4linux/v4l2-framework.txt | 28 +++++++++----
drivers/media/video/ivtv/ivtv-ioctl.c | 2 +-
drivers/media/video/omap3isp/ispccdc.c | 2 +-
drivers/media/video/omap3isp/ispstat.c | 2 +-
drivers/media/video/v4l2-ctrls.c | 2 +-
drivers/media/video/v4l2-event.c | 54 ++++++++++++++++++++------
drivers/usb/gadget/uvc_v4l2.c | 2 +-
include/media/v4l2-event.h | 24 ++++++++----
8 files changed, 86 insertions(+), 30 deletions(-)
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 659b2ba..b77bb48 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -941,21 +941,35 @@ fast.
Useful functions:
-- v4l2_event_queue()
+void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
Queue events to video device. The driver's only responsibility is to fill
in the type and the data fields. The other fields will be filled in by
V4L2.
-- v4l2_event_subscribe()
+int v4l2_event_subscribe(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub, unsigned elems,
+ const struct v4l2_subscribed_event_ops *ops)
The video_device->ioctl_ops->vidioc_subscribe_event must check the driver
is able to produce events with specified event id. Then it calls
- v4l2_event_subscribe() to subscribe the event. The last argument is the
- size of the event queue for this event. If it is 0, then the framework
- will fill in a default value (this depends on the event type).
+ v4l2_event_subscribe() to subscribe the event.
-- v4l2_event_unsubscribe()
+ The elems argument is the size of the event queue for this event. If it is 0,
+ then the framework will fill in a default value (this depends on the event
+ type).
+
+ The ops argument allows the driver to specify a number of callbacks:
+ * add: called when a new listener gets added (subscribing to the same
+ event twice will only cause this callback to get called once)
+ * del: called when a listener stops listening
+ * replace: replace event 'old' with event 'new'.
+ * merge: merge event 'old' into event 'new'.
+ All 4 callbacks are optional, if you don't want to specify any callbacks
+ the ops argument itself maybe NULL.
+
+int v4l2_event_unsubscribe(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
vidioc_unsubscribe_event in struct v4l2_ioctl_ops. A driver may use
v4l2_event_unsubscribe() directly unless it wants to be involved in
@@ -964,7 +978,7 @@ Useful functions:
The special type V4L2_EVENT_ALL may be used to unsubscribe all events. The
drivers may want to handle this in a special way.
-- v4l2_event_pending()
+int v4l2_event_pending(struct v4l2_fh *fh)
Returns the number of pending events. Useful when implementing poll.
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 5452bee..5b41e5b 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
case V4L2_EVENT_VSYNC:
case V4L2_EVENT_EOS:
case V4L2_EVENT_CTRL:
- return v4l2_event_subscribe(fh, sub, 0);
+ return v4l2_event_subscribe(fh, sub, 0, NULL);
default:
return -EINVAL;
}
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index eaabc27..1f3c16d 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,
if (sub->id != 0)
return -EINVAL;
- return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS);
+ return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS, NULL);
}
static 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 11871ec..b8640be 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,
if (sub->type != stat->event_type)
return -EINVAL;
- return v4l2_event_subscribe(fh, sub, STAT_NEVENTS);
+ return v4l2_event_subscribe(fh, sub, STAT_NEVENTS, NULL);
}
int 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 18015c0..7023e6d 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -2425,7 +2425,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
if (sub->type == V4L2_EVENT_CTRL)
- return v4l2_event_subscribe(fh, sub, 0);
+ return v4l2_event_subscribe(fh, sub, 0, NULL);
return -EINVAL;
}
EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c
index c26ad96..0ba2dfa 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
if (sev == NULL)
return;
+ /*
+ * If the event has been added to the fh->subscribed list, but its
+ * add op has not completed yet elems will be 0, treat this as
+ * not being subscribed.
+ */
+ if (!sev->elems)
+ return;
+
/* Increase event sequence number on fh. */
fh->sequence++;
@@ -132,14 +140,14 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
sev->first = sev_pos(sev, 1);
fh->navailable--;
if (sev->elems == 1) {
- if (sev->replace) {
- sev->replace(&kev->event, ev);
+ if (sev->ops && sev->ops->replace) {
+ sev->ops->replace(&kev->event, ev);
copy_payload = false;
}
- } else if (sev->merge) {
+ } else if (sev->ops && sev->ops->merge) {
struct v4l2_kevent *second_oldest =
sev->events + sev_pos(sev, 0);
- sev->merge(&kev->event, &second_oldest->event);
+ sev->ops->merge(&kev->event, &second_oldest->event);
}
}
@@ -208,8 +216,14 @@ static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new)
new->u.ctrl.changes |= old->u.ctrl.changes;
}
+static const struct v4l2_subscribed_event_ops ctrl_ops = {
+ .replace = ctrls_replace,
+ .merge = ctrls_merge,
+};
+
int v4l2_event_subscribe(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub, unsigned elems)
+ struct v4l2_event_subscription *sub, unsigned elems,
+ const struct v4l2_subscribed_event_ops *ops)
{
struct v4l2_subscribed_event *sev, *found_ev;
struct v4l2_ctrl *ctrl = NULL;
@@ -236,10 +250,9 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
sev->id = sub->id;
sev->flags = sub->flags;
sev->fh = fh;
- sev->elems = elems;
+ sev->ops = ops;
if (ctrl) {
- sev->replace = ctrls_replace;
- sev->merge = ctrls_merge;
+ sev->ops = &ctrl_ops;
}
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
@@ -248,12 +261,27 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
list_add(&sev->list, &fh->subscribed);
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
- /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
- if (found_ev)
+ if (found_ev) {
kfree(sev);
- else if (ctrl)
+ return 0; /* Already listening */
+ }
+
+ if (sev->ops && sev->ops->add) {
+ int ret = sev->ops->add(sev);
+ if (ret) {
+ sev->ops = NULL;
+ v4l2_event_unsubscribe(fh, sub);
+ return ret;
+ }
+ }
+
+ /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
+ if (ctrl)
v4l2_ctrl_add_event(ctrl, sev);
+ /* Mark as ready for use */
+ sev->elems = elems;
+
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_event_subscribe);
@@ -306,6 +334,10 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
}
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
+
+ if (sev && sev->ops && sev->ops->del)
+ sev->ops->del(sev);
+
if (sev && sev->type == V4L2_EVENT_CTRL) {
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id);
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c
index f6e083b..90db5fe 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)
if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
return -EINVAL;
- return v4l2_event_subscribe(&handle->vfh, arg, 2);
+ return v4l2_event_subscribe(&handle->vfh, arg, 2, NULL);
}
case VIDIOC_UNSUBSCRIBE_EVENT:
diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h
index 5f14e88..88fa9a1 100644
--- a/include/media/v4l2-event.h
+++ b/include/media/v4l2-event.h
@@ -78,6 +78,19 @@ struct v4l2_kevent {
struct v4l2_event event;
};
+/** struct v4l2_subscribed_event_ops - Subscribed event operations.
+ * @add: Optional callback, called when a new listener is added
+ * @del: Optional callback, called when a listener stops listening
+ * @replace: Optional callback that can replace event 'old' with event 'new'.
+ * @merge: Optional callback that can merge event 'old' into event 'new'.
+ */
+struct v4l2_subscribed_event_ops {
+ int (*add)(struct v4l2_subscribed_event *sev);
+ void (*del)(struct v4l2_subscribed_event *sev);
+ void (*replace)(struct v4l2_event *old, const struct v4l2_event *new);
+ void (*merge)(const struct v4l2_event *old, struct v4l2_event *new);
+};
+
/** struct v4l2_subscribed_event - Internal struct representing a subscribed event.
* @list: List node for the v4l2_fh->subscribed list.
* @type: Event type.
@@ -85,8 +98,7 @@ struct v4l2_kevent {
* @flags: Copy of v4l2_event_subscription->flags.
* @fh: Filehandle that subscribed to this event.
* @node: List node that hooks into the object's event list (if there is one).
- * @replace: Optional callback that can replace event 'old' with event 'new'.
- * @merge: Optional callback that can merge event 'old' into event 'new'.
+ * @ops: v4l2_subscribed_event_ops
* @elems: The number of elements in the events array.
* @first: The index of the events containing the oldest available event.
* @in_use: The number of queued events.
@@ -99,10 +111,7 @@ struct v4l2_subscribed_event {
u32 flags;
struct v4l2_fh *fh;
struct list_head node;
- void (*replace)(struct v4l2_event *old,
- const struct v4l2_event *new);
- void (*merge)(const struct v4l2_event *old,
- struct v4l2_event *new);
+ const struct v4l2_subscribed_event_ops *ops;
unsigned elems;
unsigned first;
unsigned in_use;
@@ -115,7 +124,8 @@ void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev);
void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev);
int v4l2_event_pending(struct v4l2_fh *fh);
int v4l2_event_subscribe(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub, unsigned elems);
+ struct v4l2_event_subscription *sub, unsigned elems,
+ const struct v4l2_subscribed_event_ops *ops);
int v4l2_event_unsubscribe(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 03/10] v4l2-ctrls: Use v4l2_subscribed_event_ops
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
2012-04-08 15:59 ` [PATCH 01/10] media/radio: use v4l2_ctrl_subscribe_event where possible Hans de Goede
2012-04-08 15:59 ` [PATCH 02/10] v4l2-event: Add v4l2_subscribed_event_ops Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 04/10] uvcvideo: Fix a "ignoring return value of ‘__clear_user’" warning Hans de Goede
` (7 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/video/ivtv/ivtv-ioctl.c | 3 +-
drivers/media/video/v4l2-ctrls.c | 58 ++++++++++++++++++++++++++-------
drivers/media/video/v4l2-event.c | 39 ----------------------
include/media/v4l2-ctrls.h | 7 ++--
4 files changed, 52 insertions(+), 55 deletions(-)
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 5b41e5b..0c9cf0d 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
switch (sub->type) {
case V4L2_EVENT_VSYNC:
case V4L2_EVENT_EOS:
- case V4L2_EVENT_CTRL:
return v4l2_event_subscribe(fh, sub, 0, NULL);
+ case V4L2_EVENT_CTRL:
+ return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
default:
return -EINVAL;
}
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 7023e6d..2a44355 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -2381,10 +2381,22 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
}
EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
-void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev)
+static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev)
{
- v4l2_ctrl_lock(ctrl);
+ struct v4l2_ctrl_handler *hdl = sev->fh->ctrl_handler;
+ struct v4l2_ctrl_ref *ref;
+ struct v4l2_ctrl *ctrl;
+ int ret = 0;
+
+ mutex_lock(&hdl->lock);
+
+ ref = find_ref(hdl, sev->id);
+ if (!ref) {
+ ret = -EINVAL;
+ goto leave;
+ }
+ ctrl = ref->ctrl;
+
list_add_tail(&sev->node, &ctrl->ev_subs);
if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
(sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) {
@@ -2396,18 +2408,42 @@ void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
fill_event(&ev, ctrl, changes);
v4l2_event_queue_fh(sev->fh, &ev);
}
- v4l2_ctrl_unlock(ctrl);
+leave:
+ mutex_unlock(&hdl->lock);
+ return ret;
}
-EXPORT_SYMBOL(v4l2_ctrl_add_event);
-void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev)
+static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev)
{
- v4l2_ctrl_lock(ctrl);
+ struct v4l2_ctrl_handler *hdl = sev->fh->ctrl_handler;
+
+ mutex_lock(&hdl->lock);
list_del(&sev->node);
- v4l2_ctrl_unlock(ctrl);
+ mutex_unlock(&hdl->lock);
}
-EXPORT_SYMBOL(v4l2_ctrl_del_event);
+
+void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new)
+{
+ u32 old_changes = old->u.ctrl.changes;
+
+ old->u.ctrl = new->u.ctrl;
+ old->u.ctrl.changes |= old_changes;
+}
+EXPORT_SYMBOL(v4l2_ctrl_replace);
+
+void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new)
+{
+ new->u.ctrl.changes |= old->u.ctrl.changes;
+}
+EXPORT_SYMBOL(v4l2_ctrl_merge);
+
+const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = {
+ .add = v4l2_ctrl_add_event,
+ .del = v4l2_ctrl_del_event,
+ .replace = v4l2_ctrl_replace,
+ .merge = v4l2_ctrl_merge,
+};
+EXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops);
int v4l2_ctrl_log_status(struct file *file, void *fh)
{
@@ -2425,7 +2461,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
if (sub->type == V4L2_EVENT_CTRL)
- return v4l2_event_subscribe(fh, sub, 0, NULL);
+ return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
return -EINVAL;
}
EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c
index 0ba2dfa..60b4e2e 100644
--- a/drivers/media/video/v4l2-event.c
+++ b/drivers/media/video/v4l2-event.c
@@ -25,7 +25,6 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-event.h>
-#include <media/v4l2-ctrls.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -203,30 +202,11 @@ int v4l2_event_pending(struct v4l2_fh *fh)
}
EXPORT_SYMBOL_GPL(v4l2_event_pending);
-static void ctrls_replace(struct v4l2_event *old, const struct v4l2_event *new)
-{
- u32 old_changes = old->u.ctrl.changes;
-
- old->u.ctrl = new->u.ctrl;
- old->u.ctrl.changes |= old_changes;
-}
-
-static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new)
-{
- new->u.ctrl.changes |= old->u.ctrl.changes;
-}
-
-static const struct v4l2_subscribed_event_ops ctrl_ops = {
- .replace = ctrls_replace,
- .merge = ctrls_merge,
-};
-
int v4l2_event_subscribe(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub, unsigned elems,
const struct v4l2_subscribed_event_ops *ops)
{
struct v4l2_subscribed_event *sev, *found_ev;
- struct v4l2_ctrl *ctrl = NULL;
unsigned long flags;
unsigned i;
@@ -235,11 +215,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
if (elems < 1)
elems = 1;
- if (sub->type == V4L2_EVENT_CTRL) {
- ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
- if (ctrl == NULL)
- return -EINVAL;
- }
sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL);
if (!sev)
@@ -251,9 +226,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
sev->flags = sub->flags;
sev->fh = fh;
sev->ops = ops;
- if (ctrl) {
- sev->ops = &ctrl_ops;
- }
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
@@ -275,10 +247,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
}
}
- /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
- if (ctrl)
- v4l2_ctrl_add_event(ctrl, sev);
-
/* Mark as ready for use */
sev->elems = elems;
@@ -338,13 +306,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
if (sev && sev->ops && sev->ops->del)
sev->ops->del(sev);
- if (sev && sev->type == V4L2_EVENT_CTRL) {
- struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id);
-
- if (ctrl)
- v4l2_ctrl_del_event(ctrl, sev);
- }
-
kfree(sev);
return 0;
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 11e6756..fe82376 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -487,10 +487,9 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
/* Internal helper functions that deal with control events. */
-void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev);
-void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev);
+extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops;
+void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new);
+void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new);
/* Can be used as a vidioc_log_status function that just dumps all controls
associated with the filehandle. */
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 04/10] uvcvideo: Fix a "ignoring return value of ‘__clear_user’" warning
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (2 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 03/10] v4l2-ctrls: Use v4l2_subscribed_event_ops Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 05/10] uvcvideo: Refactor uvc_ctrl_get and query Hans de Goede
` (6 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/uvc/uvc_v4l2.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index ff2cddd..8db90ef 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -1097,7 +1097,8 @@ static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
__put_user(kp->menu_count, &up->menu_count))
return -EFAULT;
- __clear_user(up->reserved, sizeof(up->reserved));
+ if (__clear_user(up->reserved, sizeof(up->reserved)))
+ return -EFAULT;
if (kp->menu_count == 0)
return 0;
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 05/10] uvcvideo: Refactor uvc_ctrl_get and query
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (3 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 04/10] uvcvideo: Fix a "ignoring return value of ‘__clear_user’" warning Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 06/10] uvcvideo: Move __uvc_ctrl_get() up Hans de Goede
` (5 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
This is a preparation patch for adding ctrl event support.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/video/uvc/uvc_ctrl.c | 77 +++++++++++++++++++++++-------------
1 file changed, 49 insertions(+), 28 deletions(-)
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 0efd3b1..d20d0de 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -899,24 +899,13 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
return 0;
}
-int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
struct v4l2_queryctrl *v4l2_ctrl)
{
- struct uvc_control *ctrl;
- struct uvc_control_mapping *mapping;
struct uvc_menu_info *menu;
unsigned int i;
- int ret;
-
- ret = mutex_lock_interruptible(&chain->ctrl_mutex);
- if (ret < 0)
- return -ERESTARTSYS;
-
- ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
- if (ctrl == NULL) {
- ret = -EINVAL;
- goto done;
- }
memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
v4l2_ctrl->id = mapping->id;
@@ -930,9 +919,9 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
if (!ctrl->cached) {
- ret = uvc_ctrl_populate_cache(chain, ctrl);
+ int ret = uvc_ctrl_populate_cache(chain, ctrl);
if (ret < 0)
- goto done;
+ return ret;
}
if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
@@ -954,19 +943,19 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
}
}
- goto done;
+ return 0;
case V4L2_CTRL_TYPE_BOOLEAN:
v4l2_ctrl->minimum = 0;
v4l2_ctrl->maximum = 1;
v4l2_ctrl->step = 1;
- goto done;
+ return 0;
case V4L2_CTRL_TYPE_BUTTON:
v4l2_ctrl->minimum = 0;
v4l2_ctrl->maximum = 0;
v4l2_ctrl->step = 0;
- goto done;
+ return 0;
default:
break;
@@ -984,6 +973,27 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
+ return 0;
+}
+
+int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+ struct v4l2_queryctrl *v4l2_ctrl)
+{
+ struct uvc_control *ctrl;
+ struct uvc_control_mapping *mapping;
+ int ret;
+
+ ret = mutex_lock_interruptible(&chain->ctrl_mutex);
+ if (ret < 0)
+ return -ERESTARTSYS;
+
+ ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
+ if (ctrl == NULL) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl);
done:
mutex_unlock(&chain->ctrl_mutex);
return ret;
@@ -1148,17 +1158,15 @@ done:
return ret;
}
-int uvc_ctrl_get(struct uvc_video_chain *chain,
- struct v4l2_ext_control *xctrl)
+static int __uvc_ctrl_get(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
+ s32 *value)
{
- struct uvc_control *ctrl;
- struct uvc_control_mapping *mapping;
struct uvc_menu_info *menu;
unsigned int i;
int ret;
- ctrl = uvc_find_control(chain, xctrl->id, &mapping);
- if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
+ if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
return -EINVAL;
if (!ctrl->loaded) {
@@ -1172,14 +1180,14 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
ctrl->loaded = 1;
}
- xctrl->value = mapping->get(mapping, UVC_GET_CUR,
+ *value = mapping->get(mapping, UVC_GET_CUR,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
menu = mapping->menu_info;
for (i = 0; i < mapping->menu_count; ++i, ++menu) {
- if (menu->value == xctrl->value) {
- xctrl->value = i;
+ if (menu->value == *value) {
+ *value = i;
break;
}
}
@@ -1188,6 +1196,19 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
return 0;
}
+int uvc_ctrl_get(struct uvc_video_chain *chain,
+ struct v4l2_ext_control *xctrl)
+{
+ struct uvc_control *ctrl;
+ struct uvc_control_mapping *mapping;
+
+ ctrl = uvc_find_control(chain, xctrl->id, &mapping);
+ if (ctrl == NULL)
+ return -EINVAL;
+
+ return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
+}
+
int uvc_ctrl_set(struct uvc_video_chain *chain,
struct v4l2_ext_control *xctrl)
{
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 06/10] uvcvideo: Move __uvc_ctrl_get() up
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (4 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 05/10] uvcvideo: Refactor uvc_ctrl_get and query Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 07/10] uvcvideo: Add support for control events Hans de Goede
` (4 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
This avoids the need for doing a forward declaration of __uvc_ctrl_get
(which is a static function) in later patches in this series.
Note to reviewers this patch does not change a single line of code, it
just moves the function up in uvc_ctrl.c a bit.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/video/uvc/uvc_ctrl.c | 76 ++++++++++++++++++------------------
1 file changed, 38 insertions(+), 38 deletions(-)
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index d20d0de..0c27cc1 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -899,6 +899,44 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
return 0;
}
+static int __uvc_ctrl_get(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
+ s32 *value)
+{
+ struct uvc_menu_info *menu;
+ unsigned int i;
+ int ret;
+
+ if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
+ return -EINVAL;
+
+ if (!ctrl->loaded) {
+ ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
+ chain->dev->intfnum, ctrl->info.selector,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+ ctrl->info.size);
+ if (ret < 0)
+ return ret;
+
+ ctrl->loaded = 1;
+ }
+
+ *value = mapping->get(mapping, UVC_GET_CUR,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+
+ if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
+ menu = mapping->menu_info;
+ for (i = 0; i < mapping->menu_count; ++i, ++menu) {
+ if (menu->value == *value) {
+ *value = i;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
struct uvc_control *ctrl,
struct uvc_control_mapping *mapping,
@@ -1158,44 +1196,6 @@ done:
return ret;
}
-static int __uvc_ctrl_get(struct uvc_video_chain *chain,
- struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
- s32 *value)
-{
- struct uvc_menu_info *menu;
- unsigned int i;
- int ret;
-
- if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
- return -EINVAL;
-
- if (!ctrl->loaded) {
- ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
- chain->dev->intfnum, ctrl->info.selector,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
- ctrl->info.size);
- if (ret < 0)
- return ret;
-
- ctrl->loaded = 1;
- }
-
- *value = mapping->get(mapping, UVC_GET_CUR,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
-
- if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
- menu = mapping->menu_info;
- for (i = 0; i < mapping->menu_count; ++i, ++menu) {
- if (menu->value == *value) {
- *value = i;
- break;
- }
- }
- }
-
- return 0;
-}
-
int uvc_ctrl_get(struct uvc_video_chain *chain,
struct v4l2_ext_control *xctrl)
{
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 07/10] uvcvideo: Add support for control events
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (5 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 06/10] uvcvideo: Move __uvc_ctrl_get() up Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 08/10] uvcvideo: Properly report the inactive flag for inactive controls Hans de Goede
` (3 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/video/uvc/uvc_ctrl.c | 120 +++++++++++++++++++++++++++++++++++-
drivers/media/video/uvc/uvc_v4l2.c | 43 ++++++++++---
drivers/media/video/uvc/uvcvideo.h | 20 ++++--
3 files changed, 169 insertions(+), 14 deletions(-)
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 0c27cc1..bc837a4 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -21,6 +21,7 @@
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/atomic.h>
+#include <media/v4l2-ctrls.h>
#include "uvcvideo.h"
@@ -1102,6 +1103,116 @@ done:
return ret;
}
+/* --------------------------------------------------------------------------
+ * Ctrl event handling
+ */
+
+static void uvc_ctrl_fill_event(struct uvc_video_chain *chain,
+ struct v4l2_event *ev,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
+ s32 value, u32 changes)
+{
+ struct v4l2_queryctrl v4l2_ctrl;
+
+ __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl);
+
+ memset(ev->reserved, 0, sizeof(ev->reserved));
+ ev->type = V4L2_EVENT_CTRL;
+ ev->id = v4l2_ctrl.id;
+ ev->u.ctrl.value = value;
+ ev->u.ctrl.changes = changes;
+ ev->u.ctrl.type = v4l2_ctrl.type;
+ ev->u.ctrl.flags = v4l2_ctrl.flags;
+ ev->u.ctrl.minimum = v4l2_ctrl.minimum;
+ ev->u.ctrl.maximum = v4l2_ctrl.maximum;
+ ev->u.ctrl.step = v4l2_ctrl.step;
+ ev->u.ctrl.default_value = v4l2_ctrl.default_value;
+}
+
+static void uvc_ctrl_send_event(struct uvc_fh *handle,
+ struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
+ s32 value, u32 changes)
+{
+ struct v4l2_subscribed_event *sev;
+ struct v4l2_event ev;
+
+ if (list_empty(&mapping->ev_subs))
+ return;
+
+ uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, value, changes);
+
+ list_for_each_entry(sev, &mapping->ev_subs, node)
+ if (sev->fh && (sev->fh != &handle->vfh ||
+ (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
+ v4l2_event_queue_fh(sev->fh, &ev);
+}
+
+static void uvc_ctrl_send_events(struct uvc_fh *handle,
+ const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
+{
+ struct uvc_control_mapping *mapping;
+ struct uvc_control *ctrl;
+ unsigned int i;
+
+ for (i = 0; i < xctrls_count; ++i) {
+ ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
+ uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
+ V4L2_EVENT_CTRL_CH_VALUE);
+ }
+}
+
+static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev)
+{
+ struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
+ struct uvc_control_mapping *mapping;
+ struct uvc_control *ctrl;
+ int ret;
+
+ ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex);
+ if (ret < 0)
+ return -ERESTARTSYS;
+
+ ctrl = uvc_find_control(handle->chain, sev->id, &mapping);
+ if (ctrl == NULL) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ list_add_tail(&sev->node, &mapping->ev_subs);
+ if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) {
+ struct v4l2_event ev;
+ u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
+ s32 val = 0;
+
+ if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
+ changes |= V4L2_EVENT_CTRL_CH_VALUE;
+
+ uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val,
+ changes);
+ v4l2_event_queue_fh(sev->fh, &ev);
+ }
+
+done:
+ mutex_unlock(&handle->chain->ctrl_mutex);
+ return ret;
+}
+
+static void uvc_ctrl_del_event(struct v4l2_subscribed_event *sev)
+{
+ struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
+
+ mutex_lock(&handle->chain->ctrl_mutex);
+ list_del(&sev->node);
+ mutex_unlock(&handle->chain->ctrl_mutex);
+}
+
+const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops = {
+ .add = uvc_ctrl_add_event,
+ .del = uvc_ctrl_del_event,
+ .replace = v4l2_ctrl_replace,
+ .merge = v4l2_ctrl_merge,
+};
/* --------------------------------------------------------------------------
* Control transactions
@@ -1179,8 +1290,11 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
return 0;
}
-int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback)
+int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
+ const struct v4l2_ext_control *xctrls,
+ unsigned int xctrls_count)
{
+ struct uvc_video_chain *chain = handle->chain;
struct uvc_entity *entity;
int ret = 0;
@@ -1191,6 +1305,8 @@ int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback)
goto done;
}
+ if (!rollback)
+ uvc_ctrl_send_events(handle, xctrls, xctrls_count);
done:
mutex_unlock(&chain->ctrl_mutex);
return ret;
@@ -1662,6 +1778,8 @@ static int __uvc_ctrl_add_mapping(struct uvc_device *dev,
if (map == NULL)
return -ENOMEM;
+ INIT_LIST_HEAD(&map->ev_subs);
+
size = sizeof(*mapping->menu_info) * mapping->menu_count;
map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL);
if (map->menu_info == NULL) {
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 8db90ef..edc81aa 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -25,6 +25,8 @@
#include <linux/atomic.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include "uvcvideo.h"
@@ -505,6 +507,8 @@ static int uvc_v4l2_open(struct file *file)
}
}
+ v4l2_fh_init(&handle->vfh, stream->vdev);
+ v4l2_fh_add(&handle->vfh);
handle->chain = stream->chain;
handle->stream = stream;
handle->state = UVC_HANDLE_PASSIVE;
@@ -528,6 +532,8 @@ static int uvc_v4l2_release(struct file *file)
/* Release the file handle. */
uvc_dismiss_privileges(handle);
+ v4l2_fh_del(&handle->vfh);
+ v4l2_fh_exit(&handle->vfh);
kfree(handle);
file->private_data = NULL;
@@ -584,7 +590,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return ret;
ret = uvc_ctrl_get(chain, &xctrl);
- uvc_ctrl_rollback(chain);
+ uvc_ctrl_rollback(handle);
if (ret >= 0)
ctrl->value = xctrl.value;
break;
@@ -605,10 +611,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
ret = uvc_ctrl_set(chain, &xctrl);
if (ret < 0) {
- uvc_ctrl_rollback(chain);
+ uvc_ctrl_rollback(handle);
return ret;
}
- ret = uvc_ctrl_commit(chain);
+ ret = uvc_ctrl_commit(handle, &xctrl, 1);
if (ret == 0)
ctrl->value = xctrl.value;
break;
@@ -630,13 +636,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
for (i = 0; i < ctrls->count; ++ctrl, ++i) {
ret = uvc_ctrl_get(chain, ctrl);
if (ret < 0) {
- uvc_ctrl_rollback(chain);
+ uvc_ctrl_rollback(handle);
ctrls->error_idx = i;
return ret;
}
}
ctrls->error_idx = 0;
- ret = uvc_ctrl_rollback(chain);
+ ret = uvc_ctrl_rollback(handle);
break;
}
@@ -654,7 +660,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
for (i = 0; i < ctrls->count; ++ctrl, ++i) {
ret = uvc_ctrl_set(chain, ctrl);
if (ret < 0) {
- uvc_ctrl_rollback(chain);
+ uvc_ctrl_rollback(handle);
ctrls->error_idx = i;
return ret;
}
@@ -663,9 +669,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
ctrls->error_idx = 0;
if (cmd == VIDIOC_S_EXT_CTRLS)
- ret = uvc_ctrl_commit(chain);
+ ret = uvc_ctrl_commit(handle,
+ ctrls->controls, ctrls->count);
else
- ret = uvc_ctrl_rollback(chain);
+ ret = uvc_ctrl_rollback(handle);
break;
}
@@ -990,6 +997,26 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return uvc_video_enable(stream, 0);
}
+ case VIDIOC_SUBSCRIBE_EVENT:
+ {
+ struct v4l2_event_subscription *sub = arg;
+
+ switch (sub->type) {
+ case V4L2_EVENT_CTRL:
+ return v4l2_event_subscribe(&handle->vfh, sub, 0,
+ &uvc_ctrl_sub_ev_ops);
+ default:
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+ return v4l2_event_unsubscribe(&handle->vfh, arg);
+
+ case VIDIOC_DQEVENT:
+ return v4l2_event_dequeue(&handle->vfh, arg,
+ file->f_flags & O_NONBLOCK);
+
/* Analog video standards make no sense for digital cameras. */
case VIDIOC_ENUMSTD:
case VIDIOC_QUERYSTD:
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 67f88d8..e43deb7 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -13,6 +13,8 @@
#include <linux/videodev2.h>
#include <media/media-device.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
#include <media/videobuf2-core.h>
/* --------------------------------------------------------------------------
@@ -153,6 +155,7 @@ struct uvc_control_info {
struct uvc_control_mapping {
struct list_head list;
+ struct list_head ev_subs;
struct uvc_control_info *ctrl;
@@ -524,6 +527,7 @@ enum uvc_handle_state {
};
struct uvc_fh {
+ struct v4l2_fh vfh;
struct uvc_video_chain *chain;
struct uvc_streaming *stream;
enum uvc_handle_state state;
@@ -643,6 +647,8 @@ extern int uvc_status_suspend(struct uvc_device *dev);
extern int uvc_status_resume(struct uvc_device *dev);
/* Controls */
+extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops;
+
extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
struct v4l2_queryctrl *v4l2_ctrl);
extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
@@ -655,14 +661,18 @@ extern void uvc_ctrl_cleanup_device(struct uvc_device *dev);
extern int uvc_ctrl_resume_device(struct uvc_device *dev);
extern int uvc_ctrl_begin(struct uvc_video_chain *chain);
-extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback);
-static inline int uvc_ctrl_commit(struct uvc_video_chain *chain)
+extern int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
+ const struct v4l2_ext_control *xctrls,
+ unsigned int xctrls_count);
+static inline int uvc_ctrl_commit(struct uvc_fh *handle,
+ const struct v4l2_ext_control *xctrls,
+ unsigned int xctrls_count)
{
- return __uvc_ctrl_commit(chain, 0);
+ return __uvc_ctrl_commit(handle, 0, xctrls, xctrls_count);
}
-static inline int uvc_ctrl_rollback(struct uvc_video_chain *chain)
+static inline int uvc_ctrl_rollback(struct uvc_fh *handle)
{
- return __uvc_ctrl_commit(chain, 1);
+ return __uvc_ctrl_commit(handle, 1, NULL, 0);
}
extern int uvc_ctrl_get(struct uvc_video_chain *chain,
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 08/10] uvcvideo: Properly report the inactive flag for inactive controls
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (6 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 07/10] uvcvideo: Add support for control events Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 09/10] uvcvideo: Send control change events for slave ctrls when the master changes Hans de Goede
` (2 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
Note the unused in this patch slave_ids addition to the mappings will get
used in a follow up patch to generate control change events for the slave
ctrls when their flags change due to the master control changing value.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/uvc/uvc_ctrl.c | 33 +++++++++++++++++++++++++++++++++
drivers/media/video/uvc/uvcvideo.h | 4 ++++
2 files changed, 37 insertions(+)
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index bc837a4..75a4995 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -421,6 +421,8 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
+ .master_id = V4L2_CID_HUE_AUTO,
+ .master_manual = 0,
},
{
.id = V4L2_CID_SATURATION,
@@ -493,6 +495,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
+ .slave_ids = { V4L2_CID_HUE, },
},
{
.id = V4L2_CID_EXPOSURE_AUTO,
@@ -505,6 +508,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.data_type = UVC_CTRL_DATA_TYPE_BITMASK,
.menu_info = exposure_auto_controls,
.menu_count = ARRAY_SIZE(exposure_auto_controls),
+ .slave_ids = { V4L2_CID_EXPOSURE_ABSOLUTE, },
},
{
.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
@@ -525,6 +529,8 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
+ .master_id = V4L2_CID_EXPOSURE_AUTO,
+ .master_manual = V4L2_EXPOSURE_MANUAL,
},
{
.id = V4L2_CID_AUTO_WHITE_BALANCE,
@@ -535,6 +541,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
+ .slave_ids = { V4L2_CID_WHITE_BALANCE_TEMPERATURE, },
},
{
.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
@@ -545,6 +552,8 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
+ .master_id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .master_manual = 0,
},
{
.id = V4L2_CID_AUTO_WHITE_BALANCE,
@@ -555,6 +564,8 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
+ .slave_ids = { V4L2_CID_BLUE_BALANCE,
+ V4L2_CID_RED_BALANCE },
},
{
.id = V4L2_CID_BLUE_BALANCE,
@@ -565,6 +576,8 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
+ .master_id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .master_manual = 0,
},
{
.id = V4L2_CID_RED_BALANCE,
@@ -575,6 +588,8 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 16,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
+ .master_id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .master_manual = 0,
},
{
.id = V4L2_CID_FOCUS_ABSOLUTE,
@@ -585,6 +600,8 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
+ .master_id = V4L2_CID_FOCUS_AUTO,
+ .master_manual = 0,
},
{
.id = V4L2_CID_FOCUS_AUTO,
@@ -595,6 +612,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
+ .slave_ids = { V4L2_CID_FOCUS_ABSOLUTE, },
},
{
.id = V4L2_CID_IRIS_ABSOLUTE,
@@ -943,6 +961,8 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
struct uvc_control_mapping *mapping,
struct v4l2_queryctrl *v4l2_ctrl)
{
+ struct uvc_control_mapping *master_map = NULL;
+ struct uvc_control *master_ctrl = NULL;
struct uvc_menu_info *menu;
unsigned int i;
@@ -957,6 +977,19 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ if (mapping->master_id)
+ __uvc_find_control(ctrl->entity, mapping->master_id,
+ &master_map, &master_ctrl, 0);
+ if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) {
+ s32 val;
+ int ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != mapping->master_manual)
+ v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ }
+
if (!ctrl->cached) {
int ret = uvc_ctrl_populate_cache(chain, ctrl);
if (ret < 0)
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index e43deb7..777bb75 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -172,6 +172,10 @@ struct uvc_control_mapping {
struct uvc_menu_info *menu_info;
__u32 menu_count;
+ __u32 master_id;
+ __s32 master_manual;
+ __u32 slave_ids[2];
+
__s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,
const __u8 *data);
void (*set) (struct uvc_control_mapping *mapping, __s32 value,
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 09/10] uvcvideo: Send control change events for slave ctrls when the master changes
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (7 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 08/10] uvcvideo: Properly report the inactive flag for inactive controls Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-23 22:18 ` Laurent Pinchart
2012-04-08 15:59 ` [PATCH 10/10] uvcvideo: Drop unused ctrl member from struct uvc_control_mapping Hans de Goede
2012-04-23 18:08 ` [PATCH 00/10] uvcvideo: Add support for control events (v2) Laurent Pinchart
10 siblings, 1 reply; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
This allows v4l2 control UI-s to update the inactive state (ie grey-ing
out of controls) for slave controls when the master control changes.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/uvc/uvc_ctrl.c | 57 ++++++++++++++++++++++++++++++++++--
1 file changed, 54 insertions(+), 3 deletions(-)
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 75a4995..38d633a 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1177,21 +1177,72 @@ static void uvc_ctrl_send_event(struct uvc_fh *handle,
list_for_each_entry(sev, &mapping->ev_subs, node)
if (sev->fh && (sev->fh != &handle->vfh ||
- (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
+ (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) ||
+ (changes & V4L2_EVENT_CTRL_CH_FLAGS)))
v4l2_event_queue_fh(sev->fh, &ev);
}
-static void uvc_ctrl_send_events(struct uvc_fh *handle,
+static void uvc_ctrl_send_slave_event(struct uvc_fh *handle, u32 slave_id,
const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
{
struct uvc_control_mapping *mapping;
struct uvc_control *ctrl;
+ u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
+ s32 val = 0;
unsigned int i;
+ /*
+ * We can skip sending an event for the slave if the slave
+ * is being modified in the same transaction.
+ */
+ for (i = 0; i < xctrls_count; i++)
+ if (xctrls[i].id == slave_id)
+ return;
+
+ ctrl = uvc_find_control(handle->chain, slave_id, &mapping);
+ if (ctrl == NULL)
+ return;
+
+ if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
+ changes |= V4L2_EVENT_CTRL_CH_VALUE;
+
+ uvc_ctrl_send_event(handle, ctrl, mapping, val, changes);
+}
+
+static void uvc_ctrl_send_events(struct uvc_fh *handle,
+ const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
+{
+ struct uvc_control_mapping *mapping;
+ struct uvc_control *ctrl;
+ u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
+ unsigned int i, j;
+
for (i = 0; i < xctrls_count; ++i) {
ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
+
+ for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) {
+ if (!mapping->slave_ids[j])
+ break;
+ uvc_ctrl_send_slave_event(handle,
+ mapping->slave_ids[j],
+ xctrls, xctrls_count);
+ }
+
+ /*
+ * If the master is being modified in the same transaction
+ * flags may change too.
+ */
+ if (mapping->master_id) {
+ for (j = 0; j < xctrls_count; j++) {
+ if (xctrls[j].id == mapping->master_id) {
+ changes |= V4L2_EVENT_CTRL_CH_FLAGS;
+ break;
+ }
+ }
+ }
+
uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
- V4L2_EVENT_CTRL_CH_VALUE);
+ changes);
}
}
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 10/10] uvcvideo: Drop unused ctrl member from struct uvc_control_mapping
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (8 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 09/10] uvcvideo: Send control change events for slave ctrls when the master changes Hans de Goede
@ 2012-04-08 15:59 ` Hans de Goede
2012-04-23 18:08 ` [PATCH 00/10] uvcvideo: Add support for control events (v2) Laurent Pinchart
10 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-08 15:59 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linux Media Mailing List, Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/uvc/uvc_ctrl.c | 1 -
drivers/media/video/uvc/uvcvideo.h | 2 --
2 files changed, 3 deletions(-)
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 38d633a..d520c5c 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1876,7 +1876,6 @@ static int __uvc_ctrl_add_mapping(struct uvc_device *dev,
if (map->set == NULL)
map->set = uvc_set_le_value;
- map->ctrl = &ctrl->info;
list_add_tail(&map->list, &ctrl->info.mappings);
uvc_trace(UVC_TRACE_CONTROL,
"Adding mapping '%s' to control %pUl/%u.\n",
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 777bb75..7c3d082 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -157,8 +157,6 @@ struct uvc_control_mapping {
struct list_head list;
struct list_head ev_subs;
- struct uvc_control_info *ctrl;
-
__u32 id;
__u8 name[32];
__u8 entity[16];
--
1.7.9.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 00/10] uvcvideo: Add support for control events (v2)
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
` (9 preceding siblings ...)
2012-04-08 15:59 ` [PATCH 10/10] uvcvideo: Drop unused ctrl member from struct uvc_control_mapping Hans de Goede
@ 2012-04-23 18:08 ` Laurent Pinchart
10 siblings, 0 replies; 15+ messages in thread
From: Laurent Pinchart @ 2012-04-23 18:08 UTC (permalink / raw)
To: Hans de Goede; +Cc: Linux Media Mailing List
Hi Hans,
On Sunday 08 April 2012 17:59:44 Hans de Goede wrote:
> Here is v2 of my uvcvideo ctrl events patchset. It hopefully addresses
> all remarks you had wrt the previous version.
>
> As discussed before this also contains some none uvcvideo changes, which
> are necessary for the uvcvideo ctrl event support. Since these patches
> have already been reviewed and they are a dependency of the further patches
> in this set it is probably best for these patches to go upstream through
> your tree too.
Thank you for the patches. I haven't forgotten about you, but I've been very
busy lately. I'll try to go through your patches in the next couple of days.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 09/10] uvcvideo: Send control change events for slave ctrls when the master changes
2012-04-08 15:59 ` [PATCH 09/10] uvcvideo: Send control change events for slave ctrls when the master changes Hans de Goede
@ 2012-04-23 22:18 ` Laurent Pinchart
2012-04-23 22:48 ` [PATCH v2] " Laurent Pinchart
0 siblings, 1 reply; 15+ messages in thread
From: Laurent Pinchart @ 2012-04-23 22:18 UTC (permalink / raw)
To: Hans de Goede; +Cc: Linux Media Mailing List
Hi Hans,
Thanks for the patch.
On Sunday 08 April 2012 17:59:53 Hans de Goede wrote:
> This allows v4l2 control UI-s to update the inactive state (ie grey-ing
> out of controls) for slave controls when the master control changes.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
> drivers/media/video/uvc/uvc_ctrl.c | 57 +++++++++++++++++++++++++++++++--
> 1 file changed, 54 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/media/video/uvc/uvc_ctrl.c
> b/drivers/media/video/uvc/uvc_ctrl.c index 75a4995..38d633a 100644
> --- a/drivers/media/video/uvc/uvc_ctrl.c
> +++ b/drivers/media/video/uvc/uvc_ctrl.c
> @@ -1177,21 +1177,72 @@ static void uvc_ctrl_send_event(struct uvc_fh
> *handle,
>
> list_for_each_entry(sev, &mapping->ev_subs, node)
> if (sev->fh && (sev->fh != &handle->vfh ||
> - (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
> + (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) ||
> + (changes & V4L2_EVENT_CTRL_CH_FLAGS)))
> v4l2_event_queue_fh(sev->fh, &ev);
> }
>
> -static void uvc_ctrl_send_events(struct uvc_fh *handle,
> +static void uvc_ctrl_send_slave_event(struct uvc_fh *handle, u32 slave_id,
> const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
> {
> struct uvc_control_mapping *mapping;
> struct uvc_control *ctrl;
> + u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
> + s32 val = 0;
> unsigned int i;
>
> + /*
> + * We can skip sending an event for the slave if the slave
> + * is being modified in the same transaction.
> + */
> + for (i = 0; i < xctrls_count; i++)
> + if (xctrls[i].id == slave_id)
> + return;
> +
> + ctrl = uvc_find_control(handle->chain, slave_id, &mapping);
As an optimization, what do you think about calling __uvc_find_control()
instead (with the master control being passed as an argument to
uvc_ctrl_send_slave_event() to get the entity) ? There's no need to resubmit,
I can modify the patch myself.
> + if (ctrl == NULL)
> + return;
> +
> + if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
> + changes |= V4L2_EVENT_CTRL_CH_VALUE;
> +
> + uvc_ctrl_send_event(handle, ctrl, mapping, val, changes);
> +}
> +
> +static void uvc_ctrl_send_events(struct uvc_fh *handle,
> + const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
> +{
> + struct uvc_control_mapping *mapping;
> + struct uvc_control *ctrl;
> + u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
> + unsigned int i, j;
> +
> for (i = 0; i < xctrls_count; ++i) {
> ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
> +
> + for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) {
> + if (!mapping->slave_ids[j])
> + break;
> + uvc_ctrl_send_slave_event(handle,
> + mapping->slave_ids[j],
> + xctrls, xctrls_count);
> + }
> +
> + /*
> + * If the master is being modified in the same transaction
> + * flags may change too.
> + */
> + if (mapping->master_id) {
> + for (j = 0; j < xctrls_count; j++) {
> + if (xctrls[j].id == mapping->master_id) {
> + changes |= V4L2_EVENT_CTRL_CH_FLAGS;
> + break;
> + }
> + }
> + }
> +
> uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
> - V4L2_EVENT_CTRL_CH_VALUE);
> + changes);
> }
> }
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2] uvcvideo: Send control change events for slave ctrls when the master changes
2012-04-23 22:18 ` Laurent Pinchart
@ 2012-04-23 22:48 ` Laurent Pinchart
2012-04-24 13:08 ` Hans de Goede
0 siblings, 1 reply; 15+ messages in thread
From: Laurent Pinchart @ 2012-04-23 22:48 UTC (permalink / raw)
To: Hans de Goede; +Cc: linux-media
From: Hans de Goede <hdegoede@redhat.com>
This allows v4l2 control UI-s to update the inactive state (ie grey-ing
out of controls) for slave controls when the master control changes.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
[Use __uvc_find_control() to find slave controls, as they're always
located in the same entity as the corresponding master control]
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/video/uvc/uvc_ctrl.c | 58 ++++++++++++++++++++++++++++++++++-
1 files changed, 56 insertions(+), 2 deletions(-)
Hi Hans,
This is your 09/10 patch after replacing uvc_find_control() with
__uvc_find_control(). Could you please test it ?
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index ae7371f..03212c7 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1177,21 +1177,75 @@ static void uvc_ctrl_send_event(struct uvc_fh *handle,
list_for_each_entry(sev, &mapping->ev_subs, node)
if (sev->fh && (sev->fh != &handle->vfh ||
- (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
+ (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) ||
+ (changes & V4L2_EVENT_CTRL_CH_FLAGS)))
v4l2_event_queue_fh(sev->fh, &ev);
}
+static void uvc_ctrl_send_slave_event(struct uvc_fh *handle,
+ struct uvc_control *master, u32 slave_id,
+ const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
+{
+ struct uvc_control_mapping *mapping = NULL;
+ struct uvc_control *ctrl = NULL;
+ u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
+ unsigned int i;
+ s32 val = 0;
+
+ /*
+ * We can skip sending an event for the slave if the slave
+ * is being modified in the same transaction.
+ */
+ for (i = 0; i < xctrls_count; i++) {
+ if (xctrls[i].id == slave_id)
+ return;
+ }
+
+ __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0);
+ if (ctrl == NULL)
+ return;
+
+ if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
+ changes |= V4L2_EVENT_CTRL_CH_VALUE;
+
+ uvc_ctrl_send_event(handle, ctrl, mapping, val, changes);
+}
+
static void uvc_ctrl_send_events(struct uvc_fh *handle,
const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
{
struct uvc_control_mapping *mapping;
struct uvc_control *ctrl;
+ u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
unsigned int i;
+ unsigned int j;
for (i = 0; i < xctrls_count; ++i) {
ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
+
+ for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) {
+ if (!mapping->slave_ids[j])
+ break;
+ uvc_ctrl_send_slave_event(handle, ctrl,
+ mapping->slave_ids[j],
+ xctrls, xctrls_count);
+ }
+
+ /*
+ * If the master is being modified in the same transaction
+ * flags may change too.
+ */
+ if (mapping->master_id) {
+ for (j = 0; j < xctrls_count; j++) {
+ if (xctrls[j].id == mapping->master_id) {
+ changes |= V4L2_EVENT_CTRL_CH_FLAGS;
+ break;
+ }
+ }
+ }
+
uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
- V4L2_EVENT_CTRL_CH_VALUE);
+ changes);
}
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2] uvcvideo: Send control change events for slave ctrls when the master changes
2012-04-23 22:48 ` [PATCH v2] " Laurent Pinchart
@ 2012-04-24 13:08 ` Hans de Goede
0 siblings, 0 replies; 15+ messages in thread
From: Hans de Goede @ 2012-04-24 13:08 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: linux-media
Hi,
Good optimization, ACK.
Regards,
Hans
On 04/24/2012 12:48 AM, Laurent Pinchart wrote:
> From: Hans de Goede<hdegoede@redhat.com>
>
> This allows v4l2 control UI-s to update the inactive state (ie grey-ing
> out of controls) for slave controls when the master control changes.
>
> Signed-off-by: Hans de Goede<hdegoede@redhat.com>
> [Use __uvc_find_control() to find slave controls, as they're always
> located in the same entity as the corresponding master control]
> Signed-off-by: Laurent Pinchart<laurent.pinchart@ideasonboard.com>
> ---
> drivers/media/video/uvc/uvc_ctrl.c | 58 ++++++++++++++++++++++++++++++++++-
> 1 files changed, 56 insertions(+), 2 deletions(-)
>
> Hi Hans,
>
> This is your 09/10 patch after replacing uvc_find_control() with
> __uvc_find_control(). Could you please test it ?
>
> diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
> index ae7371f..03212c7 100644
> --- a/drivers/media/video/uvc/uvc_ctrl.c
> +++ b/drivers/media/video/uvc/uvc_ctrl.c
> @@ -1177,21 +1177,75 @@ static void uvc_ctrl_send_event(struct uvc_fh *handle,
>
> list_for_each_entry(sev,&mapping->ev_subs, node)
> if (sev->fh&& (sev->fh !=&handle->vfh ||
> - (sev->flags& V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
> + (sev->flags& V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) ||
> + (changes& V4L2_EVENT_CTRL_CH_FLAGS)))
> v4l2_event_queue_fh(sev->fh,&ev);
> }
>
> +static void uvc_ctrl_send_slave_event(struct uvc_fh *handle,
> + struct uvc_control *master, u32 slave_id,
> + const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
> +{
> + struct uvc_control_mapping *mapping = NULL;
> + struct uvc_control *ctrl = NULL;
> + u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
> + unsigned int i;
> + s32 val = 0;
> +
> + /*
> + * We can skip sending an event for the slave if the slave
> + * is being modified in the same transaction.
> + */
> + for (i = 0; i< xctrls_count; i++) {
> + if (xctrls[i].id == slave_id)
> + return;
> + }
> +
> + __uvc_find_control(master->entity, slave_id,&mapping,&ctrl, 0);
> + if (ctrl == NULL)
> + return;
> +
> + if (__uvc_ctrl_get(handle->chain, ctrl, mapping,&val) == 0)
> + changes |= V4L2_EVENT_CTRL_CH_VALUE;
> +
> + uvc_ctrl_send_event(handle, ctrl, mapping, val, changes);
> +}
> +
> static void uvc_ctrl_send_events(struct uvc_fh *handle,
> const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
> {
> struct uvc_control_mapping *mapping;
> struct uvc_control *ctrl;
> + u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
> unsigned int i;
> + unsigned int j;
>
> for (i = 0; i< xctrls_count; ++i) {
> ctrl = uvc_find_control(handle->chain, xctrls[i].id,&mapping);
> +
> + for (j = 0; j< ARRAY_SIZE(mapping->slave_ids); ++j) {
> + if (!mapping->slave_ids[j])
> + break;
> + uvc_ctrl_send_slave_event(handle, ctrl,
> + mapping->slave_ids[j],
> + xctrls, xctrls_count);
> + }
> +
> + /*
> + * If the master is being modified in the same transaction
> + * flags may change too.
> + */
> + if (mapping->master_id) {
> + for (j = 0; j< xctrls_count; j++) {
> + if (xctrls[j].id == mapping->master_id) {
> + changes |= V4L2_EVENT_CTRL_CH_FLAGS;
> + break;
> + }
> + }
> + }
> +
> uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
> - V4L2_EVENT_CTRL_CH_VALUE);
> + changes);
> }
> }
>
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2012-04-24 13:06 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-08 15:59 [PATCH 00/10] uvcvideo: Add support for control events (v2) Hans de Goede
2012-04-08 15:59 ` [PATCH 01/10] media/radio: use v4l2_ctrl_subscribe_event where possible Hans de Goede
2012-04-08 15:59 ` [PATCH 02/10] v4l2-event: Add v4l2_subscribed_event_ops Hans de Goede
2012-04-08 15:59 ` [PATCH 03/10] v4l2-ctrls: Use v4l2_subscribed_event_ops Hans de Goede
2012-04-08 15:59 ` [PATCH 04/10] uvcvideo: Fix a "ignoring return value of ‘__clear_user’" warning Hans de Goede
2012-04-08 15:59 ` [PATCH 05/10] uvcvideo: Refactor uvc_ctrl_get and query Hans de Goede
2012-04-08 15:59 ` [PATCH 06/10] uvcvideo: Move __uvc_ctrl_get() up Hans de Goede
2012-04-08 15:59 ` [PATCH 07/10] uvcvideo: Add support for control events Hans de Goede
2012-04-08 15:59 ` [PATCH 08/10] uvcvideo: Properly report the inactive flag for inactive controls Hans de Goede
2012-04-08 15:59 ` [PATCH 09/10] uvcvideo: Send control change events for slave ctrls when the master changes Hans de Goede
2012-04-23 22:18 ` Laurent Pinchart
2012-04-23 22:48 ` [PATCH v2] " Laurent Pinchart
2012-04-24 13:08 ` Hans de Goede
2012-04-08 15:59 ` [PATCH 10/10] uvcvideo: Drop unused ctrl member from struct uvc_control_mapping Hans de Goede
2012-04-23 18:08 ` [PATCH 00/10] uvcvideo: Add support for control events (v2) Laurent Pinchart
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).