MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+ /* FIXME: This is required to avoid OOPS on some cases, since mmap_mapper()
+ method should be called before _iolock.
+ On some cases, the mmap_mapper() is called only after scheduling.
+
+ However, this way is just too dirty! Better to wait for some event.
+ */
+ schedule_timeout(HZ);
+
return CALL(q,iolock,q,vb,fbuf);
}
/* --------------------------------------------------------------------- */
-void videobuf_queue_init(struct videobuf_queue* q,
+void videobuf_queue_core_init(struct videobuf_queue* q,
struct videobuf_queue_ops *ops,
void *dev,
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
unsigned int msize,
- void *priv)
+ void *priv,
+ struct videobuf_qtype_ops *int_ops)
{
memset(q,0,sizeof(*q));
- q->irqlock = irqlock;
- q->dev = dev;
- q->type = type;
- q->field = field;
- q->msize = msize;
- q->ops = ops;
+ q->irqlock = irqlock;
+ q->dev = dev;
+ q->type = type;
+ q->field = field;
+ q->msize = msize;
+ q->ops = ops;
q->priv_data = priv;
+ q->int_ops = int_ops;
/* All buffer operations are mandatory */
BUG_ON (!q->ops->buf_setup);
BUG_ON (!q->ops->buf_queue);
BUG_ON (!q->ops->buf_release);
+ /* Having implementations for abstract methods are mandatory */
+ BUG_ON (!q->int_ops);
+
mutex_init(&q->lock);
INIT_LIST_HEAD(&q->stream);
}
goto done;
}
- req->count = count;
+ req->count = retval;
done:
mutex_unlock(&q->lock);
int videobuf_streamon(struct videobuf_queue *q)
{
struct videobuf_buffer *buf;
- struct list_head *list;
unsigned long flags=0;
int retval;
q->streaming = 1;
if (q->irqlock)
spin_lock_irqsave(q->irqlock,flags);
- list_for_each(list,&q->stream) {
- buf = list_entry(list, struct videobuf_buffer, stream);
+ list_for_each_entry(buf, &q->stream, stream)
if (buf->state == STATE_PREPARED)
q->ops->buf_queue(q,buf);
- }
if (q->irqlock)
spin_unlock_irqrestore(q->irqlock,flags);
}
/* Copy to userspace */
- retval=CALL(q,copy_to_user,q,data,count,nonblocking);
+ retval=CALL(q,video_copy_to_user,q,data,count,nonblocking);
if (retval<0)
goto done;
{
enum v4l2_field field;
unsigned long flags=0;
- int count = 0, size = 0;
+ unsigned int count = 0, size = 0;
int err, i;
q->ops->buf_setup(q,&count,&size);
size = PAGE_ALIGN(size);
err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR);
- if (err)
+ if (err < 0)
return err;
+ count = err;
+
for (i = 0; i < count; i++) {
field = videobuf_next_field(q);
err = q->ops->buf_prepare(q,q->bufs[i],field);
}
if (q->read_buf->state == STATE_DONE) {
- rc = CALL (q,copy_stream, q, data, count,
+ rc = CALL (q,copy_stream, q, data + retval, count,
retval, vbihack, nonblocking);
if (rc < 0) {
retval = rc;
for (i = 0; i < bcount; i++) {
q->bufs[i] = videobuf_alloc(q);
+ if (q->bufs[i] == NULL)
+ break;
+
q->bufs[i]->i = i;
q->bufs[i]->input = UNSET;
q->bufs[i]->memory = memory;
}
}
+ if (!i)
+ return -ENOMEM;
+
dprintk(1,"mmap setup: %d buffers, %d bytes each\n",
- bcount,bsize);
+ i, bsize);
- return 0;
+ return i;
}
int videobuf_mmap_free(struct videobuf_queue *q)
return 0;
}
+EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
#endif
/* --------------------------------------------------------------------- */
EXPORT_SYMBOL_GPL(videobuf_alloc);
-EXPORT_SYMBOL_GPL(videobuf_queue_init);
+EXPORT_SYMBOL_GPL(videobuf_queue_core_init);
EXPORT_SYMBOL_GPL(videobuf_queue_cancel);
EXPORT_SYMBOL_GPL(videobuf_queue_is_busy);
EXPORT_SYMBOL_GPL(videobuf_querybuf);
EXPORT_SYMBOL_GPL(videobuf_qbuf);
EXPORT_SYMBOL_GPL(videobuf_dqbuf);
-EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
EXPORT_SYMBOL_GPL(videobuf_streamon);
EXPORT_SYMBOL_GPL(videobuf_streamoff);