[PATCH] USB: rndis updates (mostly cleanup)
authorDavid Brownell <david-b@pacbell.net>
Thu, 28 Apr 2005 20:45:25 +0000 (13:45 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 27 Jun 2005 21:43:50 +0000 (14:43 -0700)
Some bugfixes and lots of cleanup (net code shrink):

  - On reset, force the RNDIS state machine its initial state

  - Hook up the RNDIS (outgoing) filters to the CDC mechanism

  - Lots of cleanup:
     * Eliminate duplicate copy of OID table;
     * Unify handlying of the OID "query" response data pointer;
     * Reduce code duplication for calculating query response lengths;
     * Remove some checks for "can't happen" errors;
     * Get rid of debugging #ifdefs by making the debug flag an integer level

Most of the patch, by volume, relates to those query response cleanups.
It incidentally shaves off a few hundred bytes of object code.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/ether.c
drivers/usb/gadget/ndis.h
drivers/usb/gadget/rndis.c
drivers/usb/gadget/rndis.h

index 3f783cb..a766c29 100644 (file)
@@ -94,8 +94,9 @@ static const char driver_desc [] = DRIVER_DESC;
 #ifdef CONFIG_USB_ETH_RNDIS
 #include "rndis.h"
 #else
-#define rndis_init() 0
-#define rndis_exit() do{}while(0)
+#define rndis_init()   0
+#define rndis_uninit(x)        do{}while(0)
+#define rndis_exit()   do{}while(0)
 #endif
 
 /* CDC and RNDIS support the same host-chosen outgoing packet filters. */
@@ -395,7 +396,8 @@ static inline int BITRATE(struct usb_gadget *g)
 #define STRING_SUBSET                  8
 #define STRING_RNDIS                   9
 
-#define USB_BUFSIZ     256             /* holds our biggest descriptor */
+/* holds our biggest descriptor (or RNDIS response) */
+#define USB_BUFSIZ     256
 
 /*
  * This device advertises one configuration, eth_config, unless RNDIS
@@ -1124,6 +1126,7 @@ static void eth_reset_config (struct eth_dev *dev)
 
        netif_stop_queue (dev->net);
        netif_carrier_off (dev->net);
+       rndis_uninit(dev->rndis_config);
 
        /* disable endpoints, forcing (synchronous) completion of
         * pending i/o.  then free the requests.
@@ -2565,7 +2568,7 @@ fail0:
                /* these set up a lot of the OIDs that RNDIS needs */
                rndis_set_host_mac (dev->rndis_config, dev->host_mac);
                if (rndis_set_param_dev (dev->rndis_config, dev->net,
-                                        &dev->stats))
+                                        &dev->stats, &dev->cdc_filter))
                        goto fail0;
                if (rndis_set_param_vendor (dev->rndis_config, vendorID,
                                            manufacturer))
index c553bbf..09e3ee4 100644 (file)
@@ -47,17 +47,17 @@ struct NDIS_PM_WAKE_UP_CAPABILITIES {
 #define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE   0x00000004
 
 struct NDIS_PNP_CAPABILITIES {
-       u32                                     Flags;
+       __le32                                  Flags;
        struct NDIS_PM_WAKE_UP_CAPABILITIES     WakeUpCapabilities;
 };
 
 struct NDIS_PM_PACKET_PATTERN {
-       u32     Priority;
-       u32     Reserved;
-       u32     MaskSize;
-       u32     PatternOffset;
-       u32     PatternSize;
-       u32     PatternFlags;
+       __le32  Priority;
+       __le32  Reserved;
+       __le32  MaskSize;
+       __le32  PatternOffset;
+       __le32  PatternSize;
+       __le32  PatternFlags;
 };
 
 
index 7457268..c9a0af2 100644 (file)
@@ -41,6 +41,7 @@
 
 
 #undef RNDIS_PM
+#undef RNDIS_WAKEUP
 #undef VERBOSE
 
 #include "rndis.h"
@@ -60,7 +61,7 @@
        } while (0)
 static int rndis_debug = 0;
 
-module_param (rndis_debug, bool, 0);
+module_param (rndis_debug, int, 0);
 MODULE_PARM_DESC (rndis_debug, "enable debugging");
 
 #else
@@ -78,22 +79,103 @@ static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
 static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1);
 
 /* Function Prototypes */
-static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
-static int rndis_query_response (int configNr, rndis_query_msg_type *buf);
-static int rndis_set_response (int configNr, rndis_set_msg_type *buf);
-static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf);
-static int rndis_keepalive_response (int configNr, 
-                                    rndis_keepalive_msg_type *buf);
-
 static rndis_resp_t *rndis_add_response (int configNr, u32 length);
 
 
