Please merge to 2.6.3; thanks in advance!

- Dave



[USB] usbnet updates:  new devices, cleanups

New devices:  Aten UC210T, Zaurus SL-6000

Cleanup, factoring out shared CDC glue for Ethernet, Zaurus,
and eventually RNDIS.


--- a/drivers/usb/net/Kconfig   Wed Feb  4 20:30:57 2004
+++ b/drivers/usb/net/Kconfig   Wed Feb  4 20:30:57 2004
@@ -254,13 +254,14 @@
          10/100 Ethernet devices.
 
          This driver should work with at least the following devices:
+           * Aten UC210T
            * ASIX AX88172
            * D-Link DUB-E100
            * Hawking UF200
            * Linksys USB200M
            * Netgear FA120
-           * Intellinet
-           * ST Lab USB Ethernet
+           * Intellinet USB 2.0 Ethernet
+           * ST Lab USB 2.0 Ethernet
            * TrendNet TU2-ET100
 
          This driver creates an interface named "ethX", where X depends on
--- a/drivers/usb/net/usbnet.c  Wed Feb  4 20:30:57 2004
+++ b/drivers/usb/net/usbnet.c  Wed Feb  4 20:30:57 2004
@@ -222,6 +222,7 @@
 #define FLAG_FRAMING_NC        0x0001          /* guard against device dropouts */ 
 #define FLAG_FRAMING_GL        0x0002          /* genelink batches packets */
 #define FLAG_FRAMING_Z 0x0004          /* zaurus adds a trailer */
+#define FLAG_FRAMING_RN        0x0008          /* RNDIS batches, plus huge header */
 
 #define FLAG_NO_SETINT 0x0010          /* device can't set_interface() */
 #define FLAG_ETHER     0x0020          /* maybe use "eth%d" names */
@@ -300,7 +301,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static struct ethtool_ops usbnet_ethtool_ops;
 static void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
 static u32 usbnet_get_link (struct net_device *);
 static u32 usbnet_get_msglevel (struct net_device *);
@@ -364,6 +364,25 @@
        return 0;
 }
 
+static void skb_return (struct usbnet *dev, struct sk_buff *skb)
+{
+       int     status;
+
+       skb->dev = dev->net;
+       skb->protocol = eth_type_trans (skb, dev->net);
+       dev->stats.rx_packets++;
+       dev->stats.rx_bytes += skb->len;
+
+#ifdef VERBOSE
+       devdbg (dev, "< rx, len %d, type 0x%x",
+               skb->len + sizeof (struct ethhdr), skb->protocol);
+#endif
+       memset (skb->cb, 0, sizeof (struct skb_data));
+       status = netif_rx (skb);
+       if (status != NET_RX_SUCCESS)
+               devdbg (dev, "netif_rx status %d", status);
+}
+
 
 #ifdef CONFIG_USB_AN2720
 #define        HAVE_HARDWARE
@@ -818,23 +837,30 @@
 
 
 
