linux-omap 2.6.37: sync with OE .dev
[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
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);
110 +                       if (copy_from_user(parg, (void __user *)arg, n))
111                                 goto out;
112 -               break;
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         }
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  }
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);
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 -}
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;
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);
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 -               }
227 -               err = -EFAULT;
228 -               if (_IOC_DIR(cmd) & _IOC_WRITE) {
229 -                       unsigned long n = cmd_input_size(cmd);
231 -                       if (copy_from_user(parg, (void __user *)arg, n))
232 -                               goto out;
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 -       }
243 -       if (is_ext_ctrl) {
244 -               struct v4l2_ext_controls *p = parg;
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 -       }
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;
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;
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 -       }
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