[glsdk/meta-ti-glsdk.git] / recipes-bsp / linux / linux-omap / media / 0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch
1 From d71c2e533be956a95e4ddde8b87f657ada3c9de3 Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Mon, 12 Jul 2010 16:09:41 +0200
4 Subject: [PATCH 01/43] v4l: Share code between video_usercopy and video_ioctl2
6 The two functions are mostly identical. They handle the copy_from_user
7 and copy_to_user operations related with V4L2 ioctls and call the real
8 ioctl handler.
10 Create a __video_usercopy function that implements the core of
11 video_usercopy and video_ioctl2, and call that function from both.
13 Signed-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(-)
18 diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
19 index 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
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;
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);
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 }
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;
126 @@ -440,7 +477,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
127 }
128 }
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);
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 }
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 --
296 1.6.6.1