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);

Reply via email to