-#if    defined (CONFIG_USB_CDCETHER) || defined (CONFIG_USB_ZAURUS)
-
 /*-------------------------------------------------------------------------
  *
- * Communications Device Class, Ethernet Control model
- * 
- * Takes two interfaces.  The DATA interface is inactive till an altsetting
- * is selected.  Configuration data includes class descriptors.
- *
- * Zaurus uses nonstandard framing, and doesn't uniquify its Ethernet
- * addresses, but is otherwise CDC Ether.
- *
- * This should interop with whatever the 2.4 "CDCEther.c" driver
- * (by Brad Hards) talked with.
+ * Communications Device Class declarations.
+ * Used by CDC Ethernet, and some CDC variants
  *
  *-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_USB_CDCETHER
+#define NEED_GENERIC_CDC
+#endif
+
+#ifdef CONFIG_USB_ZAURUS
+/* Ethernet variant uses funky framing, broken ethernet addressing */
+#define NEED_GENERIC_CDC
+#endif
+
+#ifdef CONFIG_USB_RNDIS
+/* ACM variant uses even funkier framing, complex control RPC scheme */
+#define NEED_GENERIC_CDC
+#endif
+
+
+#ifdef NEED_GENERIC_CDC
+
 /* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
 struct header_desc {
        u8      bLength;
@@ -876,43 +902,21 @@
        struct usb_interface    *data;
 };
 
-#include <linux/ctype.h>
-
-static u8 nibble (unsigned char c)
-{
-       if (likely (isdigit (c)))
-               return c - '0';
-       c = toupper (c);
-       if (likely (isxdigit (c)))
-               return 10 + c - 'A';
-       return 0;
-}
-
-static inline int get_ethernet_addr (struct usbnet *dev, struct ether_desc *e)
-{
-       int             tmp, i;
-       unsigned char   buf [13];
-
-       tmp = usb_string (dev->udev, e->iMACAddress, buf, sizeof buf);
-       if (tmp < 0)
-               return tmp;
-       else if (tmp != 12)
-               return -EINVAL;
-       for (i = tmp = 0; i < 6; i++, tmp += 2)
-               dev->net->dev_addr [i] =
-                        (nibble (buf [tmp]) << 4) + nibble (buf [tmp + 1]);
-       return 0;
-}
-
 static struct usb_driver usbnet_driver;
 
-static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
+/*
+ * probes control interface, claims data interface, collects the bulk
+ * endpoints, activates data interface (if needed), maybe sets MTU.
+ * all pure cdc, except for certain firmware workarounds.
+ */
+static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
 {
        u8                              *buf = intf->altsetting->extra;
        int                             len = intf->altsetting->extralen;
        struct usb_interface_descriptor *d;
        struct cdc_state                *info = (void *) &dev->data;
        int                             status;
+       int                             rndis;
 
        if (sizeof dev->data < sizeof *info)
                return -EDOM;
@@ -931,14 +935,23 @@
                                "CDC descriptors on config\n");
        }
 
+       /* this assumes that if there's a non-RNDIS vendor variant
+        * of cdc-acm, it'll fail RNDIS requests cleanly.
+        */
+       rndis = (intf->altsetting->desc.bInterfaceProtocol == 0xff);
+
        memset (info, 0, sizeof *info);
        info->control = intf;
        while (len > 3) {
                if (buf [1] != USB_DT_CS_INTERFACE)
                        goto next_desc;
 
-               /* bDescriptorSubType identifies three "must have" descriptors;
-                * save them for later.
+               /* use bDescriptorSubType to identify the CDC descriptors.
+                * We expect devices with CDC header and union descriptors.
+                * For CDC Ethernet we need the ethernet descriptor.
+                * For RNDIS, ignore two (pointless) CDC modem descriptors
+                * in favor of a complicated OID-based RPC scheme doing what
+                * CDC Ethernet achieves with a simple descriptor.
                 */
                switch (buf [2]) {
                case 0x00:              /* Header, mostly useless */
@@ -1001,8 +1014,6 @@
                                        d->bInterfaceClass);
                                goto bad_desc;
                        }
-                       if (usb_interface_claimed (info->data))
-                               return -EBUSY;
                        break;
                case 0x0F:              /* Ethernet Networking */
                        if (info->ether) {
@@ -1015,13 +1026,20 @@
                                        info->u->bLength);
                                goto bad_desc;
                        }
+                       dev->net->mtu = cpu_to_le16p (
+                                               &info->ether->wMaxSegmentSize)
+                                       - ETH_HLEN;
+                       /* because of Zaurus, we may be ignoring the host
+                        * side link address we were given.
+                        */
                        break;
                }
 next_desc:
                len -= buf [0]; /* bLength */
                buf += buf [0];
        }
