public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* 2.6.6-rc1: cdc-acm still (differently) broken
@ 2004-04-15 18:11 Colin Leroy
  2004-04-15 18:50 ` [linux-usb-devel] " Oliver Neukum
  2004-04-15 18:54 ` David Brownell
  0 siblings, 2 replies; 10+ messages in thread
From: Colin Leroy @ 2004-04-15 18:11 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 673 bytes --]

Hi,

cdc-acm was broken since after 2.6.4, due to the alt_cursetting changes. I sent a patch, which has been integrated (well, the same one has ;-)) not long ago.
I gave 2.6.6-rc1 a try, and found that cdc-acm is now broken is a new way:
when plugging the phone, acm_probe() fails on interface #0; I traced the problem to this: usb_interface_claimed() returns true - and in fact intf->dev.driver is already cdc-acm (despite the fact that this is the first call to acm_probe() !), for reasons beyond my comprehension.

But, even if the interface is claimed, the intfdata hasn't been set, which allows to do another check: the attached patch fixes this bug. 

HTH,
-- 
Colin

[-- Attachment #2: cdc-acm.patch --]
[-- Type: application/octet-stream, Size: 468 bytes --]

--- drivers/usb/class/cdc-acm.c.orig	2004-04-15 20:04:47.051145144 +0200
+++ drivers/usb/class/cdc-acm.c	2004-04-15 20:05:52.419207688 +0200
@@ -585,7 +585,8 @@
 
 		for (j = 0; j < cfacm->desc.bNumInterfaces - 1; j++) {
 		    
-			if (usb_interface_claimed(cfacm->interface[j]) ||
+			if ((usb_interface_claimed(cfacm->interface[j]) 
+				&& usb_get_intfdata(cfacm->interface[j]) != NULL ) ||
 			    usb_interface_claimed(cfacm->interface[j + 1]))
 				continue;
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-15 18:11 2.6.6-rc1: cdc-acm still (differently) broken Colin Leroy
@ 2004-04-15 18:50 ` Oliver Neukum
  2004-04-15 18:54 ` David Brownell
  1 sibling, 0 replies; 10+ messages in thread
From: Oliver Neukum @ 2004-04-15 18:50 UTC (permalink / raw)
  To: Colin Leroy, linux-kernel; +Cc: linux-usb-devel

Am Donnerstag, 15. April 2004 20:11 schrieb Colin Leroy:
> Hi,
>
> cdc-acm was broken since after 2.6.4, due to the alt_cursetting changes. I
> sent a patch, which has been integrated (well, the same one has ;-)) not
> long ago. I gave 2.6.6-rc1 a try, and found that cdc-acm is now broken is a
> new way: when plugging the phone, acm_probe() fails on interface #0; I
> traced the problem to this: usb_interface_claimed() returns true - and in
> fact intf->dev.driver is already cdc-acm (despite the fact that this is the
> first call to acm_probe() !), for reasons beyond my comprehension.
>
> But, even if the interface is claimed, the intfdata hasn't been set, which
> allows to do another check: the attached patch fixes this bug.

But somebody else may have claimed the interface. You can't simply
assume that only cdc-acm will take the device.

	Regards
		Oliver


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-15 18:11 2.6.6-rc1: cdc-acm still (differently) broken Colin Leroy
  2004-04-15 18:50 ` [linux-usb-devel] " Oliver Neukum
@ 2004-04-15 18:54 ` David Brownell
  2004-04-15 19:23   ` Colin Leroy
  1 sibling, 1 reply; 10+ messages in thread
From: David Brownell @ 2004-04-15 18:54 UTC (permalink / raw)
  To: Colin Leroy; +Cc: linux-kernel, linux-usb-devel

Colin Leroy wrote:
> Hi,
> 
> I gave 2.6.6-rc1 a try, and found that cdc-acm is now broken is a new way:
> ... usb_interface_claimed() returns true ... intf->dev.driver is already cdc-acm 

The interface being probed is by definition not going to be claimed
by any other driver ... it shouldn't check or claim that interface.

That test has always been buggy -- better to just remove it.  For
that matter, usb_interface_claimed() calls should all vanish ... it's
better to fail if claiming the interface fails (one step, not two).
Care to try an updated patch?

This started to matter because as of RC1, usbcore got rid of the last of
some pre-driver-model code for driver binding.  There might be a similar
bug in the ALSA usb audio driver, according to 'grep'.

- Dave



> 
> HTH,



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-15 18:54 ` David Brownell
@ 2004-04-15 19:23   ` Colin Leroy
  2004-04-15 19:59     ` David Brownell
  2004-04-15 20:24     ` Alan Stern
  0 siblings, 2 replies; 10+ messages in thread
From: Colin Leroy @ 2004-04-15 19:23 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-kernel, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 474 bytes --]

On 15 Apr 2004 at 11h04, David Brownell wrote:

Hi David, 

> That test has always been buggy -- better to just remove it.  For
> that matter, usb_interface_claimed() calls should all vanish ... it's
> better to fail if claiming the interface fails (one step, not two).
> Care to try an updated patch?

Like this one? It works. I'm a bit wondering, however, how comes 
usb_interface_claimed() returns true, and the check in 
usb_driver_claim_interface() passes?


-- 
Colin

[-- Attachment #2: cdc-acm.patch --]
[-- Type: application/octet-stream, Size: 924 bytes --]

--- drivers/usb/class/cdc-acm.c.orig	2004-04-15 20:04:47.000000000 +0200
+++ drivers/usb/class/cdc-acm.c	2004-04-15 21:20:00.255123616 +0200
@@ -585,10 +585,6 @@
 
 		for (j = 0; j < cfacm->desc.bNumInterfaces - 1; j++) {
 		    
-			if (usb_interface_claimed(cfacm->interface[j]) ||
-			    usb_interface_claimed(cfacm->interface[j + 1]))
-				continue;
-
 			/* We know we're probe()d with the control interface.
 			 * FIXME ACM doesn't guarantee the data interface is
 			 * adjacent to the control interface, or that if one
@@ -696,7 +692,13 @@
 			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);
+				kfree(acm);
+				kfree(buf);
+				return j;
+			} 
 
 			tty_register_device(acm_tty_driver, minor, &intf->dev);
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-15 19:23   ` Colin Leroy
@ 2004-04-15 19:59     ` David Brownell
  2004-04-16 10:24       ` Colin Leroy
  2004-04-15 20:24     ` Alan Stern
  1 sibling, 1 reply; 10+ messages in thread
From: David Brownell @ 2004-04-15 19:59 UTC (permalink / raw)
  To: Colin Leroy; +Cc: linux-kernel, linux-usb-devel

Hi Colin,

>>That test has always been buggy -- better to just remove it.  For
>>that matter, usb_interface_claimed() calls should all vanish ... it's
>>better to fail if claiming the interface fails (one step, not two).
>>Care to try an updated patch?
> 
> 
> Like this one? It works. I'm a bit wondering, however, how comes 
> usb_interface_claimed() returns true, and the check in 
> usb_driver_claim_interface() passes?

Pretty much like that one, but not leaking the other urbs ... :)

There are two interfaces involved, for "control" and "data".
"Control" is being probed; and "data" is what gets claimed.

For more info, you could see how "usbnet" handles CDC Ethernet;
see how it parses the CDC Union descriptor (which is what the
FIXME refers to).  Or read the CDC spec, from www.usb.org as PDF.

- Dave




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-15 19:23   ` Colin Leroy
  2004-04-15 19:59     ` David Brownell
@ 2004-04-15 20:24     ` Alan Stern
  1 sibling, 0 replies; 10+ messages in thread
From: Alan Stern @ 2004-04-15 20:24 UTC (permalink / raw)
  To: Colin Leroy; +Cc: David Brownell, Kernel development list, USB development list

On Thu, 15 Apr 2004, Colin Leroy wrote:

> Like this one? It works. I'm a bit wondering, however, how comes 
> usb_interface_claimed() returns true, and the check in 
> usb_driver_claim_interface() passes?

While an interface is being probed, usb_interface_claimed() will always
return true for it.  That's because the probing code sets
interface->dev.driver (which is what usb_interface_claimed() tests) before
calling the probe function.  If the probe fails then interface->dev.driver
will be reset.  This all happens inside bus_match() in drivers/base/bus.c.

For the same reason, the test of (dev->driver) in 
usb_driver_claim_interface() -- that is the test you meant, isn't it? -- 
passes (i.e., yields a true value).

Alan Stern


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-15 19:59     ` David Brownell
@ 2004-04-16 10:24       ` Colin Leroy
  2004-04-16 18:44         ` David Brownell
  0 siblings, 1 reply; 10+ messages in thread
From: Colin Leroy @ 2004-04-16 10:24 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-kernel, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 560 bytes --]

On 15 Apr 2004 at 12h04, David Brownell wrote:

Hi, 

> Pretty much like that one, but not leaking the other urbs ... :)

The joys of copy/pasting :)

> There are two interfaces involved, for "control" and "data".
> "Control" is being probed; and "data" is what gets claimed.

Yup, I realized that after sending the mail.

Here's another patch, which fixes the leak. It also fixes the FIXME, by looking at all interfaces to find the data one. Is it correct ?

(indentation is ugly in this part, I'll send a cosmetic patch if this one is accepted)...
-- 
Colin

[-- Attachment #2: cdc-acm.patch --]
[-- Type: application/octet-stream, Size: 3479 bytes --]

--- drivers/usb/class/cdc-acm.c.orig	2004-04-15 20:04:47.000000000 +0200
+++ drivers/usb/class/cdc-acm.c	2004-04-16 12:21:40.120865512 +0200
@@ -581,45 +581,47 @@
 
 	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;
-
-			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;
+
+				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;
+
+					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;
+
 			}
 
 			for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
@@ -696,16 +698,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)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-16 10:24       ` Colin Leroy
@ 2004-04-16 18:44         ` David Brownell
  2004-04-16 21:48           ` [PATCH] " Colin Leroy
  0 siblings, 1 reply; 10+ messages in thread
From: David Brownell @ 2004-04-16 18:44 UTC (permalink / raw)
  To: Colin Leroy; +Cc: linux-kernel, linux-usb-devel

Hi Colin,

> Here's another patch, which fixes the leak. It also fixes the
> FIXME, by looking at all interfaces to find the data one. Is it correct ?

It's looking better, but what I'd rather see is code scanning the
CDC descriptors (see "usbnet").  The deal is that there's actually
no guarantee that there's only one data interface, although that
seems to hold true for many current products.

But unless you're interested in finishing a much-needed rewrite
of that cdc-acm probe() code, this might be a good place to stop.
(Or at least pause!)

- Dave




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-16 18:44         ` David Brownell
@ 2004-04-16 21:48           ` Colin Leroy
  2004-04-17  9:54             ` Colin Leroy
  0 siblings, 1 reply; 10+ messages in thread
From: Colin Leroy @ 2004-04-16 21:48 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-kernel, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 686 bytes --]

On 16 Apr 2004 at 11h04, David Brownell wrote:

Hi, 

> It's looking better, but what I'd rather see is code scanning the
> CDC descriptors (see "usbnet").  The deal is that there's actually
> no guarantee that there's only one data interface, although that
> seems to hold true for many current products.

Ok... However I don't think i'll find the time to do that right now.
So I think I'll take your advice that it's a good place to pause :)

> But unless you're interested in finishing a much-needed rewrite
> of that cdc-acm probe() code, this might be a good place to stop.
> (Or at least pause!)

Ok, here is the cosmetic patch following the previous one, then :)

HTH,
-- 
Colin

[-- Attachment #2: cdc-acm-cosmetic.patch --]
[-- Type: application/octet-stream, Size: 7663 bytes --]

--- drivers/usb/class/cdc-acm.c.new	2004-04-16 23:44:14.208234976 +0200
+++ drivers/usb/class/cdc-acm.c	2004-04-16 23:44:45.442486648 +0200
@@ -581,138 +581,138 @@
 
 	dev = interface_to_usbdev (intf);
 
-			cfacm = dev->actconfig;
-	
-			/* We know we're probe()d with the control interface. */
-			ifcom = intf->cur_altsetting;
-
-			/* 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 find
-			 * it
-			 */
-			for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
-				ifdata = cfacm->interface[j]->cur_altsetting;
-				data = cfacm->interface[j];
-
-				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;
-
-					dbg("found data interface at %d\n", j);
-					break;
-				} else {
+	cfacm = dev->actconfig;
+
+	/* We know we're probe()d with the control interface. */
+	ifcom = intf->cur_altsetting;
+
+	/* 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 find
+	 * it
+	 */
+	for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
+		ifdata = cfacm->interface[j]->cur_altsetting;
+		data = cfacm->interface[j];
+
+		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;
+
+			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;
-
-			}
-
-			for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
-			if (acm_table[minor]) {
-				err("no more free acm devices");
-				return -ENODEV;
-			}
-
-			if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
-				err("out of memory");
-				return -ENOMEM;
-			}
-			memset(acm, 0, sizeof(struct acm));
-
-			ctrlsize = epctrl->wMaxPacketSize;
-			readsize = epread->wMaxPacketSize;
-			acm->writesize = epwrite->wMaxPacketSize;
-			acm->control = intf;
-			acm->data = data;
-			acm->minor = minor;
-			acm->dev = dev;
-
-			acm->bh.func = acm_rx_tasklet;
-			acm->bh.data = (unsigned long) acm;
-			INIT_WORK(&acm->work, acm_softint, acm);
-
-			if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
-				err("out of memory");
-				kfree(acm);
-				return -ENOMEM;
-			}
-
-			acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!acm->ctrlurb) {
-				err("out of memory");
-				kfree(acm);
-				kfree(buf);
-				return -ENOMEM;
-			}
-			acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!acm->readurb) {
-				err("out of memory");
-				usb_free_urb(acm->ctrlurb);
-				kfree(acm);
-				kfree(buf);
-				return -ENOMEM;
-			}
-			acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!acm->writeurb) {
-				err("out of memory");
-				usb_free_urb(acm->readurb);
-				usb_free_urb(acm->ctrlurb);
-				kfree(acm);
-				kfree(buf);
-				return -ENOMEM;
-			}
-
-			usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
-				buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
-
-			usb_fill_bulk_urb(acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
-				buf += ctrlsize, readsize, acm_read_bulk, acm);
-			acm->readurb->transfer_flags |= URB_NO_FSBR;
-
-			usb_fill_bulk_urb(acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
-				buf += readsize, acm->writesize, acm_write_bulk, acm);
-			acm->writeurb->transfer_flags |= URB_NO_FSBR;
-
-			dev_info(&intf->dev, "ttyACM%d: USB ACM device", minor);
-
-			acm_set_control(acm, acm->ctrlout);
-
-			acm->line.speed = cpu_to_le32(9600);
-			acm->line.databits = 8;
-			acm_set_line(acm, &acm->line);
-
-			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;
+			ifdata = NULL;
+			data = NULL;
+		}
+	}
+
+	/* there's been a problem */
+	if (!ifdata) {
+		dbg("interface not found (%p)\n", ifdata);
+		return -ENODEV;
+
+	}
+
+	for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+	if (acm_table[minor]) {
+		err("no more free acm devices");
+		return -ENODEV;
+	}
+
+	if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
+		err("out of memory");
+		return -ENOMEM;
+	}
+	memset(acm, 0, sizeof(struct acm));
+
+	ctrlsize = epctrl->wMaxPacketSize;
+	readsize = epread->wMaxPacketSize;
+	acm->writesize = epwrite->wMaxPacketSize;
+	acm->control = intf;
+	acm->data = data;
+	acm->minor = minor;
+	acm->dev = dev;
+
+	acm->bh.func = acm_rx_tasklet;
+	acm->bh.data = (unsigned long) acm;
+	INIT_WORK(&acm->work, acm_softint, acm);
+
+	if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+		err("out of memory");
+		kfree(acm);
+		return -ENOMEM;
+	}
+
+	acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!acm->ctrlurb) {
+		err("out of memory");
+		kfree(acm);
+		kfree(buf);
+		return -ENOMEM;
+	}
+	acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!acm->readurb) {
+		err("out of memory");
+		usb_free_urb(acm->ctrlurb);
+		kfree(acm);
+		kfree(buf);
+		return -ENOMEM;
+	}
+	acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!acm->writeurb) {
+		err("out of memory");
+		usb_free_urb(acm->readurb);
+		usb_free_urb(acm->ctrlurb);
+		kfree(acm);
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
+		buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+
+	usb_fill_bulk_urb(acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+		buf += ctrlsize, readsize, acm_read_bulk, acm);
+	acm->readurb->transfer_flags |= URB_NO_FSBR;
+
+	usb_fill_bulk_urb(acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+		buf += readsize, acm->writesize, acm_write_bulk, acm);
+	acm->writeurb->transfer_flags |= URB_NO_FSBR;
+
+	dev_info(&intf->dev, "ttyACM%d: USB ACM device", minor);
+
+	acm_set_control(acm, acm->ctrlout);
+
+	acm->line.speed = cpu_to_le32(9600);
+	acm->line.databits = 8;
+	acm_set_line(acm, &acm->line);
+
+	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;
 }
 
 static void acm_disconnect(struct usb_interface *intf)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Re: [linux-usb-devel] 2.6.6-rc1: cdc-acm still (differently) broken
  2004-04-16 21:48           ` [PATCH] " Colin Leroy
@ 2004-04-17  9:54             ` Colin Leroy
  0 siblings, 0 replies; 10+ messages in thread
From: Colin Leroy @ 2004-04-17  9:54 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-kernel, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 187 bytes --]

On 16 Apr 2004 at 23h04, Colin Leroy wrote:

Hi, 

> Ok, here is the cosmetic patch following the previous one, then :)

Uhm, previous patch is broken.
Here are the two again.

-- 
Colin

[-- Attachment #2: 1_cdc-acm.patch --]
[-- Type: application/octet-stream, Size: 3474 bytes --]

--- drivers/usb/class/cdc-acm.c.orig	2004-04-15 20:04:47.000000000 +0200
+++ drivers/usb/class/cdc-acm.c	2004-04-16 12:21:40.120865512 +0200
@@ -581,45 +581,47 @@
 
 	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;
-
-			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;
+
+				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;
+
+					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;
+
 			}
 
 			for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
@@ -696,16 +698,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)

[-- Attachment #3: 2_cdc-acm-cosmetic.patch --]
[-- Type: application/octet-stream, Size: 7663 bytes --]

--- drivers/usb/class/cdc-acm.c.new	2004-04-16 23:44:14.208234976 +0200
+++ drivers/usb/class/cdc-acm.c	2004-04-16 23:44:45.442486648 +0200
@@ -581,138 +581,138 @@
 
 	dev = interface_to_usbdev (intf);
 
-			cfacm = dev->actconfig;
-	
-			/* We know we're probe()d with the control interface. */
-			ifcom = intf->cur_altsetting;
-
-			/* 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 find
-			 * it
-			 */
-			for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
-				ifdata = cfacm->interface[j]->cur_altsetting;
-				data = cfacm->interface[j];
-
-				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;
-
-					dbg("found data interface at %d\n", j);
-					break;
-				} else {
+	cfacm = dev->actconfig;
+
+	/* We know we're probe()d with the control interface. */
+	ifcom = intf->cur_altsetting;
+
+	/* 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 find
+	 * it
+	 */
+	for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
+		ifdata = cfacm->interface[j]->cur_altsetting;
+		data = cfacm->interface[j];
+
+		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;
+
+			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;
-
-			}
-
-			for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
-			if (acm_table[minor]) {
-				err("no more free acm devices");
-				return -ENODEV;
-			}
-
-			if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
-				err("out of memory");
-				return -ENOMEM;
-			}
-			memset(acm, 0, sizeof(struct acm));
-
-			ctrlsize = epctrl->wMaxPacketSize;
-			readsize = epread->wMaxPacketSize;
-			acm->writesize = epwrite->wMaxPacketSize;
-			acm->control = intf;
-			acm->data = data;
-			acm->minor = minor;
-			acm->dev = dev;
-
-			acm->bh.func = acm_rx_tasklet;
-			acm->bh.data = (unsigned long) acm;
-			INIT_WORK(&acm->work, acm_softint, acm);
-
-			if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
-				err("out of memory");
-				kfree(acm);
-				return -ENOMEM;
-			}
-
-			acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!acm->ctrlurb) {
-				err("out of memory");
-				kfree(acm);
-				kfree(buf);
-				return -ENOMEM;
-			}
-			acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!acm->readurb) {
-				err("out of memory");
-				usb_free_urb(acm->ctrlurb);
-				kfree(acm);
-				kfree(buf);
-				return -ENOMEM;
-			}
-			acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!acm->writeurb) {
-				err("out of memory");
-				usb_free_urb(acm->readurb);
-				usb_free_urb(acm->ctrlurb);
-				kfree(acm);
-				kfree(buf);
-				return -ENOMEM;
-			}
-
-			usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
-				buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
-
-			usb_fill_bulk_urb(acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
-				buf += ctrlsize, readsize, acm_read_bulk, acm);
-			acm->readurb->transfer_flags |= URB_NO_FSBR;
-
-			usb_fill_bulk_urb(acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
-				buf += readsize, acm->writesize, acm_write_bulk, acm);
-			acm->writeurb->transfer_flags |= URB_NO_FSBR;
-
-			dev_info(&intf->dev, "ttyACM%d: USB ACM device", minor);
-
-			acm_set_control(acm, acm->ctrlout);
-
-			acm->line.speed = cpu_to_le32(9600);
-			acm->line.databits = 8;
-			acm_set_line(acm, &acm->line);
-
-			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;
+			ifdata = NULL;
+			data = NULL;
+		}
+	}
+
+	/* there's been a problem */
+	if (!ifdata) {
+		dbg("interface not found (%p)\n", ifdata);
+		return -ENODEV;
+
+	}
+
+	for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+	if (acm_table[minor]) {
+		err("no more free acm devices");
+		return -ENODEV;
+	}
+
+	if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
+		err("out of memory");
+		return -ENOMEM;
+	}
+	memset(acm, 0, sizeof(struct acm));
+
+	ctrlsize = epctrl->wMaxPacketSize;
+	readsize = epread->wMaxPacketSize;
+	acm->writesize = epwrite->wMaxPacketSize;
+	acm->control = intf;
+	acm->data = data;
+	acm->minor = minor;
+	acm->dev = dev;
+
+	acm->bh.func = acm_rx_tasklet;
+	acm->bh.data = (unsigned long) acm;
+	INIT_WORK(&acm->work, acm_softint, acm);
+
+	if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+		err("out of memory");
+		kfree(acm);
+		return -ENOMEM;
+	}
+
+	acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!acm->ctrlurb) {
+		err("out of memory");
+		kfree(acm);
+		kfree(buf);
+		return -ENOMEM;
+	}
+	acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!acm->readurb) {
+		err("out of memory");
+		usb_free_urb(acm->ctrlurb);
+		kfree(acm);
+		kfree(buf);
+		return -ENOMEM;
+	}
+	acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!acm->writeurb) {
+		err("out of memory");
+		usb_free_urb(acm->readurb);
+		usb_free_urb(acm->ctrlurb);
+		kfree(acm);
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
+		buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+
+	usb_fill_bulk_urb(acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+		buf += ctrlsize, readsize, acm_read_bulk, acm);
+	acm->readurb->transfer_flags |= URB_NO_FSBR;
+
+	usb_fill_bulk_urb(acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+		buf += readsize, acm->writesize, acm_write_bulk, acm);
+	acm->writeurb->transfer_flags |= URB_NO_FSBR;
+
+	dev_info(&intf->dev, "ttyACM%d: USB ACM device", minor);
+
+	acm_set_control(acm, acm->ctrlout);
+
+	acm->line.speed = cpu_to_le32(9600);
+	acm->line.databits = 8;
+	acm_set_line(acm, &acm->line);
+
+	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;
 }
 
 static void acm_disconnect(struct usb_interface *intf)

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2004-04-17 10:04 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-15 18:11 2.6.6-rc1: cdc-acm still (differently) broken Colin Leroy
2004-04-15 18:50 ` [linux-usb-devel] " Oliver Neukum
2004-04-15 18:54 ` David Brownell
2004-04-15 19:23   ` Colin Leroy
2004-04-15 19:59     ` David Brownell
2004-04-16 10:24       ` Colin Leroy
2004-04-16 18:44         ` David Brownell
2004-04-16 21:48           ` [PATCH] " Colin Leroy
2004-04-17  9:54             ` Colin Leroy
2004-04-15 20:24     ` Alan Stern

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox