[PATCH 0/8] RFC: Wireless Extensions for rndis_host
Hello all, I have here a patchset that needs some review. This patchset adds wireless extensions for rndis_host to enable support for RNDIS based USB wireless LAN adapters (e.g. Linksys WUSB54GS, Belkin F05D7051). In this patchset: 1. Fix sparse warning: returning void valued expression 2. Hardwire CDC descriptors when missing 3. Use 1KB buffer in rndis_unbind 4. Halt device if rndis_bind fails 5. Fix rndis packet filter flags 6. Split up rndis_host.c 7. Add Wireless Extensions for rndis_host 8. Use wlan device name for RNDIS wireless devices The first five patches are more generic fixes that I think can be applied as they are. Of these, patch 2 is required to get these wireless devices working. Patches 6-8 introduce some larger changes that may need a closer look. All these patches should be applied in order. The entire series should apply cleanly to current linux kernel and net-2.6.25 trees. regards, Bjorge Dijkstra -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/8] [PATCH] Use 1KB buffer in rndis_unbind
From: Jussi Kivilinna <[EMAIL PROTECTED]> rndis_command requires the caller to pass in a buffer of at least 1KB. Signed-off-by: Jussi Kivilinna <[EMAIL PROTECTED]> Signed-off-by: Bjorge Dijkstra <[EMAIL PROTECTED]> --- drivers/net/usb/rndis_host.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 96ef6a9..42b161c 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -577,7 +577,7 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) struct rndis_halt *halt; /* try to clear any rndis state/activity (no i/o from stack!) */ - halt = kzalloc(sizeof *halt, GFP_KERNEL); + halt = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL); if (halt) { halt->msg_type = RNDIS_MSG_HALT; halt->msg_len = ccpu2(sizeof *halt); -- 1.5.2.5 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/8] [PATCH] Split up rndis_host.c
Split up rndis_host.c into rndis_host.h and rndis_base.c and change Makefile accordingly. This is done so we can add extra source files to the rndis_host module later on. Signed-off-by: Bjorge Dijkstra <[EMAIL PROTECTED]> --- drivers/net/usb/Makefile |1 + drivers/net/usb/rndis_base.c | 548 ++ drivers/net/usb/rndis_host.c | 763 -- drivers/net/usb/rndis_host.h | 256 ++ 4 files changed, 805 insertions(+), 763 deletions(-) create mode 100644 drivers/net/usb/rndis_base.c delete mode 100644 drivers/net/usb/rndis_host.c create mode 100644 drivers/net/usb/rndis_host.h diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 595a539..611ab62 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_USB_NET_GL620A) += gl620a.o obj-$(CONFIG_USB_NET_NET1080) += net1080.o obj-$(CONFIG_USB_NET_PLUSB)+= plusb.o obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o +rndis_host-objs+= rndis_base.o obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o diff --git a/drivers/net/usb/rndis_base.c b/drivers/net/usb/rndis_base.c new file mode 100644 index 000..f3b0c00 --- /dev/null +++ b/drivers/net/usb/rndis_base.c @@ -0,0 +1,548 @@ +/* + * Host Side support for RNDIS Networking Links + * Copyright (C) 2005 by David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// #define DEBUG // error path messages, extra info +// #define VERBOSE // more; success messages + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usbnet.h" +#include "rndis_host.h" + + +/* + * RNDIS is NDIS remoted over USB. It's a MSFT variant of CDC ACM ... of + * course ACM was intended for modems, not Ethernet links! USB's standard + * for Ethernet links is "CDC Ethernet", which is significantly simpler. + * + * NOTE that Microsoft's "RNDIS 1.0" specification is incomplete. Issues + * include: + *- Power management in particular relies on information that's scattered + * through other documentation, and which is incomplete or incorrect even + * there. + *- There are various undocumented protocol requirements, such as the + * need to send unused garbage in control-OUT messages. + *- In some cases, MS-Windows will emit undocumented requests; this + * matters more to peripheral implementations than host ones. + * + * Moreover there's a no-open-specs variant of RNDIS called "ActiveSync". + * + * For these reasons and others, ** USE OF RNDIS IS STRONGLY DISCOURAGED ** in + * favor of such non-proprietary alternatives as CDC Ethernet or the newer (and + * currently rare) "Ethernet Emulation Model" (EEM). + */ + +/* + * RNDIS notifications from device: command completion; "reverse" + * keepalives; etc + */ +void rndis_status(struct usbnet *dev, struct urb *urb) +{ + devdbg(dev, "rndis status urb, len %d stat %d", + urb->actual_length, urb->status); + // FIXME for keepalives, respond immediately (asynchronously) + // if not an RNDIS status, do like cdc_status(dev,urb) does +} +EXPORT_SYMBOL_GPL(rndis_status); + +/* + * RPC done RNDIS-style. Caller guarantees: + * - message is properly byteswapped + * - there's no other request pending + * - buf can hold up to 1KB response (required by RNDIS spec) + * On return, the first few entries are already byteswapped. + * + * Call context is likely probe(), before interface name is known, + * which is why we won't try to use it in the diagnostics. + */ +int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) +{ + struct cdc_state*info = (void *) &dev->data; + int master_ifnum; + int retval; + unsignedcount; + __le32 rsp; + u32 xid = 0, msg_len, request_id; + + /* REVISIT when this gets called from contexts other than
[PATCH 8/8] [PATCH] Use wlan device name for RNDIS wireless devices
From: Jussi Kivilinna <[EMAIL PROTECTED]> Use wlan device name for RNDIS wireless devices. Signed-off-by: Jussi Kivilinna <[EMAIL PROTECTED]> Signed-off-by: Bjorge Dijkstra <[EMAIL PROTECTED]> --- drivers/net/usb/rndis_wext.c |2 +- drivers/net/usb/usbnet.c |3 +++ drivers/net/usb/usbnet.h |2 ++ 3 files changed, 6 insertions(+), 1 deletions(-) diff --git a/drivers/net/usb/rndis_wext.c b/drivers/net/usb/rndis_wext.c index a9ce944..1c28b2a 100644 --- a/drivers/net/usb/rndis_wext.c +++ b/drivers/net/usb/rndis_wext.c @@ -2166,7 +2166,7 @@ static int rndis_wext_reset(struct usbnet *dev) struct driver_info rndis_wext_info = { .description = "Wireless RNDIS device", - .flags =FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .flags =FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, .bind = rndis_wext_bind, .unbind = rndis_wext_unbind, .status = rndis_status, diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8ed1fc5..a2a2d5e 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1204,6 +1204,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if ((dev->driver_info->flags & FLAG_ETHER) != 0 && (net->dev_addr [0] & 0x02) == 0) strcpy (net->name, "eth%d"); + /* WLAN devices should always be named "wlan%d" */ + if ((dev->driver_info->flags & FLAG_WLAN) != 0) + strcpy(net->name, "wlan%d"); /* maybe the remote can't receive an Ethernet MTU */ if (net->mtu > (dev->hard_mtu - net->hard_header_len)) diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h index 83860a0..5c98ddc 100644 --- a/drivers/net/usb/usbnet.h +++ b/drivers/net/usb/usbnet.h @@ -88,6 +88,8 @@ struct driver_info { #define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */ #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ +#define FLAG_WLAN 0x0080 /* use "wlan%d" names */ + /* init device ... can sleep, or cause probe() failure */ int (*bind)(struct usbnet *, struct usb_interface *); -- 1.5.2.5 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/8] [PATCH] Hardwire CDC descriptors when missing
Just as ActiveSync devices, some regular RNDIS devices also lack the CDC descriptors (e.g. devices based on BCM4320 WLAN chip). This patch hardwires the CDC descriptors for all RNDIS style devices when they are missing. Signed-off-by: Bjorge Dijkstra <[EMAIL PROTECTED]> --- drivers/net/usb/cdc_ether.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index a42acc3..97c17bb 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -228,15 +228,16 @@ next_desc: buf += buf [0]; } - /* Microsoft ActiveSync based RNDIS devices lack the CDC descriptors, -* so we'll hard-wire the interfaces and not check for descriptors. + /* Microsoft ActiveSync based and some regular RNDIS devices lack the +* CDC descriptors, so we'll hard-wire the interfaces and not check +* for descriptors. */ - if (is_activesync(&intf->cur_altsetting->desc) && !info->u) { + if (rndis && !info->u) { info->control = usb_ifnum_to_if(dev->udev, 0); info->data = usb_ifnum_to_if(dev->udev, 1); if (!info->control || !info->data) { dev_dbg(&intf->dev, - "activesync: master #0/%p slave #1/%p\n", + "rndis: master #0/%p slave #1/%p\n", info->control, info->data); goto bad_desc; @@ -316,7 +317,6 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); - /*- * * Communications Device Class, Ethernet Control model -- 1.5.2.5 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/8] [PATCH] Halt device if rndis_bind fails.
From: Jussi Kivilinna <[EMAIL PROTECTED]> When bind fails after device was initialized, shutdown device properly by sending RNDIS_MSG_HALT. Signed-off-by: Jussi Kivilinna <[EMAIL PROTECTED]> Signed-off-by: Bjorge Dijkstra <[EMAIL PROTECTED]> --- drivers/net/usb/rndis_host.c | 12 +--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 42b161c..c686025 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -467,6 +467,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) struct rndis_query_c*get_c; struct rndis_set*set; struct rndis_set_c *set_c; + struct rndis_halt *halt; } u; u32 tmp; int reply_len; @@ -517,7 +518,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) "dev can't take %u byte packets (max %u)\n", dev->hard_mtu, tmp); retval = -EINVAL; - goto fail_and_release; + goto halt_fail_and_release; } dev->hard_mtu = tmp; net->mtu = dev->hard_mtu - net->hard_header_len; @@ -539,7 +540,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) 48, (void **) &bp, &reply_len); if (unlikely(retval< 0)) { dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval); - goto fail_and_release; + goto halt_fail_and_release; } memcpy(net->dev_addr, bp, ETH_ALEN); @@ -555,7 +556,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) retval = rndis_command(dev, u.header); if (unlikely(retval < 0)) { dev_err(&intf->dev, "rndis set packet filter, %d\n", retval); - goto fail_and_release; + goto halt_fail_and_release; } retval = 0; @@ -563,6 +564,11 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) kfree(u.buf); return retval; +halt_fail_and_release: + memset(u.halt, 0, sizeof *u.halt); + u.halt->msg_type = RNDIS_MSG_HALT; + u.halt->msg_len = ccpu2(sizeof *u.halt); + (void) rndis_command(dev, (void *)u.halt); fail_and_release: usb_set_intfdata(info->data, NULL); usb_driver_release_interface(driver_of(intf), info->data); -- 1.5.2.5 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/8] Fix sparse warning: returning void-valued expression
rndis_unbind and usbnet_cdc_unbind don't return anything. Signed-off-by: Bjorge Dijkstra <[EMAIL PROTECTED]> --- drivers/net/usb/rndis_host.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 1ebe325..96ef6a9 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -585,7 +585,7 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) kfree(halt); } - return usbnet_cdc_unbind(dev, intf); + usbnet_cdc_unbind(dev, intf); } /* -- 1.5.2.5 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/8] Fix rndis packet filter flags.
From: Jussi Kivilinna <[EMAIL PROTECTED]> RNDIS packet filter flags are not exactly the same as CDC flags so we cannot reuse them. Signed-off-by: Jussi Kivilinna <[EMAIL PROTECTED]> Signed-off-by: Bjorge Dijkstra <[EMAIL PROTECTED]> --- drivers/net/usb/rndis_host.c | 23 ++- 1 files changed, 22 insertions(+), 1 deletions(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index c686025..3c116f9 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -256,6 +256,27 @@ struct rndis_keepalive_c { /* IN (optionally OUT) */ #define OID_GEN_MAXIMUM_FRAME_SIZE ccpu2(0x00010106) #define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e) +/* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */ +#define RNDIS_PACKET_TYPE_DIRECTED ccpu2(0x0001) +#define RNDIS_PACKET_TYPE_MULTICASTccpu2(0x0002) +#define RNDIS_PACKET_TYPE_ALL_MULTICASTccpu2(0x0004) +#define RNDIS_PACKET_TYPE_BROADCASTccpu2(0x0008) +#define RNDIS_PACKET_TYPE_SOURCE_ROUTING ccpu2(0x0010) +#define RNDIS_PACKET_TYPE_PROMISCUOUS ccpu2(0x0020) +#define RNDIS_PACKET_TYPE_SMT ccpu2(0x0040) +#define RNDIS_PACKET_TYPE_ALL_LOCALccpu2(0x0080) +#define RNDIS_PACKET_TYPE_GROUPccpu2(0x1000) +#define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL ccpu2(0x2000) +#define RNDIS_PACKET_TYPE_FUNCTIONAL ccpu2(0x4000) +#define RNDIS_PACKET_TYPE_MAC_FRAMEccpu2(0x8000) + +/* default filter used with RNDIS devices */ +#define RNDIS_DEFAULT_FILTER ( \ + RNDIS_PACKET_TYPE_DIRECTED | \ + RNDIS_PACKET_TYPE_BROADCAST | \ + RNDIS_PACKET_TYPE_ALL_MULTICAST | \ + RNDIS_PACKET_TYPE_PROMISCUOUS ) + /* * RNDIS notifications from device: command completion; "reverse" * keepalives; etc @@ -551,7 +572,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) u.set->oid = OID_GEN_CURRENT_PACKET_FILTER; u.set->len = ccpu2(4); u.set->offset = ccpu2((sizeof *u.set) - 8); - *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER); + *(__le32 *)(u.buf + sizeof *u.set) = RNDIS_DEFAULT_FILTER; retval = rndis_command(dev, u.header); if (unlikely(retval < 0)) { -- 1.5.2.5 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html