aboutsummaryrefslogtreecommitdiff
path: root/include/media/v4l2-event.h
blob: 6741910c3a18978cfd7fd2dc295a4a11ea680538 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * v4l2-event.h
 *
 * V4L2 events.
 *
 * Copyright (C) 2009--2010 Nokia Corporation.
 *
 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#ifndef V4L2_EVENT_H
#define V4L2_EVENT_H

#include <linux/types.h>
#include <linux/videodev2.h>
#include <linux/wait.h>

/*
 * Overview:
 *
 * Events are subscribed per-filehandle. An event specification consists of a
 * type and is optionally associated with an object identified through the
 * 'id' field. So an event is uniquely identified by the (type, id) tuple.
 *
 * The v4l2-fh struct has a list of subscribed events. The v4l2_subscribed_event
 * struct is added to that list, one for every subscribed event.
 *
 * Each v4l2_subscribed_event struct ends with an array of v4l2_kevent structs.
 * This array (ringbuffer, really) is used to store any events raised by the
 * driver. The v4l2_kevent struct links into the 'available' list of the
 * v4l2_fh struct so VIDIOC_DQEVENT will know which event to dequeue first.
 *
 * Finally, if the event subscription is associated with a particular object
 * such as a V4L2 control, then that object needs to know about that as well
 * so that an event can be raised by that object. So the 'node' field can
 * be used to link the v4l2_subscribed_event struct into a list of that
 * object.
 *
 * So to summarize:
 *
 * struct v4l2_fh has two lists: one of the subscribed events, and one of the
 * pending events.
 *
 * struct v4l2_subscribed_event has a ringbuffer of raised (pending) events of
 * that particular type.
 *
 * If struct v4l2_subscribed_event is associated with a specific object, then
 * that object will have an internal list of struct v4l2_subscribed_event so
 * it knows who subscribed an event to that object.
 */

struct v4l2_fh;
struct v4l2_subdev;
struct v4l2_subscribed_event;
struct video_device;

/**
 * struct v4l2_kevent - Internal kernel event struct.
 * @list:	List node for the v4l2_fh->available list.
 * @sev:	Pointer to parent v4l2_subscribed_event.
 * @event:	The event itself.
 */
struct v4l2_kevent {
	struct list_head	list;
	struct v4l2_subscribed_event *sev;
	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, unsigned int elems);
	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.
 * @id:	Associated object ID (e.g. control ID). 0 if there isn't any.
 * @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).
 * @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.
 * @events:	An array of @elems events.
 */
struct v4l2_subscribed_event {
	struct list_head	list;
	u32			type;
	u32			id;
	u32			flags;
	struct v4l2_fh		*fh;
	struct list_head	node;
	const struct v4l2_subscribed_event_ops *ops;
	unsigned int		elems;
	unsigned int		first;
	unsigned int		in_use;
	struct v4l2_kevent	events[];
};

/**
 * v4l2_event_dequeue - Dequeue events from video device.
 *
 * @fh: pointer to struct v4l2_fh
 * @event: pointer to struct v4l2_event
 * @nonblocking: if not zero, waits for an event to arrive
 */
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
		       int nonblocking);

/**
 * v4l2_event_queue - Queue events to video device.
 *
 * @vdev: pointer to &struct video_device
 * @ev: pointer to &struct v4l2_event
 *
 * The event will be queued for all &struct v4l2_fh file handlers.
 *
 * .. note::
 *    The driver's only responsibility is to fill in the type and the data
 *    fields.The other fields will be filled in by  V4L2.
 */
void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev);

/**
 * v4l2_event_queue_fh - Queue events to video device.
 *
 * @fh: pointer to &struct v4l2_fh
 * @ev: pointer to &struct v4l2_event
 *
 *
 * The event will be queued only for the specified &struct v4l2_fh file handler.
 *
 * .. note::
 *    The driver's only responsibility is to fill in the type and the data
 *    fields.The other fields will be filled in by  V4L2.
 */
void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev);

/**
 * v4l2_event_pending - Check if an event is available
 *
 * @fh: pointer to &struct v4l2_fh
 *
 * Returns the number of pending events.
 */
int v4l2_event_pending(struct v4l2_fh *fh);

/**
 * v4l2_event_subscribe - Subscribes to an event
 *
 * @fh: pointer to &struct v4l2_fh
 * @sub: pointer to &struct v4l2_event_subscription
 * @elems: size of the events queue
 * @ops: pointer to &v4l2_subscribed_event_ops
 *
 * .. note::
 *
 *    if @elems is zero, the framework will fill in a default value,
 *    with is currently 1 element.
 */
int v4l2_event_subscribe(struct v4l2_fh *fh,
			 const struct v4l2_event_subscription *sub,
			 unsigned int elems,
			 const struct v4l2_subscribed_event_ops *ops);
/**
 * v4l2_event_unsubscribe - Unsubscribes to an event
 *
 * @fh: pointer to &struct v4l2_fh
 * @sub: pointer to &struct v4l2_event_subscription
 */
int v4l2_event_unsubscribe(struct v4l2_fh *fh,
			   const struct v4l2_event_subscription *sub);
/**
 * v4l2_event_unsubscribe_all - Unsubscribes to all events
 *
 * @fh: pointer to &struct v4l2_fh
 */
void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);

/**
 * v4l2_event_subdev_unsubscribe - Subdev variant of v4l2_event_unsubscribe()
 *
 * @sd: pointer to &struct v4l2_subdev
 * @fh: pointer to &struct v4l2_fh
 * @sub: pointer to &struct v4l2_event_subscription
 *
 * .. note::
 *
 *	This function should be used for the &struct v4l2_subdev_core_ops
 *	%unsubscribe_event field.
 */
int v4l2_event_subdev_unsubscribe(struct v4l2_subdev *sd,
				  struct v4l2_fh *fh,
				  struct v4l2_event_subscription *sub);
/**
 * v4l2_src_change_event_subscribe - helper function that calls
 * 	v4l2_event_subscribe() if the event is %V4L2_EVENT_SOURCE_CHANGE.
 *
 * @fh: pointer to struct v4l2_fh
 * @sub: pointer to &struct v4l2_event_subscription
 */
int v4l2_src_change_event_subscribe(struct v4l2_fh *fh,
				    const struct v4l2_event_subscription *sub);
/**
 * v4l2_src_change_event_subdev_subscribe - Variant of v4l2_event_subscribe(),
 *	meant to subscribe only events of the type %V4L2_EVENT_SOURCE_CHANGE.
 *
 * @sd: pointer to &struct v4l2_subdev
 * @fh: pointer to &struct v4l2_fh
 * @sub: pointer to &struct v4l2_event_subscription
 */
int v4l2_src_change_event_subdev_subscribe(struct v4l2_subdev *sd,
					   struct v4l2_fh *fh,
					   struct v4l2_event_subscription *sub);
#endif /* V4L2_EVENT_H */