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;