diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-07-08 05:58:15 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:18:04 -0400 |
commit | ac0d6df69bc72eabda944fd14a958074dc08ca0c (patch) | |
tree | 28d452f1d5f4ca2316b8e1ad11c7476998567407 | |
parent | c41492c89a00630c7482eae25deaf9af91b73c98 (diff) |
V4L/DVB (8232): gspca: Change the USERPTR mechanism.
main: Change the packet copy mechanism for userptr.
Cannot do reqbufs ioctl when already done and count != 0.
Accept count < frame size in read().
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 | 202 | ||||
-rw-r--r-- | drivers/media/video/gspca/gspca.h | 2 |
2 files changed, 52 insertions, 152 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index cb0aeb0c0a45..77e5e4f4335b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -36,15 +36,14 @@ | |||
36 | #include "gspca.h" | 36 | #include "gspca.h" |
37 | 37 | ||
38 | /* global values */ | 38 | /* global values */ |
39 | #define DEF_NURBS 2 /* default number of URBs (mmap) */ | 39 | #define DEF_NURBS 2 /* default number of URBs */ |
40 | #define USR_NURBS 5 /* default number of URBs (userptr) */ | ||
41 | 40 | ||
42 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 41 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); |
43 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 42 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
44 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
45 | 44 | ||
46 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5) | 45 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 6) |
47 | static const char version[] = "2.1.5"; | 46 | static const char version[] = "2.1.6"; |
48 | 47 | ||
49 | static int video_nr = -1; | 48 | static int video_nr = -1; |
50 | 49 | ||
@@ -153,7 +152,6 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
153 | } | 152 | } |
154 | 153 | ||
155 | /* resubmit the URB */ | 154 | /* resubmit the URB */ |
156 | /*fixme: don't do that when userptr and too many URBs sent*/ | ||
157 | urb->status = 0; | 155 | urb->status = 0; |
158 | st = usb_submit_urb(urb, GFP_ATOMIC); | 156 | st = usb_submit_urb(urb, GFP_ATOMIC); |
159 | if (st < 0) | 157 | if (st < 0) |
@@ -163,18 +161,9 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
163 | /* | 161 | /* |
164 | * ISOC message interrupt from the USB device | 162 | * ISOC message interrupt from the USB device |
165 | * | 163 | * |
166 | * Analyse each packet and call the subdriver for copy | 164 | * Analyse each packet and call the subdriver for copy to the frame buffer. |
167 | * to the frame buffer. | ||
168 | * | ||
169 | * There are 2 functions: | ||
170 | * - the first one (isoc_irq_mmap) is used when the application | ||
171 | * buffers are mapped. The frame detection and copy is done | ||
172 | * at interrupt level. | ||
173 | * - the second one (isoc_irq_user) is used when the application | ||
174 | * buffers are in user space (userptr). The frame detection | ||
175 | * and copy is done by the application. | ||
176 | */ | 165 | */ |
177 | static void isoc_irq_mmap(struct urb *urb | 166 | static void isoc_irq(struct urb *urb |
178 | ) | 167 | ) |
179 | { | 168 | { |
180 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | 169 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; |
@@ -185,56 +174,11 @@ static void isoc_irq_mmap(struct urb *urb | |||
185 | fill_frame(gspca_dev, urb); | 174 | fill_frame(gspca_dev, urb); |
186 | } | 175 | } |
187 | 176 | ||
188 | static void isoc_irq_user(struct urb *urb | ||
189 | ) | ||
190 | { | ||
191 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
192 | int i; | ||
193 | |||
194 | PDEBUG(D_PACK, "isoc irq user"); | ||
195 | if (!gspca_dev->streaming) | ||
196 | return; | ||
197 | |||
198 | i = gspca_dev->urb_in % gspca_dev->nurbs; | ||
199 | if (urb != gspca_dev->urb[i]) { | ||
200 | PDEBUG(D_ERR|D_PACK, "urb out of sequence"); | ||
201 | return; /* should never occur */ | ||
202 | } | ||
203 | |||
204 | gspca_dev->urb_in++; | ||
205 | atomic_inc(&gspca_dev->nevent); /* new event */ | ||
206 | wake_up_interruptible(&gspca_dev->wq); | ||
207 | /*fixme: submit a new URBs until urb_in == urb_out (% nurbs)*/ | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * treat the isoc messages | ||
212 | * | ||
213 | * This routine is called by the application (case userptr). | ||
214 | */ | ||
215 | static void isoc_transfer(struct gspca_dev *gspca_dev) | ||
216 | { | ||
217 | struct urb *urb; | ||
218 | int i; | ||
219 | |||
220 | for (;;) { | ||
221 | i = gspca_dev->urb_out; | ||
222 | PDEBUG(D_PACK, "isoc transf i:%d o:%d", gspca_dev->urb_in, i); | ||
223 | if (i == gspca_dev->urb_in) /* isoc message to read */ | ||
224 | break; /* no (more) message */ | ||
225 | atomic_dec(&gspca_dev->nevent); | ||
226 | /*PDEBUG(D_PACK, "isoc_trf nevent: %d", atomic_read(&gspca_dev->nevent));*/ | ||
227 | gspca_dev->urb_out = i + 1; /* message treated */ | ||
228 | urb = gspca_dev->urb[i % gspca_dev->nurbs]; | ||
229 | fill_frame(gspca_dev, urb); | ||
230 | } | ||
231 | } | ||
232 | |||
233 | /* | 177 | /* |
234 | * add data to the current frame | 178 | * add data to the current frame |
235 | * | 179 | * |
236 | * This function is called by the subdrivers at interrupt level | 180 | * This function is called by the subdrivers at interrupt level. |
237 | * or user level. | 181 | * |
238 | * To build a frame, these ones must add | 182 | * To build a frame, these ones must add |
239 | * - one FIRST_PACKET | 183 | * - one FIRST_PACKET |
240 | * - 0 or many INTER_PACKETs | 184 | * - 0 or many INTER_PACKETs |
@@ -277,16 +221,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
277 | frame->v4l2_buf.length); | 221 | frame->v4l2_buf.length); |
278 | packet_type = DISCARD_PACKET; | 222 | packet_type = DISCARD_PACKET; |
279 | } else { | 223 | } else { |
280 | if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR) { | 224 | memcpy(frame->data_end, data, len); |
281 | memcpy(frame->data_end, data, len); | ||
282 | } else { | ||
283 | if (copy_to_user(frame->data_end, | ||
284 | data, len) != 0) { | ||
285 | PDEBUG(D_ERR|D_PACK, | ||
286 | "copy to user failed"); | ||
287 | packet_type = DISCARD_PACKET; | ||
288 | } | ||
289 | } | ||
290 | frame->data_end += len; | 225 | frame->data_end += len; |
291 | } | 226 | } |
292 | } | 227 | } |
@@ -333,7 +268,6 @@ static void *rvmalloc(unsigned long size) | |||
333 | /* size = PAGE_ALIGN(size); (already done) */ | 268 | /* size = PAGE_ALIGN(size); (already done) */ |
334 | mem = vmalloc_32(size); | 269 | mem = vmalloc_32(size); |
335 | if (mem != NULL) { | 270 | if (mem != NULL) { |
336 | memset(mem, 0, size); | ||
337 | adr = (unsigned long) mem; | 271 | adr = (unsigned long) mem; |
338 | while ((long) size > 0) { | 272 | while ((long) size > 0) { |
339 | SetPageReserved(vmalloc_to_page((void *) adr)); | 273 | SetPageReserved(vmalloc_to_page((void *) adr)); |
@@ -344,14 +278,12 @@ static void *rvmalloc(unsigned long size) | |||
344 | return mem; | 278 | return mem; |
345 | } | 279 | } |
346 | 280 | ||
347 | static void rvfree(void *mem, unsigned long size) | 281 | static void rvfree(void *mem, long size) |
348 | { | 282 | { |
349 | unsigned long adr; | 283 | unsigned long adr; |
350 | 284 | ||
351 | if (!mem) | ||
352 | return; | ||
353 | adr = (unsigned long) mem; | 285 | adr = (unsigned long) mem; |
354 | while ((long) size > 0) { | 286 | while (size > 0) { |
355 | ClearPageReserved(vmalloc_to_page((void *) adr)); | 287 | ClearPageReserved(vmalloc_to_page((void *) adr)); |
356 | adr += PAGE_SIZE; | 288 | adr += PAGE_SIZE; |
357 | size -= PAGE_SIZE; | 289 | size -= PAGE_SIZE; |
@@ -370,16 +302,13 @@ static int frame_alloc(struct gspca_dev *gspca_dev, | |||
370 | frsz = gspca_dev->cam.cam_mode[i].sizeimage; | 302 | frsz = gspca_dev->cam.cam_mode[i].sizeimage; |
371 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); | 303 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); |
372 | frsz = PAGE_ALIGN(frsz); | 304 | frsz = PAGE_ALIGN(frsz); |
373 | PDEBUG(D_STREAM, "new fr_sz: %d", frsz); | ||
374 | gspca_dev->frsz = frsz; | 305 | gspca_dev->frsz = frsz; |
375 | if (count > GSPCA_MAX_FRAMES) | 306 | if (count > GSPCA_MAX_FRAMES) |
376 | count = GSPCA_MAX_FRAMES; | 307 | count = GSPCA_MAX_FRAMES; |
377 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) { | 308 | gspca_dev->frbuf = rvmalloc(frsz * count); |
378 | gspca_dev->frbuf = rvmalloc(frsz * count); | 309 | if (!gspca_dev->frbuf) { |
379 | if (!gspca_dev->frbuf) { | 310 | err("frame alloc failed"); |
380 | err("frame alloc failed"); | 311 | return -ENOMEM; |
381 | return -ENOMEM; | ||
382 | } | ||
383 | } | 312 | } |
384 | gspca_dev->nframes = count; | 313 | gspca_dev->nframes = count; |
385 | for (i = 0; i < count; i++) { | 314 | for (i = 0; i < count; i++) { |
@@ -391,11 +320,9 @@ static int frame_alloc(struct gspca_dev *gspca_dev, | |||
391 | frame->v4l2_buf.length = frsz; | 320 | frame->v4l2_buf.length = frsz; |
392 | frame->v4l2_buf.memory = gspca_dev->memory; | 321 | frame->v4l2_buf.memory = gspca_dev->memory; |
393 | frame->v4l2_buf.sequence = 0; | 322 | frame->v4l2_buf.sequence = 0; |
394 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) { | 323 | frame->data = frame->data_end = |
395 | frame->data = frame->data_end = | ||
396 | gspca_dev->frbuf + i * frsz; | 324 | gspca_dev->frbuf + i * frsz; |
397 | frame->v4l2_buf.m.offset = i * frsz; | 325 | frame->v4l2_buf.m.offset = i * frsz; |
398 | } | ||
399 | } | 326 | } |
400 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; | 327 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; |
401 | gspca_dev->last_packet_type = DISCARD_PACKET; | 328 | gspca_dev->last_packet_type = DISCARD_PACKET; |
@@ -509,7 +436,6 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
509 | { | 436 | { |
510 | struct urb *urb; | 437 | struct urb *urb; |
511 | int n, nurbs, i, psize, npkt, bsize; | 438 | int n, nurbs, i, psize, npkt, bsize; |
512 | usb_complete_t usb_complete; | ||
513 | 439 | ||
514 | /* calculate the packet size and the number of packets */ | 440 | /* calculate the packet size and the number of packets */ |
515 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 441 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
@@ -522,14 +448,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
522 | bsize = psize * npkt; | 448 | bsize = psize * npkt; |
523 | PDEBUG(D_STREAM, | 449 | PDEBUG(D_STREAM, |
524 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); | 450 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); |
525 | /*fixme:don't submit all URBs when userptr*/ | 451 | nurbs = DEF_NURBS; |
526 | if (gspca_dev->memory != V4L2_MEMORY_USERPTR) { | ||
527 | usb_complete = isoc_irq_mmap; | ||
528 | nurbs = DEF_NURBS; | ||
529 | } else { | ||
530 | usb_complete = isoc_irq_user; | ||
531 | nurbs = USR_NURBS; | ||
532 | } | ||
533 | gspca_dev->nurbs = nurbs; | 452 | gspca_dev->nurbs = nurbs; |
534 | for (n = 0; n < nurbs; n++) { | 453 | for (n = 0; n < nurbs; n++) { |
535 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 454 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
@@ -556,7 +475,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
556 | urb->transfer_flags = URB_ISO_ASAP | 475 | urb->transfer_flags = URB_ISO_ASAP |
557 | | URB_NO_TRANSFER_DMA_MAP; | 476 | | URB_NO_TRANSFER_DMA_MAP; |
558 | urb->interval = ep->desc.bInterval; | 477 | urb->interval = ep->desc.bInterval; |
559 | urb->complete = usb_complete; | 478 | urb->complete = isoc_irq; |
560 | urb->number_of_packets = npkt; | 479 | urb->number_of_packets = npkt; |
561 | urb->transfer_buffer_length = bsize; | 480 | urb->transfer_buffer_length = bsize; |
562 | for (i = 0; i < npkt; i++) { | 481 | for (i = 0; i < npkt; i++) { |
@@ -564,7 +483,6 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
564 | urb->iso_frame_desc[i].offset = psize * i; | 483 | urb->iso_frame_desc[i].offset = psize * i; |
565 | } | 484 | } |
566 | } | 485 | } |
567 | gspca_dev->urb_in = gspca_dev->urb_out = 0; | ||
568 | return 0; | 486 | return 0; |
569 | } | 487 | } |
570 | 488 | ||
@@ -1063,6 +981,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1063 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 981 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1064 | return -EINVAL; | 982 | return -EINVAL; |
1065 | switch (rb->memory) { | 983 | switch (rb->memory) { |
984 | case GSPCA_MEMORY_READ: | ||
1066 | case V4L2_MEMORY_MMAP: | 985 | case V4L2_MEMORY_MMAP: |
1067 | case V4L2_MEMORY_USERPTR: | 986 | case V4L2_MEMORY_USERPTR: |
1068 | break; | 987 | break; |
@@ -1072,13 +991,6 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1072 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 991 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1073 | return -ERESTARTSYS; | 992 | return -ERESTARTSYS; |
1074 | 993 | ||
1075 | for (i = 0; i < gspca_dev->nframes; i++) { | ||
1076 | if (gspca_dev->frame[i].vma_use_count) { | ||
1077 | ret = -EBUSY; | ||
1078 | goto out; | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | /* only one file may do capture */ | 994 | /* only one file may do capture */ |
1083 | if ((gspca_dev->capt_file != NULL && gspca_dev->capt_file != file) | 995 | if ((gspca_dev->capt_file != NULL && gspca_dev->capt_file != file) |
1084 | || gspca_dev->streaming) { | 996 | || gspca_dev->streaming) { |
@@ -1086,10 +998,20 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1086 | goto out; | 998 | goto out; |
1087 | } | 999 | } |
1088 | 1000 | ||
1089 | if (rb->count == 0) { /* unrequest? */ | 1001 | if (rb->count == 0) { /* unrequest */ |
1002 | for (i = 0; i < gspca_dev->nframes; i++) { | ||
1003 | if (gspca_dev->frame[i].vma_use_count) { | ||
1004 | ret = -EBUSY; | ||
1005 | goto out; | ||
1006 | } | ||
1007 | } | ||
1090 | frame_free(gspca_dev); | 1008 | frame_free(gspca_dev); |
1091 | gspca_dev->capt_file = NULL; | 1009 | gspca_dev->capt_file = NULL; |
1092 | } else { | 1010 | } else { |
1011 | if (gspca_dev->nframes != 0) { | ||
1012 | ret = -EBUSY; | ||
1013 | goto out; | ||
1014 | } | ||
1093 | gspca_dev->memory = rb->memory; | 1015 | gspca_dev->memory = rb->memory; |
1094 | ret = frame_alloc(gspca_dev, rb->count); | 1016 | ret = frame_alloc(gspca_dev, rb->count); |
1095 | if (ret == 0) { | 1017 | if (ret == 0) { |
@@ -1301,9 +1223,6 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1301 | struct page *page; | 1223 | struct page *page; |
1302 | unsigned long addr, start, size; | 1224 | unsigned long addr, start, size; |
1303 | int i, ret; | 1225 | int i, ret; |
1304 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1305 | int compat = 0; | ||
1306 | #endif | ||
1307 | 1226 | ||
1308 | start = vma->vm_start; | 1227 | start = vma->vm_start; |
1309 | size = vma->vm_end - vma->vm_start; | 1228 | size = vma->vm_end - vma->vm_start; |
@@ -1338,11 +1257,11 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1338 | goto out; | 1257 | goto out; |
1339 | } | 1258 | } |
1340 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1259 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1341 | if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes) | 1260 | /* v4l1 maps all the buffers */ |
1342 | compat = 1; | 1261 | if (i != 0 |
1343 | else | 1262 | || size != frame->v4l2_buf.length * gspca_dev->nframes) |
1344 | #endif | 1263 | #endif |
1345 | if (size != frame->v4l2_buf.length) { | 1264 | if (size != frame->v4l2_buf.length) { |
1346 | PDEBUG(D_STREAM, "mmap bad size"); | 1265 | PDEBUG(D_STREAM, "mmap bad size"); |
1347 | ret = -EINVAL; | 1266 | ret = -EINVAL; |
1348 | goto out; | 1267 | goto out; |
@@ -1368,14 +1287,6 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1368 | vma->vm_ops = &gspca_vm_ops; | 1287 | vma->vm_ops = &gspca_vm_ops; |
1369 | vma->vm_private_data = frame; | 1288 | vma->vm_private_data = frame; |
1370 | gspca_vm_open(vma); | 1289 | gspca_vm_open(vma); |
1371 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1372 | if (compat) { | ||
1373 | /*fixme: ugly*/ | ||
1374 | for (i = 1; i < gspca_dev->nframes; ++i) | ||
1375 | gspca_dev->frame[i].v4l2_buf.flags |= | ||
1376 | V4L2_BUF_FLAG_MAPPED; | ||
1377 | } | ||
1378 | #endif | ||
1379 | ret = 0; | 1290 | ret = 0; |
1380 | out: | 1291 | out: |
1381 | mutex_unlock(&gspca_dev->queue_lock); | 1292 | mutex_unlock(&gspca_dev->queue_lock); |
@@ -1393,10 +1304,6 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1393 | struct gspca_frame *frame; | 1304 | struct gspca_frame *frame; |
1394 | int i, j, ret; | 1305 | int i, j, ret; |
1395 | 1306 | ||
1396 | /* if userptr, treat the awaiting URBs */ | ||
1397 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR) | ||
1398 | isoc_transfer(gspca_dev); | ||
1399 | |||
1400 | /* check if a frame is ready */ | 1307 | /* check if a frame is ready */ |
1401 | i = gspca_dev->fr_o; | 1308 | i = gspca_dev->fr_o; |
1402 | j = gspca_dev->fr_queue[i]; | 1309 | j = gspca_dev->fr_queue[i]; |
@@ -1421,8 +1328,6 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1421 | atomic_dec(&gspca_dev->nevent); | 1328 | atomic_dec(&gspca_dev->nevent); |
1422 | if (!gspca_dev->streaming || !gspca_dev->present) | 1329 | if (!gspca_dev->streaming || !gspca_dev->present) |
1423 | return -EIO; | 1330 | return -EIO; |
1424 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR) | ||
1425 | isoc_transfer(gspca_dev); | ||
1426 | i = gspca_dev->fr_o; | 1331 | i = gspca_dev->fr_o; |
1427 | j = gspca_dev->fr_queue[i]; | 1332 | j = gspca_dev->fr_queue[i]; |
1428 | frame = &gspca_dev->frame[j]; | 1333 | frame = &gspca_dev->frame[j]; |
@@ -1455,9 +1360,9 @@ static int vidioc_dqbuf(struct file *file, void *priv, | |||
1455 | int i, ret; | 1360 | int i, ret; |
1456 | 1361 | ||
1457 | PDEBUG(D_FRAM, "dqbuf"); | 1362 | PDEBUG(D_FRAM, "dqbuf"); |
1458 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE | 1363 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1459 | || (v4l2_buf->memory != V4L2_MEMORY_MMAP | 1364 | return -EINVAL; |
1460 | && v4l2_buf->memory != V4L2_MEMORY_USERPTR)) | 1365 | if (v4l2_buf->memory != gspca_dev->memory) |
1461 | return -EINVAL; | 1366 | return -EINVAL; |
1462 | if (!gspca_dev->streaming) | 1367 | if (!gspca_dev->streaming) |
1463 | return -EINVAL; | 1368 | return -EINVAL; |
@@ -1475,6 +1380,16 @@ static int vidioc_dqbuf(struct file *file, void *priv, | |||
1475 | goto out; | 1380 | goto out; |
1476 | i = ret; /* frame index */ | 1381 | i = ret; /* frame index */ |
1477 | frame = &gspca_dev->frame[i]; | 1382 | frame = &gspca_dev->frame[i]; |
1383 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR) { | ||
1384 | if (copy_to_user((__u8 *) frame->v4l2_buf.m.userptr, | ||
1385 | frame->data, | ||
1386 | frame->v4l2_buf.bytesused)) { | ||
1387 | PDEBUG(D_ERR|D_STREAM, | ||
1388 | "dqbuf cp to user failed"); | ||
1389 | ret = -EFAULT; | ||
1390 | goto out; | ||
1391 | } | ||
1392 | } | ||
1478 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; | 1393 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; |
1479 | memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); | 1394 | memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); |
1480 | PDEBUG(D_FRAM, "dqbuf %d", i); | 1395 | PDEBUG(D_FRAM, "dqbuf %d", i); |
@@ -1529,8 +1444,6 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
1529 | /* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */ | 1444 | /* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */ |
1530 | 1445 | ||
1531 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { | 1446 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { |
1532 | frame->data = frame->data_end = | ||
1533 | (__u8 *) v4l2_buf->m.userptr; | ||
1534 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; | 1447 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; |
1535 | frame->v4l2_buf.length = v4l2_buf->length; | 1448 | frame->v4l2_buf.length = v4l2_buf->length; |
1536 | } | 1449 | } |
@@ -1568,7 +1481,7 @@ static int read_alloc(struct gspca_dev *gspca_dev, | |||
1568 | memset(&rb, 0, sizeof rb); | 1481 | memset(&rb, 0, sizeof rb); |
1569 | rb.count = gspca_dev->nbufread; | 1482 | rb.count = gspca_dev->nbufread; |
1570 | rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1483 | rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1571 | rb.memory = V4L2_MEMORY_MMAP; | 1484 | rb.memory = GSPCA_MEMORY_READ; |
1572 | ret = vidioc_reqbufs(file, gspca_dev, &rb); | 1485 | ret = vidioc_reqbufs(file, gspca_dev, &rb); |
1573 | if (ret != 0) { | 1486 | if (ret != 0) { |
1574 | PDEBUG(D_STREAM, "read reqbuf err %d", ret); | 1487 | PDEBUG(D_STREAM, "read reqbuf err %d", ret); |
@@ -1576,7 +1489,7 @@ static int read_alloc(struct gspca_dev *gspca_dev, | |||
1576 | } | 1489 | } |
1577 | memset(&v4l2_buf, 0, sizeof v4l2_buf); | 1490 | memset(&v4l2_buf, 0, sizeof v4l2_buf); |
1578 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1491 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1579 | v4l2_buf.memory = V4L2_MEMORY_MMAP; | 1492 | v4l2_buf.memory = GSPCA_MEMORY_READ; |
1580 | for (i = 0; i < gspca_dev->nbufread; i++) { | 1493 | for (i = 0; i < gspca_dev->nbufread; i++) { |
1581 | v4l2_buf.index = i; | 1494 | v4l2_buf.index = i; |
1582 | /*fixme: ugly!*/ | 1495 | /*fixme: ugly!*/ |
@@ -1629,11 +1542,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) | |||
1629 | goto out; | 1542 | goto out; |
1630 | } | 1543 | } |
1631 | 1544 | ||
1632 | /* if userptr, treat the awaiting URBs */ | ||
1633 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR | ||
1634 | && gspca_dev->capt_file == file) | ||
1635 | isoc_transfer(gspca_dev); | ||
1636 | |||
1637 | i = gspca_dev->fr_o; | 1545 | i = gspca_dev->fr_o; |
1638 | i = gspca_dev->fr_queue[i]; | 1546 | i = gspca_dev->fr_queue[i]; |
1639 | if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE) | 1547 | if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE) |
@@ -1678,7 +1586,7 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1678 | for (;;) { | 1586 | for (;;) { |
1679 | memset(&v4l2_buf, 0, sizeof v4l2_buf); | 1587 | memset(&v4l2_buf, 0, sizeof v4l2_buf); |
1680 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1588 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1681 | v4l2_buf.memory = V4L2_MEMORY_MMAP; | 1589 | v4l2_buf.memory = GSPCA_MEMORY_READ; |
1682 | ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf); | 1590 | ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf); |
1683 | if (ret != 0) { | 1591 | if (ret != 0) { |
1684 | PDEBUG(D_STREAM, "read dqbuf err %d", ret); | 1592 | PDEBUG(D_STREAM, "read dqbuf err %d", ret); |
@@ -1700,14 +1608,8 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1700 | } | 1608 | } |
1701 | 1609 | ||
1702 | /* copy the frame */ | 1610 | /* copy the frame */ |
1703 | if (count < frame->v4l2_buf.bytesused) { | 1611 | if (count > frame->v4l2_buf.bytesused) |
1704 | PDEBUG(D_STREAM, "read bad count: %d < %d", | 1612 | count = frame->v4l2_buf.bytesused; |
1705 | count, frame->v4l2_buf.bytesused); | ||
1706 | /*fixme: special errno?*/ | ||
1707 | ret = -EINVAL; | ||
1708 | goto out; | ||
1709 | } | ||
1710 | count = frame->v4l2_buf.bytesused; | ||
1711 | ret = copy_to_user(data, frame->data, count); | 1613 | ret = copy_to_user(data, frame->data, count); |
1712 | if (ret != 0) { | 1614 | if (ret != 0) { |
1713 | PDEBUG(D_ERR|D_STREAM, | 1615 | PDEBUG(D_ERR|D_STREAM, |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 945f1ab4c9eb..9b645af81a07 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -156,8 +156,6 @@ struct gspca_dev { | |||
156 | char nbufread; /* number of buffers for read() */ | 156 | char nbufread; /* number of buffers for read() */ |
157 | char nurbs; /* number of allocated URBs */ | 157 | char nurbs; /* number of allocated URBs */ |
158 | char memory; /* memory type (V4L2_MEMORY_xxx) */ | 158 | char memory; /* memory type (V4L2_MEMORY_xxx) */ |
159 | __u8 urb_in; /* URB pointers - used when !mmap */ | ||
160 | __u8 urb_out; | ||
161 | __u8 nbalt; /* number of USB alternate settings */ | 159 | __u8 nbalt; /* number of USB alternate settings */ |
162 | }; | 160 | }; |
163 | 161 | ||