Hi,

Here's a patch against 2.5.1-pre7 that fixes the channel selection logic
in the usb audio driver, and removes the USB_ST_* error codes.

thanks,

greg k-h


diff -Nru a/drivers/usb/audio.c b/drivers/usb/audio.c
--- a/drivers/usb/audio.c       Fri Dec  7 21:30:07 2001
+++ b/drivers/usb/audio.c       Fri Dec  7 21:30:07 2001
@@ -899,7 +899,7 @@
        struct usbin *u = &as->usbin;
        unsigned long flags;
        unsigned int mask;
-       int suret = USB_ST_NOERROR;
+       int suret = 0;
 
 #if 0
        printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", 
urb->status, urb->error_count, u->flags);
@@ -917,7 +917,7 @@
        if (!usbin_retire_desc(u, urb) &&
            u->flags & FLG_RUNNING &&
            !usbin_prepare_desc(u, urb) && 
-           (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+           (suret = usb_submit_urb(urb)) == 0) {
                u->flags |= mask;
        } else {
                u->flags &= ~(mask | FLG_RUNNING);
@@ -964,7 +964,7 @@
        struct usbin *u = &as->usbin;
        unsigned long flags;
        unsigned int mask;
-       int suret = USB_ST_NOERROR;
+       int suret = 0;
 
 #if 0
        printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", 
urb->status, urb->error_count, u->flags);
@@ -982,7 +982,7 @@
        if (!usbin_sync_retire_desc(u, urb) &&
            u->flags & FLG_RUNNING &&
            !usbin_sync_prepare_desc(u, urb) && 
-           (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+           (suret = usb_submit_urb(urb)) == 0) {
                u->flags |= mask;
        } else {
                u->flags &= ~(mask | FLG_RUNNING);
@@ -1257,7 +1257,7 @@
        struct usbout *u = &as->usbout;
        unsigned long flags;
        unsigned int mask;
-       int suret = USB_ST_NOERROR;
+       int suret = 0;
 
 #if 0
        printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", 
urb->status, urb->error_count, u->flags);
@@ -1275,7 +1275,7 @@
        if (!usbout_retire_desc(u, urb) &&
            u->flags & FLG_RUNNING &&
            !usbout_prepare_desc(u, urb) && 
-           (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+           (suret = usb_submit_urb(urb)) == 0) {
                u->flags |= mask;
        } else {
                u->flags &= ~(mask | FLG_RUNNING);
@@ -1329,7 +1329,7 @@
        struct usbout *u = &as->usbout;
        unsigned long flags;
        unsigned int mask;
-       int suret = USB_ST_NOERROR;
+       int suret = 0;
 
 #if 0
        printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", 
urb->status, urb->error_count, u->flags);
@@ -1347,7 +1347,7 @@
        if (!usbout_sync_retire_desc(u, urb) &&
            u->flags & FLG_RUNNING &&
            !usbout_sync_prepare_desc(u, urb) && 
-           (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+           (suret = usb_submit_urb(urb)) == 0) {
                u->flags |= mask;
        } else {
                u->flags &= ~(mask | FLG_RUNNING);
@@ -3362,28 +3362,48 @@
        struct usb_device *dev = state->s->usbdev;
        unsigned char data[1];
 #endif
+       unsigned char nr_logical_channels, i;
 
        usb_audio_recurseunit(state, ftr[4]);
+
+       if (ftr[5] == 0 ) {
+               printk(KERN_ERR "usbaudio: wrong controls size in feature unit 
+%u\n",ftr[3]);
+               return;
+       }
+
        if (state->nrchannels == 0) {
                printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", 
ftr[3]);
                return;
        }
        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_DEBUG "usbaudio: workaround for Philips camera microphone 
descriptor enabled\n");
-               mchftr = ftr[6];
-               chftr = 0;
-       } else {
-               if (ftr[0] < 7+ftr[5]*(1+state->nrchannels)) {
-                       printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT 
descriptor\n", ftr[3]);
-                       return;
+
+       nr_logical_channels=(ftr[0]-7)/ftr[5]-1;
+
+       if (nr_logical_channels != state->nrchannels) {
+               printk(KERN_WARNING "usbaudio: warning: found %d of %d logical 
+channels.\n", state->nrchannels,nr_logical_channels);
+
+               if (state->nrchannels == 1 && nr_logical_channels==0) {
+                       printk(KERN_INFO "usbaudio: assuming the channel found is the 
+master channel (got a Philips camera?). Should be fine.\n");
+               } else if (state->nrchannels == 1 && nr_logical_channels==2) {
+                       printk(KERN_INFO "usbaudio: assuming that a stereo channel 
+connected directly to a mixer is missing in search (got Labtec headset?). Should be 
+fine.\n");
+                       state->nrchannels=nr_logical_channels;
+               } else {
+                       printk(KERN_WARNING "usbaudio: no idea what's going on..., 
+contact [EMAIL PROTECTED]\n");
                }
-               mchftr = ftr[6];
+       }
+
+       /* There is always a master channel */
+       mchftr = ftr[6];
+       /* Binary AND over logical channels if they exist */
+       if (nr_logical_channels) {
                chftr = ftr[6+ftr[5]];
-               if (state->nrchannels > 1)
-                       chftr &= ftr[6+2*ftr[5]];
+               for (i = 2; i <= nr_logical_channels; i++)
+                       chftr &= ftr[6+i*ftr[5]];
+       } else {
+               chftr = 0;
        }
+
        /* volume control */
        if (chftr & 2) {
                ch = getmixchannel(state, getvolchannel(state));


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to