+/* supported OIDs */
+static const u32 oid_supported_list [] = 
+{
+       /* the general stuff */
+       OID_GEN_SUPPORTED_LIST,
+       OID_GEN_HARDWARE_STATUS,
+       OID_GEN_MEDIA_SUPPORTED,
+       OID_GEN_MEDIA_IN_USE,
+       OID_GEN_MAXIMUM_FRAME_SIZE,
+       OID_GEN_LINK_SPEED,
+       OID_GEN_TRANSMIT_BLOCK_SIZE,
+       OID_GEN_RECEIVE_BLOCK_SIZE,
+       OID_GEN_VENDOR_ID,
+       OID_GEN_VENDOR_DESCRIPTION,
+       OID_GEN_VENDOR_DRIVER_VERSION,
+       OID_GEN_CURRENT_PACKET_FILTER,
+       OID_GEN_MAXIMUM_TOTAL_SIZE,
+       OID_GEN_MEDIA_CONNECT_STATUS,
+       OID_GEN_PHYSICAL_MEDIUM,
+#if 0
+       OID_GEN_RNDIS_CONFIG_PARAMETER,
+#endif
+       
+       /* the statistical stuff */
+       OID_GEN_XMIT_OK,
+       OID_GEN_RCV_OK,
+       OID_GEN_XMIT_ERROR,
+       OID_GEN_RCV_ERROR,
+       OID_GEN_RCV_NO_BUFFER,
+#ifdef RNDIS_OPTIONAL_STATS
+       OID_GEN_DIRECTED_BYTES_XMIT,
+       OID_GEN_DIRECTED_FRAMES_XMIT,
+       OID_GEN_MULTICAST_BYTES_XMIT,
+       OID_GEN_MULTICAST_FRAMES_XMIT,
+       OID_GEN_BROADCAST_BYTES_XMIT,
+       OID_GEN_BROADCAST_FRAMES_XMIT,
+       OID_GEN_DIRECTED_BYTES_RCV,
+       OID_GEN_DIRECTED_FRAMES_RCV,
+       OID_GEN_MULTICAST_BYTES_RCV,
+       OID_GEN_MULTICAST_FRAMES_RCV,
+       OID_GEN_BROADCAST_BYTES_RCV,
+       OID_GEN_BROADCAST_FRAMES_RCV,
+       OID_GEN_RCV_CRC_ERROR,
+       OID_GEN_TRANSMIT_QUEUE_LENGTH,
+#endif /* RNDIS_OPTIONAL_STATS */
+
+       /* mandatory 802.3 */
+       /* the general stuff */
+       OID_802_3_PERMANENT_ADDRESS,
+       OID_802_3_CURRENT_ADDRESS,
+       OID_802_3_MULTICAST_LIST,
+       OID_802_3_MAC_OPTIONS,
+       OID_802_3_MAXIMUM_LIST_SIZE,
+       
+       /* the statistical stuff */
+       OID_802_3_RCV_ERROR_ALIGNMENT,
+       OID_802_3_XMIT_ONE_COLLISION,
+       OID_802_3_XMIT_MORE_COLLISIONS,
+#ifdef RNDIS_OPTIONAL_STATS
+       OID_802_3_XMIT_DEFERRED,
+       OID_802_3_XMIT_MAX_COLLISIONS,
+       OID_802_3_RCV_OVERRUN,
+       OID_802_3_XMIT_UNDERRUN,
+       OID_802_3_XMIT_HEARTBEAT_FAILURE,
+       OID_802_3_XMIT_TIMES_CRS_LOST,
+       OID_802_3_XMIT_LATE_COLLISIONS,
+#endif /* RNDIS_OPTIONAL_STATS */
+
+#ifdef RNDIS_PM
+       /* PM and wakeup are mandatory for USB: */
+
+       /* power management */
+       OID_PNP_CAPABILITIES,
+       OID_PNP_QUERY_POWER,
+       OID_PNP_SET_POWER,
+
+#ifdef RNDIS_WAKEUP
+       /* wake up host */
+       OID_PNP_ENABLE_WAKE_UP,
+       OID_PNP_ADD_WAKE_UP_PATTERN,
+       OID_PNP_REMOVE_WAKE_UP_PATTERN,
+#endif /* RNDIS_WAKEUP */
+#endif /* RNDIS_PM */
+};
+
+
 /* NDIS Functions */
