On Wed, Apr 03, 2002 at 10:45:09AM -0800, Greg KH wrote:
> [EMAIL PROTECTED], 2002-04-02 16:52:19-08:00, [EMAIL PROTECTED]
>   USB CDCEther driver update
>   
>     1. adds support for devices that don't have the interrupt endpoint, which is
>        basically Sharp Zaurus SL-5000D support. Untested by me, if anyone has this
>        hardware, please test and report.                                          
>     
>     2. Ethtool ioctl support. Currently the link state always reports good, but
>        if I had proper interrupt support on a test device, I could probably make it
>        more logical. Anyone with a CDC Ethernet device that actually reports       
>        anything over the interrupt notification endpoint should get in contact with
>        me.                                                                         
>      
>     3. Removes the ALIGN macro.
>     
>     4. Avoids the "device not claimed" warning.
>     
>     5. General code cleanup.
> 
>  drivers/usb/CDCEther.c |  664 ++++++++++++++++++++++++++++---------------------
>  drivers/usb/CDCEther.h |   58 ++--
>  2 files changed, 428 insertions(+), 294 deletions(-)


# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.302   -> 1.303  
#       drivers/usb/CDCEther.c  1.5     -> 1.6    
#       drivers/usb/CDCEther.h  1.2     -> 1.3    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/04/02      [EMAIL PROTECTED]   1.303
# USB CDCEther driver update
# 
#   1. adds support for devices that don't have the interrupt endpoint, which is
#      basically Sharp Zaurus SL-5000D support. Untested by me, if anyone has this
#      hardware, please test and report.                                          
#   
#   2. Ethtool ioctl support. Currently the link state always reports good, but
#      if I had proper interrupt support on a test device, I could probably make it
#      more logical. Anyone with a CDC Ethernet device that actually reports       
#      anything over the interrupt notification endpoint should get in contact with
#      me.                                                                         
#    
#   3. Removes the ALIGN macro.
#   
#   4. Avoids the "device not claimed" warning.
#   
#   5. General code cleanup.
# --------------------------------------------
#
diff -Nru a/drivers/usb/CDCEther.c b/drivers/usb/CDCEther.c
--- a/drivers/usb/CDCEther.c    Wed Apr  3 10:47:46 2002
+++ b/drivers/usb/CDCEther.c    Wed Apr  3 10:47:46 2002
@@ -1,4 +1,4 @@
-// Portions of this file taken from 
+// Portions of this file taken from
 // Petko Manolov - Petkan ([EMAIL PROTECTED])
 // from his driver pegasus.c
 
@@ -25,20 +25,27 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/usb.h>
 #include <linux/module.h>
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+
+#define DEBUG
+#include <linux/usb.h>
+
 #include "CDCEther.h"
 
-static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another";
+#define SHORT_DRIVER_DESC "CDC Ethernet Class"
+#define DRIVER_VERSION "0.98.6"
 
-/* Take any CDC device, and sort it out in probe() */
+static const char *version = __FILE__ ": " DRIVER_VERSION " 7 Jan 2002 Brad Hards and 
+another";
+// We only try to claim CDC Ethernet model devices */
 static struct usb_device_id CDCEther_ids[] = {
-       { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
-       { } /* Terminating null entry */
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, 6, 0) },
+       { }
 };
 
-/* 
- * module parameter that provides an alternate upper limit on the 
+/*
+ * 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
@@ -47,7 +54,6 @@
  */
 static int multicast_filter_limit = 32767;
 
-
 //////////////////////////////////////////////////////////////////////////////
 // Callback routines from USB device /////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -59,7 +65,16 @@
        int count = urb->actual_length, res;
        struct sk_buff  *skb;
 
-       // Sanity check 
+       switch ( urb->status ) {
+               case USB_ST_NOERROR:
+                       break;
+               case USB_ST_URB_KILLED:
+                       return;
+               default:
+                       dbg("rx status %d", urb->status);
+       }
+
+       // Sanity check
        if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
                dbg("BULK IN callback but driver is not active!");
                return;
@@ -133,7 +148,7 @@
        // Give this to the USB subsystem so it can tell us 
        // when more data arrives.
        if ( (res = usb_submit_urb(&ether_dev->rx_urb)) ) {
-               warn( __FUNCTION__ " failed submint rx_urb %d", res);
+               warn( __FUNCTION__ " failed submit rx_urb %d", res);
        }
        
        // We are no longer busy, show us the frames!!!
@@ -160,47 +175,69 @@
 
        // Hmm...  What on Earth could have happened???
        if ( urb->status ) {
-               info("%s: TX status %d", ether_dev->net->name, urb->status);
+               dbg("%s: TX status %d", ether_dev->net->name, urb->status);
        }
 
        // Update the network interface and tell it we are
        // ready for another frame
        ether_dev->net->trans_start = jiffies;
        netif_wake_queue( ether_dev->net );
+
 }
 
