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]