diff options
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 245 |
1 files changed, 170 insertions, 75 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ac95c55887df..c21af312ee7c 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
30 | #include <linux/pagemap.h> | 30 | #include <linux/pagemap.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/kref.h> | ||
32 | #include <asm/page.h> | 33 | #include <asm/page.h> |
33 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
34 | #include <linux/jiffies.h> | 35 | #include <linux/jiffies.h> |
@@ -43,7 +44,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
43 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 44 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
44 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
45 | 46 | ||
46 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 2, 0) | 47 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 3, 0) |
47 | 48 | ||
48 | static int video_nr = -1; | 49 | static int video_nr = -1; |
49 | 50 | ||
@@ -102,6 +103,22 @@ static struct vm_operations_struct gspca_vm_ops = { | |||
102 | .close = gspca_vm_close, | 103 | .close = gspca_vm_close, |
103 | }; | 104 | }; |
104 | 105 | ||
106 | /* get the current input frame buffer */ | ||
107 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) | ||
108 | { | ||
109 | struct gspca_frame *frame; | ||
110 | int i; | ||
111 | |||
112 | i = gspca_dev->fr_i; | ||
113 | i = gspca_dev->fr_queue[i]; | ||
114 | frame = &gspca_dev->frame[i]; | ||
115 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
116 | != V4L2_BUF_FLAG_QUEUED) | ||
117 | return NULL; | ||
118 | return frame; | ||
119 | } | ||
120 | EXPORT_SYMBOL(gspca_get_i_frame); | ||
121 | |||
105 | /* | 122 | /* |
106 | * fill a video frame from an URB and resubmit | 123 | * fill a video frame from an URB and resubmit |
107 | */ | 124 | */ |
@@ -110,7 +127,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
110 | { | 127 | { |
111 | struct gspca_frame *frame; | 128 | struct gspca_frame *frame; |
112 | __u8 *data; /* address of data in the iso message */ | 129 | __u8 *data; /* address of data in the iso message */ |
113 | int i, j, len, st; | 130 | int i, len, st; |
114 | cam_pkt_op pkt_scan; | 131 | cam_pkt_op pkt_scan; |
115 | 132 | ||
116 | if (urb->status != 0) { | 133 | if (urb->status != 0) { |
@@ -124,11 +141,8 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
124 | for (i = 0; i < urb->number_of_packets; i++) { | 141 | for (i = 0; i < urb->number_of_packets; i++) { |
125 | 142 | ||
126 | /* check the availability of the frame buffer */ | 143 | /* check the availability of the frame buffer */ |
127 | j = gspca_dev->fr_i; | 144 | frame = gspca_get_i_frame(gspca_dev); |
128 | j = gspca_dev->fr_queue[j]; | 145 | if (!frame) { |
129 | frame = &gspca_dev->frame[j]; | ||
130 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
131 | != V4L2_BUF_FLAG_QUEUED) { | ||
132 | gspca_dev->last_packet_type = DISCARD_PACKET; | 146 | gspca_dev->last_packet_type = DISCARD_PACKET; |
133 | break; | 147 | break; |
134 | } | 148 | } |
@@ -178,6 +192,39 @@ static void isoc_irq(struct urb *urb | |||
178 | } | 192 | } |
179 | 193 | ||
180 | /* | 194 | /* |
195 | * bulk message interrupt from the USB device | ||
196 | */ | ||
197 | static void bulk_irq(struct urb *urb | ||
198 | ) | ||
199 | { | ||
200 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
201 | struct gspca_frame *frame; | ||
202 | |||
203 | PDEBUG(D_PACK, "bulk irq"); | ||
204 | if (!gspca_dev->streaming) | ||
205 | return; | ||
206 | if (urb->status != 0 && urb->status != -ECONNRESET) { | ||
207 | #ifdef CONFIG_PM | ||
208 | if (!gspca_dev->frozen) | ||
209 | #endif | ||
210 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); | ||
211 | return; /* disconnection ? */ | ||
212 | } | ||
213 | |||
214 | /* check the availability of the frame buffer */ | ||
215 | frame = gspca_get_i_frame(gspca_dev); | ||
216 | if (!frame) { | ||
217 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
218 | } else { | ||
219 | PDEBUG(D_PACK, "packet l:%d", urb->actual_length); | ||
220 | gspca_dev->sd_desc->pkt_scan(gspca_dev, | ||
221 | frame, | ||
222 | urb->transfer_buffer, | ||
223 | urb->actual_length); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | /* | ||
181 | * add data to the current frame | 228 | * add data to the current frame |
182 | * | 229 | * |
183 | * This function is called by the subdrivers at interrupt level. | 230 | * This function is called by the subdrivers at interrupt level. |
@@ -190,7 +237,7 @@ static void isoc_irq(struct urb *urb | |||
190 | * On LAST_PACKET, a new frame is returned. | 237 | * On LAST_PACKET, a new frame is returned. |
191 | */ | 238 | */ |
192 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | 239 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, |
193 | int packet_type, | 240 | enum gspca_packet_type packet_type, |
194 | struct gspca_frame *frame, | 241 | struct gspca_frame *frame, |
195 | const __u8 *data, | 242 | const __u8 *data, |
196 | int len) | 243 | int len) |
@@ -232,7 +279,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
232 | } | 279 | } |
233 | gspca_dev->last_packet_type = packet_type; | 280 | gspca_dev->last_packet_type = packet_type; |
234 | 281 | ||
235 | /* if last packet, wake the application and advance in the queue */ | 282 | /* if last packet, wake up the application and advance in the queue */ |
236 | if (packet_type == LAST_PACKET) { | 283 | if (packet_type == LAST_PACKET) { |
237 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; | 284 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; |
238 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | 285 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; |
@@ -270,7 +317,6 @@ static void *rvmalloc(unsigned long size) | |||
270 | void *mem; | 317 | void *mem; |
271 | unsigned long adr; | 318 | unsigned long adr; |
272 | 319 | ||
273 | /* size = PAGE_ALIGN(size); (already done) */ | ||
274 | mem = vmalloc_32(size); | 320 | mem = vmalloc_32(size); |
275 | if (mem != NULL) { | 321 | if (mem != NULL) { |
276 | adr = (unsigned long) mem; | 322 | adr = (unsigned long) mem; |
@@ -374,10 +420,11 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) | |||
374 | } | 420 | } |
375 | 421 | ||
376 | /* | 422 | /* |
377 | * search an input isochronous endpoint in an alternate setting | 423 | * look for an input transfer endpoint in an alternate setting |
378 | */ | 424 | */ |
379 | static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | 425 | static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, |
380 | __u8 epaddr) | 426 | __u8 epaddr, |
427 | __u8 xfer) | ||
381 | { | 428 | { |
382 | struct usb_host_endpoint *ep; | 429 | struct usb_host_endpoint *ep; |
383 | int i, attr; | 430 | int i, attr; |
@@ -388,7 +435,7 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | |||
388 | if (ep->desc.bEndpointAddress == epaddr) { | 435 | if (ep->desc.bEndpointAddress == epaddr) { |
389 | attr = ep->desc.bmAttributes | 436 | attr = ep->desc.bmAttributes |
390 | & USB_ENDPOINT_XFERTYPE_MASK; | 437 | & USB_ENDPOINT_XFERTYPE_MASK; |
391 | if (attr == USB_ENDPOINT_XFER_ISOC) | 438 | if (attr == xfer) |
392 | return ep; | 439 | return ep; |
393 | break; | 440 | break; |
394 | } | 441 | } |
@@ -397,14 +444,14 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | |||
397 | } | 444 | } |
398 | 445 | ||
399 | /* | 446 | /* |
400 | * search an input isochronous endpoint | 447 | * look for an input (isoc or bulk) endpoint |
401 | * | 448 | * |
402 | * The endpoint is defined by the subdriver. | 449 | * The endpoint is defined by the subdriver. |
403 | * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). | 450 | * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). |
404 | * This routine may be called many times when the bandwidth is too small | 451 | * This routine may be called many times when the bandwidth is too small |
405 | * (the bandwidth is checked on urb submit). | 452 | * (the bandwidth is checked on urb submit). |
406 | */ | 453 | */ |
407 | static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) | 454 | static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) |
408 | { | 455 | { |
409 | struct usb_interface *intf; | 456 | struct usb_interface *intf; |
410 | struct usb_host_endpoint *ep; | 457 | struct usb_host_endpoint *ep; |
@@ -413,28 +460,41 @@ static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) | |||
413 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | 460 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); |
414 | ep = NULL; | 461 | ep = NULL; |
415 | i = gspca_dev->alt; /* previous alt setting */ | 462 | i = gspca_dev->alt; /* previous alt setting */ |
463 | |||
464 | /* try isoc */ | ||
416 | while (--i > 0) { /* alt 0 is unusable */ | 465 | while (--i > 0) { /* alt 0 is unusable */ |
417 | ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr); | 466 | ep = alt_xfer(&intf->altsetting[i], |
467 | gspca_dev->cam.epaddr, | ||
468 | USB_ENDPOINT_XFER_ISOC); | ||
418 | if (ep) | 469 | if (ep) |
419 | break; | 470 | break; |
420 | } | 471 | } |
472 | |||
473 | /* if no isoc, try bulk */ | ||
421 | if (ep == NULL) { | 474 | if (ep == NULL) { |
422 | err("no ISOC endpoint found"); | 475 | ep = alt_xfer(&intf->altsetting[0], |
423 | return NULL; | 476 | gspca_dev->cam.epaddr, |
477 | USB_ENDPOINT_XFER_BULK); | ||
478 | if (ep == NULL) { | ||
479 | err("no transfer endpoint found"); | ||
480 | return NULL; | ||
481 | } | ||
424 | } | 482 | } |
425 | PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x", | 483 | PDEBUG(D_STREAM, "use alt %d ep 0x%02x", |
426 | i, ep->desc.bEndpointAddress); | 484 | i, ep->desc.bEndpointAddress); |
427 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); | 485 | if (i > 0) { |
428 | if (ret < 0) { | 486 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); |
429 | err("set interface err %d", ret); | 487 | if (ret < 0) { |
430 | return NULL; | 488 | err("set interface err %d", ret); |
489 | return NULL; | ||
490 | } | ||
431 | } | 491 | } |
432 | gspca_dev->alt = i; /* memorize the current alt setting */ | 492 | gspca_dev->alt = i; /* memorize the current alt setting */ |
433 | return ep; | 493 | return ep; |
434 | } | 494 | } |
435 | 495 | ||
436 | /* | 496 | /* |
437 | * create the isochronous URBs | 497 | * create the URBs for image transfer |
438 | */ | 498 | */ |
439 | static int create_urbs(struct gspca_dev *gspca_dev, | 499 | static int create_urbs(struct gspca_dev *gspca_dev, |
440 | struct usb_host_endpoint *ep) | 500 | struct usb_host_endpoint *ep) |
@@ -445,15 +505,27 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
445 | /* calculate the packet size and the number of packets */ | 505 | /* calculate the packet size and the number of packets */ |
446 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 506 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
447 | 507 | ||
448 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ | 508 | if (gspca_dev->alt != 0) { /* isoc */ |
449 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | 509 | |
450 | npkt = ISO_MAX_SIZE / psize; | 510 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ |
451 | if (npkt > ISO_MAX_PKT) | 511 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); |
452 | npkt = ISO_MAX_PKT; | 512 | npkt = ISO_MAX_SIZE / psize; |
453 | bsize = psize * npkt; | 513 | if (npkt > ISO_MAX_PKT) |
454 | PDEBUG(D_STREAM, | 514 | npkt = ISO_MAX_PKT; |
455 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); | 515 | bsize = psize * npkt; |
456 | nurbs = DEF_NURBS; | 516 | PDEBUG(D_STREAM, |
517 | "isoc %d pkts size %d = bsize:%d", | ||
518 | npkt, psize, bsize); | ||
519 | nurbs = DEF_NURBS; | ||
520 | } else { /* bulk */ | ||
521 | npkt = 0; | ||
522 | bsize = gspca_dev->cam. bulk_size; | ||
523 | if (bsize == 0) | ||
524 | bsize = psize; | ||
525 | PDEBUG(D_STREAM, "bulk bsize:%d", bsize); | ||
526 | nurbs = 1; | ||
527 | } | ||
528 | |||
457 | gspca_dev->nurbs = nurbs; | 529 | gspca_dev->nurbs = nurbs; |
458 | for (n = 0; n < nurbs; n++) { | 530 | for (n = 0; n < nurbs; n++) { |
459 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 531 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
@@ -476,17 +548,24 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
476 | gspca_dev->urb[n] = urb; | 548 | gspca_dev->urb[n] = urb; |
477 | urb->dev = gspca_dev->dev; | 549 | urb->dev = gspca_dev->dev; |
478 | urb->context = gspca_dev; | 550 | urb->context = gspca_dev; |
479 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, | ||
480 | ep->desc.bEndpointAddress); | ||
481 | urb->transfer_flags = URB_ISO_ASAP | ||
482 | | URB_NO_TRANSFER_DMA_MAP; | ||
483 | urb->interval = ep->desc.bInterval; | ||
484 | urb->complete = isoc_irq; | ||
485 | urb->number_of_packets = npkt; | ||
486 | urb->transfer_buffer_length = bsize; | 551 | urb->transfer_buffer_length = bsize; |
487 | for (i = 0; i < npkt; i++) { | 552 | if (npkt != 0) { /* ISOC */ |
488 | urb->iso_frame_desc[i].length = psize; | 553 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, |
489 | urb->iso_frame_desc[i].offset = psize * i; | 554 | ep->desc.bEndpointAddress); |
555 | urb->transfer_flags = URB_ISO_ASAP | ||
556 | | URB_NO_TRANSFER_DMA_MAP; | ||
557 | urb->interval = ep->desc.bInterval; | ||
558 | urb->complete = isoc_irq; | ||
559 | urb->number_of_packets = npkt; | ||
560 | for (i = 0; i < npkt; i++) { | ||
561 | urb->iso_frame_desc[i].length = psize; | ||
562 | urb->iso_frame_desc[i].offset = psize * i; | ||
563 | } | ||
564 | } else { /* bulk */ | ||
565 | urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, | ||
566 | ep->desc.bEndpointAddress), | ||
567 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
568 | urb->complete = bulk_irq; | ||
490 | } | 569 | } |
491 | } | 570 | } |
492 | return 0; | 571 | return 0; |
@@ -508,7 +587,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
508 | gspca_dev->alt = gspca_dev->nbalt; | 587 | gspca_dev->alt = gspca_dev->nbalt; |
509 | for (;;) { | 588 | for (;;) { |
510 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); | 589 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); |
511 | ep = get_isoc_ep(gspca_dev); | 590 | ep = get_ep(gspca_dev); |
512 | if (ep == NULL) { | 591 | if (ep == NULL) { |
513 | ret = -EIO; | 592 | ret = -EIO; |
514 | goto out; | 593 | goto out; |
@@ -518,10 +597,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
518 | goto out; | 597 | goto out; |
519 | 598 | ||
520 | /* start the cam */ | 599 | /* start the cam */ |
521 | gspca_dev->sd_desc->start(gspca_dev); | 600 | ret = gspca_dev->sd_desc->start(gspca_dev); |
601 | if (ret < 0) { | ||
602 | destroy_urbs(gspca_dev); | ||
603 | goto out; | ||
604 | } | ||
522 | gspca_dev->streaming = 1; | 605 | gspca_dev->streaming = 1; |
523 | atomic_set(&gspca_dev->nevent, 0); | 606 | atomic_set(&gspca_dev->nevent, 0); |
524 | 607 | ||
608 | /* bulk transfers are started by the subdriver */ | ||
609 | if (gspca_dev->alt == 0) | ||
610 | break; | ||
611 | |||
525 | /* submit the URBs */ | 612 | /* submit the URBs */ |
526 | for (n = 0; n < gspca_dev->nurbs; n++) { | 613 | for (n = 0; n < gspca_dev->nurbs; n++) { |
527 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 614 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); |
@@ -553,7 +640,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) | |||
553 | return ret; | 640 | return ret; |
554 | } | 641 | } |
555 | 642 | ||
556 | /* Note both the queue and the usb lock should be hold when calling this */ | 643 | /* Note: both the queue and the usb locks should be held when calling this */ |
557 | static void gspca_stream_off(struct gspca_dev *gspca_dev) | 644 | static void gspca_stream_off(struct gspca_dev *gspca_dev) |
558 | { | 645 | { |
559 | gspca_dev->streaming = 0; | 646 | gspca_dev->streaming = 0; |
@@ -759,6 +846,16 @@ out: | |||
759 | return ret; | 846 | return ret; |
760 | } | 847 | } |
761 | 848 | ||
849 | static void gspca_delete(struct kref *kref) | ||
850 | { | ||
851 | struct gspca_dev *gspca_dev = container_of(kref, struct gspca_dev, kref); | ||
852 | |||
853 | PDEBUG(D_STREAM, "device deleted"); | ||
854 | |||
855 | kfree(gspca_dev->usb_buf); | ||
856 | kfree(gspca_dev); | ||
857 | } | ||
858 | |||
762 | static int dev_open(struct inode *inode, struct file *file) | 859 | static int dev_open(struct inode *inode, struct file *file) |
763 | { | 860 | { |
764 | struct gspca_dev *gspca_dev; | 861 | struct gspca_dev *gspca_dev; |
@@ -778,13 +875,19 @@ static int dev_open(struct inode *inode, struct file *file) | |||
778 | goto out; | 875 | goto out; |
779 | } | 876 | } |
780 | gspca_dev->users++; | 877 | gspca_dev->users++; |
878 | |||
879 | /* one more user */ | ||
880 | kref_get(&gspca_dev->kref); | ||
881 | |||
781 | file->private_data = gspca_dev; | 882 | file->private_data = gspca_dev; |
782 | #ifdef GSPCA_DEBUG | 883 | #ifdef GSPCA_DEBUG |
783 | /* activate the v4l2 debug */ | 884 | /* activate the v4l2 debug */ |
784 | if (gspca_debug & D_V4L2) | 885 | if (gspca_debug & D_V4L2) |
785 | gspca_dev->vdev.debug |= 3; | 886 | gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL |
887 | | V4L2_DEBUG_IOCTL_ARG; | ||
786 | else | 888 | else |
787 | gspca_dev->vdev.debug &= ~3; | 889 | gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL |
890 | | V4L2_DEBUG_IOCTL_ARG); | ||
788 | #endif | 891 | #endif |
789 | ret = 0; | 892 | ret = 0; |
790 | out: | 893 | out: |
@@ -818,7 +921,11 @@ static int dev_close(struct inode *inode, struct file *file) | |||
818 | } | 921 | } |
819 | file->private_data = NULL; | 922 | file->private_data = NULL; |
820 | mutex_unlock(&gspca_dev->queue_lock); | 923 | mutex_unlock(&gspca_dev->queue_lock); |
924 | |||
821 | PDEBUG(D_STREAM, "close done"); | 925 | PDEBUG(D_STREAM, "close done"); |
926 | |||
927 | kref_put(&gspca_dev->kref, gspca_delete); | ||
928 | |||
822 | return 0; | 929 | return 0; |
823 | } | 930 | } |
824 | 931 | ||
@@ -829,7 +936,6 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
829 | 936 | ||
830 | memset(cap, 0, sizeof *cap); | 937 | memset(cap, 0, sizeof *cap); |
831 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); | 938 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); |
832 | /* strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); */ | ||
833 | if (gspca_dev->dev->product != NULL) { | 939 | if (gspca_dev->dev->product != NULL) { |
834 | strncpy(cap->card, gspca_dev->dev->product, | 940 | strncpy(cap->card, gspca_dev->dev->product, |
835 | sizeof cap->card); | 941 | sizeof cap->card); |
@@ -1463,7 +1569,6 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
1463 | } | 1569 | } |
1464 | 1570 | ||
1465 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; | 1571 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; |
1466 | /* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */ | ||
1467 | 1572 | ||
1468 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { | 1573 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { |
1469 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; | 1574 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; |
@@ -1610,7 +1715,7 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1610 | } | 1715 | } |
1611 | 1716 | ||
1612 | /* if the process slept for more than 1 second, | 1717 | /* if the process slept for more than 1 second, |
1613 | * get anewer frame */ | 1718 | * get a newer frame */ |
1614 | frame = &gspca_dev->frame[v4l2_buf.index]; | 1719 | frame = &gspca_dev->frame[v4l2_buf.index]; |
1615 | if (--n < 0) | 1720 | if (--n < 0) |
1616 | break; /* avoid infinite loop */ | 1721 | break; /* avoid infinite loop */ |
@@ -1728,21 +1833,21 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1728 | if (dev_size < sizeof *gspca_dev) | 1833 | if (dev_size < sizeof *gspca_dev) |
1729 | dev_size = sizeof *gspca_dev; | 1834 | dev_size = sizeof *gspca_dev; |
1730 | gspca_dev = kzalloc(dev_size, GFP_KERNEL); | 1835 | gspca_dev = kzalloc(dev_size, GFP_KERNEL); |
1731 | if (gspca_dev == NULL) { | 1836 | if (!gspca_dev) { |
1732 | err("couldn't kzalloc gspca struct"); | 1837 | err("couldn't kzalloc gspca struct"); |
1733 | return -EIO; | 1838 | return -ENOMEM; |
1734 | } | 1839 | } |
1840 | kref_init(&gspca_dev->kref); | ||
1735 | gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); | 1841 | gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); |
1736 | if (!gspca_dev->usb_buf) { | 1842 | if (!gspca_dev->usb_buf) { |
1737 | err("out of memory"); | 1843 | err("out of memory"); |
1738 | ret = -EIO; | 1844 | ret = -ENOMEM; |
1739 | goto out; | 1845 | goto out; |
1740 | } | 1846 | } |
1741 | gspca_dev->dev = dev; | 1847 | gspca_dev->dev = dev; |
1742 | gspca_dev->iface = interface->bInterfaceNumber; | 1848 | gspca_dev->iface = interface->bInterfaceNumber; |
1743 | gspca_dev->nbalt = intf->num_altsetting; | 1849 | gspca_dev->nbalt = intf->num_altsetting; |
1744 | gspca_dev->sd_desc = sd_desc; | 1850 | gspca_dev->sd_desc = sd_desc; |
1745 | /* gspca_dev->users = 0; (done by kzalloc) */ | ||
1746 | gspca_dev->nbufread = 2; | 1851 | gspca_dev->nbufread = 2; |
1747 | 1852 | ||
1748 | /* configure the subdriver and initialize the USB device */ | 1853 | /* configure the subdriver and initialize the USB device */ |
@@ -1781,8 +1886,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1781 | PDEBUG(D_PROBE, "probe ok"); | 1886 | PDEBUG(D_PROBE, "probe ok"); |
1782 | return 0; | 1887 | return 0; |
1783 | out: | 1888 | out: |
1784 | kfree(gspca_dev->usb_buf); | 1889 | kref_put(&gspca_dev->kref, gspca_delete); |
1785 | kfree(gspca_dev); | ||
1786 | return ret; | 1890 | return ret; |
1787 | } | 1891 | } |
1788 | EXPORT_SYMBOL(gspca_dev_probe); | 1892 | EXPORT_SYMBOL(gspca_dev_probe); |
@@ -1797,25 +1901,16 @@ void gspca_disconnect(struct usb_interface *intf) | |||
1797 | { | 1901 | { |
1798 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 1902 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
1799 | 1903 | ||
1800 | if (!gspca_dev) | 1904 | usb_set_intfdata(intf, NULL); |
1801 | return; | 1905 | |
1802 | gspca_dev->present = 0; | ||
1803 | mutex_lock(&gspca_dev->queue_lock); | ||
1804 | mutex_lock(&gspca_dev->usb_lock); | ||
1805 | gspca_dev->streaming = 0; | ||
1806 | destroy_urbs(gspca_dev); | ||
1807 | mutex_unlock(&gspca_dev->usb_lock); | ||
1808 | mutex_unlock(&gspca_dev->queue_lock); | ||
1809 | while (gspca_dev->users != 0) { /* wait until fully closed */ | ||
1810 | atomic_inc(&gspca_dev->nevent); | ||
1811 | wake_up_interruptible(&gspca_dev->wq); /* wake processes */ | ||
1812 | schedule(); | ||
1813 | } | ||
1814 | /* We don't want people trying to open up the device */ | 1906 | /* We don't want people trying to open up the device */ |
1815 | video_unregister_device(&gspca_dev->vdev); | 1907 | video_unregister_device(&gspca_dev->vdev); |
1816 | /* Free the memory */ | 1908 | |
1817 | kfree(gspca_dev->usb_buf); | 1909 | gspca_dev->present = 0; |
1818 | kfree(gspca_dev); | 1910 | gspca_dev->streaming = 0; |
1911 | |||
1912 | kref_put(&gspca_dev->kref, gspca_delete); | ||
1913 | |||
1819 | PDEBUG(D_PROBE, "disconnect complete"); | 1914 | PDEBUG(D_PROBE, "disconnect complete"); |
1820 | } | 1915 | } |
1821 | EXPORT_SYMBOL(gspca_disconnect); | 1916 | EXPORT_SYMBOL(gspca_disconnect); |