-static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
+static int
+gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+               rndis_resp_t *r)
 {
        int                     retval = -ENOTSUPP;
-       u32                     length = 0;
-       __le32                  *tmp;
+       u32                     length = 4;     /* usually */
+       __le32                  *outbuf;
        int                     i, count;
        rndis_query_cmplt_type  *resp;
 
@@ -101,7 +183,22 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        resp = (rndis_query_cmplt_type *) r->buf;
 
        if (!resp) return -ENOMEM;
-       
+
+       if (buf_len && rndis_debug > 1) {
+               DEBUG("query OID %08x value, len %d:\n", OID, buf_len);
+               for (i = 0; i < buf_len; i += 16) {
+                       DEBUG ("%03d: %08x %08x %08x %08x\n", i,
+                               le32_to_cpup((__le32 *)&buf[i]),
+                               le32_to_cpup((__le32 *)&buf[i + 4]),
+                               le32_to_cpup((__le32 *)&buf[i + 8]),
+                               le32_to_cpup((__le32 *)&buf[i + 12]));
+               }
+       }
+
+       /* response goes here, right after the header */
+       outbuf = (__le32 *) &resp[1];
+       resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
+
        switch (OID) {
 
        /* general oids (table 4-1) */
@@ -111,42 +208,36 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
                length = sizeof (oid_supported_list);
                count  = length / sizeof (u32);
-               tmp = (__le32 *) ((u8 *)resp + 24);
                for (i = 0; i < count; i++)
-                       tmp[i] = cpu_to_le32 (oid_supported_list[i]);
+                       outbuf[i] = cpu_to_le32 (oid_supported_list[i]);
                retval = 0;
                break;
                
        /* mandatory */
        case OID_GEN_HARDWARE_STATUS:
                DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
-               length = 4;
                /* Bogus question! 
                 * Hardware must be ready to receive high level protocols.
                 * BTW: 
                 * reddite ergo quae sunt Caesaris Caesari
                 * et quae sunt Dei Deo!
                 */
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+               *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
                
        /* mandatory */
        case OID_GEN_MEDIA_SUPPORTED:
                DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = cpu_to_le32 (
-                                       rndis_per_dev_params [configNr].medium);
+               *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
                break;
                
        /* mandatory */
        case OID_GEN_MEDIA_IN_USE:
                DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
-               length = 4;
                /* one medium, one transport... (maybe you do it better) */
-               *((__le32 *) resp + 6) = cpu_to_le32 (
-                                       rndis_per_dev_params [configNr].medium);
+               *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
                break;
                
@@ -154,25 +245,21 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        case OID_GEN_MAXIMUM_FRAME_SIZE:
                DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        /* mandatory */
        case OID_GEN_LINK_SPEED:
-//             DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
-               length = 4;
+               if (rndis_debug > 1)
+                       DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].media_state
-                       == NDIS_MEDIA_STATE_DISCONNECTED)
-                   *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+                               == NDIS_MEDIA_STATE_DISCONNECTED)
+                       *outbuf = __constant_cpu_to_le32 (0);
                else
-                   *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].speed);
                retval = 0;
                break;
@@ -181,8 +268,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        case OID_GEN_TRANSMIT_BLOCK_SIZE:
                DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
                        retval = 0;
                }
@@ -192,8 +278,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        case OID_GEN_RECEIVE_BLOCK_SIZE:
                DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
                        retval = 0;
                }
@@ -202,8 +287,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        /* mandatory */
        case OID_GEN_VENDOR_ID:
                DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = cpu_to_le32 (
+               *outbuf = cpu_to_le32 (
                        rndis_per_dev_params [configNr].vendorID);
                retval = 0;
                break;
@@ -212,51 +296,44 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        case OID_GEN_VENDOR_DESCRIPTION:
                DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
                length = strlen (rndis_per_dev_params [configNr].vendorDescr);
-               memcpy ((u8 *) resp + 24, 
+               memcpy (outbuf,
                        rndis_per_dev_params [configNr].vendorDescr, length);
                retval = 0;
                break;
 
        case OID_GEN_VENDOR_DRIVER_VERSION:
                DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
-               length = 4;
                /* Created as LE */
-               *((__le32 *) resp + 6) = rndis_driver_version;
+               *outbuf = rndis_driver_version;
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_CURRENT_PACKET_FILTER:
                DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = cpu_to_le32 (
-                                       rndis_per_dev_params[configNr].filter);
+               *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MAXIMUM_TOTAL_SIZE:
                DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32(
-                                       RNDIS_MAX_TOTAL_SIZE);
+               *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MEDIA_CONNECT_STATUS:
-               DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = cpu_to_le32 (
-                                       rndis_per_dev_params [configNr]
+               if (rndis_debug > 1)
+                       DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
+               *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                                .media_state);
                retval = 0;
                break;
 
        case OID_GEN_PHYSICAL_MEDIUM:
                DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+               *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
@@ -266,8 +343,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
         */
        case OID_GEN_MAC_OPTIONS:               /* from WinME */
                DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32(
+               *outbuf = __constant_cpu_to_le32(
                          NDIS_MAC_OPTION_RECEIVE_SERIALIZED
                        | NDIS_MAC_OPTION_FULL_DUPLEX);
                retval = 0;
@@ -277,62 +353,49 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
 
        /* mandatory */
        case OID_GEN_XMIT_OK:
-               DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
+               if (rndis_debug > 1)
+                       DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                            rndis_per_dev_params [configNr].stats->tx_packets - 
                            rndis_per_dev_params [configNr].stats->tx_errors -
                            rndis_per_dev_params [configNr].stats->tx_dropped);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
 
        /* mandatory */
        case OID_GEN_RCV_OK:
-               DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
+               if (rndis_debug > 1)
+                       DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                            rndis_per_dev_params [configNr].stats->rx_packets - 
                            rndis_per_dev_params [configNr].stats->rx_errors -
                            rndis_per_dev_params [configNr].stats->rx_dropped);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        /* mandatory */
        case OID_GEN_XMIT_ERROR:
-               DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
+               if (rndis_debug > 1)
+                       DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_errors);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        /* mandatory */
        case OID_GEN_RCV_ERROR:
-               DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
+               if (rndis_debug > 1)
+                       DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_errors);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
@@ -340,13 +403,9 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        case OID_GEN_RCV_NO_BUFFER:
                DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_dropped);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
 
@@ -359,8 +418,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                 * divided by weight of Alpha Centauri
                 */
                if (rndis_per_dev_params [configNr].stats) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                                (rndis_per_dev_params [configNr]
                                        .stats->tx_packets - 
                                 rndis_per_dev_params [configNr]
@@ -369,9 +427,6 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                                         .stats->tx_dropped)
                                * 123);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
@@ -379,8 +434,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
                /* dito */
                if (rndis_per_dev_params [configNr].stats) {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
+                       *outbuf = cpu_to_le32 (
                                (rndis_per_dev_params [configNr]
                                        .stats->tx_packets - 
                                 rndis_per_dev_params [configNr]
@@ -389,144 +443,105 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                                         .stats->tx_dropped)
                                / 123);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_MULTICAST_BYTES_XMIT:
                DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast*1234);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_MULTICAST_FRAMES_XMIT:
                DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_BROADCAST_BYTES_XMIT:
                DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_packets/42*255);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_BROADCAST_FRAMES_XMIT:
                DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->tx_packets/42);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_DIRECTED_BYTES_RCV:
                DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+               *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
                
        case OID_GEN_DIRECTED_FRAMES_RCV:
                DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+               *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
                
        case OID_GEN_MULTICAST_BYTES_RCV:
                DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast * 1111);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_MULTICAST_FRAMES_RCV:
                DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->multicast);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_BROADCAST_BYTES_RCV:
                DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_packets/42*255);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_BROADCAST_FRAMES_RCV:
                DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_packets/42);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_RCV_CRC_ERROR:
                DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].stats) {
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_crc_errors);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
                DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+               *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 #endif /* RNDIS_OPTIONAL_STATS */
@@ -538,13 +553,10 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
-                       memcpy ((u8 *) resp + 24,
+                       memcpy (outbuf,
                                rndis_per_dev_params [configNr].host_mac,
                                length);
                        retval = 0;
-               } else {
-                       *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
-                       retval = 0;
                }
                break;
                
@@ -553,7 +565,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
-                       memcpy ((u8 *) resp + 24,
+                       memcpy (outbuf,
                                rndis_per_dev_params [configNr].host_mac,
                                length);
                        retval = 0;
@@ -563,18 +575,16 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        /* mandatory */
        case OID_802_3_MULTICAST_LIST:
                DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
-               length = 4;
                /* Multicast base address only */
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
+               *outbuf = __constant_cpu_to_le32 (0xE0000000);
                retval = 0;
                break;
                
        /* mandatory */
        case OID_802_3_MAXIMUM_LIST_SIZE:
                DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
-                length = 4;
                /* Multicast base address only */
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (1);
+               *outbuf = __constant_cpu_to_le32 (1);
                retval = 0;
                break;
                
@@ -587,11 +597,8 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        /* mandatory */
        case OID_802_3_RCV_ERROR_ALIGNMENT:
                DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
-               if (rndis_per_dev_params [configNr].stats)
-               {
-                       length = 4;
-                       *((__le32 *) resp + 6) = cpu_to_le32 (
-                               rndis_per_dev_params [configNr]
+               if (rndis_per_dev_params [configNr].stats) {
+                       *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                        .stats->rx_frame_errors);
                        retval = 0;
                }
@@ -600,16 +607,14 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        /* mandatory */
        case OID_802_3_XMIT_ONE_COLLISION:
                DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+               *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
                
        /* mandatory */
        case OID_802_3_XMIT_MORE_COLLISIONS:
                DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
-               length = 4;
-               *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
+               *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
                
@@ -655,27 +660,18 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
        case OID_PNP_CAPABILITIES:
                DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
 
-               /* just PM, and remote wakeup on link status change
-                * (not magic packet or pattern match)
-                */
+               /* for now, no wakeup capabilities */
                length = sizeof (struct NDIS_PNP_CAPABILITIES);
-               memset (resp, 0, length);
-               {
-                       struct NDIS_PNP_CAPABILITIES *caps = (void *) resp;
-
-                       caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE;
-                       caps->WakeUpCapabilities.MinLinkChangeWakeUp 
-                                = NdisDeviceStateD3;
-
-                       /* FIXME then use usb_gadget_wakeup(), and
-                        * set USB_CONFIG_ATT_WAKEUP in config desc
-                        */
-               }
+               memset(outbuf, 0, length);
                retval = 0;
                break;
        case OID_PNP_QUERY_POWER:
-               DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__);
-               /* sure, handle any power state that maps to USB suspend */
+               DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
+                               le32_to_cpup((__le32 *) buf) - 1);
+               /* only suspend is a real power state, and
+                * it can't be entered by OID_PNP_SET_POWER...
+                */
+               length = 0;
                retval = 0;
                break;
 #endif
@@ -684,11 +680,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
                printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", 
                         __FUNCTION__, OID);
        }
+       if (retval < 0)
+               length = 0;
        
-       resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
        resp->InformationBufferLength = cpu_to_le32 (length);
-       resp->MessageLength = cpu_to_le32 (24 + length);
-       r->length = 24 + length;
+       r->length = length + sizeof *resp;
+       resp->MessageLength = cpu_to_le32 (r->length);
        return retval;
 }
 
@@ -705,45 +702,40 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
        if (!resp)
                return -ENOMEM;
 
-       DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
-       for (i = 0; i < buf_len; i += 16) {
-               DEBUG ("%03d: "
-                       " %02x %02x %02x %02x"
-                       " %02x %02x %02x %02x"
-                       " %02x %02x %02x %02x"
-                       " %02x %02x %02x %02x"
-                       "\n",
-                       i,
-                       buf[i], buf [i+1],
-                               buf[i+2], buf[i+3],
-                       buf[i+4], buf [i+5],
-                               buf[i+6], buf[i+7],
-                       buf[i+8], buf [i+9],
-                               buf[i+10], buf[i+11],
-                       buf[i+12], buf [i+13],
-                               buf[i+14], buf[i+15]);
+       if (buf_len && rndis_debug > 1) {
+               DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
+               for (i = 0; i < buf_len; i += 16) {
+                       DEBUG ("%03d: %08x %08x %08x %08x\n", i,
+                               le32_to_cpup((__le32 *)&buf[i]),
+                               le32_to_cpup((__le32 *)&buf[i + 4]),
+                               le32_to_cpup((__le32 *)&buf[i + 8]),
+                               le32_to_cpup((__le32 *)&buf[i + 12]));
+               }
        }
 
+       params = &rndis_per_dev_params [configNr];
        switch (OID) {
        case OID_GEN_CURRENT_PACKET_FILTER:
-               params = &rndis_per_dev_params [configNr];
-               retval = 0;
 
-               /* FIXME use these NDIS_PACKET_TYPE_* bitflags to
-                * set the cdc_filter; it's not RNDIS-specific
+               /* these NDIS_PACKET_TYPE_* bitflags are shared with
+                * cdc_filter; it's not RNDIS-specific
                 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
                 *      PROMISCUOUS, DIRECTED,
                 *      MULTICAST, ALL_MULTICAST, BROADCAST
                 */
-               params->filter = le32_to_cpup((__le32 *)buf);
+               *params->filter = (u16) le32_to_cpup((__le32 *)buf);
                DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
-                       __FUNCTION__, params->filter);
+                       __FUNCTION__, *params->filter);
 
                /* this call has a significant side effect:  it's
                 * what makes the packet flow start and stop, like
                 * activating the CDC Ethernet altsetting.
                 */
-               if (params->filter) {
+#ifdef RNDIS_PM
+update_linkstate:
+#endif
+               retval = 0;
+               if (*params->filter) {
                        params->state = RNDIS_DATA_INITIALIZED;
                        netif_carrier_on(params->dev);
                        if (netif_running(params->dev))
@@ -776,21 +768,34 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
 
 #ifdef RNDIS_PM
        case OID_PNP_SET_POWER:
-               DEBUG ("OID_PNP_SET_POWER\n");
-               /* sure, handle any power state that maps to USB suspend */
-               retval = 0;
-               break;
-
-       case OID_PNP_ENABLE_WAKE_UP:
-               /* always-connected ... */
-               DEBUG ("OID_PNP_ENABLE_WAKE_UP\n");
-               retval = 0;
+               /* The only real power state is USB suspend, and RNDIS requests
+                * can't enter it; this one isn't really about power.  After
+                * resuming, Windows forces a reset, and then SET_POWER D0.
+                * FIXME ... then things go batty; Windows wedges itself.
+                */
+               i = le32_to_cpup((__force __le32 *)buf);
+               DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
+               switch (i) {
+               case NdisDeviceStateD0:
+                       *params->filter = params->saved_filter;
+                       goto update_linkstate;
+               case NdisDeviceStateD3:
+               case NdisDeviceStateD2:
+               case NdisDeviceStateD1:
+                       params->saved_filter = *params->filter;
+                       retval = 0;
+                       break;
+               }
                break;
 
-       // no PM resume patterns supported (specified where?)
-       // so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails
+#ifdef RNDIS_WAKEUP
+       // no wakeup support advertised, so wakeup OIDs always fail:
+       //  - OID_PNP_ENABLE_WAKE_UP
+       //  - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
 #endif
 
+#endif /* RNDIS_PM */
+
        default:
                printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", 
                         __FUNCTION__, OID, buf_len);
@@ -811,13 +816,10 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
        if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
        
        r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
-       
-       if (!r) return -ENOMEM;
-       
+       if (!r)
+               return -ENOMEM;
        resp = (rndis_init_cmplt_type *) r->buf;
        
-       if (!resp) return -ENOMEM;
-       
        resp->MessageType = __constant_cpu_to_le32 (
                        REMOTE_NDIS_INITIALIZE_CMPLT);
        resp->MessageLength = __constant_cpu_to_le32 (52);
@@ -857,20 +859,22 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
         * oid_supported_list is the largest answer 
         */
        r = rndis_add_response (configNr, sizeof (oid_supported_list));
-       
-       if (!r) return -ENOMEM;
+       if (!r)
+               return -ENOMEM;
        resp = (rndis_query_cmplt_type *) r->buf;
        
-       if (!resp) return -ENOMEM;
-       
        resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
-       resp->MessageLength = __constant_cpu_to_le32 (24);
        resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-       
-       if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) {
+       
+       if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),
+                       le32_to_cpu(buf->InformationBufferOffset)
+                                       + 8 + (u8 *) buf,
+                       le32_to_cpu(buf->InformationBufferLength),
+                       r)) {
                /* OID not supported */
                resp->Status = __constant_cpu_to_le32 (
                                RNDIS_STATUS_NOT_SUPPORTED);
+               resp->MessageLength = __constant_cpu_to_le32 (sizeof *resp);
                resp->InformationBufferLength = __constant_cpu_to_le32 (0);
                resp->InformationBufferOffset = __constant_cpu_to_le32 (0);
        } else
@@ -889,10 +893,9 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
        rndis_resp_t            *r;
        
        r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
-       
-       if (!r) return -ENOMEM;
+       if (!r)
+               return -ENOMEM;
        resp = (rndis_set_cmplt_type *) r->buf;
-       if (!resp) return -ENOMEM;
 
        BufLength = le32_to_cpu (buf->InformationBufferLength);
        BufOffset = le32_to_cpu (buf->InformationBufferOffset);
@@ -930,10 +933,9 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
        rndis_resp_t            *r;
        
        r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
-       
-       if (!r) return -ENOMEM;
+       if (!r)
+               return -ENOMEM;
        resp = (rndis_reset_cmplt_type *) r->buf;
-       if (!resp) return -ENOMEM;
        
        resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
        resp->MessageLength = __constant_cpu_to_le32 (16);