-       if (!info->header || !info ->u || !info->ether) {
+
+       if (!info->header || !info->u || (!rndis && !info->ether)) {
                dev_dbg (&intf->dev, "missing cdc %s%s%sdescriptor\n",
                        info->header ? "" : "header ",
                        info->u ? "" : "union ",
@@ -1029,18 +1047,6 @@
                goto bad_desc;
        }
 
-#ifdef CONFIG_USB_ZAURUS
-       /* Zaurus ethernet addresses aren't unique ... */
-       if ((dev->driver_info->flags & FLAG_FRAMING_Z) != 0)
-               /* ignore */ ;
-       else
-#endif
-       {
-               status = get_ethernet_addr (dev, info->ether);
-               if (status < 0)
-                       return status;
-       }
-
        /* claim data interface and set it up ... with side effects.
         * network traffic can't flow until an altsetting is enabled.
         */
@@ -1049,16 +1055,11 @@
                return status;
        status = get_endpoints (dev, info->data);
        if (status < 0) {
+               /* ensure immediate exit from usbnet_disconnect */
+               usb_set_intfdata(info->data, NULL);
                usb_driver_release_interface (&usbnet_driver, info->data);
                return status;
        }
-
-       /* FIXME cdc-ether has some multicast code too, though it complains
-        * in routine cases.  info->ether describes the multicast support.
-        */
-
-       dev->net->mtu = cpu_to_le16p (&info->ether->wMaxSegmentSize)
-               - ETH_HLEN;
        return 0;
 
 bad_desc:
@@ -1072,24 +1073,89 @@
 
        /* disconnect master --> disconnect slave */
        if (intf == info->control && info->data) {
+               /* ensure immediate exit from usbnet_disconnect */
+               usb_set_intfdata(info->data, NULL);
                usb_driver_release_interface (&usbnet_driver, info->data);
                info->data = 0;
        }
 
        /* and vice versa (just in case) */
        else if (intf == info->data && info->control) {
+               /* ensure immediate exit from usbnet_disconnect */
+               usb_set_intfdata(info->control, NULL);
                usb_driver_release_interface (&usbnet_driver, info->control);
                info->control = 0;
        }
-
 }
 
-#endif /* CONFIG_USB_ZAURUS || CONFIG_USB_CDCETHER */
-
+#endif /* NEED_GENERIC_CDC */
 
+
 #ifdef CONFIG_USB_CDCETHER
 #define        HAVE_HARDWARE
 
+/*-------------------------------------------------------------------------
+ *
+ * Communications Device Class, Ethernet Control model
+ * 
+ * Takes two interfaces.  The DATA interface is inactive till an altsetting
+ * is selected.  Configuration data includes class descriptors.
+ *
+ * This should interop with whatever the 2.4 "CDCEther.c" driver
+ * (by Brad Hards) talked with.
+ *
+ *-------------------------------------------------------------------------*/
+
+#include <linux/ctype.h>
+
+static u8 nibble (unsigned char c)
+{
+       if (likely (isdigit (c)))
+               return c - '0';
+       c = toupper (c);
+       if (likely (isxdigit (c)))
+               return 10 + c - 'A';
+       return 0;
+}
+
+static inline int
+get_ethernet_addr (struct usbnet *dev, struct ether_desc *e)
+{
+       int             tmp, i;
+       unsigned char   buf [13];
+
+       tmp = usb_string (dev->udev, e->iMACAddress, buf, sizeof buf);
+       if (tmp < 0)
+               return tmp;
+       else if (tmp != 12)
+               return -EINVAL;
+       for (i = tmp = 0; i < 6; i++, tmp += 2)
+               dev->net->dev_addr [i] =
+                        (nibble (buf [tmp]) << 4) + nibble (buf [tmp + 1]);
+       return 0;
+}
+
+static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
+{
+       int                             status;
+       struct cdc_state                *info = (void *) &dev->data;
+
+       status = generic_cdc_bind (dev, intf);
+       if (status < 0)
+               return status;
+
+       status = get_ethernet_addr (dev, info->ether);
+       if (status < 0) {
+               usb_driver_release_interface (&usbnet_driver, info->data);
+               return status;
+       }
+
+       /* FIXME cdc-ether has some multicast code too, though it complains
+        * in routine cases.  info->ether describes the multicast support.
+        */
+       return 0;
+}
+
 static const struct driver_info        cdc_info = {
        .description =  "CDC Ethernet Device",
        .flags =        FLAG_ETHER,
@@ -1337,7 +1403,6 @@
        struct gl_header        *header;
        struct gl_packet        *packet;
        struct sk_buff          *gl_skb;
-       int                     status;
        u32                     size;
 
        header = (struct gl_header *) skb->data;
@@ -1373,17 +1438,7 @@
 
                        // copy the packet data to the new skb
                        memcpy(skb_put(gl_skb, size), packet->packet_data, size);
-                       gl_skb->dev = dev->net;
-
-                       // determine the packet's protocol ID
-                       gl_skb->protocol = eth_type_trans (gl_skb, dev->net);
-
-                       // update the status
-                       dev->stats.rx_packets++;
-                       dev->stats.rx_bytes += size;
-
-                       // notify os of the received packet
-                       status = netif_rx (gl_skb);
+                       skb_return (dev, skb);
                }
 
                // advance to the next packet
@@ -2141,7 +2196,7 @@
        .description =  "Sharp Zaurus SL-5x00",
        .flags =        FLAG_FRAMING_Z,
        .check_connect = always_connected,
-       .bind =         cdc_bind,
+       .bind =         generic_cdc_bind,
        .unbind =       cdc_unbind,
        .tx_fixup =     zaurus_tx_fixup,
 };
