On 24-Mar-00 Nemosoft Unv. wrote:
> I'm looking into it further myself, but maybe some of you have a good idea
> (or a simple patch).

Nah, fixed it myself :-)

The attached patch allows the USB audio module to work with the built-in
microphones of the Philips webcams. It changes the parsing of the
configuration data to allow for the way audio-control en -streaming
interfaces are reported by these cams (the current implemention cut one
corner).

Second, it corrects the selection of an alt interface in set_format(), by
taking both format and samplerate into account; the current code ignores the
samplerate.

This patch is against 2.3.51; since I don't have any other USB audio devices
I can't test if it breaks anything (don't think so), but the cameras do
work.

 - Nemosoft

-----------------------------------------------------------------------------
Try SorceryNet!   One of the best IRC-networks around!   irc.sorcery.net:9000
URL: never        IRC: nemosoft      IscaBBS (bbs.isca.uiowa.edu): Nemosoft
                        >> Never mind the daylight << 
diff -u -r linux-2.3.51-dist/drivers/usb/audio.c linux-2.3.51/drivers/usb/audio.
c
--- linux-2.3.51-dist/drivers/usb/audio.c       Wed Mar 15 21:30:20 2000
+++ linux-2.3.51/drivers/usb/audio.c    Sat Mar 25 00:24:19 2000
@@ -1395,25 +1395,30 @@
 
 /* --------------------------------------------------------------------- */
 
-static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsig
ned int fmt)
+static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsig
ned int fmt, unsigned int rate)
 {
        unsigned int i;
 
-       /* first find an exact match */
-       for (i = 0; i < nr; i++)
-               if (afp[i].format == fmt)
+       /* first find an exact match, taking both format and sample rate into account,
+          but ignore stereo bit */
+       for (i = 0; i < nr; i++) {
+               if (afp[i].format == (fmt & ~AFMT_STEREO) && rate >= afp[i].sratelo && 
+rate <
= afp[i].sratehi)
                        return i;
+       }
+               
        /* second find a match with the same stereo/mono and 8bit/16bit property */
        for (i = 0; i < nr; i++)
                if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) &&
-                   !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt))
+                   !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt) && 
+                   rate >= afp[i].sratelo && rate <= afp[i].sratehi)
                        return i;
        /* third find a match with the same number of channels */
        for (i = 0; i < nr; i++)
-               if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt))
+               if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) && 
+                   rate >= afp[i].sratelo && rate <= afp[i].sratehi)
                        return i;
-       /* return anything */
-       return 0;
+       /* return failure */
+       return -1;
 }
 
 static int set_format_in(struct usb_audiodev *as)
@@ -1432,7 +1437,13 @@
        if (u->interface < 0 || u->interface >= config->bNumInterfaces)
                return 0;
        iface = &config->interface[u->interface];
-       fmtnr = find_format(as->fmtin, as->numfmtin, d->format);
+
+       fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate);
+       if (fmtnr < 0) {
+               printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired 
+format/spe
ed combination.\n");
+               return -1;
+       }
+
        fmt = as->fmtin + fmtnr;
        alts = &iface->altsetting[fmt->altsetting];
        u->format = fmt->format;
@@ -1513,7 +1524,13 @@
        if (u->interface < 0 || u->interface >= config->bNumInterfaces)
                return 0;
        iface = &config->interface[u->interface];
-       fmtnr = find_format(as->fmtout, as->numfmtout, d->format);
+
+       fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate);
+       if (fmtnr < 0) {
+               printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired 
+format/sp
eed combination.\n");
+               return -1;
+       }
+
        fmt = as->fmtout + fmtnr;
        u->format = fmt->format;
        alts = &iface->altsetting[fmt->altsetting];
@@ -3330,7 +3347,7 @@
        struct usb_interface *iface;
        unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES];
        unsigned char *p1;
-       unsigned int i, j, numifin = 0, numifout = 0;
+       unsigned int i, j, k, numifin = 0, numifout = 0;
        
        if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL)))
                return NULL;
@@ -3377,12 +3394,25 @@
                               dev->devnum, ctrlif, j);
                        continue;
                }
-               if (iface->num_altsetting < 2 ||
-                   iface->altsetting[0].bNumEndpoints > 0) {
-                       printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u 
altsetting 0 
not zero bandwidth\n",
-                              dev->devnum, ctrlif);
+               if (iface->num_altsetting == 0) {
+                       printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u 
+has no workin
g interface.\n", dev->devnum, ctrlif);
+                       continue;
+               }
+               if (iface->num_altsetting == 1) {
+                       printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u 
+has only 1 al
tsetting.\n", dev->devnum, ctrlif);
                        continue;
                }
+               if (iface->altsetting[0].bNumEndpoints > 0) {
+                       /* Check all endpoints; should they all have a bandwidth of 0 
+? */
+                       for (k = 0; k < iface->altsetting[0].bNumEndpoints; k++) {
+                               if (iface->altsetting[0].endpoint[k].wMaxPacketSize > 
+0) {
+                                       printk(KERN_ERR "usbaudio: device %d 
+audiocontrol interface %u endpoint %d
 does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k);
+                                       break;
+                               }
+                       }
+                       if (k < iface->altsetting[0].bNumEndpoints)
+                               continue;
+               }
                if (iface->altsetting[1].bNumEndpoints < 1) {
                        printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u 
interface %u 
has no endpoint\n",
                               dev->devnum, ctrlif, j);
@@ -3418,7 +3448,7 @@
                p1 = find_csinterface_descriptor(buffer, buflen, p1, OUTPUT_TERMINAL, 
ctrlif,
 -1);
        }
 
- ret:
+ret:
        if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) {
                kfree(s);
                return NULL;
diff -u -r linux-2.3.51-dist/drivers/usb/audio.h linux-2.3.51/drivers/usb/audio.
h
--- linux-2.3.51-dist/drivers/usb/audio.h       Sun Oct 17 15:15:29 1999
+++ linux-2.3.51/drivers/usb/audio.h    Fri Mar 24 23:59:41 2000
@@ -30,7 +30,7 @@
 #define MAX_FREQ                       16
 #define MAX_IFACE                      8
 #define MAX_FORMAT                     8
-#define MAX_ALT                                8
+#define MAX_ALT                                32      /* Sorry, we need quite a few 
+for the Philips webcams */
 
 struct usb_audio_terminal
 {      
diff -u -r linux-2.3.51-dist/drivers/usb/usb.c linux-2.3.51/drivers/usb/usb.c
--- linux-2.3.51-dist/drivers/usb/usb.c Wed Mar 15 21:30:23 2000
+++ linux-2.3.51/drivers/usb/usb.c      Sat Mar 25 00:33:42 2000
@@ -1576,7 +1576,7 @@
                        err("config descriptor too short (expected %i, got 
%i)",tmp,result);
                        kfree(bigbuffer);
                        goto err;
-               }               
+               }
                result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer);
                kfree(bigbuffer);
 
@@ -1590,8 +1590,8 @@
        }
 
        return 0;
-       err:
-       dev->descriptor.bNumConfigurations=cfgno;
+err:
+       dev->descriptor.bNumConfigurations = cfgno;
        return result;
 }
 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to