diff -Naru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	2005-04-14 03:20:40 -07:00
+++ b/drivers/usb/class/cdc-acm.c	2005-04-14 03:20:40 -07:00
@@ -581,45 +581,51 @@
 
 	dev = interface_to_usbdev (intf);
 
-		cfacm = dev->actconfig;
-
-		for (j = 0; j < cfacm->desc.bNumInterfaces - 1; j++) {
-		    
-			if (usb_interface_claimed(cfacm->interface[j]) ||
-			    usb_interface_claimed(cfacm->interface[j + 1]))
-			continue;
+			cfacm = dev->actconfig;
+	
+			/* We know we're probe()d with the control interface. */
+			ifcom = intf->cur_altsetting;
 
-			/* We know we're probe()d with the control interface.
-			 * FIXME ACM doesn't guarantee the data interface is
+			/* ACM doesn't guarantee the data interface is
 			 * adjacent to the control interface, or that if one
-			 * is there it's not for call management ... so use
-			 * the cdc union descriptor whenever there is one.
+			 * is there it's not for call management ... so find
+			 * it
 			 */
-			ifcom = intf->cur_altsetting;
-			if (intf == cfacm->interface[j]) {
-				ifdata = cfacm->interface[j + 1]->cur_altsetting;
-				data = cfacm->interface[j + 1];
-			} else if (intf == cfacm->interface[j + 1]) {
+			for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
 				ifdata = cfacm->interface[j]->cur_altsetting;
 				data = cfacm->interface[j];
-			} else
-				continue;
 
-			if (ifdata->desc.bInterfaceClass != 10 || ifdata->desc.bNumEndpoints < 2)
-				continue;
+				if (ifdata->desc.bInterfaceClass == 10 &&
+				    ifdata->desc.bNumEndpoints == 2) {
+					epctrl = &ifcom->endpoint[0].desc;
+					epread = &ifdata->endpoint[0].desc;
+					epwrite = &ifdata->endpoint[1].desc;
+
+					if ((epctrl->bEndpointAddress & 0x80) != 0x80 ||
+					    (epctrl->bmAttributes & 3) != 3 ||
+					    (epread->bmAttributes & 3) != 2 || 
+					    (epwrite->bmAttributes & 3) != 2 ||
+					    ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) 
+						goto next_interface;
+
+					if ((epread->bEndpointAddress & 0x80) != 0x80) {
+						epread = &ifdata->endpoint[1].desc;
+						epwrite = &ifdata->endpoint[0].desc;
+					}
+					dbg("found data interface at %d\n", j);
+					break;
+				} else {
+next_interface:
+					ifdata = NULL;
+					data = NULL;
+				}
+			}
+
+			/* there's been a problem */
+			if (!ifdata) {
+				dbg("interface not found (%p)\n", ifdata);
+				return -ENODEV;
 
-			epctrl = &ifcom->endpoint[0].desc;
-			epread = &ifdata->endpoint[0].desc;
-			epwrite = &ifdata->endpoint[1].desc;
-
-			if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
-			   (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
-			   ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
-				continue;
-
-			if ((epread->bEndpointAddress & 0x80) != 0x80) {
-				epread = &ifdata->endpoint[1].desc;
-				epwrite = &ifdata->endpoint[0].desc;
 			}
 
 			for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
@@ -696,16 +702,21 @@
 			acm->line.databits = 8;
 			acm_set_line(acm, &acm->line);
 
-			usb_driver_claim_interface(&acm_driver, data, acm);
+			if ( (j = usb_driver_claim_interface(&acm_driver, data, acm)) != 0) {
+				err("claim failed");
+				usb_free_urb(acm->ctrlurb);
+				usb_free_urb(acm->readurb);
+				usb_free_urb(acm->writeurb);
+				kfree(acm);
+				kfree(buf);
+				return j;
+			} 
 
 			tty_register_device(acm_tty_driver, minor, &intf->dev);
 
 			acm_table[minor] = acm;
 			usb_set_intfdata (intf, acm);
 			return 0;
-		}
-
-	return -EIO;
 }
 
 static void acm_disconnect(struct usb_interface *intf)
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/22 13:32:24-07:00 colin@colino.net 
#   [PATCH] USB: fix cdc-acm as it is still (differently) broken
# 
# drivers/usb/class/cdc-acm.c
#   2004/04/18 04:18:36-07:00 colin@colino.net +47 -36
#   USB: fix cdc-acm as it is still (differently) broken
#