Bryce Nesbitt found a case where audio handled the
OSS API wrongly. This is basically his patch fixing
it.
Please apply.
Tom
--- audio.c.orig Mon Jun 18 15:05:56 2001
+++ audio.c Tue Jun 19 10:47:49 2001
@@ -12,6 +12,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
+ * Debugging:
+ * Use the 'lsusb' utility to dump the descriptors.
*
* 1999-09-07: Alan Cox
* Parsing Audio descriptor patch
@@ -97,6 +99,8 @@
* for abs. Bug report by Andrew Morton <[EMAIL PROTECTED]>
* 2001-04-08: gb
* Identify version on module load.
+ * 2001-06-16: Bryce Nesbitt <[EMAIL PROTECTED]>
+ * Fix SNDCTL_DSP_STEREO API violation
*/
/*
@@ -207,6 +211,9 @@
#define dprintk(x)
+#undef abs
+extern int abs(int __x) __attribute__ ((__const__)); /* Shut up warning */
+
/* --------------------------------------------------------------------- */
/*
@@ -498,10 +505,10 @@
}
db->bufsize = nr << PAGE_SHIFT;
db->ready = 1;
- dprintk((KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d
ossmaxfrags %d "
- "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt
0x%x\n",
+ dprintk((KERN_DEBUG "usbaudio: dmabuf_init bytepersec %d bufs %d ossfragshift
+%d ossmaxfrags %d "
+ "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x
+srate %d\n",
bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift,
db->fragsize,
- db->numfrag, db->dmasize, db->bufsize, db->format));
+ db->numfrag, db->dmasize, db->bufsize, db->format, db->srate));
return 0;
}
@@ -873,9 +880,11 @@
u->dma.count += cnt;
if (u->format == u->dma.format) {
/* we do not need format conversion */
+ dprintk((KERN_DEBUG "usbaudio: no sample format
+conversion\n"));
dmabuf_copyin(&u->dma, cp, cnt);
} else {
/* we need sampling format conversion */
+ dprintk((KERN_DEBUG "usbaudio: sample format conversion %x !=
+%x\n", u->format, u->dma.format));
usbin_convert(u, cp, scnt);
}
}
@@ -1546,7 +1555,7 @@
d->srate = fmt->sratelo;
if (d->srate > fmt->sratehi)
d->srate = fmt->sratehi;
- dprintk((KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n",
alts->bInterfaceNumber, fmt->altsetting));
+ dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n",
+alts->bInterfaceNumber, fmt->altsetting));
if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {
printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d
interface %d altsetting %d\n",
dev->devnum, u->interface, fmt->altsetting);
@@ -1641,7 +1650,7 @@
d->srate = fmt->sratelo;
if (d->srate > fmt->sratehi)
d->srate = fmt->sratehi;
- dprintk((KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n",
alts->bInterfaceNumber, fmt->altsetting));
+ dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n",
+alts->bInterfaceNumber, fmt->altsetting));
if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d
interface %d altsetting %d\n",
dev->devnum, u->interface, fmt->altsetting);
@@ -2354,12 +2363,18 @@
unsigned long flags;
audio_buf_info abinfo;
count_info cinfo;
- int val, val2, mapped, ret;
+ int val = 0;
+ int val2, mapped, ret;
if (!s->usbdev)
return -EIO;
mapped = ((file->f_mode & FMODE_WRITE) && as->usbout.dma.mapped) ||
((file->f_mode & FMODE_READ) && as->usbin.dma.mapped);
+#if 0
+ if (arg)
+ get_user(val, (int *)arg);
+ printk(KERN_DEBUG "usbaudio: usb_audio_ioctl cmd=%x arg=%lx *arg=%d\n", cmd,
+arg, val)
+#endif
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, (int *)arg);
@@ -2401,8 +2416,14 @@
return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate :
as->usbout.dma.srate, (int *)arg);
case SNDCTL_DSP_STEREO:
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format :
as->usbout.dma.format;
- if (set_format(as, file->f_mode, val2 | AFMT_STEREO, 0))
+ if (val)
+ val2 |= AFMT_STEREO;
+ else
+ val2 &= ~AFMT_STEREO;
+ if (set_format(as, file->f_mode, val2, 0))
return -EIO;
return 0;
@@ -2603,6 +2624,7 @@
case SOUND_PCM_READ_FILTER:
return -EINVAL;
}
+ dprintk((KERN_DEBUG "usbaudio: usb_audio_ioctl - no command found\n"));
return -ENOIOCTLCMD;
}
@@ -2828,8 +2850,10 @@
if (alts->bInterfaceClass != USB_CLASS_AUDIO ||
alts->bInterfaceSubClass != 2)
continue;
if (alts->bNumEndpoints < 1) {
- printk(KERN_ERR "usbaudio: device %u interface %u
altsetting %u does not have an endpoint\n",
- dev->devnum, asifin, i);
+ if (i != 0) { /* altsetting 0 has no endpoints
+(Section B.3.4.1) */
+ printk(KERN_ERR "usbaudio: device %u interface
+%u altsetting %u does not have an endpoint\n",
+ dev->devnum, asifin, i);
+ }
continue;
}
if ((alts->endpoint[0].bmAttributes & 0x03) != 0x01 ||
@@ -2884,8 +2908,10 @@
fp->format = format;
fp->altsetting = i;
fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10]
<< 16);
+ printk(KERN_INFO "usbaudio: valid input sample rate %u\n",
+fp->sratelo);
for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) {
k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] <<
16);
+ printk(KERN_INFO "usbaudio: valid input sample rate
+%u\n", k);
if (k > fp->sratehi)
fp->sratehi = k;
if (k < fp->sratelo)
@@ -2915,6 +2941,7 @@
dev->devnum, asifout, i);
continue;
}
+ /* See USB audio formats manual, section 2 */
fmt = find_csinterface_descriptor(buffer, buflen, NULL,
AS_GENERAL, asifout, i);
if (!fmt) {
printk(KERN_ERR "usbaudio: device %u interface %u
altsetting %u FORMAT_TYPE descriptor not found\n",
@@ -2964,8 +2991,10 @@
fp->format = format;
fp->altsetting = i;
fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10]
<< 16);
+ printk(KERN_INFO "usbaudio: valid output sample rate %u\n",
+fp->sratelo);
for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) {
k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] <<
16);
+ printk(KERN_INFO "usbaudio: valid output sample rate
+%u\n", k);
if (k > fp->sratehi)
fp->sratehi = k;
if (k < fp->sratelo)
@@ -2985,6 +3014,7 @@
kfree(as);
return;
}
+ printk(KERN_INFO "usbaudio: registered dsp 14,%d\n", as->dev_audio);
/* everything successful */
list_add_tail(&as->list, &s->audiolist);
}
@@ -3331,6 +3361,8 @@
state->chconfig = proc[8+proc[6]] | (proc[9+proc[6]] << 8);
}
+
+/* See Audio Class Spec, section 4.3.2.5 */
static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr)
{
struct mixerchannel *ch;
@@ -3348,7 +3380,7 @@
if (state->nrchannels > 2)
printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface
does not support more than 2 channels\n", ftr[3]);
if (state->nrchannels == 1 && ftr[0] == 7+ftr[5]) {
- printk(KERN_WARNING "usbaudio: workaround for broken Philips Camera
Microphone descriptor enabled\n");
+ printk(KERN_DEBUG "usbaudio: workaround for Philips camera microphone
+descriptor enabled\n");
mchftr = ftr[6];
chftr = 0;
} else {
@@ -3478,7 +3510,7 @@
usb_audio_selectorunit(state, p1);
return;
- case FEATURE_UNIT:
+ case FEATURE_UNIT: /* See USB Audio Class Spec 4.3.2.5 */
if (p1[0] < 7 || p1[0] < 7+p1[5]) {
printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT
descriptor\n", unitid);
return;
@@ -3530,7 +3562,7 @@
state.buflen = buflen;
state.ctrlif = ctrlif;
set_bit(oterm[3], &state.unitbitmap); /* mark terminal ID as visited */
- printk(KERN_INFO "usbaudio: constructing mixer for Terminal %u type 0x%04x\n",
+ printk(KERN_DEBUG "usbaudio: constructing mixer for Terminal %u type 0x%04x\n",
oterm[3], oterm[4] | (oterm[5] << 8));
usb_audio_recurseunit(&state, oterm[7]);
if (!state.nrmixch) {
@@ -3549,6 +3581,7 @@
kfree(ms);
return;
}
+ printk(KERN_INFO "usbaudio: registered mixer 14,%d\n", ms->dev_mixer);
list_add_tail(&ms->list, &s->mixerlist);
}
@@ -3733,11 +3766,11 @@
/* we get called with -1 for every audiostreaming interface registered */
if (s == (struct usb_audio_state *)-1) {
- dprintk((KERN_DEBUG "usb_audio_disconnect: called with -1\n"));
+ dprintk((KERN_DEBUG "usbaudio: note, usb_audio_disconnect called with
+-1\n"));
return;
}
if (!s->usbdev) {
- dprintk((KERN_DEBUG "usb_audio_disconnect: already called for %p!\n",
s));
+ dprintk((KERN_DEBUG "usbaudio: error, usb_audio_disconnect already
+called for %p!\n", s));
return;
}
down(&open_sem);
@@ -3751,14 +3784,18 @@
usbout_disc(as);
wake_up(&as->usbin.dma.wait);
wake_up(&as->usbout.dma.wait);
- if (as->dev_audio >= 0)
+ if (as->dev_audio >= 0) {
unregister_sound_dsp(as->dev_audio);
+ printk(KERN_INFO "usbaudio: unregister dsp 14,%d\n",
+as->dev_audio);
+ }
as->dev_audio = -1;
}
for(list = s->mixerlist.next; list != &s->mixerlist; list = list->next) {
ms = list_entry(list, struct usb_mixerdev, list);
- if (ms->dev_mixer >= 0)
+ if (ms->dev_mixer >= 0) {
unregister_sound_mixer(ms->dev_mixer);
+ printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n",
+ms->dev_mixer);
+ }
ms->dev_mixer = -1;
}
release(s);