+static int queue_setup(struct vb2_queue *vbq, unsigned int *nbuf,
+ unsigned int *nplanes, unsigned int *sizes, struct device **alloc_ctx)
+{
+ if(vbq->num_buffers + *nbuf < 2) {
+ *nbuf = 2 - vbq->num_buffers;
+ }
+
+ *nplanes = 1;
+ sizes[0] = frame_size;
+ alloc_ctx[0] = 0;
+ return 0;
+}
+
+static int buf_prepare(struct vb2_buffer *vb)
+{
+ if(vb2_plane_size(vb, 0) < frame_size) {
+ printk(KERN_ALERT "vdummy: buffer too small\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void buf_queue(struct vb2_buffer *vb)
+{
+ 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.vb2_buf, st);
+ }
+ buflist = buflist_tail = 0;
+ spin_unlock(&blist_lock);
+}
+
+static int start_streaming(struct vb2_queue *vbq, unsigned int count)
+{
+ ktime_t frame_interval;
+
+ streaming = 1;
+ seqno = 0;
+
+ /* calculate frame interval in nanoseconds */
+ if(framerate <= 1) {
+ frame_interval = ktime_set(1, 0);
+ } else {
+ frame_interval = ktime_set(0, 1000000000ul / (unsigned long)framerate);
+ }
+
+ hrtimer_start(&timer, frame_interval, HRTIMER_MODE_REL);
+ return 0;
+}
+
+static void stop_streaming(struct vb2_queue *vbq)
+{
+ hrtimer_cancel(&timer);
+
+ streaming = 0;
+ clear_queue(VB2_BUF_STATE_ERROR);
+}
+