-//static void intr_callback( struct urb *urb )
-//{
-//     ether_dev_t *ether_dev = urb->context;
-//     struct net_device *net;
-//     __u8    *d;
-//
-//     if ( !ether_dev )
-//             return;
-//             
-//     switch ( urb->status ) {
-//             case USB_ST_NOERROR:
-//                     break;
-//             case USB_ST_URB_KILLED:
-//                     return;
-//             default:
-//                     info("intr status %d", urb->status);
-//     }
-//
-//     d = urb->transfer_buffer;
-//     net = ether_dev->net;
-//     if ( d[0] & 0xfc ) {
-//             ether_dev->stats.tx_errors++;
-//             if ( d[0] & TX_UNDERRUN )
-//                     ether_dev->stats.tx_fifo_errors++;
-//             if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
-//                     ether_dev->stats.tx_aborted_errors++;
-//             if ( d[0] & LATE_COL )
-//                     ether_dev->stats.tx_window_errors++;
-//             if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
-//                     ether_dev->stats.tx_carrier_errors++;
-//     }
-//}
+#if 0
+static void setpktfilter_done( struct urb *urb )
+{
+       ether_dev_t *ether_dev = urb->context;
+       struct net_device *net;
+
+       if ( !ether_dev )
+               return;
+       dbg("got ctrl callback for setting packet filter");
+       switch ( urb->status ) {
+               case USB_ST_NOERROR:
+                       break;
+               case USB_ST_URB_KILLED:
+                       return;
+               default:
+                       dbg("intr status %d", urb->status);
+       }
+}
+#endif 
+
+static void intr_callback( struct urb *urb )
+{
+       ether_dev_t *ether_dev = urb->context;
+       struct net_device *net;
+       __u8    *d;
+
+       if ( !ether_dev )
+               return;
+       dbg("got intr callback");
+       switch ( urb->status ) {
+               case USB_ST_NOERROR:
+                       break;
+               case USB_ST_URB_KILLED:
+                       return;
+               default:
+                       dbg("intr status %d", urb->status);
+       }
+
+       d = urb->transfer_buffer;
+       dbg("d: %x", d[0]);
+       net = ether_dev->net;
+       if ( d[0] & 0xfc ) {
+               ether_dev->stats.tx_errors++;
+               if ( d[0] & TX_UNDERRUN )
+                       ether_dev->stats.tx_fifo_errors++;
+               if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
+                       ether_dev->stats.tx_aborted_errors++;
+               if ( d[0] & LATE_COL )
+                       ether_dev->stats.tx_window_errors++;
+               if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
+                       netif_carrier_off(net);
+       }
+}
 
 //////////////////////////////////////////////////////////////////////////////
 // Routines for turning net traffic on and off on the USB side ///////////////
@@ -213,8 +250,8 @@
        // Here would be the time to set the data interface to the configuration where
        // it has two endpoints that use a protocol we can understand.
 
