forked from clearlinux-pkgs/linux-iot-lts2018
-
Notifications
You must be signed in to change notification settings - Fork 0
/
0048-v4l-subdev-Add-GS-_ROUTING-subdev-ioctls-and.patch
279 lines (266 loc) · 9.22 KB
/
0048-v4l-subdev-Add-GS-_ROUTING-subdev-ioctls-and.patch
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
From d199b0c765e2231c91654335a593fa5dafe3e19e Mon Sep 17 00:00:00 2001
From: Meng Wei <[email protected]>
Date: Fri, 26 Oct 2018 09:52:15 +0800
Subject: [PATCH 05/25] v4l: subdev: Add [GS]_ROUTING subdev ioctls and
operations
add get/set_routing subdev ioctls and helper functions.
Signed-off-by: Chang Ying <[email protected]>
Signed-off-by: Meng Wei <[email protected]>
---
drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 70 +++++++++++++++++++
drivers/media/v4l2-core/v4l2-ioctl.c | 16 +++++
drivers/media/v4l2-core/v4l2-subdev.c | 34 +++++++++
include/media/v4l2-subdev.h | 4 ++
include/uapi/linux/v4l2-subdev.h | 45 ++++++++++++
5 files changed, 169 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 222653915699..1fbb67714312 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1051,6 +1051,57 @@ static int put_v4l2_event32(struct v4l2_event __user *p64,
return 0;
}
+struct v4l2_subdev_routing32 {
+ compat_caddr_t routes;
+ __u32 num_routes;
+ __u32 reserved[5];
+};
+
+static int get_v4l2_subdev_routing(struct v4l2_subdev_routing __user *kp,
+ struct v4l2_subdev_routing32 __user *up)
+{
+ compat_caddr_t p;
+ u32 num_routes;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(p, &up->routes) ||
+ put_user(compat_ptr(p), &kp->routes) ||
+ get_user(num_routes, &kp->num_routes) ||
+ assign_in_user(&kp->num_routes, &up->num_routes) ||
+ !access_ok(VERIFY_READ, up->reserved, sizeof(*up->reserved)) ||
+ num_routes > U32_MAX / sizeof(*kp->routes))
+ return -EFAULT;
+
+ if (!access_ok(VERIFY_READ, compat_ptr(p),
+ num_routes * (u32)sizeof(*kp->routes)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int put_v4l2_subdev_routing(struct v4l2_subdev_routing __user *kp,
+ struct v4l2_subdev_routing32 __user *up)
+{
+ struct v4l2_subdev_route __user *uroutes;
+ compat_caddr_t p;
+ u32 num_routes;
+
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ get_user(p, &up->routes) ||
+ get_user(num_routes, &kp->num_routes) ||
+ assign_in_user(&up->num_routes, &kp->num_routes) ||
+ !access_ok(VERIFY_WRITE, up->reserved, sizeof(*up->reserved)))
+ return -EFAULT;
+
+ uroutes = compat_ptr(p);
+
+ if (!access_ok(VERIFY_WRITE, uroutes,
+ num_routes * sizeof(*kp->routes)))
+ return -EFAULT;
+
+ return 0;
+}
+
struct v4l2_edid32 {
__u32 pad;
__u32 start_block;
@@ -1123,6 +1174,8 @@ static int put_v4l2_edid32(struct v4l2_edid __user *p64,
#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
#define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
+#define VIDIOC_SUBDEV_G_ROUTING32 _IOWR('V', 38, struct v4l2_subdev_routing32)
+#define VIDIOC_SUBDEV_S_ROUTING32 _IOWR('V', 39, struct v4l2_subdev_routing32)
#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
@@ -1201,6 +1254,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
+ case VIDIOC_SUBDEV_G_ROUTING32: cmd = VIDIOC_SUBDEV_G_ROUTING; break;
+ case VIDIOC_SUBDEV_S_ROUTING32: cmd = VIDIOC_SUBDEV_S_ROUTING; break;
case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
@@ -1233,6 +1288,14 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
compatible_arg = 0;
break;
+ case VIDIOC_SUBDEV_G_ROUTING:
+ case VIDIOC_SUBDEV_S_ROUTING:
+ err = alloc_userspace(sizeof(struct v4l2_subdev_routing), 0, &new_p64);
+ if (!err)
+ err = get_v4l2_subdev_routing(new_p64, p32);
+ compatible_arg = 0;
+ break;
+
case VIDIOC_G_EDID:
case VIDIOC_S_EDID:
err = alloc_userspace(sizeof(struct v4l2_edid), 0, &new_p64);
@@ -1374,6 +1437,13 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
if (put_v4l2_edid32(new_p64, p32))
err = -EFAULT;
break;
+ case VIDIOC_SUBDEV_G_ROUTING:
+ case VIDIOC_SUBDEV_S_ROUTING:
+ err = alloc_userspace(sizeof(struct v4l2_subdev_routing), 0, &new_p64);
+ if (!err)
+ if (put_v4l2_subdev_routing(new_p64, p32))
+ err = -EFAULT;
+ break;
}
if (err)
return err;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 54afc9c7ee6e..41bfb83665ef 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2924,6 +2924,22 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
}
break;
}
+ case VIDIOC_SUBDEV_G_ROUTING:
+ case VIDIOC_SUBDEV_S_ROUTING: {
+ struct v4l2_subdev_routing *route = parg;
+
+ if (route->num_routes > 0) {
+ if (route->num_routes > 256)
+ return -EINVAL;
+
+ *user_ptr = (void __user *)route->routes;
+ *kernel_ptr = (void *)&route->routes;
+ *array_size = sizeof(struct v4l2_subdev_route)
+ * route->num_routes;
+ ret = 1;
+ }
+ break;
+ }
}
return ret;
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 12eb646c4bc7..5d0ee2fd384a 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -522,6 +522,40 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_QUERYSTD:
return v4l2_subdev_call(sd, video, querystd, arg);
+
+ case VIDIOC_SUBDEV_G_ROUTING:
+ return v4l2_subdev_call(sd, pad, get_routing, arg);
+
+ case VIDIOC_SUBDEV_S_ROUTING: {
+ struct v4l2_subdev_routing *route = arg;
+ unsigned int i;
+ int rval;
+
+ if (route->num_routes > sd->entity.num_pads)
+ return -EINVAL;
+
+ for (i = 0; i < route->num_routes; ++i) {
+ unsigned int sink = route->routes[i].sink_pad;
+ unsigned int source = route->routes[i].source_pad;
+ struct media_pad *pads = sd->entity.pads;
+
+ if (sink >= sd->entity.num_pads ||
+ source >= sd->entity.num_pads)
+ return -EINVAL;
+
+ if ((!(route->routes[i].flags &
+ V4L2_SUBDEV_ROUTE_FL_SOURCE) &&
+ !(pads[sink].flags & MEDIA_PAD_FL_SINK)) ||
+ !(pads[source].flags & MEDIA_PAD_FL_SOURCE))
+ return -EINVAL;
+ }
+
+ mutex_lock(&sd->entity.graph_obj.mdev->graph_mutex);
+ rval = v4l2_subdev_call(sd, pad, set_routing, route);
+ mutex_unlock(&sd->entity.graph_obj.mdev->graph_mutex);
+
+ return rval;
+ }
#endif
default:
return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 6f87e7f81759..4bd777a68d64 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -719,6 +719,10 @@ struct v4l2_subdev_pad_ops {
struct v4l2_mbus_frame_desc *fd);
int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
struct v4l2_mbus_frame_desc *fd);
+ int (*get_routing)(struct v4l2_subdev *sd,
+ struct v4l2_subdev_routing *route);
+ int (*set_routing)(struct v4l2_subdev *sd,
+ struct v4l2_subdev_routing *route);
};
/**
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 51f637dff468..2ed7ebae6e83 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -168,6 +168,49 @@ struct v4l2_subdev_selection {
__u32 reserved[7];
};
+#define V4L2_SUBDEV_ROUTE_FL_ACTIVE (1 << 0)
+#define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE (1 << 1)
+#define V4L2_SUBDEV_ROUTE_FL_SOURCE (1 << 2)
+
+/**
+ * struct v4l2_subdev_route - A signal route inside a subdev
+ * @sink_pad: the sink pad
+ * @sink_stream: the sink stream
+ * @source_pad: the source pad
+ * @source_stream: the source stream
+ * @flags: route flags:
+ *
+ * V4L2_SUBDEV_ROUTE_FL_ACTIVE: Is the stream in use or not? An
+ * active stream will start when streaming is enabled on a video
+ * node. Set by the user.
+ *
+ * V4L2_SUBDEV_ROUTE_FL_IMMUTABLE: Is the stream immutable, i.e.
+ * can it be activated and inactivated? Set by the driver.
+ *
+ * V4L2_SUBDEV_ROUTE_FL_SOURCE: Is the sub-device the source of a
+ * stream? In this case the sink information is unused (and
+ * zero). Set by the driver.
+ */
+struct v4l2_subdev_route {
+ __u32 sink_pad;
+ __u32 sink_stream;
+ __u32 source_pad;
+ __u32 source_stream;
+ __u32 flags;
+ __u32 reserved[5];
+};
+
+/**
+ * struct v4l2_subdev_routing - Routing information
+ * @routes: the routes array
+ * @num_routes: the total number of routes in the routes array
+ */
+struct v4l2_subdev_routing {
+ struct v4l2_subdev_route *routes;
+ __u32 num_routes;
+ __u32 reserved[5];
+};
+
/* Backwards compatibility define --- to be removed */
#define v4l2_subdev_edid v4l2_edid
@@ -194,5 +237,7 @@ struct v4l2_subdev_selection {
#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings)
#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings)
#define VIDIOC_SUBDEV_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap)
+#define VIDIOC_SUBDEV_G_ROUTING _IOWR('V', 38, struct v4l2_subdev_routing)
+#define VIDIOC_SUBDEV_S_ROUTING _IOWR('V', 39, struct v4l2_subdev_routing)
#endif
--
2.19.1