@@ -2256,6 +2311,11 @@
                size = 6 + (sizeof (struct ethhdr) + dev->net->mtu);
        else
 #endif
+#ifdef CONFIG_USB_RNDIS
+       if (dev->driver_info->flags & FLAG_FRAMING_RN)
+               size = RNDIS_MAX_TRANSFER;
+       else
+#endif
                size = (sizeof (struct ethhdr) + dev->net->mtu);
 
        if ((skb = alloc_skb (size, flags)) == 0) {
@@ -2319,23 +2379,9 @@
                goto error;
        // else network stack removes extra byte if we forced a short packet
 
-       if (skb->len) {
-               int     status;
-
-               skb->dev = dev->net;
-               skb->protocol = eth_type_trans (skb, dev->net);
-               dev->stats.rx_packets++;
-               dev->stats.rx_bytes += skb->len;
-
-#ifdef VERBOSE
-               devdbg (dev, "< rx, len %d, type 0x%x",
-                       skb->len + sizeof (struct ethhdr), skb->protocol);
-#endif
-               memset (skb->cb, 0, sizeof (struct skb_data));
-               status = netif_rx (skb);
-               if (status != NET_RX_SUCCESS)
-                       devdbg (dev, "netif_rx status %d", status);
-       } else {
+       if (skb->len)
+               skb_return (dev, skb);
+       else {
                devdbg (dev, "drop");
 error:
                dev->stats.rx_errors++;
@@ -2544,6 +2590,8 @@
                        framing = "GeneSys";
                else if (dev->driver_info->flags & FLAG_FRAMING_Z)
                        framing = "Zaurus";
+               else if (dev->driver_info->flags & FLAG_FRAMING_RN)
+                       framing = "RNDIS";
                else
                        framing = "simple";
 
@@ -2941,6 +2989,8 @@
 
 /*-------------------------------------------------------------------------*/
 
+static struct ethtool_ops usbnet_ethtool_ops;
+
 // precondition: never called in_interrupt
 
 int
@@ -3127,7 +3177,11 @@
        // Hawking UF200, TrendNet TU2-ET100
        USB_DEVICE (0x07b8, 0x420a),
        .driver_info =  (unsigned long) &hawking_uf200_info,
-}, 
+}, {
+       // ATEN UC210T
+       USB_DEVICE (0x0557, 0x2009),
+       .driver_info =  (unsigned long) &ax8817x_info,
+},
 #endif
 
 #ifdef CONFIG_USB_EPSON2888
@@ -3167,6 +3221,14 @@
 },
 #endif
 
+#ifdef CONFIG_USB_RNDIS
+{
+       /* RNDIS is MSFT's un-official variant of CDC ACM */
+       USB_INTERFACE_INFO (USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
+       .driver_info = (unsigned long) &rndis_info,
+},
+#endif
+
 #ifdef CONFIG_USB_ARMLINUX
 /*
  * SA-1100 using standard ARM Linux kernels, or compatible.
@@ -3238,7 +3300,16 @@
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
-       .idProduct              = 0x9031,       /* C-750 */
+       .idProduct              = 0x9031,       /* C-750 C-760 */
+       .bInterfaceClass        = 0x02,
+       .bInterfaceSubClass     = 0x0a,
+       .bInterfaceProtocol     = 0x00,
+       .driver_info =  (unsigned long) &zaurus_pxa_info,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x9032,       /* SL-6000 */
        .bInterfaceClass        = 0x02,
        .bInterfaceSubClass     = 0x0a,
        .bInterfaceProtocol     = 0x00,

Reply via email to