aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/videodev.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-06-04 09:06:18 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-06-25 01:05:04 -0400
commit401998fa96fe18b057af3f906527196522dd2d9d (patch)
tree32d656e18410ab05204c83b57969db23665e4fe9 /drivers/media/video/videodev.c
parent7565ab082de88ec274283d6b83980144e520a2fc (diff)
V4L/DVB (4065): Several improvements at videodev.c
Videodev now is capable of better handling V4L2 api, by processing V4L2 ioctls and using callbacks to the driver. The drivers should be migrated to the newer way and the older one will be obsoleted soon. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/videodev.c')
-rw-r--r--drivers/media/video/videodev.c1172
1 files changed, 1156 insertions, 16 deletions
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 5f87dd5f1d0b..3f7a94b80c63 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -1,20 +1,31 @@
1/* 1/*
2 * Video capture interface for Linux 2 * Video capture interface for Linux version 2
3 * 3 *
4 * A generic video device interface for the LINUX operating system 4 * A generic video device interface for the LINUX operating system
5 * using a set of device structures/vectors for low level operations. 5 * using a set of device structures/vectors for low level operations.
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 * 11 *
12 * Author: Alan Cox, <alan@redhat.com> 12 * Authors: Alan Cox, <alan@redhat.com> (version 1)
13 * Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
13 * 14 *
14 * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com> 15 * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com>
15 * - Added procfs support 16 * - Added procfs support
16 */ 17 */
17 18
19#define dbgarg(cmd, fmt, arg...) \
20 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
21 printk (KERN_DEBUG "%s: ", vfd->name); \
22 v4l_printk_ioctl(cmd); \
23 printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
24
25#define dbgarg2(fmt, arg...) \
26 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
27 printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
28
18#include <linux/module.h> 29#include <linux/module.h>
19#include <linux/types.h> 30#include <linux/types.h>
20#include <linux/kernel.h> 31#include <linux/kernel.h>
@@ -30,7 +41,13 @@
30#include <asm/uaccess.h> 41#include <asm/uaccess.h>
31#include <asm/system.h> 42#include <asm/system.h>
32 43
44#define __OLD_VIDIOC_ /* To allow fixing old calls*/
45#include <linux/videodev2.h>
46
47#ifdef CONFIG_VIDEO_V4L1
33#include <linux/videodev.h> 48#include <linux/videodev.h>
49#endif
50#include <media/v4l2-common.h>
34 51
35#define VIDEO_NUM_DEVICES 256 52#define VIDEO_NUM_DEVICES 256
36#define VIDEO_NAME "video4linux" 53#define VIDEO_NAME "video4linux"
@@ -41,7 +58,8 @@
41 58
42static ssize_t show_name(struct class_device *cd, char *buf) 59static ssize_t show_name(struct class_device *cd, char *buf)
43{ 60{
44 struct video_device *vfd = container_of(cd, struct video_device, class_dev); 61 struct video_device *vfd = container_of(cd, struct video_device,
62 class_dev);
45 return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name); 63 return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name);
46} 64}
47 65
@@ -62,7 +80,8 @@ void video_device_release(struct video_device *vfd)
62 80
63static void video_release(struct class_device *cd) 81static void video_release(struct class_device *cd)
64{ 82{
65 struct video_device *vfd = container_of(cd, struct video_device, class_dev); 83 struct video_device *vfd = container_of(cd, struct video_device,
84 class_dev);
66 85
67#if 1 86#if 1
68 /* needed until all drivers are fixed */ 87 /* needed until all drivers are fixed */
@@ -90,7 +109,7 @@ struct video_device* video_devdata(struct file *file)
90} 109}
91 110
92/* 111/*
93 * Open a video device. 112 * Open a video device - FIXME: Obsoleted
94 */ 113 */
95static int video_open(struct inode *inode, struct file *file) 114static int video_open(struct inode *inode, struct file *file)
96{ 115{
@@ -130,6 +149,7 @@ static int video_open(struct inode *inode, struct file *file)
130 * helper function -- handles userspace copying for ioctl arguments 149 * helper function -- handles userspace copying for ioctl arguments
131 */ 150 */
132 151
152#ifdef __OLD_VIDIOC_
133static unsigned int 153static unsigned int
134video_fix_command(unsigned int cmd) 154video_fix_command(unsigned int cmd)
135{ 155{
@@ -155,7 +175,11 @@ video_fix_command(unsigned int cmd)
155 } 175 }
156 return cmd; 176 return cmd;
157} 177}
178#endif
158 179
180/*
181 * Obsolete usercopy function - Should be removed soon
182 */
159int 183int
160video_usercopy(struct inode *inode, struct file *file, 184video_usercopy(struct inode *inode, struct file *file,
161 unsigned int cmd, unsigned long arg, 185 unsigned int cmd, unsigned long arg,
@@ -167,7 +191,9 @@ video_usercopy(struct inode *inode, struct file *file,
167 void *parg = NULL; 191 void *parg = NULL;
168 int err = -EINVAL; 192 int err = -EINVAL;
169 193
194#ifdef __OLD_VIDIOC_
170 cmd = video_fix_command(cmd); 195 cmd = video_fix_command(cmd);
196#endif
171 197
172 /* Copy arguments into temp kernel buffer */ 198 /* Copy arguments into temp kernel buffer */
173 switch (_IOC_DIR(cmd)) { 199 switch (_IOC_DIR(cmd)) {
@@ -189,7 +215,8 @@ video_usercopy(struct inode *inode, struct file *file,
189 215
190 err = -EFAULT; 216 err = -EFAULT;
191 if (_IOC_DIR(cmd) & _IOC_WRITE) 217 if (_IOC_DIR(cmd) & _IOC_WRITE)
192 if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) 218 if (copy_from_user(parg, (void __user *)arg,
219 _IOC_SIZE(cmd)))
193 goto out; 220 goto out;
194 break; 221 break;
195 } 222 }
@@ -218,6 +245,7 @@ out:
218 245
219/* 246/*
220 * open/release helper functions -- handle exclusive opens 247 * open/release helper functions -- handle exclusive opens
248 * Should be removed soon
221 */ 249 */
222int video_exclusive_open(struct inode *inode, struct file *file) 250int video_exclusive_open(struct inode *inode, struct file *file)
223{ 251{
@@ -242,6 +270,1115 @@ int video_exclusive_release(struct inode *inode, struct file *file)
242 return 0; 270 return 0;
243} 271}
244 272
273static char *v4l2_memory_names[] = {
274 [V4L2_MEMORY_MMAP] = "mmap",
275 [V4L2_MEMORY_USERPTR] = "userptr",
276 [V4L2_MEMORY_OVERLAY] = "overlay",
277};
278
279
280/* FIXME: Those stuff are replicated also on v4l2-common.c */
281static char *v4l2_type_names_FIXME[] = {
282 [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
283 [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
284 [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
285 [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
286 [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
287 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
288 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture",
289 [V4L2_BUF_TYPE_PRIVATE] = "private",
290};
291
292static char *v4l2_field_names_FIXME[] = {
293 [V4L2_FIELD_ANY] = "any",
294 [V4L2_FIELD_NONE] = "none",
295 [V4L2_FIELD_TOP] = "top",
296 [V4L2_FIELD_BOTTOM] = "bottom",
297 [V4L2_FIELD_INTERLACED] = "interlaced",
298 [V4L2_FIELD_SEQ_TB] = "seq-tb",
299 [V4L2_FIELD_SEQ_BT] = "seq-bt",
300 [V4L2_FIELD_ALTERNATE] = "alternate",
301};
302
303#define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
304
305static void dbgbuf(unsigned int cmd, struct video_device *vfd,
306 struct v4l2_buffer *p)
307{
308 struct v4l2_timecode *tc=&p->timecode;
309
310 dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
311 "bytesused=%d, flags=0x%08d, "
312 "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
313 (p->timestamp.tv_sec/3600),
314 (int)(p->timestamp.tv_sec/60)%60,
315 (int)(p->timestamp.tv_sec%60),
316 p->timestamp.tv_usec,
317 p->index,
318 prt_names(p->type,v4l2_type_names_FIXME),
319 p->bytesused,p->flags,
320 p->field,p->sequence,
321 prt_names(p->memory,v4l2_memory_names),
322 p->m.userptr);
323 dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
324 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
325 tc->hours,tc->minutes,tc->seconds,
326 tc->type, tc->flags, tc->frames, (__u32) tc->userbits);
327}
328
329static inline void dbgrect(struct video_device *vfd, char *s,
330 struct v4l2_rect *r)
331{
332 dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top,
333 r->width, r->height);
334};
335
336static inline void v4l_print_pix_fmt (struct video_device *vfd,
337 struct v4l2_pix_format *fmt)
338{
339 dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, "
340 "bytesperline=%d sizeimage=%d, colorspace=%d\n",
341 fmt->width,fmt->height,fmt->pixelformat,
342 prt_names(fmt->field,v4l2_field_names_FIXME),
343 fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
344};
345
346
347static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
348{
349 switch (type) {
350 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
351 if (vfd->vidioc_try_fmt_cap)
352 return (0);
353 break;
354 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
355 if (vfd->vidioc_try_fmt_overlay)
356 return (0);
357 break;
358 case V4L2_BUF_TYPE_VBI_CAPTURE:
359 if (vfd->vidioc_try_fmt_vbi)
360 return (0);
361 break;
362 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
363 if (vfd->vidioc_try_fmt_vbi_output)
364 return (0);
365 break;
366 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
367 if (vfd->vidioc_try_fmt_vbi_capture)
368 return (0);
369 break;
370 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
371 if (vfd->vidioc_try_fmt_video_output)
372 return (0);
373 break;
374 case V4L2_BUF_TYPE_VBI_OUTPUT:
375 if (vfd->vidioc_try_fmt_vbi_output)
376 return (0);
377 break;
378 case V4L2_BUF_TYPE_PRIVATE:
379 if (vfd->vidioc_try_fmt_type_private)
380 return (0);
381 break;
382 }
383 return (-EINVAL);
384}
385
386static int __video_do_ioctl(struct inode *inode, struct file *file,
387 unsigned int cmd, void *arg)
388{
389 struct video_device *vfd = video_devdata(file);
390 void *fh = file->private_data;
391 int ret = -EINVAL;
392
393 if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
394 !(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) {
395 v4l_print_ioctl(vfd->name, cmd);
396 }
397
398 switch(cmd) {
399 /* --- capabilities ------------------------------------------ */
400 case VIDIOC_QUERYCAP:
401 {
402 struct v4l2_capability *cap = (struct v4l2_capability*)arg;
403 memset(cap, 0, sizeof(*cap));
404
405 if (!vfd->vidioc_querycap)
406 break;
407
408 ret=vfd->vidioc_querycap(file, fh, cap);
409 if (!ret)
410 dbgarg (cmd, "driver=%s, card=%s, bus=%s, "
411 "version=0x%08x, "
412 "capabilities=0x%08x\n",
413 cap->driver,cap->card,cap->bus_info,
414 cap->version,
415 cap->capabilities);
416 break;
417 }
418
419 /* --- priority ------------------------------------------ */
420 case VIDIOC_G_PRIORITY:
421 {
422 enum v4l2_priority *p=arg;
423
424 if (!vfd->vidioc_g_priority)
425 break;
426 ret=vfd->vidioc_g_priority(file, fh, p);
427 if (!ret)
428 dbgarg(cmd, "priority is %d\n", *p);
429 break;
430 }
431 case VIDIOC_S_PRIORITY:
432 {
433 enum v4l2_priority *p=arg;
434
435 if (!vfd->vidioc_s_priority)
436 break;
437 dbgarg(cmd, "setting priority to %d\n", *p);
438 ret=vfd->vidioc_s_priority(file, fh, *p);
439 break;
440 }
441
442 /* --- capture ioctls ---------------------------------------- */
443 case VIDIOC_ENUM_FMT:
444 {
445 struct v4l2_fmtdesc *f = arg;
446 enum v4l2_buf_type type;
447 unsigned int index;
448
449 index = f->index;
450 type = f->type;
451 memset(f,0,sizeof(*f));
452 f->index = index;
453 f->type = type;
454
455 switch (type) {
456 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
457 if (vfd->vidioc_enum_fmt_cap)
458 ret=vfd->vidioc_enum_fmt_cap(file, fh, f);
459 break;
460 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
461 if (vfd->vidioc_enum_fmt_overlay)
462 ret=vfd->vidioc_enum_fmt_overlay(file, fh, f);
463 break;
464 case V4L2_BUF_TYPE_VBI_CAPTURE:
465 if (vfd->vidioc_enum_fmt_vbi)
466 ret=vfd->vidioc_enum_fmt_vbi(file, fh, f);
467 break;
468 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
469 if (vfd->vidioc_enum_fmt_vbi_output)
470 ret=vfd->vidioc_enum_fmt_vbi_output(file,
471 fh, f);
472 break;
473 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
474 if (vfd->vidioc_enum_fmt_vbi_capture)
475 ret=vfd->vidioc_enum_fmt_vbi_capture(file,
476 fh, f);
477 break;
478 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
479 if (vfd->vidioc_enum_fmt_video_output)
480 ret=vfd->vidioc_enum_fmt_video_output(file,
481 fh, f);
482 break;
483 case V4L2_BUF_TYPE_VBI_OUTPUT:
484 if (vfd->vidioc_enum_fmt_vbi_output)
485 ret=vfd->vidioc_enum_fmt_vbi_output(file,
486 fh, f);
487 break;
488 case V4L2_BUF_TYPE_PRIVATE:
489 if (vfd->vidioc_enum_fmt_type_private)
490 ret=vfd->vidioc_enum_fmt_type_private(file,
491 fh, f);
492 break;
493 }
494 if (!ret)
495 dbgarg (cmd, "index=%d, type=%d, flags=%d, "
496 "description=%s,"
497 " pixelformat=0x%8x\n",
498 f->index, f->type, f->flags,
499 f->description,
500 f->pixelformat);
501
502 break;
503 }
504 case VIDIOC_G_FMT:
505 {
506 struct v4l2_format *f = (struct v4l2_format *)arg;
507 enum v4l2_buf_type type=f->type;
508
509 memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
510 f->type=type;
511
512 /* FIXME: Should be one dump per type */
513 dbgarg (cmd, "type=%s\n", prt_names(type,
514 v4l2_type_names_FIXME));
515
516 switch (type) {
517 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
518 if (vfd->vidioc_g_fmt_cap)
519 ret=vfd->vidioc_g_fmt_cap(file, fh, f);
520 if (!ret)
521 v4l_print_pix_fmt(vfd,&f->fmt.pix);
522 break;
523 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
524 if (vfd->vidioc_g_fmt_overlay)
525 ret=vfd->vidioc_g_fmt_overlay(file, fh, f);
526 break;
527 case V4L2_BUF_TYPE_VBI_CAPTURE:
528 if (vfd->vidioc_g_fmt_vbi)
529 ret=vfd->vidioc_g_fmt_vbi(file, fh, f);
530 break;
531 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
532 if (vfd->vidioc_g_fmt_vbi_output)
533 ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
534 break;
535 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
536 if (vfd->vidioc_g_fmt_vbi_capture)
537 ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f);
538 break;
539 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
540 if (vfd->vidioc_g_fmt_video_output)
541 ret=vfd->vidioc_g_fmt_video_output(file,
542 fh, f);
543 break;
544 case V4L2_BUF_TYPE_VBI_OUTPUT:
545 if (vfd->vidioc_g_fmt_vbi_output)
546 ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
547 break;
548 case V4L2_BUF_TYPE_PRIVATE:
549 if (vfd->vidioc_g_fmt_type_private)
550 ret=vfd->vidioc_g_fmt_type_private(file,
551 fh, f);
552 break;
553 }
554
555 break;
556 }
557 case VIDIOC_S_FMT:
558 {
559 struct v4l2_format *f = (struct v4l2_format *)arg;
560
561 /* FIXME: Should be one dump per type */
562 dbgarg (cmd, "type=%s\n", prt_names(f->type,
563 v4l2_type_names_FIXME));
564
565 switch (f->type) {
566 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
567 v4l_print_pix_fmt(vfd,&f->fmt.pix);
568 if (vfd->vidioc_s_fmt_cap)
569 ret=vfd->vidioc_s_fmt_cap(file, fh, f);
570 break;
571 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
572 if (vfd->vidioc_s_fmt_overlay)
573 ret=vfd->vidioc_s_fmt_overlay(file, fh, f);
574 break;
575 case V4L2_BUF_TYPE_VBI_CAPTURE:
576 if (vfd->vidioc_s_fmt_vbi)
577 ret=vfd->vidioc_s_fmt_vbi(file, fh, f);
578 break;
579 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
580 if (vfd->vidioc_s_fmt_vbi_output)
581 ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f);
582 break;
583 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
584 if (vfd->vidioc_s_fmt_vbi_capture)
585 ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f);
586 break;
587 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
588 if (vfd->vidioc_s_fmt_video_output)
589 ret=vfd->vidioc_s_fmt_video_output(file,
590 fh, f);
591 break;
592 case V4L2_BUF_TYPE_VBI_OUTPUT:
593 if (vfd->vidioc_s_fmt_vbi_output)
594 ret=vfd->vidioc_s_fmt_vbi_output(file,
595 fh, f);
596 break;
597 case V4L2_BUF_TYPE_PRIVATE:
598 if (vfd->vidioc_s_fmt_type_private)
599 ret=vfd->vidioc_s_fmt_type_private(file,
600 fh, f);
601 break;
602 }
603 break;
604 }
605 case VIDIOC_TRY_FMT:
606 {
607 struct v4l2_format *f = (struct v4l2_format *)arg;
608
609 /* FIXME: Should be one dump per type */
610 dbgarg (cmd, "type=%s\n", prt_names(f->type,
611 v4l2_type_names_FIXME));
612 switch (f->type) {
613 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
614 if (vfd->vidioc_try_fmt_cap)
615 ret=vfd->vidioc_try_fmt_cap(file, fh, f);
616 if (!ret)
617 v4l_print_pix_fmt(vfd,&f->fmt.pix);
618 break;
619 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
620 if (vfd->vidioc_try_fmt_overlay)
621 ret=vfd->vidioc_try_fmt_overlay(file, fh, f);
622 break;
623 case V4L2_BUF_TYPE_VBI_CAPTURE:
624 if (vfd->vidioc_try_fmt_vbi)
625 ret=vfd->vidioc_try_fmt_vbi(file, fh, f);
626 break;
627 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
628 if (vfd->vidioc_try_fmt_vbi_output)
629 ret=vfd->vidioc_try_fmt_vbi_output(file,
630 fh, f);
631 break;
632 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
633 if (vfd->vidioc_try_fmt_vbi_capture)
634 ret=vfd->vidioc_try_fmt_vbi_capture(file,
635 fh, f);
636 break;
637 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
638 if (vfd->vidioc_try_fmt_video_output)
639 ret=vfd->vidioc_try_fmt_video_output(file,
640 fh, f);
641 break;
642 case V4L2_BUF_TYPE_VBI_OUTPUT:
643 if (vfd->vidioc_try_fmt_vbi_output)
644 ret=vfd->vidioc_try_fmt_vbi_output(file,
645 fh, f);
646 break;
647 case V4L2_BUF_TYPE_PRIVATE:
648 if (vfd->vidioc_try_fmt_type_private)
649 ret=vfd->vidioc_try_fmt_type_private(file,
650 fh, f);
651 break;
652 }
653
654 break;
655 }
656 /* FIXME: Those buf reqs could be handled here,
657 with some changes on videobuf to allow its header to be included at
658 videodev2.h or being merged at videodev2.
659 */
660 case VIDIOC_REQBUFS:
661 {
662 struct v4l2_requestbuffers *p=arg;
663
664 if (!vfd->vidioc_reqbufs)
665 break;
666 ret = check_fmt (vfd, p->type);
667 if (ret)
668 break;
669
670 ret=vfd->vidioc_reqbufs(file, fh, p);
671 dbgarg (cmd, "count=%d, type=%s, memory=%s\n",
672 p->count,
673 prt_names(p->type,v4l2_type_names_FIXME),
674 prt_names(p->memory,v4l2_memory_names));
675 break;
676 }
677 case VIDIOC_QUERYBUF:
678 {
679 struct v4l2_buffer *p=arg;
680
681 if (!vfd->vidioc_querybuf)
682 break;
683 ret = check_fmt (vfd, p->type);
684 if (ret)
685 break;
686
687 ret=vfd->vidioc_querybuf(file, fh, p);
688 if (!ret)
689 dbgbuf(cmd,vfd,p);
690 break;
691 }
692 case VIDIOC_QBUF:
693 {
694 struct v4l2_buffer *p=arg;
695
696 if (!vfd->vidioc_qbuf)
697 break;
698 ret = check_fmt (vfd, p->type);
699 if (ret)
700 break;
701
702 ret=vfd->vidioc_qbuf(file, fh, p);
703 if (!ret)
704 dbgbuf(cmd,vfd,p);
705 break;
706 }
707 case VIDIOC_DQBUF:
708 {
709 struct v4l2_buffer *p=arg;
710 if (!vfd->vidioc_qbuf)
711 break;
712 ret = check_fmt (vfd, p->type);
713 if (ret)
714 break;
715
716 ret=vfd->vidioc_qbuf(file, fh, p);
717 if (!ret)
718 dbgbuf(cmd,vfd,p);
719 break;
720 }
721 case VIDIOC_OVERLAY:
722 {
723 int *i = arg;
724
725 if (!vfd->vidioc_overlay)
726 break;
727 dbgarg (cmd, "value=%d\n",*i);
728 ret=vfd->vidioc_overlay(file, fh, *i);
729 break;
730 }
731#ifdef HAVE_V4L1
732 /* --- streaming capture ------------------------------------- */
733 case VIDIOCGMBUF:
734 {
735 struct video_mbuf *p=arg;
736
737 memset(&p,0,sizeof(p));
738
739 if (!vfd->vidiocgmbuf)
740 break;
741 ret=vfd->vidiocgmbuf(file, fh, p);
742 if (!ret)
743 dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
744 p->size, p->frames,
745 (unsigned long)p->offsets);
746 break;
747 }
748#endif
749 case VIDIOC_G_FBUF:
750 {
751 struct v4l2_framebuffer *p=arg;
752 if (!vfd->vidioc_g_fbuf)
753 break;
754 ret=vfd->vidioc_g_fbuf(file, fh, arg);
755 if (!ret) {
756 dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
757 p->capability,p->flags,
758 (unsigned long)p->base);
759 v4l_print_pix_fmt (vfd, &p->fmt);
760 }
761 break;
762 }
763 case VIDIOC_S_FBUF:
764 {
765 struct v4l2_framebuffer *p=arg;
766 if (!vfd->vidioc_s_fbuf)
767 break;
768
769 dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
770 p->capability,p->flags,(unsigned long)p->base);
771 v4l_print_pix_fmt (vfd, &p->fmt);
772 ret=vfd->vidioc_s_fbuf(file, fh, arg);
773
774 break;
775 }
776 case VIDIOC_STREAMON:
777 {
778 enum v4l2_buf_type i = *(int *)arg;
779 if (!vfd->vidioc_streamon)
780 break;
781 dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
782 ret=vfd->vidioc_streamon(file, fh,i);
783 break;
784 }
785 case VIDIOC_STREAMOFF:
786 {
787 enum v4l2_buf_type i = *(int *)arg;
788
789 if (!vfd->vidioc_streamoff)
790 break;
791 dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
792 ret=vfd->vidioc_streamoff(file, fh, i);
793 break;
794 }
795 /* ---------- tv norms ---------- */
796 case VIDIOC_ENUMSTD:
797 {
798 struct v4l2_standard *p = arg;
799 unsigned int index = p->index;
800
801 if (!vfd->tvnormsize) {
802 printk (KERN_WARNING "%s: no TV norms defined!\n",
803 vfd->name);
804 break;
805 }
806
807 if (index<=0 || index >= vfd->tvnormsize) {
808 ret=-EINVAL;
809 break;
810 }
811 v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
812 vfd->tvnorms[p->index].name);
813 p->index = index;
814
815 dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
816 "framelines=%d\n", p->index,
817 (unsigned long long)p->id, p->name,
818 p->frameperiod.numerator,
819 p->frameperiod.denominator,
820 p->framelines);
821
822 ret=0;
823 break;
824 }
825 case VIDIOC_G_STD:
826 {
827 v4l2_std_id *id = arg;
828
829 *id = vfd->current_norm;
830
831 dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
832
833 ret=0;
834 break;
835 }
836 case VIDIOC_S_STD:
837 {
838 v4l2_std_id *id = arg;
839 unsigned int i;
840
841 if (!vfd->tvnormsize) {
842 printk (KERN_WARNING "%s: no TV norms defined!\n",
843 vfd->name);
844 break;
845 }
846
847 dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
848
849 /* First search for exact match */
850 for (i = 0; i < vfd->tvnormsize; i++)
851 if (*id == vfd->tvnorms[i].id)
852 break;
853 /* Then for a generic video std that contains desired std */
854 if (i == vfd->tvnormsize)
855 for (i = 0; i < vfd->tvnormsize; i++)
856 if (*id & vfd->tvnorms[i].id)
857 break;
858 if (i == vfd->tvnormsize) {
859 break;
860 }
861
862 /* Calls the specific handler */
863 if (vfd->vidioc_s_std)
864 ret=vfd->vidioc_s_std(file, fh, i);
865 else
866 ret=-EINVAL;
867
868 /* Updates standard information */
869 if (!ret)
870 vfd->current_norm=*id;
871
872 break;
873 }
874 case VIDIOC_QUERYSTD:
875 {
876 v4l2_std_id *p=arg;
877
878 if (!vfd->vidioc_querystd)
879 break;
880 ret=vfd->vidioc_querystd(file, fh, arg);
881 if (!ret)
882 dbgarg (cmd, "detected std=%Lu\n",
883 (unsigned long long)*p);
884 break;
885 }
886 /* ------ input switching ---------- */
887 /* FIXME: Inputs can be handled inside videodev2 */
888 case VIDIOC_ENUMINPUT:
889 {
890 struct v4l2_input *p=arg;
891 int i=p->index;
892
893 if (!vfd->vidioc_enum_input)
894 break;
895 memset(p, 0, sizeof(*p));
896 p->index=i;
897
898 ret=vfd->vidioc_enum_input(file, fh, p);
899 if (!ret)
900 dbgarg (cmd, "index=%d, name=%s, type=%d, "
901 "audioset=%d, "
902 "tuner=%d, std=%Ld, status=%d\n",
903 p->index,p->name,p->type,p->audioset,
904 p->tuner,
905 (unsigned long long)p->std,
906 p->status);
907 break;
908 }
909 case VIDIOC_G_INPUT:
910 {
911 unsigned int *i = arg;
912
913 if (!vfd->vidioc_g_input)
914 break;
915 ret=vfd->vidioc_g_input(file, fh, i);
916 if (!ret)
917 dbgarg (cmd, "value=%d\n",*i);
918 break;
919 }
920 case VIDIOC_S_INPUT:
921 {
922 unsigned int *i = arg;
923
924 if (!vfd->vidioc_s_input)
925 break;
926 dbgarg (cmd, "value=%d\n",*i);
927 ret=vfd->vidioc_s_input(file, fh, *i);
928 break;
929 }
930
931 /* ------ output switching ---------- */
932 case VIDIOC_G_OUTPUT:
933 {
934 unsigned int *i = arg;
935
936 if (!vfd->vidioc_g_output)
937 break;
938 ret=vfd->vidioc_g_output(file, fh, i);
939 if (!ret)
940 dbgarg (cmd, "value=%d\n",*i);
941 break;
942 }
943 case VIDIOC_S_OUTPUT:
944 {
945 unsigned int *i = arg;
946
947 if (!vfd->vidioc_s_output)
948 break;
949 dbgarg (cmd, "value=%d\n",*i);
950 ret=vfd->vidioc_s_output(file, fh, *i);
951 break;
952 }
953
954 /* --- controls ---------------------------------------------- */
955 case VIDIOC_QUERYCTRL:
956 {
957 struct v4l2_queryctrl *p=arg;
958
959 if (!vfd->vidioc_queryctrl)
960 break;
961 ret=vfd->vidioc_queryctrl(file, fh, p);
962
963 if (!ret)
964 dbgarg (cmd, "id=%d, type=%d, name=%s, "
965 "min/max=%d/%d,"
966 " step=%d, default=%d, flags=0x%08x\n",
967 p->id,p->type,p->name,p->minimum,
968 p->maximum,p->step,p->default_value,
969 p->flags);
970 break;
971 }
972 case VIDIOC_G_CTRL:
973 {
974 struct v4l2_control *p = arg;
975
976 if (!vfd->vidioc_g_ctrl)
977 break;
978 dbgarg(cmd, "Enum for index=%d\n", p->id);
979
980 ret=vfd->vidioc_g_ctrl(file, fh, p);
981 if (!ret)
982 dbgarg2 ( "id=%d, value=%d\n", p->id, p->value);
983 break;
984 }
985 case VIDIOC_S_CTRL:
986 {
987 struct v4l2_control *p = arg;
988
989 if (!vfd->vidioc_s_ctrl)
990 break;
991 dbgarg (cmd, "id=%d, value=%d\n", p->id, p->value);
992
993 ret=vfd->vidioc_s_ctrl(file, fh, p);
994 break;
995 }
996 case VIDIOC_QUERYMENU:
997 {
998 struct v4l2_querymenu *p=arg;
999 if (!vfd->vidioc_querymenu)
1000 break;
1001 ret=vfd->vidioc_querymenu(file, fh, p);
1002 if (!ret)
1003 dbgarg (cmd, "id=%d, index=%d, name=%s\n",
1004 p->id,p->index,p->name);
1005 break;
1006 }
1007 /* --- audio ---------------------------------------------- */
1008 case VIDIOC_ENUMAUDIO:
1009 {
1010 struct v4l2_audio *p=arg;
1011
1012 if (!vfd->vidioc_enumaudio)
1013 break;
1014 dbgarg(cmd, "Enum for index=%d\n", p->index);
1015 ret=vfd->vidioc_enumaudio(file, fh, p);
1016 if (!ret)
1017 dbgarg2("index=%d, name=%s, capability=%d, "
1018 "mode=%d\n",p->index,p->name,
1019 p->capability, p->mode);
1020 break;
1021 }
1022 case VIDIOC_G_AUDIO:
1023 {
1024 struct v4l2_audio *p=arg;
1025
1026 if (!vfd->vidioc_g_audio)
1027 break;
1028 dbgarg(cmd, "Get for index=%d\n", p->index);
1029 ret=vfd->vidioc_g_audio(file, fh, p);
1030 if (!ret)
1031 dbgarg2("index=%d, name=%s, capability=%d, "
1032 "mode=%d\n",p->index,
1033 p->name,p->capability, p->mode);
1034 break;
1035 }
1036 case VIDIOC_S_AUDIO:
1037 {
1038 struct v4l2_audio *p=arg;
1039
1040 if (!vfd->vidioc_s_audio)
1041 break;
1042 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1043 "mode=%d\n", p->index, p->name,
1044 p->capability, p->mode);
1045 ret=vfd->vidioc_s_audio(file, fh, p);
1046 break;
1047 }
1048 case VIDIOC_ENUMAUDOUT:
1049 {
1050 struct v4l2_audioout *p=arg;
1051
1052 if (!vfd->vidioc_enumaudout)
1053 break;
1054 dbgarg(cmd, "Enum for index=%d\n", p->index);
1055 ret=vfd->vidioc_enumaudout(file, fh, p);
1056 if (!ret)
1057 dbgarg2("index=%d, name=%s, capability=%d, "
1058 "mode=%d\n", p->index, p->name,
1059 p->capability,p->mode);
1060 break;
1061 }
1062 case VIDIOC_G_AUDOUT:
1063 {
1064 struct v4l2_audioout *p=arg;
1065
1066 if (!vfd->vidioc_g_audout)
1067 break;
1068 dbgarg(cmd, "Enum for index=%d\n", p->index);
1069 ret=vfd->vidioc_g_audout(file, fh, p);
1070 if (!ret)
1071 dbgarg2("index=%d, name=%s, capability=%d, "
1072 "mode=%d\n", p->index, p->name,
1073 p->capability,p->mode);
1074 break;
1075 }
1076 case VIDIOC_S_AUDOUT:
1077 {
1078 struct v4l2_audioout *p=arg;
1079
1080 if (!vfd->vidioc_s_audout)
1081 break;
1082 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1083 "mode=%d\n", p->index, p->name,
1084 p->capability,p->mode);
1085
1086 ret=vfd->vidioc_s_audout(file, fh, p);
1087 break;
1088 }
1089 case VIDIOC_G_MODULATOR:
1090 {
1091 struct v4l2_modulator *p=arg;
1092 if (!vfd->vidioc_g_modulator)
1093 break;
1094 ret=vfd->vidioc_g_modulator(file, fh, p);
1095 if (!ret)
1096 dbgarg(cmd, "index=%d, name=%s, "
1097 "capability=%d, rangelow=%d,"
1098 " rangehigh=%d, txsubchans=%d\n",
1099 p->index, p->name,p->capability,
1100 p->rangelow, p->rangehigh,
1101 p->txsubchans);
1102 break;
1103 }
1104 case VIDIOC_S_MODULATOR:
1105 {
1106 struct v4l2_modulator *p=arg;
1107 if (!vfd->vidioc_s_modulator)
1108 break;
1109 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1110 "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
1111 p->index, p->name,p->capability,p->rangelow,
1112 p->rangehigh,p->txsubchans);
1113 ret=vfd->vidioc_s_modulator(file, fh, p);
1114 break;
1115 }
1116 case VIDIOC_G_CROP:
1117 {
1118 struct v4l2_crop *p=arg;
1119 if (!vfd->vidioc_g_crop)
1120 break;
1121 ret=vfd->vidioc_g_crop(file, fh, p);
1122 if (!ret) {
1123 dbgarg(cmd, "type=%d\n", p->type);
1124 dbgrect(vfd, "", &p->c);
1125 }
1126 break;
1127 }
1128 case VIDIOC_S_CROP:
1129 {
1130 struct v4l2_crop *p=arg;
1131 if (!vfd->vidioc_s_crop)
1132 break;
1133 dbgarg(cmd, "type=%d\n", p->type);
1134 dbgrect(vfd, "", &p->c);
1135 ret=vfd->vidioc_s_crop(file, fh, p);
1136 break;
1137 }
1138 case VIDIOC_CROPCAP:
1139 {
1140 struct v4l2_cropcap *p=arg;
1141 /*FIXME: Should also show v4l2_fract pixelaspect */
1142 if (!vfd->vidioc_cropcap)
1143 break;
1144 dbgarg(cmd, "type=%d\n", p->type);
1145 dbgrect(vfd, "bounds ", &p->bounds);
1146 dbgrect(vfd, "defrect ", &p->defrect);
1147 ret=vfd->vidioc_cropcap(file, fh, p);
1148 break;
1149 }
1150 case VIDIOC_G_MPEGCOMP:
1151 {
1152 struct v4l2_mpeg_compression *p=arg;
1153 /*FIXME: Several fields not shown */
1154 if (!vfd->vidioc_g_mpegcomp)
1155 break;
1156 ret=vfd->vidioc_g_mpegcomp(file, fh, p);
1157 if (!ret)
1158 dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d,"
1159 " ts_pid_video=%d, ts_pid_pcr=%d, "
1160 "ps_size=%d, au_sample_rate=%d, "
1161 "au_pesid=%c, vi_frame_rate=%d, "
1162 "vi_frames_per_gop=%d, "
1163 "vi_bframes_count=%d, vi_pesid=%c\n",
1164 p->ts_pid_pmt,p->ts_pid_audio,
1165 p->ts_pid_video,p->ts_pid_pcr,
1166 p->ps_size, p->au_sample_rate,
1167 p->au_pesid, p->vi_frame_rate,
1168 p->vi_frames_per_gop,
1169 p->vi_bframes_count, p->vi_pesid);
1170 break;
1171 }
1172 case VIDIOC_S_MPEGCOMP:
1173 {
1174 struct v4l2_mpeg_compression *p=arg;
1175 /*FIXME: Several fields not shown */
1176 if (!vfd->vidioc_s_mpegcomp)
1177 break;
1178 dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d, "
1179 "ts_pid_video=%d, ts_pid_pcr=%d, ps_size=%d, "
1180 "au_sample_rate=%d, au_pesid=%c, "
1181 "vi_frame_rate=%d, vi_frames_per_gop=%d, "
1182 "vi_bframes_count=%d, vi_pesid=%c\n",
1183 p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video,
1184 p->ts_pid_pcr, p->ps_size, p->au_sample_rate,
1185 p->au_pesid, p->vi_frame_rate,
1186 p->vi_frames_per_gop, p->vi_bframes_count,
1187 p->vi_pesid);
1188 ret=vfd->vidioc_s_mpegcomp(file, fh, p);
1189 break;
1190 }
1191 case VIDIOC_G_JPEGCOMP:
1192 {
1193 struct v4l2_jpegcompression *p=arg;
1194 if (!vfd->vidioc_g_jpegcomp)
1195 break;
1196 ret=vfd->vidioc_g_jpegcomp(file, fh, p);
1197 if (!ret)
1198 dbgarg (cmd, "quality=%d, APPn=%d, "
1199 "APP_len=%d, COM_len=%d, "
1200 "jpeg_markers=%d\n",
1201 p->quality,p->APPn,p->APP_len,
1202 p->COM_len,p->jpeg_markers);
1203 break;
1204 }
1205 case VIDIOC_S_JPEGCOMP:
1206 {
1207 struct v4l2_jpegcompression *p=arg;
1208 if (!vfd->vidioc_g_jpegcomp)
1209 break;
1210 dbgarg (cmd, "quality=%d, APPn=%d, APP_len=%d, "
1211 "COM_len=%d, jpeg_markers=%d\n",
1212 p->quality,p->APPn,p->APP_len,
1213 p->COM_len,p->jpeg_markers);
1214 ret=vfd->vidioc_s_jpegcomp(file, fh, p);
1215 break;
1216 }
1217 case VIDIOC_G_PARM:
1218 {
1219 struct v4l2_streamparm *p=arg;
1220 if (!vfd->vidioc_g_parm)
1221 break;
1222 ret=vfd->vidioc_g_parm(file, fh, p);
1223 dbgarg (cmd, "type=%d\n", p->type);
1224 break;
1225 }
1226 case VIDIOC_S_PARM:
1227 {
1228 struct v4l2_streamparm *p=arg;
1229 if (!vfd->vidioc_s_parm)
1230 break;
1231 dbgarg (cmd, "type=%d\n", p->type);
1232 ret=vfd->vidioc_s_parm(file, fh, p);
1233 break;
1234 }
1235 case VIDIOC_G_TUNER:
1236 {
1237 struct v4l2_tuner *p=arg;
1238 if (!vfd->vidioc_g_tuner)
1239 break;
1240 ret=vfd->vidioc_g_tuner(file, fh, p);
1241 if (!ret)
1242 dbgarg (cmd, "index=%d, name=%s, type=%d, "
1243 "capability=%d, rangelow=%d, "
1244 "rangehigh=%d, signal=%d, afc=%d, "
1245 "rxsubchans=%d, audmode=%d\n",
1246 p->index, p->name, p->type,
1247 p->capability, p->rangelow,
1248 p->rangehigh, p->rxsubchans,
1249 p->audmode, p->signal, p->afc);
1250 break;
1251 }
1252 case VIDIOC_S_TUNER:
1253 {
1254 struct v4l2_tuner *p=arg;
1255 if (!vfd->vidioc_s_tuner)
1256 break;
1257 dbgarg (cmd, "index=%d, name=%s, type=%d, "
1258 "capability=%d, rangelow=%d, rangehigh=%d, "
1259 "signal=%d, afc=%d, rxsubchans=%d, "
1260 "audmode=%d\n",p->index, p->name, p->type,
1261 p->capability, p->rangelow,p->rangehigh,
1262 p->rxsubchans, p->audmode, p->signal,
1263 p->afc);
1264 ret=vfd->vidioc_s_tuner(file, fh, p);
1265 break;
1266 }
1267 case VIDIOC_G_FREQUENCY:
1268 {
1269 struct v4l2_frequency *p=arg;
1270 if (!vfd->vidioc_g_frequency)
1271 break;
1272 ret=vfd->vidioc_g_frequency(file, fh, p);
1273 if (!ret)
1274 dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
1275 p->tuner,p->type,p->frequency);
1276 break;
1277 }
1278 case VIDIOC_S_FREQUENCY:
1279 {
1280 struct v4l2_frequency *p=arg;
1281 if (!vfd->vidioc_s_frequency)
1282 break;
1283 dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
1284 p->tuner,p->type,p->frequency);
1285 ret=vfd->vidioc_s_frequency(file, fh, p);
1286 break;
1287 }
1288 case VIDIOC_G_SLICED_VBI_CAP:
1289 {
1290 struct v4l2_sliced_vbi_cap *p=arg;
1291 if (!vfd->vidioc_g_sliced_vbi_cap)
1292 break;
1293 ret=vfd->vidioc_g_sliced_vbi_cap(file, fh, p);
1294 if (!ret)
1295 dbgarg (cmd, "service_set=%d\n", p->service_set);
1296 break;
1297 }
1298 case VIDIOC_LOG_STATUS:
1299 {
1300 if (!vfd->vidioc_log_status)
1301 break;
1302 ret=vfd->vidioc_log_status(file, fh);
1303 break;
1304 }
1305
1306 /* --- Others --------------------------------------------- */
1307
1308 default:
1309 ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl);
1310 }
1311
1312 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
1313 if (ret<0) {
1314 printk ("%s: err:\n", vfd->name);
1315 v4l_print_ioctl(vfd->name, cmd);
1316 }
1317 }
1318
1319 return ret;
1320}
1321
1322int video_ioctl2 (struct inode *inode, struct file *file,
1323 unsigned int cmd, unsigned long arg)
1324{
1325 char sbuf[128];
1326 void *mbuf = NULL;
1327 void *parg = NULL;
1328 int err = -EINVAL;
1329
1330#ifdef __OLD_VIDIOC_
1331 cmd = video_fix_command(cmd);
1332#endif
1333
1334 /* Copy arguments into temp kernel buffer */
1335 switch (_IOC_DIR(cmd)) {
1336 case _IOC_NONE:
1337 parg = NULL;
1338 break;
1339 case _IOC_READ:
1340 case _IOC_WRITE:
1341 case (_IOC_WRITE | _IOC_READ):
1342 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
1343 parg = sbuf;
1344 } else {
1345 /* too big to allocate from stack */
1346 mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
1347 if (NULL == mbuf)
1348 return -ENOMEM;
1349 parg = mbuf;
1350 }
1351
1352 err = -EFAULT;
1353 if (_IOC_DIR(cmd) & _IOC_WRITE)
1354 if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
1355 goto out;
1356 break;
1357 }
1358
1359 /* Handles IOCTL */
1360 err = __video_do_ioctl(inode, file, cmd, parg);
1361 if (err == -ENOIOCTLCMD)
1362 err = -EINVAL;
1363 if (err < 0)
1364 goto out;
1365
1366 /* Copy results into user buffer */
1367 switch (_IOC_DIR(cmd))
1368 {
1369 case _IOC_READ:
1370 case (_IOC_WRITE | _IOC_READ):
1371 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
1372 err = -EFAULT;
1373 break;
1374 }
1375
1376out:
1377 kfree(mbuf);
1378 return err;
1379}
1380
1381
245static struct file_operations video_fops; 1382static struct file_operations video_fops;
246 1383
247/** 1384/**
@@ -371,7 +1508,9 @@ void video_unregister_device(struct video_device *vfd)
371 mutex_unlock(&videodev_lock); 1508 mutex_unlock(&videodev_lock);
372} 1509}
373 1510
374 1511/*
1512 * Video fs operations
1513 */
375static struct file_operations video_fops= 1514static struct file_operations video_fops=
376{ 1515{
377 .owner = THIS_MODULE, 1516 .owner = THIS_MODULE,
@@ -387,7 +1526,7 @@ static int __init videodev_init(void)
387{ 1526{
388 int ret; 1527 int ret;
389 1528
390 printk(KERN_INFO "Linux video capture interface: v1.00\n"); 1529 printk(KERN_INFO "Linux video capture interface: v2.00\n");
391 if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { 1530 if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
392 printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); 1531 printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
393 return -EIO; 1532 return -EIO;
@@ -418,11 +1557,12 @@ EXPORT_SYMBOL(video_devdata);
418EXPORT_SYMBOL(video_usercopy); 1557EXPORT_SYMBOL(video_usercopy);
419EXPORT_SYMBOL(video_exclusive_open); 1558EXPORT_SYMBOL(video_exclusive_open);
420EXPORT_SYMBOL(video_exclusive_release); 1559EXPORT_SYMBOL(video_exclusive_release);
1560EXPORT_SYMBOL(video_ioctl2);
421EXPORT_SYMBOL(video_device_alloc); 1561EXPORT_SYMBOL(video_device_alloc);
422EXPORT_SYMBOL(video_device_release); 1562EXPORT_SYMBOL(video_device_release);
423 1563
424MODULE_AUTHOR("Alan Cox"); 1564MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
425MODULE_DESCRIPTION("Device registrar for Video4Linux drivers"); 1565MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
426MODULE_LICENSE("GPL"); 1566MODULE_LICENSE("GPL");
427 1567
428 1568