X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=vdummy;a=blobdiff_plain;f=vdummy.c;h=fcc68c01f1429f7323f9f79fdab57e7725788f58;hp=e01eba6e93406ad44497864dd297deee02a8c87a;hb=f9dfe187cb687f6e8c8d3763e0325bffa4e00fea;hpb=dfbabe3bf9b7ffefdf7ab48dd62cf506855ec3fb diff --git a/vdummy.c b/vdummy.c index e01eba6..fcc68c0 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"); @@ -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,30 @@ 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) { + memcpy(vb2_plane_vaddr(&buf->vb, 0), frame, frame_size); + + /*v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + buf->vb.v4l2_buf.sequence = seqno++; + buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;*/ + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + } + return 0; }