From 20c6b42bcf958aadd363950c27f76e64700d52e3 Mon Sep 17 00:00:00 2001
From: nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Wed, 7 Jan 2009 04:26:14 +0000
Subject: [PATCH] make broadcom-wl robust against implicit kernel config
 changes (e.g. netfilter), upgrade it from minor version .2 to .3 (adds fixed
 bssid support for ad-hoc)

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13912 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 package/broadcom-wl/Makefile                  |  4 +-
 .../broadcom-wl/files/lib/wifi/broadcom.sh    |  8 +++
 package/broadcom-wl/src/include/wlioctl.h     |  6 +-
 package/broadcom-wl/src/wlc/wlc.c             | 64 +++++++++++++++++-
 .../brcm-2.4/patches/100-wl_config.patch      | 66 +++++++++++++++++++
 5 files changed, 143 insertions(+), 5 deletions(-)
 create mode 100644 target/linux/brcm-2.4/patches/100-wl_config.patch

diff --git a/package/broadcom-wl/Makefile b/package/broadcom-wl/Makefile
index 5db45cdba..345f84999 100644
--- a/package/broadcom-wl/Makefile
+++ b/package/broadcom-wl/Makefile
@@ -10,13 +10,13 @@ include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=broadcom-wl
-PKG_VERSION:=4.150.10.5.2
+PKG_VERSION:=4.150.10.5.3
 PKG_RELEASE:=1
 WLC_VERSION:=0.1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://downloads.openwrt.org/sources
-PKG_MD5SUM:=904a808dd98da076814fb7cb4b66a695
+PKG_MD5SUM:=cc615fd49719eea8bce5b2a8813783f3
 
 WL_WEXT=1
 
diff --git a/package/broadcom-wl/files/lib/wifi/broadcom.sh b/package/broadcom-wl/files/lib/wifi/broadcom.sh
index e0d741b95..4c03aff04 100644
--- a/package/broadcom-wl/files/lib/wifi/broadcom.sh
+++ b/package/broadcom-wl/files/lib/wifi/broadcom.sh
@@ -232,6 +232,14 @@ enable_broadcom() {
 			append vif_post_up "monitor $monitor" "$N"
 			append vif_post_up "passive $passive" "$N"
 		}
+
+		[ "$mode" = "adhoc" ] && {
+			config_get bssid "$vif" bssid
+			[ -n "$bssid" ] && {
+				append vif_pre_up "des_bssid $bssid" "$N"
+				append vif_pre_up "allow_mode 1" "$N"
+			}
+		} || append vif_pre_up "allow_mode 0" "$N"
 		
 		append vif_post_up "enabled 1" "$N"
 		
diff --git a/package/broadcom-wl/src/include/wlioctl.h b/package/broadcom-wl/src/include/wlioctl.h
index 0558415d3..43eddd1d0 100644
--- a/package/broadcom-wl/src/include/wlioctl.h
+++ b/package/broadcom-wl/src/include/wlioctl.h
@@ -762,7 +762,11 @@ typedef struct wl_instance_info {
 #define WLC_NVOTPW				274
 #define WLC_OTPW				275
 #define WLC_SET_LOCALE				278
-#define WLC_LAST				279	/* do not change - use get_var/set_var */
+#define WLC_GET_ALLOW_MODE			279
+#define WLC_SET_ALLOW_MODE			280
+#define WLC_GET_DESIRED_BSSID			281
+#define WLC_SET_DESIRED_BSSID			282
+#define WLC_LAST				283	/* do not change - use get_var/set_var */
 
 /*
  * Minor kludge alert:
diff --git a/package/broadcom-wl/src/wlc/wlc.c b/package/broadcom-wl/src/wlc/wlc.c
index e0d016feb..790bdfff5 100644
--- a/package/broadcom-wl/src/wlc/wlc.c
+++ b/package/broadcom-wl/src/wlc/wlc.c
@@ -66,6 +66,7 @@ typedef enum {
 	PARAM_TYPE =    0x00f,
 	INT =    0x001,
 	STRING = 0x002,
+	MAC =    0x003,
 
 	/* options */
 	PARAM_OPTIONS = 0x0f0,
@@ -106,11 +107,13 @@ static int wlc_ioctl(wlc_param param, void *data, void *value)
 		return wl_ioctl(interface, ioc, NULL, 0);
 	}
 	switch(param & PARAM_TYPE) {
+		case MAC:
+			return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, 6);
 		case INT:
 			return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, sizeof(int));
 		case STRING:
 			return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, BUFSIZE);
-	}	
+	}
 	return 0;
 }
 
@@ -124,12 +127,20 @@ static int wlc_iovar(wlc_param param, void *data, void *value)
 		switch(param & PARAM_TYPE) {
 			case INT:
 				ret = wl_iovar_setint(interface, iov, *val);
+				break;
+			case MAC:
+				ret = wl_iovar_set(interface, iov, value, 6);
+				break;
 		}
 	}
 	if (param & GET) {
 		switch(param & PARAM_TYPE) {
 			case INT:
 				ret = wl_iovar_getint(interface, iov, val);
+				break;
+			case MAC:
+				ret = wl_iovar_get(interface, iov, value, 6);
+				break;
 		}
 	}
 
@@ -859,6 +870,41 @@ static const struct wlc_call wlc_calls[] = {
 		.handler = wlc_afterburner,
 		.desc = "Broadcom Afterburner"
 	},
