From patchwork Sun Jun 21 08:22:15 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 31638 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n5L8L48s023434 for ; Sun, 21 Jun 2009 08:21:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751244AbZFUIUk (ORCPT ); Sun, 21 Jun 2009 04:20:40 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751708AbZFUIUj (ORCPT ); Sun, 21 Jun 2009 04:20:39 -0400 Received: from mx2.redhat.com ([66.187.237.31]:39570 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751244AbZFUIUg (ORCPT ); Sun, 21 Jun 2009 04:20:36 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n5L8KTL9012628; Sun, 21 Jun 2009 04:20:29 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n5L8KPlk013527; Sun, 21 Jun 2009 04:20:25 -0400 Received: from localhost.localdomain (vpn-10-31.str.redhat.com [10.32.10.31]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n5L8KIld027891; Sun, 21 Jun 2009 04:20:19 -0400 Message-ID: <4A3DEDB7.3010400@redhat.com> Date: Sun, 21 Jun 2009 10:22:15 +0200 From: Hans de Goede User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1b3pre) Gecko/20090513 Fedora/3.0-2.3.beta2.fc11 Thunderbird/3.0b2 MIME-Version: 1.0 To: Mauro Carvalho Chehab CC: Linux Media Mailing List , Jean-Francois Moine Subject: Re: PULL request - http://linuxtv.org/hg/~hgoede/gspca References: <4A396620.2000702@redhat.com> <20090620075159.1e741bb3@pedra.chehab.org> <4A3CE381.8080007@redhat.com> <20090620213934.320b2d41@pedra.chehab.org> In-Reply-To: <20090620213934.320b2d41@pedra.chehab.org> X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Hi, On 06/21/2009 02:39 AM, Mauro Carvalho Chehab wrote: > Em Sat, 20 Jun 2009 15:26:25 +0200 > Hans de Goede 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;