aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-07-12 08:28:04 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:26:09 -0400
commit5b77ae7776183d733ec86727bcc34c52a336afd6 (patch)
treef7b71b30108e5397ad4e6277e7bb414c95e13df7
parent51fc8e3bc03aeddc557d3084d08425eb4cb8ed41 (diff)
V4L/DVB (8350): gspca: Conform to v4l2 spec and mutex unlock fix.
gspca: Empty the application queues on streamoff ioctl. streamon/off and qbuf ioctls may be done by any application. Don't handle MJPEG pixel format as JPEG. (thanks to Hans de Goede) Authorize reqbufs ioctl when streaming. Bad mutex unlock in poll() when streaming problem. (thanks to Mauro Carvalho Chehab) Don't handle 'webcam disconnected' in stream off. 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.c146
1 files changed, 74 insertions, 72 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 2ffb00ab0811..a566fd394895 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -42,8 +42,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
42MODULE_DESCRIPTION("GSPCA USB Camera Driver"); 42MODULE_DESCRIPTION("GSPCA USB Camera Driver");
43MODULE_LICENSE("GPL"); 43MODULE_LICENSE("GPL");
44 44
45#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 6) 45#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
46static const char version[] = "2.1.6"; 46static const char version[] = "2.1.7";
47 47
48static int video_nr = -1; 48static int video_nr = -1;
49 49
@@ -558,11 +558,6 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
558 gspca_set_alt0(gspca_dev); 558 gspca_set_alt0(gspca_dev);
559 gspca_dev->sd_desc->stop0(gspca_dev); 559 gspca_dev->sd_desc->stop0(gspca_dev);
560 PDEBUG(D_STREAM, "stream off OK"); 560 PDEBUG(D_STREAM, "stream off OK");
561 } else {
562 destroy_urbs(gspca_dev);
563 atomic_inc(&gspca_dev->nevent);
564 wake_up_interruptible(&gspca_dev->wq);
565 PDEBUG(D_ERR|D_STREAM, "stream off no device ??");
566 } 561 }
567} 562}
568 563
@@ -680,9 +675,6 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
680 w = fmt->fmt.pix.width; 675 w = fmt->fmt.pix.width;
681 h = fmt->fmt.pix.height; 676 h = fmt->fmt.pix.height;
682 677
683 /* (luvcview problem) */
684 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
685 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
686#ifdef CONFIG_VIDEO_ADV_DEBUG 678#ifdef CONFIG_VIDEO_ADV_DEBUG
687 if (gspca_debug & D_CONF) 679 if (gspca_debug & D_CONF)
688 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); 680 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
@@ -816,7 +808,7 @@ static int dev_close(struct inode *inode, struct file *file)
816 return -ERESTARTSYS; 808 return -ERESTARTSYS;
817 gspca_dev->users--; 809 gspca_dev->users--;
818 810
819 /* if the file did capture, free the streaming resources */ 811 /* if the file did the capture, free the streaming resources */
820 if (gspca_dev->capt_file == file) { 812 if (gspca_dev->capt_file == file) {
821 mutex_lock(&gspca_dev->usb_lock); 813 mutex_lock(&gspca_dev->usb_lock);
822 if (gspca_dev->streaming) 814 if (gspca_dev->streaming)
@@ -981,7 +973,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
981 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 973 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
982 return -EINVAL; 974 return -EINVAL;
983 switch (rb->memory) { 975 switch (rb->memory) {
984 case GSPCA_MEMORY_READ: 976 case GSPCA_MEMORY_READ: /* (internal call) */
985 case V4L2_MEMORY_MMAP: 977 case V4L2_MEMORY_MMAP:
986 case V4L2_MEMORY_USERPTR: 978 case V4L2_MEMORY_USERPTR:
987 break; 979 break;
@@ -991,33 +983,46 @@ static int vidioc_reqbufs(struct file *file, void *priv,
991 if (mutex_lock_interruptible(&gspca_dev->queue_lock)) 983 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
992 return -ERESTARTSYS; 984 return -ERESTARTSYS;
993 985
994 /* only one file may do capture */ 986 if (gspca_dev->memory != GSPCA_MEMORY_NO
995 if ((gspca_dev->capt_file != NULL && gspca_dev->capt_file != file) 987 && gspca_dev->memory != rb->memory) {
996 || gspca_dev->streaming) {
997 ret = -EBUSY; 988 ret = -EBUSY;
998 goto out; 989 goto out;
999 } 990 }
1000 991
1001 if (rb->count == 0) { /* unrequest */ 992 /* only one file may do the capture */
1002 for (i = 0; i < gspca_dev->nframes; i++) { 993 if (gspca_dev->capt_file != NULL
1003 if (gspca_dev->frame[i].vma_use_count) { 994 && gspca_dev->capt_file != file) {
1004 ret = -EBUSY; 995 ret = -EBUSY;
1005 goto out; 996 goto out;
1006 } 997 }
1007 } 998
1008 frame_free(gspca_dev); 999 /* if allocated, the buffers must not be mapped */
1009 gspca_dev->capt_file = NULL; 1000 for (i = 0; i < gspca_dev->nframes; i++) {
1010 } else { 1001 if (gspca_dev->frame[i].vma_use_count) {
1011 if (gspca_dev->nframes != 0) {
1012 ret = -EBUSY; 1002 ret = -EBUSY;
1013 goto out; 1003 goto out;
1014 } 1004 }
1015 gspca_dev->memory = rb->memory; 1005 }
1016 ret = frame_alloc(gspca_dev, rb->count); 1006
1017 if (ret == 0) { 1007 /* stop streaming */
1018 rb->count = gspca_dev->nframes; 1008 if (gspca_dev->streaming) {
1019 gspca_dev->capt_file = file; 1009 mutex_lock(&gspca_dev->usb_lock);
1020 } 1010 gspca_stream_off(gspca_dev);
1011 mutex_unlock(&gspca_dev->usb_lock);
1012 }
1013
1014 /* free the previous allocated buffers, if any */
1015 if (gspca_dev->nframes != 0) {
1016 frame_free(gspca_dev);
1017 gspca_dev->capt_file = NULL;
1018 }
1019 if (rb->count == 0) /* unrequest */
1020 goto out;
1021 gspca_dev->memory = rb->memory;
1022 ret = frame_alloc(gspca_dev, rb->count);
1023 if (ret == 0) {
1024 rb->count = gspca_dev->nframes;
1025 gspca_dev->capt_file = file;
1021 } 1026 }
1022out: 1027out:
1023 mutex_unlock(&gspca_dev->queue_lock); 1028 mutex_unlock(&gspca_dev->queue_lock);
@@ -1059,10 +1064,6 @@ static int vidioc_streamon(struct file *file, void *priv,
1059 ret = -EINVAL; 1064 ret = -EINVAL;
1060 goto out; 1065 goto out;
1061 } 1066 }
1062 if (gspca_dev->capt_file != file) {
1063 ret = -EINVAL;
1064 goto out;
1065 }
1066 if (!gspca_dev->streaming) { 1067 if (!gspca_dev->streaming) {
1067 ret = gspca_init_transfer(gspca_dev); 1068 ret = gspca_init_transfer(gspca_dev);
1068 if (ret < 0) 1069 if (ret < 0)
@@ -1086,7 +1087,7 @@ static int vidioc_streamoff(struct file *file, void *priv,
1086 enum v4l2_buf_type buf_type) 1087 enum v4l2_buf_type buf_type)
1087{ 1088{
1088 struct gspca_dev *gspca_dev = priv; 1089 struct gspca_dev *gspca_dev = priv;
1089 int ret; 1090 int i, ret;
1090 1091
1091 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1092 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1092 return -EINVAL; 1093 return -EINVAL;
@@ -1094,18 +1095,23 @@ static int vidioc_streamoff(struct file *file, void *priv,
1094 return 0; 1095 return 0;
1095 if (mutex_lock_interruptible(&gspca_dev->queue_lock)) 1096 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1096 return -ERESTARTSYS; 1097 return -ERESTARTSYS;
1098
1099 /* stop streaming */
1097 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { 1100 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1098 ret = -ERESTARTSYS; 1101 ret = -ERESTARTSYS;
1099 goto out; 1102 goto out;
1100 } 1103 }
1101 if (gspca_dev->capt_file != file) {
1102 ret = -EINVAL;
1103 goto out2;
1104 }
1105 gspca_stream_off(gspca_dev); 1104 gspca_stream_off(gspca_dev);
1106 ret = 0;
1107out2:
1108 mutex_unlock(&gspca_dev->usb_lock); 1105 mutex_unlock(&gspca_dev->usb_lock);
1106
1107 /* empty the application queues */
1108 for (i = 0; i < gspca_dev->nframes; i++)
1109 gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
1110 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
1111 gspca_dev->last_packet_type = DISCARD_PACKET;
1112 gspca_dev->sequence = 0;
1113 atomic_set(&gspca_dev->nevent, 0);
1114 ret = 0;
1109out: 1115out:
1110 mutex_unlock(&gspca_dev->queue_lock); 1116 mutex_unlock(&gspca_dev->queue_lock);
1111 return ret; 1117 return ret;
@@ -1364,14 +1370,17 @@ static int vidioc_dqbuf(struct file *file, void *priv,
1364 return -EINVAL; 1370 return -EINVAL;
1365 if (v4l2_buf->memory != gspca_dev->memory) 1371 if (v4l2_buf->memory != gspca_dev->memory)
1366 return -EINVAL; 1372 return -EINVAL;
1367 if (!gspca_dev->streaming) 1373
1374 /* if not streaming, be sure the application will not loop forever */
1375 if (!(file->f_flags & O_NONBLOCK)
1376 && !gspca_dev->streaming && gspca_dev->users == 1)
1368 return -EINVAL; 1377 return -EINVAL;
1369 if (gspca_dev->capt_file != file) {
1370 ret = -EINVAL;
1371 goto out;
1372 }
1373 1378
1374 /* only one read */ 1379 /* only the capturing file may dequeue */
1380 if (gspca_dev->capt_file != file)
1381 return -EINVAL;
1382
1383 /* only one dequeue / read at a time */
1375 if (mutex_lock_interruptible(&gspca_dev->read_lock)) 1384 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1376 return -ERESTARTSYS; 1385 return -ERESTARTSYS;
1377 1386
@@ -1416,24 +1425,23 @@ static int vidioc_qbuf(struct file *file, void *priv,
1416 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1425 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1417 return -EINVAL; 1426 return -EINVAL;
1418 1427
1428 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1429 return -ERESTARTSYS;
1430
1419 index = v4l2_buf->index; 1431 index = v4l2_buf->index;
1420 if ((unsigned) index >= gspca_dev->nframes) { 1432 if ((unsigned) index >= gspca_dev->nframes) {
1421 PDEBUG(D_FRAM, 1433 PDEBUG(D_FRAM,
1422 "qbuf idx %d >= %d", index, gspca_dev->nframes); 1434 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1423 return -EINVAL; 1435 ret = -EINVAL;
1436 goto out;
1424 } 1437 }
1425 frame = &gspca_dev->frame[index]; 1438 if (v4l2_buf->memory != gspca_dev->memory) {
1426
1427 if (v4l2_buf->memory != frame->v4l2_buf.memory) {
1428 PDEBUG(D_FRAM, "qbuf bad memory type"); 1439 PDEBUG(D_FRAM, "qbuf bad memory type");
1429 return -EINVAL; 1440 ret = -EINVAL;
1441 goto out;
1430 } 1442 }
1431 if (gspca_dev->capt_file != file)
1432 return -EINVAL;
1433
1434 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1435 return -ERESTARTSYS;
1436 1443
1444 frame = &gspca_dev->frame[index];
1437 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) { 1445 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1438 PDEBUG(D_FRAM, "qbuf bad state"); 1446 PDEBUG(D_FRAM, "qbuf bad state");
1439 ret = -EINVAL; 1447 ret = -EINVAL;
@@ -1492,9 +1500,6 @@ static int read_alloc(struct gspca_dev *gspca_dev,
1492 v4l2_buf.memory = GSPCA_MEMORY_READ; 1500 v4l2_buf.memory = GSPCA_MEMORY_READ;
1493 for (i = 0; i < gspca_dev->nbufread; i++) { 1501 for (i = 0; i < gspca_dev->nbufread; i++) {
1494 v4l2_buf.index = i; 1502 v4l2_buf.index = i;
1495/*fixme: ugly!*/
1496 gspca_dev->frame[i].v4l2_buf.flags |=
1497 V4L2_BUF_FLAG_MAPPED;
1498 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); 1503 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1499 if (ret != 0) { 1504 if (ret != 0) {
1500 PDEBUG(D_STREAM, "read qbuf err: %d", ret); 1505 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
@@ -1522,17 +1527,13 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
1522 if (!gspca_dev->present) 1527 if (!gspca_dev->present)
1523 return POLLERR; 1528 return POLLERR;
1524 1529
1525 /* if not streaming, the user would use read() */ 1530 /* if reqbufs is not done, the user would use read() */
1526 if (!gspca_dev->streaming) { 1531 if (gspca_dev->nframes == 0) {
1527 if (gspca_dev->memory != GSPCA_MEMORY_NO) { 1532 if (gspca_dev->memory != GSPCA_MEMORY_NO)
1528 ret = POLLERR; /* not the 1st time */ 1533 return POLLERR; /* not the 1st time */
1529 goto out;
1530 }
1531 ret = read_alloc(gspca_dev, file); 1534 ret = read_alloc(gspca_dev, file);
1532 if (ret != 0) { 1535 if (ret != 0)
1533 ret = POLLERR; 1536 return POLLERR;
1534 goto out;
1535 }
1536 } 1537 }
1537 1538
1538 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) 1539 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
@@ -1542,6 +1543,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
1542 goto out; 1543 goto out;
1543 } 1544 }
1544 1545
1546 /* check the next incoming buffer */
1545 i = gspca_dev->fr_o; 1547 i = gspca_dev->fr_o;
1546 i = gspca_dev->fr_queue[i]; 1548 i = gspca_dev->fr_queue[i];
1547 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE) 1549 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE)