summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile168
-rwxr-xr-xlib/LICENSE.txt68
-rw-r--r--lib/wlc_hybrid.o_shippedbin0 -> 7350128 bytes
-rw-r--r--src/common/include/proto/802.11.h3081
-rw-r--r--src/common/include/proto/802.1d.h40
-rw-r--r--src/common/include/proto/bcmeth.h62
-rw-r--r--src/common/include/proto/bcmevent.h343
-rw-r--r--src/common/include/proto/bcmip.h196
-rw-r--r--src/common/include/proto/ethernet.h156
-rw-r--r--src/common/include/proto/ieee80211_radiotap.h161
-rw-r--r--src/common/include/proto/wpa.h148
-rw-r--r--src/include/bcmcrypto/tkhash.h33
-rw-r--r--src/include/bcmdefs.h164
-rw-r--r--src/include/bcmendian.h280
-rw-r--r--src/include/bcmutils.h657
-rw-r--r--src/include/epivers.h41
-rw-r--r--src/include/linux_osl.h338
-rw-r--r--src/include/linuxver.h594
-rw-r--r--src/include/osl.h132
-rw-r--r--src/include/packed_section_end.h41
-rw-r--r--src/include/packed_section_start.h48
-rw-r--r--src/include/pcicfg.h83
-rw-r--r--src/include/siutils.h409
-rw-r--r--src/include/typedefs.h217
-rw-r--r--src/include/wlioctl.h1165
-rw-r--r--src/shared/bcmwifi/include/bcmwifi_channels.h353
-rw-r--r--src/shared/bcmwifi/include/bcmwifi_rates.h705
-rw-r--r--src/shared/linux_osl.c1107
-rw-r--r--src/wl/sys/wl_cfg80211_hybrid.c3022
-rw-r--r--src/wl/sys/wl_cfg80211_hybrid.h231
-rw-r--r--src/wl/sys/wl_dbg.h74
-rw-r--r--src/wl/sys/wl_export.h81
-rw-r--r--src/wl/sys/wl_iw.c2830
-rw-r--r--src/wl/sys/wl_iw.h150
-rw-r--r--src/wl/sys/wl_linux.c3371
-rw-r--r--src/wl/sys/wl_linux.h192
-rw-r--r--src/wl/sys/wlc_ethereal.h129
-rw-r--r--src/wl/sys/wlc_key.h76
-rw-r--r--src/wl/sys/wlc_pub.h927
-rw-r--r--src/wl/sys/wlc_types.h137
-rw-r--r--src/wl/sys/wlc_utils.h51
-rw-r--r--src/wl/sys/wlc_wowl.h86
42 files changed, 22147 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a323a0d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,168 @@
+#
+# Makefile fragment for Linux 2.6
+# Broadcom 802.11abg Networking Device Driver
+#
+# Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# $Id: Makefile_kbuild_portsrc 580354 2015-08-18 23:42:37Z $
+
+ifneq ($(KERNELRELEASE),)
+
+ LINUXVER_GOODFOR_CFG80211:=$(strip $(shell \
+ if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "32" -o "$(VERSION)" -ge "3" ]; then \
+ echo TRUE; \
+ else \
+ echo FALSE; \
+ fi \
+ ))
+
+ LINUXVER_WEXT_ONLY:=$(strip $(shell \
+ if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "17" ]; then \
+ echo FALSE; \
+ else \
+ echo TRUE; \
+ fi \
+ ))
+
+ ifneq ($(API),)
+ ifeq ($(API), CFG80211)
+ APICHOICE := FORCE_CFG80211
+ $(info CFG80211 API specified in command line)
+ else
+ ifeq ($(API), WEXT)
+ APICHOICE := FORCE_WEXT
+ $(info Wireless Extension API specified in command line)
+ else
+ $(error Unknown API type)
+ endif
+ endif
+ else
+ ifeq ($(LINUXVER_GOODFOR_CFG80211),TRUE)
+ APICHOICE := PREFER_CFG80211
+ $(info CFG80211 API is prefered for this kernel version)
+ else
+ ifeq ($(LINUXVER_WEXT_ONLY),TRUE)
+ APICHOICE := FORCE_WEXT
+ $(info Wireless Extension is the only possible API for this kernel version)
+ else
+ APICHOICE := PREFER_WEXT
+ $(info Wireless Extension API is prefered for this kernel version)
+ endif
+ endif
+ endif
+
+ ifeq ($(APICHOICE),FORCE_CFG80211)
+ ifneq ($(CONFIG_CFG80211),)
+ APIFINAL := CFG80211
+ else
+ $(error CFG80211 is specified but it is not enabled in kernel)
+ endif
+ endif
+
+ ifeq ($(APICHOICE),FORCE_WEXT)
+ APIFINAL := WEXT
+ endif
+
+ ifeq ($(APICHOICE),PREFER_CFG80211)
+ ifneq ($(CONFIG_CFG80211),)
+ APIFINAL := CFG80211
+ else
+ ifneq ($(CONFIG_WIRELESS_EXT),)
+ APIFINAL := WEXT
+ else
+ $(warning Neither CFG80211 nor Wireless Extension is enabled in kernel)
+ endif
+ endif
+ endif
+
+ ifeq ($(APICHOICE),PREFER_WEXT)
+ ifneq ($(CONFIG_WIRELESS_EXT),)
+ APIFINAL := WEXT
+ else
+ ifneq ($(CONFIG_CFG80211),)
+ APIFINAL := CFG80211
+ else
+ $(warning Neither CFG80211 nor Wireless Extension is enabled in kernel)
+ endif
+ endif
+ endif
+
+endif
+
+#Check GCC version so we can apply -Wno-date-time if supported. GCC >= 4.9
+empty:=
+space:= $(empty) $(empty)
+GCCVERSIONSTRING := $(shell expr `$(CC) -dumpversion`)
+#Create version number without "."
+GCCVERSION := $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f1 -d.)
+GCCVERSION += $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f2 -d.)
+GCCVERSION += $(shell expr `echo $(GCCVERSIONSTRING)` | cut -f3 -d.)
+# Make sure the version number has at least 3 decimals
+GCCVERSION += 00
+# Remove spaces from the version number
+GCCVERSION := $(subst $(space),$(empty),$(GCCVERSION))
+# Crop the version number to 3 decimals.
+GCCVERSION := $(shell expr `echo $(GCCVERSION)` | cut -b1-3)
+GE_49 := $(shell expr `echo $(GCCVERSION)` \>= 490)
+
+EXTRA_CFLAGS :=
+
+ifeq ($(APIFINAL),CFG80211)
+ EXTRA_CFLAGS += -DUSE_CFG80211
+ $(info Using CFG80211 API)
+endif
+
+ifeq ($(APIFINAL),WEXT)
+ EXTRA_CFLAGS += -DUSE_IW
+ $(info Using Wireless Extension API)
+endif
+
+obj-m += wl.o
+
+wl-objs :=
+wl-objs += src/shared/linux_osl.o
+wl-objs += src/wl/sys/wl_linux.o
+wl-objs += src/wl/sys/wl_iw.o
+wl-objs += src/wl/sys/wl_cfg80211_hybrid.o
+
+EXTRA_CFLAGS += -I$(src)/src/include -I$(src)/src/common/include
+EXTRA_CFLAGS += -I$(src)/src/wl/sys -I$(src)/src/wl/phy -I$(src)/src/wl/ppr/include
+EXTRA_CFLAGS += -I$(src)/src/shared/bcmwifi/include
+#EXTRA_CFLAGS += -DBCMDBG_ASSERT -DBCMDBG_ERR
+ifeq "$(GE_49)" "1"
+EXTRA_CFLAGS += -Wno-date-time
+endif
+
+EXTRA_LDFLAGS := $(src)/lib/wlc_hybrid.o_shipped
+
+KBASE ?= /lib/modules/`uname -r`
+KBUILD_DIR ?= $(KBASE)/build
+MDEST_DIR ?= $(KBASE)/kernel/drivers/net/wireless
+
+# Cross compile setup. Tool chain and kernel tree, replace with your own.
+CROSS_TOOLS = /path/to/tools
+CROSS_KBUILD_DIR = /path/to/kernel/tree
+
+all:
+ KBUILD_NOPEDANTIC=1 make -C $(KBUILD_DIR) M=`pwd`
+
+cross:
+ KBUILD_NOPEDANTIC=1 make CROSS_COMPILE=${CROSS_TOOLS} -C $(CROSS_KBUILD_DIR) M=`pwd`
+
+clean:
+ KBUILD_NOPEDANTIC=1 make -C $(KBUILD_DIR) M=`pwd` clean
+
+install:
+ install -D -m 755 wl.ko $(MDEST_DIR)
diff --git a/lib/LICENSE.txt b/lib/LICENSE.txt
new file mode 100755
index 0000000..896b95c
--- /dev/null
+++ b/lib/LICENSE.txt
@@ -0,0 +1,68 @@
+SOFTWARE LICENSE AGREEMENT
+
+Unless you and Broadcom Corporation (“Broadcom”) execute a separate written software license agreement governing use of the accompanying software, this software is licensed to you under the terms of this Software License Agreement (“Agreement”).
+
+ANY USE, REPRODUCTION OR DISTRIBUTION OF THE SOFTWARE CONSTITUTES YOUR ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS.
+
+1.1. “Broadcom Product” means any of the proprietary integrated circuit product(s) sold by Broadcom with which the Software was designed to be used, or their successors.
+
+1.2. “Licensee” means you or if you are accepting on behalf of an entity then the entity and its affiliates exercising rights under, and complying with all of the terms of this Agreement.
+
+1.3. “Software” shall mean that software made available by Broadcom to Licensee in binary code form with this Agreement.
+
+2. LICENSE GRANT; OWNERSHIP
+
+2.1. License Grants. Subject to the terms and conditions of this Agreement, Broadcom hereby grants to Licensee a non-exclusive, non-transferable, royalty-free license (i) to use and integrate the Software in conjunction with any other software; and (ii) to reproduce and distribute the Software complete, unmodified and only for use with a Broadcom Product.
+
+2.2. Restriction on Modification. If and to the extent that the Software is designed to be compliant with any published communications standard (including, without limitation, DOCSIS, HomePNA, IEEE, and ITU standards), Licensee may not make any modifications to the Software that would cause the Software or the accompanying Broadcom Products to be incompatible with such standard.
+
+2.3. Restriction on Distribution. Licensee shall only distribute the Software (a) under the terms of this Agreement and a copy of this Agreement accompanies such distribution, and (b) agrees to defend and indemnify Broadcom and its licensors from and against any damages, costs, liabilities, settlement amounts and/or expenses (including attorneys' fees) incurred in connection with any claim, lawsuit or action by any third party that arises or results from the use or distribution of any and all Software by the Licensee except as contemplated herein.
+
+2.4. Proprietary Notices. Licensee shall not remove, efface or obscure any copyright or trademark notices from the Software. Licensee shall include reproductions of the Broadcom copyright notice with each copy of the Software, except where such Software is embedded in a manner not readily accessible to the end user. Licensee acknowledges that any symbols, trademarks, tradenames, and service marks adopted by Broadcom to identify the Software belong to Broadcom and that Licensee shall have no rights therein.
+
+2.5. Ownership. Broadcom shall retain all right, title and interest, including all intellectual property rights, in and to the Software. Licensee hereby covenants that it will not assert any claim that the Software created by or for Broadcom infringe any intellectual property right owned or controlled by Licensee.
+
+2.6. No Other Rights Granted; Restrictions. Apart from the license rights expressly set forth in this Agreement, Broadcom does not grant and Licensee does not receive any ownership right, title or interest nor any security interest or other interest in any intellectual property rights relating to the Software, nor in any copy of any part of the foregoing. Licensee shall not (i) use, license, sell or otherwise distribute the Software except as provided in this Agreement, (ii) attempt to reverse engineer, decompile or disassemble any portion of the Software; or (iii) use the Software or other material in violation of any applicable law or regulation, including but not limited to any regulatory agency, such as FCC, rules.
+
+3. NO WARRANTY OR SUPPORT
+
+3.1. No Warranty. THE SOFTWARE IS OFFERED “AS IS,” AND BROADCOM GRANTS AND LICENSEE RECEIVES NO WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR CONDUCT WITH LICENSEE, OR OTHERWISE. BROADCOM SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THE SOFTWARE OR ANY UPGRADES TO OR DOCUMENTATION FOR THE SOFTWARE. WITHOUT LIMITATION OF THE ABOVE, BROADCOM GRANTS NO WARRANTY THAT THE SOFTWARE IS ERROR-FREE OR WILL OPERATE WITHOUT INTERRUPTION, AND GRANTS NO WARRANTY REGARDING ITS USE OR THE RESULTS THEREFROM INCLUDING, WITHOUT LIMITATION, ITS CORRECTNESS, ACCURACY OR RELIABILITY.
+
+3.2. No Support. Nothing in this agreement shall obligate Broadcom to provide any support for the Software. Broadcom may, but shall be under no obligation to, correct any defects in the Software and/or provide updates to licensees of the Software. Licensee shall make reasonable efforts to promptly report to Broadcom any defects it finds in the Software, as an aid to creating improved revisions of the Software.
+
+3.3. Dangerous Applications. The Software is not designed, intended, or certified for use in components of systems intended for the operation of weapons, weapons systems, nuclear installations, means of mass transportation, aviation, life-support computers or equipment (including resuscitation equipment and surgical implants), pollution control, hazardous substances management, or for any other dangerous application in which the failure of the Software could create a situation where personal injury or death may occur.  Licensee understands that use of the Software in such applications is fully at the risk of Licensee.
+
+4. TERM AND TERMINATION
+
+4.1. Termination. This Agreement will automatically terminate if Licensee fails to comply with any of the terms and conditions hereof. In such event, Licensee must destroy all copies of the Software and all of its component parts.
+
+4.2. Effect Of Termination. Upon any termination of this Agreement, the rights and licenses granted to Licensee under this Agreement shall immediately terminate.
+
+4.3. Survival. The rights and obligations under this Agreement which by their nature should survive termination will remain in effect after expiration or termination of this Agreement.
+
+5. CONFIDENTIALITY
+
+5.1. Obligations. Licensee acknowledges and agrees that any documentation relating to the Software, and any other information (if such other information is identified as confidential or should be recognized as confidential under the circumstances) provided to Licensee by Broadcom hereunder (collectively, “Confidential Information”) constitute the confidential and proprietary information of Broadcom, and that Licensee’s protection thereof is an essential condition to Licensee’s use and possession of the Software. Licensee shall retain all Confidential Information in strict confidence and not disclose it to any third party or use it in any way except under a written agreement with terms and conditions at least as protective as the terms of this Section. Licensee will exercise at least the same amount of diligence in preserving the secrecy of the Confidential Information as it uses in preserving the secrecy of its own most valuable confidential information, but in no event less than reasonable diligence. Information shall not be considered Confidential Information if and to the extent that it: (i) was in the public domain at the time it was disclosed or has entered the public domain through no fault of Licensee; (ii) was known to Licensee, without restriction, at the time of disclosure as proven by the files of Licensee in existence at the time of disclosure; or (iii) becomes known to Licensee, without restriction, from a source other than Broadcom without breach of this Agreement by Licensee and otherwise not in violation of Broadcom’s rights.
+
+5.2. Return of Confidential Information. Notwithstanding the foregoing, all documents and other tangible objects containing or representing Broadcom Confidential Information and all copies thereof which are in the possession of Licensee shall be and remain the property of Broadcom, and shall be promptly returned to Broadcom upon written request by Broadcom or upon termination of this Agreement.
+
+6. LIMITATION OF LIABILITY
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ANY OF BROADCOM’S LICENSORS HAVE ANY LIABILITY FOR ANY INDIRECT, INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER FOR BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS, EVEN IF SUCH PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In no event will Broadcom’s liability whether in contract, tort (including negligence), or otherwise, exceed the amount paid by Licensee for Software under this Agreement. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
+
+7. MISCELLANEOUS
+
+7.1. Assignment. This Agreement shall be binding upon and inure to the benefit of the parties and their respective successors and assigns, provided, however that Licensee may not assign this Agreement or any rights or obligation hereunder, directly or indirectly, by operation of law or otherwise, without the prior written consent of Broadcom, and any such attempted assignment shall be void. Notwithstanding the foregoing, Licensee may assign this Agreement to a successor to all or substantially all of its business or assets to which this Agreement relates that is not a competitor of Broadcom.
+
+7.2. Governing Law; Venue. This Agreement shall be governed by the laws of California without regard to any conflict-of-laws rules, and the United Nations Convention on Contracts for the International Sale of Goods is hereby excluded. The sole jurisdiction and venue for actions related to the subject matter hereof shall be the state and federal courts located in the County of Orange, California, and both parties hereby consent to such jurisdiction and venue.
+
+7.3. Severability. All terms and provisions of this Agreement shall, if possible, be construed in a manner which makes them valid, but in the event any term or provision of this Agreement is found by a court of competent jurisdiction to be illegal or unenforceable, the validity or enforceability of the remainder of this Agreement shall not be affected if the illegal or unenforceable provision does not materially affect the intent of this Agreement. If the illegal or unenforceable provision materially affects the intent of the parties to this Agreement, this Agreement shall become terminated.
+
+7.4. Equitable Relief. Licensee hereby acknowledges that its breach of this Agreement would cause irreparable harm and significant injury to Broadcom that may be difficult to ascertain and that a remedy at law would be inadequate. Accordingly, Licensee agrees that Broadcom shall have the right to seek and obtain immediate injunctive relief to enforce obligations under the Agreement in addition to any other rights and remedies it may have.
+
+7.5. Export Regulations. The parties agree that they shall each comply, at their own expense, with the U.S. Foreign Corrupt Practices Act and all  import and export laws, restrictions, national security controls and regulations of the United States and any applicable foreign agency or authority.  The parties shall not import, export or re-export, or authorize the export or re-export of the Software or any other product, technology, or information that it obtains or learns hereunder, or any copy or direct product thereof, in violation of any of such laws, restrictions, or regulations or without any license or approval required thereunder.  Any and all obligations of the parties to provide the Software or any other product, technology, or information hereunder shall be subject in all respects to such laws, restrictions, and regulations.
+
+7.6. Waiver. The waiver of, or failure to enforce, any breach or default hereunder shall not constitute the waiver of any other or subsequent breach or default.
+
+7.7. Entire Agreement. This Agreement sets forth the entire Agreement between the parties and supersedes any and all prior proposals, agreements and representations between them, whether written or oral concerning the Software. This Agreement may be changed only by mutual agreement of the parties in writing.
diff --git a/lib/wlc_hybrid.o_shipped b/lib/wlc_hybrid.o_shipped
new file mode 100644
index 0000000..91ecb23
--- /dev/null
+++ b/lib/wlc_hybrid.o_shipped
Binary files differ
diff --git a/src/common/include/proto/802.11.h b/src/common/include/proto/802.11.h
new file mode 100644
index 0000000..5b0ccb8
--- /dev/null
+++ b/src/common/include/proto/802.11.h
@@ -0,0 +1,3081 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id: 802.11.h 394280 2013-04-01 23:04:24Z $
+ */
+
+#ifndef _802_11_H_
+#define _802_11_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+#include <proto/wpa.h>
+
+#include <packed_section_start.h>
+
+#define DOT11_TU_TO_US 1024
+
+#define DOT11_A3_HDR_LEN 24
+#define DOT11_A4_HDR_LEN 30
+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN
+#define DOT11_FCS_LEN 4
+#define DOT11_ICV_LEN 4
+#define DOT11_ICV_AES_LEN 8
+#define DOT11_QOS_LEN 2
+#define DOT11_HTC_LEN 4
+
+#define DOT11_KEY_INDEX_SHIFT 6
+#define DOT11_IV_LEN 4
+#define DOT11_IV_TKIP_LEN 8
+#define DOT11_IV_AES_OCB_LEN 4
+#define DOT11_IV_AES_CCM_LEN 8
+#define DOT11_IV_MAX_LEN 8
+
+#define DOT11_MAX_MPDU_BODY_LEN 2304
+
+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ DOT11_IV_AES_CCM_LEN + \
+ DOT11_MAX_MPDU_BODY_LEN + \
+ DOT11_ICV_LEN + \
+ DOT11_FCS_LEN)
+
+#define DOT11_MAX_SSID_LEN 32
+
+#define DOT11_DEFAULT_RTS_LEN 2347
+#define DOT11_MAX_RTS_LEN 2347
+
+#define DOT11_MIN_FRAG_LEN 256
+#define DOT11_MAX_FRAG_LEN 2346
+#define DOT11_DEFAULT_FRAG_LEN 2346
+
+#define DOT11_MIN_BEACON_PERIOD 1
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF
+
+#define DOT11_MIN_DTIM_PERIOD 1
+#define DOT11_MAX_DTIM_PERIOD 0xFF
+
+#define DOT11_LLC_SNAP_HDR_LEN 8
+#define DOT11_OUI_LEN 3
+BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header {
+ uint8 dsap;
+ uint8 ssap;
+ uint8 ctl;
+ uint8 oui[DOT11_OUI_LEN];
+ uint16 type;
+} BWL_POST_PACKED_STRUCT;
+
+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN)
+
+BWL_PRE_PACKED_STRUCT struct dot11_header {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr a1;
+ struct ether_addr a2;
+ struct ether_addr a3;
+ uint16 seq;
+ struct ether_addr a4;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rts_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_RTS_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_cts_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CTS_LEN 10
+
+BWL_PRE_PACKED_STRUCT struct dot11_ack_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACK_LEN 10
+
+BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr bssid;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_PS_POLL_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+ struct ether_addr bssid;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CS_END_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific {
+ uint8 category;
+ uint8 OUI[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 data[1040];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr {
+ uint8 category;
+ uint8 OUI[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t;
+#define DOT11_ACTION_VS_HDR_LEN 6
+
+#define BCM_ACTION_OUI_BYTE0 0x00
+#define BCM_ACTION_OUI_BYTE1 0x90
+#define BCM_ACTION_OUI_BYTE2 0x4c
+
+#define DOT11_BA_CTL_POLICY_NORMAL 0x0000
+#define DOT11_BA_CTL_POLICY_NOACK 0x0001
+#define DOT11_BA_CTL_POLICY_MASK 0x0001
+
+#define DOT11_BA_CTL_MTID 0x0002
+#define DOT11_BA_CTL_COMPRESSED 0x0004
+
+#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0
+#define DOT11_BA_CTL_NUMMSDU_SHIFT 6
+
+#define DOT11_BA_CTL_TID_MASK 0xF000
+#define DOT11_BA_CTL_TID_SHIFT 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_ctl_header {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CTL_HDR_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_bar {
+ uint16 bar_control;
+ uint16 seqnum;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BAR_LEN 4
+
+#define DOT11_BA_BITMAP_LEN 128
+#define DOT11_BA_CMP_BITMAP_LEN 8
+
+BWL_PRE_PACKED_STRUCT struct dot11_ba {
+ uint16 ba_control;
+ uint16 seqnum;
+ uint8 bitmap[DOT11_BA_BITMAP_LEN];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BA_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_management_header {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr da;
+ struct ether_addr sa;
+ struct ether_addr bssid;
+ uint16 seq;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_MGMT_HDR_LEN 24
+
+BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb {
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 capability;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BCN_PRB_LEN 12
+#define DOT11_BCN_PRB_FIXED_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_auth {
+ uint16 alg;
+ uint16 seq;
+ uint16 status;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_AUTH_FIXED_LEN 6
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_req {
+ uint16 capability;
+ uint16 listen;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_REQ_FIXED_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req {
+ uint16 capability;
+ uint16 listen;
+ struct ether_addr ap;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_REASSOC_REQ_FIXED_LEN 10
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp {
+ uint16 capability;
+ uint16 status;
+ uint16 aid;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_RESP_FIXED_LEN 6
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_measure {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACTION_MEASURE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width {
+ uint8 category;
+ uint8 action;
+ uint8 ch_width;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops {
+ uint8 category;
+ uint8 action;
+ uint8 control;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query {
+ uint8 category;
+ uint8 action;
+ uint16 id;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_vht_oper_mode {
+ uint8 category;
+ uint8 action;
+ uint8 mode;
+} BWL_POST_PACKED_STRUCT;
+
+#define SM_PWRSAVE_ENABLE 1
+#define SM_PWRSAVE_MODE 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_power_cnst {
+ uint8 id;
+ uint8 len;
+ uint8 power;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_power_cnst dot11_power_cnst_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_power_cap {
+ uint8 min;
+ uint8 max;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_power_cap dot11_power_cap_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep {
+ uint8 id;
+ uint8 len;
+ uint8 tx_pwr;
+ uint8 margin;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tpc_rep dot11_tpc_rep_t;
+#define DOT11_MNG_IE_TPC_REPORT_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_supp_channels {
+ uint8 id;
+ uint8 len;
+ uint8 first_channel;
+ uint8 num_channels;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_supp_channels dot11_supp_channels_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_extch {
+ uint8 id;
+ uint8 len;
+ uint8 extch;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extch dot11_extch_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 type;
+ uint8 extch;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t;
+
+#define BRCM_EXTCH_IE_LEN 5
+#define BRCM_EXTCH_IE_TYPE 53
+#define DOT11_EXTCH_IE_LEN 1
+#define DOT11_EXT_CH_MASK 0x03
+#define DOT11_EXT_CH_UPPER 0x01
+#define DOT11_EXT_CH_LOWER 0x03
+#define DOT11_EXT_CH_NONE 0x00
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr {
+ uint8 category;
+ uint8 action;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACTION_FRMHDR_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch {
+ uint8 id;
+ uint8 len;
+ uint8 mode;
+ uint8 channel;
+ uint8 count;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_channel_switch dot11_chan_switch_ie_t;
+
+#define DOT11_SWITCH_IE_LEN 3
+
+#define DOT11_CSA_MODE_ADVISORY 0
+#define DOT11_CSA_MODE_NO_TX 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel {
+ uint8 category;
+ uint8 action;
+ dot11_chan_switch_ie_t chan_switch_ie;
+ dot11_brcm_extch_ie_t extch_ie;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_csa_body {
+ uint8 mode;
+ uint8 reg;
+ uint8 channel;
+ uint8 count;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ext_csa {
+ uint8 id;
+ uint8 len;
+ struct dot11_csa_body b;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ext_csa dot11_ext_csa_ie_t;
+#define DOT11_EXT_CSA_IE_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ dot11_ext_csa_ie_t chan_switch_ie;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ struct dot11_csa_body b;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_wide_bw_channel_switch {
+ uint8 id;
+ uint8 len;
+ uint8 channel_width;
+ uint8 center_frequency_segment_0;
+ uint8 center_frequency_segment_1;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wide_bw_channel_switch dot11_wide_bw_chan_switch_ie_t;
+
+#define DOT11_WIDE_BW_SWITCH_IE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch_wrapper {
+ uint8 id;
+ uint8 len;
+ dot11_wide_bw_chan_switch_ie_t wb_chan_switch_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_channel_switch_wrapper dot11_chan_switch_wrapper_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_vht_transmit_power_envelope {
+ uint8 id;
+ uint8 len;
+ uint8 transmit_power_info;
+ uint8 local_max_transmit_power_20;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_vht_transmit_power_envelope dot11_vht_transmit_power_envelope_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_coex {
+ uint8 id;
+ uint8 len;
+ uint8 info;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_coex dot11_obss_coex_t;
+#define DOT11_OBSS_COEXINFO_LEN 1
+
+#define DOT11_OBSS_COEX_INFO_REQ 0x01
+#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02
+#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist {
+ uint8 id;
+ uint8 len;
+ uint8 regclass;
+ uint8 chanlist[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_chanlist dot11_obss_chanlist_t;
+#define DOT11_OBSS_CHANLIST_FIXED_LEN 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie {
+ uint8 id;
+ uint8 len;
+ uint8 cap[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extcap_ie dot11_extcap_ie_t;
+
+#define DOT11_EXTCAP_LEN_MAX 8
+#define DOT11_EXTCAP_LEN_COEX 1
+#define DOT11_EXTCAP_LEN_BT 3
+#define DOT11_EXTCAP_LEN_IW 4
+#define DOT11_EXTCAP_LEN_SI 6
+
+#define DOT11_EXTCAP_LEN_TDLS 5
+#define DOT11_11AC_EXTCAP_LEN_TDLS 8
+
+#define DOT11_EXTCAP_LEN_FMS 2
+#define DOT11_EXTCAP_LEN_PROXY_ARP 2
+#define DOT11_EXTCAP_LEN_TFS 3
+#define DOT11_EXTCAP_LEN_WNM_SLEEP 3
+#define DOT11_EXTCAP_LEN_TIMBC 3
+#define DOT11_EXTCAP_LEN_BSS_TRANSITION 3
+#define DOT11_EXTCAP_LEN_DMS 4
+#define DOT11_EXTCAP_LEN_WNM_NOTIFICATION 6
+#define DOT11_EXTCAP_LEN_TDLS_WBW 8
+#define DOT11_EXTCAP_LEN_OPMODE_NOTIFICATION 8
+
+BWL_PRE_PACKED_STRUCT struct dot11_extcap {
+ uint8 extcap[DOT11_EXTCAP_LEN_MAX];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extcap dot11_extcap_t;
+
+#define DOT11_TDLS_CAP_TDLS 37
+#define DOT11_TDLS_CAP_PU_BUFFER_STA 28
+#define DOT11_TDLS_CAP_PEER_PSM 20
+#define DOT11_TDLS_CAP_CH_SW 30
+#define DOT11_TDLS_CAP_PROH 38
+#define DOT11_TDLS_CAP_CH_SW_PROH 39
+#define DOT11_TDLS_CAP_TDLS_WIDER_BW 61
+
+#define DOT11_MEASURE_TYPE_BASIC 0
+#define DOT11_MEASURE_TYPE_CCA 1
+#define DOT11_MEASURE_TYPE_RPI 2
+#define DOT11_MEASURE_TYPE_CHLOAD 3
+#define DOT11_MEASURE_TYPE_NOISE 4
+#define DOT11_MEASURE_TYPE_BEACON 5
+#define DOT11_MEASURE_TYPE_FRAME 6
+#define DOT11_MEASURE_TYPE_STAT 7
+#define DOT11_MEASURE_TYPE_LCI 8
+#define DOT11_MEASURE_TYPE_TXSTREAM 9
+#define DOT11_MEASURE_TYPE_PAUSE 255
+
+#define DOT11_MEASURE_MODE_PARALLEL (1<<0)
+#define DOT11_MEASURE_MODE_ENABLE (1<<1)
+#define DOT11_MEASURE_MODE_REQUEST (1<<2)
+#define DOT11_MEASURE_MODE_REPORT (1<<3)
+#define DOT11_MEASURE_MODE_DUR (1<<4)
+
+#define DOT11_MEASURE_MODE_LATE (1<<0)
+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1)
+#define DOT11_MEASURE_MODE_REFUSED (1<<2)
+
+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0))
+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1))
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2))
+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3))
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4))
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_req {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_req dot11_meas_req_t;
+#define DOT11_MNG_IE_MREQ_LEN 14
+
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ BWL_PRE_PACKED_STRUCT union
+ {
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+ } BWL_POST_PACKED_STRUCT basic;
+ uint8 data[1];
+ } BWL_POST_PACKED_STRUCT rep;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_rep dot11_meas_rep_t;
+
+#define DOT11_MNG_IE_MREP_FIXED_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
+#define DOT11_MEASURE_BASIC_REP_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_quiet {
+ uint8 id;
+ uint8 len;
+ uint8 count;
+ uint8 period;
+ uint16 duration;
+ uint16 offset;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_quiet dot11_quiet_t;
+
+BWL_PRE_PACKED_STRUCT struct chan_map_tuple {
+ uint8 channel;
+ uint8 map;
+} BWL_POST_PACKED_STRUCT;
+typedef struct chan_map_tuple chan_map_tuple_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs {
+ uint8 id;
+ uint8 len;
+ uint8 eaddr[ETHER_ADDR_LEN];
+ uint8 interval;
+ chan_map_tuple_t map[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ibss_dfs dot11_ibss_dfs_t;
+
+#define WME_OUI "\x00\x50\xf2"
+#define WME_OUI_LEN 3
+#define WME_OUI_TYPE 2
+#define WME_TYPE 2
+#define WME_SUBTYPE_IE 0
+#define WME_SUBTYPE_PARAM_IE 1
+#define WME_SUBTYPE_TSPEC 2
+#define WME_VER 1
+
+#define AC_BE 0
+#define AC_BK 1
+#define AC_VI 2
+#define AC_VO 3
+#define AC_COUNT 4
+
+typedef uint8 ac_bitmap_t;
+
+#define AC_BITMAP_NONE 0x0
+#define AC_BITMAP_ALL 0xf
+#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0)
+#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac))))
+#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac))))
+
+BWL_PRE_PACKED_STRUCT struct wme_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct wme_ie wme_ie_t;
+#define WME_IE_LEN 7
+
+BWL_PRE_PACKED_STRUCT struct edcf_acparam {
+ uint8 ACI;
+ uint8 ECW;
+ uint16 TXOP;
+} BWL_POST_PACKED_STRUCT;
+typedef struct edcf_acparam edcf_acparam_t;
+
+BWL_PRE_PACKED_STRUCT struct wme_param_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} BWL_POST_PACKED_STRUCT;
+typedef struct wme_param_ie wme_param_ie_t;
+#define WME_PARAM_IE_LEN 24
+
+#define WME_QI_AP_APSD_MASK 0x80
+#define WME_QI_AP_APSD_SHIFT 7
+#define WME_QI_AP_COUNT_MASK 0x0f
+#define WME_QI_AP_COUNT_SHIFT 0
+
+#define WME_QI_STA_MAXSPLEN_MASK 0x60
+#define WME_QI_STA_MAXSPLEN_SHIFT 5
+#define WME_QI_STA_APSD_ALL_MASK 0xf
+#define WME_QI_STA_APSD_ALL_SHIFT 0
+#define WME_QI_STA_APSD_BE_MASK 0x8
+#define WME_QI_STA_APSD_BE_SHIFT 3
+#define WME_QI_STA_APSD_BK_MASK 0x4
+#define WME_QI_STA_APSD_BK_SHIFT 2
+#define WME_QI_STA_APSD_VI_MASK 0x2
+#define WME_QI_STA_APSD_VI_SHIFT 1
+#define WME_QI_STA_APSD_VO_MASK 0x1
+#define WME_QI_STA_APSD_VO_SHIFT 0
+
+#define EDCF_AIFSN_MIN 1
+#define EDCF_AIFSN_MAX 15
+#define EDCF_AIFSN_MASK 0x0f
+#define EDCF_ACM_MASK 0x10
+#define EDCF_ACI_MASK 0x60
+#define EDCF_ACI_SHIFT 5
+#define EDCF_AIFSN_SHIFT 12
+
+#define EDCF_ECW_MIN 0
+#define EDCF_ECW_MAX 15
+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
+#define EDCF_ECWMIN_MASK 0x0f
+#define EDCF_ECWMAX_MASK 0xf0
+#define EDCF_ECWMAX_SHIFT 4
+
+#define EDCF_TXOP_MIN 0
+#define EDCF_TXOP_MAX 65535
+#define EDCF_TXOP2USEC(txop) ((txop) << 5)
+
+#define NON_EDCF_AC_BE_ACI_STA 0x02
+
+#define EDCF_AC_BE_ACI_STA 0x03
+#define EDCF_AC_BE_ECW_STA 0xA4
+#define EDCF_AC_BE_TXOP_STA 0x0000
+#define EDCF_AC_BK_ACI_STA 0x27
+#define EDCF_AC_BK_ECW_STA 0xA4
+#define EDCF_AC_BK_TXOP_STA 0x0000
+#define EDCF_AC_VI_ACI_STA 0x42
+#define EDCF_AC_VI_ECW_STA 0x43
+#define EDCF_AC_VI_TXOP_STA 0x005e
+#define EDCF_AC_VO_ACI_STA 0x62
+#define EDCF_AC_VO_ECW_STA 0x32
+#define EDCF_AC_VO_TXOP_STA 0x002f
+
+#define EDCF_AC_BE_ACI_AP 0x03
+#define EDCF_AC_BE_ECW_AP 0x64
+#define EDCF_AC_BE_TXOP_AP 0x0000
+#define EDCF_AC_BK_ACI_AP 0x27
+#define EDCF_AC_BK_ECW_AP 0xA4
+#define EDCF_AC_BK_TXOP_AP 0x0000
+#define EDCF_AC_VI_ACI_AP 0x41
+#define EDCF_AC_VI_ECW_AP 0x43
+#define EDCF_AC_VI_TXOP_AP 0x005e
+#define EDCF_AC_VO_ACI_AP 0x61
+#define EDCF_AC_VO_ECW_AP 0x32
+#define EDCF_AC_VO_TXOP_AP 0x002f
+
+BWL_PRE_PACKED_STRUCT struct edca_param_ie {
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} BWL_POST_PACKED_STRUCT;
+typedef struct edca_param_ie edca_param_ie_t;
+#define EDCA_PARAM_IE_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct qos_cap_ie {
+ uint8 qosinfo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct qos_cap_ie qos_cap_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie {
+ uint8 id;
+ uint8 length;
+ uint16 station_count;
+ uint8 channel_utilization;
+ uint16 aac;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t;
+#define BSS_LOAD_IE_SIZE 7
+
+#define FIXED_MSDU_SIZE 0x8000
+#define MSDU_SIZE_MASK 0x7fff
+
+#define INTEGER_SHIFT 13
+#define FRACTION_MASK 0x1FFF
+
+BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_MGMT_NOTIFICATION_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct ti_ie {
+ uint8 ti_type;
+ uint32 ti_val;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ti_ie ti_ie_t;
+#define TI_TYPE_REASSOC_DEADLINE 1
+#define TI_TYPE_KEY_LIFETIME 2
+
+#define WME_ADDTS_REQUEST 0
+#define WME_ADDTS_RESPONSE 1
+#define WME_DELTS_REQUEST 2
+
+#define WME_ADMISSION_ACCEPTED 0
+#define WME_INVALID_PARAMETERS 1
+#define WME_ADMISSION_REFUSED 3
+
+#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN)
+
+#define DOT11_OPEN_SYSTEM 0
+#define DOT11_SHARED_KEY 1
+#define DOT11_FAST_BSS 2
+#define DOT11_CHALLENGE_LEN 128
+
+#define FC_PVER_MASK 0x3
+#define FC_PVER_SHIFT 0
+#define FC_TYPE_MASK 0xC
+#define FC_TYPE_SHIFT 2
+#define FC_SUBTYPE_MASK 0xF0
+#define FC_SUBTYPE_SHIFT 4
+#define FC_TODS 0x100
+#define FC_TODS_SHIFT 8
+#define FC_FROMDS 0x200
+#define FC_FROMDS_SHIFT 9
+#define FC_MOREFRAG 0x400
+#define FC_MOREFRAG_SHIFT 10
+#define FC_RETRY 0x800
+#define FC_RETRY_SHIFT 11
+#define FC_PM 0x1000
+#define FC_PM_SHIFT 12
+#define FC_MOREDATA 0x2000
+#define FC_MOREDATA_SHIFT 13
+#define FC_WEP 0x4000
+#define FC_WEP_SHIFT 14
+#define FC_ORDER 0x8000
+#define FC_ORDER_SHIFT 15
+
+#define SEQNUM_SHIFT 4
+#define SEQNUM_MAX 0x1000
+#define FRAGNUM_MASK 0xF
+
+#define FC_TYPE_MNG 0
+#define FC_TYPE_CTL 1
+#define FC_TYPE_DATA 2
+
+#define FC_SUBTYPE_ASSOC_REQ 0
+#define FC_SUBTYPE_ASSOC_RESP 1
+#define FC_SUBTYPE_REASSOC_REQ 2
+#define FC_SUBTYPE_REASSOC_RESP 3
+#define FC_SUBTYPE_PROBE_REQ 4
+#define FC_SUBTYPE_PROBE_RESP 5
+#define FC_SUBTYPE_BEACON 8
+#define FC_SUBTYPE_ATIM 9
+#define FC_SUBTYPE_DISASSOC 10
+#define FC_SUBTYPE_AUTH 11
+#define FC_SUBTYPE_DEAUTH 12
+#define FC_SUBTYPE_ACTION 13
+#define FC_SUBTYPE_ACTION_NOACK 14
+
+#define FC_SUBTYPE_CTL_WRAPPER 7
+#define FC_SUBTYPE_BLOCKACK_REQ 8
+#define FC_SUBTYPE_BLOCKACK 9
+#define FC_SUBTYPE_PS_POLL 10
+#define FC_SUBTYPE_RTS 11
+#define FC_SUBTYPE_CTS 12
+#define FC_SUBTYPE_ACK 13
+#define FC_SUBTYPE_CF_END 14
+#define FC_SUBTYPE_CF_END_ACK 15
+
+#define FC_SUBTYPE_DATA 0
+#define FC_SUBTYPE_DATA_CF_ACK 1
+#define FC_SUBTYPE_DATA_CF_POLL 2
+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3
+#define FC_SUBTYPE_NULL 4
+#define FC_SUBTYPE_CF_ACK 5
+#define FC_SUBTYPE_CF_POLL 6
+#define FC_SUBTYPE_CF_ACK_POLL 7
+#define FC_SUBTYPE_QOS_DATA 8
+#define FC_SUBTYPE_QOS_DATA_CF_ACK 9
+#define FC_SUBTYPE_QOS_DATA_CF_POLL 10
+#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11
+#define FC_SUBTYPE_QOS_NULL 12
+#define FC_SUBTYPE_QOS_CF_POLL 14
+#define FC_SUBTYPE_QOS_CF_ACK_POLL 15
+
+#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0)
+#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0)
+#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0)
+#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0)
+
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK)
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))
+
+#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT)
+#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT)
+
+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ)
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP)
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ)
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP)
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ)
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP)
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON)
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC)
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH)
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH)
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION)
+#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK)
+
+#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER)
+#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ)
+#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK)
+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL)
+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS)
+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS)
+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK)
+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END)
+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK)
+
+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA)
+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL)
+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK)
+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA)
+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL)
+
+#define QOS_PRIO_SHIFT 0
+#define QOS_PRIO_MASK 0x0007
+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT)
+
+#define QOS_TID_SHIFT 0
+#define QOS_TID_MASK 0x000f
+#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT)
+
+#define QOS_EOSP_SHIFT 4
+#define QOS_EOSP_MASK 0x0010
+#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT)
+
+#define QOS_ACK_NORMAL_ACK 0
+#define QOS_ACK_NO_ACK 1
+#define QOS_ACK_NO_EXP_ACK 2
+#define QOS_ACK_BLOCK_ACK 3
+#define QOS_ACK_SHIFT 5
+#define QOS_ACK_MASK 0x0060
+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT)
+
+#define QOS_AMSDU_SHIFT 7
+#define QOS_AMSDU_MASK 0x0080
+
+#define DOT11_MNG_AUTH_ALGO_LEN 2
+#define DOT11_MNG_AUTH_SEQ_LEN 2
+#define DOT11_MNG_BEACON_INT_LEN 2
+#define DOT11_MNG_CAP_LEN 2
+#define DOT11_MNG_AP_ADDR_LEN 6
+#define DOT11_MNG_LISTEN_INT_LEN 2
+#define DOT11_MNG_REASON_LEN 2
+#define DOT11_MNG_AID_LEN 2
+#define DOT11_MNG_STATUS_LEN 2
+#define DOT11_MNG_TIMESTAMP_LEN 8
+
+#define DOT11_AID_MASK 0x3fff
+
+#define DOT11_RC_RESERVED 0
+#define DOT11_RC_UNSPECIFIED 1
+#define DOT11_RC_AUTH_INVAL 2
+#define DOT11_RC_DEAUTH_LEAVING 3
+#define DOT11_RC_INACTIVITY 4
+#define DOT11_RC_BUSY 5
+#define DOT11_RC_INVAL_CLASS_2 6
+#define DOT11_RC_INVAL_CLASS_3 7
+#define DOT11_RC_DISASSOC_LEAVING 8
+#define DOT11_RC_NOT_AUTH 9
+#define DOT11_RC_BAD_PC 10
+#define DOT11_RC_BAD_CHANNELS 11
+
+#define DOT11_RC_UNSPECIFIED_QOS 32
+#define DOT11_RC_INSUFFCIENT_BW 33
+#define DOT11_RC_EXCESSIVE_FRAMES 34
+#define DOT11_RC_TX_OUTSIDE_TXOP 35
+#define DOT11_RC_LEAVING_QBSS 36
+#define DOT11_RC_BAD_MECHANISM 37
+#define DOT11_RC_SETUP_NEEDED 38
+#define DOT11_RC_TIMEOUT 39
+
+#define DOT11_RC_MAX 23
+
+#define DOT11_RC_TDLS_PEER_UNREACH 25
+#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26
+
+#define DOT11_SC_SUCCESS 0
+#define DOT11_SC_FAILURE 1
+#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2
+
+#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3
+#define DOT11_SC_TDLS_SEC_DISABLED 5
+#define DOT11_SC_LIFETIME_REJ 6
+#define DOT11_SC_NOT_SAME_BSS 7
+#define DOT11_SC_CAP_MISMATCH 10
+#define DOT11_SC_REASSOC_FAIL 11
+#define DOT11_SC_ASSOC_FAIL 12
+#define DOT11_SC_AUTH_MISMATCH 13
+#define DOT11_SC_AUTH_SEQ 14
+#define DOT11_SC_AUTH_CHALLENGE_FAIL 15
+#define DOT11_SC_AUTH_TIMEOUT 16
+#define DOT11_SC_ASSOC_BUSY_FAIL 17
+#define DOT11_SC_ASSOC_RATE_MISMATCH 18
+#define DOT11_SC_ASSOC_SHORT_REQUIRED 19
+#define DOT11_SC_ASSOC_PBCC_REQUIRED 20
+#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21
+#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22
+#define DOT11_SC_ASSOC_BAD_POWER_CAP 23
+#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24
+#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25
+#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26
+#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27
+#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28
+#define DOT11_SC_ASSOC_TRY_LATER 30
+#define DOT11_SC_ASSOC_MFP_VIOLATION 31
+
+#define DOT11_SC_DECLINED 37
+#define DOT11_SC_INVALID_PARAMS 38
+#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42
+#define DOT11_SC_INVALID_AKMP 43
+#define DOT11_SC_INVALID_RSNIE_CAP 45
+#define DOT11_SC_DLS_NOT_ALLOWED 48
+#define DOT11_SC_INVALID_PMKID 53
+#define DOT11_SC_INVALID_MDID 54
+#define DOT11_SC_INVALID_FTIE 55
+
+#define DOT11_SC_ADV_PROTO_NOT_SUPPORTED 59
+#define DOT11_SC_NO_OUTSTAND_REQ 60
+#define DOT11_SC_RSP_NOT_RX_FROM_SERVER 61
+#define DOT11_SC_TIMEOUT 62
+#define DOT11_SC_QUERY_RSP_TOO_LARGE 63
+#define DOT11_SC_SERVER_UNREACHABLE 65
+
+#define DOT11_SC_UNEXP_MSG 70
+#define DOT11_SC_INVALID_SNONCE 71
+#define DOT11_SC_INVALID_RSNIE 72
+
+#define DOT11_SC_TRANSMIT_FAILURE 79
+
+#define DOT11_MNG_DS_PARAM_LEN 1
+#define DOT11_MNG_IBSS_PARAM_LEN 2
+
+#define DOT11_MNG_TIM_FIXED_LEN 3
+#define DOT11_MNG_TIM_DTIM_COUNT 0
+#define DOT11_MNG_TIM_DTIM_PERIOD 1
+#define DOT11_MNG_TIM_BITMAP_CTL 2
+#define DOT11_MNG_TIM_PVB 3
+
+#define TLV_TAG_OFF 0
+#define TLV_LEN_OFF 1
+#define TLV_HDR_LEN 2
+#define TLV_BODY_OFF 2
+
+#define DOT11_MNG_SSID_ID 0
+#define DOT11_MNG_RATES_ID 1
+#define DOT11_MNG_FH_PARMS_ID 2
+#define DOT11_MNG_DS_PARMS_ID 3
+#define DOT11_MNG_CF_PARMS_ID 4
+#define DOT11_MNG_TIM_ID 5
+#define DOT11_MNG_IBSS_PARMS_ID 6
+#define DOT11_MNG_COUNTRY_ID 7
+#define DOT11_MNG_HOPPING_PARMS_ID 8
+#define DOT11_MNG_HOPPING_TABLE_ID 9
+#define DOT11_MNG_REQUEST_ID 10
+#define DOT11_MNG_QBSS_LOAD_ID 11
+#define DOT11_MNG_EDCA_PARAM_ID 12
+#define DOT11_MNG_TSPEC_ID 13
+#define DOT11_MNG_TCLAS_ID 14
+#define DOT11_MNG_CHALLENGE_ID 16
+#define DOT11_MNG_PWR_CONSTRAINT_ID 32
+#define DOT11_MNG_PWR_CAP_ID 33
+#define DOT11_MNG_TPC_REQUEST_ID 34
+#define DOT11_MNG_TPC_REPORT_ID 35
+#define DOT11_MNG_SUPP_CHANNELS_ID 36
+#define DOT11_MNG_CHANNEL_SWITCH_ID 37
+#define DOT11_MNG_MEASURE_REQUEST_ID 38
+#define DOT11_MNG_MEASURE_REPORT_ID 39
+#define DOT11_MNG_QUIET_ID 40
+#define DOT11_MNG_IBSS_DFS_ID 41
+#define DOT11_MNG_ERP_ID 42
+#define DOT11_MNG_TS_DELAY_ID 43
+#define DOT11_MNG_TCLAS_PROC_ID 44
+#define DOT11_MNG_HT_CAP 45
+#define DOT11_MNG_QOS_CAP_ID 46
+#define DOT11_MNG_NONERP_ID 47
+#define DOT11_MNG_RSN_ID 48
+#define DOT11_MNG_EXT_RATES_ID 50
+#define DOT11_MNG_AP_CHREP_ID 51
+#define DOT11_MNG_NBR_REP_ID 52
+#define DOT11_MNG_RCPI_ID 53
+#define DOT11_MNG_MDIE_ID 54
+#define DOT11_MNG_FTIE_ID 55
+#define DOT11_MNG_FT_TI_ID 56
+#define DOT11_MNG_RDE_ID 57
+#define DOT11_MNG_REGCLASS_ID 59
+#define DOT11_MNG_EXT_CSA_ID 60
+#define DOT11_MNG_HT_ADD 61
+#define DOT11_MNG_EXT_CHANNEL_OFFSET 62
+#define DOT11_MNG_BSS_AVR_ACCESS_DELAY_ID 63
+#define DOT11_MNG_ANTENNA_ID 64
+#define DOT11_MNG_RSNI_ID 65
+#define DOT11_MNG_MEASUREMENT_PILOT_TX_ID 66
+#define DOT11_MNG_BSS_AVAL_ADMISSION_CAP_ID 67
+#define DOT11_MNG_BSS_AC_ACCESS_DELAY_ID 68
+#define DOT11_MNG_WAPI_ID 68
+#define DOT11_MNG_TIME_ADVERTISE_ID 69
+#define DOT11_MNG_RRM_CAP_ID 70
+#define DOT11_MNG_MULTIPLE_BSSID_ID 71
+#define DOT11_MNG_HT_BSS_COEXINFO_ID 72
+#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73
+#define DOT11_MNG_HT_OBSS_ID 74
+#define DOT11_MNG_MMIE_ID 76
+#define DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID 90
+#define DOT11_MNG_TFS_REQUEST_ID 91
+#define DOT11_MNG_TFS_RESPONSE_ID 92
+#define DOT11_MNG_WNM_SLEEP_MODE_ID 93
+#define DOT11_MNG_TIMBC_REQ_ID 94
+#define DOT11_MNG_TIMBC_RESP_ID 95
+#define DOT11_MNG_CHANNEL_USAGE 97
+#define DOT11_MNG_TIME_ZONE_ID 98
+#define DOT11_MNG_DMS_REQUEST_ID 99
+#define DOT11_MNG_DMS_RESPONSE_ID 100
+#define DOT11_MNG_LINK_IDENTIFIER_ID 101
+#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102
+#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104
+#define DOT11_MNG_PTI_CONTROL_ID 105
+#define DOT11_MNG_PU_BUFFER_STATUS_ID 106
+#define DOT11_MNG_INTERWORKING_ID 107
+#define DOT11_MNG_ADVERTISEMENT_ID 108
+#define DOT11_MNG_EXP_BW_REQ_ID 109
+#define DOT11_MNG_QOS_MAP_ID 110
+#define DOT11_MNG_ROAM_CONSORT_ID 111
+#define DOT11_MNG_EMERGCY_ALERT_ID 112
+#define DOT11_MNG_EXT_CAP_ID 127
+#define DOT11_MNG_VHT_CAP_ID 191
+#define DOT11_MNG_VHT_OPERATION_ID 192
+#define DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID 194
+#define DOT11_MNG_VHT_TRANSMIT_POWER_ENVELOPE_ID 195
+#define DOT11_MNG_CHANNEL_SWITCH_WRAPPER_ID 196
+#define DOT11_MNG_AID_ID 197
+#define DOT11_MNG_OPER_MODE_NOTIF_ID 199
+
+#define DOT11_MNG_WPA_ID 221
+#define DOT11_MNG_PROPR_ID 221
+
+#define DOT11_MNG_VS_ID 221
+
+#define DOT11_RATE_1M 2
+#define DOT11_RATE_2M 4
+#define DOT11_RATE_5M5 11
+#define DOT11_RATE_11M 22
+#define DOT11_RATE_6M 12
+#define DOT11_RATE_9M 18
+#define DOT11_RATE_12M 24
+#define DOT11_RATE_18M 36
+#define DOT11_RATE_24M 48
+#define DOT11_RATE_36M 72
+#define DOT11_RATE_48M 96
+#define DOT11_RATE_54M 108
+#define DOT11_RATE_MAX 108
+
+#define DOT11_RATE_BASIC 0x80
+#define DOT11_RATE_MASK 0x7F
+
+#define DOT11_MNG_ERP_LEN 1
+#define DOT11_MNG_NONERP_PRESENT 0x01
+#define DOT11_MNG_USE_PROTECTION 0x02
+#define DOT11_MNG_BARKER_PREAMBLE 0x04
+
+#define DOT11_MGN_TS_DELAY_LEN 4
+#define TS_DELAY_FIELD_SIZE 4
+
+#define DOT11_CAP_ESS 0x0001
+#define DOT11_CAP_IBSS 0x0002
+#define DOT11_CAP_POLLABLE 0x0004
+#define DOT11_CAP_POLL_RQ 0x0008
+#define DOT11_CAP_PRIVACY 0x0010
+#define DOT11_CAP_SHORT 0x0020
+#define DOT11_CAP_PBCC 0x0040
+#define DOT11_CAP_AGILITY 0x0080
+#define DOT11_CAP_SPECTRUM 0x0100
+#define DOT11_CAP_QOS 0x0200
+#define DOT11_CAP_SHORTSLOT 0x0400
+#define DOT11_CAP_APSD 0x0800
+#define DOT11_CAP_RRM 0x1000
+#define DOT11_CAP_CCK_OFDM 0x2000
+#define DOT11_CAP_DELAY_BA 0x4000
+#define DOT11_CAP_IMMEDIATE_BA 0x8000
+
+#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0
+
+#define DOT11_EXT_CAP_SPSMP 6
+
+#define DOT11_EXT_CAP_FMS 11
+
+#define DOT11_EXT_CAP_PROXY_ARP 12
+
+#define DOT11_EXT_CAP_TFS 16
+
+#define DOT11_EXT_CAP_WNM_SLEEP 17
+
+#define DOT11_EXT_CAP_TIMBC 18
+
+#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19
+
+#define DOT11_EXT_CAP_DMS 26
+
+#define DOT11_EXT_CAP_IW 31
+
+#define DOT11_EXT_CAP_SI 41
+#define DOT11_EXT_CAP_SI_MASK 0x0E
+
+#define DOT11_EXT_CAP_WNM_NOTIF 46
+
+#define DOT11_EXT_CAP_OPER_MODE_NOTIF 62
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT 0
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_MASK 0x3
+#define DOT11_OPER_MODE_RXNSS_SHIFT 4
+#define DOT11_OPER_MODE_RXNSS_MASK 0x70
+#define DOT11_OPER_MODE_RXNSS_TYPE_SHIFT 7
+#define DOT11_OPER_MODE_RXNSS_TYPE_MASK 0x80
+
+#define DOT11_OPER_MODE(type, nss, chanw) (\
+ ((type) << DOT11_OPER_MODE_RXNSS_TYPE_SHIFT &\
+ DOT11_OPER_MODE_RXNSS_TYPE_MASK) |\
+ (((nss) - 1) << DOT11_OPER_MODE_RXNSS_SHIFT & DOT11_OPER_MODE_RXNSS_MASK) |\
+ ((chanw) << DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT &\
+ DOT11_OPER_MODE_CHANNEL_WIDTH_MASK))
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH(mode) \
+ (((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK)\
+ >> DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT)
+#define DOT11_OPER_MODE_RXNSS(mode) \
+ ((((mode) & DOT11_OPER_MODE_RXNSS_MASK) \
+ >> DOT11_OPER_MODE_RXNSS_SHIFT) + 1)
+#define DOT11_OPER_MODE_RXNSS_TYPE(mode) \
+ (((mode) & DOT11_OPER_MODE_RXNSS_TYPE_MASK)\
+ >> DOT11_OPER_MODE_RXNSS_TYPE_SHIFT)
+
+#define DOT11_OPER_MODE_20MHZ 0
+#define DOT11_OPER_MODE_40MHZ 1
+#define DOT11_OPER_MODE_80MHZ 2
+#define DOT11_OPER_MODE_160MHZ 3
+#define DOT11_OPER_MODE_8080MHZ 3
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_20MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_20MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_40MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_40MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_80MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_80MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_160MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_160MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_8080MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_8080MHZ)
+
+BWL_PRE_PACKED_STRUCT struct dot11_oper_mode_notif_ie {
+ uint8 mode;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_oper_mode_notif_ie dot11_oper_mode_notif_ie_t;
+
+#define DOT11_OPER_MODE_NOTIF_IE_LEN 1
+
+#define DOT11_ACTION_HDR_LEN 2
+#define DOT11_ACTION_CAT_OFF 0
+#define DOT11_ACTION_ACT_OFF 1
+
+#define DOT11_ACTION_CAT_ERR_MASK 0x80
+#define DOT11_ACTION_CAT_MASK 0x7F
+#define DOT11_ACTION_CAT_SPECT_MNG 0
+#define DOT11_ACTION_CAT_QOS 1
+#define DOT11_ACTION_CAT_DLS 2
+#define DOT11_ACTION_CAT_BLOCKACK 3
+#define DOT11_ACTION_CAT_PUBLIC 4
+#define DOT11_ACTION_CAT_RRM 5
+#define DOT11_ACTION_CAT_FBT 6
+#define DOT11_ACTION_CAT_HT 7
+#define DOT11_ACTION_CAT_SA_QUERY 8
+#define DOT11_ACTION_CAT_PDPA 9
+#define DOT11_ACTION_CAT_WNM 10
+#define DOT11_ACTION_CAT_UWNM 11
+#define DOT11_ACTION_NOTIFICATION 17
+#define DOT11_ACTION_CAT_VHT 21
+#define DOT11_ACTION_CAT_VSP 126
+#define DOT11_ACTION_CAT_VS 127
+
+#define DOT11_SM_ACTION_M_REQ 0
+#define DOT11_SM_ACTION_M_REP 1
+#define DOT11_SM_ACTION_TPC_REQ 2
+#define DOT11_SM_ACTION_TPC_REP 3
+#define DOT11_SM_ACTION_CHANNEL_SWITCH 4
+#define DOT11_SM_ACTION_EXT_CSA 5
+
+#define DOT11_ACTION_ID_HT_CH_WIDTH 0
+#define DOT11_ACTION_ID_HT_MIMO_PS 1
+
+#define DOT11_PUB_ACTION_BSS_COEX_MNG 0
+#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4
+#define DOT11_PUB_ACTION_GAS_CB_REQ 12
+
+#define DOT11_BA_ACTION_ADDBA_REQ 0
+#define DOT11_BA_ACTION_ADDBA_RESP 1
+#define DOT11_BA_ACTION_DELBA 2
+
+#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001
+#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002
+#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1
+#define DOT11_ADDBA_PARAM_TID_MASK 0x003c
+#define DOT11_ADDBA_PARAM_TID_SHIFT 2
+#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0
+#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6
+
+#define DOT11_ADDBA_POLICY_DELAYED 0
+#define DOT11_ADDBA_POLICY_IMMEDIATE 1
+
+#define DOT11_FT_ACTION_FT_RESERVED 0
+#define DOT11_FT_ACTION_FT_REQ 1
+#define DOT11_FT_ACTION_FT_RES 2
+#define DOT11_FT_ACTION_FT_CON 3
+#define DOT11_FT_ACTION_FT_ACK 4
+
+#define DOT11_DLS_ACTION_REQ 0
+#define DOT11_DLS_ACTION_RESP 1
+#define DOT11_DLS_ACTION_TD 2
+
+#define DOT11_WNM_ACTION_EVENT_REQ 0
+#define DOT11_WNM_ACTION_EVENT_REP 1
+#define DOT11_WNM_ACTION_DIAG_REQ 2
+#define DOT11_WNM_ACTION_DIAG_REP 3
+#define DOT11_WNM_ACTION_LOC_CFG_REQ 4
+#define DOT11_WNM_ACTION_LOC_RFG_RESP 5
+#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6
+#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7
+#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8
+#define DOT11_WNM_ACTION_FMS_REQ 9
+#define DOT11_WNM_ACTION_FMS_RESP 10
+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11
+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12
+#define DOT11_WNM_ACTION_TFS_REQ 13
+#define DOT11_WNM_ACTION_TFS_RESP 14
+#define DOT11_WNM_ACTION_TFS_NOTIFY 15
+#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16
+#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17
+#define DOT11_WNM_ACTION_TIMBC_REQ 18
+#define DOT11_WNM_ACTION_TIMBC_RESP 19
+#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20
+#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21
+#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22
+#define DOT11_WNM_ACTION_DMS_REQ 23
+#define DOT11_WNM_ACTION_DMS_RESP 24
+#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25
+#define DOT11_WNM_ACTION_NOTFCTN_REQ 26
+#define DOT11_WNM_ACTION_NOTFCTN_RES 27
+
+#define DOT11_UWNM_ACTION_TIM 0
+#define DOT11_UWNM_ACTION_TIMING_MEASUREMENT 1
+
+#define DOT11_MNG_COUNTRY_ID_LEN 3
+
+#define DOT11_VHT_ACTION_CBF 0
+#define DOT11_VHT_ACTION_GID_MGMT 1
+#define DOT11_VHT_ACTION_OPER_MODE_NOTIF 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dls_req {
+ uint8 category;
+ uint8 action;
+ struct ether_addr da;
+ struct ether_addr sa;
+ uint16 cap;
+ uint16 timeout;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_req dot11_dls_req_t;
+#define DOT11_DLS_REQ_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_dls_resp {
+ uint8 category;
+ uint8 action;
+ uint16 status;
+ struct ether_addr da;
+ struct ether_addr sa;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_resp dot11_dls_resp_t;
+#define DOT11_DLS_RESP_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 reason;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_trans_query dot11_bss_trans_query_t;
+#define DOT11_BSS_TRANS_QUERY_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 reqmode;
+ uint16 disassoc_tmr;
+ uint8 validity_intrvl;
+ uint8 data[1];
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_trans_req dot11_bss_trans_req_t;
+#define DOT11_BSS_TRANS_REQ_LEN 7
+
+#define DOT11_BSS_TERM_DUR_LEN 12
+
+#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01
+#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02
+#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04
+#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08
+#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 term_delay;
+ uint8 data[1];
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_trans_res dot11_bss_trans_res_t;
+#define DOT11_BSS_TRANS_RES_LEN 5
+
+#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0
+#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8
+
+#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY_UNKNOWN 0x0002
+#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003
+#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004
+#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0
+
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200
+
+#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3
+#define DOT11_NBR_RPRT_SUBELEM_BSS_TERM_DUR_ID 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_term_dur_subelem {
+ uint8 id;
+ uint8 len;
+ uint8 bss_term_tsf[8];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_term_dur_subelem dot11_bss_term_dur_subelem_t;
+#define DOT11_BSS_TERM_DUR_SUBELEM_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_max_idle_period_ie {
+ uint8 id;
+ uint8 length;
+ uint16 max_idle_period;
+ uint8 idle_opt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_max_idle_period_ie dot11_bss_max_idle_period_ie_t;
+#define DOT11_BSS_MAX_IDLE_PERIOD_IE_LEN 3
+#define DOT11_BSS_MAX_IDLE_PERIOD_OPT_PROTECTED 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req_ie {
+ uint8 id;
+ uint8 length;
+ uint8 interval;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req_ie dot11_timbc_req_ie_t;
+#define DOT11_TIMBC_REQ_IE_LEN 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req dot11_timbc_req_t;
+#define DOT11_TIMBC_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp_ie {
+ uint8 id;
+ uint8 length;
+ uint8 status;
+ uint8 interval;
+ int32 offset;
+ uint16 high_rate;
+ uint16 low_rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp_ie dot11_timbc_resp_ie_t;
+#define DOT11_TIMBC_DENY_RESP_IE_LEN 1
+#define DOT11_TIMBC_ACCEPT_RESP_IE_LEN 10
+
+#define DOT11_TIMBC_STATUS_ACCEPT 0
+#define DOT11_TIMBC_STATUS_ACCEPT_TSTAMP 1
+#define DOT11_TIMBC_STATUS_DENY 2
+#define DOT11_TIMBC_STATUS_OVERRIDDEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp dot11_timbc_resp_t;
+#define DOT11_TIMBC_RESP_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tim_ie {
+ uint8 id;
+ uint8 len;
+ uint8 dtim_count;
+ uint8 dtim_period;
+ uint8 bitmap_control;
+ uint8 pvb[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tim_ie dot11_tim_ie_t;
+#define DOT11_TIM_IE_FIXED_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc {
+ uint8 category;
+ uint8 action;
+ uint8 check_beacon;
+ uint8 tsf[8];
+ dot11_tim_ie_t tim_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc dot11_timbc_t;
+#define DOT11_TIMBC_HDR_LEN (sizeof(dot11_timbc_t) - sizeof(dot11_tim_ie_t))
+#define DOT11_TIMBC_FIXED_LEN (sizeof(dot11_timbc_t) - 1)
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_hdr {
+ uint8 type;
+ uint8 mask;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_hdr dot11_tclas_fc_hdr_t;
+#define DOT11_TCLAS_FC_HDR_LEN 2
+
+#define DOT11_TCLAS_MASK_0 0x1
+#define DOT11_TCLAS_MASK_1 0x2
+#define DOT11_TCLAS_MASK_2 0x4
+#define DOT11_TCLAS_MASK_3 0x8
+#define DOT11_TCLAS_MASK_4 0x10
+#define DOT11_TCLAS_MASK_5 0x20
+#define DOT11_TCLAS_MASK_6 0x40
+#define DOT11_TCLAS_MASK_7 0x80
+
+#define DOT11_TCLAS_FC_0_ETH 0
+#define DOT11_TCLAS_FC_1_IP 1
+#define DOT11_TCLAS_FC_2_8021Q 2
+#define DOT11_TCLAS_FC_3_OFFSET 3
+#define DOT11_TCLAS_FC_4_IP_HIGHER 4
+#define DOT11_TCLAS_FC_5_8021D 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_0_eth {
+ uint8 type;
+ uint8 mask;
+ uint8 sa[ETHER_ADDR_LEN];
+ uint8 da[ETHER_ADDR_LEN];
+ uint16 eth_type;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_0_eth dot11_tclas_fc_0_eth_t;
+#define DOT11_TCLAS_FC_0_ETH_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_1_ipv4 {
+ uint8 type;
+ uint8 mask;
+ uint8 version;
+ uint32 src_ip;
+ uint32 dst_ip;
+ uint16 src_port;
+ uint16 dst_port;
+ uint8 dscp;
+ uint8 protocol;
+ uint8 reserved;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_1_ipv4_t;
+#define DOT11_TCLAS_FC_1_IPV4_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_2_8021q {
+ uint8 type;
+ uint8 mask;
+ uint16 tci;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_2_8021q dot11_tclas_fc_2_8021q_t;
+#define DOT11_TCLAS_FC_2_8021Q_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_3_filter {
+ uint8 type;
+ uint8 mask;
+ uint16 offset;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_3_filter dot11_tclas_fc_3_filter_t;
+#define DOT11_TCLAS_FC_3_FILTER_LEN 4
+
+typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_4_ipv4_t;
+#define DOT11_TCLAS_FC_4_IPV4_LEN DOT11_TCLAS_FC_1_IPV4_LEN
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_4_ipv6 {
+ uint8 type;
+ uint8 mask;
+ uint8 version;
+ uint8 saddr[16];
+ uint8 daddr[16];
+ uint16 src_port;
+ uint16 dst_port;
+ uint8 dscp;
+ uint8 nexthdr;
+ uint8 flow_lbl[3];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_4_ipv6 dot11_tclas_fc_4_ipv6_t;
+#define DOT11_TCLAS_FC_4_IPV6_LEN 44
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_5_8021d {
+ uint8 type;
+ uint8 mask;
+ uint8 pcp;
+ uint8 cfi;
+ uint16 vid;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_5_8021d dot11_tclas_fc_5_8021d_t;
+#define DOT11_TCLAS_FC_5_8021D_LEN 6
+
+BWL_PRE_PACKED_STRUCT union dot11_tclas_fc {
+ uint8 data[1];
+ dot11_tclas_fc_hdr_t hdr;
+ dot11_tclas_fc_0_eth_t t0_eth;
+ dot11_tclas_fc_1_ipv4_t t1_ipv4;
+ dot11_tclas_fc_2_8021q_t t2_8021q;
+ dot11_tclas_fc_3_filter_t t3_filter;
+ dot11_tclas_fc_4_ipv4_t t4_ipv4;
+ dot11_tclas_fc_4_ipv6_t t4_ipv6;
+ dot11_tclas_fc_5_8021d_t t5_8021d;
+} BWL_POST_PACKED_STRUCT;
+typedef union dot11_tclas_fc dot11_tclas_fc_t;
+#define DOT11_TCLAS_FC_MIN_LEN 4
+#define DOT11_TCLAS_FC_MAX_LEN 254
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_ie {
+ uint8 id;
+ uint8 length;
+ uint8 user_priority;
+ dot11_tclas_fc_t fc;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_ie dot11_tclas_ie_t;
+#define DOT11_TCLAS_IE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_proc_ie {
+ uint8 id;
+ uint8 length;
+ uint8 process;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_proc_ie dot11_tclas_proc_ie_t;
+#define DOT11_TCLAS_PROC_IE_LEN 3
+
+#define DOT11_TCLAS_PROC_MATCHALL 0
+#define DOT11_TCLAS_PROC_MATCHONE 1
+#define DOT11_TCLAS_PROC_NONMATCH 2
+
+#define DOT11_TSPEC_IE_LEN 57
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req_ie {
+ uint8 id;
+ uint8 length;
+ uint8 tfs_id;
+ uint8 tfs_actcode;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_req_ie dot11_tfs_req_ie_t;
+#define DOT11_TFS_REQ_IE_LEN 4
+
+#define DOT11_TFS_ACTCODE_DELETE 1
+#define DOT11_TFS_ACTCODE_MODIFY 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_se {
+ uint8 sub_id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_se dot11_tfs_se_t;
+
+#define DOT11_TFS_REQ_SUBELEM_LEN 2
+
+#define DOT11_TFS_SUBELEM_ID_TFS 1
+#define DOT11_TFS_SUBELEM_ID_VENDOR 221
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp_ie {
+ uint8 id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp_ie dot11_tfs_resp_ie_t;
+#define DOT11_TFS_RESP_IE_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_status_se {
+ uint8 id;
+ uint8 length;
+ uint8 resp_st;
+ uint8 tfs_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_status_se dot11_tfs_status_se_t;
+
+#define DOT11_TFS_STATUS_SE_LEN 4
+#define DOT11_TFS_STATUS_SE_DATA_LEN 2
+
+#define DOT11_TFS_STATUS_SE_ID_TFS_ST 1
+#define DOT11_TFS_STATUS_SE_ID_TFS 2
+#define DOT11_TFS_STATUS_SE_ID_VENDOR 221
+
+#define DOT11_TFS_RESP_ST_ACCEPT 0
+#define DOT11_TFS_RESP_ST_DENY_FORMAT 1
+#define DOT11_TFS_RESP_ST_DENY_RESOURCE 2
+#define DOT11_TFS_RESP_ST_DENY_POLICY 4
+#define DOT11_TFS_RESP_ST_PREFERRED_AP_INCAP 14
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_req dot11_tfs_req_t;
+#define DOT11_TFS_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp dot11_tfs_resp_t;
+#define DOT11_TFS_RESP_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify {
+ uint8 category;
+ uint8 action;
+ uint8 num_tfs_id;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify dot11_tfs_notify_t;
+#define DOT11_TFS_NOTIFY_LEN 3
+
+#define DOT11_TFS_NOTIFY_ACT_DEL 1
+#define DOT11_TFS_NOTIFY_ACT_NOTIFY 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_req dot11_wnm_sleep_req_t;
+#define DOT11_WNM_SLEEP_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 key_len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_resp dot11_wnm_sleep_resp_t;
+#define DOT11_WNM_SLEEP_RESP_LEN 5
+
+#define DOT11_WNM_SLEEP_SUBELEM_ID_GTK 0
+#define DOT11_WNM_SLEEP_SUBELEM_ID_IGTK 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_gtk {
+ uint8 sub_id;
+ uint8 length;
+ uint16 key_info;
+ uint8 key_length;
+ uint8 rsc[8];
+ uint8 key[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_subelem_gtk dot11_wnm_sleep_subelem_gtk_t;
+#define DOT11_WNM_SLEEP_SUBELEM_GTK_FIXED_LEN 11
+#define DOT11_WNM_SLEEP_SUBELEM_GTK_MAX_LEN 43
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_igtk {
+ uint8 sub_id;
+ uint8 length;
+ uint16 key_id;
+ uint8 pn[6];
+ uint8 key[16];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_subelem_igtk dot11_wnm_sleep_subelem_igtk_t;
+#define DOT11_WNM_SLEEP_SUBELEM_IGTK_LEN 24
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_ie {
+ uint8 id;
+ uint8 length;
+ uint8 act_type;
+ uint8 resp_status;
+ uint16 interval;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_ie dot11_wnm_sleep_ie_t;
+#define DOT11_WNM_SLEEP_IE_LEN 4
+
+#define DOT11_WNM_SLEEP_ACT_TYPE_ENTER 0
+#define DOT11_WNM_SLEEP_ACT_TYPE_EXIT 1
+
+#define DOT11_WNM_SLEEP_RESP_ACCEPT 0
+#define DOT11_WNM_SLEEP_RESP_UPDATE 1
+#define DOT11_WNM_SLEEP_RESP_DENY 2
+#define DOT11_WNM_SLEEP_RESP_DENY_TEMP 3
+#define DOT11_WNM_SLEEP_RESP_DENY_KEY 4
+#define DOT11_WNM_SLEEP_RESP_DENY_INUSE 5
+#define DOT11_WNM_SLEEP_RESP_LAST 6
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req dot11_dms_req_t;
+#define DOT11_DMS_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp dot11_dms_resp_t;
+#define DOT11_DMS_RESP_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_ie {
+ uint8 id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req_ie dot11_dms_req_ie_t;
+#define DOT11_DMS_REQ_IE_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_ie {
+ uint8 id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp_ie dot11_dms_resp_ie_t;
+#define DOT11_DMS_RESP_IE_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_desc {
+ uint8 dms_id;
+ uint8 length;
+ uint8 type;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req_desc dot11_dms_req_desc_t;
+#define DOT11_DMS_REQ_DESC_LEN 3
+
+#define DOT11_DMS_REQ_TYPE_ADD 0
+#define DOT11_DMS_REQ_TYPE_REMOVE 1
+#define DOT11_DMS_REQ_TYPE_CHANGE 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_st {
+ uint8 dms_id;
+ uint8 length;
+ uint8 type;
+ uint16 lsc;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp_st dot11_dms_resp_st_t;
+#define DOT11_DMS_RESP_STATUS_LEN 5
+
+#define DOT11_DMS_RESP_TYPE_ACCEPT 0
+#define DOT11_DMS_RESP_TYPE_DENY 1
+#define DOT11_DMS_RESP_TYPE_TERM 2
+
+#define DOT11_DMS_RESP_LSC_UNSUPPORTED 0xFFFF
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 addba_param_set;
+ uint16 timeout;
+ uint16 start_seqnum;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_req dot11_addba_req_t;
+#define DOT11_ADDBA_REQ_LEN 9
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 status;
+ uint16 addba_param_set;
+ uint16 timeout;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_resp dot11_addba_resp_t;
+#define DOT11_ADDBA_RESP_LEN 9
+
+#define DOT11_DELBA_PARAM_INIT_MASK 0x0800
+#define DOT11_DELBA_PARAM_INIT_SHIFT 11
+#define DOT11_DELBA_PARAM_TID_MASK 0xf000
+#define DOT11_DELBA_PARAM_TID_SHIFT 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_delba {
+ uint8 category;
+ uint8 action;
+ uint16 delba_param_set;
+ uint16 reason;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_delba dot11_delba_t;
+#define DOT11_DELBA_LEN 6
+
+#define SA_QUERY_REQUEST 0
+#define SA_QUERY_RESPONSE 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_ft_req {
+ uint8 category;
+ uint8 action;
+ uint8 sta_addr[ETHER_ADDR_LEN];
+ uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_req dot11_ft_req_t;
+#define DOT11_FT_REQ_FIXED_LEN 14
+
+BWL_PRE_PACKED_STRUCT struct dot11_ft_res {
+ uint8 category;
+ uint8 action;
+ uint8 sta_addr[ETHER_ADDR_LEN];
+ uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+ uint16 status;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_res dot11_ft_res_t;
+#define DOT11_FT_RES_FIXED_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_rde_ie {
+ uint8 id;
+ uint8 length;
+ uint8 rde_id;
+ uint8 rd_count;
+ uint16 status;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rde_ie dot11_rde_ie_t;
+
+#define DOT11_MNG_RDE_IE_LEN sizeof(dot11_rde_ie_t)
+
+#define DOT11_RRM_CAP_LEN 5
+#define RCPI_IE_LEN 1
+#define RSNI_IE_LEN 1
+BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie {
+ uint8 cap[DOT11_RRM_CAP_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t;
+
+#define DOT11_RRM_CAP_LINK 0
+#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1
+#define DOT11_RRM_CAP_PARALLEL 2
+#define DOT11_RRM_CAP_REPEATED 3
+#define DOT11_RRM_CAP_BCN_PASSIVE 4
+#define DOT11_RRM_CAP_BCN_ACTIVE 5
+#define DOT11_RRM_CAP_BCN_TABLE 6
+#define DOT11_RRM_CAP_BCN_REP_COND 7
+#define DOT11_RRM_CAP_AP_CHANREP 16
+
+#define DOT11_OP_CLASS_NONE 255
+
+BWL_PRE_PACKED_STRUCT struct do11_ap_chrep {
+ uint8 id;
+ uint8 len;
+ uint8 reg;
+ uint8 chanlist[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct do11_ap_chrep dot11_ap_chrep_t;
+
+#define DOT11_RM_ACTION_RM_REQ 0
+#define DOT11_RM_ACTION_RM_REP 1
+#define DOT11_RM_ACTION_LM_REQ 2
+#define DOT11_RM_ACTION_LM_REP 3
+#define DOT11_RM_ACTION_NR_REQ 4
+#define DOT11_RM_ACTION_NR_REP 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_rm_action {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rm_action dot11_rm_action_t;
+#define DOT11_RM_ACTION_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 reps;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq dot11_rmreq_t;
+#define DOT11_RMREQ_LEN 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_rm_ie {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rm_ie dot11_rm_ie_t;
+#define DOT11_RM_IE_LEN 5
+
+#define DOT11_RMREQ_MODE_PARALLEL 1
+#define DOT11_RMREQ_MODE_ENABLE 2
+#define DOT11_RMREQ_MODE_REQUEST 4
+#define DOT11_RMREQ_MODE_REPORT 8
+#define DOT11_RMREQ_MODE_DURMAND 0x10
+
+#define DOT11_RMREP_MODE_LATE 1
+#define DOT11_RMREP_MODE_INCAPABLE 2
+#define DOT11_RMREP_MODE_REFUSED 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+ uint8 bcn_mode;
+ struct ether_addr bssid;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t;
+#define DOT11_RMREQ_BCN_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 frame_info;
+ uint8 rcpi;
+ uint8 rsni;
+ struct ether_addr bssid;
+ uint8 antenna_id;
+ uint32 parent_tsf;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t;
+#define DOT11_RMREP_BCN_LEN 26
+
+#define DOT11_RMREQ_BCN_PASSIVE 0
+#define DOT11_RMREQ_BCN_ACTIVE 1
+#define DOT11_RMREQ_BCN_TABLE 2
+
+#define DOT11_RMREQ_BCN_SSID_ID 0
+#define DOT11_RMREQ_BCN_REPINFO_ID 1
+#define DOT11_RMREQ_BCN_REPDET_ID 2
+#define DOT11_RMREQ_BCN_REQUEST_ID 10
+#define DOT11_RMREQ_BCN_APCHREP_ID DOT11_MNG_AP_CHREP_ID
+
+#define DOT11_RMREQ_BCN_REPDET_FIXED 0
+#define DOT11_RMREQ_BCN_REPDET_REQUEST 1
+#define DOT11_RMREQ_BCN_REPDET_ALL 2
+
+#define DOT11_RMREP_BCN_FRM_BODY 1
+
+#define DOT11_RMREP_FRAME_COUNT_REPORT 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_chanload {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_chanload dot11_rmreq_chanload_t;
+#define DOT11_RMREQ_CHANLOAD_LEN 11
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_chanload {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 channel_load;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_chanload dot11_rmrep_chanload_t;
+#define DOT11_RMREP_CHANLOAD_LEN 13
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_noise {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_noise dot11_rmreq_noise_t;
+#define DOT11_RMREQ_NOISE_LEN 11
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_noise {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 antid;
+ uint8 anpi;
+ uint8 ipi0_dens;
+ uint8 ipi1_dens;
+ uint8 ipi2_dens;
+ uint8 ipi3_dens;
+ uint8 ipi4_dens;
+ uint8 ipi5_dens;
+ uint8 ipi6_dens;
+ uint8 ipi7_dens;
+ uint8 ipi8_dens;
+ uint8 ipi9_dens;
+ uint8 ipi10_dens;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_noise dot11_rmrep_noise_t;
+#define DOT11_RMREP_NOISE_LEN 25
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_frame {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+ uint8 req_type;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_frame dot11_rmreq_frame_t;
+#define DOT11_RMREQ_FRAME_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frame {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_frame dot11_rmrep_frame_t;
+#define DOT11_RMREP_FRAME_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frmentry {
+ struct ether_addr ta;
+ struct ether_addr bssid;
+ uint8 phy_type;
+ uint8 avg_rcpi;
+ uint8 last_rsni;
+ uint8 last_rcpi;
+ uint8 ant_id;
+ uint16 frame_cnt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_frmentry dot11_rmrep_frmentry_t;
+#define DOT11_RMREP_FRMENTRY_LEN 19
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_stat {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ struct ether_addr peer;
+ uint16 interval;
+ uint16 duration;
+ uint8 group_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_stat dot11_rmreq_stat_t;
+#define DOT11_RMREQ_STAT_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_stat {
+ uint16 duration;
+ uint8 group_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_stat dot11_rmrep_stat_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_tx_stream {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint16 interval;
+ uint16 duration;
+ struct ether_addr peer;
+ uint8 traffic_id;
+ uint8 bin0_range;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_tx_stream dot11_rmreq_tx_stream_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_tx_stream {
+ uint32 starttime[2];
+ uint16 duration;
+ struct ether_addr peer;
+ uint8 traffic_id;
+ uint8 reason;
+ uint32 txmsdu_cnt;
+ uint32 msdu_discarded_cnt;
+ uint32 msdufailed_cnt;
+ uint32 msduretry_cnt;
+ uint32 cfpolls_lost_cnt;
+ uint32 avrqueue_delay;
+ uint32 avrtx_delay;
+ uint8 bin0_range;
+ uint32 bin0;
+ uint32 bin1;
+ uint32 bin2;
+ uint32 bin3;
+ uint32 bin4;
+ uint32 bin5;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_tx_stream dot11_rmrep_tx_stream_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_pause_time {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint16 pause_time;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_pause_time dot11_rmreq_pause_time_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr {
+ struct ether_addr bssid;
+ uint32 bssid_info;
+ uint8 reg;
+ uint8 channel;
+ uint8 phytype;
+ uchar sub_elements[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t;
+#define DOT11_RMREP_NBR_LEN 13
+
+BWL_PRE_PACKED_STRUCT struct dot11_rrmrep_nbr {
+ uint8 id;
+ uint8 len;
+ dot11_rmrep_nbr_t nbr_rrmrep;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rrmrep_nbr dot11_rrmrep_nbr_t;
+#define DOT11_RRMREP_NBR_LEN 15
+
+#define DOT11_BSSTYPE_INFRASTRUCTURE 0
+#define DOT11_BSSTYPE_INDEPENDENT 1
+#define DOT11_BSSTYPE_ANY 2
+#define DOT11_SCANTYPE_ACTIVE 0
+#define DOT11_SCANTYPE_PASSIVE 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_lmreq {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 txpwr;
+ uint8 maxtxpwr;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lmreq dot11_lmreq_t;
+#define DOT11_LMREQ_LEN 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_lmrep {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ dot11_tpc_rep_t tpc;
+ uint8 rxant;
+ uint8 txant;
+ uint8 rcpi;
+ uint8 rsni;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lmrep dot11_lmrep_t;
+#define DOT11_LMREP_LEN 11
+
+#define PREN_PREAMBLE 24
+#define PREN_MM_EXT 12
+#define PREN_PREAMBLE_EXT 4
+
+#define RIFS_11N_TIME 2
+
+#define HT_SIG1_MCS_MASK 0x00007F
+#define HT_SIG1_CBW 0x000080
+#define HT_SIG1_HT_LENGTH 0xFFFF00
+
+#define HT_SIG2_SMOOTHING 0x000001
+#define HT_SIG2_NOT_SOUNDING 0x000002
+#define HT_SIG2_RESERVED 0x000004
+#define HT_SIG2_AGGREGATION 0x000008
+#define HT_SIG2_STBC_MASK 0x000030
+#define HT_SIG2_STBC_SHIFT 4
+#define HT_SIG2_FEC_CODING 0x000040
+#define HT_SIG2_SHORT_GI 0x000080
+#define HT_SIG2_ESS_MASK 0x000300
+#define HT_SIG2_ESS_SHIFT 8
+#define HT_SIG2_CRC 0x03FC00
+#define HT_SIG2_TAIL 0x1C0000
+
+#define HT_T_LEG_PREAMBLE 16
+#define HT_T_L_SIG 4
+#define HT_T_SIG 8
+#define HT_T_LTF1 4
+#define HT_T_GF_LTF1 8
+#define HT_T_LTFs 4
+#define HT_T_STF 4
+#define HT_T_GF_STF 8
+#define HT_T_SYML 4
+
+#define HT_N_SERVICE 16
+#define HT_N_TAIL 6
+
+#define APHY_SLOT_TIME 9
+#define APHY_SIFS_TIME 16
+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME))
+#define APHY_PREAMBLE_TIME 16
+#define APHY_SIGNAL_TIME 4
+#define APHY_SYMBOL_TIME 4
+#define APHY_SERVICE_NBITS 16
+#define APHY_TAIL_NBITS 6
+#define APHY_CWMIN 15
+
+#define BPHY_SLOT_TIME 20
+#define BPHY_SIFS_TIME 10
+#define BPHY_DIFS_TIME 50
+#define BPHY_PLCP_TIME 192
+#define BPHY_PLCP_SHORT_TIME 96
+#define BPHY_CWMIN 31
+
+#define DOT11_OFDM_SIGNAL_EXTENSION 6
+
+#define PHY_CWMAX 1023
+
+#define DOT11_MAXNUMFRAGS 16
+
+typedef int vht_group_id_t;
+
+#define VHT_SIGA1_CONST_MASK 0x800004
+
+#define VHT_SIGA1_BW_MASK 0x000003
+#define VHT_SIGA1_20MHZ_VAL 0x000000
+#define VHT_SIGA1_40MHZ_VAL 0x000001
+#define VHT_SIGA1_80MHZ_VAL 0x000002
+#define VHT_SIGA1_160MHZ_VAL 0x000003
+
+#define VHT_SIGA1_STBC 0x000008
+
+#define VHT_SIGA1_GID_MASK 0x0003f0
+#define VHT_SIGA1_GID_SHIFT 4
+#define VHT_SIGA1_GID_TO_AP 0x00
+#define VHT_SIGA1_GID_NOT_TO_AP 0x3f
+#define VHT_SIGA1_GID_MAX_GID 0x3f
+
+#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00
+#define VHT_SIGA1_NSTS_SHIFT 10
+
+#define VHT_SIGA1_PARTIAL_AID_MASK 0x3fe000
+#define VHT_SIGA1_PARTIAL_AID_SHIFT 13
+
+#define VHT_SIGA1_TXOP_PS_NOT_ALLOWED 0x400000
+
+#define VHT_SIGA2_GI_NONE 0x000000
+#define VHT_SIGA2_GI_SHORT 0x000001
+#define VHT_SIGA2_GI_W_MOD10 0x000002
+#define VHT_SIGA2_CODING_LDPC 0x000004
+#define VHT_SIGA2_LDPC_EXTRA_OFDM_SYM 0x000008
+#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100
+#define VHT_SIGA2_MCS_SHIFT 4
+
+#define VHT_SIGA2_B9_RESERVED 0x000200
+#define VHT_SIGA2_TAIL_MASK 0xfc0000
+#define VHT_SIGA2_TAIL_VALUE 0x000000
+
+#define VHT_T_LEG_PREAMBLE 16
+#define VHT_T_L_SIG 4
+#define VHT_T_SIG_A 8
+#define VHT_T_LTF 4
+#define VHT_T_STF 4
+#define VHT_T_SIG_B 4
+#define VHT_T_SYML 4
+
+#define VHT_N_SERVICE 16
+#define VHT_N_TAIL 6
+
+typedef struct d11cnt {
+ uint32 txfrag;
+ uint32 txmulti;
+ uint32 txfail;
+ uint32 txretry;
+ uint32 txretrie;
+ uint32 rxdup;
+ uint32 txrts;
+ uint32 txnocts;
+ uint32 txnoack;
+ uint32 rxfrag;
+ uint32 rxmulti;
+ uint32 rxcrc;
+ uint32 txfrmsnt;
+ uint32 rxundec;
+} d11cnt_t;
+
+#define BRCM_PROP_OUI "\x00\x90\x4C"
+
+#define BRCM_SYSCAP_WET_TUNNEL 0x0100
+
+#define BRCM_OUI "\x00\x10\x18"
+
+BWL_PRE_PACKED_STRUCT struct brcm_ie {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 ver;
+ uint8 assoc;
+ uint8 flags;
+ uint8 flags1;
+ uint16 amsdu_mtu_pref;
+} BWL_POST_PACKED_STRUCT;
+typedef struct brcm_ie brcm_ie_t;
+#define BRCM_IE_LEN 11
+#define BRCM_IE_VER 2
+#define BRCM_IE_LEGACY_AES_VER 1
+
+#define BRF_LZWDS 0x4
+#define BRF_BLOCKACK 0x8
+
+#define BRF1_AMSDU 0x1
+#define BRF1_WMEPS 0x4
+#define BRF1_PSOFIX 0x8
+#define BRF1_RX_LARGE_AGG 0x10
+#define BRF1_RFAWARE_DCS 0x20
+#define BRF1_SOFTAP 0x40
+#define BRF1_DWDS 0x80
+
+BWL_PRE_PACKED_STRUCT struct vndr_ie {
+ uchar id;
+ uchar len;
+ uchar oui [3];
+ uchar data [1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct vndr_ie vndr_ie_t;
+
+#define VNDR_IE_HDR_LEN 2
+#define VNDR_IE_MIN_LEN 3
+#define VNDR_IE_MAX_LEN 255
+
+BWL_PRE_PACKED_STRUCT struct member_of_brcm_prop_ie {
+ uchar id;
+ uchar len;
+ uchar oui[3];
+ uint8 type;
+ struct ether_addr ea;
+} BWL_POST_PACKED_STRUCT;
+typedef struct member_of_brcm_prop_ie member_of_brcm_prop_ie_t;
+
+#define MEMBER_OF_BRCM_PROP_IE_LEN 10
+#define MEMBER_OF_BRCM_PROP_IE_TYPE 54
+
+BWL_PRE_PACKED_STRUCT struct relmcast_brcm_prop_ie {
+ uchar id;
+ uchar len;
+ uchar oui[3];
+ uint8 type;
+ struct ether_addr ea;
+ struct ether_addr mcast_ea;
+ uint8 updtmo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct relmcast_brcm_prop_ie relmcast_brcm_prop_ie_t;
+
+#define RELMCAST_BRCM_PROP_IE_LEN (sizeof(relmcast_brcm_prop_ie_t)-2)
+#define RELMCAST_BRCM_PROP_IE_TYPE 55
+
+#define MCSSET_LEN 16
+#define MAX_MCS_NUM (128)
+
+BWL_PRE_PACKED_STRUCT struct ht_cap_ie {
+ uint16 cap;
+ uint8 params;
+ uint8 supp_mcs[MCSSET_LEN];
+ uint16 ext_htcap;
+ uint32 txbf_cap;
+ uint8 as_cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_cap_ie ht_cap_ie_t;
+BWL_PRE_PACKED_STRUCT struct dot11_ht_cap_ie {
+ uint8 id;
+ uint8 len;
+ ht_cap_ie_t ht_cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ht_cap_ie dot11_ht_cap_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 type;
+ ht_cap_ie_t cap_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_prop_cap_ie ht_prop_cap_ie_t;
+
+#define HT_PROP_IE_OVERHEAD 4
+#define HT_CAP_IE_LEN 26
+#define HT_CAP_IE_TYPE 51
+
+#define HT_CAP_LDPC_CODING 0x0001
+#define HT_CAP_40MHZ 0x0002
+#define HT_CAP_MIMO_PS_MASK 0x000C
+#define HT_CAP_MIMO_PS_SHIFT 0x0002
+#define HT_CAP_MIMO_PS_OFF 0x0003
+#define HT_CAP_MIMO_PS_RTS 0x0001
+#define HT_CAP_MIMO_PS_ON 0x0000
+#define HT_CAP_GF 0x0010
+#define HT_CAP_SHORT_GI_20 0x0020
+#define HT_CAP_SHORT_GI_40 0x0040
+#define HT_CAP_TX_STBC 0x0080
+#define HT_CAP_RX_STBC_MASK 0x0300
+#define HT_CAP_RX_STBC_SHIFT 8
+#define HT_CAP_DELAYED_BA 0x0400
+#define HT_CAP_MAX_AMSDU 0x0800
+
+#define HT_CAP_DSSS_CCK 0x1000
+#define HT_CAP_PSMP 0x2000
+#define HT_CAP_40MHZ_INTOLERANT 0x4000
+#define HT_CAP_LSIG_TXOP 0x8000
+
+#define HT_CAP_RX_STBC_NO 0x0
+#define HT_CAP_RX_STBC_ONE_STREAM 0x1
+#define HT_CAP_RX_STBC_TWO_STREAM 0x2
+#define HT_CAP_RX_STBC_THREE_STREAM 0x3
+
+#define HT_CAP_TXBF_CAP_IMPLICIT_TXBF_RX 0x1
+#define HT_CAP_TXBF_CAP_NDP_TX 0x8
+#define HT_CAP_TXBF_CAP_NDP_RX 0x10
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI 0x100
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_STEERING 0x200
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_STEERING 0x400
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_MASK 0x1800
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_SHIFT 11
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_MASK 0x6000
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_SHIFT 13
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_MASK 0x18000
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_SHIFT 15
+#define HT_CAP_TXBF_CAP_CSI_BFR_ANT_SHIFT 19
+#define HT_CAP_TXBF_CAP_NC_BFR_ANT_SHIFT 21
+#define HT_CAP_TXBF_CAP_C_BFR_ANT_SHIFT 23
+#define HT_CAP_TXBF_CAP_C_BFR_ANT_MASK 0x1800000
+
+#define HT_CAP_TXBF_CAP_CHAN_ESTIM_SHIFT 27
+#define HT_CAP_TXBF_CAP_CHAN_ESTIM_MASK 0x18000000
+
+#define HT_CAP_TXBF_FB_TYPE_NONE 0
+#define HT_CAP_TXBF_FB_TYPE_DELAYED 1
+#define HT_CAP_TXBF_FB_TYPE_IMMEDIATE 2
+#define HT_CAP_TXBF_FB_TYPE_BOTH 3
+
+#define VHT_MAX_MPDU 11454
+#define VHT_MPDU_MSDU_DELTA 56
+
+#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA)
+
+#define HT_MAX_AMSDU 7935
+#define HT_MIN_AMSDU 3835
+
+#define HT_PARAMS_RX_FACTOR_MASK 0x03
+#define HT_PARAMS_DENSITY_MASK 0x1C
+#define HT_PARAMS_DENSITY_SHIFT 2
+
+#define AMPDU_MAX_MPDU_DENSITY 7
+#define AMPDU_DENSITY_NONE 0
+#define AMPDU_DENSITY_1over4_US 1
+#define AMPDU_DENSITY_1over2_US 2
+#define AMPDU_DENSITY_1_US 3
+#define AMPDU_DENSITY_2_US 4
+#define AMPDU_DENSITY_4_US 5
+#define AMPDU_DENSITY_8_US 6
+#define AMPDU_DENSITY_16_US 7
+#define AMPDU_RX_FACTOR_8K 0
+#define AMPDU_RX_FACTOR_16K 1
+#define AMPDU_RX_FACTOR_32K 2
+#define AMPDU_RX_FACTOR_64K 3
+#define AMPDU_RX_FACTOR_BASE 8*1024
+
+#define AMPDU_DELIMITER_LEN 4
+#define AMPDU_DELIMITER_LEN_MAX 63
+
+#define HT_CAP_EXT_PCO 0x0001
+#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006
+#define HT_CAP_EXT_PCO_TTIME_SHIFT 1
+#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300
+#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8
+#define HT_CAP_EXT_HTC 0x0400
+#define HT_CAP_EXT_RD_RESP 0x0800
+
+BWL_PRE_PACKED_STRUCT struct ht_add_ie {
+ uint8 ctl_ch;
+ uint8 byte1;
+ uint16 opmode;
+ uint16 misc_bits;
+ uint8 basic_mcs[MCSSET_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_add_ie ht_add_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 type;
+ ht_add_ie_t add_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_prop_add_ie ht_prop_add_ie_t;
+
+#define HT_ADD_IE_LEN 22
+#define HT_ADD_IE_TYPE 52
+
+#define HT_BW_ANY 0x04
+#define HT_RIFS_PERMITTED 0x08
+
+#define HT_OPMODE_MASK 0x0003
+#define HT_OPMODE_SHIFT 0
+#define HT_OPMODE_PURE 0x0000
+#define HT_OPMODE_OPTIONAL 0x0001
+#define HT_OPMODE_HT20IN40 0x0002
+#define HT_OPMODE_MIXED 0x0003
+#define HT_OPMODE_NONGF 0x0004
+#define DOT11N_TXBURST 0x0008
+#define DOT11N_OBSS_NONHT 0x0010
+
+#define HT_BASIC_STBC_MCS 0x007f
+#define HT_DUAL_STBC_PROT 0x0080
+#define HT_SECOND_BCN 0x0100
+#define HT_LSIG_TXOP 0x0200
+#define HT_PCO_ACTIVE 0x0400
+#define HT_PCO_PHASE 0x0800
+#define HT_DUALCTS_PROTECTION 0x0080
+
+#define DOT11N_2G_TXBURST_LIMIT 6160
+#define DOT11N_5G_TXBURST_LIMIT 3080
+
+#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ >> HT_OPMODE_SHIFT)
+#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_MIXED)
+#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_HT20IN40)
+#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_OPTIONAL)
+#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \
+ HT_MIXEDMODE_PRESENT((add_ie)))
+#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \
+ == HT_OPMODE_NONGF)
+#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \
+ == DOT11N_TXBURST)
+#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \
+ == DOT11N_OBSS_NONHT)
+
+BWL_PRE_PACKED_STRUCT struct obss_params {
+ uint16 passive_dwell;
+ uint16 active_dwell;
+ uint16 bss_widthscan_interval;
+ uint16 passive_total;
+ uint16 active_total;
+ uint16 chanwidth_transition_dly;
+ uint16 activity_threshold;
+} BWL_POST_PACKED_STRUCT;
+typedef struct obss_params obss_params_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_ie {
+ uint8 id;
+ uint8 len;
+ obss_params_t obss_params;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_ie dot11_obss_ie_t;
+#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t)
+
+#define HT_CTRL_LA_TRQ 0x00000002
+#define HT_CTRL_LA_MAI 0x0000003C
+#define HT_CTRL_LA_MAI_SHIFT 2
+#define HT_CTRL_LA_MAI_MRQ 0x00000004
+#define HT_CTRL_LA_MAI_MSI 0x00000038
+#define HT_CTRL_LA_MFSI 0x000001C0
+#define HT_CTRL_LA_MFSI_SHIFT 6
+#define HT_CTRL_LA_MFB_ASELC 0x0000FE00
+#define HT_CTRL_LA_MFB_ASELC_SH 9
+#define HT_CTRL_LA_ASELC_CMD 0x00000C00
+#define HT_CTRL_LA_ASELC_DATA 0x0000F000
+#define HT_CTRL_CAL_POS 0x00030000
+#define HT_CTRL_CAL_SEQ 0x000C0000
+#define HT_CTRL_CSI_STEERING 0x00C00000
+#define HT_CTRL_CSI_STEER_SHIFT 22
+#define HT_CTRL_CSI_STEER_NFB 0
+#define HT_CTRL_CSI_STEER_CSI 1
+#define HT_CTRL_CSI_STEER_NCOM 2
+#define HT_CTRL_CSI_STEER_COM 3
+#define HT_CTRL_NDP_ANNOUNCE 0x01000000
+#define HT_CTRL_AC_CONSTRAINT 0x40000000
+#define HT_CTRL_RDG_MOREPPDU 0x80000000
+
+#define HT_OPMODE_OPTIONAL 0x0001
+#define HT_OPMODE_HT20IN40 0x0002
+#define HT_OPMODE_MIXED 0x0003
+#define HT_OPMODE_NONGF 0x0004
+#define DOT11N_TXBURST 0x0008
+#define DOT11N_OBSS_NONHT 0x0010
+
+BWL_PRE_PACKED_STRUCT struct vht_cap_ie {
+ uint32 vht_cap_info;
+
+ uint16 rx_mcs_map;
+ uint16 rx_max_rate;
+ uint16 tx_mcs_map;
+ uint16 tx_max_rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_cap_ie vht_cap_ie_t;
+
+#define VHT_CAP_IE_LEN 12
+
+#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003
+#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c
+#define VHT_CAP_INFO_LDPC 0x00000010
+#define VHT_CAP_INFO_SGI_80MHZ 0x00000020
+#define VHT_CAP_INFO_SGI_160MHZ 0x00000040
+#define VHT_CAP_INFO_TX_STBC 0x00000080
+#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700
+#define VHT_CAP_INFO_RX_STBC_SHIFT 8
+#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800
+#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000
+#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000
+#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13
+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000
+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16
+#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000
+#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000
+#define VHT_CAP_INFO_TXOPPS 0x00200000
+#define VHT_CAP_INFO_HTCVHT 0x00400000
+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000
+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23
+#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000
+#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26
+
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0
+
+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff
+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0
+
+#define VHT_CAP_MCS_MAP_0_7 0
+#define VHT_CAP_MCS_MAP_0_8 1
+#define VHT_CAP_MCS_MAP_0_9 2
+#define VHT_CAP_MCS_MAP_NONE 3
+#define VHT_CAP_MCS_MAP_S 2
+#define VHT_CAP_MCS_MAP_M 0x3
+
+#define VHT_CAP_MCS_MAP_NONE_ALL 0xffff
+
+#define VHT_CAP_MCS_MAP_0_9_NSS3 \
+ ((VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(1)) | \
+ (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(2)) | \
+ (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(3)))
+
+#define VHT_CAP_MCS_MAP_NSS_MAX 8
+
+#define VHT_CAP_MCS_MAP_CREATE(mcsmap, nss, mcs) \
+ do { \
+ int i; \
+ for (i = 1; i <= nss; i++) { \
+ VHT_MCS_MAP_SET_MCS_PER_SS(i, mcs, mcsmap); \
+ } \
+ } while (0)
+
+#define VHT_MCS_CODE_TO_MCS_MAP(mcs_code) \
+ ((mcs_code == VHT_CAP_MCS_MAP_0_7) ? 0xff : \
+ (mcs_code == VHT_CAP_MCS_MAP_0_8) ? 0x1ff : \
+ (mcs_code == VHT_CAP_MCS_MAP_0_9) ? 0x3ff : 0)
+
+#define VHT_MCS_MAP_TO_MCS_CODE(mcs_map) \
+ ((mcs_map == 0xff) ? VHT_CAP_MCS_MAP_0_7 : \
+ (mcs_map == 0x1ff) ? VHT_CAP_MCS_MAP_0_8 : \
+ (mcs_map == 0x3ff) ? VHT_CAP_MCS_MAP_0_9 : VHT_CAP_MCS_MAP_NONE)
+
+typedef enum vht_cap_chan_width {
+ VHT_CAP_CHAN_WIDTH_SUPPORT_MANDATORY = 0x00,
+ VHT_CAP_CHAN_WIDTH_SUPPORT_160 = 0x04,
+ VHT_CAP_CHAN_WIDTH_SUPPORT_160_8080 = 0x08
+} vht_cap_chan_width_t;
+
+typedef enum vht_cap_max_mpdu_len {
+ VHT_CAP_MPDU_MAX_4K = 0x00,
+ VHT_CAP_MPDU_MAX_8K = 0x01,
+ VHT_CAP_MPDU_MAX_11K = 0x02
+} vht_cap_max_mpdu_len_t;
+
+#define VHT_MPDU_LIMIT_4K 3895
+#define VHT_MPDU_LIMIT_8K 7991
+#define VHT_MPDU_LIMIT_11K 11454
+
+BWL_PRE_PACKED_STRUCT struct vht_op_ie {
+ uint8 chan_width;
+ uint8 chan1;
+ uint8 chan2;
+ uint16 supp_mcs;
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_op_ie vht_op_ie_t;
+
+#define VHT_OP_IE_LEN 5
+
+typedef enum vht_op_chan_width {
+ VHT_OP_CHAN_WIDTH_20_40 = 0,
+ VHT_OP_CHAN_WIDTH_80 = 1,
+ VHT_OP_CHAN_WIDTH_160 = 2,
+ VHT_OP_CHAN_WIDTH_80_80 = 3
+} vht_op_chan_width_t;
+
+#define AID_IE_LEN 2
+
+#define VHT_FEATURES_IE_TYPE 0x4
+BWL_PRE_PACKED_STRUCT struct vht_features_ie_hdr {
+ uint8 oui[3];
+ uint8 type;
+ uint8 rate_mask;
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_features_ie_hdr vht_features_ie_hdr_t;
+
+#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1) * VHT_CAP_MCS_MAP_S)
+#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \
+ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & VHT_CAP_MCS_MAP_M)
+#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \
+ do { \
+ (mcsMap) &= (~(VHT_CAP_MCS_MAP_M << VHT_MCS_MAP_GET_SS_IDX(nss))); \
+ (mcsMap) |= (((numMcs) & VHT_CAP_MCS_MAP_M) << VHT_MCS_MAP_GET_SS_IDX(nss)); \
+ } while (0)
+#define VHT_MCS_SS_SUPPORTED(nss, mcsMap) \
+ (VHT_MCS_MAP_GET_MCS_PER_SS((nss), (mcsMap)) != VHT_CAP_MCS_MAP_NONE)
+
+#define WPA_OUI "\x00\x50\xF2"
+#define WPA_OUI_LEN 3
+#define WPA_OUI_TYPE 1
+#define WPA_VERSION 1
+#define WPA2_OUI "\x00\x0F\xAC"
+#define WPA2_OUI_LEN 3
+#define WPA2_VERSION 1
+#define WPA2_VERSION_LEN 2
+
+#define WPS_OUI "\x00\x50\xF2"
+#define WPS_OUI_LEN 3
+#define WPS_OUI_TYPE 4
+
+#define WFA_OUI "\x50\x6F\x9A"
+#define WFA_OUI_LEN 3
+#define WFA_OUI_TYPE_P2P 9
+
+#define WFA_OUI_TYPE_TPC 8
+
+#define RSN_AKM_NONE 0
+#define RSN_AKM_UNSPECIFIED 1
+#define RSN_AKM_PSK 2
+#define RSN_AKM_FBT_1X 3
+#define RSN_AKM_FBT_PSK 4
+#define RSN_AKM_MFP_1X 5
+#define RSN_AKM_MFP_PSK 6
+#define RSN_AKM_TPK 7
+
+#define DOT11_MAX_DEFAULT_KEYS 4
+#define DOT11_MAX_KEY_SIZE 32
+#define DOT11_MAX_IV_SIZE 16
+#define DOT11_EXT_IV_FLAG (1<<5)
+#define DOT11_WPA_KEY_RSC_LEN 8
+
+#define WEP1_KEY_SIZE 5
+#define WEP1_KEY_HEX_SIZE 10
+#define WEP128_KEY_SIZE 13
+#define WEP128_KEY_HEX_SIZE 26
+#define TKIP_MIC_SIZE 8
+#define TKIP_EOM_SIZE 7
+#define TKIP_EOM_FLAG 0x5a
+#define TKIP_KEY_SIZE 32
+#define TKIP_MIC_AUTH_TX 16
+#define TKIP_MIC_AUTH_RX 24
+#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX
+#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX
+#define AES_KEY_SIZE 16
+#define AES_MIC_SIZE 8
+#define BIP_KEY_SIZE 16
+#define BIP_MIC_SIZE 8
+
+#define WCN_OUI "\x00\x50\xf2"
+#define WCN_TYPE 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie {
+ uint8 id;
+ uint8 len;
+ uint16 mdid;
+ uint8 cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_mdid_ie dot11_mdid_ie_t;
+
+#define FBT_MDID_CAP_OVERDS 0x01
+#define FBT_MDID_CAP_RRP 0x02
+
+BWL_PRE_PACKED_STRUCT struct dot11_ft_ie {
+ uint8 id;
+ uint8 len;
+ uint16 mic_control;
+ uint8 mic[16];
+ uint8 anonce[32];
+ uint8 snonce[32];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_ie dot11_ft_ie_t;
+
+#define TIE_TYPE_RESERVED 0
+#define TIE_TYPE_REASSOC_DEADLINE 1
+#define TIE_TYPE_KEY_LIEFTIME 2
+#define TIE_TYPE_ASSOC_COMEBACK 3
+BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie {
+ uint8 id;
+ uint8 len;
+ uint8 type;
+ uint32 value;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timeout_ie dot11_timeout_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie {
+ uint8 id;
+ uint8 len;
+ uint16 key_info;
+ uint8 key_len;
+ uint8 rsc[8];
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_gtk_ie dot11_gtk_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct mmic_ie {
+ uint8 id;
+ uint8 len;
+ uint16 key_id;
+ uint8 ipn[6];
+ uint8 mic[BIP_MIC_SIZE];
+} BWL_POST_PACKED_STRUCT;
+typedef struct mmic_ie mmic_ie_t;
+
+#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00"
+#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF"
+
+#define WMM_OUI "\x00\x50\xF2"
+#define WMM_OUI_LEN 3
+#define WMM_OUI_TYPE 2
+#define WMM_VERSION 1
+#define WMM_VERSION_LEN 1
+
+#define WMM_OUI_SUBTYPE_PARAMETER 1
+#define WMM_PARAMETER_IE_LEN 24
+
+BWL_PRE_PACKED_STRUCT struct link_id_ie {
+ uint8 id;
+ uint8 len;
+ struct ether_addr bssid;
+ struct ether_addr tdls_init_mac;
+ struct ether_addr tdls_resp_mac;
+} BWL_POST_PACKED_STRUCT;
+typedef struct link_id_ie link_id_ie_t;
+#define TDLS_LINK_ID_IE_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie {
+ uint8 id;
+ uint8 len;
+ uint32 offset;
+ uint32 interval;
+ uint32 awake_win_slots;
+ uint32 max_wake_win;
+ uint16 idle_cnt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct wakeup_sch_ie wakeup_sch_ie_t;
+#define TDLS_WAKEUP_SCH_IE_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie {
+ uint8 id;
+ uint8 len;
+ uint16 switch_time;
+ uint16 switch_timeout;
+} BWL_POST_PACKED_STRUCT;
+typedef struct channel_switch_timing_ie channel_switch_timing_ie_t;
+#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct pti_control_ie {
+ uint8 id;
+ uint8 len;
+ uint8 tid;
+ uint16 seq_control;
+} BWL_POST_PACKED_STRUCT;
+typedef struct pti_control_ie pti_control_ie_t;
+#define TDLS_PTI_CONTROL_IE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie {
+ uint8 id;
+ uint8 len;
+ uint8 status;
+} BWL_POST_PACKED_STRUCT;
+typedef struct pu_buffer_status_ie pu_buffer_status_ie_t;
+#define TDLS_PU_BUFFER_STATUS_IE_LEN 1
+#define TDLS_PU_BUFFER_STATUS_AC_BK 1
+#define TDLS_PU_BUFFER_STATUS_AC_BE 2
+#define TDLS_PU_BUFFER_STATUS_AC_VI 4
+#define TDLS_PU_BUFFER_STATUS_AC_VO 8
+
+#define GAS_REQUEST_ACTION_FRAME 10
+#define GAS_RESPONSE_ACTION_FRAME 11
+#define GAS_COMEBACK_REQUEST_ACTION_FRAME 12
+#define GAS_COMEBACK_RESPONSE_ACTION_FRAME 13
+
+#define IW_ANT_MASK 0x0f
+#define IW_INTERNET_MASK 0x10
+#define IW_ASRA_MASK 0x20
+#define IW_ESR_MASK 0x40
+#define IW_UESA_MASK 0x80
+
+#define IW_ANT_PRIVATE_NETWORK 0
+#define IW_ANT_PRIVATE_NETWORK_WITH_GUEST 1
+#define IW_ANT_CHARGEABLE_PUBLIC_NETWORK 2
+#define IW_ANT_FREE_PUBLIC_NETWORK 3
+#define IW_ANT_PERSONAL_DEVICE_NETWORK 4
+#define IW_ANT_EMERGENCY_SERVICES_NETWORK 5
+#define IW_ANT_TEST_NETWORK 14
+#define IW_ANT_WILDCARD_NETWORK 15
+
+#define ADVP_ANQP_PROTOCOL_ID 0
+
+#define ADVP_QRL_MASK 0x7f
+#define ADVP_PAME_BI_MASK 0x80
+
+#define ADVP_QRL_REQUEST 0x00
+#define ADVP_QRL_RESPONSE 0x7f
+#define ADVP_PAME_BI_DEPENDENT 0x00
+#define ADVP_PAME_BI_INDEPENDENT ADVP_PAME_BI_MASK
+
+#define ANQP_ID_QUERY_LIST 256
+#define ANQP_ID_CAPABILITY_LIST 257
+#define ANQP_ID_VENUE_NAME_INFO 258
+#define ANQP_ID_EMERGENCY_CALL_NUMBER_INFO 259
+#define ANQP_ID_NETWORK_AUTHENTICATION_TYPE_INFO 260
+#define ANQP_ID_ROAMING_CONSORTIUM_LIST 261
+#define ANQP_ID_IP_ADDRESS_TYPE_AVAILABILITY_INFO 262
+#define ANQP_ID_NAI_REALM_LIST 263
+#define ANQP_ID_G3PP_CELLULAR_NETWORK_INFO 264
+#define ANQP_ID_AP_GEOSPATIAL_LOCATION 265
+#define ANQP_ID_AP_CIVIC_LOCATION 266
+#define ANQP_ID_AP_LOCATION_PUBLIC_ID_URI 267
+#define ANQP_ID_DOMAIN_NAME_LIST 268
+#define ANQP_ID_EMERGENCY_ALERT_ID_URI 269
+#define ANQP_ID_EMERGENCY_NAI 271
+#define ANQP_ID_VENDOR_SPECIFIC_LIST 56797
+
+#define ANQP_OUI_SUBTYPE 9
+
+#define VENUE_LANGUAGE_CODE_SIZE 3
+#define VENUE_NAME_SIZE 255
+
+#define VENUE_UNSPECIFIED 0
+#define VENUE_ASSEMBLY 1
+#define VENUE_BUSINESS 2
+#define VENUE_EDUCATIONAL 3
+#define VENUE_FACTORY 4
+#define VENUE_INSTITUTIONAL 5
+#define VENUE_MERCANTILE 6
+#define VENUE_RESIDENTIAL 7
+#define VENUE_STORAGE 8
+#define VENUE_UTILITY 9
+#define VENUE_VEHICULAR 10
+#define VENUE_OUTDOOR 11
+
+#define NATI_ACCEPTANCE_OF_TERMS_CONDITIONS 0
+#define NATI_ONLINE_ENROLLMENT_SUPPORTED 1
+#define NATI_HTTP_HTTPS_REDIRECTION 2
+#define NATI_DNS_REDIRECTION 3
+
+#define IPA_IPV6_SHIFT 0
+#define IPA_IPV6_MASK (0x03 << IPA_IPV6_SHIFT)
+#define IPA_IPV6_NOT_AVAILABLE 0x00
+#define IPA_IPV6_AVAILABLE 0x01
+#define IPA_IPV6_UNKNOWN_AVAILABILITY 0x02
+
+#define IPA_IPV4_SHIFT 2
+#define IPA_IPV4_MASK (0x3f << IPA_IPV4_SHIFT)
+#define IPA_IPV4_NOT_AVAILABLE 0x00
+#define IPA_IPV4_PUBLIC 0x01
+#define IPA_IPV4_PORT_RESTRICT 0x02
+#define IPA_IPV4_SINGLE_NAT 0x03
+#define IPA_IPV4_DOUBLE_NAT 0x04
+#define IPA_IPV4_PORT_RESTRICT_SINGLE_NAT 0x05
+#define IPA_IPV4_PORT_RESTRICT_DOUBLE_NAT 0x06
+#define IPA_IPV4_UNKNOWN_AVAILABILITY 0x07
+
+#define REALM_ENCODING_RFC4282 0
+#define REALM_ENCODING_UTF8 1
+
+#define REALM_EAP_TLS 13
+#define REALM_EAP_SIM 18
+#define REALM_EAP_TTLS 21
+#define REALM_EAP_AKA 23
+#define REALM_EAP_PSK 47
+#define REALM_EAP_AKAP 50
+
+#define REALM_EXPANDED_EAP 1
+#define REALM_NON_EAP_INNER_AUTHENTICATION 2
+#define REALM_INNER_AUTHENTICATION_EAP 3
+#define REALM_EXPANDED_INNER_EAP 4
+#define REALM_CREDENTIAL 5
+#define REALM_TUNNELED_EAP_CREDENTIAL 6
+#define REALM_VENDOR_SPECIFIC_EAP 221
+
+#define REALM_PAP 1
+#define REALM_CHAP 2
+#define REALM_MSCHAP 3
+#define REALM_MSCHAPV2 4
+
+#define REALM_SIM 1
+#define REALM_USIM 2
+#define REALM_NFC 3
+#define REALM_HARDWARE_TOKEN 4
+#define REALM_SOFTOKEN 5
+#define REALM_CERTIFICATE 6
+#define REALM_USERNAME_PASSWORD 7
+#define REALM_SERVER_SIDE 8
+
+#define G3PP_GUD_VERSION 0
+#define G3PP_PLMN_LIST_IE 0
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/802.1d.h b/src/common/include/proto/802.1d.h
new file mode 100644
index 0000000..b30912d
--- /dev/null
+++ b/src/common/include/proto/802.1d.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Fundamental types and constants relating to 802.1D
+ *
+ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _802_1_D_
+#define _802_1_D_
+
+#define PRIO_8021D_NONE 2
+#define PRIO_8021D_BK 1
+#define PRIO_8021D_BE 0
+#define PRIO_8021D_EE 3
+#define PRIO_8021D_CL 4
+#define PRIO_8021D_VI 5
+#define PRIO_8021D_VO 6
+#define PRIO_8021D_NC 7
+#define MAXPRIO 7
+#define NUMPRIO (MAXPRIO + 1)
+
+#define ALLPRIO -1
+
+#define PRIO2PREC(prio) \
+ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio))
+
+#endif
diff --git a/src/common/include/proto/bcmeth.h b/src/common/include/proto/bcmeth.h
new file mode 100644
index 0000000..55fef46
--- /dev/null
+++ b/src/common/include/proto/bcmeth.h
@@ -0,0 +1,62 @@
+/*
+ * Broadcom Ethernettype protocol definitions
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $
+ */
+
+#ifndef _BCMETH_H_
+#define _BCMETH_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#include <packed_section_start.h>
+
+#define BCMILCP_SUBTYPE_RATE 1
+#define BCMILCP_SUBTYPE_LINK 2
+#define BCMILCP_SUBTYPE_CSA 3
+#define BCMILCP_SUBTYPE_LARQ 4
+#define BCMILCP_SUBTYPE_VENDOR 5
+#define BCMILCP_SUBTYPE_FLH 17
+
+#define BCMILCP_SUBTYPE_VENDOR_LONG 32769
+#define BCMILCP_SUBTYPE_CERT 32770
+#define BCMILCP_SUBTYPE_SES 32771
+
+#define BCMILCP_BCM_SUBTYPE_RESERVED 0
+#define BCMILCP_BCM_SUBTYPE_EVENT 1
+#define BCMILCP_BCM_SUBTYPE_SES 2
+
+#define BCMILCP_BCM_SUBTYPE_DPT 4
+
+#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8
+#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0
+
+typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr
+{
+ uint16 subtype;
+ uint16 length;
+ uint8 version;
+ uint8 oui[3];
+
+ uint16 usr_subtype;
+} BWL_POST_PACKED_STRUCT bcmeth_hdr_t;
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/bcmevent.h b/src/common/include/proto/bcmevent.h
new file mode 100644
index 0000000..f7253c0
--- /dev/null
+++ b/src/common/include/proto/bcmevent.h
@@ -0,0 +1,343 @@
+/*
+ * Broadcom Event protocol definitions
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Dependencies: proto/bcmeth.h
+ *
+ * $Id: bcmevent.h 382794 2013-02-04 17:34:08Z $
+ *
+ */
+
+#ifndef _BCMEVENT_H_
+#define _BCMEVENT_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#include <proto/bcmeth.h>
+
+#include <packed_section_start.h>
+
+#define BCM_EVENT_MSG_VERSION 2
+#define BCM_MSG_IFNAME_MAX 16
+
+#define WLC_EVENT_MSG_LINK 0x01
+#define WLC_EVENT_MSG_FLUSHTXQ 0x02
+#define WLC_EVENT_MSG_GROUP 0x04
+#define WLC_EVENT_MSG_UNKBSS 0x08
+#define WLC_EVENT_MSG_UNKIF 0x10
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint16 version;
+ uint16 flags;
+ uint32 event_type;
+ uint32 status;
+ uint32 reason;
+ uint32 auth_type;
+ uint32 datalen;
+ struct ether_addr addr;
+ char ifname[BCM_MSG_IFNAME_MAX];
+} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint16 version;
+ uint16 flags;
+ uint32 event_type;
+ uint32 status;
+ uint32 reason;
+ uint32 auth_type;
+ uint32 datalen;
+ struct ether_addr addr;
+ char ifname[BCM_MSG_IFNAME_MAX];
+ uint8 ifidx;
+ uint8 bsscfgidx;
+} BWL_POST_PACKED_STRUCT wl_event_msg_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
+ struct ether_header eth;
+ bcmeth_hdr_t bcm_hdr;
+ wl_event_msg_t event;
+
+} BWL_POST_PACKED_STRUCT bcm_event_t;
+
+#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
+
+#define WLC_E_SET_SSID 0
+#define WLC_E_JOIN 1
+#define WLC_E_START 2
+#define WLC_E_AUTH 3
+#define WLC_E_AUTH_IND 4
+#define WLC_E_DEAUTH 5
+#define WLC_E_DEAUTH_IND 6
+#define WLC_E_ASSOC 7
+#define WLC_E_ASSOC_IND 8
+#define WLC_E_REASSOC 9
+#define WLC_E_REASSOC_IND 10
+#define WLC_E_DISASSOC 11
+#define WLC_E_DISASSOC_IND 12
+#define WLC_E_QUIET_START 13
+#define WLC_E_QUIET_END 14
+#define WLC_E_BEACON_RX 15
+#define WLC_E_LINK 16
+#define WLC_E_MIC_ERROR 17
+#define WLC_E_NDIS_LINK 18
+#define WLC_E_ROAM 19
+#define WLC_E_TXFAIL 20
+#define WLC_E_PMKID_CACHE 21
+#define WLC_E_RETROGRADE_TSF 22
+#define WLC_E_PRUNE 23
+#define WLC_E_AUTOAUTH 24
+#define WLC_E_EAPOL_MSG 25
+#define WLC_E_SCAN_COMPLETE 26
+#define WLC_E_ADDTS_IND 27
+#define WLC_E_DELTS_IND 28
+#define WLC_E_BCNSENT_IND 29
+#define WLC_E_BCNRX_MSG 30
+#define WLC_E_BCNLOST_MSG 31
+#define WLC_E_ROAM_PREP 32
+#define WLC_E_PFN_NET_FOUND 33
+#define WLC_E_PFN_NET_LOST 34
+#define WLC_E_RESET_COMPLETE 35
+#define WLC_E_JOIN_START 36
+#define WLC_E_ROAM_START 37
+#define WLC_E_ASSOC_START 38
+#define WLC_E_IBSS_ASSOC 39
+#define WLC_E_RADIO 40
+#define WLC_E_PSM_WATCHDOG 41
+#define WLC_E_PROBREQ_MSG 44
+#define WLC_E_SCAN_CONFIRM_IND 45
+#define WLC_E_PSK_SUP 46
+#define WLC_E_COUNTRY_CODE_CHANGED 47
+#define WLC_E_EXCEEDED_MEDIUM_TIME 48
+#define WLC_E_ICV_ERROR 49
+#define WLC_E_UNICAST_DECODE_ERROR 50
+#define WLC_E_MULTICAST_DECODE_ERROR 51
+#define WLC_E_TRACE 52
+#define WLC_E_IF 54
+#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55
+#define WLC_E_RSSI 56
+#define WLC_E_PFN_SCAN_COMPLETE 57
+#define WLC_E_EXTLOG_MSG 58
+#define WLC_E_ACTION_FRAME 59
+#define WLC_E_ACTION_FRAME_COMPLETE 60
+#define WLC_E_PRE_ASSOC_IND 61
+#define WLC_E_PRE_REASSOC_IND 62
+#define WLC_E_CHANNEL_ADOPTED 63
+#define WLC_E_AP_STARTED 64
+#define WLC_E_DFS_AP_STOP 65
+#define WLC_E_DFS_AP_RESUME 66
+#define WLC_E_WAI_STA_EVENT 67
+#define WLC_E_WAI_MSG 68
+#define WLC_E_ESCAN_RESULT 69
+#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70
+#define WLC_E_PROBRESP_MSG 71
+#define WLC_E_P2P_PROBREQ_MSG 72
+#define WLC_E_DCS_REQUEST 73
+
+#define WLC_E_FIFO_CREDIT_MAP 74
+
+#define WLC_E_ACTION_FRAME_RX 75
+#define WLC_E_WAKE_EVENT 76
+#define WLC_E_RM_COMPLETE 77
+#define WLC_E_HTSFSYNC 78
+#define WLC_E_OVERLAY_REQ 79
+#define WLC_E_CSA_COMPLETE_IND 80
+#define WLC_E_EXCESS_PM_WAKE_EVENT 81
+#define WLC_E_PFN_SCAN_NONE 82
+#define WLC_E_PFN_SCAN_ALLGONE 83
+#define WLC_E_GTK_PLUMBED 84
+#define WLC_E_ASSOC_IND_NDIS 85
+#define WLC_E_REASSOC_IND_NDIS 86
+#define WLC_E_ASSOC_REQ_IE 87
+#define WLC_E_ASSOC_RESP_IE 88
+#define WLC_E_ASSOC_RECREATED 89
+#define WLC_E_ACTION_FRAME_RX_NDIS 90
+#define WLC_E_AUTH_REQ 91
+#define WLC_E_TDLS_PEER_EVENT 92
+#define WLC_E_SPEEDY_RECREATE_FAIL 93
+#define WLC_E_NATIVE 94
+#define WLC_E_PKTDELAY_IND 95
+#define WLC_E_IBSS_COALESCE 96
+#define WLC_E_SERVICE_FOUND 102
+#define WLC_E_GAS_FRAGMENT_RX 103
+#define WLC_E_GAS_COMPLETE 104
+#define WLC_E_P2PO_ADD_DEVICE 105
+#define WLC_E_P2PO_DEL_DEVICE 106
+#define WLC_E_WNM_STA_SLEEP 107
+#define WLC_E_NONE 108
+#define WLC_E_PROXD 109
+#define WLC_E_AWDL_AW_EXT_END 111
+#define WLC_E_AWDL_AW_EXT_START 112
+#define WLC_E_AWDL_AW_START 113
+#define WLC_E_AWDL_RADIO_OFF 114
+#define WLC_E_AWDL_PEER_STATE 115
+#define WLC_E_AWDL_SYNC_STATE_CHANGED 116
+#define WLC_E_AWDL_CHIP_RESET 117
+#define WLC_E_AWDL_INTERLEAVED_SCAN_START 118
+#define WLC_E_AWDL_INTERLEAVED_SCAN_STOP 119
+#define WLC_E_AWDL_PEER_CACHE_CONTROL 120
+#define WLC_E_CSA_START_IND 121
+#define WLC_E_CSA_DONE_IND 122
+#define WLC_E_CSA_FAILURE_IND 123
+#define WLC_E_LAST 124
+
+typedef struct {
+ uint event;
+ const char *name;
+} bcmevent_name_t;
+
+extern const bcmevent_name_t bcmevent_names[];
+extern const int bcmevent_names_size;
+
+#define WLC_E_STATUS_SUCCESS 0
+#define WLC_E_STATUS_FAIL 1
+#define WLC_E_STATUS_TIMEOUT 2
+#define WLC_E_STATUS_NO_NETWORKS 3
+#define WLC_E_STATUS_ABORT 4
+#define WLC_E_STATUS_NO_ACK 5
+#define WLC_E_STATUS_UNSOLICITED 6
+#define WLC_E_STATUS_ATTEMPT 7
+#define WLC_E_STATUS_PARTIAL 8
+#define WLC_E_STATUS_NEWSCAN 9
+#define WLC_E_STATUS_NEWASSOC 10
+#define WLC_E_STATUS_11HQUIET 11
+#define WLC_E_STATUS_SUPPRESS 12
+#define WLC_E_STATUS_NOCHANS 13
+#define WLC_E_STATUS_CS_ABORT 15
+#define WLC_E_STATUS_ERROR 16
+
+#define WLC_E_REASON_INITIAL_ASSOC 0
+#define WLC_E_REASON_LOW_RSSI 1
+#define WLC_E_REASON_DEAUTH 2
+#define WLC_E_REASON_DISASSOC 3
+#define WLC_E_REASON_BCNS_LOST 4
+#define WLC_E_REASON_MINTXRATE 9
+#define WLC_E_REASON_TXFAIL 10
+
+#define WLC_E_REASON_FAST_ROAM_FAILED 5
+#define WLC_E_REASON_DIRECTED_ROAM 6
+#define WLC_E_REASON_TSPEC_REJECTED 7
+#define WLC_E_REASON_BETTER_AP 8
+
+#define WLC_E_REASON_REQUESTED_ROAM 11
+
+#define WLC_E_PRUNE_ENCR_MISMATCH 1
+#define WLC_E_PRUNE_BCAST_BSSID 2
+#define WLC_E_PRUNE_MAC_DENY 3
+#define WLC_E_PRUNE_MAC_NA 4
+#define WLC_E_PRUNE_REG_PASSV 5
+#define WLC_E_PRUNE_SPCT_MGMT 6
+#define WLC_E_PRUNE_RADAR 7
+#define WLC_E_RSN_MISMATCH 8
+#define WLC_E_PRUNE_NO_COMMON_RATES 9
+#define WLC_E_PRUNE_BASIC_RATES 10
+#define WLC_E_PRUNE_CIPHER_NA 12
+#define WLC_E_PRUNE_KNOWN_STA 13
+#define WLC_E_PRUNE_WDS_PEER 15
+#define WLC_E_PRUNE_QBSS_LOAD 16
+#define WLC_E_PRUNE_HOME_AP 17
+
+#define WLC_E_SUP_OTHER 0
+#define WLC_E_SUP_DECRYPT_KEY_DATA 1
+#define WLC_E_SUP_BAD_UCAST_WEP128 2
+#define WLC_E_SUP_BAD_UCAST_WEP40 3
+#define WLC_E_SUP_UNSUP_KEY_LEN 4
+#define WLC_E_SUP_PW_KEY_CIPHER 5
+#define WLC_E_SUP_MSG3_TOO_MANY_IE 6
+#define WLC_E_SUP_MSG3_IE_MISMATCH 7
+#define WLC_E_SUP_NO_INSTALL_FLAG 8
+#define WLC_E_SUP_MSG3_NO_GTK 9
+#define WLC_E_SUP_GRP_KEY_CIPHER 10
+#define WLC_E_SUP_GRP_MSG1_NO_GTK 11
+#define WLC_E_SUP_GTK_DECRYPT_FAIL 12
+#define WLC_E_SUP_SEND_FAIL 13
+#define WLC_E_SUP_DEAUTH 14
+#define WLC_E_SUP_WPA_PSK_TMO 15
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data {
+ uint16 version;
+ uint16 channel;
+ int32 rssi;
+ uint32 mactime;
+ uint32 rate;
+} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t;
+
+#define BCM_RX_FRAME_DATA_VERSION 1
+
+typedef struct wl_event_data_if {
+ uint8 ifidx;
+ uint8 opcode;
+ uint8 reserved;
+ uint8 bssidx;
+ uint8 role;
+} wl_event_data_if_t;
+
+#define WLC_E_IF_ADD 1
+#define WLC_E_IF_DEL 2
+#define WLC_E_IF_CHANGE 3
+
+#define WLC_E_IF_FLAGS_BSSCFG_NOIF 0x1
+
+#define WLC_E_IF_ROLE_STA 0
+#define WLC_E_IF_ROLE_AP 1
+#define WLC_E_IF_ROLE_WDS 2
+#define WLC_E_IF_ROLE_P2P_GO 3
+#define WLC_E_IF_ROLE_P2P_CLIENT 4
+
+#define WLC_E_LINK_BCN_LOSS 1
+#define WLC_E_LINK_DISASSOC 2
+#define WLC_E_LINK_ASSOC_REC 3
+#define WLC_E_LINK_BSSCFG_DIS 4
+
+#define WLC_E_OVL_DOWNLOAD 0
+#define WLC_E_OVL_UPDATE_IND 1
+
+#define WLC_E_TDLS_PEER_DISCOVERED 0
+#define WLC_E_TDLS_PEER_CONNECTED 1
+#define WLC_E_TDLS_PEER_DISCONNECTED 2
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas {
+ uint16 channel;
+ uint8 dialog_token;
+ uint8 fragment_id;
+ uint16 status_code;
+ uint16 data_len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT wl_event_gas_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_sd_tlv {
+ uint16 length;
+ uint8 protocol;
+ uint8 transaction_id;
+ uint8 status_code;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT wl_sd_tlv_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd {
+ uint16 channel;
+ uint8 count;
+ wl_sd_tlv_t tlv[1];
+} BWL_POST_PACKED_STRUCT wl_event_sd_t;
+
+#define WLC_E_PROXD_FOUND 1
+#define WLC_E_PROXD_GONE 2
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/bcmip.h b/src/common/include/proto/bcmip.h
new file mode 100644
index 0000000..50ce97d
--- /dev/null
+++ b/src/common/include/proto/bcmip.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Fundamental constants relating to IP Protocol
+ *
+ * $Id: bcmip.h 329791 2012-04-26 22:36:58Z $
+ */
+
+#ifndef _bcmip_h_
+#define _bcmip_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#include <packed_section_start.h>
+
+#define IP_VER_OFFSET 0x0
+#define IP_VER_MASK 0xf0
+#define IP_VER_SHIFT 4
+#define IP_VER_4 4
+#define IP_VER_6 6
+
+#define IP_VER(ip_body) \
+ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT)
+
+#define IP_PROT_ICMP 0x1
+#define IP_PROT_IGMP 0x2
+#define IP_PROT_TCP 0x6
+#define IP_PROT_UDP 0x11
+#define IP_PROT_ICMP6 0x3a
+
+#define IPV4_VER_HL_OFFSET 0
+#define IPV4_TOS_OFFSET 1
+#define IPV4_PKTLEN_OFFSET 2
+#define IPV4_PKTFLAG_OFFSET 6
+#define IPV4_PROT_OFFSET 9
+#define IPV4_CHKSUM_OFFSET 10
+#define IPV4_SRC_IP_OFFSET 12
+#define IPV4_DEST_IP_OFFSET 16
+#define IPV4_OPTIONS_OFFSET 20
+#define IPV4_MIN_HEADER_LEN 20
+
+#define IPV4_VER_MASK 0xf0
+#define IPV4_VER_SHIFT 4
+
+#define IPV4_HLEN_MASK 0x0f
+#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK))
+
+#define IPV4_ADDR_LEN 4
+
+#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \
+ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0)
+
+#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \
+ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff)
+
+#define IPV4_TOS_DSCP_MASK 0xfc
+#define IPV4_TOS_DSCP_SHIFT 2
+
+#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET])
+
+#define IPV4_TOS_PREC_MASK 0xe0
+#define IPV4_TOS_PREC_SHIFT 5
+
+#define IPV4_TOS_LOWDELAY 0x10
+#define IPV4_TOS_THROUGHPUT 0x8
+#define IPV4_TOS_RELIABILITY 0x4
+
+#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET])
+
+#define IPV4_FRAG_RESV 0x8000
+#define IPV4_FRAG_DONT 0x4000
+#define IPV4_FRAG_MORE 0x2000
+#define IPV4_FRAG_OFFSET_MASK 0x1fff
+
+#define IPV4_ADDR_STR_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct ipv4_addr {
+ uint8 addr[IPV4_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ipv4_hdr {
+ uint8 version_ihl;
+ uint8 tos;
+ uint16 tot_len;
+ uint16 id;
+ uint16 frag;
+ uint8 ttl;
+ uint8 prot;
+ uint16 hdr_chksum;
+ uint8 src_ip[IPV4_ADDR_LEN];
+ uint8 dst_ip[IPV4_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+#define IPV6_PAYLOAD_LEN_OFFSET 4
+#define IPV6_NEXT_HDR_OFFSET 6
+#define IPV6_HOP_LIMIT_OFFSET 7
+#define IPV6_SRC_IP_OFFSET 8
+#define IPV6_DEST_IP_OFFSET 24
+
+#define IPV6_TRAFFIC_CLASS(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \
+ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4))
+
+#define IPV6_FLOW_LABEL(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \
+ (((uint8 *)(ipv6_body))[2] << 8) | \
+ (((uint8 *)(ipv6_body))[3]))
+
+#define IPV6_PAYLOAD_LEN(ipv6_body) \
+ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \
+ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1])
+
+#define IPV6_NEXT_HDR(ipv6_body) \
+ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET])
+
+#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body)
+
+#define IPV6_ADDR_LEN 16
+
+#define IP_TOS46(ip_body) \
+ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \
+ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0)
+
+#define IPV6_EXTHDR_HOP 0
+#define IPV6_EXTHDR_ROUTING 43
+#define IPV6_EXTHDR_FRAGMENT 44
+#define IPV6_EXTHDR_AUTH 51
+#define IPV6_EXTHDR_NONE 59
+#define IPV6_EXTHDR_DEST 60
+
+#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \
+ ((prot) == IPV6_EXTHDR_ROUTING) || \
+ ((prot) == IPV6_EXTHDR_FRAGMENT) || \
+ ((prot) == IPV6_EXTHDR_AUTH) || \
+ ((prot) == IPV6_EXTHDR_NONE) || \
+ ((prot) == IPV6_EXTHDR_DEST))
+
+#define IPV6_MIN_HLEN 40
+
+#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3)
+
+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr {
+ uint8 nexthdr;
+ uint8 hdrlen;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag {
+ uint8 nexthdr;
+ uint8 rsvd;
+ uint16 frag_off;
+ uint32 ident;
+} BWL_POST_PACKED_STRUCT;
+
+static INLINE int32
+ipv6_exthdr_len(uint8 *h, uint8 *proto)
+{
+ uint16 len = 0, hlen;
+ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h;
+
+ while (IPV6_EXTHDR(eh->nexthdr)) {
+ if (eh->nexthdr == IPV6_EXTHDR_NONE)
+ return -1;
+ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT)
+ hlen = 8;
+ else if (eh->nexthdr == IPV6_EXTHDR_AUTH)
+ hlen = (eh->hdrlen + 2) << 2;
+ else
+ hlen = IPV6_EXTHDR_LEN(eh);
+
+ len += hlen;
+ eh = (struct ipv6_exthdr *)(h + len);
+ }
+
+ *proto = eh->nexthdr;
+ return len;
+}
+
+#define IPV4_ISMULTI(a) (((a) & 0xf0000000) == 0xe0000000)
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/ethernet.h b/src/common/include/proto/ethernet.h
new file mode 100644
index 0000000..09315c9
--- /dev/null
+++ b/src/common/include/proto/ethernet.h
@@ -0,0 +1,156 @@
+/*
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ethernet.h 370577 2012-11-22 07:55:21Z $
+ */
+
+#ifndef _NET_ETHERNET_H_
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+#include <packed_section_start.h>
+
+#define ETHER_ADDR_LEN 6
+
+#define ETHER_TYPE_LEN 2
+
+#define ETHER_CRC_LEN 4
+
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+
+#define ETHER_MIN_LEN 64
+
+#define ETHER_MIN_DATA 46
+
+#define ETHER_MAX_LEN 1518
+
+#define ETHER_MAX_DATA 1500
+
+#define ETHER_TYPE_MIN 0x0600
+#define ETHER_TYPE_IP 0x0800
+#define ETHER_TYPE_ARP 0x0806
+#define ETHER_TYPE_8021Q 0x8100
+#define ETHER_TYPE_IPV6 0x86dd
+#define ETHER_TYPE_BRCM 0x886c
+#define ETHER_TYPE_802_1X 0x888e
+#define ETHER_TYPE_802_1X_PREAUTH 0x88c7
+#define ETHER_TYPE_WAI 0x88b4
+#define ETHER_TYPE_89_0D 0x890d
+
+#define ETHER_TYPE_PPP_SES 0x8864
+
+#define ETHER_TYPE_IPV6 0x86dd
+
+#define ETHER_BRCM_SUBTYPE_LEN 4
+
+#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN)
+#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN)
+#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN)
+
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \
+ ((uint8 *)ea)[0] = 0x01; \
+ ((uint8 *)ea)[1] = 0x00; \
+ ((uint8 *)ea)[2] = 0x5e; \
+ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \
+ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \
+ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \
+}
+
+#ifndef __INCif_etherh
+
+BWL_PRE_PACKED_STRUCT struct ether_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 ether_type;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+#endif
+
+#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2))
+#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2)
+#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd))
+#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2))
+
+#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1))
+
+#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1)
+
+#define eacmp(a, b) ((((const uint16 *)(a))[0] ^ ((const uint16 *)(b))[0]) | \
+ (((const uint16 *)(a))[1] ^ ((const uint16 *)(b))[1]) | \
+ (((const uint16 *)(a))[2] ^ ((const uint16 *)(b))[2]))
+
+#define ether_cmp(a, b) eacmp(a, b)
+
+#define eacopy(s, d) \
+do { \
+ ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \
+ ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \
+ ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \
+} while (0)
+
+#define ether_copy(s, d) eacopy(s, d)
+
+#define ether_rcopy(s, d) \
+do { \
+ ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \
+ ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \
+ ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \
+} while (0)
+
+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}};
+static const struct ether_addr ether_ipv6_mcast = {{0x33, 0x33, 0x00, 0x00, 0x00, 0x01}};
+
+#define ETHER_ISBCAST(ea) ((((const uint8 *)(ea))[0] & \
+ ((const uint8 *)(ea))[1] & \
+ ((const uint8 *)(ea))[2] & \
+ ((const uint8 *)(ea))[3] & \
+ ((const uint8 *)(ea))[4] & \
+ ((const uint8 *)(ea))[5]) == 0xff)
+#define ETHER_ISNULLADDR(ea) ((((const uint8 *)(ea))[0] | \
+ ((const uint8 *)(ea))[1] | \
+ ((const uint8 *)(ea))[2] | \
+ ((const uint8 *)(ea))[3] | \
+ ((const uint8 *)(ea))[4] | \
+ ((const uint8 *)(ea))[5]) == 0)
+
+#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \
+ ((const uint16 *)(da))[1] | \
+ ((const uint16 *)(da))[2]) == 0)
+#define ETHER_ISNULLSRC(sa) ETHER_ISNULLDEST(sa)
+
+#define ETHER_MOVE_HDR(d, s) \
+do { \
+ struct ether_header t; \
+ t = *(struct ether_header *)(s); \
+ *(struct ether_header *)(d) = t; \
+} while (0)
+
+#define ETHER_ISUCAST(ea) ((((uint8 *)(ea))[0] & 0x01) == 0)
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/ieee80211_radiotap.h b/src/common/include/proto/ieee80211_radiotap.h
new file mode 100644
index 0000000..d3945b8
--- /dev/null
+++ b/src/common/include/proto/ieee80211_radiotap.h
@@ -0,0 +1,161 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.11 2007/12/13 01:23:40 sam Exp $ */
+
+#ifndef _NET80211_IEEE80211_RADIOTAP_H_
+#define _NET80211_IEEE80211_RADIOTAP_H_
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+#ifndef DLT_IEEE802_11_RADIO
+#define DLT_IEEE802_11_RADIO 127
+#endif
+#endif
+
+#define IEEE80211_RADIOTAP_HDRLEN 64
+
+struct ieee80211_radiotap_header {
+ uint8_t it_version;
+ uint8_t it_pad;
+ uint16_t it_len;
+ uint32_t it_present;
+} __attribute__((packed));
+
+enum ieee80211_radiotap_type {
+ IEEE80211_RADIOTAP_TSFT = 0,
+ IEEE80211_RADIOTAP_FLAGS = 1,
+ IEEE80211_RADIOTAP_RATE = 2,
+ IEEE80211_RADIOTAP_CHANNEL = 3,
+ IEEE80211_RADIOTAP_FHSS = 4,
+ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+ IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+ IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+ IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+
+ IEEE80211_RADIOTAP_TXFLAGS = 15,
+ IEEE80211_RADIOTAP_RETRIES = 17,
+ IEEE80211_RADIOTAP_XCHANNEL = 18,
+ IEEE80211_RADIOTAP_MCS = 19,
+ IEEE80211_RADIOTAP_AMPDU = 20,
+ IEEE80211_RADIOTAP_VHT = 21,
+ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
+ IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
+ IEEE80211_RADIOTAP_EXT = 31,
+ };
+
+#ifndef _KERNEL
+
+#define IEEE80211_CHAN_TURBO 0x00000010
+#define IEEE80211_CHAN_CCK 0x00000020
+#define IEEE80211_CHAN_OFDM 0x00000040
+#define IEEE80211_CHAN_2GHZ 0x00000080
+#define IEEE80211_CHAN_5GHZ 0x00000100
+#define IEEE80211_CHAN_PASSIVE 0x00000200
+#define IEEE80211_CHAN_DYN 0x00000400
+#define IEEE80211_CHAN_GFSK 0x00000800
+#define IEEE80211_CHAN_GSM 0x00001000
+#define IEEE80211_CHAN_STURBO 0x00002000
+#define IEEE80211_CHAN_HALF 0x00004000
+#define IEEE80211_CHAN_QUARTER 0x00008000
+#define IEEE80211_CHAN_HT20 0x00010000
+#define IEEE80211_CHAN_HT40U 0x00020000
+#define IEEE80211_CHAN_HT40D 0x00040000
+#endif
+
+#define IEEE80211_RADIOTAP_F_CFP 0x01
+#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02
+#define IEEE80211_RADIOTAP_F_WEP 0x04
+#define IEEE80211_RADIOTAP_F_FRAG 0x08
+#define IEEE80211_RADIOTAP_F_FCS 0x10
+#define IEEE80211_RADIOTAP_F_DATAPAD 0x20
+#define IEEE80211_RADIOTAP_F_BADFCS 0x40
+
+#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
+#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
+#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
+#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
+#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
+
+#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
+#define IEEE80211_RADIOTAP_MCS_BW_20 0
+#define IEEE80211_RADIOTAP_MCS_BW_40 1
+#define IEEE80211_RADIOTAP_MCS_BW_20L 2
+#define IEEE80211_RADIOTAP_MCS_BW_20U 3
+#define IEEE80211_RADIOTAP_MCS_SGI 0x04
+#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
+#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
+
+#define IEEE80211_RADIOTAP_MCS_BW_80 0x20
+#define IEEE80211_RADIOTAP_MCS_BW_20LL 0x40
+#define IEEE80211_RADIOTAP_MCS_BW_20LU 0x60
+#define IEEE80211_RADIOTAP_MCS_BW_20UL 0x80
+#define IEEE80211_RADIOTAP_MCS_BW_20UU 0xa0
+#define IEEE80211_RADIOTAP_MCS_BW_40L 0xc0
+#define IEEE80211_RADIOTAP_MCS_BW_40U 0xe0
+
+#define IEEE80211_RADIOTAP_VHT_HAVE_STBC 0x0001
+#define IEEE80211_RADIOTAP_VHT_HAVE_TXOP_PS 0x0002
+#define IEEE80211_RADIOTAP_VHT_HAVE_GI 0x0004
+#define IEEE80211_RADIOTAP_VHT_HAVE_SGI_NSYM_DA 0x0008
+#define IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA 0x0010
+#define IEEE80211_RADIOTAP_VHT_HAVE_BF 0x0020
+#define IEEE80211_RADIOTAP_VHT_HAVE_BW 0x0040
+#define IEEE80211_RADIOTAP_VHT_HAVE_GID 0x0080
+#define IEEE80211_RADIOTAP_VHT_HAVE_PAID 0x0100
+
+#define IEEE80211_RADIOTAP_VHT_STBC 0x01
+#define IEEE80211_RADIOTAP_VHT_TXOP_PS 0x02
+#define IEEE80211_RADIOTAP_VHT_SGI 0x04
+#define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DA 0x08
+#define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA 0x10
+#define IEEE80211_RADIOTAP_VHT_BF 0x20
+
+#define IEEE80211_RADIOTAP_VHT_NSS 0x0f
+#define IEEE80211_RADIOTAP_VHT_MCS 0xf0
+
+#define IEEE80211_RADIOTAP_VHT_CODING_LDPC 0x01
+
+#define IEEE80211_RADIOTAP_VHT_BW_20 IEEE80211_RADIOTAP_MCS_BW_20
+#define IEEE80211_RADIOTAP_VHT_BW_40 IEEE80211_RADIOTAP_MCS_BW_40
+#define IEEE80211_RADIOTAP_VHT_BW_20L IEEE80211_RADIOTAP_MCS_BW_20L
+#define IEEE80211_RADIOTAP_VHT_BW_20U IEEE80211_RADIOTAP_MCS_BW_20U
+#define IEEE80211_RADIOTAP_VHT_BW_80 4
+#define IEEE80211_RADIOTAP_VHT_BW_40L 5
+#define IEEE80211_RADIOTAP_VHT_BW_40U 6
+#define IEEE80211_RADIOTAP_VHT_BW_20LL 7
+#define IEEE80211_RADIOTAP_VHT_BW_20LU 8
+#define IEEE80211_RADIOTAP_VHT_BW_20UL 9
+#define IEEE80211_RADIOTAP_VHT_BW_20UU 10
+#define IEEE80211_RADIOTAP_VHT_BW_160 11
+#define IEEE80211_RADIOTAP_VHT_BW_80L 12
+#define IEEE80211_RADIOTAP_VHT_BW_80U 13
+#define IEEE80211_RADIOTAP_VHT_BW_40LL 14
+#define IEEE80211_RADIOTAP_VHT_BW_40LU 15
+#define IEEE80211_RADIOTAP_VHT_BW_40UL 16
+#define IEEE80211_RADIOTAP_VHT_BW_40UU 17
+#define IEEE80211_RADIOTAP_VHT_BW_20LLL 18
+#define IEEE80211_RADIOTAP_VHT_BW_20LLU 19
+#define IEEE80211_RADIOTAP_VHT_BW_20LUL 20
+#define IEEE80211_RADIOTAP_VHT_BW_20LUU 21
+#define IEEE80211_RADIOTAP_VHT_BW_20ULL 22
+#define IEEE80211_RADIOTAP_VHT_BW_20ULU 23
+#define IEEE80211_RADIOTAP_VHT_BW_20UUL 24
+#define IEEE80211_RADIOTAP_VHT_BW_20UUU 25
+
+#define IEEE80211_RADIOTAP_TXF_FAIL 0x0001
+#define IEEE80211_RADIOTAP_TXF_CTS 0x0002
+#define IEEE80211_RADIOTAP_TXF_RTSCTS 0x0004
+#define IEEE80211_RADIOTAP_TXF_NOACK 0x0008
+#define IEEE80211_RADIOTAP_TXF_SEQOVR 0x0010
+
+#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
+#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
+#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
+#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
+#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
+#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
+#define IEEE80211_RADIOTAP_AMPDU_MPDU_ONLY 0x8000
+
+#endif
diff --git a/src/common/include/proto/wpa.h b/src/common/include/proto/wpa.h
new file mode 100644
index 0000000..19cfdf0
--- /dev/null
+++ b/src/common/include/proto/wpa.h
@@ -0,0 +1,148 @@
+/*
+ * Fundamental types and constants relating to WPA
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wpa.h 367468 2012-11-08 05:49:44Z $
+ */
+
+#ifndef _proto_wpa_h_
+#define _proto_wpa_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+
+#include <packed_section_start.h>
+
+#define DOT11_RC_INVALID_WPA_IE 13
+#define DOT11_RC_MIC_FAILURE 14
+#define DOT11_RC_4WH_TIMEOUT 15
+#define DOT11_RC_GTK_UPDATE_TIMEOUT 16
+#define DOT11_RC_WPA_IE_MISMATCH 17
+#define DOT11_RC_INVALID_MC_CIPHER 18
+#define DOT11_RC_INVALID_UC_CIPHER 19
+#define DOT11_RC_INVALID_AKMP 20
+#define DOT11_RC_BAD_WPA_VERSION 21
+#define DOT11_RC_INVALID_WPA_CAP 22
+#define DOT11_RC_8021X_AUTH_FAIL 23
+
+#define WPA2_PMKID_LEN 16
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint8 tag;
+ uint8 length;
+ uint8 oui[3];
+ uint8 oui_type;
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT version;
+} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t;
+#define WPA_IE_OUITYPE_LEN 4
+#define WPA_IE_FIXED_LEN 8
+#define WPA_IE_TAG_FIXED_LEN 6
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint8 tag;
+ uint8 length;
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT version;
+} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t;
+#define WPA_RSN_IE_FIXED_LEN 4
+#define WPA_RSN_IE_TAG_FIXED_LEN 2
+typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN];
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint8 oui[3];
+ uint8 type;
+} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t;
+#define WPA_SUITE_LEN 4
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT count;
+ wpa_suite_t list[1];
+} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+#define WPA_IE_SUITE_COUNT_LEN 2
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT count;
+ wpa_pmkid_t list[1];
+} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t;
+
+#define WPA_CIPHER_NONE 0
+#define WPA_CIPHER_WEP_40 1
+#define WPA_CIPHER_TKIP 2
+#define WPA_CIPHER_AES_OCB 3
+#define WPA_CIPHER_AES_CCM 4
+#define WPA_CIPHER_WEP_104 5
+#define WPA_CIPHER_BIP 6
+#define WPA_CIPHER_TPK 7
+
+#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \
+ (cipher) == WPA_CIPHER_WEP_40 || \
+ (cipher) == WPA_CIPHER_WEP_104 || \
+ (cipher) == WPA_CIPHER_TKIP || \
+ (cipher) == WPA_CIPHER_AES_OCB || \
+ (cipher) == WPA_CIPHER_AES_CCM || \
+ (cipher) == WPA_CIPHER_TPK)
+
+#define WPA_TKIP_CM_DETECT 60
+#define WPA_TKIP_CM_BLOCK 60
+
+#define RSN_CAP_LEN 2
+
+#define RSN_CAP_PREAUTH 0x0001
+#define RSN_CAP_NOPAIRWISE 0x0002
+#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
+#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2
+#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030
+#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4
+#define RSN_CAP_1_REPLAY_CNTR 0
+#define RSN_CAP_2_REPLAY_CNTRS 1
+#define RSN_CAP_4_REPLAY_CNTRS 2
+#define RSN_CAP_16_REPLAY_CNTRS 3
+#define RSN_CAP_MFPR 0x0040
+#define RSN_CAP_MFPC 0x0080
+#define RSN_CAP_SPPC 0x0400
+#define RSN_CAP_SPPR 0x0800
+
+#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS
+#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS
+#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT
+#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK
+
+#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1)
+
+#define WPA_CAP_LEN RSN_CAP_LEN
+#define WPA_PMKID_CNT_LEN 2
+
+#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH
+
+#define WPA2_PMKID_COUNT_LEN 2
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/include/bcmcrypto/tkhash.h b/src/include/bcmcrypto/tkhash.h
new file mode 100644
index 0000000..6afc334
--- /dev/null
+++ b/src/include/bcmcrypto/tkhash.h
@@ -0,0 +1,33 @@
+/*
+ * tkhash.h
+ * Prototypes for TKIP hash functions.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: tkhash.h 458337 2014-02-26 18:39:26Z $
+ */
+
+#ifndef _TKHASH_H_
+#define _TKHASH_H_
+
+#include <typedefs.h>
+
+#define TKHASH_P1_KEY_SIZE 10
+#define TKHASH_P2_KEY_SIZE 16
+
+extern void BCMROMFN(tkhash_phase1)(uint16 *P1K, const uint8 *TK, const uint8 *TA, uint32 IV32);
+extern void BCMROMFN(tkhash_phase2)(uint8 *RC4KEY, const uint8 *TK, const uint16 *P1K, uint16 IV16);
+
+#endif
diff --git a/src/include/bcmdefs.h b/src/include/bcmdefs.h
new file mode 100644
index 0000000..413ce84
--- /dev/null
+++ b/src/include/bcmdefs.h
@@ -0,0 +1,164 @@
+/*
+ * Misc system wide definitions
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmdefs.h 432150 2013-10-25 20:57:18Z $
+ */
+
+#ifndef _bcmdefs_h_
+#define _bcmdefs_h_
+
+#define BCM_REFERENCE(data) ((void)(data))
+
+#ifdef __GNUC__
+#define UNUSED_VAR __attribute__ ((unused))
+#else
+#define UNUSED_VAR
+#endif
+
+#define STATIC_ASSERT(expr) { \
+ \
+ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e UNUSED_VAR; \
+ \
+ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1] UNUSED_VAR; \
+}
+
+#define bcmreclaimed 0
+#define BCMATTACHDATA(_data) _data
+#define BCMATTACHFN(_fn) _fn
+#define BCMPREATTACHDATA(_data) _data
+#define BCMPREATTACHFN(_fn) _fn
+#define BCMINITDATA(_data) _data
+#define BCMINITFN(_fn) _fn
+#define BCMUNINITFN(_fn) _fn
+#define BCMNMIATTACHFN(_fn) _fn
+#define BCMNMIATTACHDATA(_data) _data
+#define CONST const
+#if defined(BCM47XX) && defined(__ARM_ARCH_7A__)
+#define BCM47XX_CA9
+#else
+#undef BCM47XX_CA9
+#endif
+#if defined(BCM47XX_CA9)
+#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath")))
+#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host")))
+#else
+#define BCMFASTPATH
+#define BCMFASTPATH_HOST
+#endif
+
+#define BCMROMDATA(_data) _data
+#define BCMROMDAT_NAME(_data) _data
+#define BCMROMFN(_fn) _fn
+#define BCMROMFN_NAME(_fn) _fn
+#define STATIC static
+#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data)
+#define BCMROMDAT_SIZEOF(data) sizeof(data)
+#define BCMROMDAT_APATCH(data)
+#define BCMROMDAT_SPATCH(data)
+
+#define SI_BUS 0
+#define PCI_BUS 1
+#define PCMCIA_BUS 2
+#define SDIO_BUS 3
+#define JTAG_BUS 4
+#define USB_BUS 5
+#define SPI_BUS 6
+#define RPC_BUS 7
+
+#define BUSTYPE(bus) (bus)
+
+#define CHIPTYPE(bus) (bus)
+
+#define SPROMBUS (PCI_BUS)
+
+#define CHIPID(chip) (chip)
+
+#define CHIPREV(rev) (rev)
+
+#define DMADDR_MASK_32 0x0
+#define DMADDR_MASK_30 0xc0000000
+#define DMADDR_MASK_0 0xffffffff
+
+#define DMADDRWIDTH_30 30
+#define DMADDRWIDTH_32 32
+#define DMADDRWIDTH_63 63
+#define DMADDRWIDTH_64 64
+
+typedef unsigned long dmaaddr_t;
+#define PHYSADDRHI(_pa) (0)
+#define PHYSADDRHISET(_pa, _val)
+#define PHYSADDRLO(_pa) ((_pa))
+#define PHYSADDRLOSET(_pa, _val) \
+ do { \
+ (_pa) = (_val); \
+ } while (0)
+
+typedef struct {
+ dmaaddr_t addr;
+ uint32 length;
+} hnddma_seg_t;
+
+#define MAX_DMA_SEGS 8
+
+typedef struct {
+ void *oshdmah;
+ uint origsize;
+ uint nsegs;
+ hnddma_seg_t segs[MAX_DMA_SEGS];
+} hnddma_seg_map_t;
+
+#define BCMEXTRAHDROOM 204
+
+#define SDALIGN 32
+
+#define BCMDONGLEHDRSZ 12
+#define BCMDONGLEPADSZ 16
+
+#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ)
+
+#ifdef BCMDBG
+
+#ifndef BCMDBG_ERR
+#define BCMDBG_ERR
+#endif
+
+#ifndef BCMDBG_ASSERT
+#define BCMDBG_ASSERT
+#endif
+
+#endif
+
+#if defined(BCMDBG_ASSERT)
+#define BCMASSERT_SUPPORT
+#endif
+
+#define BITFIELD_MASK(width) \
+ (((unsigned)1 << (width)) - 1)
+#define GFIELD(val, field) \
+ (((val) >> field ## _S) & field ## _M)
+#define SFIELD(val, field, bits) \
+ (((val) & (~(field ## _M << field ## _S))) | \
+ ((unsigned)(bits) << field ## _S))
+
+#undef BCMSPACE
+#define bcmspace FALSE
+
+#ifndef MAXSZ_NVRAM_VARS
+#define MAXSZ_NVRAM_VARS 4096
+#endif
+
+#endif
diff --git a/src/include/bcmendian.h b/src/include/bcmendian.h
new file mode 100644
index 0000000..4b04c6e
--- /dev/null
+++ b/src/include/bcmendian.h
@@ -0,0 +1,280 @@
+/*
+ * Byte order utilities
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmendian.h 370210 2012-11-21 05:35:27Z $
+ *
+ * This file by default provides proper behavior on little-endian architectures.
+ * On big-endian architectures, IL_BIGENDIAN should be defined.
+ */
+
+#ifndef _BCMENDIAN_H_
+#define _BCMENDIAN_H_
+
+#include <typedefs.h>
+
+#define BCMSWAP16(val) \
+ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
+ (((uint16)(val) & (uint16)0xff00U) >> 8)))
+
+#define BCMSWAP32(val) \
+ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
+ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \
+ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \
+ (((uint32)(val) & (uint32)0xff000000U) >> 24)))
+
+#define BCMSWAP32BY16(val) \
+ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
+ (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
+
+#define BCMSWAP64(val) \
+ ((uint64)((((uint64)(val) & 0x00000000000000ffULL) << 56) | \
+ (((uint64)(val) & 0x000000000000ff00ULL) << 40) | \
+ (((uint64)(val) & 0x0000000000ff0000ULL) << 24) | \
+ (((uint64)(val) & 0x00000000ff000000ULL) << 8) | \
+ (((uint64)(val) & 0x000000ff00000000ULL) >> 8) | \
+ (((uint64)(val) & 0x0000ff0000000000ULL) >> 24) | \
+ (((uint64)(val) & 0x00ff000000000000ULL) >> 40) | \
+ (((uint64)(val) & 0xff00000000000000ULL) >> 56)))
+
+#define BCMSWAP64BY32(val) \
+ ((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \
+ (((uint64)(val) & 0xffffffff00000000ULL) >> 32)))
+
+#ifndef hton16
+#define HTON16(i) BCMSWAP16(i)
+#define hton16(i) bcmswap16(i)
+#define HTON32(i) BCMSWAP32(i)
+#define hton32(i) bcmswap32(i)
+#define NTOH16(i) BCMSWAP16(i)
+#define ntoh16(i) bcmswap16(i)
+#define NTOH32(i) BCMSWAP32(i)
+#define ntoh32(i) bcmswap32(i)
+#define LTOH16(i) (i)
+#define ltoh16(i) (i)
+#define LTOH32(i) (i)
+#define ltoh32(i) (i)
+#define HTOL16(i) (i)
+#define htol16(i) (i)
+#define HTOL32(i) (i)
+#define htol32(i) (i)
+#define HTOL64(i) (i)
+#define htol64(i) (i)
+#endif
+
+#define ltoh16_buf(buf, i)
+#define htol16_buf(buf, i)
+
+#define load32_ua(a) ltoh32_ua(a)
+#define store32_ua(a, v) htol32_ua_store(v, a)
+#define load16_ua(a) ltoh16_ua(a)
+#define store16_ua(a, v) htol16_ua_store(v, a)
+
+#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8))
+#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
+#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1])
+#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
+
+#define ltoh_ua(ptr) \
+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
+ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \
+ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \
+ *(uint8 *)0)
+
+#define ntoh_ua(ptr) \
+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
+ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \
+ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \
+ *(uint8 *)0)
+
+#ifdef __GNUC__
+
+#define bcmswap16(val) ({ \
+ uint16 _val = (val); \
+ BCMSWAP16(_val); \
+})
+
+#define bcmswap32(val) ({ \
+ uint32 _val = (val); \
+ BCMSWAP32(_val); \
+})
+
+#define bcmswap64(val) ({ \
+ uint64 _val = (val); \
+ BCMSWAP64(_val); \
+})
+
+#define bcmswap32by16(val) ({ \
+ uint32 _val = (val); \
+ BCMSWAP32BY16(_val); \
+})
+
+#define bcmswap16_buf(buf, len) ({ \
+ uint16 *_buf = (uint16 *)(buf); \
+ uint _wds = (len) / 2; \
+ while (_wds--) { \
+ *_buf = bcmswap16(*_buf); \
+ _buf++; \
+ } \
+})
+
+#define htol16_ua_store(val, bytes) ({ \
+ uint16 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val & 0xff; \
+ _bytes[1] = _val >> 8; \
+})
+
+#define htol32_ua_store(val, bytes) ({ \
+ uint32 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val & 0xff; \
+ _bytes[1] = (_val >> 8) & 0xff; \
+ _bytes[2] = (_val >> 16) & 0xff; \
+ _bytes[3] = _val >> 24; \
+})
+
+#define hton16_ua_store(val, bytes) ({ \
+ uint16 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val >> 8; \
+ _bytes[1] = _val & 0xff; \
+})
+
+#define hton32_ua_store(val, bytes) ({ \
+ uint32 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val >> 24; \
+ _bytes[1] = (_val >> 16) & 0xff; \
+ _bytes[2] = (_val >> 8) & 0xff; \
+ _bytes[3] = _val & 0xff; \
+})
+
+#define ltoh16_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _LTOH16_UA(_bytes); \
+})
+
+#define ltoh32_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _LTOH32_UA(_bytes); \
+})
+
+#define ntoh16_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _NTOH16_UA(_bytes); \
+})
+
+#define ntoh32_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _NTOH32_UA(_bytes); \
+})
+
+#else
+
+static INLINE uint16
+bcmswap16(uint16 val)
+{
+ return BCMSWAP16(val);
+}
+
+static INLINE uint32
+bcmswap32(uint32 val)
+{
+ return BCMSWAP32(val);
+}
+
+static INLINE uint64
+bcmswap64(uint64 val)
+{
+ return BCMSWAP64(val);
+}
+
+static INLINE uint32
+bcmswap32by16(uint32 val)
+{
+ return BCMSWAP32BY16(val);
+}
+
+static INLINE void
+bcmswap16_buf(uint16 *buf, uint len)
+{
+ len = len / 2;
+
+ while (len--) {
+ *buf = bcmswap16(*buf);
+ buf++;
+ }
+}
+
+static INLINE void
+htol16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[0] = val & 0xff;
+ bytes[1] = val >> 8;
+}
+
+static INLINE void
+htol32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[0] = val & 0xff;
+ bytes[1] = (val >> 8) & 0xff;
+ bytes[2] = (val >> 16) & 0xff;
+ bytes[3] = val >> 24;
+}
+
+static INLINE void
+hton16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[0] = val >> 8;
+ bytes[1] = val & 0xff;
+}
+
+static INLINE void
+hton32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[0] = val >> 24;
+ bytes[1] = (val >> 16) & 0xff;
+ bytes[2] = (val >> 8) & 0xff;
+ bytes[3] = val & 0xff;
+}
+
+static INLINE uint16
+ltoh16_ua(const void *bytes)
+{
+ return _LTOH16_UA((const uint8 *)bytes);
+}
+
+static INLINE uint32
+ltoh32_ua(const void *bytes)
+{
+ return _LTOH32_UA((const uint8 *)bytes);
+}
+
+static INLINE uint16
+ntoh16_ua(const void *bytes)
+{
+ return _NTOH16_UA((const uint8 *)bytes);
+}
+
+static INLINE uint32
+ntoh32_ua(const void *bytes)
+{
+ return _NTOH32_UA((const uint8 *)bytes);
+}
+
+#endif
+#endif
diff --git a/src/include/bcmutils.h b/src/include/bcmutils.h
new file mode 100644
index 0000000..5fafe3d
--- /dev/null
+++ b/src/include/bcmutils.h
@@ -0,0 +1,657 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmutils.h 410746 2013-07-02 23:56:47Z $
+ */
+
+#ifndef _bcmutils_h_
+#define _bcmutils_h_
+
+#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src))
+#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count))
+#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src))
+#define bcm_sprintf_s snprintf
+
+#define _BCM_U 0x01
+#define _BCM_L 0x02
+#define _BCM_D 0x04
+#define _BCM_C 0x08
+#define _BCM_P 0x10
+#define _BCM_S 0x20
+#define _BCM_X 0x40
+#define _BCM_SP 0x80
+
+extern const unsigned char bcm_ctype[];
+#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)])
+
+#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
+#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0)
+#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0)
+#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0)
+#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
+#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0)
+#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0)
+#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0)
+#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
+#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c))
+
+struct bcmstrbuf {
+ char *buf;
+ unsigned int size;
+ char *origbuf;
+ unsigned int origsize;
+};
+
+#include <osl.h>
+
+#define GPIO_PIN_NOTDEFINED 0x20
+
+#define SPINWAIT_POLL_PERIOD 10
+
+#define SPINWAIT(exp, us) { \
+ uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1); \
+ while ((exp) && (countdown >= SPINWAIT_POLL_PERIOD)) {\
+ OSL_DELAY(SPINWAIT_POLL_PERIOD); \
+ countdown -= SPINWAIT_POLL_PERIOD; \
+ } \
+}
+
+#ifndef PKTQ_LEN_DEFAULT
+#define PKTQ_LEN_DEFAULT 128
+#endif
+#ifndef PKTQ_MAX_PREC
+#define PKTQ_MAX_PREC 16
+#endif
+
+typedef struct pktq_prec {
+ void *head;
+ void *tail;
+ uint16 len;
+ uint16 max;
+} pktq_prec_t;
+
+#define PKTQ_COMMON \
+ uint16 num_prec; \
+ uint16 hi_prec; \
+ uint16 max; \
+ uint16 len;
+
+struct pktq {
+ PKTQ_COMMON
+
+ struct pktq_prec q[PKTQ_MAX_PREC];
+};
+
+struct spktq {
+ PKTQ_COMMON
+
+ struct pktq_prec q[1];
+};
+
+#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
+
+typedef bool (*ifpkt_cb_t)(void*, int);
+
+#define POOL_ENAB(bus) 0
+#define SHARED_POOL ((struct pktpool *)NULL)
+
+#ifndef PKTPOOL_LEN_MAX
+#define PKTPOOL_LEN_MAX 40
+#endif
+#define PKTPOOL_CB_MAX 3
+
+struct pktpool;
+typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg);
+typedef struct {
+ pktpool_cb_t cb;
+ void *arg;
+} pktpool_cbinfo_t;
+
+typedef struct pktpool {
+ bool inited;
+ uint16 r;
+ uint16 w;
+ uint16 len;
+ uint16 maxlen;
+ uint16 plen;
+ bool istx;
+ bool empty;
+ uint8 cbtoggle;
+ uint8 cbcnt;
+ uint8 ecbcnt;
+ bool emptycb_disable;
+ pktpool_cbinfo_t *availcb_excl;
+ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX];
+ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX];
+ void *q[PKTPOOL_LEN_MAX + 1];
+
+} pktpool_t;
+
+#if defined(BCM4329C0)
+extern pktpool_t *pktpool_shared_ptr;
+#else
+extern pktpool_t *pktpool_shared;
+#endif
+
+extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx);
+extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp);
+extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal);
+extern void* pktpool_get(pktpool_t *pktp);
+extern void pktpool_free(pktpool_t *pktp, void *p);
+extern int pktpool_add(pktpool_t *pktp, void *p);
+extern uint16 pktpool_avail(pktpool_t *pktp);
+extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp);
+extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb);
+extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen);
+extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen);
+extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable);
+extern bool pktpool_emptycb_disabled(pktpool_t *pktp);
+
+#define POOLPTR(pp) ((pktpool_t *)(pp))
+#define pktpool_len(pp) (POOLPTR(pp)->len - 1)
+#define pktpool_plen(pp) (POOLPTR(pp)->plen)
+#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen)
+
+struct ether_addr;
+
+extern int ether_isbcast(const void *ea);
+extern int ether_isnulladdr(const void *ea);
+
+#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
+#define pktq_pmax(pq, prec) ((pq)->q[prec].max)
+#define pktq_plen(pq, prec) ((pq)->q[prec].len)
+#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len)
+#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max)
+#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0)
+
+#define pktq_ppeek(pq, prec) ((pq)->q[prec].head)
+#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail)
+
+extern void *pktq_penq(struct pktq *pq, int prec, void *p);
+extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
+extern void *pktq_pdeq(struct pktq *pq, int prec);
+extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
+extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
+
+extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir,
+ ifpkt_cb_t fn, int arg);
+
+extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
+
+extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
+extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
+extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
+
+#define pktq_len(pq) ((int)(pq)->len)
+#define pktq_max(pq) ((int)(pq)->max)
+#define pktq_avail(pq) ((int)((pq)->max - (pq)->len))
+#define pktq_full(pq) ((pq)->len >= (pq)->max)
+#define pktq_empty(pq) ((pq)->len == 0)
+
+#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p))
+#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
+#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0)
+#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
+#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len)
+
+extern void pktq_init(struct pktq *pq, int num_prec, int max_len);
+extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
+
+extern void *pktq_deq(struct pktq *pq, int *prec_out);
+extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
+extern void *pktq_peek(struct pktq *pq, int *prec_out);
+extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
+extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg);
+
+extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf);
+extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf);
+extern uint pkttotlen(osl_t *osh, void *p);
+extern void *pktlast(osl_t *osh, void *p);
+extern uint pktsegcnt(osl_t *osh, void *p);
+extern uint pktsegcnt_war(osl_t *osh, void *p);
+extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset);
+extern void *pktoffset(osl_t *osh, void *p, uint offset);
+
+#define PKTPRIO_VDSCP 0x100
+#define PKTPRIO_VLAN 0x200
+#define PKTPRIO_UPD 0x400
+#define PKTPRIO_DSCP 0x800
+
+extern uint pktsetprio(void *pkt, bool update_vtag);
+
+extern int BCMROMFN(bcm_atoi)(const char *s);
+extern ulong BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base);
+extern char *BCMROMFN(bcmstrstr)(const char *haystack, const char *needle);
+extern char *BCMROMFN(bcmstrcat)(char *dest, const char *src);
+extern char *BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size);
+extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen);
+char* bcmstrtok(char **string, const char *delimiters, char *tokdelim);
+int bcmstricmp(const char *s1, const char *s2);
+int bcmstrnicmp(const char* s1, const char* s2, int cnt);
+
+extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf);
+extern int BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea);
+
+struct ipv4_addr;
+extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf);
+extern char *bcm_ipv6_ntoa(void *ipv6, char *buf);
+
+extern void bcm_mdelay(uint ms);
+
+#define NVRAM_RECLAIM_CHECK(name)
+
+extern char *getvar(char *vars, const char *name);
+extern int getintvar(char *vars, const char *name);
+extern int getintvararray(char *vars, const char *name, int index);
+extern int getintvararraysize(char *vars, const char *name);
+extern uint getgpiopin(char *vars, char *pin_name, uint def_pin);
+#ifdef BCMDBG
+extern void prpkt(const char *msg, osl_t *osh, void *p0);
+#endif
+#define bcm_perf_enable()
+#define bcmstats(fmt)
+#define bcmlog(fmt, a1, a2)
+#define bcmdumplog(buf, size) *buf = '\0'
+#define bcmdumplogent(buf, idx) -1
+
+#define TSF_TICKS_PER_MS 1024
+#define bcmtslog(tstamp, fmt, a1, a2)
+#define bcmprinttslogs()
+#define bcmprinttstamp(us)
+#define bcmdumptslog(buf, size)
+
+extern char *bcm_nvram_vars(uint *length);
+extern int bcm_nvram_cache(void *sih);
+
+typedef struct bcm_iovar {
+ const char *name;
+ uint16 varid;
+ uint16 flags;
+ uint16 type;
+ uint16 minlen;
+} bcm_iovar_t;
+
+#define IOV_GET 0
+#define IOV_SET 1
+
+#define IOV_GVAL(id) ((id) * 2)
+#define IOV_SVAL(id) ((id) * 2 + IOV_SET)
+#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET)
+#define IOV_ID(actionid) (actionid >> 1)
+
+extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name);
+extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set);
+#if defined(BCMDBG)
+extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len);
+#endif
+
+#define IOVT_VOID 0
+#define IOVT_BOOL 1
+#define IOVT_INT8 2
+#define IOVT_UINT8 3
+#define IOVT_INT16 4
+#define IOVT_UINT16 5
+#define IOVT_INT32 6
+#define IOVT_UINT32 7
+#define IOVT_BUFFER 8
+#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
+
+#define BCM_IOV_TYPE_INIT { \
+ "void", \
+ "bool", \
+ "int8", \
+ "uint8", \
+ "int16", \
+ "uint16", \
+ "int32", \
+ "uint32", \
+ "buffer", \
+ "" }
+
+#define BCM_IOVT_IS_INT(type) (\
+ (type == IOVT_BOOL) || \
+ (type == IOVT_INT8) || \
+ (type == IOVT_UINT8) || \
+ (type == IOVT_INT16) || \
+ (type == IOVT_UINT16) || \
+ (type == IOVT_INT32) || \
+ (type == IOVT_UINT32))
+
+#define BCME_STRLEN 64
+#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST))
+
+#define BCME_OK 0
+#define BCME_ERROR -1
+#define BCME_BADARG -2
+#define BCME_BADOPTION -3
+#define BCME_NOTUP -4
+#define BCME_NOTDOWN -5
+#define BCME_NOTAP -6
+#define BCME_NOTSTA -7
+#define BCME_BADKEYIDX -8
+#define BCME_RADIOOFF -9
+#define BCME_NOTBANDLOCKED -10
+#define BCME_NOCLK -11
+#define BCME_BADRATESET -12
+#define BCME_BADBAND -13
+#define BCME_BUFTOOSHORT -14
+#define BCME_BUFTOOLONG -15
+#define BCME_BUSY -16
+#define BCME_NOTASSOCIATED -17
+#define BCME_BADSSIDLEN -18
+#define BCME_OUTOFRANGECHAN -19
+#define BCME_BADCHAN -20
+#define BCME_BADADDR -21
+#define BCME_NORESOURCE -22
+#define BCME_UNSUPPORTED -23
+#define BCME_BADLEN -24
+#define BCME_NOTREADY -25
+#define BCME_EPERM -26
+#define BCME_NOMEM -27
+#define BCME_ASSOCIATED -28
+#define BCME_RANGE -29
+#define BCME_NOTFOUND -30
+#define BCME_WME_NOT_ENABLED -31
+#define BCME_TSPEC_NOTFOUND -32
+#define BCME_ACM_NOTSUPPORTED -33
+#define BCME_NOT_WME_ASSOCIATION -34
+#define BCME_SDIO_ERROR -35
+#define BCME_DONGLE_DOWN -36
+#define BCME_VERSION -37
+#define BCME_TXFAIL -38
+#define BCME_RXFAIL -39
+#define BCME_NODEVICE -40
+#define BCME_NMODE_DISABLED -41
+#define BCME_NONRESIDENT -42
+#define BCME_SCANREJECT -43
+#define BCME_LAST BCME_SCANREJECT
+
+#define BCMERRSTRINGTABLE { \
+ "OK", \
+ "Undefined error", \
+ "Bad Argument", \
+ "Bad Option", \
+ "Not up", \
+ "Not down", \
+ "Not AP", \
+ "Not STA", \
+ "Bad Key Index", \
+ "Radio Off", \
+ "Not band locked", \
+ "No clock", \
+ "Bad Rate valueset", \
+ "Bad Band", \
+ "Buffer too short", \
+ "Buffer too long", \
+ "Busy", \
+ "Not Associated", \
+ "Bad SSID len", \
+ "Out of Range Channel", \
+ "Bad Channel", \
+ "Bad Address", \
+ "Not Enough Resources", \
+ "Unsupported", \
+ "Bad length", \
+ "Not Ready", \
+ "Not Permitted", \
+ "No Memory", \
+ "Associated", \
+ "Not In Range", \
+ "Not Found", \
+ "WME Not Enabled", \
+ "TSPEC Not Found", \
+ "ACM Not Supported", \
+ "Not WME Association", \
+ "SDIO Bus Error", \
+ "Dongle Not Accessible", \
+ "Incorrect version", \
+ "TX Failure", \
+ "RX Failure", \
+ "Device Not Present", \
+ "NMODE Disabled", \
+ "Nonresident overlay access", \
+ "Scan Rejected", \
+}
+
+#ifndef ABS
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef LIMIT_TO_RANGE
+#define LIMIT_TO_RANGE(x, min, max) \
+ ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
+#endif
+
+#ifndef LIMIT_TO_MAX
+#define LIMIT_TO_MAX(x, max) \
+ (((x) > (max) ? (max) : (x)))
+#endif
+
+#ifndef LIMIT_TO_MIN
+#define LIMIT_TO_MIN(x, min) \
+ (((x) < (min) ? (min) : (x)))
+#endif
+
+#define CEIL(x, y) (((x) + ((y) - 1)) / (y))
+#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0)
+#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \
+ & ~((boundary) - 1))
+#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \
+ & ~((boundary) - 1))
+#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0)
+#define VALID_MASK(mask) !((mask) & ((mask) + 1))
+
+#ifndef OFFSETOF
+#ifdef __ARMCC_VERSION
+
+#include <stddef.h>
+#define OFFSETOF(type, member) offsetof(type, member)
+#elif __GNUC__ >= 4
+
+#define OFFSETOF(type, member) __builtin_offsetof(type, member)
+#else
+#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member)
+#endif
+#endif
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+extern void *_bcmutils_dummy_fn;
+#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f))
+
+#ifndef setbit
+#ifndef NBBY
+#define NBBY 8
+#endif
+#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY))
+#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY)))
+#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY)))
+#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0)
+#endif
+
+#define isbitset(a, i) (((a) & (1 << (i))) != 0)
+
+#define NBITS(type) (sizeof(type) * 8)
+#define NBITVAL(nbits) (1 << (nbits))
+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
+#define NBITMASK(nbits) MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
+
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
+
+#define MODADD(x, y, bound) \
+ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
+#define MODSUB(x, y, bound) \
+ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
+
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
+#define CRC8_INIT_VALUE 0xff
+#define CRC8_GOOD_VALUE 0x9f
+#define CRC16_INIT_VALUE 0xffff
+#define CRC16_GOOD_VALUE 0xf0b8
+#define CRC32_INIT_VALUE 0xffffffff
+#define CRC32_GOOD_VALUE 0xdebb20e3
+
+#define MACF "%02x:%02x:%02x:%02x:%02x:%02x"
+#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \
+ ((struct ether_addr *) (ea))->octet[1], \
+ ((struct ether_addr *) (ea))->octet[2], \
+ ((struct ether_addr *) (ea))->octet[3], \
+ ((struct ether_addr *) (ea))->octet[4], \
+ ((struct ether_addr *) (ea))->octet[5]
+
+#define ETHER_TO_MACF(ea) (ea).octet[0], \
+ (ea).octet[1], \
+ (ea).octet[2], \
+ (ea).octet[3], \
+ (ea).octet[4], \
+ (ea).octet[5]
+
+typedef struct bcm_bit_desc {
+ uint32 bit;
+ const char* name;
+} bcm_bit_desc_t;
+
+typedef struct bcm_bit_desc_ex {
+ uint32 mask;
+ const bcm_bit_desc_t *bitfield;
+} bcm_bit_desc_ex_t;
+
+typedef struct bcm_tlv {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} bcm_tlv_t;
+
+#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len))
+
+#define ETHER_ADDR_STR_LEN 18
+
+static INLINE void
+xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst)
+{
+ if (
+#ifdef __i386__
+ 1 ||
+#endif
+ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) {
+
+ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0];
+ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1];
+ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2];
+ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3];
+ } else {
+
+ int k;
+ for (k = 0; k < 16; k++)
+ dst[k] = src1[k] ^ src2[k];
+ }
+}
+
+extern uint8 BCMROMFN(hndcrc8)(uint8 *p, uint nbytes, uint8 crc);
+extern uint16 BCMROMFN(hndcrc16)(uint8 *p, uint nbytes, uint16 crc);
+extern uint32 BCMROMFN(hndcrc32)(uint8 *p, uint nbytes, uint32 crc);
+
+#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(BCMDBG_DUMP)
+
+extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len);
+
+extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len);
+#endif
+
+#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(BCMDBG_DUMP) || \
+ defined(WLMEDIA_PEAKRATE)
+extern int bcm_format_hex(char *str, const void *bytes, int len);
+#endif
+
+#ifdef BCMDBG
+extern void deadbeef(void *p, uint len);
+#endif
+extern const char *bcm_crypto_algo_name(uint algo);
+extern char *bcm_chipname(uint chipid, char *buf, uint len);
+extern char *bcm_brev_str(uint32 brev, char *buf);
+extern void printbig(char *buf);
+extern void prhex(const char *msg, uchar *buf, uint len);
+
+extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen);
+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key);
+extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key);
+
+extern const char *bcmerrorstr(int bcmerror);
+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key);
+
+typedef uint32 mbool;
+#define mboolset(mb, bit) ((mb) |= (bit))
+#define mboolclr(mb, bit) ((mb) &= ~(bit))
+#define mboolisset(mb, bit) (((mb) & (bit)) != 0)
+#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
+
+struct fielddesc {
+ const char *nameandfmt;
+ uint32 offset;
+ uint32 len;
+};
+
+extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
+extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len);
+
+extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount);
+extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes);
+extern void bcm_print_bytes(const char *name, const uchar *cdata, int len);
+
+typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset);
+extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str,
+ char *buf, uint32 bufsize);
+extern uint BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint bytelength);
+
+extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
+
+extern uint16 BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm);
+extern uint8 BCMROMFN(bcm_mw_to_qdbm)(uint16 mw);
+extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len);
+
+unsigned int process_nvram_vars(char *varbuf, unsigned int len);
+
+extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c);
+
+extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
+
+#endif
diff --git a/src/include/epivers.h b/src/include/epivers.h
new file mode 100644
index 0000000..df6f248
--- /dev/null
+++ b/src/include/epivers.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $
+ *
+*/
+
+#ifndef _epivers_h_
+#define _epivers_h_
+
+#define EPI_MAJOR_VERSION 6
+
+#define EPI_MINOR_VERSION 30
+
+#define EPI_RC_NUMBER 223
+
+#define EPI_INCREMENTAL_NUMBER 271
+
+#define EPI_BUILD_NUMBER 0
+
+#define EPI_VERSION 6, 30, 223, 271
+
+#define EPI_VERSION_NUM 0x061edf10
+
+#define EPI_VERSION_DEV 6.30.223
+
+#define EPI_VERSION_STR "6.30.223.271 (r587334)"
+
+#endif
diff --git a/src/include/linux_osl.h b/src/include/linux_osl.h
new file mode 100644
index 0000000..bae45bb
--- /dev/null
+++ b/src/include/linux_osl.h
@@ -0,0 +1,338 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: linux_osl.h 383331 2013-02-06 10:27:24Z $
+ */
+
+#ifndef _linux_osl_h_
+#define _linux_osl_h_
+
+#include <typedefs.h>
+
+extern void * osl_os_open_image(char * filename);
+extern int osl_os_get_image_block(char * buf, int len, void * image);
+extern void osl_os_close_image(void * image);
+extern int osl_os_image_size(void *image);
+
+extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag);
+extern void osl_detach(osl_t *osh);
+
+extern uint32 g_assert_type;
+
+#if defined(BCMDBG_ASSERT)
+ #define ASSERT(exp) \
+ do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
+extern void osl_assert(const char *exp, const char *file, int line);
+#else
+ #ifdef __GNUC__
+ #define GCC_VERSION \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+ #if GCC_VERSION > 30100
+ #define ASSERT(exp) do {} while (0)
+ #else
+
+ #define ASSERT(exp)
+ #endif
+ #endif
+#endif
+
+#define OSL_DELAY(usec) osl_delay(usec)
+extern void osl_delay(uint usec);
+
+#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \
+ osl_pcmcia_read_attr((osh), (offset), (buf), (size))
+#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \
+ osl_pcmcia_write_attr((osh), (offset), (buf), (size))
+extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size);
+extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size);
+
+#define OSL_PCI_READ_CONFIG(osh, offset, size) \
+ osl_pci_read_config((osh), (offset), (size))
+#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \
+ osl_pci_write_config((osh), (offset), (size), (val))
+extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size);
+extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val);
+
+#define OSL_PCI_BUS(osh) osl_pci_bus(osh)
+#define OSL_PCI_SLOT(osh) osl_pci_slot(osh)
+extern uint osl_pci_bus(osl_t *osh);
+extern uint osl_pci_slot(osl_t *osh);
+extern struct pci_dev *osl_pci_device(osl_t *osh);
+
+typedef struct {
+ bool pkttag;
+ bool mmbus;
+ pktfree_cb_fn_t tx_fn;
+ void *tx_ctx;
+ void *unused[3];
+} osl_pubinfo_t;
+
+#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \
+ do { \
+ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \
+ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \
+ } while (0)
+
+#define BUS_SWAP32(v) (v)
+
+#ifdef BCMDBG_MEM
+ #define MALLOC(osh, size) osl_debug_malloc((osh), (size), __LINE__, __FILE__)
+ #define MFREE(osh, addr, size) osl_debug_mfree((osh), (addr), (size), __LINE__, __FILE__)
+ #define MALLOCED(osh) osl_malloced((osh))
+ #define MALLOC_DUMP(osh, b) osl_debug_memdump((osh), (b))
+ extern void *osl_debug_malloc(osl_t *osh, uint size, int line, const char* file);
+ extern void osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, const char* file);
+ extern uint osl_malloced(osl_t *osh);
+ struct bcmstrbuf;
+ extern int osl_debug_memdump(osl_t *osh, struct bcmstrbuf *b);
+#else
+ #define MALLOC(osh, size) osl_malloc((osh), (size))
+ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size))
+ #define MALLOCED(osh) osl_malloced((osh))
+ extern void *osl_malloc(osl_t *osh, uint size);
+ extern void osl_mfree(osl_t *osh, void *addr, uint size);
+ extern uint osl_malloced(osl_t *osh);
+#endif
+
+#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC)
+#define NATIVE_MFREE(osh, addr, size) kfree(addr)
+
+#define MALLOC_FAILED(osh) osl_malloc_failed((osh))
+extern uint osl_malloc_failed(osl_t *osh);
+
+#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align()
+#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \
+ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
+#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
+
+#define DMA_ALLOC_CONSISTENT_FORCE32(osh, size, align, tot, pap, dmah) \
+ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
+#define DMA_FREE_CONSISTENT_FORCE32(osh, va, size, pa, dmah) \
+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
+
+extern uint osl_dma_consistent_align(void);
+extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap);
+extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa);
+
+#define DMA_TX 1
+#define DMA_RX 2
+
+#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \
+ osl_dma_unmap((osh), (pa), (size), (direction))
+extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
+ hnddma_seg_map_t *txp_dmah);
+extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction);
+
+#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0)
+
+ #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op
+ #define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op
+
+#define OSL_ERROR(bcmerror) osl_error(bcmerror)
+extern int osl_error(int bcmerror);
+
+#define PKTBUFSZ 2048
+
+#if defined(LINUX_PORT)
+ #define printf(fmt, args...) printk(fmt , ## args)
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+
+ #define bcopy(src, dst, len) memcpy((dst), (src), (len))
+ #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
+ #define bzero(b, len) memset((b), '\0', (len))
+
+ extern int osl_printf(const char *format, ...);
+ extern int osl_sprintf(char *buf, const char *format, ...);
+ extern int osl_snprintf(char *buf, size_t n, const char *format, ...);
+ extern int osl_vsprintf(char *buf, const char *format, va_list ap);
+ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap);
+ extern int osl_strcmp(const char *s1, const char *s2);
+ extern int osl_strncmp(const char *s1, const char *s2, uint n);
+ extern int osl_strlen(const char *s);
+ extern char* osl_strcpy(char *d, const char *s);
+ extern char* osl_strncpy(char *d, const char *s, uint n);
+ extern char* osl_strchr(const char *s, int c);
+ extern char* osl_strrchr(const char *s, int c);
+ extern void *osl_memset(void *d, int c, size_t n);
+ extern void *osl_memcpy(void *d, const void *s, size_t n);
+ extern void *osl_memmove(void *d, const void *s, size_t n);
+ extern int osl_memcmp(const void *s1, const void *s2, size_t n);
+#else
+
+ #include <stdarg.h>
+ #include <stddef.h>
+ #undef printf
+ #undef sprintf
+ #undef snprintf
+ #undef vsprintf
+ #undef vsnprintf
+ #define printf(fmt, args...) osl_printf((fmt) , ## args)
+ #define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt) , ## args)
+ #define snprintf(buf, n, fmt, args...) osl_snprintf((buf), (n), (fmt) , ## args)
+ #define vsprintf(buf, fmt, ap) osl_vsprintf((buf), (fmt), (ap))
+ #define vsnprintf(buf, n, fmt, ap) osl_vsnprintf((buf), (n), (fmt), (ap))
+ extern int osl_printf(const char *format, ...);
+ extern int osl_sprintf(char *buf, const char *format, ...);
+ extern int osl_snprintf(char *buf, size_t n, const char *format, ...);
+ extern int osl_vsprintf(char *buf, const char *format, va_list ap);
+ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap);
+
+ #undef strcmp
+ #undef strncmp
+ #undef strlen
+ #undef strcpy
+ #undef strncpy
+ #undef strchr
+ #undef strrchr
+ #define strcmp(s1, s2) osl_strcmp((s1), (s2))
+ #define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n))
+ #define strlen(s) osl_strlen((s))
+ #define strcpy(d, s) osl_strcpy((d), (s))
+ #define strncpy(d, s, n) osl_strncpy((d), (s), (n))
+ #define strchr(s, c) osl_strchr((s), (c))
+ #define strrchr(s, c) osl_strrchr((s), (c))
+ extern int osl_strcmp(const char *s1, const char *s2);
+ extern int osl_strncmp(const char *s1, const char *s2, uint n);
+ extern int osl_strlen(const char *s);
+ extern char* osl_strcpy(char *d, const char *s);
+ extern char* osl_strncpy(char *d, const char *s, uint n);
+ extern char* osl_strchr(const char *s, int c);
+ extern char* osl_strrchr(const char *s, int c);
+
+ #undef memset
+ #undef memcpy
+ #undef memcmp
+ #define memset(d, c, n) osl_memset((d), (c), (n))
+ #define memcpy(d, s, n) osl_memcpy((d), (s), (n))
+ #define memmove(d, s, n) osl_memmove((d), (s), (n))
+ #define memcmp(s1, s2, n) osl_memcmp((s1), (s2), (n))
+ extern void *osl_memset(void *d, int c, size_t n);
+ extern void *osl_memcpy(void *d, const void *s, size_t n);
+ extern void *osl_memmove(void *d, const void *s, size_t n);
+ extern int osl_memcmp(const void *s1, const void *s2, size_t n);
+
+ #undef bcopy
+ #undef bcmp
+ #undef bzero
+ #define bcopy(src, dst, len) osl_memcpy((dst), (src), (len))
+ #define bcmp(b1, b2, len) osl_memcmp((b1), (b2), (len))
+ #define bzero(b, len) osl_memset((b), '\0', (len))
+#endif
+
+#define R_REG(osh, r) (\
+ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \
+ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \
+ osl_readl((volatile uint32*)(r)) \
+)
+#define W_REG(osh, r, v) do { \
+ switch (sizeof(*(r))) { \
+ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \
+ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \
+ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \
+ } \
+} while (0)
+
+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
+extern uint8 osl_readb(volatile uint8 *r);
+extern uint16 osl_readw(volatile uint16 *r);
+extern uint32 osl_readl(volatile uint32 *r);
+extern void osl_writeb(uint8 v, volatile uint8 *r);
+extern void osl_writew(uint16 v, volatile uint16 *r);
+extern void osl_writel(uint32 v, volatile uint32 *r);
+
+#define OSL_SYSUPTIME() osl_sysuptime()
+extern uint32 osl_sysuptime(void);
+
+#define OSL_UNCACHED(va) osl_uncached((va))
+extern void *osl_uncached(void *va);
+#define OSL_CACHED(va) osl_cached((va))
+extern void *osl_cached(void *va);
+
+#define OSL_PREF_RANGE_LD(va, sz)
+#define OSL_PREF_RANGE_ST(va, sz)
+
+#define OSL_GETCYCLES(x) ((x) = osl_getcycles())
+extern uint osl_getcycles(void);
+
+#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr))
+extern int osl_busprobe(uint32 *val, uint32 addr);
+
+#define REG_MAP(pa, size) osl_reg_map((pa), (size))
+#define REG_UNMAP(va) osl_reg_unmap((va))
+extern void *osl_reg_map(uint32 pa, uint size);
+extern void osl_reg_unmap(void *va);
+
+#define R_SM(r) *(r)
+#define W_SM(r, v) (*(r) = (v))
+#define BZERO_SM(r, len) bzero((r), (len))
+
+#define PKTGET(osh, len, send) osl_pktget((osh), (len))
+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb))
+#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative((osh), (skb))
+#define PKTLIST_DUMP(osh, buf)
+#define PKTDBG_TRACE(osh, pkt, bit)
+#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send))
+#define PKTDATA(osh, skb) osl_pktdata((osh), (skb))
+#define PKTLEN(osh, skb) osl_pktlen((osh), (skb))
+#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb))
+#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb))
+#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb))
+#define PKTSETNEXT(osh, skb, x) osl_pktsetnext((skb), (x))
+#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len))
+#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes))
+#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes))
+#define PKTTAG(skb) osl_pkttag((skb))
+#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osh), (pkt))
+#define PKTLINK(skb) osl_pktlink((skb))
+#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x))
+#define PKTPRIO(skb) osl_pktprio((skb))
+#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x))
+#define PKTSHARED(skb) osl_pktshared((skb))
+#define PKTSETPOOL(osh, skb, x, y) do {} while (0)
+#define PKTPOOL(osh, skb) FALSE
+
+extern void *osl_pktget(osl_t *osh, uint len);
+extern void *osl_pktdup(osl_t *osh, void *skb);
+extern void *osl_pkt_frmnative(osl_t *osh, void *skb);
+extern void osl_pktfree(osl_t *osh, void *skb, bool send);
+extern uchar *osl_pktdata(osl_t *osh, void *skb);
+extern uint osl_pktlen(osl_t *osh, void *skb);
+extern uint osl_pktheadroom(osl_t *osh, void *skb);
+extern uint osl_pkttailroom(osl_t *osh, void *skb);
+extern void *osl_pktnext(osl_t *osh, void *skb);
+extern void osl_pktsetnext(void *skb, void *x);
+extern void osl_pktsetlen(osl_t *osh, void *skb, uint len);
+extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes);
+extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes);
+extern void *osl_pkttag(void *skb);
+extern void *osl_pktlink(void *skb);
+extern void osl_pktsetlink(void *skb, void *x);
+extern uint osl_pktprio(void *skb);
+extern void osl_pktsetprio(void *skb, uint x);
+extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt);
+extern bool osl_pktshared(void *skb);
+
+#define PKTALLOCED(osh) osl_pktalloced(osh)
+extern uint osl_pktalloced(osl_t *osh);
+
+#define DMA_MAP(osh, va, size, direction, p, dmah) \
+ osl_dma_map((osh), (va), (size), (direction), (p), (dmah))
+
+#endif
diff --git a/src/include/linuxver.h b/src/include/linuxver.h
new file mode 100644
index 0000000..b05bc32
--- /dev/null
+++ b/src/include/linuxver.h
@@ -0,0 +1,594 @@
+/*
+ * Linux-specific abstractions to gain some independence from linux kernel versions.
+ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: linuxver.h 372519 2012-12-04 01:21:16Z $
+ */
+
+#ifndef _linuxver_h_
+#define _linuxver_h_
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+#include <linux/config.h>
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+#include <generated/autoconf.h>
+#else
+#include <linux/autoconf.h>
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
+#include <linux/kconfig.h>
+#endif
+
+#include <linux/module.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
+
+#ifdef __UNDEF_NO_VERSION__
+#undef __NO_VERSION__
+#else
+#define __NO_VERSION__
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i")
+#define module_param_string(_name_, _string_, _size_, _perm_) \
+ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9))
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+#undef IP_TOS
+#endif
+#include <asm/io.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41))
+#include <linux/workqueue.h>
+#else
+#include <linux/tqueue.h>
+#ifndef work_struct
+#define work_struct tq_struct
+#endif
+#ifndef INIT_WORK
+#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data))
+#endif
+#ifndef schedule_work
+#define schedule_work(_work) schedule_task((_work))
+#endif
+#ifndef flush_scheduled_work
+#define flush_scheduled_work() flush_scheduled_tasks()
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define DAEMONIZE(a) daemonize(a); \
+ allow_signal(SIGKILL); \
+ allow_signal(SIGTERM);
+#else
+#define RAISE_RX_SOFTIRQ() \
+ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
+#define DAEMONIZE(a) daemonize(); \
+ do { if (a) \
+ strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a)))); \
+ } while (0);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func)
+#else
+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work)
+#if !(LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18) && defined(RHEL_MAJOR) && \
+ (RHEL_MAJOR == 5))
+
+typedef void (*work_func_t)(void *work);
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+
+#ifndef IRQ_NONE
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#define IRQ_RETVAL(x)
+#endif
+#else
+typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#define IRQF_SHARED SA_SHIRQ
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67)
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+#include <linux/sched.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#include <net/lib80211.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#include <linux/ieee80211.h>
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#include <net/ieee80211.h>
+#endif
+#endif
+
+#ifdef CUSTOMER_HW4
+#include <linux/kthread.h>
+#endif
+
+#ifndef __exit
+#define __exit
+#endif
+#ifndef __devexit
+#define __devexit
+#endif
+#ifndef __devinit
+#define __devinit __init
+#endif
+#ifndef __devinitdata
+#define __devinitdata
+#endif
+#ifndef __devexit_p
+#define __devexit_p(x) x
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
+
+#define pci_get_drvdata(dev) (dev)->sysdata
+#define pci_set_drvdata(dev, value) (dev)->sysdata = (value)
+
+struct pci_device_id {
+ unsigned int vendor, device;
+ unsigned int subvendor, subdevice;
+ unsigned int class, class_mask;
+ unsigned long driver_data;
+};
+
+struct pci_driver {
+ struct list_head node;
+ char *name;
+ const struct pci_device_id *id_table;
+ int (*probe)(struct pci_dev *dev,
+ const struct pci_device_id *id);
+ void (*remove)(struct pci_dev *dev);
+ void (*suspend)(struct pci_dev *dev);
+ void (*resume)(struct pci_dev *dev);
+};
+
+#define MODULE_DEVICE_TABLE(type, name)
+#define PCI_ANY_ID (~0)
+
+#define pci_module_init pci_register_driver
+extern int pci_register_driver(struct pci_driver *drv);
+extern void pci_unregister_driver(struct pci_driver *drv);
+
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
+#define pci_module_init pci_register_driver
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18))
+#define module_init(x) __initcall(x);
+#define module_exit(x) __exitcall(x);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+#define WL_USE_NETDEV_OPS
+#else
+#undef WL_USE_NETDEV_OPS
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL)
+#define WL_CONFIG_RFKILL
+#else
+#undef WL_CONFIG_RFKILL
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48))
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13))
+#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)])
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44))
+#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23))
+#define pci_enable_device(dev) do { } while (0)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14))
+#define net_device device
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42))
+
+#ifndef PCI_DMA_TODEVICE
+#define PCI_DMA_TODEVICE 1
+#define PCI_DMA_FROMDEVICE 2
+#endif
+
+typedef u32 dma_addr_t;
+
+static inline int get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *ret;
+ int gfp = GFP_ATOMIC | GFP_DMA;
+
+ ret = (void *)__get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ return ret;
+}
+static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(cookie, address, size, dir)
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43))
+
+#define dev_kfree_skb_any(a) dev_kfree_skb(a)
+#define netif_down(dev) do { (dev)->start = 0; } while (0)
+
+#ifndef _COMPAT_NETDEVICE_H
+
+#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
+#define netif_wake_queue(dev) \
+ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0)
+#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy)
+
+static inline void netif_start_queue(struct net_device *dev)
+{
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+}
+
+#define netif_queue_stopped(dev) (dev)->tbusy
+#define netif_running(dev) (dev)->start
+
+#endif
+
+#define netif_device_attach(dev) netif_start_queue(dev)
+#define netif_device_detach(dev) netif_stop_queue(dev)
+
+#define tasklet_struct tq_struct
+static inline void tasklet_schedule(struct tasklet_struct *tasklet)
+{
+ queue_task(tasklet, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+static inline void tasklet_init(struct tasklet_struct *tasklet,
+ void (*func)(unsigned long),
+ unsigned long data)
+{
+ tasklet->next = NULL;
+ tasklet->sync = 0;
+ tasklet->routine = (void (*)(void *))func;
+ tasklet->data = (void *)data;
+}
+#define tasklet_kill(tasklet) { do {} while (0); }
+
+#define del_timer_sync(timer) del_timer(timer)
+
+#else
+
+#define netif_down(dev)
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3))
+
+#define PREPARE_TQUEUE(_tq, _routine, _data) \
+ do { \
+ (_tq)->routine = _routine; \
+ (_tq)->data = _data; \
+ } while (0)
+
+#define INIT_TQUEUE(_tq, _routine, _data) \
+ do { \
+ INIT_LIST_HEAD(&(_tq)->list); \
+ (_tq)->sync = 0; \
+ PREPARE_TQUEUE((_tq), (_routine), (_data)); \
+ } while (0)
+
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9)
+#define PCI_SAVE_STATE(a, b) pci_save_state(a)
+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a)
+#else
+#define PCI_SAVE_STATE(a, b) pci_save_state(a, b)
+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6))
+static inline int
+pci_save_state(struct pci_dev *dev, u32 *buffer)
+{
+ int i;
+ if (buffer) {
+ for (i = 0; i < 16; i++)
+ pci_read_config_dword(dev, i * 4, &buffer[i]);
+ }
+ return 0;
+}
+
+static inline int
+pci_restore_state(struct pci_dev *dev, u32 *buffer)
+{
+ int i;
+
+ if (buffer) {
+ for (i = 0; i < 16; i++)
+ pci_write_config_dword(dev, i * 4, buffer[i]);
+ }
+
+ else {
+ for (i = 0; i < 6; i ++)
+ pci_write_config_dword(dev,
+ PCI_BASE_ADDRESS_0 + (i * 4),
+ pci_resource_start(dev, i));
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+ return 0;
+}
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19))
+#define read_c0_count() read_32bit_cp0_register(CP0_COUNT)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#ifndef SET_MODULE_OWNER
+#define SET_MODULE_OWNER(dev) do {} while (0)
+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#else
+#define OLD_MOD_INC_USE_COUNT do {} while (0)
+#define OLD_MOD_DEC_USE_COUNT do {} while (0)
+#endif
+#else
+#ifndef SET_MODULE_OWNER
+#define SET_MODULE_OWNER(dev) do {} while (0)
+#endif
+#ifndef MOD_INC_USE_COUNT
+#define MOD_INC_USE_COUNT do {} while (0)
+#endif
+#ifndef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT do {} while (0)
+#endif
+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#endif
+
+#ifndef SET_NETDEV_DEV
+#define SET_NETDEV_DEV(net, pdev) do {} while (0)
+#endif
+
+#ifndef HAVE_FREE_NETDEV
+#define free_netdev(dev) kfree(dev)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+
+#define af_packet_priv data
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+#define DRV_SUSPEND_STATE_TYPE pm_message_t
+#else
+#define DRV_SUSPEND_STATE_TYPE uint32
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+#define CHECKSUM_HW CHECKSUM_PARTIAL
+#endif
+
+typedef struct {
+ void *parent;
+ struct task_struct *p_task;
+ long thr_pid;
+ int prio;
+ struct semaphore sema;
+ int terminated;
+ struct completion completed;
+} tsk_ctl_t;
+
+#define DBG_THR(x)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x)
+#else
+#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x)
+#endif
+
+#define PROC_START(thread_func, owner, tsk_ctl, flags) \
+{ \
+ sema_init(&((tsk_ctl)->sema), 0); \
+ init_completion(&((tsk_ctl)->completed)); \
+ (tsk_ctl)->parent = owner; \
+ (tsk_ctl)->terminated = FALSE; \
+ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \
+ if ((tsk_ctl)->thr_pid > 0) \
+ wait_for_completion(&((tsk_ctl)->completed)); \
+ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
+}
+
+#ifdef USE_KTHREAD_API
+#define PROC_START2(thread_func, owner, tsk_ctl, flags, name) \
+{ \
+ sema_init(&((tsk_ctl)->sema), 0); \
+ init_completion(&((tsk_ctl)->completed)); \
+ (tsk_ctl)->parent = owner; \
+ (tsk_ctl)->terminated = FALSE; \
+ (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \
+ (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \
+ DBG_THR(("%s thr:%lx created\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
+}
+#endif
+
+#define PROC_STOP(tsk_ctl) \
+{ \
+ (tsk_ctl)->terminated = TRUE; \
+ smp_wmb(); \
+ up(&((tsk_ctl)->sema)); \
+ wait_for_completion(&((tsk_ctl)->completed)); \
+ DBG_THR(("%s thr:%lx terminated OK\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
+ (tsk_ctl)->thr_pid = -1; \
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+#define KILL_PROC(nr, sig) \
+{ \
+struct task_struct *tsk; \
+struct pid *pid; \
+pid = find_get_pid((pid_t)nr); \
+tsk = pid_task(pid, PIDTYPE_PID); \
+if (tsk) send_sig(sig, tsk, 1); \
+}
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(2, 6, 30))
+#define KILL_PROC(pid, sig) \
+{ \
+ struct task_struct *tsk; \
+ tsk = find_task_by_vpid(pid); \
+ if (tsk) send_sig(sig, tsk, 1); \
+}
+#else
+#define KILL_PROC(pid, sig) \
+{ \
+ kill_proc(pid, sig, 1); \
+}
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#include <linux/time.h>
+#include <linux/wait.h>
+#else
+#include <linux/sched.h>
+
+#define __wait_event_interruptible_timeout(wq, condition, ret) \
+do { \
+ wait_queue_t __wait; \
+ init_waitqueue_entry(&__wait, current); \
+ \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ set_current_state(TASK_INTERRUPTIBLE); \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ ret = schedule_timeout(ret); \
+ if (!ret) \
+ break; \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) \
+ __wait_event_interruptible_timeout(wq, condition, __ret); \
+ __ret; \
+})
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#define DEV_PRIV(dev) (dev->priv)
+#else
+#define DEV_PRIV(dev) netdev_priv(dev)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+#define WL_ISR(i, d, p) wl_isr((i), (d))
+#else
+#define WL_ISR(i, d, p) wl_isr((i), (d), (p))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+#define netdev_priv(dev) dev->priv
+#endif
+
+#endif
diff --git a/src/include/osl.h b/src/include/osl.h
new file mode 100644
index 0000000..407b257
--- /dev/null
+++ b/src/include/osl.h
@@ -0,0 +1,132 @@
+/*
+ * OS Abstraction Layer
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: osl.h 431503 2013-10-23 21:42:47Z $
+ */
+
+#ifndef _osl_h_
+#define _osl_h_
+
+typedef struct osl_info osl_t;
+typedef struct osl_dmainfo osldma_t;
+
+#define OSL_PKTTAG_SZ 32
+
+typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status);
+
+typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size);
+typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size);
+
+#ifdef __mips__
+#define PREF_LOAD 0
+#define PREF_STORE 1
+#define PREF_LOAD_STREAMED 4
+#define PREF_STORE_STREAMED 5
+#define PREF_LOAD_RETAINED 6
+#define PREF_STORE_RETAINED 7
+#define PREF_WBACK_INV 25
+#define PREF_PREPARE4STORE 30
+
+#define MAKE_PREFETCH_FN(hint) \
+static inline void prefetch_##hint(const void *addr) \
+{ \
+ __asm__ __volatile__(\
+ " .set mips4 \n" \
+ " pref %0, (%1) \n" \
+ " .set mips0 \n" \
+ : \
+ : "i" (hint), "r" (addr)); \
+}
+
+#define MAKE_PREFETCH_RANGE_FN(hint) \
+static inline void prefetch_range_##hint(const void *addr, int len) \
+{ \
+ int size = len; \
+ while (size > 0) { \
+ prefetch_##hint(addr); \
+ size -= 32; \
+ } \
+}
+
+MAKE_PREFETCH_FN(PREF_LOAD)
+MAKE_PREFETCH_RANGE_FN(PREF_LOAD)
+MAKE_PREFETCH_FN(PREF_STORE)
+MAKE_PREFETCH_RANGE_FN(PREF_STORE)
+MAKE_PREFETCH_FN(PREF_LOAD_STREAMED)
+MAKE_PREFETCH_RANGE_FN(PREF_LOAD_STREAMED)
+MAKE_PREFETCH_FN(PREF_STORE_STREAMED)
+MAKE_PREFETCH_RANGE_FN(PREF_STORE_STREAMED)
+MAKE_PREFETCH_FN(PREF_LOAD_RETAINED)
+MAKE_PREFETCH_RANGE_FN(PREF_LOAD_RETAINED)
+MAKE_PREFETCH_FN(PREF_STORE_RETAINED)
+MAKE_PREFETCH_RANGE_FN(PREF_STORE_RETAINED)
+#endif
+
+#include <linux_osl.h>
+
+#ifndef PKTDBG_TRACE
+#define PKTDBG_TRACE(osh, pkt, bit)
+#endif
+
+#define PKTCTFMAP(osh, p)
+
+#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val)))
+
+#ifndef AND_REG
+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
+#endif
+
+#ifndef OR_REG
+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
+#endif
+
+#if !defined(OSL_SYSUPTIME)
+#define OSL_SYSUPTIME() (0)
+#define OSL_SYSUPTIME_SUPPORT FALSE
+#else
+#define OSL_SYSUPTIME_SUPPORT TRUE
+#endif
+
+#if !defined(PKTC_DONGLE)
+#define PKTCGETATTR(s) (0)
+#define PKTCSETATTR(skb, f, p, b)
+#define PKTCCLRATTR(skb)
+#define PKTCCNT(skb) (1)
+#define PKTCLEN(skb) PKTLEN(NULL, skb)
+#define PKTCGETFLAGS(skb) (0)
+#define PKTCSETFLAGS(skb, f)
+#define PKTCCLRFLAGS(skb)
+#define PKTCFLAGS(skb) (0)
+#define PKTCSETCNT(skb, c)
+#define PKTCINCRCNT(skb)
+#define PKTCADDCNT(skb, c)
+#define PKTCSETLEN(skb, l)
+#define PKTCADDLEN(skb, l)
+#define PKTCSETFLAG(skb, fb)
+#define PKTCCLRFLAG(skb, fb)
+#define PKTCLINK(skb) NULL
+#define PKTSETCLINK(skb, x)
+#define FOREACH_CHAINED_PKT(skb, nskb) \
+ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb))
+#define PKTCFREE PKTFREE
+#endif
+
+#define PKTSETCHAINED(osh, skb)
+#define PKTCLRCHAINED(osh, skb)
+#define PKTISCHAINED(skb) (FALSE)
+
+#endif
diff --git a/src/include/packed_section_end.h b/src/include/packed_section_end.h
new file mode 100644
index 0000000..8a98795
--- /dev/null
+++ b/src/include/packed_section_end.h
@@ -0,0 +1,41 @@
+/*
+ * Declare directives for structure packing. No padding will be provided
+ * between the members of packed structures, and therefore, there is no
+ * guarantee that structure members will be aligned.
+ *
+ * Declaring packed structures is compiler specific. In order to handle all
+ * cases, packed structures should be delared as:
+ *
+ * #include <packed_section_start.h>
+ *
+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
+ * some_struct_members;
+ * } BWL_POST_PACKED_STRUCT foobar_t;
+ *
+ * #include <packed_section_end.h>
+ *
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * $Id: packed_section_end.h 395414 2013-04-07 19:26:09Z $
+ */
+
+#ifdef BWL_PACKED_SECTION
+ #undef BWL_PACKED_SECTION
+#else
+ #error "BWL_PACKED_SECTION is NOT defined!"
+#endif
+
+#undef BWL_PRE_PACKED_STRUCT
+#undef BWL_POST_PACKED_STRUCT
diff --git a/src/include/packed_section_start.h b/src/include/packed_section_start.h
new file mode 100644
index 0000000..4922850
--- /dev/null
+++ b/src/include/packed_section_start.h
@@ -0,0 +1,48 @@
+/*
+ * Declare directives for structure packing. No padding will be provided
+ * between the members of packed structures, and therefore, there is no
+ * guarantee that structure members will be aligned.
+ *
+ * Declaring packed structures is compiler specific. In order to handle all
+ * cases, packed structures should be delared as:
+ *
+ * #include <packed_section_start.h>
+ *
+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
+ * some_struct_members;
+ * } BWL_POST_PACKED_STRUCT foobar_t;
+ *
+ * #include <packed_section_end.h>
+ *
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * $Id: packed_section_start.h 395414 2013-04-07 19:26:09Z $
+ */
+
+#ifdef BWL_PACKED_SECTION
+ #error "BWL_PACKED_SECTION is already defined!"
+#else
+ #define BWL_PACKED_SECTION
+#endif
+
+#if defined(__GNUC__) || defined(__lint)
+ #define BWL_PRE_PACKED_STRUCT
+ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed))
+#elif defined(__CC_ARM)
+ #define BWL_PRE_PACKED_STRUCT __packed
+ #define BWL_POST_PACKED_STRUCT
+#else
+ #error "Unknown compiler!"
+#endif
diff --git a/src/include/pcicfg.h b/src/include/pcicfg.h
new file mode 100644
index 0000000..784b56f
--- /dev/null
+++ b/src/include/pcicfg.h
@@ -0,0 +1,83 @@
+/*
+ * pcicfg.h: PCI configuration constants and structures.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: pcicfg.h 392809 2013-03-24 22:49:08Z $
+ */
+
+#ifndef _h_pcicfg_
+#define _h_pcicfg_
+
+#define PCI_CFG_VID 0
+#define PCI_CFG_DID 2
+#define PCI_CFG_CMD 4
+#define PCI_CFG_STAT 6
+#define PCI_CFG_REV 8
+#define PCI_CFG_PROGIF 9
+#define PCI_CFG_SUBCL 0xa
+#define PCI_CFG_BASECL 0xb
+#define PCI_CFG_CLSZ 0xc
+#define PCI_CFG_LATTIM 0xd
+#define PCI_CFG_HDR 0xe
+#define PCI_CFG_BIST 0xf
+#define PCI_CFG_BAR0 0x10
+#define PCI_CFG_BAR1 0x14
+#define PCI_CFG_BAR2 0x18
+#define PCI_CFG_BAR3 0x1c
+#define PCI_CFG_BAR4 0x20
+#define PCI_CFG_BAR5 0x24
+#define PCI_CFG_CIS 0x28
+#define PCI_CFG_SVID 0x2c
+#define PCI_CFG_SSID 0x2e
+#define PCI_CFG_ROMBAR 0x30
+#define PCI_CFG_CAPPTR 0x34
+#define PCI_CFG_INT 0x3c
+#define PCI_CFG_PIN 0x3d
+#define PCI_CFG_MINGNT 0x3e
+#define PCI_CFG_MAXLAT 0x3f
+#define PCI_CFG_DEVCTRL 0xd8
+#define PCI_BAR0_WIN 0x80
+#define PCI_BAR1_WIN 0x84
+#define PCI_SPROM_CONTROL 0x88
+#define PCI_BAR1_CONTROL 0x8c
+#define PCI_INT_STATUS 0x90
+#define PCI_INT_MASK 0x94
+#define PCI_TO_SB_MB 0x98
+#define PCI_BACKPLANE_ADDR 0xa0
+#define PCI_BACKPLANE_DATA 0xa4
+#define PCI_CLK_CTL_ST 0xa8
+#define PCI_BAR0_WIN2 0xac
+#define PCI_GPIO_IN 0xb0
+#define PCI_GPIO_OUT 0xb4
+#define PCI_GPIO_OUTEN 0xb8
+
+#define PCI_BAR0_SHADOW_OFFSET (2 * 1024)
+#define PCI_BAR0_SPROM_OFFSET (4 * 1024)
+#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024)
+#define PCI_BAR0_PCISBR_OFFSET (4 * 1024)
+
+#define PCIE2_BAR0_WIN2 0x70
+#define PCIE2_BAR0_CORE2_WIN 0x74
+#define PCIE2_BAR0_CORE2_WIN2 0x78
+
+#define PCI_BAR0_WINSZ (16 * 1024)
+
+#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024)
+#define PCI_16KB0_CCREGS_OFFSET (12 * 1024)
+#define PCI_16KBB0_WINSZ (16 * 1024)
+
+#define PCI_CONFIG_SPACE_SIZE 256
+#endif
diff --git a/src/include/siutils.h b/src/include/siutils.h
new file mode 100644
index 0000000..fad8f62
--- /dev/null
+++ b/src/include/siutils.h
@@ -0,0 +1,409 @@
+/*
+ * Misc utility routines for accessing the SOC Interconnects
+ * of Broadcom HNBU chips.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: siutils.h 434387 2013-11-06 04:50:08Z $
+ */
+
+#ifndef _siutils_h_
+#define _siutils_h_
+
+#include <bcmutils.h>
+
+struct si_pub {
+ uint socitype;
+
+ uint bustype;
+ uint buscoretype;
+ uint buscorerev;
+ uint buscoreidx;
+ int ccrev;
+ uint32 cccaps;
+ uint32 cccaps_ext;
+ int pmurev;
+ uint32 pmucaps;
+ uint boardtype;
+ uint boardrev;
+ uint boardvendor;
+ uint boardflags;
+ uint boardflags2;
+ uint chip;
+ uint chiprev;
+ uint chippkg;
+ uint32 chipst;
+ bool issim;
+ uint socirev;
+ bool pci_pr32414;
+
+#ifdef SI_ENUM_BASE_VARIABLE
+ uint32 si_enum_base;
+#endif
+};
+
+typedef const struct si_pub si_t;
+
+#ifdef ATE_BUILD
+typedef struct _ate_params {
+ void* wl;
+ uint8 gpio_input;
+ uint8 gpio_output;
+ bool cmd_proceed;
+ uint16 cmd_idx;
+ bool ate_cmd_done;
+} ate_params_t;
+#endif
+
+#define SI_OSH NULL
+
+#define BADIDX (SI_MAXCORES + 1)
+
+#define XTAL 0x1
+#define PLL 0x2
+
+#define CLK_FAST 0
+#define CLK_DYNAMIC 2
+
+#define GPIO_DRV_PRIORITY 0
+#define GPIO_APP_PRIORITY 1
+#define GPIO_HI_PRIORITY 2
+
+#define GPIO_PULLUP 0
+#define GPIO_PULLDN 1
+
+#define GPIO_REGEVT 0
+#define GPIO_REGEVT_INTMSK 1
+#define GPIO_REGEVT_INTPOL 2
+
+#define SI_DEVPATH_BUFSZ 16
+
+#define SI_DOATTACH 1
+#define SI_PCIDOWN 2
+#define SI_PCIUP 3
+
+#define ISSIM_ENAB(sih) FALSE
+
+#if defined(BCMPMUCTL)
+#define PMUCTL_ENAB(sih) (BCMPMUCTL)
+#else
+#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU)
+#endif
+
+#if defined(BCMPMUCTL) && BCMPMUCTL
+#define CCCTL_ENAB(sih) (0)
+#define CCPLL_ENAB(sih) (0)
+#else
+#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL)
+#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK)
+#endif
+
+typedef void (*gpio_handler_t)(uint32 stat, void *arg);
+
+#define CC_BTCOEX_EN_MASK 0x01
+
+#define GPIO_CTRL_EPA_EN_MASK 0x40
+
+#define GPIO_CTRL_5_6_EN_MASK 0x60
+#define GPIO_CTRL_7_6_EN_MASK 0xC0
+#define GPIO_OUT_7_EN_MASK 0x80
+
+#define SI_CR4_CAP (0x04)
+#define SI_CR4_BANKIDX (0x40)
+#define SI_CR4_BANKINFO (0x44)
+
+#define ARMCR4_TCBBNB_MASK 0xf0
+#define ARMCR4_TCBBNB_SHIFT 4
+#define ARMCR4_TCBANB_MASK 0xf
+#define ARMCR4_TCBANB_SHIFT 0
+
+#define SICF_CPUHALT (0x0020)
+#define ARMCR4_BSZ_MASK 0x3f
+#define ARMCR4_BSZ_MULT 8192
+
+extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype,
+ void *sdh, char **vars, uint *varsz);
+extern si_t *si_kattach(osl_t *osh);
+extern void si_detach(si_t *sih);
+extern bool si_pci_war16165(si_t *sih);
+
+extern uint si_corelist(si_t *sih, uint coreid[]);
+extern uint si_coreid(si_t *sih);
+extern uint si_flag(si_t *sih);
+extern uint si_flag_alt(si_t *sih);
+extern uint si_intflag(si_t *sih);
+extern uint si_coreidx(si_t *sih);
+extern uint si_coreunit(si_t *sih);
+extern uint si_corevendor(si_t *sih);
+extern uint si_corerev(si_t *sih);
+extern void *si_osh(si_t *sih);
+extern void si_setosh(si_t *sih, osl_t *osh);
+extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
+extern void *si_coreregs(si_t *sih);
+extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val);
+extern void *si_wrapperregs(si_t *sih);
+extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val);
+extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val);
+extern bool si_iscoreup(si_t *sih);
+extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit);
+extern void *si_setcoreidx(si_t *sih, uint coreidx);
+extern void *si_setcore(si_t *sih, uint coreid, uint coreunit);
+extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val);
+extern void si_restore_core(si_t *sih, uint coreid, uint intr_val);
+extern int si_numaddrspaces(si_t *sih);
+extern uint32 si_addrspace(si_t *sih, uint asidx);
+extern uint32 si_addrspacesize(si_t *sih, uint asidx);
+extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size);
+extern int si_corebist(si_t *sih);
+extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
+extern void si_core_disable(si_t *sih, uint32 bits);
+extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m);
+extern uint si_chip_hostif(si_t *sih);
+extern bool si_read_pmu_autopll(si_t *sih);
+extern uint32 si_clock(si_t *sih);
+extern uint32 si_alp_clock(si_t *sih);
+extern uint32 si_ilp_clock(si_t *sih);
+extern void si_pci_setup(si_t *sih, uint coremask);
+extern void si_pcmcia_init(si_t *sih);
+extern void si_setint(si_t *sih, int siflag);
+extern bool si_backplane64(si_t *sih);
+extern void si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
+ void *intrsenabled_fn, void *intr_arg);
+extern void si_deregister_intr_callback(si_t *sih);
+extern void si_clkctl_init(si_t *sih);
+extern uint16 si_clkctl_fast_pwrup_delay(si_t *sih);
+extern bool si_clkctl_cc(si_t *sih, uint mode);
+extern int si_clkctl_xtal(si_t *sih, uint what, bool on);
+extern uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 val);
+extern void si_btcgpiowar(si_t *sih);
+extern bool si_deviceremoved(si_t *sih);
+extern uint32 si_socram_size(si_t *sih);
+extern uint32 si_socdevram_size(si_t *sih);
+extern void si_socdevram(si_t *sih, bool set, uint8 *ennable, uint8 *protect, uint8 *remap);
+extern bool si_socdevram_pkg(si_t *sih);
+extern bool si_socdevram_remap_isenb(si_t *sih);
+extern uint32 si_socdevram_remap_size(si_t *sih);
+
+extern void si_watchdog(si_t *sih, uint ticks);
+extern void si_watchdog_ms(si_t *sih, uint32 ms);
+extern uint32 si_watchdog_msticks(void);
+extern void *si_gpiosetcore(si_t *sih);
+extern uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioin(si_t *sih);
+extern uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_gpioreserve(si_t *sih, uint32 gpio_num, uint8 priority);
+extern uint32 si_gpiorelease(si_t *sih, uint32 gpio_num, uint8 priority);
+extern uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val);
+extern uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val);
+extern uint32 si_gpio_int_enable(si_t *sih, bool enable);
+
+extern void *si_gpio_handler_register(si_t *sih, uint32 e, bool lev, gpio_handler_t cb, void *arg);
+extern void si_gpio_handler_unregister(si_t *sih, void* gpioh);
+extern void si_gpio_handler_process(si_t *sih);
+
+extern bool si_pci_pmecap(si_t *sih);
+struct osl_info;
+extern bool si_pci_fastpmecap(struct osl_info *osh);
+extern bool si_pci_pmestat(si_t *sih);
+extern void si_pci_pmeclr(si_t *sih);
+extern void si_pci_pmeen(si_t *sih);
+extern void si_pci_pmestatclr(si_t *sih);
+extern uint si_pcie_readreg(void *sih, uint addrtype, uint offset);
+extern uint si_pcie_writereg(void *sih, uint addrtype, uint offset, uint val);
+
+extern uint16 si_d11_devid(si_t *sih);
+extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
+ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, uint8 *pciheader);
+
+#if defined(BCMECICOEX)
+extern bool si_eci(si_t *sih);
+extern int si_eci_init(si_t *sih);
+extern void si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt);
+extern bool si_seci(si_t *sih);
+extern void* si_seci_init(si_t *sih, uint8 seci_mode);
+extern void* si_gci_init(si_t *sih);
+extern void si_seci_down(si_t *sih);
+extern void si_seci_upd(si_t *sih, bool enable);
+extern bool si_gci(si_t *sih);
+#else
+#define si_eci(sih) 0
+static INLINE void * si_eci_init(si_t *sih) {return NULL;}
+#define si_eci_notify_bt(sih, type, val) (0)
+#define si_seci(sih) 0
+#define si_seci_upd(sih, a) do {} while (0)
+static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;}
+static INLINE void * si_gci_init(si_t *sih) {return NULL;}
+#define si_seci_down(sih) do {} while (0)
+#define si_gci(sih) 0
+#endif
+
+extern bool si_is_otp_disabled(si_t *sih);
+extern bool si_is_otp_powered(si_t *sih);
+extern void si_otp_power(si_t *sih, bool on);
+
+extern bool si_is_sprom_available(si_t *sih);
+extern bool si_is_sprom_enabled(si_t *sih);
+extern void si_sprom_enable(si_t *sih, bool enable);
+#ifdef SI_SPROM_PROBE
+extern void si_sprom_init(si_t *sih);
+#endif
+
+extern int si_cis_source(si_t *sih);
+#define CIS_DEFAULT 0
+#define CIS_SROM 1
+#define CIS_OTP 2
+
+#define DEFAULT_FAB 0x0
+#define CSM_FAB7 0x1
+#define TSMC_FAB12 0x2
+#define SMIC_FAB4 0x3
+
+extern int BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw);
+extern uint16 BCMATTACHFN(si_fabid)(si_t *sih);
+
+extern int si_devpath(si_t *sih, char *path, int size);
+
+extern char *si_getdevpathvar(si_t *sih, const char *name);
+extern int si_getdevpathintvar(si_t *sih, const char *name);
+extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name);
+
+extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val);
+extern uint8 si_pcieltrenable(si_t *sih, uint32 mask, uint32 val);
+extern uint8 si_pcieobffenable(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcieltr_reg(si_t *sih, uint32 reg, uint32 mask, uint32 val);
+extern uint32 si_pcieltrspacing_reg(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcieltrhysteresiscnt_reg(si_t *sih, uint32 mask, uint32 val);
+extern void si_pcie_set_error_injection(si_t *sih, uint32 mode);
+extern void si_pcie_set_L1substate(si_t *sih, uint32 substate);
+extern uint32 si_pcie_get_L1substate(si_t *sih);
+extern void si_war42780_clkreq(si_t *sih, bool clkreq);
+extern void si_pci_down(si_t *sih);
+extern void si_pci_up(si_t *sih);
+extern void si_pci_sleep(si_t *sih);
+extern void si_pcie_war_ovr_update(si_t *sih, uint8 aspm);
+extern void si_pcie_power_save_enable(si_t *sih, bool enable);
+extern void si_pcie_extendL1timer(si_t *sih, bool extend);
+extern int si_pci_fixcfg(si_t *sih);
+extern bool si_ldo_war(si_t *sih, uint devid);
+extern void si_chippkg_set(si_t *sih, uint);
+
+extern void si_chipcontrl_btshd0_4331(si_t *sih, bool on);
+extern void si_chipcontrl_restore(si_t *sih, uint32 val);
+extern uint32 si_chipcontrl_read(si_t *sih);
+extern void si_chipcontrl_epa4331(si_t *sih, bool on);
+extern void si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl);
+extern void si_chipcontrl_srom4360(si_t *sih, bool on);
+
+extern void si_epa_4313war(si_t *sih);
+extern void si_btc_enable_chipcontrol(si_t *sih);
+
+extern void si_btcombo_p250_4313_war(si_t *sih);
+extern void si_btcombo_43228_war(si_t *sih);
+extern void si_clk_pmu_htavail_set(si_t *sih, bool set_clear);
+extern void si_pmu_synth_pwrsw_4313_war(si_t *sih);
+extern uint si_pll_reset(si_t *sih);
+
+extern bool si_taclear(si_t *sih, bool details);
+
+#ifdef BCMDBG
+extern void si_view(si_t *sih, bool verbose);
+extern void si_viewall(si_t *sih, bool verbose);
+#if defined(BCM_BACKPLANE_TIMEOUT)
+extern void si_setup_backplanetimeout(osl_t *osh, si_t *sih, uint val);
+extern void si_setup_curmap(osl_t *osh, si_t *sih);
+#endif
+#endif
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+extern int si_dump_pcieinfo(si_t *sih, struct bcmstrbuf *b);
+#endif
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+struct bcmstrbuf;
+extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b);
+#endif
+extern uint32 si_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type);
+extern uint32 write_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val);
+extern void si_pcie_set_request_size(si_t *sih, uint16 size);
+extern uint16 si_pcie_get_request_size(si_t *sih);
+extern void si_pcie_set_maxpayload_size(si_t *sih, uint16 size);
+extern uint16 si_pcie_get_maxpayload_size(si_t *sih);
+extern uint16 si_pcie_get_ssid(si_t *sih);
+extern uint32 si_pcie_get_bar0(si_t *sih);
+extern int si_pcie_configspace_cache(si_t *sih);
+extern int si_pcie_configspace_restore(si_t *sih);
+extern int si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size);
+
+char *si_getnvramflvar(si_t *sih, const char *name);
+
+extern void BCMATTACHFN(si_muxenab)(si_t *sih, uint32 w);
+
+extern uint32 si_tcm_size(si_t *sih);
+extern bool si_has_flops(si_t *sih);
+
+extern uint32 si_gci_direct(si_t *sih, uint offset, uint32 mask, uint32 val);
+extern uint32 si_gci_indirect(si_t *sih, uint regidx, uint offset, uint32 mask, uint32 val);
+extern uint32 si_gci_output(si_t *sih, uint reg, uint32 mask, uint32 val);
+extern uint32 si_gci_input(si_t *sih, uint reg);
+extern uint32 si_gci_int_enable(si_t *sih, bool enable);
+extern void si_gci_reset(si_t *sih);
+extern void si_ercx_init(si_t *sih);
+extern void si_wci2_init(si_t *sih);
+extern void si_gci_seci_init(si_t *sih);
+extern void si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel);
+extern uint8 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos);
+extern uint32 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val);
+extern int si_set_sromctl(si_t *sih, uint32 value);
+extern uint32 si_get_sromctl(si_t *sih);
+
+extern uint16 si_cc_get_reg16(uint32 reg_offs);
+extern uint32 si_cc_get_reg32(uint32 reg_offs);
+extern uint32 si_cc_set_reg32(uint32 reg_offs, uint32 val);
+extern uint32 si_gci_preinit_upd_indirect(uint32 regidx, uint32 setval, uint32 mask);
+
+#define CHIPCTRLREG1 0x1
+#define CHIPCTRLREG2 0x2
+#define CHIPCTRLREG3 0x3
+#define CHIPCTRLREG4 0x4
+#define CHIPCTRLREG5 0x5
+#define REGCTRLREG4 0x4
+#define MINRESMASKREG 0x618
+#define MAXRESMASKREG 0x61c
+#define CHIPCTRLADDR 0x650
+#define CHIPCTRLDATA 0x654
+#define RSRCTABLEADDR 0x620
+#define RSRCUPDWNTIME 0x628
+#define PMUREG_RESREQ_MASK 0x68c
+
+extern void si_update_masks(si_t *sih);
+
+extern void si_force_islanding(si_t *sih, bool enable);
+
+extern uint32 si_pmu_res_req_timer_clr(si_t *sih);
+extern void si_pmu_rfldo(si_t *sih, bool on);
+extern void si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 spert_val);
+extern void si_pcie_ltr_war(si_t *sih);
+extern uint si_jtag_ureg_read(si_t *sih, uint num);
+extern void si_jtag_ureg_write(si_t *sih, uint num, uint data);
+extern uint si_bbpll_war(si_t *sih, uint state);
+#endif
diff --git a/src/include/typedefs.h b/src/include/typedefs.h
new file mode 100644
index 0000000..d26ab14
--- /dev/null
+++ b/src/include/typedefs.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * $Id: typedefs.h 382996 2013-02-05 06:55:24Z $
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+#if defined(__x86_64__)
+#define TYPEDEF_UINTPTR
+typedef unsigned long long int uintptr;
+#endif
+
+#if defined(__sparc__)
+#define TYPEDEF_ULONG
+#endif
+
+#if defined(LINUX_PORT)
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
+#define TYPEDEF_BOOL
+#endif
+
+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18))
+#include <linux/compiler.h>
+#endif
+#endif
+#endif
+
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif
+
+#if !defined(__BOB__)
+
+#if defined(__KERNEL__)
+
+#if defined(LINUX_PORT)
+#include <linux/types.h>
+#endif
+
+#else
+
+#include <sys/types.h>
+
+#endif
+
+#endif
+
+#define USE_TYPEDEF_DEFAULTS
+
+#ifdef USE_TYPEDEF_DEFAULTS
+#undef USE_TYPEDEF_DEFAULTS
+
+#ifndef TYPEDEF_BOOL
+typedef unsigned char bool;
+#endif
+
+#ifndef TYPEDEF_UCHAR
+typedef unsigned char uchar;
+#endif
+
+#ifndef TYPEDEF_USHORT
+typedef unsigned short ushort;
+#endif
+
+#ifndef TYPEDEF_UINT
+typedef unsigned int uint;
+#endif
+
+#ifndef TYPEDEF_ULONG
+typedef unsigned long ulong;
+#endif
+
+#ifndef TYPEDEF_UINT8
+typedef unsigned char uint8;
+#endif
+
+#ifndef TYPEDEF_UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef TYPEDEF_UINT32
+typedef unsigned int uint32;
+#endif
+
+#ifndef TYPEDEF_UINT64
+typedef unsigned long long uint64;
+#endif
+
+#ifndef TYPEDEF_UINTPTR
+typedef unsigned int uintptr;
+#endif
+
+#ifndef TYPEDEF_INT8
+typedef signed char int8;
+#endif
+
+#ifndef TYPEDEF_INT16
+typedef signed short int16;
+#endif
+
+#ifndef TYPEDEF_INT32
+typedef signed int int32;
+#endif
+
+#ifndef TYPEDEF_INT64
+typedef signed long long int64;
+#endif
+
+#ifndef TYPEDEF_FLOAT32
+typedef float float32;
+#endif
+
+#ifndef TYPEDEF_FLOAT64
+typedef double float64;
+#endif
+
+#ifndef TYPEDEF_FLOAT_T
+
+#if defined(FLOAT32)
+typedef float32 float_t;
+#else
+typedef float64 float_t;
+#endif
+
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+
+#ifndef ON
+#define ON 1
+#endif
+
+#define AUTO (-1)
+
+#ifndef PTRSZ
+#define PTRSZ sizeof(char*)
+#endif
+
+#if defined(__GNUC__) || defined(__lint)
+ #define BWL_COMPILER_GNU
+#elif defined(__CC_ARM) && __CC_ARM
+ #define BWL_COMPILER_ARMCC
+#else
+ #error "Unknown compiler!"
+#endif
+
+#ifndef INLINE
+ #if defined(BWL_COMPILER_MICROSOFT)
+ #define INLINE __inline
+ #elif defined(BWL_COMPILER_GNU)
+ #define INLINE __inline__
+ #elif defined(BWL_COMPILER_ARMCC)
+ #define INLINE __inline
+ #else
+ #define INLINE
+ #endif
+#endif
+
+#undef TYPEDEF_BOOL
+#undef TYPEDEF_UCHAR
+#undef TYPEDEF_USHORT
+#undef TYPEDEF_UINT
+#undef TYPEDEF_ULONG
+#undef TYPEDEF_UINT8
+#undef TYPEDEF_UINT16
+#undef TYPEDEF_UINT32
+#undef TYPEDEF_UINT64
+#undef TYPEDEF_UINTPTR
+#undef TYPEDEF_INT8
+#undef TYPEDEF_INT16
+#undef TYPEDEF_INT32
+#undef TYPEDEF_INT64
+#undef TYPEDEF_FLOAT32
+#undef TYPEDEF_FLOAT64
+#undef TYPEDEF_FLOAT_T
+
+#endif
+
+#define UNUSED_PARAMETER(x) (void)(x)
+
+#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr))
+
+#include <bcmdefs.h>
+#endif
diff --git a/src/include/wlioctl.h b/src/include/wlioctl.h
new file mode 100644
index 0000000..2c05c7c
--- /dev/null
+++ b/src/include/wlioctl.h
@@ -0,0 +1,1165 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlioctl.h 464835 2014-03-26 01:35:40Z $
+ */
+
+#ifndef _wlioctl_h_
+#define _wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/bcmeth.h>
+#include <proto/bcmip.h>
+#include <proto/bcmevent.h>
+#include <proto/802.11.h>
+#include <bcmwifi_channels.h>
+#include <bcmwifi_rates.h>
+
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+#define WL_BSS_INFO_VERSION 109
+
+typedef struct wl_bss_info {
+ uint32 version;
+ uint32 length;
+ struct ether_addr BSSID;
+ uint16 beacon_period;
+ uint16 capability;
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count;
+ uint8 rates[16];
+ } rateset;
+ chanspec_t chanspec;
+ uint16 atim_window;
+ uint8 dtim_period;
+ int16 RSSI;
+ int8 phy_noise;
+
+ uint8 n_cap;
+ uint32 nbss_cap;
+ uint8 ctl_ch;
+ uint8 padding1[3];
+ uint16 vht_rxmcsmap;
+ uint16 vht_txmcsmap;
+ uint8 flags;
+ uint8 vht_cap;
+ uint8 reserved[2];
+ uint8 basic_mcs[MCSSET_LEN];
+
+ uint16 ie_offset;
+ uint32 ie_length;
+ int16 SNR;
+
+} wl_bss_info_t;
+
+#define WL_BSS_FLAGS_FROM_BEACON 0x01
+#define WL_BSS_FLAGS_FROM_CACHE 0x02
+#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04
+
+#define VHT_BI_SGI_80MHZ 0x00000100
+#define VHT_BI_80MHZ 0x00000200
+#define VHT_BI_160MHZ 0x00000400
+#define VHT_BI_8080MHZ 0x00000800
+
+typedef struct wlc_ssid {
+ uint32 SSID_len;
+ uchar SSID[32];
+} wlc_ssid_t;
+
+typedef struct wl_scan_results {
+ uint32 buflen;
+ uint32 version;
+ uint32 count;
+ wl_bss_info_t bss_info[1];
+} wl_scan_results_t;
+
+#define WL_MAXRATES_IN_SET 16
+typedef struct wl_rateset {
+ uint32 count;
+ uint8 rates[WL_MAXRATES_IN_SET];
+} wl_rateset_t;
+
+typedef struct wl_rateset_args {
+ uint32 count;
+ uint8 rates[WL_MAXRATES_IN_SET];
+ uint8 mcs[MCSSET_LEN];
+ uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX];
+} wl_rateset_args_t;
+
+#define TXBF_RATE_MCS_ALL 4
+#define TXBF_RATE_VHT_ALL 4
+#define TXBF_RATE_OFDM_ALL 8
+
+typedef struct wl_txbf_rateset {
+ uint8 txbf_rate_mcs[TXBF_RATE_MCS_ALL];
+ uint8 txbf_rate_mcs_bcm[TXBF_RATE_MCS_ALL];
+ uint16 txbf_rate_vht[TXBF_RATE_VHT_ALL];
+ uint16 txbf_rate_vht_bcm[TXBF_RATE_VHT_ALL];
+ uint8 txbf_rate_ofdm[TXBF_RATE_OFDM_ALL];
+ uint8 txbf_rate_ofdm_bcm[TXBF_RATE_OFDM_ALL];
+ uint8 txbf_rate_ofdm_cnt;
+ uint8 txbf_rate_ofdm_cnt_bcm;
+} wl_txbf_rateset_t;
+
+#define OFDM_RATE_MASK 0x0000007f
+typedef uint8 ofdm_rates_t;
+
+typedef struct wl_uint32_list {
+
+ uint32 count;
+
+ uint32 element[1];
+} wl_uint32_list_t;
+
+typedef struct wl_assoc_params {
+ struct ether_addr bssid;
+ int32 chanspec_num;
+ chanspec_t chanspec_list[1];
+} wl_assoc_params_t;
+#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list)
+
+typedef wl_assoc_params_t wl_reassoc_params_t;
+#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE
+
+typedef wl_assoc_params_t wl_join_assoc_params_t;
+#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE
+
+typedef struct wl_join_params {
+ wlc_ssid_t ssid;
+ wl_assoc_params_t params;
+} wl_join_params_t;
+
+#define WLC_CNTRY_BUF_SZ 4
+
+#define CRYPTO_ALGO_OFF 0
+#define CRYPTO_ALGO_WEP1 1
+#define CRYPTO_ALGO_TKIP 2
+#define CRYPTO_ALGO_WEP128 3
+#define CRYPTO_ALGO_AES_CCM 4
+#define CRYPTO_ALGO_AES_OCB_MSDU 5
+#define CRYPTO_ALGO_AES_OCB_MPDU 6
+#define CRYPTO_ALGO_NALG 7
+#define CRYPTO_ALGO_PMK 12
+#define CRYPTO_ALGO_BIP 13
+
+#define WSEC_GEN_MIC_ERROR 0x0001
+#define WSEC_GEN_REPLAY 0x0002
+#define WSEC_GEN_ICV_ERROR 0x0004
+#define WSEC_GEN_MFP_ACT_ERROR 0x0008
+#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010
+#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020
+
+#define WL_SOFT_KEY (1 << 0)
+#define WL_PRIMARY_KEY (1 << 1)
+#define WL_KF_RES_4 (1 << 4)
+#define WL_KF_RES_5 (1 << 5)
+#define WL_IBSS_PEER_GROUP_KEY (1 << 6)
+
+typedef struct wl_wsec_key {
+ uint32 index;
+ uint32 len;
+ uint8 data[DOT11_MAX_KEY_SIZE];
+ uint32 pad_1[18];
+ uint32 algo;
+ uint32 flags;
+ uint32 pad_2[2];
+ int pad_3;
+ int iv_initialized;
+ int pad_4;
+
+ struct {
+ uint32 hi;
+ uint16 lo;
+ } rxiv;
+ uint32 pad_5[2];
+ struct ether_addr ea;
+} wl_wsec_key_t;
+
+#define WSEC_MIN_PSK_LEN 8
+#define WSEC_MAX_PSK_LEN 64
+
+#define WSEC_PASSPHRASE (1<<0)
+
+typedef struct {
+ ushort key_len;
+ ushort flags;
+ uint8 key[WSEC_MAX_PSK_LEN];
+} wsec_pmk_t;
+
+#define WEP_ENABLED 0x0001
+#define TKIP_ENABLED 0x0002
+#define AES_ENABLED 0x0004
+#define WSEC_SWFLAG 0x0008
+#define SES_OW_ENABLED 0x0040
+
+#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED)
+
+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED)
+
+#define MFP_CAPABLE 0x0200
+#define MFP_REQUIRED 0x0400
+#define MFP_SHA256 0x0800
+
+#define WPA_AUTH_DISABLED 0x0000
+#define WPA_AUTH_NONE 0x0001
+#define WPA_AUTH_UNSPECIFIED 0x0002
+#define WPA_AUTH_PSK 0x0004
+
+#define WPA2_AUTH_UNSPECIFIED 0x0040
+#define WPA2_AUTH_PSK 0x0080
+#define BRCM_AUTH_PSK 0x0100
+#define BRCM_AUTH_DPT 0x0200
+#define WPA2_AUTH_MFP 0x1000
+#define WPA2_AUTH_TPK 0x2000
+#define WPA2_AUTH_FT 0x4000
+#define WPA_AUTH_PFN_ANY 0xffffffff
+
+#define MAXPMKID 16
+
+typedef struct _pmkid {
+ struct ether_addr BSSID;
+ uint8 PMKID[WPA2_PMKID_LEN];
+} pmkid_t;
+
+typedef struct _pmkid_list {
+ uint32 npmkid;
+ pmkid_t pmkid[1];
+} pmkid_list_t;
+
+typedef struct _pmkid_cand {
+ struct ether_addr BSSID;
+ uint8 preauth;
+} pmkid_cand_t;
+
+typedef struct _pmkid_cand_list {
+ uint32 npmkid_cand;
+ pmkid_cand_t pmkid_cand[1];
+} pmkid_cand_list_t;
+
+typedef struct {
+ uint32 val;
+ struct ether_addr ea;
+} scb_val_t;
+
+typedef struct {
+ uint32 code;
+ scb_val_t ioctl_args;
+} authops_t;
+
+typedef struct channel_info {
+ int hw_channel;
+ int target_channel;
+ int scan_channel;
+} channel_info_t;
+
+struct maclist {
+ uint count;
+ struct ether_addr ea[1];
+};
+
+typedef struct wl_ioctl {
+ uint cmd;
+ void *buf;
+ uint len;
+ uint8 set;
+ uint used;
+ uint needed;
+} wl_ioctl_t;
+
+#define ioctl_subtype set
+#define ioctl_pid used
+#define ioctl_status needed
+
+typedef struct wlc_rev_info {
+ uint vendorid;
+ uint deviceid;
+ uint radiorev;
+ uint chiprev;
+ uint corerev;
+ uint boardid;
+ uint boardvendor;
+ uint boardrev;
+ uint driverrev;
+ uint ucoderev;
+ uint bus;
+ uint chipnum;
+ uint phytype;
+ uint phyrev;
+ uint anarev;
+ uint chippkg;
+ uint nvramrev;
+} wlc_rev_info_t;
+
+#define WL_REV_INFO_LEGACY_LENGTH 48
+
+#define WLC_IOCTL_MAXLEN 8192
+#define WLC_IOCTL_SMLEN 256
+#define WLC_IOCTL_MEDLEN 1536
+#if defined(LCNCONF) || defined(LCN40CONF)
+#define WLC_SAMPLECOLLECT_MAXLEN 8192
+#else
+#define WLC_SAMPLECOLLECT_MAXLEN 10240
+#endif
+#define WLC_SAMPLECOLLECT_MAXLEN_LCN40 8192
+
+#define WLC_GET_MAGIC 0
+#define WLC_GET_VERSION 1
+#define WLC_UP 2
+#define WLC_DOWN 3
+#define WLC_GET_LOOP 4
+#define WLC_SET_LOOP 5
+#define WLC_DUMP 6
+#define WLC_GET_MSGLEVEL 7
+#define WLC_SET_MSGLEVEL 8
+#define WLC_GET_PROMISC 9
+#define WLC_SET_PROMISC 10
+
+#define WLC_GET_RATE 12
+#define WLC_GET_MAX_RATE 13
+#define WLC_GET_INSTANCE 14
+
+#define WLC_GET_INFRA 19
+#define WLC_SET_INFRA 20
+#define WLC_GET_AUTH 21
+#define WLC_SET_AUTH 22
+#define WLC_GET_BSSID 23
+#define WLC_SET_BSSID 24
+#define WLC_GET_SSID 25
+#define WLC_SET_SSID 26
+#define WLC_RESTART 27
+#define WLC_TERMINATED 28
+
+#define WLC_GET_CHANNEL 29
+#define WLC_SET_CHANNEL 30
+#define WLC_GET_SRL 31
+#define WLC_SET_SRL 32
+#define WLC_GET_LRL 33
+#define WLC_SET_LRL 34
+#define WLC_GET_PLCPHDR 35
+#define WLC_SET_PLCPHDR 36
+#define WLC_GET_RADIO 37
+#define WLC_SET_RADIO 38
+#define WLC_GET_PHYTYPE 39
+#define WLC_DUMP_RATE 40
+#define WLC_SET_RATE_PARAMS 41
+#define WLC_GET_FIXRATE 42
+#define WLC_SET_FIXRATE 43
+
+#define WLC_GET_KEY 44
+#define WLC_SET_KEY 45
+#define WLC_GET_REGULATORY 46
+#define WLC_SET_REGULATORY 47
+#define WLC_GET_PASSIVE_SCAN 48
+#define WLC_SET_PASSIVE_SCAN 49
+#define WLC_SCAN 50
+#define WLC_SCAN_RESULTS 51
+#define WLC_DISASSOC 52
+#define WLC_REASSOC 53
+#define WLC_GET_ROAM_TRIGGER 54
+#define WLC_SET_ROAM_TRIGGER 55
+#define WLC_GET_ROAM_DELTA 56
+#define WLC_SET_ROAM_DELTA 57
+#define WLC_GET_ROAM_SCAN_PERIOD 58
+#define WLC_SET_ROAM_SCAN_PERIOD 59
+#define WLC_EVM 60
+#define WLC_GET_TXANT 61
+#define WLC_SET_TXANT 62
+#define WLC_GET_ANTDIV 63
+#define WLC_SET_ANTDIV 64
+
+#define WLC_GET_CLOSED 67
+#define WLC_SET_CLOSED 68
+#define WLC_GET_MACLIST 69
+#define WLC_SET_MACLIST 70
+#define WLC_GET_RATESET 71
+#define WLC_SET_RATESET 72
+
+#define WLC_LONGTRAIN 74
+#define WLC_GET_BCNPRD 75
+#define WLC_SET_BCNPRD 76
+#define WLC_GET_DTIMPRD 77
+#define WLC_SET_DTIMPRD 78
+#define WLC_GET_SROM 79
+#define WLC_SET_SROM 80
+#define WLC_GET_WEP_RESTRICT 81
+#define WLC_SET_WEP_RESTRICT 82
+#define WLC_GET_COUNTRY 83
+#define WLC_SET_COUNTRY 84
+#define WLC_GET_PM 85
+#define WLC_SET_PM 86
+#define WLC_GET_WAKE 87
+#define WLC_SET_WAKE 88
+
+#define WLC_GET_FORCELINK 90
+#define WLC_SET_FORCELINK 91
+#define WLC_FREQ_ACCURACY 92
+#define WLC_CARRIER_SUPPRESS 93
+#define WLC_GET_PHYREG 94
+#define WLC_SET_PHYREG 95
+#define WLC_GET_RADIOREG 96
+#define WLC_SET_RADIOREG 97
+#define WLC_GET_REVINFO 98
+#define WLC_GET_UCANTDIV 99
+#define WLC_SET_UCANTDIV 100
+#define WLC_R_REG 101
+#define WLC_W_REG 102
+
+#define WLC_GET_MACMODE 105
+#define WLC_SET_MACMODE 106
+#define WLC_GET_MONITOR 107
+#define WLC_SET_MONITOR 108
+#define WLC_GET_GMODE 109
+#define WLC_SET_GMODE 110
+#define WLC_GET_LEGACY_ERP 111
+#define WLC_SET_LEGACY_ERP 112
+#define WLC_GET_RX_ANT 113
+#define WLC_GET_CURR_RATESET 114
+#define WLC_GET_SCANSUPPRESS 115
+#define WLC_SET_SCANSUPPRESS 116
+#define WLC_GET_AP 117
+#define WLC_SET_AP 118
+#define WLC_GET_EAP_RESTRICT 119
+#define WLC_SET_EAP_RESTRICT 120
+#define WLC_SCB_AUTHORIZE 121
+#define WLC_SCB_DEAUTHORIZE 122
+#define WLC_GET_WDSLIST 123
+#define WLC_SET_WDSLIST 124
+#define WLC_GET_ATIM 125
+#define WLC_SET_ATIM 126
+#define WLC_GET_RSSI 127
+#define WLC_GET_PHYANTDIV 128
+#define WLC_SET_PHYANTDIV 129
+#define WLC_AP_RX_ONLY 130
+#define WLC_GET_TX_PATH_PWR 131
+#define WLC_SET_TX_PATH_PWR 132
+#define WLC_GET_WSEC 133
+#define WLC_SET_WSEC 134
+#define WLC_GET_PHY_NOISE 135
+#define WLC_GET_BSS_INFO 136
+#define WLC_GET_PKTCNTS 137
+#define WLC_GET_LAZYWDS 138
+#define WLC_SET_LAZYWDS 139
+#define WLC_GET_BANDLIST 140
+
+#define WLC_GET_PHYLIST 180
+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201
+#define WLC_GET_VALID_CHANNELS 217
+#define WLC_GET_FAKEFRAG 218
+#define WLC_SET_FAKEFRAG 219
+#define WLC_GET_PWROUT_PERCENTAGE 220
+#define WLC_SET_PWROUT_PERCENTAGE 221
+#define WLC_SET_BAD_FRAME_PREEMPT 222
+#define WLC_GET_BAD_FRAME_PREEMPT 223
+#define WLC_SET_LEAP_LIST 224
+#define WLC_GET_LEAP_LIST 225
+#define WLC_GET_CWMIN 226
+#define WLC_SET_CWMIN 227
+#define WLC_GET_CWMAX 228
+#define WLC_SET_CWMAX 229
+#define WLC_GET_WET 230
+#define WLC_SET_WET 231
+#define WLC_GET_PUB 232
+
+#define WLC_GET_KEY_PRIMARY 235
+#define WLC_SET_KEY_PRIMARY 236
+
+#define WLC_GET_VAR 262
+#define WLC_SET_VAR 263
+
+#define WL_RADIO_SW_DISABLE (1<<0)
+#define WL_RADIO_HW_DISABLE (1<<1)
+#define WL_RADIO_MPC_DISABLE (1<<2)
+#define WL_RADIO_COUNTRY_DISABLE (1<<3)
+
+#define WL_SPURAVOID_OFF 0
+#define WL_SPURAVOID_ON1 1
+#define WL_SPURAVOID_ON2 2
+
+#define WL_4335_SPURAVOID_ON1 1
+#define WL_4335_SPURAVOID_ON2 2
+#define WL_4335_SPURAVOID_ON3 3
+#define WL_4335_SPURAVOID_ON4 4
+#define WL_4335_SPURAVOID_ON5 5
+#define WL_4335_SPURAVOID_ON6 6
+#define WL_4335_SPURAVOID_ON7 7
+#define WL_4335_SPURAVOID_ON8 8
+#define WL_4335_SPURAVOID_ON9 9
+
+#define WL_TXPWR_OVERRIDE (1U<<31)
+#define WL_TXPWR_NEG (1U<<30)
+
+#define WLC_PHY_TYPE_A 0
+#define WLC_PHY_TYPE_B 1
+#define WLC_PHY_TYPE_G 2
+#define WLC_PHY_TYPE_N 4
+#define WLC_PHY_TYPE_LP 5
+#define WLC_PHY_TYPE_SSN 6
+#define WLC_PHY_TYPE_HT 7
+#define WLC_PHY_TYPE_LCN 8
+#define WLC_PHY_TYPE_LCN40 10
+#define WLC_PHY_TYPE_AC 11
+#define WLC_PHY_TYPE_NULL 0xf
+
+#define PM_OFF 0
+#define PM_MAX 1
+#define PM_FAST 2
+#define PM_FORCE_OFF 3
+
+#define NFIFO 6
+#define NREINITREASONCOUNT 8
+#define REINITREASONIDX(_x) (((_x) < NREINITREASONCOUNT) ? (_x) : 0)
+
+#define WL_CNT_T_VERSION 10
+
+typedef struct {
+ uint16 version;
+ uint16 length;
+
+ uint32 txframe;
+ uint32 txbyte;
+ uint32 txretrans;
+ uint32 txerror;
+ uint32 txctl;
+ uint32 txprshort;
+ uint32 txserr;
+ uint32 txnobuf;
+ uint32 txnoassoc;
+ uint32 txrunt;
+ uint32 txchit;
+ uint32 txcmiss;
+
+ uint32 txuflo;
+ uint32 txphyerr;
+ uint32 txphycrs;
+
+ uint32 rxframe;
+ uint32 rxbyte;
+ uint32 rxerror;
+ uint32 rxctl;
+ uint32 rxnobuf;
+ uint32 rxnondata;
+ uint32 rxbadds;
+ uint32 rxbadcm;
+ uint32 rxfragerr;
+ uint32 rxrunt;
+ uint32 rxgiant;
+ uint32 rxnoscb;
+ uint32 rxbadproto;
+ uint32 rxbadsrcmac;
+ uint32 rxbadda;
+ uint32 rxfilter;
+
+ uint32 rxoflo;
+ uint32 rxuflo[NFIFO];
+
+ uint32 d11cnt_txrts_off;
+ uint32 d11cnt_rxcrc_off;
+ uint32 d11cnt_txnocts_off;
+
+ uint32 dmade;
+ uint32 dmada;
+ uint32 dmape;
+ uint32 reset;
+ uint32 tbtt;
+ uint32 txdmawar;
+ uint32 pkt_callback_reg_fail;
+
+ uint32 txallfrm;
+ uint32 txrtsfrm;
+ uint32 txctsfrm;
+ uint32 txackfrm;
+ uint32 txdnlfrm;
+ uint32 txbcnfrm;
+ uint32 txfunfl[8];
+ uint32 txtplunfl;
+ uint32 txphyerror;
+ uint32 rxfrmtoolong;
+ uint32 rxfrmtooshrt;
+ uint32 rxinvmachdr;
+ uint32 rxbadfcs;
+ uint32 rxbadplcp;
+ uint32 rxcrsglitch;
+ uint32 rxstrt;
+ uint32 rxdfrmucastmbss;
+ uint32 rxmfrmucastmbss;
+ uint32 rxcfrmucast;
+ uint32 rxrtsucast;
+ uint32 rxctsucast;
+ uint32 rxackucast;
+ uint32 rxdfrmocast;
+ uint32 rxmfrmocast;
+ uint32 rxcfrmocast;
+ uint32 rxrtsocast;
+ uint32 rxctsocast;
+ uint32 rxdfrmmcast;
+ uint32 rxmfrmmcast;
+ uint32 rxcfrmmcast;
+ uint32 rxbeaconmbss;
+ uint32 rxdfrmucastobss;
+ uint32 rxbeaconobss;
+ uint32 rxrsptmout;
+ uint32 bcntxcancl;
+ uint32 rxf0ovfl;
+ uint32 rxf1ovfl;
+ uint32 rxf2ovfl;
+ uint32 txsfovfl;
+ uint32 pmqovfl;
+ uint32 rxcgprqfrm;
+ uint32 rxcgprsqovfl;
+ uint32 txcgprsfail;
+ uint32 txcgprssuc;
+ uint32 prs_timeout;
+ uint32 rxnack;
+ uint32 frmscons;
+ uint32 txnack;
+ uint32 txglitch_nack;
+ uint32 txburst;
+
+ uint32 txfrag;
+ uint32 txmulti;
+ uint32 txfail;
+ uint32 txretry;
+ uint32 txretrie;
+ uint32 rxdup;
+ uint32 txrts;
+ uint32 txnocts;
+ uint32 txnoack;
+ uint32 rxfrag;
+ uint32 rxmulti;
+ uint32 rxcrc;
+ uint32 txfrmsnt;
+ uint32 rxundec;
+
+ uint32 tkipmicfaill;
+ uint32 tkipcntrmsr;
+ uint32 tkipreplay;
+ uint32 ccmpfmterr;
+ uint32 ccmpreplay;
+ uint32 ccmpundec;
+ uint32 fourwayfail;
+ uint32 wepundec;
+ uint32 wepicverr;
+ uint32 decsuccess;
+ uint32 tkipicverr;
+ uint32 wepexcluded;
+
+ uint32 txchanrej;
+ uint32 psmwds;
+ uint32 phywatchdog;
+
+ uint32 prq_entries_handled;
+ uint32 prq_undirected_entries;
+ uint32 prq_bad_entries;
+ uint32 atim_suppress_count;
+ uint32 bcn_template_not_ready;
+ uint32 bcn_template_not_ready_done;
+ uint32 late_tbtt_dpc;
+
+ uint32 rx1mbps;
+ uint32 rx2mbps;
+ uint32 rx5mbps5;
+ uint32 rx6mbps;
+ uint32 rx9mbps;
+ uint32 rx11mbps;
+ uint32 rx12mbps;
+ uint32 rx18mbps;
+ uint32 rx24mbps;
+ uint32 rx36mbps;
+ uint32 rx48mbps;
+ uint32 rx54mbps;
+ uint32 rx108mbps;
+ uint32 rx162mbps;
+ uint32 rx216mbps;
+ uint32 rx270mbps;
+ uint32 rx324mbps;
+ uint32 rx378mbps;
+ uint32 rx432mbps;
+ uint32 rx486mbps;
+ uint32 rx540mbps;
+
+ uint32 pktengrxducast;
+ uint32 pktengrxdmcast;
+
+ uint32 rfdisable;
+ uint32 bphy_rxcrsglitch;
+ uint32 bphy_badplcp;
+
+ uint32 txexptime;
+
+ uint32 txmpdu_sgi;
+ uint32 rxmpdu_sgi;
+ uint32 txmpdu_stbc;
+ uint32 rxmpdu_stbc;
+
+ uint32 rxundec_mcst;
+
+ uint32 tkipmicfaill_mcst;
+ uint32 tkipcntrmsr_mcst;
+ uint32 tkipreplay_mcst;
+ uint32 ccmpfmterr_mcst;
+ uint32 ccmpreplay_mcst;
+ uint32 ccmpundec_mcst;
+ uint32 fourwayfail_mcst;
+ uint32 wepundec_mcst;
+ uint32 wepicverr_mcst;
+ uint32 decsuccess_mcst;
+ uint32 tkipicverr_mcst;
+ uint32 wepexcluded_mcst;
+
+ uint32 dma_hang;
+ uint32 reinit;
+
+ uint32 pstatxucast;
+ uint32 pstatxnoassoc;
+ uint32 pstarxucast;
+ uint32 pstarxbcmc;
+ uint32 pstatxbcmc;
+
+ uint32 cso_passthrough;
+ uint32 cso_normal;
+ uint32 chained;
+ uint32 chainedsz1;
+ uint32 unchained;
+ uint32 maxchainsz;
+ uint32 currchainsz;
+ uint32 pciereset;
+ uint32 cfgrestore;
+ uint32 reinitreason[NREINITREASONCOUNT];
+} wl_cnt_t;
+
+typedef struct {
+ bool auto_en;
+ uint8 active_ant;
+ uint32 rxcount;
+ int16 avg_snr_per_ant0;
+ int16 avg_snr_per_ant1;
+ uint32 swap_ge_rxcount0;
+ uint32 swap_ge_rxcount1;
+ uint32 swap_ge_snrthresh0;
+ uint32 swap_ge_snrthresh1;
+ uint32 swap_txfail0;
+ uint32 swap_txfail1;
+ uint32 swap_timer0;
+ uint32 swap_timer1;
+ uint32 swap_alivecheck0;
+ uint32 swap_alivecheck1;
+ uint32 rxcount_per_ant0;
+ uint32 rxcount_per_ant1;
+ uint32 acc_rxcount;
+ uint32 acc_rxcount_per_ant0;
+ uint32 acc_rxcount_per_ant1;
+} wlc_swdiv_stats_t;
+
+#define WL_WME_CNT_VERSION 1
+
+typedef struct {
+ uint32 packets;
+ uint32 bytes;
+} wl_traffic_stats_t;
+
+typedef struct {
+ uint16 version;
+ uint16 length;
+
+ wl_traffic_stats_t tx[AC_COUNT];
+ wl_traffic_stats_t tx_failed[AC_COUNT];
+ wl_traffic_stats_t rx[AC_COUNT];
+ wl_traffic_stats_t rx_failed[AC_COUNT];
+
+ wl_traffic_stats_t forward[AC_COUNT];
+
+ wl_traffic_stats_t tx_expired[AC_COUNT];
+
+} wl_wme_cnt_t;
+
+typedef struct wl_mkeep_alive_pkt {
+ uint16 version;
+ uint16 length;
+ uint32 period_msec;
+ uint16 len_bytes;
+ uint8 keep_alive_id;
+ uint8 data[1];
+} wl_mkeep_alive_pkt_t;
+
+#define WL_MKEEP_ALIVE_VERSION 1
+#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data)
+#define WL_MKEEP_ALIVE_PRECISION 500
+
+typedef struct wl_mtcpkeep_alive_conn_pkt {
+ struct ether_addr saddr;
+ struct ether_addr daddr;
+ struct ipv4_addr sipaddr;
+ struct ipv4_addr dipaddr;
+ uint16 sport;
+ uint16 dport;
+ uint32 seq;
+ uint32 ack;
+ uint16 tcpwin;
+} wl_mtcpkeep_alive_conn_pkt_t;
+
+typedef struct wl_mtcpkeep_alive_timers_pkt {
+ uint16 interval;
+ uint16 retry_interval;
+ uint16 retry_count;
+} wl_mtcpkeep_alive_timers_pkt_t;
+
+#ifndef ETHER_MAX_DATA
+#define ETHER_MAX_DATA 1500
+#endif
+
+typedef struct wake_info {
+ uint32 wake_reason;
+ uint32 wake_info_len;
+ uchar packet[1];
+} wake_info_t;
+
+typedef struct wake_pkt {
+ uint32 wake_pkt_len;
+ uchar packet[1];
+} wake_pkt_t;
+
+#define WL_MTCPKEEP_ALIVE_VERSION 1
+
+#ifdef WLBA
+
+#define WLC_BA_CNT_VERSION 1
+
+typedef struct wlc_ba_cnt {
+ uint16 version;
+ uint16 length;
+
+ uint32 txpdu;
+ uint32 txsdu;
+ uint32 txfc;
+ uint32 txfci;
+ uint32 txretrans;
+ uint32 txbatimer;
+ uint32 txdrop;
+ uint32 txaddbareq;
+ uint32 txaddbaresp;
+ uint32 txdelba;
+ uint32 txba;
+ uint32 txbar;
+ uint32 txpad[4];
+
+ uint32 rxpdu;
+ uint32 rxqed;
+ uint32 rxdup;
+ uint32 rxnobuf;
+ uint32 rxaddbareq;
+ uint32 rxaddbaresp;
+ uint32 rxdelba;
+ uint32 rxba;
+ uint32 rxbar;
+ uint32 rxinvba;
+ uint32 rxbaholes;
+ uint32 rxunexp;
+ uint32 rxpad[4];
+} wlc_ba_cnt_t;
+#endif
+
+struct ampdu_tid_control {
+ uint8 tid;
+ uint8 enable;
+};
+
+struct ampdu_ea_tid {
+ struct ether_addr ea;
+ uint8 tid;
+};
+
+struct ampdu_retry_tid {
+ uint8 tid;
+ uint8 retry;
+};
+
+#define TOE_TX_CSUM_OL 0x00000001
+#define TOE_RX_CSUM_OL 0x00000002
+
+#define TOE_ERRTEST_TX_CSUM 0x00000001
+#define TOE_ERRTEST_RX_CSUM 0x00000002
+#define TOE_ERRTEST_RX_CSUM2 0x00000004
+
+struct toe_ol_stats_t {
+
+ uint32 tx_summed;
+
+ uint32 tx_iph_fill;
+ uint32 tx_tcp_fill;
+ uint32 tx_udp_fill;
+ uint32 tx_icmp_fill;
+
+ uint32 rx_iph_good;
+ uint32 rx_iph_bad;
+ uint32 rx_tcp_good;
+ uint32 rx_tcp_bad;
+ uint32 rx_udp_good;
+ uint32 rx_udp_bad;
+ uint32 rx_icmp_good;
+ uint32 rx_icmp_bad;
+
+ uint32 tx_tcp_errinj;
+ uint32 tx_udp_errinj;
+ uint32 tx_icmp_errinj;
+
+ uint32 rx_tcp_errinj;
+ uint32 rx_udp_errinj;
+ uint32 rx_icmp_errinj;
+};
+
+#define ARP_OL_AGENT 0x00000001
+#define ARP_OL_SNOOP 0x00000002
+#define ARP_OL_HOST_AUTO_REPLY 0x00000004
+#define ARP_OL_PEER_AUTO_REPLY 0x00000008
+
+#define ARP_ERRTEST_REPLY_PEER 0x1
+#define ARP_ERRTEST_REPLY_HOST 0x2
+
+#define ARP_MULTIHOMING_MAX 8
+#define ND_MULTIHOMING_MAX 10
+
+struct arp_ol_stats_t {
+ uint32 host_ip_entries;
+ uint32 host_ip_overflow;
+
+ uint32 arp_table_entries;
+ uint32 arp_table_overflow;
+
+ uint32 host_request;
+ uint32 host_reply;
+ uint32 host_service;
+
+ uint32 peer_request;
+ uint32 peer_request_drop;
+ uint32 peer_reply;
+ uint32 peer_reply_drop;
+ uint32 peer_service;
+};
+
+struct nd_ol_stats_t {
+ uint32 host_ip_entries;
+ uint32 host_ip_overflow;
+ uint32 peer_request;
+ uint32 peer_request_drop;
+ uint32 peer_reply_drop;
+ uint32 peer_service;
+};
+
+typedef struct wl_keep_alive_pkt {
+ uint32 period_msec;
+ uint16 len_bytes;
+ uint8 data[1];
+} wl_keep_alive_pkt_t;
+
+#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data)
+
+typedef enum wl_pkt_filter_type {
+ WL_PKT_FILTER_TYPE_PATTERN_MATCH
+} wl_pkt_filter_type_t;
+
+#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t
+
+typedef struct wl_pkt_filter_pattern {
+ uint32 offset;
+ uint32 size_bytes;
+ uint8 mask_and_pattern[1];
+
+} wl_pkt_filter_pattern_t;
+
+typedef struct wl_pkt_filter {
+ uint32 id;
+ uint32 type;
+ uint32 negate_match;
+ union {
+ wl_pkt_filter_pattern_t pattern;
+ } u;
+} wl_pkt_filter_t;
+
+typedef struct wl_tcp_keep_set {
+ uint32 val1;
+ uint32 val2;
+} wl_tcp_keep_set_t;
+
+#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u)
+#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern)
+
+typedef struct wl_pkt_filter_enable {
+ uint32 id;
+ uint32 enable;
+} wl_pkt_filter_enable_t;
+
+typedef struct wl_pkt_filter_list {
+ uint32 num;
+ wl_pkt_filter_t filter[1];
+} wl_pkt_filter_list_t;
+
+#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter)
+
+typedef struct wl_pkt_filter_stats {
+ uint32 num_pkts_matched;
+ uint32 num_pkts_forwarded;
+ uint32 num_pkts_discarded;
+} wl_pkt_filter_stats_t;
+
+#define WL_WOWL_MAGIC (1 << 0)
+#define WL_WOWL_NET (1 << 1)
+#define WL_WOWL_DIS (1 << 2)
+#define WL_WOWL_RETR (1 << 3)
+#define WL_WOWL_BCN (1 << 4)
+#define WL_WOWL_TST (1 << 5)
+#define WL_WOWL_M1 (1 << 6)
+#define WL_WOWL_EAPID (1 << 7)
+#define WL_WOWL_PME_GPIO (1 << 8)
+#define WL_WOWL_NEEDTKIP1 (1 << 9)
+#define WL_WOWL_GTK_FAILURE (1 << 10)
+#define WL_WOWL_EXTMAGPAT (1 << 11)
+#define WL_WOWL_ARPOFFLOAD (1 << 12)
+#define WL_WOWL_WPA2 (1 << 13)
+#define WL_WOWL_KEYROT (1 << 14)
+#define WL_WOWL_BCAST (1 << 15)
+#define WL_WOWL_SCANOL (1 << 16)
+#define WL_WOWL_TCPKEEP_TIME (1 << 17)
+#define WL_WOWL_MDNS_CONFLICT (1 << 18)
+#define WL_WOWL_MDNS_SERVICE (1 << 19)
+#define WL_WOWL_TCPKEEP_DATA (1 << 20)
+#define WL_WOWL_FW_HALT (1 << 21)
+#define WL_WOWL_ENAB_HWRADIO (1 << 22)
+#define WL_WOWL_MIC_FAIL (1 << 23)
+#define WL_WOWL_LINKDOWN (1 << 31)
+
+#define MAGIC_PKT_MINLEN 102
+#define MAGIC_PKT_NUM_MAC_ADDRS 16
+
+typedef enum {
+ wowl_pattern_type_bitmap = 0,
+ wowl_pattern_type_arp,
+ wowl_pattern_type_na
+} wowl_pattern_type_t;
+
+typedef struct wl_wowl_pattern {
+ uint32 masksize;
+ uint32 offset;
+ uint32 patternoffset;
+ uint32 patternsize;
+ uint32 id;
+ uint32 reasonsize;
+ wowl_pattern_type_t type;
+
+} wl_wowl_pattern_t;
+
+typedef struct wl_wowl_pattern_list {
+ uint count;
+ wl_wowl_pattern_t pattern[1];
+} wl_wowl_pattern_list_t;
+
+typedef struct wl_wowl_wakeind {
+ uint8 pci_wakeind;
+ uint32 ucode_wakeind;
+} wl_wowl_wakeind_t;
+
+typedef struct {
+ uint32 pktlen;
+ void *sdu;
+} tcp_keepalive_wake_pkt_infop_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct nbr_element {
+ uint8 id;
+ uint8 len;
+ struct ether_addr bssid;
+ uint32 bssid_info;
+ uint8 reg;
+ uint8 channel;
+ uint8 phytype;
+} BWL_POST_PACKED_STRUCT nbr_element_t;
+
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+
+#include <packed_section_end.h>
+
+typedef struct bcnreq {
+ uint8 bcn_mode;
+ int dur;
+ int channel;
+ struct ether_addr da;
+ uint16 random_int;
+ wlc_ssid_t ssid;
+ uint16 reps;
+} bcnreq_t;
+
+typedef struct rrmreq {
+ struct ether_addr da;
+ uint8 reg;
+ uint8 chan;
+ uint16 random_int;
+ uint16 dur;
+ uint16 reps;
+} rrmreq_t;
+
+typedef struct framereq {
+ struct ether_addr da;
+ uint8 reg;
+ uint8 chan;
+ uint16 random_int;
+ uint16 dur;
+ struct ether_addr ta;
+ uint16 reps;
+} framereq_t;
+
+typedef struct statreq {
+ struct ether_addr da;
+ struct ether_addr peer;
+ uint16 random_int;
+ uint16 dur;
+ uint8 group_id;
+ uint16 reps;
+} statreq_t;
+
+typedef struct wlc_l2keepalive_ol_params {
+ uint8 flags;
+ uint8 prio;
+ uint16 period_ms;
+} wlc_l2keepalive_ol_params_t;
+
+typedef struct wlc_dwds_config {
+ uint32 mode;
+ struct ether_addr ea;
+} wlc_dwds_config_t;
+
+#define WLC_KCK_LEN 16
+#define WLC_KEK_LEN 16
+#define WLC_REPLAY_CTR_LEN 8
+
+typedef struct wlc_rekey_info {
+ uint32 offload_id;
+ uint8 kek[WLC_KEK_LEN];
+ uint8 kck[WLC_KCK_LEN];
+ uint8 replay_counter[WLC_REPLAY_CTR_LEN];
+} wlc_rekey_info_t;
+
+#endif
diff --git a/src/shared/bcmwifi/include/bcmwifi_channels.h b/src/shared/bcmwifi/include/bcmwifi_channels.h
new file mode 100644
index 0000000..550c4fd
--- /dev/null
+++ b/src/shared/bcmwifi/include/bcmwifi_channels.h
@@ -0,0 +1,353 @@
+/*
+ * Misc utility routines for WL and Apps
+ * This header file housing the define and function prototype use by
+ * both the wl driver, tools & Apps.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: bcmwifi_channels.h 309193 2012-01-19 00:03:57Z $
+ */
+
+#ifndef _bcmwifi_channels_h_
+#define _bcmwifi_channels_h_
+
+#if defined(__FreeBSD__)
+#include <stdbool.h>
+#endif
+
+typedef uint16 chanspec_t;
+
+#define CH_UPPER_SB 0x01
+#define CH_LOWER_SB 0x02
+#define CH_EWA_VALID 0x04
+#define CH_80MHZ_APART 16
+#define CH_40MHZ_APART 8
+#define CH_20MHZ_APART 4
+#define CH_10MHZ_APART 2
+#define CH_5MHZ_APART 1
+#define CH_MAX_2G_CHANNEL 14
+#define MAXCHANNEL 224
+#define MAXCHANNEL_NUM (MAXCHANNEL - 1)
+
+#define CH_NUM_VALID_RANGE(ch_num) ((ch_num) > 0 && (ch_num) <= MAXCHANNEL_NUM)
+
+#define CHSPEC_CTLOVLP(sp1, sp2, sep) (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < \
+ (sep))
+
+#undef D11AC_IOTYPES
+#define D11AC_IOTYPES
+
+#define WL_CHANSPEC_CHAN_MASK 0x00ff
+#define WL_CHANSPEC_CHAN_SHIFT 0
+#define WL_CHANSPEC_CHAN1_MASK 0x000f
+#define WL_CHANSPEC_CHAN1_SHIFT 0
+#define WL_CHANSPEC_CHAN2_MASK 0x00f0
+#define WL_CHANSPEC_CHAN2_SHIFT 4
+
+#define WL_CHANSPEC_CTL_SB_MASK 0x0700
+#define WL_CHANSPEC_CTL_SB_SHIFT 8
+#define WL_CHANSPEC_CTL_SB_LLL 0x0000
+#define WL_CHANSPEC_CTL_SB_LLU 0x0100
+#define WL_CHANSPEC_CTL_SB_LUL 0x0200
+#define WL_CHANSPEC_CTL_SB_LUU 0x0300
+#define WL_CHANSPEC_CTL_SB_ULL 0x0400
+#define WL_CHANSPEC_CTL_SB_ULU 0x0500
+#define WL_CHANSPEC_CTL_SB_UUL 0x0600
+#define WL_CHANSPEC_CTL_SB_UUU 0x0700
+#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL
+#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU
+#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
+
+#define WL_CHANSPEC_BW_MASK 0x3800
+#define WL_CHANSPEC_BW_SHIFT 11
+#define WL_CHANSPEC_BW_5 0x0000
+#define WL_CHANSPEC_BW_10 0x0800
+#define WL_CHANSPEC_BW_20 0x1000
+#define WL_CHANSPEC_BW_40 0x1800
+#define WL_CHANSPEC_BW_80 0x2000
+#define WL_CHANSPEC_BW_160 0x2800
+#define WL_CHANSPEC_BW_8080 0x3000
+#define WL_CHANSPEC_BW_2P5 0x3800
+
+#define WL_CHANSPEC_BAND_MASK 0xc000
+#define WL_CHANSPEC_BAND_SHIFT 14
+#define WL_CHANSPEC_BAND_2G 0x0000
+#define WL_CHANSPEC_BAND_3G 0x4000
+#define WL_CHANSPEC_BAND_4G 0x8000
+#define WL_CHANSPEC_BAND_5G 0xc000
+#define INVCHANSPEC 255
+#define MAX_CHANSPEC 0xFFFF
+
+#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \
+ ((channel) - CH_10MHZ_APART) : 0)
+#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
+ ((channel) + CH_10MHZ_APART) : 0)
+
+#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0)
+#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \
+ ((channel) + 3 * CH_10MHZ_APART) : 0)
+#define LU_20_SB(channel) LOWER_20_SB(channel)
+#define UL_20_SB(channel) UPPER_20_SB(channel)
+
+#define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART)
+#define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART)
+#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
+#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH2P5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_2P5 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_5 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH10MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_10 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
+ ((channel) + CH_20MHZ_APART) : 0)
+#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
+ WL_CHANSPEC_BAND_5G))
+#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | \
+ WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G)
+#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | \
+ WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
+#define CHBW_CHSPEC(bw, channel) (chanspec_t)((chanspec_t)(channel) | (bw) | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+
+#ifdef WL11AC_80P80
+#define CHSPEC_CHANNEL(chspec) wf_chspec_channel(chspec)
+#else
+#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
+#endif
+#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT
+#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT
+#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
+
+#define CHSPEC_IS2P5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5)
+#define CHSPEC_IS5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5)
+#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
+#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+#endif
+#ifndef CHSPEC_IS80
+#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
+#endif
+#ifndef CHSPEC_IS160
+#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160)
+#endif
+#ifndef CHSPEC_IS8080
+#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080)
+#endif
+
+#ifdef WL11ULB
+
+#define BW_LE20(bw) (((bw) == WL_CHANSPEC_BW_2P5) || \
+ ((bw) == WL_CHANSPEC_BW_5) || \
+ ((bw) == WL_CHANSPEC_BW_10) || \
+ ((bw) == WL_CHANSPEC_BW_20))
+#define CHSPEC_ISLE20(chspec) (CHSPEC_IS2P5(chspec) || CHSPEC_IS5(chspec) || \
+ CHSPEC_IS10(chspec) || CHSPEC_IS20(chspec))
+#else
+#define BW_LE20(bw) ((bw) == WL_CHANSPEC_BW_20)
+#define CHSPEC_ISLE20(chspec) (CHSPEC_IS20(chspec))
+#endif
+
+#define BW_LE40(bw) (BW_LE20(bw) || ((bw) == WL_CHANSPEC_BW_40))
+#define BW_LE80(bw) (BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80))
+#define BW_LE160(bw) (BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160))
+#define CHSPEC_BW_LE20(chspec) (BW_LE20(CHSPEC_BW(chspec)))
+#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+#define CHSPEC_SB_UPPER(chspec) \
+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
+#define CHSPEC_SB_LOWER(chspec) \
+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
+#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
+
+#define CHANSPEC_STR_LEN 20
+
+#define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\
+ CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080)
+
+#ifdef WL11ULB
+#define CHSPEC_BW_GE(chspec, bw) \
+ (((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) >= (bw))) && \
+ (!(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
+#else
+#define CHSPEC_BW_GE(chspec, bw) \
+ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) >= (bw)))
+#endif
+
+#ifdef WL11ULB
+#define CHSPEC_BW_LE(chspec, bw) \
+ (((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) <= (bw))) || \
+ (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5))
+#else
+#define CHSPEC_BW_LE(chspec, bw) \
+ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) <= (bw)))
+#endif
+
+#ifdef WL11ULB
+#define CHSPEC_BW_GT(chspec, bw) \
+ ((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) > (bw))) && \
+ (CHSPEC_BW(chspec) != WL_CHANSPEC_BW_2P5))
+#else
+#define CHSPEC_BW_GT(chspec, bw) \
+ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) > (bw)))
+#endif
+
+#ifdef WL11ULB
+#define CHSPEC_BW_LT(chspec, bw) \
+ ((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) < (bw))) || \
+ ((CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
+#else
+#define CHSPEC_BW_LT(chspec, bw) \
+ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) < (bw)))
+#endif
+
+#define WL_LCHANSPEC_CHAN_MASK 0x00ff
+#define WL_LCHANSPEC_CHAN_SHIFT 0
+
+#define WL_LCHANSPEC_CTL_SB_MASK 0x0300
+#define WL_LCHANSPEC_CTL_SB_SHIFT 8
+#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100
+#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200
+#define WL_LCHANSPEC_CTL_SB_NONE 0x0300
+
+#define WL_LCHANSPEC_BW_MASK 0x0C00
+#define WL_LCHANSPEC_BW_SHIFT 10
+#define WL_LCHANSPEC_BW_10 0x0400
+#define WL_LCHANSPEC_BW_20 0x0800
+#define WL_LCHANSPEC_BW_40 0x0C00
+
+#define WL_LCHANSPEC_BAND_MASK 0xf000
+#define WL_LCHANSPEC_BAND_SHIFT 12
+#define WL_LCHANSPEC_BAND_5G 0x1000
+#define WL_LCHANSPEC_BAND_2G 0x2000
+
+#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK))
+#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK)
+#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK)
+#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK)
+#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10)
+#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20)
+#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)
+#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
+#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
+
+#define LCHSPEC_SB_UPPER(chspec) \
+ ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
+ (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+#define LCHSPEC_SB_LOWER(chspec) \
+ ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
+ (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+
+#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band)))
+
+#define CH20MHZ_LCHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \
+ WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
+
+#define WF_CHAN_FACTOR_2_4_G 4814
+
+#define WF_CHAN_FACTOR_5_G 10000
+
+#define WF_CHAN_FACTOR_4_G 8000
+
+#define WLC_2G_25MHZ_OFFSET 5
+
+#define WF_NUM_SIDEBANDS_40MHZ 2
+#define WF_NUM_SIDEBANDS_80MHZ 4
+#define WF_NUM_SIDEBANDS_8080MHZ 4
+#define WF_NUM_SIDEBANDS_160MHZ 8
+
+extern char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf);
+
+extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf);
+
+extern chanspec_t wf_chspec_aton(const char *a);
+
+extern bool wf_chspec_malformed(chanspec_t chanspec);
+
+extern bool wf_chspec_valid(chanspec_t chanspec);
+
+extern uint8 wf_chspec_ctlchan(chanspec_t chspec);
+
+extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
+
+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec);
+
+extern int wf_mhz2channel(uint freq, uint start_factor);
+
+extern int wf_channel2mhz(uint channel, uint start_factor);
+
+extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel);
+
+extern uint16 wf_channel2chspec(uint ctl_ch, uint bw);
+
+extern uint wf_channel2freq(uint channel);
+extern uint wf_freq2channel(uint freq);
+
+extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz,
+ uint8 chan0_80Mhz, uint8 chan1_80Mhz);
+
+extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec);
+
+extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec);
+
+extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec);
+
+#ifdef WL11AC_80P80
+
+extern uint8 wf_chspec_channel(chanspec_t chspec);
+#endif
+#endif
diff --git a/src/shared/bcmwifi/include/bcmwifi_rates.h b/src/shared/bcmwifi/include/bcmwifi_rates.h
new file mode 100644
index 0000000..a2b8009
--- /dev/null
+++ b/src/shared/bcmwifi/include/bcmwifi_rates.h
@@ -0,0 +1,705 @@
+/*
+ * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: bcmwifi_rates.h 5187 2012-06-29 06:17:50Z $
+ */
+
+#ifndef _bcmwifi_rates_h_
+#define _bcmwifi_rates_h_
+
+#define WL_RATESET_SZ_DSSS 4
+#define WL_RATESET_SZ_OFDM 8
+#define WL_RATESET_SZ_VHT_MCS 10
+#define WL_RATESET_SZ_VHT_MCS_P 12
+
+#if defined(WLPROPRIETARY_11N_RATES)
+#define WL_RATESET_SZ_HT_MCS WL_RATESET_SZ_VHT_MCS
+#else
+#define WL_RATESET_SZ_HT_MCS 8
+#endif
+
+#define WL_RATESET_SZ_HT_IOCTL 8
+
+#define WL_TX_CHAINS_MAX 4
+
+#define WL_RATE_DISABLED (-128)
+
+typedef enum wl_tx_bw {
+ WL_TX_BW_20,
+ WL_TX_BW_40,
+ WL_TX_BW_80,
+ WL_TX_BW_20IN40,
+ WL_TX_BW_20IN80,
+ WL_TX_BW_40IN80,
+ WL_TX_BW_160,
+ WL_TX_BW_20IN160,
+ WL_TX_BW_40IN160,
+ WL_TX_BW_80IN160,
+ WL_TX_BW_ALL,
+ WL_TX_BW_8080,
+ WL_TX_BW_8080CHAN2,
+ WL_TX_BW_20IN8080,
+ WL_TX_BW_40IN8080,
+ WL_TX_BW_80IN8080,
+ WL_TX_BW_2P5,
+ WL_TX_BW_5,
+ WL_TX_BW_10
+} wl_tx_bw_t;
+
+typedef enum wl_tx_mode {
+ WL_TX_MODE_NONE,
+ WL_TX_MODE_STBC,
+ WL_TX_MODE_CDD,
+ WL_TX_MODE_TXBF,
+ WL_NUM_TX_MODES
+} wl_tx_mode_t;
+
+typedef enum wl_tx_chains {
+ WL_TX_CHAINS_1 = 1,
+ WL_TX_CHAINS_2,
+ WL_TX_CHAINS_3,
+ WL_TX_CHAINS_4
+} wl_tx_chains_t;
+
+typedef enum wl_tx_nss {
+ WL_TX_NSS_1 = 1,
+ WL_TX_NSS_2,
+ WL_TX_NSS_3,
+ WL_TX_NSS_4
+} wl_tx_nss_t;
+
+typedef enum clm_rates {
+
+ WL_RATE_1X1_DSSS_1 = 0,
+ WL_RATE_1X1_DSSS_2 = 1,
+ WL_RATE_1X1_DSSS_5_5 = 2,
+ WL_RATE_1X1_DSSS_11 = 3,
+
+ WL_RATE_1X1_OFDM_6 = 4,
+ WL_RATE_1X1_OFDM_9 = 5,
+ WL_RATE_1X1_OFDM_12 = 6,
+ WL_RATE_1X1_OFDM_18 = 7,
+ WL_RATE_1X1_OFDM_24 = 8,
+ WL_RATE_1X1_OFDM_36 = 9,
+ WL_RATE_1X1_OFDM_48 = 10,
+ WL_RATE_1X1_OFDM_54 = 11,
+
+ WL_RATE_1X1_MCS0 = 12,
+ WL_RATE_1X1_MCS1 = 13,
+ WL_RATE_1X1_MCS2 = 14,
+ WL_RATE_1X1_MCS3 = 15,
+ WL_RATE_1X1_MCS4 = 16,
+ WL_RATE_1X1_MCS5 = 17,
+ WL_RATE_1X1_MCS6 = 18,
+ WL_RATE_1X1_MCS7 = 19,
+ WL_RATE_P_1X1_MCS87 = 20,
+ WL_RATE_P_1X1_MCS88 = 21,
+
+ WL_RATE_1X1_VHT0SS1 = 12,
+ WL_RATE_1X1_VHT1SS1 = 13,
+ WL_RATE_1X1_VHT2SS1 = 14,
+ WL_RATE_1X1_VHT3SS1 = 15,
+ WL_RATE_1X1_VHT4SS1 = 16,
+ WL_RATE_1X1_VHT5SS1 = 17,
+ WL_RATE_1X1_VHT6SS1 = 18,
+ WL_RATE_1X1_VHT7SS1 = 19,
+ WL_RATE_1X1_VHT8SS1 = 20,
+ WL_RATE_1X1_VHT9SS1 = 21,
+ WL_RATE_P_1X1_VHT10SS1 = 22,
+ WL_RATE_P_1X1_VHT11SS1 = 23,
+
+ WL_RATE_1X2_DSSS_1 = 24,
+ WL_RATE_1X2_DSSS_2 = 25,
+ WL_RATE_1X2_DSSS_5_5 = 26,
+ WL_RATE_1X2_DSSS_11 = 27,
+
+ WL_RATE_1X2_CDD_OFDM_6 = 28,
+ WL_RATE_1X2_CDD_OFDM_9 = 29,
+ WL_RATE_1X2_CDD_OFDM_12 = 30,
+ WL_RATE_1X2_CDD_OFDM_18 = 31,
+ WL_RATE_1X2_CDD_OFDM_24 = 32,
+ WL_RATE_1X2_CDD_OFDM_36 = 33,
+ WL_RATE_1X2_CDD_OFDM_48 = 34,
+ WL_RATE_1X2_CDD_OFDM_54 = 35,
+
+ WL_RATE_1X2_CDD_MCS0 = 36,
+ WL_RATE_1X2_CDD_MCS1 = 37,
+ WL_RATE_1X2_CDD_MCS2 = 38,
+ WL_RATE_1X2_CDD_MCS3 = 39,
+ WL_RATE_1X2_CDD_MCS4 = 40,
+ WL_RATE_1X2_CDD_MCS5 = 41,
+ WL_RATE_1X2_CDD_MCS6 = 42,
+ WL_RATE_1X2_CDD_MCS7 = 43,
+ WL_RATE_P_1X2_CDD_MCS87 = 44,
+ WL_RATE_P_1X2_CDD_MCS88 = 45,
+
+ WL_RATE_1X2_VHT0SS1 = 36,
+ WL_RATE_1X2_VHT1SS1 = 37,
+ WL_RATE_1X2_VHT2SS1 = 38,
+ WL_RATE_1X2_VHT3SS1 = 39,
+ WL_RATE_1X2_VHT4SS1 = 40,
+ WL_RATE_1X2_VHT5SS1 = 41,
+ WL_RATE_1X2_VHT6SS1 = 42,
+ WL_RATE_1X2_VHT7SS1 = 43,
+ WL_RATE_1X2_VHT8SS1 = 44,
+ WL_RATE_1X2_VHT9SS1 = 45,
+ WL_RATE_P_1X2_VHT10SS1 = 46,
+ WL_RATE_P_1X2_VHT11SS1 = 47,
+
+ WL_RATE_2X2_STBC_MCS0 = 48,
+ WL_RATE_2X2_STBC_MCS1 = 49,
+ WL_RATE_2X2_STBC_MCS2 = 50,
+ WL_RATE_2X2_STBC_MCS3 = 51,
+ WL_RATE_2X2_STBC_MCS4 = 52,
+ WL_RATE_2X2_STBC_MCS5 = 53,
+ WL_RATE_2X2_STBC_MCS6 = 54,
+ WL_RATE_2X2_STBC_MCS7 = 55,
+ WL_RATE_P_2X2_STBC_MCS87 = 56,
+ WL_RATE_P_2X2_STBC_MCS88 = 57,
+
+ WL_RATE_2X2_STBC_VHT0SS1 = 48,
+ WL_RATE_2X2_STBC_VHT1SS1 = 49,
+ WL_RATE_2X2_STBC_VHT2SS1 = 50,
+ WL_RATE_2X2_STBC_VHT3SS1 = 51,
+ WL_RATE_2X2_STBC_VHT4SS1 = 52,
+ WL_RATE_2X2_STBC_VHT5SS1 = 53,
+ WL_RATE_2X2_STBC_VHT6SS1 = 54,
+ WL_RATE_2X2_STBC_VHT7SS1 = 55,
+ WL_RATE_2X2_STBC_VHT8SS1 = 56,
+ WL_RATE_2X2_STBC_VHT9SS1 = 57,
+ WL_RATE_P_2X2_STBC_VHT10SS1 = 58,
+ WL_RATE_P_2X2_STBC_VHT11SS1 = 59,
+
+ WL_RATE_2X2_SDM_MCS8 = 60,
+ WL_RATE_2X2_SDM_MCS9 = 61,
+ WL_RATE_2X2_SDM_MCS10 = 62,
+ WL_RATE_2X2_SDM_MCS11 = 63,
+ WL_RATE_2X2_SDM_MCS12 = 64,
+ WL_RATE_2X2_SDM_MCS13 = 65,
+ WL_RATE_2X2_SDM_MCS14 = 66,
+ WL_RATE_2X2_SDM_MCS15 = 67,
+ WL_RATE_P_2X2_SDM_MCS99 = 68,
+ WL_RATE_P_2X2_SDM_MCS100 = 69,
+
+ WL_RATE_2X2_VHT0SS2 = 60,
+ WL_RATE_2X2_VHT1SS2 = 61,
+ WL_RATE_2X2_VHT2SS2 = 62,
+ WL_RATE_2X2_VHT3SS2 = 63,
+ WL_RATE_2X2_VHT4SS2 = 64,
+ WL_RATE_2X2_VHT5SS2 = 65,
+ WL_RATE_2X2_VHT6SS2 = 66,
+ WL_RATE_2X2_VHT7SS2 = 67,
+ WL_RATE_2X2_VHT8SS2 = 68,
+ WL_RATE_2X2_VHT9SS2 = 69,
+ WL_RATE_P_2X2_VHT10SS2 = 70,
+ WL_RATE_P_2X2_VHT11SS2 = 71,
+
+ WL_RATE_1X2_TXBF_OFDM_6 = 72,
+ WL_RATE_1X2_TXBF_OFDM_9 = 73,
+ WL_RATE_1X2_TXBF_OFDM_12 = 74,
+ WL_RATE_1X2_TXBF_OFDM_18 = 75,
+ WL_RATE_1X2_TXBF_OFDM_24 = 76,
+ WL_RATE_1X2_TXBF_OFDM_36 = 77,
+ WL_RATE_1X2_TXBF_OFDM_48 = 78,
+ WL_RATE_1X2_TXBF_OFDM_54 = 79,
+
+ WL_RATE_1X2_TXBF_MCS0 = 80,
+ WL_RATE_1X2_TXBF_MCS1 = 81,
+ WL_RATE_1X2_TXBF_MCS2 = 82,
+ WL_RATE_1X2_TXBF_MCS3 = 83,
+ WL_RATE_1X2_TXBF_MCS4 = 84,
+ WL_RATE_1X2_TXBF_MCS5 = 85,
+ WL_RATE_1X2_TXBF_MCS6 = 86,
+ WL_RATE_1X2_TXBF_MCS7 = 87,
+ WL_RATE_P_1X2_TXBF_MCS87 = 88,
+ WL_RATE_P_1X2_TXBF_MCS88 = 89,
+
+ WL_RATE_1X2_TXBF_VHT0SS1 = 80,
+ WL_RATE_1X2_TXBF_VHT1SS1 = 81,
+ WL_RATE_1X2_TXBF_VHT2SS1 = 82,
+ WL_RATE_1X2_TXBF_VHT3SS1 = 83,
+ WL_RATE_1X2_TXBF_VHT4SS1 = 84,
+ WL_RATE_1X2_TXBF_VHT5SS1 = 85,
+ WL_RATE_1X2_TXBF_VHT6SS1 = 86,
+ WL_RATE_1X2_TXBF_VHT7SS1 = 87,
+ WL_RATE_1X2_TXBF_VHT8SS1 = 88,
+ WL_RATE_1X2_TXBF_VHT9SS1 = 89,
+ WL_RATE_P_1X2_TXBF_VHT10SS1 = 90,
+ WL_RATE_P_1X2_TXBF_VHT11SS1 = 91,
+
+ WL_RATE_2X2_TXBF_SDM_MCS8 = 92,
+ WL_RATE_2X2_TXBF_SDM_MCS9 = 93,
+ WL_RATE_2X2_TXBF_SDM_MCS10 = 94,
+ WL_RATE_2X2_TXBF_SDM_MCS11 = 95,
+ WL_RATE_2X2_TXBF_SDM_MCS12 = 96,
+ WL_RATE_2X2_TXBF_SDM_MCS13 = 97,
+ WL_RATE_2X2_TXBF_SDM_MCS14 = 98,
+ WL_RATE_2X2_TXBF_SDM_MCS15 = 99,
+ WL_RATE_P_2X2_TXBF_SDM_MCS99 = 100,
+ WL_RATE_P_2X2_TXBF_SDM_MCS100 = 101,
+
+ WL_RATE_2X2_TXBF_VHT0SS2 = 92,
+ WL_RATE_2X2_TXBF_VHT1SS2 = 93,
+ WL_RATE_2X2_TXBF_VHT2SS2 = 94,
+ WL_RATE_2X2_TXBF_VHT3SS2 = 95,
+ WL_RATE_2X2_TXBF_VHT4SS2 = 96,
+ WL_RATE_2X2_TXBF_VHT5SS2 = 97,
+ WL_RATE_2X2_TXBF_VHT6SS2 = 98,
+ WL_RATE_2X2_TXBF_VHT7SS2 = 99,
+ WL_RATE_2X2_TXBF_VHT8SS2 = 100,
+ WL_RATE_2X2_TXBF_VHT9SS2 = 101,
+ WL_RATE_P_2X2_TXBF_VHT10SS2 = 102,
+ WL_RATE_P_2X2_TXBF_VHT11SS2 = 103,
+
+ WL_RATE_1X3_DSSS_1 = 104,
+ WL_RATE_1X3_DSSS_2 = 105,
+ WL_RATE_1X3_DSSS_5_5 = 106,
+ WL_RATE_1X3_DSSS_11 = 107,
+
+ WL_RATE_1X3_CDD_OFDM_6 = 108,
+ WL_RATE_1X3_CDD_OFDM_9 = 109,
+ WL_RATE_1X3_CDD_OFDM_12 = 110,
+ WL_RATE_1X3_CDD_OFDM_18 = 111,
+ WL_RATE_1X3_CDD_OFDM_24 = 112,
+ WL_RATE_1X3_CDD_OFDM_36 = 113,
+ WL_RATE_1X3_CDD_OFDM_48 = 114,
+ WL_RATE_1X3_CDD_OFDM_54 = 115,
+
+ WL_RATE_1X3_CDD_MCS0 = 116,
+ WL_RATE_1X3_CDD_MCS1 = 117,
+ WL_RATE_1X3_CDD_MCS2 = 118,
+ WL_RATE_1X3_CDD_MCS3 = 119,
+ WL_RATE_1X3_CDD_MCS4 = 120,
+ WL_RATE_1X3_CDD_MCS5 = 121,
+ WL_RATE_1X3_CDD_MCS6 = 122,
+ WL_RATE_1X3_CDD_MCS7 = 123,
+ WL_RATE_P_1X3_CDD_MCS87 = 124,
+ WL_RATE_P_1X3_CDD_MCS88 = 125,
+
+ WL_RATE_1X3_VHT0SS1 = 116,
+ WL_RATE_1X3_VHT1SS1 = 117,
+ WL_RATE_1X3_VHT2SS1 = 118,
+ WL_RATE_1X3_VHT3SS1 = 119,
+ WL_RATE_1X3_VHT4SS1 = 120,
+ WL_RATE_1X3_VHT5SS1 = 121,
+ WL_RATE_1X3_VHT6SS1 = 122,
+ WL_RATE_1X3_VHT7SS1 = 123,
+ WL_RATE_1X3_VHT8SS1 = 124,
+ WL_RATE_1X3_VHT9SS1 = 125,
+ WL_RATE_P_1X3_VHT10SS1 = 126,
+ WL_RATE_P_1X3_VHT11SS1 = 127,
+
+ WL_RATE_2X3_STBC_MCS0 = 128,
+ WL_RATE_2X3_STBC_MCS1 = 129,
+ WL_RATE_2X3_STBC_MCS2 = 130,
+ WL_RATE_2X3_STBC_MCS3 = 131,
+ WL_RATE_2X3_STBC_MCS4 = 132,
+ WL_RATE_2X3_STBC_MCS5 = 133,
+ WL_RATE_2X3_STBC_MCS6 = 134,
+ WL_RATE_2X3_STBC_MCS7 = 135,
+ WL_RATE_P_2X3_STBC_MCS87 = 136,
+ WL_RATE_P_2X3_STBC_MCS88 = 137,
+
+ WL_RATE_2X3_STBC_VHT0SS1 = 128,
+ WL_RATE_2X3_STBC_VHT1SS1 = 129,
+ WL_RATE_2X3_STBC_VHT2SS1 = 130,
+ WL_RATE_2X3_STBC_VHT3SS1 = 131,
+ WL_RATE_2X3_STBC_VHT4SS1 = 132,
+ WL_RATE_2X3_STBC_VHT5SS1 = 133,
+ WL_RATE_2X3_STBC_VHT6SS1 = 134,
+ WL_RATE_2X3_STBC_VHT7SS1 = 135,
+ WL_RATE_2X3_STBC_VHT8SS1 = 136,
+ WL_RATE_2X3_STBC_VHT9SS1 = 137,
+ WL_RATE_P_2X3_STBC_VHT10SS1 = 138,
+ WL_RATE_P_2X3_STBC_VHT11SS1 = 139,
+
+ WL_RATE_2X3_SDM_MCS8 = 140,
+ WL_RATE_2X3_SDM_MCS9 = 141,
+ WL_RATE_2X3_SDM_MCS10 = 142,
+ WL_RATE_2X3_SDM_MCS11 = 143,
+ WL_RATE_2X3_SDM_MCS12 = 144,
+ WL_RATE_2X3_SDM_MCS13 = 145,
+ WL_RATE_2X3_SDM_MCS14 = 146,
+ WL_RATE_2X3_SDM_MCS15 = 147,
+ WL_RATE_P_2X3_SDM_MCS99 = 148,
+ WL_RATE_P_2X3_SDM_MCS100 = 149,
+
+ WL_RATE_2X3_VHT0SS2 = 140,
+ WL_RATE_2X3_VHT1SS2 = 141,
+ WL_RATE_2X3_VHT2SS2 = 142,
+ WL_RATE_2X3_VHT3SS2 = 143,
+ WL_RATE_2X3_VHT4SS2 = 144,
+ WL_RATE_2X3_VHT5SS2 = 145,
+ WL_RATE_2X3_VHT6SS2 = 146,
+ WL_RATE_2X3_VHT7SS2 = 147,
+ WL_RATE_2X3_VHT8SS2 = 148,
+ WL_RATE_2X3_VHT9SS2 = 149,
+ WL_RATE_P_2X3_VHT10SS2 = 150,
+ WL_RATE_P_2X3_VHT11SS2 = 151,
+
+ WL_RATE_3X3_SDM_MCS16 = 152,
+ WL_RATE_3X3_SDM_MCS17 = 153,
+ WL_RATE_3X3_SDM_MCS18 = 154,
+ WL_RATE_3X3_SDM_MCS19 = 155,
+ WL_RATE_3X3_SDM_MCS20 = 156,
+ WL_RATE_3X3_SDM_MCS21 = 157,
+ WL_RATE_3X3_SDM_MCS22 = 158,
+ WL_RATE_3X3_SDM_MCS23 = 159,
+ WL_RATE_P_3X3_SDM_MCS101 = 160,
+ WL_RATE_P_3X3_SDM_MCS102 = 161,
+
+ WL_RATE_3X3_VHT0SS3 = 152,
+ WL_RATE_3X3_VHT1SS3 = 153,
+ WL_RATE_3X3_VHT2SS3 = 154,
+ WL_RATE_3X3_VHT3SS3 = 155,
+ WL_RATE_3X3_VHT4SS3 = 156,
+ WL_RATE_3X3_VHT5SS3 = 157,
+ WL_RATE_3X3_VHT6SS3 = 158,
+ WL_RATE_3X3_VHT7SS3 = 159,
+ WL_RATE_3X3_VHT8SS3 = 160,
+ WL_RATE_3X3_VHT9SS3 = 161,
+ WL_RATE_P_3X3_VHT10SS3 = 162,
+ WL_RATE_P_3X3_VHT11SS3 = 163,
+
+ WL_RATE_1X3_TXBF_OFDM_6 = 164,
+ WL_RATE_1X3_TXBF_OFDM_9 = 165,
+ WL_RATE_1X3_TXBF_OFDM_12 = 166,
+ WL_RATE_1X3_TXBF_OFDM_18 = 167,
+ WL_RATE_1X3_TXBF_OFDM_24 = 168,
+ WL_RATE_1X3_TXBF_OFDM_36 = 169,
+ WL_RATE_1X3_TXBF_OFDM_48 = 170,
+ WL_RATE_1X3_TXBF_OFDM_54 = 171,
+
+ WL_RATE_1X3_TXBF_MCS0 = 172,
+ WL_RATE_1X3_TXBF_MCS1 = 173,
+ WL_RATE_1X3_TXBF_MCS2 = 174,
+ WL_RATE_1X3_TXBF_MCS3 = 175,
+ WL_RATE_1X3_TXBF_MCS4 = 176,
+ WL_RATE_1X3_TXBF_MCS5 = 177,
+ WL_RATE_1X3_TXBF_MCS6 = 178,
+ WL_RATE_1X3_TXBF_MCS7 = 179,
+ WL_RATE_P_1X3_TXBF_MCS87 = 180,
+ WL_RATE_P_1X3_TXBF_MCS88 = 181,
+
+ WL_RATE_1X3_TXBF_VHT0SS1 = 172,
+ WL_RATE_1X3_TXBF_VHT1SS1 = 173,
+ WL_RATE_1X3_TXBF_VHT2SS1 = 174,
+ WL_RATE_1X3_TXBF_VHT3SS1 = 175,
+ WL_RATE_1X3_TXBF_VHT4SS1 = 176,
+ WL_RATE_1X3_TXBF_VHT5SS1 = 177,
+ WL_RATE_1X3_TXBF_VHT6SS1 = 178,
+ WL_RATE_1X3_TXBF_VHT7SS1 = 179,
+ WL_RATE_1X3_TXBF_VHT8SS1 = 180,
+ WL_RATE_1X3_TXBF_VHT9SS1 = 181,
+ WL_RATE_P_1X3_TXBF_VHT10SS1 = 182,
+ WL_RATE_P_1X3_TXBF_VHT11SS1 = 183,
+
+ WL_RATE_2X3_TXBF_SDM_MCS8 = 184,
+ WL_RATE_2X3_TXBF_SDM_MCS9 = 185,
+ WL_RATE_2X3_TXBF_SDM_MCS10 = 186,
+ WL_RATE_2X3_TXBF_SDM_MCS11 = 187,
+ WL_RATE_2X3_TXBF_SDM_MCS12 = 188,
+ WL_RATE_2X3_TXBF_SDM_MCS13 = 189,
+ WL_RATE_2X3_TXBF_SDM_MCS14 = 190,
+ WL_RATE_2X3_TXBF_SDM_MCS15 = 191,
+ WL_RATE_P_2X3_TXBF_SDM_MCS99 = 192,
+ WL_RATE_P_2X3_TXBF_SDM_MCS100 = 193,
+
+ WL_RATE_2X3_TXBF_VHT0SS2 = 184,
+ WL_RATE_2X3_TXBF_VHT1SS2 = 185,
+ WL_RATE_2X3_TXBF_VHT2SS2 = 186,
+ WL_RATE_2X3_TXBF_VHT3SS2 = 187,
+ WL_RATE_2X3_TXBF_VHT4SS2 = 188,
+ WL_RATE_2X3_TXBF_VHT5SS2 = 189,
+ WL_RATE_2X3_TXBF_VHT6SS2 = 190,
+ WL_RATE_2X3_TXBF_VHT7SS2 = 191,
+ WL_RATE_2X3_TXBF_VHT8SS2 = 192,
+ WL_RATE_2X3_TXBF_VHT9SS2 = 193,
+ WL_RATE_P_2X3_TXBF_VHT10SS2 = 194,
+ WL_RATE_P_2X3_TXBF_VHT11SS2 = 195,
+
+ WL_RATE_3X3_TXBF_SDM_MCS16 = 196,
+ WL_RATE_3X3_TXBF_SDM_MCS17 = 197,
+ WL_RATE_3X3_TXBF_SDM_MCS18 = 198,
+ WL_RATE_3X3_TXBF_SDM_MCS19 = 199,
+ WL_RATE_3X3_TXBF_SDM_MCS20 = 200,
+ WL_RATE_3X3_TXBF_SDM_MCS21 = 201,
+ WL_RATE_3X3_TXBF_SDM_MCS22 = 202,
+ WL_RATE_3X3_TXBF_SDM_MCS23 = 203,
+ WL_RATE_P_3X3_TXBF_SDM_MCS101 = 204,
+ WL_RATE_P_3X3_TXBF_SDM_MCS102 = 205,
+
+ WL_RATE_3X3_TXBF_VHT0SS3 = 196,
+ WL_RATE_3X3_TXBF_VHT1SS3 = 197,
+ WL_RATE_3X3_TXBF_VHT2SS3 = 198,
+ WL_RATE_3X3_TXBF_VHT3SS3 = 199,
+ WL_RATE_3X3_TXBF_VHT4SS3 = 200,
+ WL_RATE_3X3_TXBF_VHT5SS3 = 201,
+ WL_RATE_3X3_TXBF_VHT6SS3 = 202,
+ WL_RATE_3X3_TXBF_VHT7SS3 = 203,
+ WL_RATE_3X3_TXBF_VHT8SS3 = 204,
+ WL_RATE_3X3_TXBF_VHT9SS3 = 205,
+ WL_RATE_P_3X3_TXBF_VHT10SS3 = 206,
+ WL_RATE_P_3X3_TXBF_VHT11SS3 = 207,
+
+ WL_RATE_1X4_DSSS_1 = 208,
+ WL_RATE_1X4_DSSS_2 = 209,
+ WL_RATE_1X4_DSSS_5_5 = 210,
+ WL_RATE_1X4_DSSS_11 = 211,
+
+ WL_RATE_1X4_CDD_OFDM_6 = 212,
+ WL_RATE_1X4_CDD_OFDM_9 = 213,
+ WL_RATE_1X4_CDD_OFDM_12 = 214,
+ WL_RATE_1X4_CDD_OFDM_18 = 215,
+ WL_RATE_1X4_CDD_OFDM_24 = 216,
+ WL_RATE_1X4_CDD_OFDM_36 = 217,
+ WL_RATE_1X4_CDD_OFDM_48 = 218,
+ WL_RATE_1X4_CDD_OFDM_54 = 219,
+
+ WL_RATE_1X4_CDD_MCS0 = 220,
+ WL_RATE_1X4_CDD_MCS1 = 221,
+ WL_RATE_1X4_CDD_MCS2 = 222,
+ WL_RATE_1X4_CDD_MCS3 = 223,
+ WL_RATE_1X4_CDD_MCS4 = 224,
+ WL_RATE_1X4_CDD_MCS5 = 225,
+ WL_RATE_1X4_CDD_MCS6 = 226,
+ WL_RATE_1X4_CDD_MCS7 = 227,
+ WL_RATE_P_1X4_CDD_MCS87 = 228,
+ WL_RATE_P_1X4_CDD_MCS88 = 229,
+
+ WL_RATE_1X4_VHT0SS1 = 220,
+ WL_RATE_1X4_VHT1SS1 = 221,
+ WL_RATE_1X4_VHT2SS1 = 222,
+ WL_RATE_1X4_VHT3SS1 = 223,
+ WL_RATE_1X4_VHT4SS1 = 224,
+ WL_RATE_1X4_VHT5SS1 = 225,
+ WL_RATE_1X4_VHT6SS1 = 226,
+ WL_RATE_1X4_VHT7SS1 = 227,
+ WL_RATE_1X4_VHT8SS1 = 228,
+ WL_RATE_1X4_VHT9SS1 = 229,
+ WL_RATE_P_1X4_VHT10SS1 = 230,
+ WL_RATE_P_1X4_VHT11SS1 = 231,
+
+ WL_RATE_2X4_STBC_MCS0 = 232,
+ WL_RATE_2X4_STBC_MCS1 = 233,
+ WL_RATE_2X4_STBC_MCS2 = 234,
+ WL_RATE_2X4_STBC_MCS3 = 235,
+ WL_RATE_2X4_STBC_MCS4 = 236,
+ WL_RATE_2X4_STBC_MCS5 = 237,
+ WL_RATE_2X4_STBC_MCS6 = 238,
+ WL_RATE_2X4_STBC_MCS7 = 239,
+ WL_RATE_P_2X4_STBC_MCS87 = 240,
+ WL_RATE_P_2X4_STBC_MCS88 = 241,
+
+ WL_RATE_2X4_STBC_VHT0SS1 = 232,
+ WL_RATE_2X4_STBC_VHT1SS1 = 233,
+ WL_RATE_2X4_STBC_VHT2SS1 = 234,
+ WL_RATE_2X4_STBC_VHT3SS1 = 235,
+ WL_RATE_2X4_STBC_VHT4SS1 = 236,
+ WL_RATE_2X4_STBC_VHT5SS1 = 237,
+ WL_RATE_2X4_STBC_VHT6SS1 = 238,
+ WL_RATE_2X4_STBC_VHT7SS1 = 239,
+ WL_RATE_2X4_STBC_VHT8SS1 = 240,
+ WL_RATE_2X4_STBC_VHT9SS1 = 241,
+ WL_RATE_P_2X4_STBC_VHT10SS1 = 242,
+ WL_RATE_P_2X4_STBC_VHT11SS1 = 243,
+
+ WL_RATE_2X4_SDM_MCS8 = 244,
+ WL_RATE_2X4_SDM_MCS9 = 245,
+ WL_RATE_2X4_SDM_MCS10 = 246,
+ WL_RATE_2X4_SDM_MCS11 = 247,
+ WL_RATE_2X4_SDM_MCS12 = 248,
+ WL_RATE_2X4_SDM_MCS13 = 249,
+ WL_RATE_2X4_SDM_MCS14 = 250,
+ WL_RATE_2X4_SDM_MCS15 = 251,
+ WL_RATE_P_2X4_SDM_MCS99 = 252,
+ WL_RATE_P_2X4_SDM_MCS100 = 253,
+
+ WL_RATE_2X4_VHT0SS2 = 244,
+ WL_RATE_2X4_VHT1SS2 = 245,
+ WL_RATE_2X4_VHT2SS2 = 246,
+ WL_RATE_2X4_VHT3SS2 = 247,
+ WL_RATE_2X4_VHT4SS2 = 248,
+ WL_RATE_2X4_VHT5SS2 = 249,
+ WL_RATE_2X4_VHT6SS2 = 250,
+ WL_RATE_2X4_VHT7SS2 = 251,
+ WL_RATE_2X4_VHT8SS2 = 252,
+ WL_RATE_2X4_VHT9SS2 = 253,
+ WL_RATE_P_2X4_VHT10SS2 = 254,
+ WL_RATE_P_2X4_VHT11SS2 = 255,
+
+ WL_RATE_3X4_SDM_MCS16 = 256,
+ WL_RATE_3X4_SDM_MCS17 = 257,
+ WL_RATE_3X4_SDM_MCS18 = 258,
+ WL_RATE_3X4_SDM_MCS19 = 259,
+ WL_RATE_3X4_SDM_MCS20 = 260,
+ WL_RATE_3X4_SDM_MCS21 = 261,
+ WL_RATE_3X4_SDM_MCS22 = 262,
+ WL_RATE_3X4_SDM_MCS23 = 263,
+ WL_RATE_P_3X4_SDM_MCS101 = 264,
+ WL_RATE_P_3X4_SDM_MCS102 = 265,
+
+ WL_RATE_3X4_VHT0SS3 = 256,
+ WL_RATE_3X4_VHT1SS3 = 257,
+ WL_RATE_3X4_VHT2SS3 = 258,
+ WL_RATE_3X4_VHT3SS3 = 259,
+ WL_RATE_3X4_VHT4SS3 = 260,
+ WL_RATE_3X4_VHT5SS3 = 261,
+ WL_RATE_3X4_VHT6SS3 = 262,
+ WL_RATE_3X4_VHT7SS3 = 263,
+ WL_RATE_3X4_VHT8SS3 = 264,
+ WL_RATE_3X4_VHT9SS3 = 265,
+ WL_RATE_P_3X4_VHT10SS3 = 266,
+ WL_RATE_P_3X4_VHT11SS3 = 267,
+
+ WL_RATE_4X4_SDM_MCS24 = 268,
+ WL_RATE_4X4_SDM_MCS25 = 269,
+ WL_RATE_4X4_SDM_MCS26 = 270,
+ WL_RATE_4X4_SDM_MCS27 = 271,
+ WL_RATE_4X4_SDM_MCS28 = 272,
+ WL_RATE_4X4_SDM_MCS29 = 273,
+ WL_RATE_4X4_SDM_MCS30 = 274,
+ WL_RATE_4X4_SDM_MCS31 = 275,
+ WL_RATE_P_4X4_SDM_MCS103 = 276,
+ WL_RATE_P_4X4_SDM_MCS104 = 277,
+
+ WL_RATE_4X4_VHT0SS4 = 268,
+ WL_RATE_4X4_VHT1SS4 = 269,
+ WL_RATE_4X4_VHT2SS4 = 270,
+ WL_RATE_4X4_VHT3SS4 = 271,
+ WL_RATE_4X4_VHT4SS4 = 272,
+ WL_RATE_4X4_VHT5SS4 = 273,
+ WL_RATE_4X4_VHT6SS4 = 274,
+ WL_RATE_4X4_VHT7SS4 = 275,
+ WL_RATE_4X4_VHT8SS4 = 276,
+ WL_RATE_4X4_VHT9SS4 = 277,
+ WL_RATE_P_4X4_VHT10SS4 = 278,
+ WL_RATE_P_4X4_VHT11SS4 = 279,
+
+ WL_RATE_1X4_TXBF_OFDM_6 = 280,
+ WL_RATE_1X4_TXBF_OFDM_9 = 281,
+ WL_RATE_1X4_TXBF_OFDM_12 = 282,
+ WL_RATE_1X4_TXBF_OFDM_18 = 283,
+ WL_RATE_1X4_TXBF_OFDM_24 = 284,
+ WL_RATE_1X4_TXBF_OFDM_36 = 285,
+ WL_RATE_1X4_TXBF_OFDM_48 = 286,
+ WL_RATE_1X4_TXBF_OFDM_54 = 287,
+
+ WL_RATE_1X4_TXBF_MCS0 = 288,
+ WL_RATE_1X4_TXBF_MCS1 = 289,
+ WL_RATE_1X4_TXBF_MCS2 = 290,
+ WL_RATE_1X4_TXBF_MCS3 = 291,
+ WL_RATE_1X4_TXBF_MCS4 = 292,
+ WL_RATE_1X4_TXBF_MCS5 = 293,
+ WL_RATE_1X4_TXBF_MCS6 = 294,
+ WL_RATE_1X4_TXBF_MCS7 = 295,
+ WL_RATE_P_1X4_TXBF_MCS87 = 296,
+ WL_RATE_P_1X4_TXBF_MCS88 = 297,
+
+ WL_RATE_1X4_TXBF_VHT0SS1 = 288,
+ WL_RATE_1X4_TXBF_VHT1SS1 = 289,
+ WL_RATE_1X4_TXBF_VHT2SS1 = 290,
+ WL_RATE_1X4_TXBF_VHT3SS1 = 291,
+ WL_RATE_1X4_TXBF_VHT4SS1 = 292,
+ WL_RATE_1X4_TXBF_VHT5SS1 = 293,
+ WL_RATE_1X4_TXBF_VHT6SS1 = 294,
+ WL_RATE_1X4_TXBF_VHT7SS1 = 295,
+ WL_RATE_1X4_TXBF_VHT8SS1 = 296,
+ WL_RATE_1X4_TXBF_VHT9SS1 = 297,
+ WL_RATE_P_1X4_TXBF_VHT10SS1 = 298,
+ WL_RATE_P_1X4_TXBF_VHT11SS1 = 299,
+
+ WL_RATE_2X4_TXBF_SDM_MCS8 = 300,
+ WL_RATE_2X4_TXBF_SDM_MCS9 = 301,
+ WL_RATE_2X4_TXBF_SDM_MCS10 = 302,
+ WL_RATE_2X4_TXBF_SDM_MCS11 = 303,
+ WL_RATE_2X4_TXBF_SDM_MCS12 = 304,
+ WL_RATE_2X4_TXBF_SDM_MCS13 = 305,
+ WL_RATE_2X4_TXBF_SDM_MCS14 = 306,
+ WL_RATE_2X4_TXBF_SDM_MCS15 = 307,
+ WL_RATE_P_2X4_TXBF_SDM_MCS99 = 308,
+ WL_RATE_P_2X4_TXBF_SDM_MCS100 = 309,
+
+ WL_RATE_2X4_TXBF_VHT0SS2 = 300,
+ WL_RATE_2X4_TXBF_VHT1SS2 = 301,
+ WL_RATE_2X4_TXBF_VHT2SS2 = 302,
+ WL_RATE_2X4_TXBF_VHT3SS2 = 303,
+ WL_RATE_2X4_TXBF_VHT4SS2 = 304,
+ WL_RATE_2X4_TXBF_VHT5SS2 = 305,
+ WL_RATE_2X4_TXBF_VHT6SS2 = 306,
+ WL_RATE_2X4_TXBF_VHT7SS2 = 307,
+ WL_RATE_2X4_TXBF_VHT8SS2 = 308,
+ WL_RATE_2X4_TXBF_VHT9SS2 = 309,
+ WL_RATE_P_2X4_TXBF_VHT10SS2 = 310,
+ WL_RATE_P_2X4_TXBF_VHT11SS2 = 311,
+
+ WL_RATE_3X4_TXBF_SDM_MCS16 = 312,
+ WL_RATE_3X4_TXBF_SDM_MCS17 = 313,
+ WL_RATE_3X4_TXBF_SDM_MCS18 = 314,
+ WL_RATE_3X4_TXBF_SDM_MCS19 = 315,
+ WL_RATE_3X4_TXBF_SDM_MCS20 = 316,
+ WL_RATE_3X4_TXBF_SDM_MCS21 = 317,
+ WL_RATE_3X4_TXBF_SDM_MCS22 = 318,
+ WL_RATE_3X4_TXBF_SDM_MCS23 = 319,
+ WL_RATE_P_3X4_TXBF_SDM_MCS101 = 320,
+ WL_RATE_P_3X4_TXBF_SDM_MCS102 = 321,
+
+ WL_RATE_3X4_TXBF_VHT0SS3 = 312,
+ WL_RATE_3X4_TXBF_VHT1SS3 = 313,
+ WL_RATE_3X4_TXBF_VHT2SS3 = 314,
+ WL_RATE_3X4_TXBF_VHT3SS3 = 315,
+ WL_RATE_3X4_TXBF_VHT4SS3 = 316,
+ WL_RATE_3X4_TXBF_VHT5SS3 = 317,
+ WL_RATE_3X4_TXBF_VHT6SS3 = 318,
+ WL_RATE_3X4_TXBF_VHT7SS3 = 319,
+ WL_RATE_P_3X4_TXBF_VHT8SS3 = 320,
+ WL_RATE_P_3X4_TXBF_VHT9SS3 = 321,
+ WL_RATE_P_3X4_TXBF_VHT10SS3 = 322,
+ WL_RATE_P_3X4_TXBF_VHT11SS3 = 323,
+
+ WL_RATE_4X4_TXBF_SDM_MCS24 = 324,
+ WL_RATE_4X4_TXBF_SDM_MCS25 = 325,
+ WL_RATE_4X4_TXBF_SDM_MCS26 = 326,
+ WL_RATE_4X4_TXBF_SDM_MCS27 = 327,
+ WL_RATE_4X4_TXBF_SDM_MCS28 = 328,
+ WL_RATE_4X4_TXBF_SDM_MCS29 = 329,
+ WL_RATE_4X4_TXBF_SDM_MCS30 = 330,
+ WL_RATE_4X4_TXBF_SDM_MCS31 = 331,
+ WL_RATE_P_4X4_TXBF_SDM_MCS103 = 332,
+ WL_RATE_P_4X4_TXBF_SDM_MCS104 = 333,
+
+ WL_RATE_4X4_TXBF_VHT0SS4 = 324,
+ WL_RATE_4X4_TXBF_VHT1SS4 = 325,
+ WL_RATE_4X4_TXBF_VHT2SS4 = 326,
+ WL_RATE_4X4_TXBF_VHT3SS4 = 327,
+ WL_RATE_4X4_TXBF_VHT4SS4 = 328,
+ WL_RATE_4X4_TXBF_VHT5SS4 = 329,
+ WL_RATE_4X4_TXBF_VHT6SS4 = 330,
+ WL_RATE_4X4_TXBF_VHT7SS4 = 331,
+ WL_RATE_P_4X4_TXBF_VHT8SS4 = 332,
+ WL_RATE_P_4X4_TXBF_VHT9SS4 = 333,
+ WL_RATE_P_4X4_TXBF_VHT10SS4 = 334,
+ WL_RATE_P_4X4_TXBF_VHT11SS4 = 335
+
+} clm_rates_t;
+
+#define WL_NUMRATES 336
+
+#endif
diff --git a/src/shared/linux_osl.c b/src/shared/linux_osl.c
new file mode 100644
index 0000000..6157d18
--- /dev/null
+++ b/src/shared/linux_osl.c
@@ -0,0 +1,1107 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: linux_osl.c 383331 2013-02-06 10:27:24Z $
+ */
+
+#define LINUX_PORT
+
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <linuxver.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <linux/delay.h>
+#include <pcicfg.h>
+
+#include <linux/fs.h>
+
+#define PCI_CFG_RETRY 10
+
+#define OS_HANDLE_MAGIC 0x1234abcd
+#define BCM_MEM_FILENAME_LEN 24
+
+typedef struct bcm_mem_link {
+ struct bcm_mem_link *prev;
+ struct bcm_mem_link *next;
+ uint size;
+ int line;
+ void *osh;
+ char file[BCM_MEM_FILENAME_LEN];
+} bcm_mem_link_t;
+
+struct osl_info {
+ osl_pubinfo_t pub;
+ uint magic;
+ void *pdev;
+ atomic_t malloced;
+ atomic_t pktalloced;
+ uint failed;
+ uint bustype;
+ bcm_mem_link_t *dbgmem_list;
+ spinlock_t dbgmem_lock;
+ spinlock_t pktalloc_lock;
+};
+
+#define OSL_PKTTAG_CLEAR(p) \
+do { \
+ struct sk_buff *s = (struct sk_buff *)(p); \
+ ASSERT(OSL_PKTTAG_SZ == 32); \
+ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \
+ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
+ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
+ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
+} while (0)
+
+uint32 g_assert_type = FALSE;
+
+static int16 linuxbcmerrormap[] =
+{ 0,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -E2BIG,
+ -E2BIG,
+ -EBUSY,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EFAULT,
+ -ENOMEM,
+ -EOPNOTSUPP,
+ -EMSGSIZE,
+ -EINVAL,
+ -EPERM,
+ -ENOMEM,
+ -EINVAL,
+ -ERANGE,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EIO,
+ -ENODEV,
+ -EINVAL,
+ -EIO,
+ -EIO,
+ -ENODEV,
+ -EINVAL,
+ -ENODATA,
+ -EINVAL,
+
+#if BCME_LAST != -43
+#error "You need to add a OS error translation in the linuxbcmerrormap \
+ for new error code defined in bcmutils.h"
+#endif
+};
+
+int
+osl_error(int bcmerror)
+{
+ if (bcmerror > 0)
+ bcmerror = 0;
+ else if (bcmerror < BCME_LAST)
+ bcmerror = BCME_ERROR;
+
+ return linuxbcmerrormap[-bcmerror];
+}
+
+extern uint8* dhd_os_prealloc(void *osh, int section, int size);
+
+osl_t *
+osl_attach(void *pdev, uint bustype, bool pkttag)
+{
+ osl_t *osh;
+
+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
+ ASSERT(osh);
+
+ bzero(osh, sizeof(osl_t));
+
+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
+
+ osh->magic = OS_HANDLE_MAGIC;
+ atomic_set(&osh->malloced, 0);
+ osh->failed = 0;
+ osh->dbgmem_list = NULL;
+ spin_lock_init(&(osh->dbgmem_lock));
+ osh->pdev = pdev;
+ osh->pub.pkttag = pkttag;
+ osh->bustype = bustype;
+
+ switch (bustype) {
+ case PCI_BUS:
+ case SI_BUS:
+ case PCMCIA_BUS:
+ osh->pub.mmbus = TRUE;
+ break;
+ case JTAG_BUS:
+ case SDIO_BUS:
+ case USB_BUS:
+ case SPI_BUS:
+ case RPC_BUS:
+ osh->pub.mmbus = FALSE;
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ spin_lock_init(&(osh->pktalloc_lock));
+
+#ifdef BCMDBG
+ if (pkttag) {
+ struct sk_buff *skb;
+ BCM_REFERENCE(skb);
+ ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb));
+ }
+#endif
+ return osh;
+}
+
+void
+osl_detach(osl_t *osh)
+{
+ if (osh == NULL)
+ return;
+
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ kfree(osh);
+}
+
+static struct sk_buff *osl_alloc_skb(unsigned int len)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+ gfp_t flags = GFP_ATOMIC;
+ struct sk_buff *skb;
+
+ skb = __dev_alloc_skb(len, flags);
+ return skb;
+#else
+ return dev_alloc_skb(len);
+#endif
+}
+
+struct sk_buff * BCMFASTPATH
+osl_pkt_tonative(osl_t *osh, void *pkt)
+{
+ struct sk_buff *nskb;
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(pkt);
+
+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+ atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced);
+
+ }
+ return (struct sk_buff *)pkt;
+}
+
+void * BCMFASTPATH
+osl_pkt_frmnative(osl_t *osh, void *pkt)
+{
+ struct sk_buff *nskb;
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(pkt);
+
+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+ atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced);
+
+ }
+ return (void *)pkt;
+}
+
+void * BCMFASTPATH
+osl_pktget(osl_t *osh, uint len)
+{
+ struct sk_buff *skb;
+
+ if ((skb = osl_alloc_skb(len))) {
+#ifdef BCMDBG
+ skb_put(skb, len);
+#else
+ skb->tail += len;
+ skb->len += len;
+#endif
+ skb->priority = 0;
+
+ atomic_inc(&osh->pktalloced);
+ }
+
+ return ((void*) skb);
+}
+
+void BCMFASTPATH
+osl_pktfree(osl_t *osh, void *p, bool send)
+{
+ struct sk_buff *skb, *nskb;
+
+ skb = (struct sk_buff*) p;
+
+ if (send && osh->pub.tx_fn)
+ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0);
+
+ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE);
+
+ while (skb) {
+ nskb = skb->next;
+ skb->next = NULL;
+
+ {
+ if (skb->destructor)
+
+ dev_kfree_skb_any(skb);
+ else
+
+ dev_kfree_skb(skb);
+ }
+ atomic_dec(&osh->pktalloced);
+ skb = nskb;
+ }
+}
+
+uint32
+osl_pci_read_config(osl_t *osh, uint offset, uint size)
+{
+ uint val = 0;
+ uint retry = PCI_CFG_RETRY;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ ASSERT(size == 4);
+
+ do {
+ pci_read_config_dword(osh->pdev, offset, &val);
+ if (val != 0xffffffff)
+ break;
+ } while (retry--);
+
+#ifdef BCMDBG
+ if (retry < PCI_CFG_RETRY)
+ printk("PCI CONFIG READ access to %d required %d retries\n", offset,
+ (PCI_CFG_RETRY - retry));
+#endif
+
+ return (val);
+}
+
+void
+osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
+{
+ uint retry = PCI_CFG_RETRY;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ ASSERT(size == 4);
+
+ do {
+ pci_write_config_dword(osh->pdev, offset, val);
+ if (offset != PCI_BAR0_WIN)
+ break;
+ if (osl_pci_read_config(osh, offset, size) == val)
+ break;
+ } while (retry--);
+
+#ifdef BCMDBG
+ if (retry < PCI_CFG_RETRY)
+ printk("PCI CONFIG WRITE access to %d required %d retries\n", offset,
+ (PCI_CFG_RETRY - retry));
+#endif
+}
+
+uint
+osl_pci_bus(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+ return ((struct pci_dev *)osh->pdev)->bus->number;
+}
+
+uint
+osl_pci_slot(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1;
+#else
+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
+#endif
+}
+
+struct pci_dev *
+osl_pci_device(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+ return osh->pdev;
+}
+
+static void
+osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write)
+{
+}
+
+void
+osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE);
+}
+
+void
+osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE);
+}
+
+#ifdef BCMDBG_MEM
+
+static
+#endif
+void *
+osl_malloc(osl_t *osh, uint size)
+{
+ void *addr;
+
+ if (osh)
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+
+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
+ if (osh)
+ osh->failed++;
+ return (NULL);
+ }
+ if (osh)
+ atomic_add(size, &osh->malloced);
+
+ return (addr);
+}
+
+#ifdef BCMDBG_MEM
+
+static
+#endif
+void
+osl_mfree(osl_t *osh, void *addr, uint size)
+{
+ if (osh) {
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ atomic_sub(size, &osh->malloced);
+ }
+ kfree(addr);
+}
+
+uint
+osl_malloced(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (atomic_read(&osh->malloced));
+}
+
+uint
+osl_malloc_failed(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (osh->failed);
+}
+
+#ifdef BCMDBG_MEM
+#define MEMLIST_LOCK(osh, flags) spin_lock_irqsave(&(osh)->dbgmem_lock, flags)
+#define MEMLIST_UNLOCK(osh, flags) spin_unlock_irqrestore(&(osh)->dbgmem_lock, flags)
+
+void *
+osl_debug_malloc(osl_t *osh, uint size, int line, const char* file)
+{
+ bcm_mem_link_t *p;
+ const char* basename;
+ unsigned long flags = 0;
+
+ if (!size) {
+ printk("%s: allocating zero sized mem at %s line %d\n", __FUNCTION__, file, line);
+ ASSERT(0);
+ }
+
+ if (osh) {
+ MEMLIST_LOCK(osh, flags);
+ }
+ if ((p = (bcm_mem_link_t*)osl_malloc(osh, sizeof(bcm_mem_link_t) + size)) == NULL) {
+ if (osh) {
+ MEMLIST_UNLOCK(osh, flags);
+ }
+ return (NULL);
+ }
+
+ p->size = size;
+ p->line = line;
+ p->osh = (void *)osh;
+
+ basename = strrchr(file, '/');
+
+ if (basename)
+ basename++;
+
+ if (!basename)
+ basename = file;
+
+ strncpy(p->file, basename, BCM_MEM_FILENAME_LEN);
+ p->file[BCM_MEM_FILENAME_LEN - 1] = '\0';
+
+ if (osh) {
+ p->prev = NULL;
+ p->next = osh->dbgmem_list;
+ if (p->next)
+ p->next->prev = p;
+ osh->dbgmem_list = p;
+ MEMLIST_UNLOCK(osh, flags);
+ }
+
+ return p + 1;
+}
+
+void
+osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, const char* file)
+{
+ bcm_mem_link_t *p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t));
+ unsigned long flags = 0;
+
+ ASSERT(osh == NULL || osh->magic == OS_HANDLE_MAGIC);
+
+ if (p->size == 0) {
+ printk("osl_debug_mfree: double free on addr %p size %d at line %d file %s\n",
+ addr, size, line, file);
+ ASSERT(p->size);
+ return;
+ }
+
+ if (p->size != size) {
+ printk("%s: dealloca size does not match alloc size\n", __FUNCTION__);
+ printk("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
+ printk("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
+ ASSERT(p->size == size);
+ return;
+ }
+
+ if (p->osh != (void *)osh) {
+ printk("osl_debug_mfree: alloc osh %p does not match dealloc osh %p\n",
+ p->osh, osh);
+ printk("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
+ printk("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
+ ASSERT(p->osh == (void *)osh);
+ return;
+ }
+
+ if (osh) {
+ MEMLIST_LOCK(osh, flags);
+ if (p->prev)
+ p->prev->next = p->next;
+ if (p->next)
+ p->next->prev = p->prev;
+ if (osh->dbgmem_list == p)
+ osh->dbgmem_list = p->next;
+ p->next = p->prev = NULL;
+ }
+ p->size = 0;
+
+ osl_mfree(osh, p, size + sizeof(bcm_mem_link_t));
+ if (osh) {
+ MEMLIST_UNLOCK(osh, flags);
+ }
+}
+
+int
+osl_debug_memdump(osl_t *osh, struct bcmstrbuf *b)
+{
+ bcm_mem_link_t *p;
+ unsigned long flags = 0;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ MEMLIST_LOCK(osh, flags);
+ if (osh->dbgmem_list) {
+ if (b != NULL)
+ bcm_bprintf(b, " Address Size File:line\n");
+ else
+ printf(" Address Size File:line\n");
+
+ for (p = osh->dbgmem_list; p; p = p->next) {
+ if (b != NULL)
+ bcm_bprintf(b, "%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
+ p->size, p->file, p->line);
+ else
+ printf("%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
+ p->size, p->file, p->line);
+
+ if (p == p->next) {
+ if (b != NULL)
+ bcm_bprintf(b, "WARNING: loop-to-self "
+ "p %p p->next %p\n", p, p->next);
+ else
+ printf("WARNING: loop-to-self "
+ "p %p p->next %p\n", p, p->next);
+
+ break;
+ }
+ }
+ }
+ MEMLIST_UNLOCK(osh, flags);
+
+ return 0;
+}
+
+#endif
+
+uint
+osl_dma_consistent_align(void)
+{
+ return (PAGE_SIZE);
+}
+
+void*
+osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap)
+{
+ void *va;
+ uint16 align = (1 << align_bits);
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
+ size += align;
+ *alloced = size;
+
+#ifdef __ARM_ARCH_7A__
+ va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
+ if (va)
+ *pap = (ulong)__virt_to_phys(va);
+#else
+ va = pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap);
+#endif
+ return va;
+}
+
+void
+osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+#ifdef __ARM_ARCH_7A__
+ kfree(va);
+#else
+ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
+#endif
+}
+
+uint BCMFASTPATH
+osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah)
+{
+ int dir;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+
+#if defined(__ARM_ARCH_7A__) && defined(BCMDMASGLISTOSL)
+ if (dmah != NULL) {
+ int32 nsegs, i, totsegs = 0, totlen = 0;
+ struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2];
+ struct sk_buff *skb;
+ for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) {
+ sg = &_sg[totsegs];
+ if (skb_is_nonlinear(skb)) {
+ nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb));
+ ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS));
+ pci_map_sg(osh->pdev, sg, nsegs, dir);
+ } else {
+ nsegs = 1;
+ ASSERT(totsegs + nsegs <= MAX_DMA_SEGS);
+ sg->page_link = 0;
+ sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb));
+ pci_map_single(osh->pdev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir);
+ }
+ totsegs += nsegs;
+ totlen += PKTLEN(osh, skb);
+ }
+ dmah->nsegs = totsegs;
+ dmah->origsize = totlen;
+ for (i = 0, sg = _sg; i < totsegs; i++, sg++) {
+ dmah->segs[i].addr = sg_phys(sg);
+ dmah->segs[i].length = sg->length;
+ }
+ return dmah->segs[0].addr;
+ }
+#endif
+
+ return (pci_map_single(osh->pdev, va, size, dir));
+}
+
+void BCMFASTPATH
+osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction)
+{
+ int dir;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+ pci_unmap_single(osh->pdev, (uint32)pa, size, dir);
+}
+
+#if defined(BCMDBG_ASSERT)
+void
+osl_assert(const char *exp, const char *file, int line)
+{
+ char tempbuf[256];
+ const char *basename;
+
+ basename = strrchr(file, '/');
+
+ if (basename)
+ basename++;
+
+ if (!basename)
+ basename = file;
+
+#ifdef BCMDBG_ASSERT
+ snprintf(tempbuf, 256, "assertion \"%s\" failed: file \"%s\", line %d\n",
+ exp, basename, line);
+
+ if (!in_interrupt() && g_assert_type != 1) {
+ const int delay = 3;
+ printk("%s", tempbuf);
+ printk("panic in %d seconds\n", delay);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(delay * HZ);
+ }
+
+ switch (g_assert_type) {
+ case 0:
+ panic("%s", tempbuf);
+ break;
+ case 1:
+ printk("%s", tempbuf);
+ break;
+ case 2:
+ printk("%s", tempbuf);
+ BUG();
+ break;
+ default:
+ break;
+ }
+#endif
+
+}
+#endif
+
+void
+osl_delay(uint usec)
+{
+ uint d;
+
+ while (usec > 0) {
+ d = MIN(usec, 1000);
+ udelay(d);
+ usec -= d;
+ }
+}
+
+void *
+osl_pktdup(osl_t *osh, void *skb)
+{
+ void * p;
+
+ ASSERT(!PKTISCHAINED(skb));
+
+ PKTCTFMAP(osh, skb);
+
+ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL)
+ return NULL;
+
+ PKTSETCLINK(p, NULL);
+ PKTCCLRFLAGS(p);
+ PKTCSETCNT(p, 1);
+ PKTCSETLEN(p, PKTLEN(osh, skb));
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(p);
+
+ atomic_inc(&osh->pktalloced);
+ return (p);
+}
+
+uint32
+osl_sysuptime(void)
+{
+ return ((uint32)jiffies * (1000 / HZ));
+}
+
+int
+osl_printf(const char *format, ...)
+{
+ va_list args;
+ static char printbuf[1024];
+ int len;
+
+ va_start(args, format);
+ len = vsnprintf(printbuf, 1024, format, args);
+ va_end(args);
+
+ if (len > sizeof(printbuf)) {
+ printk("osl_printf: buffer overrun\n");
+ return (0);
+ }
+
+ return (printk("%s", printbuf));
+}
+
+int
+osl_sprintf(char *buf, const char *format, ...)
+{
+ va_list args;
+ int rc;
+
+ va_start(args, format);
+ rc = vsprintf(buf, format, args);
+ va_end(args);
+ return (rc);
+}
+
+int
+osl_snprintf(char *buf, size_t n, const char *format, ...)
+{
+ va_list args;
+ int rc;
+
+ va_start(args, format);
+ rc = vsnprintf(buf, n, format, args);
+ va_end(args);
+ return (rc);
+}
+
+int
+osl_vsprintf(char *buf, const char *format, va_list ap)
+{
+ return (vsprintf(buf, format, ap));
+}
+
+int
+osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap)
+{
+ return (vsnprintf(buf, n, format, ap));
+}
+
+int
+osl_strcmp(const char *s1, const char *s2)
+{
+ return (strcmp(s1, s2));
+}
+
+int
+osl_strncmp(const char *s1, const char *s2, uint n)
+{
+ return (strncmp(s1, s2, n));
+}
+
+int
+osl_strlen(const char *s)
+{
+ return (strlen(s));
+}
+
+char*
+osl_strcpy(char *d, const char *s)
+{
+ return (strcpy(d, s));
+}
+
+char*
+osl_strncpy(char *d, const char *s, uint n)
+{
+ return (strncpy(d, s, n));
+}
+
+char*
+osl_strchr(const char *s, int c)
+{
+ return (strchr(s, c));
+}
+
+char*
+osl_strrchr(const char *s, int c)
+{
+ return (strrchr(s, c));
+}
+
+void*
+osl_memset(void *d, int c, size_t n)
+{
+ return memset(d, c, n);
+}
+
+void*
+osl_memcpy(void *d, const void *s, size_t n)
+{
+ return memcpy(d, s, n);
+}
+
+void*
+osl_memmove(void *d, const void *s, size_t n)
+{
+ return memmove(d, s, n);
+}
+
+int
+osl_memcmp(const void *s1, const void *s2, size_t n)
+{
+ return memcmp(s1, s2, n);
+}
+
+uint32
+osl_readl(volatile uint32 *r)
+{
+ return (readl(r));
+}
+
+uint16
+osl_readw(volatile uint16 *r)
+{
+ return (readw(r));
+}
+
+uint8
+osl_readb(volatile uint8 *r)
+{
+ return (readb(r));
+}
+
+void
+osl_writel(uint32 v, volatile uint32 *r)
+{
+ writel(v, r);
+}
+
+void
+osl_writew(uint16 v, volatile uint16 *r)
+{
+ writew(v, r);
+}
+
+void
+osl_writeb(uint8 v, volatile uint8 *r)
+{
+ writeb(v, r);
+}
+
+void *
+osl_uncached(void *va)
+{
+ return ((void*)va);
+}
+
+void *
+osl_cached(void *va)
+{
+ return ((void*)va);
+}
+
+uint
+osl_getcycles(void)
+{
+ uint cycles;
+
+#if defined(__i386__)
+ rdtscl(cycles);
+#else
+ cycles = 0;
+#endif
+ return cycles;
+}
+
+void *
+osl_reg_map(uint32 pa, uint size)
+{
+ return (ioremap_nocache((unsigned long)pa, (unsigned long)size));
+}
+
+void
+osl_reg_unmap(void *va)
+{
+ iounmap(va);
+}
+
+int
+osl_busprobe(uint32 *val, uint32 addr)
+{
+ *val = readl((uint32 *)(uintptr)addr);
+ return 0;
+}
+
+bool
+osl_pktshared(void *skb)
+{
+ return (((struct sk_buff*)skb)->cloned);
+}
+
+uchar*
+osl_pktdata(osl_t *osh, void *skb)
+{
+ return (((struct sk_buff*)skb)->data);
+}
+
+uint
+osl_pktlen(osl_t *osh, void *skb)
+{
+ return (((struct sk_buff*)skb)->len);
+}
+
+uint
+osl_pktheadroom(osl_t *osh, void *skb)
+{
+ return (uint) skb_headroom((struct sk_buff *) skb);
+}
+
+uint
+osl_pkttailroom(osl_t *osh, void *skb)
+{
+ return (uint) skb_tailroom((struct sk_buff *) skb);
+}
+
+void*
+osl_pktnext(osl_t *osh, void *skb)
+{
+ return (((struct sk_buff*)skb)->next);
+}
+
+void
+osl_pktsetnext(void *skb, void *x)
+{
+ ((struct sk_buff*)skb)->next = (struct sk_buff*)x;
+}
+
+void
+osl_pktsetlen(osl_t *osh, void *skb, uint len)
+{
+ __skb_trim((struct sk_buff*)skb, len);
+}
+
+uchar*
+osl_pktpush(osl_t *osh, void *skb, int bytes)
+{
+ return (skb_push((struct sk_buff*)skb, bytes));
+}
+
+uchar*
+osl_pktpull(osl_t *osh, void *skb, int bytes)
+{
+ return (skb_pull((struct sk_buff*)skb, bytes));
+}
+
+void*
+osl_pkttag(void *skb)
+{
+ return ((void*)(((struct sk_buff*)skb)->cb));
+}
+
+void*
+osl_pktlink(void *skb)
+{
+ return (((struct sk_buff*)skb)->prev);
+}
+
+void
+osl_pktsetlink(void *skb, void *x)
+{
+ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x;
+}
+
+uint
+osl_pktprio(void *skb)
+{
+ return (((struct sk_buff*)skb)->priority);
+}
+
+void
+osl_pktsetprio(void *skb, uint x)
+{
+ ((struct sk_buff*)skb)->priority = x;
+}
+
+uint
+osl_pktalloced(osl_t *osh)
+{
+ return (atomic_read(&osh->pktalloced));
+}
+
+void *
+osl_os_open_image(char *filename)
+{
+ struct file *fp;
+
+ fp = filp_open(filename, O_RDONLY, 0);
+
+ if (IS_ERR(fp))
+ fp = NULL;
+
+ return fp;
+}
+
+int
+osl_os_get_image_block(char *buf, int len, void *image)
+{
+ struct file *fp = (struct file *)image;
+ int rdlen;
+
+ if (!image)
+ return 0;
+
+ rdlen = kernel_read(fp, fp->f_pos, buf, len);
+ if (rdlen > 0)
+ fp->f_pos += rdlen;
+
+ return rdlen;
+}
+
+void
+osl_os_close_image(void *image)
+{
+ if (image)
+ filp_close((struct file *)image, NULL);
+}
+
+int
+osl_os_image_size(void *image)
+{
+ int len = 0, curroffset;
+
+ if (image) {
+
+ curroffset = generic_file_llseek(image, 0, 1);
+
+ len = generic_file_llseek(image, 0, 2);
+
+ generic_file_llseek(image, curroffset, 0);
+ }
+ return len;
+}
diff --git a/src/wl/sys/wl_cfg80211_hybrid.c b/src/wl/sys/wl_cfg80211_hybrid.c
new file mode 100644
index 0000000..7b606e0
--- /dev/null
+++ b/src/wl/sys/wl_cfg80211_hybrid.c
@@ -0,0 +1,3022 @@
+/*
+ * Linux-specific portion of Broadcom 802.11abg Networking Device Driver
+ * cfg80211 interface
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_cfg80211.c,v 1.1.6.4 2011-02-11 00:22:09 $
+ */
+
+#if defined(USE_CFG80211)
+
+#define LINUX_PORT
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <linux/nl80211.h>
+#include <net/rtnetlink.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <wlioctl.h>
+#include <proto/802.11.h>
+#include <wl_cfg80211_hybrid.h>
+
+#define EVENT_TYPE(e) dtoh32((e)->event_type)
+#define EVENT_FLAGS(e) dtoh16((e)->flags)
+#define EVENT_STATUS(e) dtoh32((e)->status)
+
+#ifdef BCMDBG
+u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
+#else
+u32 wl_dbg_level = WL_DBG_ERR;
+#endif
+
+static s32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+ enum nl80211_iftype type, u32 *flags, struct vif_params *params);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy,
+ struct cfg80211_scan_request *request);
+#else
+static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request);
+#endif
+static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
+static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params);
+static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
+static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac, struct station_info *sinfo);
+#else
+static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *mac, struct station_info *sinfo);
+#endif
+
+static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev, bool enabled, s32 timeout);
+static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 dbm);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+ enum nl80211_tx_power_setting type, s32 dbm);
+#else
+static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+ enum tx_power_setting type, s32 dbm);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, s32 *dbm);
+#else
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx, bool unicast, bool multicast);
+#else
+static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params);
+static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr);
+static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
+ void *cookie, void (*callback) (void *cookie, struct key_params *params));
+#else
+static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr, struct key_params *params);
+static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr);
+static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr,
+ void *cookie, void (*callback) (void *cookie, struct key_params *params));
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev);
+#endif
+
+static s32 wl_create_event_handler(struct wl_cfg80211_priv *wl);
+static void wl_destroy_event_handler(struct wl_cfg80211_priv *wl);
+static s32 wl_event_handler(void *data);
+static void wl_init_eq(struct wl_cfg80211_priv *wl);
+static void wl_flush_eq(struct wl_cfg80211_priv *wl);
+static void wl_lock_eq(struct wl_cfg80211_priv *wl);
+static void wl_unlock_eq(struct wl_cfg80211_priv *wl);
+static void wl_init_eq_lock(struct wl_cfg80211_priv *wl);
+static void wl_init_eloop_handler(struct wl_cfg80211_event_loop *el);
+static struct wl_cfg80211_event_q *wl_deq_event(struct wl_cfg80211_priv *wl);
+static s32 wl_enq_event(struct wl_cfg80211_priv *wl, u32 type,
+ const wl_event_msg_t *msg, void *data);
+static void wl_put_event(struct wl_cfg80211_event_q *e);
+static void wl_wakeup_event(struct wl_cfg80211_priv *wl);
+
+static s32 wl_notify_connect_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_roaming_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_scan_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_bss_connect_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed);
+static s32 wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_mic_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+
+static s32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, s32 buf_len);
+static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len);
+static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
+static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval);
+static s32 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len);
+
+static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
+static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
+static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
+
+static void wl_init_prof(struct wl_cfg80211_profile *prof);
+
+static s32 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_get_assoc_ies(struct wl_cfg80211_priv *wl);
+static void wl_ch_to_chanspec(struct ieee80211_channel *chan,
+ struct wl_join_params *join_params, size_t *join_params_size);
+
+static void wl_rst_ie(struct wl_cfg80211_priv *wl);
+static __used s32 wl_add_ie(struct wl_cfg80211_priv *wl, u8 t, u8 l, u8 *v);
+static s32 wl_mrg_ie(struct wl_cfg80211_priv *wl, u8 *ie_stream, u16 ie_size);
+static s32 wl_cp_ie(struct wl_cfg80211_priv *wl, u8 *dst, u16 dst_size);
+static u32 wl_get_ielen(struct wl_cfg80211_priv *wl);
+
+static s32 wl_mode_to_nl80211_iftype(s32 mode);
+
+static s32 wl_alloc_wdev(struct device *dev, struct wireless_dev **rwdev);
+static void wl_free_wdev(struct wl_cfg80211_priv *wl);
+
+static s32 wl_inform_bss(struct wl_cfg80211_priv *wl, struct wl_scan_results *bss_list);
+static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info *bi);
+static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl);
+
+static void key_endian_to_device(struct wl_wsec_key *key);
+static void key_endian_to_host(struct wl_wsec_key *key);
+
+static s32 wl_init_priv_mem(struct wl_cfg80211_priv *wl);
+static void wl_deinit_priv_mem(struct wl_cfg80211_priv *wl);
+
+static bool wl_is_ibssmode(struct wl_cfg80211_priv *wl);
+
+static void wl_link_up(struct wl_cfg80211_priv *wl);
+static void wl_link_down(struct wl_cfg80211_priv *wl);
+static s32 wl_set_mode(struct net_device *ndev, s32 iftype);
+
+static void wl_init_conf(struct wl_cfg80211_conf *conf);
+
+static s32 wl_update_wiphybands(struct wl_cfg80211_priv *wl);
+
+static __used s32 wl_update_pmklist(struct net_device *dev,
+ struct wl_cfg80211_pmk_list *pmk_list, s32 err);
+
+#if defined(WL_DBGMSG_ENABLE)
+#define WL_DBG_ESTR_MAX 32
+static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
+ "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
+ "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
+ "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
+ "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
+ "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
+ "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
+ "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
+ "PFN_NET_LOST",
+ "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
+ "IBSS_ASSOC",
+ "RADIO", "PSM_WATCHDOG",
+ "PROBREQ_MSG",
+ "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
+ "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
+ "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
+ "IF",
+ "RSSI", "PFN_SCAN_COMPLETE", "ACTION_FRAME", "ACTION_FRAME_COMPLETE",
+};
+#endif
+
+#define CHAN2G(_channel, _freq, _flags) { \
+ .band = IEEE80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define CHAN5G(_channel, _flags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = 5000 + (5 * (_channel)), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
+#define RATETAB_ENT(_rateid, _flags) \
+ { \
+ .bitrate = RATE_TO_BASE100KBPS(_rateid), \
+ .hw_value = (_rateid), \
+ .flags = (_flags), \
+ }
+
+static struct ieee80211_rate __wl_rates[] = {
+ RATETAB_ENT(DOT11_RATE_1M, 0),
+ RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_6M, 0),
+ RATETAB_ENT(DOT11_RATE_9M, 0),
+ RATETAB_ENT(DOT11_RATE_12M, 0),
+ RATETAB_ENT(DOT11_RATE_18M, 0),
+ RATETAB_ENT(DOT11_RATE_24M, 0),
+ RATETAB_ENT(DOT11_RATE_36M, 0),
+ RATETAB_ENT(DOT11_RATE_48M, 0),
+ RATETAB_ENT(DOT11_RATE_54M, 0),
+};
+
+#define wl_a_rates (__wl_rates + 4)
+#define wl_a_rates_size 8
+#define wl_g_rates (__wl_rates + 0)
+#define wl_g_rates_size 12
+
+static struct ieee80211_channel __wl_2ghz_channels[] = {
+ CHAN2G(1, 2412, 0),
+ CHAN2G(2, 2417, 0),
+ CHAN2G(3, 2422, 0),
+ CHAN2G(4, 2427, 0),
+ CHAN2G(5, 2432, 0),
+ CHAN2G(6, 2437, 0),
+ CHAN2G(7, 2442, 0),
+ CHAN2G(8, 2447, 0),
+ CHAN2G(9, 2452, 0),
+ CHAN2G(10, 2457, 0),
+ CHAN2G(11, 2462, 0),
+ CHAN2G(12, 2467, 0),
+ CHAN2G(13, 2472, 0),
+ CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel __wl_5ghz_a_channels[] = {
+ CHAN5G(34, 0), CHAN5G(36, 0),
+ CHAN5G(38, 0), CHAN5G(40, 0),
+ CHAN5G(42, 0), CHAN5G(44, 0),
+ CHAN5G(46, 0), CHAN5G(48, 0),
+ CHAN5G(52, 0), CHAN5G(56, 0),
+ CHAN5G(60, 0), CHAN5G(64, 0),
+ CHAN5G(100, 0), CHAN5G(104, 0),
+ CHAN5G(108, 0), CHAN5G(112, 0),
+ CHAN5G(116, 0), CHAN5G(120, 0),
+ CHAN5G(124, 0), CHAN5G(128, 0),
+ CHAN5G(132, 0), CHAN5G(136, 0),
+ CHAN5G(140, 0), CHAN5G(149, 0),
+ CHAN5G(153, 0), CHAN5G(157, 0),
+ CHAN5G(161, 0), CHAN5G(165, 0),
+ CHAN5G(184, 0), CHAN5G(188, 0),
+ CHAN5G(192, 0), CHAN5G(196, 0),
+ CHAN5G(200, 0), CHAN5G(204, 0),
+ CHAN5G(208, 0), CHAN5G(212, 0),
+ CHAN5G(216, 0),
+};
+
+static struct ieee80211_channel __wl_5ghz_n_channels[] = {
+ CHAN5G(32, 0), CHAN5G(34, 0),
+ CHAN5G(36, 0), CHAN5G(38, 0),
+ CHAN5G(40, 0), CHAN5G(42, 0),
+ CHAN5G(44, 0), CHAN5G(46, 0),
+ CHAN5G(48, 0), CHAN5G(50, 0),
+ CHAN5G(52, 0), CHAN5G(54, 0),
+ CHAN5G(56, 0), CHAN5G(58, 0),
+ CHAN5G(60, 0), CHAN5G(62, 0),
+ CHAN5G(64, 0), CHAN5G(66, 0),
+ CHAN5G(68, 0), CHAN5G(70, 0),
+ CHAN5G(72, 0), CHAN5G(74, 0),
+ CHAN5G(76, 0), CHAN5G(78, 0),
+ CHAN5G(80, 0), CHAN5G(82, 0),
+ CHAN5G(84, 0), CHAN5G(86, 0),
+ CHAN5G(88, 0), CHAN5G(90, 0),
+ CHAN5G(92, 0), CHAN5G(94, 0),
+ CHAN5G(96, 0), CHAN5G(98, 0),
+ CHAN5G(100, 0), CHAN5G(102, 0),
+ CHAN5G(104, 0), CHAN5G(106, 0),
+ CHAN5G(108, 0), CHAN5G(110, 0),
+ CHAN5G(112, 0), CHAN5G(114, 0),
+ CHAN5G(116, 0), CHAN5G(118, 0),
+ CHAN5G(120, 0), CHAN5G(122, 0),
+ CHAN5G(124, 0), CHAN5G(126, 0),
+ CHAN5G(128, 0), CHAN5G(130, 0),
+ CHAN5G(132, 0), CHAN5G(134, 0),
+ CHAN5G(136, 0), CHAN5G(138, 0),
+ CHAN5G(140, 0), CHAN5G(142, 0),
+ CHAN5G(144, 0), CHAN5G(145, 0),
+ CHAN5G(146, 0), CHAN5G(147, 0),
+ CHAN5G(148, 0), CHAN5G(149, 0),
+ CHAN5G(150, 0), CHAN5G(151, 0),
+ CHAN5G(152, 0), CHAN5G(153, 0),
+ CHAN5G(154, 0), CHAN5G(155, 0),
+ CHAN5G(156, 0), CHAN5G(157, 0),
+ CHAN5G(158, 0), CHAN5G(159, 0),
+ CHAN5G(160, 0), CHAN5G(161, 0),
+ CHAN5G(162, 0), CHAN5G(163, 0),
+ CHAN5G(164, 0), CHAN5G(165, 0),
+ CHAN5G(166, 0), CHAN5G(168, 0),
+ CHAN5G(170, 0), CHAN5G(172, 0),
+ CHAN5G(174, 0), CHAN5G(176, 0),
+ CHAN5G(178, 0), CHAN5G(180, 0),
+ CHAN5G(182, 0), CHAN5G(184, 0),
+ CHAN5G(186, 0), CHAN5G(188, 0),
+ CHAN5G(190, 0), CHAN5G(192, 0),
+ CHAN5G(194, 0), CHAN5G(196, 0),
+ CHAN5G(198, 0), CHAN5G(200, 0),
+ CHAN5G(202, 0), CHAN5G(204, 0),
+ CHAN5G(206, 0), CHAN5G(208, 0),
+ CHAN5G(210, 0), CHAN5G(212, 0),
+ CHAN5G(214, 0), CHAN5G(216, 0),
+ CHAN5G(218, 0), CHAN5G(220, 0),
+ CHAN5G(222, 0), CHAN5G(224, 0),
+ CHAN5G(226, 0), CHAN5G(228, 0),
+};
+
+static struct ieee80211_supported_band __wl_band_2ghz = {
+ .band = IEEE80211_BAND_2GHZ,
+ .channels = __wl_2ghz_channels,
+ .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
+ .bitrates = wl_g_rates,
+ .n_bitrates = wl_g_rates_size,
+};
+
+static struct ieee80211_supported_band __wl_band_5ghz_a = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = __wl_5ghz_a_channels,
+ .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
+ .bitrates = wl_a_rates,
+ .n_bitrates = wl_a_rates_size,
+};
+
+static struct ieee80211_supported_band __wl_band_5ghz_n = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = __wl_5ghz_n_channels,
+ .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
+ .bitrates = wl_a_rates,
+ .n_bitrates = wl_a_rates_size,
+};
+
+static const u32 __wl_cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_AES_CMAC,
+};
+
+static void key_endian_to_device(struct wl_wsec_key *key)
+{
+ key->index = htod32(key->index);
+ key->len = htod32(key->len);
+ key->algo = htod32(key->algo);
+ key->flags = htod32(key->flags);
+ key->rxiv.hi = htod32(key->rxiv.hi);
+ key->rxiv.lo = htod16(key->rxiv.lo);
+ key->iv_initialized = htod32(key->iv_initialized);
+}
+
+static void key_endian_to_host(struct wl_wsec_key *key)
+{
+ key->index = dtoh32(key->index);
+ key->len = dtoh32(key->len);
+ key->algo = dtoh32(key->algo);
+ key->flags = dtoh32(key->flags);
+ key->rxiv.hi = dtoh32(key->rxiv.hi);
+ key->rxiv.lo = dtoh16(key->rxiv.lo);
+ key->iv_initialized = dtoh32(key->iv_initialized);
+}
+
+static s32
+wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
+{
+ struct ifreq ifr;
+ struct wl_ioctl ioc;
+ mm_segment_t fs;
+ s32 err = 0;
+
+ BUG_ON(len < sizeof(int));
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t)&ioc;
+
+ fs = get_fs();
+ set_fs(get_ds());
+#if defined(WL_USE_NETDEV_OPS)
+ err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#else
+ err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif
+ set_fs(fs);
+
+ return err;
+}
+
+static s32
+wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct wireless_dev *wdev;
+ s32 infra = 0;
+ s32 ap = 0;
+ s32 err = 0;
+
+ switch (type) {
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ WL_ERR(("type (%d) : currently we do not support this type\n",
+ type));
+ return -EOPNOTSUPP;
+ case NL80211_IFTYPE_ADHOC:
+ wl->conf->mode = WL_MODE_IBSS;
+ break;
+ case NL80211_IFTYPE_STATION:
+ wl->conf->mode = WL_MODE_BSS;
+ infra = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ infra = htod32(infra);
+ ap = htod32(ap);
+ wdev = ndev->ieee80211_ptr;
+ wdev->iftype = type;
+ WL_DBG(("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra));
+ err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+ if (err) {
+ WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+ return err;
+ }
+ err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
+ if (err) {
+ WL_ERR(("WLC_SET_AP error (%d)\n", err));
+ return err;
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy,
+ struct cfg80211_scan_request *request)
+#else
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy,
+ struct net_device *ndev,
+ struct cfg80211_scan_request *request)
+#endif
+
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+ struct net_device *ndev = request->wdev->netdev;
+#endif
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ struct cfg80211_ssid *ssids;
+ struct wl_cfg80211_scan_req *sr = wl_to_sr(wl);
+ s32 passive_scan;
+ s32 err = 0;
+
+ if (request) {
+ ssids = request->ssids;
+ }
+ else {
+
+ ssids = NULL;
+ }
+ wl->scan_request = request;
+
+ memset(&sr->ssid, 0, sizeof(sr->ssid));
+
+ if (ssids) {
+ WL_DBG(("ssid \"%s\", ssid_len (%d)\n", ssids->ssid, ssids->ssid_len));
+ sr->ssid.SSID_len = min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
+ }
+
+ if (sr->ssid.SSID_len) {
+ memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
+ sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
+ WL_DBG(("Specific scan ssid=\"%s\" len=%d\n", sr->ssid.SSID, sr->ssid.SSID_len));
+ } else {
+ WL_DBG(("Broadcast scan\n"));
+ }
+ WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
+ passive_scan = wl->active_scan ? 0 : 1;
+ err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan));
+ if (err) {
+ WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
+ goto scan_out;
+ }
+ err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid, sizeof(sr->ssid));
+ if (err) {
+ if (err == -EBUSY) {
+ WL_INF(("system busy : scan for \"%s\" "
+ "canceled\n", sr->ssid.SSID));
+ } else {
+ WL_ERR(("WLC_SCAN error (%d)\n", err));
+ }
+ goto scan_out;
+ }
+
+ return 0;
+
+scan_out:
+ wl->scan_request = NULL;
+ return err;
+}
+
+static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
+{
+ s8 buf[WLC_IOCTL_SMLEN];
+ u32 len;
+ s32 err = 0;
+
+ val = htod32(val);
+ len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+ BUG_ON(!len);
+
+ err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ }
+
+ return err;
+}
+
+static s32
+wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
+{
+ union {
+ s8 buf[WLC_IOCTL_SMLEN];
+ s32 val;
+ } var;
+ u32 len;
+ u32 data_null;
+ s32 err = 0;
+
+ len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
+ BUG_ON(!len);
+ err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ }
+ *retval = dtoh32(var.val);
+
+ return err;
+}
+
+static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
+{
+ s32 err = 0;
+
+ err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold);
+ if (err) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
+{
+ s32 err = 0;
+
+ err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold);
+ if (err) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
+{
+ s32 err = 0;
+ u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
+
+ retry = htod32(retry);
+ err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
+ if (err) {
+ WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
+ s32 err = 0;
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+ (wl->conf->rts_threshold != wiphy->rts_threshold)) {
+ wl->conf->rts_threshold = wiphy->rts_threshold;
+ err = wl_set_rts(ndev, wl->conf->rts_threshold);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+ (wl->conf->frag_threshold != wiphy->frag_threshold)) {
+ wl->conf->frag_threshold = wiphy->frag_threshold;
+ err = wl_set_frag(ndev, wl->conf->frag_threshold);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_RETRY_LONG && (wl->conf->retry_long != wiphy->retry_long)) {
+ wl->conf->retry_long = wiphy->retry_long;
+ err = wl_set_retry(ndev, wl->conf->retry_long, true);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_RETRY_SHORT && (wl->conf->retry_short != wiphy->retry_short)) {
+ wl->conf->retry_short = wiphy->retry_short;
+ err = wl_set_retry(ndev, wl->conf->retry_short, false);
+ if (!err) {
+ return err;
+ }
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params)
+{
+ struct wl_join_params join_params;
+ size_t join_params_size;
+ s32 val;
+ s32 err = 0;
+
+ WL_DBG(("\n"));
+
+ if (params->bssid) {
+ WL_ERR(("Invalid bssid\n"));
+ return -EOPNOTSUPP;
+ }
+
+ if ((err = wl_dev_intvar_set(dev, "auth", 0))) {
+ return err;
+ }
+ if ((err = wl_dev_intvar_set(dev, "wpa_auth", WPA_AUTH_NONE))) {
+ return err;
+ }
+ if ((err = wl_dev_intvar_get(dev, "wsec", &val))) {
+ return err;
+ }
+ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
+ if ((err = wl_dev_intvar_set(dev, "wsec", val))) {
+ return err;
+ }
+
+ memset(&join_params, 0, sizeof(join_params));
+ join_params_size = sizeof(join_params.ssid);
+
+ memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, params->ssid_len);
+ join_params.ssid.SSID_len = htod32(params->ssid_len);
+ if (params->bssid)
+ memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
+ else
+ memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+ wl_ch_to_chanspec(params->chandef.chan, &join_params, &join_params_size);
+#else
+ wl_ch_to_chanspec(params->channel, &join_params, &join_params_size);
+#endif
+ err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+ if (err) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ s32 err = 0;
+
+ WL_DBG(("\n"));
+
+ wl_link_down(wl);
+
+ return err;
+}
+
+static s32
+wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 val = 0;
+ s32 err = 0;
+
+ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+ else
+ val = WPA_AUTH_DISABLED;
+ WL_DBG(("setting wpa_auth to 0x%0x\n", val));
+ err = wl_dev_intvar_set(dev, "wpa_auth", val);
+ if (err) {
+ WL_ERR(("set wpa_auth failed (%d)\n", err));
+ return err;
+ }
+ wl->profile->sec.wpa_versions = sme->crypto.wpa_versions;
+ return err;
+}
+
+static s32
+wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 val = 0;
+ s32 err = 0;
+
+ switch (sme->auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ val = 0;
+ WL_DBG(("open system\n"));
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ val = 1;
+ WL_DBG(("shared key\n"));
+ break;
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ val = 2;
+ WL_DBG(("automatic\n"));
+ break;
+ case NL80211_AUTHTYPE_NETWORK_EAP:
+ WL_DBG(("network eap\n"));
+ default:
+ val = 2;
+ WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
+ break;
+ }
+
+ err = wl_dev_intvar_set(dev, "auth", val);
+ if (err) {
+ WL_ERR(("set auth failed (%d)\n", err));
+ return err;
+ }
+
+ wl->profile->sec.auth_type = sme->auth_type;
+ return err;
+}
+
+static s32
+wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 pval = 0;
+ s32 gval = 0;
+ s32 val = 0;
+ s32 err = 0;
+
+ if (sme->crypto.n_ciphers_pairwise) {
+ switch (sme->crypto.ciphers_pairwise[0]) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ pval = WEP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ pval = TKIP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ pval = AES_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ pval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]));
+ return -EINVAL;
+ }
+ }
+ if (sme->crypto.cipher_group) {
+ switch (sme->crypto.cipher_group) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ gval = WEP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ gval = TKIP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ gval = AES_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ gval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
+ return -EINVAL;
+ }
+ }
+
+ if ((err = wl_dev_intvar_get(dev, "wsec", &val))) {
+ return err;
+ }
+ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
+ val |= pval | gval;
+ WL_DBG(("set wsec to %d\n", val));
+ err = wl_dev_intvar_set(dev, "wsec", val);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ wl->profile->sec.cipher_pairwise = sme->crypto.ciphers_pairwise[0];
+ wl->profile->sec.cipher_group = sme->crypto.cipher_group;
+
+ return err;
+}
+
+static s32
+wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 val = 0;
+ s32 err = 0;
+
+ if (sme->crypto.n_akm_suites) {
+ err = wl_dev_intvar_get(dev, "wpa_auth", &val);
+ if (err) {
+ WL_ERR(("could not get wpa_auth (%d)\n", err));
+ return err;
+ }
+ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+ switch (sme->crypto.akm_suites[0]) {
+ case WLAN_AKM_SUITE_8021X:
+ val = WPA_AUTH_UNSPECIFIED;
+ break;
+ case WLAN_AKM_SUITE_PSK:
+ val = WPA_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
+ return -EINVAL;
+ }
+ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ switch (sme->crypto.akm_suites[0]) {
+ case WLAN_AKM_SUITE_8021X:
+ val = WPA2_AUTH_UNSPECIFIED;
+ break;
+ case WLAN_AKM_SUITE_PSK:
+ val = WPA2_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
+ return -EINVAL;
+ }
+ }
+
+ WL_DBG(("setting wpa_auth to %d\n", val));
+ err = wl_dev_intvar_set(dev, "wpa_auth", val);
+ if (err) {
+ WL_ERR(("could not set wpa_auth (%d)\n", err));
+ return err;
+ }
+ }
+
+ wl->profile->sec.wpa_auth = sme->crypto.akm_suites[0];
+
+ return err;
+}
+
+static s32
+wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ struct wl_cfg80211_security *sec;
+ struct wl_wsec_key key;
+ s32 err = 0;
+
+ WL_DBG(("key len (%d)\n", sme->key_len));
+ if (sme->key_len) {
+ sec = &wl->profile->sec;
+ WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
+ sec->wpa_versions, sec->cipher_pairwise));
+ if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) &&
+ (sec->cipher_pairwise &
+ (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104))) {
+ memset(&key, 0, sizeof(key));
+ key.len = (u32) sme->key_len;
+ key.index = (u32) sme->key_idx;
+ if (key.len > sizeof(key.data)) {
+ WL_ERR(("Too long key length (%u)\n", key.len));
+ return -EINVAL;
+ }
+ memcpy(key.data, sme->key, key.len);
+ key.flags = WL_PRIMARY_KEY;
+ switch (sec->cipher_pairwise) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ default:
+ WL_ERR(("Invalid algorithm (%d)\n",
+ sme->crypto.ciphers_pairwise[0]));
+ return -EINVAL;
+ }
+
+ WL_DBG(("key length (%d) key index (%d) algo (%d)\n", key.len,
+ key.index, key.algo));
+ WL_DBG(("key \"%s\"\n", key.data));
+ key_endian_to_device(&key);
+ err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (err) {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ return err;
+ }
+ }
+ }
+ return err;
+}
+
+static s32
+wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct wl_join_params join_params;
+ size_t join_params_size;
+ char valc;
+ s32 err = 0;
+
+ if (!sme->ssid) {
+ WL_ERR(("Invalid ssid\n"));
+ return -EOPNOTSUPP;
+ }
+
+ WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
+
+ err = wl_set_auth_type(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_wpa_version(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_set_cipher(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_key_mgmt(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_set_sharedkey(dev, sme);
+ if (err)
+ return err;
+
+ valc = 1;
+ wl_dev_bufvar_set(dev, "wsec_restrict", &valc, 1);
+
+ if (sme->bssid) {
+ memcpy(wl->profile->bssid, sme->bssid, ETHER_ADDR_LEN);
+ }
+ else {
+ memset(wl->profile->bssid, 0, ETHER_ADDR_LEN);
+ }
+
+ memset(&join_params, 0, sizeof(join_params));
+ join_params_size = sizeof(join_params.ssid);
+
+ join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
+ memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
+ join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+ memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+ memcpy(wl->profile->ssid.SSID, &join_params.ssid.SSID, join_params.ssid.SSID_len);
+ wl->profile->ssid.SSID_len = join_params.ssid.SSID_len;
+
+ wl_ch_to_chanspec(sme->channel, &join_params, &join_params_size);
+ WL_DBG(("join_param_size %u\n", (unsigned int)join_params_size));
+
+ if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ WL_DBG(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
+ join_params.ssid.SSID_len));
+ }
+ err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ set_bit(WL_STATUS_CONNECTING, &wl->status);
+
+ return err;
+}
+
+static s32
+wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ scb_val_t scbval;
+ s32 err = 0;
+
+ WL_DBG(("Reason %d\n", reason_code));
+
+ if (wl->profile->active) {
+ scbval.val = reason_code;
+ memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+ err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 dbm)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, s32 dbm)
+#else
+#define NL80211_TX_POWER_AUTOMATIC TX_POWER_AUTOMATIC
+#define NL80211_TX_POWER_LIMITED TX_POWER_LIMITED
+#define NL80211_TX_POWER_FIXED TX_POWER_FIXED
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, s32 dbm)
+#endif
+{
+
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
+ u16 txpwrmw;
+ s32 err = 0;
+ s32 disable = 0;
+
+ switch (type) {
+ case NL80211_TX_POWER_AUTOMATIC:
+ break;
+ case NL80211_TX_POWER_LIMITED:
+ if (dbm < 0) {
+ WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
+ return -EINVAL;
+ }
+ break;
+ case NL80211_TX_POWER_FIXED:
+ if (dbm < 0) {
+ WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
+ return -EINVAL;
+ }
+ break;
+ }
+
+ disable = WL_RADIO_SW_DISABLE << 16;
+ disable = htod32(disable);
+ err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
+ if (err) {
+ WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
+ return err;
+ }
+
+ if (dbm > 0xffff)
+ txpwrmw = 0xffff;
+ else
+ txpwrmw = (u16) dbm;
+ err = wl_dev_intvar_set(ndev, "qtxpower", (s32) (bcm_mw_to_qdbm(txpwrmw)));
+ if (err) {
+ WL_ERR(("qtxpower error (%d)\n", err));
+ return err;
+ }
+ wl->conf->tx_power = dbm;
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, s32 *dbm)
+#else
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+#endif
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
+ s32 txpwrdbm;
+ u8 result;
+ s32 err = 0;
+
+ err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
+ *dbm = (s32) bcm_qdbm_to_mw(result);
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+static s32
+wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx, bool unicast, bool multicast)
+#else
+static s32
+wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx)
+#endif
+{
+ u32 index;
+ s32 err = 0;
+
+ WL_DBG(("key index (%d)\n", key_idx));
+
+ index = (u32) key_idx;
+ index = htod32(index);
+ err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index, sizeof(index));
+ if (err) {
+ WL_DBG(("error (%d)\n", err));
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32
+wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params)
+#else
+static s32
+wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr, struct key_params *params)
+#endif
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ struct wl_wsec_key key;
+ s32 secval, secnew = 0;
+ s32 err = 0;
+
+ WL_DBG(("key index %u len %u\n", (unsigned)key_idx, params->key_len));
+
+ memset(&key, 0, sizeof(key));
+
+ key.index = (u32) key_idx;
+
+ switch (params->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ secnew = WEP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ secnew = WEP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ key.algo = CRYPTO_ALGO_TKIP;
+ secnew = TKIP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ secnew = AES_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ secnew = AES_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
+ break;
+ default:
+ WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
+ return -EINVAL;
+ }
+
+ if (mac_addr) {
+ if (!ETHER_ISMULTI(mac_addr)) {
+ memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
+ }
+ }
+
+ key.len = (u32) params->key_len;
+ if (key.len > sizeof(key.data)) {
+ WL_ERR(("Too long key length (%u)\n", key.len));
+ return -EINVAL;
+ }
+ memcpy(key.data, params->key, key.len);
+
+ if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
+ u8 keybuf[8];
+ memcpy(keybuf, &key.data[24], sizeof(keybuf));
+ memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+ memcpy(&key.data[16], keybuf, sizeof(keybuf));
+ }
+
+ if (params->seq_len) {
+ u8 *ivptr;
+ if (params->seq_len != 6) {
+ WL_ERR(("seq_len %d is unexpected, check implementation.\n",
+ params->seq_len));
+ }
+ ivptr = (u8 *) params->seq;
+ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | (ivptr[3] << 8) | ivptr[2];
+ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+ key.iv_initialized = true;
+ }
+
+ key_endian_to_device(&key);
+ if (wl->passive) {
+ schedule();
+ }
+ err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (err) {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ return err;
+ }
+
+ if ((err = wl_dev_intvar_get(dev, "wsec", &secval))) {
+ return err;
+ }
+ if (secnew == WEP_ENABLED) {
+ secval &= ~(TKIP_ENABLED | AES_ENABLED);
+ }
+ else {
+ secval &= ~(WEP_ENABLED);
+ }
+ secval |= secnew;
+ WL_DBG(("set wsec to %d\n", secval));
+ err = wl_dev_intvar_set(dev, "wsec", secval);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ if (mac_addr) {
+ wl->profile->sec.cipher_pairwise = params->cipher;
+ }
+ else {
+ wl->profile->sec.cipher_group = params->cipher;
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32
+wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr)
+#else
+static s32
+wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr)
+#endif
+{
+ struct wl_wsec_key key;
+ s32 err = 0;
+
+ WL_DBG(("key index (%d)\n", key_idx));
+
+ memset(&key, 0, sizeof(key));
+
+ key.index = (u32) key_idx;
+ key.len = 0;
+ if (mac_addr) {
+ if (!ETHER_ISMULTI(mac_addr)) {
+ memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
+ }
+ }
+ key.algo = CRYPTO_ALGO_OFF;
+
+ key_endian_to_device(&key);
+ err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (err) {
+ if (err == -EINVAL) {
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
+
+ WL_DBG(("invalid key index (%d)\n", key_idx));
+ }
+ } else {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ }
+ return err;
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32
+wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
+ void (*callback) (void *cookie, struct key_params * params))
+#else
+static s32
+wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr, void *cookie,
+ void (*callback) (void *cookie, struct key_params * params))
+#endif
+{
+ struct key_params params;
+ struct wl_wsec_key key;
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct wl_cfg80211_security *sec;
+ s32 wsec;
+ s32 err = 0;
+
+ WL_DBG(("key index (%d)\n", key_idx));
+
+ memset(&params, 0, sizeof(params));
+
+ memset(&key, 0, sizeof(key));
+ key.index = key_idx;
+ key_endian_to_device(&key);
+
+ if ((err = wl_dev_ioctl(dev, WLC_GET_KEY, &key, sizeof(key)))) {
+ return err;
+ }
+ key_endian_to_host(&key);
+
+ params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
+ memcpy((char *)params.key, key.data, params.key_len);
+
+ if ((err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
+ return err;
+ }
+ wsec = dtoh32(wsec);
+ switch (wsec) {
+ case WEP_ENABLED:
+ sec = &wl->profile->sec;
+ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP40;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP104;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ }
+ break;
+ case TKIP_ENABLED:
+ params.cipher = WLAN_CIPHER_SUITE_TKIP;
+ WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+ break;
+ case AES_ENABLED:
+ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+ WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+ break;
+ default:
+ WL_ERR(("Invalid algo (0x%x)\n", wsec));
+ return -EINVAL;
+ }
+
+ callback(cookie, &params);
+ return err;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
+static s32
+wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo)
+#else
+static s32
+wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *mac, struct station_info *sinfo)
+#endif
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ scb_val_t scb_val;
+ int rssi;
+ s32 rate;
+ s32 err = 0;
+
+ if (memcmp(mac, wl->profile->bssid, ETHER_ADDR_LEN)) {
+ WL_ERR(("Wrong Mac address, mac = %pM profile =%pM\n", mac, wl->profile->bssid));
+ return -ENOENT;
+ }
+
+ err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
+ if (err) {
+ WL_DBG(("Could not get rate (%d)\n", err));
+ } else {
+ rate = dtoh32(rate);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
+#else
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+#endif
+ sinfo->txrate.legacy = rate * 5;
+ WL_DBG(("Rate %d Mbps\n", (rate / 2)));
+ }
+
+ if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+ memset(&scb_val, 0, sizeof(scb_val));
+ err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
+ if (err) {
+ WL_DBG(("Could not get rssi (%d)\n", err));
+ return err;
+ }
+ rssi = dtoh32(scb_val.val);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+#else
+ sinfo->filled |= STATION_INFO_SIGNAL;
+#endif
+ sinfo->signal = rssi;
+ WL_DBG(("RSSI %d dBm\n", rssi));
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, s32 timeout)
+{
+ s32 pm;
+ s32 err = 0;
+
+ pm = enabled ? PM_FAST : PM_OFF;
+ pm = htod32(pm);
+ WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
+ err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+ if (err) {
+ if (err == -ENODEV)
+ WL_DBG(("net_device is not ready yet\n"));
+ else
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static __used s32
+wl_update_pmklist(struct net_device *dev, struct wl_cfg80211_pmk_list *pmk_list, s32 err)
+{
+ int i, j;
+
+ WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
+ for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
+ WL_DBG(("PMKID[%d]: %pM =\n", i,
+ &pmk_list->pmkids.pmkid[i].BSSID));
+ for (j = 0; j < WPA2_PMKID_LEN; j++) {
+ WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
+ }
+ }
+ if (!err) {
+ err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list, sizeof(*pmk_list));
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+
+static s32
+wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ s32 err = 0;
+ int i;
+
+ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
+ break;
+ if (i < WL_NUM_PMKIDS_MAX) {
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+ if (i == wl->pmk_list->pmkids.npmkid)
+ wl->pmk_list->pmkids.npmkid++;
+ } else {
+ err = -EINVAL;
+ }
+ WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
+ &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n",
+ wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].PMKID[i]));
+ }
+
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+ return err;
+}
+
+static s32
+wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct _pmkid_list pmkid;
+ s32 err = 0;
+ int i;
+
+ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+ memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+
+ WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
+ &pmkid.pmkid[0].BSSID));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
+ }
+
+ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
+ break;
+
+ if ((wl->pmk_list->pmkids.npmkid > 0) && (i < wl->pmk_list->pmkids.npmkid)) {
+ memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
+ for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
+ &wl->pmk_list->pmkids.pmkid[i + 1].BSSID, ETHER_ADDR_LEN);
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
+ &wl->pmk_list->pmkids.pmkid[i + 1].PMKID, WPA2_PMKID_LEN);
+ }
+ wl->pmk_list->pmkids.npmkid--;
+ } else {
+ err = -EINVAL;
+ }
+
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+ return err;
+
+}
+
+static s32
+wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ s32 err = 0;
+
+ memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+ return err;
+
+}
+
+#endif
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+
+static int
+wl_wowl_ind_wake_reason(struct wl_cfg80211_priv *wl, struct cfg80211_wowlan_wakeup *wakeup)
+{
+ wl_wowl_wakeind_t wowl_ind;
+ s32 err;
+
+ err = wl_dev_bufvar_get(wl_to_ndev(wl), "wowl_wakeind",
+ (s8 *)&wowl_ind, sizeof(wowl_ind));
+ if (err != 0) {
+ WL_ERR(("Unable to get wake reason, err = %d\n", err));
+ return -1;
+ }
+
+ if (wowl_ind.ucode_wakeind == 0) {
+ WL_DBG(("System woke, but not by us\n"));
+ return 0;
+ }
+ WL_DBG(("wake reason is 0x%x\n", wowl_ind.ucode_wakeind));
+
+ if (wowl_ind.ucode_wakeind & WL_WOWL_MAGIC) {
+ WL_ERR(("WOWLAN Woke for: Magic Pkt\n"));
+ wakeup->magic_pkt = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_DIS) {
+ WL_ERR(("WOWLAN Woke for: Disconnect\n"));
+ wakeup->disconnect = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_BCN) {
+ WL_ERR(("WOWLAN Woke for: Beacon Loss\n"));
+ wakeup->disconnect = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_GTK_FAILURE) {
+ WL_ERR(("WOWLAN Woke for: GTK failure\n"));
+ wakeup->gtk_rekey_failure = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_EAPID) {
+ WL_ERR(("WOWLAN Woke for: EAP identify request\n"));
+ wakeup->eap_identity_req = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_M1) {
+ WL_ERR(("WOWLAN Woke for: 4-way handshake request\n"));
+ wakeup->four_way_handshake = true;
+ }
+ return 1;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+static int
+wl_cfg80211_rekey(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_gtk_rekey_data *data)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ wlc_rekey_info_t rekey;
+ s32 err;
+
+ if (!wl->offloads) {
+ return 0;
+ }
+
+ memset(&rekey, 0, sizeof(rekey));
+ memcpy(&rekey.kek, data->kek, WLC_KEK_LEN);
+ memcpy(&rekey.kck, data->kck, WLC_KCK_LEN);
+ memcpy(&rekey.replay_counter, data->replay_ctr, WLC_REPLAY_CTR_LEN);
+ WL_INF(("Send down replay counter %x%x%x%x%x%x%x%x\n",
+ rekey.replay_counter[0], rekey.replay_counter[1], rekey.replay_counter[2],
+ rekey.replay_counter[3], rekey.replay_counter[4], rekey.replay_counter[5],
+ rekey.replay_counter[6], rekey.replay_counter[7]));
+
+ err = wl_dev_bufvar_set(wl_to_ndev(wl), "wowl_replay", (s8 *)&rekey, sizeof(rekey));
+ if (err) {
+ WL_ERR(("Error calling wowl_set_key\n"));
+ return err;
+ }
+ return err;
+}
+#endif
+
+static int wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ uint wowl = 0;
+ s32 err;
+
+ if (!wowlan) {
+ WL_DBG(("No wowlan requested\n"));
+ return 0;
+ }
+ if (!test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+ WL_INF(("No wowl when not associated.\n"));
+ return 0;
+ }
+
+ err = wl_dev_intvar_get(wl_to_ndev(wl), "wowl", &wowl);
+ if (err) {
+ WL_ERR(("Error fetching WOWL %d\n", err));
+ }
+ if (wowlan->disconnect) {
+ WL_INF(("Requesting wake on Disconnect\n"));
+ wowl |= WL_WOWL_DIS | WL_WOWL_BCN;
+ }
+ if (wowlan->magic_pkt) {
+ WL_INF(("Requesting wake on Magic Pkt\n"));
+ wowl |= WL_WOWL_MAGIC;
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ if (wowlan->gtk_rekey_failure) {
+ WL_INF(("Requesting wake GTK rekey failure Pkt\n"));
+ wowl |= WL_WOWL_GTK_FAILURE;
+ }
+ if (wowlan->four_way_handshake) {
+ WL_INF(("Requesting wake on 4way handshake request\n"));
+ wowl |= WL_WOWL_M1;
+ }
+#endif
+
+ wowl |= WL_WOWL_KEYROT;
+
+ err = wl_dev_intvar_set(wl_to_ndev(wl), "wowl", wowl);
+ if (err) {
+ WL_ERR(("Error enabling WOWL %d\n", err));
+ }
+
+ return err;
+}
+#else
+static int wl_cfg80211_suspend(struct wiphy *wiphy)
+{
+ return 0;
+}
+#endif
+
+static int wl_cfg80211_resume(struct wiphy *wiphy)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ wlc_rekey_info_t *rekey = (wlc_rekey_info_t *)wl->extra_buf;
+ s32 err;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ struct cfg80211_wowlan_wakeup wakeup;
+ int result;
+
+ memset(&wakeup, 0, sizeof(wakeup));
+ wakeup.pattern_idx = -1;
+
+ result = wl_wowl_ind_wake_reason(wl, &wakeup);
+ switch (result) {
+ case -1:
+ break;
+ case 0:
+ cfg80211_report_wowlan_wakeup(wl_to_wdev(wl), NULL, GFP_KERNEL);
+ break;
+ case 1:
+ cfg80211_report_wowlan_wakeup(wl_to_wdev(wl), &wakeup, GFP_KERNEL);
+ break;
+ }
+#endif
+
+ err = wl_dev_bufvar_get(wl_to_ndev(wl), "wowl_replay", (s8 *)rekey,
+ sizeof(wlc_rekey_info_t));
+ if (!err) {
+ WL_INF(("Send up replay counter %x%x%x%x%x%x%x%x\n",
+ rekey->replay_counter[0], rekey->replay_counter[1],
+ rekey->replay_counter[2], rekey->replay_counter[3],
+ rekey->replay_counter[4], rekey->replay_counter[5],
+ rekey->replay_counter[6], rekey->replay_counter[7]));
+ cfg80211_gtk_rekey_notify(wl_to_ndev(wl), (u8 *)&wl->bssid.octet,
+ rekey->replay_counter, GFP_KERNEL);
+ }
+#endif
+ return 0;
+}
+#endif
+
+static struct cfg80211_ops wl_cfg80211_ops = {
+ .change_virtual_intf = wl_cfg80211_change_iface,
+ .scan = wl_cfg80211_scan,
+ .set_wiphy_params = wl_cfg80211_set_wiphy_params,
+ .join_ibss = wl_cfg80211_join_ibss,
+ .leave_ibss = wl_cfg80211_leave_ibss,
+ .get_station = wl_cfg80211_get_station,
+ .set_tx_power = wl_cfg80211_set_tx_power,
+ .get_tx_power = wl_cfg80211_get_tx_power,
+ .add_key = wl_cfg80211_add_key,
+ .del_key = wl_cfg80211_del_key,
+ .get_key = wl_cfg80211_get_key,
+ .set_default_key = wl_cfg80211_config_default_key,
+ .set_power_mgmt = wl_cfg80211_set_power_mgmt,
+ .connect = wl_cfg80211_connect,
+ .disconnect = wl_cfg80211_disconnect,
+#ifdef CONFIG_PM
+ .suspend = wl_cfg80211_suspend,
+ .resume = wl_cfg80211_resume,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ .set_rekey_data = wl_cfg80211_rekey,
+#endif
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+ .set_pmksa = wl_cfg80211_set_pmksa,
+ .del_pmksa = wl_cfg80211_del_pmksa,
+ .flush_pmksa = wl_cfg80211_flush_pmksa
+#endif
+};
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+static const struct wiphy_wowlan_support wl_wowlan_support = {
+#else
+static struct wiphy_wowlan_support wl_wowlan_support = {
+#endif
+ .flags = WIPHY_WOWLAN_MAGIC_PKT
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | WIPHY_WOWLAN_GTK_REKEY_FAILURE |
+ WIPHY_WOWLAN_EAP_IDENTITY_REQ
+#endif
+ | WIPHY_WOWLAN_DISCONNECT,
+};
+#endif
+#endif
+
+static s32 wl_mode_to_nl80211_iftype(s32 mode)
+{
+ s32 err = 0;
+
+ switch (mode) {
+ case WL_MODE_BSS:
+ return NL80211_IFTYPE_STATION;
+ case WL_MODE_IBSS:
+ return NL80211_IFTYPE_ADHOC;
+ default:
+ return NL80211_IFTYPE_UNSPECIFIED;
+ }
+
+ return err;
+}
+
+static s32 wl_alloc_wdev(struct device *dev, struct wireless_dev **rwdev)
+{
+ struct wireless_dev *wdev;
+ s32 err = 0;
+
+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ if (!wdev) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ err = -ENOMEM;
+ goto early_out;
+ }
+ wdev->wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_cfg80211_priv));
+ if (!wdev->wiphy) {
+ WL_ERR(("Couldn not allocate wiphy device\n"));
+ err = -ENOMEM;
+ goto wiphy_new_out;
+ }
+ set_wiphy_dev(wdev->wiphy, dev);
+ wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+ wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+#endif
+ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
+ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;
+ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wdev->wiphy->cipher_suites = __wl_cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+
+ wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+#endif
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+ wdev->wiphy->wowlan = &wl_wowlan_support;
+#else
+ wdev->wiphy->wowlan = wl_wowlan_support;
+#endif
+#endif
+#endif
+
+ err = wiphy_register(wdev->wiphy);
+ if (err < 0) {
+ WL_ERR(("Couldn not register wiphy device (%d)\n", err));
+ goto wiphy_register_out;
+ }
+
+ *rwdev = wdev;
+ return err;
+
+wiphy_register_out:
+ wiphy_free(wdev->wiphy);
+
+wiphy_new_out:
+ kfree(wdev);
+
+early_out:
+ *rwdev = wdev;
+ return err;
+}
+
+static void wl_free_wdev(struct wl_cfg80211_priv *wl)
+{
+ struct wireless_dev *wdev = wl_to_wdev(wl);
+
+ if (!wdev) {
+ WL_ERR(("wdev is invalid\n"));
+ return;
+ }
+ wiphy_unregister(wdev->wiphy);
+ wiphy_free(wdev->wiphy);
+ kfree(wdev);
+ wl_to_wdev(wl) = NULL;
+}
+
+static s32 wl_inform_bss(struct wl_cfg80211_priv *wl, struct wl_scan_results *bss_list)
+{
+ struct wl_bss_info *bi = NULL;
+ s32 err = 0;
+ int i;
+
+ if (bss_list->version != WL_BSS_INFO_VERSION) {
+ WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n", bss_list->version));
+ return -EOPNOTSUPP;
+ }
+ WL_DBG(("scanned AP count (%d)\n", bss_list->count));
+ bi = next_bss(bss_list, bi);
+ for_each_bss(bss_list, bi, i) {
+ err = wl_inform_single_bss(wl, bi);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info *bi)
+{
+ struct wiphy *wiphy = wl_to_wiphy(wl);
+ struct ieee80211_mgmt *mgmt;
+ struct ieee80211_channel *channel;
+ struct wl_cfg80211_bss_info *notif_bss_info;
+ struct wl_cfg80211_scan_req *sr = wl_to_sr(wl);
+ struct beacon_proberesp *beacon_proberesp;
+ struct cfg80211_bss *cbss = NULL;
+ s32 mgmt_type;
+ u32 signal;
+ u32 freq;
+ s32 err = 0;
+ u8 *notify_ie;
+ size_t notify_ielen;
+
+ if (dtoh32(bi->length) > WL_BSS_INFO_MAX) {
+ WL_DBG(("Beacon is larger than buffer. Discarding\n"));
+ return err;
+ }
+ notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) +
+ WL_BSS_INFO_MAX, GFP_KERNEL);
+ if (!notif_bss_info) {
+ WL_ERR(("notif_bss_info alloc failed\n"));
+ return -ENOMEM;
+ }
+ mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
+ notif_bss_info->channel = bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec);
+
+ notif_bss_info->rssi = bi->RSSI;
+ memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
+ mgmt_type = wl->active_scan ? IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
+ if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
+ }
+ beacon_proberesp = wl->active_scan ? (struct beacon_proberesp *)&mgmt->u.probe_resp :
+ (struct beacon_proberesp *)&mgmt->u.beacon;
+ beacon_proberesp->timestamp = 0;
+ beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
+ beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
+ wl_rst_ie(wl);
+
+ wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
+ wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
+ offsetof(struct wl_cfg80211_bss_info, frame_buf));
+ notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.beacon.variable) +
+ wl_get_ielen(wl);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+ freq = ieee80211_channel_to_frequency(notif_bss_info->channel,
+ (notif_bss_info->channel <= CH_MAX_2G_CHANNEL) ?
+ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ);
+#else
+ freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+#endif
+ if (freq == 0) {
+ WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+ channel = ieee80211_get_channel(wiphy, freq);
+ if (unlikely(!channel)) {
+ WL_ERR(("ieee80211_get_channel error\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+
+ WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
+ bi->SSID, notif_bss_info->rssi, notif_bss_info->channel,
+ mgmt->u.beacon.capab_info, &bi->BSSID));
+
+ signal = notif_bss_info->rssi * 100;
+ cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
+ le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL);
+ if (unlikely(!cbss)) {
+ WL_ERR(("cfg80211_inform_bss_frame error\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+
+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+ notify_ielen = le32_to_cpu(bi->ie_length);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
+ cbss = cfg80211_inform_bss(wiphy, channel, (const u8 *)(bi->BSSID.octet),
+ 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int,
+ (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
+#else
+ cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, (const u8 *)(bi->BSSID.octet),
+ 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int,
+ (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
+#endif
+
+ if (unlikely(!cbss))
+ return -ENOMEM;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ cfg80211_put_bss(wiphy, cbss);
+#else
+ cfg80211_put_bss(cbss);
+#endif
+
+ kfree(notif_bss_info);
+
+ return err;
+}
+
+static s32
+wl_notify_connect_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 event = EVENT_TYPE(e);
+ u16 flags = EVENT_FLAGS(e);
+ u32 status = EVENT_STATUS(e);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ struct ieee80211_channel *channel = NULL;
+ struct wiphy *wiphy;
+ u32 chanspec, chan;
+ u32 freq, band;
+#endif
+
+ WL_DBG(("\n"));
+
+ if (!wl_is_ibssmode(wl)) {
+ if (event == WLC_E_LINK && (flags & WLC_EVENT_MSG_LINK)) {
+ wl_link_up(wl);
+ wl_bss_connect_done(wl, ndev, e, data, true);
+ wl->profile->active = true;
+ }
+ else if ((event == WLC_E_LINK && ~(flags & WLC_EVENT_MSG_LINK)) ||
+ event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
+ cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
+#else
+ cfg80211_disconnected(ndev, 0, NULL, 0, false, GFP_KERNEL);
+#endif
+ clear_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl_link_down(wl);
+ wl_init_prof(wl->profile);
+ }
+ else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
+ wl_bss_connect_done(wl, ndev, e, data, false);
+ }
+ else {
+ WL_DBG(("no action (BSS mode)\n"));
+ }
+ }
+ else {
+ if (event == WLC_E_JOIN) {
+ WL_DBG(("joined in IBSS network\n"));
+ }
+ if (event == WLC_E_START) {
+ WL_DBG(("started IBSS network\n"));
+ }
+ if (event == WLC_E_JOIN || event == WLC_E_START) {
+ wl_link_up(wl);
+ wl_get_assoc_ies(wl);
+ memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
+ wl_update_bss_info(wl);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ wiphy = wl_to_wiphy(wl);
+ err = wl_dev_intvar_get(ndev, "chanspec", &chanspec);
+ if (err) {
+ WL_ERR(("Could not get chanspec, err %d\n", err));
+ return err;
+ }
+ chan = wf_chspec_ctlchan(chanspec);
+ band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+ freq = ieee80211_channel_to_frequency(chan, band);
+ channel = ieee80211_get_channel(wiphy, freq);
+ cfg80211_ibss_joined(ndev, (u8 *)&wl->bssid, channel, GFP_KERNEL);
+#else
+ cfg80211_ibss_joined(ndev, (u8 *)&wl->bssid, GFP_KERNEL);
+#endif
+ set_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl->profile->active = true;
+ }
+ else if ((event == WLC_E_LINK && ~(flags & WLC_EVENT_MSG_LINK)) ||
+ event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
+ clear_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl_link_down(wl);
+ wl_init_prof(wl->profile);
+ }
+ else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
+ WL_DBG(("no action - join fail (IBSS mode)\n"));
+ }
+ else {
+ WL_DBG(("no action (IBSS mode)\n"));
+ }
+ }
+
+ return err;
+}
+
+static s32
+wl_notify_roaming_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 status = EVENT_STATUS(e);
+
+ WL_DBG(("\n"));
+
+ if (status == WLC_E_STATUS_SUCCESS) {
+ err = wl_bss_roaming_done(wl, ndev, e, data);
+ wl->profile->active = true;
+ }
+
+ return err;
+}
+
+static __used s32
+wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ u32 buflen;
+
+ buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+ BUG_ON(!buflen);
+
+ return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
+}
+
+static s32
+wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, s32 buf_len)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ u32 len;
+ s32 err = 0;
+
+ len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+ BUG_ON(!len);
+ err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+ if (err) {
+ WL_INF(("error (%d)\n", err));
+ return err;
+ }
+ memcpy(buf, wl->ioctl_buf, buf_len);
+
+ return err;
+}
+
+static s32 wl_get_assoc_ies(struct wl_cfg80211_priv *wl)
+{
+ struct net_device *ndev = wl_to_ndev(wl);
+ struct wl_cfg80211_assoc_ielen *assoc_info;
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+ u32 req_len;
+ u32 resp_len;
+ s32 err = 0;
+
+ err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf, WL_ASSOC_INFO_MAX);
+ if (err) {
+ WL_ERR(("could not get assoc info (%d)\n", err));
+ return err;
+ }
+ assoc_info = (struct wl_cfg80211_assoc_ielen *)wl->extra_buf;
+ req_len = assoc_info->req_len;
+ resp_len = assoc_info->resp_len;
+ if (req_len) {
+ err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf, WL_ASSOC_INFO_MAX);
+ if (err) {
+ WL_ERR(("could not get assoc req (%d)\n", err));
+ return err;
+ }
+ conn_info->req_ie_len = req_len;
+ conn_info->req_ie =
+ kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
+ } else {
+ conn_info->req_ie_len = 0;
+ conn_info->req_ie = NULL;
+ }
+ if (resp_len) {
+ err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf, WL_ASSOC_INFO_MAX);
+ if (err) {
+ WL_ERR(("could not get assoc resp (%d)\n", err));
+ return err;
+ }
+ conn_info->resp_ie_len = resp_len;
+ conn_info->resp_ie =
+ kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
+ } else {
+ conn_info->resp_ie_len = 0;
+ conn_info->resp_ie = NULL;
+ }
+ WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
+ conn_info->resp_ie_len));
+
+ return err;
+}
+
+static void wl_ch_to_chanspec(struct ieee80211_channel *chan, struct wl_join_params *join_params,
+ size_t *join_params_size)
+{
+ chanspec_t chanspec = 0;
+
+ if (chan) {
+ join_params->params.chanspec_num = 1;
+ join_params->params.chanspec_list[0] =
+ ieee80211_frequency_to_channel(chan->center_freq);
+
+ if (chan->band == IEEE80211_BAND_2GHZ) {
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ }
+ else if (chan->band == IEEE80211_BAND_5GHZ) {
+ chanspec |= WL_CHANSPEC_BAND_5G;
+ }
+ else {
+ WL_ERR(("Unknown band\n"));
+ BUG();
+ }
+
+ chanspec |= WL_CHANSPEC_BW_20;
+
+ *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
+ join_params->params.chanspec_num * sizeof(chanspec_t);
+
+ join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
+ join_params->params.chanspec_list[0] |= chanspec;
+ join_params->params.chanspec_list[0] =
+ htodchanspec(join_params->params.chanspec_list[0]);
+
+ join_params->params.chanspec_num = htod32(join_params->params.chanspec_num);
+
+ WL_DBG(("join_params->params.chanspec_list[0]= %#X, channel %d, chanspec %#X\n",
+ join_params->params.chanspec_list[0],
+ join_params->params.chanspec_list[0], chanspec));
+ }
+}
+
+static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ struct wiphy *wiphy = wl_to_wiphy(wl);
+#endif
+ struct cfg80211_bss *bss;
+ struct wl_bss_info *bi;
+ struct wlc_ssid *ssid;
+ struct bcm_tlv *tim;
+ s32 dtim_period;
+ size_t ie_len;
+ u8 *ie;
+ s32 err = 0;
+
+ ssid = &wl->profile->ssid;
+ bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid,
+ ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+
+ rtnl_lock();
+ if (!bss) {
+ WL_DBG(("Could not find the AP\n"));
+ *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO, wl->extra_buf,
+ WL_EXTRA_BUF_MAX);
+ if (err) {
+ WL_ERR(("Could not get bss info %d\n", err));
+ goto update_bss_info_out;
+ }
+ bi = (struct wl_bss_info *)(wl->extra_buf + 4);
+ if (memcmp(&bi->BSSID, &wl->bssid, ETHER_ADDR_LEN)) {
+ err = -EIO;
+ goto update_bss_info_out;
+ }
+ err = wl_inform_single_bss(wl, bi);
+ if (err)
+ goto update_bss_info_out;
+
+ ie = ((u8 *)bi) + bi->ie_offset;
+ ie_len = bi->ie_length;
+ } else {
+ WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+ ie = (u8 *)(bss->ies->data);
+ ie_len = bss->ies->len;
+#else
+ ie = bss->information_elements;
+ ie_len = bss->len_information_elements;
+#endif
+ wl->conf->channel = *bss->channel;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ cfg80211_put_bss(wiphy, bss);
+#else
+ cfg80211_put_bss(bss);
+#endif
+ }
+
+ tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+ if (tim) {
+ dtim_period = tim->data[1];
+ } else {
+
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_DTIMPRD,
+ &dtim_period, sizeof(dtim_period));
+ if (err) {
+ WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
+ goto update_bss_info_out;
+ }
+ }
+
+update_bss_info_out:
+ rtnl_unlock();
+ return err;
+}
+
+static s32
+wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+ s32 err = 0;
+
+ wl_get_assoc_ies(wl);
+ memcpy(wl->profile->bssid, &e->addr, ETHER_ADDR_LEN);
+ memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
+ wl_update_bss_info(wl);
+ cfg80211_roamed(ndev,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
+ &wl->conf->channel,
+#endif
+ (u8 *)&wl->bssid,
+ conn_info->req_ie, conn_info->req_ie_len,
+ conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
+ WL_DBG(("Report roaming result\n"));
+
+ set_bit(WL_STATUS_CONNECTED, &wl->status);
+
+ return err;
+}
+
+static s32
+wl_bss_connect_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed)
+{
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+ s32 err = 0;
+
+ if (wl->scan_request) {
+ WL_DBG(("%s: Aborting scan\n", __FUNCTION__));
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ }
+
+ if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
+ if (completed) {
+ wl_get_assoc_ies(wl);
+ memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
+ memcpy(wl->profile->bssid, &e->addr, ETHER_ADDR_LEN);
+ wl_update_bss_info(wl);
+ set_bit(WL_STATUS_CONNECTED, &wl->status);
+ }
+
+ WL_DBG(("Reporting BSS network join result \"%s\"\n",
+ wl->profile->ssid.SSID));
+ cfg80211_connect_result(ndev, (u8 *)&wl->bssid, conn_info->req_ie,
+ conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len,
+ completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL);
+ WL_DBG(("Connection %s\n", completed ? "Succeeded" : "FAILed"));
+ }
+
+ return err;
+}
+
+static s32
+wl_notify_mic_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ u16 flags = EVENT_FLAGS(e);
+ enum nl80211_key_type key_type;
+
+ WL_DBG(("\n"));
+
+ rtnl_lock();
+ if (flags & WLC_EVENT_MSG_GROUP)
+ key_type = NL80211_KEYTYPE_GROUP;
+ else
+ key_type = NL80211_KEYTYPE_PAIRWISE;
+
+ cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1, NULL, GFP_KERNEL);
+ rtnl_unlock();
+
+ return 0;
+}
+
+static s32
+wl_notify_scan_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct channel_info channel_inform;
+ struct wl_scan_results *bss_list;
+ u32 buflen;
+ s32 err = 0;
+
+ WL_DBG(("\n"));
+
+ rtnl_lock();
+ err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, sizeof(channel_inform));
+ if (err) {
+ WL_ERR(("scan busy (%d)\n", err));
+ goto scan_done_out;
+ }
+ channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
+ if (channel_inform.scan_channel) {
+
+ WL_DBG(("channel_inform.scan_channel (%d)\n", channel_inform.scan_channel));
+ }
+
+ for (buflen = WL_SCAN_BUF_BASE; ; ) {
+ bss_list = (struct wl_scan_results *) kmalloc(buflen, GFP_KERNEL);
+ if (!bss_list) {
+ WL_ERR(("%s Out of memory for scan results, (%d)\n", ndev->name, err));
+ goto scan_done_out;
+ }
+ memset(bss_list, 0, buflen);
+ bss_list->buflen = htod32(buflen);
+ err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, buflen);
+ if (!err) {
+ break;
+ }
+ else if (err == -E2BIG) {
+ kfree(bss_list);
+ buflen *= 2;
+ }
+ else {
+ WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
+ kfree(bss_list);
+ err = -EINVAL;
+ goto scan_done_out;
+ }
+ }
+
+ bss_list->buflen = dtoh32(bss_list->buflen);
+ bss_list->version = dtoh32(bss_list->version);
+ bss_list->count = dtoh32(bss_list->count);
+
+ err = wl_inform_bss(wl, bss_list);
+ kfree(bss_list);
+
+scan_done_out:
+ if (wl->scan_request) {
+ cfg80211_scan_done(wl->scan_request, false);
+ wl->scan_request = NULL;
+ }
+ rtnl_unlock();
+ return err;
+}
+
+static void wl_init_conf(struct wl_cfg80211_conf *conf)
+{
+ conf->mode = (u32)-1;
+ conf->frag_threshold = (u32)-1;
+ conf->rts_threshold = (u32)-1;
+ conf->retry_short = (u32)-1;
+ conf->retry_long = (u32)-1;
+ conf->tx_power = -1;
+}
+
+static void wl_init_prof(struct wl_cfg80211_profile *prof)
+{
+ memset(prof, 0, sizeof(*prof));
+}
+
+static void wl_init_eloop_handler(struct wl_cfg80211_event_loop *el)
+{
+ memset(el, 0, sizeof(*el));
+ el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
+ el->handler[WLC_E_JOIN] = wl_notify_connect_status;
+ el->handler[WLC_E_START] = wl_notify_connect_status;
+ el->handler[WLC_E_LINK] = wl_notify_connect_status;
+ el->handler[WLC_E_NDIS_LINK] = wl_notify_connect_status;
+ el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
+ el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
+ el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
+ el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
+ el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
+}
+
+static s32 wl_init_priv_mem(struct wl_cfg80211_priv *wl)
+{
+ wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
+ if (!wl->conf) {
+ WL_ERR(("wl_cfg80211_conf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL);
+ if (!wl->profile) {
+ WL_ERR(("wl_cfg80211_profile alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->scan_req_int = (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
+ if (!wl->scan_req_int) {
+ WL_ERR(("Scan req alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
+ if (!wl->ioctl_buf) {
+ WL_ERR(("Ioctl buf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+ if (!wl->extra_buf) {
+ WL_ERR(("Extra buf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+
+ wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
+ if (!wl->pmk_list) {
+ WL_ERR(("pmk list alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+
+ return 0;
+
+init_priv_mem_out:
+ wl_deinit_priv_mem(wl);
+
+ return -ENOMEM;
+}
+
+static void wl_deinit_priv_mem(struct wl_cfg80211_priv *wl)
+{
+ kfree(wl->conf);
+ wl->conf = NULL;
+ kfree(wl->profile);
+ wl->profile = NULL;
+ kfree(wl->scan_req_int);
+ wl->scan_req_int = NULL;
+ kfree(wl->ioctl_buf);
+ wl->ioctl_buf = NULL;
+ kfree(wl->extra_buf);
+ wl->extra_buf = NULL;
+ kfree(wl->pmk_list);
+ wl->pmk_list = NULL;
+}
+
+static s32 wl_create_event_handler(struct wl_cfg80211_priv *wl)
+{
+ sema_init(&wl->event_sync, 0);
+ wl->event_tsk = kthread_run(wl_event_handler, wl, "wl_event_handler");
+ if (IS_ERR(wl->event_tsk)) {
+ wl->event_tsk = NULL;
+ WL_ERR(("failed to create event thread\n"));
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void wl_destroy_event_handler(struct wl_cfg80211_priv *wl)
+{
+ if (wl->event_tsk) {
+ send_sig(SIGTERM, wl->event_tsk, 1);
+ kthread_stop(wl->event_tsk);
+ wl->event_tsk = NULL;
+ }
+}
+
+static s32 wl_init_cfg80211_priv(struct wl_cfg80211_priv *wl, struct wireless_dev *wdev)
+{
+ s32 err = 0;
+
+ wl->wdev = wdev;
+
+ wl->scan_request = NULL;
+ wl->active_scan = true;
+ wl_init_eq(wl);
+ err = wl_init_priv_mem(wl);
+ if (err)
+ return err;
+
+ if (wl_create_event_handler(wl))
+ return -ENOMEM;
+
+ wl_init_eloop_handler(&wl->el);
+
+ if (err)
+ return err;
+
+ wl_init_conf(wl->conf);
+ wl_init_prof(wl->profile);
+ wl_link_down(wl);
+
+ return err;
+}
+
+static void wl_deinit_cfg80211_priv(struct wl_cfg80211_priv *wl)
+{
+ wl_destroy_event_handler(wl);
+ wl_flush_eq(wl);
+ wl_link_down(wl);
+ wl_deinit_priv_mem(wl);
+}
+
+s32 wl_cfg80211_attach(struct net_device *ndev, struct device *dev, int passive)
+{
+ struct wireless_dev *wdev;
+ struct wl_cfg80211_priv *wl;
+ s32 err = 0;
+
+ if (!ndev) {
+ WL_ERR(("ndev is invaild\n"));
+ return -ENODEV;
+ }
+
+ err = wl_alloc_wdev(dev, &wdev);
+ if (err < 0) {
+ return err;
+ }
+
+ wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
+ wl = wdev_to_wl(wdev);
+ ndev->ieee80211_ptr = wdev;
+ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+ wdev->netdev = ndev;
+ err = wl_init_cfg80211_priv(wl, wdev);
+ if (err) {
+ WL_ERR(("Failed to init iwm_priv (%d)\n", err));
+ goto cfg80211_attach_out;
+ }
+ wl->passive = !!passive;
+
+ if (!err) {
+ WL_INF(("Registered CFG80211 phy\n"));
+ }
+ return err;
+
+cfg80211_attach_out:
+ wl_free_wdev(wl);
+ return err;
+}
+
+void wl_cfg80211_detach(struct net_device *ndev)
+{
+ struct wl_cfg80211_priv *wl;
+
+ if (ndev->ieee80211_ptr == NULL) {
+ WL_ERR(( "NULL ndev->ieee80211ptr, unable to deref wl\n"));
+ return;
+ }
+ wl = ndev_to_wl(ndev);
+
+ wl_deinit_cfg80211_priv(wl);
+ wl_free_wdev(wl);
+}
+
+static void wl_wakeup_event(struct wl_cfg80211_priv *wl)
+{
+ up(&wl->event_sync);
+}
+
+static s32 wl_event_handler(void *data)
+{
+ struct wl_cfg80211_priv *wl = (struct wl_cfg80211_priv *)data;
+ struct wl_cfg80211_event_q *e;
+
+ allow_signal(SIGTERM);
+ while (!down_interruptible(&wl->event_sync)) {
+ if (kthread_should_stop())
+ break;
+ e = wl_deq_event(wl);
+ if (!e) {
+ WL_ERR(("eqeue empty..\n"));
+ BUG();
+ }
+ if (wl->el.handler[e->etype]) {
+ WL_DBG(("event type (%d)\n", e->etype));
+ wl->el.handler[e->etype] (wl, wl_to_ndev(wl), &e->emsg, e->edata);
+ } else {
+ WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
+ }
+ wl_put_event(e);
+ }
+ WL_DBG(("%s was terminated\n", __func__));
+ return 0;
+}
+
+void
+wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+{
+
+ u32 event_type = EVENT_TYPE(e);
+
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+#if defined(WL_DBGMSG_ENABLE)
+ s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
+ wl_dbg_estr[event_type] : (s8 *) "Unknown";
+ WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
+#endif
+ if (!wl_enq_event(wl, event_type, e, data))
+ wl_wakeup_event(wl);
+}
+
+static void wl_init_eq(struct wl_cfg80211_priv *wl)
+{
+ wl_init_eq_lock(wl);
+ INIT_LIST_HEAD(&wl->eq_list);
+}
+
+static void wl_flush_eq(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_event_q *e;
+
+ wl_lock_eq(wl);
+ while (!list_empty(&wl->eq_list)) {
+ e = list_first_entry(&wl->eq_list, struct wl_cfg80211_event_q, eq_list);
+ list_del(&e->eq_list);
+ kfree(e);
+ }
+ wl_unlock_eq(wl);
+}
+
+static struct wl_cfg80211_event_q *wl_deq_event(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_event_q *e = NULL;
+
+ wl_lock_eq(wl);
+ if (!list_empty(&wl->eq_list)) {
+ e = list_first_entry(&wl->eq_list, struct wl_cfg80211_event_q, eq_list);
+ list_del(&e->eq_list);
+ }
+ wl_unlock_eq(wl);
+
+ return e;
+}
+
+static s32
+wl_enq_event(struct wl_cfg80211_priv *wl, u32 event, const wl_event_msg_t *msg, void *data)
+{
+ struct wl_cfg80211_event_q *e;
+ s32 err = 0;
+
+ e = kzalloc(sizeof(struct wl_cfg80211_event_q), GFP_ATOMIC);
+ if (!e) {
+ WL_ERR(("event alloc failed\n"));
+ return -ENOMEM;
+ }
+
+ e->etype = event;
+ memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
+ if (data) {
+ }
+
+ spin_lock(&wl->eq_lock);
+ list_add_tail(&e->eq_list, &wl->eq_list);
+ spin_unlock(&wl->eq_lock);
+
+ return err;
+}
+
+static void wl_put_event(struct wl_cfg80211_event_q *e)
+{
+ kfree(e);
+}
+
+static s32 wl_set_mode(struct net_device *ndev, s32 iftype)
+{
+ s32 infra = 0;
+ s32 ap = 0;
+ s32 err = 0;
+
+ switch (iftype) {
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ WL_ERR(("type (%d) : currently we do not support this mode\n",
+ iftype));
+ err = -EINVAL;
+ return err;
+ case NL80211_IFTYPE_ADHOC:
+ break;
+ case NL80211_IFTYPE_STATION:
+ infra = 1;
+ break;
+ default:
+ err = -EINVAL;
+ WL_ERR(("invalid type (%d)\n", iftype));
+ return err;
+ }
+ infra = htod32(infra);
+ ap = htod32(ap);
+ WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
+ err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+ if (err) {
+ WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+ return err;
+ }
+ err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
+ if (err) {
+ WL_ERR(("WLC_SET_AP error (%d)\n", err));
+ return err;
+ }
+
+ return 0;
+}
+
+static void wl_update_wowl(struct net_device *ndev)
+{
+#ifdef CONFIG_PM
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ struct wireless_dev *wdev = ndev->ieee80211_ptr;
+ s32 offloads = 0;
+ s32 err = 0;
+ err = wl_dev_bufvar_get(wl_to_ndev(wl), "offloads",
+ (s8 *)&offloads, sizeof(offloads));
+ if (err == 0 && offloads == 1) {
+ WL_INF(("Supports offloads\n"));
+ wl->offloads = true;
+ } else {
+ WL_INF(("No offloads supported\n"));
+ wl->offloads = false;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+ wdev->wiphy->wowlan = NULL;
+#else
+ memset(&wdev->wiphy->wowlan, 0, sizeof(struct wiphy_wowlan_support));
+#endif
+#endif
+ }
+#endif
+}
+
+static s32 wl_update_wiphybands(struct wl_cfg80211_priv *wl)
+{
+ struct wiphy *wiphy;
+ s32 phy_list;
+ s8 phy;
+ s32 err = 0;
+
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list, sizeof(phy_list));
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ phy = ((char *)&phy_list)[0];
+ WL_DBG(("%c phy\n", phy));
+
+ if (phy == 'n' || phy == 'a' || phy == 'v') {
+ wiphy = wl_to_wiphy(wl);
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+ }
+
+ return err;
+}
+
+s32 wl_cfg80211_up(struct net_device *ndev)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ s32 err = 0;
+ struct wireless_dev *wdev = ndev->ieee80211_ptr;
+
+ wl_set_mode(ndev, wdev->iftype);
+ err = wl_update_wiphybands(wl);
+ if (err) {
+ return err;
+ }
+
+ wl_update_wowl(ndev);
+ return 0;
+}
+
+s32 wl_cfg80211_down(struct net_device *ndev)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ s32 err = 0;
+
+ if (wl->scan_request) {
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ }
+
+ return err;
+}
+
+static bool wl_is_ibssmode(struct wl_cfg80211_priv *wl)
+{
+ return wl->conf->mode == WL_MODE_IBSS;
+}
+
+static void wl_rst_ie(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+
+ ie->offset = 0;
+}
+
+static __used s32 wl_add_ie(struct wl_cfg80211_priv *wl, u8 t, u8 l, u8 *v)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+ s32 err = 0;
+
+ if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
+ WL_ERR(("ei crosses buffer boundary\n"));
+ return -ENOSPC;
+ }
+ ie->buf[ie->offset] = t;
+ ie->buf[ie->offset + 1] = l;
+ memcpy(&ie->buf[ie->offset + 2], v, l);
+ ie->offset += l + 2;
+
+ return err;
+}
+
+static s32 wl_mrg_ie(struct wl_cfg80211_priv *wl, u8 *ie_stream, u16 ie_size)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+ s32 err = 0;
+
+ if (ie->offset + ie_size > WL_TLV_INFO_MAX) {
+ WL_ERR(("ei_stream crosses buffer boundary\n"));
+ return -ENOSPC;
+ }
+ memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
+ ie->offset += ie_size;
+
+ return err;
+}
+
+static s32 wl_cp_ie(struct wl_cfg80211_priv *wl, u8 *dst, u16 dst_size)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+ s32 err = 0;
+
+ if (ie->offset > dst_size) {
+ WL_ERR(("dst_size is not enough\n"));
+ return -ENOSPC;
+ }
+ memcpy(dst, &ie->buf[0], ie->offset);
+
+ return err;
+}
+
+static u32 wl_get_ielen(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+
+ return ie->offset;
+}
+
+static void wl_link_up(struct wl_cfg80211_priv *wl)
+{
+ WL_DBG(("\n"));
+}
+
+static void wl_link_down(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+
+ WL_DBG(("\n"));
+
+ kfree(conn_info->req_ie);
+ conn_info->req_ie = NULL;
+ conn_info->req_ie_len = 0;
+ kfree(conn_info->resp_ie);
+ conn_info->resp_ie = NULL;
+ conn_info->resp_ie_len = 0;
+}
+
+static void wl_lock_eq(struct wl_cfg80211_priv *wl)
+{
+ spin_lock_irq(&wl->eq_lock);
+}
+
+static void wl_unlock_eq(struct wl_cfg80211_priv *wl)
+{
+ spin_unlock_irq(&wl->eq_lock);
+}
+
+static void wl_init_eq_lock(struct wl_cfg80211_priv *wl)
+{
+ spin_lock_init(&wl->eq_lock);
+}
+
+#endif
diff --git a/src/wl/sys/wl_cfg80211_hybrid.h b/src/wl/sys/wl_cfg80211_hybrid.h
new file mode 100644
index 0000000..bc6f3ad
--- /dev/null
+++ b/src/wl/sys/wl_cfg80211_hybrid.h
@@ -0,0 +1,231 @@
+/*
+ * Linux-specific portion of Broadcom 802.11abg Networking Device Driver
+ * cfg80211 interface
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_cfg80211.h,v 1.1.8.1 2011-01-26 00:57:46 $
+ */
+
+#ifndef _wl_cfg80211_h_
+#define _wl_cfg80211_h_
+
+#include <net/cfg80211.h>
+#include <wlioctl.h>
+
+struct wl_cfg80211_conf;
+struct wl_cfg80211_priv;
+struct wl_cfg80211_security;
+
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+#define htodchanspec(i) i
+#define dtohchanspec(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+
+#define WL_DBGMSG_ENABLE
+
+#define WL_DBG_NONE 0
+#define WL_DBG_DBG (1 << 2)
+#define WL_DBG_INFO (1 << 1)
+#define WL_DBG_ERR (1 << 0)
+#define WL_DBG_MASK ((WL_DBG_DBG | WL_DBG_INFO | WL_DBG_ERR) << 1)
+
+#if defined(WL_DBGMSG_ENABLE)
+#define WL_DBG(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_DBG) { \
+ printk(KERN_ERR "DEBUG @%s :", __func__); \
+ printk args; \
+ } \
+} while (0)
+#else
+#define WL_DBG(args)
+#endif
+
+#define WL_ERR(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_ERR) { \
+ if (net_ratelimit()) { \
+ printk(KERN_ERR "ERROR @%s : ", __func__); \
+ printk args; \
+ } \
+ } \
+} while (0)
+
+#define WL_INF(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_INFO) { \
+ if (net_ratelimit()) { \
+ printk(KERN_ERR "INFO @%s : ", __func__); \
+ printk args; \
+ } \
+ } \
+} while (0)
+
+#define WL_NUM_SCAN_MAX 1
+#define WL_NUM_PMKIDS_MAX MAXPMKID
+#define WL_SCAN_BUF_BASE (16*1024)
+#define WL_TLV_INFO_MAX 1024
+#define WL_BSS_INFO_MAX 2048
+#define WL_ASSOC_INFO_MAX 512
+#define WL_IOCTL_LEN_MAX 2048
+#define WL_EXTRA_BUF_MAX 2048
+#define WL_AP_MAX 256
+
+enum wl_cfg80211_status {
+ WL_STATUS_CONNECTING,
+ WL_STATUS_CONNECTED
+};
+
+enum wl_cfg80211_mode {
+ WL_MODE_BSS,
+ WL_MODE_IBSS,
+ WL_MODE_AP
+};
+
+struct beacon_proberesp {
+ __le64 timestamp;
+ __le16 beacon_int;
+ __le16 capab_info;
+ u8 variable[0];
+} __attribute__ ((packed));
+
+struct wl_cfg80211_conf {
+ u32 mode;
+ u32 frag_threshold;
+ u32 rts_threshold;
+ u32 retry_short;
+ u32 retry_long;
+ s32 tx_power;
+ struct ieee80211_channel channel;
+};
+
+struct wl_cfg80211_event_loop {
+ s32(*handler[WLC_E_LAST]) (struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+};
+
+struct wl_cfg80211_bss_info {
+ u16 band;
+ u16 channel;
+ s16 rssi;
+ u16 frame_len;
+ u8 frame_buf[1];
+};
+
+struct wl_cfg80211_scan_req {
+ struct wlc_ssid ssid;
+};
+
+struct wl_cfg80211_ie {
+ u16 offset;
+ u8 buf[WL_TLV_INFO_MAX];
+};
+
+struct wl_cfg80211_event_q {
+ struct list_head eq_list;
+ u32 etype;
+ wl_event_msg_t emsg;
+ s8 edata[1];
+};
+
+struct wl_cfg80211_security {
+ u32 wpa_versions;
+ u32 auth_type;
+ u32 cipher_pairwise;
+ u32 cipher_group;
+ u32 wpa_auth;
+};
+
+struct wl_cfg80211_profile {
+ struct wlc_ssid ssid;
+ u8 bssid[ETHER_ADDR_LEN];
+ struct wl_cfg80211_security sec;
+ bool active;
+};
+
+struct wl_cfg80211_connect_info {
+ u8 *req_ie;
+ s32 req_ie_len;
+ u8 *resp_ie;
+ s32 resp_ie_len;
+};
+
+struct wl_cfg80211_assoc_ielen {
+ u32 req_len;
+ u32 resp_len;
+};
+
+struct wl_cfg80211_pmk_list {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID - 1];
+};
+
+struct wl_cfg80211_priv {
+ struct wireless_dev *wdev;
+ struct wl_cfg80211_conf *conf;
+ struct cfg80211_scan_request *scan_request;
+ struct wl_cfg80211_event_loop el;
+ struct list_head eq_list;
+ spinlock_t eq_lock;
+ struct wl_cfg80211_scan_req *scan_req_int;
+ struct wl_cfg80211_ie ie;
+ struct ether_addr bssid;
+ struct semaphore event_sync;
+ struct wl_cfg80211_profile *profile;
+ struct wl_cfg80211_connect_info conn_info;
+ struct wl_cfg80211_pmk_list *pmk_list;
+ struct task_struct *event_tsk;
+ unsigned long status;
+ bool active_scan;
+ bool passive;
+ bool offloads;
+ u8 *ioctl_buf;
+ u8 *extra_buf;
+ u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
+};
+
+#define wl_to_dev(w) (wiphy_dev(wl->wdev->wiphy))
+#define wl_to_wiphy(w) (w->wdev->wiphy)
+#define wiphy_to_wl(w) ((struct wl_cfg80211_priv *)(wiphy_priv(w)))
+#define wl_to_wdev(w) (w->wdev)
+#define wdev_to_wl(w) ((struct wl_cfg80211_priv *)(wdev_priv(w)))
+#define wl_to_ndev(w) (w->wdev->netdev)
+#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr))
+#define wl_to_sr(w) (w->scan_req_int)
+#define wl_to_ie(w) (&w->ie)
+#define wl_to_conn(w) (&w->conn_info)
+
+static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
+{
+ return bss = bss ? (struct wl_bss_info *)((unsigned long)bss +
+ dtoh32(bss->length)) : list->bss_info;
+}
+
+#define for_each_bss(list, bss, __i) \
+ for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
+
+extern s32 wl_cfg80211_attach(struct net_device *ndev, struct device *dev, int flags);
+extern void wl_cfg80211_detach(struct net_device *ndev);
+
+extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data);
+extern s32 wl_cfg80211_up(struct net_device *ndev);
+extern s32 wl_cfg80211_down(struct net_device *ndev);
+
+#endif
diff --git a/src/wl/sys/wl_dbg.h b/src/wl/sys/wl_dbg.h
new file mode 100644
index 0000000..dc8bf26
--- /dev/null
+++ b/src/wl/sys/wl_dbg.h
@@ -0,0 +1,74 @@
+/*
+ * Minimal debug/trace/assert driver definitions for
+ * Broadcom 802.11 Networking Adapter.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_dbg.h 405851 2013-06-05 00:56:21Z $
+ */
+
+#ifndef _wl_dbg_h_
+#define _wl_dbg_h_
+
+extern uint32 wl_msg_level;
+extern uint32 wl_msg_level2;
+
+#if defined(BCMDBG) && !defined(BCMDBG_EXCLUDE_HW_TIMESTAMP)
+extern char* wlc_dbg_get_hw_timestamp(void);
+
+#define WL_TIMESTAMP() do { if (wl_msg_level2 & WL_TIMESTAMP_VAL) {\
+ printf(wlc_dbg_get_hw_timestamp()); }\
+ } while (0)
+#else
+#define WL_TIMESTAMP()
+#endif
+
+#if 0 && (VERSION_MAJOR > 9)
+extern int osl_printf(const char *fmt, ...);
+#include <IOKit/apple80211/IO8Log.h>
+#define WL_PRINT(args) do { osl_printf args; } while (0)
+#define RELEASE_PRINT(args) do { WL_PRINT(args); IO8Log args; } while (0)
+#else
+#define WL_PRINT(args) do { WL_TIMESTAMP(); printf args; } while (0)
+#endif
+
+#ifdef BCMDBG
+
+#define WL_NONE(args) do {if (wl_msg_level & 0) WL_PRINT(args);} while (0)
+
+#define WL_ERROR(args) do {if (wl_msg_level & WL_ERROR_VAL) WL_PRINT(args);} while (0)
+#define WL_TRACE(args) do {if (wl_msg_level & WL_TRACE_VAL) WL_PRINT(args);} while (0)
+
+#else
+
+#define WL_NONE(args)
+
+#ifdef BCMDBG_ERR
+#define WL_ERROR(args) WL_PRINT(args)
+#else
+#define WL_ERROR(args)
+#endif
+#define WL_TRACE(args)
+#define WL_APSTA_UPDN(args)
+#define WL_APSTA_RX(args)
+#define WL_WSEC(args)
+#define WL_WSEC_DUMP(args)
+#define WL_PCIE(args) do {if (wl_msg_level2 & WL_PCIE_VAL) WL_PRINT(args);} while (0)
+#define WL_PCIE_ON() (wl_msg_level2 & WL_PCIE_VAL)
+#endif
+
+extern uint32 wl_msg_level;
+extern uint32 wl_msg_level2;
+#endif
diff --git a/src/wl/sys/wl_export.h b/src/wl/sys/wl_export.h
new file mode 100644
index 0000000..41d4251
--- /dev/null
+++ b/src/wl/sys/wl_export.h
@@ -0,0 +1,81 @@
+/*
+ * Required functions exported by the port-specific (os-dependent) driver
+ * to common (os-independent) driver code.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_export.h 579954 2015-08-17 18:08:53Z $
+ */
+
+#ifndef _wl_export_h_
+#define _wl_export_h_
+
+struct wl_info;
+struct wl_if;
+struct wlc_if;
+extern void wl_init(struct wl_info *wl);
+extern uint wl_reset(struct wl_info *wl);
+extern void wl_intrson(struct wl_info *wl);
+extern uint32 wl_intrsoff(struct wl_info *wl);
+extern void wl_intrsrestore(struct wl_info *wl, uint32 macintmask);
+extern void wl_event(struct wl_info *wl, char *ifname, wlc_event_t *e);
+extern void wl_event_sync(struct wl_info *wl, char *ifname, wlc_event_t *e);
+extern void wl_event_sendup(struct wl_info *wl, const wlc_event_t *e, uint8 *data, uint32 len);
+extern int wl_up(struct wl_info *wl);
+extern void wl_down(struct wl_info *wl);
+extern void wl_dump_ver(struct wl_info *wl, struct bcmstrbuf *b);
+extern void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state, int prio);
+extern bool wl_alloc_dma_resources(struct wl_info *wl, uint dmaddrwidth);
+extern void wl_reclaim(void);
+extern void wl_nocard_timer(void *arg);
+extern void wl_recover_nocard(struct wl_info *wl);
+extern void wl_devicerecovery(struct wl_info *wl );
+
+extern uint32 wl_pcie_bar1(struct wl_info *wl, uchar** addr);
+
+struct wl_timer;
+extern struct wl_timer *wl_init_timer(struct wl_info *wl, void (*fn)(void* arg), void *arg,
+ const char *name);
+extern void wl_free_timer(struct wl_info *wl, struct wl_timer *timer);
+extern void wl_add_timer(struct wl_info *wl, struct wl_timer *timer, uint ms, int periodic);
+extern bool wl_del_timer(struct wl_info *wl, struct wl_timer *timer);
+
+extern void wl_sendup(struct wl_info *wl, struct wl_if *wlif, void *p, int numpkt);
+extern char *wl_ifname(struct wl_info *wl, struct wl_if *wlif);
+extern struct wl_if *wl_add_if(struct wl_info *wl, struct wlc_if* wlcif, uint unit,
+ struct ether_addr *remote);
+extern void wl_del_if(struct wl_info *wl, struct wl_if *wlif);
+#ifdef DWDS
+extern void wl_dwds_del_if(struct wl_info *wl, struct wl_if *wlif, bool force);
+#endif
+
+extern int wl_osl_pcie_rc(struct wl_info *wl, uint op, int param);
+
+extern void wl_monitor(struct wl_info *wl, wl_rxsts_t *rxsts, void *p);
+extern void wl_set_monitor(struct wl_info *wl, int val);
+
+extern uint wl_buf_to_pktcopy(osl_t *osh, void *p, uchar *buf, int len, uint offset);
+extern void * wl_get_pktbuffer(osl_t *osh, int len);
+extern int wl_set_pktlen(osl_t *osh, void *p, int len);
+
+#define IFCTX_ARPI (1)
+#define IFCTX_NDI (2)
+#define IFCTX_NETDEV (3)
+extern void *wl_get_ifctx(struct wl_info *wl, int ctx_id, wl_if_t *wlif);
+
+#define wl_sort_bsslist(a, b) FALSE
+
+#define wl_outputpacket_complete(a, b, c) do { } while (0)
+#endif
diff --git a/src/wl/sys/wl_iw.c b/src/wl/sys/wl_iw.c
new file mode 100644
index 0000000..c4c610b
--- /dev/null
+++ b/src/wl/sys/wl_iw.c
@@ -0,0 +1,2830 @@
+/*
+ * Linux Wireless Extensions support
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_iw.c 458427 2014-02-26 23:12:38Z $
+ */
+
+#if defined(USE_IW)
+#define LINUX_PORT
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+typedef const struct si_pub si_t;
+#include <wlioctl.h>
+
+#include <wl_dbg.h>
+#include <wl_iw.h>
+
+extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
+ uint32 reason, char* stringBuf, uint buflen);
+
+#define MAX_WLIW_IOCTL_LEN 1024
+
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+#define htodchanspec(i) i
+#define dtohchanspec(i) i
+
+extern struct iw_statistics *wl_get_wireless_stats(struct net_device *dev);
+
+#if WIRELESS_EXT < 19
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+#endif
+
+typedef struct priv_link {
+ wl_iw_t *wliw;
+} priv_link_t;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#define WL_DEV_LINK(dev) (priv_link_t*)(dev->priv)
+#else
+#define WL_DEV_LINK(dev) (priv_link_t*)netdev_priv(dev)
+#endif
+
+#define IW_DEV_IF(dev) ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw)
+
+static void swap_key_from_BE(
+ wl_wsec_key_t *key
+)
+{
+ key->index = htod32(key->index);
+ key->len = htod32(key->len);
+ key->algo = htod32(key->algo);
+ key->flags = htod32(key->flags);
+ key->rxiv.hi = htod32(key->rxiv.hi);
+ key->rxiv.lo = htod16(key->rxiv.lo);
+ key->iv_initialized = htod32(key->iv_initialized);
+}
+
+static void swap_key_to_BE(
+ wl_wsec_key_t *key
+)
+{
+ key->index = dtoh32(key->index);
+ key->len = dtoh32(key->len);
+ key->algo = dtoh32(key->algo);
+ key->flags = dtoh32(key->flags);
+ key->rxiv.hi = dtoh32(key->rxiv.hi);
+ key->rxiv.lo = dtoh16(key->rxiv.lo);
+ key->iv_initialized = dtoh32(key->iv_initialized);
+}
+
+static int
+dev_wlc_ioctl(
+ struct net_device *dev,
+ int cmd,
+ void *arg,
+ int len
+)
+{
+ struct ifreq ifr;
+ wl_ioctl_t ioc;
+ mm_segment_t fs;
+ int ret;
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t) &ioc;
+
+ fs = get_fs();
+ set_fs(get_ds());
+#if defined(WL_USE_NETDEV_OPS)
+ ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#else
+ ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif
+ set_fs(fs);
+
+ return ret;
+}
+
+static int
+dev_wlc_intvar_set(
+ struct net_device *dev,
+ char *name,
+ int val)
+{
+ char buf[WLC_IOCTL_SMLEN];
+ uint len;
+
+ val = htod32(val);
+ len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+ ASSERT(len);
+
+ return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
+}
+
+#if WIRELESS_EXT > 17
+static int
+dev_wlc_bufvar_set(
+ struct net_device *dev,
+ char *name,
+ char *buf, int len)
+{
+ char *ioctlbuf;
+ uint buflen;
+ int error;
+
+ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
+ if (!ioctlbuf)
+ return -ENOMEM;
+
+ buflen = bcm_mkiovar(name, buf, len, ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ ASSERT(buflen);
+ error = dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen);
+
+ kfree(ioctlbuf);
+ return error;
+}
+#endif
+
+static int
+dev_wlc_bufvar_get(
+ struct net_device *dev,
+ char *name,
+ char *buf, int buflen)
+{
+ char *ioctlbuf;
+ int error;
+
+ uint len;
+
+ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
+ if (!ioctlbuf)
+ return -ENOMEM;
+ len = bcm_mkiovar(name, NULL, 0, ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ ASSERT(len);
+ BCM_REFERENCE(len);
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ if (!error)
+ bcopy(ioctlbuf, buf, buflen);
+
+ kfree(ioctlbuf);
+ return (error);
+}
+
+static int
+dev_wlc_intvar_get(
+ struct net_device *dev,
+ char *name,
+ int *retval)
+{
+ union {
+ char buf[WLC_IOCTL_SMLEN];
+ int val;
+ } var;
+ int error;
+
+ uint len;
+ uint data_null;
+
+ len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
+ ASSERT(len);
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
+
+ *retval = dtoh32(var.val);
+
+ return (error);
+}
+
+#if WIRELESS_EXT < 13
+struct iw_request_info
+{
+ __u16 cmd;
+ __u16 flags;
+};
+
+typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
+ void *wrqu, char *extra);
+#endif
+
+#if WIRELESS_EXT > 12
+static int
+wl_iw_set_leddc(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int dc = *(int *)extra;
+ int error;
+
+ error = dev_wlc_intvar_set(dev, "leddc", dc);
+ return error;
+}
+
+static int
+wl_iw_set_vlanmode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int mode = *(int *)extra;
+ int error;
+
+ mode = htod32(mode);
+ error = dev_wlc_intvar_set(dev, "vlan_mode", mode);
+ return error;
+}
+
+static int
+wl_iw_set_pm(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int pm = *(int *)extra;
+ int error;
+
+ pm = htod32(pm);
+ error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+ return error;
+}
+#endif
+
+int
+wl_iw_send_priv_event(
+ struct net_device *dev,
+ char *flag
+)
+{
+ union iwreq_data wrqu;
+ char extra[IW_CUSTOM_MAX + 1];
+ int cmd;
+
+ cmd = IWEVCUSTOM;
+ memset(&wrqu, 0, sizeof(wrqu));
+ if (strlen(flag) > sizeof(extra))
+ return -1;
+
+ strcpy(extra, flag);
+ wrqu.data.length = strlen(extra);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
+
+ return 0;
+}
+
+static int
+wl_iw_config_commit(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ void *zwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+ struct sockaddr bssid;
+
+ WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
+ return error;
+
+ ssid.SSID_len = dtoh32(ssid.SSID_len);
+
+ if (!ssid.SSID_len)
+ return 0;
+
+ bzero(&bssid, sizeof(struct sockaddr));
+ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
+ WL_ERROR(("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error));
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_name(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *cwrq,
+ char *extra
+)
+{
+ int phytype, err;
+ uint band[3];
+ char cap[5];
+
+ WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
+
+ cap[0] = 0;
+ if ((err = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))) < 0)
+ goto done;
+ if ((err = dev_wlc_ioctl(dev, WLC_GET_BANDLIST, band, sizeof(band))) < 0)
+ goto done;
+
+ band[0] = dtoh32(band[0]);
+ switch (phytype) {
+ case WLC_PHY_TYPE_A:
+ strcpy(cap, "a");
+ break;
+ case WLC_PHY_TYPE_B:
+ strcpy(cap, "b");
+ break;
+ case WLC_PHY_TYPE_LP:
+ case WLC_PHY_TYPE_G:
+ if (band[0] >= 2)
+ strcpy(cap, "abg");
+ else
+ strcpy(cap, "bg");
+ break;
+ case WLC_PHY_TYPE_N:
+ if (band[0] >= 2)
+ strcpy(cap, "abgn");
+ else
+ strcpy(cap, "bgn");
+ break;
+ }
+done:
+ snprintf(cwrq->name, IFNAMSIZ, "IEEE 802.11%s", cap);
+ return 0;
+}
+
+static int
+wl_iw_set_freq(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra
+)
+{
+ int error, chan;
+ uint sf = 0;
+
+ WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name));
+
+ if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
+ chan = fwrq->m;
+ }
+
+ else {
+
+ if (fwrq->e >= 6) {
+ fwrq->e -= 6;
+ while (fwrq->e--)
+ fwrq->m *= 10;
+ } else if (fwrq->e < 6) {
+ while (fwrq->e++ < 6)
+ fwrq->m /= 10;
+ }
+
+ if (fwrq->m > 4000 && fwrq->m < 5000)
+ sf = WF_CHAN_FACTOR_4_G;
+
+ chan = wf_mhz2channel(fwrq->m, sf);
+ }
+ chan = htod32(chan);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
+ return error;
+
+ return -EINPROGRESS;
+}
+
+static int
+wl_iw_get_freq(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra
+)
+{
+ channel_info_t ci;
+ int error;
+
+ WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+ return error;
+
+ fwrq->m = dtoh32(ci.hw_channel);
+ fwrq->e = dtoh32(0);
+ return 0;
+}
+
+static int
+wl_iw_set_mode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra
+)
+{
+ int infra = 0, ap = 0, error = 0;
+
+ WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
+
+ switch (*uwrq) {
+ case IW_MODE_MASTER:
+ infra = ap = 1;
+ break;
+ case IW_MODE_ADHOC:
+ case IW_MODE_AUTO:
+ break;
+ case IW_MODE_INFRA:
+ infra = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ infra = htod32(infra);
+ ap = htod32(ap);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
+ (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
+ return error;
+
+ return -EINPROGRESS;
+}
+
+static int
+wl_iw_get_mode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra
+)
+{
+ int error, infra = 0, ap = 0;
+
+ WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
+ return error;
+
+ infra = dtoh32(infra);
+ ap = dtoh32(ap);
+ *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
+
+ return 0;
+}
+
+static int
+wl_iw_get_range(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+ static int channels[MAXCHANNEL+1];
+ wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
+ wl_rateset_t rateset;
+ int error, i, k;
+ uint sf, ch;
+
+ int phytype;
+ int bw_cap = 0, sgi_tx = 0, nmode = 0;
+ channel_info_t ci;
+ uint8 nrate_list2copy = 0;
+ uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
+ {14, 29, 43, 58, 87, 116, 130, 144},
+ {27, 54, 81, 108, 162, 216, 243, 270},
+ {30, 60, 90, 120, 180, 240, 270, 300}};
+
+ WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ dwrq->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(*range));
+
+ range->min_nwid = range->max_nwid = 0;
+
+ list->count = htod32(MAXCHANNEL);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
+ return error;
+ for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
+ range->freq[i].i = dtoh32(list->element[i]);
+
+ ch = dtoh32(list->element[i]);
+ if (ch <= CH_MAX_2G_CHANNEL)
+ sf = WF_CHAN_FACTOR_2_4_G;
+ else
+ sf = WF_CHAN_FACTOR_5_G;
+
+ range->freq[i].m = wf_channel2mhz(ch, sf);
+ range->freq[i].e = 6;
+ }
+ range->num_frequency = range->num_channels = i;
+
+ range->max_qual.qual = 5;
+
+ range->max_qual.level = 0x100 - 200;
+
+ range->max_qual.noise = 0x100 - 200;
+
+ range->sensitivity = 65535;
+
+#if WIRELESS_EXT > 11
+
+ range->avg_qual.qual = 3;
+
+ range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
+
+ range->avg_qual.noise = 0x100 - 75;
+#endif
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+ return error;
+ rateset.count = dtoh32(rateset.count);
+ range->num_bitrates = rateset.count;
+ for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
+ range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000;
+ dev_wlc_intvar_get(dev, "nmode", &nmode);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))))
+ return error;
+
+ if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN) ||
+ (phytype == WLC_PHY_TYPE_LCN40))) {
+ dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
+ dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
+ dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t));
+ ci.hw_channel = dtoh32(ci.hw_channel);
+
+ if (bw_cap == 0 ||
+ (bw_cap == 2 && ci.hw_channel <= 14)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 0;
+ else
+ nrate_list2copy = 1;
+ }
+ if (bw_cap == 1 ||
+ (bw_cap == 2 && ci.hw_channel >= 36)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 2;
+ else
+ nrate_list2copy = 3;
+ }
+ range->num_bitrates += 8;
+ for (k = 0; i < range->num_bitrates; k++, i++) {
+
+ range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
+ }
+ }
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
+ return error;
+ i = dtoh32(i);
+ if (i == WLC_PHY_TYPE_A)
+ range->throughput = 24000000;
+ else
+ range->throughput = 1500000;
+
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+
+ range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
+ range->num_encoding_sizes = 4;
+ range->encoding_size[0] = WEP1_KEY_SIZE;
+ range->encoding_size[1] = WEP128_KEY_SIZE;
+#if WIRELESS_EXT > 17
+ range->encoding_size[2] = TKIP_KEY_SIZE;
+#else
+ range->encoding_size[2] = 0;
+#endif
+ range->encoding_size[3] = AES_KEY_SIZE;
+
+ range->min_pmp = 0;
+ range->max_pmp = 0;
+ range->min_pmt = 0;
+ range->max_pmt = 0;
+ range->pmp_flags = 0;
+ range->pm_capa = 0;
+
+ range->num_txpower = 2;
+ range->txpower[0] = 1;
+ range->txpower[1] = 255;
+ range->txpower_capa = IW_TXPOW_MWATT;
+
+#if WIRELESS_EXT > 10
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 19;
+
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->r_time_flags = 0;
+
+ range->min_retry = 1;
+ range->max_retry = 255;
+
+ range->min_r_time = 0;
+ range->max_r_time = 0;
+#endif
+
+#if WIRELESS_EXT > 17
+ range->enc_capa = IW_ENC_CAPA_WPA;
+ range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
+ range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
+ range->enc_capa |= IW_ENC_CAPA_WPA2;
+
+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
+
+#if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID)
+
+ range->scan_capa = IW_SCAN_CAPA_ESSID;
+#endif
+#endif
+
+ return 0;
+}
+
+static int
+rssi_to_qual(int rssi)
+{
+ if (rssi <= WL_IW_RSSI_NO_SIGNAL)
+ return 0;
+ else if (rssi <= WL_IW_RSSI_VERY_LOW)
+ return 1;
+ else if (rssi <= WL_IW_RSSI_LOW)
+ return 2;
+ else if (rssi <= WL_IW_RSSI_GOOD)
+ return 3;
+ else if (rssi <= WL_IW_RSSI_VERY_GOOD)
+ return 4;
+ else
+ return 5;
+}
+
+static int
+wl_iw_set_spy(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ int i;
+
+ WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
+ for (i = 0; i < iw->spy_num; i++)
+ memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
+ memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
+
+ return 0;
+}
+
+static int
+wl_iw_get_spy(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
+ int i;
+
+ WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ dwrq->length = iw->spy_num;
+ for (i = 0; i < iw->spy_num; i++) {
+ memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
+ addr[i].sa_family = AF_UNIX;
+ memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
+ iw->spy_qual[i].updated = 0;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_set_wap(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ int error = -EINVAL;
+#ifdef BCMDBG
+
+#endif
+
+ WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
+
+ if (awrq->sa_family != ARPHRD_ETHER) {
+ WL_ERROR(("%s: Invalid Header...sa_family\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
+ if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
+ scb_val_t scbval;
+ bzero(&scbval, sizeof(scb_val_t));
+ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
+ WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
+ }
+ return 0;
+ }
+
+ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) {
+ WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error));
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_wap(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
+
+ awrq->sa_family = ARPHRD_ETHER;
+ memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
+
+ (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static int
+wl_iw_mlme(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ struct iw_mlme *mlme;
+ scb_val_t scbval;
+ int error = -EINVAL;
+
+ WL_TRACE(("%s: SIOCSIWMLME\n", dev->name));
+
+ mlme = (struct iw_mlme *)extra;
+ if (mlme == NULL) {
+ WL_ERROR(("Invalid ioctl data.\n"));
+ return error;
+ }
+
+ scbval.val = mlme->reason_code;
+ bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
+
+ if (mlme->cmd == IW_MLME_DISASSOC) {
+ scbval.val = htod32(scbval.val);
+ error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
+ }
+ else if (mlme->cmd == IW_MLME_DEAUTH) {
+ scbval.val = htod32(scbval.val);
+ error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
+ sizeof(scb_val_t));
+ }
+ else {
+ WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__));
+ return error;
+ }
+
+ return error;
+}
+#endif
+
+static int
+wl_iw_get_aplist(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_scan_results_t *list;
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality qual[IW_MAX_AP];
+ wl_bss_info_t *bi = NULL;
+ int error, i;
+ uint buflen = dwrq->length;
+
+ WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ list = kmalloc(buflen, GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+ memset(list, 0, buflen);
+ list->buflen = htod32(buflen);
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
+ WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
+ kfree(list);
+ return error;
+ }
+ list->buflen = dtoh32(list->buflen);
+ list->version = dtoh32(list->version);
+ list->count = dtoh32(list->count);
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ buflen));
+
+ if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+ continue;
+
+ memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ addr[dwrq->length].sa_family = ARPHRD_ETHER;
+ qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
+ qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+ qual[dwrq->length].noise = 0x100 + bi->phy_noise;
+
+#if WIRELESS_EXT > 18
+ qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+ qual[dwrq->length].updated = 7;
+#endif
+
+ dwrq->length++;
+ }
+
+ kfree(list);
+
+ if (dwrq->length) {
+ memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
+
+ dwrq->flags = 1;
+ }
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 13
+static int
+wl_iw_set_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+
+ WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
+
+ memset(&ssid, 0, sizeof(ssid));
+
+#if WIRELESS_EXT > 17
+
+ if (wrqu->data.length == sizeof(struct iw_scan_req)) {
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
+ memcpy(ssid.SSID, req->essid, ssid.SSID_len);
+ ssid.SSID_len = htod32(ssid.SSID_len);
+ }
+ }
+#endif
+
+ (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static bool
+ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
+{
+
+ uint8 *ie = *wpaie;
+
+ if ((ie[1] >= 6) &&
+ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
+ return TRUE;
+ }
+
+ ie += ie[1] + 2;
+
+ *tlvs_len -= (int)(ie - *tlvs);
+
+ *tlvs = ie;
+ return FALSE;
+}
+
+static bool
+ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
+{
+
+ uint8 *ie = *wpsie;
+
+ if ((ie[1] >= 4) &&
+ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
+ return TRUE;
+ }
+
+ ie += ie[1] + 2;
+
+ *tlvs_len -= (int)(ie - *tlvs);
+
+ *tlvs = ie;
+ return FALSE;
+}
+#endif
+
+static int
+wl_iw_handle_scanresults_ies(char **event_p, char *end,
+ struct iw_request_info *info, wl_bss_info_t *bi)
+{
+#if WIRELESS_EXT > 17
+ struct iw_event iwe;
+ char *event;
+
+ event = *event_p;
+ if (bi->ie_length) {
+
+ bcm_tlv_t *ie;
+ uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ int ptr_len = bi->ie_length;
+
+ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ }
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+
+ if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ ptr_len = bi->ie_length;
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+ if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ *event_p = event;
+ }
+
+#endif
+ return 0;
+}
+static int
+wl_iw_get_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ channel_info_t ci;
+ wl_scan_results_t *list;
+ struct iw_event iwe;
+ wl_bss_info_t *bi = NULL;
+ int error, i, j;
+ char *event = extra, *end = extra + dwrq->length, *value;
+ uint buflen = dwrq->length;
+
+ WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+ return error;
+ ci.scan_channel = dtoh32(ci.scan_channel);
+ if (ci.scan_channel)
+ return -EAGAIN;
+
+ list = kmalloc(buflen, GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+ memset(list, 0, buflen);
+ list->buflen = htod32(buflen);
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
+ kfree(list);
+ return error;
+ }
+ list->buflen = dtoh32(list->buflen);
+ list->version = dtoh32(list->version);
+ list->count = dtoh32(list->count);
+
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ buflen));
+
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
+
+ iwe.u.data.length = dtoh32(bi->SSID_len);
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
+
+ if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+ iwe.cmd = SIOCGIWMODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+ iwe.u.mode = IW_MODE_INFRA;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
+ }
+
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
+ CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
+ iwe.u.freq.e = 6;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
+
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
+ iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+ iwe.u.qual.noise = 0x100 + bi->phy_noise;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
+
+ wl_iw_handle_scanresults_ies(&event, end, info, bi);
+
+ iwe.cmd = SIOCGIWENCODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
+
+ if (bi->rateset.count) {
+ value = event + IW_EV_LCP_LEN;
+ iwe.cmd = SIOCGIWRATE;
+
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+ for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
+ iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
+ value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+ event = value;
+ }
+ }
+
+ kfree(list);
+
+ dwrq->length = event - extra;
+ dwrq->flags = 0;
+
+ return 0;
+}
+
+#endif
+
+static int
+wl_iw_set_essid(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+
+ WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
+
+ memset(&ssid, 0, sizeof(ssid));
+ if (dwrq->length && extra) {
+#if WIRELESS_EXT > 20
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length);
+#else
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1);
+#endif
+ memcpy(ssid.SSID, extra, ssid.SSID_len);
+ ssid.SSID_len = htod32(ssid.SSID_len);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))
+ return error;
+ }
+
+ else {
+ scb_val_t scbval;
+ bzero(&scbval, sizeof(scb_val_t));
+ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t))))
+ return error;
+ }
+ return 0;
+}
+
+static int
+wl_iw_get_essid(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+
+ WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
+ WL_ERROR(("Error getting the SSID\n"));
+ return error;
+ }
+
+ ssid.SSID_len = dtoh32(ssid.SSID_len);
+
+ memcpy(extra, ssid.SSID, ssid.SSID_len);
+
+ dwrq->length = ssid.SSID_len;
+
+ dwrq->flags = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_nick(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if (dwrq->length > sizeof(iw->nickname))
+ return -E2BIG;
+
+ memcpy(iw->nickname, extra, dwrq->length);
+ iw->nickname[dwrq->length - 1] = '\0';
+
+ return 0;
+}
+
+static int
+wl_iw_get_nick(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ strcpy(extra, iw->nickname);
+ dwrq->length = strlen(extra) + 1;
+
+ return 0;
+}
+
+static int wl_iw_set_rate(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ wl_rateset_t rateset;
+ int error, rate, i, error_bg, error_a;
+
+ WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+ return error;
+
+ rateset.count = dtoh32(rateset.count);
+
+ if (vwrq->value < 0) {
+
+ rate = rateset.rates[rateset.count - 1] & 0x7f;
+ } else if (vwrq->value < rateset.count) {
+
+ rate = rateset.rates[vwrq->value] & 0x7f;
+ } else {
+
+ rate = vwrq->value / 500000;
+ }
+
+ if (vwrq->fixed) {
+
+ error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
+ error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
+
+ if (error_bg && error_a)
+ return (error_bg | error_a);
+ } else {
+
+ error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
+
+ error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
+
+ if (error_bg && error_a)
+ return (error_bg | error_a);
+
+ for (i = 0; i < rateset.count; i++)
+ if ((rateset.rates[i] & 0x7f) > rate)
+ break;
+ rateset.count = htod32(i);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
+ return error;
+ }
+
+ return 0;
+}
+
+static int wl_iw_get_rate(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rate;
+
+ WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
+ return error;
+ rate = dtoh32(rate);
+ vwrq->value = rate * 500000;
+
+ return 0;
+}
+
+static int
+wl_iw_set_rts(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rts;
+
+ WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
+
+ if (vwrq->disabled)
+ rts = DOT11_DEFAULT_RTS_LEN;
+ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
+ return -EINVAL;
+ else
+ rts = vwrq->value;
+
+ if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_rts(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rts;
+
+ WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
+
+ if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
+ return error;
+
+ vwrq->value = rts;
+ vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_frag(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, frag;
+
+ WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
+
+ if (vwrq->disabled)
+ frag = DOT11_DEFAULT_FRAG_LEN;
+ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
+ return -EINVAL;
+ else
+ frag = vwrq->value;
+
+ if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_frag(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, fragthreshold;
+
+ WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
+
+ if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
+ return error;
+
+ vwrq->value = fragthreshold;
+ vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_txpow(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, disable;
+ uint16 txpwrmw;
+ WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
+
+ disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
+ disable += WL_RADIO_SW_DISABLE << 16;
+
+ disable = htod32(disable);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
+ return error;
+
+ if (disable & WL_RADIO_SW_DISABLE)
+ return 0;
+
+ if (!(vwrq->flags & IW_TXPOW_MWATT))
+ return -EINVAL;
+
+ if (vwrq->value < 0)
+ return 0;
+
+ if (vwrq->value > 0xffff) txpwrmw = 0xffff;
+ else txpwrmw = (uint16)vwrq->value;
+
+ error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
+ return error;
+}
+
+static int
+wl_iw_get_txpow(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, disable, txpwrdbm;
+ uint8 result;
+
+ WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
+ (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
+ return error;
+
+ disable = dtoh32(disable);
+ result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
+ vwrq->value = (int32)bcm_qdbm_to_mw(result);
+ vwrq->fixed = 0;
+ vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
+ vwrq->flags = IW_TXPOW_MWATT;
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 10
+static int
+wl_iw_set_retry(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, lrl, srl;
+
+ WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
+
+ if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
+ return -EINVAL;
+
+ if (vwrq->flags & IW_RETRY_LIMIT) {
+
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
+ !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
+#else
+ if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
+#endif
+
+ lrl = htod32(vwrq->value);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
+ return error;
+ }
+
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
+ !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
+#else
+ if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
+#endif
+
+ srl = htod32(vwrq->value);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_retry(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, lrl, srl;
+
+ WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
+
+ vwrq->disabled = 0;
+
+ if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
+ return -EINVAL;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
+ return error;
+
+ lrl = dtoh32(lrl);
+ srl = dtoh32(srl);
+
+ if (vwrq->flags & IW_RETRY_MAX) {
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+ vwrq->value = lrl;
+ } else {
+ vwrq->flags = IW_RETRY_LIMIT;
+ vwrq->value = srl;
+ if (srl != lrl)
+ vwrq->flags |= IW_RETRY_MIN;
+ }
+
+ return 0;
+}
+#endif
+
+static int
+wl_iw_set_encode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error, val, wsec;
+
+ WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name));
+
+ memset(&key, 0, sizeof(key));
+
+ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
+
+ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
+ val = htod32(key.index);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ val = dtoh32(val);
+ if (val)
+ break;
+ }
+
+ if (key.index == DOT11_MAX_DEFAULT_KEYS)
+ key.index = 0;
+ } else {
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS)
+ return -EINVAL;
+ }
+
+ wsec = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
+
+ if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
+ return error;
+
+ if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
+
+ val = htod32(key.index);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ } else {
+ key.len = dwrq->length;
+
+ if (dwrq->length > sizeof(key.data))
+ return -EINVAL;
+
+ memcpy(key.data, extra, dwrq->length);
+
+ key.flags = WL_PRIMARY_KEY;
+ switch (key.len) {
+ case WEP1_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WEP128_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+ case TKIP_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_TKIP;
+ break;
+#endif
+ case AES_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ swap_key_from_BE(&key);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
+ return error;
+ }
+
+ val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
+ val = htod32(val);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_encode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error, val, wsec, auth;
+
+ WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
+
+ bzero(&key, sizeof(wl_wsec_key_t));
+
+ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
+
+ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
+ val = key.index;
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ val = dtoh32(val);
+ if (val)
+ break;
+ }
+ } else
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS)
+ key.index = 0;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
+ return error;
+
+ swap_key_to_BE(&key);
+
+ wsec = dtoh32(wsec);
+ auth = dtoh32(auth);
+
+ dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len);
+
+ dwrq->flags = key.index + 1;
+ if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
+
+ dwrq->flags |= IW_ENCODE_DISABLED;
+ }
+ if (auth) {
+
+ dwrq->flags |= IW_ENCODE_RESTRICTED;
+ }
+
+ if (dwrq->length && extra)
+ memcpy(extra, key.data, dwrq->length);
+
+ return 0;
+}
+
+static int
+wl_iw_set_power(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, pm;
+
+ WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
+
+ pm = vwrq->disabled ? PM_OFF : PM_MAX;
+
+ pm = htod32(pm);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_power(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, pm;
+
+ WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
+ return error;
+
+ pm = dtoh32(pm);
+ vwrq->disabled = pm ? 0 : 1;
+ vwrq->flags = IW_POWER_ALL_R;
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static int
+wl_iw_set_wpaie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *iwp,
+ char *extra
+)
+{
+ dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
+
+ return 0;
+}
+
+static int
+wl_iw_get_wpaie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *iwp,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
+ iwp->length = 64;
+ dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
+ return 0;
+}
+
+static int
+wl_iw_set_encodeext(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error;
+ struct iw_encode_ext *iwe;
+
+ WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
+
+ memset(&key, 0, sizeof(key));
+ iwe = (struct iw_encode_ext *)extra;
+
+ if (dwrq->flags & IW_ENCODE_DISABLED) {
+
+ }
+
+ key.index = 0;
+ if (dwrq->flags & IW_ENCODE_INDEX)
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ key.len = iwe->key_len;
+
+ if (!ETHER_ISMULTI(iwe->addr.sa_data))
+ bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
+
+ if (key.len == 0) {
+ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ WL_WSEC(("Changing the the primary Key to %d\n", key.index));
+
+ key.index = htod32(key.index);
+ error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
+ &key.index, sizeof(key.index));
+ if (error)
+ return error;
+ }
+
+ else {
+ swap_key_from_BE(&key);
+ dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ }
+ }
+
+ else {
+ if (iwe->key_len > sizeof(key.data))
+ return -EINVAL;
+
+ WL_WSEC(("Setting the key index %d\n", key.index));
+ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ WL_WSEC(("key is a Primary Key\n"));
+ key.flags = WL_PRIMARY_KEY;
+ }
+
+ bcopy((void *)iwe->key, key.data, iwe->key_len);
+
+ if (iwe->alg == IW_ENCODE_ALG_TKIP) {
+ uint8 keybuf[8];
+ bcopy(&key.data[24], keybuf, sizeof(keybuf));
+ bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
+ bcopy(keybuf, &key.data[16], sizeof(keybuf));
+ }
+
+ if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+ uchar *ivptr;
+ ivptr = (uchar *)iwe->rx_seq;
+ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
+ (ivptr[3] << 8) | ivptr[2];
+ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+ key.iv_initialized = TRUE;
+ }
+
+ switch (iwe->alg) {
+ case IW_ENCODE_ALG_NONE:
+ key.algo = CRYPTO_ALGO_OFF;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (iwe->key_len == WEP1_KEY_SIZE)
+ key.algo = CRYPTO_ALGO_WEP1;
+ else
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ key.algo = CRYPTO_ALGO_TKIP;
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ break;
+ default:
+ break;
+ }
+ swap_key_from_BE(&key);
+
+ error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+struct {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID-1];
+} pmkid_list;
+static int
+wl_iw_set_pmksa(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ struct iw_pmksa *iwpmksa;
+ uint i;
+ char eabuf[ETHER_ADDR_STR_LEN];
+ pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid;
+
+ WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name));
+ iwpmksa = (struct iw_pmksa *)extra;
+ bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
+ if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
+ WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
+ bzero((char *)&pmkid_list, sizeof(pmkid_list));
+ }
+ if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
+ pmkid_list_t pmkid, *pmkidptr;
+ pmkidptr = &pmkid;
+ bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
+ {
+ uint j;
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
+ if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
+ ETHER_ADDR_LEN))
+ break;
+ for (; i < pmkid_list.pmkids.npmkid; i++) {
+ bcopy(&pmkid_array[i+1].BSSID,
+ &pmkid_array[i].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&pmkid_array[i+1].PMKID,
+ &pmkid_array[i].PMKID,
+ WPA2_PMKID_LEN);
+ }
+ pmkid_list.pmkids.npmkid--;
+ }
+ if (iwpmksa->cmd == IW_PMKSA_ADD) {
+ bcopy(&iwpmksa->bssid.sa_data[0],
+ &pmkid_array[pmkid_list.pmkids.npmkid].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmkid_list.pmkids.npmkid].PMKID,
+ WPA2_PMKID_LEN);
+ {
+ uint j;
+ uint k;
+ k = pmkid_list.pmkids.npmkid;
+ BCM_REFERENCE(k);
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkid_array[k].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_array[k].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+ pmkid_list.pmkids.npmkid++;
+ }
+ WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid));
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
+ uint j;
+ WL_TRACE(("PMKID[%d]: %s = ", i,
+ bcm_ether_ntoa(&pmkid_array[i].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_array[i].PMKID[j]));
+ printf("\n");
+ }
+ WL_TRACE(("\n"));
+ dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
+ return 0;
+}
+#endif
+
+static int
+wl_iw_get_encodeext(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
+ return 0;
+}
+
+static int
+wl_iw_set_wpaauth(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error = 0;
+ int paramid;
+ int paramval;
+ uint32 cipher_combined;
+ int val = 0;
+ wl_iw_t *iw = IW_DEV_IF(dev);
+
+ WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
+
+ paramid = vwrq->flags & IW_AUTH_INDEX;
+ paramval = vwrq->value;
+
+ WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
+ dev->name, paramid, paramval));
+
+ switch (paramid) {
+
+ case IW_AUTH_WPA_VERSION:
+
+ if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
+ val = WPA_AUTH_DISABLED;
+ else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
+ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+ else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
+ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+ WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+
+ if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
+ iw->pwsec = paramval;
+ }
+ else {
+ iw->gwsec = paramval;
+ }
+
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
+ return error;
+
+ cipher_combined = iw->gwsec | iw->pwsec;
+ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
+ if (cipher_combined & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+ val |= WEP_ENABLED;
+ if (cipher_combined & IW_AUTH_CIPHER_TKIP)
+ val |= TKIP_ENABLED;
+ if (cipher_combined & IW_AUTH_CIPHER_CCMP)
+ val |= AES_ENABLED;
+
+ if (iw->privacy_invoked && !val) {
+ WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
+ "we're a WPS enrollee\n", dev->name, __FUNCTION__));
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
+ WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else if (val) {
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ }
+
+ if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
+ return error;
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+
+ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+ if (paramval & IW_AUTH_KEY_MGMT_PSK)
+ val = WPA_AUTH_PSK;
+ else
+ val = WPA_AUTH_UNSPECIFIED;
+ }
+ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ if (paramval & IW_AUTH_KEY_MGMT_PSK)
+ val = WPA2_AUTH_PSK;
+ else
+ val = WPA2_AUTH_UNSPECIFIED;
+ }
+ WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+
+ WL_ERROR(("Setting the D11auth %d\n", paramval));
+ if (paramval & IW_AUTH_ALG_OPEN_SYSTEM)
+ val = 0;
+ else if (paramval & IW_AUTH_ALG_SHARED_KEY)
+ val = 1;
+ else
+ error = 1;
+ if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ if (paramval == 0) {
+ val = 0;
+ WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ error = dev_wlc_intvar_set(dev, "wpa_auth", val);
+ return error;
+ }
+ else {
+
+ }
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ break;
+
+#if WIRELESS_EXT > 17
+
+ case IW_AUTH_ROAMING_CONTROL:
+ WL_TRACE(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
+
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED: {
+ int wsec;
+
+ if (paramval == 0) {
+ iw->privacy_invoked = FALSE;
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else {
+ iw->privacy_invoked = TRUE;
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
+ return error;
+
+ if (!WSEC_ENABLED(wsec)) {
+
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
+ WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else {
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ }
+ }
+ break;
+ }
+
+#endif
+
+ default:
+ break;
+ }
+ return 0;
+}
+#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
+
+static int
+wl_iw_get_wpaauth(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error;
+ int paramid;
+ int paramval = 0;
+ int val;
+ wl_iw_t *iw = IW_DEV_IF(dev);
+
+ WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
+
+ paramid = vwrq->flags & IW_AUTH_INDEX;
+
+ switch (paramid) {
+ case IW_AUTH_WPA_VERSION:
+
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
+ paramval = IW_AUTH_WPA_VERSION_DISABLED;
+ else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
+ paramval = IW_AUTH_WPA_VERSION_WPA;
+ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
+ paramval = IW_AUTH_WPA_VERSION_WPA2;
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ paramval = iw->pwsec;
+ break;
+
+ case IW_AUTH_CIPHER_GROUP:
+ paramval = iw->gwsec;
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (VAL_PSK(val))
+ paramval = IW_AUTH_KEY_MGMT_PSK;
+ else
+ paramval = IW_AUTH_KEY_MGMT_802_1X;
+
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+
+ if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
+ return error;
+ if (!val)
+ paramval = IW_AUTH_ALG_OPEN_SYSTEM;
+ else
+ paramval = IW_AUTH_ALG_SHARED_KEY;
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (val)
+ paramval = TRUE;
+ else
+ paramval = FALSE;
+ break;
+
+#if WIRELESS_EXT > 17
+
+ case IW_AUTH_ROAMING_CONTROL:
+ WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
+
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED:
+ paramval = iw->privacy_invoked;
+ break;
+
+#endif
+ }
+ vwrq->value = paramval;
+ return 0;
+}
+#endif
+
+static const iw_handler wl_iw_handler[] =
+{
+ (iw_handler) wl_iw_config_commit,
+ (iw_handler) wl_iw_get_name,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_freq,
+ (iw_handler) wl_iw_get_freq,
+ (iw_handler) wl_iw_set_mode,
+ (iw_handler) wl_iw_get_mode,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_get_range,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_spy,
+ (iw_handler) wl_iw_get_spy,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_wap,
+ (iw_handler) wl_iw_get_wap,
+#if WIRELESS_EXT > 17
+ (iw_handler) wl_iw_mlme,
+#else
+ (iw_handler) NULL,
+#endif
+ (iw_handler) wl_iw_get_aplist,
+#if WIRELESS_EXT > 13
+ (iw_handler) wl_iw_set_scan,
+ (iw_handler) wl_iw_get_scan,
+#else
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+#endif
+ (iw_handler) wl_iw_set_essid,
+ (iw_handler) wl_iw_get_essid,
+ (iw_handler) wl_iw_set_nick,
+ (iw_handler) wl_iw_get_nick,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_rate,
+ (iw_handler) wl_iw_get_rate,
+ (iw_handler) wl_iw_set_rts,
+ (iw_handler) wl_iw_get_rts,
+ (iw_handler) wl_iw_set_frag,
+ (iw_handler) wl_iw_get_frag,
+ (iw_handler) wl_iw_set_txpow,
+ (iw_handler) wl_iw_get_txpow,
+#if WIRELESS_EXT > 10
+ (iw_handler) wl_iw_set_retry,
+ (iw_handler) wl_iw_get_retry,
+#endif
+ (iw_handler) wl_iw_set_encode,
+ (iw_handler) wl_iw_get_encode,
+ (iw_handler) wl_iw_set_power,
+ (iw_handler) wl_iw_get_power,
+#if WIRELESS_EXT > 17
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_wpaie,
+ (iw_handler) wl_iw_get_wpaie,
+ (iw_handler) wl_iw_set_wpaauth,
+ (iw_handler) wl_iw_get_wpaauth,
+ (iw_handler) wl_iw_set_encodeext,
+ (iw_handler) wl_iw_get_encodeext,
+ (iw_handler) wl_iw_set_pmksa,
+#endif
+};
+
+#if WIRELESS_EXT > 12
+enum {
+ WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV,
+ WL_IW_SET_VLANMODE,
+ WL_IW_SET_PM
+};
+
+static iw_handler wl_iw_priv_handler[] = {
+ wl_iw_set_leddc,
+ wl_iw_set_vlanmode,
+ wl_iw_set_pm
+};
+
+static struct iw_priv_args wl_iw_priv_args[] = {
+ {
+ WL_IW_SET_LEDDC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_leddc"
+ },
+ {
+ WL_IW_SET_VLANMODE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_vlanmode"
+ },
+ {
+ WL_IW_SET_PM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_pm"
+ }
+};
+
+const struct iw_handler_def wl_iw_handler_def =
+{
+ .num_standard = ARRAYSIZE(wl_iw_handler),
+ .num_private = ARRAY_SIZE(wl_iw_priv_handler),
+ .num_private_args = ARRAY_SIZE(wl_iw_priv_args),
+ .standard = (iw_handler *) wl_iw_handler,
+ .private = wl_iw_priv_handler,
+ .private_args = wl_iw_priv_args,
+#if WIRELESS_EXT >= 19
+ get_wireless_stats: wl_get_wireless_stats,
+#endif
+ };
+#endif
+
+int
+wl_iw_ioctl(
+ struct net_device *dev,
+ struct ifreq *rq,
+ int cmd
+)
+{
+ struct iwreq *wrq = (struct iwreq *) rq;
+ struct iw_request_info info;
+ iw_handler handler;
+ char *extra = NULL;
+ size_t token_size = 1;
+ int max_tokens = 0, ret = 0;
+
+ if (cmd < SIOCIWFIRST ||
+ IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
+ !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)]))
+ return -EOPNOTSUPP;
+
+ switch (cmd) {
+
+ case SIOCSIWESSID:
+ case SIOCGIWESSID:
+ case SIOCSIWNICKN:
+ case SIOCGIWNICKN:
+ max_tokens = IW_ESSID_MAX_SIZE + 1;
+ break;
+
+ case SIOCSIWENCODE:
+ case SIOCGIWENCODE:
+#if WIRELESS_EXT > 17
+ case SIOCSIWENCODEEXT:
+ case SIOCGIWENCODEEXT:
+#endif
+ max_tokens = IW_ENCODING_TOKEN_MAX;
+ break;
+
+ case SIOCGIWRANGE:
+ max_tokens = sizeof(struct iw_range);
+ break;
+
+ case SIOCGIWAPLIST:
+ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
+ max_tokens = IW_MAX_AP;
+ break;
+
+#if WIRELESS_EXT > 13
+ case SIOCGIWSCAN:
+ max_tokens = IW_SCAN_MAX_DATA;
+ break;
+#endif
+
+ case SIOCSIWSPY:
+ token_size = sizeof(struct sockaddr);
+ max_tokens = IW_MAX_SPY;
+ break;
+
+ case SIOCGIWSPY:
+ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
+ max_tokens = IW_MAX_SPY;
+ break;
+ default:
+ break;
+ }
+
+ if (max_tokens && wrq->u.data.pointer) {
+ if (wrq->u.data.length > max_tokens)
+ return -E2BIG;
+
+ if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+ }
+
+ info.cmd = cmd;
+ info.flags = 0;
+
+ ret = handler(dev, &info, &wrq->u, extra);
+
+ if (extra) {
+ if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ kfree(extra);
+ }
+
+ return ret;
+}
+
+bool
+wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason,
+ char* stringBuf, uint buflen)
+{
+ typedef struct conn_fail_event_map_t {
+ uint32 inEvent;
+ uint32 inStatus;
+ uint32 inReason;
+ const char* outName;
+ const char* outCause;
+ } conn_fail_event_map_t;
+
+# define WL_IW_DONT_CARE 9999
+ const conn_fail_event_map_t event_map [] = {
+
+ {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE,
+ "Conn", "Success"},
+ {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
+ "Conn", "NoNetworks"},
+ {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "ConfigMismatch"},
+ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH,
+ "Conn", "EncrypMismatch"},
+ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH,
+ "Conn", "RsnMismatch"},
+ {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
+ "Conn", "AuthTimeout"},
+ {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "AuthFail"},
+ {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE,
+ "Conn", "AuthNoAck"},
+ {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "ReassocFail"},
+ {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
+ "Conn", "ReassocTimeout"},
+ {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE,
+ "Conn", "ReassocAbort"},
+ {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "Deauth"},
+ {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "DisassocInd"},
+ {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "Disassoc"}
+ };
+
+ const char* name = "";
+ const char* cause = NULL;
+ int i;
+
+ for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) {
+ const conn_fail_event_map_t* row = &event_map[i];
+ if (row->inEvent == event_type &&
+ (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) &&
+ (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) {
+ name = row->outName;
+ cause = row->outCause;
+ break;
+ }
+ }
+
+ if (cause) {
+ memset(stringBuf, 0, buflen);
+ snprintf(stringBuf, buflen, "%s %s %02d %02d",
+ name, cause, status, reason);
+ WL_TRACE(("Connection status: %s\n", stringBuf));
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+#if (WIRELESS_EXT > 14)
+
+static bool
+wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen)
+{
+ uint32 event = e->event_type;
+ uint32 status = e->status;
+ uint32 reason = e->reason;
+
+ if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
+ return TRUE;
+ } else
+ {
+ return FALSE;
+ }
+}
+#endif
+
+#ifndef IW_CUSTOM_MAX
+#define IW_CUSTOM_MAX 256
+#endif
+
+void
+wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
+{
+#if WIRELESS_EXT > 13
+ union iwreq_data wrqu;
+ char extra[IW_CUSTOM_MAX + 1];
+ int cmd = 0;
+ uint32 event_type = e->event_type;
+ uint16 flags = e->flags;
+ uint32 datalen = e->datalen;
+ uint32 status = e->status;
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ memset(extra, 0, sizeof(extra));
+
+ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ switch (event_type) {
+ case WLC_E_TXFAIL:
+ cmd = IWEVTXDROP;
+ break;
+#if WIRELESS_EXT > 14
+ case WLC_E_JOIN:
+ case WLC_E_ASSOC_IND:
+ case WLC_E_REASSOC_IND:
+ cmd = IWEVREGISTERED;
+ break;
+ case WLC_E_DEAUTH_IND:
+ case WLC_E_DISASSOC_IND:
+ cmd = SIOCGIWAP;
+ wrqu.data.length = strlen(extra);
+ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+ bzero(&extra, ETHER_ADDR_LEN);
+ break;
+
+ case WLC_E_LINK:
+ case WLC_E_NDIS_LINK:
+ cmd = SIOCGIWAP;
+ wrqu.data.length = strlen(extra);
+ if (!(flags & WLC_EVENT_MSG_LINK)) {
+ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+ bzero(&extra, ETHER_ADDR_LEN);
+ }
+ break;
+ case WLC_E_ACTION_FRAME:
+ cmd = IWEVCUSTOM;
+ if (datalen + 1 <= sizeof(extra)) {
+ wrqu.data.length = datalen + 1;
+ extra[0] = WLC_E_ACTION_FRAME;
+ memcpy(&extra[1], data, datalen);
+ WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
+ }
+ break;
+
+ case WLC_E_ACTION_FRAME_COMPLETE:
+ cmd = IWEVCUSTOM;
+ if (sizeof(status) + 1 <= sizeof(extra)) {
+ wrqu.data.length = sizeof(status) + 1;
+ extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
+ memcpy(&extra[1], &status, sizeof(status));
+ WL_TRACE(("wl_iw_event status %d \n", status));
+ }
+ break;
+#endif
+#if WIRELESS_EXT > 17
+ case WLC_E_MIC_ERROR: {
+ struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra;
+ cmd = IWEVMICHAELMICFAILURE;
+ wrqu.data.length = sizeof(struct iw_michaelmicfailure);
+ if (flags & WLC_EVENT_MSG_GROUP)
+ micerrevt->flags |= IW_MICFAILURE_GROUP;
+ else
+ micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
+ memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ micerrevt->src_addr.sa_family = ARPHRD_ETHER;
+
+ break;
+ }
+
+ case WLC_E_ASSOC_REQ_IE:
+ cmd = IWEVASSOCREQIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
+ case WLC_E_ASSOC_RESP_IE:
+ cmd = IWEVASSOCRESPIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
+ case WLC_E_PMKID_CACHE: {
+ struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra;
+ pmkid_cand_list_t *pmkcandlist;
+ pmkid_cand_t *pmkidcand;
+ int count;
+
+ if (data == NULL)
+ break;
+
+ cmd = IWEVPMKIDCAND;
+ pmkcandlist = data;
+ count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
+ wrqu.data.length = sizeof(struct iw_pmkid_cand);
+ pmkidcand = pmkcandlist->pmkid_cand;
+ while (count) {
+ bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand));
+ if (pmkidcand->preauth)
+ iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH;
+ bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data,
+ ETHER_ADDR_LEN);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ pmkidcand++;
+ count--;
+ }
+ break;
+ }
+#endif
+
+ case WLC_E_SCAN_COMPLETE:
+#if WIRELESS_EXT > 14
+ cmd = SIOCGIWSCAN;
+#endif
+ break;
+
+ default:
+
+ break;
+ }
+
+ if (cmd) {
+ if (cmd == SIOCGIWSCAN)
+ wireless_send_event(dev, cmd, &wrqu, NULL);
+ else
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ }
+
+#if WIRELESS_EXT > 14
+
+ memset(extra, 0, sizeof(extra));
+ if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
+ cmd = IWEVCUSTOM;
+ wrqu.data.length = strlen(extra);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ }
+#endif
+
+#endif
+}
+
+int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
+{
+ int res = 0;
+ wl_cnt_t cnt;
+ int phy_noise;
+ int rssi;
+ scb_val_t scb_val;
+
+ phy_noise = 0;
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
+ goto done;
+
+ phy_noise = dtoh32(phy_noise);
+ WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise));
+
+ scb_val.val = 0;
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
+ goto done;
+
+ rssi = dtoh32(scb_val.val);
+ WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi));
+ if (rssi <= WL_IW_RSSI_NO_SIGNAL)
+ wstats->qual.qual = 0;
+ else if (rssi <= WL_IW_RSSI_VERY_LOW)
+ wstats->qual.qual = 1;
+ else if (rssi <= WL_IW_RSSI_LOW)
+ wstats->qual.qual = 2;
+ else if (rssi <= WL_IW_RSSI_GOOD)
+ wstats->qual.qual = 3;
+ else if (rssi <= WL_IW_RSSI_VERY_GOOD)
+ wstats->qual.qual = 4;
+ else
+ wstats->qual.qual = 5;
+
+ wstats->qual.level = 0x100 + rssi;
+ wstats->qual.noise = 0x100 + phy_noise;
+#if WIRELESS_EXT > 18
+ wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
+#else
+ wstats->qual.updated |= 7;
+#endif
+
+#if WIRELESS_EXT > 11
+ WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", (int)sizeof(wl_cnt_t)));
+
+ memset(&cnt, 0, sizeof(wl_cnt_t));
+ res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
+ if (res)
+ {
+ WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res));
+ goto done;
+ }
+
+ cnt.version = dtoh16(cnt.version);
+ if (cnt.version != WL_CNT_T_VERSION) {
+ WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
+ WL_CNT_T_VERSION, cnt.version));
+ goto done;
+ }
+
+ wstats->discard.nwid = 0;
+ wstats->discard.code = dtoh32(cnt.rxundec);
+ wstats->discard.fragment = dtoh32(cnt.rxfragerr);
+ wstats->discard.retries = dtoh32(cnt.txfail);
+ wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
+ wstats->miss.beacon = 0;
+
+ WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
+ dtoh32(cnt.txframe), dtoh32(cnt.txbyte)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant)));
+
+#endif
+
+done:
+ return res;
+}
+
+int
+wl_iw_attach(struct net_device *dev, void * dhdp)
+{
+ return 0;
+}
+
+void wl_iw_detach(void)
+{
+}
+
+#endif
diff --git a/src/wl/sys/wl_iw.h b/src/wl/sys/wl_iw.h
new file mode 100644
index 0000000..3ab084f
--- /dev/null
+++ b/src/wl/sys/wl_iw.h
@@ -0,0 +1,150 @@
+/*
+ * Linux Wireless Extensions support
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_iw.h 291086 2011-10-21 01:17:24Z $
+ */
+
+#ifndef _wl_iw_h_
+#define _wl_iw_h_
+
+#include <linux/wireless.h>
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <wlioctl.h>
+
+#define WL_SCAN_PARAMS_SSID_MAX 10
+#define GET_SSID "SSID="
+#define GET_CHANNEL "CH="
+#define GET_NPROBE "NPROBE="
+#define GET_ACTIVE_ASSOC_DWELL "ACTIVE="
+#define GET_PASSIVE_ASSOC_DWELL "PASSIVE="
+#define GET_HOME_DWELL "HOME="
+#define GET_SCAN_TYPE "TYPE="
+
+#define BAND_GET_CMD "GETBAND"
+#define BAND_SET_CMD "SETBAND"
+#define DTIM_SKIP_GET_CMD "DTIMSKIPGET"
+#define DTIM_SKIP_SET_CMD "DTIMSKIPSET"
+#define SETSUSPEND_CMD "SETSUSPENDOPT"
+#define PNOSSIDCLR_SET_CMD "PNOSSIDCLR"
+
+#define PNOSETUP_SET_CMD "PNOSETUP "
+#define PNOENABLE_SET_CMD "PNOFORCE"
+#define PNODEBUG_SET_CMD "PNODEBUG"
+#define TXPOWER_SET_CMD "TXPOWER"
+
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+typedef struct wl_iw_extra_params {
+ int target_channel;
+} wl_iw_extra_params_t;
+
+struct cntry_locales_custom {
+ char iso_abbrev[WLC_CNTRY_BUF_SZ];
+ char custom_locale[WLC_CNTRY_BUF_SZ];
+ int32 custom_locale_rev;
+};
+
+#define WL_IW_RSSI_MINVAL -200
+#define WL_IW_RSSI_NO_SIGNAL -91
+#define WL_IW_RSSI_VERY_LOW -80
+#define WL_IW_RSSI_LOW -70
+#define WL_IW_RSSI_GOOD -68
+#define WL_IW_RSSI_VERY_GOOD -58
+#define WL_IW_RSSI_EXCELLENT -57
+#define WL_IW_RSSI_INVALID 0
+#define MAX_WX_STRING 80
+#define isprint(c) bcm_isprint(c)
+#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1)
+#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3)
+#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5)
+#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7)
+#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9)
+#define WL_IW_SET_STOP (SIOCIWFIRSTPRIV+11)
+#define WL_IW_SET_START (SIOCIWFIRSTPRIV+13)
+
+#define G_SCAN_RESULTS 8*1024
+#define WE_ADD_EVENT_FIX 0x80
+#define G_WLAN_SET_ON 0
+#define G_WLAN_SET_OFF 1
+
+typedef struct wl_iw {
+ char nickname[IW_ESSID_MAX_SIZE];
+
+ struct iw_statistics wstats;
+
+ int spy_num;
+ uint32 pwsec;
+ uint32 gwsec;
+ bool privacy_invoked;
+ struct ether_addr spy_addr[IW_MAX_SPY];
+ struct iw_quality spy_qual[IW_MAX_SPY];
+ void *wlinfo;
+} wl_iw_t;
+
+struct wl_ctrl {
+ struct timer_list *timer;
+ struct net_device *dev;
+ long sysioc_pid;
+ struct semaphore sysioc_sem;
+ struct completion sysioc_exited;
+};
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+extern const struct iw_handler_def wl_iw_handler_def;
+#endif
+
+extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
+extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
+int wl_iw_attach(struct net_device *dev, void * dhdp);
+int wl_iw_send_priv_event(struct net_device *dev, char *flag);
+
+void wl_iw_detach(void);
+
+#define CSCAN_COMMAND "CSCAN "
+#define CSCAN_TLV_PREFIX 'S'
+#define CSCAN_TLV_VERSION 1
+#define CSCAN_TLV_SUBVERSION 0
+#define CSCAN_TLV_TYPE_SSID_IE 'S'
+#define CSCAN_TLV_TYPE_CHANNEL_IE 'C'
+#define CSCAN_TLV_TYPE_NPROBE_IE 'N'
+#define CSCAN_TLV_TYPE_ACTIVE_IE 'A'
+#define CSCAN_TLV_TYPE_PASSIVE_IE 'P'
+#define CSCAN_TLV_TYPE_HOME_IE 'H'
+#define CSCAN_TLV_TYPE_STYPE_IE 'T'
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_event(info, stream, ends, iwe, extra)
+#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
+ iwe_stream_add_value(info, event, value, ends, iwe, event_len)
+#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_point(info, stream, ends, iwe, extra)
+#else
+#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_event(stream, ends, iwe, extra)
+#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
+ iwe_stream_add_value(event, value, ends, iwe, event_len)
+#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_point(stream, ends, iwe, extra)
+#endif
+
+#endif
diff --git a/src/wl/sys/wl_linux.c b/src/wl/sys/wl_linux.c
new file mode 100644
index 0000000..0d05100
--- /dev/null
+++ b/src/wl/sys/wl_linux.c
@@ -0,0 +1,3371 @@
+/*
+ * Linux-specific portion of
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_linux.c 580354 2015-08-18 23:42:37Z $
+ */
+
+#define LINUX_PORT
+
+#define __UNDEF_NO_VERSION__
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#include <linux/module.h>
+#endif
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/ethtool.h>
+#include <linux/completion.h>
+#include <linux/usb.h>
+#include <linux/pci_ids.h>
+#define WLC_MAXBSSCFG 1
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+#include <asm/switch_to.h>
+#else
+#include <asm/system.h>
+#endif
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+
+#include <proto/802.1d.h>
+
+#include <epivers.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+#include <bcmutils.h>
+#include <pcicfg.h>
+#include <wlioctl.h>
+#include <wlc_key.h>
+#include <siutils.h>
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5)
+#error "No support for Kernel Rev <= 2.4.5, As the older kernel revs doesn't support Tasklets"
+#endif
+
+#include <wlc_pub.h>
+#include <wl_dbg.h>
+#include <wlc_ethereal.h>
+#include <proto/ieee80211_radiotap.h>
+
+#include <wl_iw.h>
+#ifdef USE_IW
+struct iw_statistics *wl_get_wireless_stats(struct net_device *dev);
+#endif
+
+#include <wl_export.h>
+
+#include <wl_linux.h>
+
+#if defined(USE_CFG80211)
+#include <wl_cfg80211_hybrid.h>
+#endif
+
+#include <wlc_wowl.h>
+
+static void wl_timer(ulong data);
+static void _wl_timer(wl_timer_t *t);
+static struct net_device *wl_alloc_linux_if(wl_if_t *wlif);
+
+static int wl_monitor_start(struct sk_buff *skb, struct net_device *dev);
+
+static void wl_start_txqwork(wl_task_t *task);
+static void wl_txq_free(wl_info_t *wl);
+#define TXQ_LOCK(_wl) spin_lock_bh(&(_wl)->txq_lock)
+#define TXQ_UNLOCK(_wl) spin_unlock_bh(&(_wl)->txq_lock)
+
+static void wl_set_multicast_list_workitem(struct work_struct *work);
+
+static void wl_timer_task(wl_task_t *task);
+static void wl_dpc_rxwork(struct wl_task *task);
+
+static int wl_reg_proc_entry(wl_info_t *wl);
+
+static int wl_linux_watchdog(void *ctx);
+static
+int wl_found = 0;
+
+typedef struct priv_link {
+ wl_if_t *wlif;
+} priv_link_t;
+
+#define WL_DEV_IF(dev) ((wl_if_t*)((priv_link_t*)DEV_PRIV(dev))->wlif)
+
+#ifdef WL_INFO
+#undef WL_INFO
+#endif
+#define WL_INFO(dev) ((wl_info_t*)(WL_DEV_IF(dev)->wl))
+
+static int wl_open(struct net_device *dev);
+static int wl_close(struct net_device *dev);
+static int BCMFASTPATH wl_start(struct sk_buff *skb, struct net_device *dev);
+static int wl_start_int(wl_info_t *wl, wl_if_t *wlif, struct sk_buff *skb);
+
+static struct net_device_stats *wl_get_stats(struct net_device *dev);
+static int wl_set_mac_address(struct net_device *dev, void *addr);
+static void wl_set_multicast_list(struct net_device *dev);
+static void _wl_set_multicast_list(struct net_device *dev);
+static int wl_ethtool(wl_info_t *wl, void *uaddr, wl_if_t *wlif);
+static void wl_dpc(ulong data);
+static void wl_tx_tasklet(ulong data);
+static void wl_link_up(wl_info_t *wl, char * ifname);
+static void wl_link_down(wl_info_t *wl, char *ifname);
+static int wl_schedule_task(wl_info_t *wl, void (*fn)(struct wl_task *), void *context);
+#if defined(BCMDBG)
+static int wl_dump(wl_info_t *wl, struct bcmstrbuf *b);
+#endif
+static struct wl_if *wl_alloc_if(wl_info_t *wl, int iftype, uint unit, struct wlc_if* wlc_if);
+static void wl_free_if(wl_info_t *wl, wl_if_t *wlif);
+static void wl_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info);
+
+#if defined(WL_CONFIG_RFKILL)
+#include <linux/rfkill.h>
+static int wl_init_rfkill(wl_info_t *wl);
+static void wl_uninit_rfkill(wl_info_t *wl);
+static int wl_set_radio_block(void *data, bool blocked);
+static void wl_report_radio_state(wl_info_t *wl);
+#endif
+
+MODULE_LICENSE("MIXED/Proprietary");
+
+static struct pci_device_id wl_id_table[] =
+{
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, wl_id_table);
+
+static unsigned int online_cpus = 1;
+
+#ifdef BCMDBG
+static int msglevel = 0xdeadbeef;
+module_param(msglevel, int, 0);
+static int msglevel2 = 0xdeadbeef;
+module_param(msglevel2, int, 0);
+static int phymsglevel = 0xdeadbeef;
+module_param(phymsglevel, int, 0);
+#endif
+
+#ifdef BCMDBG_ASSERT
+static int assert_type = 0xdeadbeef;
+module_param(assert_type, int, 0);
+#endif
+
+static int passivemode = 0;
+module_param(passivemode, int, 0);
+
+#define WL_TXQ_THRESH 0
+static int wl_txq_thresh = WL_TXQ_THRESH;
+module_param(wl_txq_thresh, int, 0);
+
+static int oneonly = 0;
+module_param(oneonly, int, 0);
+
+static int piomode = 0;
+module_param(piomode, int, 0);
+
+static int instance_base = 0;
+module_param(instance_base, int, 0);
+
+#if defined(BCMDBG)
+static struct ether_addr local_ea;
+static char *macaddr = NULL;
+module_param(macaddr, charp, S_IRUGO);
+#endif
+
+static int nompc = 0;
+module_param(nompc, int, 0);
+
+#ifdef quote_str
+#undef quote_str
+#endif
+#ifdef to_str
+#undef to_str
+#endif
+#define to_str(s) #s
+#define quote_str(s) to_str(s)
+
+#define BRCM_WLAN_IFNAME eth%d
+
+static char intf_name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME);
+
+module_param_string(intf_name, intf_name, IFNAMSIZ, 0);
+
+static const u_int8_t brcm_oui[] = {0x00, 0x10, 0x18};
+
+#define WL_RADIOTAP_BRCM2_HT_SNS 0x01
+#define WL_RADIOTAP_BRCM2_HT_MCS 0x00000001
+
+#define WL_RADIOTAP_LEGACY_SNS 0x02
+#define WL_RADIOTAP_LEGACY_VHT 0x00000001
+
+#define IEEE80211_RADIOTAP_HTMOD_40 0x01
+#define IEEE80211_RADIOTAP_HTMOD_SGI 0x02
+#define IEEE80211_RADIOTAP_HTMOD_GF 0x04
+#define IEEE80211_RADIOTAP_HTMOD_LDPC 0x08
+#define IEEE80211_RADIOTAP_HTMOD_STBC_MASK 0x30
+#define IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT 4
+
+#define WL_RADIOTAP_F_NONHT_VHT_DYN_BW 0x01
+
+#define WL_RADIOTAP_F_NONHT_VHT_BW 0x02
+
+struct wl_radiotap_nonht_vht {
+ u_int8_t len;
+ u_int8_t flags;
+ u_int8_t bw;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_nonht_vht wl_radiotap_nonht_vht_t;
+
+struct wl_radiotap_legacy {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ u_int32_t it_present_ext;
+ u_int32_t pad1;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ uint8 flags;
+ uint8 rate;
+ uint16 channel_freq;
+ uint16 channel_flags;
+ uint8 signal;
+ uint8 noise;
+ int8 antenna;
+ uint8 pad2;
+ u_int8_t vend_oui[3];
+ u_int8_t vend_sns;
+ u_int16_t vend_skip_len;
+ wl_radiotap_nonht_vht_t nonht_vht;
+} __attribute__ ((__packed__));
+
+typedef struct wl_radiotap_legacy wl_radiotap_legacy_t;
+
+#define WL_RADIOTAP_LEGACY_SKIP_LEN htol16(sizeof(struct wl_radiotap_legacy) - \
+ offsetof(struct wl_radiotap_legacy, nonht_vht))
+
+#define WL_RADIOTAP_NONHT_VHT_LEN (sizeof(wl_radiotap_nonht_vht_t) - 1)
+
+struct wl_radiotap_ht_brcm_2 {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ u_int32_t it_present_ext;
+ u_int32_t pad1;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad2;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t pad3;
+ u_int8_t vend_oui[3];
+ u_int8_t vend_sns;
+ u_int16_t vend_skip_len;
+ u_int8_t mcs;
+ u_int8_t htflags;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_ht_brcm_2 wl_radiotap_ht_brcm_2_t;
+
+#define WL_RADIOTAP_HT_BRCM2_SKIP_LEN htol16(sizeof(struct wl_radiotap_ht_brcm_2) - \
+ offsetof(struct wl_radiotap_ht_brcm_2, mcs))
+
+struct wl_radiotap_ht_brcm_3 {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ u_int32_t it_present_ext;
+ u_int32_t pad1;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad2;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t mcs_known;
+ u_int8_t mcs_flags;
+ u_int8_t mcs_index;
+ u_int8_t vend_oui[3];
+ u_int8_t vend_sns;
+ u_int16_t vend_skip_len;
+ wl_radiotap_nonht_vht_t nonht_vht;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_ht_brcm_3 wl_radiotap_ht_brcm_3_t;
+
+struct wl_radiotap_ht {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad1;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t mcs_known;
+ u_int8_t mcs_flags;
+ u_int8_t mcs_index;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_ht wl_radiotap_ht_t;
+
+struct wl_radiotap_vht {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad1;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t pad2;
+ u_int16_t pad3;
+ uint32 ampdu_ref_num;
+ u_int16_t ampdu_flags;
+ u_int8_t ampdu_delim_crc;
+ u_int8_t ampdu_reserved;
+ u_int16_t vht_known;
+ u_int8_t vht_flags;
+ u_int8_t vht_bw;
+ u_int8_t vht_mcs_nss[4];
+ u_int8_t vht_coding;
+ u_int8_t vht_group_id;
+ u_int16_t vht_partial_aid;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_vht wl_radiotap_vht_t;
+
+#define WL_RADIOTAP_PRESENT_LEGACY \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_RATE) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | \
+ (1 << IEEE80211_RADIOTAP_EXT))
+
+#define WL_RADIOTAP_PRESENT_HT_BRCM2 \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | \
+ (1 << IEEE80211_RADIOTAP_EXT))
+
+#define WL_RADIOTAP_PRESENT_HT \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_MCS))
+
+#define WL_RADIOTAP_PRESENT_VHT \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_AMPDU) | \
+ (1 << IEEE80211_RADIOTAP_VHT))
+
+#ifndef ARPHRD_IEEE80211_RADIOTAP
+#define ARPHRD_IEEE80211_RADIOTAP 803
+#endif
+
+#ifndef SRCBASE
+#define SRCBASE "."
+#endif
+
+#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static struct ethtool_ops wl_ethtool_ops =
+#else
+static const struct ethtool_ops wl_ethtool_ops =
+#endif
+{
+ .get_drvinfo = wl_get_driver_info,
+};
+#endif
+
+#if defined(WL_USE_NETDEV_OPS)
+
+static const struct net_device_ops wl_netdev_ops =
+{
+ .ndo_open = wl_open,
+ .ndo_stop = wl_close,
+ .ndo_start_xmit = wl_start,
+ .ndo_get_stats = wl_get_stats,
+ .ndo_set_mac_address = wl_set_mac_address,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ .ndo_set_rx_mode = wl_set_multicast_list,
+#else
+ .ndo_set_multicast_list = wl_set_multicast_list,
+#endif
+ .ndo_do_ioctl = wl_ioctl
+};
+
+static const struct net_device_ops wl_netdev_monitor_ops =
+{
+ .ndo_start_xmit = wl_monitor_start,
+ .ndo_get_stats = wl_get_stats,
+ .ndo_do_ioctl = wl_ioctl
+};
+#endif
+
+static void
+wl_if_setup(struct net_device *dev)
+{
+#if defined(WL_USE_NETDEV_OPS)
+ dev->netdev_ops = &wl_netdev_ops;
+#else
+ dev->open = wl_open;
+ dev->stop = wl_close;
+ dev->hard_start_xmit = wl_start;
+ dev->get_stats = wl_get_stats;
+ dev->set_mac_address = wl_set_mac_address;
+ dev->set_multicast_list = wl_set_multicast_list;
+ dev->do_ioctl = wl_ioctl;
+#endif
+
+#ifdef USE_IW
+#if WIRELESS_EXT < 19
+ dev->get_wireless_stats = wl_get_wireless_stats;
+#endif
+#if WIRELESS_EXT > 12
+ dev->wireless_handlers = (struct iw_handler_def *) &wl_iw_handler_def;
+#endif
+#endif
+
+#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+ dev->ethtool_ops = &wl_ethtool_ops;
+#endif
+}
+
+static wl_info_t *
+wl_attach(uint16 vendor, uint16 device, ulong regs,
+ uint bustype, void *btparam, uint irq, uchar* bar1_addr, uint32 bar1_size)
+{
+ struct net_device *dev;
+ wl_if_t *wlif;
+ wl_info_t *wl;
+ osl_t *osh;
+ int unit, err;
+#if defined(USE_CFG80211)
+ struct device *parentdev;
+#endif
+
+ unit = wl_found + instance_base;
+ err = 0;
+
+ if (unit < 0) {
+ WL_ERROR(("wl%d: unit number overflow, exiting\n", unit));
+ return NULL;
+ }
+
+ if (oneonly && (unit != instance_base)) {
+ WL_ERROR(("wl%d: wl_attach: oneonly is set, exiting\n", unit));
+ return NULL;
+ }
+
+ osh = osl_attach(btparam, bustype, TRUE);
+ ASSERT(osh);
+
+ if ((wl = (wl_info_t*) MALLOC(osh, sizeof(wl_info_t))) == NULL) {
+ WL_ERROR(("wl%d: malloc wl_info_t, out of memory, malloced %d bytes\n", unit,
+ MALLOCED(osh)));
+ osl_detach(osh);
+ return NULL;
+ }
+ bzero(wl, sizeof(wl_info_t));
+
+ wl->osh = osh;
+ wl->unit = unit;
+ atomic_set(&wl->callbacks, 0);
+
+ wl->all_dispatch_mode = (passivemode == 0) ? TRUE : FALSE;
+ if (WL_ALL_PASSIVE_ENAB(wl)) {
+
+ MY_INIT_WORK(&wl->txq_task.work, (work_func_t)wl_start_txqwork);
+ wl->txq_task.context = wl;
+
+ MY_INIT_WORK(&wl->multicast_task.work, (work_func_t)wl_set_multicast_list_workitem);
+
+ MY_INIT_WORK(&wl->wl_dpc_task.work, (work_func_t)wl_dpc_rxwork);
+ wl->wl_dpc_task.context = wl;
+ }
+
+ wl->txq_dispatched = FALSE;
+ wl->txq_head = wl->txq_tail = NULL;
+ wl->txq_cnt = 0;
+
+ wlif = wl_alloc_if(wl, WL_IFTYPE_BSS, unit, NULL);
+ if (!wlif) {
+ WL_ERROR(("wl%d: %s: wl_alloc_if failed\n", unit, __FUNCTION__));
+ MFREE(osh, wl, sizeof(wl_info_t));
+ osl_detach(osh);
+ return NULL;
+ }
+
+ if (wl_alloc_linux_if(wlif) == NULL) {
+ WL_ERROR(("wl%d: %s: wl_alloc_linux_if failed\n", unit, __FUNCTION__));
+ MFREE(osh, wl, sizeof(wl_info_t));
+ osl_detach(osh);
+ return NULL;
+ }
+
+ dev = wlif->dev;
+ wl->dev = dev;
+ wl_if_setup(dev);
+
+ dev->base_addr = regs;
+
+ WL_TRACE(("wl%d: Bus: ", unit));
+ if (bustype == PCMCIA_BUS) {
+
+ wl->piomode = TRUE;
+ WL_TRACE(("PCMCIA\n"));
+ } else if (bustype == PCI_BUS) {
+
+ wl->piomode = piomode;
+ WL_TRACE(("PCI/%s\n", wl->piomode ? "PIO" : "DMA"));
+ }
+ else if (bustype == RPC_BUS) {
+
+ } else {
+ bustype = PCI_BUS;
+ WL_TRACE(("force to PCI\n"));
+ }
+ wl->bcm_bustype = bustype;
+
+ if ((wl->regsva = ioremap_nocache(dev->base_addr, PCI_BAR0_WINSZ)) == NULL) {
+ WL_ERROR(("wl%d: ioremap() failed\n", unit));
+ goto fail;
+ }
+
+ wl->bar1_addr = bar1_addr;
+ wl->bar1_size = bar1_size;
+
+ spin_lock_init(&wl->lock);
+ spin_lock_init(&wl->isr_lock);
+
+ if (WL_ALL_PASSIVE_ENAB(wl))
+ sema_init(&wl->sem, 1);
+
+ spin_lock_init(&wl->txq_lock);
+
+ if (!(wl->wlc = wlc_attach((void *) wl, vendor, device, unit, wl->piomode,
+ osh, wl->regsva, wl->bcm_bustype, btparam, &err))) {
+ printf("wl driver %s failed with code %d\n", EPI_VERSION_STR, err);
+ goto fail;
+ }
+ wl->pub = wlc_pub(wl->wlc);
+
+ wlif->wlcif = wlc_wlcif_get_by_index(wl->wlc, 0);
+
+ if (nompc) {
+ if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
+ WL_ERROR(("wl%d: Error setting MPC variable to 0\n", unit));
+ }
+ }
+
+ wlc_iovar_setint(wl->wlc, "scan_passive_time", 170);
+
+ wlc_iovar_setint(wl->wlc, "qtxpower", 23 * 4);
+
+#ifdef BCMDBG
+ if (macaddr != NULL) {
+ int dbg_err;
+
+ WL_ERROR(("wl%d: setting MAC ADDRESS %s\n", unit, macaddr));
+ bcm_ether_atoe(macaddr, &local_ea);
+
+ dbg_err = wlc_iovar_op(wl->wlc, "cur_etheraddr", NULL, 0, &local_ea,
+ ETHER_ADDR_LEN, IOV_SET, NULL);
+ if (dbg_err)
+ WL_ERROR(("wl%d: Error setting MAC ADDRESS\n", unit));
+ }
+#endif
+ bcopy(&wl->pub->cur_etheraddr, dev->dev_addr, ETHER_ADDR_LEN);
+
+ online_cpus = 1;
+
+ WL_ERROR(("wl%d: online cpus %d\n", unit, online_cpus));
+
+ tasklet_init(&wl->tasklet, wl_dpc, (ulong)wl);
+
+ tasklet_init(&wl->tx_tasklet, wl_tx_tasklet, (ulong)wl);
+
+ {
+ if (request_irq(irq, wl_isr, IRQF_SHARED, dev->name, wl)) {
+ WL_ERROR(("wl%d: request_irq() failed\n", unit));
+ goto fail;
+ }
+ dev->irq = irq;
+ }
+
+#if defined(USE_IW)
+ WL_ERROR(("Using Wireless Extension\n"));
+#endif
+
+#if defined(USE_CFG80211)
+ parentdev = NULL;
+ if (wl->bcm_bustype == PCI_BUS) {
+ parentdev = &((struct pci_dev *)btparam)->dev;
+ }
+ if (parentdev) {
+ if (wl_cfg80211_attach(dev, parentdev, WL_ALL_PASSIVE_ENAB(wl))) {
+ goto fail;
+ }
+ }
+ else {
+ WL_ERROR(("unsupported bus type\n"));
+ goto fail;
+ }
+#else
+
+ if (wl->bcm_bustype == PCI_BUS) {
+ struct pci_dev *pci_dev = (struct pci_dev *)btparam;
+ if (pci_dev != NULL)
+ SET_NETDEV_DEV(dev, &pci_dev->dev);
+ }
+#endif
+
+ if (register_netdev(dev)) {
+ WL_ERROR(("wl%d: register_netdev() failed\n", unit));
+ goto fail;
+ }
+ wlif->dev_registed = TRUE;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#endif
+#ifdef USE_IW
+ wlif->iw.wlinfo = (void *)wl;
+#endif
+
+#if defined(WL_CONFIG_RFKILL)
+ if (wl_init_rfkill(wl) < 0)
+ WL_ERROR(("%s: init_rfkill_failure\n", __FUNCTION__));
+#endif
+
+ if (wlc_iovar_setint(wl->wlc, "leddc", 0xa0000)) {
+ WL_ERROR(("wl%d: Error setting led duty-cycle\n", unit));
+ }
+ if (wlc_set(wl->wlc, WLC_SET_PM, PM_FAST)) {
+ WL_ERROR(("wl%d: Error setting PM variable to FAST PS\n", unit));
+ }
+
+ if (wlc_iovar_setint(wl->wlc, "vlan_mode", OFF)) {
+ WL_ERROR(("wl%d: Error setting vlan mode OFF\n", unit));
+ }
+
+ if (wlc_set(wl->wlc, WLC_SET_INFRA, 1)) {
+ WL_ERROR(("wl%d: Error setting infra_mode to infrastructure\n", unit));
+ }
+
+ if (wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog, NULL, NULL)) {
+ WL_ERROR(("wl%d: %s wlc_module_register() failed\n",
+ wl->pub->unit, __FUNCTION__));
+ goto fail;
+ }
+
+#ifdef BCMDBG
+ wlc_dump_register(wl->pub, "wl", (dump_fn_t)wl_dump, (void *)wl);
+#endif
+
+ wl_reg_proc_entry(wl);
+
+ printf("%s: Broadcom BCM%04x 802.11 Hybrid Wireless Controller%s %s",
+ dev->name, device,
+ WL_ALL_PASSIVE_ENAB(wl) ? ", Passive Mode" : "", EPI_VERSION_STR);
+
+#ifdef BCMDBG
+ printf(" (Compiled in " SRCBASE " at " __TIME__ " on " __DATE__ ")");
+#endif
+ printf("\n");
+
+ wl_found++;
+ return wl;
+
+fail:
+ wl_free(wl);
+ return NULL;
+}
+
+static void __devexit wl_remove(struct pci_dev *pdev);
+
+int __devinit
+wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int rc;
+ wl_info_t *wl;
+ uint32 val;
+ uint32 bar1_size = 0;
+ void* bar1_addr = NULL;
+
+ WL_TRACE(("%s: bus %d slot %d func %d irq %d\n", __FUNCTION__,
+ pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq));
+
+ if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
+ (((pdev->device & 0xff00) != 0x4300) &&
+ (pdev->device != 0x576) &&
+ ((pdev->device & 0xff00) != 0x4700) &&
+ ((pdev->device < 43000) || (pdev->device > 43999)))) {
+ WL_TRACE(("%s: unsupported vendor %x device %x\n", __FUNCTION__,
+ pdev->vendor, pdev->device));
+ return (-ENODEV);
+ }
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ WL_ERROR(("%s: Cannot enable device %d-%d_%d\n", __FUNCTION__,
+ pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)));
+ return (-ENODEV);
+ }
+ pci_set_master(pdev);
+
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ bar1_size = pci_resource_len(pdev, 2);
+ bar1_addr = (uchar *)ioremap_nocache(pci_resource_start(pdev, 2),
+ bar1_size);
+ wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0), PCI_BUS, pdev,
+ pdev->irq, bar1_addr, bar1_size);
+
+ if (!wl)
+ return -ENODEV;
+
+ pci_set_drvdata(pdev, wl);
+
+ return 0;
+}
+
+static int
+#if !defined(SIMPLE_DEV_PM_OPS)
+wl_suspend(struct pci_dev *pdev, DRV_SUSPEND_STATE_TYPE state)
+{
+#else
+wl_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+#endif
+ wl_info_t *wl = (wl_info_t *) pci_get_drvdata(pdev);
+ if (!wl) {
+ WL_ERROR(("wl: wl_suspend: pci_get_drvdata failed\n"));
+ return -ENODEV;
+ }
+ WL_ERROR(("%s: PCI Suspend handler\n", __FUNCTION__));
+
+ WL_LOCK(wl);
+ if (WLOFFLD_ENAB(wl->pub) && wlc_iovar_setint(wl->wlc, "wowl_activate", 1) == 0) {
+ WL_TRACE(("%s: Enabled WOWL OFFLOAD\n", __FUNCTION__));
+ } else {
+ WL_ERROR(("%s: Not WOWL capable\n", __FUNCTION__));
+ wl_down(wl);
+ wl->pub->hw_up = FALSE;
+ }
+ WL_UNLOCK(wl);
+
+ if (BUSTYPE(wl->pub->sih->bustype) == PCI_BUS)
+ si_pci_sleep(wl->pub->sih);
+
+ return 0;
+}
+
+static int
+#if !defined(SIMPLE_DEV_PM_OPS)
+wl_resume(struct pci_dev *pdev)
+{
+#else
+wl_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+#endif
+ int err = 0;
+ wl_info_t *wl = (wl_info_t *) pci_get_drvdata(pdev);
+ if (!wl) {
+ WL_ERROR(("wl: wl_resume: pci_get_drvdata failed\n"));
+ return -ENODEV;
+ }
+
+ WL_ERROR(("%s: PCI Resume handler\n", __FUNCTION__));
+ if (WLOFFLD_ENAB(wl->pub)) {
+ wlc_iovar_setint(wl->wlc, "wowl_activate", 0);
+ wlc_wowl_wake_reason_process(wl->wlc);
+
+ if (WOWL_ACTIVE(wl->pub)) {
+ if (BUSTYPE(wl->pub->sih->bustype) == PCI_BUS) {
+ si_pci_pmeclr(wl->pub->sih);
+ }
+ }
+ }
+
+ WL_LOCK(wl);
+ err = wl_up(wl);
+ WL_UNLOCK(wl);
+
+ return (err);
+}
+
+static void __devexit
+wl_remove(struct pci_dev *pdev)
+{
+ wl_info_t *wl = (wl_info_t *) pci_get_drvdata(pdev);
+
+ if (!wl) {
+ WL_ERROR(("wl: wl_remove: pci_get_drvdata failed\n"));
+ return;
+ }
+ if (!wlc_chipmatch(pdev->vendor, pdev->device)) {
+ WL_ERROR(("wl: wl_remove: wlc_chipmatch failed\n"));
+ return;
+ }
+
+ WL_LOCK(wl);
+ WL_APSTA_UPDN(("wl%d (%s): wl_remove() -> wl_down()\n", wl->pub->unit, wl->dev->name));
+ wl_down(wl);
+ WL_UNLOCK(wl);
+
+ wl_free(wl);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+#if defined(SIMPLE_DEV_PM_OPS)
+static SIMPLE_DEV_PM_OPS(wl_pm_ops, wl_suspend, wl_resume);
+#endif
+
+static struct pci_driver wl_pci_driver __refdata = {
+ .name = "wl",
+ .probe = wl_pci_probe,
+ .remove = __devexit_p(wl_remove),
+ .id_table = wl_id_table,
+#ifdef SIMPLE_DEV_PM_OPS
+ .driver.pm = &wl_pm_ops,
+#else
+ .suspend = wl_suspend,
+ .resume = wl_resume,
+#endif
+};
+
+static int __init
+wl_module_init(void)
+{
+ int error = -ENODEV;
+
+#ifdef BCMDBG
+ if (msglevel != 0xdeadbeef)
+ wl_msg_level = msglevel;
+ else {
+ const char *var = getvar(NULL, "wl_msglevel");
+ if (var)
+ wl_msg_level = bcm_strtoul(var, NULL, 0);
+ }
+ printf("%s: msglevel set to 0x%x\n", __FUNCTION__, wl_msg_level);
+ if (msglevel2 != 0xdeadbeef)
+ wl_msg_level2 = msglevel2;
+ else {
+ const char *var = getvar(NULL, "wl_msglevel2");
+ if (var)
+ wl_msg_level2 = bcm_strtoul(var, NULL, 0);
+ }
+ printf("%s: msglevel2 set to 0x%x\n", __FUNCTION__, wl_msg_level2);
+ {
+ extern uint32 phyhal_msg_level;
+
+ if (phymsglevel != 0xdeadbeef)
+ phyhal_msg_level = phymsglevel;
+ else {
+ const char *var = getvar(NULL, "phy_msglevel");
+ if (var)
+ phyhal_msg_level = bcm_strtoul(var, NULL, 0);
+ }
+ printf("%s: phymsglevel set to 0x%x\n", __FUNCTION__, phyhal_msg_level);
+ }
+#endif
+
+ {
+ const char *var = getvar(NULL, "wl_dispatch_mode");
+ if (var)
+ passivemode = bcm_strtoul(var, NULL, 0);
+ if (passivemode)
+ printf("%s: passivemode enabled\n", __FUNCTION__);
+ }
+
+#ifdef BCMDBG_ASSERT
+
+ if (assert_type != 0xdeadbeef)
+ g_assert_type = assert_type;
+#endif
+
+ {
+ char *var = getvar(NULL, "wl_txq_thresh");
+ if (var)
+ wl_txq_thresh = bcm_strtoul(var, NULL, 0);
+#ifdef BCMDBG
+ WL_INFORM(("%s: wl_txq_thresh set to 0x%x\n",
+ __FUNCTION__, wl_txq_thresh));
+#endif
+ }
+
+ if (!(error = pci_module_init(&wl_pci_driver)))
+ return (0);
+
+ return (error);
+}
+
+static void __exit
+wl_module_exit(void)
+{
+
+ pci_unregister_driver(&wl_pci_driver);
+
+}
+
+module_init(wl_module_init);
+module_exit(wl_module_exit);
+
+void
+wl_free(wl_info_t *wl)
+{
+ wl_timer_t *t, *next;
+ osl_t *osh;
+
+ WL_TRACE(("wl: wl_free\n"));
+ {
+ if (wl->dev && wl->dev->irq)
+ free_irq(wl->dev->irq, wl);
+ }
+
+#if defined(WL_CONFIG_RFKILL)
+ wl_uninit_rfkill(wl);
+#endif
+
+ if (wl->dev) {
+ wl_free_if(wl, WL_DEV_IF(wl->dev));
+ wl->dev = NULL;
+ }
+
+ tasklet_kill(&wl->tasklet);
+
+ tasklet_kill(&wl->tx_tasklet);
+
+ if (wl->pub) {
+ wlc_module_unregister(wl->pub, "linux", wl);
+ }
+
+ if (wl->wlc) {
+ {
+ char tmp1[128];
+ sprintf(tmp1, "%s%d", HYBRID_PROC, wl->pub->unit);
+ remove_proc_entry(tmp1, 0);
+ }
+ wlc_detach(wl->wlc);
+ wl->wlc = NULL;
+ wl->pub = NULL;
+ }
+
+ while (atomic_read(&wl->callbacks) > 0)
+ schedule();
+
+ for (t = wl->timers; t; t = next) {
+ next = t->next;
+#ifdef BCMDBG
+ if (t->name)
+ MFREE(wl->osh, t->name, strlen(t->name) + 1);
+#endif
+ MFREE(wl->osh, t, sizeof(wl_timer_t));
+ }
+
+ osh = wl->osh;
+
+ if (wl->regsva && BUSTYPE(wl->bcm_bustype) != SDIO_BUS &&
+ BUSTYPE(wl->bcm_bustype) != JTAG_BUS) {
+ iounmap((void*)wl->regsva);
+ }
+ wl->regsva = NULL;
+
+ if (wl->bar1_addr) {
+ iounmap(wl->bar1_addr);
+ wl->bar1_addr = NULL;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#endif
+
+ wl_txq_free(wl);
+
+ MFREE(osh, wl, sizeof(wl_info_t));
+
+ if (MALLOCED(osh)) {
+ printf("Memory leak of bytes %d\n", MALLOCED(osh));
+#ifndef BCMDBG_MEM
+ ASSERT(0);
+#endif
+ }
+
+#ifdef BCMDBG_MEM
+
+ MALLOC_DUMP(osh, NULL);
+#endif
+
+ osl_detach(osh);
+}
+
+static int
+wl_open(struct net_device *dev)
+{
+ wl_info_t *wl;
+ int error = 0;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_open\n", wl->pub->unit));
+
+ WL_LOCK(wl);
+ WL_APSTA_UPDN(("wl%d: (%s): wl_open() -> wl_up()\n",
+ wl->pub->unit, wl->dev->name));
+
+ error = wl_up(wl);
+ if (!error) {
+ error = wlc_set(wl->wlc, WLC_SET_PROMISC, (dev->flags & IFF_PROMISC));
+ }
+ WL_UNLOCK(wl);
+
+ if (!error)
+ OLD_MOD_INC_USE_COUNT;
+
+#if defined(USE_CFG80211)
+ if (wl_cfg80211_up(dev)) {
+ WL_ERROR(("%s: failed to bring up cfg80211\n", __func__));
+ return -1;
+ }
+#endif
+ return (error? -ENODEV : 0);
+}
+
+static int
+wl_close(struct net_device *dev)
+{
+ wl_info_t *wl;
+
+ if (!dev)
+ return -ENETDOWN;
+
+#if defined(USE_CFG80211)
+ wl_cfg80211_down(dev);
+#endif
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_close\n", wl->pub->unit));
+
+ WL_LOCK(wl);
+ WL_APSTA_UPDN(("wl%d (%s): wl_close() -> wl_down()\n",
+ wl->pub->unit, wl->dev->name));
+
+ if (wl->if_list == NULL) {
+ wl_down(wl);
+ }
+ WL_UNLOCK(wl);
+
+ OLD_MOD_DEC_USE_COUNT;
+
+ return (0);
+}
+
+void * BCMFASTPATH
+wl_get_ifctx(struct wl_info *wl, int ctx_id, wl_if_t *wlif)
+{
+ void *ifctx = NULL;
+
+ switch (ctx_id) {
+ case IFCTX_NETDEV:
+ ifctx = (void *)((wlif == NULL) ? wl->dev : wlif->dev);
+ break;
+
+ default:
+ break;
+ }
+
+ return ifctx;
+}
+
+static int BCMFASTPATH
+wl_start_int(wl_info_t *wl, wl_if_t *wlif, struct sk_buff *skb)
+{
+ void *pkt;
+
+ WL_TRACE(("wl%d: wl_start: len %d data_len %d summed %d csum: 0x%x\n",
+ wl->pub->unit, skb->len, skb->data_len, skb->ip_summed, (uint32)skb->csum));
+
+ WL_LOCK(wl);
+
+ pkt = PKTFRMNATIVE(wl->osh, skb);
+ ASSERT(pkt != NULL);
+
+ if (WME_ENAB(wl->pub) && (PKTPRIO(pkt) == 0))
+ pktsetprio(pkt, FALSE);
+
+ wlc_sendpkt(wl->wlc, pkt, wlif->wlcif);
+
+ WL_UNLOCK(wl);
+
+ return (0);
+}
+
+void
+wl_txflowcontrol(wl_info_t *wl, struct wl_if *wlif, bool state, int prio)
+{
+ struct net_device *dev;
+
+ ASSERT(prio == ALLPRIO);
+
+ if (wlif == NULL)
+ dev = wl->dev;
+ else if (!wlif->dev_registed)
+ return;
+ else
+ dev = wlif->dev;
+
+ if (state == ON)
+ netif_stop_queue(dev);
+ else
+ netif_wake_queue(dev);
+}
+
+static int
+wl_schedule_task(wl_info_t *wl, void (*fn)(struct wl_task *task), void *context)
+{
+ wl_task_t *task;
+
+ WL_TRACE(("wl%d: wl_schedule_task\n", wl->pub->unit));
+
+ if (!(task = MALLOC(wl->osh, sizeof(wl_task_t)))) {
+ WL_ERROR(("wl%d: wl_schedule_task: out of memory, malloced %d bytes\n",
+ wl->pub->unit, MALLOCED(wl->osh)));
+ return -ENOMEM;
+ }
+
+ MY_INIT_WORK(&task->work, (work_func_t)fn);
+ task->context = context;
+
+ if (!schedule_work(&task->work)) {
+ WL_ERROR(("wl%d: schedule_work() failed\n", wl->pub->unit));
+ MFREE(wl->osh, task, sizeof(wl_task_t));
+ return -ENOMEM;
+ }
+
+ atomic_inc(&wl->callbacks);
+
+ return 0;
+}
+
+static struct wl_if *
+wl_alloc_if(wl_info_t *wl, int iftype, uint subunit, struct wlc_if *wlcif)
+{
+ wl_if_t *wlif;
+ wl_if_t *p;
+
+ if (!(wlif = MALLOC(wl->osh, sizeof(wl_if_t)))) {
+ WL_ERROR(("wl%d: wl_alloc_if: out of memory, malloced %d bytes\n",
+ (wl->pub)?wl->pub->unit:subunit, MALLOCED(wl->osh)));
+ return NULL;
+ }
+ bzero(wlif, sizeof(wl_if_t));
+ wlif->wl = wl;
+ wlif->wlcif = wlcif;
+ wlif->subunit = subunit;
+ wlif->if_type = iftype;
+
+ if (wl->if_list == NULL)
+ wl->if_list = wlif;
+ else {
+ p = wl->if_list;
+ while (p->next != NULL)
+ p = p->next;
+ p->next = wlif;
+ }
+
+ return wlif;
+}
+
+static void
+wl_free_if(wl_info_t *wl, wl_if_t *wlif)
+{
+ wl_if_t *p;
+ ASSERT(wlif);
+ ASSERT(wl);
+
+ WL_TRACE(("%s\n", __FUNCTION__));
+
+ if (wlif->dev_registed) {
+ ASSERT(wlif->dev);
+ unregister_netdev(wlif->dev);
+ wlif->dev_registed = FALSE;
+ }
+
+#if defined(USE_CFG80211)
+ wl_cfg80211_detach(wlif->dev);
+#endif
+
+ p = wl->if_list;
+ if (p == wlif)
+ wl->if_list = p->next;
+ else {
+ while (p != NULL && p->next != wlif)
+ p = p->next;
+ if (p != NULL)
+ p->next = p->next->next;
+ }
+
+ if (wlif->dev) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+ MFREE(wl->osh, wlif->dev->priv, sizeof(priv_link_t));
+ MFREE(wl->osh, wlif->dev, sizeof(struct net_device));
+#else
+ free_netdev(wlif->dev);
+ wlif->dev = NULL;
+#endif
+ }
+
+ MFREE(wl->osh, wlif, sizeof(wl_if_t));
+}
+
+static struct net_device *
+wl_alloc_linux_if(wl_if_t *wlif)
+{
+ wl_info_t *wl = wlif->wl;
+ struct net_device *dev;
+ priv_link_t *priv_link;
+
+ WL_TRACE(("%s\n", __FUNCTION__));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+ dev = MALLOC(wl->osh, sizeof(struct net_device));
+ if (!dev) {
+ WL_ERROR(("wl%d: %s: malloc of net_device failed\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ return NULL;
+ }
+ bzero(dev, sizeof(struct net_device));
+ ether_setup(dev);
+
+ strncpy(dev->name, intf_name, IFNAMSIZ-1);
+ dev->name[IFNAMSIZ-1] = '\0';
+
+ priv_link = MALLOC(wl->osh, sizeof(priv_link_t));
+ if (!priv_link) {
+ WL_ERROR(("wl%d: %s: malloc of priv_link failed\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ MFREE(wl->osh, dev, sizeof(struct net_device));
+ return NULL;
+ }
+ dev->priv = priv_link;
+#else
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0))
+ dev = alloc_netdev(sizeof(priv_link_t), intf_name, ether_setup);
+#else
+ dev = alloc_netdev(sizeof(priv_link_t), intf_name, NET_NAME_UNKNOWN, ether_setup);
+#endif
+
+ if (!dev) {
+ WL_ERROR(("wl%d: %s: alloc_netdev failed\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ return NULL;
+ }
+ priv_link = netdev_priv(dev);
+ if (!priv_link) {
+ WL_ERROR(("wl%d: %s: cannot get netdev_priv\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ return NULL;
+ }
+#endif
+
+ priv_link->wlif = wlif;
+ wlif->dev = dev;
+
+ if (wlif->if_type != WL_IFTYPE_MON && wl->dev && netif_queue_stopped(wl->dev))
+ netif_stop_queue(dev);
+
+ return dev;
+}
+
+char *
+wl_ifname(wl_info_t *wl, wl_if_t *wlif)
+{
+ if (wlif) {
+ return wlif->name;
+ } else {
+ return wl->dev->name;
+ }
+}
+
+void
+wl_init(wl_info_t *wl)
+{
+ WL_TRACE(("wl%d: wl_init\n", wl->pub->unit));
+
+ wl_reset(wl);
+
+ wlc_init(wl->wlc);
+}
+
+uint
+wl_reset(wl_info_t *wl)
+{
+ uint32 macintmask;
+
+ WL_TRACE(("wl%d: wl_reset\n", wl->pub->unit));
+
+ macintmask = wl_intrsoff(wl);
+
+ wlc_reset(wl->wlc);
+
+ wl_intrsrestore(wl, macintmask);
+
+ wl->resched = 0;
+
+ return (0);
+}
+
+void BCMFASTPATH
+wl_intrson(wl_info_t *wl)
+{
+ unsigned long flags = 0;
+
+ INT_LOCK(wl, flags);
+ wlc_intrson(wl->wlc);
+ INT_UNLOCK(wl, flags);
+}
+
+bool
+wl_alloc_dma_resources(wl_info_t *wl, uint addrwidth)
+{
+ return TRUE;
+}
+
+uint32 BCMFASTPATH
+wl_intrsoff(wl_info_t *wl)
+{
+ unsigned long flags = 0;
+ uint32 status;
+
+ INT_LOCK(wl, flags);
+ status = wlc_intrsoff(wl->wlc);
+ INT_UNLOCK(wl, flags);
+ return status;
+}
+
+void
+wl_intrsrestore(wl_info_t *wl, uint32 macintmask)
+{
+ unsigned long flags = 0;
+
+ INT_LOCK(wl, flags);
+ wlc_intrsrestore(wl->wlc, macintmask);
+ INT_UNLOCK(wl, flags);
+}
+
+int
+wl_up(wl_info_t *wl)
+{
+ int error = 0;
+ wl_if_t *wlif;
+
+ WL_TRACE(("wl%d: wl_up\n", wl->pub->unit));
+
+ if (wl->pub->up)
+ return (0);
+
+ error = wlc_up(wl->wlc);
+
+ if (!error) {
+ for (wlif = wl->if_list; wlif != NULL; wlif = wlif->next) {
+ wl_txflowcontrol(wl, wlif, OFF, ALLPRIO);
+ }
+ }
+
+ return (error);
+}
+
+void
+wl_down(wl_info_t *wl)
+{
+ wl_if_t *wlif;
+ int monitor = 0;
+ uint callbacks, ret_val = 0;
+
+ WL_TRACE(("wl%d: wl_down\n", wl->pub->unit));
+
+ for (wlif = wl->if_list; wlif != NULL; wlif = wlif->next) {
+ if (wlif->dev) {
+ netif_down(wlif->dev);
+ netif_stop_queue(wlif->dev);
+ }
+ }
+
+ if (wl->monitor_dev) {
+ ret_val = wlc_ioctl(wl->wlc, WLC_SET_MONITOR, &monitor, sizeof(int), NULL);
+ if (ret_val != BCME_OK) {
+ WL_ERROR(("%s: Disabling MONITOR failed %d\n", __FUNCTION__, ret_val));
+ }
+ }
+
+ if (wl->wlc)
+ ret_val = wlc_down(wl->wlc);
+
+ callbacks = atomic_read(&wl->callbacks) - ret_val;
+ BCM_REFERENCE(callbacks);
+
+ WL_UNLOCK(wl);
+
+ if (WL_ALL_PASSIVE_ENAB(wl)) {
+ int i = 0;
+ for (i = 0; (atomic_read(&wl->callbacks) > callbacks) && i < 10000; i++) {
+ schedule();
+ flush_scheduled_work();
+ }
+ }
+ else
+ {
+
+ SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
+ }
+
+ WL_LOCK(wl);
+}
+
+static int
+wl_toe_get(wl_info_t *wl, uint32 *toe_ol)
+{
+ if (wlc_iovar_getint(wl->wlc, "toe_ol", toe_ol) != 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int
+wl_toe_set(wl_info_t *wl, uint32 toe_ol)
+{
+ if (wlc_iovar_setint(wl->wlc, "toe_ol", toe_ol) != 0)
+ return -EOPNOTSUPP;
+
+ if (wlc_iovar_setint(wl->wlc, "toe", (toe_ol != 0)) != 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static void
+wl_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ wl_info_t *wl = WL_INFO(dev);
+
+#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+ if (!wl || !wl->pub || !wl->wlc || !wl->dev)
+ return;
+#endif
+ bzero(info, sizeof(struct ethtool_drvinfo));
+ snprintf(info->driver, sizeof(info->driver), "wl%d", wl->pub->unit);
+ strncpy(info->version, EPI_VERSION_STR, sizeof(info->version));
+ info->version[(sizeof(info->version))-1] = '\0';
+}
+
+static int
+wl_ethtool(wl_info_t *wl, void *uaddr, wl_if_t *wlif)
+{
+ struct ethtool_drvinfo info;
+ struct ethtool_value edata;
+ uint32 cmd;
+ uint32 toe_cmpnt = 0, csum_dir;
+ int ret;
+
+ if (!wl || !wl->pub || !wl->wlc)
+ return -ENODEV;
+
+ WL_TRACE(("wl%d: %s\n", wl->pub->unit, __FUNCTION__));
+
+ if (copy_from_user(&cmd, uaddr, sizeof(uint32)))
+ return (-EFAULT);
+
+ switch (cmd) {
+ case ETHTOOL_GDRVINFO:
+ if (!wl->dev)
+ return -ENETDOWN;
+
+ wl_get_driver_info(wl->dev, &info);
+ info.cmd = cmd;
+ if (copy_to_user(uaddr, &info, sizeof(info)))
+ return (-EFAULT);
+ break;
+
+ case ETHTOOL_GRXCSUM:
+ case ETHTOOL_GTXCSUM:
+ if ((ret = wl_toe_get(wl, &toe_cmpnt)) < 0)
+ return ret;
+
+ csum_dir = (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ edata.cmd = cmd;
+ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
+
+ if (copy_to_user(uaddr, &edata, sizeof(edata)))
+ return (-EFAULT);
+ break;
+
+ case ETHTOOL_SRXCSUM:
+ case ETHTOOL_STXCSUM:
+ if (copy_from_user(&edata, uaddr, sizeof(edata)))
+ return (-EFAULT);
+
+ if ((ret = wl_toe_get(wl, &toe_cmpnt)) < 0)
+ return ret;
+
+ csum_dir = (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ if (edata.data != 0)
+ toe_cmpnt |= csum_dir;
+ else
+ toe_cmpnt &= ~csum_dir;
+
+ if ((ret = wl_toe_set(wl, toe_cmpnt)) < 0)
+ return ret;
+
+ if (cmd == ETHTOOL_STXCSUM) {
+ if (!wl->dev)
+ return -ENETDOWN;
+ if (edata.data)
+ wl->dev->features |= NETIF_F_IP_CSUM;
+ else
+ wl->dev->features &= ~NETIF_F_IP_CSUM;
+ }
+
+ break;
+
+ default:
+ return (-EOPNOTSUPP);
+
+ }
+
+ return (0);
+}
+
+int
+wl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ wl_info_t *wl;
+ wl_if_t *wlif;
+ void *buf = NULL;
+ wl_ioctl_t ioc;
+ int bcmerror;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wl = WL_INFO(dev);
+ wlif = WL_DEV_IF(dev);
+ if (wlif == NULL || wl == NULL || wl->dev == NULL)
+ return -ENETDOWN;
+
+ bcmerror = 0;
+
+ WL_TRACE(("wl%d: wl_ioctl: cmd 0x%x\n", wl->pub->unit, cmd));
+
+#ifdef USE_IW
+
+ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
+
+ return wl_iw_ioctl(dev, ifr, cmd);
+ }
+#endif
+
+ if (cmd == SIOCETHTOOL)
+ return (wl_ethtool(wl, (void*)ifr->ifr_data, wlif));
+
+ switch (cmd) {
+ case SIOCDEVPRIVATE :
+ break;
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ goto done2;
+ }
+
+ if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
+ bcmerror = BCME_BADADDR;
+ goto done2;
+ }
+
+ if (segment_eq(get_fs(), KERNEL_DS))
+ buf = ioc.buf;
+
+ else if (ioc.buf) {
+ if (!(buf = (void *) MALLOC(wl->osh, MAX(ioc.len, WLC_IOCTL_MAXLEN)))) {
+ bcmerror = BCME_NORESOURCE;
+ goto done2;
+ }
+
+ if (copy_from_user(buf, ioc.buf, ioc.len)) {
+ bcmerror = BCME_BADADDR;
+ goto done1;
+ }
+ }
+
+ WL_LOCK(wl);
+ if (!capable(CAP_NET_ADMIN)) {
+ bcmerror = BCME_EPERM;
+ } else {
+ bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif);
+ }
+ WL_UNLOCK(wl);
+
+done1:
+ if (ioc.buf && (ioc.buf != buf)) {
+ if (copy_to_user(ioc.buf, buf, ioc.len))
+ bcmerror = BCME_BADADDR;
+ MFREE(wl->osh, buf, MAX(ioc.len, WLC_IOCTL_MAXLEN));
+ }
+
+done2:
+ ASSERT(VALID_BCMERROR(bcmerror));
+ if (bcmerror != 0)
+ wl->pub->bcmerror = bcmerror;
+ return (OSL_ERROR(bcmerror));
+}
+
+static struct net_device_stats*
+wl_get_stats(struct net_device *dev)
+{
+ struct net_device_stats *stats_watchdog = NULL;
+ struct net_device_stats *stats = NULL;
+ wl_info_t *wl;
+ wl_if_t *wlif;
+
+ if (!dev)
+ return NULL;
+
+ if ((wl = WL_INFO(dev)) == NULL)
+ return NULL;
+
+ if ((wlif = WL_DEV_IF(dev)) == NULL)
+ return NULL;
+
+ if ((stats = &wlif->stats) == NULL)
+ return NULL;
+
+ WL_TRACE(("wl%d: wl_get_stats\n", wl->pub->unit));
+
+ ASSERT(wlif->stats_id < 2);
+ stats_watchdog = &wlif->stats_watchdog[wlif->stats_id];
+ memcpy(stats, stats_watchdog, sizeof(struct net_device_stats));
+ return (stats);
+}
+
+#ifdef USE_IW
+struct iw_statistics *
+wl_get_wireless_stats(struct net_device *dev)
+{
+ int res = 0;
+ wl_info_t *wl;
+ wl_if_t *wlif;
+ struct iw_statistics *wstats = NULL;
+ struct iw_statistics *wstats_watchdog = NULL;
+ int phy_noise, rssi;
+
+ if (!dev)
+ return NULL;
+
+ if ((wl = WL_INFO(dev)) == NULL)
+ return NULL;
+
+ if ((wlif = WL_DEV_IF(dev)) == NULL)
+ return NULL;
+
+ if ((wstats = &wlif->wstats) == NULL)
+ return NULL;
+
+ WL_TRACE(("wl%d: wl_get_wireless_stats\n", wl->pub->unit));
+
+ ASSERT(wlif->stats_id < 2);
+ wstats_watchdog = &wlif->wstats_watchdog[wlif->stats_id];
+
+ phy_noise = wlif->phy_noise;
+#if WIRELESS_EXT > 11
+ wstats->discard.nwid = 0;
+ wstats->discard.code = wstats_watchdog->discard.code;
+ wstats->discard.fragment = wstats_watchdog->discard.fragment;
+ wstats->discard.retries = wstats_watchdog->discard.retries;
+ wstats->discard.misc = wstats_watchdog->discard.misc;
+
+ wstats->miss.beacon = 0;
+#endif
+
+ if (AP_ENAB(wl->pub))
+ rssi = 0;
+ else {
+ scb_val_t scb;
+ res = wlc_ioctl(wl->wlc, WLC_GET_RSSI, &scb, sizeof(int), wlif->wlcif);
+ if (res) {
+ WL_ERROR(("wl%d: %s: WLC_GET_RSSI failed (%d)\n",
+ wl->pub->unit, __FUNCTION__, res));
+ return NULL;
+ }
+ rssi = scb.val;
+ }
+
+ if (rssi <= WLC_RSSI_NO_SIGNAL)
+ wstats->qual.qual = 0;
+ else if (rssi <= WLC_RSSI_VERY_LOW)
+ wstats->qual.qual = 1;
+ else if (rssi <= WLC_RSSI_LOW)
+ wstats->qual.qual = 2;
+ else if (rssi <= WLC_RSSI_GOOD)
+ wstats->qual.qual = 3;
+ else if (rssi <= WLC_RSSI_VERY_GOOD)
+ wstats->qual.qual = 4;
+ else
+ wstats->qual.qual = 5;
+
+ wstats->qual.level = 0x100 + rssi;
+ wstats->qual.noise = 0x100 + phy_noise;
+#if WIRELESS_EXT > 18
+ wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
+#else
+ wstats->qual.updated |= 7;
+#endif
+
+ return wstats;
+}
+#endif
+
+static int
+wl_set_mac_address(struct net_device *dev, void *addr)
+{
+ int err = 0;
+ wl_info_t *wl;
+ struct sockaddr *sa = (struct sockaddr *) addr;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_set_mac_address\n", wl->pub->unit));
+
+ WL_LOCK(wl);
+
+ bcopy(sa->sa_data, dev->dev_addr, ETHER_ADDR_LEN);
+ err = wlc_iovar_op(wl->wlc, "cur_etheraddr", NULL, 0, sa->sa_data, ETHER_ADDR_LEN,
+ IOV_SET, (WL_DEV_IF(dev))->wlcif);
+ WL_UNLOCK(wl);
+ if (err)
+ WL_ERROR(("wl%d: wl_set_mac_address: error setting MAC addr override\n",
+ wl->pub->unit));
+ return err;
+}
+
+static void
+wl_set_multicast_list(struct net_device *dev)
+{
+ if (!WL_ALL_PASSIVE_ENAB((wl_info_t *)WL_INFO(dev)))
+ _wl_set_multicast_list(dev);
+ else {
+ wl_info_t *wl = WL_INFO(dev);
+ wl->multicast_task.context = dev;
+
+ if (schedule_work(&wl->multicast_task.work)) {
+
+ atomic_inc(&wl->callbacks);
+ }
+ }
+}
+
+static void
+_wl_set_multicast_list(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
+ struct dev_mc_list *mclist;
+#else
+ struct netdev_hw_addr *ha;
+#endif
+ wl_info_t *wl;
+ int i, buflen;
+ struct maclist *maclist;
+ int allmulti;
+
+ if (!dev)
+ return;
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_set_multicast_list\n", wl->pub->unit));
+
+ if (wl->pub->up) {
+ allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: FALSE;
+
+ buflen = sizeof(struct maclist) + (MAXMULTILIST * ETHER_ADDR_LEN);
+
+ if ((maclist = MALLOC(wl->pub->osh, buflen)) == NULL) {
+ return;
+ }
+
+ i = 0;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
+ for (mclist = dev->mc_list; mclist && (i < dev->mc_count); mclist = mclist->next) {
+ if (i >= MAXMULTILIST) {
+ allmulti = TRUE;
+ i = 0;
+ break;
+ }
+ bcopy(mclist->dmi_addr, &maclist->ea[i++], ETHER_ADDR_LEN);
+ }
+#else
+ netdev_for_each_mc_addr(ha, dev) {
+ if (i >= MAXMULTILIST) {
+ allmulti = TRUE;
+ i = 0;
+ break;
+ }
+ bcopy(ha->addr, &maclist->ea[i++], ETHER_ADDR_LEN);
+ }
+#endif
+ maclist->count = i;
+
+ WL_LOCK(wl);
+
+ wlc_iovar_op(wl->wlc, "allmulti", NULL, 0, &allmulti, sizeof(allmulti), IOV_SET,
+ (WL_DEV_IF(dev))->wlcif);
+ wlc_set(wl->wlc, WLC_SET_PROMISC, (dev->flags & IFF_PROMISC));
+
+ wlc_iovar_op(wl->wlc, "mcast_list", NULL, 0, maclist, buflen, IOV_SET,
+ (WL_DEV_IF(dev))->wlcif);
+
+ WL_UNLOCK(wl);
+ MFREE(wl->pub->osh, maclist, buflen);
+ }
+
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+irqreturn_t BCMFASTPATH
+wl_isr(int irq, void *dev_id)
+#else
+irqreturn_t BCMFASTPATH
+wl_isr(int irq, void *dev_id, struct pt_regs *ptregs)
+#endif
+{
+ wl_info_t *wl;
+ bool ours, wantdpc;
+ unsigned long flags;
+
+ wl = (wl_info_t*) dev_id;
+
+ WL_ISRLOCK(wl, flags);
+
+ if ((ours = wlc_isr(wl->wlc, &wantdpc))) {
+
+ if (wantdpc) {
+
+ ASSERT(wl->resched == FALSE);
+ if (WL_ALL_PASSIVE_ENAB(wl)) {
+ if (schedule_work(&wl->wl_dpc_task.work))
+ atomic_inc(&wl->callbacks);
+ else
+ ASSERT(0);
+ } else
+ tasklet_schedule(&wl->tasklet);
+ }
+ }
+
+ WL_ISRUNLOCK(wl, flags);
+
+ return IRQ_RETVAL(ours);
+}
+
+static void BCMFASTPATH
+wl_dpc(ulong data)
+{
+ wl_info_t *wl;
+
+ wl = (wl_info_t *)data;
+
+ WL_LOCK(wl);
+
+ if (wl->pub->up) {
+ wlc_dpc_info_t dpci = {0};
+
+ if (wl->resched) {
+ unsigned long flags = 0;
+ INT_LOCK(wl, flags);
+ wlc_intrsupd(wl->wlc);
+ INT_UNLOCK(wl, flags);
+ }
+
+ wl->resched = wlc_dpc(wl->wlc, TRUE, &dpci);
+
+ wl->processed = dpci.processed;
+ }
+
+ if (!wl->pub->up) {
+
+ if ((WL_ALL_PASSIVE_ENAB(wl))) {
+ atomic_dec(&wl->callbacks);
+ }
+ goto done;
+ }
+
+ if (wl->resched) {
+ if (!(WL_ALL_PASSIVE_ENAB(wl)))
+ tasklet_schedule(&wl->tasklet);
+ else
+ if (!schedule_work(&wl->wl_dpc_task.work)) {
+
+ ASSERT(0);
+ }
+ }
+ else {
+
+ if (WL_ALL_PASSIVE_ENAB(wl))
+ atomic_dec(&wl->callbacks);
+ wl_intrson(wl);
+ }
+
+done:
+ WL_UNLOCK(wl);
+ return;
+}
+
+static void BCMFASTPATH
+wl_dpc_rxwork(struct wl_task *task)
+{
+ wl_info_t *wl = (wl_info_t *)task->context;
+ WL_TRACE(("wl%d: %s\n", wl->pub->unit, __FUNCTION__));
+
+ wl_dpc((unsigned long)wl);
+ return;
+}
+
+void BCMFASTPATH
+wl_sendup(wl_info_t *wl, wl_if_t *wlif, void *p, int numpkt)
+{
+ struct sk_buff *skb;
+ bool brcm_specialpkt;
+
+ WL_TRACE(("wl%d: wl_sendup: %d bytes\n", wl->pub->unit, PKTLEN(wl->osh, p)));
+
+ brcm_specialpkt =
+ (ntoh16_ua(PKTDATA(wl->pub->osh, p) + ETHER_TYPE_OFFSET) == ETHER_TYPE_BRCM);
+
+ if (!brcm_specialpkt) {
+
+ }
+
+ if (wlif) {
+
+ if (!wlif->dev || !netif_device_present(wlif->dev)) {
+ WL_ERROR(("wl%d: wl_sendup: interface not ready\n", wl->pub->unit));
+ PKTFREE(wl->osh, p, FALSE);
+ return;
+ }
+
+ skb = PKTTONATIVE(wl->osh, p);
+ skb->dev = wlif->dev;
+ } else {
+
+ skb = PKTTONATIVE(wl->osh, p);
+ skb->dev = wl->dev;
+
+ }
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ if (!brcm_specialpkt && !ISALIGNED(skb->data, 4)) {
+ WL_ERROR(("Unaligned assert. skb %p. skb->data %p.\n", skb, skb->data));
+ if (wlif) {
+ WL_ERROR(("wl_sendup: dev name is %s (wlif) \n", wlif->dev->name));
+ WL_ERROR(("wl_sendup: hard header len %d (wlif) \n",
+ wlif->dev->hard_header_len));
+ }
+ WL_ERROR(("wl_sendup: dev name is %s (wl) \n", wl->dev->name));
+ WL_ERROR(("wl_sendup: hard header len %d (wl) \n", wl->dev->hard_header_len));
+ ASSERT(ISALIGNED(skb->data, 4));
+ }
+
+ WL_APSTA_RX(("wl%d: wl_sendup(): pkt %p summed %d on interface %p (%s)\n",
+ wl->pub->unit, p, skb->ip_summed, wlif, skb->dev->name));
+
+ netif_rx(skb);
+
+}
+
+int
+wl_osl_pcie_rc(struct wl_info *wl, uint op, int param)
+{
+ return 0;
+}
+
+void
+wl_dump_ver(wl_info_t *wl, struct bcmstrbuf *b)
+{
+ bcm_bprintf(b, "wl%d: %s %s version %s\n", wl->pub->unit,
+ __DATE__, __TIME__, EPI_VERSION_STR);
+}
+
+#if defined(BCMDBG)
+static int
+wl_dump(wl_info_t *wl, struct bcmstrbuf *b)
+{
+ wl_if_t *p;
+ int i;
+
+ wl_dump_ver(wl, b);
+
+ bcm_bprintf(b, "name %s dev %p tbusy %d callbacks %d malloced %d\n",
+ wl->dev->name, wl->dev, (uint)netif_queue_stopped(wl->dev),
+ atomic_read(&wl->callbacks), MALLOCED(wl->osh));
+
+ p = wl->if_list;
+ if (p)
+ p = p->next;
+ for (i = 0; p != NULL; p = p->next, i++) {
+ if ((i % 4) == 0) {
+ if (i != 0)
+ bcm_bprintf(b, "\n");
+ bcm_bprintf(b, "Interfaces:");
+ }
+ bcm_bprintf(b, " name %s dev %p", p->dev->name, p->dev);
+ }
+ if (i)
+ bcm_bprintf(b, "\n");
+
+ return 0;
+}
+#endif
+
+static void
+wl_link_up(wl_info_t *wl, char *ifname)
+{
+ WL_ERROR(("wl%d: link up (%s)\n", wl->pub->unit, ifname));
+}
+
+static void
+wl_link_down(wl_info_t *wl, char *ifname)
+{
+ WL_ERROR(("wl%d: link down (%s)\n", wl->pub->unit, ifname));
+}
+
+void
+wl_event(wl_info_t *wl, char *ifname, wlc_event_t *e)
+{
+#ifdef USE_IW
+ wl_iw_event(wl->dev, &(e->event), e->data);
+#endif
+
+#if defined(USE_CFG80211)
+ wl_cfg80211_event(wl->dev, &(e->event), e->data);
+#endif
+ switch (e->event.event_type) {
+ case WLC_E_LINK:
+ case WLC_E_NDIS_LINK:
+ if (e->event.flags&WLC_EVENT_MSG_LINK)
+ wl_link_up(wl, ifname);
+ else
+ wl_link_down(wl, ifname);
+ break;
+#if defined(WL_CONFIG_RFKILL)
+ case WLC_E_RADIO: {
+ mbool i;
+ if (wlc_get(wl->wlc, WLC_GET_RADIO, &i) < 0)
+ WL_ERROR(("%s: WLC_GET_RADIO failed\n", __FUNCTION__));
+ if (wl->last_phyind == (mbool)(i & WL_RADIO_HW_DISABLE))
+ break;
+
+ wl->last_phyind = (mbool)(i & WL_RADIO_HW_DISABLE);
+
+ WL_ERROR(("wl%d: Radio hardware state changed to %d\n", wl->pub->unit, i));
+ wl_report_radio_state(wl);
+ break;
+ }
+#else
+ case WLC_E_RADIO:
+ break;
+#endif
+ }
+}
+
+void
+wl_event_sync(wl_info_t *wl, char *ifname, wlc_event_t *e)
+{
+}
+
+static void BCMFASTPATH
+wl_sched_tx_tasklet(void *t)
+{
+ wl_info_t *wl = (wl_info_t *)t;
+ tasklet_schedule(&wl->tx_tasklet);
+}
+
+#define WL_CONFIG_SMP() FALSE
+
+static int BCMFASTPATH
+wl_start(struct sk_buff *skb, struct net_device *dev)
+{
+ wl_if_t *wlif;
+ wl_info_t *wl;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wlif = WL_DEV_IF(dev);
+ wl = WL_INFO(dev);
+
+ if (WL_ALL_PASSIVE_ENAB(wl) || (WL_RTR() && WL_CONFIG_SMP())) {
+ skb->prev = NULL;
+
+ TXQ_LOCK(wl);
+
+ if ((wl_txq_thresh > 0) && (wl->txq_cnt >= wl_txq_thresh)) {
+ PKTFRMNATIVE(wl->osh, skb);
+ PKTCFREE(wl->osh, skb, TRUE);
+ TXQ_UNLOCK(wl);
+ return 0;
+ }
+
+ if (wl->txq_head == NULL)
+ wl->txq_head = skb;
+ else
+ wl->txq_tail->prev = skb;
+ wl->txq_tail = skb;
+ wl->txq_cnt++;
+
+ if (!wl->txq_dispatched) {
+ int32 err = 0;
+
+ if (!WL_ALL_PASSIVE_ENAB(wl))
+ wl_sched_tx_tasklet(wl);
+ else
+ err = (int32)(schedule_work(&wl->txq_task.work) == 0);
+
+ if (!err) {
+ atomic_inc(&wl->callbacks);
+ wl->txq_dispatched = TRUE;
+ } else
+ WL_ERROR(("wl%d: wl_start/schedule_work failed\n",
+ wl->pub->unit));
+ }
+
+ TXQ_UNLOCK(wl);
+ } else
+ return wl_start_int(wl, wlif, skb);
+
+ return (0);
+}
+
+static void BCMFASTPATH
+wl_start_txqwork(wl_task_t *task)
+{
+ wl_info_t *wl = (wl_info_t *)task->context;
+ struct sk_buff *skb;
+
+ WL_TRACE(("wl%d: %s txq_cnt %d\n", wl->pub->unit, __FUNCTION__, wl->txq_cnt));
+
+#ifdef BCMDBG
+ if (wl->txq_cnt >= 500)
+ WL_ERROR(("wl%d: WARNING dispatching over 500 packets in txqwork(%d)\n",
+ wl->pub->unit, wl->txq_cnt));
+#endif
+
+ TXQ_LOCK(wl);
+ while (wl->txq_head) {
+ skb = wl->txq_head;
+ wl->txq_head = skb->prev;
+ skb->prev = NULL;
+ if (wl->txq_head == NULL)
+ wl->txq_tail = NULL;
+ wl->txq_cnt--;
+ TXQ_UNLOCK(wl);
+
+ wl_start_int(wl, WL_DEV_IF(skb->dev), skb);
+
+ TXQ_LOCK(wl);
+ }
+
+ wl->txq_dispatched = FALSE;
+ atomic_dec(&wl->callbacks);
+ TXQ_UNLOCK(wl);
+
+ return;
+}
+
+static void BCMFASTPATH
+wl_tx_tasklet(ulong data)
+{
+ wl_task_t task;
+ task.context = (void *)data;
+ wl_start_txqwork(&task);
+}
+
+static void
+wl_txq_free(wl_info_t *wl)
+{
+ struct sk_buff *skb;
+
+ if (wl->txq_head == NULL) {
+ ASSERT(wl->txq_tail == NULL);
+ return;
+ }
+
+ while (wl->txq_head) {
+ skb = wl->txq_head;
+ wl->txq_head = skb->prev;
+ wl->txq_cnt--;
+ PKTFRMNATIVE(wl->osh, skb);
+ PKTCFREE(wl->osh, skb, TRUE);
+ }
+
+ wl->txq_tail = NULL;
+}
+
+static void
+wl_set_multicast_list_workitem(struct work_struct *work)
+{
+ wl_task_t *task = (wl_task_t *)work;
+ struct net_device *dev = (struct net_device*)task->context;
+ wl_info_t *wl;
+
+ wl = WL_INFO(dev);
+
+ atomic_dec(&wl->callbacks);
+
+ _wl_set_multicast_list(dev);
+}
+
+static void
+wl_timer_task(wl_task_t *task)
+{
+ wl_timer_t *t = (wl_timer_t *)task->context;
+
+ _wl_timer(t);
+ MFREE(t->wl->osh, task, sizeof(wl_task_t));
+
+ atomic_dec(&t->wl->callbacks);
+}
+
+static void
+wl_timer(ulong data)
+{
+ wl_timer_t *t = (wl_timer_t *)data;
+
+ if (!WL_ALL_PASSIVE_ENAB(t->wl))
+ _wl_timer(t);
+ else
+ wl_schedule_task(t->wl, wl_timer_task, t);
+}
+
+static void
+_wl_timer(wl_timer_t *t)
+{
+ wl_info_t *wl = t->wl;
+
+ WL_LOCK(wl);
+
+ if (t->set && (!timer_pending(&t->timer))) {
+ if (t->periodic) {
+ t->timer.expires = jiffies + t->ms*HZ/1000;
+ atomic_inc(&wl->callbacks);
+ add_timer(&t->timer);
+ t->set = TRUE;
+ } else
+ t->set = FALSE;
+
+ t->fn(t->arg);
+#ifdef BCMDBG
+ wlc_update_perf_stats(wl->wlc, WLC_PERF_STATS_TMR_DPC);
+ t->ticks++;
+#endif
+
+ }
+
+ atomic_dec(&wl->callbacks);
+
+ WL_UNLOCK(wl);
+}
+
+wl_timer_t *
+wl_init_timer(wl_info_t *wl, void (*fn)(void *arg), void *arg, const char *tname)
+{
+ wl_timer_t *t;
+
+ t = (wl_timer_t*)MALLOC(wl->osh, sizeof(wl_timer_t));
+
+ if (t == NULL) {
+ WL_ERROR(("wl%d: wl_init_timer: out of memory, malloced %d bytes\n",
+ wl->unit, MALLOCED(wl->osh)));
+ return 0;
+ }
+
+ bzero(t, sizeof(wl_timer_t));
+
+ init_timer(&t->timer);
+ t->timer.data = (ulong) t;
+ t->timer.function = wl_timer;
+ t->wl = wl;
+ t->fn = fn;
+ t->arg = arg;
+ t->next = wl->timers;
+ wl->timers = t;
+
+#ifdef BCMDBG
+ if ((t->name = MALLOC(wl->osh, strlen(tname) + 1)))
+ strcpy(t->name, tname);
+#endif
+
+ return t;
+}
+
+void
+wl_add_timer(wl_info_t *wl, wl_timer_t *t, uint ms, int periodic)
+{
+#ifdef BCMDBG
+ if (t->set) {
+ WL_ERROR(("%s: Already set. Name: %s, per %d\n",
+ __FUNCTION__, t->name, periodic));
+ }
+#endif
+
+ t->ms = ms;
+ t->periodic = (bool) periodic;
+
+ if (t->set)
+ return;
+
+ t->set = TRUE;
+ t->timer.expires = jiffies + ms*HZ/1000;
+
+ atomic_inc(&wl->callbacks);
+ add_timer(&t->timer);
+}
+
+bool
+wl_del_timer(wl_info_t *wl, wl_timer_t *t)
+{
+ ASSERT(t);
+ if (t->set) {
+ t->set = FALSE;
+ if (!del_timer(&t->timer)) {
+#ifdef BCMDBG
+ WL_INFORM(("wl%d: Failed to delete timer %s\n", wl->unit, t->name));
+#endif
+ return TRUE;
+ }
+ atomic_dec(&wl->callbacks);
+ }
+
+ return TRUE;
+}
+
+void
+wl_free_timer(wl_info_t *wl, wl_timer_t *t)
+{
+ wl_timer_t *tmp;
+
+ wl_del_timer(wl, t);
+
+ if (wl->timers == t) {
+ wl->timers = wl->timers->next;
+#ifdef BCMDBG
+ if (t->name)
+ MFREE(wl->osh, t->name, strlen(t->name) + 1);
+#endif
+ MFREE(wl->osh, t, sizeof(wl_timer_t));
+ return;
+
+ }
+
+ tmp = wl->timers;
+ while (tmp) {
+ if (tmp->next == t) {
+ tmp->next = t->next;
+#ifdef BCMDBG
+ if (t->name)
+ MFREE(wl->osh, t->name, strlen(t->name) + 1);
+#endif
+ MFREE(wl->osh, t, sizeof(wl_timer_t));
+ return;
+ }
+ tmp = tmp->next;
+ }
+
+}
+
+void
+wl_monitor(wl_info_t *wl, wl_rxsts_t *rxsts, void *p)
+{
+ struct sk_buff *oskb = (struct sk_buff *)p;
+ struct sk_buff *skb;
+ uchar *pdata;
+ uint len;
+
+ len = 0;
+ skb = NULL;
+ WL_TRACE(("wl%d: wl_monitor\n", wl->pub->unit));
+
+ if (!wl->monitor_dev)
+ return;
+
+ if (wl->monitor_type == 1) {
+ p80211msg_t *phdr;
+
+ len = sizeof(p80211msg_t) + oskb->len - D11_PHY_HDR_LEN;
+ if ((skb = dev_alloc_skb(len)) == NULL) {
+ WL_ERROR(("%s: dev_alloc_skb() failure, mon type 1", __FUNCTION__));
+ return;
+ }
+
+ skb_put(skb, len);
+ phdr = (p80211msg_t*)skb->data;
+
+ phdr->msgcode = WL_MON_FRAME;
+ phdr->msglen = sizeof(p80211msg_t);
+ strcpy(phdr->devname, wl->dev->name);
+
+ phdr->hosttime.did = WL_MON_FRAME_HOSTTIME;
+ phdr->hosttime.status = P80211ITEM_OK;
+ phdr->hosttime.len = 4;
+ phdr->hosttime.data = jiffies;
+
+ phdr->channel.did = WL_MON_FRAME_CHANNEL;
+ phdr->channel.status = P80211ITEM_NO_VALUE;
+ phdr->channel.len = 4;
+ phdr->channel.data = 0;
+
+ phdr->signal.did = WL_MON_FRAME_SIGNAL;
+ phdr->signal.status = P80211ITEM_OK;
+ phdr->signal.len = 4;
+
+ phdr->signal.data = rxsts->preamble;
+
+ phdr->noise.did = WL_MON_FRAME_NOISE;
+ phdr->noise.status = P80211ITEM_NO_VALUE;
+ phdr->noise.len = 4;
+ phdr->noise.data = 0;
+
+ phdr->rate.did = WL_MON_FRAME_RATE;
+ phdr->rate.status = P80211ITEM_OK;
+ phdr->rate.len = 4;
+ phdr->rate.data = rxsts->datarate;
+
+ phdr->istx.did = WL_MON_FRAME_ISTX;
+ phdr->istx.status = P80211ITEM_NO_VALUE;
+ phdr->istx.len = 4;
+ phdr->istx.data = 0;
+
+ phdr->mactime.did = WL_MON_FRAME_MACTIME;
+ phdr->mactime.status = P80211ITEM_OK;
+ phdr->mactime.len = 4;
+ phdr->mactime.data = rxsts->mactime;
+
+ phdr->rssi.did = WL_MON_FRAME_RSSI;
+ phdr->rssi.status = P80211ITEM_OK;
+ phdr->rssi.len = 4;
+ phdr->rssi.data = rxsts->signal;
+
+ phdr->sq.did = WL_MON_FRAME_SQ;
+ phdr->sq.status = P80211ITEM_OK;
+ phdr->sq.len = 4;
+ phdr->sq.data = rxsts->sq;
+
+ phdr->frmlen.did = WL_MON_FRAME_FRMLEN;
+ phdr->frmlen.status = P80211ITEM_OK;
+ phdr->frmlen.status = P80211ITEM_OK;
+ phdr->frmlen.len = 4;
+ phdr->frmlen.data = rxsts->pktlength;
+
+ pdata = skb->data + sizeof(p80211msg_t);
+ bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN);
+
+ }
+ else if (wl->monitor_type == 2) {
+ int channel_frequency;
+ uint16 channel_flags;
+ uint8 flags;
+ uint16 rtap_len;
+ struct dot11_header *mac_header;
+ uint16 fc;
+
+ if (rxsts->phytype != WL_RXS_PHY_N)
+ rtap_len = sizeof(wl_radiotap_legacy_t);
+ else
+ rtap_len = sizeof(wl_radiotap_ht_brcm_2_t);
+
+ len = rtap_len + (oskb->len - D11_PHY_HDR_LEN);
+ if ((skb = dev_alloc_skb(len)) == NULL) {
+ WL_ERROR(("%s: dev_alloc_skb() failure, mon type 2", __FUNCTION__));
+ return;
+ }
+
+ skb_put(skb, len);
+
+ if (CHSPEC_IS2G(rxsts->chanspec)) {
+ channel_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_2_4_G);
+ } else {
+ channel_flags = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_5_G);
+ }
+
+ mac_header = (struct dot11_header *)(oskb->data + D11_PHY_HDR_LEN);
+ fc = ltoh16(mac_header->fc);
+
+ flags = IEEE80211_RADIOTAP_F_FCS;
+
+ if (rxsts->preamble == WL_RXS_PREAMBLE_SHORT)
+ flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+ if (fc & FC_WEP)
+ flags |= IEEE80211_RADIOTAP_F_WEP;
+
+ if (fc & FC_MOREFRAG)
+ flags |= IEEE80211_RADIOTAP_F_FRAG;
+
+ if (rxsts->pkterror & WL_RXS_CRC_ERROR)
+ flags |= IEEE80211_RADIOTAP_F_BADFCS;
+
+ if (rxsts->phytype != WL_RXS_PHY_N) {
+ wl_radiotap_legacy_t *rtl = (wl_radiotap_legacy_t *)skb->data;
+
+ rtl->ieee_radiotap.it_version = 0;
+ rtl->ieee_radiotap.it_pad = 0;
+ rtl->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtl->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_LEGACY);
+
+ rtl->tsft_l = htol32(rxsts->mactime);
+ rtl->tsft_h = 0;
+ rtl->flags = flags;
+ rtl->rate = rxsts->datarate;
+ rtl->channel_freq = HTOL16(channel_frequency);
+ rtl->channel_flags = HTOL16(channel_flags);
+ rtl->signal = (int8)rxsts->signal;
+ rtl->noise = (int8)rxsts->noise;
+ rtl->antenna = rxsts->antenna;
+
+ memcpy(rtl->vend_oui, brcm_oui, sizeof(brcm_oui));
+ rtl->vend_skip_len = WL_RADIOTAP_LEGACY_SKIP_LEN;
+ rtl->vend_sns = 0;
+
+ memset(&rtl->nonht_vht, 0, sizeof(rtl->nonht_vht));
+ rtl->nonht_vht.len = WL_RADIOTAP_NONHT_VHT_LEN;
+ } else {
+ wl_radiotap_ht_brcm_2_t *rtht = (wl_radiotap_ht_brcm_2_t *)skb->data;
+
+ rtht->ieee_radiotap.it_version = 0;
+ rtht->ieee_radiotap.it_pad = 0;
+ rtht->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtht->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_HT_BRCM2);
+ rtht->it_present_ext = HTOL32(WL_RADIOTAP_BRCM2_HT_MCS);
+ rtht->pad1 = 0;
+
+ rtht->tsft_l = htol32(rxsts->mactime);
+ rtht->tsft_h = 0;
+ rtht->flags = flags;
+ rtht->pad2 = 0;
+ rtht->channel_freq = HTOL16(channel_frequency);
+ rtht->channel_flags = HTOL16(channel_flags);
+ rtht->signal = (int8)rxsts->signal;
+ rtht->noise = (int8)rxsts->noise;
+ rtht->antenna = rxsts->antenna;
+ rtht->pad3 = 0;
+
+ memcpy(rtht->vend_oui, brcm_oui, sizeof(brcm_oui));
+ rtht->vend_sns = WL_RADIOTAP_BRCM2_HT_SNS;
+ rtht->vend_skip_len = WL_RADIOTAP_HT_BRCM2_SKIP_LEN;
+ rtht->mcs = rxsts->mcs;
+ rtht->htflags = 0;
+ if (rxsts->htflags & WL_RXS_HTF_40)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_40;
+ if (rxsts->htflags & WL_RXS_HTF_SGI)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_SGI;
+ if (rxsts->preamble & WL_RXS_PREAMBLE_HT_GF)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_GF;
+ if (rxsts->htflags & WL_RXS_HTF_LDPC)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_LDPC;
+ rtht->htflags |=
+ (rxsts->htflags & WL_RXS_HTF_STBC_MASK) <<
+ IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT;
+ }
+
+ pdata = skb->data + rtap_len;
+ bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN);
+ }
+ else if (wl->monitor_type == 3) {
+ int channel_frequency;
+ uint16 channel_flags;
+ uint8 flags;
+ uint16 rtap_len;
+ struct dot11_header * mac_header;
+ uint16 fc;
+
+ if (rxsts->phytype == WL_RXS_PHY_N) {
+ if (rxsts->encoding == WL_RXS_ENCODING_HT)
+ rtap_len = sizeof(wl_radiotap_ht_t);
+ else if (rxsts->encoding == WL_RXS_ENCODING_VHT)
+ rtap_len = sizeof(wl_radiotap_vht_t);
+ else
+ rtap_len = sizeof(wl_radiotap_legacy_t);
+ } else {
+ rtap_len = sizeof(wl_radiotap_legacy_t);
+ }
+
+ len = rtap_len + (oskb->len - D11_PHY_HDR_LEN);
+
+ if (oskb->next) {
+ struct sk_buff *amsdu_p = oskb->next;
+ uint amsdu_len = 0;
+ while (amsdu_p) {
+ amsdu_len += amsdu_p->len;
+ amsdu_p = amsdu_p->next;
+ }
+ len += amsdu_len;
+ }
+
+ if ((skb = dev_alloc_skb(len)) == NULL) {
+ WL_ERROR(("%s: dev_alloc_skb() failure, mon type 3", __FUNCTION__));
+ return;
+ }
+
+ skb_put(skb, len);
+
+ if (CHSPEC_IS2G(rxsts->chanspec)) {
+ channel_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_2_4_G);
+ } else {
+ channel_flags = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_5_G);
+ }
+
+ mac_header = (struct dot11_header *)(oskb->data + D11_PHY_HDR_LEN);
+ fc = ltoh16(mac_header->fc);
+
+ flags = IEEE80211_RADIOTAP_F_FCS;
+
+ if (rxsts->preamble == WL_RXS_PREAMBLE_SHORT)
+ flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+ if (fc & FC_WEP)
+ flags |= IEEE80211_RADIOTAP_F_WEP;
+
+ if (fc & FC_MOREFRAG)
+ flags |= IEEE80211_RADIOTAP_F_FRAG;
+
+ if (rxsts->pkterror & WL_RXS_CRC_ERROR)
+ flags |= IEEE80211_RADIOTAP_F_BADFCS;
+
+ if ((rxsts->phytype != WL_RXS_PHY_N) ||
+ ((rxsts->encoding != WL_RXS_ENCODING_HT) &&
+ (rxsts->encoding != WL_RXS_ENCODING_VHT))) {
+ wl_radiotap_legacy_t *rtl = (wl_radiotap_legacy_t *)skb->data;
+
+ rtl->ieee_radiotap.it_version = 0;
+ rtl->ieee_radiotap.it_pad = 0;
+ rtl->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtl->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_LEGACY);
+
+ rtl->it_present_ext = HTOL32(WL_RADIOTAP_LEGACY_VHT);
+ rtl->tsft_l = htol32(rxsts->mactime);
+ rtl->tsft_h = 0;
+ rtl->flags = flags;
+ rtl->rate = rxsts->datarate;
+ rtl->channel_freq = HTOL16(channel_frequency);
+ rtl->channel_flags = HTOL16(channel_flags);
+ rtl->signal = (int8)rxsts->signal;
+ rtl->noise = (int8)rxsts->noise;
+ rtl->antenna = rxsts->antenna;
+
+ memcpy(rtl->vend_oui, brcm_oui, sizeof(brcm_oui));
+ rtl->vend_skip_len = WL_RADIOTAP_LEGACY_SKIP_LEN;
+ rtl->vend_sns = 0;
+
+ memset(&rtl->nonht_vht, 0, sizeof(rtl->nonht_vht));
+ rtl->nonht_vht.len = WL_RADIOTAP_NONHT_VHT_LEN;
+ if (((fc & FC_KIND_MASK) == FC_RTS) ||
+ ((fc & FC_KIND_MASK) == FC_CTS)) {
+ rtl->nonht_vht.flags |= WL_RADIOTAP_F_NONHT_VHT_BW;
+ rtl->nonht_vht.bw = rxsts->bw_nonht;
+ rtl->vend_sns = WL_RADIOTAP_LEGACY_SNS;
+
+ }
+ if ((fc & FC_KIND_MASK) == FC_RTS) {
+ if (rxsts->vhtflags & WL_RXS_VHTF_DYN_BW_NONHT)
+ rtl->nonht_vht.flags
+ |= WL_RADIOTAP_F_NONHT_VHT_DYN_BW;
+ }
+ }
+ else if (rxsts->encoding == WL_RXS_ENCODING_VHT) {
+ wl_radiotap_vht_t *rtvht = (wl_radiotap_vht_t *)skb->data;
+
+ rtvht->ieee_radiotap.it_version = 0;
+ rtvht->ieee_radiotap.it_pad = 0;
+ rtvht->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtvht->ieee_radiotap.it_present =
+ HTOL32(WL_RADIOTAP_PRESENT_VHT);
+
+ rtvht->tsft_l = htol32(rxsts->mactime);
+ rtvht->tsft_h = 0;
+ rtvht->flags = flags;
+ rtvht->pad1 = 0;
+ rtvht->channel_freq = HTOL16(channel_frequency);
+ rtvht->channel_flags = HTOL16(channel_flags);
+ rtvht->signal = (int8)rxsts->signal;
+ rtvht->noise = (int8)rxsts->noise;
+ rtvht->antenna = rxsts->antenna;
+
+ rtvht->vht_known = (IEEE80211_RADIOTAP_VHT_HAVE_STBC |
+ IEEE80211_RADIOTAP_VHT_HAVE_TXOP_PS |
+ IEEE80211_RADIOTAP_VHT_HAVE_GI |
+ IEEE80211_RADIOTAP_VHT_HAVE_SGI_NSYM_DA |
+ IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA |
+ IEEE80211_RADIOTAP_VHT_HAVE_BF |
+ IEEE80211_RADIOTAP_VHT_HAVE_BW |
+ IEEE80211_RADIOTAP_VHT_HAVE_GID |
+ IEEE80211_RADIOTAP_VHT_HAVE_PAID);
+
+ STATIC_ASSERT(WL_RXS_VHTF_STBC ==
+ IEEE80211_RADIOTAP_VHT_STBC);
+ STATIC_ASSERT(WL_RXS_VHTF_TXOP_PS ==
+ IEEE80211_RADIOTAP_VHT_TXOP_PS);
+ STATIC_ASSERT(WL_RXS_VHTF_SGI ==
+ IEEE80211_RADIOTAP_VHT_SGI);
+ STATIC_ASSERT(WL_RXS_VHTF_SGI_NSYM_DA ==
+ IEEE80211_RADIOTAP_VHT_SGI_NSYM_DA);
+ STATIC_ASSERT(WL_RXS_VHTF_LDPC_EXTRA ==
+ IEEE80211_RADIOTAP_VHT_LDPC_EXTRA);
+ STATIC_ASSERT(WL_RXS_VHTF_BF ==
+ IEEE80211_RADIOTAP_VHT_BF);
+
+ rtvht->vht_flags = HTOL16(rxsts->vhtflags);
+
+ STATIC_ASSERT(WL_RXS_VHT_BW_20 ==
+ IEEE80211_RADIOTAP_VHT_BW_20);
+ STATIC_ASSERT(WL_RXS_VHT_BW_40 ==
+ IEEE80211_RADIOTAP_VHT_BW_40);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20L ==
+ IEEE80211_RADIOTAP_VHT_BW_20L);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20U ==
+ IEEE80211_RADIOTAP_VHT_BW_20U);
+ STATIC_ASSERT(WL_RXS_VHT_BW_80 ==
+ IEEE80211_RADIOTAP_VHT_BW_80);
+ STATIC_ASSERT(WL_RXS_VHT_BW_40L ==
+ IEEE80211_RADIOTAP_VHT_BW_40L);
+ STATIC_ASSERT(WL_RXS_VHT_BW_40U ==
+ IEEE80211_RADIOTAP_VHT_BW_40U);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20LL ==
+ IEEE80211_RADIOTAP_VHT_BW_20LL);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20LU ==
+ IEEE80211_RADIOTAP_VHT_BW_20LU);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20UL ==
+ IEEE80211_RADIOTAP_VHT_BW_20UL);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20UU ==
+ IEEE80211_RADIOTAP_VHT_BW_2