@@ -957,8 +959,9 @@ static int rndis_keepalive_response (int configNr,
        /* host "should" check only in RNDIS_DATA_INITIALIZED state */
 
        r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
+       if (!r)
+               return -ENOMEM;
        resp = (rndis_keepalive_cmplt_type *) r->buf;
-       if (!resp) return -ENOMEM;
                
        resp->MessageType = __constant_cpu_to_le32 (
                        REMOTE_NDIS_KEEPALIVE_CMPLT);
@@ -987,10 +990,9 @@ static int rndis_indicate_status_msg (int configNr, u32 status)
        
        r = rndis_add_response (configNr, 
                                sizeof (rndis_indicate_status_msg_type));
-       if (!r) return -ENOMEM;
-       
+       if (!r)
+               return -ENOMEM;
        resp = (rndis_indicate_status_msg_type *) r->buf;
-       if (!resp) return -ENOMEM;
        
        resp->MessageType = __constant_cpu_to_le32 (
                        REMOTE_NDIS_INDICATE_STATUS_MSG);
@@ -1021,6 +1023,15 @@ int rndis_signal_disconnect (int configNr)
                                          RNDIS_STATUS_MEDIA_DISCONNECT);
 }
 
+void rndis_uninit (int configNr)
+{
+       if (configNr >= RNDIS_MAX_CONFIGS)
+               return;
+       rndis_per_dev_params [configNr].used = 0;
+       rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
+       return;
+}
+
 void rndis_set_host_mac (int configNr, const u8 *addr)
 {
        rndis_per_dev_params [configNr].host_mac = addr;
@@ -1046,9 +1057,13 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                return -ENOTSUPP;
        params = &rndis_per_dev_params [configNr];
        
+       /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
+        * rx/tx statistics and link status, in addition to KEEPALIVE traffic
+        * and normal HC level polling to see if there's any IN traffic.
+        */
+
        /* For USB: responses may take up to 10 seconds */
-       switch (MsgType)
-       {
+       switch (MsgType) {
        case REMOTE_NDIS_INITIALIZE_MSG:
                DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", 
                        __FUNCTION__ );
@@ -1082,10 +1097,9 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 
        case REMOTE_NDIS_KEEPALIVE_MSG:
                /* For USB: host does this every 5 seconds */
-#ifdef VERBOSE
-               DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 
-                       __FUNCTION__ );
-#endif
+               if (rndis_debug > 1)
+                       DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 
+                               __FUNCTION__ );
                return rndis_keepalive_response (configNr,
                                                 (rndis_keepalive_msg_type *) 
                                                 buf);
@@ -1152,7 +1166,8 @@ void rndis_deregister (int configNr)
 }
 
 int rndis_set_param_dev (u8 configNr, struct net_device *dev, 
-                        struct net_device_stats *stats)
+                        struct net_device_stats *stats,
+                        u16 *cdc_filter)
 {
        DEBUG("%s:\n", __FUNCTION__ );
        if (!dev || !stats) return -1;
@@ -1160,6 +1175,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
        
        rndis_per_dev_params [configNr].dev = dev;
        rndis_per_dev_params [configNr].stats = stats;
+       rndis_per_dev_params [configNr].filter = cdc_filter;
        
        return 0;
 }
