diff options
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/vivi.c | 622 |
1 files changed, 283 insertions, 339 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index d002561aeb4c..0aa54fb7727f 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -48,24 +48,15 @@ | |||
48 | 48 | ||
49 | #include "font.h" | 49 | #include "font.h" |
50 | 50 | ||
51 | MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); | ||
52 | MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); | ||
53 | MODULE_LICENSE("Dual BSD/GPL"); | ||
54 | |||
55 | #define VIVI_MAJOR_VERSION 0 | 51 | #define VIVI_MAJOR_VERSION 0 |
56 | #define VIVI_MINOR_VERSION 4 | 52 | #define VIVI_MINOR_VERSION 4 |
57 | #define VIVI_RELEASE 0 | 53 | #define VIVI_RELEASE 0 |
58 | #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) | 54 | #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) |
59 | 55 | ||
60 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ | 56 | /* Declare static vars that will be used as parameters */ |
61 | module_param(video_nr, int, 0); | 57 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ |
62 | 58 | static struct video_device vivi; /* Video device */ | |
63 | static int debug = 0; | 59 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ |
64 | module_param(debug, int, 0); | ||
65 | |||
66 | static unsigned int vid_limit = 16; | ||
67 | module_param(vid_limit,int,0644); | ||
68 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
69 | 60 | ||
70 | /* supported controls */ | 61 | /* supported controls */ |
71 | static struct v4l2_queryctrl vivi_qctrl[] = { | 62 | static struct v4l2_queryctrl vivi_qctrl[] = { |
@@ -119,10 +110,10 @@ static struct v4l2_queryctrl vivi_qctrl[] = { | |||
119 | 110 | ||
120 | static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; | 111 | static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; |
121 | 112 | ||
122 | #define dprintk(level,fmt, arg...) \ | 113 | #define dprintk(level,fmt, arg...) \ |
123 | do { \ | 114 | do { \ |
124 | if (debug >= (level)) \ | 115 | if (vivi.debug >= (level)) \ |
125 | printk(KERN_DEBUG "vivi: " fmt , ## arg); \ | 116 | printk(KERN_DEBUG "vivi: " fmt , ## arg); \ |
126 | } while (0) | 117 | } while (0) |
127 | 118 | ||
128 | /* ------------------------------------------------------------------ | 119 | /* ------------------------------------------------------------------ |
@@ -180,7 +171,7 @@ struct vivi_dev { | |||
180 | 171 | ||
181 | /* various device info */ | 172 | /* various device info */ |
182 | unsigned int resources; | 173 | unsigned int resources; |
183 | struct video_device video_dev; | 174 | struct video_device vfd; |
184 | 175 | ||
185 | struct vivi_dmaqueue vidq; | 176 | struct vivi_dmaqueue vidq; |
186 | 177 | ||
@@ -830,7 +821,80 @@ static struct videobuf_queue_ops vivi_video_qops = { | |||
830 | IOCTL handling | 821 | IOCTL handling |
831 | ------------------------------------------------------------------*/ | 822 | ------------------------------------------------------------------*/ |
832 | 823 | ||
833 | static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | 824 | |
825 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | ||
826 | { | ||
827 | /* is it free? */ | ||
828 | down(&dev->lock); | ||
829 | if (dev->resources) { | ||
830 | /* no, someone else uses it */ | ||
831 | up(&dev->lock); | ||
832 | return 0; | ||
833 | } | ||
834 | /* it's free, grab it */ | ||
835 | dev->resources =1; | ||
836 | dprintk(1,"res: get\n"); | ||
837 | up(&dev->lock); | ||
838 | return 1; | ||
839 | } | ||
840 | |||
841 | static int res_locked(struct vivi_dev *dev) | ||
842 | { | ||
843 | return (dev->resources); | ||
844 | } | ||
845 | |||
846 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | ||
847 | { | ||
848 | down(&dev->lock); | ||
849 | dev->resources = 0; | ||
850 | dprintk(1,"res: put\n"); | ||
851 | up(&dev->lock); | ||
852 | } | ||
853 | |||
854 | /* ------------------------------------------------------------------ | ||
855 | IOCTL vidioc handling | ||
856 | ------------------------------------------------------------------*/ | ||
857 | static int vidioc_querycap (struct file *file, void *priv, | ||
858 | struct v4l2_capability *cap) | ||
859 | { | ||
860 | strcpy(cap->driver, "vivi"); | ||
861 | strcpy(cap->card, "vivi"); | ||
862 | cap->version = VIVI_VERSION; | ||
863 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
864 | V4L2_CAP_STREAMING | | ||
865 | V4L2_CAP_READWRITE; | ||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | static int vidioc_enum_fmt_cap (struct file *file, void *priv, | ||
870 | struct v4l2_fmtdesc *f) | ||
871 | { | ||
872 | if (f->index > 0) | ||
873 | return -EINVAL; | ||
874 | |||
875 | strlcpy(f->description,format.name,sizeof(f->description)); | ||
876 | f->pixelformat = format.fourcc; | ||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | static int vidioc_g_fmt_cap (struct file *file, void *priv, | ||
881 | struct v4l2_format *f) | ||
882 | { | ||
883 | struct vivi_fh *fh=priv; | ||
884 | |||
885 | f->fmt.pix.width = fh->width; | ||
886 | f->fmt.pix.height = fh->height; | ||
887 | f->fmt.pix.field = fh->vb_vidq.field; | ||
888 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
889 | f->fmt.pix.bytesperline = | ||
890 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
891 | f->fmt.pix.sizeimage = | ||
892 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
893 | |||
894 | return (0); | ||
895 | } | ||
896 | |||
897 | static int vidioc_try_fmt_cap (struct file *file, void *priv, | ||
834 | struct v4l2_format *f) | 898 | struct v4l2_format *f) |
835 | { | 899 | { |
836 | struct vivi_fmt *fmt; | 900 | struct vivi_fmt *fmt; |
@@ -838,7 +902,8 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | |||
838 | unsigned int maxw, maxh; | 902 | unsigned int maxw, maxh; |
839 | 903 | ||
840 | if (format.fourcc != f->fmt.pix.pixelformat) { | 904 | if (format.fourcc != f->fmt.pix.pixelformat) { |
841 | dprintk(1,"Fourcc format invalid.\n"); | 905 | dprintk(1,"Fourcc format (0x%08x) invalid. Driver accepts " |
906 | "only 0x%08x\n",f->fmt.pix.pixelformat,format.fourcc); | ||
842 | return -EINVAL; | 907 | return -EINVAL; |
843 | } | 908 | } |
844 | fmt=&format; | 909 | fmt=&format; |
@@ -874,356 +939,196 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | |||
874 | return 0; | 939 | return 0; |
875 | } | 940 | } |
876 | 941 | ||
877 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | 942 | /*FIXME: This seems to be generic enough to be at videodev2 */ |
943 | static int vidioc_s_fmt_cap (struct file *file, void *priv, | ||
944 | struct v4l2_format *f) | ||
878 | { | 945 | { |
879 | /* is it free? */ | 946 | struct vivi_fh *fh=priv; |
880 | down(&dev->lock); | 947 | int ret = vidioc_try_fmt_cap(file,fh,f); |
881 | if (dev->resources) { | 948 | if (ret < 0) |
882 | /* no, someone else uses it */ | 949 | return (ret); |
883 | up(&dev->lock); | 950 | |
884 | return 0; | 951 | fh->fmt = &format; |
885 | } | 952 | fh->width = f->fmt.pix.width; |
886 | /* it's free, grab it */ | 953 | fh->height = f->fmt.pix.height; |
887 | dev->resources =1; | 954 | fh->vb_vidq.field = f->fmt.pix.field; |
888 | dprintk(1,"res: get\n"); | 955 | fh->type = f->type; |
889 | up(&dev->lock); | 956 | |
890 | return 1; | 957 | return (0); |
891 | } | 958 | } |
892 | 959 | ||
893 | static int res_locked(struct vivi_dev *dev) | 960 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) |
894 | { | 961 | { |
895 | return (dev->resources); | 962 | struct vivi_fh *fh=priv; |
896 | } | ||
897 | 963 | ||
898 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | 964 | return (videobuf_reqbufs(&fh->vb_vidq, p)); |
899 | { | ||
900 | down(&dev->lock); | ||
901 | dev->resources = 0; | ||
902 | dprintk(1,"res: put\n"); | ||
903 | up(&dev->lock); | ||
904 | } | 965 | } |
905 | 966 | ||
906 | static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) | 967 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) |
907 | { | 968 | { |
908 | struct vivi_fh *fh = file->private_data; | 969 | struct vivi_fh *fh=priv; |
909 | struct vivi_dev *dev = fh->dev; | ||
910 | int ret=0; | ||
911 | 970 | ||
912 | if (debug) { | 971 | return (videobuf_querybuf(&fh->vb_vidq, p)); |
913 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 972 | } |
914 | v4l_printk_ioctl_arg("vivi(w)",cmd, arg); | ||
915 | else if (!_IOC_DIR(cmd) & _IOC_READ) { | ||
916 | v4l_print_ioctl("vivi", cmd); | ||
917 | } | ||
918 | } | ||
919 | 973 | ||
920 | switch(cmd) { | 974 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
921 | /* --- capabilities ------------------------------------------ */ | 975 | { |
922 | case VIDIOC_QUERYCAP: | 976 | struct vivi_fh *fh=priv; |
923 | { | ||
924 | struct v4l2_capability *cap = (struct v4l2_capability*)arg; | ||
925 | |||
926 | memset(cap, 0, sizeof(*cap)); | ||
927 | |||
928 | strcpy(cap->driver, "vivi"); | ||
929 | strcpy(cap->card, "vivi"); | ||
930 | cap->version = VIVI_VERSION; | ||
931 | cap->capabilities = | ||
932 | V4L2_CAP_VIDEO_CAPTURE | | ||
933 | V4L2_CAP_STREAMING | | ||
934 | V4L2_CAP_READWRITE; | ||
935 | break; | ||
936 | } | ||
937 | /* --- capture ioctls ---------------------------------------- */ | ||
938 | case VIDIOC_ENUM_FMT: | ||
939 | { | ||
940 | struct v4l2_fmtdesc *f = arg; | ||
941 | enum v4l2_buf_type type; | ||
942 | unsigned int index; | ||
943 | 977 | ||
944 | index = f->index; | 978 | return (videobuf_qbuf(&fh->vb_vidq, p)); |
945 | type = f->type; | 979 | } |
946 | 980 | ||
947 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 981 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
948 | ret=-EINVAL; | 982 | { |
949 | break; | 983 | struct vivi_fh *fh=priv; |
950 | } | ||
951 | 984 | ||
952 | switch (type) { | 985 | return (videobuf_dqbuf(&fh->vb_vidq, p, |
953 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 986 | file->f_flags & O_NONBLOCK)); |
954 | if (index > 0){ | 987 | } |
955 | ret=-EINVAL; | ||
956 | break; | ||
957 | } | ||
958 | memset(f,0,sizeof(*f)); | ||
959 | 988 | ||
960 | f->index = index; | 989 | #ifdef HAVE_V4L1 |
961 | f->type = type; | 990 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) |
962 | strlcpy(f->description,format.name,sizeof(f->description)); | 991 | { |
963 | f->pixelformat = format.fourcc; | 992 | struct vivi_fh *fh=priv; |
964 | break; | 993 | struct videobuf_queue *q=&fh->vb_vidq; |
965 | default: | 994 | struct v4l2_requestbuffers req; |
966 | ret=-EINVAL; | 995 | unsigned int i, ret; |
967 | } | 996 | |
968 | break; | 997 | req.type = q->type; |
998 | req.count = 8; | ||
999 | req.memory = V4L2_MEMORY_MMAP; | ||
1000 | ret = videobuf_reqbufs(q,&req); | ||
1001 | if (ret < 0) | ||
1002 | return (ret); | ||
1003 | memset(mbuf,0,sizeof(*mbuf)); | ||
1004 | mbuf->frames = req.count; | ||
1005 | mbuf->size = 0; | ||
1006 | for (i = 0; i < mbuf->frames; i++) { | ||
1007 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1008 | mbuf->size += q->bufs[i]->bsize; | ||
969 | } | 1009 | } |
970 | case VIDIOC_G_FMT: | 1010 | return (0); |
971 | { | 1011 | } |
972 | struct v4l2_format *f = (struct v4l2_format *)arg; | 1012 | #endif |
973 | 1013 | ||
974 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1014 | int vidioc_streamon (struct file *file, void *priv, enum v4l2_buf_type i) |
975 | ret=-EINVAL; | 1015 | { |
976 | break; | 1016 | struct vivi_fh *fh=priv; |
977 | } | 1017 | struct vivi_dev *dev = fh->dev; |
978 | 1018 | ||
979 | memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); | 1019 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
980 | f->fmt.pix.width = fh->width; | 1020 | return -EINVAL; |
981 | f->fmt.pix.height = fh->height; | 1021 | if (i != fh->type) |
982 | f->fmt.pix.field = fh->vb_vidq.field; | 1022 | return -EINVAL; |
983 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
984 | f->fmt.pix.bytesperline = | ||
985 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
986 | f->fmt.pix.sizeimage = | ||
987 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
988 | break; | ||
989 | } | ||
990 | case VIDIOC_S_FMT: | ||
991 | { | ||
992 | struct v4l2_format *f = arg; | ||
993 | 1023 | ||
994 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1024 | if (!res_get(dev,fh)) |
995 | dprintk(1,"Only capture supported.\n"); | 1025 | return -EBUSY; |
996 | ret=-EINVAL; | 1026 | return (videobuf_streamon(&fh->vb_vidq)); |
997 | break; | 1027 | } |
998 | } | ||
999 | 1028 | ||
1000 | ret = vivi_try_fmt(dev,fh,f); | 1029 | int vidioc_streamoff (struct file *file, void *priv, enum v4l2_buf_type i) |
1001 | if (ret < 0) | 1030 | { |
1002 | break; | 1031 | struct vivi_fh *fh=priv; |
1032 | struct vivi_dev *dev = fh->dev; | ||
1003 | 1033 | ||
1004 | fh->fmt = &format; | 1034 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1005 | fh->width = f->fmt.pix.width; | 1035 | return -EINVAL; |
1006 | fh->height = f->fmt.pix.height; | 1036 | if (i != fh->type) |
1007 | fh->vb_vidq.field = f->fmt.pix.field; | 1037 | return -EINVAL; |
1008 | fh->type = f->type; | ||
1009 | 1038 | ||
1010 | break; | 1039 | videobuf_streamoff(&fh->vb_vidq); |
1011 | } | 1040 | res_free(dev,fh); |
1012 | case VIDIOC_TRY_FMT: | ||
1013 | { | ||
1014 | struct v4l2_format *f = arg; | ||
1015 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1016 | ret=-EINVAL; | ||
1017 | break; | ||
1018 | } | ||
1019 | 1041 | ||
1020 | ret=vivi_try_fmt(dev,fh,f); | 1042 | return (0); |
1021 | break; | 1043 | } |
1022 | } | 1044 | |
1023 | case VIDIOC_REQBUFS: | 1045 | static struct v4l2_tvnorm tvnorms[] = { |
1024 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1025 | ret=-EINVAL; | ||
1026 | break; | ||
1027 | } | ||
1028 | ret=videobuf_reqbufs(&fh->vb_vidq, arg); | ||
1029 | break; | ||
1030 | case VIDIOC_QUERYBUF: | ||
1031 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1032 | ret=-EINVAL; | ||
1033 | break; | ||
1034 | } | ||
1035 | ret=videobuf_querybuf(&fh->vb_vidq, arg); | ||
1036 | break; | ||
1037 | case VIDIOC_QBUF: | ||
1038 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1039 | ret=-EINVAL; | ||
1040 | break; | ||
1041 | } | ||
1042 | ret=videobuf_qbuf(&fh->vb_vidq, arg); | ||
1043 | break; | ||
1044 | case VIDIOC_DQBUF: | ||
1045 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1046 | ret=-EINVAL; | ||
1047 | break; | ||
1048 | } | ||
1049 | ret=videobuf_dqbuf(&fh->vb_vidq, arg, | ||
1050 | file->f_flags & O_NONBLOCK); | ||
1051 | break; | ||
1052 | #ifdef HAVE_V4L1 | ||
1053 | /* --- streaming capture ------------------------------------- */ | ||
1054 | case VIDIOCGMBUF: | ||
1055 | { | ||
1056 | struct video_mbuf *mbuf = arg; | ||
1057 | struct videobuf_queue *q=&fh->vb_vidq; | ||
1058 | struct v4l2_requestbuffers req; | ||
1059 | unsigned int i; | ||
1060 | |||
1061 | memset(&req,0,sizeof(req)); | ||
1062 | req.type = q->type; | ||
1063 | req.count = 8; | ||
1064 | req.memory = V4L2_MEMORY_MMAP; | ||
1065 | ret = videobuf_reqbufs(q,&req); | ||
1066 | if (ret < 0) | ||
1067 | break; | ||
1068 | memset(mbuf,0,sizeof(*mbuf)); | ||
1069 | mbuf->frames = req.count; | ||
1070 | mbuf->size = 0; | ||
1071 | for (i = 0; i < mbuf->frames; i++) { | ||
1072 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1073 | mbuf->size += q->bufs[i]->bsize; | ||
1074 | } | ||
1075 | break; | ||
1076 | } | ||
1077 | #endif | ||
1078 | case VIDIOC_STREAMON: | ||
1079 | { | ||
1080 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1081 | return -EINVAL; | ||
1082 | if (!res_get(dev,fh)) | ||
1083 | return -EBUSY; | ||
1084 | ret=videobuf_streamon(&fh->vb_vidq); | ||
1085 | break; | ||
1086 | } | ||
1087 | case VIDIOC_STREAMOFF: | ||
1088 | { | 1046 | { |
1089 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1047 | .name = "NTSC-M", |
1090 | ret=-EINVAL; | 1048 | .id = V4L2_STD_NTSC_M, |
1091 | break; | ||
1092 | } | ||
1093 | ret = videobuf_streamoff(&fh->vb_vidq); | ||
1094 | if (ret < 0) | ||
1095 | break; | ||
1096 | res_free(dev,fh); | ||
1097 | break; | ||
1098 | } | 1049 | } |
1099 | /* ---------- tv norms ---------- */ | 1050 | }; |
1100 | case VIDIOC_ENUMSTD: | ||
1101 | { | ||
1102 | struct v4l2_standard *e = arg; | ||
1103 | 1051 | ||
1104 | if (e->index>0) { | 1052 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) |
1105 | ret=-EINVAL; | 1053 | { |
1106 | break; | ||
1107 | } | ||
1108 | ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M"); | ||
1109 | 1054 | ||
1110 | /* Allows vivi to use different fps from video std */ | 1055 | return 0; |
1111 | e->frameperiod.numerator = WAKE_NUMERATOR; | 1056 | } |
1112 | e->frameperiod.denominator = WAKE_DENOMINATOR; | ||
1113 | 1057 | ||
1114 | break; | 1058 | /* only one input in this sample driver */ |
1115 | } | 1059 | static int vidioc_enum_input (struct file *file, void *priv, |
1116 | case VIDIOC_G_STD: | 1060 | struct v4l2_input *inp) |
1117 | { | 1061 | { |
1118 | v4l2_std_id *id = arg; | 1062 | if (inp->index != 0) |
1063 | return -EINVAL; | ||
1119 | 1064 | ||
1120 | *id = V4L2_STD_NTSC_M; | 1065 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
1121 | break; | 1066 | inp->std = V4L2_STD_NTSC_M; |
1122 | } | 1067 | strcpy(inp->name,"Camera"); |
1123 | case VIDIOC_S_STD: | ||
1124 | { | ||
1125 | break; | ||
1126 | } | ||
1127 | /* ------ input switching ---------- */ | ||
1128 | case VIDIOC_ENUMINPUT: | ||
1129 | { /* only one input in this sample driver */ | ||
1130 | struct v4l2_input *inp = arg; | ||
1131 | 1068 | ||
1132 | if (inp->index != 0) { | 1069 | return (0); |
1133 | ret=-EINVAL; | 1070 | } |
1134 | break; | ||
1135 | } | ||
1136 | memset(inp, 0, sizeof(*inp)); | ||
1137 | 1071 | ||
1138 | inp->index = 0; | 1072 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
1139 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 1073 | { |
1140 | inp->std = V4L2_STD_NTSC_M; | 1074 | *i = 0; |
1141 | strcpy(inp->name,"Camera"); | ||
1142 | break; | ||
1143 | } | ||
1144 | case VIDIOC_G_INPUT: | ||
1145 | { | ||
1146 | unsigned int *i = arg; | ||
1147 | 1075 | ||
1148 | *i = 0; | 1076 | return (0); |
1149 | break; | 1077 | } |
1150 | } | 1078 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
1151 | case VIDIOC_S_INPUT: | 1079 | { |
1152 | { | 1080 | if (i > 0) |
1153 | unsigned int *i = arg; | 1081 | return -EINVAL; |
1154 | 1082 | ||
1155 | if (*i > 0) | 1083 | return (0); |
1156 | ret=-EINVAL; | 1084 | } |
1157 | break; | ||
1158 | } | ||
1159 | 1085 | ||
1160 | /* --- controls ---------------------------------------------- */ | 1086 | /* --- controls ---------------------------------------------- */ |
1161 | case VIDIOC_QUERYCTRL: | 1087 | static int vidioc_queryctrl (struct file *file, void *priv, |
1162 | { | 1088 | struct v4l2_queryctrl *qc) |
1163 | struct v4l2_queryctrl *qc = arg; | 1089 | { |
1164 | int i; | 1090 | int i; |
1165 | |||
1166 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1167 | if (qc->id && qc->id == vivi_qctrl[i].id) { | ||
1168 | memcpy(qc, &(vivi_qctrl[i]), | ||
1169 | sizeof(*qc)); | ||
1170 | break; | ||
1171 | } | ||
1172 | 1091 | ||
1173 | ret=-EINVAL; | 1092 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) |
1174 | break; | 1093 | if (qc->id && qc->id == vivi_qctrl[i].id) { |
1175 | } | 1094 | memcpy(qc, &(vivi_qctrl[i]), |
1176 | case VIDIOC_G_CTRL: | 1095 | sizeof(*qc)); |
1177 | { | 1096 | return (0); |
1178 | struct v4l2_control *ctrl = arg; | 1097 | } |
1179 | int i; | ||
1180 | 1098 | ||
1181 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | 1099 | return -EINVAL; |
1182 | if (ctrl->id == vivi_qctrl[i].id) { | 1100 | } |
1183 | ctrl->value=qctl_regs[i]; | ||
1184 | break; | ||
1185 | } | ||
1186 | 1101 | ||
1187 | ret=-EINVAL; | 1102 | static int vidioc_g_ctrl (struct file *file, void *priv, |
1188 | break; | 1103 | struct v4l2_control *ctrl) |
1189 | } | 1104 | { |
1190 | case VIDIOC_S_CTRL: | 1105 | int i; |
1191 | { | ||
1192 | struct v4l2_control *ctrl = arg; | ||
1193 | int i; | ||
1194 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1195 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1196 | if (ctrl->value < | ||
1197 | vivi_qctrl[i].minimum | ||
1198 | || ctrl->value > | ||
1199 | vivi_qctrl[i].maximum) { | ||
1200 | ret=-ERANGE; | ||
1201 | break; | ||
1202 | } | ||
1203 | qctl_regs[i]=ctrl->value; | ||
1204 | break; | ||
1205 | } | ||
1206 | ret=-EINVAL; | ||
1207 | break; | ||
1208 | } | ||
1209 | default: | ||
1210 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl); | ||
1211 | } | ||
1212 | 1106 | ||
1213 | if (debug) { | 1107 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) |
1214 | if (ret<0) { | 1108 | if (ctrl->id == vivi_qctrl[i].id) { |
1215 | v4l_print_ioctl("vivi(err)", cmd); | 1109 | ctrl->value=qctl_regs[i]; |
1216 | dprintk(1,"errcode=%d\n",ret); | 1110 | return (0); |
1217 | } else if (_IOC_DIR(cmd) & _IOC_READ) | 1111 | } |
1218 | v4l_printk_ioctl_arg("vivi(r)",cmd, arg); | ||
1219 | } | ||
1220 | 1112 | ||
1221 | return ret; | 1113 | return -EINVAL; |
1222 | } | 1114 | } |
1223 | 1115 | static int vidioc_s_ctrl (struct file *file, void *priv, | |
1224 | static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 1116 | struct v4l2_control *ctrl) |
1225 | { | 1117 | { |
1226 | return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl); | 1118 | int i; |
1119 | |||
1120 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1121 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1122 | if (ctrl->value < | ||
1123 | vivi_qctrl[i].minimum | ||
1124 | || ctrl->value > | ||
1125 | vivi_qctrl[i].maximum) { | ||
1126 | return (-ERANGE); | ||
1127 | } | ||
1128 | qctl_regs[i]=ctrl->value; | ||
1129 | return (0); | ||
1130 | } | ||
1131 | return -EINVAL; | ||
1227 | } | 1132 | } |
1228 | 1133 | ||
1229 | /* ------------------------------------------------------------------ | 1134 | /* ------------------------------------------------------------------ |
@@ -1245,7 +1150,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1245 | 1150 | ||
1246 | list_for_each(list,&vivi_devlist) { | 1151 | list_for_each(list,&vivi_devlist) { |
1247 | h = list_entry(list, struct vivi_dev, vivi_devlist); | 1152 | h = list_entry(list, struct vivi_dev, vivi_devlist); |
1248 | if (h->video_dev.minor == minor) { | 1153 | if (h->vfd.minor == minor) { |
1249 | dev = h; | 1154 | dev = h; |
1250 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1155 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1251 | } | 1156 | } |
@@ -1254,6 +1159,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1254 | return -ENODEV; | 1159 | return -ENODEV; |
1255 | 1160 | ||
1256 | 1161 | ||
1162 | |||
1257 | /* If more than one user, mutex should be added */ | 1163 | /* If more than one user, mutex should be added */ |
1258 | dev->users++; | 1164 | dev->users++; |
1259 | 1165 | ||
@@ -1269,6 +1175,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1269 | 1175 | ||
1270 | file->private_data = fh; | 1176 | file->private_data = fh; |
1271 | fh->dev = dev; | 1177 | fh->dev = dev; |
1178 | |||
1272 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1179 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1273 | fh->fmt = &format; | 1180 | fh->fmt = &format; |
1274 | fh->width = 640; | 1181 | fh->width = 640; |
@@ -1304,7 +1211,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1304 | static ssize_t | 1211 | static ssize_t |
1305 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | 1212 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) |
1306 | { | 1213 | { |
1307 | struct vivi_fh *fh = file->private_data; | 1214 | struct vivi_fh *fh = file->private_data; |
1308 | 1215 | ||
1309 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1216 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1310 | if (res_locked(fh->dev)) | 1217 | if (res_locked(fh->dev)) |
@@ -1318,8 +1225,8 @@ vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | |||
1318 | static unsigned int | 1225 | static unsigned int |
1319 | vivi_poll(struct file *file, struct poll_table_struct *wait) | 1226 | vivi_poll(struct file *file, struct poll_table_struct *wait) |
1320 | { | 1227 | { |
1321 | struct vivi_fh *fh = file->private_data; | 1228 | struct vivi_fh *fh = file->private_data; |
1322 | struct vivi_buffer *buf; | 1229 | struct vivi_buffer *buf; |
1323 | 1230 | ||
1324 | dprintk(1,"%s\n",__FUNCTION__); | 1231 | dprintk(1,"%s\n",__FUNCTION__); |
1325 | 1232 | ||
@@ -1348,8 +1255,8 @@ vivi_poll(struct file *file, struct poll_table_struct *wait) | |||
1348 | 1255 | ||
1349 | static int vivi_release(struct inode *inode, struct file *file) | 1256 | static int vivi_release(struct inode *inode, struct file *file) |
1350 | { | 1257 | { |
1351 | struct vivi_fh *fh = file->private_data; | 1258 | struct vivi_fh *fh = file->private_data; |
1352 | struct vivi_dev *dev = fh->dev; | 1259 | struct vivi_dev *dev = fh->dev; |
1353 | struct vivi_dmaqueue *vidq = &dev->vidq; | 1260 | struct vivi_dmaqueue *vidq = &dev->vidq; |
1354 | 1261 | ||
1355 | int minor = iminor(inode); | 1262 | int minor = iminor(inode); |
@@ -1369,7 +1276,7 @@ static int vivi_release(struct inode *inode, struct file *file) | |||
1369 | static int | 1276 | static int |
1370 | vivi_mmap(struct file *file, struct vm_area_struct * vma) | 1277 | vivi_mmap(struct file *file, struct vm_area_struct * vma) |
1371 | { | 1278 | { |
1372 | struct vivi_fh *fh = file->private_data; | 1279 | struct vivi_fh *fh = file->private_data; |
1373 | int ret; | 1280 | int ret; |
1374 | 1281 | ||
1375 | dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); | 1282 | dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); |
@@ -1390,20 +1297,44 @@ static struct file_operations vivi_fops = { | |||
1390 | .release = vivi_release, | 1297 | .release = vivi_release, |
1391 | .read = vivi_read, | 1298 | .read = vivi_read, |
1392 | .poll = vivi_poll, | 1299 | .poll = vivi_poll, |
1393 | .ioctl = vivi_ioctl, | 1300 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ |
1394 | .mmap = vivi_mmap, | 1301 | .mmap = vivi_mmap, |
1395 | .llseek = no_llseek, | 1302 | .llseek = no_llseek, |
1396 | }; | 1303 | }; |
1397 | 1304 | ||
1398 | static struct video_device vivi = { | 1305 | static struct video_device vivi = { |
1399 | .name = "VTM Virtual Video Capture Board", | 1306 | .name = "vivi", |
1400 | .type = VID_TYPE_CAPTURE, | 1307 | .type = VID_TYPE_CAPTURE, |
1401 | .hardware = 0, | 1308 | .hardware = 0, |
1402 | .fops = &vivi_fops, | 1309 | .fops = &vivi_fops, |
1403 | .minor = -1, | 1310 | .minor = -1, |
1404 | // .release = video_device_release, | 1311 | // .release = video_device_release, |
1312 | |||
1313 | .vidioc_querycap = vidioc_querycap, | ||
1314 | .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, | ||
1315 | .vidioc_g_fmt_cap = vidioc_g_fmt_cap, | ||
1316 | .vidioc_try_fmt_cap = vidioc_try_fmt_cap, | ||
1317 | .vidioc_s_fmt_cap = vidioc_s_fmt_cap, | ||
1318 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1319 | .vidioc_querybuf = vidioc_querybuf, | ||
1320 | .vidioc_qbuf = vidioc_qbuf, | ||
1321 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1322 | .vidioc_s_std = vidioc_s_std, | ||
1323 | .vidioc_enum_input = vidioc_enum_input, | ||
1324 | .vidioc_g_input = vidioc_g_input, | ||
1325 | .vidioc_s_input = vidioc_s_input, | ||
1326 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1327 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1328 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1329 | .vidioc_streamon = vidioc_streamon, | ||
1330 | .vidioc_streamoff = vidioc_streamoff, | ||
1331 | #ifdef HAVE_V4L1 | ||
1332 | .vidiocgmbuf = vidiocgmbuf, | ||
1333 | #endif | ||
1334 | .tvnorms = tvnorms, | ||
1335 | .tvnormsize = ARRAY_SIZE(tvnorms), | ||
1405 | }; | 1336 | }; |
1406 | /* ------------------------------------------------------------------ | 1337 | /* ----------------------------------------------------------------- |
1407 | Initialization and module stuff | 1338 | Initialization and module stuff |
1408 | ------------------------------------------------------------------*/ | 1339 | ------------------------------------------------------------------*/ |
1409 | 1340 | ||
@@ -1447,3 +1378,16 @@ static void __exit vivi_exit(void) | |||
1447 | 1378 | ||
1448 | module_init(vivi_init); | 1379 | module_init(vivi_init); |
1449 | module_exit(vivi_exit); | 1380 | module_exit(vivi_exit); |
1381 | |||
1382 | MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); | ||
1383 | MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); | ||
1384 | MODULE_LICENSE("Dual BSD/GPL"); | ||
1385 | |||
1386 | module_param(video_nr, int, 0); | ||
1387 | |||
1388 | module_param_named(debug,vivi.debug, int, 0644); | ||
1389 | MODULE_PARM_DESC(debug,"activates debug info"); | ||
1390 | |||
1391 | module_param(vid_limit,int,0644); | ||
1392 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
1393 | |||