Re: PULL request - http://linuxtv.org/hg/~hgoede/gspca

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On 06/21/2009 02:39 AM, Mauro Carvalho Chehab wrote:
Em Sat, 20 Jun 2009 15:26:25 +0200
Hans de Goede<hdegoede@xxxxxxxxxx>  escreveu:

err -28 is ENOSPC which is given by usb_submit_urb, when the
required bandwidth for the isoc transfer is not available.

With most cams we then automatically fall back to an altsetting
which requires less bandwidth, but the st6422 has only one
hence the: "gspca: no transfer endpoint found" error.

There are 3 possible causes for this:
1) You are using the device through an usb 2.0 hub, this should work
     but does not work due to a bug in the usb subsystem of the kernel,
     which I have reported but most likely won't be fixed



Hi,

This morning I had a bit of inspiration, the stv6422 has a register to which
the current isoc packet size should be written, so I though, hmm, maybe the
whole one altsetting which requests max bandwidth thingie is a bit bogus, and
instead it has a variable (so not fixed by altsetting) packet size,
and indeed it has.

Attached is a patch which:
1) makes it work through an usb 2.0 hub (work around the cannot
   alloc max isoc bandwidth through a usb 2.0 hub bug, by falling
   back in speed).
2) makes the mic and video work at the same time

Unfortunately 1 + 2 combined do not work, this is clearly a bug of the usb
subsystem :(

Regards,

Hans


p.s.

Jean-Francois Moine, can you please take a look at this patch and provide
feedback? It also makes changes the gscpa core.
diff -r 2899ad868fc6 linux/drivers/media/video/gspca/gspca.c
--- a/linux/drivers/media/video/gspca/gspca.c	Thu Jun 18 19:31:36 2009 +0200
+++ b/linux/drivers/media/video/gspca/gspca.c	Sun Jun 21 10:14:28 2009 +0200
@@ -525,6 +525,9 @@
 
 		/* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
 		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+		/* Variable packet size overriding alt setting ? */
+		if (gspca_dev->isoc_pkt_sz)
+			psize = gspca_dev->isoc_pkt_sz;
 		npkt = gspca_dev->cam.npkt;
 		if (npkt == 0)
 			npkt = 32;		/* default value */
@@ -595,6 +598,7 @@
  */
 static int gspca_init_transfer(struct gspca_dev *gspca_dev)
 {
+	struct cam *cam = &gspca_dev->cam;
 	struct usb_host_endpoint *ep;
 	int n, ret;
 
@@ -609,9 +613,9 @@
 	/* set the higher alternate setting and
 	 * loop until urb submit succeeds */
 	gspca_dev->alt = gspca_dev->nbalt;
+	gspca_dev->isoc_pkt_sz = cam->max_isoc_pkt_sz;
+	ep = get_ep(gspca_dev);
 	for (;;) {
-		PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
-		ep = get_ep(gspca_dev);
 		if (ep == NULL) {
 			ret = -EIO;
 			goto out;
@@ -648,7 +652,17 @@
 				if (ret == -ENOSPC) {
 					msleep(20);	/* wait for kill
 							 * complete */
-					break;	/* try the previous alt */
+					if (gspca_dev->isoc_pkt_sz) {
+						/* Try smaller packet size */
+						gspca_dev->isoc_pkt_sz -= 100;
+						if (gspca_dev->isoc_pkt_sz <
+						    cam->min_isoc_pkt_sz)
+							goto out;
+					} else {
+						/* try the previous alt */
+						ep = get_ep(gspca_dev);
+					}
+					break;
 				}
 				goto out;
 			}
diff -r 2899ad868fc6 linux/drivers/media/video/gspca/gspca.h
--- a/linux/drivers/media/video/gspca/gspca.h	Thu Jun 18 19:31:36 2009 +0200
+++ b/linux/drivers/media/video/gspca/gspca.h	Sun Jun 21 10:14:28 2009 +0200
@@ -57,6 +57,12 @@
 	u8 bulk;		/* image transfer by 0:isoc / 1:bulk */
 	u8 npkt;		/* number of packets in an ISOC message
 				 * 0 is the default value: 32 packets */
+	/* min / max isoc packet size for camera's which have a variable
+	   packet size, when this is the case BOTH must be set to a non zero
+	   value, the wMaxPacketSize of the alsetting will be ignored and the
+	   highest alt setting will be used */
+	int min_isoc_pkt_sz;
+	int max_isoc_pkt_sz;
 	u32 input_flags;	/* value for ENUM_INPUT status flags */
 };
 
@@ -135,6 +141,7 @@
 #define USB_BUF_SZ 64
 	__u8 *usb_buf;				/* buffer for USB exchanges */
 	struct urb *urb[MAX_NURBS];
+	int isoc_pkt_sz;			/* variable isoc packet size */
 
 	__u8 *frbuf;				/* buffer for nframes */
 	struct gspca_frame frame[GSPCA_MAX_FRAMES];
diff -r 2899ad868fc6 linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	Thu Jun 18 19:31:36 2009 +0200
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	Sun Jun 21 10:14:28 2009 +0200
@@ -133,6 +133,9 @@
 
 	sd->gspca_dev.cam.cam_mode = st6422_mode;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+	sd->gspca_dev.cam.min_isoc_pkt_sz = 460;
+	sd->gspca_dev.cam.max_isoc_pkt_sz = 960;
+	sd->gspca_dev.cam.npkt = 10;
 	sd->desc.ctrls = st6422_ctrl;
 	sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
 	sd->sensor_priv = sensor_settings;
@@ -238,21 +241,11 @@
 
 static int st6422_start(struct sd *sd)
 {
-	int err, packet_size;
+	int err;
 	struct cam *cam = &sd->gspca_dev.cam;
 	s32 *sensor_settings = sd->sensor_priv;
-	struct usb_host_interface *alt;
-	struct usb_interface *intf;
 
-	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
-	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
-	if (!alt) {
-		PDEBUG(D_ERR, "Couldn't get altsetting");
-		return -EIO;
-	}
-
-	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-	err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
+	err = stv06xx_write_bridge(sd, 0x15c1, sd->gspca_dev.isoc_pkt_sz);
 	if (err < 0)
 		return err;
 

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux