diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2009-06-30 06:07:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:17:37 -0400 |
commit | 1f53b0b0107e3d4b5a4382eaed6a8b4fc146b50c (patch) | |
tree | fccb40536217d5db828ea725d1a2531521827d86 /drivers/media/video/gspca/gspca.c | |
parent | 1852e75a55287156f2a435ca4ea4f8c1c75bac6c (diff) |
V4L/DVB (12229): gspca - main: Change the ISOC initialization mechanism.
- call a new subdriver function 'isoc_init' before chosing the first
alternate setting.
- call a new subdriver function 'isoc_nego' when submitting the URBs failed.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index b8561dfb6c8c..1cc67ae3bfab 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -512,7 +512,10 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
512 | if (!gspca_dev->cam.bulk) { /* isoc */ | 512 | if (!gspca_dev->cam.bulk) { /* isoc */ |
513 | 513 | ||
514 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ | 514 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ |
515 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | 515 | if (gspca_dev->pkt_size == 0) |
516 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | ||
517 | else | ||
518 | psize = gspca_dev->pkt_size; | ||
516 | npkt = gspca_dev->cam.npkt; | 519 | npkt = gspca_dev->cam.npkt; |
517 | if (npkt == 0) | 520 | if (npkt == 0) |
518 | npkt = 32; /* default value */ | 521 | npkt = 32; /* default value */ |
@@ -597,13 +600,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
597 | /* set the higher alternate setting and | 600 | /* set the higher alternate setting and |
598 | * loop until urb submit succeeds */ | 601 | * loop until urb submit succeeds */ |
599 | gspca_dev->alt = gspca_dev->nbalt; | 602 | gspca_dev->alt = gspca_dev->nbalt; |
603 | if (gspca_dev->sd_desc->isoc_init) { | ||
604 | ret = gspca_dev->sd_desc->isoc_init(gspca_dev); | ||
605 | if (ret < 0) | ||
606 | goto out; | ||
607 | } | ||
608 | ep = get_ep(gspca_dev); | ||
609 | if (ep == NULL) { | ||
610 | ret = -EIO; | ||
611 | goto out; | ||
612 | } | ||
600 | for (;;) { | 613 | for (;;) { |
601 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); | 614 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); |
602 | ep = get_ep(gspca_dev); | ||
603 | if (ep == NULL) { | ||
604 | ret = -EIO; | ||
605 | goto out; | ||
606 | } | ||
607 | ret = create_urbs(gspca_dev, ep); | 615 | ret = create_urbs(gspca_dev, ep); |
608 | if (ret < 0) | 616 | if (ret < 0) |
609 | goto out; | 617 | goto out; |
@@ -628,21 +636,32 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
628 | /* submit the URBs */ | 636 | /* submit the URBs */ |
629 | for (n = 0; n < gspca_dev->nurbs; n++) { | 637 | for (n = 0; n < gspca_dev->nurbs; n++) { |
630 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 638 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); |
631 | if (ret < 0) { | 639 | if (ret < 0) |
632 | PDEBUG(D_ERR|D_STREAM, | 640 | break; |
633 | "usb_submit_urb [%d] err %d", n, ret); | ||
634 | gspca_dev->streaming = 0; | ||
635 | destroy_urbs(gspca_dev); | ||
636 | if (ret == -ENOSPC) { | ||
637 | msleep(20); /* wait for kill | ||
638 | * complete */ | ||
639 | break; /* try the previous alt */ | ||
640 | } | ||
641 | goto out; | ||
642 | } | ||
643 | } | 641 | } |
644 | if (ret >= 0) | 642 | if (ret >= 0) |
645 | break; | 643 | break; |
644 | PDEBUG(D_ERR|D_STREAM, | ||
645 | "usb_submit_urb alt %d err %d", gspca_dev->alt, ret); | ||
646 | gspca_dev->streaming = 0; | ||
647 | destroy_urbs(gspca_dev); | ||
648 | if (ret != -ENOSPC) | ||
649 | goto out; | ||
650 | |||
651 | /* the bandwidth is not wide enough | ||
652 | * negociate or try a lower alternate setting */ | ||
653 | msleep(20); /* wait for kill complete */ | ||
654 | if (gspca_dev->sd_desc->isoc_nego) { | ||
655 | ret = gspca_dev->sd_desc->isoc_nego(gspca_dev); | ||
656 | if (ret < 0) | ||
657 | goto out; | ||
658 | } else { | ||
659 | ep = get_ep(gspca_dev); | ||
660 | if (ep == NULL) { | ||
661 | ret = -EIO; | ||
662 | goto out; | ||
663 | } | ||
664 | } | ||
646 | } | 665 | } |
647 | out: | 666 | out: |
648 | mutex_unlock(&gspca_dev->usb_lock); | 667 | mutex_unlock(&gspca_dev->usb_lock); |