-       if (usb_set_interface( usb, 
-                               ether_dev->data_bInterfaceNumber, 
+       if (usb_set_interface( usb,
+                               ether_dev->data_bInterfaceNumber,
                                ether_dev->data_bAlternateSetting_with_traffic ) )  {
                err("usb_set_interface() failed" );
                err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
@@ -230,8 +267,8 @@
        // no endpoints.  This is what the spec suggests.
 
        if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
-               if (usb_set_interface( ether_dev->usb, 
-                                       ether_dev->data_bInterfaceNumber, 
+               if (usb_set_interface( ether_dev->usb,
+                                       ether_dev->data_bInterfaceNumber,
                                        
ether_dev->data_bAlternateSetting_without_traffic ) )   {
                        err("usb_set_interface() failed");
                }
@@ -326,6 +363,9 @@
        return 0;
 }
 
+//////////////////////////////////////////////////////////////////////////////
+// Standard routines for kernel Ethernet Device //////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
 static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net )
 {
        // Easy enough!
@@ -343,19 +383,33 @@
                return -EIO;
        }
 
-       // Prep a receive URB
+       /* Prep a receive URB */
        FILL_BULK_URB( &ether_dev->rx_urb, ether_dev->usb,
                        usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
-                       ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
+                       ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
                        read_bulk_callback, ether_dev );
 
-       // Put it out there so the device can send us stuff
-       if ( (res = usb_submit_urb(&ether_dev->rx_urb)) )
-       {
-               // Hmm...  Okay...
+       /* Put it out there so the device can send us stuff */
+       if ( (res = usb_submit_urb(&ether_dev->rx_urb)) ) {
+               /* Hmm...  Okay... */
                warn( __FUNCTION__ " failed rx_urb %d", res );
        }
 
+       if (ether_dev->properties & HAVE_NOTIFICATION_ELEMENT) {
+               /* Arm and submit the interrupt URB */
+               FILL_INT_URB( &ether_dev->intr_urb,
+                       ether_dev->usb,
+                       usb_rcvintpipe(ether_dev->usb, ether_dev->comm_ep_in),
+                       ether_dev->intr_buff,
+                       8, /* Transfer buffer length */
+                       intr_callback,
+                       ether_dev,
+                       ether_dev->intr_interval);
+               if ( (res = usb_submit_urb(&ether_dev->intr_urb)) ) {
+                       warn( __FUNCTION__ " failed intr_urb %d", res );
+               }
+       }
+
        // Tell the kernel we are ready to start receiving from it
        netif_start_queue( net );
        
@@ -386,92 +440,133 @@
        usb_unlink_urb( &ether_dev->rx_urb );
        usb_unlink_urb( &ether_dev->tx_urb );
        usb_unlink_urb( &ether_dev->intr_urb );
-       
+       usb_unlink_urb( &ether_dev->ctrl_urb );
+
        // That's it.  I'm done.
        return 0;
 }
 
-static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
+static int netdev_ethtool_ioctl(struct net_device *netdev, void *useraddr)
 {
-       //__u16 *data = (__u16 *)&rq->ifr_data;
-       //ether_dev_t   *ether_dev = net->priv;
+       ether_dev_t *ether_dev = netdev->priv;
+       u32 cmd;
+       char tmp[40];
+
+       if (get_user(cmd, (u32 *)useraddr))
+               return -EFAULT;
+
+       switch (cmd) {
+       /* get driver info */
+       case ETHTOOL_GDRVINFO: {
+       struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+               strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
+               strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+               sprintf(tmp, "usb%d:%d", ether_dev->usb->bus->busnum, 
+ether_dev->usb->devnum);
+               strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
+               sprintf(tmp, "CDC %x.%x", ((ether_dev->bcdCDC & 0xff00)>>8), 
+(ether_dev->bcdCDC & 0x00ff) );
+               strncpy(info.fw_version, tmp, ETHTOOL_BUSINFO_LEN);
+               if (copy_to_user(useraddr, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+       /* get link status */
+       case ETHTOOL_GLINK: {
+               struct ethtool_value edata = {ETHTOOL_GLINK};
+               edata.data = netif_carrier_ok(netdev);
+               if (copy_to_user(useraddr, &edata, sizeof(edata)))
+                       return -EFAULT;
+               return 0;
+       }
+       }
+       dbg("Got unsupported ioctl: %x", cmd);
+       return -EOPNOTSUPP; /* the ethtool user space tool relies on this */
+}
 
-       // No support here yet.
-       // Do we need support???
+static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
+{
        switch(cmd) {
-               case SIOCDEVPRIVATE:
-                       return -EOPNOTSUPP;
-               case SIOCDEVPRIVATE+1:
-                       return -EOPNOTSUPP;
-               case SIOCDEVPRIVATE+2:
-                       //return 0;
-                       return -EOPNOTSUPP;
-               default:
-                       return -EOPNOTSUPP;
+       case SIOCETHTOOL:
+               return netdev_ethtool_ioctl(net, (void *) rq->ifr_data);
+       default:
+               return -ENOTTY; /* per ioctl man page */
        }
 }
 
+/* Multicast routines */
+
 static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
 {
-       usb_control_msg(ether_dev->usb,
+#if 0
+       devrequest *dr = &ether_dev->ctrl_dr;
+       int res;
+
+       dr->requesttype = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE;
+       dr->request = SET_ETHERNET_PACKET_FILTER;
+       dr->value = cpu_to_le16(ether_dev->mode_flags);
+       dr->index = cpu_to_le16((u16)ether_dev->comm_interface);
+       dr->length = 0;
+
+       FILL_CONTROL_URB(&ether_dev->ctrl_urb,
+                       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 */
+                       dr,
+                       NULL,
                        NULL,
-                       0, /* size */
-                       HZ); /* timeout */
-}      
+                       setpktfilter_done,
+                       ether_dev);
+       if ( (res = usb_submit_urb(&ether_dev->ctrl_urb)) ) {
+               warn( __FUNCTION__ " failed submit ctrl_urb %d", res);
+       }
+#endif
 
+}
 
 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);
 
-      /* 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);
+       /* Note: do not reorder, GCC is clever about common statements. */
+       if (net->flags & IFF_PROMISC) {
+               /* Unconditionally log net taps. */
+               dbg( "%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);
+       } else if (net->mc_count > ether_dev->wNumberMCFilters) {
+               /* Too many to filter perfectly -- accept all multicasts. */
+               dbg("%s: too many MC filters for hardware, 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);
+               /* Filter in software */
+               dbg("%s: using allmulti", net->name);
                ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
                        MODE_FLAG_DIRECTED |
                        MODE_FLAG_BROADCAST |
                        MODE_FLAG_MULTICAST;
-        } else {
+       } else {
                /* do multicast filtering in hardware */
-                struct dev_mc_list *mclist;
-               info("%s: set multicast filters", net->name);
+               struct dev_mc_list *mclist;
+               dbg("%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);
+               for (i = 0, mclist = net->mc_list;
+                       mclist && i < net->mc_count;
+                       i++, mclist = mclist->next) {
+                               memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
                }
 #if 0
                usb_control_msg(ether_dev->usb,
@@ -487,10 +582,9 @@
                kfree(buff);
        }
 
-#if 0 
        CDC_SetEthernetPacketFilter(ether_dev);
-#endif 
-        // Tell the kernel to start giving frames to us again.
+
+       /* Tell the kernel to start giving frames to us again. */
        netif_wake_queue(net);
 }
 
@@ -498,40 +592,42 @@
 // Routines used to parse out the Functional Descriptors /////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-static int parse_header_functional_descriptor( int *bFunctionLength, 
-                                               int bDescriptorType, 
+/* Header Descriptor - CDC Spec 5.2.3.1, Table 26 */
+static int parse_header_functional_descriptor( int *bFunctionLength,
+                                               int bDescriptorType,
                                                int bDescriptorSubtype,
                                                unsigned char *data,
                                                ether_dev_t *ether_dev,
                                                int *requirements )
 {
-       // Check to make sure we haven't seen one of these already.
+       /* Check to make sure we haven't seen one of these already. */
        if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
                err( "Multiple Header Functional Descriptors found." );
                return -1;
        }
-       
-       // Is it the right size???
-       if (*bFunctionLength != 5) {
-               info( "Invalid length in Header Functional Descriptor" );
-               // This is a hack to get around a particular device (NO NAMES)
-               // It has this function length set to the length of the
-               // whole class-specific descriptor
-               *bFunctionLength = 5;
+
+       /* Check for appropriate length */
+       if (*bFunctionLength != HEADER_FUNC_DESC_LEN) {
+               dbg( "Invalid length in Header Functional Descriptor, working around 
+it." );
+               /* This is a hack to get around a particular device (NO NAMES)
+                * It has this function length set to the length of the
+                * whole class-specific descriptor */
+               *bFunctionLength = HEADER_FUNC_DESC_LEN;
        }
        
-       // Nothing extremely useful here.
-       // We'll keep it for posterity
+       /* Nothing extremely useful here */
+       /* We'll keep it for posterity */
        ether_dev->bcdCDC = data[0] + (data[1] << 8);
-       dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
+       dbg( "Found Header descriptor, CDC version %x.", ether_dev->bcdCDC);
 
-       // We've seen one of these
+       /* We've seen one of these */
        *requirements &= ~REQ_HDR_FUNC_DESCR;
-       
-       // It's all good.
+
+       /* Success */
        return 0;
 }
 
+/* Union Descriptor - CDC Spec 5.2.3.8, Table 33 */
 static int parse_union_functional_descriptor( int *bFunctionLength, 
                                               int bDescriptorType, 
                                               int bDescriptorSubtype,
@@ -539,77 +635,89 @@
                                               ether_dev_t *ether_dev,
                                               int *requirements )
 {
-       // Check to make sure we haven't seen one of these already.
+       /* Check to make sure we haven't seen one of these already. */
        if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
                err( "Multiple Union Functional Descriptors found." );
                return -1;
        }
 
-       // Is it the right size?
-       if (*bFunctionLength != 5) {
+       /* Check for appropriate length */
+       if (*bFunctionLength != UNION_FUNC_DESC_LEN) {
                // It is NOT the size we expected.
-               err( "Unsupported length in Union Functional Descriptor" );
+               err( "Invalid length in Union Functional Descriptor." );
                return -1;
        }
        
-       // Sanity check of sorts
+       /* Sanity check of sorts */
        if (ether_dev->comm_interface != data[0]) {
-               // This tells us that we are chasing the wrong comm
-               // interface or we are crazy or something else weird.
+               /* This tells us that we are chasing the wrong comm
+                * interface or we are crazy or something else weird. */
                if (ether_dev->comm_interface == data[1]) {
-                       info( "Probably broken Union descriptor, fudging data 
interface" );
-                       // We'll need this in a few microseconds, 
-                       // so guess here, and hope for the best
+                       dbg( "Probably broken Union descriptor, fudging data 
+interface." );
+                       /* We'll need this in a few microseconds,
+                        * so if the comm interface was the first slave,
+                        * then probably the master interface is the data one
+                        * Just hope for the best */
                        ether_dev->data_interface = data[0];
                } else {
-                       err( "Union Functional Descriptor is broken beyond repair" );
+                       err( "Union Functional Descriptor is broken beyond repair." );
                        return -1;
                }
-       } else{ // Descriptor is OK
-                       // We'll need this in a few microseconds!
+       } else{ /* Descriptor is OK */
                ether_dev->data_interface = data[1];
        }
 
-       // We've seen one of these now.
+       /* We've seen one of these */
        *requirements &= ~REQ_UNION_FUNC_DESCR;
-       
-       // Done
+
+       /* Success */
        return 0;
 }
 
-static int parse_ethernet_functional_descriptor( int *bFunctionLength, 
+/* Ethernet Descriptor - CDC Spec 5.2.3.16, Table 41 */
+static int parse_ethernet_functional_descriptor( int *bFunctionLength,
                                                  int bDescriptorType, 
                                                  int bDescriptorSubtype,
                                                  unsigned char *data,
                                                  ether_dev_t *ether_dev,
                                                  int *requirements )
 {
-       // Check to make sure we haven't seen one of these already.
+       //* Check to make sure we haven't seen one of these already. */
        if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
                err( "Multiple Ethernet Functional Descriptors found." );
                return -1;
        }
        
-       // Is it the right size?
-       if (*bFunctionLength != 13) {
-               err( "Invalid length in Ethernet Networking Functional Descriptor" );
+       /* Check for appropriate length */
+       if (*bFunctionLength != ETHERNET_FUNC_DESC_LEN) {
+               err( "Invalid length in Ethernet Networking Functional Descriptor." );
                return -1;
        }
-       
-       // Lots of goodies from this one.  They are all important.
+
+       /* Lots of goodies from this one.  They are all important. */
        ether_dev->iMACAddress = data[0];
        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;
+       ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8));
+       if (ether_dev->wNumberMCFilters & (1 << 15)) {
+               ether_dev->properties |= PERFECT_FILTERING;
+               dbg("Perfect filtering support");
+       } else {
+               dbg("Imperfect filtering support - need sw hashing");
+       }
+       if (0 == (ether_dev->wNumberMCFilters & (0x7f))) {
+               ether_dev->properties |= NO_SET_MULTICAST;
+               dbg("Can't use SetEthernetMulticastFilters request");
+       }
        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.
+       /* We've seen one of these */
        *requirements &= ~REQ_ETH_FUNC_DESCR;
-       
-       // That's all she wrote.
+
+       /* Success */
        return 0;
 }
 
@@ -620,15 +728,15 @@
                                                       ether_dev_t *ether_dev,
                                                       int *requirements )
 {
-       // There should only be one type if we are sane
+       /* There should only be one type if we are sane */
        if (bDescriptorType != CS_INTERFACE) {
-               info( "Invalid bDescriptorType found." );
+               err( "Invalid bDescriptorType found." );
                return -1;
        }
 
-       // The Subtype tells the tale.
-       switch (bDescriptorSubtype){
-               case 0x00:      // Header Functional Descriptor
+       /* The Subtype tells the tale - CDC spec Table 25 */
+       switch (bDescriptorSubtype) {
+               case 0x00:      /* Header Functional Descriptor */
                        return parse_header_functional_descriptor( bFunctionLength,
                                                                   bDescriptorType,
                                                                   bDescriptorSubtype,
@@ -636,7 +744,7 @@
                                                                   ether_dev,
                                                                   requirements );
                        break;
-               case 0x06:      // Union Functional Descriptor
+               case 0x06:      /* Union Functional Descriptor */
                        return parse_union_functional_descriptor( bFunctionLength,
                                                                  bDescriptorType,
                                                                  bDescriptorSubtype,
@@ -644,7 +752,7 @@
                                                                  ether_dev,
                                                                  requirements );
                        break;
-               case 0x0F:      // Ethernet Networking Functional Descriptor
+               case 0x0F:      /* Ethernet Networking Functional Descriptor */
                        return parse_ethernet_functional_descriptor( bFunctionLength,
                                                                     bDescriptorType,
                                                                     
bDescriptorSubtype,
@@ -652,12 +760,12 @@
                                                                     ether_dev,
                                                                     requirements );
                        break;
-               default:        // We don't support this at this time...
-                       // However that doesn't necessarily indicate an error.
-                       dbg( "Unexpected header type %x:", bDescriptorSubtype );
+               default:        /* We don't support this at this time... */
+                               /* However that doesn't necessarily indicate an error. 
+*/
+                       dbg( "Unexpected header type %x.", bDescriptorSubtype );
                        return 0;
        }
-       // How did we get here???
+       /* How did we get here? */
        return -1;
 }
 
@@ -668,46 +776,49 @@
        int bFunctionLength;
        int bDescriptorType;
        int bDescriptorSubtype;
-       int requirements = REQUIREMENTS_TOTAL;
+       int requirements = REQUIREMENTS_TOTAL; /* We init to our needs, and then clear
+                                               * bits as we find the descriptors */
 
-       // As long as there is something here, we will try to parse it
+       /* As long as there is something here, we will try to parse it */
+       /* All of the functional descriptors start with the same 3 byte pattern */
        while (loc < length) {
-               // Length
+               /* Length */
                bFunctionLength = data[loc];
                loc++;
-               
-               // Type
+
+               /* Type */
                bDescriptorType = data[loc];
                loc++;
-               
-               // Subtype
+
+               /* Subtype */
                bDescriptorSubtype = data[loc];
                loc++;
                
-               // ship this off to be processed elsewhere.
+               /* ship this off to be processed */
                rc = parse_protocol_unit_functional_descriptor( &bFunctionLength, 
                                                                bDescriptorType, 
                                                                bDescriptorSubtype, 
                                                                &data[loc],
                                                                ether_dev,
                                                                &requirements );
-               // Did it process okay?
+               /* Did it process okay? */
                if (rc) {
-                       // Something was hosed somewhere.
-                       // No need to continue;
+                       /* Something was hosed somewhere. */
+                       /*  No need to continue */
                        err("Bad descriptor parsing: %x", rc );
                        return -1;
                }
-               // We have already taken three bytes.
+               /* We move the loc pointer along, remembering
+                * that we have already taken three bytes */
                loc += (bFunctionLength - 3);
        }
-       // Check to see if we got everything we need.
+       /* Check to see if we got everything we need. */
        if (requirements) {
                // We missed some of the requirements...
-               err( "Not all required functional descriptors present 0x%08X", 
requirements );
+               err( "Not all required functional descriptors present 0x%08X.", 
+requirements );
                return -1;
        }
-       // We got everything.
+       /* We got everything */
        return 0;
 }
 
@@ -721,28 +832,28 @@
        struct usb_interface *comm_intf_group = NULL;
        struct usb_interface_descriptor *comm_intf = NULL;
        int rc = -1;
-       // The assumption here is that find_ethernet_comm_interface
-       // and find_valid_configuration 
-       // have already filled in the information about where to find
-       // the a valid commication interface.
+       /* The assumption here is that find_ethernet_comm_interface
+        * and find_valid_configuration
+        * have already filled in the information about where to find
+        * the a valid commication interface. */
 
        conf = &( device->config[ether_dev->configuration_num] );
        comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
        comm_intf = &( 
comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
-       // Let's check and see if it has the extra information we need...
 
+       /* Let's check and see if it has the extra information we need */
        if (comm_intf->extralen > 0) {
-               // This is where the information is SUPPOSED to be.
+               /* This is where the information is SUPPOSED to be */
                rc = parse_ethernet_class_information( comm_intf->extra, 
comm_intf->extralen, ether_dev );
        } else if (conf->extralen > 0) {
-               // This is a hack.  The spec says it should be at the interface 
-               // location checked above.  However I have seen it here also.
-               // This is the same device that requires the functional descriptor 
hack above
-               warn( "Ethernet information found at device configuration.  This is 
broken." );
+               /* This is a hack.  The spec says it should be at the interface
+                * location checked above.  However I have seen it here also.
+                * This is the same device that requires the functional descriptor 
+hack above */
+               dbg( "Ethernet information found at device configuration.  Trying to 
+use it anyway." );
                rc = parse_ethernet_class_information( conf->extra, conf->extralen, 
ether_dev );
        } else  {
-               // I don't know where else to look.
-               warn( "No ethernet information found." );
+               /* I don't know where else to look */
+               err( "No ethernet information found." );
                rc = -1;
        }
        return rc;
@@ -757,47 +868,43 @@
        struct usb_config_descriptor *conf = NULL;
        struct usb_interface *data_intf_group = NULL;
        struct usb_interface_descriptor *data_intf = NULL;
-       
-       // Walk through and get to the data interface we are checking.
+
+       /* Walk through and get to the data interface we are checking. */
        conf = &( device->config[ether_dev->configuration_num] );
        data_intf_group = &( conf->interface[ether_dev->data_interface] );
        data_intf = &( 
data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
 
-       // Start out assuming we won't find anything we can use
+       /* Start out assuming we won't find anything we can use */
        ether_dev->data_ep_in = 0;
        ether_dev->data_ep_out = 0;
-       
-       // If these are not BULK endpoints, we don't want them
-       if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {
+
+       /* If these are not BULK endpoints, we don't want them */
+       if ( data_intf->endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK ) {
                return -1;
-       } if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {
+       }
+       if ( data_intf->endpoint[1].bmAttributes != USB_ENDPOINT_XFER_BULK ) {
                return -1;
        }
 
-       // Check the first endpoint to see if it is IN or OUT
-       if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {
-               // This endpoint is IN
+       /* Check the first endpoint to see if it is IN or OUT */
+       if ( data_intf->endpoint[0].bEndpointAddress & USB_DIR_IN ) {
                ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
        } else {
-               // This endpoint is OUT
-               ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 
0x7F;
+               ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress;
                ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
        }
 
-       // Check the second endpoint to see if it is IN or OUT
-       if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {
-               // This endpoint is IN
+       /* Check the second endpoint to see if it is IN or OUT */
+       if ( data_intf->endpoint[1].bEndpointAddress & USB_DIR_IN ) {
                ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
        } else  {
-               // This endpoint is OUT
-               ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 
0x7F;
+               ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress;
                ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
        }
-       
-       // Now make sure we got both an IN and an OUT
+
+       /* Now make sure we got both an IN and an OUT */
        if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
-               // We did get both, we are in good shape...
-               info( "detected BULK OUT packets of size %d", 
ether_dev->data_ep_out_size );
+               dbg( "detected BULK OUT packets of size %d", 
+ether_dev->data_ep_out_size );
                return 0;
        }
        return -1;
@@ -887,45 +994,45 @@
                for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; 
altset_num++ ) {
                        comm_intf = &( comm_intf_group->altsetting[altset_num] );
 
-                       // Is this a communication class of interface of the
-                       // ethernet subclass variety.
-                       if ( ( comm_intf->bInterfaceClass == 0x02 )
-                          && ( comm_intf->bInterfaceSubClass == 0x06 )
-                          && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {
-                               if ( comm_intf->bNumEndpoints == 1 ) {
-                                       // Good, we found one, we will try this one
-                                       // Fill in the structure...
-                                       ether_dev->comm_interface = intf_num;
-                                       ether_dev->comm_bInterfaceNumber = 
comm_intf->bInterfaceNumber;
-                                       ether_dev->comm_interface_altset_num = 
altset_num;
-                                       ether_dev->comm_bAlternateSetting = 
comm_intf->bAlternateSetting;
-
-                                       // Look for the Ethernet Functional Descriptors
-                                       rc = 
find_and_parse_ethernet_class_information( device, ether_dev );
-                                       if (rc) {
-                                               // Nope this was no good after all.
-                                               continue;
-                                       }
-
-                                       // Check that we really can talk to the data
-                                       // interface 
-                                       // This includes # of endpoints, protocols,
-                                       // etc.
-                                       rc = verify_ethernet_data_interface( device, 
ether_dev );
-                                       if (rc) {
-                                               // We got something we didn't like
-                                               continue;
-                                       }
-                                       // This communication interface seems to give 
us everything
-                                       // we require.  We have all the ethernet info 
we need.
-                                       // Let's get out of here and go home right now.
-                                       return 0;
-                               } else {
-                                        // bNumEndPoints != 1
-                                       // We found an interface that had the wrong 
number of 
-                                       // endpoints but would have otherwise been okay
-                               } // end bNumEndpoints check.
-                       } // end interface specifics check.
+                       /* Good, we found one, we will try this one */
+                       /* Fill in the structure */
+                       ether_dev->comm_interface = intf_num;
+                       ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
+                       ether_dev->comm_interface_altset_num = altset_num;
+                       ether_dev->comm_bAlternateSetting = 
+comm_intf->bAlternateSetting;
+
+                       // Look for the Ethernet Functional Descriptors
+                       rc = find_and_parse_ethernet_class_information( device, 
+ether_dev );
+                       if (rc) {
+                               // Nope this was no good after all.
+                               continue;
+                       }
+
+                       /* Check that we really can talk to the data interface
+                        * This includes # of endpoints, protocols, etc. */
+                       rc = verify_ethernet_data_interface( device, ether_dev );
+                       if (rc) {
+                               /* We got something we didn't like */
+                               continue;
+                       }
+                       /* It is a bit ambiguous whether the Ethernet model really 
+requires
+                        * the notification element (usually an interrupt endpoint) or 
+not
+                        * And some products (eg Sharp Zaurus) don't support it, so we
+                        * only use the notification element if present */
+                       /* We check for a sane endpoint before using it */
+                       if ( (comm_intf->bNumEndpoints == 1) &&
+                               (comm_intf->endpoint[0].bEndpointAddress & USB_DIR_IN) 
+&&
+                               (comm_intf->endpoint[0].bmAttributes == 
+USB_ENDPOINT_XFER_INT)) {
+                                       ether_dev->properties |= 
+HAVE_NOTIFICATION_ELEMENT;
+                                       ether_dev->comm_ep_in = 
+(comm_intf->endpoint[0].bEndpointAddress & 0x7F);
+                                       dbg("interrupt address: 
+%x",ether_dev->comm_ep_in);
+                                       ether_dev->intr_interval = 
+(comm_intf->endpoint[0].bInterval);
+                                       dbg("interrupt interval: 
+%d",ether_dev->intr_interval);
+                       }
+                       // This communication interface seems to give us everything
+                       // we require.  We have all the ethernet info we need.
+
+                       return 0;
                } // end for altset_num
        } // end for intf_num
        return -1;
@@ -1005,8 +1112,8 @@
 
 static inline unsigned char hex2dec( unsigned char digit )
 {
-       // Is there a standard way to do this???
-       // I have written this code TOO MANY times.
+       /* Is there a standard way to do this??? */
+       /* I have written this code TOO MANY times. */
        if ( (digit >= '0') && (digit <= '9') ) {
                return (digit - '0');
        }
@@ -1016,9 +1123,14 @@
        if ( (digit >= 'A') && (digit <= 'F') ) {
                return (digit - 'A' + 10);
        }
-       return 0;
+       return 16;
 }
 
+/* CDC Ethernet devices provide the MAC address as a string */
+/* We get an index to the string in the Ethernet functional header */
+/* This routine retrieves the string, sanity checks it, and sets the */
+/* MAC address in the network device */
+/* The encoding is a bit wacky - see CDC Spec Table 41 for details */
 static void set_ethernet_addr( ether_dev_t *ether_dev )
 {
        unsigned char   mac_addr[6];
@@ -1026,7 +1138,7 @@
        int             len;
        unsigned char   buffer[13];
 
-       // Let's assume we don't get anything...
+       /* Let's assume we don't get anything */
        mac_addr[0] = 0x00;
        mac_addr[1] = 0x00;
        mac_addr[2] = 0x00;
@@ -1034,22 +1146,30 @@
        mac_addr[4] = 0x00;
        mac_addr[5] = 0x00;
 
-       // Let's ask the device...
-       len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);
+       /* Let's ask the device */
+       if (0 > (len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 
+13))) {
+               err("Attempting to get MAC address failed: %d", -1*len);
+               return;
+       }
 
-       // Sanity check!
+       /* Sanity check */
        if (len != 12)  {
-               // You gotta love failing sanity checks
+               /* You gotta love failing sanity checks */
                err("Attempting to get MAC address returned %d bytes", len);
                return;
        }
 
-       // Fill in the mac_addr
+       /* Fill in the mac_addr */
        for (i = 0; i < 6; i++) {
-               mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * 
i + 1] );
+               if ((16 == buffer[2 * i]) || (16 == buffer[2 * i + 1])) {
+                       err("Bad value in MAC address");
+               }
+               else {
+                       mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( 
+buffer[2 * i + 1] );
+               }
        }
 
-       // Now copy it over to the kernel's network driver.
+       /* Now copy it over to our network device structure */
        memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
 }
 
@@ -1067,12 +1187,12 @@
        unsigned char sern[256];
        unsigned char *mac_addr;
 
-       // Default empty strings in case we don't find a real one
+       /* Default empty strings in case we don't find a real one */
        manu[0] = 0x00;
        prod[0] = 0x00;
        sern[0] = 0x00;
 
-       // Try to get the device Manufacturer
+       /*  Try to get the device Manufacturer */
        string_num = ether_dev->usb->descriptor.iManufacturer;
        if (string_num) {
                // Put it into its buffer
@@ -1081,7 +1201,7 @@
                manu[len] = 0x00;
        }
 
-       // Try to get the device Product Name
+       /* Try to get the device Product Name */
        string_num = ether_dev->usb->descriptor.iProduct;
        if (string_num) {
                // Put it into its buffer
@@ -1090,7 +1210,7 @@
                prod[len] = 0x00;
        }
 
-       // Try to get the device Serial Number
+       /* Try to get the device Serial Number */
        string_num = ether_dev->usb->descriptor.iSerialNumber;
        if (string_num) {
                // Put it into its buffer
@@ -1099,14 +1219,20 @@
                sern[len] = 0x00;
        }
 
-       // This makes it easier for us to print
+       /* This makes it easier for us to print */
        mac_addr = ether_dev->net->dev_addr;
 
-       // Now send everything we found to the syslog
-       info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X", 
-             ether_dev->net->name, manu, prod, sern, mac_addr[0], 
-             mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], 
-             mac_addr[5] );
+       /* Now send everything we found to the syslog */
+       info( "%s: %s %s %s", ether_dev->net->name, manu, prod, sern);
+       dbg( "%s: %02X:%02X:%02X:%02X:%02X:%02X",
+               ether_dev->net->name,
+               mac_addr[0],
+               mac_addr[1],
+               mac_addr[2],
+               mac_addr[3],
+               mac_addr[4],
+               mac_addr[5] );
+
 }
 
 /* Forward declaration */
@@ -1227,11 +1353,7 @@
        // Send a message to syslog about what we are handling
        log_device_info( ether_dev );
 
-       // I claim this interface to be a CDC Ethernet Networking device
-       usb_driver_claim_interface( &CDCEther_driver, 
-                                   
&(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]), 
-                                   ether_dev );
-       // I claim this interface to be a CDC Ethernet Networking device
+       /* We need to manually claim the data interface, while the comm interface gets 
+claimed in the return */
        usb_driver_claim_interface( &CDCEther_driver, 
                                    
&(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]), 
                                    ether_dev );
@@ -1239,11 +1361,8 @@
        // Does this REALLY do anything???
        usb_inc_dev_use( usb );
 
-       // TODO - last minute HACK
-       ether_dev->comm_ep_in = 5;
-
        // Okay, we are finally done...
-       return NULL;
+       return ether_dev;
 }
 
 
@@ -1313,7 +1432,7 @@
 
 int __init CDCEther_init(void)
 {
-       info( "%s", version );
+       dbg( "%s", version );
        return usb_register( &CDCEther_driver );
 }
 
@@ -1333,10 +1452,9 @@
 MODULE_DESCRIPTION("USB CDC Ethernet driver");
 MODULE_LICENSE("GPL");
 
+MODULE_DEVICE_TABLE (usb, CDCEther_ids);
 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);
 
 //////////////////////////////////////////////////////////////////////////////
 // End of file ///////////////////////////////////////////////////////////////
diff -Nru a/drivers/usb/CDCEther.h b/drivers/usb/CDCEther.h
--- a/drivers/usb/CDCEther.h    Wed Apr  3 10:47:46 2002
+++ b/drivers/usb/CDCEther.h    Wed Apr  3 10:47:46 2002
@@ -1,4 +1,4 @@
-// Portions of this file taken from 
+// Portions of this file taken from
 // Petko Manolov - Petkan ([EMAIL PROTECTED])
 // from his driver pegasus.h
 
@@ -18,11 +18,12 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-
+/* From CDC Spec Table 24 */
 #define CS_INTERFACE                   0x24
 
 #define        CDC_ETHER_MAX_MTU               1536
 
+/* These definitions are used with the ether_dev_t flags element */
 #define        CDC_ETHER_PRESENT               0x00000001
 #define        CDC_ETHER_RUNNING               0x00000002
 #define        CDC_ETHER_TX_BUSY               0x00000004
@@ -31,10 +32,10 @@
 
 #define        CDC_ETHER_TX_TIMEOUT    (HZ*10)
 
-#define        TX_UNDERRUN                             0x80
+#define        TX_UNDERRUN                     0x80
 #define        EXCESSIVE_COL                   0x40
-#define        LATE_COL                                0x20
-#define        NO_CARRIER                              0x10
+#define        LATE_COL                        0x20
+#define        NO_CARRIER                      0x10
 #define        LOSS_CARRIER                    0x08
 #define        JABBER_TIMEOUT                  0x04
 
@@ -43,22 +44,13 @@
 #define        CDC_ETHER_REQ_GET_REGS  0xf0
 #define        CDC_ETHER_REQ_SET_REGS  0xf1
 #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;
        struct net_device_stats stats;
        unsigned                flags;
+       unsigned                properties;
        int                     configuration_num;
        int                     bConfigurationValue;
        int                     comm_interface;
@@ -79,20 +71,44 @@
        __u8                    iMACAddress;
        __u32                   bmEthernetStatistics;
        __u16                   wMaxSegmentSize;
-       __u16                   mode_flags;
        __u16                   wNumberMCFilters;
        __u8                    bNumberPowerFilters;
+       __u16                   mode_flags;
        int                     intr_interval;
-       struct urb              rx_urb, tx_urb, intr_urb;
-       unsigned char           ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
-       unsigned char           ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
-       unsigned char           ALIGN(intr_buff[8]);
+       devrequest              ctrl_dr;
+       struct urb              rx_urb, tx_urb, intr_urb, ctrl_urb;
+       unsigned char           rx_buff[CDC_ETHER_MAX_MTU] 
+__attribute__((aligned(L1_CACHE_BYTES)));
+       unsigned char           tx_buff[CDC_ETHER_MAX_MTU] 
+__attribute__((aligned(L1_CACHE_BYTES)));
+       unsigned char           intr_buff[8] __attribute__((aligned(L1_CACHE_BYTES))) ;
 } ether_dev_t;
 
+/* These definitions used in the Ethernet Packet Filtering requests */
+/* See CDC Spec Table 62 */
+#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)
+
+/* CDC Spec class requests - CDC Spec Table 46 */
+#define SET_ETHERNET_MULTICAST_FILTER    0x40
+#define SET_ETHERNET_PACKET_FILTER       0x43
+
+
+/* These definitions are used with the ether_dev_t properties field */
+#define HAVE_NOTIFICATION_ELEMENT      0x0001
+#define PERFECT_FILTERING              0x0002
+#define NO_SET_MULTICAST               0x0004
+
+/* These definitions are used in the requirements parser */
 #define REQ_HDR_FUNC_DESCR     0x0001
 #define REQ_UNION_FUNC_DESCR   0x0002
 #define REQ_ETH_FUNC_DESCR     0x0004
-#define REQUIREMENTS_TOTAL     0x0007
+#define REQUIREMENTS_TOTAL     REQ_ETH_FUNC_DESCR | REQ_UNION_FUNC_DESCR | 
+REQ_HDR_FUNC_DESCR
 
+/* Some useful lengths */
+#define HEADER_FUNC_DESC_LEN   0x5
+#define UNION_FUNC_DESC_LEN    0x5
+#define ETHERNET_FUNC_DESC_LEN 0xD /* 13 for all you decimal weenies */
 
 

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

Reply via email to