summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch297
1 files changed, 297 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch b/extras/recipes-kernel/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch
new file mode 100644
index 00000000..f2120201
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch
@@ -0,0 +1,297 @@
1From d71c2e533be956a95e4ddde8b87f657ada3c9de3 Mon Sep 17 00:00:00 2001
2From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3Date: Mon, 12 Jul 2010 16:09:41 +0200
4Subject: [PATCH 01/43] v4l: Share code between video_usercopy and video_ioctl2
5
6The two functions are mostly identical. They handle the copy_from_user
7and copy_to_user operations related with V4L2 ioctls and call the real
8ioctl handler.
9
10Create a __video_usercopy function that implements the core of
11video_usercopy and video_ioctl2, and call that function from both.
12
13Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14---
15 drivers/media/video/v4l2-ioctl.c | 218 ++++++++++++-------------------------
16 1 files changed, 71 insertions(+), 147 deletions(-)
17
18diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
19index dd9283f..1e01554 100644
20--- a/drivers/media/video/v4l2-ioctl.c
21+++ b/drivers/media/video/v4l2-ioctl.c
22@@ -374,35 +374,62 @@ video_fix_command(unsigned int cmd)
23 }
24 #endif
25
26-/*
27- * Obsolete usercopy function - Should be removed soon
28- */
29-long
30-video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
31+/* In some cases, only a few fields are used as input, i.e. when the app sets
32+ * "index" and then the driver fills in the rest of the structure for the thing
33+ * with that index. We only need to copy up the first non-input field. */
34+static unsigned long cmd_input_size(unsigned int cmd)
35+{
36+ /* Size of structure up to and including 'field' */
37+#define CMDINSIZE(cmd, type, field) \
38+ case VIDIOC_##cmd: \
39+ return offsetof(struct v4l2_##type, field) + \
40+ sizeof(((struct v4l2_##type *)0)->field);
41+
42+ switch (cmd) {
43+ CMDINSIZE(ENUM_FMT, fmtdesc, type);
44+ CMDINSIZE(G_FMT, format, type);
45+ CMDINSIZE(QUERYBUF, buffer, type);
46+ CMDINSIZE(G_PARM, streamparm, type);
47+ CMDINSIZE(ENUMSTD, standard, index);
48+ CMDINSIZE(ENUMINPUT, input, index);
49+ CMDINSIZE(G_CTRL, control, id);
50+ CMDINSIZE(G_TUNER, tuner, index);
51+ CMDINSIZE(QUERYCTRL, queryctrl, id);
52+ CMDINSIZE(QUERYMENU, querymenu, index);
53+ CMDINSIZE(ENUMOUTPUT, output, index);
54+ CMDINSIZE(G_MODULATOR, modulator, index);
55+ CMDINSIZE(G_FREQUENCY, frequency, tuner);
56+ CMDINSIZE(CROPCAP, cropcap, type);
57+ CMDINSIZE(G_CROP, crop, type);
58+ CMDINSIZE(ENUMAUDIO, audio, index);
59+ CMDINSIZE(ENUMAUDOUT, audioout, index);
60+ CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
61+ CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
62+ CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
63+ CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
64+ CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
65+ default:
66+ return _IOC_SIZE(cmd);
67+ }
68+}
69+
70+static long
71+__video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
72 v4l2_kioctl func)
73 {
74 char sbuf[128];
75 void *mbuf = NULL;
76- void *parg = NULL;
77+ void *parg = (void *)arg;
78 long err = -EINVAL;
79 int is_ext_ctrl;
80 size_t ctrls_size = 0;
81 void __user *user_ptr = NULL;
82
83-#ifdef __OLD_VIDIOC_
84- cmd = video_fix_command(cmd);
85-#endif
86 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
87 cmd == VIDIOC_TRY_EXT_CTRLS);
88
89 /* Copy arguments into temp kernel buffer */
90- switch (_IOC_DIR(cmd)) {
91- case _IOC_NONE:
92- parg = NULL;
93- break;
94- case _IOC_READ:
95- case _IOC_WRITE:
96- case (_IOC_WRITE | _IOC_READ):
97+ if (_IOC_DIR(cmd) != _IOC_NONE) {
98 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
99 parg = sbuf;
100 } else {
101@@ -414,11 +441,21 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
102 }
103
104 err = -EFAULT;
105- if (_IOC_DIR(cmd) & _IOC_WRITE)
106- if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
107+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
108+ unsigned long n = cmd_input_size(cmd);
109+
110+ if (copy_from_user(parg, (void __user *)arg, n))
111 goto out;
112- break;
113+
114+ /* zero out anything we don't copy from userspace */
115+ if (n < _IOC_SIZE(cmd))
116+ memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
117+ } else {
118+ /* read-only ioctl */
119+ memset(parg, 0, _IOC_SIZE(cmd));
120+ }
121 }
122+
123 if (is_ext_ctrl) {
124 struct v4l2_ext_controls *p = parg;
125
126@@ -440,7 +477,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
127 }
128 }
129
130- /* call driver */
131+ /* Handles IOCTL */
132 err = func(file, cmd, parg);
133 if (err == -ENOIOCTLCMD)
134 err = -EINVAL;
135@@ -469,6 +506,19 @@ out:
136 kfree(mbuf);
137 return err;
138 }
139+
140+/*
141+ * Obsolete usercopy function - Should be removed soon
142+ */
143+long
144+video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
145+ v4l2_kioctl func)
146+{
147+#ifdef __OLD_VIDIOC_
148+ cmd = video_fix_command(cmd);
149+#endif
150+ return __video_usercopy(file, cmd, arg, func);
151+}
152 EXPORT_SYMBOL(video_usercopy);
153
154 static void dbgbuf(unsigned int cmd, struct video_device *vfd,
155@@ -2041,138 +2091,12 @@ static long __video_do_ioctl(struct file *file,
156 return ret;
157 }
158
159-/* In some cases, only a few fields are used as input, i.e. when the app sets
160- * "index" and then the driver fills in the rest of the structure for the thing
161- * with that index. We only need to copy up the first non-input field. */
162-static unsigned long cmd_input_size(unsigned int cmd)
163-{
164- /* Size of structure up to and including 'field' */
165-#define CMDINSIZE(cmd, type, field) \
166- case VIDIOC_##cmd: \
167- return offsetof(struct v4l2_##type, field) + \
168- sizeof(((struct v4l2_##type *)0)->field);
169-
170- switch (cmd) {
171- CMDINSIZE(ENUM_FMT, fmtdesc, type);
172- CMDINSIZE(G_FMT, format, type);
173- CMDINSIZE(QUERYBUF, buffer, type);
174- CMDINSIZE(G_PARM, streamparm, type);
175- CMDINSIZE(ENUMSTD, standard, index);
176- CMDINSIZE(ENUMINPUT, input, index);
177- CMDINSIZE(G_CTRL, control, id);
178- CMDINSIZE(G_TUNER, tuner, index);
179- CMDINSIZE(QUERYCTRL, queryctrl, id);
180- CMDINSIZE(QUERYMENU, querymenu, index);
181- CMDINSIZE(ENUMOUTPUT, output, index);
182- CMDINSIZE(G_MODULATOR, modulator, index);
183- CMDINSIZE(G_FREQUENCY, frequency, tuner);
184- CMDINSIZE(CROPCAP, cropcap, type);
185- CMDINSIZE(G_CROP, crop, type);
186- CMDINSIZE(ENUMAUDIO, audio, index);
187- CMDINSIZE(ENUMAUDOUT, audioout, index);
188- CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
189- CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
190- CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
191- CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
192- CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
193- default:
194- return _IOC_SIZE(cmd);
195- }
196-}
197-
198 long video_ioctl2(struct file *file,
199 unsigned int cmd, unsigned long arg)
200 {
201- char sbuf[128];
202- void *mbuf = NULL;
203- void *parg = (void *)arg;
204- long err = -EINVAL;
205- int is_ext_ctrl;
206- size_t ctrls_size = 0;
207- void __user *user_ptr = NULL;
208-
209 #ifdef __OLD_VIDIOC_
210 cmd = video_fix_command(cmd);
211 #endif
212- is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
213- cmd == VIDIOC_TRY_EXT_CTRLS);
214-
215- /* Copy arguments into temp kernel buffer */
216- if (_IOC_DIR(cmd) != _IOC_NONE) {
217- if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
218- parg = sbuf;
219- } else {
220- /* too big to allocate from stack */
221- mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
222- if (NULL == mbuf)
223- return -ENOMEM;
224- parg = mbuf;
225- }
226-
227- err = -EFAULT;
228- if (_IOC_DIR(cmd) & _IOC_WRITE) {
229- unsigned long n = cmd_input_size(cmd);
230-
231- if (copy_from_user(parg, (void __user *)arg, n))
232- goto out;
233-
234- /* zero out anything we don't copy from userspace */
235- if (n < _IOC_SIZE(cmd))
236- memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
237- } else {
238- /* read-only ioctl */
239- memset(parg, 0, _IOC_SIZE(cmd));
240- }
241- }
242-
243- if (is_ext_ctrl) {
244- struct v4l2_ext_controls *p = parg;
245-
246- /* In case of an error, tell the caller that it wasn't
247- a specific control that caused it. */
248- p->error_idx = p->count;
249- user_ptr = (void __user *)p->controls;
250- if (p->count) {
251- ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
252- /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
253- mbuf = kmalloc(ctrls_size, GFP_KERNEL);
254- err = -ENOMEM;
255- if (NULL == mbuf)
256- goto out_ext_ctrl;
257- err = -EFAULT;
258- if (copy_from_user(mbuf, user_ptr, ctrls_size))
259- goto out_ext_ctrl;
260- p->controls = mbuf;
261- }
262- }
263-
264- /* Handles IOCTL */
265- err = __video_do_ioctl(file, cmd, parg);
266- if (err == -ENOIOCTLCMD)
267- err = -EINVAL;
268- if (is_ext_ctrl) {
269- struct v4l2_ext_controls *p = parg;
270-
271- p->controls = (void *)user_ptr;
272- if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
273- err = -EFAULT;
274- goto out_ext_ctrl;
275- }
276- if (err < 0)
277- goto out;
278-
279-out_ext_ctrl:
280- /* Copy results into user buffer */
281- switch (_IOC_DIR(cmd)) {
282- case _IOC_READ:
283- case (_IOC_WRITE | _IOC_READ):
284- if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
285- err = -EFAULT;
286- break;
287- }
288-
289-out:
290- kfree(mbuf);
291- return err;
292+ return __video_usercopy(file, cmd, arg, __video_do_ioctl);
293 }
294 EXPORT_SYMBOL(video_ioctl2);
295--
2961.6.6.1
297