diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-05-04 05:46:21 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:14:40 -0400 |
commit | 4aa0d037a6c8e6b37ecfd986a444f83190c32a21 (patch) | |
tree | 37ec7366de97498236b82048e7c10e0d6ebe22e2 | |
parent | e2997a72ddfafc25bd0c8f1f52bcf41979d5a559 (diff) |
V4L/DVB (8154): Fix protection problems in the main driver.
- Protect format change when streaming active.
- Protect USB exchanges on close.
- Set a timeout in frame wait.
- Have only one capture file and free the resources when closing this file.
- Simplify the URB buffer.
- Don't reset the control values at open time in pac207.
- Fix compilation warnings of stk014.
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 | 163 | ||||
-rw-r--r-- | drivers/media/video/gspca/gspca.h | 16 | ||||
-rw-r--r-- | drivers/media/video/gspca/pac207.c | 11 | ||||
-rw-r--r-- | drivers/media/video/gspca/stk014.c | 7 |
4 files changed, 113 insertions, 84 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index c4735e133611..04dbaba4b78f 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -39,8 +39,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
39 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 39 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
40 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
41 | 41 | ||
42 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 30) | 42 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 1) |
43 | static const char version[] = "0.0.30"; | 43 | static const char version[] = "0.1.1"; |
44 | 44 | ||
45 | static int video_nr = -1; | 45 | static int video_nr = -1; |
46 | 46 | ||
@@ -346,22 +346,17 @@ static int gspca_kill_transfer(struct gspca_dev *gspca_dev) | |||
346 | 346 | ||
347 | PDEBUG(D_STREAM, "kill transfer"); | 347 | PDEBUG(D_STREAM, "kill transfer"); |
348 | for (i = 0; i < NURBS; ++i) { | 348 | for (i = 0; i < NURBS; ++i) { |
349 | urb = gspca_dev->pktbuf[i].urb; | 349 | urb = gspca_dev->urb[i]; |
350 | if (urb == NULL) | 350 | if (urb == NULL) |
351 | continue; | 351 | continue; |
352 | 352 | ||
353 | gspca_dev->pktbuf[i].urb = NULL; | 353 | gspca_dev->urb[i] = NULL; |
354 | usb_kill_urb(urb); | 354 | usb_kill_urb(urb); |
355 | 355 | if (urb->transfer_buffer != 0) | |
356 | /* urb->transfer_buffer_length is not touched by USB core, | ||
357 | * so we can use it here as the buffer length */ | ||
358 | if (gspca_dev->pktbuf[i].data) { | ||
359 | usb_buffer_free(gspca_dev->dev, | 356 | usb_buffer_free(gspca_dev->dev, |
360 | urb->transfer_buffer_length, | 357 | urb->transfer_buffer_length, |
361 | gspca_dev->pktbuf[i].data, | 358 | urb->transfer_buffer, |
362 | urb->transfer_dma); | 359 | urb->transfer_dma); |
363 | gspca_dev->pktbuf[i].data = NULL; | ||
364 | } | ||
365 | usb_free_urb(urb); | 360 | usb_free_urb(urb); |
366 | } | 361 | } |
367 | return 0; | 362 | return 0; |
@@ -460,25 +455,25 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
460 | err("usb_alloc_urb failed"); | 455 | err("usb_alloc_urb failed"); |
461 | return -ENOMEM; | 456 | return -ENOMEM; |
462 | } | 457 | } |
463 | gspca_dev->pktbuf[n].data = usb_buffer_alloc(gspca_dev->dev, | 458 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, |
464 | bsize, | 459 | bsize, |
465 | GFP_KERNEL, | 460 | GFP_KERNEL, |
466 | &urb->transfer_dma); | 461 | &urb->transfer_dma); |
467 | 462 | ||
468 | if (gspca_dev->pktbuf[n].data == NULL) { | 463 | if (urb->transfer_buffer == NULL) { |
469 | usb_free_urb(urb); | 464 | usb_free_urb(urb); |
470 | gspca_kill_transfer(gspca_dev); | 465 | gspca_kill_transfer(gspca_dev); |
471 | err("usb_buffer_urb failed"); | 466 | err("usb_buffer_urb failed"); |
472 | return -ENOMEM; | 467 | return -ENOMEM; |
473 | } | 468 | } |
474 | gspca_dev->pktbuf[n].urb = urb; | 469 | gspca_dev->urb[n] = urb; |
475 | urb->dev = gspca_dev->dev; | 470 | urb->dev = gspca_dev->dev; |
476 | urb->context = gspca_dev; | 471 | urb->context = gspca_dev; |
477 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, | 472 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, |
478 | ep->desc.bEndpointAddress); | 473 | ep->desc.bEndpointAddress); |
479 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | 474 | urb->transfer_flags = URB_ISO_ASAP |
475 | | URB_NO_TRANSFER_DMA_MAP; | ||
480 | urb->interval = ep->desc.bInterval; | 476 | urb->interval = ep->desc.bInterval; |
481 | urb->transfer_buffer = gspca_dev->pktbuf[n].data; | ||
482 | urb->complete = isoc_irq; | 477 | urb->complete = isoc_irq; |
483 | urb->number_of_packets = npkt; | 478 | urb->number_of_packets = npkt; |
484 | urb->transfer_buffer_length = bsize; | 479 | urb->transfer_buffer_length = bsize; |
@@ -523,8 +518,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
523 | 518 | ||
524 | /* submit the URBs */ | 519 | /* submit the URBs */ |
525 | for (n = 0; n < NURBS; n++) { | 520 | for (n = 0; n < NURBS; n++) { |
526 | ret = usb_submit_urb(gspca_dev->pktbuf[n].urb, | 521 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); |
527 | GFP_KERNEL); | ||
528 | if (ret < 0) { | 522 | if (ret < 0) { |
529 | PDEBUG(D_ERR|D_STREAM, | 523 | PDEBUG(D_ERR|D_STREAM, |
530 | "usb_submit_urb [%d] err %d", n, ret); | 524 | "usb_submit_urb [%d] err %d", n, ret); |
@@ -732,15 +726,13 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv, | |||
732 | return 0; | 726 | return 0; |
733 | } | 727 | } |
734 | 728 | ||
735 | static int try_fmt_cap(struct file *file, | 729 | static int try_fmt_cap(struct gspca_dev *gspca_dev, |
736 | void *priv, | ||
737 | struct v4l2_format *fmt) | 730 | struct v4l2_format *fmt) |
738 | { | 731 | { |
739 | struct gspca_dev *gspca_dev = priv; | ||
740 | int w, h, mode, mode2, frsz; | 732 | int w, h, mode, mode2, frsz; |
741 | 733 | ||
742 | w = (int) fmt->fmt.pix.width; | 734 | w = fmt->fmt.pix.width; |
743 | h = (int) fmt->fmt.pix.height; | 735 | h = fmt->fmt.pix.height; |
744 | #ifdef GSPCA_DEBUG | 736 | #ifdef GSPCA_DEBUG |
745 | if (gspca_debug & D_CONF) | 737 | if (gspca_debug & D_CONF) |
746 | PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); | 738 | PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); |
@@ -786,9 +778,10 @@ static int vidioc_try_fmt_cap(struct file *file, | |||
786 | void *priv, | 778 | void *priv, |
787 | struct v4l2_format *fmt) | 779 | struct v4l2_format *fmt) |
788 | { | 780 | { |
781 | struct gspca_dev *gspca_dev = priv; | ||
789 | int ret; | 782 | int ret; |
790 | 783 | ||
791 | ret = try_fmt_cap(file, priv, fmt); | 784 | ret = try_fmt_cap(gspca_dev, fmt); |
792 | if (ret < 0) | 785 | if (ret < 0) |
793 | return ret; | 786 | return ret; |
794 | return 0; | 787 | return 0; |
@@ -809,14 +802,19 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, | |||
809 | #endif | 802 | #endif |
810 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 803 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
811 | return -ERESTARTSYS; | 804 | return -ERESTARTSYS; |
812 | ret = try_fmt_cap(file, priv, fmt); | 805 | ret = try_fmt_cap(gspca_dev, fmt); |
813 | if (ret < 0) | 806 | if (ret < 0) |
814 | goto out; | 807 | goto out; |
815 | 808 | ||
816 | if (ret == gspca_dev->curr_mode) | 809 | if (ret == gspca_dev->curr_mode) |
817 | goto out; /* same mode */ | 810 | goto out; /* same mode */ |
818 | was_streaming = gspca_dev->streaming; | 811 | was_streaming = gspca_dev->streaming; |
819 | if (was_streaming != 0) { | 812 | if (was_streaming) { |
813 | if (gspca_dev->capt_file != 0 | ||
814 | && gspca_dev->capt_file != file) { | ||
815 | ret = -EBUSY; | ||
816 | goto out; | ||
817 | } | ||
820 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { | 818 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { |
821 | ret = -ERESTARTSYS; | 819 | ret = -ERESTARTSYS; |
822 | goto out; | 820 | goto out; |
@@ -824,8 +822,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, | |||
824 | gspca_stream_off(gspca_dev); | 822 | gspca_stream_off(gspca_dev); |
825 | mutex_unlock(&gspca_dev->usb_lock); | 823 | mutex_unlock(&gspca_dev->usb_lock); |
826 | } | 824 | } |
827 | gspca_dev->width = (int) fmt->fmt.pix.width; | 825 | gspca_dev->width = fmt->fmt.pix.width; |
828 | gspca_dev->height = (int) fmt->fmt.pix.height; | 826 | gspca_dev->height = fmt->fmt.pix.height; |
829 | gspca_dev->pixfmt = fmt->fmt.pix.pixelformat; | 827 | gspca_dev->pixfmt = fmt->fmt.pix.pixelformat; |
830 | gspca_dev->curr_mode = ret; | 828 | gspca_dev->curr_mode = ret; |
831 | if (was_streaming) | 829 | if (was_streaming) |
@@ -891,17 +889,18 @@ static int dev_close(struct inode *inode, struct file *file) | |||
891 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 889 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
892 | return -ERESTARTSYS; | 890 | return -ERESTARTSYS; |
893 | gspca_dev->users--; | 891 | gspca_dev->users--; |
894 | if (gspca_dev->users > 0) { | ||
895 | mutex_unlock(&gspca_dev->queue_lock); | ||
896 | return 0; | ||
897 | } | ||
898 | 892 | ||
899 | if (gspca_dev->streaming) | 893 | /* if the file did capture, free the streaming resources */ |
900 | gspca_stream_off(gspca_dev); | 894 | if (gspca_dev->capt_file == file) { |
901 | gspca_dev->sd_desc->close(gspca_dev); | 895 | mutex_lock(&gspca_dev->usb_lock); |
902 | 896 | if (gspca_dev->streaming) | |
903 | frame_free(gspca_dev); | 897 | gspca_stream_off(gspca_dev); |
904 | file->private_data = NULL; | 898 | gspca_dev->sd_desc->close(gspca_dev); |
899 | mutex_unlock(&gspca_dev->usb_lock); | ||
900 | frame_free(gspca_dev); | ||
901 | file->private_data = NULL; | ||
902 | gspca_dev->capt_file = 0; | ||
903 | } | ||
905 | mutex_unlock(&gspca_dev->queue_lock); | 904 | mutex_unlock(&gspca_dev->queue_lock); |
906 | PDEBUG(D_STREAM, "closed"); | 905 | PDEBUG(D_STREAM, "closed"); |
907 | return 0; | 906 | return 0; |
@@ -1052,12 +1051,19 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1052 | return frsz; | 1051 | return frsz; |
1053 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1052 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1054 | return -ERESTARTSYS; | 1053 | return -ERESTARTSYS; |
1054 | if (gspca_dev->capt_file != 0) { /* only one file may do capture */ | ||
1055 | ret = -EBUSY; | ||
1056 | goto out; | ||
1057 | } | ||
1055 | ret = frame_alloc(gspca_dev, | 1058 | ret = frame_alloc(gspca_dev, |
1056 | rb->count, | 1059 | rb->count, |
1057 | (unsigned int) frsz, | 1060 | (unsigned int) frsz, |
1058 | rb->memory); | 1061 | rb->memory); |
1059 | if (ret == 0) | 1062 | if (ret == 0) { |
1060 | rb->count = gspca_dev->nframes; | 1063 | rb->count = gspca_dev->nframes; |
1064 | gspca_dev->capt_file = file; | ||
1065 | } | ||
1066 | out: | ||
1061 | mutex_unlock(&gspca_dev->queue_lock); | 1067 | mutex_unlock(&gspca_dev->queue_lock); |
1062 | PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count); | 1068 | PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count); |
1063 | return ret; | 1069 | return ret; |
@@ -1099,6 +1105,10 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
1099 | ret = -EINVAL; | 1105 | ret = -EINVAL; |
1100 | goto out; | 1106 | goto out; |
1101 | } | 1107 | } |
1108 | if (gspca_dev->capt_file != file) { | ||
1109 | ret = -EINVAL; | ||
1110 | goto out; | ||
1111 | } | ||
1102 | if (!gspca_dev->streaming) { | 1112 | if (!gspca_dev->streaming) { |
1103 | ret = gspca_init_transfer(gspca_dev); | 1113 | ret = gspca_init_transfer(gspca_dev); |
1104 | if (ret < 0) | 1114 | if (ret < 0) |
@@ -1122,22 +1132,30 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1122 | enum v4l2_buf_type buf_type) | 1132 | enum v4l2_buf_type buf_type) |
1123 | { | 1133 | { |
1124 | struct gspca_dev *gspca_dev = priv; | 1134 | struct gspca_dev *gspca_dev = priv; |
1135 | int ret; | ||
1125 | 1136 | ||
1126 | PDEBUG(D_STREAM, "stream off"); | 1137 | PDEBUG(D_STREAM, "stream off"); |
1127 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1138 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1128 | return -EINVAL; | 1139 | return -EINVAL; |
1129 | if (gspca_dev->streaming) { | 1140 | if (!gspca_dev->streaming) |
1130 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1141 | return 0; |
1131 | return -ERESTARTSYS; | 1142 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1132 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { | 1143 | return -ERESTARTSYS; |
1133 | mutex_unlock(&gspca_dev->queue_lock); | 1144 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { |
1134 | return -ERESTARTSYS; | 1145 | ret = -ERESTARTSYS; |
1135 | } | 1146 | goto out; |
1136 | gspca_stream_off(gspca_dev); | ||
1137 | mutex_unlock(&gspca_dev->usb_lock); | ||
1138 | mutex_unlock(&gspca_dev->queue_lock); | ||
1139 | } | 1147 | } |
1140 | return 0; | 1148 | if (gspca_dev->capt_file != file) { |
1149 | ret = -EINVAL; | ||
1150 | goto out2; | ||
1151 | } | ||
1152 | gspca_stream_off(gspca_dev); | ||
1153 | ret = 0; | ||
1154 | out2: | ||
1155 | mutex_unlock(&gspca_dev->usb_lock); | ||
1156 | out: | ||
1157 | mutex_unlock(&gspca_dev->queue_lock); | ||
1158 | return ret; | ||
1141 | } | 1159 | } |
1142 | 1160 | ||
1143 | static int vidioc_g_jpegcomp(struct file *file, void *priv, | 1161 | static int vidioc_g_jpegcomp(struct file *file, void *priv, |
@@ -1187,14 +1205,11 @@ static int vidioc_s_parm(struct file *filp, void *priv, | |||
1187 | struct gspca_dev *gspca_dev = priv; | 1205 | struct gspca_dev *gspca_dev = priv; |
1188 | int n; | 1206 | int n; |
1189 | 1207 | ||
1190 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1191 | return -ERESTARTSYS; | ||
1192 | n = parm->parm.capture.readbuffers; | 1208 | n = parm->parm.capture.readbuffers; |
1193 | if (n == 0 || n > GSPCA_MAX_FRAMES) | 1209 | if (n == 0 || n > GSPCA_MAX_FRAMES) |
1194 | parm->parm.capture.readbuffers = gspca_dev->nbufread; | 1210 | parm->parm.capture.readbuffers = gspca_dev->nbufread; |
1195 | else | 1211 | else |
1196 | gspca_dev->nbufread = n; | 1212 | gspca_dev->nbufread = n; |
1197 | mutex_unlock(&gspca_dev->usb_lock); | ||
1198 | return 0; | 1213 | return 0; |
1199 | } | 1214 | } |
1200 | 1215 | ||
@@ -1245,7 +1260,11 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1245 | return -ERESTARTSYS; | 1260 | return -ERESTARTSYS; |
1246 | if (!gspca_dev->present) { | 1261 | if (!gspca_dev->present) { |
1247 | ret = -ENODEV; | 1262 | ret = -ENODEV; |
1248 | goto done; | 1263 | goto out; |
1264 | } | ||
1265 | if (gspca_dev->capt_file != file) { | ||
1266 | ret = -EINVAL; | ||
1267 | goto out; | ||
1249 | } | 1268 | } |
1250 | 1269 | ||
1251 | for (i = 0; i < gspca_dev->nframes; ++i) { | 1270 | for (i = 0; i < gspca_dev->nframes; ++i) { |
@@ -1262,7 +1281,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1262 | if (frame == 0) { | 1281 | if (frame == 0) { |
1263 | PDEBUG(D_STREAM, "mmap no frame buffer found"); | 1282 | PDEBUG(D_STREAM, "mmap no frame buffer found"); |
1264 | ret = -EINVAL; | 1283 | ret = -EINVAL; |
1265 | goto done; | 1284 | goto out; |
1266 | } | 1285 | } |
1267 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1286 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1268 | if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes) | 1287 | if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes) |
@@ -1272,7 +1291,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1272 | if (size != frame->v4l2_buf.length) { | 1291 | if (size != frame->v4l2_buf.length) { |
1273 | PDEBUG(D_STREAM, "mmap bad size"); | 1292 | PDEBUG(D_STREAM, "mmap bad size"); |
1274 | ret = -EINVAL; | 1293 | ret = -EINVAL; |
1275 | goto done; | 1294 | goto out; |
1276 | } | 1295 | } |
1277 | 1296 | ||
1278 | /* | 1297 | /* |
@@ -1286,7 +1305,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1286 | page = vmalloc_to_page((void *) addr); | 1305 | page = vmalloc_to_page((void *) addr); |
1287 | ret = vm_insert_page(vma, start, page); | 1306 | ret = vm_insert_page(vma, start, page); |
1288 | if (ret < 0) | 1307 | if (ret < 0) |
1289 | goto done; | 1308 | goto out; |
1290 | start += PAGE_SIZE; | 1309 | start += PAGE_SIZE; |
1291 | addr += PAGE_SIZE; | 1310 | addr += PAGE_SIZE; |
1292 | size -= PAGE_SIZE; | 1311 | size -= PAGE_SIZE; |
@@ -1304,7 +1323,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1304 | } | 1323 | } |
1305 | #endif | 1324 | #endif |
1306 | ret = 0; | 1325 | ret = 0; |
1307 | done: | 1326 | out: |
1308 | mutex_unlock(&gspca_dev->queue_lock); | 1327 | mutex_unlock(&gspca_dev->queue_lock); |
1309 | return ret; | 1328 | return ret; |
1310 | } | 1329 | } |
@@ -1356,10 +1375,14 @@ static int gspca_frame_wait(struct gspca_dev *gspca_dev, | |||
1356 | 1375 | ||
1357 | /* wait till a frame is ready */ | 1376 | /* wait till a frame is ready */ |
1358 | for (;;) { | 1377 | for (;;) { |
1359 | ret = wait_event_interruptible(gspca_dev->wq, | 1378 | ret = wait_event_interruptible_timeout(gspca_dev->wq, |
1360 | atomic_read(&gspca_dev->nevent) > 0); | 1379 | atomic_read(&gspca_dev->nevent) > 0, |
1361 | if (ret != 0) | 1380 | msecs_to_jiffies(3000)); |
1362 | return ret; | 1381 | if (ret <= 0) { |
1382 | if (ret < 0) | ||
1383 | return ret; | ||
1384 | return -EIO; | ||
1385 | } | ||
1363 | if (!gspca_dev->streaming || !gspca_dev->present) | 1386 | if (!gspca_dev->streaming || !gspca_dev->present) |
1364 | return -EIO; | 1387 | return -EIO; |
1365 | i = gspca_dev->fr_o; | 1388 | i = gspca_dev->fr_o; |
@@ -1402,6 +1425,10 @@ static int vidioc_dqbuf(struct file *file, void *priv, | |||
1402 | return -EINVAL; | 1425 | return -EINVAL; |
1403 | if (!gspca_dev->streaming) | 1426 | if (!gspca_dev->streaming) |
1404 | return -EINVAL; | 1427 | return -EINVAL; |
1428 | if (gspca_dev->capt_file != file) { | ||
1429 | ret = -EINVAL; | ||
1430 | goto out; | ||
1431 | } | ||
1405 | 1432 | ||
1406 | /* only one read */ | 1433 | /* only one read */ |
1407 | if (mutex_lock_interruptible(&gspca_dev->read_lock)) | 1434 | if (mutex_lock_interruptible(&gspca_dev->read_lock)) |
@@ -1409,14 +1436,14 @@ static int vidioc_dqbuf(struct file *file, void *priv, | |||
1409 | 1436 | ||
1410 | ret = gspca_frame_wait(gspca_dev, file->f_flags & O_NONBLOCK); | 1437 | ret = gspca_frame_wait(gspca_dev, file->f_flags & O_NONBLOCK); |
1411 | if (ret < 0) | 1438 | if (ret < 0) |
1412 | goto done; | 1439 | goto out; |
1413 | i = ret; /* frame index */ | 1440 | i = ret; /* frame index */ |
1414 | frame = &gspca_dev->frame[i]; | 1441 | frame = &gspca_dev->frame[i]; |
1415 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; | 1442 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; |
1416 | memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); | 1443 | memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); |
1417 | PDEBUG(D_FRAM, "dqbuf %d", i); | 1444 | PDEBUG(D_FRAM, "dqbuf %d", i); |
1418 | ret = 0; | 1445 | ret = 0; |
1419 | done: | 1446 | out: |
1420 | mutex_unlock(&gspca_dev->read_lock); | 1447 | mutex_unlock(&gspca_dev->read_lock); |
1421 | return ret; | 1448 | return ret; |
1422 | } | 1449 | } |
@@ -1450,6 +1477,8 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
1450 | PDEBUG(D_STREAM, "qbuf bad memory type"); | 1477 | PDEBUG(D_STREAM, "qbuf bad memory type"); |
1451 | return -EINVAL; | 1478 | return -EINVAL; |
1452 | } | 1479 | } |
1480 | if (gspca_dev->capt_file != file) | ||
1481 | return -EINVAL; | ||
1453 | 1482 | ||
1454 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1483 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1455 | return -ERESTARTSYS; | 1484 | return -ERESTARTSYS; |
@@ -1524,7 +1553,9 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1524 | return ret; | 1553 | return ret; |
1525 | } | 1554 | } |
1526 | } | 1555 | } |
1527 | } | 1556 | } else if (gspca_dev->capt_file != file) |
1557 | return -EINVAL; | ||
1558 | |||
1528 | if (!gspca_dev->streaming) { | 1559 | if (!gspca_dev->streaming) { |
1529 | ret = vidioc_streamon(file, gspca_dev, | 1560 | ret = vidioc_streamon(file, gspca_dev, |
1530 | V4L2_BUF_TYPE_VIDEO_CAPTURE); | 1561 | V4L2_BUF_TYPE_VIDEO_CAPTURE); |
@@ -1719,7 +1750,7 @@ EXPORT_SYMBOL(gspca_dev_probe); | |||
1719 | */ | 1750 | */ |
1720 | void gspca_disconnect(struct usb_interface *intf) | 1751 | void gspca_disconnect(struct usb_interface *intf) |
1721 | { | 1752 | { |
1722 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 1753 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
1723 | 1754 | ||
1724 | if (!gspca_dev) | 1755 | if (!gspca_dev) |
1725 | return; | 1756 | return; |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 3bfb3641cf36..c2618c0e6615 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -108,11 +108,6 @@ struct sd_desc { | |||
108 | cam_qmnu_op querymenu; | 108 | cam_qmnu_op querymenu; |
109 | }; | 109 | }; |
110 | 110 | ||
111 | struct gspca_pktbuf { | ||
112 | char *data; | ||
113 | struct urb *urb; | ||
114 | }; | ||
115 | |||
116 | /* packet types when moving from iso buf to frame buf */ | 111 | /* packet types when moving from iso buf to frame buf */ |
117 | #define DISCARD_PACKET 0 | 112 | #define DISCARD_PACKET 0 |
118 | #define FIRST_PACKET 1 | 113 | #define FIRST_PACKET 1 |
@@ -121,19 +116,20 @@ struct gspca_pktbuf { | |||
121 | 116 | ||
122 | struct gspca_frame { | 117 | struct gspca_frame { |
123 | unsigned char *data; /* frame buffer */ | 118 | unsigned char *data; /* frame buffer */ |
124 | unsigned char *data_end; /* current end of frame while filling */ | 119 | unsigned char *data_end; /* end of frame while filling */ |
125 | int vma_use_count; | 120 | int vma_use_count; |
126 | struct v4l2_buffer v4l2_buf; | 121 | struct v4l2_buffer v4l2_buf; |
127 | }; | 122 | }; |
128 | 123 | ||
129 | struct gspca_dev { | 124 | struct gspca_dev { |
130 | struct video_device vdev; /* !! must be the first item */ | 125 | struct video_device vdev; /* !! must be the first item */ |
131 | struct usb_device *dev; | 126 | struct usb_device *dev; |
127 | struct file *capt_file; /* file doing video capture */ | ||
132 | 128 | ||
133 | struct cam cam; /* device information */ | 129 | struct cam cam; /* device information */ |
134 | const struct sd_desc *sd_desc; /* subdriver description */ | 130 | const struct sd_desc *sd_desc; /* subdriver description */ |
135 | 131 | ||
136 | struct gspca_pktbuf pktbuf[NURBS]; | 132 | struct urb *urb[NURBS]; |
137 | 133 | ||
138 | __u8 *frbuf; /* buffer for nframes */ | 134 | __u8 *frbuf; /* buffer for nframes */ |
139 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; | 135 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; |
@@ -147,7 +143,7 @@ struct gspca_dev { | |||
147 | 143 | ||
148 | __u8 iface; /* USB interface number */ | 144 | __u8 iface; /* USB interface number */ |
149 | __u8 alt; /* USB alternate setting */ | 145 | __u8 alt; /* USB alternate setting */ |
150 | char curr_mode; /* current camera mode */ | 146 | unsigned char curr_mode; /* current camera mode */ |
151 | __u32 pixfmt; /* current mode parameters */ | 147 | __u32 pixfmt; /* current mode parameters */ |
152 | short width; | 148 | short width; |
153 | short height; | 149 | short height; |
@@ -158,7 +154,7 @@ struct gspca_dev { | |||
158 | struct mutex read_lock; /* read protection */ | 154 | struct mutex read_lock; /* read protection */ |
159 | struct mutex queue_lock; /* ISOC queue protection */ | 155 | struct mutex queue_lock; /* ISOC queue protection */ |
160 | __u32 sequence; /* frame sequence number */ | 156 | __u32 sequence; /* frame sequence number */ |
161 | signed char streaming; | 157 | char streaming; |
162 | char users; /* # open */ | 158 | char users; /* # open */ |
163 | char present; /* device connected */ | 159 | char present; /* device connected */ |
164 | char nbufread; /* number of buffers for read() */ | 160 | char nbufread; /* number of buffers for read() */ |
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index ac16c7352892..57d48f51e3a0 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -27,8 +27,8 @@ | |||
27 | 27 | ||
28 | #include "gspca.h" | 28 | #include "gspca.h" |
29 | 29 | ||
30 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 30) | 30 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 1) |
31 | static const char version[] = "0.0.30"; | 31 | static const char version[] = "0.1.1"; |
32 | 32 | ||
33 | MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); | 33 | MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); |
34 | MODULE_DESCRIPTION("Pixart PAC207"); | 34 | MODULE_DESCRIPTION("Pixart PAC207"); |
@@ -251,6 +251,7 @@ int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index) | |||
251 | static int sd_config(struct gspca_dev *gspca_dev, | 251 | static int sd_config(struct gspca_dev *gspca_dev, |
252 | const struct usb_device_id *id) | 252 | const struct usb_device_id *id) |
253 | { | 253 | { |
254 | struct sd *sd = (struct sd *) gspca_dev; | ||
254 | struct cam *cam; | 255 | struct cam *cam; |
255 | u8 idreg[2]; | 256 | u8 idreg[2]; |
256 | 257 | ||
@@ -282,6 +283,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
282 | cam->epaddr = 0x05; | 283 | cam->epaddr = 0x05; |
283 | cam->cam_mode = sif_mode; | 284 | cam->cam_mode = sif_mode; |
284 | cam->nmodes = ARRAY_SIZE(sif_mode); | 285 | cam->nmodes = ARRAY_SIZE(sif_mode); |
286 | sd->brightness = PAC207_BRIGHTNESS_DEFAULT; | ||
287 | sd->exposure = PAC207_EXPOSURE_DEFAULT; | ||
288 | sd->gain = PAC207_GAIN_DEFAULT; | ||
285 | 289 | ||
286 | return 0; | 290 | return 0; |
287 | } | 291 | } |
@@ -291,9 +295,6 @@ static int sd_open(struct gspca_dev *gspca_dev) | |||
291 | { | 295 | { |
292 | struct sd *sd = (struct sd *) gspca_dev; | 296 | struct sd *sd = (struct sd *) gspca_dev; |
293 | 297 | ||
294 | sd->brightness = PAC207_BRIGHTNESS_DEFAULT; | ||
295 | sd->exposure = PAC207_EXPOSURE_DEFAULT; | ||
296 | sd->gain = PAC207_GAIN_DEFAULT; | ||
297 | sd->autogain = 1; | 298 | sd->autogain = 1; |
298 | 299 | ||
299 | return 0; | 300 | return 0; |
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 8fd4ff01362e..2e4cf64442ac 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -24,8 +24,8 @@ | |||
24 | #include "gspca.h" | 24 | #include "gspca.h" |
25 | #include "jpeg.h" | 25 | #include "jpeg.h" |
26 | 26 | ||
27 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 22) | 27 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) |
28 | static const char version[] = "0.0.22"; | 28 | static const char version[] = "0.1.0"; |
29 | 29 | ||
30 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 30 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); |
31 | MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); | 31 | MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); |
@@ -390,6 +390,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
390 | int len) /* iso packet length */ | 390 | int len) /* iso packet length */ |
391 | { | 391 | { |
392 | int l; | 392 | int l; |
393 | static unsigned char ffd9[] = {0xff, 0xd9}; | ||
393 | 394 | ||
394 | /* a frame starts with: | 395 | /* a frame starts with: |
395 | * - 0xff 0xfe | 396 | * - 0xff 0xfe |
@@ -445,7 +446,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
445 | if (len > frame->v4l2_buf.bytesused - 2 - l) | 446 | if (len > frame->v4l2_buf.bytesused - 2 - l) |
446 | len = frame->v4l2_buf.bytesused - 2 - l; | 447 | len = frame->v4l2_buf.bytesused - 2 - l; |
447 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 448 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); |
448 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, "\xff\xd9", 2); | 449 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, ffd9, 2); |
449 | } | 450 | } |
450 | 451 | ||
451 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 452 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |