diff -Naur -X dontdiff /mnt/zip/linux-2.4.10-pre15/Documentation/Configure.help linux/Documentation/Configure.help
--- /mnt/zip/linux-2.4.10-pre15/Documentation/Configure.help	Sun Sep 23 20:22:45 2001
+++ linux/Documentation/Configure.help	Sun Sep 23 21:25:58 2001
@@ -11572,6 +11572,29 @@
   The module will be called catc.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+USB Communication Class Ethernet driver
+CONFIG_USB_CDCETHER
+  This driver supports devices conforming to the Communication Device
+  Class Ethernet Control Model.  This is used in some cable modems.
+  For more details on the specification, get the Communication Device
+  Class specification from <http://www.usb.org>.
+
+  This driver should work with the following devices:
+        * Ericsson PipeRider (all variants)
+        * Motorola (DM100 and SB4100)
+        * Broadcom Cable Modem (reference design)
+        * Toshiba PCX1100U and possibly other cable modems
+
+  The device creates a network device (ethX, where X depends on what
+  other networking devices you have in use), as for a normal PCI
+  or ISA based ethernet network card.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called CDCEther.o.  If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+
 USB Kodak DC-2xx Camera support
 CONFIG_USB_DC2XX
   Say Y here if you want to connect this type of still camera to
diff -Naur -X dontdiff /mnt/zip/linux-2.4.10-pre15/MAINTAINERS linux/MAINTAINERS
--- /mnt/zip/linux-2.4.10-pre15/MAINTAINERS	Sun Sep 23 20:22:46 2001
+++ linux/MAINTAINERS	Sun Sep 23 21:10:13 2001
@@ -1458,7 +1458,7 @@
 
 USB CDC ETHERNET DRIVER
 P:	Brad Hards
-M:	bhards@bigpond.net.au
+M:	bradh@frogmouth.net
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
@@ -1481,7 +1481,7 @@
 
 USB KAWASAKI LSI DRIVER
 P:	Brad Hards
-M:	bhards@bigpond.net.au
+M:	bradh@frogmouth.net
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
diff -Naur -X dontdiff /mnt/zip/linux-2.4.10-pre15/drivers/usb/CDCEther.c linux/drivers/usb/CDCEther.c
--- /mnt/zip/linux-2.4.10-pre15/drivers/usb/CDCEther.c	Sun Sep 23 20:25:09 2001
+++ linux/drivers/usb/CDCEther.c	Sun Sep 23 21:15:22 2001
@@ -29,16 +29,27 @@
 #include <linux/module.h>
 #include "CDCEther.h"
 
-static const char *version = __FILE__ ": v0.98.4 4 July 2001 Brad Hards and another";
+static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another";
 
-// We will attempt to probe anything that is in the
-// communication device class...
-// We will sort through them later.
+/* We need to be selective about what we try to match on, to avoiding loading for a CDC
+ * ACM (ISDN or PSTN) modem */
 static struct usb_device_id CDCEther_ids[] = {
-	{ USB_DEVICE_INFO(2, 0, 0) },
-	{ }
+        { match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
+          bInterfaceClass: USB_CLASS_COMM, bInterfaceSubClass: 6},
+        { } /* Terminating null entry */
 };
 
+/* 
+ * module parameter that provides an alternate upper limit on the 
+ * number of multicast filters we use, with a default to use all
+ * the filters available to us. Note that the actual number used
+ * is the lesser of this parameter and the number returned in the
+ * descriptor for the particular device. See Table 41 of the CDC
+ * spec for more info on the descriptor limit.
+ */
+static int multicast_filter_limit = 32767;
+
+
 //////////////////////////////////////////////////////////////////////////////
 // Callback routines from USB device /////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -409,32 +420,83 @@
 	}
 }
 
+static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
+{
+	usb_control_msg(ether_dev->usb,
+			usb_sndctrlpipe(ether_dev->usb, 0),
+			SET_ETHERNET_PACKET_FILTER, /* request */
+			USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
+			cpu_to_le16(ether_dev->mode_flags), /* value */
+			cpu_to_le16((u16)ether_dev->comm_interface), /* index */
+			NULL,
+			0, /* size */
+			HZ); /* timeout */
+}	
+
+
 static void CDCEther_set_multicast( struct net_device *net )
 {
 	ether_dev_t *ether_dev = net->priv;
+	int i;
+	__u8 *buff;
+	
 
 	// Tell the kernel to stop sending us frames while we get this
 	// all set up.
 	netif_stop_queue(net);
 
-	// Do what we are told.
-	if (net->flags & IFF_PROMISC) {
-		// TODO - Turn on promiscuous mode
-		info( "%s: Promiscuous mode enabled", net->name);
-	} else if (net->flags & IFF_ALLMULTI){
-		// TODO - Here we need to tell the device to block ALL multicast traffic.
-		info("%s: set allmulti", net->name);
-	} else if (net->mc_count > ether_dev->wNumberMCFilters)	{
-		// TODO - Here we need to set multicast filters, but
-		// There are more than our limit...  Hmm...
-		info("%s: set too many MC filters", net->name);
-	} else {
-		// TODO - Here we are supposed to set SOME of the multicast filters.
-		// I must learn how to do this...
-		//info("%s: set Rx mode", net->name);
+      /* Note: do not reorder, GCC is clever about common statements. */
+        if (net->flags & IFF_PROMISC) {
+                /* Unconditionally log net taps. */
+                info( "%s: Promiscuous mode enabled", net->name);
+		ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS |
+			MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+        } else if (net->mc_count > ether_dev->wNumberMCFilters) {
+                /* Too many to filter perfectly -- accept all multicasts. */
+		info("%s: set too many MC filters, using allmulti", net->name);
+		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+	} else if (net->flags & IFF_ALLMULTI) {
+                /* Filter in software */
+		info("%s: using allmulti", net->name);
+		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+        } else {
+		/* do multicast filtering in hardware */
+                struct dev_mc_list *mclist;
+		info("%s: set multicast filters", net->name);
+		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+		buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+                for (i = 0, mclist = net->mc_list;
+		     mclist && i < net->mc_count;
+                     i++, mclist = mclist->next) {
+			memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
+		}
+		usb_control_msg(ether_dev->usb,
+				usb_sndctrlpipe(ether_dev->usb, 0),
+				SET_ETHERNET_MULTICAST_FILTER, /* request */
+				USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
+				cpu_to_le16(net->mc_count), /* value */
+				cpu_to_le16((u16)ether_dev->comm_interface), /* index */
+				buff,
+				(6* net->mc_count), /* size */
+				HZ); /* timeout */
+		kfree(buff);
 	}
-
-	// Tell the kernel to start giving frames to us again.
+ 
+	CDC_SetEthernetPacketFilter(ether_dev);
+	
+        // Tell the kernel to start giving frames to us again.
 	netif_wake_queue(net);
 }
 
@@ -545,6 +607,9 @@
 	ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
 	ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
 	ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;
+	if (ether_dev->wNumberMCFilters > multicast_filter_limit) {
+		ether_dev->wNumberMCFilters = multicast_filter_limit;
+		}	
 	ether_dev->bNumberPowerFilters = data[9];
 	
 	// We've seen one of these now.
@@ -1272,6 +1337,9 @@
 MODULE_AUTHOR("Brad Hards and another");
 MODULE_DESCRIPTION("USB CDC Ethernet driver");
 MODULE_LICENSE("GPL");
+
+MODULE_PARM (multicast_filter_limit, "i");
+MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");
 
 MODULE_DEVICE_TABLE (usb, CDCEther_ids);
 
diff -Naur -X dontdiff /mnt/zip/linux-2.4.10-pre15/drivers/usb/CDCEther.h linux/drivers/usb/CDCEther.h
--- /mnt/zip/linux-2.4.10-pre15/drivers/usb/CDCEther.h	Mon Aug 13 10:37:53 2001
+++ linux/drivers/usb/CDCEther.h	Sun Sep 23 20:49:43 2001
@@ -45,6 +45,15 @@
 #define	CDC_ETHER_REQ_SET_REG	PIPERIDER_REQ_SET_REGS
 #define	ALIGN(x)		x __attribute__((aligned(L1_CACHE_BYTES)))
 
+#define MODE_FLAG_PROMISCUOUS   (1<<0)
+#define MODE_FLAG_ALL_MULTICAST (1<<1)
+#define MODE_FLAG_DIRECTED      (1<<2)
+#define MODE_FLAG_BROADCAST     (1<<3)
+#define MODE_FLAG_MULTICAST     (1<<4)
+
+#define SET_ETHERNET_MULTICAST_FILTER    0x40
+#define SET_ETHERNET_PACKET_FILTER       0x43
+
 typedef struct _ether_dev_t {
 	struct usb_device	*usb;
 	struct net_device	*net;
@@ -70,6 +79,7 @@
 	__u8			iMACAddress;
 	__u32			bmEthernetStatistics;
 	__u16			wMaxSegmentSize;
+	__u16                   mode_flags;
 	__u16			wNumberMCFilters;
 	__u8			bNumberPowerFilters;
 	int			intr_interval;
diff -Naur -X dontdiff /mnt/zip/linux-2.4.10-pre15/drivers/usb/Config.in linux/drivers/usb/Config.in
--- /mnt/zip/linux-2.4.10-pre15/drivers/usb/Config.in	Sun Sep 23 20:25:09 2001
+++ linux/drivers/usb/Config.in	Sun Sep 23 20:52:38 2001
@@ -71,6 +71,7 @@
    comment 'USB Network adaptors'
    dep_tristate '  USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
    dep_tristate '  USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB CDC Ethernet class (USB cable modem) support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
    dep_tristate '  USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
    dep_tristate '  USB-to-USB Networking (NetChip, Prolific, ...) (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
 
diff -Naur -X dontdiff /mnt/zip/linux-2.4.10-pre15/drivers/usb/Makefile linux/drivers/usb/Makefile
--- /mnt/zip/linux-2.4.10-pre15/drivers/usb/Makefile	Sun Sep 23 20:25:09 2001
+++ linux/drivers/usb/Makefile	Sun Sep 23 20:53:15 2001
@@ -70,6 +70,7 @@
 obj-$(CONFIG_USB_PEGASUS)	+= pegasus.o
 obj-$(CONFIG_USB_CATC)		+= catc.o
 obj-$(CONFIG_USB_KAWETH)        += kaweth.o
+obj-$(CONFIG_USB_CDCETHER)	+= CDCEther.o
 obj-$(CONFIG_USB_RIO500)	+= rio500.o
 obj-$(CONFIG_USB_DSBR)		+= dsbr100.o
 obj-$(CONFIG_USB_MICROTEK)	+= microtek.o
diff -Naur -X dontdiff /mnt/zip/linux-2.4.10-pre15/drivers/usb/acm.c linux/drivers/usb/acm.c
--- /mnt/zip/linux-2.4.10-pre15/drivers/usb/acm.c	Sun Sep 23 20:25:09 2001
+++ linux/drivers/usb/acm.c	Sun Sep 23 21:20:30 2001
@@ -1,5 +1,5 @@
 /*
- * acm.c  Version 0.19
+ * acm.c  Version 0.20
  *
  * Copyright (c) 1999 Armin Fuerst	<fuerst@in.tum.de>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
@@ -22,6 +22,7 @@
  *	v0.17 - added new style probing
  *	v0.18 - fixed new style probing for devices with more configurations
  *	v0.19 - fixed CLOCAL handling (thanks to Richard Shih-Ping Chan)
+ *      v0.20 - switched to probing on interface (rather than device) class
  */
 
 /*
@@ -59,7 +60,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.18"
+#define DRIVER_VERSION "v0.20"
 #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
 
@@ -647,7 +648,8 @@
  */
 
 static struct usb_device_id acm_ids[] = {
-	{ USB_DEVICE_INFO(2, 0, 0) },
+	{match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
+	bInterfaceClass: USB_CLASS_COMM, bInterfaceSubClass: 2},
 	{ }
 };
 
