From: John Tsiombikas Date: Thu, 11 May 2017 04:39:43 +0000 (+0300) Subject: almost works, but apparently I need to implement the buffer mode. X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=vdummy;a=commitdiff_plain;h=8a6cb4ffb42e204ed6ed06fede5948974d2cef34 almost works, but apparently I need to implement the buffer mode. nobody uses read/write mode. --- diff --git a/vdummy.c b/vdummy.c index cde798d..55ed4da 100644 --- a/vdummy.c +++ b/vdummy.c @@ -7,17 +7,21 @@ #include #include #include +#include static int init(void); static void shutdown(void); static int open(struct file *file); static int close(struct file *file); static ssize_t read(struct file *file, char *ubuf, size_t bufsz, loff_t *offs); +//static unsigned int poll(struct file *file, struct poll_table_struct *ptab); static int ioctl_querycap(struct file *file, void *fh, struct v4l2_capability *cap); static int ioctl_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *fdesc); static int ioctl_get_fmt(struct file *file, void *fh, struct v4l2_format *fmt); static int ioctl_set_fmt(struct file *file, void *fh, struct v4l2_format *fmt); +static int ioctl_get_parm(struct file *file, void *fh, struct v4l2_streamparm *fmt); +static int ioctl_set_parm(struct file *file, void *fh, struct v4l2_streamparm *fmt); static int ioctl_queryctl(struct file *file, void *fh, struct v4l2_queryctrl *ctl); static int update_frame(int xsz, int ysz); @@ -30,10 +34,9 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Tsiombikas"); MODULE_DESCRIPTION("v4l2 test module"); -#define DEVNAME "video42" - -struct video_device *vdev; +static struct video_device *vdev; +static struct v4l2_device v4l2_dev; static struct v4l2_file_operations fops; static struct v4l2_ioctl_ops iops; static int width, height; @@ -45,24 +48,34 @@ static int init(void) { int res; + strcpy(v4l2_dev.name, "vdummy"); + if((res = v4l2_device_register(0, &v4l2_dev)) != 0) { + return res; + } + if(!(vdev = video_device_alloc())) { return -ENOMEM; } vdev->release = video_device_release; - strcpy(vdev->name, "video test"); + strcpy(vdev->name, KBUILD_MODNAME); vdev->fops = &fops; vdev->ioctl_ops = &iops; vdev->vfl_type = VFL_TYPE_GRABBER; + vdev->v4l2_dev = &v4l2_dev; + fops.owner = THIS_MODULE; fops.open = open; fops.release = close; fops.read = read; + //fops.poll = poll; fops.unlocked_ioctl = video_ioctl2; iops.vidioc_querycap = ioctl_querycap; iops.vidioc_enum_fmt_vid_cap = ioctl_enum_fmt; iops.vidioc_g_fmt_vid_cap = ioctl_get_fmt; iops.vidioc_s_fmt_vid_cap = ioctl_set_fmt; + iops.vidioc_g_parm = ioctl_get_parm; + iops.vidioc_s_parm = ioctl_set_parm; iops.vidioc_queryctrl = ioctl_queryctl; if((res = video_register_device(vdev, VFL_TYPE_GRABBER, -1)) != 0) { @@ -70,12 +83,14 @@ static int init(void) return res; } + printk(KERN_INFO "vdummy device initialized\n"); return 0; } static void shutdown(void) { video_unregister_device(vdev); + v4l2_device_unregister(&v4l2_dev); kfree(frame); } @@ -113,13 +128,19 @@ static ssize_t read(struct file *file, char *ubuf, size_t ubufsz, loff_t *offs) return sz; } +/* +static unsigned int poll(struct file *file, struct poll_table_struct *ptab) +{ +} +*/ + static int ioctl_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - strcpy(cap->driver, "vidtest"); - strcpy(cap->card, "fake"); + strcpy(cap->driver, KBUILD_MODNAME); + strcpy(cap->card, "dummy v4l2 dev"); strcpy(cap->bus_info, "nobus"); - cap->version = 0; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -158,6 +179,8 @@ static int ioctl_set_fmt(struct file *file, void *fh, struct v4l2_format *fmt) { int res; + printk(KERN_INFO "ioctl_set_fmt called\n"); + if(fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { return -EINVAL; } @@ -167,6 +190,28 @@ static int ioctl_set_fmt(struct file *file, void *fh, struct v4l2_format *fmt) return ioctl_get_fmt(file, fh, fmt); } +static int ioctl_get_parm(struct file *file, void *fh, struct v4l2_streamparm *parm) +{ + if(parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + return -EINVAL; + } + parm->parm.capture.capability = 0; + parm->parm.capture.capturemode = 0; + parm->parm.capture.timeperframe.numerator = 1; + parm->parm.capture.timeperframe.denominator = 30; + parm->parm.capture.extendedmode = 0; + parm->parm.capture.readbuffers = 1; + return 0; +} + +static int ioctl_set_parm(struct file *file, void *fh, struct v4l2_streamparm *parm) +{ + if(parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + return -EINVAL; + } + return ioctl_get_parm(file, fh, parm); +} + static int ioctl_queryctl(struct file *file, void *fh, struct v4l2_queryctrl *ctl) { return -EINVAL; @@ -176,7 +221,9 @@ static int update_frame(int xsz, int ysz) { unsigned char *tmp; int i, j; - int new_fsz = xsz * ysz; + int new_fsz = xsz * ysz * 3; + + printk(KERN_INFO "update_frame(%d, %d)\n", xsz, ysz); if(xsz == width && ysz == height) { return 0;