@@ -1178,7 +1194,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 
 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
 {
-       DEBUG("%s:\n", __FUNCTION__ );
+       DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
        
        rndis_per_dev_params [configNr].medium = medium;
@@ -1242,6 +1258,7 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length)
 {
        rndis_resp_t    *r;
        
+       /* NOTE:  this gets copied into ether.c USB_BUFSIZ bytes ... */
        r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
        if (!r) return NULL;
        
index 2b5b55d..95b4c63 100644 (file)
 #define OID_PNP_ENABLE_WAKE_UP                 0xFD010106
 
 
-/* supported OIDs */
-static const u32 oid_supported_list [] = 
-{
-       /* the general stuff */
-       OID_GEN_SUPPORTED_LIST,
-       OID_GEN_HARDWARE_STATUS,
-       OID_GEN_MEDIA_SUPPORTED,
-       OID_GEN_MEDIA_IN_USE,
-       OID_GEN_MAXIMUM_FRAME_SIZE,
-       OID_GEN_LINK_SPEED,
-       OID_GEN_TRANSMIT_BLOCK_SIZE,
-       OID_GEN_RECEIVE_BLOCK_SIZE,
-       OID_GEN_VENDOR_ID,
-       OID_GEN_VENDOR_DESCRIPTION,
-       OID_GEN_VENDOR_DRIVER_VERSION,
-       OID_GEN_CURRENT_PACKET_FILTER,
-       OID_GEN_MAXIMUM_TOTAL_SIZE,
-       OID_GEN_MEDIA_CONNECT_STATUS,
-       OID_GEN_PHYSICAL_MEDIUM,
-#if 0
-       OID_GEN_RNDIS_CONFIG_PARAMETER,
-#endif
-       
-       /* the statistical stuff */
-       OID_GEN_XMIT_OK,
-       OID_GEN_RCV_OK,
-       OID_GEN_XMIT_ERROR,
-       OID_GEN_RCV_ERROR,
-       OID_GEN_RCV_NO_BUFFER,
-#ifdef RNDIS_OPTIONAL_STATS
-       OID_GEN_DIRECTED_BYTES_XMIT,
-       OID_GEN_DIRECTED_FRAMES_XMIT,
-       OID_GEN_MULTICAST_BYTES_XMIT,
-       OID_GEN_MULTICAST_FRAMES_XMIT,
-       OID_GEN_BROADCAST_BYTES_XMIT,
-       OID_GEN_BROADCAST_FRAMES_XMIT,
-       OID_GEN_DIRECTED_BYTES_RCV,
-       OID_GEN_DIRECTED_FRAMES_RCV,
-       OID_GEN_MULTICAST_BYTES_RCV,
-       OID_GEN_MULTICAST_FRAMES_RCV,
-       OID_GEN_BROADCAST_BYTES_RCV,
-       OID_GEN_BROADCAST_FRAMES_RCV,
-       OID_GEN_RCV_CRC_ERROR,
-       OID_GEN_TRANSMIT_QUEUE_LENGTH,
-#endif /* RNDIS_OPTIONAL_STATS */
-
-       /* mandatory 802.3 */
-       /* the general stuff */
-       OID_802_3_PERMANENT_ADDRESS,
-       OID_802_3_CURRENT_ADDRESS,
-       OID_802_3_MULTICAST_LIST,
-       OID_802_3_MAC_OPTIONS,
-       OID_802_3_MAXIMUM_LIST_SIZE,
-       
-       /* the statistical stuff */
-       OID_802_3_RCV_ERROR_ALIGNMENT,
-       OID_802_3_XMIT_ONE_COLLISION,
-       OID_802_3_XMIT_MORE_COLLISIONS,
-#ifdef RNDIS_OPTIONAL_STATS
-       OID_802_3_XMIT_DEFERRED,
-       OID_802_3_XMIT_MAX_COLLISIONS,
-       OID_802_3_RCV_OVERRUN,
-       OID_802_3_XMIT_UNDERRUN,
-       OID_802_3_XMIT_HEARTBEAT_FAILURE,
-       OID_802_3_XMIT_TIMES_CRS_LOST,
-       OID_802_3_XMIT_LATE_COLLISIONS,
-#endif /* RNDIS_OPTIONAL_STATS */
-
-#ifdef RNDIS_PM
-       /* PM and wakeup are mandatory for USB: */
-
-       /* power management */
-       OID_PNP_CAPABILITIES,
-       OID_PNP_QUERY_POWER,
-       OID_PNP_SET_POWER,
-
-       /* wake up host */
-       OID_PNP_ENABLE_WAKE_UP,
-       OID_PNP_ADD_WAKE_UP_PATTERN,
-       OID_PNP_REMOVE_WAKE_UP_PATTERN,
-#endif
-};
-
-
 typedef struct rndis_init_msg_type 
 {
        __le32  MessageType;
@@ -309,15 +225,18 @@ typedef struct rndis_resp_t
 typedef struct rndis_params
 {
        u8                      confignr;
-       int                     used;
+       u8                      used;
+       u16                     saved_filter;
        enum rndis_state        state;
-       u32                     filter;
        u32                     medium;
        u32                     speed;
        u32                     media_state;
+
        const u8                *host_mac;
+       u16                     *filter;
        struct net_device       *dev;
        struct net_device_stats *stats;
+
        u32                     vendorID;
        const char              *vendorDescr;
        int                     (*ack) (struct net_device *);
@@ -329,7 +248,8 @@ int  rndis_msg_parser (u8 configNr, u8 *buf);
 int  rndis_register (int (*rndis_control_ack) (struct net_device *));
 void rndis_deregister (int configNr);
 int  rndis_set_param_dev (u8 configNr, struct net_device *dev,
-                        struct net_device_stats *stats);
+                        struct net_device_stats *stats,
+                        u16 *cdc_filter);
 int  rndis_set_param_vendor (u8 configNr, u32 vendorID, 
                            const char *vendorDescr);
 int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
@@ -338,6 +258,7 @@ int rndis_rm_hdr (struct sk_buff *skb);
 u8   *rndis_get_next_response (int configNr, u32 *length);
 void rndis_free_response (int configNr, u8 *buf);
 
+void rndis_uninit (int configNr);
 int  rndis_signal_connect (int configNr);
 int  rndis_signal_disconnect (int configNr);
 int  rndis_state (int configNr);