diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-07-12 10:09:41 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:32:41 -0400 |
commit | fc0a80798576f80ca10b3f6c9c7097f12fd1d64e (patch) | |
tree | 561546ada442b0fb9df166723d601b1587d3f6b0 /drivers/media/video/v4l2-ioctl.c | |
parent | 9f00edaef8a8741a2d5333676fe9aa23a2a3d2be (diff) |
[media] v4l: Share code between video_usercopy and video_ioctl2
The two functions are mostly identical. They handle the copy_from_user
and copy_to_user operations related with V4L2 ioctls and call the real
ioctl handler.
Create a __video_usercopy function that implements the core of
video_usercopy and video_ioctl2, and call that function from both.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/v4l2-ioctl.c')
-rw-r--r-- | drivers/media/video/v4l2-ioctl.c | 109 |
1 files changed, 11 insertions, 98 deletions
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 7a720745c3fa..db6ec3868347 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -294,101 +294,6 @@ void v4l_printk_ioctl(unsigned int cmd) | |||
294 | } | 294 | } |
295 | EXPORT_SYMBOL(v4l_printk_ioctl); | 295 | EXPORT_SYMBOL(v4l_printk_ioctl); |
296 | 296 | ||
297 | /* | ||
298 | * helper function -- handles userspace copying for ioctl arguments | ||
299 | * Obsolete usercopy function - Should be removed soon | ||
300 | */ | ||
301 | long | ||
302 | video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | ||
303 | v4l2_kioctl func) | ||
304 | { | ||
305 | char sbuf[128]; | ||
306 | void *mbuf = NULL; | ||
307 | void *parg = NULL; | ||
308 | long err = -EINVAL; | ||
309 | int is_ext_ctrl; | ||
310 | size_t ctrls_size = 0; | ||
311 | void __user *user_ptr = NULL; | ||
312 | |||
313 | is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS || | ||
314 | cmd == VIDIOC_TRY_EXT_CTRLS); | ||
315 | |||
316 | /* Copy arguments into temp kernel buffer */ | ||
317 | switch (_IOC_DIR(cmd)) { | ||
318 | case _IOC_NONE: | ||
319 | parg = NULL; | ||
320 | break; | ||
321 | case _IOC_READ: | ||
322 | case _IOC_WRITE: | ||
323 | case (_IOC_WRITE | _IOC_READ): | ||
324 | if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { | ||
325 | parg = sbuf; | ||
326 | } else { | ||
327 | /* too big to allocate from stack */ | ||
328 | mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); | ||
329 | if (NULL == mbuf) | ||
330 | return -ENOMEM; | ||
331 | parg = mbuf; | ||
332 | } | ||
333 | |||
334 | err = -EFAULT; | ||
335 | if (_IOC_DIR(cmd) & _IOC_WRITE) | ||
336 | if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) | ||
337 | goto out; | ||
338 | break; | ||
339 | } | ||
340 | if (is_ext_ctrl) { | ||
341 | struct v4l2_ext_controls *p = parg; | ||
342 | |||
343 | /* In case of an error, tell the caller that it wasn't | ||
344 | a specific control that caused it. */ | ||
345 | p->error_idx = p->count; | ||
346 | user_ptr = (void __user *)p->controls; | ||
347 | if (p->count) { | ||
348 | ctrls_size = sizeof(struct v4l2_ext_control) * p->count; | ||
349 | /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */ | ||
350 | mbuf = kmalloc(ctrls_size, GFP_KERNEL); | ||
351 | err = -ENOMEM; | ||
352 | if (NULL == mbuf) | ||
353 | goto out_ext_ctrl; | ||
354 | err = -EFAULT; | ||
355 | if (copy_from_user(mbuf, user_ptr, ctrls_size)) | ||
356 | goto out_ext_ctrl; | ||
357 | p->controls = mbuf; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | /* call driver */ | ||
362 | err = func(file, cmd, parg); | ||
363 | if (err == -ENOIOCTLCMD) | ||
364 | err = -EINVAL; | ||
365 | if (is_ext_ctrl) { | ||
366 | struct v4l2_ext_controls *p = parg; | ||
367 | |||
368 | p->controls = (void *)user_ptr; | ||
369 | if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size)) | ||
370 | err = -EFAULT; | ||
371 | goto out_ext_ctrl; | ||
372 | } | ||
373 | if (err < 0) | ||
374 | goto out; | ||
375 | |||
376 | out_ext_ctrl: | ||
377 | /* Copy results into user buffer */ | ||
378 | switch (_IOC_DIR(cmd)) { | ||
379 | case _IOC_READ: | ||
380 | case (_IOC_WRITE | _IOC_READ): | ||
381 | if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) | ||
382 | err = -EFAULT; | ||
383 | break; | ||
384 | } | ||
385 | |||
386 | out: | ||
387 | kfree(mbuf); | ||
388 | return err; | ||
389 | } | ||
390 | EXPORT_SYMBOL(video_usercopy); | ||
391 | |||
392 | static void dbgbuf(unsigned int cmd, struct video_device *vfd, | 297 | static void dbgbuf(unsigned int cmd, struct video_device *vfd, |
393 | struct v4l2_buffer *p) | 298 | struct v4l2_buffer *p) |
394 | { | 299 | { |
@@ -2332,8 +2237,9 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, | |||
2332 | return ret; | 2237 | return ret; |
2333 | } | 2238 | } |
2334 | 2239 | ||
2335 | long video_ioctl2(struct file *file, | 2240 | long |
2336 | unsigned int cmd, unsigned long arg) | 2241 | video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, |
2242 | v4l2_kioctl func) | ||
2337 | { | 2243 | { |
2338 | char sbuf[128]; | 2244 | char sbuf[128]; |
2339 | void *mbuf = NULL; | 2245 | void *mbuf = NULL; |
@@ -2395,7 +2301,7 @@ long video_ioctl2(struct file *file, | |||
2395 | } | 2301 | } |
2396 | 2302 | ||
2397 | /* Handles IOCTL */ | 2303 | /* Handles IOCTL */ |
2398 | err = __video_do_ioctl(file, cmd, parg); | 2304 | err = func(file, cmd, parg); |
2399 | if (err == -ENOIOCTLCMD) | 2305 | if (err == -ENOIOCTLCMD) |
2400 | err = -EINVAL; | 2306 | err = -EINVAL; |
2401 | 2307 | ||
@@ -2422,4 +2328,11 @@ out: | |||
2422 | kfree(mbuf); | 2328 | kfree(mbuf); |
2423 | return err; | 2329 | return err; |
2424 | } | 2330 | } |
2331 | EXPORT_SYMBOL(video_usercopy); | ||
2332 | |||
2333 | long video_ioctl2(struct file *file, | ||
2334 | unsigned int cmd, unsigned long arg) | ||
2335 | { | ||
2336 | return video_usercopy(file, cmd, arg, __video_do_ioctl); | ||
2337 | } | ||
2425 | EXPORT_SYMBOL(video_ioctl2); | 2338 | EXPORT_SYMBOL(video_ioctl2); |