aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonio Ospite <ao2@ao2.it>2014-06-25 05:27:56 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-04 13:50:11 -0400
commit2fe152451df0ead7e1ca14c0c6210b13226feafb (patch)
treedabdc7015cc8fb06b32b40619065ef69c4426709
parentb5b620584b9c4644b85e932895a742e0c192d66c (diff)
[media] gspca: provide a mechanism to select a specific transfer endpoint
Currently gspca selects the first ISOC input endpoint as the input transfer endpoint, however some devices can provide streams on endpoints different then the first one, so some subdrivers (e.g. gspca_kinect) may want to select a specific endpoint to use as a transfer endpoint. Add an xfer_ep field to struct gspca_dev, and change alt_xfer() so that it accepts a parameter which represents a specific endpoint address to look for. If a subdriver wants to specify a value for gspca_dev->xfer_ep it can do that in its sd_config() callback. Signed-off-by: Antonio Ospite <ao2@ao2.it> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/media/usb/gspca/gspca.c20
-rw-r--r--drivers/media/usb/gspca/gspca.h1
2 files changed, 15 insertions, 6 deletions
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index f3a7ace0fac9..f9a75adcf637 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -603,10 +603,13 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
603} 603}
604 604
605/* 605/*
606 * look for an input transfer endpoint in an alternate setting 606 * look for an input transfer endpoint in an alternate setting.
607 *
608 * If xfer_ep is invalid, return the first valid ep found, otherwise
609 * look for exactly the ep with address equal to xfer_ep.
607 */ 610 */
608static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, 611static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
609 int xfer) 612 int xfer, int xfer_ep)
610{ 613{
611 struct usb_host_endpoint *ep; 614 struct usb_host_endpoint *ep;
612 int i, attr; 615 int i, attr;
@@ -616,7 +619,8 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
616 attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; 619 attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
617 if (attr == xfer 620 if (attr == xfer
618 && ep->desc.wMaxPacketSize != 0 621 && ep->desc.wMaxPacketSize != 0
619 && usb_endpoint_dir_in(&ep->desc)) 622 && usb_endpoint_dir_in(&ep->desc)
623 && (xfer_ep < 0 || ep->desc.bEndpointAddress == xfer_ep))
620 return ep; 624 return ep;
621 } 625 }
622 return NULL; 626 return NULL;
@@ -689,7 +693,8 @@ static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
689 found = 0; 693 found = 0;
690 for (j = 0; j < nbalt; j++) { 694 for (j = 0; j < nbalt; j++) {
691 ep = alt_xfer(&intf->altsetting[j], 695 ep = alt_xfer(&intf->altsetting[j],
692 USB_ENDPOINT_XFER_ISOC); 696 USB_ENDPOINT_XFER_ISOC,
697 gspca_dev->xfer_ep);
693 if (ep == NULL) 698 if (ep == NULL)
694 continue; 699 continue;
695 if (ep->desc.bInterval == 0) { 700 if (ep->desc.bInterval == 0) {
@@ -862,7 +867,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
862 /* if bulk or the subdriver forced an altsetting, get the endpoint */ 867 /* if bulk or the subdriver forced an altsetting, get the endpoint */
863 if (gspca_dev->alt != 0) { 868 if (gspca_dev->alt != 0) {
864 gspca_dev->alt--; /* (previous version compatibility) */ 869 gspca_dev->alt--; /* (previous version compatibility) */
865 ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer); 870 ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer,
871 gspca_dev->xfer_ep);
866 if (ep == NULL) { 872 if (ep == NULL) {
867 pr_err("bad altsetting %d\n", gspca_dev->alt); 873 pr_err("bad altsetting %d\n", gspca_dev->alt);
868 return -EIO; 874 return -EIO;
@@ -904,7 +910,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
904 if (!gspca_dev->cam.no_urb_create) { 910 if (!gspca_dev->cam.no_urb_create) {
905 PDEBUG(D_STREAM, "init transfer alt %d", alt); 911 PDEBUG(D_STREAM, "init transfer alt %d", alt);
906 ret = create_urbs(gspca_dev, 912 ret = create_urbs(gspca_dev,
907 alt_xfer(&intf->altsetting[alt], xfer)); 913 alt_xfer(&intf->altsetting[alt], xfer,
914 gspca_dev->xfer_ep));
908 if (ret < 0) { 915 if (ret < 0) {
909 destroy_urbs(gspca_dev); 916 destroy_urbs(gspca_dev);
910 goto out; 917 goto out;
@@ -2030,6 +2037,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
2030 } 2037 }
2031 gspca_dev->dev = dev; 2038 gspca_dev->dev = dev;
2032 gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber; 2039 gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
2040 gspca_dev->xfer_ep = -1;
2033 2041
2034 /* check if any audio device */ 2042 /* check if any audio device */
2035 if (dev->actconfig->desc.bNumInterfaces != 1) { 2043 if (dev->actconfig->desc.bNumInterfaces != 1) {
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
index 300642dc1a17..f06253cd7469 100644
--- a/drivers/media/usb/gspca/gspca.h
+++ b/drivers/media/usb/gspca/gspca.h
@@ -205,6 +205,7 @@ struct gspca_dev {
205 char memory; /* memory type (V4L2_MEMORY_xxx) */ 205 char memory; /* memory type (V4L2_MEMORY_xxx) */
206 __u8 iface; /* USB interface number */ 206 __u8 iface; /* USB interface number */
207 __u8 alt; /* USB alternate setting */ 207 __u8 alt; /* USB alternate setting */
208 int xfer_ep; /* USB transfer endpoint address */
208 u8 audio; /* presence of audio device */ 209 u8 audio; /* presence of audio device */
209 210
210 /* (*) These variables are proteced by both usb_lock and queue_lock, 211 /* (*) These variables are proteced by both usb_lock and queue_lock,