Commit 82643d0e authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab

V4L/DVB (8181): gspca: read() did not work (loop in kernel, timeout...)

main:     Remove some vidioc_xx traces.
main:     read() did not work (user irq instead of mmap irq).
main:     Lack of v4l1 compat.
main:     Process loop inside kernel when no frame arriving.
main:     Double qbuf in read() when too many buffered frames.
Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 956e42d2
...@@ -35,8 +35,6 @@ ...@@ -35,8 +35,6 @@
#include "gspca.h" #include "gspca.h"
#undef CONFIG_VIDEO_V4L1_COMPAT
/* global values */ /* global values */
#define DEF_NURBS 2 /* default number of URBs (mmap) */ #define DEF_NURBS 2 /* default number of URBs (mmap) */
#define USR_NURBS 5 /* default number of URBs (userptr) */ #define USR_NURBS 5 /* default number of URBs (userptr) */
...@@ -45,8 +43,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); ...@@ -45,8 +43,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 1) #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 2)
static const char version[] = "2.1.1"; static const char version[] = "2.1.2";
static int video_nr = -1; static int video_nr = -1;
...@@ -281,10 +279,16 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, ...@@ -281,10 +279,16 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
frame->v4l2_buf.length); frame->v4l2_buf.length);
packet_type = DISCARD_PACKET; packet_type = DISCARD_PACKET;
} else { } else {
if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR) if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR) {
memcpy(frame->data_end, data, len); memcpy(frame->data_end, data, len);
else } else {
copy_to_user(frame->data_end, data, len); if (copy_to_user(frame->data_end,
data, len) != 0) {
PDEBUG(D_ERR|D_PACK,
"copy to user failed");
packet_type = DISCARD_PACKET;
}
}
frame->data_end += len; frame->data_end += len;
} }
} }
...@@ -565,9 +569,8 @@ static int create_urbs(struct gspca_dev *gspca_dev, ...@@ -565,9 +569,8 @@ static int create_urbs(struct gspca_dev *gspca_dev,
bsize = psize * npkt; bsize = psize * npkt;
PDEBUG(D_STREAM, PDEBUG(D_STREAM,
"isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
/*fixme:change for userptr*/
/*fixme:don't submit all URBs when userptr*/ /*fixme:don't submit all URBs when userptr*/
if (gspca_dev->memory == V4L2_MEMORY_MMAP) { if (gspca_dev->memory != V4L2_MEMORY_USERPTR) {
usb_complete = isoc_irq_mmap; usb_complete = isoc_irq_mmap;
nurbs = DEF_NURBS; nurbs = DEF_NURBS;
} else { } else {
...@@ -746,8 +749,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, ...@@ -746,8 +749,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
int i, j, index; int i, j, index;
__u32 fmt_tb[8]; __u32 fmt_tb[8];
PDEBUG(D_CONF, "enum fmt cap");
/* give an index to each format */ /* give an index to each format */
index = 0; index = 0;
j = 0; j = 0;
...@@ -792,14 +793,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, ...@@ -792,14 +793,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
fmt->fmt.pix.width = gspca_dev->width; fmt->fmt.pix.width = gspca_dev->width;
fmt->fmt.pix.height = gspca_dev->height; fmt->fmt.pix.height = gspca_dev->height;
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
#ifdef VIDEO_ADV_DEBUG
if (gspca_debug & D_CONF) {
PDEBUG_MODE("get fmt cap",
fmt->fmt.pix.pixelformat,
fmt->fmt.pix.width,
fmt->fmt.pix.height);
}
#endif
fmt->fmt.pix.field = V4L2_FIELD_NONE; fmt->fmt.pix.field = V4L2_FIELD_NONE;
fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat) fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
* fmt->fmt.pix.width / 8; * fmt->fmt.pix.width / 8;
...@@ -893,13 +886,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -893,13 +886,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
return 0; return 0;
} }
#endif
#ifdef VIDEO_ADV_DEBUG
if (gspca_debug & D_CONF) {
PDEBUG_MODE("set fmt cap",
fmt->fmt.pix.pixelformat,
fmt->fmt.pix.width, fmt->fmt.pix.height);
}
#endif #endif
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -1013,7 +999,6 @@ static int vidioc_querycap(struct file *file, void *priv, ...@@ -1013,7 +999,6 @@ static int vidioc_querycap(struct file *file, void *priv,
{ {
struct gspca_dev *gspca_dev = priv; struct gspca_dev *gspca_dev = priv;
PDEBUG(D_CONF, "querycap");
memset(cap, 0, sizeof *cap); memset(cap, 0, sizeof *cap);
strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
...@@ -1071,7 +1056,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, ...@@ -1071,7 +1056,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
struct ctrl *ctrls; struct ctrl *ctrls;
int i, ret; int i, ret;
PDEBUG(D_CONF, "set ctrl");
for (i = 0, ctrls = gspca_dev->sd_desc->ctrls; for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
i < gspca_dev->sd_desc->nctrls; i < gspca_dev->sd_desc->nctrls;
i++, ctrls++) { i++, ctrls++) {
...@@ -1155,7 +1139,6 @@ static int vidioc_reqbufs(struct file *file, void *priv, ...@@ -1155,7 +1139,6 @@ static int vidioc_reqbufs(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv; struct gspca_dev *gspca_dev = priv;
int i, ret = 0; int i, ret = 0;
PDEBUG(D_STREAM, "reqbufs %d", rb->count);
if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
switch (rb->memory) { switch (rb->memory) {
...@@ -1205,7 +1188,6 @@ static int vidioc_querybuf(struct file *file, void *priv, ...@@ -1205,7 +1188,6 @@ static int vidioc_querybuf(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv; struct gspca_dev *gspca_dev = priv;
struct gspca_frame *frame; struct gspca_frame *frame;
PDEBUG(D_STREAM, "querybuf");
if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
|| v4l2_buf->index < 0 || v4l2_buf->index < 0
|| v4l2_buf->index >= gspca_dev->nframes) || v4l2_buf->index >= gspca_dev->nframes)
...@@ -1222,7 +1204,6 @@ static int vidioc_streamon(struct file *file, void *priv, ...@@ -1222,7 +1204,6 @@ static int vidioc_streamon(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv; struct gspca_dev *gspca_dev = priv;
int ret; int ret;
PDEBUG(D_STREAM, "stream on");
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) if (mutex_lock_interruptible(&gspca_dev->queue_lock))
...@@ -1264,7 +1245,6 @@ static int vidioc_streamoff(struct file *file, void *priv, ...@@ -1264,7 +1245,6 @@ static int vidioc_streamoff(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv; struct gspca_dev *gspca_dev = priv;
int ret; int ret;
PDEBUG(D_STREAM, "stream off");
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
if (!gspca_dev->streaming) if (!gspca_dev->streaming)
...@@ -1499,8 +1479,10 @@ static int frame_wait(struct gspca_dev *gspca_dev, ...@@ -1499,8 +1479,10 @@ static int frame_wait(struct gspca_dev *gspca_dev,
i = gspca_dev->fr_o; i = gspca_dev->fr_o;
j = gspca_dev->fr_queue[i]; j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j]; frame = &gspca_dev->frame[j];
if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) {
atomic_dec(&gspca_dev->nevent);
goto ok; goto ok;
}
if (nonblock_ing) /* no frame yet */ if (nonblock_ing) /* no frame yet */
return -EAGAIN; return -EAGAIN;
...@@ -1511,9 +1493,10 @@ static int frame_wait(struct gspca_dev *gspca_dev, ...@@ -1511,9 +1493,10 @@ static int frame_wait(struct gspca_dev *gspca_dev,
msecs_to_jiffies(3000)); msecs_to_jiffies(3000));
if (ret <= 0) { if (ret <= 0) {
if (ret < 0) if (ret < 0)
return ret; return ret; /* interrupt */
return -EIO; return -EIO; /* timeout */
} }
atomic_dec(&gspca_dev->nevent);
if (!gspca_dev->streaming || !gspca_dev->present) if (!gspca_dev->streaming || !gspca_dev->present)
return -EIO; return -EIO;
if (gspca_dev->memory == V4L2_MEMORY_USERPTR) if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
...@@ -1525,7 +1508,6 @@ static int frame_wait(struct gspca_dev *gspca_dev, ...@@ -1525,7 +1508,6 @@ static int frame_wait(struct gspca_dev *gspca_dev,
break; break;
} }
ok: ok:
atomic_dec(&gspca_dev->nevent);
gspca_dev->fr_o = (i + 1) % gspca_dev->nframes; gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d", PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
gspca_dev->fr_q, gspca_dev->fr_q,
...@@ -1725,7 +1707,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) ...@@ -1725,7 +1707,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
goto out; goto out;
} }
/* if not mmap, treat the awaiting URBs */ /* if userptr, treat the awaiting URBs */
if (gspca_dev->memory == V4L2_MEMORY_USERPTR if (gspca_dev->memory == V4L2_MEMORY_USERPTR
&& gspca_dev->capt_file == file) && gspca_dev->capt_file == file)
isoc_transfer(gspca_dev); isoc_transfer(gspca_dev);
...@@ -1748,7 +1730,7 @@ static ssize_t dev_read(struct file *file, char __user *data, ...@@ -1748,7 +1730,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
struct gspca_frame *frame; struct gspca_frame *frame;
struct v4l2_buffer v4l2_buf; struct v4l2_buffer v4l2_buf;
struct timeval timestamp; struct timeval timestamp;
int i, ret, ret2; int n, ret, ret2;
PDEBUG(D_FRAM, "read (%d)", count); PDEBUG(D_FRAM, "read (%d)", count);
if (!gspca_dev->present) if (!gspca_dev->present)
...@@ -1760,9 +1742,9 @@ static ssize_t dev_read(struct file *file, char __user *data, ...@@ -1760,9 +1742,9 @@ static ssize_t dev_read(struct file *file, char __user *data,
return ret; return ret;
break; break;
case GSPCA_MEMORY_READ: case GSPCA_MEMORY_READ:
if (gspca_dev->capt_file != file) if (gspca_dev->capt_file == file)
return -EINVAL; break;
break; /* fall thru */
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1770,7 +1752,8 @@ static ssize_t dev_read(struct file *file, char __user *data, ...@@ -1770,7 +1752,8 @@ static ssize_t dev_read(struct file *file, char __user *data,
/* get a frame */ /* get a frame */
jiffies_to_timeval(get_jiffies_64(), &timestamp); jiffies_to_timeval(get_jiffies_64(), &timestamp);
timestamp.tv_sec--; timestamp.tv_sec--;
for (i = 0; i < 2; i++) { n = 2;
for (;;) {
memset(&v4l2_buf, 0, sizeof v4l2_buf); memset(&v4l2_buf, 0, sizeof v4l2_buf);
v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_buf.memory = V4L2_MEMORY_MMAP; v4l2_buf.memory = V4L2_MEMORY_MMAP;
...@@ -1781,8 +1764,10 @@ static ssize_t dev_read(struct file *file, char __user *data, ...@@ -1781,8 +1764,10 @@ static ssize_t dev_read(struct file *file, char __user *data,
} }
/* if the process slept for more than 1 second, /* if the process slept for more than 1 second,
* get a brand new frame */ * get anewer frame */
frame = &gspca_dev->frame[v4l2_buf.index]; frame = &gspca_dev->frame[v4l2_buf.index];
if (--n < 0)
break; /* avoid infinite loop */
if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec) if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
break; break;
ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment