diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-07-02 08:14:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:16:00 -0400 |
commit | 82643d0e90896fba965e6e43692538b2cc093d34 (patch) | |
tree | 417f6af7c540ab08767e60fcca1ce23b198f1119 | |
parent | 956e42d28f300f5bb928fb5850b3e3c0a8982d23 (diff) |
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: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 71 |
1 files changed, 28 insertions, 43 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 13cd9968f1f5..25e42bd7af87 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -35,8 +35,6 @@ | |||
35 | 35 | ||
36 | #include "gspca.h" | 36 | #include "gspca.h" |
37 | 37 | ||
38 | #undef CONFIG_VIDEO_V4L1_COMPAT | ||
39 | |||
40 | /* global values */ | 38 | /* global values */ |
41 | #define DEF_NURBS 2 /* default number of URBs (mmap) */ | 39 | #define DEF_NURBS 2 /* default number of URBs (mmap) */ |
42 | #define USR_NURBS 5 /* default number of URBs (userptr) */ | 40 | #define USR_NURBS 5 /* default number of URBs (userptr) */ |
@@ -45,8 +43,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
45 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 43 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
46 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
47 | 45 | ||
48 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 1) | 46 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 2) |
49 | static const char version[] = "2.1.1"; | 47 | static const char version[] = "2.1.2"; |
50 | 48 | ||
51 | static int video_nr = -1; | 49 | static int video_nr = -1; |
52 | 50 | ||
@@ -281,10 +279,16 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
281 | frame->v4l2_buf.length); | 279 | frame->v4l2_buf.length); |
282 | packet_type = DISCARD_PACKET; | 280 | packet_type = DISCARD_PACKET; |
283 | } else { | 281 | } else { |
284 | if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR) | 282 | if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR) { |
285 | memcpy(frame->data_end, data, len); | 283 | memcpy(frame->data_end, data, len); |
286 | else | 284 | } else { |
287 | copy_to_user(frame->data_end, data, len); | 285 | if (copy_to_user(frame->data_end, |
286 | data, len) != 0) { | ||
287 | PDEBUG(D_ERR|D_PACK, | ||
288 | "copy to user failed"); | ||
289 | packet_type = DISCARD_PACKET; | ||
290 | } | ||
291 | } | ||
288 | frame->data_end += len; | 292 | frame->data_end += len; |
289 | } | 293 | } |
290 | } | 294 | } |
@@ -565,9 +569,8 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
565 | bsize = psize * npkt; | 569 | bsize = psize * npkt; |
566 | PDEBUG(D_STREAM, | 570 | PDEBUG(D_STREAM, |
567 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); | 571 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); |
568 | /*fixme:change for userptr*/ | ||
569 | /*fixme:don't submit all URBs when userptr*/ | 572 | /*fixme:don't submit all URBs when userptr*/ |
570 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) { | 573 | if (gspca_dev->memory != V4L2_MEMORY_USERPTR) { |
571 | usb_complete = isoc_irq_mmap; | 574 | usb_complete = isoc_irq_mmap; |
572 | nurbs = DEF_NURBS; | 575 | nurbs = DEF_NURBS; |
573 | } else { | 576 | } else { |
@@ -746,8 +749,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
746 | int i, j, index; | 749 | int i, j, index; |
747 | __u32 fmt_tb[8]; | 750 | __u32 fmt_tb[8]; |
748 | 751 | ||
749 | PDEBUG(D_CONF, "enum fmt cap"); | ||
750 | |||
751 | /* give an index to each format */ | 752 | /* give an index to each format */ |
752 | index = 0; | 753 | index = 0; |
753 | j = 0; | 754 | j = 0; |
@@ -792,14 +793,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
792 | fmt->fmt.pix.width = gspca_dev->width; | 793 | fmt->fmt.pix.width = gspca_dev->width; |
793 | fmt->fmt.pix.height = gspca_dev->height; | 794 | fmt->fmt.pix.height = gspca_dev->height; |
794 | fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; | 795 | fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; |
795 | #ifdef VIDEO_ADV_DEBUG | ||
796 | if (gspca_debug & D_CONF) { | ||
797 | PDEBUG_MODE("get fmt cap", | ||
798 | fmt->fmt.pix.pixelformat, | ||
799 | fmt->fmt.pix.width, | ||
800 | fmt->fmt.pix.height); | ||
801 | } | ||
802 | #endif | ||
803 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | 796 | fmt->fmt.pix.field = V4L2_FIELD_NONE; |
804 | fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat) | 797 | fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat) |
805 | * fmt->fmt.pix.width / 8; | 798 | * fmt->fmt.pix.width / 8; |
@@ -894,13 +887,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
894 | return 0; | 887 | return 0; |
895 | } | 888 | } |
896 | #endif | 889 | #endif |
897 | #ifdef VIDEO_ADV_DEBUG | ||
898 | if (gspca_debug & D_CONF) { | ||
899 | PDEBUG_MODE("set fmt cap", | ||
900 | fmt->fmt.pix.pixelformat, | ||
901 | fmt->fmt.pix.width, fmt->fmt.pix.height); | ||
902 | } | ||
903 | #endif | ||
904 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 890 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
905 | return -ERESTARTSYS; | 891 | return -ERESTARTSYS; |
906 | 892 | ||
@@ -1013,7 +999,6 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
1013 | { | 999 | { |
1014 | struct gspca_dev *gspca_dev = priv; | 1000 | struct gspca_dev *gspca_dev = priv; |
1015 | 1001 | ||
1016 | PDEBUG(D_CONF, "querycap"); | ||
1017 | memset(cap, 0, sizeof *cap); | 1002 | memset(cap, 0, sizeof *cap); |
1018 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); | 1003 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); |
1019 | strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); | 1004 | 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 | struct ctrl *ctrls; | 1056 | struct ctrl *ctrls; |
1072 | int i, ret; | 1057 | int i, ret; |
1073 | 1058 | ||
1074 | PDEBUG(D_CONF, "set ctrl"); | ||
1075 | for (i = 0, ctrls = gspca_dev->sd_desc->ctrls; | 1059 | for (i = 0, ctrls = gspca_dev->sd_desc->ctrls; |
1076 | i < gspca_dev->sd_desc->nctrls; | 1060 | i < gspca_dev->sd_desc->nctrls; |
1077 | i++, ctrls++) { | 1061 | i++, ctrls++) { |
@@ -1155,7 +1139,6 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1155 | struct gspca_dev *gspca_dev = priv; | 1139 | struct gspca_dev *gspca_dev = priv; |
1156 | int i, ret = 0; | 1140 | int i, ret = 0; |
1157 | 1141 | ||
1158 | PDEBUG(D_STREAM, "reqbufs %d", rb->count); | ||
1159 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1142 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1160 | return -EINVAL; | 1143 | return -EINVAL; |
1161 | switch (rb->memory) { | 1144 | switch (rb->memory) { |
@@ -1205,7 +1188,6 @@ static int vidioc_querybuf(struct file *file, void *priv, | |||
1205 | struct gspca_dev *gspca_dev = priv; | 1188 | struct gspca_dev *gspca_dev = priv; |
1206 | struct gspca_frame *frame; | 1189 | struct gspca_frame *frame; |
1207 | 1190 | ||
1208 | PDEBUG(D_STREAM, "querybuf"); | ||
1209 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE | 1191 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE |
1210 | || v4l2_buf->index < 0 | 1192 | || v4l2_buf->index < 0 |
1211 | || v4l2_buf->index >= gspca_dev->nframes) | 1193 | || v4l2_buf->index >= gspca_dev->nframes) |
@@ -1222,7 +1204,6 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
1222 | struct gspca_dev *gspca_dev = priv; | 1204 | struct gspca_dev *gspca_dev = priv; |
1223 | int ret; | 1205 | int ret; |
1224 | 1206 | ||
1225 | PDEBUG(D_STREAM, "stream on"); | ||
1226 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1207 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1227 | return -EINVAL; | 1208 | return -EINVAL; |
1228 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1209 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
@@ -1264,7 +1245,6 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1264 | struct gspca_dev *gspca_dev = priv; | 1245 | struct gspca_dev *gspca_dev = priv; |
1265 | int ret; | 1246 | int ret; |
1266 | 1247 | ||
1267 | PDEBUG(D_STREAM, "stream off"); | ||
1268 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1248 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1269 | return -EINVAL; | 1249 | return -EINVAL; |
1270 | if (!gspca_dev->streaming) | 1250 | if (!gspca_dev->streaming) |
@@ -1499,8 +1479,10 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1499 | i = gspca_dev->fr_o; | 1479 | i = gspca_dev->fr_o; |
1500 | j = gspca_dev->fr_queue[i]; | 1480 | j = gspca_dev->fr_queue[i]; |
1501 | frame = &gspca_dev->frame[j]; | 1481 | frame = &gspca_dev->frame[j]; |
1502 | if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) | 1482 | if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) { |
1483 | atomic_dec(&gspca_dev->nevent); | ||
1503 | goto ok; | 1484 | goto ok; |
1485 | } | ||
1504 | if (nonblock_ing) /* no frame yet */ | 1486 | if (nonblock_ing) /* no frame yet */ |
1505 | return -EAGAIN; | 1487 | return -EAGAIN; |
1506 | 1488 | ||
@@ -1511,9 +1493,10 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1511 | msecs_to_jiffies(3000)); | 1493 | msecs_to_jiffies(3000)); |
1512 | if (ret <= 0) { | 1494 | if (ret <= 0) { |
1513 | if (ret < 0) | 1495 | if (ret < 0) |
1514 | return ret; | 1496 | return ret; /* interrupt */ |
1515 | return -EIO; | 1497 | return -EIO; /* timeout */ |
1516 | } | 1498 | } |
1499 | atomic_dec(&gspca_dev->nevent); | ||
1517 | if (!gspca_dev->streaming || !gspca_dev->present) | 1500 | if (!gspca_dev->streaming || !gspca_dev->present) |
1518 | return -EIO; | 1501 | return -EIO; |
1519 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR) | 1502 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR) |
@@ -1525,7 +1508,6 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1525 | break; | 1508 | break; |
1526 | } | 1509 | } |
1527 | ok: | 1510 | ok: |
1528 | atomic_dec(&gspca_dev->nevent); | ||
1529 | gspca_dev->fr_o = (i + 1) % gspca_dev->nframes; | 1511 | gspca_dev->fr_o = (i + 1) % gspca_dev->nframes; |
1530 | PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d", | 1512 | PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d", |
1531 | gspca_dev->fr_q, | 1513 | gspca_dev->fr_q, |
@@ -1725,7 +1707,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) | |||
1725 | goto out; | 1707 | goto out; |
1726 | } | 1708 | } |
1727 | 1709 | ||
1728 | /* if not mmap, treat the awaiting URBs */ | 1710 | /* if userptr, treat the awaiting URBs */ |
1729 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR | 1711 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR |
1730 | && gspca_dev->capt_file == file) | 1712 | && gspca_dev->capt_file == file) |
1731 | isoc_transfer(gspca_dev); | 1713 | isoc_transfer(gspca_dev); |
@@ -1748,7 +1730,7 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1748 | struct gspca_frame *frame; | 1730 | struct gspca_frame *frame; |
1749 | struct v4l2_buffer v4l2_buf; | 1731 | struct v4l2_buffer v4l2_buf; |
1750 | struct timeval timestamp; | 1732 | struct timeval timestamp; |
1751 | int i, ret, ret2; | 1733 | int n, ret, ret2; |
1752 | 1734 | ||
1753 | PDEBUG(D_FRAM, "read (%d)", count); | 1735 | PDEBUG(D_FRAM, "read (%d)", count); |
1754 | if (!gspca_dev->present) | 1736 | if (!gspca_dev->present) |
@@ -1760,9 +1742,9 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1760 | return ret; | 1742 | return ret; |
1761 | break; | 1743 | break; |
1762 | case GSPCA_MEMORY_READ: | 1744 | case GSPCA_MEMORY_READ: |
1763 | if (gspca_dev->capt_file != file) | 1745 | if (gspca_dev->capt_file == file) |
1764 | return -EINVAL; | 1746 | break; |
1765 | break; | 1747 | /* fall thru */ |
1766 | default: | 1748 | default: |
1767 | return -EINVAL; | 1749 | return -EINVAL; |
1768 | } | 1750 | } |
@@ -1770,7 +1752,8 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1770 | /* get a frame */ | 1752 | /* get a frame */ |
1771 | jiffies_to_timeval(get_jiffies_64(), ×tamp); | 1753 | jiffies_to_timeval(get_jiffies_64(), ×tamp); |
1772 | timestamp.tv_sec--; | 1754 | timestamp.tv_sec--; |
1773 | for (i = 0; i < 2; i++) { | 1755 | n = 2; |
1756 | for (;;) { | ||
1774 | memset(&v4l2_buf, 0, sizeof v4l2_buf); | 1757 | memset(&v4l2_buf, 0, sizeof v4l2_buf); |
1775 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1758 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1776 | v4l2_buf.memory = V4L2_MEMORY_MMAP; | 1759 | v4l2_buf.memory = V4L2_MEMORY_MMAP; |
@@ -1781,8 +1764,10 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1781 | } | 1764 | } |
1782 | 1765 | ||
1783 | /* if the process slept for more than 1 second, | 1766 | /* if the process slept for more than 1 second, |
1784 | * get a brand new frame */ | 1767 | * get anewer frame */ |
1785 | frame = &gspca_dev->frame[v4l2_buf.index]; | 1768 | frame = &gspca_dev->frame[v4l2_buf.index]; |
1769 | if (--n < 0) | ||
1770 | break; /* avoid infinite loop */ | ||
1786 | if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec) | 1771 | if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec) |
1787 | break; | 1772 | break; |
1788 | ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); | 1773 | ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); |