This should fix the problem David Meggy found, where RNDIS was setting
the OID_GEN_CURRENT_PACKET_FILTER state incorrectly.  It's the same
issue Andrew Morton noticed a while back, for that matter, but with
more than just a "now compiles on 64 bit" fix.

Basically the code needs to interpret 32 bits provided in the request
from the (Windows) host, rather than 8 bits of other memory that's got
some irrelevant value.

The fix is just to save the 32 bits.  I did the same thing with the
CDC Ethernet filter, which should eventually be used the same way:  to
limit what packets get sent to the host.  Also defined a couple more
of the CDC requests.

- Dave

--- 1.40/drivers/usb/gadget/ether.c     Mon May 17 11:38:30 2004
+++ edited/drivers/usb/gadget/ether.c   Mon May 17 11:57:00 2004
@@ -118,6 +118,7 @@
        unsigned                zlp:1;
        unsigned                cdc:1;
        unsigned                rndis:1;
+       u16                     cdc_filter;
        unsigned long           todo;
 #define        WORK_RX_MEMORY          0
        int                     rndis_config;
@@ -1150,6 +1151,9 @@
        }
        eth_reset_config (dev);
 
+       /* default:  pass all packets, no multicast filtering */
+       dev->cdc_filter = 0x000f;
+
        switch (number) {
        case DEV_CONFIG_VALUE:
                dev->rndis = 0;
@@ -1322,9 +1326,20 @@
  * section 3.6.2.1 table 4 has ACM requests; RNDIS requires the
  * encapsulated command mechanism.
  */
-#define CDC_SEND_ENCAPSULATED_COMMAND  0x00    /* optional */
-#define CDC_GET_ENCAPSULATED_RESPONSE  0x01    /* optional */
-#define CDC_SET_ETHERNET_PACKET_FILTER 0x43    /* required */
+#define CDC_SEND_ENCAPSULATED_COMMAND          0x00    /* optional */
+#define CDC_GET_ENCAPSULATED_RESPONSE          0x01    /* optional */
+#define CDC_SET_ETHERNET_MULTICAST_FILTERS     0x40    /* optional */
+#define CDC_SET_ETHERNET_PM_PATTERN_FILTER     0x41    /* optional */
+#define CDC_GET_ETHERNET_PM_PATTERN_FILTER     0x42    /* optional */
+#define CDC_SET_ETHERNET_PACKET_FILTER         0x43    /* required */
+#define CDC_GET_ETHERNET_STATISTIC             0x44    /* optional */
+
+/* table 62; bits in cdc_filter */
+#define        CDC_PACKET_TYPE_PROMISCUOUS             (1 << 0)
+#define        CDC_PACKET_TYPE_ALL_MULTICAST           (1 << 1) /* no filter */
+#define        CDC_PACKET_TYPE_DIRECTED                (1 << 2)
+#define        CDC_PACKET_TYPE_BROADCAST               (1 << 3)
+#define        CDC_PACKET_TYPE_MULTICAST               (1 << 4) /* filtered */
 
 #ifdef CONFIG_USB_ETH_RNDIS
 
@@ -1524,8 +1539,9 @@
                DEBUG (dev, "NOP packet filter %04x\n", ctrl->wValue);
                /* NOTE: table 62 has 5 filter bits to reduce traffic,
                 * and we "must" support multicast and promiscuous.
-                * this NOP implements a bad filter...
+                * this NOP implements a bad filter (always promisc)
                 */
+               dev->cdc_filter = ctrl->wValue;
                value = 0;
                break;
 #endif /* DEV_CONFIG_CDC */
@@ -1952,6 +1968,11 @@
        int                     retval;
        struct usb_request      *req = 0;
        unsigned long           flags;
+
+       /* FIXME check dev->cdc_filter to decide whether to send this,
+        * instead of acting as if CDC_PACKET_TYPE_PROMISCUOUS were
+        * always set.  RNDIS has the same kind of outgoing filter.
+        */
 
        spin_lock_irqsave (&dev->lock, flags);
        req = container_of (dev->tx_reqs.next, struct usb_request, list);
--- 1.6/drivers/usb/gadget/rndis.c      Mon May 17 11:38:12 2004
+++ edited/drivers/usb/gadget/rndis.c   Mon May 17 11:54:47 2004
@@ -79,44 +79,6 @@
 
 static rndis_resp_t *rndis_add_response (int configNr, u32 length);
 
-/* helper functions */
-static u32 devFlags2currentFilter (struct net_device *dev)
-{
-       u32 filter = 0;
-       
-       if (!dev) return 0;
-       
-       if (dev->flags & IFF_MULTICAST) 
-           filter |= NDIS_PACKET_TYPE_MULTICAST;
-       if (dev->flags & IFF_BROADCAST)
-           filter |= NDIS_PACKET_TYPE_BROADCAST;
-       if (dev->flags & IFF_ALLMULTI)
-           filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-       if (dev->flags & IFF_PROMISC)
-           filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
-       
-       return filter;
-}
-
-static void currentFilter2devFlags (u32 currentFilter, struct net_device *dev)
-{
-       /* FIXME the filter is supposed to control what gets
-        * forwarded from gadget to host; but dev->flags controls
-        * reporting from host to gadget ...
-        */
-#if 0
-       if (!dev) return;
-       if (currentFilter & NDIS_PACKET_TYPE_MULTICAST)
-           dev->flags |= IFF_MULTICAST;
-       if (currentFilter & NDIS_PACKET_TYPE_BROADCAST)
-           dev->flags |= IFF_BROADCAST;
-       if (currentFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
-           dev->flags |= IFF_ALLMULTI;
-       if (currentFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
-           dev->flags |= IFF_PROMISC;
-#endif
-}
-
 /* FIXME OMITTED OIDs, that RNDIS-on-USB "must" support, include
  *  - power management (OID_PNP_CAPABILITIES, ...)
  *  - network wakeup (OID_PNP_ENABLE_WAKE_UP, ...)
@@ -253,13 +215,12 @@
                        rndis_per_dev_params [configNr].vendorDescr, length);
                retval = 0;
                break;
-               
+
        /* mandatory */
        case OID_GEN_CURRENT_PACKET_FILTER:
                DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
                length = 4;
-               *((u32 *) resp + 6) = devFlags2currentFilter (
-                                       rndis_per_dev_params [configNr].dev);
+               *((u32 *) resp + 6) = rndis_per_dev_params[configNr].filter;
                retval = 0;
                break;
                
@@ -768,16 +729,24 @@
 
        switch (OID) {
        case OID_GEN_CURRENT_PACKET_FILTER:
-               DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
                params = &rndis_per_dev_params [configNr];
-               currentFilter2devFlags(cp[28], params->dev);
                retval = 0;
 
+               /* FIXME use this NDIS_PACKET_TYPE_* bitflags to
+                * filter packets in hard_start_xmit()
+                * NDIS_PACKET_TYPE_x == CDC_PACKET_TYPE_x for x in:
+                *      PROMISCUOUS, DIRECTED,
+                *      MULTICAST, ALL_MULTICAST, BROADCAST
+                */
+               params->filter = *(u32 *)buf;
+               DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+                       __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 (cp[28]) {
+               if (params->filter) {
                        params->state = RNDIS_DATA_INITIALIZED;
                        netif_carrier_on(params->dev);
                        if (netif_running(params->dev))
--- 1.5/drivers/usb/gadget/rndis.h      Thu Apr 22 10:41:41 2004
+++ edited/drivers/usb/gadget/rndis.h   Mon May 17 11:43:18 2004
@@ -277,6 +277,7 @@
        u8                      confignr;
        int                     used;
        enum rndis_state        state;
+       u32                     filter;
        u32                     medium;
        u32                     speed;
        u32                     media_state;

Reply via email to