1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/version.h>
5 #include <linux/slab.h>
6 #include <asm/uaccess.h>
7 #include <linux/videodev2.h>
8 #include <media/v4l2-dev.h>
9 #include <media/v4l2-ioctl.h>
10 #include <media/v4l2-device.h>
12 static int init(void);
13 static void shutdown(void);
14 static int open(struct file *file);
15 static int close(struct file *file);
16 static ssize_t read(struct file *file, char *ubuf, size_t bufsz, loff_t *offs);
17 //static unsigned int poll(struct file *file, struct poll_table_struct *ptab);
19 static int ioctl_querycap(struct file *file, void *fh, struct v4l2_capability *cap);
20 static int ioctl_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *fdesc);
21 static int ioctl_get_fmt(struct file *file, void *fh, struct v4l2_format *fmt);
22 static int ioctl_set_fmt(struct file *file, void *fh, struct v4l2_format *fmt);
23 static int ioctl_get_parm(struct file *file, void *fh, struct v4l2_streamparm *fmt);
24 static int ioctl_set_parm(struct file *file, void *fh, struct v4l2_streamparm *fmt);
25 static int ioctl_queryctl(struct file *file, void *fh, struct v4l2_queryctrl *ctl);
27 static int update_frame(int xsz, int ysz);
31 module_exit(shutdown);
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("John Tsiombikas");
35 MODULE_DESCRIPTION("v4l2 test module");
37 static struct video_device *vdev;
39 static struct v4l2_device v4l2_dev;
40 static struct v4l2_file_operations fops;
41 static struct v4l2_ioctl_ops iops;
42 static int width, height;
43 static unsigned char *frame;
44 static int frame_size;
51 strcpy(v4l2_dev.name, "vdummy");
52 if((res = v4l2_device_register(0, &v4l2_dev)) != 0) {
56 if(!(vdev = video_device_alloc())) {
59 vdev->release = video_device_release;
60 strcpy(vdev->name, KBUILD_MODNAME);
62 vdev->ioctl_ops = &iops;
63 vdev->vfl_type = VFL_TYPE_GRABBER;
64 vdev->v4l2_dev = &v4l2_dev;
66 fops.owner = THIS_MODULE;
71 fops.unlocked_ioctl = video_ioctl2;
73 iops.vidioc_querycap = ioctl_querycap;
74 iops.vidioc_enum_fmt_vid_cap = ioctl_enum_fmt;
75 iops.vidioc_g_fmt_vid_cap = ioctl_get_fmt;
76 iops.vidioc_s_fmt_vid_cap = ioctl_set_fmt;
77 iops.vidioc_g_parm = ioctl_get_parm;
78 iops.vidioc_s_parm = ioctl_set_parm;
79 iops.vidioc_queryctrl = ioctl_queryctl;
81 if((res = video_register_device(vdev, VFL_TYPE_GRABBER, -1)) != 0) {
82 video_device_release(vdev);
86 printk(KERN_INFO "vdummy device initialized\n");
90 static void shutdown(void)
92 video_unregister_device(vdev);
93 v4l2_device_unregister(&v4l2_dev);
97 static int open(struct file *file)
100 try_module_get(THIS_MODULE);
101 if((res = update_frame(640, 480)) != 0) {
107 static int close(struct file *file)
109 module_put(THIS_MODULE);
113 static ssize_t read(struct file *file, char *ubuf, size_t ubufsz, loff_t *offs)
115 int sz = frame_size - *offs;
117 if(sz <= 0) return 0;
118 if(ubufsz < sz) sz = ubufsz;
120 if(copy_to_user(ubuf, frame + *offs, sz) != 0) {
125 if(*offs >= frame_size) {
132 static unsigned int poll(struct file *file, struct poll_table_struct *ptab)
137 static int ioctl_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
139 strcpy(cap->driver, KBUILD_MODNAME);
140 strcpy(cap->card, "dummy v4l2 dev");
141 strcpy(cap->bus_info, "nobus");
142 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
143 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
147 static int ioctl_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *fdesc)
149 if(fdesc->index != 0 || fdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
153 strcpy(fdesc->description, "RGB24");
154 fdesc->pixelformat = V4L2_PIX_FMT_RGB24;
158 static int ioctl_get_fmt(struct file *file, void *fh, struct v4l2_format *fmt)
160 if(fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
163 fmt->fmt.pix.width = width;
164 fmt->fmt.pix.height = height;
165 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
166 fmt->fmt.pix.field = V4L2_FIELD_NONE;
167 fmt->fmt.pix.bytesperline = 0;
168 fmt->fmt.pix.sizeimage = frame_size;
169 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
170 fmt->fmt.pix.priv = 0;
171 fmt->fmt.pix.flags = 0;
172 fmt->fmt.pix.ycbcr_enc = 0;
173 fmt->fmt.pix.quantization = V4L2_QUANTIZATION_FULL_RANGE;
174 fmt->fmt.pix.xfer_func = V4L2_XFER_FUNC_NONE;
178 static int ioctl_set_fmt(struct file *file, void *fh, struct v4l2_format *fmt)
182 printk(KERN_INFO "ioctl_set_fmt called\n");
184 if(fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
187 if((res = update_frame(fmt->fmt.pix.width, fmt->fmt.pix.height)) != 0) {
190 return ioctl_get_fmt(file, fh, fmt);
193 static int ioctl_get_parm(struct file *file, void *fh, struct v4l2_streamparm *parm)
195 if(parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
198 parm->parm.capture.capability = 0;
199 parm->parm.capture.capturemode = 0;
200 parm->parm.capture.timeperframe.numerator = 1;
201 parm->parm.capture.timeperframe.denominator = 30;
202 parm->parm.capture.extendedmode = 0;
203 parm->parm.capture.readbuffers = 1;
207 static int ioctl_set_parm(struct file *file, void *fh, struct v4l2_streamparm *parm)
209 if(parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
212 return ioctl_get_parm(file, fh, parm);
215 static int ioctl_queryctl(struct file *file, void *fh, struct v4l2_queryctrl *ctl)
220 static int update_frame(int xsz, int ysz)
224 int new_fsz = xsz * ysz * 3;
226 printk(KERN_INFO "update_frame(%d, %d)\n", xsz, ysz);
228 if(xsz == width && ysz == height) {
232 if(!frame || frame_size < new_fsz) {
233 if(!(tmp = kmalloc(new_fsz, GFP_KERNEL))) {
237 frame_size = new_fsz;
244 for(i=0; i<height; i++) {
245 for(j=0; j<width; j++) {
248 *tmp++ = (val << 1) & 0xff;
249 *tmp++ = (val << 2) & 0xff;