+	{
+		.name = "join_once",
+		.param = INT,
+		.handler = wlc_iovar,
+		.data.str = "IBSS_join_once",
+		.desc = "Prevent unwanted IBSS merges"
+	},
+	{
+		.name = "bssid",
+		.param = MAC,
+		.handler = wlc_iovar,
+		.data.str = "cur_etheraddr",
+		.desc = "BSSID"
+	},
+	{
+		.name = "default_bssid",
+		.param = MAC,
+		.handler = wlc_iovar,
+		.data.str = "perm_etheraddr",
+		.desc = "Default BSSID (read-only)"
+	},
+	{
+		.name = "allow_mode",
+		.param = INT,
+		.data.num = ((WLC_GET_ALLOW_MODE << 16) | WLC_SET_ALLOW_MODE),
+		.handler = wlc_ioctl,
+		.desc = "STA/IBSS assoc mode"
+	},
+	{
+		.name = "des_bssid",
+		.param = MAC,
+		.data.num = ((WLC_GET_DESIRED_BSSID << 16) | WLC_SET_DESIRED_BSSID),
+		.handler = wlc_ioctl,
+		.desc = "Desired BSSID"
+	},
 };
 #define wlc_calls_size (sizeof(wlc_calls) / sizeof(struct wlc_call))
 
@@ -882,6 +928,7 @@ static int do_command(const struct wlc_call *cmd, char *arg)
 	int ret = 0;
 	char *format, *end;
 	int intval;
+	void *ptr = (void *) buf;
 
 	if (debug >= 10) {
 		fprintf(stderr, "do_command %-16s\t'%s'\n", cmd->name, arg);
@@ -906,6 +953,11 @@ static int do_command(const struct wlc_call *cmd, char *arg)
 					break;
 				case STRING:
 					fprintf(stdout, "%s\n", buf);
+					break;
+				case MAC:
+					my_ether_ntoa(buf, buf + 6);
+					fprintf(stdout, "%s\n", buf + 6);
+					break;
 			}
 		}
 	} else { /* SET */
@@ -923,9 +975,17 @@ static int do_command(const struct wlc_call *cmd, char *arg)
 			case STRING:
 				strncpy(buf, arg, BUFSIZE);
 				buf[BUFSIZE - 1] = 0;
+				break;
+			case MAC:
+				ptr = ether_aton(arg);
+				if (!ptr) {
+					fprintf(stderr, "%s: Invalid mac address '%s'\n", cmd->name, arg);
+					return -1;
+				}
+				break;
 		}
 
-		ret = cmd->handler(cmd->param | SET, (void *) &cmd->data, (void *) buf);
+		ret = cmd->handler(cmd->param | SET, (void *) &cmd->data, ptr);
 	}
 	
 	if ((debug > 0) && (ret != 0)) 
diff --git a/target/linux/brcm-2.4/patches/100-wl_config.patch b/target/linux/brcm-2.4/patches/100-wl_config.patch
new file mode 100644
index 000000000..4870c4c1e
--- /dev/null
+++ b/target/linux/brcm-2.4/patches/100-wl_config.patch
@@ -0,0 +1,66 @@
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -445,16 +445,12 @@ struct net_device
+ 	/* bridge stuff */
+ 	struct net_bridge_port	*br_port;
+ 
+-#ifdef CONFIG_NET_FASTROUTE
+ #define NETDEV_FASTROUTE_HMASK 0xF
+ 	/* Semi-private data. Keep it at the end of device struct. */
+ 	rwlock_t		fastpath_lock;
+ 	struct dst_entry	*fastpath[NETDEV_FASTROUTE_HMASK+1];
+-#endif
+-#ifdef CONFIG_NET_DIVERT
+ 	/* this will get initialized at each interface type init routine */
+ 	struct divert_blk	*divert;
+-#endif /* CONFIG_NET_DIVERT */
+ };
+ 
+ /* 2.6 compatibility */
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -83,7 +83,6 @@
+ #define NET_CALLER(arg) __builtin_return_address(0)
+ #endif
+ 
+-#ifdef CONFIG_NETFILTER
+ struct nf_conntrack {
+ 	atomic_t use;
+ 	void (*destroy)(struct nf_conntrack *);
+@@ -92,7 +91,6 @@ struct nf_conntrack {
+ struct nf_ct_info {
+ 	struct nf_conntrack *master;
+ };
+-#endif
+ #if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ struct nf_info;
+ #endif
+@@ -201,7 +199,6 @@ struct sk_buff {
+ 	unsigned char 	*end;			/* End pointer					*/
+ 
+ 	void 		(*destructor)(struct sk_buff *);	/* Destruct function		*/
+-#ifdef CONFIG_NETFILTER
+ 	/* Can be used for communication between hooks. */
+         unsigned long	nfmark;
+ 	/* Cache info */
+@@ -211,7 +208,6 @@ struct sk_buff {
+ #ifdef CONFIG_NETFILTER_DEBUG
+         unsigned int nf_debug;
+ #endif
+-#endif /*CONFIG_NETFILTER*/
+ 
+ #if defined(CONFIG_HIPPI)
+ 	union{
+@@ -219,12 +215,8 @@ struct sk_buff {
+ 	} private;
+ #endif
+ 
+-#ifdef CONFIG_NET_SCHED
+        __u32           tc_index;               /* traffic control index */
+-#endif
+-#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+        struct nf_info	*nf_info;
+-#endif
+ };
+ 
+ #ifdef __KERNEL__
-- 
2.20.1