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>
11 static int init(void);
12 static void shutdown(void);
13 static int open(struct file *file);
14 static int close(struct file *file);
15 static ssize_t read(struct file *file, char *ubuf, size_t bufsz, loff_t *offs);
17 static int ioctl_querycap(struct file *file, void *fh, struct v4l2_capability *cap);
18 static int ioctl_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *fdesc);
19 static int ioctl_get_fmt(struct file *file, void *fh, struct v4l2_format *fmt);
20 static int ioctl_set_fmt(struct file *file, void *fh, struct v4l2_format *fmt);
21 static int ioctl_queryctl(struct file *file, void *fh, struct v4l2_queryctrl *ctl);
23 static int update_frame(int xsz, int ysz);
27 module_exit(shutdown);
29 MODULE_LICENSE("GPL");
30 MODULE_AUTHOR("John Tsiombikas");
31 MODULE_DESCRIPTION("v4l2 test module");
33 #define DEVNAME "video42"
35 struct video_device *vdev;
37 static struct v4l2_file_operations fops;
38 static struct v4l2_ioctl_ops iops;
39 static int width, height;
40 static unsigned char *frame;
41 static int frame_size;
48 if(!(vdev = video_device_alloc())) {
51 vdev->release = video_device_release;
52 strcpy(vdev->name, "video test");
54 vdev->ioctl_ops = &iops;
55 vdev->vfl_type = VFL_TYPE_GRABBER;
60 fops.unlocked_ioctl = video_ioctl2;
62 iops.vidioc_querycap = ioctl_querycap;
63 iops.vidioc_enum_fmt_vid_cap = ioctl_enum_fmt;
64 iops.vidioc_g_fmt_vid_cap = ioctl_get_fmt;
65 iops.vidioc_s_fmt_vid_cap = ioctl_set_fmt;
66 iops.vidioc_queryctrl = ioctl_queryctl;
68 if((res = video_register_device(vdev, VFL_TYPE_GRABBER, -1)) != 0) {
69 video_device_release(vdev);
76 static void shutdown(void)
78 video_unregister_device(vdev);
82 static int open(struct file *file)
85 try_module_get(THIS_MODULE);
86 if((res = update_frame(640, 480)) != 0) {
92 static int close(struct file *file)
94 module_put(THIS_MODULE);
98 static ssize_t read(struct file *file, char *ubuf, size_t ubufsz, loff_t *offs)
100 int sz = frame_size - *offs;
102 if(sz <= 0) return 0;
103 if(ubufsz < sz) sz = ubufsz;
105 if(copy_to_user(ubuf, frame + *offs, sz) != 0) {
110 if(*offs >= frame_size) {
116 static int ioctl_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
118 strcpy(cap->driver, "vidtest");
119 strcpy(cap->card, "fake");
120 strcpy(cap->bus_info, "nobus");
122 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
126 static int ioctl_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *fdesc)
128 if(fdesc->index != 0 || fdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
132 strcpy(fdesc->description, "RGB24");
133 fdesc->pixelformat = V4L2_PIX_FMT_RGB24;
137 static int ioctl_get_fmt(struct file *file, void *fh, struct v4l2_format *fmt)
139 if(fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
142 fmt->fmt.pix.width = width;
143 fmt->fmt.pix.height = height;
144 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
145 fmt->fmt.pix.field = V4L2_FIELD_NONE;
146 fmt->fmt.pix.bytesperline = 0;
147 fmt->fmt.pix.sizeimage = frame_size;
148 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
149 fmt->fmt.pix.priv = 0;
150 fmt->fmt.pix.flags = 0;
151 fmt->fmt.pix.ycbcr_enc = 0;
152 fmt->fmt.pix.quantization = V4L2_QUANTIZATION_FULL_RANGE;
153 fmt->fmt.pix.xfer_func = V4L2_XFER_FUNC_NONE;
157 static int ioctl_set_fmt(struct file *file, void *fh, struct v4l2_format *fmt)
161 if(fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
164 if((res = update_frame(fmt->fmt.pix.width, fmt->fmt.pix.height)) != 0) {
167 return ioctl_get_fmt(file, fh, fmt);
170 static int ioctl_queryctl(struct file *file, void *fh, struct v4l2_queryctrl *ctl)
175 static int update_frame(int xsz, int ysz)
179 int new_fsz = xsz * ysz;
181 if(xsz == width && ysz == height) {
185 if(!frame || frame_size < new_fsz) {
186 if(!(tmp = kmalloc(new_fsz, GFP_KERNEL))) {
190 frame_size = new_fsz;
197 for(i=0; i<height; i++) {
198 for(j=0; j<width; j++) {
201 *tmp++ = (val << 1) & 0xff;
202 *tmp++ = (val << 2) & 0xff;