X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=vdummy;a=blobdiff_plain;f=vdummy.c;h=b0caa8252f87e32c7569851d6c9ff956987555ad;hp=e01eba6e93406ad44497864dd297deee02a8c87a;hb=c38558f6b5271d18586563c933e4b9b93c90a259;hpb=dfbabe3bf9b7ffefdf7ab48dd62cf506855ec3fb diff --git a/vdummy.c b/vdummy.c index e01eba6..b0caa82 100644 --- a/vdummy.c +++ b/vdummy.c @@ -5,10 +5,13 @@ #include #include #include +#include #include #include #include #include +#include +#include struct buffer { struct vb2_buffer vb; @@ -35,6 +38,7 @@ static void stop_streaming(struct vb2_queue *vbq); static int update_frame(int xsz, int ysz); +static int gen_frame(void); module_init(init); @@ -57,7 +61,8 @@ static unsigned char *frame; static int frame_size; static int streaming; -static struct buffer *buflist; +static spinlock_t blist_lock; +static struct buffer *buflist, *buflist_tail; static int seqno; @@ -71,6 +76,7 @@ static int init(void) } mutex_init(&mutex); + spin_lock_init(&blist_lock); vbops.queue_setup = queue_setup; vbops.buf_prepare = buf_prepare; @@ -99,12 +105,16 @@ static int init(void) if(!(vdev = video_device_alloc())) { return -ENOMEM; } + memset(vdev, 0, sizeof *vdev); vdev->release = video_device_release; strcpy(vdev->name, KBUILD_MODNAME); vdev->fops = &fops; vdev->ioctl_ops = &iops; vdev->vfl_type = VFL_TYPE_GRABBER; + vdev->vfl_dir = VFL_DIR_RX; vdev->v4l2_dev = &v4l2_dev; + vdev->lock = &mutex; + vdev->queue = &vbq; fops.owner = THIS_MODULE; fops.open = v4l2_fh_open; @@ -129,6 +139,9 @@ static int init(void) iops.vidioc_expbuf = vb2_ioctl_expbuf; iops.vidioc_streamon = vb2_ioctl_streamon; iops.vidioc_streamoff = vb2_ioctl_streamoff; + iops.vidioc_log_status = v4l2_ctrl_log_status; + iops.vidioc_subscribe_event = v4l2_ctrl_subscribe_event; + iops.vidioc_unsubscribe_event = v4l2_event_unsubscribe; if((res = video_register_device(vdev, VFL_TYPE_GRABBER, -1)) != 0) { printk(KERN_ALERT "vdummy: failed to register video device\n"); @@ -158,7 +171,7 @@ static void shutdown(void) static int ioctl_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { strcpy(cap->driver, KBUILD_MODNAME); - strcpy(cap->card, "dummy v4l2 dev"); + strcpy(cap->card, "Test V4L2 device"); strcpy(cap->bus_info, "nobus"); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -261,20 +274,44 @@ static int buf_prepare(struct vb2_buffer *vb) static void buf_queue(struct vb2_buffer *vb) { - memcpy(vb2_plane_vaddr(vb, 0), frame, frame_size); - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + struct buffer *buf = (struct buffer*)((char*)vb - offsetof(struct buffer, vb)); + + spin_lock(&blist_lock); + if(buflist) { + buflist_tail->next = buf; + buflist_tail = buf; + } else { + buflist = buflist_tail = buf; + } + buf->next = 0; + spin_unlock(&blist_lock); +} + +static void clear_queue(enum vb2_buffer_state st) +{ + spin_lock(&blist_lock); + while(buflist) { + struct buffer *buf = buflist; + buflist = buflist->next; + vb2_buffer_done(&buf->vb, st); + } + buflist = buflist_tail = 0; + spin_unlock(&blist_lock); } static int start_streaming(struct vb2_queue *vbq, unsigned int count) { streaming = 1; seqno = 0; + + gen_frame(); return 0; } static void stop_streaming(struct vb2_queue *vbq) { streaming = 0; + clear_queue(VB2_BUF_STATE_ERROR); } static int update_frame(int xsz, int ysz) @@ -309,5 +346,33 @@ static int update_frame(int xsz, int ysz) *tmp++ = (val << 2) & 0xff; } } + + return 0; +} + +static int gen_frame(void) +{ + struct buffer *buf = 0; + + spin_lock(&blist_lock); + if(buflist) { + buf = buflist; + buflist = buflist->next; + if(!buflist) buflist_tail = 0; + } + spin_unlock(&blist_lock); + + if(buf) { + struct vb2_v4l2_buffer *vvbuf; + + memcpy(vb2_plane_vaddr(&buf->vb, 0), frame, frame_size); + + vvbuf = to_vb2_v4l2_buffer(&buf->vb); + buf->vb.timestamp = ktime_get_ns(); + vvbuf->sequence = seqno++; + vvbuf->field = V4L2_FIELD_NONE; + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + } + return 0; }