Project import generated by Copybara.

NOKEYCHECK=True
GitOrigin-RevId: fb8d5c102ccf53861155f48666a27a917d89f198
diff --git a/release_notes.txt b/release_notes.txt
new file mode 100755
index 0000000..c74026b
--- /dev/null
+++ b/release_notes.txt
@@ -0,0 +1,31 @@
+================================

+WLAN DHD Driver Release Notes

+================================

+

+DHD_REL_1_141_66_4

+* Fix Makefile to resolve __DATE__ & __TIME__ macro build error seen on gcc ver 4.9.0.

+* Fix kernel WARN message seen during rmmod.

+* Linux 4.x kernel support

+* Sync Pattern Matching Timeout Filter review changes from master branch, change

+	WLC_E_PKT_FILTER event code from 154 to 165 and WLC_E_PKT_FILTER_TIMEOUT code from 0 to 1.

+

+DHD_REL_1_141_66_3

+* Fix conditional compilation build errors.

+

+DHD_REL_1_141_66_2

+* Sync wl tool cmd (Pattern Matching Timeout Filter) updates from firmware to DHD branch.

+* Add extended event mask updates to support event numbers greater than 128.

+* Sync wl tool cmd (Counters, SR Dump, UC Fatal) updates from firmware to DHD branch.

+* Fix for Interrupt Stuck issue seen during suspend/resume.

+* Sometimes DHD enters into suspend state when bus is still awake due to absence of

+	wake locks on Non-Android platforms, so perform bus sleep status check using

+	bus_sleep event to prevent dhd entering into suspend state when bus is still awake.

+

+DHD_REL_1_141_66_1

+* Avoid wowl config on android systems during suspend.

+* Add support for configuring cfg80211 wowlan pattern filters through nl80211.

+* Fix typo in get ioctl call in wl_cfg80211_update_power_mode(), it should be false.

+* Fix to reload DHD driver without the need for reloading the entire sdio stack modules.

+* Fix compilation error related to cleanup_work, because it is not present in kernel version 3.11 onwards.

+* And add new dhd build targets to Makefile.

+* Fix rmmod crash issue seen in wl_free_wdev function.

diff --git a/src/GNUmakefile.inc b/src/GNUmakefile.inc
new file mode 100644
index 0000000..f8b97dc
--- /dev/null
+++ b/src/GNUmakefile.inc
@@ -0,0 +1,576 @@
+#  Top level GNUmakefile for windows builds
+#
+#  It includes makefiles/*.mk for windows buildtype rules
+#  and sources(windows style makefile). it doesn't depend on
+#  Makerules.env except to get SRCBASE if not yet defined.
+#
+#  $Id: GNUmakefile.inc 429915 2013-10-16 16:28:57Z $
+
+WLAN_ComponentsInUse ?= bcmwifi ppr hal
+include $(dir $(lastword $(MAKEFILE_LIST)))makefiles/WLAN_Common.mk
+
+SHELL=bash
+export SHELL
+unexport C_DEFINES
+HOSTNAME=$(shell hostname)
+ERRORS :=
+WARNINGS :=
+
+ifdef ECLOUD_BUILD_ID
+  CMDSHELL := $(subst \,/,$(COMSPEC))
+  CMDSTART := $(CMDSHELL) /c start /min /separate
+else # ECLOUD_BUILD_ID
+  CMDSHELL :=
+  CMDSTART :=
+endif # ECLOUD_BUILD_ID
+
+### if SRCBASE is not defined, set it to wherever Makerules.env is found
+ifndef SRCBASE
+    ifneq ($(wildcard ../Makerules.env), )
+	SRCBASE	= ../
+    else
+	ifneq ($(wildcard ../../Makerules.env), )
+		SRCBASE	= ../..
+	else
+	    ifneq ($(wildcard ../../../Makerules.env),)
+		    SRCBASE	= ../../..
+	    else
+		ifneq ($(wildcard ../../../../Makerules.env),)
+			SRCBASE	= ../../../..
+		else
+		ifneq ($(wildcard ../../../../../Makerules.env),)
+		    SRCBASE = ../../../../..
+		else
+		    ifneq ($(wildcard ../../../../../../Makerules.env),)
+			    SRCBASE = ../../../../../..
+		    endif
+	    endif
+		endif
+	    endif
+	endif
+    endif
+endif # ifndef SRCBASE
+
+ifeq ($(strip $(SRCBASE)), )
+    ERRORS += "SRCBASE is not defined!"
+    ERRORS += "This variable must be defined in your sources or GNUsources file,"
+    ERRORS += "or it may be calculated provided you are in a CVS source repository,"
+    ERRORS += "and you are not too far below the root."
+endif
+
+### if TTYPE is not defined, reinvoke this same makefile with TTYPE defined
+###retail:free:   --> $(MAKE) -f $(SRCBASE)/GNUmakefile.inc TTYPE=OPT all
+###debug:checked: --> $(MAKE) -f $(SRCBASE)/GNUmakefile.inc TTYPE=DBG all
+###%:             --> $(MAKE) -f $(SRCBASE)/GNUmakefile.inc TTYPE=DBG MAKECMDGOALS=$@ $@
+
+ifeq ($(origin TTYPE), undefined)
+
+all : debug free
+
+release : all
+
+unexport SRCFILE
+ifndef SRCFILE
+	SRCFILE = ./sources
+endif
+include $(SRCFILE)
+
+#   In some rare instances you may want to have the makefile synthesize
+#   explicit rules for all of your source files.  You must do this if you
+#   are building a target with multiple source files of the same name,
+#   e.g. ./utils.c and ../ntddksim/utils.c.  You might also want to use
+#   this method if you don't want to use VPATHs.
+#
+ifdef USE_SRCRULES
+
+SRCRULES=$(SRCFILE).mk
+SOURCES.CPP	:= $(filter %.cpp %.CPP,$(SOURCES))
+SOURCES.C	:= $(filter %.c %.C,$(SOURCES))
+
+$(SRCRULES) : $(SRCFILE)
+	@echo "building explicit source rules..."
+	@( \
+	echo "# DO NOT EDIT!!!!  DO NOT EDIT!!!!  DO NOT EDIT!!!!"; \
+	echo "# This file is automatically generated."; \
+	echo "#"; \
+	$(foreach f,$(SOURCES.C), echo '$$(OUTDIR_$$(TTYPE))/$(patsubst %.c,%.obj,$(subst /,_,$(f))) : $(f)'; echo '	$$(c-obj-command)'; echo;) \
+	$(foreach f,$(SOURCES.CPP), echo '$$(OUTDIR_$$(TTYPE))/$(patsubst %.cpp,%.obj,$(subst /,_,$(f))) : $(f)'; echo '	$$(cpp-obj-command)'; echo;) \
+	) >$(SRCFILE).mk
+
+$(SRCFILE) :
+	echo making $@
+
+retail free :: $(SRCRULES)
+
+debug checked :: $(SRCRULES)
+
+endif # USE_SRCRULES
+
+#
+# End of rule synthesis section
+#
+
+retail free ::
+	$(MAKE) -f $(SRCBASE)/GNUmakefile.inc TTYPE=OPT all
+
+debug checked ::
+	$(MAKE) -f $(SRCBASE)/GNUmakefile.inc TTYPE=DBG all
+
+%GNUmakefile.inc :
+	echo making $@
+
+GNUmakefile :
+	echo making $@
+
+clean :
+	$(MAKE) -f $(SRCBASE)/GNUmakefile.inc TTYPE=DBG MAKECMDGOALS=$@ $@
+
+## This catch-all generic rule breaks make targets defined in module which
+## call this makefile.
+## % : FORCE
+## 	$(MAKE) -f $(SRCBASE)/GNUmakefile.inc TTYPE=DBG MAKECMDGOALS=$@ $@
+
+.PHONY: all release free checked retail debug clean FORCE
+
+
+### if TTYPE is defined,
+###   define commands, tools and compile rules
+###   include $(SRCFILE)
+###   build all :: target ::
+else # TTYPE is defined
+
+# Define default command for printing errors and warnings.  This will
+# be redefined at the end of this makefile if any errors or warnings
+# are encountered.
+#
+define print-errors
+endef
+
+define print-warnings
+endef
+
+# define the default command for compiling .c files into .obj files.
+# Some target types will redefine this command.
+#
+# %.obj :  %.c
+define c-obj-command
+    $(CC) -c $(C$(TTYPE)FLAGS) -I$(OUTDIR_$(TTYPE)) $(CPPFLAGS) $(F$(TTYPE)) -Fo$@ $<
+endef
+
+# define the default command for compiling .cpp files into .obj files.
+# Some target types will redefine this command.
+#
+# %.obj :  %.cpp
+define cpp-obj-command
+    $(CC) -c $(C$(TTYPE)FLAGS) -I$(OUTDIR_$(TTYPE)) $(CPPFLAGS) $(F$(TTYPE)) -Fo$@ $<
+endef
+
+# define the default command for compiling .asm files into .obj files.
+# Some target types will redefine this command.
+#
+# %.obj :  %.asm
+define asm-obj-command
+	$(AS) -c $(AFLAGS) $(CPPFLAGS) $(F$(TTYPE)) -Fo$@ $<
+endef
+
+# define the default command for compiling .rc files into .res files.
+# Some target types will redefine this command.
+#
+# %.res :  %.rc
+define rc-res-command
+	export INCLUDE="$(OUTDIR_$(TTYPE));$(MSINCLUDE)"; \
+	$(CMDSTART) $(RC) -r $(RCFLAGS) -fo$@ $<
+endef
+
+all ::
+	$(print-warnings)
+ifdef SHOWBUILDINFO
+	@echo " -------------------------------------------"
+	@echo " SRCFILE      = $(SRCFILE)"
+	@echo " SOURCES      = $(SOURCES)"
+	@echo " C_DEFINES    = $(C_DEFINES)"
+	@echo " WLTUNEFILE   = $(WLTUNEFILE)"
+	@echo " TARGETPATH   = $(TARGETPATH)"
+	@echo " TARGETTYPE   = $(TARGETTYPE)"
+	@echo " MAKE_VERSION = $(MAKE_VERSION)"
+	@echo " TTYPE        = $(subst OPT,OPT(free),$(subst DBG,DBG(checked),$(TTYPE)))"
+	@echo " -------------------------------------------"
+endif # SHOWBUILDINFO
+
+all ::
+	$(print-errors)
+
+include $(SRCBASE)/branding.inc
+
+ifeq ($(origin USEBCMUIO), undefined)
+#if defined(USEBCMUIO)
+USEBCMUIO=1
+#else
+# undefine USEBCMUIO
+USEBCMUIO=
+#endif
+endif
+
+BIN_OPT=retail
+BIN_DBG=debug
+BUILDENV_OPT=free
+BUILDENV_DBG=checked
+MSVSBUILDENV_OPT=Release
+MSVSBUILDENV_DBG=Debug
+OUTDIR_OPT = $(TARGETPATH)/free
+OUTDIR_DBG = $(TARGETPATH)/checked
+
+OUTDIR_FREE = $(OUTDIR_OPT)
+OUTDIR_CHECKED = $(OUTDIR_DBG)
+
+
+CC  = cl
+AS  = ml
+RC  = rc
+MC  = mc
+LD  = link
+LIBCMD = lib
+MTL = midl
+
+# Ignore any include path and lib paths that the user imports from
+# the environment.
+#
+INCLUDE =
+
+ifeq ($(origin TARGETPATH), undefined)
+    TARGETPATH=.
+endif
+TARGETPATH := $(subst \,/,$(TARGETPATH))
+
+DDKBUILDENV := $(BUILDENV_$(TTYPE))
+MSVSBUILDENV := $(MSVSBUILDENV_$(TTYPE))
+BIN         := $(BIN_$(TTYPE))
+MC_FLAGS = -v
+
+### assume sources as entry point
+ifndef SRCFILE
+	SRCFILE=./sources
+endif
+
+include $(SRCFILE)
+SRCRULES=$(SRCFILE).mk
+
+ifeq ($(findstring $(TARGETTYPE), "EXE DRIVER LIB DLL DLL16 EXE16 DYNLINK DOSEXE PROGRAM DUMMY"), )
+	ERRORS += "TARGETTYPE is not defined or not recognized!"
+	ERRORS += "This variable must be defined with a recognized value"
+	ERRORS += "in your sources or GNUsources file."
+endif
+
+# include any branding defined if they exist in the environment
+ifneq ($(BRAND),)
+    C_DEFINES += -DBRAND="'$(BRAND)'"
+endif # BRAND
+
+SOURCES.IDL	:= $(filter %.idl,$(SOURCES))
+SOURCES.TLB	:= $(patsubst %.idl,%.tlb,$(SOURCES.IDL))
+SOURCES._IC     := $(patsubst %.idl,%_i.c,$(SOURCES.IDL))
+
+SOURCES.OBJ	:= $(SOURCES)
+SOURCES.OBJ	:= $(patsubst %.cpp,%.obj,$(SOURCES.OBJ))
+SOURCES.OBJ	:= $(patsubst %.CPP,%.obj,$(SOURCES.OBJ))
+SOURCES.OBJ	:= $(patsubst %.asm,%.obj,$(SOURCES.OBJ))
+SOURCES.OBJ	:= $(patsubst %.ASM,%.obj,$(SOURCES.OBJ))
+SOURCES.OBJ	:= $(patsubst %.c,%.obj,$(SOURCES.OBJ))
+SOURCES.OBJ	:= $(patsubst %.C,%.obj,$(SOURCES.OBJ))
+SOURCES.OBJ	:= $(filter %.obj,$(SOURCES.OBJ))
+# SOURCES.OBJ	:= $(notdir $(SOURCES.OBJ))
+SOURCES.OBJ	:= $(subst /,_,$(SOURCES.OBJ))
+
+SOURCES.RES	:= $(patsubst %.rc,%.res,$(filter %.rc,$(SOURCES)))
+SOURCES.MSG	:= $(patsubst %.mc,%.h,$(filter %.mc,$(SOURCES)))
+
+vpath %.rc 	.:..:../..
+
+
+ifdef USE_DEPENDENCIES
+
+# MAKECMDGOALS is not supported until gnumake version 3.76 so we hack
+# it by explicitly setting MAKECMDGOALS in the clean rule at the top
+# of this file.
+#
+ifneq ($(MAKECMDGOALS),clean)
+
+# BUG -- BUG -- BUG
+# This code assumes that files are still unique without the extension.
+# So no foo.c and foo.cpp in the same makefile.
+
+SOURCES.D       :=  $(SOURCES)
+SOURCES.D       :=  $(patsubst %.c,%.d,$(SOURCES.D))
+SOURCES.D       :=  $(patsubst %.C,%.d,$(SOURCES.D))
+SOURCES.D       :=  $(patsubst %.cpp,%.d,$(SOURCES.D))
+SOURCES.D       :=  $(patsubst %.CPP,%.d,$(SOURCES.D))
+SOURCES.D       :=  $(filter %.d,$(SOURCES.D))
+
+endif  # MAKECMDGOALS != clean
+
+endif  # ifdef USE_DEPENDENCIES
+
+SI_FLAGS = -translate:always,source,package
+
+
+
+# Target all just depends upon our target file.
+all :: target post-build-target
+
+# The target file depends upon the directory where it will reside.
+target :: $(OUTDIR_$(TTYPE))/NUL
+
+WLCFGDIR        ?= $(SRCBASE)/wl/config
+WLTUNEFILE      ?= wltunable_sample.h
+
+# Create target directory if necessary.
+$(OUTDIR_$(TTYPE))/NUL :
+	[ -d "$(@D)" ] || mkdir -p $(@D)
+ifeq ($(WLCONF_GEN),true)
+	@if [ ! -f "$(@D)/wlconf.h" ]; then \
+	    cp -v $(WLCFGDIR)/$(WLTUNEFILE) $(@D)/wlconf.h; \
+	elif ! diff -q $(WLCFGDIR)/$(WLTUNEFILE) $(@D)/wlconf.h; then \
+	    cp -v $(WLCFGDIR)/$(WLTUNEFILE) $(@D)/wlconf.h; \
+	fi
+endif
+
+#
+# If the sources file specified a NTTARGETFILE0, build that first.
+#
+target :: $(NTTARGETFILE0)
+
+
+# calculate some dynamic variables that are useful in build rules.
+#
+DEPS_OBJ = $(patsubst %,$(OUTDIR_$(TTYPE))/%,$(SOURCES.OBJ))
+DEPS_RES = $(patsubst %,$(OUTDIR_$(TTYPE))/%,$(SOURCES.RES))
+DEPS_TLB = $(patsubst %,$(OUTDIR_$(TTYPE))/%,$(SOURCES.TLB))
+DEPS_MSG = $(patsubst %,$(OUTDIR_$(TTYPE))/%,$(SOURCES.MSG))
+# Finally generate DEPENDENCIES list that are made as explicit dependencies
+# in src/makefile/<obj-type>.mk file
+DEPENDENCIES =    $(DEPS_TLB) $(DEPS_MSG) $(DEPS_OBJ) $(DEPS_RES)
+DOS_DEPS= $(shell echo $(filter-out %.tlb %.TLB %.h %.H %.def %.DEF,$^) | sed 's%//\(.\)/%\1:/%g')
+
+
+$(OUTDIR_$(TTYPE))/%.i :  %.c
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(CC) -E -P $(C$(TTYPE)FLAGS) $(CPPFLAGS) $(F$(TTYPE)) $< >$@
+
+$(OUTDIR_$(TTYPE))/%.i :  %.cpp
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(CC) -E -P $(C$(TTYPE)FLAGS) $(CPPFLAGS) $(F$(TTYPE)) $< >$@
+
+$(OUTDIR_$(TTYPE))/%.d :  %.c
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(calculate_dependencies)
+
+$(OUTDIR_$(TTYPE))/%.d :  %.C
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(calculate_dependencies)
+
+$(OUTDIR_$(TTYPE))/%.d :  %.cpp
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(calculate_dependencies)
+
+$(OUTDIR_$(TTYPE))/%.d :  %.CPP
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(calculate_dependencies)
+
+$(OUTDIR_$(TTYPE))/%.obj :  %.c
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(c-obj-command)
+
+$(OUTDIR_$(TTYPE))/%.obj :  $(OUTDIR_$(TTYPE))/%.c
+	@echo "Compiling $(notdir $<) -> $(OUTDIR_$(TTYPE))/$(notdir $@)"
+	$(c-obj-command)
+
+$(OUTDIR_$(TTYPE))/%.obj :  %.C
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(c-obj-command)
+
+$(OUTDIR_$(TTYPE))/%.obj :  %.cpp
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(cpp-obj-command)
+
+$(OUTDIR_$(TTYPE))/%.obj :  %.CPP
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(cpp-obj-command)
+
+ifdef ECLOUD_BUILD_ID
+$(OUTDIR_$(TTYPE))/%.res :  RC = rc
+endif # ECLOUD_BUILD_ID
+
+$(OUTDIR_$(TTYPE))/%.res :  %.rc
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(rc-res-command)
+
+# build rule for IDL files.
+$(OUTDIR_$(TTYPE))/%.tlb $(OUTDIR_$(TTYPE))/%.h $(OUTDIR_$(TTYPE))/%_i.c : %.idl
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(MTL) /I $(MSSDK)/include /nologo /Oicf /out $(OUTDIR_$(TTYPE)) $<
+
+# Build rule for message file
+$(OUTDIR_$(TTYPE))/%.rc $(OUTDIR_$(TTYPE))/%.h : %.mc
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(MC) -h $(OUTDIR_$(TTYPE)) -r $(OUTDIR_$(TTYPE)) $(MC_FLAGS) $<
+
+$(OUTDIR_$(TTYPE))/%.obj: %.asm
+	@echo "Compiling $(notdir $<) -> $(notdir $@)"
+	$(asm-obj-command)
+
+FORCE:
+
+clean ::
+	rm -rf $(OUTDIR_CHECKED) $(OUTDIR_FREE) $(SRCRULES)
+
+
+ifeq  ("$(TARGETTYPE)", "DRIVER")
+ifeq  ("$(DRIVERTYPE)", "WDM")
+include $(SRCBASE)/makefiles/wdm.mk
+else
+ifeq  ("$(DRIVERTYPE)", "WDM2600")
+    include $(SRCBASE)/makefiles/wdm2600.mk
+else
+    include $(SRCBASE)/makefiles/driver.mk
+endif
+endif
+endif
+
+ifneq ($(findstring x$(TARGETTYPE)x, "xDLLx xDYNLINKx"), )
+ifneq ($(findstring x$(HOSTOS)x, "xwincex"), )
+include $(SRCBASE)/makefiles/dllce.mk
+else
+include $(SRCBASE)/makefiles/dll.mk
+endif
+endif
+
+ifneq ($(findstring $(TARGETTYPE)x, "DLL16x"), )
+include $(SRCBASE)/makefiles/dll16.mk
+endif
+
+ifneq ($(findstring $(TARGETTYPE)x, "EXE16x"), )
+include $(SRCBASE)/makefiles/exe16.mk
+endif
+
+ifneq ($(findstring $(TARGETTYPE), "LIB"), )
+ifneq ($(findstring x$(HOSTOS)x, "xwincex"), )
+include $(SRCBASE)/makefiles/libce.mk
+else
+include $(SRCBASE)/makefiles/lib.mk
+endif
+endif
+
+ifneq ($(findstring $(TARGETTYPE), "xEXEx xPROGRAMx"), )
+ifneq ($(findstring x$(HOSTOS)x, "xwincex"), )
+include $(SRCBASE)/makefiles/exece.mk
+else
+include $(SRCBASE)/makefiles/exe.mk
+endif
+endif
+
+ifneq ($(findstring x$(TARGETTYPE)x, "xDOSEXEx"), )
+include $(SRCBASE)/makefiles/dosexe.mk
+endif
+
+ifneq ($(findstring $(TARGETTYPE), "DUMMY"), )
+include $(SRCBASE)/makefiles/dummy.mk
+endif
+
+# Set make variables that help find things like DDK's, SDK's, etc,
+# depending upon the requirements expressed in the individual
+# makefile(s).
+include $(SRCBASE)/makefiles/env.mk
+
+#
+# Add some rules so that our target depends on any libraries we are going
+# to link against.
+#
+#target :: $(LIBS)
+
+
+target :: $(OUTDIR_$(TTYPE))/$(TARGET)
+
+ifneq ($(wildcard ./makefile.inc), )
+include .\makefile.inc
+endif
+
+
+#
+# If the sources file specified a NTTARGETFILES, build that last.
+#
+
+target :: $(NTTARGETFILES)
+
+
+target ::
+	@echo Finished compiling $@
+	@echo ""
+
+post-build-target ::
+
+release: all
+
+.PHONY: all target release clean $(OUTDIR_$(TTYPE))/.depends
+
+ifneq ($(wildcard $(SRCRULES)), )
+include $(SRCRULES)
+endif
+
+# only try to do dependency checking if we have some dependencies to check!
+#
+# It seems counter-intiutive but it looks like the
+# include dependencies are evaluated in reverse order from their
+# appearance in the makefile.  Therefore we include the NUL file from
+# the object directory *after* we include the dependency files
+# themselves.  This results in the object directory getting created
+# before we build any of the dependency files.
+#
+ifneq ($(strip $(SOURCES.D)),)
+include $(patsubst %,$(OUTDIR_$(TTYPE))/%,$(SOURCES.D))
+include $(OUTDIR_$(TTYPE))/NUL
+endif
+
+define calculate_dependencies
+	@ echo making $@
+	$(SHELL) -ec 'gcc -MM -w -D_M_IX86=500 $(C_DEFINES) $(CPPFLAGS) $< \
+	| sed '\''s?$*\.o[ :]*?$@ &?g'\'' >$@'
+endef
+
+ifdef OTHER_SOURCES
+all clean :: $(OTHER_SOURCES)
+	@echo "Go through OTHER_SOURCES: $(OTHER_SOURCES)"
+	$(foreach SRCFILE,$(OTHER_SOURCES),$(MAKE) SRCFILE=$(SRCFILE) TTYPE=$(TTYPE) $@; )
+endif
+
+vpath %.Lib $(LIBVPATH)
+vpath %.LIB $(LIBVPATH)
+vpath %.lib $(LIBVPATH)
+
+export PATH:=$(subst $(space),:,$(strip $(NEWPATH))):$(PATH)
+
+foo:
+	@echo _SDKROOT=$(_SDKROOT)
+	@echo NEWPATH=$(NEWPATH)
+
+endif
+###  end of ifeq ($(origin TTYPE), undefined)
+
+printenv:
+	env
+
+ifdef WARNING
+define print-warnings
+@echo "Warning **** Warning **** Warning **** Warning **** Warning"
+@for warn in $(WARNING) ; do echo $$warn; done
+@echo "Continuing..."
+endef
+endif # WARNING
+
+ifdef ERRORS
+define print-errors
+@echo "Error **** Error **** Error **** Error **** Error"
+@for err in $(ERRORS) ; do echo $$err; done
+@echo "Exiting makefile."
+@exit 1
+endef
+endif # ERRORS
diff --git a/src/Makerules b/src/Makerules
new file mode 100644
index 0000000..19c8789
--- /dev/null
+++ b/src/Makerules
@@ -0,0 +1,604 @@
+#
+#  Top level Makerules
+#  it uses Makerules.env for build env vars and optional branding.inc
+#
+#  $ Copyright Open Broadcom Corporation $
+#
+# $Id: Makerules 444746 2013-12-20 20:22:37Z $
+
+# This is the TOP level makefile rules, which is used by many makefiles.
+# Please be cautious on changes, especially compatibilities.
+#   e.g. new gcc compile option should be protected with version check 
+#        or "check_gcc" trick
+
+# first rule (default)
+all:
+
+WLAN_ComponentsInUse ?= bcmwifi
+include $(dir $(lastword $(MAKEFILE_LIST)))makefiles/WLAN_Common.mk
+
+# Set up the build environment variables
+include ${SRCBASE}/Makerules.env
+
+ifeq ($(HOSTOS), Windows_NT)
+
+# force use of bash, otherwise you will get the broken sh.exe.
+SHELL=bash
+
+endif
+
+#
+# Setup make variables depending on target
+#
+
+ifeq ($(TARGETOS), unix)
+
+	# The environment for native unix builds
+
+	EXEEXT	= 
+	OBJEXT	= .o
+	GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_ComponentIncPath)) $(WLAN_StdIncPathA)
+	GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) -DTARGETARCH_$(TARGETARCH)
+
+	ifeq ($(TARGETARCH), x86_mmx)
+		GCDEFS	:= $(GCDEFS) -D_X86_ -D_MMX_
+	endif
+	ifeq ($(TARGETARCH), x86)
+		GCDEFS	:= $(GCDEFS) -D_X86_
+	endif
+	ifeq ($(TARGETARCH), x86_android_ndk_r6b)
+		GCDEFS	:= $(GCDEFS) -D_X86_
+	endif
+	ifeq ($(TARGETARCH), mips)
+		GCDEFS	:= $(GCDEFS) -D_MIPS_
+	endif
+	ifeq ($(TARGETARCH), mips_be)
+		GCDEFS	:= $(GCDEFS) -D_MIPS_ -DIL_BIGENDIAN
+	endif
+	ifeq ($(TARGETARCH), arm)
+		GCDEFS	:= $(GCDEFS) -D_ARM_ -DIL_BIGENDIAN
+	endif
+	ifeq ($(TARGETARCH), arm_le)
+		GCDEFS	:= $(GCDEFS) -D_ARM_
+	endif
+	ifeq ($(TARGETARCH), arm_android)
+		GCDEFS	:= $(GCDEFS) -D_ARM_
+	endif
+	ifeq ($(TARGETARCH), arm_android_ndk_r6b)
+		GCDEFS	:= $(GCDEFS) -D_ARM_
+	endif
+
+	ifeq ($(TARGETENV), freebsd)
+		GCINCS	:= $(GCINCS) -I/usr/pkg/include -I/usr/include
+	endif
+	ifeq ($(TARGETENV), sun4)
+		GCDEFS	:= $(GCDEFS) -D_SPARC_
+	endif
+	ifeq ($(TARGETENV), macos)
+		MACOS_VER := $(shell sw_vers -productVersion)
+
+		ifneq (,$(findstring 10.9,$(MACOS_VER)))
+			SDK=/Applications/Xcode.app/Contents/Developer/SDKs/MacOSX10.9.sdk
+		else
+		ifneq (,$(findstring 10.8,$(MACOS_VER)))
+			SDK=/Applications/Xcode.app/Contents/Developer/SDKs/MacOSX10.8.sdk
+		else
+		ifneq (,$(findstring 10.7,$(MACOS_VER)))
+			SDK=/Developer/SDKs/MacOSX10.7.sdk
+		else
+		ifneq (,$(findstring 10.6,$(MACOS_VER)))
+			SDK=/Developer/SDKs/MacOSX10.6.sdk
+		else
+		ifneq (,$(findstring 10.5,$(MACOS_VER)))
+			SDK=/Developer/SDKs/MacOSX10.5.sdk
+		else
+			SDK=/Developer/SDKs/MacOSX10.4u.sdk
+		endif
+		endif
+		endif
+		endif
+		endif
+
+		GCDEFS	:= $(GCDEFS) -DMACOSX
+		GCDEFS	:= $(GCDEFS) -pipe -fpascal-strings -fasm-blocks -fmessage-length=0
+		GCDEFS	:= $(GCDEFS) -fvisibility=hidden -isysroot $(SDK)
+
+		ifeq ($(TARGETARCH), PPC)
+			GCDEFS	:= $(GCDEFS) -arch ppc -mtune=G4
+			GLDFLAGS = -arch ppc -Wl,-syslibroot,$(SDK)
+		endif
+		ifeq ($(TARGETARCH), x86)
+			GCDEFS	:= $(GCDEFS) -arch x86_64
+			GLDFLAGS = -arch x86_64
+		endif
+	endif
+
+	GCOPTS	=
+	GCFLAGS	= -g -Wall
+
+	CC_TARGET	=-o $@
+	LINK_TARGET	=-o $@
+
+	ifeq ($(TARGETENV), linuxmips)
+		TARGET_PREFIX = mipsel-linux-
+	else
+	ifeq ($(TARGETENV), linuxmips_be)
+		TARGET_PREFIX = mips-linux-
+	else
+	ifeq ($(TARGETENV), linuxarm)
+		TARGET_PREFIX = armeb-linux-
+	else
+	ifeq ($(TARGETENV), linuxarm_le)
+		TARGET_PREFIX = arm-linux-
+	else
+	ifeq ($(TARGETENV), android)
+		TARGET_PREFIX = arm-eabi-
+		GCFLAGS += -Dlinux
+		GCFLAGS += -I/projects/hnd/tools/linux/hndtools-arm-eabi-4.2.1/android-ndk-r3/build/platforms/android-3/arch-arm/usr/include
+#		GCFLAGS += -I/projects/hnd/tools/linux/hndtools-arm-eabi-4.2.1/arm-eabi/include/bionic/libc/include
+#		GCFLAGS += -I/projects/hnd/tools/linux/hndtools-arm-eabi-4.2.1/arm-eabi/include/bionic/libc/arch-arm/include/
+		GCFLAGS += -I/tools/linux/src/linux-2.6.25-01843-gfea26b0/include/
+	else
+	ifeq ($(TARGETENV), android_ndk_r6b)
+		#TARGET_PREFIX = arm-linux-androideabi-
+
+		ifeq ($(TARGET_PREFIX),)
+$(warning : TARGET_PREFIX is not set!)
+		endif
+		ifeq ($(TARGET_NDK),)
+$(warning : TARGET_NDK is not set!)
+		endif
+		ifeq ($(LINUXDIR),)
+$(warning : LINUXDIR is not set!)
+		endif
+		GCDEFS	:= $(GCDEFS) -fno-short-enums
+
+		GCFLAGS += -Dlinux -DTARGETENV_android
+		ifeq ($(TARGETARCH), arm_android_ndk_r6b)
+			GCFLAGS += -DTARGETARCH_arm_android
+			GCFLAGS += -I$(TARGET_NDK)/platforms/android-9/arch-arm/usr/include/
+			GCFLAGS += -march=armv5te -mtune=xscale -msoft-float
+			GCFLAGS += -mthumb-interwork
+		else
+		ifeq ($(TARGETARCH), x86_android_ndk_r6b)
+			GCFLAGS += -DTARGETARCH_x86_android
+			GCFLAGS += -I$(TARGET_NDK)/platforms/android-9/arch-x86/usr/include/
+			GCFLAGS += -march=i686
+		endif
+		endif
+		GCFLAGS += -fpic -fno-exceptions
+		GCFLAGS += -ffunction-sections -funwind-tables
+		GCFLAGS += -fstack-protector -fmessage-length=0
+		GCFLAGS += -I$(LINUXDIR)/include/
+	else
+		TARGET_PREFIX =
+	endif
+	endif
+	endif
+	endif
+	endif
+	endif
+
+	CC = $(TARGET_PREFIX)gcc
+	AS = $(TARGET_PREFIX)as
+	LD = $(TARGET_PREFIX)ld
+	AR = $(TARGET_PREFIX)ar
+
+	INSTALL = install -c
+
+	TCFLAGS =
+
+	ifeq ($(TARGETENV), freebsd)
+		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), linuxarm)
+		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), linuxarm_le)
+#		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), android)
+		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), android_ndk_r6b)
+		GLDFLAGS = -Bdynamic -Wl,-dynamic-linker,/system/bin/linker
+		GLDFLAGS += -lm -lc -ldl
+		GLDFLAGS += -nostdlib
+		GLDFLAGS += -Wl,--gc-sections -Wl,-z,nocopyreloc
+		GLDFLAGS += -Wl,--no-undefined
+		ifeq ($(TARGETARCH), arm_android_ndk_r6b)
+			GLDFLAGS += -ldl
+			GLDFLAGS += -Wl,-T,$(TARGET_NDK)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x
+			GLDFLAGS += -Wl,-rpath-link=$(TARGET_NDK)/platforms/android-9/arch-arm
+			GLDFLAGS += -L$(TARGET_NDK)/platforms/android-9/arch-arm/usr/lib
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-arm/usr/lib/crtend_android.o
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-arm/usr/lib/crtbegin_dynamic.o
+			GLDFLAGS += $(TARGET_NDK)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a
+		else
+		ifeq ($(TARGETARCH), x86_android_ndk_r6b)
+			GLDFLAGS += -m32 -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now
+			GLDFLAGS += -Wl,-z,relro,-z,now -fPIE -pie
+			GLDFLAGS += -L$(TARGET_NDK)/platforms/android-9/arch-x86/usr/lib
+			GLDFLAGS += -Wl,-rpath-link=$(TARGET_NDK)/platforms/android-9/arch-x86
+			GLDFLAGS += -lstdc++
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-x86/usr/lib/crtbegin_dynamic.o
+			GLDFLAGS += -Wl,--whole-archive -Wl,--no-whole-archive
+			GLDFLAGS += $(TARGET_NDK)/toolchains/x86-4.4.3/prebuilt/linux-x86/lib/gcc/i686-android-linux/4.4.3/libgcc.a
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-x86/usr/lib/crtend_android.o
+		endif
+		endif
+	endif
+
+	GLDLIBS = -lgcc
+
+endif	# $(TARGETOS) == unix
+
+ifeq ($(TARGETOS), Windows_NT)
+
+	# The environment for windows builds
+
+	EXEEXT = .exe
+
+	ifeq ($(TARGETENV), win32)
+		# standard win32 using MS compiler
+		OBJEXT	= .obj
+		GCINCS	= $(strip /I$(SRCBASE)/include $(patsubst -I%,/I%,$(WLAN_StdIncPathA)) $(patsubst -I%,/I%,$(WLAN_ComponentIncPath)))
+		GCDEFS	= /DTARGETENV_$(TARGETENV) /DTARGETOS_$(TARGETOS) \
+			/DTARGETARCH_$(TARGETARCH) /D_X86_
+		ifeq ($(TARGETARCH), x86_mmx)
+			GCDEFS += /D_MMX_
+		endif
+		GCOPTS	= /nologo
+		GCFLAGS	= /GM /W3 /Z7
+
+		CC_TARGET	=-Fo$@
+		LINK_TARGET	=-out:$@
+
+		CC = cl
+		AS = cl
+		LD = cl
+
+		TCFLAGS =
+		GLDFLAGS = /nologo /link /nologo /INCREMENTAL:NO
+
+		GLDLIBS =
+	else
+		# cygwin32 based environment
+		OBJEXT	= .o
+		GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) $(WLAN_ComponentIncPath))
+		GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) \
+			-DTARGETARCH_$(TARGETARCH) -D_X86_
+		ifeq ($(TARGETARCH), x86_mmx)
+			GCDEFS += -D_MMX_
+		endif
+		GCOPTS	=
+		GCFLAGS	= -g -Wall
+
+		CC_TARGET	=-o $@
+		LINK_TARGET	=-o $@
+
+		CC = gcc
+		AS = gcc
+		LD = gcc
+		INSTALL = install -c
+
+		TCFLAGS =
+		GLDFLAGS =
+
+		GLDLIBS = -liberty -lgcc
+	endif
+
+	# Tools common to cygwin/win32
+
+	INSTALL = install -c
+	BUILD = build -ceZ
+
+	# RELEASE_TARGET is a the directory under RELEASE_DIR where
+	# target dependant files go. It is composed of the OS and
+	# the CPU, some examples are: winnt40/i386, win98 ...
+	#
+	# NEEDSWORK: For now only NT 4.0 stuff uses it.
+	ifneq ($(findstring $(TARGETPLATFORM), "Wdm wdm"), )
+		RELEASE_TARGET = wdm/i386
+	else
+		RELEASE_TARGET = winnt40/i386
+	endif
+
+	# RELEASE_TOOLS_DIR is a the directory under RELEASE_DIR where
+	# common tools go.
+	# For compatability with previous installs &test scripts, old
+	# tools still go in "yosemite".
+	RELEASE_YOS_DIR = yosemite
+	RELEASE_TOOLS_DIR = tools
+
+endif	# $(TARGETOS) == Windows_NT
+
+ifeq ($(TARGETOS), vxWorks)
+	WIND_REGISTRY = sol
+	ifndef WIND_BASE
+		ifeq ($(HOSTOS), unix)
+			WIND_BASE = /dfs/tools/vxWorks
+		else
+			WIND_BASE = $(WLAN_WINPFX)/tools/vxWorks
+		endif
+	endif
+	include $(WIND_BASE)/target/h/make/defs.default
+
+	ifeq ($(HOSTENV), Windows_NT)
+		WIND_HOST_TYPE = x86-win32
+	else
+		ifeq ($(HOSTENV), sun4)
+			WIND_HOST_TYPE = sun4-solaris2
+		else
+			WIND_HOST_TYPE = i386-freebsd
+		endif
+	endif
+
+	ifeq ($(TARGETENV), vxsim)
+		CPU = SIMSPARCSOLARIS
+	else
+		ifeq ($(TARGETENV), vx386)
+			CPU = i386
+		else
+			CPU = R4650
+			VXFLAGS  = -DCPU_VAR=$(CPU)
+		endif
+	endif
+
+	include $(WIND_BASE)/target/h/make/make.$(CPU)$(TOOL)
+	include $(WIND_BASE)/target/h/make/defs.$(WIND_HOST_TYPE)
+
+	GCINCS	= -I$(WIND_BASE)/target/h -I$(SRCBASE)/include $(WLAN_StdIncPathA)
+	GCDEFS	= $(DEFINE_CC) -DCPU=$(CPU) -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) -DTARGETARCH_$(TARGETARCH)
+	GCOPTS	= -g -O2
+	GCFLAGS	= -Wall $(CC_ARCH_SPEC)
+	LDFLAGS	= $(GLDFLAGS) $(LLDFLAGS)
+	GLDLIBS	= $(LIBS)
+
+	WIND_BIN = $(WIND_BASE)/host/$(WIND_HOST_TYPE)/bin
+
+	AR	:= $(WIND_BIN)/$(AR)
+	AS	:= $(WIND_BIN)/$(AS)
+	BINHEX	:= $(WIND_BIN)/$(BINHEX)
+	CC	:= $(WIND_BIN)/$(CC)
+	CF	:= $(WIND_BIN)/$(CF)
+	LD	:= $(CC)
+	NM	:= $(WIND_BIN)/$(NM)
+	RANLIB	:= $(WIND_BIN)/$(RANLIB)
+	BINXSYM_NAME := $(WIND_BIN)/$(BINXSYM)
+
+endif	# $(TARGETOS) == vxWorks
+
+ifeq ($(TARGETENV), nucleusarm)
+
+	# The environment for nucleus builds
+	ifeq ($(BSP_BASE_DIR),)
+		BSP_BASE_DIR := $(SRCBASE)/../bsp
+	endif
+   
+	ifeq ($(NUCLEUS_INC_DIR),)
+		NUCLEUS_INC_DIR := $(BSP_BASE_DIR)/rtos/nucleus/inc
+	endif
+
+	EXEEXT	:= 
+	OBJEXT	:= .o
+	GCINCS	:= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) -I$(NUCLEUS_INC_DIR) $(WLAN_ComponentIncPath))
+	GCDEFS	:= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) -DTARGETARCH_$(TARGETARCH)
+	GCOPTS	:=
+   
+	ifeq ($(OBJDIR),)
+		OBJDIR	:= $(TARGETENV)/
+	endif
+   
+	# --md:  This option compiles the source and writes make file dependency lines 
+	#        to a file. The output file is suitable for use by a make utility.
+	# -c:    Compiles but does not perform the link phase.
+	# -O2:   High optimization.
+	# ---memaccess -UL41: This option tells the compiler that the memory in the 
+	#        target system has slightly restricted or expanded capabilities.
+	#        Disables unaligned mode for code that uses pre-ARMv6 unaligned 
+	#        access behavior.
+	# "/adsabi" is added to "--apcs /interwork/$(SWST)" so that objects created
+	#	under ADS 1.2 can be linked with objects compiled under RVCT 2.2.
+	# --diag_suppress 2084,1658 = blocks the diagnostic warning "Warning: C2084W: support for --apcs /adsabi is deprecated"
+	#                 1293: Suppress "assignment in condition" warning.
+	#                  550: Suppress "variable set but never used" warning.
+	GCFLAGS	:= --md \
+			-c \
+			-O2 \
+			--memaccess -UL41 \
+			--apcs /adsabi/interwork/NOSWST \
+			--diag_suppress 2084,1658,1293,550 \
+			--li
+
+	# --cpu 'name': This option generates code for a specific ARM processor or architecture.
+	ifeq ($(TARGETCPU),2153)
+		GCFLAGS += --cpu ARM1136J-S
+	else
+      $(error "Unknown target CPU type!")
+	endif
+
+	#CPPFLAGS	:= -embeddedcplusplus
+
+	CC_TARGET	=-o $@
+	CPP_TARGET	=-o $@
+	LINK_TARGET	=-o $@
+
+	CC := tcc
+	CPP := tcpp
+	AS := armasm
+	LD := armlink
+	AR := armar -c -r --create
+
+	INSTALL := install -c
+
+	TCFLAGS :=
+
+	GLDFLAGS := 
+	GLDLIBS := --ELF --symbols --debug --map --info sizes,totals --errors link.err --list link.map --verbose
+
+	# Convert windows style directories to cygwin style.
+	# It should be used in situations where the host environment is cygwin, and
+	# the host compiler is a native Win32 app (non-cygwin). It will convert the 
+	# Windows style directories in the dependencies list to cygwin style. This is
+	# necessary for the dependency files to be included by cygwin make.
+	ifeq ($(HOSTOS),Windows_NT)
+		FILTER_DEPENDS_IN_C_TO_OBJ_RULE := 1
+	endif
+
+endif	# $(TARGETENV) == nucleusarm
+
+ifeq	($(TARGETENV), bcmmips)
+
+	OBJEXT	= .o
+	GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) $(WLAN_ComponentIncPath))
+	GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) \
+		-DTARGETARCH_$(TARGETARCH) -D__mips__
+	GCOPTS	= -g -O2
+	GCFLAGS	= -Wall 
+	GLDFLAGS = -Wl,-tidt.dld
+
+	AS		= bcmas
+	CC		= bcmgcc
+	LD		= $(CC)
+	NM		= bcmnm
+	RANLIB		= bcmranlib
+
+endif	# $(TARGETENV) == bcmmips
+
+ifeq	($(TARGETENV), klsi)
+
+	OBJEXT	= .obj
+	GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) $(WLAN_ComponentIncPath))
+	GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) \
+		-DTARGETARCH_$(TARGETARCH) -D__klsi__
+
+	AS		= qtasm
+	GASFLAGS	= -m20
+	CC		= qtcc
+	TCFLAGS		= -w asm=$(GASFLAGS) +c -Vcdv -w cc=+reginfo
+
+endif	# $(TARGETENV) == klsi
+
+CFLAGS = $(LCINCS) $(GCINCS) $(GCDEFS) $(GCOPTS) $(GCFLAGS) $(TCFLAGS) $(HCFLAGS) \
+$(LCDEFS) $(LCOPTS) $(LCFLAGS) $(CENV)
+
+ASFLAGS	= $(GASFLAGS) $(LASFLAGS) $(ASENV)
+LDFLAGS	= $(GLDFLAGS) $(LLDFLAGS) $(LDENV)
+LDLIBS	= $(LLDLIBS) $(GLDLIBS)
+
+# dependency files including the .d file itself.
+# note the example in GNU documentation seems to have a bug:
+# two backslashes where one is correct.
+%.d: %.c
+ifeq ($(findstring s, $(MAKEFLAGS) ),)
+	@ echo making $@
+endif
+	@ $(SHELL) -ec '$(CC) -MM $(CFLAGS) $(CPPFLAGS) $< \
+	| sed '\''s/$*\.o[ :]*/$@ &/g'\'' >$@'
+
+ifeq ($(TARGETENV), win32)
+
+# win32 needs different command line args 
+
+%.s: %.c
+	$(CC) /FAs $(CFLAGS) $(CPPFLAGS) /Fa$@ /c $<
+
+%.i: %.c
+	$(CC) /E $(CFLAGS) $(CPPFLAGS) $< > $@
+
+else # !win32
+
+%.s: %.c
+	$(CC) -S $(CFLAGS) $(CPPFLAGS) -o $@ $<
+
+%.i: %.c
+	$(CC) -o $@ -E -dD $(CFLAGS) $(CPPFLAGS) $<
+
+endif # win32
+
+ifeq	($(TARGETENV), klsi)
+
+%$(OBJEXT): %.c
+	$(CC) $(CFLAGS) $*.c
+
+%$(OBJEXT): %.asm
+	$(AS) $(ASFLAGS) $*.asm
+
+%.asm: %.c
+	$(CC) $(CFLAGS) -asm $*.c
+
+%.i: %.c
+	$(CC) $(CFLAGS) -cc -peep -asm $*.c
+	mv $*.pp $*.i
+
+else
+
+
+# This command sequence will:
+#  - Convert back-slashes to foward-slashes
+#  - Convert long filenames to 8.3 format (e.g. Program Files --> PROGRA~1)
+#  - Convert windows-style drive letters to cygwin style.
+#
+# It should be used in situations where the host environment is cygwin, and
+# the host compiler is a native Win32 app (non-cygwin). It will convert the 
+# Windows style directories in the dependencies list to cygwin style. This is
+# necessary for the dependency files to be included by cygwin make.
+define FILTER_DEPENDS
+	sed -e 's/\\/\//g'		\
+		-e 's/Program Files/PROGRA~1/g'	\
+		-e 's/\([A-Za-z]\):\//\/cygdrive\/\1\//' < $(notdir $(@:.o=.d)) > $(@:.o=.d) && \
+	rm -f $(notdir $(@:.o=.d))
+endef
+
+
+$(OBJDIR)%$(OBJEXT): %.c
+	$(CC) -c $(CFLAGS) $(CPPFLAGS) $(CC_TARGET) $<
+ifeq ($(FILTER_DEPENDS_IN_C_TO_OBJ_RULE),1)
+	${FILTER_DEPENDS}
+endif   
+
+$(OBJDIR)%$(OBJEXT): %.cpp
+	$(CPP) -c $(CFLAGS) $(CPPFLAGS) $(CPP_TARGET) $<
+ifeq ($(FILTER_DEPENDS_IN_C_TO_OBJ_RULE),1)
+	${FILTER_DEPENDS}
+endif   
+
+
+endif # klsi
+
+%.h: %.x
+	rpcgen -C -h $< > $@
+
+%_xdr.c: %.x
+	@ (if [ ! -f `basename $<` ] ; then ln -s $< . ; fi; true)
+	rpcgen -C -c -i 0 `basename $<` > $@
+
+# Makefile debugging rule
+env:
+	printenv
+
+# if the user mistakenly specified RELEASE_DIR in unix-style notation,
+# convert it to Win32 notation for them.
+#
+# RELEASE_DIR is assumed to be in windows-style notation if it has both 
+# backslashes ('\') and colons (':').
+#
+
+ifneq  ("$(subst \,,$(RELEASE_DIR))", "$(RELEASE_DIR)")
+ifneq  ("$(subst :,,$(RELEASE_DIR))", "$(RELEASE_DIR)")
+RELEASE_DIR := $(subst :,,$(RELEASE_DIR))
+RELEASE_DIR := $(subst \,/,$(RELEASE_DIR))
+RELEASE_DIR := //$(RELEASE_DIR)
+endif
+endif
+
+# all release rules depend on a valid RELEASE_DIR
+release: check_release_dir
+check_release_dir:
+	@if [ "x$(RELEASE_DIR)" = "x" ]; then \
+		echo "RELEASE_DIR is not set!"; \
+		exit 1; \
+	fi;
+
+include ${SRCBASE}/branding.inc
diff --git a/src/Makerules.env b/src/Makerules.env
new file mode 100644
index 0000000..a50f101
--- /dev/null
+++ b/src/Makerules.env
@@ -0,0 +1,139 @@
+#*******************************************************************************
+# $Id: Makerules.env 389557 2013-03-07 02:50:19Z $
+# Top-level Makerules for defining environment variables
+# can be included by anyone doing software at Epigram
+#*******************************************************************************
+
+# HOSTOS is either unix or Windows_NT.
+# HOSTENV differentiates HOSTOS and is either freebsd, sun4, or Windows_NT.
+# This refers to the *BUILD* environment. All environments use "GNU C" 
+# except Windows_NT which may use "GNU C" or "Microsoft C".
+
+ifndef	HOSTENV
+    # Figure what type of host we are in. 
+    UNAME = $(shell uname)
+
+    ifneq ($(findstring "$(UNAME)", "FreeBSD" "NetBSD"), )
+	HOSTENV = freebsd
+	HOSTOS = unix
+    else
+	ifneq ($(findstring "$(UNAME)", "sun4" "SunOS"), )
+	    HOSTENV = sun4
+	    HOSTOS = unix
+	else
+	    ifeq ($(UNAME), Linux)
+		HOSTENV = linux
+		HOSTOS = unix
+	    else
+		ifneq ($(findstring CYGWIN,$(UNAME)),)
+		    HOSTENV = Windows_NT
+		    HOSTOS = Windows_NT
+		else
+		    ifeq ($(UNAME), Darwin)
+			HOSTENV = macos
+			HOSTOS = unix
+		    else	
+		    	HOSTENV = unknown
+		    	HOSTOS = unknown
+		    endif
+		endif
+	    endif
+	endif
+    endif
+endif
+# In case we just defined them, make sure they are known
+export HOSTENV
+export HOSTOS
+	
+# TARGETENV is one of freebsd, sun4, linux, linuxarm, android, android_ndk_r6b, linuxmips, linuxmips_be, cygwin32, win32, or macos
+# TARGETENV defaults to HOSTENV unless HOSTENV is Windows_NT, in
+# which case it defaults to win32.
+
+ifndef	TARGETENV
+    ifeq ($(HOSTENV), Windows_NT)
+	TARGETENV = win32
+    else
+        TARGETENV = $(HOSTENV)
+    endif
+endif
+export TARGETENV
+
+# TARGETOS defaults to HOSTOS in most cases
+ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "linuxarm" "linuxarm_le" "android" "android_ndk_r6b" "linuxmips" "linuxmips_be" "sun4" "cygwin32" "win32" "macos"), )
+    TARGETOS = $(HOSTOS)
+endif
+ifeq	($(TARGETENV), bcmmips)
+    TARGETOS = bcmmips
+endif
+ifeq	($(TARGETENV), klsi)
+    TARGETOS = klsi
+endif
+ifeq	($(TARGETENV), nucleusarm)
+    TARGETOS = nucleus
+endif
+ifndef TARGETOS
+    TARGETOS = unknown
+endif
+export TARGETOS
+
+# TARGETARCH is the target processor architecture
+# Currently valid values are: x86, x86_mmx, sparc, unknown, or a list of any
+# of the valid values.
+# For the x86* family, a generic x86 is assuemd if not otherwise specified
+# Order is important since "linux" matches both linuxmips and linux.
+ifndef TARGETARCH
+    ifneq ($(findstring "$(TARGETENV)", "android"), )
+	TARGETARCH = arm_android
+    endif
+
+    ifneq ($(findstring "$(TARGETENV)", "android_ndk_r6b"), )
+	TARGETARCH = arm_android_ndk_r6b
+    endif
+
+    ifneq ($(findstring "$(TARGETENV)", "linuxarm_le"), )
+	TARGETARCH = arm_le
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "linuxarm nucleusarm"), )
+	TARGETARCH = arm
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "bcmmips" "linuxmips" "linuxmips_be"), )
+	TARGETARCH = mips
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "sun4"), )
+	TARGETARCH = sparc
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "cygwin32" "win32"), )
+	TARGETCPU = $(shell uname -m)
+	ifneq ($(findstring "$(TARGETCPU)", "sparc" "sparc64"), )
+		TARGETARCH = $(TARGETCPU)
+	else
+		TARGETARCH = x86_mmx
+	endif
+    endif
+    ifeq	($(TARGETENV), macos)
+	TARGETCPU = $(shell uname -p)
+	ifneq ($(findstring "$(TARGETCPU)", "powerpc"), )
+		TARGETARCH = PPC
+	else
+		TARGETARCH = x86
+	endif
+    endif
+    ifeq	($(TARGETENV), klsi)
+	TARGETARCH = klsi
+    endif
+    ifndef TARGETARCH
+	TARGETARCH = unknown
+    endif
+endif
+export TARGETARCH
+
+# TARGET_TYPE is either "all" or one or more of: float64, float32, int16
+# default is int16.  "all" will get expanded into a list of all possible types
+ifndef  TARGET_TYPE
+	TARGET_TYPE = int16
+endif
+        
+ifeq ($(TARGET_TYPE), all)
+	TARGET_TYPE = int16 float32 float64
+endif
+export TARGET_TYPE
diff --git a/src/branding.inc b/src/branding.inc
new file mode 100644
index 0000000..88d6d05
--- /dev/null
+++ b/src/branding.inc
@@ -0,0 +1,5 @@
+# $ Copyright Open Broadcom Corporation $
+#  
+BRAND=
+
+export RELAY_FILE_BASE=bcm42rly
diff --git a/src/common/include/devctrl_if/wlioctl_defs.h b/src/common/include/devctrl_if/wlioctl_defs.h
new file mode 100644
index 0000000..d75ac18
--- /dev/null
+++ b/src/common/include/devctrl_if/wlioctl_defs.h
@@ -0,0 +1,2032 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: wlioctl_defs.h 403826 2013-05-22 16:40:55Z $
+ */
+
+
+#ifndef wlioctl_defs_h
+#define wlioctl_defs_h
+
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+
+
+/* All builds use the new 11ac ratespec/chanspec */
+#undef  D11AC_IOTYPES
+#define D11AC_IOTYPES
+
+/* WL_RSPEC defines for rate information */
+#define WL_RSPEC_RATE_MASK      0x000000FF      /* rate or HT MCS value */
+#define WL_RSPEC_VHT_MCS_MASK   0x0000000F      /* VHT MCS value */
+#define WL_RSPEC_VHT_NSS_MASK   0x000000F0      /* VHT Nss value */
+#define WL_RSPEC_VHT_NSS_SHIFT  4               /* VHT Nss value shift */
+#define WL_RSPEC_TXEXP_MASK     0x00000300
+#define WL_RSPEC_TXEXP_SHIFT    8
+#define WL_RSPEC_BW_MASK        0x00070000      /* bandwidth mask */
+#define WL_RSPEC_BW_SHIFT       16              /* bandwidth shift */
+#define WL_RSPEC_STBC           0x00100000      /* STBC encoding, Nsts = 2 x Nss */
+#define WL_RSPEC_TXBF           0x00200000      /* bit indicates TXBF mode */
+#define WL_RSPEC_LDPC           0x00400000      /* bit indicates adv coding in use */
+#define WL_RSPEC_SGI            0x00800000      /* Short GI mode */
+#define WL_RSPEC_ENCODING_MASK  0x03000000      /* Encoding of Rate/MCS field */
+#define WL_RSPEC_OVERRIDE_RATE  0x40000000      /* bit indicate to override mcs only */
+#define WL_RSPEC_OVERRIDE_MODE  0x80000000      /* bit indicates override both rate & mode */
+
+/* WL_RSPEC_ENCODING field defs */
+#define WL_RSPEC_ENCODE_RATE    0x00000000      /* Legacy rate is stored in RSPEC_RATE_MASK */
+#define WL_RSPEC_ENCODE_HT      0x01000000      /* HT MCS is stored in RSPEC_RATE_MASK */
+#define WL_RSPEC_ENCODE_VHT     0x02000000      /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */
+
+/* WL_RSPEC_BW field defs */
+#define WL_RSPEC_BW_UNSPECIFIED 0
+#define WL_RSPEC_BW_20MHZ       0x00010000
+#define WL_RSPEC_BW_40MHZ       0x00020000
+#define WL_RSPEC_BW_80MHZ       0x00030000
+#define WL_RSPEC_BW_160MHZ      0x00040000
+
+/* Legacy defines for the nrate iovar */
+#define OLD_NRATE_MCS_INUSE         0x00000080 /* MSC in use,indicates b0-6 holds an mcs */
+#define OLD_NRATE_RATE_MASK         0x0000007f /* rate/mcs value */
+#define OLD_NRATE_STF_MASK          0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */
+#define OLD_NRATE_STF_SHIFT         8          /* stf mode shift */
+#define OLD_NRATE_OVERRIDE          0x80000000 /* bit indicates override both rate & mode */
+#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */
+#define OLD_NRATE_SGI               0x00800000 /* sgi mode */
+#define OLD_NRATE_LDPC_CODING       0x00400000 /* bit indicates adv coding in use */
+
+#define OLD_NRATE_STF_SISO	0		/* stf mode SISO */
+#define OLD_NRATE_STF_CDD	1		/* stf mode CDD */
+#define OLD_NRATE_STF_STBC	2		/* stf mode STBC */
+#define OLD_NRATE_STF_SDM	3		/* stf mode SDM */
+
+#define HIGHEST_SINGLE_STREAM_MCS	7 /* MCS values greater than this enable multiple streams */
+
+#define MAX_CCA_CHANNELS 38	/* Max number of 20 Mhz wide channels */
+#define MAX_CCA_SECS	60	/* CCA keeps this many seconds history */
+
+#define IBSS_MED        15	/* Mediom in-bss congestion percentage */
+#define IBSS_HI         25	/* Hi in-bss congestion percentage */
+#define OBSS_MED        12
+#define OBSS_HI         25
+#define INTERFER_MED    5
+#define INTERFER_HI     10
+
+#define  CCA_FLAG_2G_ONLY		0x01	/* Return a channel from 2.4 Ghz band */
+#define  CCA_FLAG_5G_ONLY		0x02	/* Return a channel from 2.4 Ghz band */
+#define  CCA_FLAG_IGNORE_DURATION	0x04	/* Ignore dwell time for each channel */
+#define  CCA_FLAGS_PREFER_1_6_11	0x10
+#define  CCA_FLAG_IGNORE_INTERFER 	0x20 /* do not exlude channel based on interfer level */
+
+#define CCA_ERRNO_BAND 		1	/* After filtering for band pref, no choices left */
+#define CCA_ERRNO_DURATION	2	/* After filtering for duration, no choices left */
+#define CCA_ERRNO_PREF_CHAN	3	/* After filtering for chan pref, no choices left */
+#define CCA_ERRNO_INTERFER	4	/* After filtering for interference, no choices left */
+#define CCA_ERRNO_TOO_FEW	5	/* Only 1 channel was input */
+
+#define WL_STA_AID(a)		((a) &~ 0xc000)
+
+/* Flags for sta_info_t indicating properties of STA */
+#define WL_STA_BRCM		0x00000001	/* Running a Broadcom driver */
+#define WL_STA_WME		0x00000002	/* WMM association */
+#define WL_STA_NONERP		0x00000004	/* No ERP */
+#define WL_STA_AUTHE		0x00000008	/* Authenticated */
+#define WL_STA_ASSOC		0x00000010	/* Associated */
+#define WL_STA_AUTHO		0x00000020	/* Authorized */
+#define WL_STA_WDS		0x00000040	/* Wireless Distribution System */
+#define WL_STA_WDS_LINKUP	0x00000080	/* WDS traffic/probes flowing properly */
+#define WL_STA_PS		0x00000100	/* STA is in power save mode from AP's viewpoint */
+#define WL_STA_APSD_BE		0x00000200	/* APSD delv/trigger for AC_BE is default enabled */
+#define WL_STA_APSD_BK		0x00000400	/* APSD delv/trigger for AC_BK is default enabled */
+#define WL_STA_APSD_VI		0x00000800	/* APSD delv/trigger for AC_VI is default enabled */
+#define WL_STA_APSD_VO		0x00001000	/* APSD delv/trigger for AC_VO is default enabled */
+#define WL_STA_N_CAP		0x00002000	/* STA 802.11n capable */
+#define WL_STA_SCBSTATS		0x00004000	/* Per STA debug stats */
+#define WL_STA_AMPDU_CAP	0x00008000	/* STA AMPDU capable */
+#define WL_STA_AMSDU_CAP	0x00010000	/* STA AMSDU capable */
+#define WL_STA_MIMO_PS		0x00020000	/* mimo ps mode is enabled */
+#define WL_STA_MIMO_RTS		0x00040000	/* send rts in mimo ps mode */
+#define WL_STA_RIFS_CAP		0x00080000	/* rifs enabled */
+#define WL_STA_VHT_CAP		0x00100000	/* STA VHT(11ac) capable */
+#define WL_STA_WPS		0x00200000	/* WPS state */
+
+#define WL_WDS_LINKUP		WL_STA_WDS_LINKUP	/* deprecated */
+
+/* STA HT cap fields */
+#define WL_STA_CAP_LDPC_CODING		0x0001	/* Support for rx of LDPC coded pkts */
+#define WL_STA_CAP_40MHZ		0x0002  /* FALSE:20Mhz, TRUE:20/40MHZ supported */
+#define WL_STA_CAP_MIMO_PS_MASK		0x000C  /* Mimo PS mask */
+#define WL_STA_CAP_MIMO_PS_SHIFT	0x0002	/* Mimo PS shift */
+#define WL_STA_CAP_MIMO_PS_OFF		0x0003	/* Mimo PS, no restriction */
+#define WL_STA_CAP_MIMO_PS_RTS		0x0001	/* Mimo PS, send RTS/CTS around MIMO frames */
+#define WL_STA_CAP_MIMO_PS_ON		0x0000	/* Mimo PS, MIMO disallowed */
+#define WL_STA_CAP_GF			0x0010	/* Greenfield preamble support */
+#define WL_STA_CAP_SHORT_GI_20		0x0020	/* 20MHZ short guard interval support */
+#define WL_STA_CAP_SHORT_GI_40		0x0040	/* 40Mhz short guard interval support */
+#define WL_STA_CAP_TX_STBC		0x0080	/* Tx STBC support */
+#define WL_STA_CAP_RX_STBC_MASK		0x0300	/* Rx STBC mask */
+#define WL_STA_CAP_RX_STBC_SHIFT	8	/* Rx STBC shift */
+#define WL_STA_CAP_DELAYED_BA		0x0400	/* delayed BA support */
+#define WL_STA_CAP_MAX_AMSDU		0x0800	/* Max AMSDU size in bytes , 0=3839, 1=7935 */
+#define WL_STA_CAP_DSSS_CCK		0x1000	/* DSSS/CCK supported by the BSS */
+#define WL_STA_CAP_PSMP			0x2000	/* Power Save Multi Poll support */
+#define WL_STA_CAP_40MHZ_INTOLERANT	0x4000	/* 40MHz Intolerant */
+#define WL_STA_CAP_LSIG_TXOP		0x8000	/* L-SIG TXOP protection support */
+
+#define WL_STA_CAP_RX_STBC_NO		0x0	/* no rx STBC support */
+#define WL_STA_CAP_RX_STBC_ONE_STREAM	0x1	/* rx STBC support of 1 spatial stream */
+#define WL_STA_CAP_RX_STBC_TWO_STREAM	0x2	/* rx STBC support of 1-2 spatial streams */
+#define WL_STA_CAP_RX_STBC_THREE_STREAM	0x3	/* rx STBC support of 1-3 spatial streams */
+
+/* scb vht flags */
+#define WL_STA_VHT_LDPCCAP	0x0001
+#define WL_STA_SGI80		0x0002
+#define WL_STA_SGI160		0x0004
+#define WL_STA_VHT_TX_STBCCAP	0x0008
+#define WL_STA_VHT_RX_STBCCAP	0x0010
+#define WL_STA_SU_BEAMFORMER	0x0020
+#define WL_STA_SU_BEAMFORMEE	0x0040
+#define WL_STA_MU_BEAMFORMER	0x0080
+#define WL_STA_MU_BEAMFORMEE	0x0100
+#define WL_STA_VHT_TXOP_PS	0x0200
+#define WL_STA_HTC_VHT_CAP	0x0400
+
+/* Values for TX Filter override mode */
+#define WLC_TXFILTER_OVERRIDE_DISABLED  0
+#define WLC_TXFILTER_OVERRIDE_ENABLED   1
+
+#define WL_IOCTL_ACTION_GET				0x0
+#define WL_IOCTL_ACTION_SET				0x1
+#define WL_IOCTL_ACTION_OVL_IDX_MASK	0x1e
+#define WL_IOCTL_ACTION_OVL_RSV			0x20
+#define WL_IOCTL_ACTION_OVL				0x40
+#define WL_IOCTL_ACTION_MASK			0x7e
+#define WL_IOCTL_ACTION_OVL_SHIFT		1
+
+#define WL_BSSTYPE_INFRA 1
+#define WL_BSSTYPE_INDEP 0
+#define WL_BSSTYPE_ANY   2
+
+/* Bitmask for scan_type */
+#define WL_SCANFLAGS_PASSIVE	0x01	/* force passive scan */
+#define WL_SCANFLAGS_RESERVED	0x02	/* Reserved */
+#define WL_SCANFLAGS_PROHIBITED	0x04	/* allow scanning prohibited channels */
+#define WL_SCANFLAGS_OFFCHAN	0x08	/* allow scanning/reporting off-channel APs */
+#define WL_SCANFLAGS_HOTSPOT	0x10	/* automatic ANQP to hotspot APs */
+
+/* wl_iscan_results status values */
+#define WL_SCAN_RESULTS_SUCCESS	0
+#define WL_SCAN_RESULTS_PARTIAL	1
+#define WL_SCAN_RESULTS_PENDING	2
+#define WL_SCAN_RESULTS_ABORTED	3
+#define WL_SCAN_RESULTS_NO_MEM  4
+
+#define SCANOL_ENABLED			(1 << 0)
+#define SCANOL_BCAST_SSID		(1 << 1)
+#define SCANOL_NOTIFY_BCAST_SSID	(1 << 2)
+#define SCANOL_RESULTS_PER_CYCLE	(1 << 3)
+
+/* scan times in milliseconds */
+#define SCANOL_HOME_TIME		45	/* for home channel processing */
+#define SCANOL_ASSOC_TIME		20	/* dwell on a channel while associated */
+#define SCANOL_UNASSOC_TIME		40	/* dwell on a channel while unassociated */
+#define SCANOL_PASSIVE_TIME		110	/* listen on a channelfor passive scan */
+#define SCANOL_AWAY_LIMIT		100	/* max time to be away from home channel */
+#define SCANOL_IDLE_REST_TIME		40
+#define SCANOL_IDLE_REST_MULTIPLIER	0
+#define SCANOL_ACTIVE_REST_TIME		20
+#define SCANOL_ACTIVE_REST_MULTIPLIER	0
+#define SCANOL_CYCLE_IDLE_REST_TIME	300000	/* Idle Rest Time between Scan Cycle (msec) */
+#define SCANOL_CYCLE_IDLE_REST_MULTIPLIER	0	/* Idle Rest Time Multiplier */
+#define SCANOL_CYCLE_ACTIVE_REST_TIME	200
+#define SCANOL_CYCLE_ACTIVE_REST_MULTIPLIER	0
+#define SCANOL_MAX_REST_TIME		3600000	/* max rest time between scan cycle (msec) */
+#define SCANOL_CYCLE_DEFAULT		0	/* default for Max Scan Cycle, 0 = forever */
+#define SCANOL_CYCLE_MAX		864000	/* Max Scan Cycle */
+						/* 10 sec/scan cycle => 100 days */
+#define SCANOL_NPROBES			2	/* for Active scan; send n probes on each channel */
+#define SCANOL_NPROBES_MAX		5	/* for Active scan; send n probes on each channel */
+#define SCANOL_SCAN_START_DLY		10	/* delay start of offload scan (sec) */
+#define SCANOL_SCAN_START_DLY_MAX	240	/* delay start of offload scan (sec) */
+#define SCANOL_MULTIPLIER_MAX		10	/* Max Multiplier */
+#define SCANOL_UNASSOC_TIME_MAX		100	/* max dwell on a channel while unassociated */
+#define SCANOL_PASSIVE_TIME_MAX		500	/* max listen on a channel for passive scan */
+#define SCANOL_SSID_MAX			16	/* max supported preferred SSID */
+
+/* masks for channel and ssid count */
+#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff
+#define WL_SCAN_PARAMS_NSSID_SHIFT 16
+
+#define WL_SCAN_ACTION_START      1
+#define WL_SCAN_ACTION_CONTINUE   2
+#define WL_SCAN_ACTION_ABORT      3
+
+#if defined(SIMPLE_ISCAN)
+#define ISCAN_RETRY_CNT   5
+#define ISCAN_STATE_IDLE   0
+#define ISCAN_STATE_SCANING 1
+#define ISCAN_STATE_PENDING 2
+#endif /* SIMPLE_ISCAN */
+
+#define ANTENNA_NUM_1	1		/* total number of antennas to be used */
+#define ANTENNA_NUM_2	2
+#define ANTENNA_NUM_3	3
+#define ANTENNA_NUM_4	4
+
+#define ANT_SELCFG_AUTO		0x80	/* bit indicates antenna sel AUTO */
+#define ANT_SELCFG_MASK		0x33	/* antenna configuration mask */
+#define ANT_SELCFG_TX_UNICAST	0	/* unicast tx antenna configuration */
+#define ANT_SELCFG_RX_UNICAST	1	/* unicast rx antenna configuration */
+#define ANT_SELCFG_TX_DEF	2	/* default tx antenna configuration */
+#define ANT_SELCFG_RX_DEF	3	/* default rx antenna configuration */
+
+/* interference source detection and identification mode */
+#define ITFR_MODE_DISABLE	0	/* disable feature */
+#define ITFR_MODE_MANUAL_ENABLE	1	/* enable manual detection */
+#define ITFR_MODE_AUTO_ENABLE	2	/* enable auto detection */
+
+/* bit definitions for flags in interference source report */
+#define ITFR_INTERFERENCED	1	/* interference detected */
+#define ITFR_HOME_CHANNEL	2	/* home channel has interference */
+#define ITFR_NOISY_ENVIRONMENT	4	/* noisy environemnt so feature stopped */
+
+#define WL_NUM_RPI_BINS		8
+#define WL_RM_TYPE_BASIC	1
+#define WL_RM_TYPE_CCA		2
+#define WL_RM_TYPE_RPI		3
+
+#define WL_RM_FLAG_PARALLEL	(1<<0)
+
+#define WL_RM_FLAG_LATE		(1<<1)
+#define WL_RM_FLAG_INCAPABLE	(1<<2)
+#define WL_RM_FLAG_REFUSED	(1<<3)
+
+/* flags */
+#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */
+
+#define WLC_CIS_DEFAULT	0	/* built-in default */
+#define WLC_CIS_SROM	1	/* source is sprom */
+#define WLC_CIS_OTP	2	/* source is otp */
+
+/* PCL - Power Control Loop */
+/* current gain setting is replaced by user input */
+#define WL_ATTEN_APP_INPUT_PCL_OFF	0	/* turn off PCL, apply supplied input */
+#define WL_ATTEN_PCL_ON			1	/* turn on PCL */
+/* current gain setting is maintained */
+#define WL_ATTEN_PCL_OFF		2	/* turn off PCL. */
+
+#define	PLC_CMD_FAILOVER	1
+#define	PLC_CMD_MAC_COST	2
+#define	PLC_CMD_LINK_COST	3
+#define	PLC_CMD_NODE_LIST	4
+
+#define NODE_TYPE_UNKNOWN	0	/* Unknown link */
+#define NODE_TYPE_WIFI_ONLY	1	/* Pure Wireless STA node */
+#define NODE_TYPE_PLC_ONLY	2	/* Pure PLC only node */
+#define NODE_TYPE_WIFI_PLC	3	/* WiFi PLC capable node */
+
+/* defines used by poweridx iovar - it controls power in a-band */
+/* current gain setting is maintained */
+#define WL_PWRIDX_PCL_OFF	-2	/* turn off PCL.  */
+#define WL_PWRIDX_PCL_ON	-1	/* turn on PCL */
+#define WL_PWRIDX_LOWER_LIMIT	-2	/* lower limit */
+#define WL_PWRIDX_UPPER_LIMIT	63	/* upper limit */
+/* value >= 0 causes
+ *	- input to be set to that value
+ *	- PCL to be off
+ */
+
+#define BCM_MAC_STATUS_INDICATION	(0x40010200L)
+
+/* Values for TX Filter override mode */
+#define WLC_TXFILTER_OVERRIDE_DISABLED  0
+#define WLC_TXFILTER_OVERRIDE_ENABLED   1
+
+/* magic pattern used for mismatch driver and wl */
+#define WL_TXFIFO_SZ_MAGIC	0xa5a5
+
+/* check this magic number */
+#define WLC_IOCTL_MAGIC		0x14e46c77
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* bss_info_cap_t flags */
+#define WL_BSS_FLAGS_FROM_BEACON	0x01	/* bss_info derived from beacon */
+#define WL_BSS_FLAGS_FROM_CACHE		0x02	/* bss_info collected from cache */
+#define WL_BSS_FLAGS_RSSI_ONCHANNEL	0x04	/* rssi info received on channel (vs offchannel) */
+#define WL_BSS_FLAGS_HS20		0x08	/* hotspot 2.0 capable */
+#define WL_BSS_FLAGS_RSSI_INVALID	0x10	/* BSS contains invalid RSSI */
+#define WL_BSS_FLAGS_RSSI_INACCURATE	0x20	/* BSS contains inaccurate RSSI */
+
+/* bssinfo flag for nbss_cap */
+#define VHT_BI_SGI_80MHZ			0x00000100
+#define VHT_BI_80MHZ			    0x00000200
+#define VHT_BI_160MHZ			    0x00000400
+#define VHT_BI_8080MHZ			    0x00000800
+
+/* reference to wl_ioctl_t struct used by usermode driver */
+#define ioctl_subtype	set		/* subtype param */
+#define ioctl_pid	used		/* pid param */
+#define ioctl_status	needed		/* status param */
+
+
+/* Enumerate crypto algorithms */
+#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
+#if !defined(BCMCCX) && !defined(BCMEXTCCX)
+#define CRYPTO_ALGO_NALG		7
+#else
+#define CRYPTO_ALGO_CKIP		7
+#define CRYPTO_ALGO_CKIP_MMH	8
+#define CRYPTO_ALGO_WEP_MMH		9
+#define CRYPTO_ALGO_NALG		10
+#endif /* !BCMCCX && !BCMEXTCCX */
+
+#define CRYPTO_ALGO_SMS4		11
+#define CRYPTO_ALGO_PMK			12	/* for 802.1x supp to set PMK before 4-way */
+#define CRYPTO_ALGO_BIP			13  /* 802.11w BIP (aes cmac) */
+
+#define CRYPTO_ALGO_AES_GCM     14  /* 128 bit GCM */
+#define CRYPTO_ALGO_AES_CCM256  15  /* 256 bit CCM */
+#define CRYPTO_ALGO_AES_GCM256  16  /* 256 bit GCM */
+#define CRYPTO_ALGO_BIP_CMAC256 17  /* 256 bit BIP CMAC */
+#define CRYPTO_ALGO_BIP_GMAC    18  /* 128 bit BIP GMAC */
+#define CRYPTO_ALGO_BIP_GMAC256 19  /* 256 bit BIP GMAC */
+
+#define CRYPTO_ALGO_NONE        CRYPTO_ALGO_OFF
+
+#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)	/* Indicates this key is using soft encrypt */
+#define WL_PRIMARY_KEY	(1 << 1)	/* Indicates this key is the primary (ie tx) key */
+#if defined(BCMCCX) || defined(BCMEXTCCX)
+#define WL_CKIP_KP	(1 << 4)	/* CMIC */
+#define WL_CKIP_MMH	(1 << 5)	/* CKIP */
+#else
+#define WL_KF_RES_4	(1 << 4)	/* Reserved for backward compat */
+#define WL_KF_RES_5	(1 << 5)	/* Reserved for backward compat */
+#endif /* BCMCCX || BCMEXTCCX */
+#define WL_IBSS_PEER_GROUP_KEY	(1 << 6)	/* Indicates a group key for a IBSS PEER */
+
+/* wireless security bitvec */
+#define WEP_ENABLED		0x0001
+#define TKIP_ENABLED		0x0002
+#define AES_ENABLED		0x0004
+#define WSEC_SWFLAG		0x0008
+#ifdef BCMCCX
+#define CKIP_KP_ENABLED		0x0010
+#define CKIP_MIC_ENABLED	0x0020
+#endif /* BCMCCX */
+#define SES_OW_ENABLED		0x0040	/* to go into transition mode without setting wep */
+#ifdef BCMWAPI_WPI
+#define SMS4_ENABLED		0x0100
+#endif /* BCMWAPI_WPI */
+
+/* wsec macros for operating on the above definitions */
+#define WSEC_WEP_ENABLED(wsec)	((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec)	((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec)	((wsec) & AES_ENABLED)
+
+#ifdef BCMCCX
+#define WSEC_CKIP_KP_ENABLED(wsec)	((wsec) & CKIP_KP_ENABLED)
+#define WSEC_CKIP_MIC_ENABLED(wsec)	((wsec) & CKIP_MIC_ENABLED)
+#define WSEC_CKIP_ENABLED(wsec)	((wsec) & (CKIP_KP_ENABLED|CKIP_MIC_ENABLED))
+
+#ifdef BCMWAPI_WPI
+#define WSEC_ENABLED(wsec) \
+	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | CKIP_KP_ENABLED |	\
+	  CKIP_MIC_ENABLED | SMS4_ENABLED))
+#else /* BCMWAPI_WPI */
+#define WSEC_ENABLED(wsec) \
+		((wsec) & \
+		 (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | CKIP_KP_ENABLED | CKIP_MIC_ENABLED))
+#endif /* BCMWAPI_WPI */
+#else /* defined BCMCCX */
+#ifdef BCMWAPI_WPI
+#define WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
+#else /* BCMWAPI_WPI */
+#define WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#endif /* BCMWAPI_WPI */
+#endif /* BCMCCX */
+#define WSEC_SES_OW_ENABLED(wsec)	((wsec) & SES_OW_ENABLED)
+#ifdef BCMWAPI_WAI
+#define WSEC_SMS4_ENABLED(wsec)	((wsec) & SMS4_ENABLED)
+#endif /* BCMWAPI_WAI */
+
+#define MFP_CAPABLE		0x0200
+#define MFP_REQUIRED	0x0400
+#define MFP_SHA256		0x0800 /* a special configuration for STA for WIFI test tool */
+
+/* WPA authentication mode bitvec */
+#define WPA_AUTH_DISABLED	0x0000	/* Legacy (i.e., non-WPA) */
+#define WPA_AUTH_NONE		0x0001	/* none (IBSS) */
+#define WPA_AUTH_UNSPECIFIED	0x0002	/* over 802.1x */
+#define WPA_AUTH_PSK		0x0004	/* Pre-shared key */
+#if defined(BCMCCX) || defined(BCMEXTCCX)
+#define WPA_AUTH_CCKM		0x0008	/* CCKM */
+#define WPA2_AUTH_CCKM		0x0010	/* CCKM2 */
+#endif	/* BCMCCX || BCMEXTCCX */
+/* #define WPA_AUTH_8021X 0x0020 */	/* 802.1x, reserved */
+#define WPA2_AUTH_UNSPECIFIED	0x0040	/* over 802.1x */
+#define WPA2_AUTH_PSK		0x0080	/* Pre-shared key */
+#define BRCM_AUTH_PSK           0x0100  /* BRCM specific PSK */
+#define BRCM_AUTH_DPT		0x0200	/* DPT PSK without group keys */
+#if defined(BCMWAPI_WAI) || defined(BCMWAPI_WPI)
+#define WPA_AUTH_WAPI           0x0400
+#define WAPI_AUTH_NONE		WPA_AUTH_NONE	/* none (IBSS) */
+#define WAPI_AUTH_UNSPECIFIED	0x0400	/* over AS */
+#define WAPI_AUTH_PSK		0x0800	/* Pre-shared key */
+#endif /* BCMWAPI_WAI || BCMWAPI_WPI */
+#define WPA2_AUTH_MFP           0x1000  /* MFP (11w) in contrast to CCX */
+#define WPA2_AUTH_TPK		0x2000 	/* TDLS Peer Key */
+#define WPA2_AUTH_FT		0x4000 	/* Fast Transition. */
+#define WPA_AUTH_PFN_ANY	0xffffffff	/* for PFN, match only ssid */
+
+/* pmkid */
+#define	MAXPMKID		16
+
+#define	WLC_IOCTL_MAXLEN		8192	/* max length ioctl buffer required */
+#define	WLC_IOCTL_SMLEN			256	/* "small" length ioctl buffer required */
+#define WLC_IOCTL_MEDLEN		1536    /* "med" length ioctl buffer required */
+#if defined(LCNCONF) || defined(LCN40CONF)
+#define WLC_SAMPLECOLLECT_MAXLEN	8192	/* Max Sample Collect buffer */
+#else
+#define WLC_SAMPLECOLLECT_MAXLEN	10240	/* Max Sample Collect buffer for two cores */
+#endif
+#define WLC_SAMPLECOLLECT_MAXLEN_LCN40  8192
+
+/* common ioctl definitions */
+#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_OVERLAY_IOCTL			11 */ /* not supported */
+#define WLC_GET_RATE				12
+#define WLC_GET_MAX_RATE			13
+#define WLC_GET_INSTANCE			14
+/* #define WLC_GET_FRAG				15 */ /* no longer supported */
+/* #define WLC_SET_FRAG				16 */ /* no longer supported */
+/* #define WLC_GET_RTS				17 */ /* no longer supported */
+/* #define WLC_SET_RTS				18 */ /* no longer supported */
+#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_DUMP_SCB				28 */ /* no longer supported */
+#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_WEP				42 */ /* no longer supported */
+/* #define WLC_SET_WEP				43 */ /* no longer supported */
+#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	/* diag */
+#define WLC_GET_TXANT				61
+#define WLC_SET_TXANT				62
+#define WLC_GET_ANTDIV				63
+#define WLC_SET_ANTDIV				64
+/* #define WLC_GET_TXPWR			65 */ /* no longer supported */
+/* #define WLC_SET_TXPWR			66 */ /* no longer supported */
+#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_GET_LOCALE			73 */ /* no longer supported */
+#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_D11CNTS			89 */ /* -> "counters" iovar */
+#define WLC_GET_FORCELINK			90	/* ndis only */
+#define WLC_SET_FORCELINK			91	/* ndis only */
+#define WLC_FREQ_ACCURACY			92	/* diag */
+#define WLC_CARRIER_SUPPRESS			93	/* diag */
+#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_DIAG_LOOPBACK			103	old tray diag */
+/* #define WLC_RESET_D11CNTS			104 */ /* -> "reset_d11cnts" iovar */
+#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	/* current rateset */
+#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
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_GET_BAND				141
+#define WLC_SET_BAND				142
+#define WLC_SCB_DEAUTHENTICATE			143
+#define WLC_GET_SHORTSLOT			144
+#define WLC_GET_SHORTSLOT_OVERRIDE		145
+#define WLC_SET_SHORTSLOT_OVERRIDE		146
+#define WLC_GET_SHORTSLOT_RESTRICT		147
+#define WLC_SET_SHORTSLOT_RESTRICT		148
+#define WLC_GET_GMODE_PROTECTION		149
+#define WLC_GET_GMODE_PROTECTION_OVERRIDE	150
+#define WLC_SET_GMODE_PROTECTION_OVERRIDE	151
+#define WLC_UPGRADE				152
+/* #define WLC_GET_MRATE			153 */ /* no longer supported */
+/* #define WLC_SET_MRATE			154 */ /* no longer supported */
+#define WLC_GET_IGNORE_BCNS			155
+#define WLC_SET_IGNORE_BCNS			156
+#define WLC_GET_SCB_TIMEOUT			157
+#define WLC_SET_SCB_TIMEOUT			158
+#define WLC_GET_ASSOCLIST			159
+#define WLC_GET_CLK				160
+#define WLC_SET_CLK				161
+#define WLC_GET_UP				162
+#define WLC_OUT					163
+#define WLC_GET_WPA_AUTH			164
+#define WLC_SET_WPA_AUTH			165
+#define WLC_GET_UCFLAGS				166
+#define WLC_SET_UCFLAGS				167
+#define WLC_GET_PWRIDX				168
+#define WLC_SET_PWRIDX				169
+#define WLC_GET_TSSI				170
+#define WLC_GET_SUP_RATESET_OVERRIDE		171
+#define WLC_SET_SUP_RATESET_OVERRIDE		172
+/* #define WLC_SET_FAST_TIMER			173 */ /* no longer supported */
+/* #define WLC_GET_FAST_TIMER			174 */ /* no longer supported */
+/* #define WLC_SET_SLOW_TIMER			175 */ /* no longer supported */
+/* #define WLC_GET_SLOW_TIMER			176 */ /* no longer supported */
+/* #define WLC_DUMP_PHYREGS			177 */ /* no longer supported */
+#define WLC_GET_PROTECTION_CONTROL		178
+#define WLC_SET_PROTECTION_CONTROL		179
+#endif /* LINUX_POSTMOGRIFY_REMOVAL  */
+#define WLC_GET_PHYLIST				180
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_ENCRYPT_STRENGTH			181	/* ndis only */
+#define WLC_DECRYPT_STATUS			182	/* ndis only */
+#define WLC_GET_KEY_SEQ				183
+#define WLC_GET_SCAN_CHANNEL_TIME		184
+#define WLC_SET_SCAN_CHANNEL_TIME		185
+#define WLC_GET_SCAN_UNASSOC_TIME		186
+#define WLC_SET_SCAN_UNASSOC_TIME		187
+#define WLC_GET_SCAN_HOME_TIME			188
+#define WLC_SET_SCAN_HOME_TIME			189
+#define WLC_GET_SCAN_NPROBES			190
+#define WLC_SET_SCAN_NPROBES			191
+#define WLC_GET_PRB_RESP_TIMEOUT		192
+#define WLC_SET_PRB_RESP_TIMEOUT		193
+#define WLC_GET_ATTEN				194
+#define WLC_SET_ATTEN				195
+#define WLC_GET_SHMEM				196	/* diag */
+#define WLC_SET_SHMEM				197	/* diag */
+/* #define WLC_GET_GMODE_PROTECTION_CTS		198 */ /* no longer supported */
+/* #define WLC_SET_GMODE_PROTECTION_CTS		199 */ /* no longer supported */
+#define WLC_SET_WSEC_TEST			200
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON	201
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_TKIP_COUNTERMEASURES		202
+#define WLC_GET_PIOMODE				203
+#define WLC_SET_PIOMODE				204
+#define WLC_SET_ASSOC_PREFER			205
+#define WLC_GET_ASSOC_PREFER			206
+#define WLC_SET_ROAM_PREFER			207
+#define WLC_GET_ROAM_PREFER			208
+#define WLC_SET_LED				209
+#define WLC_GET_LED				210
+#define WLC_GET_INTERFERENCE_MODE		211
+#define WLC_SET_INTERFERENCE_MODE		212
+#define WLC_GET_CHANNEL_QA			213
+#define WLC_START_CHANNEL_QA			214
+#define WLC_GET_CHANNEL_SEL			215
+#define WLC_START_CHANNEL_SEL			216
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#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_SET_GLACIAL_TIMER		233 */ /* no longer supported */
+/* #define WLC_GET_GLACIAL_TIMER		234 */ /* no longer supported */
+#define WLC_GET_KEY_PRIMARY			235
+#define WLC_SET_KEY_PRIMARY			236
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+/* #define WLC_DUMP_RADIOREGS			237 */ /* no longer supported */
+#define WLC_GET_ACI_ARGS			238
+#define WLC_SET_ACI_ARGS			239
+#define WLC_UNSET_CALLBACK			240
+#define WLC_SET_CALLBACK			241
+#define WLC_GET_RADAR				242
+#define WLC_SET_RADAR				243
+#define WLC_SET_SPECT_MANAGMENT			244
+#define WLC_GET_SPECT_MANAGMENT			245
+#define WLC_WDS_GET_REMOTE_HWADDR		246	/* handled in wl_linux.c/wl_vx.c */
+#define WLC_WDS_GET_WPA_SUP			247
+#define WLC_SET_CS_SCAN_TIMER			248
+#define WLC_GET_CS_SCAN_TIMER			249
+#define WLC_MEASURE_REQUEST			250
+#define WLC_INIT				251
+#define WLC_SEND_QUIET				252
+#define WLC_KEEPALIVE			253
+#define WLC_SEND_PWR_CONSTRAINT			254
+#define WLC_UPGRADE_STATUS			255
+#define WLC_CURRENT_PWR				256
+#define WLC_GET_SCAN_PASSIVE_TIME		257
+#define WLC_SET_SCAN_PASSIVE_TIME		258
+#define WLC_LEGACY_LINK_BEHAVIOR		259
+#define WLC_GET_CHANNELS_IN_COUNTRY		260
+#define WLC_GET_COUNTRY_LIST			261
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WLC_GET_VAR				262	/* get value of named variable */
+#define WLC_SET_VAR				263	/* set named variable to value */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_NVRAM_GET				264	/* deprecated */
+#define WLC_NVRAM_SET				265
+#define WLC_NVRAM_DUMP				266
+#define WLC_REBOOT				267
+#endif /* !LINUX_POSTMOGRIFY_REMOVAL */
+#define WLC_SET_WSEC_PMK			268
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_GET_AUTH_MODE			269
+#define WLC_SET_AUTH_MODE			270
+#define WLC_GET_WAKEENTRY			271
+#define WLC_SET_WAKEENTRY			272
+#define WLC_NDCONFIG_ITEM			273	/* currently handled in wl_oid.c */
+#define WLC_NVOTPW				274
+#define WLC_OTPW				275
+#define WLC_IOV_BLOCK_GET			276
+#define WLC_IOV_MODULES_GET			277
+#define WLC_SOFT_RESET				278
+#define WLC_GET_ALLOW_MODE			279
+#define WLC_SET_ALLOW_MODE			280
+#define WLC_GET_DESIRED_BSSID			281
+#define WLC_SET_DESIRED_BSSID			282
+#define	WLC_DISASSOC_MYAP			283
+#define WLC_GET_NBANDS				284	/* for Dongle EXT_STA support */
+#define WLC_GET_BANDSTATES			285	/* for Dongle EXT_STA support */
+#define WLC_GET_WLC_BSS_INFO			286	/* for Dongle EXT_STA support */
+#define WLC_GET_ASSOC_INFO			287	/* for Dongle EXT_STA support */
+#define WLC_GET_OID_PHY				288	/* for Dongle EXT_STA support */
+#define WLC_SET_OID_PHY				289	/* for Dongle EXT_STA support */
+#define WLC_SET_ASSOC_TIME			290	/* for Dongle EXT_STA support */
+#define WLC_GET_DESIRED_SSID			291	/* for Dongle EXT_STA support */
+#define WLC_GET_CHANSPEC			292	/* for Dongle EXT_STA support */
+#define WLC_GET_ASSOC_STATE			293	/* for Dongle EXT_STA support */
+#define WLC_SET_PHY_STATE			294	/* for Dongle EXT_STA support */
+#define WLC_GET_SCAN_PENDING			295	/* for Dongle EXT_STA support */
+#define WLC_GET_SCANREQ_PENDING			296	/* for Dongle EXT_STA support */
+#define WLC_GET_PREV_ROAM_REASON		297	/* for Dongle EXT_STA support */
+#define WLC_SET_PREV_ROAM_REASON		298	/* for Dongle EXT_STA support */
+#define WLC_GET_BANDSTATES_PI			299	/* for Dongle EXT_STA support */
+#define WLC_GET_PHY_STATE			300	/* for Dongle EXT_STA support */
+#define WLC_GET_BSS_WPA_RSN			301	/* for Dongle EXT_STA support */
+#define WLC_GET_BSS_WPA2_RSN			302	/* for Dongle EXT_STA support */
+#define WLC_GET_BSS_BCN_TS			303	/* for Dongle EXT_STA support */
+#define WLC_GET_INT_DISASSOC			304	/* for Dongle EXT_STA support */
+#define WLC_SET_NUM_PEERS			305     /* for Dongle EXT_STA support */
+#define WLC_GET_NUM_BSS				306	/* for Dongle EXT_STA support */
+#define WLC_PHY_SAMPLE_COLLECT			307	/* phy sample collect mode */
+/* #define WLC_UM_PRIV				308 */	/* Deprecated: usermode driver */
+#define WLC_GET_CMD				309
+/* #define WLC_LAST				310 */	/* Never used - can be reused */
+#define WLC_SET_INTERFERENCE_OVERRIDE_MODE	311	/* set inter mode override */
+#define WLC_GET_INTERFERENCE_OVERRIDE_MODE	312	/* get inter mode override */
+/* #define WLC_GET_WAI_RESTRICT			313 */	/* for WAPI, deprecated use iovar instead */
+/* #define WLC_SET_WAI_RESTRICT			314 */	/* for WAPI, deprecated use iovar instead */
+/* #define WLC_SET_WAI_REKEY			315 */	/* for WAPI, deprecated use iovar instead */
+#define WLC_SET_NAT_CONFIG			316	/* for configuring NAT filter driver */
+#define WLC_GET_NAT_STATE			317
+#define WLC_GET_TXBF_RATESET			318
+#define WLC_SET_TXBF_RATESET			319
+#define WLC_SCAN_CQ				320
+#define WLC_GET_RSSI_QDB			321 /* qdB portion of the RSSI */
+
+#define WLC_LAST				322
+#ifndef EPICTRL_COOKIE
+#define EPICTRL_COOKIE		0xABADCEDE
+#endif
+
+/* vx wlc ioctl's offset */
+#define CMN_IOCTL_OFF 0x180
+
+/*
+ * custom OID support
+ *
+ * 0xFF - implementation specific OID
+ * 0xE4 - first byte of Broadcom PCI vendor ID
+ * 0x14 - second byte of Broadcom PCI vendor ID
+ * 0xXX - the custom OID number
+ */
+
+/* begin 0x1f values beyond the start of the ET driver range. */
+#define WL_OID_BASE		0xFFE41420
+
+/* NDIS overrides */
+#define OID_WL_GETINSTANCE	(WL_OID_BASE + WLC_GET_INSTANCE)
+#define OID_WL_GET_FORCELINK	(WL_OID_BASE + WLC_GET_FORCELINK)
+#define OID_WL_SET_FORCELINK	(WL_OID_BASE + WLC_SET_FORCELINK)
+#define	OID_WL_ENCRYPT_STRENGTH	(WL_OID_BASE + WLC_ENCRYPT_STRENGTH)
+#define OID_WL_DECRYPT_STATUS	(WL_OID_BASE + WLC_DECRYPT_STATUS)
+#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR)
+#define OID_WL_NDCONFIG_ITEM	(WL_OID_BASE + WLC_NDCONFIG_ITEM)
+
+/* EXT_STA Dongle suuport */
+#define OID_STA_CHANSPEC	(WL_OID_BASE + WLC_GET_CHANSPEC)
+#define OID_STA_NBANDS		(WL_OID_BASE + WLC_GET_NBANDS)
+#define OID_STA_GET_PHY		(WL_OID_BASE + WLC_GET_OID_PHY)
+#define OID_STA_SET_PHY		(WL_OID_BASE + WLC_SET_OID_PHY)
+#define OID_STA_ASSOC_TIME	(WL_OID_BASE + WLC_SET_ASSOC_TIME)
+#define OID_STA_DESIRED_SSID	(WL_OID_BASE + WLC_GET_DESIRED_SSID)
+#define OID_STA_SET_PHY_STATE	(WL_OID_BASE + WLC_SET_PHY_STATE)
+#define OID_STA_SCAN_PENDING	(WL_OID_BASE + WLC_GET_SCAN_PENDING)
+#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING)
+#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON)
+#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON)
+#define OID_STA_GET_PHY_STATE	(WL_OID_BASE + WLC_GET_PHY_STATE)
+#define OID_STA_INT_DISASSOC	(WL_OID_BASE + WLC_GET_INT_DISASSOC)
+#define OID_STA_SET_NUM_PEERS	(WL_OID_BASE + WLC_SET_NUM_PEERS)
+#define OID_STA_GET_NUM_BSS	(WL_OID_BASE + WLC_GET_NUM_BSS)
+
+/* NAT filter driver support */
+#define OID_NAT_SET_CONFIG	(WL_OID_BASE + WLC_SET_NAT_CONFIG)
+#define OID_NAT_GET_STATE	(WL_OID_BASE + WLC_GET_NAT_STATE)
+
+#define WL_DECRYPT_STATUS_SUCCESS	1
+#define WL_DECRYPT_STATUS_FAILURE	2
+#define WL_DECRYPT_STATUS_UNKNOWN	3
+
+/* allows user-mode app to poll the status of USB image upgrade */
+#define WLC_UPGRADE_SUCCESS			0
+#define WLC_UPGRADE_PENDING			1
+
+/* WLC_GET_AUTH, WLC_SET_AUTH values */
+#define WL_AUTH_OPEN_SYSTEM		0	/* d11 open authentication */
+#define WL_AUTH_SHARED_KEY		1	/* d11 shared authentication */
+#define WL_AUTH_OPEN_SHARED		2	/* try open, then shared if open failed w/rc 13 */
+
+/* a large TX Power as an init value to factor out of MIN() calculations,
+ * keep low enough to fit in an int8, units are .25 dBm
+ */
+#define WLC_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
+
+/* "diag" iovar argument and error code */
+#define WL_DIAG_INTERRUPT			1	/* d11 loopback interrupt test */
+#define WL_DIAG_LOOPBACK			2	/* d11 loopback data test */
+#define WL_DIAG_MEMORY				3	/* d11 memory test */
+#define WL_DIAG_LED				4	/* LED test */
+#define WL_DIAG_REG				5	/* d11/phy register test */
+#define WL_DIAG_SROM				6	/* srom read/crc test */
+#define WL_DIAG_DMA				7	/* DMA test */
+#define WL_DIAG_LOOPBACK_EXT			8	/* enhenced d11 loopback data test */
+
+#define WL_DIAGERR_SUCCESS			0
+#define WL_DIAGERR_FAIL_TO_RUN			1	/* unable to run requested diag */
+#define WL_DIAGERR_NOT_SUPPORTED		2	/* diag requested is not supported */
+#define WL_DIAGERR_INTERRUPT_FAIL		3	/* loopback interrupt test failed */
+#define WL_DIAGERR_LOOPBACK_FAIL		4	/* loopback data test failed */
+#define WL_DIAGERR_SROM_FAIL			5	/* srom read failed */
+#define WL_DIAGERR_SROM_BADCRC			6	/* srom crc failed */
+#define WL_DIAGERR_REG_FAIL			7	/* d11/phy register test failed */
+#define WL_DIAGERR_MEMORY_FAIL			8	/* d11 memory test failed */
+#define WL_DIAGERR_NOMEM			9	/* diag test failed due to no memory */
+#define WL_DIAGERR_DMA_FAIL			10	/* DMA test failed */
+
+#define WL_DIAGERR_MEMORY_TIMEOUT		11	/* d11 memory test didn't finish in time */
+#define WL_DIAGERR_MEMORY_BADPATTERN		12	/* d11 memory test result in bad pattern */
+
+/* band types */
+#define	WLC_BAND_AUTO		0	/* auto-select */
+#define	WLC_BAND_5G		1	/* 5 Ghz */
+#define	WLC_BAND_2G		2	/* 2.4 Ghz */
+#define	WLC_BAND_ALL		3	/* all bands */
+
+/* band range returned by band_range iovar */
+#define WL_CHAN_FREQ_RANGE_2G      0
+#define WL_CHAN_FREQ_RANGE_5GL     1
+#define WL_CHAN_FREQ_RANGE_5GM     2
+#define WL_CHAN_FREQ_RANGE_5GH     3
+
+#define WL_CHAN_FREQ_RANGE_5GLL_5BAND    4
+#define WL_CHAN_FREQ_RANGE_5GLH_5BAND    5
+#define WL_CHAN_FREQ_RANGE_5GML_5BAND    6
+#define WL_CHAN_FREQ_RANGE_5GMH_5BAND    7
+#define WL_CHAN_FREQ_RANGE_5GH_5BAND     8
+
+#define WL_CHAN_FREQ_RANGE_5G_BAND0     1
+#define WL_CHAN_FREQ_RANGE_5G_BAND1     2
+#define WL_CHAN_FREQ_RANGE_5G_BAND2     3
+#define WL_CHAN_FREQ_RANGE_5G_BAND3     4
+
+#define WL_CHAN_FREQ_RANGE_5G_4BAND	5
+
+/* MAC list modes */
+#define WLC_MACMODE_DISABLED	0	/* MAC list disabled */
+#define WLC_MACMODE_DENY	1	/* Deny specified (i.e. allow unspecified) */
+#define WLC_MACMODE_ALLOW	2	/* Allow specified (i.e. deny unspecified) */
+
+/*
+ * 54g modes (basic bits may still be overridden)
+ *
+ * GMODE_LEGACY_B			Rateset: 1b, 2b, 5.5, 11
+ *					Preamble: Long
+ *					Shortslot: Off
+ * GMODE_AUTO				Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *					Extended Rateset: 6, 9, 12, 48
+ *					Preamble: Long
+ *					Shortslot: Auto
+ * GMODE_ONLY				Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
+ *					Extended Rateset: 6b, 9, 12b, 48
+ *					Preamble: Short required
+ *					Shortslot: Auto
+ * GMODE_B_DEFERRED			Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *					Extended Rateset: 6, 9, 12, 48
+ *					Preamble: Long
+ *					Shortslot: On
+ * GMODE_PERFORMANCE			Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
+ *					Preamble: Short required
+ *					Shortslot: On and required
+ * GMODE_LRS				Rateset: 1b, 2b, 5.5b, 11b
+ *					Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
+ *					Preamble: Long
+ *					Shortslot: Auto
+ */
+#define GMODE_LEGACY_B		0
+#define GMODE_AUTO		1
+#define GMODE_ONLY		2
+#define GMODE_B_DEFERRED	3
+#define GMODE_PERFORMANCE	4
+#define GMODE_LRS		5
+#define GMODE_MAX		6
+
+/* values for PLCPHdr_override */
+#define WLC_PLCP_AUTO	-1
+#define WLC_PLCP_SHORT	0
+#define WLC_PLCP_LONG	1
+
+/* values for g_protection_override and n_protection_override */
+#define WLC_PROTECTION_AUTO		-1
+#define WLC_PROTECTION_OFF		0
+#define WLC_PROTECTION_ON		1
+#define WLC_PROTECTION_MMHDR_ONLY	2
+#define WLC_PROTECTION_CTS_ONLY		3
+
+/* values for g_protection_control and n_protection_control */
+#define WLC_PROTECTION_CTL_OFF		0
+#define WLC_PROTECTION_CTL_LOCAL	1
+#define WLC_PROTECTION_CTL_OVERLAP	2
+
+/* values for n_protection */
+#define WLC_N_PROTECTION_OFF		0
+#define WLC_N_PROTECTION_OPTIONAL	1
+#define WLC_N_PROTECTION_20IN40		2
+#define WLC_N_PROTECTION_MIXEDMODE	3
+
+/* values for n_preamble_type */
+#define WLC_N_PREAMBLE_MIXEDMODE	0
+#define WLC_N_PREAMBLE_GF		1
+#define WLC_N_PREAMBLE_GF_BRCM          2
+
+/* values for band specific 40MHz capabilities (deprecated) */
+#define WLC_N_BW_20ALL			0
+#define WLC_N_BW_40ALL			1
+#define WLC_N_BW_20IN2G_40IN5G		2
+
+#define WLC_BW_20MHZ_BIT		(1<<0)
+#define WLC_BW_40MHZ_BIT		(1<<1)
+#define WLC_BW_80MHZ_BIT		(1<<2)
+#define WLC_BW_160MHZ_BIT		(1<<3)
+
+/* Bandwidth capabilities */
+#define WLC_BW_CAP_20MHZ		(WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_40MHZ		(WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_80MHZ		(WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_160MHZ		(WLC_BW_160MHZ_BIT|WLC_BW_80MHZ_BIT| \
+	WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_UNRESTRICTED		0xFF
+
+#define WL_BW_CAP_20MHZ(bw_cap)	(((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_40MHZ(bw_cap)	(((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_80MHZ(bw_cap)	(((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_160MHZ(bw_cap)(((bw_cap) & WLC_BW_160MHZ_BIT) ? TRUE : FALSE)
+
+/* values to force tx/rx chain */
+#define WLC_N_TXRX_CHAIN0		0
+#define WLC_N_TXRX_CHAIN1		1
+
+/* bitflags for SGI support (sgi_rx iovar) */
+#define WLC_N_SGI_20			0x01
+#define WLC_N_SGI_40			0x02
+#define WLC_VHT_SGI_80			0x04
+
+/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */
+#define WLC_SGI_ALL				0x02
+
+#define LISTEN_INTERVAL			10
+/* interference mitigation options */
+#define	INTERFERE_OVRRIDE_OFF	-1	/* interference override off */
+#define	INTERFERE_NONE	0	/* off */
+#define	NON_WLAN	1	/* foreign/non 802.11 interference, no auto detect */
+#define	WLAN_MANUAL	2	/* ACI: no auto detection */
+#define	WLAN_AUTO	3	/* ACI: auto detect */
+#define	WLAN_AUTO_W_NOISE	4	/* ACI: auto - detect and non 802.11 interference */
+#define AUTO_ACTIVE	(1 << 7) /* Auto is currently active */
+
+/* interfernece mode bit-masks (ACPHY) */
+#define ACPHY_ACI_GLITCHBASED_DESENSE 1   /* bit 0 */
+#define ACPHY_ACI_HWACI_PKTGAINLMT 2      /* bit 1 */
+#define ACPHY_ACI_W2NB_PKTGAINLMT 4       /* bit 2 */
+#define ACPHY_ACI_PREEMPTION 8            /* bit 3 */
+#define ACPHY_ACI_MAX_MODE 15
+
+/* AP environment */
+#define AP_ENV_DETECT_NOT_USED		0 /* We aren't using AP environment detection */
+#define AP_ENV_DENSE			1 /* "Corporate" or other AP dense environment */
+#define AP_ENV_SPARSE			2 /* "Home" or other sparse environment */
+#define AP_ENV_INDETERMINATE		3 /* AP environment hasn't been identified */
+
+#define TRIGGER_NOW				0
+#define TRIGGER_CRS				0x01
+#define TRIGGER_CRSDEASSERT			0x02
+#define TRIGGER_GOODFCS				0x04
+#define TRIGGER_BADFCS				0x08
+#define TRIGGER_BADPLCP				0x10
+#define TRIGGER_CRSGLITCH			0x20
+
+#define	WL_SAMPLEDATA_HEADER_TYPE	1
+#define WL_SAMPLEDATA_HEADER_SIZE	80	/* sample collect header size (bytes) */
+#define	WL_SAMPLEDATA_TYPE		2
+#define	WL_SAMPLEDATA_SEQ		0xff	/* sequence # */
+#define	WL_SAMPLEDATA_MORE_DATA		0x100	/* more data mask */
+
+/* WL_OTA START */
+#define WL_OTA_ARG_PARSE_BLK_SIZE	1200
+#define WL_OTA_TEST_MAX_NUM_RATE	30
+#define WL_OTA_TEST_MAX_NUM_SEQ		100
+
+#define WL_THRESHOLD_LO_BAND	70	/* range from 5250MHz - 5350MHz */
+
+/* radar iovar SET defines */
+#define WL_RADAR_DETECTOR_OFF		0	/* radar detector off */
+#define WL_RADAR_DETECTOR_ON		1	/* radar detector on */
+#define WL_RADAR_SIMULATED		2	/* force radar detector to declare
+						 * detection once
+						 */
+#define WL_RSSI_ANT_VERSION	1	/* current version of wl_rssi_ant_t */
+#define WL_ANT_RX_MAX		2	/* max 2 receive antennas */
+#define WL_ANT_HT_RX_MAX	3	/* max 3 receive antennas/cores */
+#define WL_ANT_IDX_1		0	/* antenna index 1 */
+#define WL_ANT_IDX_2		1	/* antenna index 2 */
+
+#ifndef WL_RSSI_ANT_MAX
+#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
+#elif WL_RSSI_ANT_MAX != 4
+#error "WL_RSSI_ANT_MAX does not match"
+#endif
+
+/* dfs_status iovar-related defines */
+
+/* cac - channel availability check,
+ * ism - in-service monitoring
+ * csa - channel switching announcement
+ */
+
+/* cac state values */
+#define WL_DFS_CACSTATE_IDLE		0	/* state for operating in non-radar channel */
+#define	WL_DFS_CACSTATE_PREISM_CAC	1	/* CAC in progress */
+#define WL_DFS_CACSTATE_ISM		2	/* ISM in progress */
+#define WL_DFS_CACSTATE_CSA		3	/* csa */
+#define WL_DFS_CACSTATE_POSTISM_CAC	4	/* ISM CAC */
+#define WL_DFS_CACSTATE_PREISM_OOC	5	/* PREISM OOC */
+#define WL_DFS_CACSTATE_POSTISM_OOC	6	/* POSTISM OOC */
+#define WL_DFS_CACSTATES		7	/* this many states exist */
+
+/* Defines used with channel_bandwidth for curpower */
+#define WL_BW_20MHZ		0
+#define WL_BW_40MHZ		1
+#define WL_BW_80MHZ		2
+#define WL_BW_160MHZ		3
+
+/* tx_power_t.flags bits */
+#define WL_TX_POWER_F_ENABLED	1
+#define WL_TX_POWER_F_HW		2
+#define WL_TX_POWER_F_MIMO		4
+#define WL_TX_POWER_F_SISO		8
+#define WL_TX_POWER_F_HT		0x10
+#define WL_TX_POWER_F_VHT		0x20
+#define WL_TX_POWER_F_OPENLOOP		0x40
+
+/* Message levels */
+#define WL_ERROR_VAL		0x00000001
+#define WL_TRACE_VAL		0x00000002
+#define WL_PRHDRS_VAL		0x00000004
+#define WL_PRPKT_VAL		0x00000008
+#define WL_INFORM_VAL		0x00000010
+#define WL_TMP_VAL		0x00000020
+#define WL_OID_VAL		0x00000040
+#define WL_RATE_VAL		0x00000080
+#define WL_ASSOC_VAL		0x00000100
+#define WL_PRUSR_VAL		0x00000200
+#define WL_PS_VAL		0x00000400
+#define WL_TXPWR_VAL		0x00000800	/* retired in TOT on 6/10/2009 */
+#define WL_PORT_VAL		0x00001000
+#define WL_DUAL_VAL		0x00002000
+#define WL_WSEC_VAL		0x00004000
+#define WL_WSEC_DUMP_VAL	0x00008000
+#define WL_LOG_VAL		0x00010000
+#define WL_NRSSI_VAL		0x00020000	/* retired in TOT on 6/10/2009 */
+#define WL_LOFT_VAL		0x00040000	/* retired in TOT on 6/10/2009 */
+#define WL_REGULATORY_VAL	0x00080000
+#define WL_PHYCAL_VAL		0x00100000	/* retired in TOT on 6/10/2009 */
+#define WL_RADAR_VAL		0x00200000	/* retired in TOT on 6/10/2009 */
+#define WL_MPC_VAL		0x00400000
+#define WL_APSTA_VAL		0x00800000
+#define WL_DFS_VAL		0x01000000
+#define WL_BA_VAL		0x02000000	/* retired in TOT on 6/14/2010 */
+#define WL_ACI_VAL		0x04000000
+#define WL_MBSS_VAL		0x04000000
+#define WL_CAC_VAL		0x08000000
+#define WL_AMSDU_VAL		0x10000000
+#define WL_AMPDU_VAL		0x20000000
+#define WL_FFPLD_VAL		0x40000000
+
+/* wl_msg_level is full. For new bits take the next one and AND with
+ * wl_msg_level2 in wl_dbg.h
+ */
+#define WL_DPT_VAL		0x00000001
+#define WL_SCAN_VAL		0x00000002
+#define WL_WOWL_VAL		0x00000004
+#define WL_COEX_VAL		0x00000008
+#define WL_RTDC_VAL		0x00000010
+#define WL_PROTO_VAL		0x00000020
+#define WL_BTA_VAL		0x00000040
+#define WL_CHANINT_VAL		0x00000080
+#define WL_WMF_VAL		0x00000100
+#define WL_P2P_VAL		0x00000200
+#define WL_ITFR_VAL		0x00000400
+#define WL_MCHAN_VAL		0x00000800
+#define WL_TDLS_VAL		0x00001000
+#define WL_MCNX_VAL		0x00002000
+#define WL_PROT_VAL		0x00004000
+#define WL_PSTA_VAL		0x00008000
+#define WL_TSO_VAL		0x00010000
+#define WL_TRF_MGMT_VAL		0x00020000
+#define WL_LPC_VAL	        0x00040000
+#define WL_L2FILTER_VAL		0x00080000
+#define WL_TXBF_VAL		0x00100000
+#define WL_P2PO_VAL		0x00200000
+#define WL_TBTT_VAL		0x00400000
+#define WL_NIC_VAL		0x00800000
+#define WL_MQ_VAL		0x01000000
+
+/* This level is currently used in Phoenix2 only */
+#define WL_SRSCAN_VAL		0x02000000
+
+#define WL_WNM_VAL		0x04000000
+#define WL_PWRSEL_VAL		0x10000000
+#define WL_NET_DETECT_VAL	0x20000000
+#define WL_PCIE_VAL		0x40000000
+
+/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier
+ * rather than a message-type of its own
+ */
+#define WL_TIMESTAMP_VAL        0x80000000
+
+/* max # of leds supported by GPIO (gpio pin# == led index#) */
+#define	WL_LED_NUMGPIO		32	/* gpio 0-31 */
+
+/* led per-pin behaviors */
+#define	WL_LED_OFF		0		/* always off */
+#define	WL_LED_ON		1		/* always on */
+#define	WL_LED_ACTIVITY		2		/* activity */
+#define	WL_LED_RADIO		3		/* radio enabled */
+#define	WL_LED_ARADIO		4		/* 5  Ghz radio enabled */
+#define	WL_LED_BRADIO		5		/* 2.4Ghz radio enabled */
+#define	WL_LED_BGMODE		6		/* on if gmode, off if bmode */
+#define	WL_LED_WI1		7
+#define	WL_LED_WI2		8
+#define	WL_LED_WI3		9
+#define	WL_LED_ASSOC		10		/* associated state indicator */
+#define	WL_LED_INACTIVE		11		/* null behavior (clears default behavior) */
+#define	WL_LED_ASSOCACT		12		/* on when associated; blink fast for activity */
+#define WL_LED_WI4		13
+#define WL_LED_WI5		14
+#define	WL_LED_BLINKSLOW	15		/* blink slow */
+#define	WL_LED_BLINKMED		16		/* blink med */
+#define	WL_LED_BLINKFAST	17		/* blink fast */
+#define	WL_LED_BLINKCUSTOM	18		/* blink custom */
+#define	WL_LED_BLINKPERIODIC	19		/* blink periodic (custom 1000ms / off 400ms) */
+#define WL_LED_ASSOC_WITH_SEC	20		/* when connected with security */
+						/* keep on for 300 sec */
+#define WL_LED_START_OFF	21		/* off upon boot, could be turned on later */
+#define WL_LED_WI6		22
+#define WL_LED_WI7		23
+#define WL_LED_WI8		24
+#define	WL_LED_NUMBEHAVIOR	25
+
+/* led behavior numeric value format */
+#define	WL_LED_BEH_MASK		0x7f		/* behavior mask */
+#define	WL_LED_AL_MASK		0x80		/* activelow (polarity) bit */
+
+/* number of bytes needed to define a proper bit mask for MAC event reporting */
+#define BCMIO_ROUNDUP(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
+#define BCMIO_NBBY		8
+/* number of bytes needed to define a mask for MAC event reporting */
+#define WL_EVENTING_MASK_LEN	(((WLC_E_LAST) / 8) + (((WLC_E_LAST % 8) > 0) ? 1 : 0))
+
+
+/* join preference types */
+#define WL_JOIN_PREF_RSSI	1	/* by RSSI */
+#define WL_JOIN_PREF_WPA	2	/* by akm and ciphers */
+#define WL_JOIN_PREF_BAND	3	/* by 802.11 band */
+#define WL_JOIN_PREF_RSSI_DELTA	4	/* by 802.11 band only if RSSI delta condition matches */
+#define WL_JOIN_PREF_TRANS_PREF	5	/* defined by requesting AP */
+
+/* band preference */
+#define WLJP_BAND_ASSOC_PREF	255	/* use what WLC_SET_ASSOC_PREFER ioctl specifies */
+
+/* any multicast cipher suite */
+#define WL_WPA_ACP_MCS_ANY	"\x00\x00\x00\x00"
+
+/* 802.11h measurement types */
+#define WLC_MEASURE_TPC			1
+#define WLC_MEASURE_CHANNEL_BASIC	2
+#define WLC_MEASURE_CHANNEL_CCA		3
+#define WLC_MEASURE_CHANNEL_RPI		4
+
+/* regulatory enforcement levels */
+#define SPECT_MNGMT_OFF			0		/* both 11h and 11d disabled */
+#define SPECT_MNGMT_LOOSE_11H		1		/* allow non-11h APs in scan lists */
+#define SPECT_MNGMT_STRICT_11H		2		/* prune out non-11h APs from scan list */
+#define SPECT_MNGMT_STRICT_11D		3		/* switch to 802.11D mode */
+/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE
+ * adoption is done regardless of capability spectrum_management
+ */
+#define SPECT_MNGMT_LOOSE_11H_D		4		/* operation defined above */
+
+#define WL_CHAN_VALID_HW	(1 << 0)	/* valid with current HW */
+#define WL_CHAN_VALID_SW	(1 << 1)	/* valid with current country setting */
+#define WL_CHAN_BAND_5G		(1 << 2)	/* 5GHz-band channel */
+#define WL_CHAN_RADAR		(1 << 3)	/* radar sensitive  channel */
+#define WL_CHAN_INACTIVE	(1 << 4)	/* temporarily inactive due to radar */
+#define WL_CHAN_PASSIVE		(1 << 5)	/* channel is in passive mode */
+#define WL_CHAN_RESTRICTED	(1 << 6)	/* restricted use channel */
+
+/* BTC mode used by "btc_mode" iovar */
+#define	WL_BTC_DISABLE		0	/* disable BT coexistence */
+#define WL_BTC_FULLTDM      1	/* full TDM COEX */
+#define WL_BTC_ENABLE       1	/* full TDM COEX to maintain backward compatiblity */
+#define WL_BTC_PREMPT      2    /* full TDM COEX with preemption */
+#define WL_BTC_LITE        3	/* light weight coex for large isolation platform */
+#define WL_BTC_PARALLEL		4   /* BT and WLAN run in parallel with separate antenna  */
+#define WL_BTC_HYBRID		5   /* hybrid coex, only ack is allowed to transmit in BT slot */
+#define WL_BTC_DEFAULT		8	/* set the default mode for the device */
+#define WL_INF_BTC_DISABLE      0
+#define WL_INF_BTC_ENABLE       1
+#define WL_INF_BTC_AUTO         3
+
+/* BTC wire used by "btc_wire" iovar */
+#define	WL_BTC_DEFWIRE		0	/* use default wire setting */
+#define WL_BTC_2WIRE		2	/* use 2-wire BTC */
+#define WL_BTC_3WIRE		3	/* use 3-wire BTC */
+#define WL_BTC_4WIRE		4	/* use 4-wire BTC */
+
+/* BTC flags: BTC configuration that can be set by host */
+#define WL_BTC_FLAG_PREMPT               (1 << 0)
+#define WL_BTC_FLAG_BT_DEF               (1 << 1)
+#define WL_BTC_FLAG_ACTIVE_PROT          (1 << 2)
+#define WL_BTC_FLAG_SIM_RSP              (1 << 3)
+#define WL_BTC_FLAG_PS_PROTECT           (1 << 4)
+#define WL_BTC_FLAG_SIM_TX_LP	         (1 << 5)
+#define WL_BTC_FLAG_ECI                  (1 << 6)
+#define WL_BTC_FLAG_LIGHT                (1 << 7)
+#define WL_BTC_FLAG_PARALLEL             (1 << 8)
+
+/* maximum channels returned by the get valid channels iovar */
+#define WL_NUMCHANNELS		64
+
+/* max number of chanspecs (used by the iovar to calc. buf space) */
+#define WL_NUMCHANSPECS 110
+
+/* WDS link local endpoint WPA role */
+#define WL_WDS_WPA_ROLE_AUTH	0	/* authenticator */
+#define WL_WDS_WPA_ROLE_SUP	1	/* supplicant */
+#define WL_WDS_WPA_ROLE_AUTO	255	/* auto, based on mac addr value */
+
+/* Base offset values */
+#define WL_PKT_FILTER_BASE_PKT   0
+#define WL_PKT_FILTER_BASE_END   1
+#define WL_PKT_FILTER_BASE_D11_H 2 /* May be removed */
+#define WL_PKT_FILTER_BASE_D11_D 3 /* May be removed */
+#define WL_PKT_FILTER_BASE_ETH_H 4
+#define WL_PKT_FILTER_BASE_ETH_D 5
+#define WL_PKT_FILTER_BASE_ARP_H 6
+#define WL_PKT_FILTER_BASE_ARP_D 7 /* May be removed */
+#define WL_PKT_FILTER_BASE_IP4_H 8
+#define WL_PKT_FILTER_BASE_IP4_D 9
+#define WL_PKT_FILTER_BASE_IP6_H 10
+#define WL_PKT_FILTER_BASE_IP6_D 11
+#define WL_PKT_FILTER_BASE_TCP_H 12
+#define WL_PKT_FILTER_BASE_TCP_D 13 /* May be removed */
+#define WL_PKT_FILTER_BASE_UDP_H 14
+#define WL_PKT_FILTER_BASE_UDP_D 15
+#define WL_PKT_FILTER_BASE_IP6_P 16
+#define WL_PKT_FILTER_BASE_COUNT 17 /* May be removed */
+
+/* String mapping for bases that may be used by applications or debug */
+#define WL_PKT_FILTER_BASE_NAMES \
+	{ "START", WL_PKT_FILTER_BASE_PKT },   \
+	{ "END",   WL_PKT_FILTER_BASE_END },   \
+	{ "ETH_H", WL_PKT_FILTER_BASE_ETH_H }, \
+	{ "ETH_D", WL_PKT_FILTER_BASE_ETH_D }, \
+	{ "D11_H", WL_PKT_FILTER_BASE_D11_H }, \
+	{ "D11_D", WL_PKT_FILTER_BASE_D11_D }, \
+	{ "ARP_H", WL_PKT_FILTER_BASE_ARP_H }, \
+	{ "IP4_H", WL_PKT_FILTER_BASE_IP4_H }, \
+	{ "IP4_D", WL_PKT_FILTER_BASE_IP4_D }, \
+	{ "IP6_H", WL_PKT_FILTER_BASE_IP6_H }, \
+	{ "IP6_D", WL_PKT_FILTER_BASE_IP6_D }, \
+	{ "IP6_P", WL_PKT_FILTER_BASE_IP6_P }, \
+	{ "TCP_H", WL_PKT_FILTER_BASE_TCP_H }, \
+	{ "TCP_D", WL_PKT_FILTER_BASE_TCP_D }, \
+	{ "UDP_H", WL_PKT_FILTER_BASE_UDP_H }, \
+	{ "UDP_D", WL_PKT_FILTER_BASE_UDP_D }
+
+/* Flags for a pattern list element */
+#define WL_PKT_FILTER_MFLAG_NEG 0x0001
+
+/*
+ * Packet engine interface
+ */
+
+#define WL_PKTENG_PER_TX_START			0x01
+#define WL_PKTENG_PER_TX_STOP			0x02
+#define WL_PKTENG_PER_RX_START			0x04
+#define WL_PKTENG_PER_RX_WITH_ACK_START		0x05
+#define WL_PKTENG_PER_TX_WITH_ACK_START		0x06
+#define WL_PKTENG_PER_RX_STOP			0x08
+#define WL_PKTENG_PER_MASK			0xff
+
+#define WL_PKTENG_SYNCHRONOUS			0x100	/* synchronous flag */
+
+#define WL_PKTENG_MAXPKTSZ				16384	/* max pktsz limit for pkteng */
+
+#define NUM_80211b_RATES	4
+#define NUM_80211ag_RATES	8
+#define NUM_80211n_RATES	32
+#define NUM_80211_RATES		(NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES)
+
+/*
+ * WOWL capability/override settings
+ */
+#define WL_WOWL_MAGIC           (1 << 0)    /* Wakeup on Magic packet */
+#define WL_WOWL_NET             (1 << 1)    /* Wakeup on Netpattern */
+#define WL_WOWL_DIS             (1 << 2)    /* Wakeup on loss-of-link due to Disassoc/Deauth */
+#define WL_WOWL_RETR            (1 << 3)    /* Wakeup on retrograde TSF */
+#define WL_WOWL_BCN             (1 << 4)    /* Wakeup on loss of beacon */
+#define WL_WOWL_TST             (1 << 5)    /* Wakeup after test */
+#define WL_WOWL_M1              (1 << 6)    /* Wakeup after PTK refresh */
+#define WL_WOWL_EAPID           (1 << 7)    /* Wakeup after receipt of EAP-Identity Req */
+#define WL_WOWL_PME_GPIO        (1 << 8)    /* Wakeind via PME(0) or GPIO(1) */
+#define WL_WOWL_NEEDTKIP1       (1 << 9)    /* need tkip phase 1 key to be updated by the driver */
+#define WL_WOWL_GTK_FAILURE     (1 << 10)   /* enable wakeup if GTK fails */
+#define WL_WOWL_EXTMAGPAT       (1 << 11)   /* support extended magic packets */
+#define WL_WOWL_ARPOFFLOAD      (1 << 12)   /* support ARP/NS/keepalive offloading */
+#define WL_WOWL_WPA2            (1 << 13)   /* read protocol version for EAPOL frames */
+#define WL_WOWL_KEYROT          (1 << 14)   /* If the bit is set, use key rotaton */
+#define WL_WOWL_BCAST           (1 << 15)   /* If the bit is set, frm received was bcast frame */
+#define WL_WOWL_SCANOL          (1 << 16)   /* If the bit is set, scan offload is enabled */
+#define WL_WOWL_TCPKEEP_TIME    (1 << 17)   /* Wakeup on tcpkeep alive timeout */
+#define WL_WOWL_MDNS_CONFLICT   (1 << 18)   /* Wakeup on mDNS Conflict Resolution */
+#define WL_WOWL_MDNS_SERVICE    (1 << 19)   /* Wakeup on mDNS Service Connect */
+#define WL_WOWL_TCPKEEP_DATA    (1 << 20)   /* tcp keepalive got data */
+#define WL_WOWL_FW_HALT         (1 << 21)   /* Firmware died in wowl mode */
+#define WL_WOWL_ENAB_HWRADIO    (1 << 22)   /* Enable detection of radio button changes */
+#define WL_WOWL_MIC_FAIL        (1 << 23)   /* Offloads detected MIC failure(s) */
+#define WL_WOWL_LINKDOWN        (1 << 31)   /* Link Down indication in WoWL mode */
+
+#define WL_WOWL_TCPKEEP         (1 << 20)   /* temp copy to satisfy automerger */
+#define MAGIC_PKT_MINLEN 102    /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
+
+#define WOWL_PATTEN_TYPE_ARP	(1 << 0)	/* ARP offload Pattern */
+#define WOWL_PATTEN_TYPE_NA	(1 << 1)	/* NA offload Pattern */
+
+#define MAGIC_PKT_MINLEN	102    /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
+#define MAGIC_PKT_NUM_MAC_ADDRS	16
+
+
+/* Overlap BSS Scan parameters default, minimum, maximum */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT		20	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN			5	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX			1000	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT		10	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN			10	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX			1000	/* unit TU */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT	300	/* unit Sec */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN		10	/* unit Sec */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX		900	/* unit Sec */
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT	5
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN	5
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX	100
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT	200	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN	200	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX	10000	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT	20	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN	20	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX	10000	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT	25	/* unit percent */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN		0	/* unit percent */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX		100	/* unit percent */
+
+#define WL_MIN_NUM_OBSS_SCAN_ARG 7	/* minimum number of arguments required for OBSS Scan */
+
+#define WL_COEX_INFO_MASK		0x07
+#define WL_COEX_INFO_REQ		0x01
+#define	WL_COEX_40MHZ_INTOLERANT	0x02
+#define	WL_COEX_WIDTH20			0x04
+
+#define	WLC_RSSI_INVALID	 0	/* invalid RSSI value */
+
+#define MAX_RSSI_LEVELS 8
+
+/* **** EXTLOG **** */
+#define EXTLOG_CUR_VER		0x0100
+
+#define MAX_ARGSTR_LEN		18 /* At least big enough for storing ETHER_ADDR_STR_LEN */
+
+/* log modules (bitmap) */
+#define LOG_MODULE_COMMON	0x0001
+#define LOG_MODULE_ASSOC	0x0002
+#define LOG_MODULE_EVENT	0x0004
+#define LOG_MODULE_MAX		3			/* Update when adding module */
+
+/* log levels */
+#define WL_LOG_LEVEL_DISABLE	0
+#define WL_LOG_LEVEL_ERR	1
+#define WL_LOG_LEVEL_WARN	2
+#define WL_LOG_LEVEL_INFO	3
+#define WL_LOG_LEVEL_MAX	WL_LOG_LEVEL_INFO	/* Update when adding level */
+
+/* flag */
+#define LOG_FLAG_EVENT		1
+
+/* log arg_type */
+#define LOG_ARGTYPE_NULL	0
+#define LOG_ARGTYPE_STR		1	/* %s */
+#define LOG_ARGTYPE_INT		2	/* %d */
+#define LOG_ARGTYPE_INT_STR	3	/* %d...%s */
+#define LOG_ARGTYPE_STR_INT	4	/* %s...%d */
+
+/* 802.11 Mgmt Packet flags */
+#define VNDR_IE_BEACON_FLAG	0x1
+#define VNDR_IE_PRBRSP_FLAG	0x2
+#define VNDR_IE_ASSOCRSP_FLAG	0x4
+#define VNDR_IE_AUTHRSP_FLAG	0x8
+#define VNDR_IE_PRBREQ_FLAG	0x10
+#define VNDR_IE_ASSOCREQ_FLAG	0x20
+#define VNDR_IE_IWAPID_FLAG	0x40 /* vendor IE in IW advertisement protocol ID field */
+#define VNDR_IE_CUSTOM_FLAG	0x100 /* allow custom IE id */
+
+#if defined(WLP2P)
+/* P2P Action Frames flags (spec ordered) */
+#define VNDR_IE_GONREQ_FLAG     0x001000
+#define VNDR_IE_GONRSP_FLAG     0x002000
+#define VNDR_IE_GONCFM_FLAG     0x004000
+#define VNDR_IE_INVREQ_FLAG     0x008000
+#define VNDR_IE_INVRSP_FLAG     0x010000
+#define VNDR_IE_DISREQ_FLAG     0x020000
+#define VNDR_IE_DISRSP_FLAG     0x040000
+#define VNDR_IE_PRDREQ_FLAG     0x080000
+#define VNDR_IE_PRDRSP_FLAG     0x100000
+
+#define VNDR_IE_P2PAF_SHIFT	12
+#endif /* WLP2P */
+
+/* channel interference measurement (chanim) related defines */
+
+/* chanim mode */
+#define CHANIM_DISABLE	0	/* disabled */
+#define CHANIM_DETECT	1	/* detection only */
+#define CHANIM_EXT		2	/* external state machine */
+#define CHANIM_ACT		3	/* full internal state machine, detect + act */
+#define CHANIM_MODE_MAX 4
+
+/* define for apcs reason code */
+#define APCS_INIT		0
+#define APCS_IOCTL		1
+#define APCS_CHANIM		2
+#define APCS_CSTIMER		3
+#define APCS_BTA		4
+#define APCS_TXDLY		5
+#define APCS_NONACSD		6
+#define APCS_DFS_REENTRY	7
+#define APCS_TXFAIL		8
+#define APCS_MAX		9
+
+/* number of ACS record entries */
+#define CHANIM_ACS_RECORD			10
+
+/* CHANIM */
+#define CCASTATS_TXDUR  0
+#define CCASTATS_INBSS  1
+#define CCASTATS_OBSS   2
+#define CCASTATS_NOCTG  3
+#define CCASTATS_NOPKT  4
+#define CCASTATS_DOZE   5
+#define CCASTATS_TXOP	6
+#define CCASTATS_GDTXDUR        7
+#define CCASTATS_BDTXDUR        8
+#define CCASTATS_MAX    9
+
+#define WL_CHANIM_COUNT_ALL	0xff
+#define WL_CHANIM_COUNT_ONE	0x1
+
+/* ap tpc modes */
+#define	AP_TPC_OFF		0
+#define	AP_TPC_BSS_PWR		1	/* BSS power control */
+#define AP_TPC_AP_PWR		2	/* AP power control */
+#define	AP_TPC_AP_BSS_PWR	3	/* Both AP and BSS power control */
+#define AP_TPC_MAX_LINK_MARGIN	127
+
+/* ap tpc modes */
+#define	AP_TPC_OFF		0
+#define	AP_TPC_BSS_PWR		1	/* BSS power control */
+#define AP_TPC_AP_PWR		2	/* AP power control */
+#define	AP_TPC_AP_BSS_PWR	3	/* Both AP and BSS power control */
+#define AP_TPC_MAX_LINK_MARGIN	127
+
+/* state */
+#define WL_P2P_DISC_ST_SCAN	0
+#define WL_P2P_DISC_ST_LISTEN	1
+#define WL_P2P_DISC_ST_SEARCH	2
+
+/* i/f type */
+#define WL_P2P_IF_CLIENT	0
+#define WL_P2P_IF_GO		1
+#define WL_P2P_IF_DYNBCN_GO	2
+#define WL_P2P_IF_DEV		3
+
+/* count */
+#define WL_P2P_SCHED_RSVD	0
+#define WL_P2P_SCHED_REPEAT	255	/* anything > 255 will be treated as 255 */
+
+#define WL_P2P_SCHED_FIXED_LEN		3
+
+/* schedule type */
+#define WL_P2P_SCHED_TYPE_ABS		0	/* Scheduled Absence */
+#define WL_P2P_SCHED_TYPE_REQ_ABS	1	/* Requested Absence */
+
+/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */
+#define WL_P2P_SCHED_ACTION_NONE	0	/* no action */
+#define WL_P2P_SCHED_ACTION_DOZE	1	/* doze */
+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
+#define WL_P2P_SCHED_ACTION_GOOFF	2	/* turn off GO beacon/prbrsp functions */
+/* schedule option - WL_P2P_SCHED_TYPE_XXX */
+#define WL_P2P_SCHED_ACTION_RESET	255	/* reset */
+
+/* schedule option - WL_P2P_SCHED_TYPE_ABS */
+#define WL_P2P_SCHED_OPTION_NORMAL	0	/* normal start/interval/duration/count */
+#define WL_P2P_SCHED_OPTION_BCNPCT	1	/* percentage of beacon interval */
+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
+#define WL_P2P_SCHED_OPTION_TSFOFS	2	/* normal start/internal/duration/count with
+						 * start being an offset of the 'current' TSF
+						 */
+
+/* feature flags */
+#define WL_P2P_FEAT_GO_CSA	(1 << 0)	/* GO moves with the STA using CSA method */
+#define WL_P2P_FEAT_GO_NOLEGACY	(1 << 1)	/* GO does not probe respond to non-p2p probe
+						 * requests
+						 */
+#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2)	/* Restrict p2p dev interface from responding */
+
+/* n-mode support capability */
+/* 2x2 includes both 1x1 & 2x2 devices
+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
+ * control it independently
+ */
+#define WL_11N_2x2			1
+#define WL_11N_3x3			3
+#define WL_11N_4x4			4
+
+/* define 11n feature disable flags */
+#define WLFEATURE_DISABLE_11N		0x00000001
+#define WLFEATURE_DISABLE_11N_STBC_TX	0x00000002
+#define WLFEATURE_DISABLE_11N_STBC_RX	0x00000004
+#define WLFEATURE_DISABLE_11N_SGI_TX	0x00000008
+#define WLFEATURE_DISABLE_11N_SGI_RX	0x00000010
+#define WLFEATURE_DISABLE_11N_AMPDU_TX	0x00000020
+#define WLFEATURE_DISABLE_11N_AMPDU_RX	0x00000040
+#define WLFEATURE_DISABLE_11N_GF	0x00000080
+
+/* Proxy STA modes */
+#define PSTA_MODE_DISABLED		0
+#define PSTA_MODE_PROXY			1
+#define PSTA_MODE_REPEATER		2
+
+/* op code in nat_cfg */
+#define NAT_OP_ENABLE		1	/* enable NAT on given interface */
+#define NAT_OP_DISABLE		2	/* disable NAT on given interface */
+#define NAT_OP_DISABLE_ALL	3	/* disable NAT on all interfaces */
+
+/* NAT state */
+#define NAT_STATE_ENABLED	1	/* NAT is enabled */
+#define NAT_STATE_DISABLED	2	/* NAT is disabled */
+
+#define CHANNEL_5G_LOW_START	36	/* 5G low (36..48) CDD enable/disable bit mask */
+#define CHANNEL_5G_MID_START	52	/* 5G mid (52..64) CDD enable/disable bit mask */
+#define CHANNEL_5G_HIGH_START	100	/* 5G high (100..140) CDD enable/disable bit mask */
+#define CHANNEL_5G_UPPER_START	149	/* 5G upper (149..161) CDD enable/disable bit mask */
+
+/* D0 Coalescing */
+#define IPV4_ARP_FILTER		0x0001
+#define IPV4_NETBT_FILTER	0x0002
+#define IPV4_LLMNR_FILTER	0x0004
+#define IPV4_SSDP_FILTER	0x0008
+#define IPV4_WSD_FILTER		0x0010
+#define IPV6_NETBT_FILTER	0x0200
+#define IPV6_LLMNR_FILTER	0x0400
+#define IPV6_SSDP_FILTER	0x0800
+#define IPV6_WSD_FILTER		0x1000
+
+/* Network Offload Engine */
+#define NWOE_OL_ENABLE		0x00000001
+
+/*
+ * Traffic management structures/defines.
+ */
+
+/* Traffic management bandwidth parameters */
+#define TRF_MGMT_MAX_PRIORITIES                 3
+
+#define TRF_MGMT_FLAG_ADD_DSCP                  0x0001  /* Add DSCP to IP TOS field */
+#define TRF_MGMT_FLAG_DISABLE_SHAPING           0x0002  /* Don't shape traffic */
+#define TRF_MGMT_FLAG_MANAGE_LOCAL_TRAFFIC      0x0008  /* Manage traffic over our local subnet */
+#define TRF_MGMT_FLAG_FILTER_ON_MACADDR         0x0010  /* filter on MAC address */
+#define TRF_MGMT_FLAG_NO_RX                     0x0020  /* do not apply fiters to rx packets */
+
+#define TRF_FILTER_MAC_ADDR              0x0001 /* L2 filter use dst mac address for filtering */
+#define TRF_FILTER_IP_ADDR               0x0002 /* L3 filter use ip ddress for filtering */
+#define TRF_FILTER_L4                    0x0004 /* L4 filter use tcp/udp for filtering */
+#define TRF_FILTER_DWM                   0x0008 /* L3 filter use DSCP for filtering */
+#define TRF_FILTER_FAVORED               0x0010 /* Tag the packet FAVORED */
+
+/* WNM/NPS subfeatures mask */
+#define WL_WNM_BSSTRANS		0x00000001
+#define WL_WNM_PROXYARP		0x00000002
+#define WL_WNM_MAXIDLE		0x00000004
+#define WL_WNM_TIMBC		0x00000008
+#define WL_WNM_TFS		0x00000010
+#define WL_WNM_SLEEP		0x00000020
+#define WL_WNM_DMS		0x00000040
+#define WL_WNM_FMS		0x00000080
+#define WL_WNM_NOTIF		0x00000100
+#define WL_WNM_MAX		0x00000200
+
+#ifndef ETHER_MAX_DATA
+#define ETHER_MAX_DATA	1500
+#endif /* ETHER_MAX_DATA */
+
+/* Different discovery modes for dpt */
+#define	DPT_DISCOVERY_MANUAL	0x01	/* manual discovery mode */
+#define	DPT_DISCOVERY_AUTO	0x02	/* auto discovery mode */
+#define	DPT_DISCOVERY_SCAN	0x04	/* scan-based discovery mode */
+
+/* different path selection values */
+#define DPT_PATHSEL_AUTO	0	/* auto mode for path selection */
+#define DPT_PATHSEL_DIRECT	1	/* always use direct DPT path */
+#define DPT_PATHSEL_APPATH	2	/* always use AP path */
+
+/* different ops for deny list */
+#define DPT_DENY_LIST_ADD	1	/* add to dpt deny list */
+#define DPT_DENY_LIST_REMOVE	2	/* remove from dpt deny list */
+
+/* different ops for manual end point */
+#define DPT_MANUAL_EP_CREATE	1	/* create manual dpt endpoint */
+#define DPT_MANUAL_EP_MODIFY	2	/* modify manual dpt endpoint */
+#define DPT_MANUAL_EP_DELETE	3	/* delete manual dpt endpoint */
+
+/* flags to indicate DPT status */
+#define	DPT_STATUS_ACTIVE	0x01	/* link active (though may be suspended) */
+#define	DPT_STATUS_AES		0x02	/* link secured through AES encryption */
+#define	DPT_STATUS_FAILED	0x04	/* DPT link failed */
+
+#ifdef WLTDLS
+/* different ops for manual end point */
+#define TDLS_MANUAL_EP_CREATE	1	/* create manual dpt endpoint */
+#define TDLS_MANUAL_EP_MODIFY	2	/* modify manual dpt endpoint */
+#define TDLS_MANUAL_EP_DELETE	3	/* delete manual dpt endpoint */
+#define TDLS_MANUAL_EP_PM		4	/*  put dpt endpoint in PM mode */
+#define TDLS_MANUAL_EP_WAKE		5	/* wake up dpt endpoint from PM */
+#define TDLS_MANUAL_EP_DISCOVERY	6	/* discover if endpoint is TDLS capable */
+#define TDLS_MANUAL_EP_CHSW		7	/* channel switch */
+#define TDLS_MANUAL_EP_WFD_TPQ	8	/* WiFi-Display Tunneled Probe reQuest */
+
+/* modes */
+#define TDLS_WFD_IE_TX			0
+#define TDLS_WFD_IE_RX			1
+#define TDLS_WFD_PROBE_IE_TX	2
+#define TDLS_WFD_PROBE_IE_RX	3
+#endif /* WLTDLS */
+
+/* define for flag */
+#define TSPEC_PENDING		0	/* TSPEC pending */
+#define TSPEC_ACCEPTED		1	/* TSPEC accepted */
+#define TSPEC_REJECTED		2	/* TSPEC rejected */
+#define TSPEC_UNKNOWN		3	/* TSPEC unknown */
+#define TSPEC_STATUS_MASK	7	/* TSPEC status mask */
+
+#ifdef BCMCCX
+/* "wlan_reason" iovar interface */
+#define WL_WLAN_ASSOC_REASON_NORMAL_NETWORK	0 /* normal WLAN network setup */
+#define WL_WLAN_ASSOC_REASON_ROAM_FROM_CELLULAR_NETWORK	1 /* roam from Cellular network */
+#define WL_WLAN_ASSOC_REASON_ROAM_FROM_LAN	2 /* roam from LAN */
+#define WL_WLAN_ASSOC_REASON_MAX		2 /* largest value allowed */
+#endif /* BCMCCX */
+
+/* Software feature flag defines used by wlfeatureflag */
+#ifdef WLAFTERBURNER
+#define WL_SWFL_ABBFL       0x0001 /* Allow Afterburner on systems w/o hardware BFL */
+#define WL_SWFL_ABENCORE    0x0002 /* Allow AB on non-4318E chips */
+#endif /* WLAFTERBURNER */
+#define WL_SWFL_NOHWRADIO	0x0004
+#define WL_SWFL_FLOWCONTROL     0x0008 /* Enable backpressure to OS stack */
+#define WL_SWFL_WLBSSSORT	0x0010 /* Per-port supports sorting of BSS */
+
+#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */
+
+#define CSA_BROADCAST_ACTION_FRAME	0	/* csa broadcast action frame */
+#define CSA_UNICAST_ACTION_FRAME	  1 /* csa unicast action frame */
+
+/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER.
+ *
+ * (-100 < value < 0)   value is used directly as a roaming trigger in dBm
+ * (0 <= value) value specifies a logical roaming trigger level from
+ *                      the list below
+ *
+ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never
+ * the logical roam trigger value.
+ */
+#define WLC_ROAM_TRIGGER_DEFAULT	0 /* default roaming trigger */
+#define WLC_ROAM_TRIGGER_BANDWIDTH	1 /* optimize for bandwidth roaming trigger */
+#define WLC_ROAM_TRIGGER_DISTANCE	2 /* optimize for distance roaming trigger */
+#define WLC_ROAM_TRIGGER_AUTO		3 /* auto-detect environment */
+#define WLC_ROAM_TRIGGER_MAX_VALUE	3 /* max. valid value */
+
+#define WLC_ROAM_NEVER_ROAM_TRIGGER	(-100) /* Avoid Roaming by setting a large value */
+
+/* Preferred Network Offload (PNO, formerly PFN) defines */
+#define WPA_AUTH_PFN_ANY	0xffffffff	/* for PFN, match only ssid */
+
+#define SORT_CRITERIA_BIT		0
+#define AUTO_NET_SWITCH_BIT		1
+#define ENABLE_BKGRD_SCAN_BIT		2
+#define IMMEDIATE_SCAN_BIT		3
+#define	AUTO_CONNECT_BIT		4
+#define	ENABLE_BD_SCAN_BIT		5
+#define ENABLE_ADAPTSCAN_BIT		6
+#define IMMEDIATE_EVENT_BIT		8
+#define SUPPRESS_SSID_BIT		9
+#define ENABLE_NET_OFFLOAD_BIT		10
+
+#define SORT_CRITERIA_MASK		0x0001
+#define AUTO_NET_SWITCH_MASK		0x0002
+#define ENABLE_BKGRD_SCAN_MASK		0x0004
+#define IMMEDIATE_SCAN_MASK		0x0008
+#define	AUTO_CONNECT_MASK		0x0010
+
+#define ENABLE_BD_SCAN_MASK		0x0020
+#define ENABLE_ADAPTSCAN_MASK		0x00c0
+#define IMMEDIATE_EVENT_MASK		0x0100
+#define SUPPRESS_SSID_MASK		0x0200
+#define ENABLE_NET_OFFLOAD_MASK		0x0400
+
+#define PFN_VERSION			2
+#define PFN_SCANRESULT_VERSION		1
+#define MAX_PFN_LIST_COUNT		16
+
+#define PFN_COMPLETE			1
+#define PFN_INCOMPLETE			0
+
+#define DEFAULT_BESTN			2
+#define DEFAULT_MSCAN			0
+#define DEFAULT_REPEAT			10
+#define DEFAULT_EXP				2
+
+#define WL_PFN_SUPPRESSFOUND_MASK	0x08
+#define WL_PFN_SUPPRESSLOST_MASK	0x10
+#define WL_PFN_RSSI_MASK			0xff00
+#define WL_PFN_RSSI_SHIFT			8
+
+#define WL_PFN_REPORT_ALLNET    0
+#define WL_PFN_REPORT_SSIDNET   1
+#define WL_PFN_REPORT_BSSIDNET  2
+
+#define WL_PFN_CFG_FLAGS_PROHIBITED	0x00000001	/* Accept and use prohibited channels */
+#define WL_PFN_CFG_FLAGS_RESERVED	0xfffffffe	/* Remaining reserved for future use */
+
+#define WL_PFN_HIDDEN_BIT		2
+#define PNO_SCAN_MAX_FW			508*1000	/* max time scan time in msec */
+#define PNO_SCAN_MAX_FW_SEC		PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */
+#define PNO_SCAN_MIN_FW_SEC		10			/* min time scan time in SEC */
+#define WL_PFN_HIDDEN_MASK		0x4
+
+/* TCP Checksum Offload error injection for testing */
+#define TOE_ERRTEST_TX_CSUM	0x00000001
+#define TOE_ERRTEST_RX_CSUM	0x00000002
+#define TOE_ERRTEST_RX_CSUM2	0x00000004
+
+/* ARP Offload feature flags for arp_ol iovar */
+#define ARP_OL_AGENT		0x00000001
+#define ARP_OL_SNOOP		0x00000002
+#define ARP_OL_HOST_AUTO_REPLY	0x00000004
+#define ARP_OL_PEER_AUTO_REPLY	0x00000008
+
+/* ARP Offload error injection */
+#define ARP_ERRTEST_REPLY_PEER	0x1
+#define ARP_ERRTEST_REPLY_HOST	0x2
+
+#define ARP_MULTIHOMING_MAX	8	/* Maximum local host IP addresses */
+#define ND_MULTIHOMING_MAX 10	/* Maximum local host IP addresses */
+#define ND_REQUEST_MAX		5	/* Max set of offload params */
+
+
+/* AOAC wake event flag */
+#define WAKE_EVENT_NLO_DISCOVERY_BIT		1
+#define WAKE_EVENT_AP_ASSOCIATION_LOST_BIT	2
+#define WAKE_EVENT_GTK_HANDSHAKE_ERROR_BIT 4
+#define WAKE_EVENT_4WAY_HANDSHAKE_REQUEST_BIT 8
+
+#define MAX_NUM_WOL_PATTERN	16 /* LOGO requirements min 16 */
+
+/* Packet filter operation mode */
+/* True: 1; False: 0 */
+#define PKT_FILTER_MODE_FORWARD_ON_MATCH		1
+/* Enable and disable pkt_filter as a whole */
+#define PKT_FILTER_MODE_DISABLE					2
+/* Cache first matched rx pkt(be queried by host later) */
+#define PKT_FILTER_MODE_PKT_CACHE_ON_MATCH		4
+/* If pkt_filter is enabled and no filter is set, don't forward anything */
+#define PKT_FILTER_MODE_PKT_FORWARD_OFF_DEFAULT 8
+
+#ifdef DONGLEOVERLAYS
+#define OVERLAY_IDX_MASK		0x000000ff
+#define OVERLAY_IDX_SHIFT		0
+#define OVERLAY_FLAGS_MASK		0xffffff00
+#define OVERLAY_FLAGS_SHIFT		8
+/* overlay written to device memory immediately after loading the base image */
+#define OVERLAY_FLAG_POSTLOAD	0x100
+/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */
+#define OVERLAY_FLAG_DEFER_DL	0x200
+/* overlay downloaded prior to the host going to sleep */
+#define OVERLAY_FLAG_PRESLEEP	0x400
+#define OVERLAY_DOWNLOAD_CHUNKSIZE	1024
+#endif /* DONGLEOVERLAYS */
+
+/* reuse two number in the sc/rc space */
+#define	SMFS_CODE_MALFORMED 0xFFFE
+#define SMFS_CODE_IGNORED	0xFFFD
+
+/* RFAWARE def */
+#define BCM_ACTION_RFAWARE		0x77
+#define BCM_ACTION_RFAWARE_DCS  0x01
+
+/* DCS reason code define */
+#define BCM_DCS_IOVAR		0x1
+#define BCM_DCS_UNKNOWN		0xFF
+
+
+#ifdef PROP_TXSTATUS
+/* Bit definitions for tlv iovar */
+/*
+ * enable RSSI signals:
+ * WLFC_CTL_TYPE_RSSI
+ */
+#define WLFC_FLAGS_RSSI_SIGNALS			0x0001
+
+/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals:
+ *
+ * WLFC_CTL_TYPE_MAC_OPEN
+ * WLFC_CTL_TYPE_MAC_CLOSE
+ *
+ * WLFC_CTL_TYPE_INTERFACE_OPEN
+ * WLFC_CTL_TYPE_INTERFACE_CLOSE
+ *
+ * WLFC_CTL_TYPE_MACDESC_ADD
+ * WLFC_CTL_TYPE_MACDESC_DEL
+ *
+ */
+#define WLFC_FLAGS_XONXOFF_SIGNALS		0x0002
+
+/* enable (status, fifo_credit, mac_credit) signals
+ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT
+ * WLFC_CTL_TYPE_TXSTATUS
+ * WLFC_CTL_TYPE_FIFO_CREDITBACK
+ */
+#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS	0x0004
+
+#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE	0x0008
+#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE	0x0010
+#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE	0x0020
+#define WLFC_FLAGS_HOST_RXRERODER_ACTIVE	0x0040
+#define WLFC_FLAGS_PKT_STAMP_SIGNALS		0x0080
+
+#endif /* PROP_TXSTATUS */
+
+#define WL_TIMBC_STATUS_AP_UNKNOWN	255	/* AP status for internal use only */
+
+#define WL_DFRTS_LOGIC_OFF	0	/* Feature is disabled */
+#define WL_DFRTS_LOGIC_OR	1	/* OR all non-zero threshold conditions */
+#define WL_DFRTS_LOGIC_AND	2	/* AND all non-zero threshold conditions */
+
+/* Definitions for Reliable Multicast */
+#define WL_RELMCAST_MAX_CLIENT		32
+#define WL_RELMCAST_FLAG_INBLACKLIST	1
+#define WL_RELMCAST_FLAG_ACTIVEACKER	2
+#define WL_RELMCAST_FLAG_RELMCAST	4
+
+/* structures for proximity detection device role */
+#define WL_PROXD_MODE_DISABLE	0
+#define WL_PROXD_MODE_NEUTRAL	1
+#define WL_PROXD_MODE_INITIATOR	2
+#define WL_PROXD_MODE_TARGET	3
+#define WL_PROXD_RANDOM_WAKEUP	0x8000
+
+
+#ifdef NET_DETECT
+#define NET_DETECT_MAX_WAKE_DATA_SIZE	2048
+#define NET_DETECT_MAX_PROFILES		16
+#define NET_DETECT_MAX_CHANNELS		50
+#endif /* NET_DETECT */
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+#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)	/* some countries don't support any channel */
+
+#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
+
+/* Override bit for WLC_SET_TXPWR.  if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE	(1U<<31)
+#define WL_TXPWR_NEG   (1U<<30)
+
+
+/* phy types (returned by WLC_GET_PHYTPE) */
+#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
+
+/* Values for PM */
+#define PM_OFF	0
+#define PM_MAX	1
+#define PM_FAST 2
+#define PM_FORCE_OFF 3		/* use this bit to force PM off even bt is active */
+
+#define WL_WME_CNT_VERSION	1	/* current version of wl_wme_cnt_t */
+
+/* fbt_cap: FBT assoc / reassoc modes. */
+#define WLC_FBT_CAP_DRV_4WAY_AND_REASSOC  1 /* Driver 4-way handshake & reassoc (WLFBT). */
+
+/* monitor_promisc_level bits */
+#define WL_MONPROMISC_PROMISC 0x0001
+#define WL_MONPROMISC_CTRL 0x0002
+#define WL_MONPROMISC_FCS 0x0004
+
+/* TCP Checksum Offload defines */
+#define TOE_TX_CSUM_OL		0x00000001
+#define TOE_RX_CSUM_OL		0x00000002
+
+#endif /* wlioctl_defs_h */
diff --git a/src/common/include/proto/802.11.h b/src/common/include/proto/802.11.h
new file mode 100644
index 0000000..b26593c
--- /dev/null
+++ b/src/common/include/proto/802.11.h
@@ -0,0 +1,3686 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id: 802.11.h 444070 2013-12-18 13:20:12Z $
+ */
+
+#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;
+
+
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_40MHZ	1
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_80MHZ	2
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_160MHZ	3
+
+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_BSSTRANS		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 TDLS_CAP_MAX_BIT		39		
+
+
+
+#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_SUBTYPE_ANY_PSPOLL(s)	(((s) & 10) != 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_DSSSOFDM_REQUIRED 26	
+#define DOT11_SC_ASSOC_HT_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_ASSOC_VHT_REQUIRED	104	
+
+#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 TLV_BODY_LEN_MAX	255	
+
+
+#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_NEIGHBOR_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_FMS_DESCR_ID			86	
+#define DOT11_MNG_FMS_REQ_ID			87	
+#define DOT11_MNG_FMS_RESP_ID			88	
+#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_BSS_MEMBERSHIP_HT         0xFF  
+#define DOT11_BSS_MEMBERSHIP_VHT        0xFE  
+
+
+#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_EXT_CHAN_SWITCHING	2
+
+#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_BSSTRANS_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_OBSS_COEX_MNG_SUPPORT	0x01	
+
+
+#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_BSSTRANS_QUERY		6
+#define DOT11_WNM_ACTION_BSSTRANS_REQ		7
+#define DOT11_WNM_ACTION_BSSTRANS_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_REQ		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_RESP		27
+#define DOT11_WNM_ACTION_TFS_NOTIFY_RESP	28
+
+
+#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_bsstrans_query {
+	uint8 category;			
+	uint8 action;			
+	uint8 token;			
+	uint8 reason;			
+	uint8 data[1];			
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_query dot11_bsstrans_query_t;
+#define DOT11_BSSTRANS_QUERY_LEN 4	
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_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_bsstrans_req dot11_bsstrans_req_t;
+#define DOT11_BSSTRANS_REQ_LEN 7	
+
+
+#define DOT11_BSSTRANS_REQMODE_PREF_LIST_INCL		0x01
+#define DOT11_BSSTRANS_REQMODE_ABRIDGED			0x02
+#define DOT11_BSSTRANS_REQMODE_DISASSOC_IMMINENT	0x04
+#define DOT11_BSSTRANS_REQMODE_BSS_TERM_INCL		0x08
+#define DOT11_BSSTRANS_REQMODE_ESS_DISASSOC_IMNT	0x10
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_resp {
+	uint8 category;			
+	uint8 action;			
+	uint8 token;			
+	uint8 status;			
+	uint8 term_delay;		
+	uint8 data[1];			
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_resp dot11_bsstrans_resp_t;
+#define DOT11_BSSTRANS_RESP_LEN 5	
+
+
+#define DOT11_BSSTRANS_RESP_STATUS_ACCEPT			0
+#define DOT11_BSSTRANS_RESP_STATUS_REJECT			1
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_BCN		2
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_CAP		3
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_UNDESIRED		4
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_DELAY_REQ		5
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_BSS_LIST_PROVIDED	6
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_NO_SUITABLE_BSS		7
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_LEAVING_ESS		8
+
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_max_idle_period_ie {
+	uint8 id;				
+	uint8 len;
+	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 len;
+	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 len;
+	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
+#define DOT11_TIMBC_STATUS_RESERVED		4
+
+
+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	
+#define DOT11_TIM_IE_FIXED_TOTAL_LEN	5	
+
+
+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)	
+#define DOT11_TIMBC_LEN			11	
+
+
+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 len;
+	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 len;
+	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 len;
+	uint8 tfs_id;
+	uint8 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		2	
+
+
+#define DOT11_TFS_ACTCODE_DELETE	1
+#define DOT11_TFS_ACTCODE_NOTIFY	2
+
+
+#define DOT11_TFS_REQ_TFS_SE_ID		1
+#define DOT11_TFS_REQ_VENDOR_SE_ID	221
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 data[1];				
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_se dot11_tfs_se_t;
+
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp_ie {
+	uint8 id;				
+	uint8 len;
+	uint8 tfs_id;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp_ie dot11_tfs_resp_ie_t;
+#define DOT11_TFS_RESP_IE_LEN		1	
+
+
+#define DOT11_TFS_RESP_TFS_STATUS_SE_ID		1
+#define DOT11_TFS_RESP_TFS_SE_ID		2
+#define DOT11_TFS_RESP_VENDOR_SE_ID		221
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_status_se {
+	uint8 sub_id;				
+	uint8 len;
+	uint8 resp_st;
+	uint8 data[1];				
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_status_se dot11_tfs_status_se_t;
+#define DOT11_TFS_STATUS_SE_LEN			1	
+
+
+
+#define DOT11_TFS_STATUS_ACCEPT			0
+#define DOT11_TFS_STATUS_DENY_FORMAT		1
+#define DOT11_TFS_STATUS_DENY_RESOURCE		2
+#define DOT11_TFS_STATUS_DENY_POLICY		4
+#define DOT11_TFS_STATUS_DENY_UNSPECIFIED	5
+#define DOT11_TFS_STATUS_ALTPREF_POLICY		7
+#define DOT11_TFS_STATUS_ALTPREF_TCLAS_UNSUPP	14
+
+
+#define DOT11_FMS_TFS_STATUS_ACCEPT		0
+#define DOT11_FMS_TFS_STATUS_DENY_FORMAT	1
+#define DOT11_FMS_TFS_STATUS_DENY_RESOURCE	2
+#define DOT11_FMS_TFS_STATUS_DENY_MULTIPLE_DI	3
+#define DOT11_FMS_TFS_STATUS_DENY_POLICY	4
+#define DOT11_FMS_TFS_STATUS_DENY_UNSPECIFIED	5
+#define DOT11_FMS_TFS_STATUS_ALT_DIFF_DI	6
+#define DOT11_FMS_TFS_STATUS_ALT_POLICY		7
+#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_DI	8
+#define DOT11_FMS_TFS_STATUS_ALT_MCRATE		9
+#define DOT11_FMS_TFS_STATUS_TERM_POLICY	10
+#define DOT11_FMS_TFS_STATUS_TERM_RESOURCE	11
+#define DOT11_FMS_TFS_STATUS_TERM_HIGHER_PRIO	12
+#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_MDI	13
+#define DOT11_FMS_TFS_STATUS_ALT_TCLAS_UNSUPP	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_req {
+	uint8 category;				
+	uint8 action;				
+	uint8 tfs_id_cnt;			
+	uint8 tfs_id[1];			
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify_req dot11_tfs_notify_req_t;
+#define DOT11_TFS_NOTIFY_REQ_LEN	3	
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_resp {
+	uint8 category;				
+	uint8 action;				
+	uint8 tfs_id_cnt;			
+	uint8 tfs_id[1];			
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify_resp dot11_tfs_notify_resp_t;
+#define DOT11_TFS_NOTIFY_RESP_LEN	3	
+
+
+
+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 len;
+	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 len;
+	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 len;
+	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 len;
+	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 len;
+	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 len;
+	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 len;
+	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_fms_req {
+	uint8 category;				
+	uint8 action;				
+	uint8 token;				
+	uint8 data[1];				
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_req dot11_fms_req_t;
+#define DOT11_FMS_REQ_LEN		3	
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_fms_resp {
+	uint8 category;				
+	uint8 action;				
+	uint8 token;				
+	uint8 data[1];				
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_resp dot11_fms_resp_t;
+#define DOT11_FMS_RESP_LEN		3	
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_fms_desc {
+	uint8 id;
+	uint8 len;
+	uint8 num_fms_cnt;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_desc dot11_fms_desc_t;
+#define DOT11_FMS_DESC_LEN		1	
+
+#define DOT11_FMS_CNTR_MAX		0x8
+#define DOT11_FMS_CNTR_ID_MASK		0x7
+#define DOT11_FMS_CNTR_ID_SHIFT		0x0
+#define DOT11_FMS_CNTR_COUNT_MASK	0xf1
+#define DOT11_FMS_CNTR_SHIFT		0x3
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_fms_req_ie {
+	uint8 id;
+	uint8 len;
+	uint8 fms_token;			
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_req_ie dot11_fms_req_ie_t;
+#define DOT11_FMS_REQ_IE_FIX_LEN		1	
+
+BWL_PRE_PACKED_STRUCT struct dot11_rate_id_field {
+	uint8 mask;
+	uint8 mcs_idx;
+	uint16 rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rate_id_field dot11_rate_id_field_t;
+#define DOT11_RATE_ID_FIELD_MCS_SEL_MASK	0x7
+#define DOT11_RATE_ID_FIELD_MCS_SEL_OFFSET	0
+#define DOT11_RATE_ID_FIELD_RATETYPE_MASK	0x18
+#define DOT11_RATE_ID_FIELD_RATETYPE_OFFSET	3
+#define DOT11_RATE_ID_FIELD_LEN		sizeof(dot11_rate_id_field_t)
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_fms_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 interval;
+	uint8 max_interval;
+	dot11_rate_id_field_t rate;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_se dot11_fms_se_t;
+#define DOT11_FMS_REQ_SE_LEN		6	
+
+#define DOT11_FMS_REQ_SE_ID_FMS		1	
+#define DOT11_FMS_REQ_SE_ID_VS		221	
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_fms_resp_ie {
+	uint8 id;
+	uint8 len;
+	uint8 fms_token;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_resp_ie dot11_fms_resp_ie_t;
+#define DOT11_FMS_RESP_IE_FIX_LEN		1	
+
+
+#define DOT11_FMS_STATUS_SE_ID_FMS	1	
+#define DOT11_FMS_STATUS_SE_ID_TCLAS	2	
+#define DOT11_FMS_STATUS_SE_ID_VS	221	
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_fms_status_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 status;
+	uint8 interval;
+	uint8 max_interval;
+	uint8 fmsid;
+	uint8 counter;
+	dot11_rate_id_field_t rate;
+	uint8 mcast_addr[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_status_se dot11_fms_status_se_t;
+#define DOT11_FMS_STATUS_SE_LEN		15	
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_status_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 fmsid;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_status_se dot11_tclas_status_se_t;
+#define DOT11_TCLAS_STATUS_SE_LEN		1	
+
+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_FM		8
+#define DOT11_RRM_CAP_CLM		9
+#define DOT11_RRM_CAP_NHM		10
+#define DOT11_RRM_CAP_SM		11
+#define DOT11_RRM_CAP_LCIM		12
+#define DOT11_RRM_CAP_LCIA		13
+#define DOT11_RRM_CAP_TSCM		14
+#define DOT11_RRM_CAP_TTSCM		15
+#define DOT11_RRM_CAP_AP_CHANREP	16
+#define DOT11_RRM_CAP_RMMIB		17
+
+#define DOT11_RRM_CAP_MPTI		27
+#define DOT11_RRM_CAP_NBRTSFO		28
+#define DOT11_RRM_CAP_RCPI		29
+#define DOT11_RRM_CAP_RSNI		30
+#define DOT11_RRM_CAP_BSSAAD		31
+#define DOT11_RRM_CAP_BSSAAC		32
+#define DOT11_RRM_CAP_AI		33
+
+
+#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;
+
+
+
+#define DOT11_NGBR_TSF_INFO_SE_ID	1
+#define DOT11_NGBR_CCS_SE_ID		2
+#define DOT11_NGBR_BSSTRANS_PREF_SE_ID	3
+#define DOT11_NGBR_BSS_TERM_DUR_SE_ID	4
+#define DOT11_NGBR_BEARING_SE_ID	5
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bsstrans_pref_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 preference;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ngbr_bsstrans_pref_se dot11_ngbr_bsstrans_pref_se_t;
+#define DOT11_NGBR_BSSTRANS_PREF_SE_LEN	1
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bss_term_dur_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 tsf[8];
+	uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ngbr_bss_term_dur_se dot11_ngbr_bss_term_dur_se_t;
+#define DOT11_NGBR_BSS_TERM_DUR_SE_LEN	10
+
+
+#define DOT11_NGBR_BI_REACHABILTY_UNKN	0x0002
+#define DOT11_NGBR_BI_REACHABILTY	0x0003
+#define DOT11_NGBR_BI_SEC		0x0004
+#define DOT11_NGBR_BI_KEY_SCOPE		0x0008
+#define DOT11_NGBR_BI_CAP		0x03f0
+#define DOT11_NGBR_BI_CAP_SPEC_MGMT	0x0010
+#define DOT11_NGBR_BI_CAP_QOS		0x0020
+#define DOT11_NGBR_BI_CAP_APSD		0x0040
+#define DOT11_NGBR_BI_CAP_RDIO_MSMT	0x0080
+#define DOT11_NGBR_BI_CAP_DEL_BA	0x0100
+#define DOT11_NGBR_BI_CAP_IMM_BA	0x0200
+#define DOT11_NGBR_BI_MOBILITY		0x0400
+#define DOT11_NGBR_BI_HT		0x0800
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_neighbor_rep_ie {
+	uint8 id;
+	uint8 len;
+	struct ether_addr bssid;
+	uint32 bssid_info;
+	uint8 reg;		
+	uint8 channel;
+	uint8 phytype;
+	uint8 data[1]; 		
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_neighbor_rep_ie dot11_neighbor_rep_ie_t;
+#define DOT11_NEIGHBOR_REP_IE_FIXED_LEN	13
+
+
+
+#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 RWL_WIFI_DEFAULT		0
+#define RWL_WIFI_FIND_MY_PEER		9 
+#define RWL_WIFI_FOUND_PEER		10 
+#define RWL_ACTION_WIFI_FRAG_TYPE	85 
+
+#define PROXD_AF_TYPE			11 
+#define BRCM_RELMACST_AF_TYPE	        12 
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+#define BRCM_EVT_WL_BSS_INFO	64
+
+
+BWL_PRE_PACKED_STRUCT struct brcm_prop_ie_s {
+	uint8 id;		
+	uint8 len;		
+	uint8 oui[3];		
+	uint8 type;		
+	uint16 cap;		
+} BWL_POST_PACKED_STRUCT;
+typedef struct brcm_prop_ie_s brcm_prop_ie_t;
+
+#define BRCM_PROP_IE_LEN	6	
+
+#define DPT_IE_TYPE		2
+#define BRCM_SYSCAP_IE_TYPE	3
+#define WET_TUNNEL_IE_TYPE	3
+#endif 
+
+
+#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_FIXED_LEN	(VNDR_IE_HDR_LEN + VNDR_IE_MIN_LEN)
+
+#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_HDRLEN	        (sizeof(member_of_brcm_prop_ie_t))
+#define MEMBER_OF_BRCM_PROP_IE_TYPE		54
+
+
+BWL_PRE_PACKED_STRUCT struct relmcast_brcm_prop_ie {
+	uint8 id;
+	uint8 len;
+	uint8 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*sizeof(uint8)))
+
+#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 HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_MASK	0x400
+#define HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_SHIFT	10
+#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_MASK 0x18000
+#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_SHIFT 15
+
+#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_128K    4       
+#define AMPDU_RX_FACTOR_256K    5       
+#define AMPDU_RX_FACTOR_512K    6       
+#define AMPDU_RX_FACTOR_1024K   7       
+
+#define AMPDU_RX_FACTOR_BASE    8*1024  
+#define AMPDU_RX_FACTOR_BASE_PWR	13	
+
+#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	
+
+
+
+
+
+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
+
+
+
+#ifdef P2P_IE_OVRD
+#define WFA_OUI			MAC_OUI
+#else
+#define WFA_OUI			"\x50\x6F\x9A"	
+#endif 
+#define WFA_OUI_LEN		3		
+#ifdef P2P_IE_OVRD
+#define WFA_OUI_TYPE_P2P	MAC_OUI_TYPE_P2P
+#else
+#define WFA_OUI_TYPE_TPC	8
+#define WFA_OUI_TYPE_P2P	9
+#endif
+
+#define WFA_OUI_TYPE_TPC	8
+#ifdef WLTDLS
+#define WFA_OUI_TYPE_TPQ	4	
+#define WFA_OUI_TYPE_TPS	5	
+#define WFA_OUI_TYPE_WFD	10
+#endif 
+#define WFA_OUI_TYPE_HS20	0x10
+
+
+#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_IGTK_KEYS		2
+#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_TK_SIZE		16
+#define TKIP_MIC_KEY_SIZE	8
+#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 AES_GCM_MIC_SIZE	16	
+
+#define AES256_KEY_SIZE		32	
+#define AES256_MIC_SIZE		16	
+
+
+#define WCN_OUI			"\x00\x50\xf2"	
+#define WCN_TYPE		4	
+
+#ifdef BCMWAPI_WPI
+#define SMS4_KEY_LEN		16
+#define SMS4_WPI_CBC_MAC_LEN	16
+#endif
+
+
+
+
+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[16];			
+} 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"
+
+#ifdef BCMWAPI_WAI
+#define WAPI_IE_MIN_LEN 	20	
+#define WAPI_VERSION		1	
+#define WAPI_VERSION_LEN	2	
+#define WAPI_OUI		"\x00\x14\x72"	
+#define WAPI_OUI_LEN		DOT11_OUI_LEN	
+#endif 
+
+
+#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 TDLS_SETUP_REQ				0
+#define TDLS_SETUP_RESP				1
+#define TDLS_SETUP_CONFIRM			2
+#define TDLS_TEARDOWN				3
+#define TDLS_PEER_TRAFFIC_IND			4
+#define TDLS_CHANNEL_SWITCH_REQ			5
+#define TDLS_CHANNEL_SWITCH_RESP		6
+#define TDLS_PEER_PSM_REQ			7
+#define TDLS_PEER_PSM_RESP			8
+#define TDLS_PEER_TRAFFIC_RESP			9
+#define TDLS_DISCOVERY_REQ			10
+
+
+#define TDLS_DISCOVERY_RESP			14
+
+
+#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_EAP_EXPANDED				254
+
+
+#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
+
+
+BWL_PRE_PACKED_STRUCT struct hs20_ie {
+	uint8 oui[3];
+	uint8 type;
+	uint8 config;
+} BWL_POST_PACKED_STRUCT;
+typedef struct hs20_ie hs20_ie_t;
+#define HS20_IE_LEN 5	
+
+
+typedef enum {
+	DOT11_2GHZ_20MHZ_CLASS_12		= 81,	
+	DOT11_5GHZ_20MHZ_CLASS_1		= 115,	
+	DOT11_5GHZ_20MHZ_CLASS_2_DFS	= 118,	
+	DOT11_5GHZ_20MHZ_CLASS_3		= 124,	
+	DOT11_5GHZ_20MHZ_CLASS_4_DFS	= 121,	
+	DOT11_5GHZ_20MHZ_CLASS_5		= 125,	
+	DOT11_5GHZ_40MHZ_CLASS_22		= 116,	
+	DOT11_5GHZ_40MHZ_CLASS_23_DFS 	= 119,	
+	DOT11_5GHZ_40MHZ_CLASS_24_DFS	= 122,	
+	DOT11_5GHZ_40MHZ_CLASS_25		= 126,	
+	DOT11_5GHZ_40MHZ_CLASS_27		= 117,	
+	DOT11_5GHZ_40MHZ_CLASS_28_DFS	= 120,	
+	DOT11_5GHZ_40MHZ_CLASS_29_DFS	= 123,	
+	DOT11_5GHZ_40MHZ_CLASS_30		= 127,	
+	DOT11_2GHZ_40MHZ_CLASS_32		= 83,	
+	DOT11_2GHZ_40MHZ_CLASS_33		= 84,	
+} dot11_op_class_t;
+
+
+#include <packed_section_end.h>
+
+#endif 
diff --git a/src/common/include/proto/802.11_bta.h b/src/common/include/proto/802.11_bta.h
new file mode 100644
index 0000000..1a53542
--- /dev/null
+++ b/src/common/include/proto/802.11_bta.h
@@ -0,0 +1,27 @@
+/*
+ * BT-AMP (BlueTooth Alternate Mac and Phy) 802.11 PAL (Protocol Adaptation Layer)
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: 802.11_bta.h 382882 2013-02-04 23:24:31Z $
+*/
+
+#ifndef _802_11_BTA_H_
+#define _802_11_BTA_H_
+
+#define BT_SIG_SNAP_MPROT		"\xAA\xAA\x03\x00\x19\x58"
+
+/* BT-AMP 802.11 PAL Protocols */
+#define BTA_PROT_L2CAP				1
+#define	BTA_PROT_ACTIVITY_REPORT		2
+#define BTA_PROT_SECURITY			3
+#define BTA_PROT_LINK_SUPERVISION_REQUEST	4
+#define BTA_PROT_LINK_SUPERVISION_REPLY		5
+
+/* BT-AMP 802.11 PAL AMP_ASSOC Type IDs */
+#define BTA_TYPE_ID_MAC_ADDRESS			1
+#define BTA_TYPE_ID_PREFERRED_CHANNELS		2
+#define BTA_TYPE_ID_CONNECTED_CHANNELS		3
+#define BTA_TYPE_ID_CAPABILITIES		4
+#define BTA_TYPE_ID_VERSION			5
+#endif /* _802_11_bta_h_ */
diff --git a/src/common/include/proto/802.11_ccx.h b/src/common/include/proto/802.11_ccx.h
new file mode 100644
index 0000000..1036b65
--- /dev/null
+++ b/src/common/include/proto/802.11_ccx.h
@@ -0,0 +1,703 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Fundamental types and constants relating to 802.11 ccx
+ *
+ * $Id: 802.11_ccx.h 382882 2013-02-04 23:24:31Z $
+ */
+
+#ifndef _802_11_CCX_H_
+#define _802_11_CCX_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+#define DOT11_LEAP_AUTH		0x80	/* LEAP authentication frame payload constants */
+
+/* Management Frame Information Element IDs */
+#define DOT11_MNG_AIRONET_ID		133	/* AIRONET id */
+#define DOT11_MNG_CELL_PWR_ID		150	/* cell power id */
+#define DOT11_MNG_CCKM_REASSOC_ID	156	/* CCKM reassoc. id */
+#define DOT11_MNG_SSIDL_ID		221	/* SSIDL id */
+
+#define CISCO_BASE			8	/* base of Cisco cipher and AKM vals */
+
+/* AIRONET IE field offsets */
+#define AIRONET_IE_REFRESH_RATE	3	/* refresh rate */
+#define AIRONET_IE_CWMIN	4	/* cwmin */
+#define AIRONET_IE_CWMAX	6	/* cwmax */
+#define AIRONET_IE_CKIP		8	/* CKIP */
+#define AIRONET_IE_NAME		10	/* offset to AP/Machine name field */
+#define	AIRONET_IE_DEVICE_ID	0x66	/* Dev ID */
+
+#define AIRONET_IE_MAX_NAME_LEN		16	/* device name length, include NULL */
+
+BWL_PRE_PACKED_STRUCT struct aironet_assoc_ie {
+	uint8	id;			/* IE ID  */
+	uint8	len;		/* IE length */
+	uint8	load;
+	uint8	hops;
+	uint8	device;
+	uint8	refresh_rate;
+	uint16  cwmin;
+	uint16  cwmax;
+	uint8	flags;
+	uint8	distance;
+	char	name[AIRONET_IE_MAX_NAME_LEN];	/* AP or Client's machine name */
+	uint16	num_assoc;	/* number of clients associated */
+	uint16	radiotype;
+} BWL_POST_PACKED_STRUCT;
+typedef	struct aironet_assoc_ie aironet_assoc_ie_t;
+
+/* CKIP Negotiation bit fields */
+#define	CKIP_MIC		0x08	/* MIC */
+#define CKIP_KP			0x10	/* KP */
+#define CKIP_LLC_SNAP_LEN		8 /* SKIP LLC SNAP header length */
+
+#define CCX_DDP_LLC_SNAP_LEN	8	/* CCX DDP/LLC/SNAP length */
+#define CCX_DDP_MSG_LEN		40	/* CCX DDP MSG length */
+#define CCX_DDP_ROGUE_NAME_LEN	16	/* CCX DDP rogue name length */
+BWL_PRE_PACKED_STRUCT struct ccx_ddp_pkt_s {
+	struct ether_header eth;
+	struct dot11_llc_snap_header snap;
+	uint16 msg_len;
+	uint8  msg_type;
+	uint8  fcn_code;
+	struct ether_addr dest_mac;
+	struct ether_addr src_mac;
+	uint16 fail_reason;
+	struct ether_addr rogue_mac;
+	uint8  rogue_name[CCX_DDP_ROGUE_NAME_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_ddp_pkt_s	ccx_ddp_pkt_t;
+#define CCX_DDP_PKT_LEN		(ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN + CCX_DDP_MSG_LEN)
+
+#define	CCX_ROGUE_INVALID_AUTH	1	/* invalid auth. */
+#define	CCX_ROGUE_LEAP_TIMEOUT	2	/* LEAP timeout */
+#define CCX_ROGUE_CHAN_FROM_AP	3	/* chan. from AP */
+#define	CCX_ROGUE_CHAN_TO_AP	4	/* chan. to AP */
+
+/* Cisco/Aironet IAPP packet defs */
+
+#define CISCO_AIRONET_OUI	"\x00\x40\x96"	/* Cisco AIRONET OUI */
+#define CISCO_AIRONET_SNAP	"\xAA\xAA\x03\x00\x40\x96\x00\x00"	/* Cisco AIRONET SNAP */
+
+#define CCX_IAPP_ID_MASK	0xf000	/* IAPP id mask */
+#define CCX_IAPP_LEN_MASK	0x0fff	/* IAPP len mask */
+#define CCX_IAPP_ID_SHIFT	12		/* IAPP id shift */
+
+#define CCX_IAPP_ID_CONTROL	0x0000	/* IAPP id control */
+#define CCX_IAPP_TYPE_RM	0x32	/* IAPP radio measurement request type */
+#define	CCX_IAPP_TYPE_ROAM	0x33	/* IAPP roam request type */
+#define CCX_IAPP_TYPE_LINK_TEST	0x41	/* IAPP link test request type */
+#define CCX_IAPP_SUBTYPE_REQ	0x01	/* IAPP subtype request */
+#define CCX_IAPP_SUBTYPE_ROAM_REP	0x81	/* IAPP subtype report */
+#define	CCX_IAPP_SUBTYPE_ROAM_REQ	0x82	/* IAPP subtype directed roam request */
+#define CCXv2_IAPP_TYPE_ROAM		0x30	/* CCXv2 IAPP roam request type */
+#define	CCXv2_IAPP_SUBTYPE_ROAM_REQ	0x00	/* CCXv2 IAPP roam subtype request */
+#define CCX_IAPP_TYPE_DIAG_GROUP	0x60	/* IAPP type for diag. group(s64, s65 and s66) */
+
+/* Cisco/Aironet IAPP header */
+BWL_PRE_PACKED_STRUCT struct ccx_iapp_hdr {
+	uint16	id_len;		/* IAPP ID & Length */
+	uint8	type;		/* IAPP Type */
+	uint8	subtype;	/* IAPP Subtype */
+	struct ether_addr da;
+	struct ether_addr sa;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_iapp_hdr ccx_iapp_hdr_t;
+#define CCX_IAPP_HDR_LEN	16	/* IAPP header length */
+
+/* CCXv2 Transmit Power Control IE */
+BWL_PRE_PACKED_STRUCT struct ccx_cell_pwr {
+	uint8 id;	/* 150, DOT11_MNG_CELL_PWR_ID */
+	uint8 len;
+	uint8 oui[3];	/* 00:40:96, CISCO_AIRONET_OUI */
+	uint8 ver;	/* 0 */
+	uint8 power;	/* signed int dBm */
+	uint8 reserved;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_cell_pwr ccx_cell_pwr_t;
+
+#define CCX_RM_STATE_NORMAL	1	/* Radio Management Capability IE state */
+#define CCX_RM_STATE_MBSSID_MASK	0x0700  /* MBSSID Mask field */
+#define CCX_RM_STATE_MBSSID_SHIFT	8       /* MBSSID Mask field */
+
+/* CCXv2 Radio Management Capability IE */
+BWL_PRE_PACKED_STRUCT struct ccx_radio_mgmt {
+	uint8 id;	/* 221, DOT11_MNG_PROPR_ID */
+	uint8 len;
+	uint8 oui[3];	/* 00:40:96, CISCO_AIRONET_OUI */
+	uint8 ver;	/* 1 */
+	uint16 state;	/* Radio Mgmt state, 1->Normal.  MBSSID mask starts at bit 8 */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_radio_mgmt ccx_radio_mgmt_t;
+
+#define CCX_QOS_IE_TYPE		4	/* CCX QoS IE type */
+#define CCX_QOS_IE_LEN		0x16	/* CCX QoS IE length */
+#define CCX_VERSION_IE_TYPE	3	/* CCX version IE type */
+#define CCX_VERSION_IE_LEN	5	/* CCX version IE length */
+#define CCX_RM_CAP_IE_TYPE	1	/* CCX RM cap IE type */
+
+/* CCXv2 QOS Parameter set IE */
+BWL_PRE_PACKED_STRUCT struct ccx_qos_params {
+	uint8 id;		/* 221, DOT11_MNG_PROPR_ID */
+	uint8 len;
+	uint8 oui[3];		/* 00:40:96, CISCO_AIRONET_OUI */
+	uint8 type;		/* 4 */
+	uint8 unused;
+	uint8 count;		/* incremented when element changes */
+	uint8 aifsn_0;		/* AIFSN class 0 */
+	uint8 ecw_0;		/* ECWmin/ECWmax class 0 */
+	uint16 txop_0;		/* TXOP Limit class 0 */
+	uint8 aifsn_1;		/* AIFSN class 1 */
+	uint8 ecw_1;		/* ECWmin/ECWmax class 1 */
+	uint16 txop_1;		/* TXOP Limit class 1 */
+	uint8 aifsn_2;		/* AIFSN class 2 */
+	uint8 ecw_2;		/* ECWmin/ECWmax class 2 */
+	uint16 txop_2;		/* TXOP Limit class 2 */
+	uint8 aifsn_3;		/* AIFSN class 3 */
+	uint8 ecw_3;		/* ECWmin/ECWmax class 3 */
+	uint16 txop_3;		/* TXOP Limit class 3 */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_qos_params ccx_qos_params_t;
+
+/* CCXv2 Version IE */
+BWL_PRE_PACKED_STRUCT struct ccx_version_ie {
+	uint8 id;      		/* 221, DOT11_MNG_PROPR_ID */
+	uint8 len;
+	uint8 oui[DOT11_OUI_LEN];	/* 00:40:96, CISCO_AIRONET_OUI */
+	uint8 type;		/* 3 */
+	uint8 version;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_version_ie ccx_version_ie_t;
+
+/* CCX Adjacent AP Report IE in roam IAPP packet */
+BWL_PRE_PACKED_STRUCT struct ccx_roam_ap_ie_s {
+	uint16 tag;		/* 0x9b - Adjacent AP report */
+	uint16 len;
+	uint8 oui[DOT11_OUI_LEN];	/* Aironet OUI 0x00 0x40 0x96 0x00 */
+	uint8 ver;
+	struct ether_addr mac;	/* MAC address of AP */
+	uint16 channel;
+	uint16 ssid_len;
+	uint8 ssid[32];
+	uint16 disassoc_time;	/* Seconds that the client has been disassociated */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_roam_ap_ie_s ccx_roam_ap_ie_t;
+#define CCX_ROAM_AP_IE_LEN	52	/* CCX roam AP IE length */
+
+/* CCX IAPP packet sent to AP on association with info on previous AP */
+BWL_PRE_PACKED_STRUCT struct ccx_roam_iapp_pkt_s {
+	struct ether_header eth;
+	struct dot11_llc_snap_header snap;
+	uint16 msg_len;
+	uint8  msg_type;
+	uint8  fcn_code;
+	struct ether_addr dest_mac;
+	struct ether_addr src_mac;
+	ccx_roam_ap_ie_t ap_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_roam_iapp_pkt_s	ccx_roam_iapp_pkt_t;
+
+/* CCX roam IAPP message length */
+#define CCX_ROAM_IAPP_MSG_SIZE 	(sizeof(ccx_roam_iapp_pkt_t) - sizeof(struct ether_header))
+#define CCX_ROAM_ADJ_AP_TAG		0x9b	/* CCX adjacent AP tag */
+
+/* CCXv4 S51 */
+/* CCX roam reason IE in roam IAPP packet */
+BWL_PRE_PACKED_STRUCT struct ccx_roam_reason_ie {
+	uint16 tag;		/* 0x9c - roam reason tag */
+	uint16 len;
+	uint8 oui[DOT11_OUI_LEN];	/* Aironet OUI 0x00 0x40 0x96 0x00 */
+	uint8 ver;
+	uint8 reason;		/* roam reason */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_roam_reason_ie ccx_roam_reason_ie_t;
+#define CCX_ROAM_REASON_IE_LEN	8	/* CCX roam reason IE length */
+
+/* CCX roam neighbor report IE in roam IAPP packet */
+BWL_PRE_PACKED_STRUCT struct ccx_neighbor_rept_ie {
+	uint8	id;		/* CCX_ROAM_NEIGHBOR_REPT_ID */
+	uint8	len;		/* length beyond len */
+	struct ether_addr mac;	/* MAC address of neighbor AP */
+	uint8	channel;	/* current channel of neighbor AP */
+	uint8	band;		/* band of current channel of neighbor AP */
+	uint8	phy_type;	/* PHY type of current channel of neighbor AP */
+	/* variable subelements follows */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_neighbor_rept_ie ccx_neighbor_rept_ie_t;
+#define CCX_NEIGHBOR_REPT_IE_LEN	11	/* CCX neighbor report IE length */
+#define CCX_NEIGHBOR_REPT_IE_LEN_W_H	9	/* CCX_NEIGHBOR_REPT_IE_LEN - header (2) */
+/* RF parameter subelement for neighbor ie */
+BWL_PRE_PACKED_STRUCT struct ccx_radio_param_subie {
+	uint8	sub_id;		/* subelement id */
+	uint8	len;		/* length beyond len */
+	int8	min_rssi;	/* min. recv pwr in dBm required to associate with the AP */
+	int8	ap_tx_pwr;	/* tx pwr in dBm of neighbor AP */
+	int8	sta_tx_pwr;	/* tx pwr in dBm of sta advertised by neighbor AP */
+	int8	roam_delta;	/* roam delta */
+	int8	roam_trigger;	/* roam trigger */
+	uint8	roam_time;	/* transition time(in 0.1s) permmited in roam */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_radio_param_subie ccx_radio_param_subie_t;
+#define CCX_RADIO_PARAM_SUBIE_LEN	8	/* CCX RF parameter sub IE length */
+
+/* TSF info. subelement for neighbor ie */
+BWL_PRE_PACKED_STRUCT struct ccx_tsf_info_subie {
+	uint8	sub_id;		/* subelement id */
+	uint8	len;		/* length beyond len */
+	BWL_PRE_PACKED_STRUCT struct {
+		uint16 offset;	/* TSF time offset in TUs between serving AP and this AP */
+		uint16 bcn_interval;	/* beacon interval of AP */
+	} BWL_POST_PACKED_STRUCT TSF;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_tsf_info_subie ccx_tsf_info_subie_t;
+#define CCX_TSF_INFO_SUBIE_LEN	6	/* CCX TSF info. sub IE length */
+
+/* subelement id */
+#define	CCX_ROAM_SUB_RF_PARAMS	1	/* CCX neighbor element RF subelement id */
+#define	CCX_ROAM_SUB_TSF_INFO	2	/* CCX neighbor element TSF subelement id */
+
+/* roam reason */
+#define CCX_ROAM_UNSPECIFIED	0	/* unspecified */
+#define CCX_ROAM_NORMAL		1	/* poor link(excessive retries, RSSI too low...) */
+#define CCX_ROAM_LOAD_BALANCING	2	/* normal roam, load balancing */
+#define CCX_ROAM_AP_INCAPACITY	3	/* AP has insufficient capacity(TSPEC rejected) */
+#define CCX_ROAM_DIRECTED_ROAM	4	/* Infrastructure directed roam */
+#define CCX_ROAM_FIRST_ASSOC	5	/* first association to WLAN */
+#define CCX_ROAM_IN_NET		6	/* roaming in from cellular or other WAN */
+#define CCX_ROAM_OUT_NET	7	/* roaming out to cellular or other WAN */
+#define CCX_ROAM_BETTER_AP	8	/* normal roaming, better AP found */
+#define CCX_ROAM_LINK_DOWN	9	/* deauthnticated or disassociated from the previous AP */
+
+/* band */
+#define	CCX_CHAN_BAND_2G	0	/* 2.4 GHz band */
+#define	CCX_CHAN_BAND_5G	1	/* 5 GHz band */
+
+#define CCX_ROAM_NEIGHBOR_REPT_ID	0x28	/* CCX roam neighbor report id */
+
+#define CCX_ROAM_REASON_TAG	0x9c	/* roam reason tag */
+
+#if defined(BCMSUP_PSK) || !defined(BCMINTSUP)
+#define CCKM_KRK_LEN		16	/* CCKM KRK length */
+#define CCKM_BTK_LEN		32	/* CCKM BTK length */
+
+#define CCKM_OUI_TYPE		0	/* CCKM OUI type */
+#define CCKM_RSC_LEN		8	/* CCKM RSC length */
+#define	CCKM_MIC_LEN		8	/* CCKM MIC length */
+
+BWL_PRE_PACKED_STRUCT struct cckm_reassoc_req_ie_s {
+	uint8	id;			/* DOT11_MNG_CCKM_REASSOC_ID */
+	uint8	len;			/* length beyond len */
+	uint8	oui[DOT11_OUI_LEN];	/* expect AIRONET_OUI */
+	uint8	oui_type;		/* expect CCKM_OUI_TYPE */
+	uint8	timestamp[DOT11_MNG_TIMESTAMP_LEN];	/* TSF timer value (LE) */
+	uint32 rn;				/* reassociation request number (LE) */
+	uint8	mic[CCKM_MIC_LEN];	/* MIC computed using KRK */
+} BWL_POST_PACKED_STRUCT;
+typedef struct cckm_reassoc_req_ie_s cckm_reassoc_req_ie_t;
+#define CCKM_REASSOC_REQ_IE_LEN		26	/* CCKM reassoc. request IE length */
+
+BWL_PRE_PACKED_STRUCT struct cckm_reassoc_resp_ie_s {
+	uint8	id;			/* DOT11_MNG_CCKM_REASSOC_ID */
+	uint8	len;			/* length beyond len */
+	uint8	oui[DOT11_OUI_LEN];	/* expect AIRONET_OUI */
+	uint8	oui_type;		/* expect CCKM_OUI_TYPE */
+	uint32	rn;			/* rekey value */
+	uint8	ucast_idx;		/* ucast key index; expect 0 */
+	uint8	mcast_idx;		/* mcast key index */
+	uint8	rsc[CCKM_RSC_LEN];	/* mcast RSC */
+	uint16	gtklen;			/* mcast key len */
+	uint8	mic[CCKM_MIC_LEN];	/* msg integrity code */
+	uint8	egtk[1];		/* encrypted group key */
+} BWL_POST_PACKED_STRUCT;
+typedef struct cckm_reassoc_resp_ie_s cckm_reassoc_resp_ie_t;
+#define CCKM_REASSOC_RESP_IE_LEN	31	/* CCKM reassoc. response IE length */
+
+#endif /* BCMSUP_PSK || !BCMINTSUP */
+
+/* CCX Radio Managment definitions, CCX spec section S36 */
+
+#define CCX_RM_IE_HDR_LEN	4	/* length of Radio Mgmt IE ID plus Len */
+
+/* Radio Measurement IE IDs */
+#define CCX_RM_ID_REQUEST	38	/* CCX radio measurement request id */
+#define CCX_RM_ID_REPORT	39	/* CCX radio measurement respond id */
+
+/* Radio Measurement Request Type field */
+#define CCX_RM_TYPE_LOAD	1	/*  CCX radio measurement load request */
+#define CCX_RM_TYPE_NOISE	2	/*  CCX radio measurement noise request */
+#ifndef CCX_SDK	/* CCX SDK defined the same RM types with the same names */
+#define CCX_RM_TYPE_BEACON	3	/*  CCX radio measurement beacon request */
+#define CCX_RM_TYPE_FRAME	4	/*  CCX radio measurement frame request */
+#endif /* CCX_SDK */
+#define CCXv4_RM_TYPE_PATHLOSS	6	/*  CCX radio measurement PathLoss request for CCXv4 */
+#define CCX_RM_TYPE_PATHLOSS	9	/*  CCX radio measurement PathLoss request */
+#define CCX_RM_TYPE_STATISTICS	10	/* CCX radio measurement Statistics request */
+
+/* Radio Measurement Request Mode field */
+#define CCX_RM_MODE_PARALLEL	(1<<0)	/*  CCX radio measurement parallel request */
+#define CCX_RM_MODE_ENABLE	(1<<2)	/*  CCX radio measurement autonomous request */
+#define CCX_RM_MODE_REPORT	(1<<3)	/*  CCX radio measurement report */
+/* Radio Measurement Report Modes */
+#define CCX_RM_MODE_INCAPABLE	(1<<1)	/*  CCX radio measurement incapable */
+#define CCX_RM_MODE_REFUSED	(1<<2)	/*  CCX radio measurement refused */
+
+/* Radio Measurement Beacon scan types */
+#define CCX_RM_BEACON_PASSIVE_SCAN	0	/*  CCX radio measurement beacon passive scan */
+#define CCX_RM_BEACON_ACTIVE_SCAN	1	/*  CCX radio measurement beacon active scan */
+#define CCX_RM_BEACON_TABLE		2	/*  CCX radio measurement beacon table */
+
+/* Radio Measurement Beacon PHY Types */
+#define CCX_RM_PHY_FH		1	/*  CCX radio measurement FH */
+#define CCX_RM_PHY_DSS		2	/*  CCX radio measurement DSS */
+#define CCX_RM_PHY_OFDM		4	/*  CCX radio measurement OFDM */
+#define CCX_RM_PHY_HRDSS	5	/*  CCX radio measurement HRDSS */
+#define CCX_RM_PHY_ERP		6	/*  CCX radio measurement ERP */
+
+/* CCXv2 Radio Measurment Request frame
+ * Encapsulated in Cisco Aironet IAPP frame
+ */
+BWL_PRE_PACKED_STRUCT struct ccx_rm_req {
+	uint16		token;		/* Dialog Token */
+	uint8		delay;		/* Request Activation Delay (TBTTs) */
+	uint8		offset;		/* Request Activation Offset (TUs) */
+	uint8		data[1];	/* Request information elts */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_req ccx_rm_req_t;
+#define CCX_RM_REQ_LEN 4	/*  CCX radio measurement request header length */
+
+/* CCXv2 Radio Measurment Report frame header
+ * Encapsulated in Cisco Aironet IAPP frame
+ */
+BWL_PRE_PACKED_STRUCT struct ccx_rm_rep {
+	uint16		token;		/* Dialog Token */
+	uint8		data[1];	/* Report information elts */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_rep ccx_rm_rep_t;
+#define CCX_RM_REP_LEN		2	/*  CCX radio measurement reponse header length */
+/* Max length of CCXv2 Radio Measurment Report data section based on
+ * the maximum size of the LLC_SNAP encapsulating frame.
+ */
+#define CCX_RM_REP_DATA_MAX_LEN	\
+	(ETHER_MAX_DATA - (DOT11_LLC_SNAP_HDR_LEN +	CCX_IAPP_HDR_LEN +	\
+	CCX_RM_REP_LEN))		/*  CCX radio measurement max report data length */
+
+/* CCXv2 Radio Measurment Request IE
+ * Encapsulated in a CCXv2 Radio Measurment Request frame
+ */
+BWL_PRE_PACKED_STRUCT struct ccx_rm_req_ie {
+	uint16	id;
+	uint16	len;
+	uint16	token;		/* Dialog Token */
+	uint8	mode;
+	uint8	type;
+	/* end of fixed portion */
+	/* variable data, depends on mode and type */
+	uint8	channel;	/* channel for the measurment */
+	uint8	param;		/* measurement parameter */
+	uint16	duration;	/* measurement duration (TUs) */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_req_ie ccx_rm_req_ie_t;
+#define CCX_RM_REQ_IE_FIXED_LEN	8	/*  CCX radio measurement request IE fixed length */
+
+/* CCXv2 Radio Measurment Report IE
+ * Encapsulated in a CCXv2 Radio Measurment Report frame
+ */
+BWL_PRE_PACKED_STRUCT struct ccx_rm_rep_ie {
+	uint16	id;
+	uint16	len;
+	uint16	token;
+	uint8	mode;
+	uint8	type;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_rep_ie ccx_rm_rep_ie_t;
+#define CCX_RM_REP_IE_FIXED_LEN	8	/*  CCX radio measurement report IE fixed length */
+
+BWL_PRE_PACKED_STRUCT struct ccx_rm_beacon_rep {
+	uint8	channel;
+	uint8	spare;
+	uint16	duration;
+	uint8	phy_type;
+	int8	rssi;
+	struct ether_addr bssid;
+	uint32	parent_tsf;
+	uint32	target_tsf_low;
+	uint32	target_tsf_hi;
+	uint16	beacon_interval;
+	uint16	capability;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_beacon_rep ccx_rm_beacon_rep_t;
+#define CCX_RM_BEACON_REP_FIXED_LEN	28	/*  CCX rm beacon report fixed length */
+
+BWL_PRE_PACKED_STRUCT struct ccx_rm_frm_rep_elt {
+	struct ether_addr ta;	/* transmitter address */
+	struct ether_addr bssid;	/* bssid transmitter belongs to */
+	uint8	rssi;	/* average RSSI */
+	uint8	frames;	/* total number of frames */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_frm_rep_elt ccx_rm_frm_rep_elt_t;
+#define CCX_RM_FRAME_REP_ENTRY_LEN	14	/*  CCX rm frame report entry length */
+
+BWL_PRE_PACKED_STRUCT struct ccx_rm_frame_rep {
+	uint8	channel;
+	uint8	spare;
+	uint16	duration;
+	ccx_rm_frm_rep_elt_t	elt[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_frame_rep ccx_rm_frame_rep_t;
+#define CCX_RM_FRAME_REP_FIXED_LEN	4	/*  CCX rm frame report fixed length */
+
+BWL_PRE_PACKED_STRUCT struct ccx_rm_load_rep {
+	uint8	channel;
+	uint8	spare;
+	uint16	duration;
+	uint8	fraction;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_load_rep ccx_rm_load_rep_t;
+#define CCX_RM_LOAD_REP_LEN	5	/*  CCX radio measurement load report length */
+
+BWL_PRE_PACKED_STRUCT struct ccx_rm_noise_rep {
+	uint8	channel;
+	uint8	spare;
+	uint16	duration;
+	uint8	rpi[8];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_noise_rep ccx_rm_noise_rep_t;
+#define CCX_RM_NOISE_REP_LEN	12	/*  CCX radio measurement noise report length */
+
+/* SSIDL Elements.  CCXv4 S53 */
+#define SSIDL_OUI		"\x00\x50\xf2"	/* SSIDL OUI */
+#define SSIDL_OUI_LEN		3	/* SSIDL OUI length */
+#define SSIDL_TYPE		5	/* SSIDL type */
+
+/* extended capability bits */
+#define PRI_EXT_CAP_8021X	1	/* primary ssid supports 802.1x */
+#define PRI_EXT_CAP_WPS		2	/* primary ssid supports WPS */
+
+/* hidden ssid capability field */
+#define SEC_CAP_MC_CIPHER_MASK	0x0000000f	/* mcast cipher mask */
+#define SEC_CAP_UC_CIPHER_MASK	0x000efff0	/* ucast cipher mask */
+#define SEC_CAP_AKM_MASK	0x7e000000	/* AKM mask */
+#define SEC_CAP_UC_CIPHER_SHIFT	4	/* ucast cipher shift */
+#define SEC_CAP_AKM_SHIFT	25	/* AKM shift */
+
+/* SEC_CAP_MC_CIPHER value */
+enum {
+	MC_CIPHER_NONE,
+	MC_CIPHER_WEP40,
+	MC_CIPHER_WEP104,
+	MC_CIPHER_TKIP,
+	MC_CIPHER_CCMP,
+	MC_CIPHER_CKIP_CMIC,
+	MC_CIPHER_CKIP,
+	MC_CIPHER_CMIC
+};
+
+/* SEC_CAP_UC_CIPHER value */
+#define UC_CIPHER_NONE		(1 << 0)
+#define UC_CIPHER_WEP40		(1 << 1)
+#define UC_CIPHER_WEP104	(1 << 2)
+#define UC_CIPHER_TKIP		(1 << 3)
+#define UC_CIPHER_CCMP		(1 << 4)
+#define UC_CIPHER_CKIP_CMIC	(1 << 5)
+#define UC_CIPHER_CKIP		(1 << 6)
+#define UC_CIPHER_CMIC		(1 << 7)
+#define UC_CIPHER_WPA2_WEP40	(1 << 8)
+#define UC_CIPHER_WPA2_WEP104	(1 << 9)
+#define UC_CIPHER_WPA2_TKIP	(1 << 10)
+#define UC_CIPHER_WPA2_CCMP	(1 << 11)
+#define UC_CIPHER_WPA2_CKIP_CMIC	(1 << 12)
+#define UC_CIPHER_WPA2_CKIP	(1 << 13)
+#define UC_CIPHER_WPA2_CMIC	(1 << 14)
+
+/* SEC_CAP_AKM value */
+#define AKM_WPA1_1X		(1 << 0)
+#define AKM_WPA1_PSK		(1 << 1)
+#define AKM_WPA2_1X		(1 << 2)
+#define AKM_WPA2_PSK		(1 << 3)
+#define AKM_WPA1_CCKM		(1 << 4)
+#define AKM_WPA2_CCKM		(1 << 5)
+
+BWL_PRE_PACKED_STRUCT struct ccx_hidden_ssid {
+	uint8	ext_cap;	/* hidden ssid extended capability */
+	uint32	capability;	/* hidden ssid capability */
+	uint8	ssid_len;	/* ssid name length */
+	uint8	ssid[1];	/* ssid.  variable length */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_hidden_ssid ccx_hidden_ssid_t;
+
+/* CCXv4 SSIDL IE */
+BWL_PRE_PACKED_STRUCT struct ccx_ssidl_ie {
+	uint8	id;		/* 221, DOT11_MNG_SSIDL_ID */
+	uint8	length;
+	uint8 	oui[3];		/* 00:50:f2 */
+	uint8	type;		/* 5 */
+	uint8	pri_ext_cap;	/* primary ssid extended capability */
+	/* following fields are optional */
+	uint8	ssid_count;	/* number of hidden ssids followed */
+	ccx_hidden_ssid_t	hidden_ssid[1];	/* hidden ssid start */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_ssidl_ie ccx_ssidl_ie_t;
+
+/* link test.  CCXv4 S62 */
+BWL_PRE_PACKED_STRUCT struct ccx_link_test_s {
+	uint16	frm_num;	/* frame number */
+	uint32	time;		/* time from sender */
+	uint8	rsq;		/* raw signal quality of request */
+	uint8	rss;		/* raw signal strength of request */
+	uint8	txretried;	/* retries in sending previous response */
+	uint8	rssi;		/* signal strength in dBm of request */
+	uint8	sqp;		/* signal quality as percent of request */
+	uint8	ssp;		/* signal strength as percent of request */
+	uint8	data[1];	/* start data set by sender */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_link_test_s ccx_link_test_t;
+#define CCX_LINK_TEST_REQ_LEN 12	/* line test request length */
+
+/* Supported Features Advertisement(SFA) IE.  CCXv5 S63 */
+BWL_PRE_PACKED_STRUCT struct ccx_sfa_ie {
+	uint8	id;		/* 221, DOT11_MNG_PROPR_ID */
+	uint8	length;		/* 5 */
+	uint8 	oui[3];		/* 00:40:96 */
+	uint8	type;		/* 14 */
+	uint8	capability;	/* capability to support CCXv5 features */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_sfa_ie ccx_sfa_ie_t;
+#define CCX_SFA_IE_TYPE	0x14	/* SFA IE type */
+/* feature bit in capability field */
+#define CAP_MFP			0x01	/* S67. MFP */
+#define CAP_DIAG_CHANL	0x02	/* S64. Diagnostic channel */
+#define CAP_LOC_SERVICE	0x04	/* S69. Location services */
+#define CAP_EXP_BNDWITH	0x08	/* S70. Expedited Bandwidth Requests */
+
+/* MHDR IE.  CCXv5 S67 */
+BWL_PRE_PACKED_STRUCT struct ccx_mhdr_ie {
+	uint8	id;		/* 221, DOT11_MNG_PROPR_ID */
+	uint8	length;		/* 12 */
+	uint8 	oui[3];		/* 00:40:96 */
+	uint8	type;		/* 16 */
+	uint8	fc[2];
+	struct ether_addr bssid;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_mhdr_ie ccx_mhdr_ie_t;
+#define CCX_HMDR_IE_TYPE	16
+
+#define CKIP_MIC_SIZE		4	/* size of CKIP MIC */
+#define CKIP_SEQ_SIZE		4	/* size of CKIP SEQ */
+#define CKIP_KEY_SIZE		16	/* size of CKIP key */
+
+/* 802.11e MSDU Lifetime IE */
+BWL_PRE_PACKED_STRUCT typedef struct {
+	uint8	oui[DOT11_OUI_LEN];	/* 3 bytes OUI */
+	uint8	oui_type;		/* OUI Type */
+	uint8	tid;			/* traffic stream ID */
+	uint16	msdu_lifetime;	/* time in TU, specify per AC */
+} BWL_POST_PACKED_STRUCT ccx_msdu_lifetime_t;
+
+/* CCX traffic stream rateset IE */
+BWL_PRE_PACKED_STRUCT typedef struct {
+	uint8	oui[DOT11_OUI_LEN];	/* 3 bytes OUI */
+	uint8	oui_type;		/* OUI Type */
+	uint8	tid;			/* traffic stream ID */
+	uint8	rateset[1];		/* nominal rate to use (multiple of 500k) */
+} BWL_POST_PACKED_STRUCT ccx_stream_rs_t;
+#define CAC_STREAM_RS_HDR_LEN	(DOT11_OUI_LEN + 2)	/* len from oui to tid */
+
+/* CCX traffic stream metrics IE */
+BWL_PRE_PACKED_STRUCT typedef struct {
+	uint8	oui[DOT11_OUI_LEN];	/* 3 bytes OUI */
+	uint8	oui_type;		/* OUI Type */
+	uint8	tid;			/* traffic stream ID */
+	uint8	state;			/* metrics enable or disable */
+	uint16	measure_interval;	/* interval time in TU */
+} BWL_POST_PACKED_STRUCT ccx_ts_metrics_t;
+
+#define CCX_CAC_TS_METRICS_TYPE		7	/* Traffic Stream Metrics type */
+#define CCX_CAC_TS_RATESET_TYPE		8	/* Traffic Stream Rateset type */
+#define CCX_CAC_MSDU_LIFETIME_TYPE	9	/* MSUD Lifetime type */
+
+/* CCX Traffic Stream Metrics IE in IAPP packet */
+BWL_PRE_PACKED_STRUCT typedef struct {
+	uint16 dialog_token;	/* dialog token should set to 0 */
+	uint16 id;		/* ID should be 0x27 */
+	uint16 len;		/* len start from token to end of struct */
+	uint16 token;		/* token should set to 0 */
+	uint8 mode;		/* mode should set to 0 */
+	uint8 type;		/* Traffic Stream Metrics type set to 6 */
+	uint16 avg_delay;	/* average delay in msec */
+	uint16 cnt_delay10;	/* bucket for <= 10 msec delay */
+	uint16 cnt_delay20;	/* bucket for > 10 && <= 20 msec delay */
+	uint16 cnt_delay40;	/* bucket for >20 && <= 40 msec delay */
+	uint16 cnt_delay;	/* bucket for > 40 msec delay */
+	uint32 media_delay;	/* average media delay in TU */
+	uint16 pkt_loss;	/* packet loss per AC */
+	uint16 pkt_cnt;		/* packet count per AC */
+	uint8 roam_cnt;		/* roam count */
+	uint16 roam_delay;	/* roam delay measure in TU */
+	/* following fields are added in CCXv5 */
+	uint16 used_time;	/* defined in section 3.5.1 in the WMM */
+	uint8 tid;			/* traffic stream ID */
+} BWL_POST_PACKED_STRUCT ccx_tsm_param_t;
+
+/* ccx_tsm_param_t defines */
+#define CCX_TSM_LEN_DELTA	3	/* length delta between V4 and later versions */
+#define CCX_TSM_LEN	(sizeof(ccx_tsm_param_t))	/* length */
+#define CCX_TSM_V4_LEN	(CCX_TSM_LEN - CCX_TSM_LEN_DELTA)
+#define CCX_TSM_IE_LEN	28	/* length (from token to end of struct) */
+#define CCX_TSM_IE_V4_LEN	(CCX_TSM_IE_LEN - CCX_TSM_LEN_DELTA)
+#define CCX_TSM_ID  	0x27	/* ID */
+#define CCX_TSM_TOKEN	0	/* Token */
+#define CCX_TSM_MODE	0	/* Mode */
+#define CCX_TSM_TYPE	8	/* Type */
+#define CCX_TSM_V4_TYPE	6	/* Type for V4 */
+
+/* CCX IAPP packet sent to AP on ts metrics interval */
+#define CCX_TSM_IAPP_PKT_LEN	(DOT11_LLC_SNAP_HDR_LEN + CCX_TSM_IAPP_LEN)
+#define CCX_TSM_IAPP_PKT_V4_LEN	(DOT11_LLC_SNAP_HDR_LEN + CCX_TSM_IAPP_V4_LEN)
+#define CCX_TSM_IAPP_LEN	(CCX_IAPP_HDR_LEN + CCX_TSM_LEN)
+#define CCX_TSM_IAPP_V4_LEN	(CCX_IAPP_HDR_LEN + CCX_TSM_V4_LEN)
+#define CCX_TSM_IAPP_SUBTYPE	0x81	/* CCX IAPP Subtype for Traffic Stream Metrics */
+
+/* CCXv4 S60 PathLoss Measurement req */
+BWL_PRE_PACKED_STRUCT struct ccx_rm_pathlossreq {
+	uint16			nbursts;	/* Number of Bursts */
+	uint16			burstinterval;	/* Burst Interval in seconds */
+	uint8 			burstlen;	/* Burst len */
+	uint16			duration;	/* Measurement Duration in TUs 1024 us */
+	uint8			txpower;	/* Desired txpower -128 to +127dBm */
+	struct ether_addr 	addr;		/* multicast Address for the report */
+	uint8			nchannels;	/* number of Channels */
+	uint8			channel[1];	/* Channel list */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ccx_rm_pathlossreq ccx_rm_pathlossreq_t;
+#define CCX_RM_PATHLOSSREQ_FIXEDLEN	15
+
+/* CCXv4 S60 PathLoss Measurement Frame */
+BWL_PRE_PACKED_STRUCT struct ccx_rm_pathlossmeas_frame {
+	uint16 			seq;
+	int8 			txpower;
+	uint8 			txchannel;
+} BWL_POST_PACKED_STRUCT;
+#define CCX_RM_PATHLOSS_SEQ_MASK		0x0FFF
+#define CCX_RM_IAPP_SUBTYPE	0x82	/* CCX IAPP Subtype for Pathloss Measurement */
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif	/* _802_11_CCX_H_ */
diff --git a/src/common/include/proto/802.11e.h b/src/common/include/proto/802.11e.h
new file mode 100644
index 0000000..914d278
--- /dev/null
+++ b/src/common/include/proto/802.11e.h
@@ -0,0 +1,120 @@
+/*
+ * 802.11e protocol header file
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: 802.11e.h 382883 2013-02-04 23:26:09Z $
+ */
+
+#ifndef _802_11e_H_
+#define _802_11e_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/* WME Traffic Specification (TSPEC) element */
+#define WME_TSPEC_HDR_LEN           2           /* WME TSPEC header length */
+#define WME_TSPEC_BODY_OFF          2           /* WME TSPEC body offset */
+
+#define WME_CATEGORY_CODE_OFFSET	0		/* WME Category code offset */
+#define WME_ACTION_CODE_OFFSET		1		/* WME Action code offset */
+#define WME_TOKEN_CODE_OFFSET		2		/* WME Token code offset */
+#define WME_STATUS_CODE_OFFSET		3		/* WME Status code offset */
+
+BWL_PRE_PACKED_STRUCT struct tsinfo {
+	uint8 octets[3];
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct tsinfo tsinfo_t;
+
+/* 802.11e TSPEC IE */
+typedef BWL_PRE_PACKED_STRUCT struct tspec {
+	uint8 oui[DOT11_OUI_LEN];	/* WME_OUI */
+	uint8 type;					/* WME_TYPE */
+	uint8 subtype;				/* WME_SUBTYPE_TSPEC */
+	uint8 version;				/* WME_VERSION */
+	tsinfo_t tsinfo;			/* TS Info bit field */
+	uint16 nom_msdu_size;		/* (Nominal or fixed) MSDU Size (bytes) */
+	uint16 max_msdu_size;		/* Maximum MSDU Size (bytes) */
+	uint32 min_srv_interval;	/* Minimum Service Interval (us) */
+	uint32 max_srv_interval;	/* Maximum Service Interval (us) */
+	uint32 inactivity_interval;	/* Inactivity Interval (us) */
+	uint32 suspension_interval; /* Suspension Interval (us) */
+	uint32 srv_start_time;		/* Service Start Time (us) */
+	uint32 min_data_rate;		/* Minimum Data Rate (bps) */
+	uint32 mean_data_rate;		/* Mean Data Rate (bps) */
+	uint32 peak_data_rate;		/* Peak Data Rate (bps) */
+	uint32 max_burst_size;		/* Maximum Burst Size (bytes) */
+	uint32 delay_bound;			/* Delay Bound (us) */
+	uint32 min_phy_rate;		/* Minimum PHY Rate (bps) */
+	uint16 surplus_bw;			/* Surplus Bandwidth Allowance (range 1.0-8.0) */
+	uint16 medium_time;			/* Medium Time (32 us/s periods) */
+} BWL_POST_PACKED_STRUCT tspec_t;
+
+#define WME_TSPEC_LEN	(sizeof(tspec_t))		/* not including 2-bytes of header */
+
+/* ts_info */
+/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */
+#define TS_INFO_TID_SHIFT		1	/* TS info. TID shift */
+#define TS_INFO_TID_MASK		(0xf << TS_INFO_TID_SHIFT)	/* TS info. TID mask */
+#define TS_INFO_CONTENTION_SHIFT	7	/* TS info. contention shift */
+#define TS_INFO_CONTENTION_MASK	(0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */
+#define TS_INFO_DIRECTION_SHIFT	5	/* TS info. direction shift */
+#define TS_INFO_DIRECTION_MASK	(0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */
+#define TS_INFO_PSB_SHIFT		2		/* TS info. PSB bit Shift */
+#define TS_INFO_PSB_MASK		(1 << TS_INFO_PSB_SHIFT)	/* TS info. PSB mask */
+#define TS_INFO_UPLINK			(0 << TS_INFO_DIRECTION_SHIFT)	/* TS info. uplink */
+#define TS_INFO_DOWNLINK		(1 << TS_INFO_DIRECTION_SHIFT)	/* TS info. downlink */
+#define TS_INFO_BIDIRECTIONAL	(3 << TS_INFO_DIRECTION_SHIFT)	/* TS info. bidirectional */
+#define TS_INFO_USER_PRIO_SHIFT	3	/* TS info. user priority shift */
+/* TS info. user priority mask */
+#define TS_INFO_USER_PRIO_MASK	(0x7 << TS_INFO_USER_PRIO_SHIFT)
+
+/* Macro to get/set bit(s) field in TSINFO */
+#define WLC_CAC_GET_TID(pt)	((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT)
+#define WLC_CAC_GET_DIR(pt)	((((pt).octets[0]) & \
+	TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT)
+#define WLC_CAC_GET_PSB(pt)	((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT)
+#define WLC_CAC_GET_USER_PRIO(pt)	((((pt).octets[1]) & \
+	TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT)
+
+#define WLC_CAC_SET_TID(pt, id)	((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \
+	((id) << TS_INFO_TID_SHIFT))
+#define WLC_CAC_SET_USER_PRIO(pt, prio)	((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \
+	((prio) << TS_INFO_USER_PRIO_SHIFT))
+
+/* 802.11e QBSS Load IE */
+#define QBSS_LOAD_IE_LEN		5	/* QBSS Load IE length */
+#define QBSS_LOAD_AAC_OFF		3	/* AAC offset in IE */
+
+#define CAC_ADDTS_RESP_TIMEOUT		1000	/* default ADDTS response timeout in ms */
+						/* DEFVAL dot11ADDTSResponseTimeout = 1s */
+
+/* 802.11e ADDTS status code */
+#define DOT11E_STATUS_ADMISSION_ACCEPTED	0	/* TSPEC Admission accepted status */
+#define DOT11E_STATUS_ADDTS_INVALID_PARAM	1	/* TSPEC invalid parameter status */
+#define DOT11E_STATUS_ADDTS_REFUSED_NSBW	3	/* ADDTS refused (non-sufficient BW) */
+#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE	47	/* ADDTS refused but could retry later */
+#ifdef BCMCCX
+#define CCX_STATUS_ASSOC_DENIED_UNKNOWN    0xc8	/* unspecified QoS related failure */
+#define CCX_STATUS_ASSOC_DENIED_AP_POLICY  0xc9	/* TSPEC refused due to AP policy */
+#define CCX_STATUS_ASSOC_DENIED_NO_BW	   0xca	/* Assoc denied due to AP insufficient BW */
+#define CCX_STATUS_ASSOC_DENIED_BAD_PARAM  0xcb	/* one or more TSPEC with invalid parameter */
+#endif	/* BCMCCX */
+
+/* 802.11e DELTS status code */
+#define DOT11E_STATUS_QSTA_LEAVE_QBSS		36	/* STA leave QBSS */
+#define DOT11E_STATUS_END_TS				37	/* END TS */
+#define DOT11E_STATUS_UNKNOWN_TS			38	/* UNKNOWN TS */
+#define DOT11E_STATUS_QSTA_REQ_TIMEOUT		39	/* STA ADDTS request timeout */
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _802_11e_CAC_H_ */
diff --git a/src/common/include/proto/802.1d.h b/src/common/include/proto/802.1d.h
new file mode 100644
index 0000000..f2c6e2d
--- /dev/null
+++ b/src/common/include/proto/802.1d.h
@@ -0,0 +1,30 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Fundamental types and constants relating to 802.1D
+ *
+ * $Id: 802.1d.h 382882 2013-02-04 23:24:31Z $
+ */
+
+#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/802.3.h b/src/common/include/proto/802.3.h
new file mode 100644
index 0000000..9901a23
--- /dev/null
+++ b/src/common/include/proto/802.3.h
@@ -0,0 +1,34 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Fundamental constants relating to 802.3
+ *
+ * $Id: 802.3.h 417943 2013-08-13 07:54:04Z $
+ */
+
+#ifndef _802_3_h_
+#define _802_3_h_
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define SNAP_HDR_LEN	6	/* 802.3 SNAP header length */
+#define DOT3_OUI_LEN	3	/* 802.3 oui length */
+
+BWL_PRE_PACKED_STRUCT struct dot3_mac_llc_snap_header {
+	uint8	ether_dhost[ETHER_ADDR_LEN];	/* dest mac */
+	uint8	ether_shost[ETHER_ADDR_LEN];	/* src mac */
+	uint16	length;				/* frame length incl header */
+	uint8	dsap;				/* always 0xAA */
+	uint8	ssap;				/* always 0xAA */
+	uint8	ctl;				/* always 0x03 */
+	uint8	oui[DOT3_OUI_LEN];		/* RFC1042: 0x00 0x00 0x00
+						 * Bridge-Tunnel: 0x00 0x00 0xF8
+						 */
+	uint16	type;				/* ethertype */
+} BWL_POST_PACKED_STRUCT;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif	/* #ifndef _802_3_h_ */
diff --git a/src/common/include/proto/bcmeth.h b/src/common/include/proto/bcmeth.h
new file mode 100644
index 0000000..f030584
--- /dev/null
+++ b/src/common/include/proto/bcmeth.h
@@ -0,0 +1,64 @@
+/*
+ * Broadcom Ethernettype  protocol definitions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmeth.h 382882 2013-02-04 23:24:31Z $
+ */
+
+
+
+#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..b129808
--- /dev/null
+++ b/src/common/include/proto/bcmevent.h
@@ -0,0 +1,436 @@
+/*
+ * Broadcom Event  protocol definitions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Dependencies: proto/bcmeth.h
+ *
+ * $Id: bcmevent.h 642996 2016-06-11 01:13:46Z $
+ *
+ */
+
+
+
+#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	
+#if defined(BCMCCX) && defined(CCX_SDK)
+#define WLC_E_CCX_ASSOC_START	42	
+#define WLC_E_CCX_ASSOC_ABORT	43	
+#endif 
+#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
+#ifdef WLBTAMP
+#define WLC_E_BTA_HCI_EVENT	53	
+#endif
+#define WLC_E_IF		54	
+#define WLC_E_P2P_DISC_LISTEN_COMPLETE	55	
+#define WLC_E_RSSI		56	
+
+#define WLC_E_PFN_BEST_BATCHING     57
+#define WLC_E_PFN_SCAN_COMPLETE	57	
+
+#define WLC_E_PFN_BEST_BATCHING	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_BSSID_NET_FOUND	82
+#define WLC_E_PFN_SCAN_ALLGONE		83	
+
+#define WLC_E_PFN_BSSID_NET_LOST	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_PSTA_PRIMARY_INTF_IND	99	
+#define WLC_E_EVENT_100			100
+#define WLC_E_BEACON_FRAME_RX		101
+#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_TXFAIL_THRESH		108	
+#define WLC_E_PROXD			109	
+#define WLC_E_IBSS_COALESCE		110	
+#define WLC_E_AIBSS_TXFAIL		110	
+#define WLC_E_CSA_START_IND		121
+#define WLC_E_CSA_DONE_IND		122
+#define WLC_E_CSA_FAILURE_IND		123
+#define WLC_E_CCA_CHAN_QUAL		124	
+#define WLC_E_BSSID		125	
+#define WLC_E_TX_STAT_ERROR		126	
+#define WLC_E_BCMC_CREDIT_SUPPORT	127	
+#define WLC_E_PKT_FILTER			164 
+#define WLC_E_LAST			165	
+
+#if (WLC_E_LAST > 165)
+#error "WLC_E_LAST: Invalid value for last event; must be <= 155."
+#endif 
+
+
+
+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	
+#ifdef BCMCCX
+#define WLC_E_STATUS_CCXFASTRM		14	
+#endif 
+#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_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_MINTXRATE		9	
+#define WLC_E_REASON_TXFAIL		10	
+#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	
+#ifdef BCMCCX
+#define WLC_E_PRUNE_CCXFAST_PREVAP	11	
+#endif 
+#define WLC_E_PRUNE_CIPHER_NA		12	
+#define WLC_E_PRUNE_KNOWN_STA		13	
+#ifdef BCMCCX
+#define WLC_E_PRUNE_CCXFAST_DROAM	14	
+#endif 
+#define WLC_E_PRUNE_WDS_PEER		15	
+#define WLC_E_PRUNE_QBSS_LOAD		16	
+#define WLC_E_PRUNE_HOME_AP		17	
+#ifdef BCMCCX
+#define WLC_E_PRUNE_AP_BLOCKED		18	
+#define WLC_E_PRUNE_NO_DIAG_SUPPORT	19	
+#endif 
+
+
+#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_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	
+#ifdef WLBTAMP
+#define WLC_E_IF_ROLE_BTA_CREATOR	5	
+#define WLC_E_IF_ROLE_BTA_ACCEPTOR	6	
+#endif
+
+
+typedef struct wl_event_data_rssi {
+	int32 rssi;
+	int32 snr;
+	int32 noise;
+} wl_event_data_rssi_t;
+
+
+#define WLC_E_IF_FLAGS_BSSCFG_NOIF	0x1	
+
+
+#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
+
+#ifdef WLTDLS
+
+#define TDLS_AF_CATEGORY		12
+
+
+#define TDLS_VENDOR_SPECIFIC					127
+
+#define TDLS_ACTION_SETUP_REQ					0
+#define TDLS_ACTION_SETUP_RESP					1
+#define TDLS_ACTION_SETUP_CONFIRM				2
+#define TDLS_ACTION_TEARDOWN					3
+#define WLAN_TDLS_SET_WFD_IE		 11
+#endif
+
+
+
+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_PKT_FILTER_TIMEOUT	1 
+
+
+#define WLC_E_PROXD_FOUND	1	
+#define WLC_E_PROXD_GONE	2	
+
+
+
+#define INTFER_EVENT_VERSION		1
+#define INTFER_STREAM_TYPE_NONTCP	1
+#define INTFER_STREAM_TYPE_TCP		2
+#define WLINTFER_STATS_NSMPLS		4
+typedef struct wl_intfer_event {
+	uint16 version;			
+	uint16 status;			
+	uint8 txfail_histo[WLINTFER_STATS_NSMPLS]; 
+} wl_intfer_event_t;
+
+
+typedef struct wl_psta_primary_intf_event {
+	struct ether_addr prim_ea;	
+} wl_psta_primary_intf_event_t;
+
+
+#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..acce811
--- /dev/null
+++ b/src/common/include/proto/bcmip.h
@@ -0,0 +1,213 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Fundamental constants relating to IP Protocol
+ *
+ * $Id: bcmip.h 457888 2014-02-25 03:34:39Z $
+ */
+
+#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 IP_DSCP46(ip_body) (IP_TOS46(ip_body) >> IPV4_TOS_DSCP_SHIFT);
+
+
+#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)
+
+#define IPV4_MCAST_TO_ETHER_MCAST(ipv4, ether) \
+{ \
+	ether[0] = 0x01; \
+	ether[1] = 0x00; \
+	ether[2] = 0x5E; \
+	ether[3] = (ipv4 & 0x7f0000) >> 16; \
+	ether[4] = (ipv4 & 0xff00) >> 8; \
+	ether[5] = (ipv4 & 0xff); \
+}
+
+
+#include <packed_section_end.h>
+
+#define IPV4_ADDR_STR "%d.%d.%d.%d"
+#define IPV4_ADDR_TO_STR(addr)	((uint32)addr & 0xff000000) >> 24, \
+								((uint32)addr & 0x00ff0000) >> 16, \
+								((uint32)addr & 0x0000ff00) >> 8, \
+								((uint32)addr & 0x000000ff)
+
+#endif	
diff --git a/src/common/include/proto/bcmipv6.h b/src/common/include/proto/bcmipv6.h
new file mode 100644
index 0000000..58f9752
--- /dev/null
+++ b/src/common/include/proto/bcmipv6.h
@@ -0,0 +1,141 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Fundamental constants relating to Neighbor Discovery Protocol
+ *
+ * $Id: bcmipv6.h 399482 2013-04-30 09:24:37Z $
+ */
+
+#ifndef _bcmipv6_h_
+#define _bcmipv6_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* Extension headers */
+#define IPV6_EXT_HOP	0
+#define IPV6_EXT_ROUTE	43
+#define IPV6_EXT_FRAG	44
+#define IPV6_EXT_DEST	60
+#define IPV6_EXT_ESEC	50
+#define IPV6_EXT_AUTH	51
+
+/* Minimum size (extension header "word" length) */
+#define IPV6_EXT_WORD	8
+
+/* Offsets for most extension headers */
+#define IPV6_EXT_NEXTHDR	0
+#define IPV6_EXT_HDRLEN		1
+
+/* Constants specific to fragmentation header */
+#define IPV6_FRAG_MORE_MASK	0x0001
+#define IPV6_FRAG_MORE_SHIFT	0
+#define IPV6_FRAG_OFFS_MASK	0xfff8
+#define IPV6_FRAG_OFFS_SHIFT	3
+
+/* For icmpv6 */
+#define ICMPV6_HEADER_TYPE 	0x3A
+#define ICMPV6_PKT_TYPE_NS	135
+#define ICMPV6_PKT_TYPE_NA	136
+
+#define ICMPV6_ND_OPT_TYPE_TARGET_MAC	2
+#define ICMPV6_ND_OPT_TYPE_SRC_MAC		1
+
+#define ICMPV6_ND_OPT_LEN_LINKADDR		1
+
+#define ICMPV6_ND_OPT_LEN_LINKADDR		1
+
+#define IPV6_VERSION 	6
+#define IPV6_HOP_LIMIT 	255
+
+#define IPV6_ADDR_NULL(a)	((a[0] | a[1] | a[2] | a[3] | a[4] | \
+							 a[5] | a[6] | a[7] | a[8] | a[9] | \
+							 a[10] | a[11] | a[12] | a[13] | \
+							 a[14] | a[15]) == 0)
+
+#define IPV6_ADDR_LOCAL(a)	(((a[0] == 0xfe) && (a[1] & 0x80))? TRUE: FALSE)
+
+/* IPV6 address */
+BWL_PRE_PACKED_STRUCT struct ipv6_addr {
+		uint8		addr[16];
+} BWL_POST_PACKED_STRUCT;
+
+
+/* ICMPV6 Header */
+BWL_PRE_PACKED_STRUCT struct icmp6_hdr {
+	uint8	icmp6_type;
+	uint8	icmp6_code;
+	uint16	icmp6_cksum;
+	BWL_PRE_PACKED_STRUCT union {
+		uint32 reserved;
+		BWL_PRE_PACKED_STRUCT struct nd_advt {
+			uint32	reserved1:5,
+				override:1,
+				solicited:1,
+				router:1,
+				reserved2:24;
+		} BWL_POST_PACKED_STRUCT nd_advt;
+	} BWL_POST_PACKED_STRUCT opt;
+} BWL_POST_PACKED_STRUCT;
+
+/* Ipv6 Header Format */
+BWL_PRE_PACKED_STRUCT struct ipv6_hdr {
+	uint8	priority:4,
+		version:4;
+	uint8	flow_lbl[3];
+	uint16	payload_len;
+	uint8	nexthdr;
+	uint8 	hop_limit;
+	struct	ipv6_addr	saddr;
+	struct	ipv6_addr	daddr;
+} BWL_POST_PACKED_STRUCT;
+
+/* Neighbor Advertisement/Solicitation Packet Structure */
+BWL_PRE_PACKED_STRUCT struct nd_msg {
+	struct icmp6_hdr	icmph;
+	struct ipv6_addr target;
+} BWL_POST_PACKED_STRUCT;
+
+
+/* Neighibor Solicitation/Advertisement Optional Structure */
+BWL_PRE_PACKED_STRUCT struct nd_msg_opt {
+	uint8 type;
+	uint8 len;
+	uint8 mac_addr[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+/* Ipv6 Fragmentation Header */
+BWL_PRE_PACKED_STRUCT struct ipv6_frag {
+	uint8	nexthdr;
+	uint8	reserved;
+	uint16	frag_offset;
+	uint32	ident;
+} BWL_POST_PACKED_STRUCT;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+static const struct ipv6_addr all_node_ipv6_maddr = {
+									{ 0xff, 0x2, 0, 0,
+									0, 0, 0, 0,
+									0, 0, 0, 0,
+									0, 0, 0, 1
+									}};
+
+#define IPV6_ISMULTI(a) (a[0] == 0xff)
+
+#define IPV6_MCAST_TO_ETHER_MCAST(ipv6, ether) \
+{ \
+	ether[0] = 0x33; \
+	ether[1] = 0x33; \
+	ether[2] = ipv6[12]; \
+	ether[3] = ipv6[13]; \
+	ether[4] = ipv6[14]; \
+	ether[5] = ipv6[15]; \
+}
+
+#endif	/* !defined(_bcmipv6_h_) */
diff --git a/src/common/include/proto/bcmtcp.h b/src/common/include/proto/bcmtcp.h
new file mode 100644
index 0000000..f9af5e3
--- /dev/null
+++ b/src/common/include/proto/bcmtcp.h
@@ -0,0 +1,72 @@
+/*
+ * Fundamental constants relating to TCP Protocol
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmtcp.h 457888 2014-02-25 03:34:39Z $
+ */
+
+#ifndef _bcmtcp_h_
+#define _bcmtcp_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+
+#include <packed_section_start.h>
+
+
+#define TCP_SRC_PORT_OFFSET	0	
+#define TCP_DEST_PORT_OFFSET	2	
+#define TCP_SEQ_NUM_OFFSET	4	
+#define TCP_ACK_NUM_OFFSET	8	
+#define TCP_HLEN_OFFSET		12	
+#define TCP_FLAGS_OFFSET	13	
+#define TCP_CHKSUM_OFFSET	16	
+
+#define TCP_PORT_LEN		2	
+
+
+#define TCP_FLAG_URG            0x20
+#define TCP_FLAG_ACK            0x10
+#define TCP_FLAG_PSH            0x08
+#define TCP_FLAG_RST            0x04
+#define TCP_FLAG_SYN            0x02
+#define TCP_FLAG_FIN            0x01
+
+#define TCP_HLEN_MASK           0xf000
+#define TCP_HLEN_SHIFT          12
+
+
+BWL_PRE_PACKED_STRUCT struct bcmtcp_hdr
+{
+	uint16	src_port;	
+	uint16	dst_port;	
+	uint32	seq_num;	
+	uint32	ack_num;	
+	uint16	hdrlen_rsvd_flags;	
+	uint16	tcpwin;		
+	uint16	chksum;		
+	uint16	urg_ptr;	
+} BWL_POST_PACKED_STRUCT;
+
+#define TCP_MIN_HEADER_LEN 20
+
+#define TCP_HDRLEN_MASK 0xf0
+#define TCP_HDRLEN_SHIFT 4
+#define TCP_HDRLEN(hdrlen) (((hdrlen) & TCP_HDRLEN_MASK) >> TCP_HDRLEN_SHIFT)
+
+#define TCP_FLAGS_MASK  0x1f
+#define TCP_FLAGS(hdrlen) ((hdrlen) & TCP_FLAGS_MASK)
+
+
+#include <packed_section_end.h>
+
+
+#define IS_TCPSEQ_GE(a, b) ((a - b) < NBITVAL(31))		
+#define IS_TCPSEQ_LE(a, b) ((b - a) < NBITVAL(31))		
+#define IS_TCPSEQ_GT(a, b) !IS_TCPSEQ_LE(a, b)		
+#define IS_TCPSEQ_LT(a, b) !IS_TCPSEQ_GE(a, b)		
+
+#endif	
diff --git a/src/common/include/proto/bt_amp_hci.h b/src/common/include/proto/bt_amp_hci.h
new file mode 100644
index 0000000..bc91f84
--- /dev/null
+++ b/src/common/include/proto/bt_amp_hci.h
@@ -0,0 +1,423 @@
+/*
+ * BT-AMP (BlueTooth Alternate Mac and Phy) HCI (Host/Controller Interface)
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bt_amp_hci.h 382882 2013-02-04 23:24:31Z $
+*/
+
+#ifndef _bt_amp_hci_h
+#define _bt_amp_hci_h
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/* AMP HCI CMD packet format */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_cmd {
+	uint16 opcode;
+	uint8 plen;
+	uint8 parms[1];
+} BWL_POST_PACKED_STRUCT amp_hci_cmd_t;
+
+#define HCI_CMD_PREAMBLE_SIZE		OFFSETOF(amp_hci_cmd_t, parms)
+#define HCI_CMD_DATA_SIZE		255
+
+/* AMP HCI CMD opcode layout */
+#define HCI_CMD_OPCODE(ogf, ocf)	((((ogf) & 0x3F) << 10) | ((ocf) & 0x03FF))
+#define HCI_CMD_OGF(opcode)		((uint8)(((opcode) >> 10) & 0x3F))
+#define HCI_CMD_OCF(opcode)		((opcode) & 0x03FF)
+
+/* AMP HCI command opcodes */
+#define HCI_Read_Failed_Contact_Counter		HCI_CMD_OPCODE(0x05, 0x0001)
+#define HCI_Reset_Failed_Contact_Counter	HCI_CMD_OPCODE(0x05, 0x0002)
+#define HCI_Read_Link_Quality			HCI_CMD_OPCODE(0x05, 0x0003)
+#define HCI_Read_Local_AMP_Info			HCI_CMD_OPCODE(0x05, 0x0009)
+#define HCI_Read_Local_AMP_ASSOC		HCI_CMD_OPCODE(0x05, 0x000A)
+#define HCI_Write_Remote_AMP_ASSOC		HCI_CMD_OPCODE(0x05, 0x000B)
+#define HCI_Create_Physical_Link		HCI_CMD_OPCODE(0x01, 0x0035)
+#define HCI_Accept_Physical_Link_Request	HCI_CMD_OPCODE(0x01, 0x0036)
+#define HCI_Disconnect_Physical_Link		HCI_CMD_OPCODE(0x01, 0x0037)
+#define HCI_Create_Logical_Link			HCI_CMD_OPCODE(0x01, 0x0038)
+#define HCI_Accept_Logical_Link			HCI_CMD_OPCODE(0x01, 0x0039)
+#define HCI_Disconnect_Logical_Link		HCI_CMD_OPCODE(0x01, 0x003A)
+#define HCI_Logical_Link_Cancel			HCI_CMD_OPCODE(0x01, 0x003B)
+#define HCI_Flow_Spec_Modify			HCI_CMD_OPCODE(0x01, 0x003C)
+#define HCI_Write_Flow_Control_Mode		HCI_CMD_OPCODE(0x01, 0x0067)
+#define HCI_Read_Best_Effort_Flush_Timeout	HCI_CMD_OPCODE(0x01, 0x0069)
+#define HCI_Write_Best_Effort_Flush_Timeout	HCI_CMD_OPCODE(0x01, 0x006A)
+#define HCI_Short_Range_Mode			HCI_CMD_OPCODE(0x01, 0x006B)
+#define HCI_Reset				HCI_CMD_OPCODE(0x03, 0x0003)
+#define HCI_Read_Connection_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0015)
+#define HCI_Write_Connection_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0016)
+#define HCI_Read_Link_Supervision_Timeout	HCI_CMD_OPCODE(0x03, 0x0036)
+#define HCI_Write_Link_Supervision_Timeout	HCI_CMD_OPCODE(0x03, 0x0037)
+#define HCI_Enhanced_Flush			HCI_CMD_OPCODE(0x03, 0x005F)
+#define HCI_Read_Logical_Link_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0061)
+#define HCI_Write_Logical_Link_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0062)
+#define HCI_Set_Event_Mask_Page_2		HCI_CMD_OPCODE(0x03, 0x0063)
+#define HCI_Read_Location_Data_Command		HCI_CMD_OPCODE(0x03, 0x0064)
+#define HCI_Write_Location_Data_Command		HCI_CMD_OPCODE(0x03, 0x0065)
+#define HCI_Read_Local_Version_Info		HCI_CMD_OPCODE(0x04, 0x0001)
+#define HCI_Read_Local_Supported_Commands	HCI_CMD_OPCODE(0x04, 0x0002)
+#define HCI_Read_Buffer_Size			HCI_CMD_OPCODE(0x04, 0x0005)
+#define HCI_Read_Data_Block_Size		HCI_CMD_OPCODE(0x04, 0x000A)
+
+/* AMP HCI command parameters */
+typedef BWL_PRE_PACKED_STRUCT struct read_local_cmd_parms {
+	uint8 plh;
+	uint8 offset[2];			/* length so far */
+	uint8 max_remote[2];
+} BWL_POST_PACKED_STRUCT read_local_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct write_remote_cmd_parms {
+	uint8 plh;
+	uint8 offset[2];
+	uint8 len[2];
+	uint8 frag[1];
+} BWL_POST_PACKED_STRUCT write_remote_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct phy_link_cmd_parms {
+	uint8 plh;
+	uint8 key_length;
+	uint8 key_type;
+	uint8 key[1];
+} BWL_POST_PACKED_STRUCT phy_link_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_cmd_parms {
+	uint8 plh;
+	uint8 reason;
+} BWL_POST_PACKED_STRUCT dis_phy_link_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_cmd_parms {
+	uint8 plh;
+	uint8 txflow[16];
+	uint8 rxflow[16];
+} BWL_POST_PACKED_STRUCT log_link_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ext_flow_spec {
+	uint8 id;
+	uint8 service_type;
+	uint8 max_sdu[2];
+	uint8 sdu_ia_time[4];
+	uint8 access_latency[4];
+	uint8 flush_timeout[4];
+} BWL_POST_PACKED_STRUCT ext_flow_spec_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_cmd_parms {
+	uint8 plh;
+	uint8 tx_fs_ID;
+} BWL_POST_PACKED_STRUCT log_link_cancel_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_cmd_parms {
+	uint8 llh[2];
+	uint8 txflow[16];
+	uint8 rxflow[16];
+} BWL_POST_PACKED_STRUCT flow_spec_mod_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct plh_pad {
+	uint8 plh;
+	uint8 pad;
+} BWL_POST_PACKED_STRUCT plh_pad_t;
+
+typedef BWL_PRE_PACKED_STRUCT union hci_handle {
+	uint16 bredr;
+	plh_pad_t amp;
+} BWL_POST_PACKED_STRUCT hci_handle_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ls_to_cmd_parms {
+	hci_handle_t handle;
+	uint8 timeout[2];
+} BWL_POST_PACKED_STRUCT ls_to_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct befto_cmd_parms {
+	uint8 llh[2];
+	uint8 befto[4];
+} BWL_POST_PACKED_STRUCT befto_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct srm_cmd_parms {
+	uint8 plh;
+	uint8 srm;
+} BWL_POST_PACKED_STRUCT srm_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ld_cmd_parms {
+	uint8 ld_aware;
+	uint8 ld[2];
+	uint8 ld_opts;
+	uint8 l_opts;
+} BWL_POST_PACKED_STRUCT ld_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct eflush_cmd_parms {
+	uint8 llh[2];
+	uint8 packet_type;
+} BWL_POST_PACKED_STRUCT eflush_cmd_parms_t;
+
+/* Generic AMP extended flow spec service types */
+#define EFS_SVCTYPE_NO_TRAFFIC		0
+#define EFS_SVCTYPE_BEST_EFFORT		1
+#define EFS_SVCTYPE_GUARANTEED		2
+
+/* AMP HCI event packet format */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_event {
+	uint8 ecode;
+	uint8 plen;
+	uint8 parms[1];
+} BWL_POST_PACKED_STRUCT amp_hci_event_t;
+
+#define HCI_EVT_PREAMBLE_SIZE			OFFSETOF(amp_hci_event_t, parms)
+
+/* AMP HCI event codes */
+#define HCI_Command_Complete			0x0E
+#define HCI_Command_Status			0x0F
+#define HCI_Flush_Occurred			0x11
+#define HCI_Enhanced_Flush_Complete		0x39
+#define HCI_Physical_Link_Complete		0x40
+#define HCI_Channel_Select			0x41
+#define HCI_Disconnect_Physical_Link_Complete	0x42
+#define HCI_Logical_Link_Complete		0x45
+#define HCI_Disconnect_Logical_Link_Complete	0x46
+#define HCI_Flow_Spec_Modify_Complete		0x47
+#define HCI_Number_of_Completed_Data_Blocks	0x48
+#define HCI_Short_Range_Mode_Change_Complete	0x4C
+#define HCI_Status_Change_Event			0x4D
+#define HCI_Vendor_Specific			0xFF
+
+/* AMP HCI event mask bit positions */
+#define HCI_Physical_Link_Complete_Event_Mask			0x0001
+#define HCI_Channel_Select_Event_Mask				0x0002
+#define HCI_Disconnect_Physical_Link_Complete_Event_Mask	0x0004
+#define HCI_Logical_Link_Complete_Event_Mask			0x0020
+#define HCI_Disconnect_Logical_Link_Complete_Event_Mask		0x0040
+#define HCI_Flow_Spec_Modify_Complete_Event_Mask		0x0080
+#define HCI_Number_of_Completed_Data_Blocks_Event_Mask		0x0100
+#define HCI_Short_Range_Mode_Change_Complete_Event_Mask		0x1000
+#define HCI_Status_Change_Event_Mask				0x2000
+#define HCI_All_Event_Mask					0x31e7
+/* AMP HCI event parameters */
+typedef BWL_PRE_PACKED_STRUCT struct cmd_status_parms {
+	uint8 status;
+	uint8 cmdpkts;
+	uint16 opcode;
+} BWL_POST_PACKED_STRUCT cmd_status_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct cmd_complete_parms {
+	uint8 cmdpkts;
+	uint16 opcode;
+	uint8 parms[1];
+} BWL_POST_PACKED_STRUCT cmd_complete_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct flush_occurred_evt_parms {
+	uint16 handle;
+} BWL_POST_PACKED_STRUCT flush_occurred_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct write_remote_evt_parms {
+	uint8 status;
+	uint8 plh;
+} BWL_POST_PACKED_STRUCT write_remote_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_local_evt_parms {
+	uint8 status;
+	uint8 plh;
+	uint16 len;
+	uint8 frag[1];
+} BWL_POST_PACKED_STRUCT read_local_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_local_info_evt_parms {
+	uint8 status;
+	uint8 AMP_status;
+	uint32 bandwidth;
+	uint32 gbandwidth;
+	uint32 latency;
+	uint32 PDU_size;
+	uint8 ctrl_type;
+	uint16 PAL_cap;
+	uint16 AMP_ASSOC_len;
+	uint32 max_flush_timeout;
+	uint32 be_flush_timeout;
+} BWL_POST_PACKED_STRUCT read_local_info_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_evt_parms {
+	uint8 status;
+	uint16 llh;
+	uint8 plh;
+	uint8 tx_fs_ID;
+} BWL_POST_PACKED_STRUCT log_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct disc_log_link_evt_parms {
+	uint8 status;
+	uint16 llh;
+	uint8 reason;
+} BWL_POST_PACKED_STRUCT disc_log_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_evt_parms {
+	uint8 status;
+	uint8 plh;
+	uint8 tx_fs_ID;
+} BWL_POST_PACKED_STRUCT log_link_cancel_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_evt_parms {
+	uint8 status;
+	uint16 llh;
+} BWL_POST_PACKED_STRUCT flow_spec_mod_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct phy_link_evt_parms {
+	uint8 status;
+	uint8 plh;
+} BWL_POST_PACKED_STRUCT phy_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_evt_parms {
+	uint8 status;
+	uint8 plh;
+	uint8 reason;
+} BWL_POST_PACKED_STRUCT dis_phy_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_ls_to_evt_parms {
+	uint8 status;
+	hci_handle_t handle;
+	uint16 timeout;
+} BWL_POST_PACKED_STRUCT read_ls_to_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_lla_ca_to_evt_parms {
+	uint8 status;
+	uint16 timeout;
+} BWL_POST_PACKED_STRUCT read_lla_ca_to_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_data_block_size_evt_parms {
+	uint8 status;
+	uint16 ACL_pkt_len;
+	uint16 data_block_len;
+	uint16 data_block_num;
+} BWL_POST_PACKED_STRUCT read_data_block_size_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct data_blocks {
+	uint16 handle;
+	uint16 pkts;
+	uint16 blocks;
+} BWL_POST_PACKED_STRUCT data_blocks_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct num_completed_data_blocks_evt_parms {
+	uint16 num_blocks;
+	uint8 num_handles;
+	data_blocks_t completed[1];
+} BWL_POST_PACKED_STRUCT num_completed_data_blocks_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct befto_evt_parms {
+	uint8 status;
+	uint32 befto;
+} BWL_POST_PACKED_STRUCT befto_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct srm_evt_parms {
+	uint8 status;
+	uint8 plh;
+	uint8 srm;
+} BWL_POST_PACKED_STRUCT srm_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct contact_counter_evt_parms {
+	uint8 status;
+	uint8 llh[2];
+	uint16 counter;
+} BWL_POST_PACKED_STRUCT contact_counter_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct contact_counter_reset_evt_parms {
+	uint8 status;
+	uint8 llh[2];
+} BWL_POST_PACKED_STRUCT contact_counter_reset_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_linkq_evt_parms {
+	uint8 status;
+	hci_handle_t handle;
+	uint8 link_quality;
+} BWL_POST_PACKED_STRUCT read_linkq_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ld_evt_parms {
+	uint8 status;
+	uint8 ld_aware;
+	uint8 ld[2];
+	uint8 ld_opts;
+	uint8 l_opts;
+} BWL_POST_PACKED_STRUCT ld_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct eflush_complete_evt_parms {
+	uint16 handle;
+} BWL_POST_PACKED_STRUCT eflush_complete_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct vendor_specific_evt_parms {
+	uint8 len;
+	uint8 parms[1];
+} BWL_POST_PACKED_STRUCT vendor_specific_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct local_version_info_evt_parms {
+	uint8 status;
+	uint8 hci_version;
+	uint16 hci_revision;
+	uint8 pal_version;
+	uint16 mfg_name;
+	uint16 pal_subversion;
+} BWL_POST_PACKED_STRUCT local_version_info_evt_parms_t;
+
+#define MAX_SUPPORTED_CMD_BYTE	64
+typedef BWL_PRE_PACKED_STRUCT struct local_supported_cmd_evt_parms {
+	uint8 status;
+	uint8 cmd[MAX_SUPPORTED_CMD_BYTE];
+} BWL_POST_PACKED_STRUCT local_supported_cmd_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct status_change_evt_parms {
+	uint8 status;
+	uint8 amp_status;
+} BWL_POST_PACKED_STRUCT status_change_evt_parms_t;
+
+/* AMP HCI error codes */
+#define HCI_SUCCESS				0x00
+#define HCI_ERR_ILLEGAL_COMMAND			0x01
+#define HCI_ERR_NO_CONNECTION			0x02
+#define HCI_ERR_MEMORY_FULL			0x07
+#define HCI_ERR_CONNECTION_TIMEOUT		0x08
+#define HCI_ERR_MAX_NUM_OF_CONNECTIONS		0x09
+#define HCI_ERR_CONNECTION_EXISTS		0x0B
+#define HCI_ERR_CONNECTION_DISALLOWED		0x0C
+#define HCI_ERR_CONNECTION_ACCEPT_TIMEOUT	0x10
+#define HCI_ERR_UNSUPPORTED_VALUE		0x11
+#define HCI_ERR_ILLEGAL_PARAMETER_FMT		0x12
+#define HCI_ERR_CONN_TERM_BY_LOCAL_HOST		0x16
+#define HCI_ERR_UNSPECIFIED			0x1F
+#define HCI_ERR_UNIT_KEY_USED			0x26
+#define HCI_ERR_QOS_REJECTED			0x2D
+#define HCI_ERR_PARAM_OUT_OF_RANGE		0x30
+#define HCI_ERR_NO_SUITABLE_CHANNEL		0x39
+#define HCI_ERR_CHANNEL_MOVE			0xFF
+
+/* AMP HCI ACL Data packet format */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_ACL_data {
+	uint16	handle;			/* 12-bit connection handle + 2-bit PB and 2-bit BC flags */
+	uint16	dlen;			/* data total length */
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT amp_hci_ACL_data_t;
+
+#define HCI_ACL_DATA_PREAMBLE_SIZE	OFFSETOF(amp_hci_ACL_data_t, data)
+
+#define HCI_ACL_DATA_BC_FLAGS		(0x0 << 14)
+#define HCI_ACL_DATA_PB_FLAGS		(0x3 << 12)
+
+#define HCI_ACL_DATA_HANDLE(handle)	((handle) & 0x0fff)
+#define HCI_ACL_DATA_FLAGS(handle)	((handle) >> 12)
+
+/* AMP Activity Report packet formats */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report {
+	uint8	ScheduleKnown;
+	uint8	NumReports;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT amp_hci_activity_report_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report_triple {
+	uint32	StartTime;
+	uint32	Duration;
+	uint32	Periodicity;
+} BWL_POST_PACKED_STRUCT amp_hci_activity_report_triple_t;
+
+#define HCI_AR_SCHEDULE_KNOWN		0x01
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _bt_amp_hci_h_ */
diff --git a/src/common/include/proto/eapol.h b/src/common/include/proto/eapol.h
new file mode 100644
index 0000000..3f283a6
--- /dev/null
+++ b/src/common/include/proto/eapol.h
@@ -0,0 +1,193 @@
+/*
+ * 802.1x EAPOL definitions
+ *
+ * See
+ * IEEE Std 802.1X-2001
+ * IEEE 802.1X RADIUS Usage Guidelines
+ *
+ * Copyright Open Broadcom Corporation
+ *
+ * $Id: eapol.h 452678 2014-01-31 19:16:29Z $
+ */
+
+#ifndef _eapol_h_
+#define _eapol_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#include <bcmcrypto/aeskeywrap.h>
+
+/* EAPOL for 802.3/Ethernet */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	struct ether_header eth;	/* 802.3/Ethernet header */
+	unsigned char version;		/* EAPOL protocol version */
+	unsigned char type;		/* EAPOL type */
+	unsigned short length;		/* Length of body */
+	unsigned char body[1];		/* Body (optional) */
+} BWL_POST_PACKED_STRUCT eapol_header_t;
+
+#define EAPOL_HEADER_LEN 18
+
+typedef struct {
+	unsigned char version;		/* EAPOL protocol version */
+	unsigned char type;		/* EAPOL type */
+	unsigned short length;		/* Length of body */
+} eapol_hdr_t;
+
+#define EAPOL_HDR_LEN 4
+
+/* EAPOL version */
+#define WPA2_EAPOL_VERSION	2
+#define WPA_EAPOL_VERSION	1
+#define LEAP_EAPOL_VERSION	1
+#define SES_EAPOL_VERSION	1
+
+/* EAPOL types */
+#define EAP_PACKET		0
+#define EAPOL_START		1
+#define EAPOL_LOGOFF		2
+#define EAPOL_KEY		3
+#define EAPOL_ASF		4
+
+/* EAPOL-Key types */
+#define EAPOL_RC4_KEY		1
+#define EAPOL_WPA2_KEY		2	/* 802.11i/WPA2 */
+#define EAPOL_WPA_KEY		254	/* WPA */
+
+/* RC4 EAPOL-Key header field sizes */
+#define EAPOL_KEY_REPLAY_LEN	8
+#define EAPOL_KEY_IV_LEN	16
+#define EAPOL_KEY_SIG_LEN	16
+
+/* RC4 EAPOL-Key */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	unsigned char type;			/* Key Descriptor Type */
+	unsigned short length;			/* Key Length (unaligned) */
+	unsigned char replay[EAPOL_KEY_REPLAY_LEN];	/* Replay Counter */
+	unsigned char iv[EAPOL_KEY_IV_LEN];		/* Key IV */
+	unsigned char index;				/* Key Flags & Index */
+	unsigned char signature[EAPOL_KEY_SIG_LEN];	/* Key Signature */
+	unsigned char key[1];				/* Key (optional) */
+} BWL_POST_PACKED_STRUCT eapol_key_header_t;
+
+#define EAPOL_KEY_HEADER_LEN 	44
+
+/* RC4 EAPOL-Key flags */
+#define EAPOL_KEY_FLAGS_MASK	0x80
+#define EAPOL_KEY_BROADCAST	0
+#define EAPOL_KEY_UNICAST	0x80
+
+/* RC4 EAPOL-Key index */
+#define EAPOL_KEY_INDEX_MASK	0x7f
+
+/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */
+#define EAPOL_WPA_KEY_REPLAY_LEN	8
+#define EAPOL_WPA_KEY_NONCE_LEN		32
+#define EAPOL_WPA_KEY_IV_LEN		16
+#define EAPOL_WPA_KEY_RSC_LEN		8
+#define EAPOL_WPA_KEY_ID_LEN		8
+#define EAPOL_WPA_KEY_MIC_LEN		16
+#define EAPOL_WPA_KEY_DATA_LEN		(EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN)
+#define EAPOL_WPA_MAX_KEY_SIZE		32
+
+/* WPA EAPOL-Key */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	unsigned char type;		/* Key Descriptor Type */
+	unsigned short key_info;	/* Key Information (unaligned) */
+	unsigned short key_len;		/* Key Length (unaligned) */
+	unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN];	/* Replay Counter */
+	unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN];	/* Nonce */
+	unsigned char iv[EAPOL_WPA_KEY_IV_LEN];		/* Key IV */
+	unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN];	/* Key RSC */
+	unsigned char id[EAPOL_WPA_KEY_ID_LEN];		/* WPA:Key ID, 802.11i/WPA2: Reserved */
+	unsigned char mic[EAPOL_WPA_KEY_MIC_LEN];	/* Key MIC */
+	unsigned short data_len;			/* Key Data Length */
+	unsigned char data[EAPOL_WPA_KEY_DATA_LEN];	/* Key data */
+} BWL_POST_PACKED_STRUCT eapol_wpa_key_header_t;
+
+#define EAPOL_WPA_KEY_LEN 		95
+
+/* WPA/802.11i/WPA2 KEY KEY_INFO bits */
+#define WPA_KEY_DESC_V1		0x01
+#define WPA_KEY_DESC_V2		0x02
+#define WPA_KEY_DESC_V3		0x03
+#define WPA_KEY_PAIRWISE	0x08
+#define WPA_KEY_INSTALL		0x40
+#define WPA_KEY_ACK		0x80
+#define WPA_KEY_MIC		0x100
+#define WPA_KEY_SECURE		0x200
+#define WPA_KEY_ERROR		0x400
+#define WPA_KEY_REQ		0x800
+
+#define WPA_KEY_DESC_V2_OR_V3 WPA_KEY_DESC_V2
+
+/* WPA-only KEY KEY_INFO bits */
+#define WPA_KEY_INDEX_0		0x00
+#define WPA_KEY_INDEX_1		0x10
+#define WPA_KEY_INDEX_2		0x20
+#define WPA_KEY_INDEX_3		0x30
+#define WPA_KEY_INDEX_MASK	0x30
+#define WPA_KEY_INDEX_SHIFT	0x04
+
+/* 802.11i/WPA2-only KEY KEY_INFO bits */
+#define WPA_KEY_ENCRYPTED_DATA	0x1000
+
+/* Key Data encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8 type;
+	uint8 length;
+	uint8 oui[3];
+	uint8 subtype;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_encap_data_t;
+
+#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 	6
+
+#define WPA2_KEY_DATA_SUBTYPE_GTK	1
+#define WPA2_KEY_DATA_SUBTYPE_STAKEY	2
+#define WPA2_KEY_DATA_SUBTYPE_MAC	3
+#define WPA2_KEY_DATA_SUBTYPE_PMKID	4
+#define WPA2_KEY_DATA_SUBTYPE_IGTK	9
+
+/* GTK encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8	flags;
+	uint8	reserved;
+	uint8	gtk[EAPOL_WPA_MAX_KEY_SIZE];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_key_gtk_encap_t;
+
+#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 	2
+
+#define WPA2_GTK_INDEX_MASK	0x03
+#define WPA2_GTK_INDEX_SHIFT	0x00
+
+#define WPA2_GTK_TRANSMIT	0x04
+
+/* IGTK encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16	key_id;
+	uint8	ipn[6];
+	uint8	key[EAPOL_WPA_MAX_KEY_SIZE];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_key_igtk_encap_t;
+
+#define EAPOL_WPA2_KEY_IGTK_ENCAP_HDR_LEN 	8
+
+/* STAKey encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8	reserved[2];
+	uint8	mac[ETHER_ADDR_LEN];
+	uint8	stakey[EAPOL_WPA_MAX_KEY_SIZE];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_key_stakey_encap_t;
+
+#define WPA2_KEY_DATA_PAD	0xdd
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _eapol_h_ */
diff --git a/src/common/include/proto/ethernet.h b/src/common/include/proto/ethernet.h
new file mode 100644
index 0000000..ba06a33
--- /dev/null
+++ b/src/common/include/proto/ethernet.h
@@ -0,0 +1,174 @@
+/*
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: ethernet.h 403353 2013-05-20 14:05:33Z $
+ */
+
+#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		
+#ifdef PLC
+#define	ETHER_TYPE_88E1		0x88e1		
+#define	ETHER_TYPE_8912		0x8912		
+#define ETHER_TYPE_GIGLED	0xffff		
+#endif 
+#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_IAPP_L2_UPDATE	0x6	
+
+
+#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/p2p.h b/src/common/include/proto/p2p.h
new file mode 100644
index 0000000..f4077ac
--- /dev/null
+++ b/src/common/include/proto/p2p.h
@@ -0,0 +1,574 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * Fundamental types and constants relating to WFA P2P (aka WiFi Direct)
+ *
+ * $Id: p2p.h 444066 2013-12-18 12:49:24Z $
+ */
+
+#ifndef _P2P_H_
+#define _P2P_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+#include <wlioctl.h>
+#include <proto/802.11.h>
+
+
+#include <packed_section_start.h>
+
+
+
+#define P2P_OUI			WFA_OUI			
+#define P2P_VER			WFA_OUI_TYPE_P2P	
+
+#define P2P_IE_ID		0xdd			
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_ie {
+	uint8	id;		
+	uint8	len;		
+	uint8	OUI[3];		
+	uint8	oui_type;	
+	uint8	subelts[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_ie wifi_p2p_ie_t;
+
+#define P2P_IE_FIXED_LEN	6
+
+#define P2P_ATTR_ID_OFF		0
+#define P2P_ATTR_LEN_OFF	1
+#define P2P_ATTR_DATA_OFF	3
+
+#define P2P_ATTR_ID_LEN		1	
+#define P2P_ATTR_LEN_LEN	2	
+#define P2P_ATTR_HDR_LEN	3 
+
+
+#define P2P_SEID_STATUS			0	
+#define P2P_SEID_MINOR_RC		1	
+#define P2P_SEID_P2P_INFO		2	
+#define P2P_SEID_DEV_ID			3	
+#define P2P_SEID_INTENT			4	
+#define P2P_SEID_CFG_TIMEOUT		5	
+#define P2P_SEID_CHANNEL		6	
+#define P2P_SEID_GRP_BSSID		7	
+#define P2P_SEID_XT_TIMING		8	
+#define P2P_SEID_INTINTADDR		9	
+#define P2P_SEID_P2P_MGBTY		10	
+#define P2P_SEID_CHAN_LIST		11	
+#define P2P_SEID_ABSENCE		12	
+#define P2P_SEID_DEV_INFO		13	
+#define P2P_SEID_GROUP_INFO		14	
+#define P2P_SEID_GROUP_ID		15	
+#define P2P_SEID_P2P_IF			16	
+#define P2P_SEID_OP_CHANNEL		17	
+#define P2P_SEID_INVITE_FLAGS		18	
+#define P2P_SEID_VNDR			221	
+
+#define P2P_SE_VS_ID_SERVICES	0x1b
+
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_info_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	dev;		
+	uint8	group;		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_info_se_s wifi_p2p_info_se_t;
+
+
+#define P2P_CAPSE_DEV_SERVICE_DIS	0x1 
+#define P2P_CAPSE_DEV_CLIENT_DIS	0x2 
+#define P2P_CAPSE_DEV_CONCURRENT	0x4 
+#define P2P_CAPSE_DEV_INFRA_MAN		0x8 
+#define P2P_CAPSE_DEV_LIMIT			0x10 
+#define P2P_CAPSE_INVITE_PROC		0x20 
+
+
+#define P2P_CAPSE_GRP_OWNER			0x1 
+#define P2P_CAPSE_PERSIST_GRP		0x2 
+#define P2P_CAPSE_GRP_LIMIT			0x4 
+#define P2P_CAPSE_GRP_INTRA_BSS		0x8 
+#define P2P_CAPSE_GRP_X_CONNECT		0x10 
+#define P2P_CAPSE_GRP_PERSISTENT	0x20 
+#define P2P_CAPSE_GRP_FORMATION		0x40 
+
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_intent_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	intent;		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_intent_se_s wifi_p2p_intent_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_cfg_tmo_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	go_tmo;		
+	uint8	client_tmo;	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_cfg_tmo_se_s wifi_p2p_cfg_tmo_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_listen_channel_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	country[3];	
+	uint8	op_class;	
+	uint8	channel;	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_listen_channel_se_s wifi_p2p_listen_channel_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_bssid_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	mac[6];		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_grp_bssid_se_s wifi_p2p_grp_bssid_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_id_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	mac[6];		
+	uint8	ssid[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_grp_id_se_s wifi_p2p_grp_id_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_intf_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	mac[6];		
+	uint8	ifaddrs;	
+	uint8	ifaddr[1][6];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_intf_se_s wifi_p2p_intf_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_status_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	status;		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_status_se_s wifi_p2p_status_se_t;
+
+
+#define P2P_STATSE_SUCCESS			0
+				
+#define P2P_STATSE_FAIL_INFO_CURR_UNAVAIL	1
+				
+#define P2P_STATSE_PASSED_UP			P2P_STATSE_FAIL_INFO_CURR_UNAVAIL
+				
+#define P2P_STATSE_FAIL_INCOMPAT_PARAMS		2
+				
+#define P2P_STATSE_FAIL_LIMIT_REACHED		3
+				
+#define P2P_STATSE_FAIL_INVALID_PARAMS		4
+				
+#define P2P_STATSE_FAIL_UNABLE_TO_ACCOM		5
+				
+#define P2P_STATSE_FAIL_PROTO_ERROR		6
+				
+#define P2P_STATSE_FAIL_NO_COMMON_CHAN		7
+				
+#define P2P_STATSE_FAIL_UNKNOWN_GROUP		8
+				
+#define P2P_STATSE_FAIL_INTENT			9
+				
+#define P2P_STATSE_FAIL_INCOMPAT_PROVIS		10
+				
+#define P2P_STATSE_FAIL_USER_REJECT		11
+				
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_ext_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	avail[2];	
+	uint8	interval[2];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_ext_se_s wifi_p2p_ext_se_t;
+
+#define P2P_EXT_MIN	10	
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_intintad_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	mac[6];		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_intintad_se_s wifi_p2p_intintad_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_channel_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	band;		
+	uint8	channel;	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_channel_se_s wifi_p2p_channel_se_t;
+
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_entry_s {
+	uint8	band;						
+	uint8	num_channels;				
+	uint8	channels[WL_NUMCHANNELS];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_chanlist_entry_s wifi_p2p_chanlist_entry_t;
+#define WIFI_P2P_CHANLIST_SE_MAX_ENTRIES 2
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	country[3];	
+	uint8	num_entries;	
+	wifi_p2p_chanlist_entry_t	entries[WIFI_P2P_CHANLIST_SE_MAX_ENTRIES];
+						
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_chanlist_se_s wifi_p2p_chanlist_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_pri_devtype_s {
+	uint16	cat_id;		
+	uint8	OUI[3];		
+	uint8	oui_type;	
+	uint16	sub_cat_id;	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_pri_devtype_s wifi_p2p_pri_devtype_t;
+
+
+#define P2P_DISE_SUBCATEGORY_MINVAL		1
+#define P2P_DISE_CATEGORY_COMPUTER		1
+#define P2P_DISE_SUBCATEGORY_COMPUTER_MAXVAL		8
+#define P2P_DISE_CATEGORY_INPUT_DEVICE		2
+#define P2P_DISE_SUBCATEGORY_INPUT_DEVICE_MAXVAL	9
+#define P2P_DISE_CATEGORY_PRINTER		3
+#define P2P_DISE_SUBCATEGORY_PRINTER_MAXVAL		5
+#define P2P_DISE_CATEGORY_CAMERA		4
+#define P2P_DISE_SUBCATEGORY_CAMERA_MAXVAL		4
+#define P2P_DISE_CATEGORY_STORAGE		5
+#define P2P_DISE_SUBCATEGORY_STORAGE_MAXVAL		1
+#define P2P_DISE_CATEGORY_NETWORK_INFRA		6
+#define P2P_DISE_SUBCATEGORY_NETWORK_INFRA_MAXVAL	4
+#define P2P_DISE_CATEGORY_DISPLAY		7
+#define P2P_DISE_SUBCATEGORY_DISPLAY_MAXVAL		4
+#define P2P_DISE_CATEGORY_MULTIMEDIA		8
+#define P2P_DISE_SUBCATEGORY_MULTIMEDIA_MAXVAL		6
+#define P2P_DISE_CATEGORY_GAMING		9
+#define P2P_DISE_SUBCATEGORY_GAMING_MAXVAL		5
+#define P2P_DISE_CATEGORY_TELEPHONE		10
+#define P2P_DISE_SUBCATEGORY_TELEPHONE_MAXVAL		5
+#define P2P_DISE_CATEGORY_AUDIO			11
+#define P2P_DISE_SUBCATEGORY_AUDIO_MAXVAL		6
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_devinfo_se_s {
+	uint8	eltId;			
+	uint8	len[2];			
+	uint8	mac[6];			
+	uint16	wps_cfg_meths;		
+	uint8	pri_devtype[8];		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_devinfo_se_s wifi_p2p_devinfo_se_t;
+
+#define P2P_DEV_TYPE_LEN	8
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_cid_fixed_s {
+	uint8	len;
+	uint8	devaddr[ETHER_ADDR_LEN];	
+	uint8	ifaddr[ETHER_ADDR_LEN];		
+	uint8	devcap;				
+	uint8	cfg_meths[2];			
+	uint8	pridt[P2P_DEV_TYPE_LEN];	
+	uint8	secdts;				
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_cid_fixed_s wifi_p2p_cid_fixed_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_devid_se_s {
+	uint8	eltId;
+	uint8	len[2];
+	struct ether_addr	addr;			
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_devid_se_s wifi_p2p_devid_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_mgbt_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	mg_bitmap;	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_mgbt_se_s wifi_p2p_mgbt_se_t;
+
+#define P2P_MGBTSE_P2PDEVMGMT_FLAG   0x1 
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_grpinfo_se_s {
+	uint8	eltId;			
+	uint8	len[2];			
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_grpinfo_se_s wifi_p2p_grpinfo_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_op_channel_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	country[3];	
+	uint8	op_class;	
+	uint8	channel;	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_op_channel_se_s wifi_p2p_op_channel_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_invite_flags_se_s {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	flags;		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_invite_flags_se_s wifi_p2p_invite_flags_se_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_action_frame {
+	uint8	category;	
+	uint8	OUI[3];		
+	uint8	type;		
+	uint8	subtype;	
+	uint8	dialog_token;	
+	uint8	elts[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_action_frame wifi_p2p_action_frame_t;
+#define P2P_AF_CATEGORY		0x7f
+
+#define P2P_AF_FIXED_LEN	7
+
+
+#define P2P_AF_NOTICE_OF_ABSENCE	0	
+#define P2P_AF_PRESENCE_REQ		1	
+#define P2P_AF_PRESENCE_RSP		2	
+#define P2P_AF_GO_DISC_REQ		3	
+
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_pub_act_frame {
+	uint8	category;	
+	uint8	action;		
+	uint8	oui[3];		
+	uint8	oui_type;	
+	uint8	subtype;	
+	uint8	dialog_token;	
+	uint8	elts[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t;
+#define P2P_PUB_AF_FIXED_LEN	8
+#define P2P_PUB_AF_CATEGORY	0x04
+#define P2P_PUB_AF_ACTION	0x09
+
+
+#define P2P_PAF_GON_REQ		0	
+#define P2P_PAF_GON_RSP		1	
+#define P2P_PAF_GON_CONF	2	
+#define P2P_PAF_INVITE_REQ	3	
+#define P2P_PAF_INVITE_RSP	4	
+#define P2P_PAF_DEVDIS_REQ	5	
+#define P2P_PAF_DEVDIS_RSP	6	
+#define P2P_PAF_PROVDIS_REQ	7	
+#define P2P_PAF_PROVDIS_RSP	8	
+#define P2P_PAF_SUBTYPE_INVALID	255	
+
+
+#define P2P_TYPE_MNREQ		P2P_PAF_GON_REQ
+#define P2P_TYPE_MNRSP		P2P_PAF_GON_RSP
+#define P2P_TYPE_MNCONF		P2P_PAF_GON_CONF
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_desc {
+	uint8	cnt_type;	
+	uint32	duration;	
+	uint32	interval;	
+	uint32	start;		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_noa_desc wifi_p2p_noa_desc_t;
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_se {
+	uint8	eltId;		
+	uint8	len[2];		
+	uint8	index;		
+	uint8	ops_ctw_parms;	
+	wifi_p2p_noa_desc_t	desc[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_noa_se wifi_p2p_noa_se_t;
+
+#define P2P_NOA_SE_FIXED_LEN	5
+
+#define P2P_NOA_SE_MAX_DESC	2	
+
+
+#define P2P_NOA_DESC_CNT_RESERVED	0	
+#define P2P_NOA_DESC_CNT_REPEAT		255	
+#define P2P_NOA_DESC_TYPE_PREFERRED	1	
+#define P2P_NOA_DESC_TYPE_ACCEPTABLE	2	
+
+
+#define P2P_NOA_CTW_MASK	0x7f
+#define P2P_NOA_OPS_MASK	0x80
+#define P2P_NOA_OPS_SHIFT	7
+
+#define P2P_CTW_MIN	10	
+
+
+#define	P2PSD_ACTION_CATEGORY		0x04
+				
+#define	P2PSD_ACTION_ID_GAS_IREQ	0x0a
+				
+#define	P2PSD_ACTION_ID_GAS_IRESP	0x0b
+				
+#define	P2PSD_ACTION_ID_GAS_CREQ	0x0c
+				
+#define	P2PSD_ACTION_ID_GAS_CRESP	0x0d
+				
+#define P2PSD_AD_EID				0x6c
+				
+#define P2PSD_ADP_TUPLE_QLMT_PAMEBI	0x00
+				
+#define P2PSD_ADP_PROTO_ID			0x00
+				
+#define P2PSD_GAS_OUI				P2P_OUI
+				
+#define P2PSD_GAS_OUI_SUBTYPE		P2P_VER
+				
+#define P2PSD_GAS_NQP_INFOID		0xDDDD
+				
+#define P2PSD_GAS_COMEBACKDEALY		0x00
+				
+
+
+typedef enum p2psd_svc_protype {
+	SVC_RPOTYPE_ALL = 0,
+	SVC_RPOTYPE_BONJOUR = 1,
+	SVC_RPOTYPE_UPNP = 2,
+	SVC_RPOTYPE_WSD = 3,
+	SVC_RPOTYPE_VENDOR = 255
+} p2psd_svc_protype_t;
+
+
+typedef enum {
+	P2PSD_RESP_STATUS_SUCCESS = 0,
+	P2PSD_RESP_STATUS_PROTYPE_NA = 1,
+	P2PSD_RESP_STATUS_DATA_NA = 2,
+	P2PSD_RESP_STATUS_BAD_REQUEST = 3
+} p2psd_resp_status_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_tpl {
+	uint8	llm_pamebi;	
+	uint8	adp_id;		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_adp_tpl wifi_p2psd_adp_tpl_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_ie {
+	uint8	id;		
+	uint8	len;	
+	wifi_p2psd_adp_tpl_t adp_tpl;  
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_adp_ie wifi_p2psd_adp_ie_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_nqp_query_vsc {
+	uint8	oui_subtype;	
+	uint16	svc_updi;		
+	uint8	svc_tlvs[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_nqp_query_vsc wifi_p2psd_nqp_query_vsc_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_tlv {
+	uint16	len;			
+	uint8	svc_prot;		
+	uint8	svc_tscid;		
+	uint8	query_data[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qreq_tlv wifi_p2psd_qreq_tlv_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_frame {
+	uint16	info_id;	
+	uint16	len;		
+	uint8	oui[3];		
+	uint8	qreq_vsc[1]; 
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qreq_frame wifi_p2psd_qreq_frame_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_ireq_frame {
+	wifi_p2psd_adp_ie_t		adp_ie;		
+	uint16					qreq_len;	
+	uint8	qreq_frm[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_ireq_frame wifi_p2psd_gas_ireq_frame_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_tlv {
+	uint16	len;				
+	uint8	svc_prot;			
+	uint8	svc_tscid;			
+	uint8	status;				
+	uint8	query_data[1];		
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qresp_tlv wifi_p2psd_qresp_tlv_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_frame {
+	uint16	info_id;	
+	uint16	len;		
+	uint8	oui[3];		
+	uint8	qresp_vsc[1]; 
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qresp_frame wifi_p2psd_qresp_frame_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_iresp_frame {
+	uint16	status;			
+	uint16	cb_delay;		
+	wifi_p2psd_adp_ie_t	adp_ie;		
+	uint16		qresp_len;	
+	uint8	qresp_frm[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_iresp_frame wifi_p2psd_gas_iresp_frame_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_cresp_frame {
+	uint16	status;			
+	uint8	fragment_id;	
+	uint16	cb_delay;		
+	wifi_p2psd_adp_ie_t	adp_ie;		
+	uint16	qresp_len;		
+	uint8	qresp_frm[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_cresp_frame wifi_p2psd_gas_cresp_frame_t;
+
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_pub_act_frame {
+	uint8	category;		
+	uint8	action;			
+	uint8	dialog_token;	
+	uint8	query_data[1];	
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_pub_act_frame wifi_p2psd_gas_pub_act_frame_t;
+
+
+#include <packed_section_end.h>
+
+#endif 
diff --git a/src/common/include/proto/sdspi.h b/src/common/include/proto/sdspi.h
new file mode 100644
index 0000000..647a217
--- /dev/null
+++ b/src/common/include/proto/sdspi.h
@@ -0,0 +1,57 @@
+/*
+ * SD-SPI Protocol Standard
+ *
+ * $ Copyright Open Broadcom Corporation $
+ *
+ * $Id: sdspi.h 382882 2013-02-04 23:24:31Z $
+ */
+#ifndef	_SD_SPI_H
+#define	_SD_SPI_H
+
+#define SPI_START_M		BITFIELD_MASK(1)	/* Bit [31] 	- Start Bit */
+#define SPI_START_S		31
+#define SPI_DIR_M		BITFIELD_MASK(1)	/* Bit [30] 	- Direction */
+#define SPI_DIR_S		30
+#define SPI_CMD_INDEX_M		BITFIELD_MASK(6)	/* Bits [29:24] - Command number */
+#define SPI_CMD_INDEX_S		24
+#define SPI_RW_M		BITFIELD_MASK(1)	/* Bit [23] 	- Read=0, Write=1 */
+#define SPI_RW_S		23
+#define SPI_FUNC_M		BITFIELD_MASK(3)	/* Bits [22:20]	- Function Number */
+#define SPI_FUNC_S		20
+#define SPI_RAW_M		BITFIELD_MASK(1)	/* Bit [19] 	- Read After Wr */
+#define SPI_RAW_S		19
+#define SPI_STUFF_M		BITFIELD_MASK(1)	/* Bit [18] 	- Stuff bit */
+#define SPI_STUFF_S		18
+#define SPI_BLKMODE_M		BITFIELD_MASK(1)	/* Bit [19] 	- Blockmode 1=blk */
+#define SPI_BLKMODE_S		19
+#define SPI_OPCODE_M		BITFIELD_MASK(1)	/* Bit [18] 	- OP Code */
+#define SPI_OPCODE_S		18
+#define SPI_ADDR_M		BITFIELD_MASK(17)	/* Bits [17:1] 	- Address */
+#define SPI_ADDR_S		1
+#define SPI_STUFF0_M		BITFIELD_MASK(1)	/* Bit [0] 	- Stuff bit */
+#define SPI_STUFF0_S		0
+
+#define SPI_RSP_START_M		BITFIELD_MASK(1)	/* Bit [7] 	- Start Bit (always 0) */
+#define SPI_RSP_START_S		7
+#define SPI_RSP_PARAM_ERR_M	BITFIELD_MASK(1)	/* Bit [6] 	- Parameter Error */
+#define SPI_RSP_PARAM_ERR_S	6
+#define SPI_RSP_RFU5_M		BITFIELD_MASK(1)	/* Bit [5] 	- RFU (Always 0) */
+#define SPI_RSP_RFU5_S		5
+#define SPI_RSP_FUNC_ERR_M	BITFIELD_MASK(1)	/* Bit [4] 	- Function number error */
+#define SPI_RSP_FUNC_ERR_S	4
+#define SPI_RSP_CRC_ERR_M	BITFIELD_MASK(1)	/* Bit [3] 	- COM CRC Error */
+#define SPI_RSP_CRC_ERR_S	3
+#define SPI_RSP_ILL_CMD_M	BITFIELD_MASK(1)	/* Bit [2] 	- Illegal Command error */
+#define SPI_RSP_ILL_CMD_S	2
+#define SPI_RSP_RFU1_M		BITFIELD_MASK(1)	/* Bit [1] 	- RFU (Always 0) */
+#define SPI_RSP_RFU1_S		1
+#define SPI_RSP_IDLE_M		BITFIELD_MASK(1)	/* Bit [0] 	- In idle state */
+#define SPI_RSP_IDLE_S		0
+
+/* SD-SPI Protocol Definitions */
+#define SDSPI_COMMAND_LEN	6	/* Number of bytes in an SD command */
+#define SDSPI_START_BLOCK	0xFE	/* SD Start Block Token */
+#define SDSPI_IDLE_PAD		0xFF	/* SD-SPI idle value for MOSI */
+#define SDSPI_START_BIT_MASK	0x80
+
+#endif /* _SD_SPI_H */
diff --git a/src/common/include/proto/vlan.h b/src/common/include/proto/vlan.h
new file mode 100644
index 0000000..bf48965
--- /dev/null
+++ b/src/common/include/proto/vlan.h
@@ -0,0 +1,75 @@
+/*
+ * 802.1Q VLAN protocol definitions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: vlan.h 382883 2013-02-04 23:26:09Z $
+ */
+
+#ifndef _vlan_h_
+#define _vlan_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+
+#include <packed_section_start.h>
+
+#ifndef	 VLAN_VID_MASK
+#define VLAN_VID_MASK		0xfff	
+#endif
+
+#define	VLAN_CFI_SHIFT		12	
+#define VLAN_PRI_SHIFT		13	
+
+#define VLAN_PRI_MASK		7	
+
+#define	VLAN_TPID_OFFSET	12	
+#define	VLAN_TCI_OFFSET		14	
+
+#define	VLAN_TAG_LEN		4
+#define	VLAN_TAG_OFFSET		(2 * ETHER_ADDR_LEN)	
+
+#define VLAN_TPID		0x8100	
+
+struct vlan_header {
+	uint16	vlan_type;		
+	uint16	vlan_tag;		
+};
+
+struct ethervlan_header {
+	uint8	ether_dhost[ETHER_ADDR_LEN];
+	uint8	ether_shost[ETHER_ADDR_LEN];
+	uint16	vlan_type;		
+	uint16	vlan_tag;		
+	uint16	ether_type;
+};
+
+struct dot3_mac_llc_snapvlan_header {
+	uint8	ether_dhost[ETHER_ADDR_LEN];	
+	uint8	ether_shost[ETHER_ADDR_LEN];	
+	uint16	length;				
+	uint8	dsap;				
+	uint8	ssap;				
+	uint8	ctl;				
+	uint8	oui[3];				
+	uint16	vlan_type;			
+	uint16	vlan_tag;			
+	uint16	ether_type;			
+};
+
+#define	ETHERVLAN_HDR_LEN	(ETHER_HDR_LEN + VLAN_TAG_LEN)
+
+
+
+#include <packed_section_end.h>
+
+#define ETHERVLAN_MOVE_HDR(d, s) \
+do { \
+	struct ethervlan_header t; \
+	t = *(struct ethervlan_header *)(s); \
+	*(struct ethervlan_header *)(d) = t; \
+} while (0)
+
+#endif 
diff --git a/src/common/include/proto/wpa.h b/src/common/include/proto/wpa.h
new file mode 100644
index 0000000..519df36
--- /dev/null
+++ b/src/common/include/proto/wpa.h
@@ -0,0 +1,194 @@
+/*
+ * Fundamental types and constants relating to WPA
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: wpa.h 384536 2013-02-12 04:13:09Z $
+ */
+
+#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	
+#ifdef BCMCCX
+#define WPA_CIPHER_CKIP		8	
+#define WPA_CIPHER_CKIP_MMH	9	
+#define WPA_CIPHER_WEP_MMH	10	
+
+#define IS_CCX_CIPHER(cipher)	((cipher) == WPA_CIPHER_CKIP || \
+				 (cipher) == WPA_CIPHER_CKIP_MMH || \
+				 (cipher) == WPA_CIPHER_WEP_MMH)
+#endif
+
+#ifdef BCMWAPI_WAI
+#define WAPI_CIPHER_NONE	WPA_CIPHER_NONE
+#define WAPI_CIPHER_SMS4	11
+
+#define WAPI_CSE_WPI_SMS4	1
+#endif 
+
+#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)
+
+#ifdef BCMWAPI_WAI
+#define IS_WAPI_CIPHER(cipher)	((cipher) == WAPI_CIPHER_NONE || \
+				 (cipher) == WAPI_CSE_WPI_SMS4)
+
+
+#define WAPI_CSE_WPI_2_CIPHER(cse) ((cse) == WAPI_CSE_WPI_SMS4 ? \
+				WAPI_CIPHER_SMS4 : WAPI_CIPHER_NONE)
+
+#define WAPI_CIPHER_2_CSE_WPI(cipher) ((cipher) == WAPI_CIPHER_SMS4 ? \
+				WAPI_CSE_WPI_SMS4 : WAPI_CIPHER_NONE)
+#endif 
+
+
+#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
+
+#ifdef BCMWAPI_WAI
+#define WAPI_CAP_PREAUTH		RSN_CAP_PREAUTH
+
+
+#define WAPI_WAI_REQUEST		0x00F1
+#define WAPI_UNICAST_REKEY		0x00F2
+#define WAPI_STA_AGING			0x00F3
+#define WAPI_MUTIL_REKEY		0x00F4
+#define WAPI_STA_STATS			0x00F5
+
+#define WAPI_USK_REKEY_COUNT		0x4000000 
+#define WAPI_MSK_REKEY_COUNT		0x4000000 
+#endif 
+
+
+#include <packed_section_end.h>
+
+#endif 
diff --git a/src/common/include/proto/wps.h b/src/common/include/proto/wps.h
new file mode 100644
index 0000000..43c4996
--- /dev/null
+++ b/src/common/include/proto/wps.h
@@ -0,0 +1,361 @@
+/*
+ * WPS IE definitions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id$
+ */
+
+#ifndef _WPS_
+#define _WPS_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Data Element Definitions */
+#define WPS_ID_AP_CHANNEL         0x1001
+#define WPS_ID_ASSOC_STATE        0x1002
+#define WPS_ID_AUTH_TYPE          0x1003
+#define WPS_ID_AUTH_TYPE_FLAGS    0x1004
+#define WPS_ID_AUTHENTICATOR      0x1005
+#define WPS_ID_CONFIG_METHODS     0x1008
+#define WPS_ID_CONFIG_ERROR       0x1009
+#define WPS_ID_CONF_URL4          0x100A
+#define WPS_ID_CONF_URL6          0x100B
+#define WPS_ID_CONN_TYPE          0x100C
+#define WPS_ID_CONN_TYPE_FLAGS    0x100D
+#define WPS_ID_CREDENTIAL         0x100E
+#define WPS_ID_DEVICE_NAME        0x1011
+#define WPS_ID_DEVICE_PWD_ID      0x1012
+#define WPS_ID_E_HASH1            0x1014
+#define WPS_ID_E_HASH2            0x1015
+#define WPS_ID_E_SNONCE1          0x1016
+#define WPS_ID_E_SNONCE2          0x1017
+#define WPS_ID_ENCR_SETTINGS      0x1018
+#define WPS_ID_ENCR_TYPE          0x100F
+#define WPS_ID_ENCR_TYPE_FLAGS    0x1010
+#define WPS_ID_ENROLLEE_NONCE     0x101A
+#define WPS_ID_FEATURE_ID         0x101B
+#define WPS_ID_IDENTITY           0x101C
+#define WPS_ID_IDENTITY_PROOF     0x101D
+#define WPS_ID_KEY_WRAP_AUTH      0x101E
+#define WPS_ID_KEY_IDENTIFIER     0x101F
+#define WPS_ID_MAC_ADDR           0x1020
+#define WPS_ID_MANUFACTURER       0x1021
+#define WPS_ID_MSG_TYPE           0x1022
+#define WPS_ID_MODEL_NAME         0x1023
+#define WPS_ID_MODEL_NUMBER       0x1024
+#define WPS_ID_NW_INDEX           0x1026
+#define WPS_ID_NW_KEY             0x1027
+#define WPS_ID_NW_KEY_INDEX       0x1028
+#define WPS_ID_NEW_DEVICE_NAME    0x1029
+#define WPS_ID_NEW_PWD            0x102A
+#define WPS_ID_OOB_DEV_PWD        0x102C
+#define WPS_ID_OS_VERSION         0x102D
+#define WPS_ID_POWER_LEVEL        0x102F
+#define WPS_ID_PSK_CURRENT        0x1030
+#define WPS_ID_PSK_MAX            0x1031
+#define WPS_ID_PUBLIC_KEY         0x1032
+#define WPS_ID_RADIO_ENABLED      0x1033
+#define WPS_ID_REBOOT             0x1034
+#define WPS_ID_REGISTRAR_CURRENT  0x1035
+#define WPS_ID_REGISTRAR_ESTBLSHD 0x1036
+#define WPS_ID_REGISTRAR_LIST     0x1037
+#define WPS_ID_REGISTRAR_MAX      0x1038
+#define WPS_ID_REGISTRAR_NONCE    0x1039
+#define WPS_ID_REQ_TYPE           0x103A
+#define WPS_ID_RESP_TYPE          0x103B
+#define WPS_ID_RF_BAND            0x103C
+#define WPS_ID_R_HASH1            0x103D
+#define WPS_ID_R_HASH2            0x103E
+#define WPS_ID_R_SNONCE1          0x103F
+#define WPS_ID_R_SNONCE2          0x1040
+#define WPS_ID_SEL_REGISTRAR      0x1041
+#define WPS_ID_SERIAL_NUM         0x1042
+#define WPS_ID_SC_STATE           0x1044
+#define WPS_ID_SSID               0x1045
+#define WPS_ID_TOT_NETWORKS       0x1046
+#define WPS_ID_UUID_E             0x1047
+#define WPS_ID_UUID_R             0x1048
+#define WPS_ID_VENDOR_EXT         0x1049
+#define WPS_ID_VERSION            0x104A
+#define WPS_ID_X509_CERT_REQ      0x104B
+#define WPS_ID_X509_CERT          0x104C
+#define WPS_ID_EAP_IDENTITY       0x104D
+#define WPS_ID_MSG_COUNTER        0x104E
+#define WPS_ID_PUBKEY_HASH        0x104F
+#define WPS_ID_REKEY_KEY          0x1050
+#define WPS_ID_KEY_LIFETIME       0x1051
+#define WPS_ID_PERM_CFG_METHODS   0x1052
+#define WPS_ID_SEL_REG_CFG_METHODS 0x1053
+#define WPS_ID_PRIM_DEV_TYPE      0x1054
+#define WPS_ID_SEC_DEV_TYPE_LIST  0x1055
+#define WPS_ID_PORTABLE_DEVICE    0x1056
+#define WPS_ID_AP_SETUP_LOCKED    0x1057
+#define WPS_ID_APP_LIST           0x1058
+#define WPS_ID_EAP_TYPE           0x1059
+#define WPS_ID_INIT_VECTOR        0x1060
+#define WPS_ID_KEY_PROVIDED_AUTO  0x1061
+#define WPS_ID_8021X_ENABLED      0x1062
+#define WPS_ID_WEP_TRANSMIT_KEY   0x1064
+#define WPS_ID_REQ_DEV_TYPE       0x106A
+
+/* WSC 2.0, WFA Vendor Extension Subelements */
+#define WFA_VENDOR_EXT_ID                 "\x00\x37\x2A"
+#define WPS_WFA_SUBID_VERSION2            0x00
+#define WPS_WFA_SUBID_AUTHORIZED_MACS     0x01
+#define WPS_WFA_SUBID_NW_KEY_SHAREABLE    0x02
+#define WPS_WFA_SUBID_REQ_TO_ENROLL       0x03
+#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME 0x04
+
+
+/* WCN-NET Windows Rally Vertical Pairing Vendor Extensions */
+#define MS_VENDOR_EXT_ID           "\x00\x01\x37"
+#define WPS_MS_ID_VPI               0x1001	/* Vertical Pairing Identifier TLV */
+#define WPS_MS_ID_TRANSPORT_UUID    0x1002      /* Transport UUID TLV */
+
+/* Vertical Pairing Identifier TLV Definitions */
+#define WPS_MS_VPI_TRANSPORT_NONE   0x00        /* None */
+#define WPS_MS_VPI_TRANSPORT_DPWS   0x01        /* Devices Profile for Web Services */
+#define WPS_MS_VPI_TRANSPORT_UPNP   0x02        /* uPnP */
+#define WPS_MS_VPI_TRANSPORT_SDNWS  0x03        /* Secure Devices Profile for Web Services */
+#define WPS_MS_VPI_NO_PROFILE_REQ   0x00        /* Wi-Fi profile not requested.
+						 * Not supported in Windows 7
+						 */
+#define WPS_MS_VPI_PROFILE_REQ      0x01        /* Wi-Fi profile requested.  */
+
+/* sizes of the fixed size elements */
+#define WPS_ID_AP_CHANNEL_S       2
+#define WPS_ID_ASSOC_STATE_S      2
+#define WPS_ID_AUTH_TYPE_S        2
+#define WPS_ID_AUTH_TYPE_FLAGS_S  2
+#define WPS_ID_AUTHENTICATOR_S    8
+#define WPS_ID_CONFIG_METHODS_S   2
+#define WPS_ID_CONFIG_ERROR_S     2
+#define WPS_ID_CONN_TYPE_S          1
+#define WPS_ID_CONN_TYPE_FLAGS_S    1
+#define WPS_ID_DEVICE_PWD_ID_S      2
+#define WPS_ID_ENCR_TYPE_S          2
+#define WPS_ID_ENCR_TYPE_FLAGS_S    2
+#define WPS_ID_FEATURE_ID_S         4
+#define WPS_ID_MAC_ADDR_S           6
+#define WPS_ID_MSG_TYPE_S           1
+#define WPS_ID_SC_STATE_S           1
+#define WPS_ID_RF_BAND_S            1
+#define WPS_ID_OS_VERSION_S         4
+#define WPS_ID_VERSION_S            1
+#define WPS_ID_SEL_REGISTRAR_S      1
+#define WPS_ID_SEL_REG_CFG_METHODS_S 2
+#define WPS_ID_REQ_TYPE_S           1
+#define WPS_ID_RESP_TYPE_S          1
+#define WPS_ID_AP_SETUP_LOCKED_S    1
+
+/* WSC 2.0, WFA Vendor Extension Subelements */
+#define WPS_WFA_SUBID_VERSION2_S            1
+#define WPS_WFA_SUBID_NW_KEY_SHAREABLE_S    1
+#define WPS_WFA_SUBID_REQ_TO_ENROLL_S       1
+#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME_S 1
+
+/* Association states */
+#define WPS_ASSOC_NOT_ASSOCIATED  0
+#define WPS_ASSOC_CONN_SUCCESS    1
+#define WPS_ASSOC_CONFIG_FAIL     2
+#define WPS_ASSOC_ASSOC_FAIL      3
+#define WPS_ASSOC_IP_FAIL         4
+
+/* Authentication types */
+#define WPS_AUTHTYPE_OPEN        0x0001
+#define WPS_AUTHTYPE_WPAPSK      0x0002	/* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_SHARED      0x0004	/* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_WPA         0x0008	/* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_WPA2        0x0010
+#define WPS_AUTHTYPE_WPA2PSK     0x0020
+
+/* Config methods */
+#define WPS_CONFMET_USBA            0x0001	/* Deprecated in WSC 2.0 */
+#define WPS_CONFMET_ETHERNET        0x0002	/* Deprecated in WSC 2.0 */
+#define WPS_CONFMET_LABEL           0x0004
+#define WPS_CONFMET_DISPLAY         0x0008
+#define WPS_CONFMET_EXT_NFC_TOK     0x0010
+#define WPS_CONFMET_INT_NFC_TOK     0x0020
+#define WPS_CONFMET_NFC_INTF        0x0040
+#define WPS_CONFMET_PBC             0x0080
+#define WPS_CONFMET_KEYPAD          0x0100
+/* WSC 2.0 */
+#define WPS_CONFMET_VIRT_PBC        0x0280
+#define WPS_CONFMET_PHY_PBC         0x0480
+#define WPS_CONFMET_VIRT_DISPLAY    0x2008
+#define WPS_CONFMET_PHY_DISPLAY     0x4008
+
+/* WPS error messages */
+#define WPS_ERROR_NO_ERROR                0
+#define WPS_ERROR_OOB_INT_READ_ERR        1
+#define WPS_ERROR_DECRYPT_CRC_FAIL        2
+#define WPS_ERROR_CHAN24_NOT_SUPP         3
+#define WPS_ERROR_CHAN50_NOT_SUPP         4
+#define WPS_ERROR_SIGNAL_WEAK             5	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NW_AUTH_FAIL            6	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NW_ASSOC_FAIL           7	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NO_DHCP_RESP            8	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_FAILED_DHCP_CONF        9	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_IP_ADDR_CONFLICT        10	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_FAIL_CONN_REGISTRAR     11
+#define WPS_ERROR_MULTI_PBC_DETECTED      12
+#define WPS_ERROR_ROGUE_SUSPECTED         13
+#define WPS_ERROR_DEVICE_BUSY             14
+#define WPS_ERROR_SETUP_LOCKED            15
+#define WPS_ERROR_MSG_TIMEOUT             16	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_REG_SESSION_TIMEOUT     17	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_DEV_PWD_AUTH_FAIL       18
+
+/* Connection types */
+#define WPS_CONNTYPE_ESS    0x01
+#define WPS_CONNTYPE_IBSS   0x02
+
+/* Device password ID */
+#define WPS_DEVICEPWDID_DEFAULT          0x0000
+#define WPS_DEVICEPWDID_USER_SPEC        0x0001
+#define WPS_DEVICEPWDID_MACHINE_SPEC     0x0002
+#define WPS_DEVICEPWDID_REKEY            0x0003
+#define WPS_DEVICEPWDID_PUSH_BTN         0x0004
+#define WPS_DEVICEPWDID_REG_SPEC         0x0005
+
+/* Encryption type */
+#define WPS_ENCRTYPE_NONE    0x0001
+#define WPS_ENCRTYPE_WEP     0x0002	/* Deprecated in WSC 2.0 */
+#define WPS_ENCRTYPE_TKIP    0x0004	/* Deprecated in version 2.0. TKIP can only
+					  * be advertised on the AP when Mixed Mode
+					  * is enabled (Encryption Type is 0x000c).
+					  */
+#define WPS_ENCRTYPE_AES     0x0008
+
+
+/* WPS Message Types */
+#define WPS_ID_BEACON            0x01
+#define WPS_ID_PROBE_REQ         0x02
+#define WPS_ID_PROBE_RESP        0x03
+#define WPS_ID_MESSAGE_M1        0x04
+#define WPS_ID_MESSAGE_M2        0x05
+#define WPS_ID_MESSAGE_M2D       0x06
+#define WPS_ID_MESSAGE_M3        0x07
+#define WPS_ID_MESSAGE_M4        0x08
+#define WPS_ID_MESSAGE_M5        0x09
+#define WPS_ID_MESSAGE_M6        0x0A
+#define WPS_ID_MESSAGE_M7        0x0B
+#define WPS_ID_MESSAGE_M8        0x0C
+#define WPS_ID_MESSAGE_ACK       0x0D
+#define WPS_ID_MESSAGE_NACK      0x0E
+#define WPS_ID_MESSAGE_DONE      0x0F
+
+/* WSP private ID for local use */
+#define WPS_PRIVATE_ID_IDENTITY		(WPS_ID_MESSAGE_DONE + 1)
+#define WPS_PRIVATE_ID_WPS_START	(WPS_ID_MESSAGE_DONE + 2)
+#define WPS_PRIVATE_ID_FAILURE		(WPS_ID_MESSAGE_DONE + 3)
+#define WPS_PRIVATE_ID_FRAG		(WPS_ID_MESSAGE_DONE + 4)
+#define WPS_PRIVATE_ID_FRAG_ACK		(WPS_ID_MESSAGE_DONE + 5)
+#define WPS_PRIVATE_ID_EAPOL_START	(WPS_ID_MESSAGE_DONE + 6)
+
+
+/* Device Type categories for primary and secondary device types */
+#define WPS_DEVICE_TYPE_CAT_COMPUTER        1
+#define WPS_DEVICE_TYPE_CAT_INPUT_DEVICE    2
+#define WPS_DEVICE_TYPE_CAT_PRINTER         3
+#define WPS_DEVICE_TYPE_CAT_CAMERA          4
+#define WPS_DEVICE_TYPE_CAT_STORAGE         5
+#define WPS_DEVICE_TYPE_CAT_NW_INFRA        6
+#define WPS_DEVICE_TYPE_CAT_DISPLAYS        7
+#define WPS_DEVICE_TYPE_CAT_MM_DEVICES      8
+#define WPS_DEVICE_TYPE_CAT_GAME_DEVICES    9
+#define WPS_DEVICE_TYPE_CAT_TELEPHONE       10
+#define WPS_DEVICE_TYPE_CAT_AUDIO_DEVICES   11	/* WSC 2.0 */
+
+/* Device Type sub categories for primary and secondary device types */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_PC         1
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_SERVER     2
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MEDIA_CTR  3
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_UM_PC      4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NOTEBOOK   5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_DESKTOP    6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MID        7	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NETBOOK    8	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_Keyboard    1	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_MOUSE       2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_JOYSTICK    3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_TRACKBALL   4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_GAM_CTRL    5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_REMOTE      6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_TOUCHSCREEN 7	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_BIO_READER  8	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_BAR_READER  9	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_PRINTER    1
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_SCANNER    2
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_FAX        3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_COPIER     4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_ALLINONE   5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_DGTL_STILL  1
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_VIDEO_CAM   2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_WEB_CAM     3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_SECU_CAM    4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_STOR_NAS        1
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_AP           1
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_ROUTER       2
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_SWITCH       3
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_GATEWAY      4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_BRIDGE       5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_TV         1
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PIC_FRAME  2
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PROJECTOR  3
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_MONITOR    4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_DAR          1
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVR          2
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_MCX          3
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_STB          4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_MS_ME        5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVP          6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX        1
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX_360    2
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PS          3
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_GC          4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PGD         5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_WM        1
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PSM       2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PDM       3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SSM       4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SDM       5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_TUNER     1	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_SPEAKERS  2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_PMP       3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HEADSET   4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HPHONE    5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_MPHONE    6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HTS       7	/* WSC 2.0 */
+
+
+/* Device request/response type */
+#define WPS_MSGTYPE_ENROLLEE_INFO_ONLY    0x00
+#define WPS_MSGTYPE_ENROLLEE_OPEN_8021X   0x01
+#define WPS_MSGTYPE_REGISTRAR             0x02
+#define WPS_MSGTYPE_AP_WLAN_MGR           0x03
+
+/* RF Band */
+#define WPS_RFBAND_24GHZ    0x01
+#define WPS_RFBAND_50GHZ    0x02
+
+/* Simple Config state */
+#define WPS_SCSTATE_UNCONFIGURED    0x01
+#define WPS_SCSTATE_CONFIGURED      0x02
+#define WPS_SCSTATE_OFF 11
+
+/* WPS Vendor extension key */
+#define WPS_OUI_HEADER_LEN 2
+#define WPS_OUI_HEADER_SIZE 4
+#define WPS_OUI_FIXED_HEADER_OFF 16
+#define WPS_WFA_SUBID_V2_OFF 3
+#define WPS_WFA_V2_OFF 5
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WPS_ */
diff --git a/src/dhd/exe/GNUmakefile b/src/dhd/exe/GNUmakefile
new file mode 100644
index 0000000..409c225
--- /dev/null
+++ b/src/dhd/exe/GNUmakefile
@@ -0,0 +1,128 @@
+#
+# GNUmakefile for dhd/exe
+#
+# Copyright (c) 2000, Broadcom Corp.
+# $Id: GNUmakefile,v 1.27 2010-09-13 14:20:34 $
+
+WLAN_ComponentsInUse := bcmwifi
+include ../../makefiles/WLAN_Common.mk
+SRCBASE := $(WLAN_SrcBaseR)
+
+UNAME = $(shell uname)
+
+#-----------------------------------------------------------------
+# Windows build
+# 1) windows, don't include Makerules due to all: conflict
+
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+
+include ../../GNUmakefile.inc
+
+else # UNAME
+
+# 2) not windows, need to include first to pick up TARGETENV dependent vars
+include $(SRCBASE)/Makerules
+
+CFLAGS += $(EXTRA_PLATFORM_CFLAGS)
+
+# use nl80211 for driver access (ioctl replacement)
+ifdef NL80211
+CFLAGS += -DNL80211
+endif
+
+#ifdef BCMWPA2
+CFLAGS += -DBCMWPA2
+#endif
+# Always include pktgen commands in the application
+CFLAGS += -DSDTEST
+#ifndef OEM_ANDROID
+CFLAGS += -DBCMSPI
+#endif
+
+#ifdef WLCNT
+CFLAGS += -DWLCNT
+#endif
+
+
+CFLAGS += -DWLBTAMP
+CFLAGS += -DWLPFN -DLINUX -g -I$(SRCBASE)/wl/exe
+
+vpath %.c $(SRCBASE)/shared $(SRCBASE)/wl/exe $(WLAN_StdSrcDirsR) $(WLAN_ComponentSrcDirsR)
+
+#-----------------------------------------------------------------
+# Linux build
+#
+# This should be one of values recognized in src/Makerules
+
+# Change to the new dhd driver trunk build structure as discussed 
+# by the build team 
+ifeq ($(BUILD_TAG),TRUNK)
+
+# $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files
+DHD_OBJS := $(TARGETARCH)/dhdu.o $(TARGETARCH)/dhdu_linux.o $(TARGETARCH)/bcmutils.o $(TARGETARCH)/bcmwifi_channels.o $(TARGETARCH)/wlu_client_shared.o $(TARGETARCH)/wlu_pipe_linux.o $(TARGETARCH)/wlu_pipe.o $(TARGETARCH)/miniopt.o $(TARGETARCH)/bcm_app_utils.o $(TARGETARCH)/ucode_download.o $(TARGETARCH)/wlu_common.o
+DHD_EXE  := $(TARGETARCH)/dhd
+
+include netlink.inc
+
+all: $(DHD_EXE)
+
+clean:
+	 rm -fr $(DHD_EXE) $(DHD_OBJS) $(TARGETARCH)
+
+$(DHD_EXE): $(DHD_OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+$(TARGETARCH)/%.o: %.c
+	@mkdir -p $(TARGETARCH)
+	$(CC) -c $(CFLAGS) -DRWL_SOCKET -DRWL_WIFI -DRWL_DONGLE -o $@ $^
+
+else # BUILD_TAG
+
+# Preserve the old build structure for other components that still haven't not
+# changed to the new build structure, once everyone moved to the new structure
+# , we can remove the whole else BUILD_TAG code
+
+ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le android android_ndk_r6b"),)
+# $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files
+DHD_OBJS := dhdu.o dhdu_linux.o bcmutils.o bcmwifi_channels.o wlu_client_shared.o wlu_pipe_linux.o wlu_pipe.o miniopt.o bcm_app_utils.o ucode_download.o wlu_common.o
+DHD_EXE  := dhd
+DHD_OBJS := $(DHD_OBJS:%.o=%.o)
+
+include netlink.inc
+
+ifeq ($(findstring $(TARGETARCH), "x86 x86_mmx"),)
+  DHD_EXE  := $(DHD_EXE)$(TARGETARCH)
+  DHD_OBJS := $(DHD_OBJS:%.o=$(TARGETARCH)/%.o)
+endif
+
+all: $(DHD_EXE)
+
+clean:
+	 rm -fr $(DHD_EXE) $(DHD_OBJS) $(TARGETARCH)
+
+$(DHD_EXE): $(DHD_OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+# net_priv target is for building the dhd with NET_ADMIN privilege (i.e. to avoid running as root)
+# note: The 'setcap' command is availble from the libcap2-bin package
+# note: linux kernel < 2.6.33 doesn't support Security File Capabilities by default
+net_priv: $(DHD_EXE)
+	sudo setcap CAP_NET_ADMIN=eip $^
+
+%.o: %.c
+	$(CC) -c $(CFLAGS) -DRWL_SOCKET -DRWL_WIFI -DRWL_DONGLE -o $@ $^
+
+
+ifeq ($(findstring $(TARGETARCH), "x86 x86_mmx"),)
+$(TARGETARCH)/%.o: %.c
+	@mkdir -p $(TARGETARCH)
+	$(CC) -c $(CFLAGS) -DRWL_SOCKET -DRWL_WIFI -DRWL_DONGLE -o $@ $^
+endif
+
+endif # TARGETENV linux
+
+endif # BUILD_TAG
+
+.PHONY: all clean net_priv
+
+endif # UNAME
diff --git a/src/dhd/exe/dhdu.c b/src/dhd/exe/dhdu.c
new file mode 100644
index 0000000..9343b38
--- /dev/null
+++ b/src/dhd/exe/dhdu.c
@@ -0,0 +1,3480 @@
+/*
+ * Common code for DHD command-line utility
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: dhdu.c 479444 2014-05-21 04:19:36Z $
+ */
+
+/* For backwards compatibility, the absence of the define 'BWL_NO_FILESYSTEM_SUPPORT'
+ * implies that a filesystem is supported.
+ */
+#if !defined(BWL_NO_FILESYSTEM_SUPPORT)
+#define BWL_FILESYSTEM_SUPPORT
+#endif
+
+#ifndef PROP_TXSTATUS
+#define PROP_TXSTATUS
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <typedefs.h>
+#include <epivers.h>
+#include <proto/ethernet.h>
+#include <dhdioctl.h>
+#include <sdiovar.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "dhdu.h"
+#include "miniopt.h"
+#include <usbrdl.h>
+#include <proto/bcmip.h>
+#include <hndrte_debug.h>
+#include <hndrte_armtrap.h>
+#include <hndrte_cons.h>
+#define IPV4_ADDR_LEN 4
+#ifdef WLBTAMP
+#include <proto/bt_amp_hci.h>
+#endif
+
+#include <errno.h>
+
+#include <trxhdr.h>
+#include "ucode_download.h"
+
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+
+static cmd_func_t dhd_var_void;
+static cmd_func_t dhd_varint, dhd_varstr;
+static cmd_func_t dhd_var_getandprintstr, dhd_var_getint, dhd_var_get;
+static cmd_func_t dhd_var_setint;
+
+static cmd_func_t dhd_version, dhd_list, dhd_msglevel;
+
+#ifdef SDTEST
+static cmd_func_t dhd_pktgen;
+#endif
+static cmd_func_t dhd_sprom;
+static cmd_func_t dhd_sdreg;
+static cmd_func_t dhd_reg2args;
+static cmd_func_t dhd_pcie_dmaxfer;
+static cmd_func_t dhd_sd_msglevel, dhd_sd_blocksize, dhd_sd_mode, dhd_sd_reg;
+static cmd_func_t dhd_dma_mode;
+static cmd_func_t dhd_membytes, dhd_download, dhd_dldn,
+	dhd_upload, dhd_coredump, dhd_consoledump, dhd_vars, dhd_idleclock, dhd_idletime;
+static cmd_func_t dhd_logstamp;
+#ifdef BCMSPI
+static cmd_func_t dhd_spierrstats;
+#endif /* BCMSPI */
+
+static cmd_func_t dhd_hostreorder_flows;
+
+#ifdef QMONITOR
+static int dhd_qtime_thres(void *dhd, cmd_t *cmd, char **argv);
+static int dhd_qtime_percent(void *dhd, cmd_t *cmd, char **argv);
+#endif
+
+#ifdef PROP_TXSTATUS
+static cmd_func_t dhd_proptxstatusenable;
+static cmd_func_t dhd_proptxstatusmode;
+static cmd_func_t dhd_proptxopt;
+#endif
+static int dhd_var_getbuf(void *dhd, char *iovar, void *param, int param_len, void **bufptr);
+static int dhd_var_setbuf(void *dhd, char *iovar, void *param, int param_len);
+
+static uint dhd_iovar_mkbuf(char *name, char *data, uint datalen,
+                            char *buf, uint buflen, int *perr);
+static int dhd_iovar_getint(void *dhd, char *name, int *var);
+static int dhd_iovar_setint(void *dhd, char *name, int var);
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+static int file_size(char *fname);
+static int read_vars(char *fname, char *buf, int buf_maxlen);
+#endif
+
+#ifdef WLBTAMP
+static cmd_func_t wl_HCI_cmd;
+static cmd_func_t wl_HCI_ACL_data;
+#endif
+
+/* dword align allocation */
+static union {
+	char bufdata[DHD_IOCTL_MAXLEN];
+	uint32 alignme;
+} bufstruct_dhd;
+static char *buf = (char*) &bufstruct_dhd.bufdata;
+
+/* integer output format, default to signed integer */
+static uint8 int_fmt;
+
+#define DEBUG_INFO_PTRS_END 0xffffffff
+const uint32 debug_info_ptrs[] = {0xf8, 0x878, DEBUG_INFO_PTRS_END};
+
+typedef struct {
+	uint value;
+	char *string;
+} dbg_msg_t;
+
+static int dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg);
+
+/* Actual command table */
+cmd_t dhd_cmds[] = {
+	{ "cmds", dhd_list, -1, -1,
+	"generate a short list of available commands"},
+	{ "version", dhd_version, DHD_GET_VAR, -1,
+	"get version information" },
+	{ "msglevel", dhd_msglevel, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set message bits" },
+	{ "bcmerrorstr", dhd_var_getandprintstr, DHD_GET_VAR, -1,
+	"errorstring"},
+	{ "wdtick", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"watchdog tick time (ms units)"},
+	{ "msi_sim", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"simulate MSI interrupts for the PCIE full dongle operation"},
+	{ "pcie_lpbk", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"send a loopback message on the bus"},
+	{ "pcie_dmaxfer", dhd_pcie_dmaxfer, -1, DHD_SET_VAR,
+	"send a dma transfer message on the bus"},
+	{ "pcie_tx_lpbk", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"enable/disable loopback of tx packets on the bus"},
+	{ "pcie_suspend", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"suspend/resume pcie bus"},
+	{ "pciereg", dhd_reg2args, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set a pciereg from the device"},
+	{ "pciecorereg", dhd_reg2args, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set a pciecorereg from the device"},
+	{ "pciecfgreg", dhd_reg2args, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set a pciecfgreg from the device"},
+	{ "sleep_allowed", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"boolean to indicate whether the device is allowed to go to deep sleep"},
+	{ "cc_nvmshadow", dhd_varstr, DHD_GET_VAR, -1,
+	"dump OTP/SPROM shadow in chip common enum space"},
+	{ "intr", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"use interrupts on the bus"},
+	{ "pollrate", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"number of ticks between bus polls (0 means no polling)"},
+	{ "idletime", dhd_idletime, DHD_GET_VAR, DHD_SET_VAR,
+	"number of ticks for activity timeout (-1: immediate, 0: never)"},
+	{ "idleclock", dhd_idleclock, DHD_GET_VAR, DHD_SET_VAR,
+	"idleclock active | stopped | <N>\n"
+	"\tactive (0)   - do not request any change to the SD clock\n"
+	"\tstopped (-1) - request SD clock be stopped on activity timeout\n"
+	"\t<N> (other)  - an sd_divisor value to request on activity timeout\n"},
+	{ "sd1idle", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"change mode to SD1 when turning off clock at idle"},
+	{ "forceeven", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"force SD tx/rx buffers to be even"},
+	{ "readahead", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"enable readahead feature (look for next frame len in headers)"},
+	{ "sdrxchain", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"enable packet chains to SDIO stack for glom receive"},
+	{ "alignctl", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"align control frames"},
+	{ "sdalign", dhd_varint, DHD_GET_VAR, -1,
+	"display the (compiled in) alignment target for sd requests"},
+	{ "txbound", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set maximum number of tx frames per scheduling"},
+	{ "rxbound", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set maximum number of rx frames per scheduling"},
+	{ "txminmax", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set maximum number of tx frames per scheduling while rx frames outstanding"},
+	{ "dconpoll", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set dongle console polling interval (ms)"},
+	{ "dump", dhd_varstr, DHD_GET_VAR, -1,
+	"dump information"},
+	{ "cons", dhd_varstr, -1, DHD_SET_VAR,
+	"send string to device console (sd only)"},
+	{ "clearcounts", dhd_var_void, -1, DHD_SET_VAR,
+	"reset the bus stats shown in the dhd dump"},
+	{ "logdump", dhd_varstr, DHD_GET_VAR, -1,
+	"dump the timestamp logging buffer"},
+	{ "logcal", dhd_varint, -1, DHD_SET_VAR,
+	"logcal <n>  -- log around an osl_delay of <n> usecs"},
+	{ "logstamp", dhd_logstamp, -1, DHD_SET_VAR,
+	"logstamp [<n1>] [<n2>]  -- add a message to the log"},
+	{ "ramstart", dhd_varint, DHD_GET_VAR, -1,
+	"display start address of onchip SOCRAM"},
+	{ "ramsize", dhd_varint, DHD_GET_VAR, -1,
+	"display size of onchip SOCRAM"},
+	{ "membytes", dhd_membytes, DHD_GET_VAR, DHD_SET_VAR,
+	"membytes [-h | -r | -i] <address> <length> [<data>]\n"
+	"\tread or write data in the dongle ram\n"
+	"\t-h   <data> is a sequence of hex digits rather than a char string\n"
+	"\t-r   output binary to stdout rather hex\n"},
+	{ "download", dhd_download, -1, DHD_SET_VAR,
+	"download [-a <address>] [--noreset] [--norun] [--verify] <binfile> [<varsfile>]\n"
+	"\tdownload file to specified dongle ram address and start CPU\n"
+	"\toptional vars file will replace vars parsed from the CIS\n"
+	"\t--noreset    do not reset SOCRAM core before download\n"
+	"\t--norun      do not start dongle CPU after download\n"
+	"\t--verify     do readback verify \n"
+	"\tdefault <address> is 0\n"},
+	{ "dldn", dhd_dldn, -1, DHD_SET_VAR,
+	"download <binfile>\n"
+	"\tdownload file to specified dongle ram address 0\n"},
+	{ "vars", dhd_vars, DHD_GET_VAR, DHD_SET_VAR,
+	"vars [<file>]\n"
+	"\toverride SPROM vars with <file> (before download)\n"},
+	{ "coredump", dhd_coredump, -1, -1,
+	"coredump <file>\n"
+	"\tdump dongle RAM content into a file in dumpfile format\n"
+	"\tfor use with ELF core generator"},
+	{ "consoledump", dhd_consoledump, -1, -1,
+	"consoledump\n"
+	"\tdump dongle debug console buffer"},
+	{ "upload", dhd_upload, -1, -1,
+	"upload [-a <address> ] <file> [<size>]\n"
+	"\tupload dongle RAM content into a file\n"
+	"\tdefault <address> is 0, default <size> is RAM size"},
+	{ "srdump", dhd_sprom, DHD_GET_VAR, -1,
+	"display SPROM content" },
+	{ "srwrite", dhd_sprom, -1, DHD_SET_VAR,
+	"write data or file content to SPROM\n"
+	"\tsrwrite <word-offset> <word-value> ...\n"
+	"\tsrwrite [-c] <srom-file-path>\n"
+	"\t  -c means write regardless of crc"},
+	{ "sleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"enter/exit simulated host sleep (bus powerdown w/OOB wakeup)"},
+	{ "kso", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"keep sdio on"},
+	{ "devcap", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"brcm device capabilities"},
+	{ "devsleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"Sleep CMD14"},
+#ifdef SDTEST
+	{ "extloop", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"external loopback: convert all tx data to echo test frames"},
+	{ "pktgen", dhd_pktgen, DHD_GET_VAR, DHD_SET_VAR,
+	"configure/report pktgen status (SDIO)\n"
+	"\t-f N     frequency: send/recv a burst every N ticks\n"
+	"\t-c N     count: send/recv N packets each burst\n"
+	"\t-t N     total: stop after a total of N packets\n"
+	"\t-p N     print: display counts on console every N bursts\n"
+	"\t-m N     min: set minimum length of packet data\n"
+	"\t-M N     Max: set maximum length of packet data\n"
+	"\t-l N     len: set fixed length of packet data\n"
+	"\t-s N     stop after N tx failures\n"
+	"\t-d dir   test direction/type:\n"
+	"\t            send -- send packets discarded by dongle\n"
+	"\t            echo -- send packets to be echoed by dongle\n"
+	"\t            burst -- request bursts (of size <-c>) from dongle\n"
+	"\t              one every <-f> ticks, until <-t> total requests\n"
+	"\t            recv -- request dongle enter continuous send mode,\n"
+	"\t              read up to <-c> pkts every <-f> ticks until <-t>\n"
+	"\t              total reads\n"},
+#endif /* SDTEST */
+	{ "dngl_isolation", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set dongle isolation, so the dev could be disabled with out effecting the dongle state"},
+	{ "ltrsleep_on_unload", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set sending ltr sleep message on unload config"},
+	{ "sdreg", dhd_sdreg, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set sdpcmdev core register (f1) across SDIO (CMD53)"},
+	{ "sbreg", dhd_sdreg, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set any backplane core register (f1) across SDIO (CMD53)"},
+	{ "sd_cis", dhd_var_getandprintstr, DHD_GET_VAR, -1,
+	"dump sdio CIS"},
+	{ "sd_devreg", dhd_sd_reg, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set device register across SDIO bus (CMD52)"},
+	{ "sd_hostreg", dhd_sd_reg, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set local controller register"},
+	{ "sd_blocksize", dhd_sd_blocksize, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set block size for a function"},
+	{ "sd_blockmode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set blockmode"},
+	{ "sd_ints", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set client ints"},
+	{ "sd_dma", dhd_dma_mode, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set dma usage: [PIO | SDMA | ADMA1 | ADMA2]"},
+	{ "sd_yieldcpu", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"allow blocking (yield of CPU) on data xfer"},
+	{ "sd_minyield", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"minimum xfer size to allow CPU yield"},
+	{ "sd_forcerb", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"force readback when changing local interrupt settings"},
+	{ "sd_numints", dhd_varint, DHD_GET_VAR, -1,
+	"number of device interrupts"},
+	{ "sd_numlocalints", dhd_varint, DHD_GET_VAR, -1,
+	"number of non-device interrupts"},
+	{ "sd_divisor", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"set the divisor for SDIO clock generation"},
+	{ "sd_power", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"set the SD Card slot power"},
+	{ "sd_power_save", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"set the SDIO3.0 power save value"},
+	{ "sd_clock", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"turn on/off the SD Clock"},
+	{ "sd_crc", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"turn on/off CRC checking in SPI mode"},
+	{ "sd_mode", dhd_sd_mode, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set SDIO bus mode (spi, sd1, sd4)"},
+	{ "sd_highspeed", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"set the high-speed clocking mode"},
+	{ "sd_msglevel", dhd_sd_msglevel, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set debug message level"},
+	{ "sd_hciregs", dhd_varstr, DHD_GET_VAR, -1,
+	"display host-controller interrupt registers"},
+	{ "sdiod_drive", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"SDIO Device drive strength in milliamps. (0=tri-state, 1-12mA)"},
+#ifdef BCMSPI
+	{ "spi_errstats", dhd_spierrstats, DHD_GET_VAR, DHD_SET_VAR,
+	"SPI device status error statistics."},
+	{ "spi_respdelay", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set response delay flag."},
+#endif /* BCMSPI */
+	{ "devreset", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"Move device into or out of reset state (1/reset, or 0/operational)"},
+	{ "ioctl_timeout", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"IOCTL response timeout (milliseconds)."},
+#ifdef WLBTAMP
+	{ "HCI_cmd", wl_HCI_cmd, -1, DHD_SET_VAR,
+	"carries HCI commands to the driver\n"
+	"\tusage: dhd HCI_cmd <command> <args>\n" },
+	{ "HCI_ACL_data", wl_HCI_ACL_data, -1, DHD_SET_VAR,
+	"carries HCI ACL data packet to the driver\n"
+	"\tusage: dhd HCI_ACL_data <logical link handle> <data>\n" },
+#endif
+#ifdef QMONITOR
+	{ "qtime_percent", dhd_qtime_percent, DHD_GET_VAR, -1,
+	"qtime_percent gives the percentage of time where DHD TX queue\n"
+	"has a number of packets queued above a threshold set by\n"
+	"the iovar qtimer_thres"},
+	{ "qtime_thres", dhd_qtime_thres, DHD_GET_VAR, DHD_SET_VAR,
+	"qtime_thres sets the thresold of number of packets used\n"
+	"by the iovar qtime_percent"},
+#endif
+#ifdef PROP_TXSTATUS
+	{ "proptx", dhd_proptxstatusenable, DHD_GET_VAR, DHD_SET_VAR,
+	"enable/disable the proptxtstatus feature\n"
+	"0 - disabled\n"
+	"1 - enabled\n"},
+	{ "ptxmode", dhd_proptxstatusmode, DHD_GET_VAR, DHD_SET_VAR,
+	"set the proptxtstatus operation mode:\n"
+	"0 - Unsupported\n"
+	"1 - Use implied credit from a packet status\n"
+	"2 - Use explicit credit\n" },
+	{ "proptx_opt", dhd_proptxopt, DHD_GET_VAR, DHD_SET_VAR,
+	"enable/disable proptxtstatus optimizations to increase throughput:\n"
+	"0 - Unsupported\n"
+	"1 - Enable proptxstatus optimizations to increase throughput\n" },
+	{ "pmodule_ignore", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"use/bypass the proptxtstatus module\n"
+	"0 - apply\n"
+	"1 - bypass\n"},
+	{ "pcredit_ignore", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"apply/ignore the proptxtstatus credit control\n"
+	"0 - apply\n"
+	"1 - ignore\n"},
+	{ "ptxstatus_ignore", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"process/ignore the proptxtstatus txstaus\n"
+	"0 - process\n"
+	"1 - ignore\n"},
+	{ "rxpkt_chk", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"check/ignore rx packet for multiple AC detection\n"
+	"0 - ignore\n"
+	"1 - check\n"},
+#endif /* PROP_TXSTATUS */
+	{ "sd_uhsimode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"g/set UHSI Mode"},
+	{ "host_reorder_flows", dhd_hostreorder_flows, DHD_GET_VAR, -1,
+	"get host reorder flows "},
+	{ "txglomsize", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"max glom size for sdio tx\n"},
+	{ "txglommode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"glom mode for sdio tx 0- copy, 1- multidescriptor\n"},
+	{ "fw_hang_report", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"enable/disable report firmware hangs for firmware reload\n"
+	"0 - disabled (for testing)\n"
+	"1 - enabled (default)\n"},
+	{ "tuning_mode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set tuning mode \n"
+	"1 - Disabled periodic tuning \n"
+	"0 - Enable periodic tuning \n"},
+	{ "tcpack_suppress", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"Turn tcpack_suppress on/off\n"
+	"0 - off\n"
+	"1 - on\n"},
+	{ "txinrx_thres", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+	"get/set threshold for num of in-queued pkts to tx in rx process\n"
+	"0 - always send out in rx process\n"
+	"num - amount of in-queued pkts\n"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+cmd_t dhd_varcmd = {"var", dhd_varint, -1, -1, "unrecognized name, type -h for help"};
+char *dhdu_av0;
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+static int
+file_size(char *fname)
+{
+	FILE *fp;
+	long size = -1;
+
+	/* Can't use stat() because of Win CE */
+
+	if ((fp = fopen(fname, "rb")) == NULL ||
+	    fseek(fp, 0, SEEK_END) < 0 ||
+	    (size = ftell(fp)) < 0)
+		fprintf(stderr, "Could not determine size of %s: %s\n",
+		        fname, strerror(errno));
+
+	if (fp != NULL)
+		fclose(fp);
+
+	return (int)size;
+}
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+
+
+/* parse/validate the command line arguments */
+/*
+* pargv is updated upon return if the first argument is an option.
+ * It remains intact otherwise.
+ */
+int
+dhd_option(char ***pargv, char **pifname, int *phelp)
+{
+	char *ifname = NULL;
+	int help = FALSE;
+	int status = CMD_OPT;
+	char **argv = *pargv;
+
+	int_fmt = INT_FMT_DEC;
+
+	while (*argv) {
+		/* select different adapter */
+		if (!strcmp(*argv, "-a") || !strcmp(*argv, "-i")) {
+			char *opt = *argv++;
+			ifname = *argv;
+			if (!ifname) {
+				fprintf(stderr,
+					"error: expected interface name after option %s\n", opt);
+				status = CMD_ERR;
+				break;
+			}
+		}
+
+		/* integer output format */
+		else if (!strcmp(*argv, "-d"))
+			int_fmt = INT_FMT_DEC;
+		else if (!strcmp(*argv, "-u"))
+			int_fmt = INT_FMT_UINT;
+		else if (!strcmp(*argv, "-x"))
+			int_fmt = INT_FMT_HEX;
+
+		/* command usage */
+		else if (!strcmp(*argv, "-h"))
+			help = TRUE;
+
+		/* done with generic options */
+		else {
+			status = CMD_DHD;
+			break;
+		}
+
+		/* consume the argument */
+		argv ++;
+		break;
+	}
+
+	*phelp = help;
+	*pifname = ifname;
+	*pargv = argv;
+
+	return status;
+}
+
+void
+dhd_cmd_usage(cmd_t *cmd)
+{
+	if (strlen(cmd->name) >= 8)
+		fprintf(stderr, "%s\n\t%s\n\n", cmd->name, cmd->help);
+	else
+		fprintf(stderr, "%s\t%s\n\n", cmd->name, cmd->help);
+}
+
+/* Dump out short list of commands */
+static int
+dhd_list(void *dhd, cmd_t *garb, char **argv)
+{
+	cmd_t *cmd;
+	int nrows, i, len;
+	char *buf;
+	int letter, col, row, pad;
+
+	UNUSED_PARAMETER(dhd);
+	UNUSED_PARAMETER(garb);
+	UNUSED_PARAMETER(argv);
+
+	for (cmd = dhd_cmds, nrows = 0; cmd->name; cmd++)
+		    nrows++;
+
+	nrows /= 4;
+	nrows++;
+
+	len = nrows * 80 + 2;
+	buf = malloc(len);
+	if (buf == NULL) {
+		fprintf(stderr, "Failed to allocate buffer of %d bytes\n", len);
+		return BCME_NOMEM;
+	}
+	for (i = 0; i < len; i++)
+		*(buf+i) = 0;
+
+	row = col = 0;
+	for (letter = 'a'; letter < 'z'; letter++) {
+		for (cmd = dhd_cmds; cmd->name; cmd++) {
+			if (cmd->name[0] == letter || cmd->name[0] == letter - 0x20) {
+				strcat(buf+row*80, cmd->name);
+				pad = 18 * (col + 1) - strlen(buf+row*80);
+				if (pad < 1)
+					pad = 1;
+				for (; pad; pad--)
+					strcat(buf+row*80, " ");
+				row++;
+				if (row == nrows) {
+					col++; row = 0;
+				}
+			}
+		}
+	}
+	for (row = 0; row < nrows; row++)
+		printf("%s\n", buf+row*80);
+
+	printf("\n");
+	free(buf);
+	return (0);
+}
+
+void
+dhd_cmds_usage(cmd_t *port_cmds)
+{
+	cmd_t *port_cmd;
+	cmd_t *cmd;
+
+	/* print usage of port commands */
+	for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
+		/* Check for wc_cmd */
+		dhd_cmd_usage(port_cmd);
+
+	/* print usage of common commands without port counterparts */
+	for (cmd = dhd_cmds; cmd->name; cmd++) {
+		/* search if port counterpart exists */
+		for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
+			if (!strcmp(port_cmd->name, cmd->name))
+				break;
+		if (!port_cmd || !port_cmd->name)
+			dhd_cmd_usage(cmd);
+	}
+}
+
+void
+dhd_usage(cmd_t *port_cmds)
+{
+	fprintf(stderr,
+	        "Usage: %s [-a|i <adapter>] [-h] [-d|u|x] <command> [arguments]\n",
+		dhdu_av0);
+
+	fprintf(stderr, "\n");
+	fprintf(stderr, "  -h		this message\n");
+	fprintf(stderr, "  -a, -i	adapter name or number\n");
+	fprintf(stderr, "  -d		display values as signed integer\n");
+	fprintf(stderr, "  -u		display values as unsigned integer\n");
+	fprintf(stderr, "  -x		display values as hexdecimal\n");
+	fprintf(stderr, "\n");
+
+	dhd_cmds_usage(port_cmds);
+}
+
+int
+dhd_check(void *dhd)
+{
+	int ret;
+	int val;
+
+	if ((ret = dhd_get(dhd, DHD_GET_MAGIC, &val, sizeof(int))) < 0)
+		return ret;
+	if (val != DHD_IOCTL_MAGIC)
+		return -1;
+	if ((ret = dhd_get(dhd, DHD_GET_VERSION, &val, sizeof(int))) < 0)
+		return ret;
+	if (val > DHD_IOCTL_VERSION) {
+		fprintf(stderr, "Version mismatch, please upgrade\n");
+		return -1;
+	}
+	return 0;
+}
+
+void
+dhd_printint(int val)
+{
+	switch (int_fmt) {
+	case INT_FMT_UINT:
+		printf("%u\n", val);
+		break;
+	case INT_FMT_HEX:
+		printf("0x%x\n", val);
+		break;
+	case INT_FMT_DEC:
+	default:
+		printf("%d\n", val);
+		break;
+	}
+}
+
+/* pretty hex print a contiguous buffer (tweaked from wlu) */
+void
+dhd_hexdump(uchar *buf, uint nbytes, uint saddr)
+{
+	char line[256];
+	char* p;
+	uint i;
+
+	if (nbytes == 0) {
+		printf("\n");
+		return;
+	}
+
+	p = line;
+	for (i = 0; i < nbytes; i++) {
+		if (i % 16 == 0) {
+			p += sprintf(p, "%08x: ", saddr + i);	/* line prefix */
+		}
+		p += sprintf(p, "%02x ", buf[i]);
+		if (i % 16 == 15) {
+			uint j;
+			p += sprintf(p, "  ");
+			for (j = i-15; j <= i; j++)
+				p += sprintf(p, "%c",
+				             ((buf[j] >= 0x20 && buf[j] <= 0x7f) ? buf[j] : '.'));
+			printf("%s\n", line);		/* flush line */
+			p = line;
+		}
+	}
+
+	/* flush last partial line */
+	if (p != line)
+		printf("%s\n", line);
+}
+
+
+#ifdef SDTEST
+static int
+dhd_pktgen(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	void *ptr = NULL;
+	dhd_pktgen_t pktgen;
+	char *str;
+
+	UNUSED_PARAMETER(dhd);
+	UNUSED_PARAMETER(cmd);
+
+	/* Get current settings */
+	if ((ret = dhd_var_getbuf(dhd, "pktgen", NULL, 0, &ptr)) != 0)
+		return ret;
+	memcpy(&pktgen, ptr, sizeof(pktgen));
+
+	if (pktgen.version != DHD_PKTGEN_VERSION) {
+		fprintf(stderr, "pktgen version mismatch (module %d app %d)\n",
+		        pktgen.version, DHD_PKTGEN_VERSION);
+		return BCME_ERROR;
+	}
+
+	/* Presence of args implies a set, else a get */
+	if (*++argv) {
+		miniopt_t opts;
+		int opt_err;
+
+		/* Initialize option parser */
+		miniopt_init(&opts, "pktgen", "", FALSE);
+
+		while ((opt_err = miniopt(&opts, argv)) != -1) {
+			if (opt_err == 1) {
+				fprintf(stderr, "pktgen options error\n");
+				ret = -1;
+				goto exit;
+			}
+			argv += opts.consumed;
+
+			if (!opts.good_int && opts.opt != 'd') {
+				fprintf(stderr, "invalid integer %s\n", opts.valstr);
+				ret = -1;
+				goto exit;
+			}
+
+			switch (opts.opt) {
+			case 'f':
+				pktgen.freq = opts.uval;
+				break;
+			case 'c':
+				pktgen.count = opts.uval;
+				break;
+			case 'p':
+				pktgen.print = opts.uval;
+				break;
+			case 't':
+				pktgen.total = opts.uval;
+				break;
+			case 's':
+				pktgen.stop = opts.uval;
+				break;
+			case 'm':
+				pktgen.minlen = opts.uval;
+				break;
+			case 'M':
+				pktgen.maxlen = opts.uval;
+				break;
+			case 'l': case 'L':
+				pktgen.minlen = pktgen.maxlen = opts.uval;
+				break;
+			case 'd':
+				if (!strcmp(opts.valstr, "send"))
+					pktgen.mode = DHD_PKTGEN_SEND;
+				else if (!strcmp(opts.valstr, "echo"))
+					pktgen.mode = DHD_PKTGEN_ECHO;
+				else if (!strcmp(opts.valstr, "burst"))
+					pktgen.mode = DHD_PKTGEN_RXBURST;
+				else if (!strcmp(opts.valstr, "recv"))
+					pktgen.mode = DHD_PKTGEN_RECV;
+				else {
+					fprintf(stderr, "unrecognized dir mode %s\n",
+					        opts.valstr);
+					return BCME_USAGE_ERROR;
+				}
+				break;
+
+			default:
+				fprintf(stderr, "option parsing error (key %s valstr %s)\n",
+				        opts.key, opts.valstr);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+
+		if (pktgen.maxlen < pktgen.minlen) {
+			fprintf(stderr, "min/max error (%d/%d)\n", pktgen.minlen, pktgen.maxlen);
+			ret = -1;
+			goto exit;
+		}
+
+		/* Set the new values */
+		ret = dhd_var_setbuf(dhd, "pktgen", &pktgen, sizeof(pktgen));
+	} else {
+		printf("Counts: %d send attempts, %d received, %d tx failures\n",
+		       pktgen.numsent, pktgen.numrcvd, pktgen.numfail);
+	}
+
+	/* Show configuration in either case */
+	switch (pktgen.mode) {
+	case DHD_PKTGEN_ECHO: str = "echo"; break;
+	case DHD_PKTGEN_SEND: str = "send"; break;
+	case DHD_PKTGEN_RECV: str = "recv"; break;
+	case DHD_PKTGEN_RXBURST: str = "burst"; break;
+	default: str = "UNKNOWN"; break;
+	}
+
+	printf("Config: mode %s %d pkts (len %d-%d) each %d ticks\n",
+	       str, pktgen.count, pktgen.minlen, pktgen.maxlen, pktgen.freq);
+
+	/* Second config line for optional items */
+	str = "        ";
+	if (pktgen.total) {
+		printf("%slimit %d", str, pktgen.total);
+		str = ", ";
+	}
+	if (pktgen.print) {
+		printf("%sprint every %d ticks", str, (pktgen.freq * pktgen.print));
+		str = ", ";
+	}
+	if (pktgen.stop) {
+		printf("%sstop after %d tx failures", str, pktgen.stop);
+		str = ", ";
+	}
+	if (str[0] == ',')
+		printf("\n");
+
+exit:
+	return ret;
+}
+#endif /* SDTEST */
+
+static dbg_msg_t dhd_sd_msgs[] = {
+	{SDH_ERROR_VAL,	"error"},
+	{SDH_TRACE_VAL,	"trace"},
+	{SDH_INFO_VAL,	"info"},
+	{SDH_DATA_VAL,	"data"},
+	{SDH_CTRL_VAL,	"control"},
+	{SDH_LOG_VAL,	"log"},
+	{SDH_DMA_VAL,	"dma"},
+	{0,		NULL}
+};
+
+static int
+dhd_sd_msglevel(void *dhd, cmd_t *cmd, char **argv)
+{
+	return dhd_do_msglevel(dhd, cmd, argv, dhd_sd_msgs);
+}
+
+static int
+dhd_sd_blocksize(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc;
+	char *endptr = NULL;
+	void *ptr = NULL;
+	int func, size;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc < 1 || argc > 2) {
+		printf("required args: function [size] (size 0 means max)\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	func = strtol(argv[1], &endptr, 0);
+	if (*endptr != '\0') {
+		printf("Invalid function: %s\n", argv[1]);
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argc > 1) {
+		size = strtol(argv[2], &endptr, 0);
+		if (*endptr != '\0') {
+			printf("Invalid size: %s\n", argv[1]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if (argc == 1) {
+		if ((ret = dhd_var_getbuf(dhd, cmd->name, &func, sizeof(func), &ptr)) >= 0)
+			printf("Function %d block size: %d\n", func, *(int*)ptr);
+	} else {
+		printf("Setting function %d block size to %d\n", func, size);
+		size &= 0x0000ffff; size |= (func << 16);
+		ret = dhd_var_setbuf(dhd, cmd->name, &size, sizeof(size));
+	}
+
+	return (ret);
+}
+
+static int
+dhd_sd_mode(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc;
+	int sdmode;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argv[1]) {
+		if (!strcmp(argv[1], "spi")) {
+			strcpy(argv[1], "0");
+		} else if (!strcmp(argv[1], "sd1")) {
+			strcpy(argv[1], "1");
+		} else if (!strcmp(argv[1], "sd4")) {
+			strcpy(argv[1], "2");
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		ret = dhd_var_setint(wl, cmd, argv);
+
+	} else {
+		if ((ret = dhd_var_get(wl, cmd, argv))) {
+			return (ret);
+		} else {
+			sdmode = *(int32*)buf;
+
+			printf("SD Mode is: %s\n",
+			       sdmode == 0 ? "SPI"
+			       : sdmode == 1 ? "SD1"
+				   : sdmode == 2 ? "SD4" : "Unknown");
+		}
+	}
+
+	return (ret);
+}
+
+static int
+dhd_dma_mode(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc;
+	int dmamode;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argv[1]) {
+		if (!stricmp(argv[1], "pio")) {
+			strcpy(argv[1], "0");
+		} else if (!strcmp(argv[1], "0")) {
+		} else if (!stricmp(argv[1], "dma")) {
+			strcpy(argv[1], "1");
+		} else if (!stricmp(argv[1], "sdma")) {
+			strcpy(argv[1], "1");
+		} else if (!strcmp(argv[1], "1")) {
+		} else if (!stricmp(argv[1], "adma1")) {
+			strcpy(argv[1], "2");
+		} else if (!stricmp(argv[1], "adma")) {
+			strcpy(argv[1], "3");
+		} else if (!stricmp(argv[1], "adma2")) {
+			strcpy(argv[1], "3");
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		ret = dhd_var_setint(wl, cmd, argv);
+
+	} else {
+		if ((ret = dhd_var_get(wl, cmd, argv))) {
+			return (ret);
+		} else {
+			dmamode = *(int32*)buf;
+
+			printf("DMA Mode is: %s\n",
+			       dmamode == 0 ? "PIO"
+			       : dmamode == 1 ? "SDMA"
+			       : dmamode == 2 ? "ADMA1"
+			       : dmamode == 3 ? "ADMA2"
+			       : "Unknown");
+		}
+	}
+
+	return (ret);
+}
+
+
+/*
+ * dhd_regs2args is a generic function that is used for setting/getting
+ * DHDIOVAR variables that require address for read, and
+ * address + data for write.
+ */
+static int
+dhd_reg2args(void *dhd, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	uint32 int_val;
+	bool get = TRUE;
+	uint32 len;
+	void *ptr = NULL;
+	char *endptr;
+	int ret = 0;
+
+	if (argv[1]) {
+		len = sizeof(int_val);
+		int_val = strtoul(argv[1], &endptr, 0);
+		memcpy(var, (char *)&int_val, sizeof(int_val));
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	if (argv[2]) {
+		get = FALSE;
+		int_val = strtoul(argv[2], &endptr, 0);
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+	if (get) {
+		if ((ret = dhd_var_getbuf(dhd, cmd->name, var, sizeof(var), &ptr)) < 0)
+			return ret;
+
+		printf("0x%x\n", (*(int *)ptr));
+	}
+	else
+		ret = dhd_var_setbuf(dhd, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+static int
+dhd_pcie_dmaxfer(void *dhd, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	uint32 int_val;
+	uint32 len;
+	char *endptr;
+	int ret = 0;
+
+	bzero(var, sizeof(var));
+	if (argv[1]) {
+		len = sizeof(int_val);
+		int_val = strtoul(argv[1], &endptr, 0);
+		memcpy(var, (char *)&int_val, sizeof(int_val));
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	if (argv[2]) {
+		int_val = strtoul(argv[2], &endptr, 0);
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+
+	if (argv[3]) {
+		int_val = strtoul(argv[3], &endptr, 0);
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+	ret = dhd_var_setbuf(dhd, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+static int
+dhd_sdreg(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret;
+	sdreg_t sdreg;
+	uint argc;
+	char *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	bzero(&sdreg, sizeof(sdreg));
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	/* required args: offset (will default size) */
+	if (argc < 1) {
+		printf("required args: offset[/size] [value]\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	sdreg.offset = strtoul(argv[1], &ptr, 0);
+	if (*ptr && *ptr != '/') {
+		printf("Bad arg: %s\n", argv[1]);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* read optional /size */
+	if (*ptr == '/') {
+		sdreg.func = strtol((ptr+1), &ptr, 0);
+		if (*ptr || ((sdreg.func != 2) && sdreg.func != 4)) {
+			printf("Bad size option?\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	else {
+		sdreg.func = 4;
+		printf("Defaulting to register size 4\n");
+	}
+
+	if (argc > 1) {
+		sdreg.value = strtoul(argv[2], &ptr, 0);
+		if (*ptr) {
+			printf("Bad value: %s\n", argv[2]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if (argc <= 1) {
+		ret = dhd_var_getbuf(dhd, argv[0], &sdreg, sizeof(sdreg), (void**)&ptr);
+		if (ret >= 0)
+			printf("0x%0*x\n", (2 * sdreg.func), *(int *)ptr);
+	} else {
+		ret = dhd_var_setbuf(dhd, argv[0], &sdreg, sizeof(sdreg));
+	}
+
+	return (ret);
+}
+
+static int
+dhd_membytes(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	uint argc;
+	char *ptr;
+	int params[2];
+	uint addr;
+	uint len;
+	int align;
+
+	int rawout, hexin;
+
+	miniopt_t opts;
+	int opt_err;
+
+	/* Parse command-line options */
+	miniopt_init(&opts, "membytes", "rh", FALSE);
+
+	rawout = hexin = 0;
+
+	argv++;
+	while ((opt_err = miniopt(&opts, argv)) != -1) {
+		if (opt_err == 1) {
+			fprintf(stderr, "membytes options error\n");
+			ret = -1;
+			goto exit;
+		}
+
+		if (opts.positional)
+			break;
+
+		argv += opts.consumed;
+
+		if (opts.opt == 'h') {
+			hexin = 1;
+		} else if (opts.opt == 'r') {
+			rawout = 1;
+		} else {
+			fprintf(stderr, "membytes command error\n");
+			ret = -1;
+			goto exit;
+		}
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	/* required args: address size [<data>]] */
+	if (argc < 2) {
+		fprintf(stderr, "required args: address size [<data>]\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argc < 3 && hexin) {
+		fprintf(stderr, "missing <data> required by -h\n");
+		return BCME_USAGE_ERROR;
+	}
+	if ((argc > 2) && (rawout)) {
+		fprintf(stderr, "can't have <data> arg with -r\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* read address */
+	addr = strtoul(argv[0], &ptr, 0);
+	if (*ptr) {
+		fprintf(stderr, "Bad arg: %s\n", argv[0]);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* read size */
+	len = strtoul(argv[1], &ptr, 0);
+	if (*ptr) {
+		fprintf(stderr, "Bad value: %s\n", argv[1]);
+		return BCME_USAGE_ERROR;
+	}
+
+	align = addr & 0x03;
+	if (align && argc > 2) {
+		fprintf(stderr, "Can only write starting at long-aligned addresses.\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* get can just use utility function, set must copy custom buffer */
+	if (argc == 2) {
+		/* Read */
+		uint chunk = DHD_IOCTL_MAXLEN;
+		for (addr -= align, len += align; len; addr += chunk, len -= chunk, align = 0) {
+			chunk = MIN(chunk, len);
+			params[0] = addr;
+			params[1] = ROUNDUP(chunk, 4);
+			ret = dhd_var_getbuf(dhd, "membytes",
+			                     params, (2 * sizeof(int)), (void**)&ptr);
+			if (ret < 0)
+				goto exit;
+
+			if (rawout) {
+				fwrite(ptr + align, sizeof(char), chunk - align, stdout);
+			} else {
+				dhd_hexdump((uchar*)ptr + align, chunk - align, addr + align);
+			}
+		}
+	} else {
+		/* Write */
+		uint patlen = strlen(argv[2]);
+		uint chunk, maxchunk;
+		char *sptr;
+
+		if (hexin) {
+			char *inptr, *outptr;
+			if (patlen & 1) {
+				fprintf(stderr, "Hex (-h) must consist of whole bytes\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			for (inptr = outptr = argv[2]; patlen; patlen -= 2) {
+				int n1, n2;
+
+				n1 = (int)((unsigned char)*inptr++);
+				n2 = (int)((unsigned char)*inptr++);
+				if (!isxdigit(n1) || !isxdigit(n2)) {
+					fprintf(stderr, "invalid hex digit %c\n",
+					        (isxdigit(n1) ? n2 : n1));
+					ret = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				n1 = isdigit(n1) ? (n1 - '0')
+				        : ((islower(n1) ? (toupper(n1)) : n1) - 'A' + 10);
+				n2 = isdigit(n2) ? (n2 - '0')
+				        : ((islower(n2) ? (toupper(n2)) : n2) - 'A' + 10);
+				*outptr++ = (n1 * 16) + n2;
+			}
+
+			patlen = outptr - argv[2];
+		}
+
+		sptr = argv[2];
+		maxchunk = DHD_IOCTL_MAXLEN - (strlen(cmd->name) + 1 + (2 * sizeof(int)));
+
+		while (len) {
+			chunk = (len > maxchunk) ? (maxchunk & ~0x3) : len;
+
+			/* build the iovar command */
+			memset(buf, 0, DHD_IOCTL_MAXLEN);
+			strcpy(buf, cmd->name);
+			ptr = buf + strlen(buf) + 1;
+			params[0] = addr; params[1] = chunk;
+			memcpy(ptr, params, (2 * sizeof(int)));
+			ptr += (2 * sizeof(int));
+			addr += chunk; len -= chunk;
+
+			while (chunk--) {
+				*ptr++ = *sptr++;
+				if (sptr >= (argv[2] + patlen))
+					sptr = argv[2];
+			}
+
+			ret = dhd_set(dhd, DHD_SET_VAR, &buf[0], (ptr - buf));
+			if (ret < 0)
+				goto exit;
+		}
+	}
+
+exit:
+	return ret;
+}
+
+static int
+dhd_idletime(void *dhd, cmd_t *cmd, char **argv)
+{
+	int32 idletime;
+	char *endptr = NULL;
+	int err = 0;
+
+	if (argv[1]) {
+		if (!strcmp(argv[1], "never")) {
+			idletime = 0;
+		} else if (!strcmp(argv[1], "immediate") || !strcmp(argv[1], "immed")) {
+			idletime = DHD_IDLE_IMMEDIATE;
+		} else {
+			idletime = strtol(argv[1], &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr, "invalid number %s\n", argv[1]);
+				err = BCME_USAGE_ERROR;
+			}
+		}
+		if ((idletime < 0) && (idletime != DHD_IDLE_IMMEDIATE)) {
+			fprintf(stderr, "invalid value %s\n", argv[1]);
+			err = -1;
+		}
+
+		if (!err) {
+			strcpy(buf, "idletime");
+			endptr = buf + strlen(buf) + 1;
+			memcpy(endptr, &idletime, sizeof(uint32));
+			endptr += sizeof(uint32);
+			err = dhd_set(dhd, DHD_SET_VAR, &buf[0], (endptr - buf));
+		}
+	} else {
+		if ((err = dhd_var_get(dhd, cmd, argv))) {
+			return err;
+		} else {
+			idletime = *(int32*)buf;
+
+			if (idletime == 0) {
+				printf("0 (never)\n");
+			} else if (idletime == DHD_IDLE_IMMEDIATE) {
+				printf("-1 (immediate)\n");
+			} else if (idletime > 0) {
+				printf("%d\n", idletime);
+			} else printf("%d (invalid)\n", idletime);
+		}
+	}
+	return err;
+}
+
+static int
+dhd_idleclock(void *dhd, cmd_t *cmd, char **argv)
+{
+	int32 idleclock;
+	char *endptr = NULL;
+	int err = 0;
+
+	if (argv[1]) {
+		if (!strcmp(argv[1], "active")) {
+			idleclock = DHD_IDLE_ACTIVE;
+		} else if (!strcmp(argv[1], "stopped")) {
+			idleclock = DHD_IDLE_STOP;
+		} else {
+			idleclock = strtol(argv[1], &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr, "invalid number %s\n", argv[1]);
+				err = BCME_USAGE_ERROR;
+			}
+		}
+
+		if (!err) {
+			strcpy(buf, "idleclock");
+			endptr = buf + strlen(buf) + 1;
+			memcpy(endptr, &idleclock, sizeof(int32));
+			endptr += sizeof(int32);
+			err = dhd_set(dhd, DHD_SET_VAR, &buf[0], (endptr - buf));
+		}
+	} else {
+		if ((err = dhd_var_get(dhd, cmd, argv))) {
+			return err;
+		} else {
+			idleclock = *(int32*)buf;
+
+			if (idleclock == DHD_IDLE_ACTIVE)
+				printf("Idleclock %d (active)\n", idleclock);
+			else if (idleclock == DHD_IDLE_STOP)
+				printf("Idleclock %d (stopped)\n", idleclock);
+			else
+				printf("Idleclock divisor %d\n", idleclock);
+		}
+	}
+	return err;
+}
+
+/* Word count for a 4kb SPROM */
+#define SPROM_WORDS 256
+
+static int
+dhd_sprom(void *dhd, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	return (-1);
+#else
+	int ret, i;
+	uint argc;
+	char *endptr;
+	char *bufp, *countptr;
+	uint16 *wordptr;
+	uint offset, words, bytes;
+	bool nocrc = FALSE;
+
+	char *fname;
+	FILE *fp;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	/* init buffer */
+	bufp = buf;
+	memset(bufp, 0, DHD_IOCTL_MAXLEN);
+	strcpy(bufp, "sprom");
+	bufp += strlen("sprom") + 1;
+
+	if (strcmp(argv[0], "srdump") == 0) {
+		if (argc) {
+			fprintf(stderr, "Command srdump doesn't take args\n");
+			return BCME_USAGE_ERROR;
+		}
+		offset = 0;
+		words = SPROM_WORDS;
+		bytes = 2 * words;
+
+		memcpy(bufp, &offset, sizeof(int));
+		bufp += sizeof(int);
+		memcpy(bufp, &bytes, sizeof(int));
+		bufp += sizeof(int);
+
+		if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) {
+			fprintf(stderr, "Internal error: unaligned word buffer\n");
+			return BCME_ERROR;
+		}
+	} else {
+		if (strcmp(argv[0], "srwrite") != 0) {
+			fprintf(stderr, "Unimplemented sprom command: %s\n", argv[0]);
+			return BCME_USAGE_ERROR;
+		}
+
+		if (argc == 0) {
+			return BCME_USAGE_ERROR;
+		} else if ((argc == 1) ||
+		           ((argc == 2) && ((nocrc = !strcmp(argv[1], "-c"))))) {
+
+			fname = nocrc ? argv[2] : argv[1];
+
+			/* determine and validate file size */
+			if ((ret = file_size(fname)) < 0)
+				return BCME_ERROR;
+
+			bytes = ret;
+			offset = 0;
+			words = bytes / 2;
+
+			if (bytes != 2 * SPROM_WORDS) {
+				fprintf(stderr, "Bad file size\n");
+				return BCME_ERROR;
+			}
+
+			memcpy(bufp, &offset, sizeof(int));
+			bufp += sizeof(int);
+			memcpy(bufp, &bytes, sizeof(int));
+			bufp += sizeof(int);
+
+			if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) {
+				fprintf(stderr, "Internal error: unaligned word buffer\n");
+				return BCME_ERROR;
+			}
+
+			if ((fp = fopen(fname, "rb")) == NULL) {
+				fprintf(stderr, "Could not open %s: %s\n",
+				        fname, strerror(errno));
+				return BCME_ERROR;
+			}
+
+			if (fread((uint16*)bufp, sizeof(uint16), words, fp) != words) {
+				fprintf(stderr, "Could not read %d bytes from %s\n",
+				        words * 2, fname);
+				fclose(fp);
+				return BCME_ERROR;
+			}
+
+			fclose(fp);
+
+			if (!nocrc &&
+			    hndcrc8((uint8*)bufp, bytes, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
+				fprintf(stderr, "CRC check failed: 0x%02x, should be 0x%02x.\n",
+				        ((uint8*)bufp)[bytes-1],
+				        ~hndcrc8((uint8*)bufp, bytes - 1, CRC8_INIT_VALUE) & 0xff);
+				return BCME_ERROR;
+			}
+
+			ltoh16_buf(bufp, bytes);
+		} else {
+			offset = strtoul(*++argv, &endptr, 0) * 2;
+			if (*endptr != '\0') {
+				fprintf(stderr, "offset %s is not an integer\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+
+			memcpy(bufp, &offset, sizeof(int));
+			bufp += sizeof(int);
+			countptr = bufp;
+			bufp += sizeof(int);
+
+			if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) {
+				fprintf(stderr, "Internal error: unaligned word buffer\n");
+				return BCME_ERROR;
+			}
+
+			for (words = 0, wordptr = (uint16*)bufp; *++argv; words++) {
+				*wordptr++ = (uint16)strtoul(*argv, &endptr, 0);
+				if (*endptr != '\0') {
+					fprintf(stderr, "value %s is not an integer\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+				if (words > SPROM_WORDS) {
+					fprintf(stderr, "max of %d words\n", SPROM_WORDS);
+					return BCME_USAGE_ERROR;
+				}
+			}
+
+			bytes = 2 * words;
+			memcpy(countptr, &bytes, sizeof(int));
+		}
+	}
+
+	if (argc) {
+		ret = dhd_set(dhd, DHD_SET_VAR, buf,
+		              (strlen("sprom") + 1) + (2 * sizeof(int)) + bytes);
+		return (ret);
+	} else {
+		ret = dhd_get(dhd, DHD_GET_VAR, buf,
+		              (strlen("sprom") + 1) + (2 * sizeof(int)) + bytes);
+		if (ret < 0) {
+			return ret;
+		}
+
+		for (i = 0; i < (int)words; i++) {
+			if ((i % 8) == 0)
+				printf("\n  srom[%03d]:  ", i);
+			printf("0x%04x  ", ((uint16*)buf)[i]);
+		}
+		printf("\n");
+	}
+
+	return 0;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+/*
+ * read_vars: reads an environment variables file into a buffer,
+ * reformatting them and returning the length (-1 on error).
+ *
+ * The input text file consists of lines of the form "<var>=<value>\n".
+ * CRs are ignored, as are blank lines and comments beginning with '#'.
+ *
+ * The output buffer consists of blocks of the form "<var>=<value>\0"
+ * (the newlines have been replaced by NULs)
+ *
+ * Todo: allow quoted variable names and quoted values.
+*/
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+static int
+read_vars(char *fname, char *buf, int buf_maxlen)
+{
+	FILE *fp;
+	int buf_len, slen;
+	char line[256], *s, *e;
+	int line_no = 0;
+
+	if ((fp = fopen(fname, "rb")) == NULL) {
+		fprintf(stderr, "Cannot open NVRAM file %s: %s\n",
+		        fname, strerror(errno));
+		exit(1);
+	}
+
+	buf_len = 0;
+
+	while (fgets(line, sizeof(line), fp) != NULL) {
+		bool found_eq = FALSE;
+
+		/* Ensure line length is limited */
+		line[sizeof(line) - 1] = 0;
+
+		/* Skip any initial white space */
+		for (s = line; *s == ' ' || *s == '\t'; s++)
+			;
+
+		/* Determine end of string */
+		for (e = s; *e != 0 && *e != '#' && *e != '\r' && *e != '\n'; e++)
+			if (*e == '=')
+				found_eq = TRUE;
+
+		/* Strip any white space from end of string */
+		while (e > s && (e[-1] == ' ' || e[-1] == '\t'))
+			e--;
+
+		slen = e - s;
+
+		/* Skip lines that end up blank */
+		if (slen == 0)
+			continue;
+
+		if (!found_eq) {
+			fprintf(stderr, "Invalid line %d in NVRAM file %s\n", line_no, fname);
+			fclose(fp);
+			return -1;
+		}
+
+		if (buf_len + slen + 1 > buf_maxlen) {
+			fprintf(stderr, "NVRAM file %s too long\n", fname);
+			fclose(fp);
+			return -1;
+		}
+
+		memcpy(buf + buf_len, s, slen);
+		buf_len += slen;
+		buf[buf_len++] = 0;
+	}
+
+	fclose(fp);
+
+	return buf_len;
+}
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+
+static int
+dhd_vars(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint argc;
+	char *bufp;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	switch (argc) {
+	case 0: /* get */
+	{
+		if ((ret = dhd_var_getbuf(dhd, "vars", NULL, 0, (void**)&bufp)))
+			break;
+		while (*bufp) {
+			printf("%s\n", bufp);
+			bufp += strlen(bufp) + 1;
+		}
+	}
+	break;
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+	case 1: /* set */
+	{
+		char *vname;
+		uint nvram_len;
+
+		vname = argv[1];
+
+		bufp = buf;
+		strcpy(bufp, "vars");
+		bufp += strlen("vars") + 1;
+
+		if ((ret = read_vars(vname, bufp,
+		                           DHD_IOCTL_MAXLEN - (strlen("vars") + 3))) < 0) {
+			ret = -1;
+			break;
+		}
+
+		nvram_len = ret;
+		bufp += nvram_len;
+		*bufp++ = 0;
+
+		ret = dhd_set(dhd, DHD_SET_VAR, buf, bufp - buf);
+	}
+	break;
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+
+	default:
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+#define MEMBLOCK 2048
+
+/* Check that strlen("membytes")+1 + 2*sizeof(int32) + MEMBLOCK <= DHD_IOCTL_MAXLEN */
+#if (MEMBLOCK + 17 > DHD_IOCTL_MAXLEN)
+#error MEMBLOCK/DHD_IOCTL_MAXLEN sizing
+#endif
+
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+static int
+dhd_verify_file_bytes(void *dhd, uint8 *memblock, int start, uint len)
+{
+	int ret = 0;
+	uint i = 0;
+	char *ptr;
+	int params[2];
+	uint8 *src, *dst;
+
+	params[0] = start;
+	params[1] = len;
+	ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
+	if (ret) {
+		fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
+		__FUNCTION__, len, start);
+		return ret;
+	}
+
+	src = (uint8 *)memblock;
+	dst = (uint8 *)ptr;
+	while (i < len) {
+		if (src[i] != dst[i]) {
+			fprintf(stderr, "   0x%x: exp[0x%02X] != got[0x%02X]\n",
+				start+i, src[i], dst[i]);
+			ret = -1;
+		}
+		i++;
+	}
+
+	return ret;
+}
+
+static int
+dhd_load_file_bytes(void *dhd, cmd_t *cmd, FILE *fp, int fsize, int start, uint blk_sz, bool verify)
+{
+	int tot_len = 0;
+	uint read_len;
+	char *bufp;
+	uint len;
+	uint8 memblock[MEMBLOCK];
+	int ret;
+	int retry;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!fsize || !fp)
+		return -1;
+
+	assert(blk_sz <= MEMBLOCK);
+
+	while (tot_len < fsize) {
+		read_len = fsize - tot_len;
+		if (read_len >= blk_sz) {
+			read_len = blk_sz;
+
+			if (!ISALIGNED(start, MEMBLOCK))
+				read_len = ROUNDUP(start, MEMBLOCK) - start;
+		}
+
+		len = fread(memblock, sizeof(uint8), read_len, fp);
+		if ((len < read_len) && !feof(fp)) {
+			fprintf(stderr, "%s: error reading file\n", __FUNCTION__);
+			return -1;
+
+		}
+		retry = 0;
+failed_retry:
+
+		bufp = buf;
+		memset(bufp, 0, DHD_IOCTL_MAXLEN);
+		strcpy(bufp, "membytes");
+		bufp += strlen("membytes") + 1;
+		memcpy(bufp, &start, sizeof(int));
+		bufp += sizeof(int);
+		memcpy(bufp, &len, sizeof(int));
+		bufp += sizeof(int);
+		memcpy(bufp, memblock, len);
+
+		ret = dhd_set(dhd, DHD_SET_VAR, &buf[0], (bufp - buf + len));
+
+		if (ret) {
+			fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
+			        __FUNCTION__, ret, len, start);
+			return ret;
+		}
+
+		if (verify == TRUE) {
+			if (dhd_verify_file_bytes(dhd, memblock, start, len) != 0) {
+				if (retry++ < 5000)
+				{
+					fprintf(stderr, "%s: verify failed %d membytes "
+						"from 0x%08x\n", __FUNCTION__, len, start);
+					goto failed_retry;
+				}
+			}
+		}
+
+		start += len;
+		tot_len += len;
+	}
+	return 0;
+}
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+
+#ifdef QMONITOR
+static int
+dhd_qtime_thres(void *dhd, cmd_t *cmd, char **argv)
+{
+	int flag = 0xdead;
+
+	if (argv[1]) {
+		flag = atoi(argv[1]);
+		dhd_iovar_setint(dhd, cmd->name, flag);
+	}
+	else {
+		dhd_iovar_getint(dhd, cmd->name, &flag);
+		printf("qtime_thres: %d\n", flag);
+	}
+	return 0;
+}
+
+static int
+dhd_qtime_percent(void *dhd, cmd_t *cmd, char **argv)
+{
+	int flag = 0xdead;
+
+	if (argv[1]) {
+		flag = atoi(argv[1]);
+		dhd_iovar_setint(dhd, cmd->name, flag);
+	}
+	else {
+		dhd_iovar_getint(dhd, cmd->name, &flag);
+		printf("qtime_percent: %d %%\n", flag);
+	}
+	return 0;
+}
+#endif /* QMONITOR */
+
+
+#ifdef PROP_TXSTATUS
+static int
+dhd_proptxstatusenable(void *dhd, cmd_t *cmd, char **argv)
+{
+	int flag = 0xdead;
+	int ret;
+
+	if (argv[1]) {
+		flag = atoi(argv[1]);
+		ret = dhd_iovar_setint(dhd, cmd->name, flag);
+	}
+	else {
+		ret = dhd_iovar_getint(dhd, cmd->name, &flag);
+		if (ret >= 0)
+			printf("proptxstatus: %d\n", flag);
+	}
+	return ret;
+}
+
+static int
+dhd_proptxstatusmode(void *dhd, cmd_t *cmd, char **argv)
+{
+	int mode = 0xdead;
+	int ret;
+
+	if (argv[1]) {
+		mode = atoi(argv[1]);
+		ret = dhd_iovar_setint(dhd, cmd->name, mode);
+	}
+	else {
+		ret = dhd_iovar_getint(dhd, cmd->name, &mode);
+		if (ret >= 0)
+			printf("proptxstatusmode: %d\n", mode);
+	}
+	return ret;
+}
+
+static int
+dhd_proptxopt(void *dhd, cmd_t *cmd, char **argv)
+{
+	int flag = 0xdead;
+	int ret;
+
+	if (argv[1]) {
+		flag = atoi(argv[1]);
+		ret = dhd_iovar_setint(dhd, cmd->name, flag);
+	}
+	else {
+		ret = dhd_iovar_getint(dhd, cmd->name, &flag);
+		if (ret >= 0)
+			printf("proptx_opt: %d\n", flag);
+	}
+	return ret;
+}
+
+#endif /* PROP_TXSTATUS */
+
+static int
+dhd_get_ramstart(void *dhd, uint32 *ramstart)
+{
+	int ret;
+	char *ramstart_args[] = {"ramstart", NULL};
+
+	/* Read the bus type the DHD driver is associated to */
+	if ((ret = dhd_var_get(dhd, NULL, ramstart_args)) != BCME_OK) {
+		fprintf(stderr, "%s: error obtaining ramstart\n", __FUNCTION__);
+
+		return ret;
+	}
+
+	*ramstart = *(uint32 *)buf;
+
+	return BCME_OK;
+}
+
+static int
+dhd_download(void *dhd, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	return (-1);
+#else
+	bool reset = TRUE;
+	bool run = TRUE;
+	bool verify = FALSE;
+	char *fname = NULL;
+	char *vname = NULL;
+	uint32 start;
+	int ret = 0;
+	int fsize;
+	uint32 bustype;
+	long filepos;
+
+	FILE *fp = NULL;
+	uint32 ramsize;
+	char *memszargs[] = { "ramsize", NULL };
+
+	char *bufp;
+
+	miniopt_t opts;
+	int opt_err;
+	uint nvram_len;
+	struct trx_header trx_hdr;
+	uint32 trx_hdr_len;
+	bool trx_file = FALSE;
+	uint memblock_sz = MEMBLOCK;
+	bool embedded_ucode = FALSE;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((ret = dhd_get_ramstart(dhd, &start)) != BCME_OK)
+		goto exit;
+
+	/* Parse command-line options */
+	miniopt_init(&opts, "download", "", TRUE);
+
+	argv++;
+	while ((opt_err = miniopt(&opts, argv)) != -1) {
+		if (opt_err == 1) {
+			fprintf(stderr, "download options error\n");
+			ret = -1;
+			goto exit;
+		}
+		argv += opts.consumed;
+
+		if (opts.opt == 'a') {
+			if (!opts.good_int) {
+				fprintf(stderr, "invalid address %s\n", opts.valstr);
+				ret = -1;
+				goto exit;
+			}
+			start = (uint32)opts.uval;
+		} else if (opts.positional) {
+			if (fname && vname) {
+				fprintf(stderr, "extra positional arg, %s\n",
+				        opts.valstr);
+				ret = -1;
+				goto exit;
+			}
+			if (fname)
+				vname = opts.valstr;
+			else
+				fname = opts.valstr;
+		} else if (!opts.opt) {
+			if (!strcmp(opts.key, "noreset")) {
+				reset = FALSE;
+			} else if (!strcmp(opts.key, "norun")) {
+				run = FALSE;
+			} else if (!strcmp(opts.key, "verify")) {
+				verify = TRUE;
+			} else {
+				fprintf(stderr, "unrecognized option %s\n", opts.valstr);
+				ret = -1;
+				goto exit;
+			}
+		} else {
+			fprintf(stderr, "unrecognized option %c\n", opts.opt);
+			ret = -1;
+			goto exit;
+		}
+	}
+
+	/* validate arguments */
+	if (!fname) {
+		fprintf(stderr, "filename required\n");
+		ret = -1;
+		goto exit;
+	}
+
+	/* validate file size compared to memory size */
+	if ((fsize = file_size(fname)) < 0) {
+		ret = -1;
+		goto exit;
+	}
+	/* read the file and push blocks down to memory */
+	if ((fp = fopen(fname, "rb")) == NULL) {
+		fprintf(stderr, "%s: unable to open %s: %s\n",
+		        __FUNCTION__, fname, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+	/* Verify the file is a regular bin file or trx file */
+	{
+		uint32 tmp_len;
+		trx_hdr_len = sizeof(struct trx_header);
+		tmp_len = fread(&trx_hdr, sizeof(uint8), trx_hdr_len, fp);
+		if (tmp_len == trx_hdr_len) {
+			if (trx_hdr.magic == TRX_MAGIC) {
+				trx_file = TRUE;
+				if (trx_hdr.flag_version & TRX_EMBED_UCODE)
+					embedded_ucode = TRUE;
+			}
+			else
+				fseek(fp, 0, SEEK_SET);
+		}
+		else
+			fseek(fp, 0, SEEK_SET);
+	}
+
+	/* Check on which bus the dhd driver is sitting. Downloading methodology differs from
+	 * USB to SDIO.
+	 */
+	{
+		char* bustype_args[] = {"bustype", NULL};
+
+		/* Read the bus type the DHD driver is associated to */
+		if ((ret = dhd_var_get(dhd, NULL, bustype_args))) {
+			fprintf(stderr, "%s: error obtaining bustype\n", __FUNCTION__);
+			goto exit;
+		}
+
+		bustype = *(uint32*)buf;
+	}
+
+	if (trx_file)
+		fsize = (int)(trx_hdr.offsets[0]);
+	if (bustype == BUS_TYPE_PCIE) {
+		if ((ret = dhd_var_get(dhd, NULL, memszargs))) {
+			fprintf(stderr, "%s: error obtaining memsize\n", __FUNCTION__);
+			goto exit;
+		}
+		ramsize = *(uint32*)buf;
+	}
+
+	if (bustype == BUS_TYPE_SDIO) {
+		if ((ret = dhd_var_get(dhd, NULL, memszargs))) {
+			fprintf(stderr, "%s: error obtaining ramsize\n", __FUNCTION__);
+			goto exit;
+		}
+		ramsize = *(uint32*)buf;
+	}
+
+
+	BCM_REFERENCE(ramsize);
+
+	/* do the download reset if not suppressed */
+	if (reset) {
+		if ((ret = dhd_iovar_setint(dhd, "dwnldstate", TRUE))) {
+			fprintf(stderr, "%s: failed to put dongle in download mode\n",
+			        __FUNCTION__);
+			goto exit;
+		}
+	}
+
+	if (BUS_TYPE_USB == bustype) {
+		/* store the cur pos pointing to base image which should be written */
+		filepos = ftell(fp);
+		if (filepos == -1) {
+			fprintf(stderr, "%s: ftell failed.\n", __FUNCTION__);
+		}
+
+		/* In case of USB, we need to write header information also to dongle. */
+		fseek(fp, 0, SEEK_SET);
+
+		/* The file size is "base_image + TRX_Header_size" */
+		fsize = (int)(trx_hdr.offsets[0] + sizeof(struct trx_header));
+
+		memblock_sz = RDL_CHUNK;
+	}
+
+
+	/* Load the ram image */
+	if ((ret = dhd_load_file_bytes(dhd, cmd, fp, fsize, start, memblock_sz, verify))) {
+		fprintf(stderr, "%s: error loading the ramimage at addr 0x%x\n",
+		        __FUNCTION__, start);
+		goto exit;
+	}
+
+	if (trx_file) {
+
+		filepos = ftell(fp);
+		if (filepos == -1) {
+			fprintf(stderr, "%s: ftell failed.\n", __FUNCTION__);
+		}
+
+		if (BUS_TYPE_SDIO == bustype) {
+
+		}
+	}
+
+	fclose(fp);
+	fp = NULL;
+
+	/* download the vars file if specified */
+	if (vname) {
+		bufp = buf;
+		strcpy(bufp, "vars");
+		bufp += strlen("vars") + 1;
+
+		if ((ret = read_vars(vname, bufp,
+		                           DHD_IOCTL_MAXLEN - (strlen("vars") + 3))) < 0) {
+			ret = -1;
+			goto exit;
+		}
+
+		nvram_len = ret;
+		bufp += nvram_len;
+		*bufp++ = 0;
+
+		ret = dhd_set(dhd, DHD_SET_VAR, buf, (bufp - buf));
+		if (ret) {
+			fprintf(stderr, "%s: error %d on delivering vars\n",
+			        __FUNCTION__, ret);
+			goto exit;
+		}
+	}
+
+	/* start running the downloaded code if not suppressed */
+	if (run) {
+		if ((ret = dhd_iovar_setint(dhd, "dwnldstate", FALSE))) {
+
+			fprintf(stderr, "%s: failed to take dongle out of download mode\n",
+			        __FUNCTION__);
+			/* USB Error return values */
+			if (BUS_TYPE_USB == bustype) {
+				if (ret == -1)
+					fprintf(stderr, "%s: CPU is not in RUNNABLE State\n",
+						__FUNCTION__);
+				else
+					fprintf(stderr, "%s: Error in setting CPU to RUN mode.\n",
+						__FUNCTION__);
+			}
+			goto exit;
+		}
+	}
+	if (embedded_ucode) {
+	}
+
+exit:
+	if (fp)
+		fclose(fp);
+
+	return ret;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+dhd_dldn(void *dhd, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	return (-1);
+#else
+	char *fname = NULL;
+	uint32 start;
+	int ret = 0;
+	int fsize;
+	int fd = 0;
+
+	FILE *fp = NULL;
+	uint32 ramsize;
+
+	uint len;
+	uint8 memblock[MEMBLOCK];
+
+	miniopt_t opts;
+	int opt_err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Parse command-line options */
+	miniopt_init(&opts, "download", "", TRUE);
+	argv++;
+
+	while ((opt_err = miniopt(&opts, argv)) != -1) {
+		if (opt_err == 1) {
+			fprintf(stderr, "download options error\n");
+			ret = -1;
+			goto exit;
+		}
+		argv += opts.consumed;
+
+		if (opts.positional) {
+			if (fname) {
+				fprintf(stderr, "extra positional arg, %s\n",
+				        opts.valstr);
+				ret = -1;
+				goto exit;
+			}
+			if (!fname)
+				fname = opts.valstr;
+		} else {
+			fprintf(stderr, "unrecognized option %c\n", opts.opt);
+			ret = -1;
+			goto exit;
+		}
+	}
+
+	fd = dhd_set(dhd, DHD_DLDN_ST, NULL, 0);
+	if (fd < 0) {
+		ret = -1;
+		goto exit;
+	}
+
+	/* validate arguments */
+	if (!fname) {
+		fprintf(stderr, "filename required\n");
+		ret = -1;
+		goto exit;
+	}
+
+	/* validate file size compared to memory size */
+	if ((fsize = file_size(fname)) < 0) {
+		ret = -1;
+		goto exit;
+	}
+
+	ramsize = 393216;
+
+	if (ramsize && ((uint32)fsize > ramsize)) {
+		fprintf(stderr, "%s: file %s too large (%d > %d)\n",
+		        __FUNCTION__, fname, fsize, ramsize);
+		ret = -1;
+		goto exit;
+	}
+
+	/* read the file and push blocks down to memory */
+	if ((fp = fopen(fname, "rb")) == NULL) {
+		fprintf(stderr, "%s: unable to open %s: %s\n",
+		        __FUNCTION__, fname, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+
+	if ((ret = dhd_get_ramstart(dhd, &start)) != BCME_OK)
+		goto exit;
+
+	while ((len = fread(memblock, sizeof(uint8), MEMBLOCK, fp))) {
+		if (len < MEMBLOCK && !feof(fp)) {
+			fprintf(stderr, "%s: error reading file %s\n", __FUNCTION__, fname);
+			ret = -1;
+			goto exit;
+		}
+
+		ret = dhd_set(dhd, DHD_DLDN_WRITE, memblock, len);
+		if (ret) {
+			fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
+			        __FUNCTION__, ret, len, start);
+			goto exit;
+		}
+
+		start += len;
+	}
+
+	if (!feof(fp)) {
+		fprintf(stderr, "%s: error reading file %s\n", __FUNCTION__, fname);
+		ret = -1;
+		goto exit;
+	}
+	fclose(fp);
+	fp = NULL;
+
+exit:
+	if (fp)
+		fclose(fp);
+
+	if (fd)
+		ret = dhd_set(dhd, DHD_DLDN_END, NULL, 0);
+
+	return ret;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+dhd_upload(void *dhd, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	return (-1);
+#else
+	char *fname = NULL;
+	uint32 start;
+	uint32 size = 0;
+	int ret = 0;
+
+	FILE *fp;
+	uint32 ramsize;
+	char *memszargs[] = { "ramsize", NULL };
+
+	uint len;
+
+	miniopt_t opts;
+	int opt_err;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = dhd_get_ramstart(dhd, &start)) != BCME_OK)
+		goto exit;
+
+	/* Parse command-line options */
+	miniopt_init(&opts, "upload", "", TRUE);
+
+	argv++;
+	while ((opt_err = miniopt(&opts, argv)) != -1) {
+		if (opt_err == 1) {
+			fprintf(stderr, "upload options error\n");
+			ret = -1;
+			goto exit;
+		}
+		argv += opts.consumed;
+
+		if (opts.opt == 'a') {
+			if (!opts.good_int) {
+				fprintf(stderr, "invalid address %s\n", opts.valstr);
+				ret = -1;
+				goto exit;
+			}
+			start = (uint32)opts.uval;
+		} else if (opts.positional) {
+			if (!fname) {
+				fname = opts.valstr;
+			} else if (opts.good_int) {
+				size = (uint32)opts.uval;
+			} else {
+				fprintf(stderr, "upload options error\n");
+				ret = -1;
+				goto exit;
+			}
+		} else if (!opts.opt) {
+			fprintf(stderr, "unrecognized option %s\n", opts.valstr);
+			ret = -1;
+			goto exit;
+		} else {
+			fprintf(stderr, "unrecognized option %c\n", opts.opt);
+			ret = -1;
+			goto exit;
+		}
+	}
+
+	/* validate arguments */
+	if (!fname) {
+		fprintf(stderr, "filename required\n");
+		ret = -1;
+		goto exit;
+	}
+
+	if ((ret = dhd_var_get(dhd, NULL, memszargs))) {
+		fprintf(stderr, "%s: error obtaining ramsize\n", __FUNCTION__);
+		goto exit;
+	}
+	ramsize = *(uint32*)buf;
+
+	if (!ramsize)
+		ramsize = size;
+
+	if ((fp = fopen(fname, "wb")) == NULL) {
+		fprintf(stderr, "%s: Could not open %s: %s\n",
+		        __FUNCTION__, fname, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+
+	/* default size to full RAM */
+	if (!size)
+		size = ramsize;
+
+	/* read memory and write to file */
+	while (size) {
+		char *ptr;
+		int params[2];
+
+		len = MIN(MEMBLOCK, size);
+
+		params[0] = start;
+		params[1] = len;
+		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
+		if (ret) {
+			fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
+			        __FUNCTION__, len, start);
+			break;
+		}
+
+		if (fwrite(ptr, sizeof(char), len, fp) != len) {
+			fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
+			ret = -1;
+			break;
+		}
+
+		start += len;
+		size -= len;
+	}
+
+	fclose(fp);
+exit:
+	return ret;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+#ifdef BWL_FILESYSTEM_SUPPORT
+static int
+dhd_get_debug_info(void *dhd, hndrte_debug_t *debug_info)
+{
+	int i;
+	int ret;
+	int params[2];
+
+	uint32 *buffer;
+	uint32 debug_info_ptr;
+	uint32 ramstart;
+
+	if ((ret = dhd_get_ramstart(dhd, &ramstart)) != BCME_OK)
+		return ret;
+
+	/*
+	 * Different chips have different fixed debug_info_ptrs
+	 * because of different ROM locations/uses.  Try them all looking
+	 * for the magic number.
+	 */
+	for (i = 0; ; i++) {
+		if (debug_info_ptrs[i] == DEBUG_INFO_PTRS_END) {
+			fprintf(stderr, "Error: cannot find pointer to debug_info\n");
+			return -1;
+		}
+
+		params[0] = debug_info_ptrs[i] + ramstart;
+		params[1] = 8;
+		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&buffer);
+		if ((ret == 0) &&
+		    (*buffer == HNDRTE_DEBUG_PTR_PTR_MAGIC)) {
+			break;
+		}
+	}
+
+	debug_info_ptr = *(buffer + 1);
+	if (debug_info_ptr == 0) {
+		fprintf(stderr, "Error: Debug info pointer is zero\n");
+		return -1;
+	}
+
+	/* Read the area the debuginfoptr points at */
+	params[0] = debug_info_ptr;
+	params[1] = sizeof(hndrte_debug_t);
+	ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&buffer);
+	if (ret) {
+		fprintf(stderr, "%s: failed reading %lu membytes from 0x%08lx\n",
+			__FUNCTION__, (long unsigned) params[1], (long unsigned) params[0]);
+		return ret;
+	}
+
+	memcpy((char *) debug_info, buffer, sizeof(hndrte_debug_t));
+
+	/* Sanity check the area */
+	if ((debug_info->magic != HNDRTE_DEBUG_MAGIC) ||
+	    (debug_info->version != HNDRTE_DEBUG_VERSION)) {
+		fprintf(stderr, "Error: Invalid debug info area\n");
+		return -1;
+	}
+
+	return 0;
+}
+#endif /* BWL_FILESYSTEM_SUPPORT */
+
+static int
+dhd_coredump(void *dhd, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	return (-1);
+#else
+	char *fname = NULL;
+	int ret;
+
+	FILE *fp;
+
+	hndrte_debug_t debugInfo;
+
+	miniopt_t opts;
+	int opt_err;
+
+	int params[2];
+	char *ptr;
+
+	unsigned int start;
+	unsigned int size;
+
+	prstatus_t prstatus;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	/* Parse command-line options */
+	miniopt_init(&opts, "dump", "", TRUE);
+
+	argv++;
+	while ((opt_err = miniopt(&opts, argv)) != -1) {
+		if (opt_err == 1) {
+			fprintf(stderr, "dump options error\n");
+			ret = -1;
+			goto exit;
+		}
+		argv += opts.consumed;
+
+		if (opts.positional) {
+			if (!fname) {
+				fname = opts.valstr;
+			} else {
+				fprintf(stderr, "dump options error\n");
+				ret = -1;
+				goto exit;
+			}
+		} else if (!opts.opt) {
+			fprintf(stderr, "unrecognized option %s\n", opts.valstr);
+			ret = -1;
+			goto exit;
+		} else {
+			fprintf(stderr, "unrecognized option %c\n", opts.opt);
+			ret = -1;
+			goto exit;
+		}
+	}
+
+	/* validate arguments */
+	if (!fname) {
+		fprintf(stderr, "filename required\n");
+		ret = -1;
+		goto exit;
+	}
+
+	if ((ret = dhd_get_debug_info(dhd, &debugInfo)) < 0)
+		goto exit;
+
+	/* Get the base and size to dump */
+	start = debugInfo.ram_base;
+	size = debugInfo.ram_size;
+
+	/* Get the arm trap area */
+	bzero(&prstatus, sizeof(prstatus_t));
+	if (debugInfo.trap_ptr != 0) {
+		int i;
+		trap_t armtrap;
+		uint32 *reg;
+
+		params[0] = debugInfo.trap_ptr;
+		params[1] = sizeof(trap_t);
+		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
+		if (ret) {
+			fprintf(stderr, "%s: failed reading %lu membytes from 0x%08lx\n",
+				__FUNCTION__, (long unsigned) params[1], (long unsigned) params[0]);
+			goto exit;
+		}
+
+		memcpy((char *) &armtrap, ptr, sizeof(trap_t));
+
+		/* Populate the prstatus */
+		prstatus.si_signo = armtrap.type;
+		reg = &armtrap.r0;
+		for (i = 0; i < 15; i++, reg++) {
+			prstatus.uregs[i] = *reg;
+		}
+		prstatus.uregs[15] = armtrap.epc;
+	}
+
+	if ((fp = fopen(fname, "wb")) == NULL) {
+		fprintf(stderr, "%s: Could not open %s: %s\n",
+		        __FUNCTION__, fname, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+
+	/* Write the preamble and debug header */
+	fprintf(fp, "Dump starts for version %s FWID 01-%x\n", debugInfo.epivers, debugInfo.fwid);
+	fprintf(fp, "XXXXXXXXXXXXXXXXXXXX");
+	fprintf(fp, "%8.8lX", (long unsigned) sizeof(debugInfo));
+	if (fwrite(&debugInfo, sizeof(unsigned char), sizeof(debugInfo), fp) != sizeof(debugInfo)) {
+		fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
+		ret = -1;
+		fclose(fp);
+		goto exit;
+	}
+
+	/* Write the prstatus */
+	if (fwrite(&prstatus, sizeof(unsigned char), sizeof(prstatus), fp) != sizeof(prstatus)) {
+		fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
+		ret = -1;
+		fclose(fp);
+		goto exit;
+	}
+
+	/* Write the ram size as another sanity check */
+	fprintf(fp, "%8.8X", size);
+
+	/* read memory and write to file */
+	while (size) {
+		int len;
+		len = MIN(MEMBLOCK, size);
+
+		params[0] = start;
+		params[1] = len;
+		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
+		if (ret) {
+			fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
+			        __FUNCTION__, len, start);
+			break;
+		}
+
+		if (fwrite(ptr, sizeof(char), len, fp) != (uint) len) {
+			fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
+			ret = -1;
+			break;
+		}
+
+		start += len;
+		size -= len;
+	}
+
+	fclose(fp);
+exit:
+	return ret;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+dhd_consoledump(void *dhd, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	return (-1);
+#else
+	int ret;
+
+	hndrte_debug_t debugInfo;
+
+	miniopt_t opts;
+	int opt_err;
+
+	int params[2];
+	char *ptr;
+
+	unsigned int start;
+	unsigned int size;
+	int len;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	/* Parse command-line options */
+	miniopt_init(&opts, "consoledump", "", TRUE);
+
+	argv++;
+	while ((opt_err = miniopt(&opts, argv)) != -1) {
+		if (opt_err == 1) {
+			fprintf(stderr, "dump options error\n");
+			ret = -1;
+			goto exit;
+		}
+		argv += opts.consumed;
+
+		if (!opts.opt) {
+			fprintf(stderr, "unrecognized option %s\n", opts.valstr);
+			ret = -1;
+			goto exit;
+		} else {
+			fprintf(stderr, "unrecognized option %c\n", opts.opt);
+			ret = -1;
+			goto exit;
+		}
+	}
+
+	if ((ret = dhd_get_debug_info(dhd, &debugInfo)) < 0)
+		goto exit;
+
+	if (debugInfo.console <= debugInfo.ram_base) {
+		fprintf(stderr, "%s: console not found\n", __FUNCTION__);
+		ret = -1;
+		goto exit;
+	}
+
+	/* Get the debug console area */
+	params[0] = debugInfo.console;
+	params[1] = sizeof(hndrte_cons_t);
+	ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
+	if (ret) {
+		fprintf(stderr, "%s: failed reading %lu membytes from 0x%08lx\n",
+			__FUNCTION__, (long unsigned) params[1], (long unsigned) params[0]);
+		goto exit;
+	}
+
+	if (ptr == NULL) {
+		fprintf(stderr, "%s: console not initialised\n", __FUNCTION__);
+		ret = -1;
+		goto exit;
+	}
+
+	start = (unsigned int)((hndrte_cons_t *)ptr)->log.buf;
+	size = ((hndrte_cons_t *)ptr)->log.buf_size;
+
+	if (start <= debugInfo.ram_base) {
+		fprintf(stderr, "%s: console buffer not initialised\n", __FUNCTION__);
+		ret = -1;
+		goto exit;
+	}
+
+	/* read memory and write to file */
+	while (size > 0) {
+		len = MIN(MEMBLOCK, size);
+
+		params[0] = start;
+		params[1] = len;
+		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
+		if (ret) {
+			fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
+			        __FUNCTION__, len, start);
+			break;
+		}
+
+		printf("%s", ptr);
+
+		start += len;
+		size -= len;
+	}
+
+exit:
+	return ret;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+dhd_logstamp(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char *endptr = NULL;
+	uint argc;
+	int valn[2] = {0, 0};
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--; argv++;
+
+	if (argc > 2)
+		return BCME_USAGE_ERROR;
+
+	if (argc) {
+		valn[0] = strtol(argv[0], &endptr, 0);
+		if (*endptr != '\0') {
+			printf("bad val1: %s\n", argv[0]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if (argc > 1) {
+		valn[1] = strtol(argv[1], &endptr, 0);
+		if (*endptr != '\0') {
+			printf("bad val2: %s\n", argv[1]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	ret = dhd_var_setbuf(dhd, cmd->name, valn, argc * sizeof(int));
+
+	return (ret);
+}
+
+static int
+dhd_sd_reg(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret;
+	sdreg_t sdreg;
+	char *endptr = NULL;
+	uint argc;
+	void *ptr = NULL;
+
+	bzero(&sdreg, sizeof(sdreg));
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	/* hostreg: offset [value]; devreg: func offset [value] */
+	if (!strcmp(cmd->name, "sd_hostreg")) {
+		argv++;
+		if (argc < 1) {
+			printf("required args: offset [value]\n");
+			return BCME_USAGE_ERROR;
+		}
+
+	} else if (!strcmp(cmd->name, "sd_devreg")) {
+		argv++;
+		if (argc < 2) {
+			printf("required args: func offset [value]\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		sdreg.func = strtoul(*argv++, &endptr, 0);
+		if (*endptr != '\0') {
+			printf("Invalid function number\n");
+			return BCME_USAGE_ERROR;
+		}
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	sdreg.offset = strtoul(*argv++, &endptr, 0);
+	if (*endptr != '\0') {
+		printf("Invalid offset value\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* third arg: value */
+	if (*argv) {
+		sdreg.value = strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			printf("Invalid value\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* no third arg means get, otherwise set */
+	if (!*argv) {
+		if ((ret = dhd_var_getbuf(dhd, cmd->name, &sdreg, sizeof(sdreg), &ptr)) >= 0)
+			printf("0x%x\n", *(int *)ptr);
+	} else {
+		ret = dhd_var_setbuf(dhd, cmd->name, &sdreg, sizeof(sdreg));
+	}
+
+	return (ret);
+}
+
+static dbg_msg_t dhd_msgs[] = {
+	{DHD_ERROR_VAL,	"error"},
+	{DHD_ERROR_VAL, "err"},
+	{DHD_TRACE_VAL, "trace"},
+	{DHD_INFO_VAL,	"inform"},
+	{DHD_INFO_VAL,	"info"},
+	{DHD_INFO_VAL,	"inf"},
+	{DHD_DATA_VAL,	"data"},
+	{DHD_CTL_VAL,	"ctl"},
+	{DHD_TIMER_VAL,	"timer"},
+	{DHD_HDRS_VAL,	"hdrs"},
+	{DHD_BYTES_VAL,	"bytes"},
+	{DHD_INTR_VAL,	"intr"},
+	{DHD_LOG_VAL,	"log"},
+	{DHD_GLOM_VAL,	"glom"},
+	{DHD_EVENT_VAL,	"event"},
+	{DHD_BTA_VAL,	"bta"},
+	{DHD_ISCAN_VAL,	"iscan"},
+	{DHD_ARPOE_VAL,	"arpoe"},
+	{DHD_REORDER_VAL, "reorder"},
+	{0,		NULL}
+};
+
+static int
+dhd_msglevel(void *dhd, cmd_t *cmd, char **argv)
+{
+	return dhd_do_msglevel(dhd, cmd, argv, dhd_msgs);
+}
+
+static int
+dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg)
+{
+	int ret, i;
+	uint val, last_val = 0, msglevel = 0, msglevel_add = 0, msglevel_del = 0;
+	char *endptr = NULL;
+
+	if ((ret = dhd_iovar_getint(dhd, cmd->name, (int*)&msglevel)) < 0)
+		return (ret);
+
+	if (!*++argv) {
+		printf("0x%x ", msglevel);
+		for (i = 0; (val = dbg_msg[i].value); i++) {
+			if ((msglevel & val) && (val != last_val))
+				printf(" %s", dbg_msg[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			msglevel_del = ~0;	/* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		/* not a plain integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = dbg_msg[i].value); i++)
+				if (stricmp(dbg_msg[i].string, s) == 0)
+					break;
+			if (!val)
+				goto usage;
+		}
+		if (**argv == '-')
+			msglevel_del |= val;
+		else
+			msglevel_add |= val;
+		++argv;
+	}
+
+	msglevel &= ~msglevel_del;
+	msglevel |= msglevel_add;
+
+	return (dhd_iovar_setint(dhd, cmd->name, msglevel));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+
+	for (i = 0; (val = dbg_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string);
+		else
+			fprintf(stderr, ", %s", dbg_msg[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+
+	return 0;
+}
+
+static char *
+ver2str(unsigned int vms, unsigned int vls)
+{
+	static char verstr[100];
+	unsigned int maj, year, month, day, build;
+
+	maj = (vms >> 16) & 0xFFFF;
+	if (maj > 1000) {
+		/* it is probably a date... */
+		year = (vms >> 16) & 0xFFFF;
+		month = vms & 0xFFFF;
+		day = (vls >> 16) & 0xFFFF;
+		build = vls & 0xFFFF;
+		sprintf(verstr, "%d/%d/%d build %d",
+			month, day, year, build);
+	} else {
+		/* it is a tagged release. */
+		sprintf(verstr, "%d.%d RC%d.%d",
+			(vms>>16)&0xFFFF, vms&0xFFFF,
+			(vls>>16)&0xFFFF, vls&0xFFFF);
+	}
+	return verstr;
+}
+
+static int
+dhd_version(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char *ptr;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	/* Display the application version info */
+	printf("%s: %s\n", dhdu_av0,
+		ver2str((EPI_MAJOR_VERSION << 16)| EPI_MINOR_VERSION,
+		(EPI_RC_NUMBER << 16) | EPI_INCREMENTAL_NUMBER));
+
+	if ((ret = dhd_var_getbuf(dhd, cmd->name, NULL, 0, (void**)&ptr)) < 0)
+		return ret;
+
+	/* Display the returned string */
+	printf("%s\n", ptr);
+
+	return 0;
+}
+
+static int
+dhd_var_setint(void *dhd, cmd_t *cmd, char **argv)
+{
+	int32 val;
+	int len;
+	char *varname;
+	char *endptr = NULL;
+	char *p;
+
+	if (cmd->set == -1) {
+		printf("set not defined for %s\n", cmd->name);
+		return BCME_ERROR;
+	}
+
+	if (!*argv) {
+		printf("set: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (!*argv) {
+		printf("set: missing value argument for set of \"%s\"\n", varname);
+		return BCME_USAGE_ERROR;
+	}
+
+	val = strtol(*argv, &endptr, 0);
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n",
+			*argv, varname);
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, varname);
+	p = buf;
+	while (*p != '\0') {
+		*p = tolower(*p);
+		p++;
+	}
+
+	/* skip the NUL */
+	p++;
+
+	memcpy(p, &val, sizeof(uint));
+	len = (p - buf) +  sizeof(uint);
+
+	return (dhd_set(dhd, DHD_SET_VAR, &buf[0], len));
+}
+
+static int
+dhd_var_get(void *dhd, cmd_t *cmd, char **argv)
+{
+	char *varname;
+	char *p;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("get: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (*argv) {
+		printf("get: error, extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, varname);
+	p = buf;
+	while (*p != '\0') {
+		*p = tolower(*p);
+		p++;
+	}
+	return (dhd_get(dhd, DHD_GET_VAR, &buf[0], DHD_IOCTL_MAXLEN));
+}
+
+static int
+dhd_var_getint(void *dhd, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 val;
+	if (cmd->get == -1) {
+		printf("get not defined for %s\n", cmd->name);
+		return BCME_ERROR;
+	}
+
+	if ((err = dhd_var_get(dhd, cmd, argv)))
+		return (err);
+
+	val = *(int32*)buf;
+
+	if (val < 10)
+		printf("%d\n", val);
+	else
+		printf("%d (0x%x)\n", val, val);
+
+	return (0);
+}
+
+static int
+dhd_var_getandprintstr(void *dhd, cmd_t *cmd, char **argv)
+{
+	int err;
+
+	if ((err = dhd_var_get(dhd, cmd, argv)))
+		return (err);
+
+	printf("%s\n", buf);
+	return (0);
+}
+
+
+void
+dhd_printlasterror(void *dhd)
+{
+	char *cmd[2] = {"bcmerrorstr"};
+
+	if (dhd_var_get(dhd, NULL, cmd) != 0) {
+		fprintf(stderr, "%s: \nError getting the last error\n", dhdu_av0);
+	} else {
+		fprintf(stderr, "%s: %s\n", dhdu_av0, buf);
+	}
+}
+
+static int
+dhd_varint(void *dhd, cmd_t *cmd, char *argv[])
+{
+	if (argv[1])
+		return (dhd_var_setint(dhd, cmd, argv));
+	else
+		return (dhd_var_getint(dhd, cmd, argv));
+}
+
+static int
+dhd_var_getbuf(void *dhd, char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	memset(buf, 0, DHD_IOCTL_MAXLEN);
+	strcpy(buf, iovar);
+
+	/* include the NUL */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return dhd_get(dhd, DHD_GET_VAR, &buf[0], DHD_IOCTL_MAXLEN);
+}
+
+static int
+dhd_var_setbuf(void *dhd, char *iovar, void *param, int param_len)
+{
+	int len;
+
+	memset(buf, 0, DHD_IOCTL_MAXLEN);
+	strcpy(buf, iovar);
+
+	/* include the NUL */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	len += param_len;
+
+	return dhd_set(dhd, DHD_SET_VAR, &buf[0], len);
+}
+
+static int
+dhd_var_void(void *dhd, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(argv);
+
+	if (cmd->set < 0)
+		return BCME_ERROR;
+
+	return dhd_var_setbuf(dhd, cmd->name, NULL, 0);
+}
+
+/*
+ * format an iovar buffer
+ */
+static uint
+dhd_iovar_mkbuf(char *name, char *data, uint datalen, char *buf, uint buflen, int *perr)
+{
+	uint len;
+
+	len = strlen(name) + 1;
+
+	/* check for overflow */
+	if ((len + datalen) > buflen) {
+		*perr = BCME_BUFTOOSHORT;
+		return 0;
+	}
+
+	strcpy(buf, name);
+
+	/* append data onto the end of the name string */
+	if (datalen > 0)
+		memcpy(&buf[len], data, datalen);
+
+	len += datalen;
+
+	*perr = 0;
+	return len;
+}
+
+static int
+dhd_iovar_getint(void *dhd, char *name, int *var)
+{
+	char ibuf[DHD_IOCTL_SMLEN];
+	int error;
+
+	dhd_iovar_mkbuf(name, NULL, 0, ibuf, sizeof(ibuf), &error);
+	if (error)
+		return error;
+
+	if ((error = dhd_get(dhd, DHD_GET_VAR, &ibuf, sizeof(ibuf))) < 0)
+		return error;
+
+	memcpy(var, ibuf, sizeof(int));
+
+	return 0;
+}
+
+static int
+dhd_iovar_setint(void *dhd, char *name, int var)
+{
+	int len;
+	char ibuf[DHD_IOCTL_SMLEN];
+	int error;
+
+	len = dhd_iovar_mkbuf(name, (char *)&var, sizeof(var), ibuf, sizeof(ibuf), &error);
+	if (error)
+		return error;
+
+	if ((error = dhd_set(dhd, DHD_SET_VAR, &ibuf, len)) < 0)
+		return error;
+
+	return 0;
+}
+
+static int
+dhd_varstr(void *dhd, cmd_t *cmd, char **argv)
+{
+	int error;
+	char *str;
+
+	if (!*++argv) {
+		void *ptr;
+
+		if ((error = dhd_var_getbuf(dhd, cmd->name, NULL, 0, &ptr)) < 0)
+			return (error);
+
+		str = (char *)ptr;
+		printf("%s\n", str);
+		return (0);
+	} else {
+		str = *argv;
+		/* iovar buffer length includes NUL */
+		return dhd_var_setbuf(dhd, cmd->name, str, strlen(str) + 1);
+	}
+}
+
+
+static int
+dhd_hostreorder_flows(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret, count, i = 0;
+	void *ptr;
+	uint8 *flow_id;
+
+
+	if ((ret = dhd_var_getbuf(dhd, cmd->name, NULL, 0, &ptr)) < 0) {
+		printf("error getting reorder flows from the host\n");
+		return ret;
+	}
+	flow_id = (uint8 *)ptr;
+	count = *flow_id;
+	if (!count)
+		printf("there are no active flows\n");
+	else {
+		printf("flows(%d): \t", count);
+		while (i++ < count)
+			printf("%d  ", *flow_id++);
+		printf("\n");
+	}
+	return 0;
+}
+
+#ifdef BCMSPI
+static int
+dhd_spierrstats(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	struct spierrstats_t spierrstats, *p;
+	uint argc;
+	void *ptr = NULL;
+
+	bzero(&spierrstats, sizeof(spierrstats));
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (strcmp(cmd->name, "spi_errstats")) {
+		printf("Supported only for SPI. Required cmd name missing\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Check 3rd argument */
+	argv++;
+
+	/* no third arg means get, otherwise set */
+	if (!*argv) {
+		if ((ret = dhd_var_getbuf(dhd, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		p = (struct spierrstats_t *)ptr;
+
+		printf("Last %d device-status-bits\n", NUM_PREV_TRANSACTIONS);
+
+		for (i = 0; i < NUM_PREV_TRANSACTIONS; i++)
+			printf("dstatus[%d] = 0x%x, spicmd[%d] = 0x%x\n", i, p->dstatus[i],
+			        i, p->spicmd[i]);
+
+		printf("The requested data was not available  = %d\n",
+			p->dna);
+		printf("FIFO underflow happened due to F2 rd command = %d\n",
+			p->rdunderflow);
+		printf("FIFO overflow happened due to F1/F2 wr command = %d\n",
+			p->wroverflow);
+		printf("F2 interrupt (OR of all F2 related intr status bits) = %d\n",
+			p->f2interrupt);
+		printf("F2 FIFO is not ready to receive data = %d\n",
+			p->f2rxnotready);
+		printf("Error in command or host data, detected by checksum = %d\n",
+			p->hostcmddataerr);
+		printf("Packet is available in F2 TX FIFO = %d\n",
+			p->f2pktavailable);
+
+	} else {
+		ret = dhd_var_setbuf(dhd, cmd->name, &spierrstats, sizeof(spierrstats));
+	}
+
+	return (ret);
+}
+#endif /* BCMSPI */
+
+#ifdef WLBTAMP
+
+#define MATCH_OP(op, opstr)	(strlen(op) == strlen(opstr) && strncmp(op, opstr, strlen(op)) == 0)
+
+static int
+wl_HCI_cmd(void *wl, cmd_t *cmd, char **argv)
+{
+	union {
+		char buf[HCI_CMD_PREAMBLE_SIZE + HCI_CMD_DATA_SIZE];
+		uint32 alignme;
+	} cbuf;
+	amp_hci_cmd_t *cpkt = (amp_hci_cmd_t *)&cbuf.buf[0];
+
+	char *op;
+	uint8 plen;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	/* recognize and encode operations */
+	op = *argv++;
+	if (MATCH_OP(op, "Read_Link_Quality")) {
+		cpkt->opcode = HCI_Read_Link_Quality;
+	} else if (MATCH_OP(op, "Read_Local_AMP_Info")) {
+		cpkt->opcode = HCI_Read_Local_AMP_Info;
+	} else if (MATCH_OP(op, "Read_Local_AMP_ASSOC")) {
+		cpkt->opcode = HCI_Read_Local_AMP_ASSOC;
+	} else if (MATCH_OP(op, "Write_Remote_AMP_ASSOC")) {
+		cpkt->opcode = HCI_Write_Remote_AMP_ASSOC;
+	} else if (MATCH_OP(op, "Create_Physical_Link")) {
+		cpkt->opcode = HCI_Create_Physical_Link;
+	} else if (MATCH_OP(op, "Accept_Physical_Link_Request")) {
+		cpkt->opcode = HCI_Accept_Physical_Link_Request;
+	} else if (MATCH_OP(op, "Disconnect_Physical_Link")) {
+		cpkt->opcode = HCI_Disconnect_Physical_Link;
+	} else if (MATCH_OP(op, "Create_Logical_Link")) {
+		cpkt->opcode = HCI_Create_Logical_Link;
+	} else if (MATCH_OP(op, "Accept_Logical_Link")) {
+		cpkt->opcode = HCI_Accept_Logical_Link;
+	} else if (MATCH_OP(op, "Disconnect_Logical_Link")) {
+		cpkt->opcode = HCI_Disconnect_Logical_Link;
+	} else if (MATCH_OP(op, "Logical_Link_Cancel")) {
+		cpkt->opcode = HCI_Logical_Link_Cancel;
+	} else if (MATCH_OP(op, "Short_Range_Mode")) {
+		cpkt->opcode = HCI_Short_Range_Mode;
+	} else if (MATCH_OP(op, "Read_Connection_Accept_Timeout")) {
+		cpkt->opcode = HCI_Read_Connection_Accept_Timeout;
+	} else if (MATCH_OP(op, "Write_Connection_Accept_Timeout")) {
+		cpkt->opcode = HCI_Write_Connection_Accept_Timeout;
+	} else if (MATCH_OP(op, "Read_Link_Supervision_Timeout")) {
+		cpkt->opcode = HCI_Read_Link_Supervision_Timeout;
+	} else if (MATCH_OP(op, "Write_Link_Supervision_Timeout")) {
+		cpkt->opcode = HCI_Write_Link_Supervision_Timeout;
+	} else if (MATCH_OP(op, "Reset")) {
+		cpkt->opcode = HCI_Reset;
+	} else if (MATCH_OP(op, "Enhanced_Flush")) {
+		cpkt->opcode = HCI_Enhanced_Flush;
+	} else if (MATCH_OP(op, "Read_Best_Effort_Flush_Timeout")) {
+		cpkt->opcode = HCI_Read_Best_Effort_Flush_Timeout;
+	} else if (MATCH_OP(op, "Write_Best_Effort_Flush_Timeout")) {
+		cpkt->opcode = HCI_Write_Best_Effort_Flush_Timeout;
+	} else if (MATCH_OP(op, "Read_Logical_Link_Accept_Timeout")) {
+		cpkt->opcode = HCI_Read_Logical_Link_Accept_Timeout;
+	} else if (MATCH_OP(op, "Write_Logical_Link_Accept_Timeout")) {
+		cpkt->opcode = HCI_Write_Logical_Link_Accept_Timeout;
+	} else if (MATCH_OP(op, "Read_Buffer_Size")) {
+		cpkt->opcode = HCI_Read_Buffer_Size;
+	} else if (MATCH_OP(op, "Read_Data_Block_Size")) {
+		cpkt->opcode = HCI_Read_Data_Block_Size;
+	} else if (MATCH_OP(op, "Set_Event_Mask_Page_2")) {
+		cpkt->opcode = HCI_Set_Event_Mask_Page_2;
+	} else if (MATCH_OP(op, "Flow_Spec_Modify")) {
+		cpkt->opcode = HCI_Flow_Spec_Modify;
+	} else if (MATCH_OP(op, "Read_Local_Version_Info")) {
+		cpkt->opcode = HCI_Read_Local_Version_Info;
+	} else if (MATCH_OP(op, "Read_Local_Supported_Commands")) {
+		cpkt->opcode = HCI_Read_Local_Supported_Commands;
+	} else if (MATCH_OP(op, "Read_Failed_Contact_Counter")) {
+		cpkt->opcode = HCI_Read_Failed_Contact_Counter;
+	} else if (MATCH_OP(op, "Reset_Failed_Contact_Counter")) {
+		cpkt->opcode = HCI_Reset_Failed_Contact_Counter;
+	} else {
+		printf("unsupported HCI command: %s\n", op);
+		return (-1);
+	}
+
+	plen = 0;
+	while (*argv && (plen < HCI_CMD_DATA_SIZE)) {
+		cpkt->parms[plen++] = (uint8)strtol(*argv++, NULL, 0);
+	}
+	cpkt->plen = plen;
+
+	return dhd_var_setbuf(wl, cmd->name, cpkt, HCI_CMD_PREAMBLE_SIZE + plen);
+}
+
+typedef union {
+	uint8 buf[HCI_ACL_DATA_PREAMBLE_SIZE + 2048];
+	uint32 alignme;
+} g_hci_dbuf_t;
+
+static int
+wl_HCI_ACL_data(void *wl, cmd_t *cmd, char **argv)
+{
+	/* Align struct. Also declare static so that large array isn't allocated
+	 * from the stack.
+	 */
+	static g_hci_dbuf_t g_hci_dbuf;
+
+	amp_hci_ACL_data_t *dpkt = (amp_hci_ACL_data_t *)&g_hci_dbuf.buf[0];
+	uint16 dlen;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	/* get logical link handle */
+	dpkt->handle = (HCI_ACL_DATA_BC_FLAGS | HCI_ACL_DATA_PB_FLAGS);
+	dpkt->handle |= (uint16)strtol(*argv++, NULL, 0);
+
+	/* get data */
+	dlen = 0;
+	while (*argv && (dlen < 2048)) {
+		dpkt->data[dlen++] = (uint8)strtol(*argv++, NULL, 0);
+	}
+	dpkt->dlen = dlen;
+
+	return dhd_var_setbuf(wl, cmd->name, dpkt, HCI_ACL_DATA_PREAMBLE_SIZE + dlen);
+}
+#endif /* WLBTAMP */
+
+/* These two utility functions are used by dhdu_linux.c
+ * The code is taken from wlu.c.
+ */
+int
+dhd_atoip(const char *a, struct ipv4_addr *n)
+{
+	char *c;
+	int i = 0;
+
+	for (;;) {
+	        n->addr[i++] = (uint8)strtoul(a, &c, 0);
+	        if (*c++ != '.' || i == IPV4_ADDR_LEN)
+	                break;
+	        a = c;
+	}
+	return (i == IPV4_ADDR_LEN);
+}
+
+int
+dhd_ether_atoe(const char *a, struct ether_addr *n)
+{
+	char *c;
+	int i = 0;
+
+	memset(n, 0, ETHER_ADDR_LEN);
+	for (;;) {
+	        n->octet[i++] = (uint8)strtoul(a, &c, 16);
+	        if (!*c++ || i == ETHER_ADDR_LEN)
+	                break;
+	        a = c;
+	}
+	return (i == ETHER_ADDR_LEN);
+}
diff --git a/src/dhd/exe/dhdu.h b/src/dhd/exe/dhdu.h
new file mode 100644
index 0000000..6718c10
--- /dev/null
+++ b/src/dhd/exe/dhdu.h
@@ -0,0 +1,47 @@
+/*
+ * Definitions for DHD command-line utility
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: dhdu.h 379386 2013-01-17 07:20:55Z $
+ */
+
+#ifndef _dhdu_h_
+#define _dhdu_h_
+
+#include "dhdu_cmd.h"
+
+extern char *dhdu_av0;
+
+/* parse common option */
+extern int dhd_option(char ***pargv, char **pifname, int *phelp);
+extern void dhd_cmd_init(void);
+
+/* print usage */
+extern void dhd_cmd_usage(cmd_t *cmd);
+extern void dhd_usage(cmd_t *port_cmds);
+extern void dhd_cmds_usage(cmd_t *port_cmds);
+
+/* print helpers */
+extern void dhd_printlasterror(void *dhd);
+extern void dhd_printint(int val);
+
+/* check driver version */
+extern int dhd_check(void *dhd);
+
+/* utility functions */
+struct ipv4_addr;
+int dhd_ether_atoe(const char *a, struct ether_addr *n);
+int dhd_atoip(const char *a, struct ipv4_addr *n);
+
+/* integer output format */
+#define INT_FMT_DEC	0	/* signed integer */
+#define INT_FMT_UINT	1	/* unsigned integer */
+#define INT_FMT_HEX	2	/* hexdecimal */
+
+/* command line argument usage */
+#define CMD_ERR		-1	/* Error for command */
+#define CMD_OPT		0	/* a command line option */
+#define CMD_DHD		1	/* the start of a dhd command */
+
+#endif /* _dhdu_h_ */
diff --git a/src/dhd/exe/dhdu_cmd.h b/src/dhd/exe/dhdu_cmd.h
new file mode 100644
index 0000000..e7f9a3e
--- /dev/null
+++ b/src/dhd/exe/dhdu_cmd.h
@@ -0,0 +1,37 @@
+/*
+ * Command structure for dhd command line utility, copied from wl utility
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: dhdu_cmd.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _dhdu_cmd_h_
+#define _dhdu_cmd_h_
+
+typedef struct cmd cmd_t;
+typedef int (cmd_func_t)(void *dhd, cmd_t *cmd, char **argv);
+
+/* generic command line argument handler */
+struct cmd {
+	char *name;
+	cmd_func_t *func;
+	int get;
+	int set;
+	char *help;
+};
+
+/* list of command line arguments */
+extern cmd_t dhd_cmds[];
+extern cmd_t dhd_varcmd;
+
+/* Special set cmds to do download via dev node interface if present */
+#define	DHD_DLDN_ST		0x400
+#define	DHD_DLDN_WRITE		(DHD_DLDN_ST + 1)
+#define	DHD_DLDN_END		(DHD_DLDN_ST + 2)
+
+/* per-port ioctl handlers */
+extern int dhd_get(void *dhd, int cmd, void *buf, int len);
+extern int dhd_set(void *dhd, int cmd, void *buf, int len);
+
+#endif /* _dhdu_cmd_h_ */
diff --git a/src/dhd/exe/dhdu_common.h b/src/dhd/exe/dhdu_common.h
new file mode 100644
index 0000000..8464b3c
--- /dev/null
+++ b/src/dhd/exe/dhdu_common.h
@@ -0,0 +1,83 @@
+/*
+ * Linux port of dhd command line utility, hacked from wl utility.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: dhdu_common.h 379386 2013-01-17 07:20:55Z $
+ */
+
+/* Common header file for dhdu_linux.c and dhdu_ndis.c */
+
+#ifndef _dhdu_common_h
+#define _dhdu_common_h
+
+#if !defined(RWL_WIFI) && !defined(RWL_DONGLE) && !defined(RWL_SOCKET) && \
+	!defined(RWL_SERIAL)
+
+#define NO_REMOTE       0
+#define REMOTE_SERIAL 	1
+#define REMOTE_SOCKET 	2
+#define REMOTE_WIFI     3
+#define REMOTE_DONGLE   4
+
+/* For cross OS support */
+#define LINUX_OS  	1
+#define WIN32_OS  	2
+#define MAC_OSX		3
+#define BACKLOG 	4
+#define WINVISTA_OS	5
+#define INDONGLE	6
+
+#define RWL_WIFI_ACTION_CMD   		"wifiaction"
+#define RWL_WIFI_GET_ACTION_CMD         "rwlwifivsaction"
+#define RWL_DONGLE_SET_CMD		"dongleset"
+
+#define SUCCESS 	1
+#define FAIL   		-1
+#define NO_PACKET       -2
+
+/* Added for debug utility support */
+#define ERR		stderr
+#define OUTPUT		stdout
+#define DEBUG_ERR	0x0001
+#define DEBUG_INFO	0x0002
+#define DEBUG_DBG	0x0004
+
+#define DPRINT_ERR	if (defined_debug & DEBUG_ERR) \
+			    fprintf
+#define DPRINT_INFO	if (defined_debug & DEBUG_INFO) \
+			    fprintf
+#define DPRINT_DBG	if (defined_debug & DEBUG_DBG) \
+			    fprintf
+
+extern int wl_get(void *wl, int cmd, void *buf, int len);
+extern int wl_set(void *wl, int cmd, void *buf, int len);
+#endif /* !RWL_WIFI & !RWL_DONGLE & !RWL_SOCKET & !RWL_SERIAL */
+
+/* DHD utility function declarations */
+extern int dhd_check(void *dhd);
+extern int dhd_atoip(const char *a, struct ipv4_addr *n);
+extern int dhd_option(char ***pargv, char **pifname, int *phelp);
+void dhd_usage(cmd_t *port_cmds);
+
+/* Remote DHD declarations */
+int remote_type = NO_REMOTE;
+extern char *g_rwl_buf_mac;
+extern char* g_rwl_device_name_serial;
+unsigned short g_rwl_servport;
+char *g_rwl_servIP = NULL;
+unsigned short defined_debug = DEBUG_ERR | DEBUG_INFO;
+
+
+static int process_args(struct ifreq* ifr, char **argv);
+
+#define dtoh32(i) i
+#define dtoh16(i) i
+
+#endif  /* _dhdu_common_h_ */
diff --git a/src/dhd/exe/dhdu_linux.c b/src/dhd/exe/dhdu_linux.c
new file mode 100644
index 0000000..d64c609
--- /dev/null
+++ b/src/dhd/exe/dhdu_linux.c
@@ -0,0 +1,721 @@
+/*
+ * Linux port of dhd command line utility, hacked from wl utility.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: dhdu_linux.c 454520 2014-02-11 01:37:22Z $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <proto/ethernet.h>
+#include <proto/bcmip.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#ifndef TARGETENV_android
+#include <error.h>
+typedef u_int64_t u64;
+typedef u_int32_t u32;
+typedef u_int16_t u16;
+typedef u_int8_t u8;
+#endif /* TARGETENV_android */
+#include <linux/sockios.h>
+#include <linux/types.h>
+#include <linux/ethtool.h>
+
+#include <typedefs.h>
+#include <signal.h>
+#include <dhdioctl.h>
+#include <wlioctl.h>
+#include <bcmcdc.h>
+#include <bcmutils.h>
+
+#if defined(RWL_WIFI) || defined(RWL_DONGLE) || defined(RWL_SOCKET) \
+	||defined(RWL_SERIAL)
+#define RWL_ENABLE
+#endif /* RWL_WIFI | RWL_DONGLE | RWL_SOCKET | RWL_SERIAL */
+
+#include "dhdu.h"
+#ifdef RWL_ENABLE
+#include "wlu_remote.h"
+#include "wlu_client_shared.h"
+#include "wlu_pipe.h"
+#endif /* RWL_ENABLE */
+#include <netdb.h>
+#include <netinet/in.h>
+#include <dhdioctl.h>
+#include "dhdu_common.h"
+#include "dhdu_nl80211.h"
+
+char *av0;
+static int rwl_os_type = LINUX_OS;
+/* Search the dhd_cmds table for a matching command name.
+ * Return the matching command or NULL if no match found.
+ */
+static cmd_t *
+dhd_find_cmd(char* name)
+{
+	cmd_t *cmd = NULL;
+	/* search the dhd_cmds for a matching name */
+	for (cmd = dhd_cmds; cmd->name && strcmp(cmd->name, name); cmd++);
+	if (cmd->name == NULL)
+		cmd = NULL;
+	return cmd;
+}
+
+#ifdef NL80211
+static void
+syserr(const char *s)
+{
+}
+
+static int __dhd_drvio_nltestmode(void *dhd, dhd_ioctl_t *ioc)
+{
+	struct dhd_netlink_info dhd_nli;
+	struct ifreq *ifr = (struct ifreq *)dhd;
+	int ret = 0;
+
+	dhd_nli.ifidx = if_nametoindex(ifr->ifr_name);
+	if (!dhd_nli.ifidx) {
+		fprintf(stderr, "invalid device %s\n", ifr->ifr_name);
+		return BCME_IOCTL_ERROR;
+	}
+
+	if (dhd_nl_sock_connect(&dhd_nli) < 0) {
+		fprintf(stderr, "%s: ", av0);
+		perror("socket");
+		exit(errno);
+	}
+
+	ret = dhd_nl_do_testmode(&dhd_nli, ioc);
+	dhd_nl_sock_disconnect(&dhd_nli);
+	return ret;
+}
+#else
+static void
+syserr(const char *s)
+{
+	fprintf(stderr, "%s: ", av0);
+	perror(s);
+	exit(errno);
+}
+
+static int __dhd_drvio_nltestmode(void *dhd, dhd_ioctl_t *ioc)
+{
+	return BCME_IOCTL_ERROR;
+}
+#endif /* NL80211 */
+static int __dhd_drvio_ioctl(void *dhd, dhd_ioctl_t *ioc)
+{
+	struct ifreq *ifr = (struct ifreq *)dhd;
+	int s;
+	int ret = 0;
+
+	/* pass ioctl data */
+	ifr->ifr_data = (caddr_t)ioc;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	ret = ioctl(s, SIOCDEVPRIVATE, ifr);
+	if (ret < 0 && errno != EAGAIN)
+		syserr(__FUNCTION__);
+
+	/* cleanup */
+	close(s);
+	return ret;
+}
+
+static int (*g_dhd_driver_io)(void *dhd, dhd_ioctl_t *ioc) = __dhd_drvio_ioctl;
+/* This function is called by ioctl_setinformation_fe or ioctl_queryinformation_fe
+ * for executing  remote commands or local commands
+ */
+static int
+dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set)
+{
+	dhd_ioctl_t ioc;
+	int ret = 0;
+
+	/* By default try to execute wl commands */
+	int driver_magic = WLC_IOCTL_MAGIC;
+	int get_magic = WLC_GET_MAGIC;
+
+	/* For local dhd commands execute dhd. For wifi transport we still
+	 * execute wl commands.
+	 */
+	if (remote_type == NO_REMOTE && strncmp (buf, RWL_WIFI_ACTION_CMD,
+		strlen(RWL_WIFI_ACTION_CMD)) && strncmp(buf, RWL_WIFI_GET_ACTION_CMD,
+		strlen(RWL_WIFI_GET_ACTION_CMD))) {
+		driver_magic = DHD_IOCTL_MAGIC;
+		get_magic = DHD_GET_MAGIC;
+	}
+
+	/* do it */
+	ioc.cmd = cmd;
+	ioc.buf = buf;
+	ioc.len = len;
+	ioc.set = set;
+	ioc.driver = driver_magic;
+
+	ret = g_dhd_driver_io(dhd, &ioc);
+	if (ret < 0) {
+		if (g_dhd_driver_io == __dhd_drvio_ioctl) {
+			/* try using nl80211 testmode interface */
+			ret = __dhd_drvio_nltestmode(dhd, &ioc);
+			if (ret >= 0) {
+				g_dhd_driver_io = __dhd_drvio_nltestmode;
+				goto exit;
+			}
+		}
+		if (cmd != get_magic)
+			ret = BCME_IOCTL_ERROR;
+	}
+
+exit:
+	return ret;
+}
+
+/* This function is called in wlu_pipe.c remote_wifi_ser_init() to execute
+ * the initial set of wl commands for wifi transport (e.g slow_timer, fast_timer etc)
+ */
+int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set)
+{
+	return dhd_ioctl(wl, cmd, buf, len, set); /* Call actual wl_ioctl here: Shubhro */
+}
+
+/* Search if dhd adapter or wl adapter is present
+ * This is called by dhd_find to check if it supports wl or dhd
+ * The reason for checking wl adapter is that we can still send remote dhd commands over
+ * wifi transport.
+ */
+static int
+dhd_get_dev_type(char *name, void *buf, char *type)
+{
+	int s;
+	int ret;
+	struct ifreq ifr;
+	struct ethtool_drvinfo info;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* get device type */
+	memset(&info, 0, sizeof(info));
+	info.cmd = ETHTOOL_GDRVINFO;
+	strcpy(info.driver, "?");
+	strcat(info.driver, type);
+	ifr.ifr_data = (caddr_t)&info;
+	strncpy(ifr.ifr_name, name, IFNAMSIZ);
+	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
+
+		if (errno != EAGAIN)
+			syserr(__FUNCTION__);
+
+		*(char *)buf = '\0';
+	}
+	else
+		strcpy(buf, info.driver);
+
+	close(s);
+	return ret;
+}
+
+/* dhd_get/dhd_set is called by several functions in dhdu.c. This used to call dhd_ioctl
+ * directly. However now we need to execute the dhd commands remotely.
+ * So we make use of wl pipes to execute this.
+ * wl_get or wl_set functions also check if it is a local command hence they in turn
+ * call dhd_ioctl if required. Name wl_get/wl_set is retained because these functions are
+ * also called by wlu_pipe.c wlu_client_shared.c
+ */
+int
+dhd_get(void *dhd, int cmd, void *buf, int len)
+{
+	return wl_get(dhd, cmd, buf, len);
+}
+
+/*
+ * To use /dev/node interface:
+ *   1.  mknod /dev/hnd0 c 248 0
+ *   2.  chmod 777 /dev/hnd0
+ */
+#define NODE "/dev/hnd0"
+
+int
+dhd_set(void *dhd, int cmd, void *buf, int len)
+{
+	static int dnode = -1;
+
+	switch (cmd) {
+	case DHD_DLDN_ST:
+		if (dnode == -1)
+			dnode = open(NODE, O_RDWR);
+		else
+			fprintf(stderr, "devnode already opened!\n");
+
+		return dnode;
+		break;
+	case DHD_DLDN_WRITE:
+		if (dnode > 0)
+			return write(dnode, buf, len);
+		break;
+	case DHD_DLDN_END:
+		if (dnode > 0)
+			return close(dnode);
+		break;
+	default:
+		return wl_set(dhd, cmd, buf, len);
+
+	}
+
+	return -1;
+}
+
+/* Verify the wl adapter found.
+ * This is called by dhd_find to check if it supports wl
+ * The reason for checking wl adapter is that we can still send remote dhd commands over
+ * wifi transport. The function is copied from wlu.c.
+ */
+int
+wl_check(void *wl)
+{
+	int ret;
+	int val = 0;
+
+	if (!dhd_check (wl))
+		return 0;
+
+	/*
+	 *  If dhd_check() fails then go for a regular wl driver verification
+	 */
+	if ((ret = wl_get(wl, WLC_GET_MAGIC, &val, sizeof(int))) < 0)
+		return ret;
+	if (val != WLC_IOCTL_MAGIC)
+		return BCME_ERROR;
+	if ((ret = wl_get(wl, WLC_GET_VERSION, &val, sizeof(int))) < 0)
+		return ret;
+	if (val > WLC_IOCTL_VERSION) {
+		fprintf(stderr, "Version mismatch, please upgrade\n");
+		return BCME_ERROR;
+	}
+	return 0;
+}
+/* Search and verify the request type of adapter (wl or dhd)
+ * This is called by main before executing local dhd commands
+ * or sending remote dhd commands over wifi transport
+ */
+void
+dhd_find(struct ifreq *ifr, char *type)
+{
+	char proc_net_dev[] = "/proc/net/dev";
+	FILE *fp = NULL;
+	static char buf[400];
+	char *c, *name;
+	char dev_type[32];
+
+	ifr->ifr_name[0] = '\0';
+	/* eat first two lines */
+	if (!(fp = fopen(proc_net_dev, "r")) ||
+	    !fgets(buf, sizeof(buf), fp) ||
+	    !fgets(buf, sizeof(buf), fp))
+		goto exit;
+
+	while (fgets(buf, sizeof(buf), fp)) {
+		c = buf;
+		while (isspace(*c))
+			c++;
+		if (!(name = strsep(&c, ":")))
+			continue;
+		strncpy(ifr->ifr_name, name, IFNAMSIZ);
+		if (dhd_get_dev_type(name, dev_type, type) >= 0 &&
+			!strncmp(dev_type, type, strlen(dev_type) - 1))
+		{
+			if (!wl_check((void*)ifr))
+				break;
+		}
+		ifr->ifr_name[0] = '\0';
+	}
+
+exit:
+	if (fp)
+		fclose(fp);
+}
+/* This function is called by wl_get to execute either local dhd command
+ * or send a dhd command over wl transport
+ */
+static int
+ioctl_queryinformation_fe(void *wl, int cmd, void* input_buf, int *input_len)
+{
+	if (remote_type == NO_REMOTE) {
+		return dhd_ioctl(wl, cmd, input_buf, *input_len, FALSE);
+	}
+#ifdef RWL_ENABLE
+	else {
+		return rwl_queryinformation_fe(wl, cmd, input_buf,
+			(unsigned long*)input_len, 0, RDHD_GET_IOCTL);
+	}
+#else /* RWL_ENABLE */
+	return BCME_IOCTL_ERROR;
+#endif /* RWL_ENABLE */
+}
+
+/* This function is called by wl_set to execute either local dhd command
+ * or send a dhd command over wl transport
+ */
+static int
+ioctl_setinformation_fe(void *wl, int cmd, void* buf, int *len)
+{
+	if (remote_type == NO_REMOTE) {
+		return dhd_ioctl(wl,  cmd, buf, *len, TRUE);
+	}
+#ifdef RWL_ENABLE
+	else {
+		return rwl_setinformation_fe(wl, cmd, buf, (unsigned long*)len, 0, RDHD_SET_IOCTL);
+
+	}
+#else /* RWL_ENABLE */
+	return BCME_IOCTL_ERROR;
+#endif /* RWL_ENABLE */
+}
+
+/* The function is replica of wl_get in wlu_linux.c. Optimize when we have some
+ * common code between wlu_linux.c and dhdu_linux.c
+ */
+int
+wl_get(void *wl, int cmd, void *buf, int len)
+{
+	int error = BCME_OK;
+	/* For RWL: When interfacing to a Windows client, need t add in OID_BASE */
+	if ((rwl_os_type == WIN32_OS) && (remote_type != NO_REMOTE)) {
+		error = (int)ioctl_queryinformation_fe(wl, WL_OID_BASE + cmd, buf, &len);
+	} else {
+		error = (int)ioctl_queryinformation_fe(wl, cmd, buf, &len);
+	}
+	if (error == BCME_SERIAL_PORT_ERR)
+		return BCME_SERIAL_PORT_ERR;
+
+	if (error != 0)
+		return BCME_IOCTL_ERROR;
+
+	return error;
+}
+
+/* The function is replica of wl_set in wlu_linux.c. Optimize when we have some
+ * common code between wlu_linux.c and dhdu_linux.c
+ */
+int
+wl_set(void *wl, int cmd, void *buf, int len)
+{
+	int error = BCME_OK;
+
+	/* For RWL: When interfacing to a Windows client, need t add in OID_BASE */
+	if ((rwl_os_type == WIN32_OS) && (remote_type != NO_REMOTE)) {
+		error = (int)ioctl_setinformation_fe(wl, WL_OID_BASE + cmd, buf, &len);
+	} else {
+		error = (int)ioctl_setinformation_fe(wl, cmd, buf, &len);
+	}
+
+	if (error == BCME_SERIAL_PORT_ERR)
+		return BCME_SERIAL_PORT_ERR;
+
+	if (error != 0) {
+		return BCME_IOCTL_ERROR;
+	}
+	return error;
+}
+
+int
+wl_validatedev(void *dev_handle)
+{
+	int retval = 1;
+	struct ifreq *ifr = (struct ifreq *)dev_handle;
+	/* validate the interface */
+	if (!ifr->ifr_name || wl_check((void *)ifr)) {
+		retval = 0;
+	}
+	return retval;
+}
+
+/* Main client function
+ * The code is mostly from wlu_linux.c. This function takes care of executing remote dhd commands
+ * along with the local dhd commands now.
+ */
+int
+main(int argc, char **argv)
+{
+	struct ifreq ifr;
+	char *ifname = NULL;
+	int err = 0;
+	int help = 0;
+	int status = CMD_DHD;
+#ifdef RWL_DONGLE
+	void* serialHandle = NULL;
+#endif /* RWL_DONGLE */
+#ifdef RWL_SOCKET
+	struct ipv4_addr temp;
+#endif /* RWL_SOCKET */
+
+	UNUSED_PARAMETER(argc);
+
+	av0 = argv[0];
+	memset(&ifr, 0, sizeof(ifr));
+	argv++;
+
+	if ((status = dhd_option(&argv, &ifname, &help)) == CMD_OPT) {
+		if (ifname)
+			strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+	}
+	/* Linux client looking for a Win32 server */
+	if (*argv && strncmp (*argv, "--wince", strlen(*argv)) == 0) {
+		rwl_os_type = WIN32_OS;
+		argv++;
+	}
+
+	/* RWL socket transport Usage: --socket ipaddr [port num] */
+	if (*argv && strncmp (*argv, "--socket", strlen(*argv)) == 0) {
+		argv++;
+
+		remote_type = REMOTE_SOCKET;
+#ifdef RWL_SOCKET
+		if (!(*argv)) {
+			rwl_usage(remote_type);
+			return err;
+		}
+
+		if (!dhd_atoip(*argv, &temp)) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		g_rwl_servIP = *argv;
+		argv++;
+
+		g_rwl_servport = DEFAULT_SERVER_PORT;
+		if ((*argv) && isdigit(**argv)) {
+			g_rwl_servport = atoi(*argv);
+			argv++;
+		}
+#endif /* RWL_SOCKET */
+	}
+
+	/* RWL from system serial port on client to uart dongle port on server */
+	/* Usage: --dongle /dev/ttyS0 */
+	if (*argv && strncmp (*argv, "--dongle", strlen(*argv)) == 0) {
+		argv++;
+		remote_type = REMOTE_DONGLE;
+#ifdef RWL_DONGLE
+		if (!(*argv)) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		g_rwl_device_name_serial = *argv;
+		argv++;
+		if ((serialHandle = rwl_open_pipe(remote_type, "\0", 0, 0)) == NULL) {
+			DPRINT_ERR(ERR, "serial device open error\r\n");
+			return BCME_ERROR;
+		}
+		ifr = (*(struct ifreq *)serialHandle);
+#endif /* RWL_DONGLE */
+	}
+
+	/* RWL over wifi.  Usage: --wifi mac_address */
+	if (*argv && strncmp (*argv, "--wifi", strlen(*argv)) == 0) {
+		argv++;
+#ifdef RWL_WIFI
+		remote_type = NO_REMOTE;
+		if (!ifr.ifr_name[0])
+		{
+			dhd_find(&ifr, "wl");
+		}
+		/* validate the interface */
+		if (!ifr.ifr_name[0] || wl_check((void*)&ifr)) {
+			fprintf(stderr, "%s: wl driver adapter not found\n", av0);
+			exit(1);
+		}
+		remote_type = REMOTE_WIFI;
+
+		if (argc < 4) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		/* copy server mac address to local buffer for later use by findserver cmd */
+		if (!dhd_ether_atoe(*argv, (struct ether_addr *)g_rwl_buf_mac)) {
+			fprintf(stderr,
+			        "could not parse as an ethernet MAC address\n");
+			return FAIL;
+		}
+		argv++;
+#else /* RWL_WIFI */
+		remote_type = REMOTE_WIFI;
+#endif /* RWL_WIFI */
+	}
+
+	/* Process for local dhd */
+	if (remote_type == NO_REMOTE) {
+		err = process_args(&ifr, argv);
+		return err;
+	}
+
+#ifdef RWL_ENABLE
+	if (*argv) {
+		err = process_args(&ifr, argv);
+		if ((err == BCME_SERIAL_PORT_ERR) && (remote_type == REMOTE_DONGLE)) {
+			DPRINT_ERR(ERR, "\n Retry again\n");
+			err = process_args((struct ifreq*)&ifr, argv);
+		}
+		return err;
+	}
+	rwl_usage(remote_type);
+#endif /* RWL_ENABLE */
+
+#ifdef RWL_DONGLE
+	if (remote_type == REMOTE_DONGLE)
+		rwl_close_pipe(remote_type, (void*)&ifr);
+#endif /* RWL_DONGLE */
+	return err;
+}
+/*
+ * Function called for  'local' execution and for 'remote' non-interactive session
+ * (shell cmd, wl cmd) .The code is mostly from wlu_linux.c. This code can be
+ * common to wlu_linux.c and dhdu_linux.c
+ */
+static int
+process_args(struct ifreq* ifr, char **argv)
+{
+	char *ifname = NULL;
+	int help = 0;
+	int status = 0;
+	int err = BCME_OK;
+	cmd_t *cmd = NULL;
+	while (*argv) {
+#ifdef RWL_ENABLE
+		if ((strcmp (*argv, "sh") == 0) && (remote_type != NO_REMOTE)) {
+			argv++; /* Get the shell command */
+			if (*argv) {
+				/* Register handler in case of shell command only */
+				signal(SIGINT, ctrlc_handler);
+				err = rwl_shell_cmd_proc((void*)ifr, argv, SHELL_CMD);
+			} else {
+				DPRINT_ERR(ERR,
+				"Enter the shell command (e.g ls(Linux) or dir(Win CE) \n");
+				err = BCME_ERROR;
+			}
+			return err;
+		}
+#endif /* RWL_ENABLE */
+		if ((status = dhd_option(&argv, &ifname, &help)) == CMD_OPT) {
+			if (help)
+				break;
+			if (ifname)
+				strncpy(ifr->ifr_name, ifname, IFNAMSIZ);
+			continue;
+		}
+		/* parse error */
+		else if (status == CMD_ERR)
+		    break;
+
+		if (remote_type == NO_REMOTE) {
+			int ret;
+
+			/* use default interface */
+			if (!ifr->ifr_name[0])
+				dhd_find(ifr, "dhd");
+			/* validate the interface */
+			if (!ifr->ifr_name[0]) {
+				if (strcmp("dldn", *argv) != 0) {
+					exit(ENXIO);
+					syserr("interface");
+				}
+			}
+			if ((ret = dhd_check((void *)ifr)) != 0) {
+				if (strcmp("dldn", *argv) != 0) {
+					errno = -ret;
+					syserr("dhd_check");
+				}
+			}
+		}
+		/* search for command */
+		cmd = dhd_find_cmd(*argv);
+		/* if not found, use default set_var and get_var commands */
+		if (!cmd) {
+			cmd = &dhd_varcmd;
+		}
+
+		/* do command */
+		err = (*cmd->func)((void *) ifr, cmd, argv);
+		break;
+	} /* while loop end */
+
+	/* provide for help on a particular command */
+	if (help && *argv) {
+		cmd = dhd_find_cmd(*argv);
+		if (cmd) {
+			dhd_cmd_usage(cmd);
+		} else {
+			DPRINT_ERR(ERR, "%s: Unrecognized command \"%s\", type -h for help\n",
+			           av0, *argv);
+		}
+	} else if (!cmd)
+		dhd_usage(NULL);
+	else if (err == BCME_USAGE_ERROR)
+		dhd_cmd_usage(cmd);
+	else if (err == BCME_IOCTL_ERROR)
+		dhd_printlasterror((void *) ifr);
+
+	return err;
+}
+
+int
+rwl_shell_createproc(void *wl)
+{
+	UNUSED_PARAMETER(wl);
+	return fork();
+}
+
+void
+rwl_shell_killproc(int pid)
+{
+	kill(pid, SIGKILL);
+}
+
+#ifdef RWL_SOCKET
+/* validate hostname/ip given by the client */
+int
+validate_server_address()
+{
+	struct hostent *he;
+	struct ipv4_addr temp;
+
+	if (!dhd_atoip(g_rwl_servIP, &temp)) {
+	/* Wrong IP address format check for hostname */
+		if ((he = gethostbyname(g_rwl_servIP)) != NULL) {
+			if (!dhd_atoip(*he->h_addr_list, &temp)) {
+				g_rwl_servIP = inet_ntoa(*(struct in_addr *)*he->h_addr_list);
+				if (g_rwl_servIP == NULL) {
+					DPRINT_ERR(ERR, "Error at inet_ntoa \n");
+					return FAIL;
+				}
+			} else {
+				DPRINT_ERR(ERR, "Error in IP address \n");
+				return FAIL;
+			}
+		} else {
+			DPRINT_ERR(ERR, "Enter correct IP address/hostname format\n");
+			return FAIL;
+		}
+	}
+	return SUCCESS;
+}
+#endif /* RWL_SOCKET */
diff --git a/src/dhd/exe/dhdu_nl80211.c b/src/dhd/exe/dhdu_nl80211.c
new file mode 100644
index 0000000..322d5f1
--- /dev/null
+++ b/src/dhd/exe/dhdu_nl80211.c
@@ -0,0 +1,185 @@
+/*
+ * nl80211 linux driver interface.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: $
+ */
+#include <errno.h>
+#include <linux/nl80211.h>
+#include <dhdioctl.h>
+#include <brcm_nl80211.h>
+#include "dhdu_nl80211.h"
+
+static struct nla_policy dhd_nl_policy[BCM_NLATTR_MAX + 1] = {
+	[BCM_NLATTR_LEN] = { .type = NLA_U16 },
+	[BCM_NLATTR_DATA] = { .type = NLA_UNSPEC },
+};
+
+/* libnl 1.x compatibility code */
+#if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30)
+static inline struct nl_handle *nl_socket_alloc(void)
+{
+	return nl_handle_alloc();
+}
+
+static inline void nl_socket_free(struct nl_sock *h)
+{
+	nl_handle_destroy(h);
+}
+#endif /* CONFIG_LIBNL20 && CONFIG_LIBNL30 */
+
+static int dhd_nl_error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
+{
+	if (err->error)
+		fprintf(stderr, "%s:error:%d\n", __func__, err->error);
+	return NL_SKIP;
+}
+
+static int dhd_nl_finish_handler(struct nl_msg *msg, void *arg)
+{
+	return NL_SKIP;
+}
+
+static int dhd_nl_ack_handler(struct nl_msg *msg, void *arg)
+{
+	struct nl_prv_data *prv = arg;
+
+	prv->err = 0;
+	return NL_STOP;
+}
+
+static int dhd_nl_valid_handler(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+	struct nlattr *nl_dhd[BCM_NLATTR_MAX + 1];
+	struct nl_prv_data *prv = arg;
+	int ret;
+	uint payload;
+
+	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		genlmsg_attrlen(gnlh, 0), NULL);
+	if (!attrs[NL80211_ATTR_TESTDATA]) {
+		fprintf(stderr, "Could not find attrs NL80211_ATTR_TESTDATA\n");
+		return NL_SKIP;
+	}
+
+	ret = nla_parse_nested(nl_dhd, BCM_NLATTR_MAX,
+		attrs[NL80211_ATTR_TESTDATA], dhd_nl_policy);
+	if (ret != 0 || !nl_dhd[BCM_NLATTR_LEN] || !nl_dhd[BCM_NLATTR_DATA]) {
+		fprintf(stderr, "nla_parse_nested error\n");
+		return NL_SKIP;
+	}
+
+	payload = nla_get_u16(nl_dhd[BCM_NLATTR_LEN]);
+	if (payload > prv->len)
+		payload = prv->len;
+	memcpy(prv->data, nla_data(nl_dhd[BCM_NLATTR_DATA]), payload);
+	prv->data += payload;
+	prv->len -= payload;
+
+	return NL_SKIP;
+}
+
+int dhd_nl_sock_connect(struct dhd_netlink_info *dhd_nli)
+{
+	dhd_nli->nl = nl_socket_alloc();
+	if (dhd_nli->nl == NULL)
+		return -1;
+
+	if (genl_connect(dhd_nli->nl) < 0) {
+		fprintf(stderr, "netlink connection failed\n");
+		goto err;
+	}
+
+	dhd_nli->nl_id = genl_ctrl_resolve(dhd_nli->nl, "nl80211");
+	if (dhd_nli->nl_id < 0) {
+		fprintf(stderr, "'nl80211' netlink not found\n");
+		goto err;
+	}
+
+	dhd_nli->cb = nl_cb_alloc(NL_CB_DEBUG);
+	if (dhd_nli->cb == NULL)
+		goto err;
+
+	nl_socket_set_cb(dhd_nli->nl, dhd_nli->cb);
+	return 0;
+
+err:
+	nl_cb_put(dhd_nli->cb);
+	nl_socket_free(dhd_nli->nl);
+	fprintf(stderr, "nl80211 connection failed\n");
+	return -1;
+}
+
+void dhd_nl_sock_disconnect(struct dhd_netlink_info *dhd_nli)
+{
+	nl_cb_put(dhd_nli->cb);
+	nl_socket_free(dhd_nli->nl);
+}
+
+int dhd_nl_do_testmode(struct dhd_netlink_info *dhd_nli, dhd_ioctl_t *ioc)
+{
+	struct nl_msg *msg;
+	struct nl_prv_data prv_dat;
+	struct bcm_nlmsg_hdr *nlioc;
+	uint msglen = ioc->len;
+
+	msg = nlmsg_alloc();
+	if (msg == NULL)
+		return -ENOMEM;
+
+	/* nlmsg_alloc() can only allocate default_pagesize packet, cap
+	 * any buffer send down to 1024 bytes
+	 * Maximum downlink buffer ATM is required for PNO ssid list (900 bytes)
+	 * DO NOT switch to nlmsg_alloc_size because Android doesn't support it
+	 */
+	if (msglen > 0x400)
+		msglen = 0x400;
+	msglen += sizeof(struct bcm_nlmsg_hdr);
+	nlioc = malloc(msglen);
+	if (nlioc == NULL) {
+		nlmsg_free(msg);
+		return -ENOMEM;
+	}
+	nlioc->cmd = ioc->cmd;
+	nlioc->len = ioc->len;
+	nlioc->offset = sizeof(struct bcm_nlmsg_hdr);
+	nlioc->set = ioc->set;
+	nlioc->magic = ioc->driver;
+	memcpy(((void *)nlioc) + nlioc->offset, ioc->buf, msglen - nlioc->offset);
+
+	/* fill testmode message */
+	genlmsg_put(msg, 0, 0, dhd_nli->nl_id, 0, 0,
+		NL80211_CMD_TESTMODE, 0);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dhd_nli->ifidx);
+	NLA_PUT(msg, NL80211_ATTR_TESTDATA, msglen, nlioc);
+
+	prv_dat.err = nl_send_auto_complete(dhd_nli->nl, msg);
+	if (prv_dat.err < 0)
+		goto out;
+
+	prv_dat.err = 1;
+	prv_dat.nlioc = nlioc;
+	prv_dat.data = ioc->buf;
+	prv_dat.len = ioc->len;
+	nl_cb_err(dhd_nli->cb, NL_CB_CUSTOM, dhd_nl_error_handler, &prv_dat);
+	nl_cb_set(dhd_nli->cb, NL_CB_ACK, NL_CB_CUSTOM,
+		dhd_nl_ack_handler, &prv_dat);
+	nl_cb_set(dhd_nli->cb, NL_CB_FINISH, NL_CB_CUSTOM,
+		dhd_nl_finish_handler, &prv_dat);
+	nl_cb_set(dhd_nli->cb, NL_CB_VALID, NL_CB_CUSTOM,
+		dhd_nl_valid_handler, &prv_dat);
+	while (prv_dat.err > 0)
+		nl_recvmsgs(dhd_nli->nl, dhd_nli->cb);
+out:
+	free(nlioc);
+	nlmsg_free(msg);
+	return prv_dat.err;
+
+nla_put_failure:
+	fprintf(stderr, "setting netlink attribute failed\n");
+	prv_dat.err = -EFAULT;
+	goto out;
+}
diff --git a/src/dhd/exe/dhdu_nl80211.h b/src/dhd/exe/dhdu_nl80211.h
new file mode 100644
index 0000000..30be86f
--- /dev/null
+++ b/src/dhd/exe/dhdu_nl80211.h
@@ -0,0 +1,37 @@
+/*
+ * Definitions for DHD nl80211 driver interface.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: $
+ */
+
+#ifndef DHDU_NL80211_H_
+#define DHDU_NL80211_H_
+
+#ifdef NL80211
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+
+/* libnl 1.x compatibility code */
+#if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30)
+#define nl_sock		nl_handle
+#endif
+
+struct dhd_netlink_info
+{
+	struct nl_sock *nl;
+	struct nl_cb *cb;
+	int nl_id;
+	int ifidx;
+};
+
+int dhd_nl_sock_connect(struct dhd_netlink_info *dhd_nli);
+void dhd_nl_sock_disconnect(struct dhd_netlink_info *dhd_nli);
+int dhd_nl_do_testmode(struct dhd_netlink_info *dhd_nli, dhd_ioctl_t *ioc);
+
+#endif /* NL80211 */
+
+#endif /* DHDU_NL80211_H_ */
diff --git a/src/dhd/exe/netlink.inc b/src/dhd/exe/netlink.inc
new file mode 100644
index 0000000..6d6a4ad
--- /dev/null
+++ b/src/dhd/exe/netlink.inc
@@ -0,0 +1,90 @@
+#
+# netlink.inc for dhd/exe
+#
+# Copyright (c) 2013, Broadcom Corp.
+# $Id: netlink.inc 454524 2014-02-11 01:45:50Z $
+
+ifdef NL80211
+
+ifneq ($(findstring android,$(TARGETENV)),)
+
+include $(dir $(lastword $(MAKEFILE_LIST)))/../../makefiles/WLAN_Common.mk
+
+ifeq ($(NLHEADERS_PATH),)
+$(error libnl headers path must be specified)
+endif
+ifeq ($(NLSTATICLIB_PATH),)
+$(error libnl static library path must be specified)
+endif
+
+CFLAGS += -I$(NLHEADERS_PATH)
+LIBS += -Wl,--whole-archive -Wl,--no-whole-archive $(NLSTATICLIB_PATH)
+
+LIBNLVER = $(shell grep "LIBNL_VERSION" $(NLHEADERS_PATH)/netlink/version.h | cut -d " " -f 3 | sed "s/\"//g")
+
+ifeq ($(call wlan_version_ge,$(LIBNLVER),3.0),TRUE)
+CFLAGS += -DCONFIG_LIBNL30
+else ifeq ($(call wlan_version_ge,$(LIBNLVER),2.0),TRUE)
+CFLAGS += -DCONFIG_LIBNL20
+endif
+
+else #ifneq ($(findstring android,$(TARGETENV)),)
+
+PKG_CONFIG ?= pkg-config
+
+NL1FOUND := $(shell $(PKG_CONFIG) --atleast-version=1 libnl-1 && echo Y)
+NL2FOUND := $(shell $(PKG_CONFIG) --atleast-version=2 libnl-2.0 && echo Y)
+NL3FOUND := $(shell $(PKG_CONFIG) --atleast-version=3 libnl-3.0 && echo Y)
+NL31FOUND := $(shell $(PKG_CONFIG) --exact-version=3.1 libnl-3.1 && echo Y)
+NL3xFOUND := $(shell $(PKG_CONFIG) --atleast-version=3.2 libnl-3.0 && echo Y)
+
+$(sh echo "what to do")
+
+ifeq ($(NL1FOUND),Y)
+NLLIBNAME = libnl-1
+endif
+
+ifeq ($(NL2FOUND),Y)
+CFLAGS += -DCONFIG_LIBNL20
+LIBS += -lnl-genl
+NLLIBNAME = libnl-2.0
+endif
+
+ifeq ($(NL3xFOUND),Y)
+# libnl 3.2 might be found as 3.2 and 3.0
+NL3FOUND = N
+CFLAGS += -DCONFIG_LIBNL30
+LIBS += -lnl-genl-3
+NLLIBNAME = libnl-3.0
+endif
+
+ifeq ($(NL3FOUND),Y)
+CFLAGS += -DCONFIG_LIBNL30
+LIBS += -lnl-genl
+NLLIBNAME = libnl-3.0
+endif
+
+# nl-3.1 has a broken libnl-gnl-3.1.pc file
+# as show by pkg-config --debug --libs --cflags --exact-version=3.1 libnl-genl-3.1;echo $?
+ifeq ($(NL31FOUND),Y)
+CFLAGS += -DCONFIG_LIBNL30
+LIBS += -lnl-genl
+NLLIBNAME = libnl-3.1
+endif
+
+ifeq ($(NLLIBNAME),)
+$(error Cannot find development files for any supported version of libnl)
+endif
+
+LIBS += $(shell $(PKG_CONFIG) --libs $(NLLIBNAME))
+CFLAGS += $(shell $(PKG_CONFIG) --cflags $(NLLIBNAME))
+
+endif #ifneq ($(findstring android,$(TARGETENV)),)
+
+ifeq ($(BUILD_TAG),TRUNK)
+DHD_OBJS += $(TARGETARCH)/dhdu_nl80211.o
+else
+DHD_OBJS += dhdu_nl80211.o
+endif
+
+endif # NL80211
diff --git a/src/dhd/exe/ucode_download.c b/src/dhd/exe/ucode_download.c
new file mode 100644
index 0000000..b2c7a3c
--- /dev/null
+++ b/src/dhd/exe/ucode_download.c
@@ -0,0 +1,251 @@
+/*
+ * Ucode download related utility functions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: ucode_download.c 297277 2011-11-18 14:10:09Z $
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <trxhdr.h>
+#include <bcmendian.h>
+#include <wlu_common.h>
+
+#define DEVPRESENT_DELAY  10000	/* in microsecs */
+#define DEVPRESENT_RETRIES   100
+
+extern int wl_validatedev(void *dev_handle);
+
+int
+dload_generic_data(void *wl, uint16 dload_type, unsigned char *dload_buf, int len)
+{
+	struct wl_dload_data *dload_ptr = (struct wl_dload_data *)dload_buf;
+	int err = 0;
+	int actual_data_offset;
+	char *buf;
+
+	actual_data_offset = OFFSETOF(struct wl_dload_data, data);
+	dload_ptr->flag = (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT);
+	dload_ptr->flag |= DL_CRC_NOT_INUSE;
+	dload_ptr->dload_type = dload_type;
+	dload_ptr->len = htod32(len - actual_data_offset);
+	dload_ptr->crc = 0;
+
+	len = len + 8 - (len%8);
+
+	buf = malloc(WLC_IOCTL_MEDLEN);
+	if (buf) {
+		bzero(buf, WLC_IOCTL_MEDLEN);
+		err = wlu_iovar_setbuf(wl, "generic_dload", dload_buf, len, buf,
+			WLC_IOCTL_MEDLEN);
+	}
+	free(buf);
+	return err;
+}
+
+int
+dload_ucode_part(void *wl, uint8 ucode_type, uint32 datalen, unsigned char *org_buf)
+{
+	int num_chunks, chunk_len, cumulative_len = 0;
+	int size2alloc, ucode_chunk_len = 0;
+	unsigned char *new_buf;
+	struct wl_ucode_info *ucode_ptr;
+	int err = 0, ucode_offset, chunk_offset;
+
+	ucode_offset = OFFSETOF(wl_dload_data_t, data);
+	chunk_offset = OFFSETOF(wl_ucode_info_t, data_chunk);
+
+	err = wlu_iovar_getint(wl, "ucdload_chunk_len",
+		&ucode_chunk_len);
+	if (err) {
+		printf("err in getting ucode chunk len, exiting\n");
+		return err;
+	}
+
+	num_chunks = datalen/ucode_chunk_len;
+	if (datalen % ucode_chunk_len != 0)
+		num_chunks++;
+	size2alloc = ucode_offset + chunk_offset + ucode_chunk_len;
+
+	/* single chunk buffer */
+	new_buf = (unsigned char *)malloc(size2alloc);
+	memset(new_buf, 0, size2alloc);
+	ucode_ptr = (struct wl_ucode_info *)((uint8 *)new_buf+ucode_offset);
+	ucode_ptr->ucode_type = ucode_type;
+	ucode_ptr->num_chunks = num_chunks;
+	do {
+		if (datalen >= ucode_chunk_len)
+			chunk_len = ucode_chunk_len;
+		else
+			chunk_len = datalen;
+		memset(new_buf+ucode_offset+chunk_offset, 0, size2alloc-ucode_offset-chunk_offset);
+		ucode_ptr->chunk_len = htod32(chunk_len);
+		ucode_ptr->chunk_num++;
+		memcpy(&ucode_ptr->data_chunk[0], org_buf + cumulative_len, chunk_len);
+		cumulative_len += chunk_len;
+		err = dload_generic_data(wl, DL_TYPE_UCODE, new_buf, size2alloc);
+		if (err) {
+			printf("error while writing %s to the memory\n",
+				(ucode_type == UCODE_FW)? "ucode" : "initvals");
+			break;
+		}
+		datalen = datalen - chunk_len;
+	} while (datalen > 0);
+	free(new_buf);
+
+	return err;
+}
+
+static int
+check_ucode_file(unsigned char *headers)
+{
+	struct trx_header *trx;
+	int actual_data_len = -1;
+
+	/* Extract trx header */
+	trx = (struct trx_header *)headers;
+	if (trx->magic != TRX_MAGIC) {
+		printf("Error: trx bad hdr\n");
+		goto err;
+	}
+	actual_data_len = ROUNDUP(trx->offsets[0], 4) + ROUNDUP(trx->offsets[1], 4);
+err:
+	return actual_data_len;
+}
+
+int
+proc_ucode_download(char* fw_filename, void *dev_handle)
+{
+	FILE *fp = NULL;
+	int ret = 0, loopcnt = 0;
+	struct trx_header main_trx_hdr, *ucode_trx_hdr;
+	uint32 maintrx_hdr_len, tmp_len;
+	uint32 fw_size, second_offset, ucode_trx_offset;
+	long ucode_pos;
+	unsigned long ucode_info_len = 0, status;
+	unsigned char *ucodetrx_buf, *initvals_ptr;
+	int ucode_len, initvals_len;
+	int ucdload_status = 0;
+	int is_devpresent;
+
+	/* read the file and push blocks down to memory */
+	if ((fp = fopen(fw_filename, "rb")) == NULL) {
+		fprintf(stderr, "%s: unable to open %s: %s\n",
+		        __FUNCTION__, fw_filename, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+
+	maintrx_hdr_len = sizeof(struct trx_header);
+	tmp_len = fread(&main_trx_hdr, sizeof(uint8), maintrx_hdr_len, fp);
+
+	if (tmp_len == maintrx_hdr_len) {
+		if (main_trx_hdr.magic == TRX_MAGIC) {
+			fw_size = main_trx_hdr.offsets[0];
+			second_offset = main_trx_hdr.offsets[2];
+
+			if (second_offset == maintrx_hdr_len) {
+				second_offset = 0;
+			}
+			ucode_trx_offset = maintrx_hdr_len +
+				ROUNDUP(fw_size, 4) + ROUNDUP(second_offset, 4);
+			ucode_pos = fseek(fp, ucode_trx_offset, SEEK_SET);
+			BCM_REFERENCE(ucode_pos);
+
+			if ((ucode_trx_hdr = malloc(sizeof(struct trx_header)))
+				== NULL) {
+				printf("Unable to allocate %d bytes!\n", maintrx_hdr_len);
+				ret = -ENOMEM;
+				goto exit;
+			}
+
+			/* Read ONLY the firmware-file-header into the new_buffer */
+			status = fread(ucode_trx_hdr, sizeof(uint8),
+				maintrx_hdr_len, fp);
+			if (status < sizeof(struct trx_header)) {
+				printf("Short read in hdr read for %s!\n", fw_filename);
+				ret = -EINVAL;
+				goto exit;
+			}
+
+			if ((ucode_info_len = check_ucode_file(
+				(unsigned char *)ucode_trx_hdr)) <= 0) {
+				printf("not a valid ucode.trx\n");
+				ret = -1;
+				goto exit;
+			}
+
+			ucodetrx_buf = (unsigned char *)malloc(ucode_info_len *
+				sizeof(char));
+			tmp_len = fread(ucodetrx_buf, sizeof(uint8),
+				ucode_info_len, fp);
+			if (ucode_info_len > 0) {
+				ucode_len = ucode_trx_hdr->offsets[0];
+				initvals_ptr = ucodetrx_buf +
+					ROUNDUP(ucode_trx_hdr->offsets[0], 4);
+				initvals_len = ucode_trx_hdr->offsets[1];
+			}
+			free(ucode_trx_hdr);
+
+			init_cmd_batchingmode();
+			do {
+				is_devpresent = wl_validatedev(dev_handle);
+				loopcnt++;
+				/* in USB after dongle fw starts running wl interface
+				might not appear in the list of interfaces immediately, hence try
+				after some delay of 10ms
+				*/
+				if (!is_devpresent)
+					usleep(DEVPRESENT_DELAY);
+				else {
+						/* below iovar to verify if the for foundout
+						interface has already ucode been downloaded
+						*/
+						ret = wlu_iovar_getint(dev_handle, "ucdload_status",
+							&ucdload_status);
+						if (ret) {
+							printf("err in ucdload_status, exiting\n");
+							goto exit;
+						}
+						if (ucdload_status) {
+							/* Number of 'wl' interfaces to skip
+							in the next round of going thru wl_find
+							*/
+							printf("ucode is already downloaded\n");
+						}
+				}
+			/* usb seems to take some time to come up, hence the
+			loop value of 100
+			*/
+			} while (loopcnt < DEVPRESENT_RETRIES && !is_devpresent);
+
+			if (loopcnt < DEVPRESENT_RETRIES) {
+				/* download the ucode fw */
+				ret = dload_ucode_part(dev_handle, UCODE_FW, ucode_len,
+					ucodetrx_buf);
+				if (ret) {
+					printf("error while downloading ucode, exiting\n");
+					goto exit;
+				}
+				/* download the initvals to the dongle */
+				ret = dload_ucode_part(dev_handle, INIT_VALS,
+					initvals_len, initvals_ptr);
+
+				if (ret) {
+					printf("error while downloading initvals, exiting\n");
+					goto exit;
+				}
+			}
+			else {
+				printf("wl device is not present\n");
+			}
+			free(ucodetrx_buf);
+		}
+	}
+
+exit:
+	if (fp)
+		fclose(fp);
+	return ret;
+}
diff --git a/src/dhd/exe/ucode_download.h b/src/dhd/exe/ucode_download.h
new file mode 100644
index 0000000..ad0a3e5
--- /dev/null
+++ b/src/dhd/exe/ucode_download.h
@@ -0,0 +1,9 @@
+/*
+ * Ucode download related utility functions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: ucode_download.h 241182 2011-02-17 21:50:03Z $
+ */
+extern int
+proc_ucode_download(char* fw_filename, void *dev_handle);
diff --git a/src/include/bcm_cfg.h b/src/include/bcm_cfg.h
new file mode 100644
index 0000000..eaea1cc
--- /dev/null
+++ b/src/include/bcm_cfg.h
@@ -0,0 +1,11 @@
+/*
+ * BCM common config options
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcm_cfg.h 351867 2012-08-21 18:46:16Z $
+ */
+
+#ifndef _bcm_cfg_h_
+#define _bcm_cfg_h_
+#endif 
diff --git a/src/include/bcm_mpool_pub.h b/src/include/bcm_mpool_pub.h
new file mode 100644
index 0000000..0375285
--- /dev/null
+++ b/src/include/bcm_mpool_pub.h
@@ -0,0 +1,343 @@
+/*
+ * Memory pools library, Public interface
+ *
+ * API Overview
+ *
+ * This package provides a memory allocation subsystem based on pools of
+ * homogenous objects.
+ *
+ * Instrumentation is available for reporting memory utilization both
+ * on a per-data-structure basis and system wide.
+ *
+ * There are two main types defined in this API.
+ *
+ *    pool manager: A singleton object that acts as a factory for
+ *                  pool allocators. It also is used for global
+ *                  instrumentation, such as reporting all blocks
+ *                  in use across all data structures. The pool manager
+ *                  creates and provides individual memory pools
+ *                  upon request to application code.
+ *
+ *    memory pool:  An object for allocating homogenous memory blocks.
+ *
+ * Global identifiers in this module use the following prefixes:
+ *    bcm_mpm_*     Memory pool manager
+ *    bcm_mp_*      Memory pool
+ *
+ * There are two main types of memory pools:
+ *
+ *    prealloc: The contiguous memory block of objects can either be supplied
+ *              by the client or malloc'ed by the memory manager. The objects are
+ *              allocated out of a block of memory and freed back to the block.
+ *
+ *    heap:     The memory pool allocator uses the heap (malloc/free) for memory.
+ *              In this case, the pool allocator is just providing statistics
+ *              and instrumentation on top of the heap, without modifying the heap
+ *              allocation implementation.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcm_mpool_pub.h 407097 2013-06-11 18:43:16Z $
+ */
+
+#ifndef _BCM_MPOOL_PUB_H
+#define _BCM_MPOOL_PUB_H 1
+
+#include <typedefs.h> /* needed for uint16 */
+
+
+/*
+**************************************************************************
+*
+* Type definitions, handles
+*
+**************************************************************************
+*/
+
+/* Forward declaration of OSL handle. */
+struct osl_info;
+
+/* Forward declaration of string buffer. */
+struct bcmstrbuf;
+
+/*
+ * Opaque type definition for the pool manager handle. This object is used for global
+ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and
+ * instrumentation/debugging.
+ */
+struct bcm_mpm_mgr;
+typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h;
+
+/*
+ * Opaque type definition for an instance of a pool. This handle is used for allocating
+ * and freeing memory through the pool, as well as management/instrumentation on this
+ * specific pool.
+ */
+struct bcm_mp_pool;
+typedef struct bcm_mp_pool *bcm_mp_pool_h;
+
+
+/*
+ * To make instrumentation more readable, every memory
+ * pool must have a readable name. Pool names are up to
+ * 8 bytes including '\0' termination. (7 printable characters.)
+ */
+#define BCM_MP_NAMELEN 8
+
+
+/*
+ * Type definition for pool statistics.
+ */
+typedef struct bcm_mp_stats {
+	char name[BCM_MP_NAMELEN];  /* Name of this pool. */
+	unsigned int objsz;         /* Object size allocated in this pool */
+	uint16 nobj;                /* Total number of objects in this pool */
+	uint16 num_alloc;           /* Number of objects currently allocated */
+	uint16 high_water;          /* Max number of allocated objects. */
+	uint16 failed_alloc;        /* Failed allocations. */
+} bcm_mp_stats_t;
+
+
+/*
+**************************************************************************
+*
+* API Routines on the pool manager.
+*
+**************************************************************************
+*/
+
+/*
+ * bcm_mpm_init() - initialize the whole memory pool system.
+ *
+ * Parameters:
+ *    osh:       INPUT  Operating system handle. Needed for heap memory allocation.
+ *    max_pools: INPUT Maximum number of mempools supported.
+ *    mgr:       OUTPUT The handle is written with the new pools manager object/handle.
+ *
+ * Returns:
+ *    BCME_OK     Object initialized successfully. May be used.
+ *    BCME_NOMEM  Initialization failed due to no memory. Object must not be used.
+ */
+int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp);
+
+
+/*
+ * bcm_mpm_deinit() - de-initialize the whole memory pool system.
+ *
+ * Parameters:
+ *    mgr:     INPUT  Pointer to pool manager handle.
+ *
+ * Returns:
+ *    BCME_OK  Memory pool manager successfully de-initialized.
+ *    other    Indicated error occured during de-initialization.
+ */
+int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp);
+
+/*
+ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The
+ *                                  pool uses a contiguous block of pre-alloced
+ *                                  memory. The memory block may either be provided
+ *                                  by the client or dynamically allocated by the
+ *                                  pool manager.
+ *
+ * Parameters:
+ *    mgr:      INPUT  The handle to the pool manager
+ *    obj_sz:   INPUT  Size of objects that will be allocated by the new pool
+ *                     Must be >= sizeof(void *).
+ *    nobj:     INPUT  Maximum number of concurrently existing objects to support
+ *    memstart  INPUT  Pointer to the memory to use, or NULL to malloc()
+ *    memsize   INPUT  Number of bytes referenced from memstart (for error checking).
+ *                     Must be 0 if 'memstart' is NULL.
+ *    poolname  INPUT  For instrumentation, the name of the pool
+ *    newp:     OUTPUT The handle for the new pool, if creation is successful
+ *
+ * Returns:
+ *    BCME_OK   Pool created ok.
+ *    other     Pool not created due to indicated error. newpoolp set to NULL.
+ *
+ *
+ */
+int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr,
+                                 unsigned int obj_sz,
+                                 int nobj,
+                                 void *memstart,
+                                 unsigned int memsize,
+                                 const char poolname[BCM_MP_NAMELEN],
+                                 bcm_mp_pool_h *newp);
+
+
+/*
+ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after
+ *                                  all memory objects have been freed back to the pool.
+ *
+ * Parameters:
+ *    mgr:     INPUT The handle to the pools manager
+ *    pool:    INPUT The handle of the  pool to delete
+ *
+ * Returns:
+ *    BCME_OK   Pool deleted ok.
+ *    other     Pool not deleted due to indicated error.
+ *
+ */
+int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
+
+/*
+ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory
+ *                              pool allocator uses the heap (malloc/free) for memory.
+ *                              In this case, the pool allocator is just providing
+ *                              statistics and instrumentation on top of the heap,
+ *                              without modifying the heap allocation implementation.
+ *
+ * Parameters:
+ *    mgr:      INPUT  The handle to the pool manager
+ *    obj_sz:   INPUT  Size of objects that will be allocated by the new pool
+ *    poolname  INPUT  For instrumentation, the name of the pool
+ *    newp:     OUTPUT The handle for the new pool, if creation is successful
+ *
+ * Returns:
+ *    BCME_OK   Pool created ok.
+ *    other     Pool not created due to indicated error. newpoolp set to NULL.
+ *
+ *
+ */
+int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz,
+                             const char poolname[BCM_MP_NAMELEN],
+                             bcm_mp_pool_h *newp);
+
+
+/*
+ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after
+ *                              all memory objects have been freed back to the pool.
+ *
+ * Parameters:
+ *    mgr:     INPUT The handle to the pools manager
+ *    pool:    INPUT The handle of the  pool to delete
+ *
+ * Returns:
+ *    BCME_OK   Pool deleted ok.
+ *    other     Pool not deleted due to indicated error.
+ *
+ */
+int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
+
+
+/*
+ * bcm_mpm_stats() - Return stats for all pools
+ *
+ * Parameters:
+ *    mgr:         INPUT   The handle to the pools manager
+ *    stats:       OUTPUT  Array of pool statistics.
+ *    nentries:    MOD     Max elements in 'stats' array on INPUT. Actual number
+ *                         of array elements copied to 'stats' on OUTPUT.
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error getting stats.
+ *
+ */
+int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries);
+
+
+/*
+ * bcm_mpm_dump() - Display statistics on all pools
+ *
+ * Parameters:
+ *    mgr:     INPUT  The handle to the pools manager
+ *    b:       OUTPUT Output buffer.
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error during dump.
+ *
+ */
+int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b);
+
+
+/*
+ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to
+ *                          compensate for alignment requirements of the objects.
+ *                          This function provides the padded object size. If clients
+ *                          pre-allocate a memory slab for a memory pool, the
+ *                          padded object size should be used by the client to allocate
+ *                          the memory slab (in order to provide sufficent space for
+ *                          the maximum number of objects).
+ *
+ * Parameters:
+ *    mgr:            INPUT   The handle to the pools manager.
+ *    obj_sz:         INPUT   Input object size.
+ *    padded_obj_sz:  OUTPUT  Padded object size.
+ *
+ * Returns:
+ *    BCME_OK      Ok
+ *    BCME_BADARG  Bad arguments.
+ *
+ */
+int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz);
+
+
+/*
+***************************************************************************
+*
+* API Routines on a specific pool.
+*
+***************************************************************************
+*/
+
+
+/*
+ * bcm_mp_alloc() - Allocate a memory pool object.
+ *
+ * Parameters:
+ *    pool:    INPUT    The handle to the pool.
+ *
+ * Returns:
+ *    A pointer to the new object. NULL on error.
+ *
+ */
+void* bcm_mp_alloc(bcm_mp_pool_h pool);
+
+/*
+ * bcm_mp_free() - Free a memory pool object.
+ *
+ * Parameters:
+ *    pool:  INPUT   The handle to the pool.
+ *    objp:  INPUT   A pointer to the object to free.
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error during free.
+ *
+ */
+int bcm_mp_free(bcm_mp_pool_h pool, void *objp);
+
+/*
+ * bcm_mp_stats() - Return stats for this pool
+ *
+ * Parameters:
+ *    pool:     INPUT    The handle to the pool
+ *    stats:    OUTPUT   Pool statistics
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error getting statistics.
+ *
+ */
+int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats);
+
+
+/*
+ * bcm_mp_dump() - Dump a pool
+ *
+ * Parameters:
+ *    pool:    INPUT    The handle to the pool
+ *    b        OUTPUT   Output buffer
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error during dump.
+ *
+ */
+int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b);
+
+
+#endif /* _BCM_MPOOL_PUB_H */
diff --git a/src/include/bcmcdc.h b/src/include/bcmcdc.h
new file mode 100644
index 0000000..7d00f1e
--- /dev/null
+++ b/src/include/bcmcdc.h
@@ -0,0 +1,108 @@
+/*
+ * CDC network driver ioctl/indication encoding
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmcdc.h 318308 2012-03-02 02:23:42Z $
+ */
+#ifndef _bcmcdc_h_
+#define	_bcmcdc_h_
+#include <proto/ethernet.h>
+
+typedef struct cdc_ioctl {
+	uint32 cmd;      
+	uint32 len;      
+	uint32 flags;    
+	uint32 status;   
+} cdc_ioctl_t;
+
+
+#define CDC_MAX_MSG_SIZE   ETHER_MAX_LEN
+
+
+#define CDCL_IOC_OUTLEN_MASK   0x0000FFFF  
+					   
+#define CDCL_IOC_OUTLEN_SHIFT  0
+#define CDCL_IOC_INLEN_MASK    0xFFFF0000   
+#define CDCL_IOC_INLEN_SHIFT   16
+
+
+#define CDCF_IOC_ERROR		0x01	
+#define CDCF_IOC_SET		0x02	
+#define CDCF_IOC_OVL_IDX_MASK	0x3c	
+#define CDCF_IOC_OVL_RSV	0x40	
+#define CDCF_IOC_OVL		0x80	
+#define CDCF_IOC_ACTION_MASK	0xfe	
+#define CDCF_IOC_ACTION_SHIFT	1	
+#define CDCF_IOC_IF_MASK	0xF000	
+#define CDCF_IOC_IF_SHIFT	12
+#define CDCF_IOC_ID_MASK	0xFFFF0000	
+#define CDCF_IOC_ID_SHIFT	16		
+
+#define CDC_IOC_IF_IDX(flags)	(((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
+#define CDC_IOC_ID(flags)	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
+
+#define CDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
+#define CDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT)))
+
+
+
+struct bdc_header {
+	uint8	flags;			
+	uint8	priority;		
+	uint8	flags2;
+	uint8	dataOffset;		
+};
+
+#define	BDC_HEADER_LEN		4
+
+
+#define BDC_FLAG_80211_PKT	0x01	
+#define BDC_FLAG_SUM_GOOD	0x04	
+#define BDC_FLAG_SUM_NEEDED	0x08	
+#define BDC_FLAG_EVENT_MSG	0x08	
+#define BDC_FLAG_VER_MASK	0xf0	
+#define BDC_FLAG_VER_SHIFT	4	
+
+
+#define BDC_PRIORITY_MASK	0x07
+#define BDC_PRIORITY_FC_MASK	0xf0	
+#define BDC_PRIORITY_FC_SHIFT	4	
+
+
+#define BDC_FLAG2_IF_MASK	0x0f	
+#define BDC_FLAG2_IF_SHIFT	0
+#define BDC_FLAG2_FC_FLAG	0x10	
+					
+
+
+#define BDC_PROTO_VER_1		1	
+#define BDC_PROTO_VER		2	
+
+
+#define BDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+#define BDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT)))
+
+#define BDC_FLAG2_PAD_MASK		0xf0
+#define BDC_FLAG_PAD_MASK		0x03
+#define BDC_FLAG2_PAD_SHIFT		2
+#define BDC_FLAG_PAD_SHIFT		0
+#define BDC_FLAG2_PAD_IDX		0x3c
+#define BDC_FLAG_PAD_IDX		0x03
+#define BDC_GET_PAD_LEN(hdr) \
+	((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \
+	((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT)))
+#define BDC_SET_PAD_LEN(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \
+	(((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \
+	((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \
+	(((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT)))
+
+#endif 
diff --git a/src/include/bcmdefs.h b/src/include/bcmdefs.h
new file mode 100644
index 0000000..be36485
--- /dev/null
+++ b/src/include/bcmdefs.h
@@ -0,0 +1,297 @@
+/*
+ * Misc system wide definitions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmdefs.h 433011 2013-10-30 09:19:54Z $
+ */
+
+#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(__ARM_ARCH_7A__) && !defined(OEM_ANDROID)
+#define BCM47XX_CA9
+#else
+#undef BCM47XX_CA9
+#endif 
+
+#ifndef BCMFASTPATH
+#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
+#endif 
+
+
+
+	#define BCMRAMFN(_fn)	_fn
+
+
+
+
+#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	
+
+
+#ifdef BCMBUSTYPE
+#define BUSTYPE(bus) 	(BCMBUSTYPE)
+#else
+#define BUSTYPE(bus) 	(bus)
+#endif
+
+
+#ifdef BCMCHIPTYPE
+#define CHIPTYPE(bus) 	(BCMCHIPTYPE)
+#else
+#define CHIPTYPE(bus) 	(bus)
+#endif
+
+
+
+#if defined(BCMSPROMBUS)
+#define SPROMBUS	(BCMSPROMBUS)
+#elif defined(SI_PCMCIA_SROM)
+#define SPROMBUS	(PCMCIA_BUS)
+#else
+#define SPROMBUS	(PCI_BUS)
+#endif
+
+
+#ifdef BCMCHIPID
+#define CHIPID(chip)	(BCMCHIPID)
+#else
+#define CHIPID(chip)	(chip)
+#endif
+
+#ifdef BCMCHIPREV
+#define CHIPREV(rev)	(BCMCHIPREV)
+#else
+#define CHIPREV(rev)	(rev)
+#endif
+
+
+#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 struct {
+	uint32 loaddr;
+	uint32 hiaddr;
+} dma64addr_t;
+
+#define PHYSADDR64HI(_pa) ((_pa).hiaddr)
+#define PHYSADDR64HISET(_pa, _val) \
+	do { \
+		(_pa).hiaddr = (_val);		\
+	} while (0)
+#define PHYSADDR64LO(_pa) ((_pa).loaddr)
+#define PHYSADDR64LOSET(_pa, _val) \
+	do { \
+		(_pa).loaddr = (_val);		\
+	} while (0)
+
+#ifdef BCMDMA64OSL
+typedef dma64addr_t dmaaddr_t;
+#define PHYSADDRHI(_pa) PHYSADDR64HI(_pa)
+#define PHYSADDRHISET(_pa, _val) PHYSADDR64HISET(_pa, _val)
+#define PHYSADDRLO(_pa)  PHYSADDR64LO(_pa)
+#define PHYSADDRLOSET(_pa, _val) PHYSADDR64LOSET(_pa, _val)
+
+#else
+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)
+#endif 
+
+
+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;
+
+
+
+
+#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY)
+
+#define BCMEXTRAHDROOM 260
+#else 
+#if defined(BCM47XX_CA9)
+#define BCMEXTRAHDROOM 224
+#else
+#define BCMEXTRAHDROOM 204
+#endif 
+#endif 
+
+
+#ifndef SDALIGN
+#define SDALIGN	32
+#endif
+
+
+#define BCMDONGLEHDRSZ 12
+#define BCMDONGLEPADSZ 16
+
+#define BCMDONGLEOVERHEAD	(BCMDONGLEHDRSZ + BCMDONGLEPADSZ)
+
+
+#if defined(NO_BCMDBG_ASSERT)
+# undef BCMDBG_ASSERT
+# undef BCMASSERT_LOG
+#endif
+
+#if defined(BCMASSERT_LOG)
+#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))
+
+
+#ifdef BCMSMALL
+#undef	BCMSPACE
+#define bcmspace	FALSE	
+#else
+#define	BCMSPACE
+#define bcmspace	TRUE	
+#endif
+
+
+#ifndef MAXSZ_NVRAM_VARS
+#define	MAXSZ_NVRAM_VARS	4096
+#endif
+
+
+
+
+
+
+#ifdef BCMLFRAG 
+	extern bool _bcmlfrag;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define BCMLFRAG_ENAB() (_bcmlfrag)
+	#elif defined(BCMLFRAG_DISABLED)
+		#define BCMLFRAG_ENAB()	(0)
+	#else
+		#define BCMLFRAG_ENAB()	(1)
+	#endif
+#else
+	#define BCMLFRAG_ENAB()		(0)
+#endif 
+#ifdef BCMSPLITRX 
+	extern bool _bcmsplitrx;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define BCMSPLITRX_ENAB() (_bcmsplitrx)
+	#elif defined(BCMSPLITRX_DISABLED)
+		#define BCMSPLITRX_ENAB()	(0)
+	#else
+		#define BCMSPLITRX_ENAB()	(1)
+	#endif
+#else
+	#define BCMSPLITRX_ENAB()		(0)
+#endif 
+#ifdef BCM_SPLITBUF
+	extern bool _bcmsplitbuf;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define BCM_SPLITBUF_ENAB() (_bcmsplitbuf)
+	#elif defined(BCM_SPLITBUF_DISABLED)
+		#define BCM_SPLITBUF_ENAB()	(0)
+	#else
+		#define BCM_SPLITBUF_ENAB()	(1)
+	#endif
+#else
+	#define BCM_SPLITBUF_ENAB()		(0)
+#endif	
+
+#ifdef DL_NVRAM
+#define NVRAM_ARRAY_MAXSIZE	DL_NVRAM
+#else
+#define NVRAM_ARRAY_MAXSIZE	MAXSZ_NVRAM_VARS
+#endif 
+
+#ifdef BCMUSBDEV_ENABLED
+extern uint32 gFWID;
+#endif
+
+
+#endif 
diff --git a/src/include/bcmdevs.h b/src/include/bcmdevs.h
new file mode 100644
index 0000000..3fd94a0
--- /dev/null
+++ b/src/include/bcmdevs.h
@@ -0,0 +1,1029 @@
+/*
+ * Broadcom device-specific manifest constants.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmdevs.h 475454 2014-05-05 20:54:58Z $
+ */
+
+#ifndef	_BCMDEVS_H
+#define	_BCMDEVS_H
+
+
+#define	VENDOR_EPIGRAM		0xfeda
+#define	VENDOR_BROADCOM		0x14e4
+#define	VENDOR_3COM		0x10b7
+#define	VENDOR_NETGEAR		0x1385
+#define	VENDOR_DIAMOND		0x1092
+#define	VENDOR_INTEL		0x8086
+#define	VENDOR_DELL		0x1028
+#define	VENDOR_HP		0x103c
+#define	VENDOR_HP_COMPAQ	0x0e11
+#define	VENDOR_APPLE		0x106b
+#define VENDOR_SI_IMAGE		0x1095		
+#define VENDOR_BUFFALO		0x1154		
+#define VENDOR_TI		0x104c		
+#define VENDOR_RICOH		0x1180		
+#define VENDOR_JMICRON		0x197b
+
+
+
+#define	VENDOR_BROADCOM_PCMCIA	0x02d0
+
+
+#define	VENDOR_BROADCOM_SDIO	0x00BF
+
+
+#define BCM_DNGL_VID		0x0a5c
+#define BCM_DNGL_BL_PID_4328	0xbd12
+#define BCM_DNGL_BL_PID_4322	0xbd13
+#define BCM_DNGL_BL_PID_4319    0xbd16
+#define BCM_DNGL_BL_PID_43236   0xbd17
+#define BCM_DNGL_BL_PID_4332	0xbd18
+#define BCM_DNGL_BL_PID_4330	0xbd19
+#define BCM_DNGL_BL_PID_4334	0xbd1a
+#define BCM_DNGL_BL_PID_43239   0xbd1b
+#define BCM_DNGL_BL_PID_4324	0xbd1c
+#define BCM_DNGL_BL_PID_4360	0xbd1d
+#define BCM_DNGL_BL_PID_43143	0xbd1e
+#define BCM_DNGL_BL_PID_43242	0xbd1f
+#define BCM_DNGL_BL_PID_43342	0xbd21
+#define BCM_DNGL_BL_PID_4335	0xbd20
+#define BCM_DNGL_BL_PID_43341	0xbd22
+#define BCM_DNGL_BL_PID_4350    0xbd23
+#define BCM_DNGL_BL_PID_4345    0xbd24
+#define BCM_DNGL_BL_PID_4349	0xbd25
+#define BCM_DNGL_BL_PID_4354	0xbd26
+
+#define BCM_DNGL_BDC_PID	0x0bdc
+#define BCM_DNGL_JTAG_PID	0x4a44
+
+
+#define BCM_HWUSB_PID_43239     43239
+
+
+#define	BCM4210_DEVICE_ID	0x1072		
+#define	BCM4230_DEVICE_ID	0x1086		
+#define	BCM4401_ENET_ID		0x170c		
+#define	BCM3352_DEVICE_ID	0x3352		
+#define	BCM3360_DEVICE_ID	0x3360		
+#define	BCM4211_DEVICE_ID	0x4211
+#define	BCM4231_DEVICE_ID	0x4231
+#define	BCM4303_D11B_ID		0x4303		
+#define	BCM4311_D11G_ID		0x4311		
+#define	BCM4311_D11DUAL_ID	0x4312		
+#define	BCM4311_D11A_ID		0x4313		
+#define	BCM4328_D11DUAL_ID	0x4314		
+#define	BCM4328_D11G_ID		0x4315		
+#define	BCM4328_D11A_ID		0x4316		
+#define	BCM4318_D11G_ID		0x4318		
+#define	BCM4318_D11DUAL_ID	0x4319		
+#define	BCM4318_D11A_ID		0x431a		
+#define	BCM4325_D11DUAL_ID	0x431b		
+#define	BCM4325_D11G_ID		0x431c		
+#define	BCM4325_D11A_ID		0x431d		
+#define	BCM4306_D11G_ID		0x4320		
+#define	BCM4306_D11A_ID		0x4321		
+#define	BCM4306_UART_ID		0x4322		
+#define	BCM4306_V90_ID		0x4323		
+#define	BCM4306_D11DUAL_ID	0x4324		
+#define	BCM4306_D11G_ID2	0x4325		
+#define	BCM4321_D11N_ID		0x4328		
+#define	BCM4321_D11N2G_ID	0x4329		
+#define	BCM4321_D11N5G_ID	0x432a		
+#define BCM4322_D11N_ID		0x432b		
+#define BCM4322_D11N2G_ID	0x432c		
+#define BCM4322_D11N5G_ID	0x432d		
+#define BCM4329_D11N_ID		0x432e		
+#define BCM4329_D11N2G_ID	0x432f		
+#define BCM4329_D11N5G_ID	0x4330		
+#define	BCM4315_D11DUAL_ID	0x4334		
+#define	BCM4315_D11G_ID		0x4335		
+#define	BCM4315_D11A_ID		0x4336		
+#define BCM4319_D11N_ID		0x4337		
+#define BCM4319_D11N2G_ID	0x4338		
+#define BCM4319_D11N5G_ID	0x4339		
+#define BCM43231_D11N2G_ID	0x4340		
+#define BCM43221_D11N2G_ID	0x4341		
+#define BCM43222_D11N_ID	0x4350		
+#define BCM43222_D11N2G_ID	0x4351		
+#define BCM43222_D11N5G_ID	0x4352		
+#define BCM43224_D11N_ID	0x4353		
+#define BCM43224_D11N_ID_VEN1	0x0576		
+#define BCM43226_D11N_ID	0x4354		
+#define BCM43236_D11N_ID	0x4346		
+#define BCM43236_D11N2G_ID	0x4347		
+#define BCM43236_D11N5G_ID	0x4348		
+#define BCM43225_D11N2G_ID	0x4357		
+#define BCM43421_D11N_ID	0xA99D		
+#define BCM4313_D11N2G_ID	0x4727		
+#define BCM4330_D11N_ID         0x4360          
+#define BCM4330_D11N2G_ID       0x4361          
+#define BCM4330_D11N5G_ID       0x4362          
+#define BCM4336_D11N_ID		0x4343		
+#define BCM6362_D11N_ID		0x435f		
+#define BCM6362_D11N2G_ID	0x433f		
+#define BCM6362_D11N5G_ID	0x434f		
+#define BCM4331_D11N_ID		0x4331		
+#define BCM4331_D11N2G_ID	0x4332		
+#define BCM4331_D11N5G_ID	0x4333		
+#define BCM43237_D11N_ID	0x4355		
+#define BCM43237_D11N5G_ID	0x4356		
+#define BCM43227_D11N2G_ID	0x4358		
+#define BCM43228_D11N_ID	0x4359		
+#define BCM43228_D11N5G_ID	0x435a		
+#define BCM43362_D11N_ID	0x4363		
+#define BCM43239_D11N_ID	0x4370		
+#define BCM4324_D11N_ID		0x4374		
+#define BCM43217_D11N2G_ID	0x43a9		
+#define BCM43131_D11N2G_ID	0x43aa		
+#define BCM4314_D11N2G_ID	0x4364		
+#define BCM43142_D11N2G_ID	0x4365		
+#define BCM43143_D11N2G_ID	0x4366		
+#define BCM4334_D11N_ID		0x4380		
+#define BCM4334_D11N2G_ID	0x4381		
+#define BCM4334_D11N5G_ID	0x4382		
+#define BCM43342_D11N_ID	0x4383		
+#define BCM43342_D11N2G_ID	0x4384		
+#define BCM43342_D11N5G_ID	0x4385		
+#define BCM43341_D11N_ID	0x4386		
+#define BCM43341_D11N2G_ID	0x4387		
+#define BCM43341_D11N5G_ID	0x4388		
+#define BCM4360_D11AC_ID	0x43a0
+#define BCM4360_D11AC2G_ID	0x43a1
+#define BCM4360_D11AC5G_ID	0x43a2
+#define BCM4345_D11AC_ID	0x43ab		
+#define BCM4345_D11AC2G_ID	0x43ac		
+#define BCM4345_D11AC5G_ID	0x43ad		
+#define BCM4335_D11AC_ID	0x43ae
+#define BCM4335_D11AC2G_ID	0x43af
+#define BCM4335_D11AC5G_ID	0x43b0
+#define BCM4352_D11AC_ID	0x43b1		
+#define BCM4352_D11AC2G_ID	0x43b2		
+#define BCM4352_D11AC5G_ID	0x43b3		
+#define BCM43602_D11AC_ID	0x43ba		
+#define BCM43602_D11AC2G_ID	0x43bb		
+#define BCM43602_D11AC5G_ID	0x43bc		
+
+
+#define BCM943228HMB_SSID_VEN1	0x0607
+#define BCM94313HMGBL_SSID_VEN1	0x0608
+#define BCM94313HMG_SSID_VEN1	0x0609
+#define BCM943142HM_SSID_VEN1	0x0611
+
+#define BCM43143_D11N2G_ID	0x4366		
+
+#define BCM43242_D11N_ID	0x4367		
+#define BCM43242_D11N2G_ID	0x4368		
+#define BCM43242_D11N5G_ID	0x4369		
+
+#define BCM4350_D11AC_ID	0x43a3
+#define BCM4350_D11AC2G_ID	0x43a4
+#define BCM4350_D11AC5G_ID	0x43a5
+
+#define BCM43556_D11AC_ID	0x43b7
+#define BCM43556_D11AC2G_ID	0x43b8
+#define BCM43556_D11AC5G_ID	0x43b9
+
+#define BCM43558_D11AC_ID	0x43c0
+#define BCM43558_D11AC2G_ID	0x43c1
+#define BCM43558_D11AC5G_ID	0x43c2
+
+#define BCM43566_D11AC_ID	0x43d3
+#define BCM43566_D11AC2G_ID	0x43d4
+#define BCM43566_D11AC5G_ID	0x43d5
+
+#define BCM43568_D11AC_ID	0x43d6
+#define BCM43568_D11AC2G_ID	0x43d7
+#define BCM43568_D11AC5G_ID	0x43d8
+
+#define BCM43569_D11AC_ID	0x43d9
+#define BCM43569_D11AC2G_ID	0x43da
+#define BCM43569_D11AC5G_ID	0x43db
+
+#define BCM4354_D11AC_ID	0x43df		
+#define BCM4354_D11AC2G_ID	0x43e0		
+#define BCM4354_D11AC5G_ID	0x43e1		
+#define BCM43430_D11N2G_ID	0x43e2		
+
+
+#define BCM43349_D11N_ID	0x43e6		
+#define BCM43349_D11N2G_ID	0x43e7		
+#define BCM43349_D11N5G_ID	0x43e8		
+
+#define BCM4356_D11AC_ID	0x43ec		
+#define BCM4356_D11AC2G_ID	0x43ed		
+#define BCM4356_D11AC5G_ID	0x43ee		
+
+#define	BCMGPRS_UART_ID		0x4333		
+#define	BCMGPRS2_UART_ID	0x4344		
+#define FPGA_JTAGM_ID		0x43f0		
+#define BCM_JTAGM_ID		0x43f1		
+#define SDIOH_FPGA_ID		0x43f2		
+#define BCM_SDIOH_ID		0x43f3		
+#define SDIOD_FPGA_ID		0x43f4		
+#define SPIH_FPGA_ID		0x43f5		
+#define BCM_SPIH_ID		0x43f6		
+#define MIMO_FPGA_ID		0x43f8		
+#define BCM_JTAGM2_ID		0x43f9		
+#define SDHCI_FPGA_ID		0x43fa		
+#define	BCM4402_ENET_ID		0x4402		
+#define	BCM4402_V90_ID		0x4403		
+#define	BCM4410_DEVICE_ID	0x4410		
+#define	BCM4412_DEVICE_ID	0x4412		
+#define	BCM4430_DEVICE_ID	0x4430		
+#define	BCM4432_DEVICE_ID	0x4432		
+#define	BCM4704_ENET_ID		0x4706		
+#define	BCM4710_DEVICE_ID	0x4710		
+#define	BCM47XX_AUDIO_ID	0x4711		
+#define	BCM47XX_V90_ID		0x4712		
+#define	BCM47XX_ENET_ID		0x4713		
+#define	BCM47XX_EXT_ID		0x4714		
+#define	BCM47XX_GMAC_ID		0x4715		
+#define	BCM47XX_USBH_ID		0x4716		
+#define	BCM47XX_USBD_ID		0x4717		
+#define	BCM47XX_IPSEC_ID	0x4718		
+#define	BCM47XX_ROBO_ID		0x4719		
+#define	BCM47XX_USB20H_ID	0x471a		
+#define	BCM47XX_USB20D_ID	0x471b		
+#define	BCM47XX_ATA100_ID	0x471d		
+#define	BCM47XX_SATAXOR_ID	0x471e		
+#define	BCM47XX_GIGETH_ID	0x471f		
+#define	BCM4712_MIPS_ID		0x4720		
+#define	BCM4716_DEVICE_ID	0x4722		
+#define	BCM47XX_USB30H_ID	0x472a		
+#define	BCM47XX_USB30D_ID	0x472b		
+#define BCM47XX_SMBUS_EMU_ID	0x47fe		
+#define	BCM47XX_XOR_EMU_ID	0x47ff		
+#define	EPI41210_DEVICE_ID	0xa0fa		
+#define	EPI41230_DEVICE_ID	0xa10e		
+#define JINVANI_SDIOH_ID	0x4743		
+#define BCM27XX_SDIOH_ID	0x2702		
+#define PCIXX21_FLASHMEDIA_ID	0x803b		
+#define PCIXX21_SDIOH_ID	0x803c		
+#define R5C822_SDIOH_ID		0x0822		
+#define JMICRON_SDIOH_ID	0x2381		
+
+
+#define	BCM4306_CHIP_ID		0x4306		
+#define	BCM4311_CHIP_ID		0x4311		
+#define	BCM43111_CHIP_ID	43111		
+#define	BCM43112_CHIP_ID	43112		
+#define	BCM4312_CHIP_ID		0x4312		
+#define BCM4313_CHIP_ID		0x4313		
+#define	BCM43131_CHIP_ID	43131		
+#define	BCM4315_CHIP_ID		0x4315		
+#define	BCM4318_CHIP_ID		0x4318		
+#define	BCM4319_CHIP_ID		0x4319		
+#define	BCM4320_CHIP_ID		0x4320		
+#define	BCM4321_CHIP_ID		0x4321		
+#define	BCM43217_CHIP_ID	43217		
+#define	BCM4322_CHIP_ID		0x4322		
+#define	BCM43221_CHIP_ID	43221		
+#define	BCM43222_CHIP_ID	43222		
+#define	BCM43224_CHIP_ID	43224		
+#define	BCM43225_CHIP_ID	43225		
+#define	BCM43227_CHIP_ID	43227		
+#define	BCM43228_CHIP_ID	43228		
+#define	BCM43226_CHIP_ID	43226		
+#define	BCM43231_CHIP_ID	43231		
+#define	BCM43234_CHIP_ID	43234		
+#define	BCM43235_CHIP_ID	43235		
+#define	BCM43236_CHIP_ID	43236		
+#define	BCM43237_CHIP_ID	43237		
+#define	BCM43238_CHIP_ID	43238		
+#define	BCM43239_CHIP_ID	43239		
+#define	BCM43420_CHIP_ID	43420		
+#define	BCM43421_CHIP_ID	43421		
+#define	BCM43428_CHIP_ID	43428		
+#define	BCM43431_CHIP_ID	43431		
+#define	BCM43460_CHIP_ID	43460		
+#define	BCM4325_CHIP_ID		0x4325		
+#define	BCM4328_CHIP_ID		0x4328		
+#define	BCM4329_CHIP_ID		0x4329		
+#define	BCM4331_CHIP_ID		0x4331		
+#define BCM4336_CHIP_ID		0x4336		
+#define BCM43362_CHIP_ID	43362		
+#define BCM4330_CHIP_ID		0x4330		
+#define BCM6362_CHIP_ID		0x6362		
+#define BCM4314_CHIP_ID		0x4314		
+#define BCM43142_CHIP_ID	43142		
+#define BCM43143_CHIP_ID	43143		
+#define	BCM4324_CHIP_ID		0x4324		
+#define	BCM43242_CHIP_ID	43242		
+#define	BCM43243_CHIP_ID	43243		
+#define BCM4334_CHIP_ID		0x4334		
+#define BCM4335_CHIP_ID		0x4335		
+#define BCM4339_CHIP_ID		0x4339		
+#define BCM43349_CHIP_ID	43349			
+#define BCM4360_CHIP_ID		0x4360          
+#define BCM4352_CHIP_ID		0x4352          
+#define BCM43526_CHIP_ID	0xAA06
+#define BCM43340_CHIP_ID	43340		
+#define BCM43341_CHIP_ID	43341		
+#define BCM43342_CHIP_ID	43342		
+#define BCM4350_CHIP_ID		0x4350          
+#define BCM4354_CHIP_ID		0x4354          
+#define BCM4356_CHIP_ID		0x4356          
+#define BCM43556_CHIP_ID	0xAA24          
+#define BCM43558_CHIP_ID	0xAA26          
+#define BCM43566_CHIP_ID	0xAA2E          
+#define BCM43568_CHIP_ID	0xAA30          
+#define BCM43569_CHIP_ID	0xAA31          
+#define BCM4350_CHIP(chipid)	((CHIPID(chipid) == BCM4350_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4354_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4356_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43556_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43558_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43566_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43568_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43569_CHIP_ID)) 
+#define BCM4345_CHIP_ID		0x4345		
+#define BCM43430_CHIP_ID	43430		
+
+#define BCM43602_CHIP_ID	0xaa52		
+
+#define	BCM4342_CHIP_ID		4342		
+#define	BCM4402_CHIP_ID		0x4402		
+#define	BCM4704_CHIP_ID		0x4704		
+#define	BCM4706_CHIP_ID		0x5300		
+#define BCM4707_CHIP_ID		53010		
+#define BCM53018_CHIP_ID	53018		
+#define BCM4707_CHIP(chipid)	(((chipid) == BCM4707_CHIP_ID) || ((chipid) == BCM53018_CHIP_ID))
+#define	BCM4710_CHIP_ID		0x4710		
+#define	BCM4712_CHIP_ID		0x4712		
+#define	BCM4716_CHIP_ID		0x4716		
+#define	BCM47162_CHIP_ID	47162		
+#define	BCM4748_CHIP_ID		0x4748		
+#define	BCM4749_CHIP_ID		0x4749		
+#define BCM4785_CHIP_ID		0x4785		
+#define	BCM5350_CHIP_ID		0x5350		
+#define	BCM5352_CHIP_ID		0x5352		
+#define	BCM5354_CHIP_ID		0x5354		
+#define BCM5365_CHIP_ID		0x5365		
+#define	BCM5356_CHIP_ID		0x5356		
+#define	BCM5357_CHIP_ID		0x5357		
+#define	BCM53572_CHIP_ID	53572		
+
+
+#define	BCM4303_PKG_ID		2		
+#define	BCM4309_PKG_ID		1		
+#define	BCM4712LARGE_PKG_ID	0		
+#define	BCM4712SMALL_PKG_ID	1		
+#define	BCM4712MID_PKG_ID	2		
+#define BCM4328USBD11G_PKG_ID	2		
+#define BCM4328USBDUAL_PKG_ID	3		
+#define BCM4328SDIOD11G_PKG_ID	4		
+#define BCM4328SDIODUAL_PKG_ID	5		
+#define BCM4329_289PIN_PKG_ID	0		
+#define BCM4329_182PIN_PKG_ID	1		
+#define BCM5354E_PKG_ID		1		
+#define	BCM4716_PKG_ID		8		
+#define	BCM4717_PKG_ID		9		
+#define	BCM4718_PKG_ID		10		
+#define BCM5356_PKG_NONMODE	1		
+#define BCM5358U_PKG_ID		8		
+#define BCM5358_PKG_ID		9		
+#define BCM47186_PKG_ID		10		
+#define BCM5357_PKG_ID		11		
+#define BCM5356U_PKG_ID		12		
+#define BCM53572_PKG_ID		8		
+#define BCM5357C0_PKG_ID	8		
+#define BCM47188_PKG_ID		9		
+#define BCM5358C0_PKG_ID	0xa		
+#define BCM5356C0_PKG_ID	0xb		
+#define BCM4331TT_PKG_ID        8		
+#define BCM4331TN_PKG_ID        9		
+#define BCM4331TNA0_PKG_ID     0xb		
+#define	BCM4706L_PKG_ID		1		
+
+#define HDLSIM5350_PKG_ID	1		
+#define HDLSIM_PKG_ID		14		
+#define HWSIM_PKG_ID		15		
+#define BCM43224_FAB_CSM	0x8		
+#define BCM43224_FAB_SMIC	0xa		
+#define BCM4336_WLBGA_PKG_ID	0x8
+#define BCM4330_WLBGA_PKG_ID	0x0
+#define BCM4314PCIE_ARM_PKG_ID		(8 | 0)	
+#define BCM4314SDIO_PKG_ID		(8 | 1)	
+#define BCM4314PCIE_PKG_ID		(8 | 2)	
+#define BCM4314SDIO_ARM_PKG_ID		(8 | 3)	
+#define BCM4314SDIO_FPBGA_PKG_ID	(8 | 4)	
+#define BCM4314DEV_PKG_ID		(8 | 6)	
+
+#define BCM4707_PKG_ID		1		
+#define BCM4708_PKG_ID		2		
+#define BCM4709_PKG_ID		0		
+
+#define PCIXX21_FLASHMEDIA0_ID	0x8033		
+#define PCIXX21_SDIOH0_ID	0x8034		
+
+#define BCM4335_WLCSP_PKG_ID	(0x0)	
+#define BCM4335_FCBGA_PKG_ID	(0x1)	
+#define BCM4335_WLBGA_PKG_ID	(0x2)	
+#define BCM4335_FCBGAD_PKG_ID	(0x3)	
+#define BCM4335_PKG_MASK	(0x3)
+
+
+#define	BFL_BTC2WIRE		0x00000001  
+#define BFL_BTCOEX      0x00000001      
+#define	BFL_PACTRL		0x00000002  
+#define BFL_AIRLINEMODE	0x00000004  
+#define	BFL_ADCDIV		0x00000008  
+#define BFL_DIS_256QAM		0x00000008
+#define	BFL_ENETROBO		0x00000010  
+#define	BFL_NOPLLDOWN		0x00000020  
+#define	BFL_CCKHIPWR		0x00000040  
+#define	BFL_ENETADM		0x00000080  
+#define	BFL_ENETVLAN		0x00000100  
+#define	BFL_UNUSED		0x00000200
+#define BFL_NOPCI		0x00000400  
+#define BFL_FEM			0x00000800  
+#define BFL_EXTLNA		0x00001000  
+#define BFL_HGPA		0x00002000  
+#define	BFL_BTC2WIRE_ALTGPIO	0x00004000  
+#define	BFL_ALTIQ		0x00008000  
+#define BFL_NOPA		0x00010000  
+#define BFL_RSSIINV		0x00020000  
+#define BFL_PAREF		0x00040000  
+#define BFL_3TSWITCH		0x00080000  
+#define BFL_PHASESHIFT		0x00100000  
+#define BFL_BUCKBOOST		0x00200000  
+#define BFL_FEM_BT		0x00400000  
+#define BFL_NOCBUCK		0x00800000  
+#define BFL_CCKFAVOREVM		0x01000000  
+#define BFL_PALDO		0x02000000  
+#define BFL_LNLDO2_2P5		0x04000000  
+#define BFL_FASTPWR		0x08000000
+#define BFL_UCPWRCTL_MININDX	0x08000000  
+#define BFL_EXTLNA_5GHz		0x10000000  
+#define BFL_TRSW_1by2		0x20000000  
+#define BFL_GAINBOOSTA01        0x20000000  
+#define BFL_LO_TRSW_R_5GHz	0x40000000  
+#define BFL_ELNA_GAINDEF	0x80000000  
+#define BFL_EXTLNA_TX	0x20000000	
+
+
+#define BFL2_RXBB_INT_REG_DIS	0x00000001  
+#define BFL2_APLL_WAR		0x00000002  
+#define BFL2_TXPWRCTRL_EN	0x00000004  
+#define BFL2_2X4_DIV		0x00000008  
+#define BFL2_5G_PWRGAIN		0x00000010  
+#define BFL2_PCIEWAR_OVR	0x00000020  
+#define BFL2_CAESERS_BRD	0x00000040  
+#define BFL2_BTC3WIRE		0x00000080  
+#define BFL2_BTCLEGACY          0x00000080  
+#define BFL2_SKWRKFEM_BRD	0x00000100  
+#define BFL2_SPUR_WAR		0x00000200  
+#define BFL2_GPLL_WAR		0x00000400  
+#define BFL2_TRISTATE_LED	0x00000800  
+#define BFL2_SINGLEANT_CCK	0x00001000  
+#define BFL2_2G_SPUR_WAR	0x00002000  
+#define BFL2_BPHY_ALL_TXCORES	0x00004000  
+#define BFL2_FCC_BANDEDGE_WAR	0x00008000  
+#define BFL2_DAC_SPUR_IMPROVEMENT 0x00008000       
+#define BFL2_GPLL_WAR2	        0x00010000  
+#define BFL2_IPALVLSHIFT_3P3    0x00020000
+#define BFL2_INTERNDET_TXIQCAL  0x00040000  
+#define BFL2_XTALBUFOUTEN       0x00080000  
+				
+				
+
+#define BFL2_ANAPACTRL_2G	0x00100000  
+#define BFL2_ANAPACTRL_5G	0x00200000  
+#define BFL2_ELNACTRL_TRSW_2G	0x00400000  
+#define BFL2_BT_SHARE_ANT0	0x00800000  
+#define BFL2_TEMPSENSE_HIGHER	0x01000000  
+#define BFL2_BTC3WIREONLY       0x02000000  
+#define BFL2_PWR_NOMINAL	0x04000000  
+#define BFL2_EXTLNA_PWRSAVE	0x08000000  
+						
+#define BFL2_4313_RADIOREG	0x10000000
+									   
+#define BFL2_DYNAMIC_VMID	0x10000000  
+
+#define BFL2_SDR_EN		0x20000000  
+#define BFL2_DYNAMIC_VMID	0x10000000  
+#define BFL2_LNA1BYPFORTR2G	0x40000000  
+#define BFL2_LNA1BYPFORTR5G	0x80000000  
+
+
+#define BFL_SROM11_BTCOEX  0x00000001  
+#define BFL_SROM11_WLAN_BT_SH_XTL  0x00000002  
+#define BFL_SROM11_EXTLNA	0x00001000  
+#define BFL_SROM11_EXTLNA_5GHz	0x10000000  
+#define BFL_SROM11_GAINBOOSTA01	0x20000000  
+#define BFL2_SROM11_APLL_WAR	0x00000002  
+#define BFL2_SROM11_ANAPACTRL_2G  0x00100000  
+#define BFL2_SROM11_ANAPACTRL_5G  0x00200000  
+#define BFL2_SROM11_SINGLEANT_CCK	0x00001000  
+
+
+#define BFL3_FEMCTRL_SUB	  0x00000007  
+#define BFL3_RCAL_WAR		  0x00000008  
+#define BFL3_TXGAINTBLID	  0x00000070  
+#define BFL3_TXGAINTBLID_SHIFT	  0x4         
+#define BFL3_TSSI_DIV_WAR	  0x00000080  
+#define BFL3_TSSI_DIV_WAR_SHIFT	  0x7         
+#define BFL3_FEMTBL_FROM_NVRAM    0x00000100  
+#define BFL3_FEMTBL_FROM_NVRAM_SHIFT 0x8         
+#define BFL3_AGC_CFG_2G           0x00000200  
+#define BFL3_AGC_CFG_5G           0x00000400  
+#define BFL3_PPR_BIT_EXT          0x00000800  
+#define BFL3_PPR_BIT_EXT_SHIFT    11          
+#define BFL3_BBPLL_SPR_MODE_DIS	  0x00001000  
+#define BFL3_RCAL_OTP_VAL_EN      0x00002000  
+#define BFL3_2GTXGAINTBL_BLANK	  0x00004000  
+#define BFL3_2GTXGAINTBL_BLANK_SHIFT 14       
+#define BFL3_5GTXGAINTBL_BLANK	  0x00008000  
+#define BFL3_5GTXGAINTBL_BLANK_SHIFT 15       
+#define BFL3_PHASETRACK_MAX_ALPHABETA	  0x00010000  
+#define BFL3_PHASETRACK_MAX_ALPHABETA_SHIFT 16       
+
+#define BFL3_LTECOEX_GAINTBL_EN           0x00060000
+
+#define BFL3_LTECOEX_GAINTBL_EN_SHIFT 17
+#define BFL3_5G_SPUR_WAR          0x00080000  
+
+
+#define BFL3_ACPHY_LPMODE_2G	  0x00300000  
+#define BFL3_ACPHY_LPMODE_2G_SHIFT	  20
+
+#define BFL3_ACPHY_LPMODE_5G	  0x00C00000  
+#define BFL3_ACPHY_LPMODE_5G_SHIFT	  22
+
+#define BFL3_EXT_LPO_ISCLOCK      0x02000000  
+#define BFL3_FORCE_INT_LPO_SEL    0x04000000  
+#define BFL3_FORCE_EXT_LPO_SEL    0x08000000  
+
+#define BFL3_EN_BRCM_IMPBF        0x10000000  
+#define BFL3_AVVMID_FROM_NVRAM    0x40000000  
+#define BFL3_VLIN_EN_FROM_NVRAM    0x80000000  
+
+#define BFL3_AVVMID_FROM_NVRAM_SHIFT   30   
+#define BFL3_VLIN_EN_FROM_NVRAM_SHIFT   31   
+
+
+
+#define	BOARD_GPIO_BTC3W_IN	0x850	
+#define	BOARD_GPIO_BTC3W_OUT	0x020	
+#define	BOARD_GPIO_BTCMOD_IN	0x010	
+#define	BOARD_GPIO_BTCMOD_OUT	0x020	
+#define	BOARD_GPIO_BTC_IN	0x080	
+#define	BOARD_GPIO_BTC_OUT	0x100	
+#define	BOARD_GPIO_PACTRL	0x200	
+#define BOARD_GPIO_12		0x1000	
+#define BOARD_GPIO_13		0x2000	
+#define BOARD_GPIO_BTC4_IN	0x0800	
+#define BOARD_GPIO_BTC4_BT	0x2000	
+#define BOARD_GPIO_BTC4_STAT	0x4000	
+#define BOARD_GPIO_BTC4_WLAN	0x8000	
+#define	BOARD_GPIO_1_WLAN_PWR	0x02	
+#define	BOARD_GPIO_2_WLAN_PWR	0x04	
+#define	BOARD_GPIO_3_WLAN_PWR	0x08	
+#define	BOARD_GPIO_4_WLAN_PWR	0x10	
+
+#define GPIO_BTC4W_OUT_4312  0x010  
+#define GPIO_BTC4W_OUT_43224  0x020  
+#define GPIO_BTC4W_OUT_43224_SHARED  0x0e0  
+#define GPIO_BTC4W_OUT_43225  0x0e0  
+#define GPIO_BTC4W_OUT_43421  0x020  
+#define GPIO_BTC4W_OUT_4313  0x060  
+#define GPIO_BTC4W_OUT_4331_SHARED  0x010  
+
+#define	PCI_CFG_GPIO_SCS	0x10	
+#define PCI_CFG_GPIO_HWRAD	0x20	
+#define PCI_CFG_GPIO_XTAL	0x40	
+#define PCI_CFG_GPIO_PLL	0x80	
+
+
+#define PLL_DELAY		150		
+#define FREF_DELAY		200		
+#define MIN_SLOW_CLK		32		
+#define	XTAL_ON_DELAY		1000		
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+#define	BU4710_BOARD		0x0400
+#define	VSIM4710_BOARD		0x0401
+#define	QT4710_BOARD		0x0402
+
+#define	BU4309_BOARD		0x040a
+#define	BCM94309CB_BOARD	0x040b
+#define	BCM94309MP_BOARD	0x040c
+#define	BCM4309AP_BOARD		0x040d
+
+#define	BCM94302MP_BOARD	0x040e
+
+#define	BU4306_BOARD		0x0416
+#define	BCM94306CB_BOARD	0x0417
+#define	BCM94306MP_BOARD	0x0418
+
+#define	BCM94710D_BOARD		0x041a
+#define	BCM94710R1_BOARD	0x041b
+#define	BCM94710R4_BOARD	0x041c
+#define	BCM94710AP_BOARD	0x041d
+
+#define	BU2050_BOARD		0x041f
+
+#define	BCM94306P50_BOARD	0x0420
+
+#define	BCM94309G_BOARD		0x0421
+
+#define	BU4704_BOARD		0x0423
+#define	BU4702_BOARD		0x0424
+
+#define	BCM94306PC_BOARD	0x0425		
+
+#define	MPSG4306_BOARD		0x0427
+
+#define	BCM94702MN_BOARD	0x0428
+
+
+#define	BCM94702CPCI_BOARD	0x0429
+
+
+#define	BCM95380RR_BOARD	0x042a
+
+
+#define	BCM94306CBSG_BOARD	0x042b
+
+
+#define	PCSG94306_BOARD		0x042d
+
+
+#define	BU4704SD_BOARD		0x042e
+
+
+#define	BCM94704AGR_BOARD	0x042f
+
+
+#define	BCM94308MP_BOARD	0x0430
+
+
+#define	BCM94306GPRS_BOARD	0x0432
+
+
+#define BU5365_FPGA_BOARD	0x0433
+
+#define BU4712_BOARD		0x0444
+#define	BU4712SD_BOARD		0x045d
+#define	BU4712L_BOARD		0x045f
+
+
+#define BCM94712AP_BOARD	0x0445
+#define BCM94712P_BOARD		0x0446
+
+
+#define BU4318_BOARD		0x0447
+#define CB4318_BOARD		0x0448
+#define MPG4318_BOARD		0x0449
+#define MP4318_BOARD		0x044a
+#define SD4318_BOARD		0x044b
+
+
+#define BCM94313BU_BOARD	0x050f
+#define BCM94313HM_BOARD	0x0510
+#define BCM94313EPA_BOARD	0x0511
+#define BCM94313HMG_BOARD       0x051C
+
+
+#define BCM96338_BOARD		0x6338
+#define BCM96348_BOARD		0x6348
+#define BCM96358_BOARD		0x6358
+#define BCM96368_BOARD		0x6368
+
+
+#define	BCM94306P_BOARD		0x044c
+
+
+#define	BCM94303MP_BOARD	0x044e
+
+
+#define	BCM94306MPSGH_BOARD	0x044f
+
+
+#define BCM94306MPM		0x0450
+#define BCM94306MPL		0x0453
+
+
+#define	BCM94712AGR_BOARD	0x0451
+
+
+#define	PC4303_BOARD		0x0454
+
+
+#define	BCM95350K_BOARD		0x0455
+
+
+#define	BCM95350R_BOARD		0x0456
+
+
+#define	BCM94306MPLNA_BOARD	0x0457
+
+
+#define	BU4320_BOARD		0x0458
+#define	BU4320S_BOARD		0x0459
+#define	BCM94320PH_BOARD	0x045a
+
+
+#define	BCM94306MPH_BOARD	0x045b
+
+
+#define	BCM94306PCIV_BOARD	0x045c
+
+#define	BU4712SD_BOARD		0x045d
+
+#define	BCM94320PFLSH_BOARD	0x045e
+
+#define	BU4712L_BOARD		0x045f
+#define	BCM94712LGR_BOARD	0x0460
+#define	BCM94320R_BOARD		0x0461
+
+#define	BU5352_BOARD		0x0462
+
+#define	BCM94318MPGH_BOARD	0x0463
+
+#define	BU4311_BOARD		0x0464
+#define	BCM94311MC_BOARD	0x0465
+#define	BCM94311MCAG_BOARD	0x0466
+
+#define	BCM95352GR_BOARD	0x0467
+
+
+#define	BCM95351AGR_BOARD	0x0470
+
+
+#define	BCM94704MPCB_BOARD	0x0472
+
+
+#define BU4785_BOARD		0x0478
+
+
+#define BU4321_BOARD		0x046b
+#define BU4321E_BOARD		0x047c
+#define MP4321_BOARD		0x046c
+#define CB2_4321_BOARD		0x046d
+#define CB2_4321_AG_BOARD	0x0066
+#define MC4321_BOARD		0x046e
+
+
+#define BU4328_BOARD		0x0481
+#define BCM4328SDG_BOARD	0x0482
+#define BCM4328SDAG_BOARD	0x0483
+#define BCM4328UG_BOARD		0x0484
+#define BCM4328UAG_BOARD	0x0485
+#define BCM4328PC_BOARD		0x0486
+#define BCM4328CF_BOARD		0x0487
+
+
+#define BCM94325DEVBU_BOARD	0x0490
+#define BCM94325BGABU_BOARD	0x0491
+
+#define BCM94325SDGWB_BOARD	0x0492
+
+#define BCM94325SDGMDL_BOARD	0x04aa
+#define BCM94325SDGMDL2_BOARD	0x04c6
+#define BCM94325SDGMDL3_BOARD	0x04c9
+
+#define BCM94325SDABGWBA_BOARD	0x04e1
+
+
+#define BCM94322MC_SSID		0x04a4
+#define BCM94322USB_SSID	0x04a8	
+#define BCM94322HM_SSID		0x04b0
+#define BCM94322USB2D_SSID	0x04bf	
+
+
+#define	BCM4312MCGSG_BOARD	0x04b5
+
+
+#define BCM94315DEVBU_SSID	0x04c2
+#define BCM94315USBGP_SSID	0x04c7
+#define BCM94315BGABU_SSID	0x04ca
+#define BCM94315USBGP41_SSID	0x04cb
+
+
+#define BCM94319DEVBU_SSID	0X04e5
+#define BCM94319USB_SSID	0X04e6
+#define BCM94319SD_SSID		0X04e7
+
+
+#define BCM94716NR2_SSID	0x04cd
+
+
+#define BCM94319DEVBU_SSID	0X04e5
+#define BCM94319USBNP4L_SSID	0X04e6
+#define BCM94319WLUSBN4L_SSID	0X04e7
+#define BCM94319SDG_SSID	0X04ea
+#define BCM94319LCUSBSDN4L_SSID	0X04eb
+#define BCM94319USBB_SSID       0x04ee
+#define BCM94319LCSDN4L_SSID	0X0507
+#define BCM94319LSUSBN4L_SSID	0X0508
+#define BCM94319SDNA4L_SSID	0X0517
+#define BCM94319SDELNA4L_SSID	0X0518
+#define BCM94319SDELNA6L_SSID	0X0539
+#define BCM94319ARCADYAN_SSID	0X0546
+#define BCM94319WINDSOR_SSID    0x0561
+#define BCM94319MLAP_SSID       0x0562
+#define BCM94319SDNA_SSID       0x058b
+#define BCM94319BHEMU3_SSID     0x0563
+#define BCM94319SDHMB_SSID     0x058c
+#define BCM94319SDBREF_SSID     0x05a1
+#define BCM94319USBSDB_SSID     0x05a2
+
+
+
+#define BCM94329AGB_SSID	0X04b9
+#define BCM94329TDKMDL1_SSID	0X04ba
+#define BCM94329TDKMDL11_SSID	0X04fc
+#define BCM94329OLYMPICN18_SSID	0X04fd
+#define BCM94329OLYMPICN90_SSID	0X04fe
+#define BCM94329OLYMPICN90U_SSID 0X050c
+#define BCM94329OLYMPICN90M_SSID 0X050b
+#define BCM94329AGBF_SSID	0X04ff
+#define BCM94329OLYMPICX17_SSID	0X0504
+#define BCM94329OLYMPICX17M_SSID	0X050a
+#define BCM94329OLYMPICX17U_SSID	0X0509
+#define BCM94329OLYMPICUNO_SSID	0X0564
+#define BCM94329MOTOROLA_SSID   0X0565
+#define BCM94329OLYMPICLOCO_SSID	0X0568
+
+#define BCM94336SD_WLBGABU_SSID		0x0511
+#define BCM94336SD_WLBGAREF_SSID	0x0519
+#define BCM94336SDGP_SSID	0x0538
+#define BCM94336SDG_SSID	0x0519
+#define BCM94336SDGN_SSID	0x0538
+#define BCM94336SDGFC_SSID	0x056B
+
+
+#define BCM94330SDG_SSID	0x0528
+#define BCM94330SD_FCBGABU_SSID	0x052e
+#define BCM94330SD_WLBGABU_SSID	0x052f
+#define BCM94330SD_FCBGA_SSID	0x0530
+#define BCM94330FCSDAGB_SSID		0x0532
+#define BCM94330OLYMPICAMG_SSID		0x0549
+#define BCM94330OLYMPICAMGEPA_SSID		0x054F
+#define BCM94330OLYMPICUNO3_SSID	0x0551
+#define BCM94330WLSDAGB_SSID	0x0547
+#define BCM94330CSPSDAGBB_SSID	0x054A
+
+
+#define BCM943224X21        0x056e
+#define BCM943224X21_FCC    0x00d1
+#define BCM943224X21B	    0x00e9
+#define BCM943224M93	    0x008b
+#define BCM943224M93A	    0x0090
+#define BCM943224X16	    0x0093
+#define BCM94322X9		    0x008d
+#define BCM94322M35e	    0x008e
+
+
+#define BCM943228BU8_SSID	0x0540
+#define BCM943228BU9_SSID	0x0541
+#define BCM943228BU_SSID	0x0542
+#define BCM943227HM4L_SSID	0x0543
+#define BCM943227HMB_SSID	0x0544
+#define BCM943228HM4L_SSID	0x0545
+#define BCM943228SD_SSID	0x0573
+
+
+#define BCM943239MOD_SSID	0x05ac
+#define BCM943239REF_SSID	0x05aa
+
+
+#define BCM94331X19               0x00D6	
+#define BCM94331X28               0x00E4	
+#define BCM94331X28B              0x010E	
+#define BCM94331PCIEBT3Ax_SSID    BCM94331X28
+#define BCM94331X12_2G_SSID       0x00EC	
+#define BCM94331X12_5G_SSID       0x00ED	
+#define BCM94331X29B              0x00EF	
+#define BCM94331X29D              0x010F	
+#define BCM94331CSAX_SSID         BCM94331X29B
+#define BCM94331X19C              0x00F5	
+#define BCM94331X33	          0x00F4	
+#define BCM94331BU_SSID           0x0523
+#define BCM94331S9BU_SSID         0x0524
+#define BCM94331MC_SSID           0x0525
+#define BCM94331MCI_SSID          0x0526
+#define BCM94331PCIEBT4_SSID      0x0527
+#define BCM94331HM_SSID           0x0574
+#define BCM94331PCIEDUAL_SSID     0x059B
+#define BCM94331MCH5_SSID         0x05A9
+#define BCM94331CS_SSID           0x05C6
+#define BCM94331CD_SSID           0x05DA
+
+
+#define BCM94314BU_SSID         0x05b1
+
+
+#define BCM953572BU_SSID       0x058D
+#define BCM953572NR2_SSID      0x058E
+#define BCM947188NR2_SSID      0x058F
+#define BCM953572SDRNR2_SSID   0x0590
+
+
+#define BCM943236OLYMPICSULLEY_SSID 0x594
+#define BCM943236PREPROTOBLU2O3_SSID 0x5b9
+#define BCM943236USBELNA_SSID 0x5f8
+
+
+#define BCM94314BUSDIO_SSID	0x05c8
+#define BCM94314BGABU_SSID	0x05c9
+#define BCM94314HMEPA_SSID	0x05ca
+#define BCM94314HMEPABK_SSID	0x05cb
+#define BCM94314SUHMEPA_SSID	0x05cc
+#define BCM94314SUHM_SSID	0x05cd
+#define BCM94314HM_SSID		0x05d1
+
+
+#define BCM94334FCAGBI_SSID	0x05df
+#define BCM94334WLAGBI_SSID	0x05dd
+
+
+#define BCM94335X52             0x0114
+
+
+#define BCM94345_SSID           0x0687
+
+
+#define BCM94360X52C            0X0117
+#define BCM94360X52D            0X0137
+#define BCM94360X29C            0X0112
+#define BCM94360X29CP2          0X1000
+#define BCM94360X51             0x0111
+#define BCM94360X51P2           0x0129
+#define BCM94360X51A            0x0135
+#define BCM94360X51B            0x0136
+#define BCM94360CS              0x061B
+#define BCM94360J28_D11AC2G     0x0c00
+#define BCM94360J28_D11AC5G     0x0c01
+
+
+#define BCM94350X52B            0X0116
+
+
+#define BCM943217BU_SSID	0x05d5
+#define BCM943217HM2L_SSID	0x05d6
+#define BCM943217HMITR2L_SSID	0x05d7
+
+
+#define BCM943142HM_SSID	0x05e0
+#endif 
+
+
+#define BCM943341WLABGS_SSID	0x062d
+
+
+#define BCM943342FCAGBI_SSID	0x0641
+
+
+#define BCM943602RSVD1_SSID	0x06a5
+#define BCM943602RSVD2_SSID	0x06a6
+
+
+#define GPIO_NUMPINS		32
+
+
+#define RDL_RAM_BASE_4319 0x60000000
+#define RDL_RAM_BASE_4329 0x60000000
+#define RDL_RAM_SIZE_4319 0x48000
+#define RDL_RAM_SIZE_4329  0x48000
+#define RDL_RAM_SIZE_43236 0x70000
+#define RDL_RAM_BASE_43236 0x60000000
+#define RDL_RAM_SIZE_4328 0x60000
+#define RDL_RAM_BASE_4328 0x80000000
+#define RDL_RAM_SIZE_4322 0x60000
+#define RDL_RAM_BASE_4322 0x60000000
+#define RDL_RAM_SIZE_4360  0xA0000
+#define RDL_RAM_BASE_4360  0x60000000
+#define RDL_RAM_SIZE_43242  0x90000
+#define RDL_RAM_BASE_43242  0x60000000
+#define RDL_RAM_SIZE_43143  0x70000
+#define RDL_RAM_BASE_43143  0x60000000
+#define RDL_RAM_SIZE_4350  0xC0000
+#define RDL_RAM_BASE_4350  0x180800
+
+
+#define MUXENAB_UART		0x00000001
+#define MUXENAB_GPIO		0x00000002
+#define MUXENAB_ERCX		0x00000004	
+#define MUXENAB_JTAG		0x00000008
+#define MUXENAB_HOST_WAKE	0x00000010	
+#define MUXENAB_I2S_EN		0x00000020
+#define MUXENAB_I2S_MASTER	0x00000040
+#define MUXENAB_I2S_FULL	0x00000080
+#define MUXENAB_SFLASH		0x00000100
+#define MUXENAB_RFSWCTRL0	0x00000200
+#define MUXENAB_RFSWCTRL1	0x00000400
+#define MUXENAB_RFSWCTRL2	0x00000800
+#define MUXENAB_SECI		0x00001000
+#define MUXENAB_BT_LEGACY	0x00002000
+#define MUXENAB_HOST_WAKE1	0x00004000	
+
+
+#define FLASH_KERNEL_NFLASH	0x00000001
+#define FLASH_BOOT_NFLASH	0x00000002
+
+#endif 
diff --git a/src/include/bcmendian.h b/src/include/bcmendian.h
new file mode 100644
index 0000000..8a510d0
--- /dev/null
+++ b/src/include/bcmendian.h
@@ -0,0 +1,290 @@
+/*
+ * Byte order utilities
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ *  $Id: bcmendian.h 402715 2013-05-16 18:50:09Z $
+ *
+ * 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/bcmnvram.h b/src/include/bcmnvram.h
new file mode 100644
index 0000000..8182480
--- /dev/null
+++ b/src/include/bcmnvram.h
@@ -0,0 +1,181 @@
+/*
+ * NVRAM variable manipulation
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmnvram.h 428512 2013-10-09 02:12:11Z $
+ */
+
+#ifndef _bcmnvram_h_
+#define _bcmnvram_h_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+
+struct nvram_header {
+	uint32 magic;
+	uint32 len;
+	uint32 crc_ver_init;	
+	uint32 config_refresh;	
+	uint32 config_ncdl;	
+};
+
+struct nvram_tuple {
+	char *name;
+	char *value;
+	struct nvram_tuple *next;
+};
+
+
+extern char *nvram_default_get(const char *name);
+
+extern void nvram_validate_all(char *prefix, bool restore);
+
+
+extern void nvram_restore_var(char *prefix, char *name);
+
+
+extern int nvram_init(void *sih);
+extern int nvram_deinit(void *sih);
+
+
+
+extern int nvram_append(void *si, char *vars, uint varsz);
+
+extern void nvram_get_global_vars(char **varlst, uint *varsz);
+
+
+
+extern int nvram_reset(void *sih);
+
+
+extern void nvram_exit(void *sih);
+
+
+extern char * nvram_get(const char *name);
+
+
+extern int BCMINITFN(nvram_resetgpio_init)(void *sih);
+
+
+static INLINE char *
+nvram_safe_get(const char *name)
+{
+	char *p = nvram_get(name);
+	return p ? p : "";
+}
+
+
+static INLINE int
+nvram_match(const char *name, const char *match)
+{
+	const char *value = nvram_get(name);
+	return (value && !strcmp(value, match));
+}
+
+
+static INLINE int
+nvram_invmatch(const char *name, const char *invmatch)
+{
+	const char *value = nvram_get(name);
+	return (value && strcmp(value, invmatch));
+}
+
+
+extern int nvram_set(const char *name, const char *value);
+
+
+extern int nvram_unset(const char *name);
+
+
+extern int nvram_commit_internal(bool nvram_corrupt);
+
+
+extern int nvram_commit(void);
+
+
+extern int nvram_getall(char *nvram_buf, int count);
+
+
+uint8 nvram_calc_crc(struct nvram_header * nvh);
+
+extern int nvram_space;
+#endif 
+
+
+#define NVRAM_SOFTWARE_VERSION	"1"
+
+#define NVRAM_MAGIC		0x48534C46	
+#define NVRAM_CLEAR_MAGIC	0x0
+#define NVRAM_INVALID_MAGIC	0xFFFFFFFF
+#define NVRAM_VERSION		1
+#define NVRAM_HEADER_SIZE	20
+
+#define NVRAM_SPACE		0x8000
+
+#ifndef MAX_NVRAM_SPACE
+#define MAX_NVRAM_SPACE		0x10000
+#endif
+#define DEF_NVRAM_SPACE		0x8000
+#define ROM_ENVRAM_SPACE	0x1000
+#define NVRAM_LZMA_MAGIC	0x4c5a4d41	
+
+#define NVRAM_MAX_VALUE_LEN 255
+#define NVRAM_MAX_PARAM_LEN 64
+
+#define NVRAM_CRC_START_POSITION	9 
+#define NVRAM_CRC_VER_MASK	0xffffff00 
+
+
+#define NVRAM_START_COMPRESSED	0x400
+#define NVRAM_START		0x1000
+
+#define BCM_JUMBO_NVRAM_DELIMIT '\n'
+#define BCM_JUMBO_START "Broadcom Jumbo Nvram file"
+
+
+#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \
+	defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__))
+#define IMAGE_SIZE "image_size"
+#define BOOTPARTITION "bootpartition"
+#define IMAGE_BOOT BOOTPARTITION
+#define PARTIALBOOTS "partialboots"
+#define MAXPARTIALBOOTS "maxpartialboots"
+#define IMAGE_1ST_FLASH_TRX "flash0.trx"
+#define IMAGE_1ST_FLASH_OS "flash0.os"
+#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
+#define IMAGE_2ND_FLASH_OS "flash0.os2"
+#define IMAGE_FIRST_OFFSET "image_first_offset"
+#define IMAGE_SECOND_OFFSET "image_second_offset"
+#define LINUX_FIRST "linux"
+#define LINUX_SECOND "linux2"
+#endif
+
+#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \
+	defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__))
+
+#define IMAGE_BOOT "image_boot"
+#define BOOTPARTITION IMAGE_BOOT
+
+#define IMAGE_1ST_FLASH_TRX "flash0.trx"
+#define IMAGE_1ST_FLASH_OS "flash0.os"
+#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
+#define IMAGE_2ND_FLASH_OS "flash0.os2"
+#define IMAGE_SIZE "image_size"
+
+
+#define IMAGE_FIRST_OFFSET "image_first_offset"
+#define IMAGE_SECOND_OFFSET "image_second_offset"
+
+
+#define LINUX_FIRST "linux"
+#define LINUX_SECOND "linux2"
+#define POLICY_TOGGLE "toggle"
+#define LINUX_PART_TO_FLASH "linux_to_flash"
+#define LINUX_FLASH_POLICY "linux_flash_policy"
+
+#endif 
+
+#endif 
diff --git a/src/include/bcmsrom_fmt.h b/src/include/bcmsrom_fmt.h
new file mode 100644
index 0000000..d5ac414
--- /dev/null
+++ b/src/include/bcmsrom_fmt.h
@@ -0,0 +1,615 @@
+/*
+ * SROM format definition.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmsrom_fmt.h 427005 2013-10-02 00:15:10Z $
+ */
+
+#ifndef	_bcmsrom_fmt_h_
+#define	_bcmsrom_fmt_h_
+
+#define SROM_MAXREV		11	/* max revisiton supported by driver */
+
+/* Maximum srom: 6 Kilobits == 768 bytes */
+#define	SROM_MAX		768
+#define SROM_MAXW		384
+#define VARS_MAX		4096
+
+/* PCI fields */
+#define PCI_F0DEVID		48
+
+
+#define	SROM_WORDS		64
+
+#define SROM3_SWRGN_OFF		28	/* s/w region offset in words */
+
+#define	SROM_SSID		2
+#define	SROM_SVID		3
+
+#define	SROM_WL1LHMAXP		29
+
+#define	SROM_WL1LPAB0		30
+#define	SROM_WL1LPAB1		31
+#define	SROM_WL1LPAB2		32
+
+#define	SROM_WL1HPAB0		33
+#define	SROM_WL1HPAB1		34
+#define	SROM_WL1HPAB2		35
+
+#define	SROM_MACHI_IL0		36
+#define	SROM_MACMID_IL0		37
+#define	SROM_MACLO_IL0		38
+#define	SROM_MACHI_ET0		39
+#define	SROM_MACMID_ET0		40
+#define	SROM_MACLO_ET0		41
+#define	SROM_MACHI_ET1		42
+#define	SROM_MACMID_ET1		43
+#define	SROM_MACLO_ET1		44
+#define	SROM3_MACHI		37
+#define	SROM3_MACMID		38
+#define	SROM3_MACLO		39
+
+#define	SROM_BXARSSI2G		40
+#define	SROM_BXARSSI5G		41
+
+#define	SROM_TRI52G		42
+#define	SROM_TRI5GHL		43
+
+#define	SROM_RXPO52G		45
+
+#define	SROM2_ENETPHY		45
+
+#define	SROM_AABREV		46
+/* Fields in AABREV */
+#define	SROM_BR_MASK		0x00ff
+#define	SROM_CC_MASK		0x0f00
+#define	SROM_CC_SHIFT		8
+#define	SROM_AA0_MASK		0x3000
+#define	SROM_AA0_SHIFT		12
+#define	SROM_AA1_MASK		0xc000
+#define	SROM_AA1_SHIFT		14
+
+#define	SROM_WL0PAB0		47
+#define	SROM_WL0PAB1		48
+#define	SROM_WL0PAB2		49
+
+#define	SROM_LEDBH10		50
+#define	SROM_LEDBH32		51
+
+#define	SROM_WL10MAXP		52
+
+#define	SROM_WL1PAB0		53
+#define	SROM_WL1PAB1		54
+#define	SROM_WL1PAB2		55
+
+#define	SROM_ITT		56
+
+#define	SROM_BFL		57
+#define	SROM_BFL2		28
+#define	SROM3_BFL2		61
+
+#define	SROM_AG10		58
+
+#define	SROM_CCODE		59
+
+#define	SROM_OPO		60
+
+#define	SROM3_LEDDC		62
+
+#define	SROM_CRCREV		63
+
+/* SROM Rev 4: Reallocate the software part of the srom to accomodate
+ * MIMO features. It assumes up to two PCIE functions and 440 bytes
+ * of useable srom i.e. the useable storage in chips with OTP that
+ * implements hardware redundancy.
+ */
+
+#define	SROM4_WORDS		220
+
+#define	SROM4_SIGN		32
+#define	SROM4_SIGNATURE		0x5372
+
+#define	SROM4_BREV		33
+
+#define	SROM4_BFL0		34
+#define	SROM4_BFL1		35
+#define	SROM4_BFL2		36
+#define	SROM4_BFL3		37
+#define	SROM5_BFL0		37
+#define	SROM5_BFL1		38
+#define	SROM5_BFL2		39
+#define	SROM5_BFL3		40
+
+#define	SROM4_MACHI		38
+#define	SROM4_MACMID		39
+#define	SROM4_MACLO		40
+#define	SROM5_MACHI		41
+#define	SROM5_MACMID		42
+#define	SROM5_MACLO		43
+
+#define	SROM4_CCODE		41
+#define	SROM4_REGREV		42
+#define	SROM5_CCODE		34
+#define	SROM5_REGREV		35
+
+#define	SROM4_LEDBH10		43
+#define	SROM4_LEDBH32		44
+#define	SROM5_LEDBH10		59
+#define	SROM5_LEDBH32		60
+
+#define	SROM4_LEDDC		45
+#define	SROM5_LEDDC		45
+
+#define	SROM4_AA		46
+#define	SROM4_AA2G_MASK		0x00ff
+#define	SROM4_AA2G_SHIFT	0
+#define	SROM4_AA5G_MASK		0xff00
+#define	SROM4_AA5G_SHIFT	8
+
+#define	SROM4_AG10		47
+#define	SROM4_AG32		48
+
+#define	SROM4_TXPID2G		49
+#define	SROM4_TXPID5G		51
+#define	SROM4_TXPID5GL		53
+#define	SROM4_TXPID5GH		55
+
+#define SROM4_TXRXC		61
+#define SROM4_TXCHAIN_MASK	0x000f
+#define SROM4_TXCHAIN_SHIFT	0
+#define SROM4_RXCHAIN_MASK	0x00f0
+#define SROM4_RXCHAIN_SHIFT	4
+#define SROM4_SWITCH_MASK	0xff00
+#define SROM4_SWITCH_SHIFT	8
+
+
+/* Per-path fields */
+#define	MAX_PATH_SROM		4
+#define	SROM4_PATH0		64
+#define	SROM4_PATH1		87
+#define	SROM4_PATH2		110
+#define	SROM4_PATH3		133
+
+#define	SROM4_2G_ITT_MAXP	0
+#define	SROM4_2G_PA		1
+#define	SROM4_5G_ITT_MAXP	5
+#define	SROM4_5GLH_MAXP		6
+#define	SROM4_5G_PA		7
+#define	SROM4_5GL_PA		11
+#define	SROM4_5GH_PA		15
+
+/* Fields in the ITT_MAXP and 5GLH_MAXP words */
+#define	B2G_MAXP_MASK		0xff
+#define	B2G_ITT_SHIFT		8
+#define	B5G_MAXP_MASK		0xff
+#define	B5G_ITT_SHIFT		8
+#define	B5GH_MAXP_MASK		0xff
+#define	B5GL_MAXP_SHIFT		8
+
+/* All the miriad power offsets */
+#define	SROM4_2G_CCKPO		156
+#define	SROM4_2G_OFDMPO		157
+#define	SROM4_5G_OFDMPO		159
+#define	SROM4_5GL_OFDMPO	161
+#define	SROM4_5GH_OFDMPO	163
+#define	SROM4_2G_MCSPO		165
+#define	SROM4_5G_MCSPO		173
+#define	SROM4_5GL_MCSPO		181
+#define	SROM4_5GH_MCSPO		189
+#define	SROM4_CDDPO		197
+#define	SROM4_STBCPO		198
+#define	SROM4_BW40PO		199
+#define	SROM4_BWDUPPO		200
+
+#define	SROM4_CRCREV		219
+
+
+/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
+ * This is acombined srom for both MIMO and SISO boards, usable in
+ * the .130 4Kilobit OTP with hardware redundancy.
+ */
+
+#define	SROM8_SIGN		64
+
+#define	SROM8_BREV		65
+
+#define	SROM8_BFL0		66
+#define	SROM8_BFL1		67
+#define	SROM8_BFL2		68
+#define	SROM8_BFL3		69
+
+#define	SROM8_MACHI		70
+#define	SROM8_MACMID		71
+#define	SROM8_MACLO		72
+
+#define	SROM8_CCODE		73
+#define	SROM8_REGREV		74
+
+#define	SROM8_LEDBH10		75
+#define	SROM8_LEDBH32		76
+
+#define	SROM8_LEDDC		77
+
+#define	SROM8_AA		78
+
+#define	SROM8_AG10		79
+#define	SROM8_AG32		80
+
+#define	SROM8_TXRXC		81
+
+#define	SROM8_BXARSSI2G		82
+#define	SROM8_BXARSSI5G		83
+#define	SROM8_TRI52G		84
+#define	SROM8_TRI5GHL		85
+#define	SROM8_RXPO52G		86
+
+#define SROM8_FEM2G		87
+#define SROM8_FEM5G		88
+#define SROM8_FEM_ANTSWLUT_MASK		0xf800
+#define SROM8_FEM_ANTSWLUT_SHIFT	11
+#define SROM8_FEM_TR_ISO_MASK		0x0700
+#define SROM8_FEM_TR_ISO_SHIFT		8
+#define SROM8_FEM_PDET_RANGE_MASK	0x00f8
+#define SROM8_FEM_PDET_RANGE_SHIFT	3
+#define SROM8_FEM_EXTPA_GAIN_MASK	0x0006
+#define SROM8_FEM_EXTPA_GAIN_SHIFT	1
+#define SROM8_FEM_TSSIPOS_MASK		0x0001
+#define SROM8_FEM_TSSIPOS_SHIFT		0
+
+#define SROM8_THERMAL		89
+
+/* Temp sense related entries */
+#define SROM8_MPWR_RAWTS		90
+#define SROM8_TS_SLP_OPT_CORRX	91
+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
+#define SROM8_FOC_HWIQ_IQSWP	92
+
+#define SROM8_EXTLNAGAIN        93
+
+/* Temperature delta for PHY calibration */
+#define SROM8_PHYCAL_TEMPDELTA	94
+
+/* Measured power 1 & 2, 0-13 bits at offset 95, MSB 2 bits are unused for now. */
+#define SROM8_MPWR_1_AND_2	95
+
+
+/* Per-path offsets & fields */
+#define	SROM8_PATH0		96
+#define	SROM8_PATH1		112
+#define	SROM8_PATH2		128
+#define	SROM8_PATH3		144
+
+#define	SROM8_2G_ITT_MAXP	0
+#define	SROM8_2G_PA		1
+#define	SROM8_5G_ITT_MAXP	4
+#define	SROM8_5GLH_MAXP		5
+#define	SROM8_5G_PA		6
+#define	SROM8_5GL_PA		9
+#define	SROM8_5GH_PA		12
+
+/* All the miriad power offsets */
+#define	SROM8_2G_CCKPO		160
+
+#define	SROM8_2G_OFDMPO		161
+#define	SROM8_5G_OFDMPO		163
+#define	SROM8_5GL_OFDMPO	165
+#define	SROM8_5GH_OFDMPO	167
+
+#define	SROM8_2G_MCSPO		169
+#define	SROM8_5G_MCSPO		177
+#define	SROM8_5GL_MCSPO		185
+#define	SROM8_5GH_MCSPO		193
+
+#define	SROM8_CDDPO		201
+#define	SROM8_STBCPO		202
+#define	SROM8_BW40PO		203
+#define	SROM8_BWDUPPO		204
+
+/* SISO PA parameters are in the path0 spaces */
+#define	SROM8_SISO		96
+
+/* Legacy names for SISO PA paramters */
+#define	SROM8_W0_ITTMAXP	(SROM8_SISO + SROM8_2G_ITT_MAXP)
+#define	SROM8_W0_PAB0		(SROM8_SISO + SROM8_2G_PA)
+#define	SROM8_W0_PAB1		(SROM8_SISO + SROM8_2G_PA + 1)
+#define	SROM8_W0_PAB2		(SROM8_SISO + SROM8_2G_PA + 2)
+#define	SROM8_W1_ITTMAXP	(SROM8_SISO + SROM8_5G_ITT_MAXP)
+#define	SROM8_W1_MAXP_LCHC	(SROM8_SISO + SROM8_5GLH_MAXP)
+#define	SROM8_W1_PAB0		(SROM8_SISO + SROM8_5G_PA)
+#define	SROM8_W1_PAB1		(SROM8_SISO + SROM8_5G_PA + 1)
+#define	SROM8_W1_PAB2		(SROM8_SISO + SROM8_5G_PA + 2)
+#define	SROM8_W1_PAB0_LC	(SROM8_SISO + SROM8_5GL_PA)
+#define	SROM8_W1_PAB1_LC	(SROM8_SISO + SROM8_5GL_PA + 1)
+#define	SROM8_W1_PAB2_LC	(SROM8_SISO + SROM8_5GL_PA + 2)
+#define	SROM8_W1_PAB0_HC	(SROM8_SISO + SROM8_5GH_PA)
+#define	SROM8_W1_PAB1_HC	(SROM8_SISO + SROM8_5GH_PA + 1)
+#define	SROM8_W1_PAB2_HC	(SROM8_SISO + SROM8_5GH_PA + 2)
+
+#define	SROM8_CRCREV		219
+
+/* SROM REV 9 */
+#define SROM9_2GPO_CCKBW20	160
+#define SROM9_2GPO_CCKBW20UL	161
+#define SROM9_2GPO_LOFDMBW20	162
+#define SROM9_2GPO_LOFDMBW20UL	164
+
+#define SROM9_5GLPO_LOFDMBW20	166
+#define SROM9_5GLPO_LOFDMBW20UL	168
+#define SROM9_5GMPO_LOFDMBW20	170
+#define SROM9_5GMPO_LOFDMBW20UL	172
+#define SROM9_5GHPO_LOFDMBW20	174
+#define SROM9_5GHPO_LOFDMBW20UL	176
+
+#define SROM9_2GPO_MCSBW20	178
+#define SROM9_2GPO_MCSBW20UL	180
+#define SROM9_2GPO_MCSBW40	182
+
+#define SROM9_5GLPO_MCSBW20	184
+#define SROM9_5GLPO_MCSBW20UL	186
+#define SROM9_5GLPO_MCSBW40	188
+#define SROM9_5GMPO_MCSBW20	190
+#define SROM9_5GMPO_MCSBW20UL	192
+#define SROM9_5GMPO_MCSBW40	194
+#define SROM9_5GHPO_MCSBW20	196
+#define SROM9_5GHPO_MCSBW20UL	198
+#define SROM9_5GHPO_MCSBW40	200
+
+#define SROM9_PO_MCS32		202
+#define SROM9_PO_LOFDM40DUP	203
+#define SROM8_RXGAINERR_2G	205
+#define SROM8_RXGAINERR_5GL	206
+#define SROM8_RXGAINERR_5GM	207
+#define SROM8_RXGAINERR_5GH	208
+#define SROM8_RXGAINERR_5GU	209
+#define SROM8_SUBBAND_PPR	210
+#define SROM8_PCIEINGRESS_WAR	211
+#define SROM9_SAR		212
+
+#define SROM8_NOISELVL_2G	213
+#define SROM8_NOISELVL_5GL	214
+#define SROM8_NOISELVL_5GM	215
+#define SROM8_NOISELVL_5GH	216
+#define SROM8_NOISELVL_5GU	217
+#define SROM8_NOISECALOFFSET	218
+
+#define SROM9_REV_CRC		219
+
+#define SROM10_CCKPWROFFSET	218
+#define SROM10_SIGN		219
+#define SROM10_SWCTRLMAP_2G	220
+#define SROM10_CRCREV		229
+
+#define	SROM10_WORDS		230
+#define	SROM10_SIGNATURE	SROM4_SIGNATURE
+
+
+/* SROM REV 11 */
+#define SROM11_BREV			65
+
+#define SROM11_BFL0			66
+#define SROM11_BFL1			67
+#define SROM11_BFL2			68
+#define SROM11_BFL3			69
+#define SROM11_BFL4			70
+#define SROM11_BFL5			71
+
+#define SROM11_MACHI			72
+#define SROM11_MACMID			73
+#define SROM11_MACLO			74
+
+#define SROM11_CCODE			75
+#define SROM11_REGREV			76
+
+#define SROM11_LEDBH10			77
+#define SROM11_LEDBH32			78
+
+#define SROM11_LEDDC			79
+
+#define SROM11_AA			80
+
+#define SROM11_AGBG10			81
+#define SROM11_AGBG2A0			82
+#define SROM11_AGA21			83
+
+#define SROM11_TXRXC			84
+
+#define SROM11_FEM_CFG1			85
+#define SROM11_FEM_CFG2			86
+
+/* Masks and offsets for FEM_CFG */
+#define SROM11_FEMCTRL_MASK		0xf800
+#define SROM11_FEMCTRL_SHIFT		11
+#define SROM11_PAPDCAP_MASK		0x0400
+#define SROM11_PAPDCAP_SHIFT		10
+#define SROM11_TWORANGETSSI_MASK	0x0200
+#define SROM11_TWORANGETSSI_SHIFT	9
+#define SROM11_PDGAIN_MASK		0x01f0
+#define SROM11_PDGAIN_SHIFT		4
+#define SROM11_EPAGAIN_MASK		0x000e
+#define SROM11_EPAGAIN_SHIFT		1
+#define SROM11_TSSIPOSSLOPE_MASK	0x0001
+#define SROM11_TSSIPOSSLOPE_SHIFT	0
+#define SROM11_GAINCTRLSPH_MASK		0xf800
+#define SROM11_GAINCTRLSPH_SHIFT	11
+
+#define SROM11_THERMAL			87
+#define SROM11_MPWR_RAWTS		88
+#define SROM11_TS_SLP_OPT_CORRX		89
+#define SROM11_XTAL_FREQ		90
+#define SROM11_5GB0_4080_W0_A1          91
+#define SROM11_PHYCAL_TEMPDELTA  	92
+#define SROM11_MPWR_1_AND_2 		93
+#define SROM11_5GB0_4080_W1_A1          94
+#define SROM11_TSSIFLOOR_2G 		95
+#define SROM11_TSSIFLOOR_5GL 		96
+#define SROM11_TSSIFLOOR_5GM 		97
+#define SROM11_TSSIFLOOR_5GH 		98
+#define SROM11_TSSIFLOOR_5GU 		99
+
+/* Masks and offsets for Terrmal parameters */
+#define SROM11_TEMPS_PERIOD_MASK	0xf0
+#define SROM11_TEMPS_PERIOD_SHIFT	4
+#define SROM11_TEMPS_HYSTERESIS_MASK	0x0f
+#define SROM11_TEMPS_HYSTERESIS_SHIFT	0
+#define SROM11_TEMPCORRX_MASK		0xfc
+#define SROM11_TEMPCORRX_SHIFT		2
+#define SROM11_TEMPSENSE_OPTION_MASK	0x3
+#define SROM11_TEMPSENSE_OPTION_SHIFT	0
+
+#define SROM11_PDOFF_2G_40M_A0_MASK     0x000f
+#define SROM11_PDOFF_2G_40M_A0_SHIFT    0
+#define SROM11_PDOFF_2G_40M_A1_MASK     0x00f0
+#define SROM11_PDOFF_2G_40M_A1_SHIFT    4
+#define SROM11_PDOFF_2G_40M_A2_MASK     0x0f00
+#define SROM11_PDOFF_2G_40M_A2_SHIFT    8
+#define SROM11_PDOFF_2G_40M_VALID_MASK  0x8000
+#define SROM11_PDOFF_2G_40M_VALID_SHIFT 15
+
+#define SROM11_PDOFF_2G_40M     	100
+#define SROM11_PDOFF_40M_A0		101
+#define SROM11_PDOFF_40M_A1		102
+#define SROM11_PDOFF_40M_A2		103
+#define SROM11_5GB0_4080_W2_A1          103
+#define SROM11_PDOFF_80M_A0		104
+#define SROM11_PDOFF_80M_A1		105
+#define SROM11_PDOFF_80M_A2		106
+#define SROM11_5GB1_4080_W0_A1          106
+
+#define SROM11_SUBBAND5GVER 		107
+
+/* Per-path fields and offset */
+#define	MAX_PATH_SROM_11		3
+#define SROM11_PATH0			108
+#define SROM11_PATH1			128
+#define SROM11_PATH2			148
+
+#define	SROM11_2G_MAXP			0
+#define SROM11_5GB1_4080_PA             0
+#define	SROM11_2G_PA			1
+#define SROM11_5GB2_4080_PA             2
+#define	SROM11_RXGAINS1			4
+#define	SROM11_RXGAINS			5
+#define SROM11_5GB3_4080_PA             5
+#define	SROM11_5GB1B0_MAXP		6
+#define	SROM11_5GB3B2_MAXP		7
+#define	SROM11_5GB0_PA			8
+#define	SROM11_5GB1_PA			11
+#define	SROM11_5GB2_PA			14
+#define	SROM11_5GB3_PA			17
+
+/* Masks and offsets for rxgains */
+#define SROM11_RXGAINS5GTRELNABYPA_MASK		0x8000
+#define SROM11_RXGAINS5GTRELNABYPA_SHIFT	15
+#define SROM11_RXGAINS5GTRISOA_MASK		0x7800
+#define SROM11_RXGAINS5GTRISOA_SHIFT		11
+#define SROM11_RXGAINS5GELNAGAINA_MASK		0x0700
+#define SROM11_RXGAINS5GELNAGAINA_SHIFT		8
+#define SROM11_RXGAINS2GTRELNABYPA_MASK		0x0080
+#define SROM11_RXGAINS2GTRELNABYPA_SHIFT	7
+#define SROM11_RXGAINS2GTRISOA_MASK		0x0078
+#define SROM11_RXGAINS2GTRISOA_SHIFT		3
+#define SROM11_RXGAINS2GELNAGAINA_MASK		0x0007
+#define SROM11_RXGAINS2GELNAGAINA_SHIFT		0
+#define SROM11_RXGAINS5GHTRELNABYPA_MASK	0x8000
+#define SROM11_RXGAINS5GHTRELNABYPA_SHIFT	15
+#define SROM11_RXGAINS5GHTRISOA_MASK		0x7800
+#define SROM11_RXGAINS5GHTRISOA_SHIFT		11
+#define SROM11_RXGAINS5GHELNAGAINA_MASK		0x0700
+#define SROM11_RXGAINS5GHELNAGAINA_SHIFT	8
+#define SROM11_RXGAINS5GMTRELNABYPA_MASK	0x0080
+#define SROM11_RXGAINS5GMTRELNABYPA_SHIFT	7
+#define SROM11_RXGAINS5GMTRISOA_MASK		0x0078
+#define SROM11_RXGAINS5GMTRISOA_SHIFT		3
+#define SROM11_RXGAINS5GMELNAGAINA_MASK		0x0007
+#define SROM11_RXGAINS5GMELNAGAINA_SHIFT	0
+
+/* Power per rate */
+#define SROM11_CCKBW202GPO		168
+#define SROM11_CCKBW20UL2GPO		169
+#define SROM11_MCSBW202GPO		170
+#define SROM11_MCSBW202GPO_1		171
+#define SROM11_MCSBW402GPO		172
+#define SROM11_MCSBW402GPO_1		173
+#define SROM11_DOT11AGOFDMHRBW202GPO	174
+#define SROM11_OFDMLRBW202GPO		175
+
+#define SROM11_MCSBW205GLPO 		176
+#define SROM11_MCSBW205GLPO_1		177
+#define SROM11_MCSBW405GLPO 		178
+#define SROM11_MCSBW405GLPO_1		179
+#define SROM11_MCSBW805GLPO 		180
+#define SROM11_MCSBW805GLPO_1		181
+#define SROM11_RPCAL_2G			182
+#define SROM11_RPCAL_5GL		183
+#define SROM11_MCSBW205GMPO 		184
+#define SROM11_MCSBW205GMPO_1		185
+#define SROM11_MCSBW405GMPO 		186
+#define SROM11_MCSBW405GMPO_1		187
+#define SROM11_MCSBW805GMPO 		188
+#define SROM11_MCSBW805GMPO_1		189
+#define SROM11_RPCAL_5GM		190
+#define SROM11_RPCAL_5GH		191
+#define SROM11_MCSBW205GHPO 		192
+#define SROM11_MCSBW205GHPO_1		193
+#define SROM11_MCSBW405GHPO 		194
+#define SROM11_MCSBW405GHPO_1		195
+#define SROM11_MCSBW805GHPO 		196
+#define SROM11_MCSBW805GHPO_1		197
+#define SROM11_RPCAL_5GU		198
+#define SROM11_PDOFF_2G_CCK	        199
+#define SROM11_MCSLR5GLPO		200
+#define SROM11_MCSLR5GMPO		201
+#define SROM11_MCSLR5GHPO		202
+
+#define SROM11_SB20IN40HRPO		203
+#define SROM11_SB20IN80AND160HR5GLPO 	204
+#define SROM11_SB40AND80HR5GLPO		205
+#define SROM11_SB20IN80AND160HR5GMPO 	206
+#define SROM11_SB40AND80HR5GMPO		207
+#define SROM11_SB20IN80AND160HR5GHPO 	208
+#define SROM11_SB40AND80HR5GHPO		209
+#define SROM11_SB20IN40LRPO 		210
+#define SROM11_SB20IN80AND160LR5GLPO	211
+#define SROM11_SB40AND80LR5GLPO		212
+#define SROM11_TXIDXCAP2G               212
+#define SROM11_SB20IN80AND160LR5GMPO	213
+#define SROM11_SB40AND80LR5GMPO		214
+#define SROM11_TXIDXCAP5G               214
+#define SROM11_SB20IN80AND160LR5GHPO	215
+#define SROM11_SB40AND80LR5GHPO		216
+
+#define SROM11_DOT11AGDUPHRPO 		217
+#define SROM11_DOT11AGDUPLRPO		218
+
+/* MISC */
+#define SROM11_PCIEINGRESS_WAR		220
+#define SROM11_SAR			221
+
+#define SROM11_NOISELVL_2G		222
+#define SROM11_NOISELVL_5GL 		223
+#define SROM11_NOISELVL_5GM 		224
+#define SROM11_NOISELVL_5GH 		225
+#define SROM11_NOISELVL_5GU 		226
+
+#define SROM11_RXGAINERR_2G		227
+#define SROM11_RXGAINERR_5GL		228
+#define SROM11_RXGAINERR_5GM		229
+#define SROM11_RXGAINERR_5GH		230
+#define SROM11_RXGAINERR_5GU		231
+
+#define SROM11_SIGN 			64
+#define SROM11_CRCREV 			233
+
+#define	SROM11_WORDS			234
+#define	SROM11_SIGNATURE		0x0634
+
+typedef struct {
+	uint8 tssipos;		/* TSSI positive slope, 1: positive, 0: negative */
+	uint8 extpagain;	/* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
+	uint8 pdetrange;	/* support 32 combinations of different Pdet dynamic ranges */
+	uint8 triso;		/* TR switch isolation */
+	uint8 antswctrllut;	/* antswctrl lookup table configuration: 32 possible choices */
+} srom_fem_t;
+
+#endif	/* _bcmsrom_fmt_h_ */
diff --git a/src/include/bcmsrom_tbl.h b/src/include/bcmsrom_tbl.h
new file mode 100644
index 0000000..37067fd
--- /dev/null
+++ b/src/include/bcmsrom_tbl.h
@@ -0,0 +1,996 @@
+/*
+ * Table that encodes the srom formats for PCI/PCIe NICs.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmsrom_tbl.h 427005 2013-10-02 00:15:10Z $
+ */
+
+#ifndef	_bcmsrom_tbl_h_
+#define	_bcmsrom_tbl_h_
+
+#include "sbpcmcia.h"
+#include "wlioctl.h"
+
+typedef struct {
+	const char *name;
+	uint32	revmask;
+	uint32	flags;
+	uint16	off;
+	uint16	mask;
+} sromvar_t;
+
+#define SRFL_MORE	1		/* value continues as described by the next entry */
+#define	SRFL_NOFFS	2		/* value bits can't be all one's */
+#define	SRFL_PRHEX	4		/* value is in hexdecimal format */
+#define	SRFL_PRSIGN	8		/* value is in signed decimal format */
+#define	SRFL_CCODE	0x10		/* value is in country code format */
+#define	SRFL_ETHADDR	0x20		/* value is an Ethernet address */
+#define SRFL_LEDDC	0x40		/* value is an LED duty cycle */
+#define SRFL_NOVAR	0x80		/* do not generate a nvram param, entry is for mfgc */
+#define SRFL_ARRAY	0x100		/* value is in an array. All elements EXCEPT FOR THE LAST
+					 * ONE in the array should have this flag set.
+					 */
+
+
+#define SROM_DEVID_PCIE	48
+
+/* Assumptions:
+ * - Ethernet address spans across 3 consective words
+ *
+ * Table rules:
+ * - Add multiple entries next to each other if a value spans across multiple words
+ *   (even multiple fields in the same word) with each entry except the last having
+ *   it's SRFL_MORE bit set.
+ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
+ *   bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
+ * - The last entry's name field must be NULL to indicate the end of the table. Other
+ *   entries must have non-NULL name.
+ */
+
+static const sromvar_t BCMATTACHDATA(pci_sromvars)[] = {
+#if defined(CABLECPE)
+	{"devid",	0xffffff00,	SRFL_PRHEX,	PCI_F0DEVID,	0xffff},
+#elif defined(BCMPCIEDEV) && defined(BCMPCIEDEV_ENABLED)
+	{"devid",	0xffffff00,	SRFL_PRHEX, SROM_DEVID_PCIE, 0xffff},
+#else
+	{"devid",	0xffffff00,	SRFL_PRHEX|SRFL_NOVAR,	PCI_F0DEVID,	0xffff},
+#endif 
+	{"boardrev",	0x0000000e,	SRFL_PRHEX,	SROM_AABREV,		SROM_BR_MASK},
+	{"boardrev",	0x000000f0,	SRFL_PRHEX,	SROM4_BREV,		0xffff},
+	{"boardrev",	0xffffff00,	SRFL_PRHEX,	SROM8_BREV,		0xffff},
+	{"boardflags",	0x00000002,	SRFL_PRHEX,	SROM_BFL,		0xffff},
+	{"boardflags",	0x00000004,	SRFL_PRHEX|SRFL_MORE,	SROM_BFL,	0xffff},
+	{"",		0,		0,		SROM_BFL2,		0xffff},
+	{"boardflags",	0x00000008,	SRFL_PRHEX|SRFL_MORE,	SROM_BFL,	0xffff},
+	{"",		0,		0,		SROM3_BFL2,		0xffff},
+	{"boardflags",	0x00000010,	SRFL_PRHEX|SRFL_MORE,	SROM4_BFL0,	0xffff},
+	{"",		0,		0,		SROM4_BFL1,		0xffff},
+	{"boardflags",	0x000000e0,	SRFL_PRHEX|SRFL_MORE,	SROM5_BFL0,	0xffff},
+	{"",		0,		0,		SROM5_BFL1,		0xffff},
+	{"boardflags",	0xffffff00,	SRFL_PRHEX|SRFL_MORE,	SROM8_BFL0,	0xffff},
+	{"",		0,		0,		SROM8_BFL1,		0xffff},
+	{"boardflags2", 0x00000010,	SRFL_PRHEX|SRFL_MORE,	SROM4_BFL2,	0xffff},
+	{"",		0,		0,		SROM4_BFL3,		0xffff},
+	{"boardflags2", 0x000000e0,	SRFL_PRHEX|SRFL_MORE,	SROM5_BFL2,	0xffff},
+	{"",		0,		0,		SROM5_BFL3,		0xffff},
+	{"boardflags2", 0xffffff00,	SRFL_PRHEX|SRFL_MORE,	SROM8_BFL2,	0xffff},
+	{"",		0,		0,		SROM8_BFL3,		0xffff},
+	{"boardtype",	0xfffffffc,	SRFL_PRHEX,	SROM_SSID,		0xffff},
+	{"subvid",	0xfffffffc,	SRFL_PRHEX,	SROM_SVID,		0xffff},
+	{"boardnum",	0x00000006,	0,		SROM_MACLO_IL0,		0xffff},
+	{"boardnum",	0x00000008,	0,		SROM3_MACLO,		0xffff},
+	{"boardnum",	0x00000010,	0,		SROM4_MACLO,		0xffff},
+	{"boardnum",	0x000000e0,	0,		SROM5_MACLO,		0xffff},
+	{"boardnum",	0x00000700,	0,		SROM8_MACLO,		0xffff},
+	{"cc",		0x00000002,	0,		SROM_AABREV,		SROM_CC_MASK},
+	{"regrev",	0x00000008,	0,		SROM_OPO,		0xff00},
+	{"regrev",	0x00000010,	0,		SROM4_REGREV,		0x00ff},
+	{"regrev",	0x000000e0,	0,		SROM5_REGREV,		0x00ff},
+	{"regrev",	0x00000700,	0,		SROM8_REGREV,		0x00ff},
+	{"ledbh0",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH10,		0x00ff},
+	{"ledbh1",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH10,		0xff00},
+	{"ledbh2",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH32,		0x00ff},
+	{"ledbh3",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH32,		0xff00},
+	{"ledbh0",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH10,		0x00ff},
+	{"ledbh1",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH10,		0xff00},
+	{"ledbh2",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH32,		0x00ff},
+	{"ledbh3",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH32,		0xff00},
+	{"ledbh0",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH10,		0x00ff},
+	{"ledbh1",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH10,		0xff00},
+	{"ledbh2",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH32,		0x00ff},
+	{"ledbh3",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH32,		0xff00},
+	{"ledbh0",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH10,		0x00ff},
+	{"ledbh1",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH10,		0xff00},
+	{"ledbh2",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH32,		0x00ff},
+	{"ledbh3",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH32,		0xff00},
+	{"pa0b0",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB0,		0xffff},
+	{"pa0b1",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB1,		0xffff},
+	{"pa0b2",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB2,		0xffff},
+	{"pa0itssit",	0x0000000e,	0,		SROM_ITT,		0x00ff},
+	{"pa0maxpwr",	0x0000000e,	0,		SROM_WL10MAXP,		0x00ff},
+	{"pa0b0",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB0,		0xffff},
+	{"pa0b1",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB1,		0xffff},
+	{"pa0b2",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB2,		0xffff},
+	{"pa0itssit",	0x00000700,	0,		SROM8_W0_ITTMAXP,	0xff00},
+	{"pa0maxpwr",	0x00000700,	0,		SROM8_W0_ITTMAXP,	0x00ff},
+	{"opo",		0x0000000c,	0,		SROM_OPO,		0x00ff},
+	{"opo",		0x00000700,	0,		SROM8_2G_OFDMPO,	0x00ff},
+	{"aa2g",	0x0000000e,	0,		SROM_AABREV,		SROM_AA0_MASK},
+	{"aa2g",	0x000000f0,	0,		SROM4_AA,		0x00ff},
+	{"aa2g",	0x00000700,	0,		SROM8_AA,		0x00ff},
+	{"aa5g",	0x0000000e,	0,		SROM_AABREV,		SROM_AA1_MASK},
+	{"aa5g",	0x000000f0,	0,		SROM4_AA,		0xff00},
+	{"aa5g",	0x00000700,	0,		SROM8_AA,		0xff00},
+	{"ag0",		0x0000000e,	0,		SROM_AG10,		0x00ff},
+	{"ag1",		0x0000000e,	0,		SROM_AG10,		0xff00},
+	{"ag0",		0x000000f0,	0,		SROM4_AG10,		0x00ff},
+	{"ag1",		0x000000f0,	0,		SROM4_AG10,		0xff00},
+	{"ag2",		0x000000f0,	0,		SROM4_AG32,		0x00ff},
+	{"ag3",		0x000000f0,	0,		SROM4_AG32,		0xff00},
+	{"ag0",		0x00000700,	0,		SROM8_AG10,		0x00ff},
+	{"ag1",		0x00000700,	0,		SROM8_AG10,		0xff00},
+	{"ag2",		0x00000700,	0,		SROM8_AG32,		0x00ff},
+	{"ag3",		0x00000700,	0,		SROM8_AG32,		0xff00},
+	{"pa1b0",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB0,		0xffff},
+	{"pa1b1",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB1,		0xffff},
+	{"pa1b2",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB2,		0xffff},
+	{"pa1lob0",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB0,		0xffff},
+	{"pa1lob1",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB1,		0xffff},
+	{"pa1lob2",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB2,		0xffff},
+	{"pa1hib0",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB0,		0xffff},
+	{"pa1hib1",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB1,		0xffff},
+	{"pa1hib2",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB2,		0xffff},
+	{"pa1itssit",	0x0000000e,	0,		SROM_ITT,		0xff00},
+	{"pa1maxpwr",	0x0000000e,	0,		SROM_WL10MAXP,		0xff00},
+	{"pa1lomaxpwr",	0x0000000c,	0,		SROM_WL1LHMAXP,		0xff00},
+	{"pa1himaxpwr",	0x0000000c,	0,		SROM_WL1LHMAXP,		0x00ff},
+	{"pa1b0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0,		0xffff},
+	{"pa1b1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1,		0xffff},
+	{"pa1b2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2,		0xffff},
+	{"pa1lob0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0_LC,	0xffff},
+	{"pa1lob1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1_LC,	0xffff},
+	{"pa1lob2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2_LC,	0xffff},
+	{"pa1hib0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0_HC,	0xffff},
+	{"pa1hib1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1_HC,	0xffff},
+	{"pa1hib2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2_HC,	0xffff},
+	{"pa1itssit",	0x00000700,	0,		SROM8_W1_ITTMAXP,	0xff00},
+	{"pa1maxpwr",	0x00000700,	0,		SROM8_W1_ITTMAXP,	0x00ff},
+	{"pa1lomaxpwr",	0x00000700,	0,		SROM8_W1_MAXP_LCHC,	0xff00},
+	{"pa1himaxpwr",	0x00000700,	0,		SROM8_W1_MAXP_LCHC,	0x00ff},
+	{"bxa2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x1800},
+	{"rssisav2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x0700},
+	{"rssismc2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x00f0},
+	{"rssismf2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x000f},
+	{"bxa2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x1800},
+	{"rssisav2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x0700},
+	{"rssismc2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x00f0},
+	{"rssismf2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x000f},
+	{"bxa5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x1800},
+	{"rssisav5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x0700},
+	{"rssismc5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x00f0},
+	{"rssismf5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x000f},
+	{"bxa5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x1800},
+	{"rssisav5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x0700},
+	{"rssismc5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x00f0},
+	{"rssismf5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x000f},
+	{"tri2g",	0x00000008,	0,		SROM_TRI52G,		0x00ff},
+	{"tri5g",	0x00000008,	0,		SROM_TRI52G,		0xff00},
+	{"tri5gl",	0x00000008,	0,		SROM_TRI5GHL,		0x00ff},
+	{"tri5gh",	0x00000008,	0,		SROM_TRI5GHL,		0xff00},
+	{"tri2g",	0x00000700,	0,		SROM8_TRI52G,		0x00ff},
+	{"tri5g",	0x00000700,	0,		SROM8_TRI52G,		0xff00},
+	{"tri5gl",	0x00000700,	0,		SROM8_TRI5GHL,		0x00ff},
+	{"tri5gh",	0x00000700,	0,		SROM8_TRI5GHL,		0xff00},
+	{"rxpo2g",	0x00000008,	SRFL_PRSIGN,	SROM_RXPO52G,		0x00ff},
+	{"rxpo5g",	0x00000008,	SRFL_PRSIGN,	SROM_RXPO52G,		0xff00},
+	{"rxpo2g",	0x00000700,	SRFL_PRSIGN,	SROM8_RXPO52G,		0x00ff},
+	{"rxpo5g",	0x00000700,	SRFL_PRSIGN,	SROM8_RXPO52G,		0xff00},
+	{"txchain",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_TXCHAIN_MASK},
+	{"rxchain",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_RXCHAIN_MASK},
+	{"antswitch",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_SWITCH_MASK},
+	{"txchain",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_TXCHAIN_MASK},
+	{"rxchain",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_RXCHAIN_MASK},
+	{"antswitch",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_SWITCH_MASK},
+	{"tssipos2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_PDET_RANGE_MASK},
+	{"triso2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_TR_ISO_MASK},
+	{"antswctl2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_ANTSWLUT_MASK},
+	{"tssipos5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_PDET_RANGE_MASK},
+	{"triso5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_TR_ISO_MASK},
+	{"antswctl5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_ANTSWLUT_MASK},
+	{"txpid2ga0",	0x000000f0,	0,		SROM4_TXPID2G,		0x00ff},
+	{"txpid2ga1",	0x000000f0,	0,		SROM4_TXPID2G,		0xff00},
+	{"txpid2ga2",	0x000000f0,	0,		SROM4_TXPID2G + 1,	0x00ff},
+	{"txpid2ga3",	0x000000f0,	0,		SROM4_TXPID2G + 1,	0xff00},
+	{"txpid5ga0",	0x000000f0,	0,		SROM4_TXPID5G,		0x00ff},
+	{"txpid5ga1",	0x000000f0,	0,		SROM4_TXPID5G,		0xff00},
+	{"txpid5ga2",	0x000000f0,	0,		SROM4_TXPID5G + 1,	0x00ff},
+	{"txpid5ga3",	0x000000f0,	0,		SROM4_TXPID5G + 1,	0xff00},
+	{"txpid5gla0",	0x000000f0,	0,		SROM4_TXPID5GL,		0x00ff},
+	{"txpid5gla1",	0x000000f0,	0,		SROM4_TXPID5GL,		0xff00},
+	{"txpid5gla2",	0x000000f0,	0,		SROM4_TXPID5GL + 1,	0x00ff},
+	{"txpid5gla3",	0x000000f0,	0,		SROM4_TXPID5GL + 1,	0xff00},
+	{"txpid5gha0",	0x000000f0,	0,		SROM4_TXPID5GH,		0x00ff},
+	{"txpid5gha1",	0x000000f0,	0,		SROM4_TXPID5GH,		0xff00},
+	{"txpid5gha2",	0x000000f0,	0,		SROM4_TXPID5GH + 1,	0x00ff},
+	{"txpid5gha3",	0x000000f0,	0,		SROM4_TXPID5GH + 1,	0xff00},
+
+	{"ccode",	0x0000000f,	SRFL_CCODE,	SROM_CCODE,		0xffff},
+	{"ccode",	0x00000010,	SRFL_CCODE,	SROM4_CCODE,		0xffff},
+	{"ccode",	0x000000e0,	SRFL_CCODE,	SROM5_CCODE,		0xffff},
+	{"ccode",	0x00000700,	SRFL_CCODE,	SROM8_CCODE,		0xffff},
+	{"macaddr",	0x00000700,	SRFL_ETHADDR,	SROM8_MACHI,		0xffff},
+	{"macaddr",	0x000000e0,	SRFL_ETHADDR,	SROM5_MACHI,		0xffff},
+	{"macaddr",	0x00000010,	SRFL_ETHADDR,	SROM4_MACHI,		0xffff},
+	{"macaddr",	0x00000008,	SRFL_ETHADDR,	SROM3_MACHI,		0xffff},
+	{"il0macaddr",	0x00000007,	SRFL_ETHADDR,	SROM_MACHI_IL0,		0xffff},
+	{"et1macaddr",	0x00000007,	SRFL_ETHADDR,	SROM_MACHI_ET1,		0xffff},
+	{"leddc",	0x00000700,	SRFL_NOFFS|SRFL_LEDDC,	SROM8_LEDDC,	0xffff},
+	{"leddc",	0x000000e0,	SRFL_NOFFS|SRFL_LEDDC,	SROM5_LEDDC,	0xffff},
+	{"leddc",	0x00000010,	SRFL_NOFFS|SRFL_LEDDC,	SROM4_LEDDC,	0xffff},
+	{"leddc",	0x00000008,	SRFL_NOFFS|SRFL_LEDDC,	SROM3_LEDDC,	0xffff},
+
+	{"tempthresh",	0x00000700,	0,		SROM8_THERMAL,		0xff00},
+	{"tempoffset",	0x00000700,	0,		SROM8_THERMAL,		0x00ff},
+	{"rawtempsense", 0x00000700,	SRFL_PRHEX,	SROM8_MPWR_RAWTS,	0x01ff},
+	{"measpower",	0x00000700,	SRFL_PRHEX,	SROM8_MPWR_RAWTS,	0xfe00},
+	{"tempsense_slope",	0x00000700,	SRFL_PRHEX, 	SROM8_TS_SLP_OPT_CORRX,	0x00ff},
+	{"tempcorrx",	0x00000700,	SRFL_PRHEX, 	SROM8_TS_SLP_OPT_CORRX,	0xfc00},
+	{"tempsense_option",	0x00000700,	SRFL_PRHEX,	SROM8_TS_SLP_OPT_CORRX,	0x0300},
+	{"freqoffset_corr",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x000f},
+	{"iqcal_swp_dis",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x0010},
+	{"hw_iqcal_en",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x0020},
+	{"elna2g",      0x00000700,     0,              SROM8_EXTLNAGAIN,       0x00ff},
+	{"elna5g",      0x00000700,     0,              SROM8_EXTLNAGAIN,       0xff00},
+	{"phycal_tempdelta",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0x00ff},
+	{"temps_period",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0x0f00},
+	{"temps_hysteresis",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0xf000},
+	{"measpower1", 0x00000700,	SRFL_PRHEX, SROM8_MPWR_1_AND_2, 	0x007f},
+	{"measpower2",	0x00000700, 	SRFL_PRHEX, SROM8_MPWR_1_AND_2, 	0x3f80},
+
+	{"cck2gpo",	0x000000f0,	0,		SROM4_2G_CCKPO,		0xffff},
+	{"cck2gpo",	0x00000100,	0,		SROM8_2G_CCKPO,		0xffff},
+	{"ofdm2gpo",	0x000000f0,	SRFL_MORE,	SROM4_2G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_2G_OFDMPO + 1,	0xffff},
+	{"ofdm5gpo",	0x000000f0,	SRFL_MORE,	SROM4_5G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_5G_OFDMPO + 1,	0xffff},
+	{"ofdm5glpo",	0x000000f0,	SRFL_MORE,	SROM4_5GL_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_5GL_OFDMPO + 1,	0xffff},
+	{"ofdm5ghpo",	0x000000f0,	SRFL_MORE,	SROM4_5GH_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_5GH_OFDMPO + 1,	0xffff},
+	{"ofdm2gpo",	0x00000100,	SRFL_MORE,	SROM8_2G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_2G_OFDMPO + 1,	0xffff},
+	{"ofdm5gpo",	0x00000100,	SRFL_MORE,	SROM8_5G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_5G_OFDMPO + 1,	0xffff},
+	{"ofdm5glpo",	0x00000100,	SRFL_MORE,	SROM8_5GL_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_5GL_OFDMPO + 1,	0xffff},
+	{"ofdm5ghpo",	0x00000100,	SRFL_MORE,	SROM8_5GH_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_5GH_OFDMPO + 1,	0xffff},
+	{"mcs2gpo0",	0x000000f0,	0,		SROM4_2G_MCSPO,		0xffff},
+	{"mcs2gpo1",	0x000000f0,	0,		SROM4_2G_MCSPO + 1,	0xffff},
+	{"mcs2gpo2",	0x000000f0,	0,		SROM4_2G_MCSPO + 2,	0xffff},
+	{"mcs2gpo3",	0x000000f0,	0,		SROM4_2G_MCSPO + 3,	0xffff},
+	{"mcs2gpo4",	0x000000f0,	0,		SROM4_2G_MCSPO + 4,	0xffff},
+	{"mcs2gpo5",	0x000000f0,	0,		SROM4_2G_MCSPO + 5,	0xffff},
+	{"mcs2gpo6",	0x000000f0,	0,		SROM4_2G_MCSPO + 6,	0xffff},
+	{"mcs2gpo7",	0x000000f0,	0,		SROM4_2G_MCSPO + 7,	0xffff},
+	{"mcs5gpo0",	0x000000f0,	0,		SROM4_5G_MCSPO,		0xffff},
+	{"mcs5gpo1",	0x000000f0,	0,		SROM4_5G_MCSPO + 1,	0xffff},
+	{"mcs5gpo2",	0x000000f0,	0,		SROM4_5G_MCSPO + 2,	0xffff},
+	{"mcs5gpo3",	0x000000f0,	0,		SROM4_5G_MCSPO + 3,	0xffff},
+	{"mcs5gpo4",	0x000000f0,	0,		SROM4_5G_MCSPO + 4,	0xffff},
+	{"mcs5gpo5",	0x000000f0,	0,		SROM4_5G_MCSPO + 5,	0xffff},
+	{"mcs5gpo6",	0x000000f0,	0,		SROM4_5G_MCSPO + 6,	0xffff},
+	{"mcs5gpo7",	0x000000f0,	0,		SROM4_5G_MCSPO + 7,	0xffff},
+	{"mcs5glpo0",	0x000000f0,	0,		SROM4_5GL_MCSPO,	0xffff},
+	{"mcs5glpo1",	0x000000f0,	0,		SROM4_5GL_MCSPO + 1,	0xffff},
+	{"mcs5glpo2",	0x000000f0,	0,		SROM4_5GL_MCSPO + 2,	0xffff},
+	{"mcs5glpo3",	0x000000f0,	0,		SROM4_5GL_MCSPO + 3,	0xffff},
+	{"mcs5glpo4",	0x000000f0,	0,		SROM4_5GL_MCSPO + 4,	0xffff},
+	{"mcs5glpo5",	0x000000f0,	0,		SROM4_5GL_MCSPO + 5,	0xffff},
+	{"mcs5glpo6",	0x000000f0,	0,		SROM4_5GL_MCSPO + 6,	0xffff},
+	{"mcs5glpo7",	0x000000f0,	0,		SROM4_5GL_MCSPO + 7,	0xffff},
+	{"mcs5ghpo0",	0x000000f0,	0,		SROM4_5GH_MCSPO,	0xffff},
+	{"mcs5ghpo1",	0x000000f0,	0,		SROM4_5GH_MCSPO + 1,	0xffff},
+	{"mcs5ghpo2",	0x000000f0,	0,		SROM4_5GH_MCSPO + 2,	0xffff},
+	{"mcs5ghpo3",	0x000000f0,	0,		SROM4_5GH_MCSPO + 3,	0xffff},
+	{"mcs5ghpo4",	0x000000f0,	0,		SROM4_5GH_MCSPO + 4,	0xffff},
+	{"mcs5ghpo5",	0x000000f0,	0,		SROM4_5GH_MCSPO + 5,	0xffff},
+	{"mcs5ghpo6",	0x000000f0,	0,		SROM4_5GH_MCSPO + 6,	0xffff},
+	{"mcs5ghpo7",	0x000000f0,	0,		SROM4_5GH_MCSPO + 7,	0xffff},
+	{"mcs2gpo0",	0x00000100,	0,		SROM8_2G_MCSPO,		0xffff},
+	{"mcs2gpo1",	0x00000100,	0,		SROM8_2G_MCSPO + 1,	0xffff},
+	{"mcs2gpo2",	0x00000100,	0,		SROM8_2G_MCSPO + 2,	0xffff},
+	{"mcs2gpo3",	0x00000100,	0,		SROM8_2G_MCSPO + 3,	0xffff},
+	{"mcs2gpo4",	0x00000100,	0,		SROM8_2G_MCSPO + 4,	0xffff},
+	{"mcs2gpo5",	0x00000100,	0,		SROM8_2G_MCSPO + 5,	0xffff},
+	{"mcs2gpo6",	0x00000100,	0,		SROM8_2G_MCSPO + 6,	0xffff},
+	{"mcs2gpo7",	0x00000100,	0,		SROM8_2G_MCSPO + 7,	0xffff},
+	{"mcs5gpo0",	0x00000100,	0,		SROM8_5G_MCSPO,		0xffff},
+	{"mcs5gpo1",	0x00000100,	0,		SROM8_5G_MCSPO + 1,	0xffff},
+	{"mcs5gpo2",	0x00000100,	0,		SROM8_5G_MCSPO + 2,	0xffff},
+	{"mcs5gpo3",	0x00000100,	0,		SROM8_5G_MCSPO + 3,	0xffff},
+	{"mcs5gpo4",	0x00000100,	0,		SROM8_5G_MCSPO + 4,	0xffff},
+	{"mcs5gpo5",	0x00000100,	0,		SROM8_5G_MCSPO + 5,	0xffff},
+	{"mcs5gpo6",	0x00000100,	0,		SROM8_5G_MCSPO + 6,	0xffff},
+	{"mcs5gpo7",	0x00000100,	0,		SROM8_5G_MCSPO + 7,	0xffff},
+	{"mcs5glpo0",	0x00000100,	0,		SROM8_5GL_MCSPO,	0xffff},
+	{"mcs5glpo1",	0x00000100,	0,		SROM8_5GL_MCSPO + 1,	0xffff},
+	{"mcs5glpo2",	0x00000100,	0,		SROM8_5GL_MCSPO + 2,	0xffff},
+	{"mcs5glpo3",	0x00000100,	0,		SROM8_5GL_MCSPO + 3,	0xffff},
+	{"mcs5glpo4",	0x00000100,	0,		SROM8_5GL_MCSPO + 4,	0xffff},
+	{"mcs5glpo5",	0x00000100,	0,		SROM8_5GL_MCSPO + 5,	0xffff},
+	{"mcs5glpo6",	0x00000100,	0,		SROM8_5GL_MCSPO + 6,	0xffff},
+	{"mcs5glpo7",	0x00000100,	0,		SROM8_5GL_MCSPO + 7,	0xffff},
+	{"mcs5ghpo0",	0x00000100,	0,		SROM8_5GH_MCSPO,	0xffff},
+	{"mcs5ghpo1",	0x00000100,	0,		SROM8_5GH_MCSPO + 1,	0xffff},
+	{"mcs5ghpo2",	0x00000100,	0,		SROM8_5GH_MCSPO + 2,	0xffff},
+	{"mcs5ghpo3",	0x00000100,	0,		SROM8_5GH_MCSPO + 3,	0xffff},
+	{"mcs5ghpo4",	0x00000100,	0,		SROM8_5GH_MCSPO + 4,	0xffff},
+	{"mcs5ghpo5",	0x00000100,	0,		SROM8_5GH_MCSPO + 5,	0xffff},
+	{"mcs5ghpo6",	0x00000100,	0,		SROM8_5GH_MCSPO + 6,	0xffff},
+	{"mcs5ghpo7",	0x00000100,	0,		SROM8_5GH_MCSPO + 7,	0xffff},
+	{"cddpo",	0x000000f0,	0,		SROM4_CDDPO,		0xffff},
+	{"stbcpo",	0x000000f0,	0,		SROM4_STBCPO,		0xffff},
+	{"bw40po",	0x000000f0,	0,		SROM4_BW40PO,		0xffff},
+	{"bwduppo",	0x000000f0,	0,		SROM4_BWDUPPO,		0xffff},
+	{"cddpo",	0x00000100,	0,		SROM8_CDDPO,		0xffff},
+	{"stbcpo",	0x00000100,	0,		SROM8_STBCPO,		0xffff},
+	{"bw40po",	0x00000100,	0,		SROM8_BW40PO,		0xffff},
+	{"bwduppo",	0x00000100,	0,		SROM8_BWDUPPO,		0xffff},
+
+	/* power per rate from sromrev 9 */
+	{"cckbw202gpo",		0x00000600,	0,	SROM9_2GPO_CCKBW20,		0xffff},
+	{"cckbw20ul2gpo",	0x00000600,	0,	SROM9_2GPO_CCKBW20UL,		0xffff},
+	{"legofdmbw202gpo",	0x00000600,	SRFL_MORE, SROM9_2GPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_2GPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul2gpo",	0x00000600,	SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_2GPO_LOFDMBW20UL + 1,	0xffff},
+	{"legofdmbw205glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_5GLPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul5glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GLPO_LOFDMBW20UL + 1,	0xffff},
+	{"legofdmbw205gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_5GMPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul5gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GMPO_LOFDMBW20UL + 1,	0xffff},
+	{"legofdmbw205ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_5GHPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul5ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GHPO_LOFDMBW20UL + 1,	0xffff},
+	{"mcsbw202gpo",		0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_2GPO_MCSBW20 + 1,		0xffff},
+	{"mcsbw20ul2gpo",      	0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_2GPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw402gpo",		0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_2GPO_MCSBW40 + 1,		0xffff},
+	{"mcsbw205glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_5GLPO_MCSBW20 + 1,	0xffff},
+	{"mcsbw20ul5glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GLPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw405glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_5GLPO_MCSBW40 + 1,	0xffff},
+	{"mcsbw205gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_5GMPO_MCSBW20 + 1,	0xffff},
+	{"mcsbw20ul5gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GMPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw405gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_5GMPO_MCSBW40 + 1,	0xffff},
+	{"mcsbw205ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_5GHPO_MCSBW20 + 1,	0xffff},
+	{"mcsbw20ul5ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GHPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw405ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_5GHPO_MCSBW40 + 1,	0xffff},
+	{"mcs32po",		0x00000600,	0,	SROM9_PO_MCS32,			0xffff},
+	{"legofdm40duppo",	0x00000600,	0,	SROM9_PO_LOFDM40DUP,	0xffff},
+	{"pcieingress_war",	0x00000700,	0,	SROM8_PCIEINGRESS_WAR,	0xf},
+	{"rxgainerr2ga0",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x003f},
+	{"rxgainerr2ga1",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x07c0},
+	{"rxgainerr2ga2",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0xf800},
+	{"rxgainerr5gla0",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0x003f},
+	{"rxgainerr5gla1",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0x07c0},
+	{"rxgainerr5gla2",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0xf800},
+	{"rxgainerr5gma0",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0x003f},
+	{"rxgainerr5gma1",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0x07c0},
+	{"rxgainerr5gma2",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0xf800},
+	{"rxgainerr5gha0",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0x003f},
+	{"rxgainerr5gha1",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0x07c0},
+	{"rxgainerr5gha2",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0xf800},
+	{"rxgainerr5gua0",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0x003f},
+	{"rxgainerr5gua1",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0x07c0},
+	{"rxgainerr5gua2",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0xf800},
+	{"sar2g",       	0x00000600,	0,	SROM9_SAR,          	0x00ff},
+	{"sar5g",           0x00000600,	0,	SROM9_SAR,	            0xff00},
+	{"noiselvl2ga0",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x001f},
+	{"noiselvl2ga1",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x03e0},
+	{"noiselvl2ga2",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x7c00},
+	{"noiselvl5gla0",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x001f},
+	{"noiselvl5gla1",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x03e0},
+	{"noiselvl5gla2",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x7c00},
+	{"noiselvl5gma0",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x001f},
+	{"noiselvl5gma1",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x03e0},
+	{"noiselvl5gma2",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x7c00},
+	{"noiselvl5gha0",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x001f},
+	{"noiselvl5gha1",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x03e0},
+	{"noiselvl5gha2",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x7c00},
+	{"noiselvl5gua0",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x001f},
+	{"noiselvl5gua1",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x03e0},
+	{"noiselvl5gua2",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x7c00},
+	{"noisecaloffset",	0x00000300,	0,	SROM8_NOISECALOFFSET,		0x00ff},
+	{"noisecaloffset5g",	0x00000300,	0,	SROM8_NOISECALOFFSET,		0xff00},
+	{"subband5gver",	0x00000700,	0,	SROM8_SUBBAND_PPR,		0x7},
+
+	{"cckPwrOffset",	0x00000400,	0,	SROM10_CCKPWROFFSET,		0xffff},
+	/* swctrlmap_2g array, note that the last element doesn't have SRFL_ARRAY flag set */
+	{"swctrlmap_2g", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G, 0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 1,			0xffff},
+	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 2, 	0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 3,			0xffff},
+	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 4,	0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 5,			0xffff},
+	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 6,	0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 7,			0xffff},
+	{"",	0x00000400, SRFL_PRHEX,	SROM10_SWCTRLMAP_2G + 8,			0xffff},
+
+	/* sromrev 11 */
+	{"boardflags3",	0xfffff800,	SRFL_PRHEX|SRFL_MORE,	SROM11_BFL4,	0xffff},
+	{"",		0,		0,			SROM11_BFL5,	0xffff},
+	{"boardnum",	0xfffff800,	0,			SROM11_MACLO,	0xffff},
+	{"macaddr",	0xfffff800,	SRFL_ETHADDR,		SROM11_MACHI,	0xffff},
+	{"ccode",	0xfffff800,	SRFL_CCODE,		SROM11_CCODE,	0xffff},
+	{"regrev",	0xfffff800,	0,			SROM11_REGREV,	0x00ff},
+	{"ledbh0",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH10,	0x00ff},
+	{"ledbh1",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH10,	0xff00},
+	{"ledbh2",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH32,	0x00ff},
+	{"ledbh3",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH32,	0xff00},
+	{"leddc",	0xfffff800,	SRFL_NOFFS|SRFL_LEDDC,	SROM11_LEDDC,	0xffff},
+	{"aa2g",	0xfffff800,	0,			SROM11_AA,	0x00ff},
+	{"aa5g",	0xfffff800,	0,			SROM11_AA,	0xff00},
+	{"agbg0",	0xfffff800,	0,			SROM11_AGBG10,  0xff00},
+	{"agbg1",	0xfffff800,	0,			SROM11_AGBG10,	0x00ff},
+	{"agbg2",	0xfffff800,	0,			SROM11_AGBG2A0,	0xff00},
+	{"aga0",	0xfffff800,	0,			SROM11_AGBG2A0,	0x00ff},
+	{"aga1",	0xfffff800,	0,			SROM11_AGA21,   0xff00},
+	{"aga2",	0xfffff800,	0,			SROM11_AGA21,	0x00ff},
+	{"txchain",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_TXCHAIN_MASK},
+	{"rxchain",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_RXCHAIN_MASK},
+	{"antswitch",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_SWITCH_MASK},
+
+	{"tssiposslope2g",	0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0001},
+	{"epagain2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x000e},
+	{"pdgain2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x01f0},
+	{"tworangetssi2g",	0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0200},
+	{"papdcap2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0400},
+	{"femctrl",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0xf800},
+
+	{"tssiposslope5g",	0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0001},
+	{"epagain5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x000e},
+	{"pdgain5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x01f0},
+	{"tworangetssi5g",	0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0200},
+	{"papdcap5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0400},
+	{"gainctrlsph",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0xf800},
+
+	{"tempthresh",		0xfffff800,	0,		SROM11_THERMAL,		0xff00},
+	{"tempoffset",		0xfffff800,	0,		SROM11_THERMAL,		0x00ff},
+	{"rawtempsense", 	0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_RAWTS,	0x01ff},
+	{"measpower",		0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_RAWTS,	0xfe00},
+	{"tempsense_slope",	0xfffff800,	SRFL_PRHEX, 	SROM11_TS_SLP_OPT_CORRX, 0x00ff},
+	{"tempcorrx",		0xfffff800,	SRFL_PRHEX, 	SROM11_TS_SLP_OPT_CORRX, 0xfc00},
+	{"tempsense_option",	0xfffff800,	SRFL_PRHEX,	SROM11_TS_SLP_OPT_CORRX, 0x0300},
+	{"xtalfreq",		0xfffff800,	0,		SROM11_XTAL_FREQ, 	0xffff},
+	/* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #1 */
+	{"pa5gbw4080a1", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W0_A1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W1_A1,                 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W2_A1,                 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_4080_W0_A1,                 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA,     0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA + 1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA,     0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 2, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA,     0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA + 1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_4080_PA + 2, 0xffff},
+	{"phycal_tempdelta",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0x00ff},
+	{"temps_period",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0x0f00},
+	{"temps_hysteresis",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0xf000},
+	{"measpower1", 		0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_1_AND_2, 	0x007f},
+	{"measpower2",		0xfffff800, 	SRFL_PRHEX,	SROM11_MPWR_1_AND_2, 	0x3f80},
+	{"tssifloor2g",		0xfffff800,	SRFL_PRHEX,	SROM11_TSSIFLOOR_2G,	0x03ff},
+	{"tssifloor5g",	0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GL,	0x03ff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GM,	0x03ff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GH,	0x03ff},
+	{"",		0xfffff800,	SRFL_PRHEX,		SROM11_TSSIFLOOR_5GU,	0x03ff},
+	{"pdoffset2g40ma0",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x000f},
+	{"pdoffset2g40ma1",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x00f0},
+	{"pdoffset2g40ma2",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x0f00},
+	{"pdoffset2g40mvalid",  0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x8000},
+	{"pdoffset40ma0",      	0xfffff800,	0,		SROM11_PDOFF_40M_A0,   	0xffff},
+	{"pdoffset40ma1",      	0xfffff800,	0,		SROM11_PDOFF_40M_A1,   	0xffff},
+	{"pdoffset40ma2",      	0xfffff800,	0,		SROM11_PDOFF_40M_A2,   	0xffff},
+	{"pdoffset80ma0",      	0xfffff800,	0,		SROM11_PDOFF_80M_A0,   	0xffff},
+	{"pdoffset80ma1",      	0xfffff800,	0,		SROM11_PDOFF_80M_A1,   	0xffff},
+	{"pdoffset80ma2",      	0xfffff800,	0,		SROM11_PDOFF_80M_A2,   	0xffff},
+
+	{"subband5gver",	0xfffff800, 	SRFL_PRHEX,	SROM11_SUBBAND5GVER, 	0xffff},
+	{"paparambwver",	0xfffff800, 	0,		SROM11_MCSLR5GLPO, 	0xf000},
+	/* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #0 */
+	{"pa5gbw4080a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 +SROM11_5GB0_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
+	/* Special PA Params for 4335 5G Band, 40 MHz BW */
+	{"pa5gbw40a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH1 + SROM11_5GB3_PA + 2, 0xffff},
+	/* Special PA Params for 4335 5G Band, 80 MHz BW */
+	{"pa5gbw80a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
+	/* Special PA Params for 4335 2G Band, CCK */
+	{"pa2gccka0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH1 + SROM11_2G_PA + 2, 0xffff},
+
+	/* power per rate */
+	{"cckbw202gpo",		0xfffff800,	0,		SROM11_CCKBW202GPO, 	0xffff},
+	{"cckbw20ul2gpo",	0xfffff800,	0,		SROM11_CCKBW20UL2GPO, 	0xffff},
+	{"mcsbw202gpo",		0xfffff800,	SRFL_MORE,	SROM11_MCSBW202GPO,   	0xffff},
+	{"",            	0xfffff800, 	0,          	SROM11_MCSBW202GPO_1, 	0xffff},
+	{"mcsbw402gpo",		0xfffff800,	SRFL_MORE,	SROM11_MCSBW402GPO,   	0xffff},
+	{"",            	0xfffff800, 	0,   		SROM11_MCSBW402GPO_1, 	0xffff},
+	{"dot11agofdmhrbw202gpo", 0xfffff800, 	0, 	SROM11_DOT11AGOFDMHRBW202GPO, 	0xffff},
+	{"ofdmlrbw202gpo",	0xfffff800, 	0, 		SROM11_OFDMLRBW202GPO,	0xffff},
+	{"mcsbw205glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GLPO, 	0xffff},
+	{"",           		0xfffff800, 	0,   		SROM11_MCSBW205GLPO_1, 	0xffff},
+	{"mcsbw405glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GLPO, 	0xffff},
+	{"",           		0xfffff800, 	0,     		SROM11_MCSBW405GLPO_1, 	0xffff},
+	{"mcsbw805glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GLPO, 	0xffff},
+	{"",           		0xfffff800, 	0,    		SROM11_MCSBW805GLPO_1, 	0xffff},
+	{"mcsbw205gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GMPO, 	0xffff},
+	{"",           		0xfffff800, 	0,     		SROM11_MCSBW205GMPO_1, 	0xffff},
+	{"mcsbw405gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GMPO, 	0xffff},
+	{"",           		0xfffff800, 	0,     		SROM11_MCSBW405GMPO_1, 	0xffff},
+	{"mcsbw805gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GMPO, 	0xffff},
+	{"",           		0xfffff800, 	0,   		SROM11_MCSBW805GMPO_1, 	0xffff},
+	{"mcsbw205ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GHPO, 	0xffff},
+	{"",           		0xfffff800, 	0,  		SROM11_MCSBW205GHPO_1, 	0xffff},
+	{"mcsbw405ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GHPO, 	0xffff},
+	{"",           		0xfffff800, 	0,   		SROM11_MCSBW405GHPO_1, 	0xffff},
+	{"mcsbw805ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GHPO, 	0xffff},
+	{"",           		0xfffff800, 	0,    		SROM11_MCSBW805GHPO_1, 	0xffff},
+	{"mcslr5glpo",		0xfffff800,	0,		SROM11_MCSLR5GLPO, 	0x0fff},
+	{"mcslr5gmpo",		0xfffff800,	0,		SROM11_MCSLR5GMPO, 	0xffff},
+	{"mcslr5ghpo",		0xfffff800,	0,		SROM11_MCSLR5GHPO, 	0xffff},
+	{"sb20in40hrpo", 	0xfffff800,	0,	SROM11_SB20IN40HRPO,		0xffff},
+	{"sb20in80and160hr5glpo", 0xfffff800, 	0, 	SROM11_SB20IN80AND160HR5GLPO, 	0xffff},
+	{"sb40and80hr5glpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GLPO,	0xffff},
+	{"sb20in80and160hr5gmpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160HR5GMPO, 	0xffff},
+	{"sb40and80hr5gmpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GMPO,	0xffff},
+	{"sb20in80and160hr5ghpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160HR5GHPO, 	0xffff},
+	{"sb40and80hr5ghpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GHPO,	0xffff},
+	{"sb20in40lrpo",	  0xfffff800, 	0,	SROM11_SB20IN40LRPO,		0xffff},
+	{"sb20in80and160lr5glpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GLPO, 	0xffff},
+	{"sb40and80lr5glpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GLPO,	0xffff},
+	{"sb20in80and160lr5gmpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GMPO, 	0xffff},
+	{"sb40and80lr5gmpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GMPO,	0xffff},
+	{"sb20in80and160lr5ghpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GHPO, 	0xffff},
+	{"sb40and80lr5ghpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GHPO,	0xffff},
+	{"dot11agduphrpo",	  0xfffff800, 	0,	SROM11_DOT11AGDUPHRPO,		0xffff},
+	{"dot11agduplrpo",	  0xfffff800, 	0,	SROM11_DOT11AGDUPLRPO,		0xffff},
+
+	/* Misc */
+	{"sar2g",       	0xfffff800,	0,	SROM11_SAR,          	0x00ff},
+	{"sar5g",           	0xfffff800,	0,	SROM11_SAR,		0xff00},
+
+	{"noiselvl2ga0",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x001f},
+	{"noiselvl2ga1",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x03e0},
+	{"noiselvl2ga2",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x7c00},
+	{"noiselvl5ga0",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x001f},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x001f},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x001f},
+	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x001f},
+	{"noiselvl5ga1",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x03e0},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x03e0},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x03e0},
+	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x03e0},
+	{"noiselvl5ga2",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x7c00},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x7c00},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x7c00},
+	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x7c00},
+
+	{"rxgainerr2ga0", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0x003f},
+	{"rxgainerr2ga1", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0x07c0},
+	{"rxgainerr2ga2", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0xf800},
+	{"rxgainerr5ga0",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0x003f},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0x003f},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0x003f},
+	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0x003f},
+	{"rxgainerr5ga1",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0x07c0},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0x07c0},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0x07c0},
+	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0x07c0},
+	{"rxgainerr5ga2",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0xf800},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0xf800},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0xf800},
+	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0xf800},
+	{"rpcal2g",      	0xfffff800, 	0,		SROM11_RPCAL_2G,        0xffff},
+	{"rpcal5gb0",      	0xfffff800, 	0,		SROM11_RPCAL_5GL,       0xffff},
+	{"rpcal5gb1",      	0xfffff800, 	0,		SROM11_RPCAL_5GM,       0xffff},
+	{"rpcal5gb2",      	0xfffff800, 	0,		SROM11_RPCAL_5GH,       0xffff},
+	{"rpcal5gb3",      	0xfffff800, 	0,		SROM11_RPCAL_5GU,       0xffff},
+	{"txidxcap2g",      	0xfffff800, 	0,		SROM11_TXIDXCAP2G,      0x0ff0},
+	{"txidxcap5g",      	0xfffff800, 	0,		SROM11_TXIDXCAP5G,      0x0ff0},
+	{"pdoffsetcckma0",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x000f},
+	{"pdoffsetcckma1",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x00f0},
+	{"pdoffsetcckma2",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x0f00},
+	{NULL,		0,		0,		0,			0}
+};
+
+static const sromvar_t perpath_pci_sromvars[] = {
+	{"maxp2ga",	0x000000f0,	0,		SROM4_2G_ITT_MAXP,	0x00ff},
+	{"itt2ga",	0x000000f0,	0,		SROM4_2G_ITT_MAXP,	0xff00},
+	{"itt5ga",	0x000000f0,	0,		SROM4_5G_ITT_MAXP,	0xff00},
+	{"pa2gw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA,		0xffff},
+	{"pa2gw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 1,	0xffff},
+	{"pa2gw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 2,	0xffff},
+	{"pa2gw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 3,	0xffff},
+	{"maxp5ga",	0x000000f0,	0,		SROM4_5G_ITT_MAXP,	0x00ff},
+	{"maxp5gha",	0x000000f0,	0,		SROM4_5GLH_MAXP,	0x00ff},
+	{"maxp5gla",	0x000000f0,	0,		SROM4_5GLH_MAXP,	0xff00},
+	{"pa5gw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA,		0xffff},
+	{"pa5gw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 1,	0xffff},
+	{"pa5gw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 2,	0xffff},
+	{"pa5gw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 3,	0xffff},
+	{"pa5glw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA,		0xffff},
+	{"pa5glw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 1,	0xffff},
+	{"pa5glw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 2,	0xffff},
+	{"pa5glw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 3,	0xffff},
+	{"pa5ghw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA,		0xffff},
+	{"pa5ghw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 1,	0xffff},
+	{"pa5ghw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 2,	0xffff},
+	{"pa5ghw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 3,	0xffff},
+	{"maxp2ga",	0x00000700,	0,		SROM8_2G_ITT_MAXP,	0x00ff},
+	{"itt2ga",	0x00000700,	0,		SROM8_2G_ITT_MAXP,	0xff00},
+	{"itt5ga",	0x00000700,	0,		SROM8_5G_ITT_MAXP,	0xff00},
+	{"pa2gw0a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA,		0xffff},
+	{"pa2gw1a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA + 1,	0xffff},
+	{"pa2gw2a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA + 2,	0xffff},
+	{"maxp5ga",	0x00000700,	0,		SROM8_5G_ITT_MAXP,	0x00ff},
+	{"maxp5gha",	0x00000700,	0,		SROM8_5GLH_MAXP,	0x00ff},
+	{"maxp5gla",	0x00000700,	0,		SROM8_5GLH_MAXP,	0xff00},
+	{"pa5gw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA,		0xffff},
+	{"pa5gw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA + 1,	0xffff},
+	{"pa5gw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA + 2,	0xffff},
+	{"pa5glw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA,		0xffff},
+	{"pa5glw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA + 1,	0xffff},
+	{"pa5glw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA + 2,	0xffff},
+	{"pa5ghw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA,		0xffff},
+	{"pa5ghw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA + 1,	0xffff},
+	{"pa5ghw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA + 2,	0xffff},
+
+	/* sromrev 11 */
+	{"maxp2ga",	0xfffff800,	0,			 SROM11_2G_MAXP,	0x00ff},
+	{"pa2ga",	0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA,		0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA + 1,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX,		 SROM11_2G_PA + 2,	0xffff},
+	{"rxgains5gmelnagaina",	0xfffff800,	0,		 SROM11_RXGAINS1,	0x0007},
+	{"rxgains5gmtrisoa",	0xfffff800,	0,		 SROM11_RXGAINS1,	0x0078},
+	{"rxgains5gmtrelnabypa", 0xfffff800,	0,		 SROM11_RXGAINS1,	0x0080},
+	{"rxgains5ghelnagaina",	0xfffff800,	0,		 SROM11_RXGAINS1,	0x0700},
+	{"rxgains5ghtrisoa",	0xfffff800,	0,		 SROM11_RXGAINS1,	0x7800},
+	{"rxgains5ghtrelnabypa", 0xfffff800,	0,		 SROM11_RXGAINS1,	0x8000},
+	{"rxgains2gelnagaina",	0xfffff800,	0,		 SROM11_RXGAINS,	0x0007},
+	{"rxgains2gtrisoa",	0xfffff800,	0,		 SROM11_RXGAINS,	0x0078},
+	{"rxgains2gtrelnabypa",	0xfffff800,	0,		 SROM11_RXGAINS,	0x0080},
+	{"rxgains5gelnagaina",	0xfffff800,	0,		 SROM11_RXGAINS,	0x0700},
+	{"rxgains5gtrisoa",	0xfffff800,	0,		 SROM11_RXGAINS,	0x7800},
+	{"rxgains5gtrelnabypa",	0xfffff800,	0,		 SROM11_RXGAINS,	0x8000},
+	{"maxp5ga",	0xfffff800,	SRFL_ARRAY,		 SROM11_5GB1B0_MAXP,	0x00ff},
+	{"",		0xfffff800,	SRFL_ARRAY,		 SROM11_5GB1B0_MAXP,	0xff00},
+	{"",		0xfffff800,	SRFL_ARRAY,		 SROM11_5GB3B2_MAXP,	0x00ff},
+	{"",		0xfffff800,	0,			 SROM11_5GB3B2_MAXP,	0xff00},
+	{"pa5ga",	0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 1,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 2,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 1,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 2,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 1,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 2,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA + 1,	0xffff},
+	{"",		0xfffff800,	SRFL_PRHEX,		 SROM11_5GB3_PA + 2,	0xffff},
+
+	{NULL,		0,		0,		0, 			0}
+};
+
+#if !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP))
+#define	PHY_TYPE_HT		7	/* HT-Phy value */
+#define	PHY_TYPE_N		4	/* N-Phy value */
+#define	PHY_TYPE_LP		5	/* LP-Phy value */
+#endif /* !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */
+#if !defined(PHY_TYPE_AC)
+#define	PHY_TYPE_AC		11	/* AC-Phy value */
+#endif /* !defined(PHY_TYPE_AC) */
+#if !defined(PHY_TYPE_NULL)
+#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
+#endif /* !defined(PHY_TYPE_NULL) */
+
+typedef struct {
+	uint16	phy_type;
+	uint16	bandrange;
+	uint16	chain;
+	const char *vars;
+} pavars_t;
+
+static const pavars_t pavars[] = {
+	/* HTPHY */
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  2, "pa2gw0a2 pa2gw1a2 pa2gw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 2, "pa5glw0a2 pa5glw1a2 pa5glw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 2, "pa5gw0a2 pa5gw1a2 pa5gw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 0, "pa5gw0a3 pa5gw1a3 pa5gw2a3"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 1,  "pa5glw0a3 pa5glw1a3 pa5glw2a3"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 2, "pa5ghw0a3 pa5ghw1a3 pa5ghw2a3"},
+	/* NPHY */
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
+	/* LPPHY */
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G,  0, "pa0b0 pa0b1 pa0b2"},
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"},
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"},
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"},
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5ga2"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+/* pavars table when paparambwver is 1 */
+static const pavars_t pavars_bwver_1[] = {
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gccka0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5gbw40a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw80a0"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+/* pavars table when paparambwver is 2 */
+static const pavars_t pavars_bwver_2[] = {
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw4080a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  3, "pa5gbw4080a1"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+typedef struct {
+	uint16	phy_type;
+	uint16	bandrange;
+	const char *vars;
+} povars_t;
+
+static const povars_t povars[] = {
+	/* NPHY */
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
+	"mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
+	"mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
+	"mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
+	"mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
+	{PHY_TYPE_NULL, 0, ""}
+};
+
+typedef struct {
+	uint8	tag;		/* Broadcom subtag name */
+	uint32	revmask;	/* Supported cis_sromrev */
+	uint8	len;		/* Length field of the tuple, note that it includes the
+				 * subtag name (1 byte): 1 + tuple content length
+				 */
+	const char *params;
+} cis_tuple_t;
+
+#define OTP_RAW		(0xff - 1)	/* Reserved tuple number for wrvar Raw input */
+#define OTP_VERS_1	(0xff - 2)	/* CISTPL_VERS_1 */
+#define OTP_MANFID	(0xff - 3)	/* CISTPL_MANFID */
+#define OTP_RAW1	(0xff - 4)	/* Like RAW, but comes first */
+
+static const cis_tuple_t cis_hnbuvars[] = {
+	{OTP_RAW1,		0xffffffff, 0, ""},	/* special case */
+	{OTP_VERS_1,	0xffffffff, 0, "smanf sproductname"},	/* special case (non BRCM tuple) */
+	{OTP_MANFID,	0xffffffff, 4, "2manfid 2prodid"},	/* special case (non BRCM tuple) */
+	/* Unified OTP: tupple to embed USB manfid inside SDIO CIS */
+	{HNBU_UMANFID,		0xffffffff, 8, "8usbmanfid"},
+	{HNBU_SROMREV,		0xffffffff, 2, "1sromrev"},
+	/* NOTE: subdevid is also written to boardtype.
+	 *       Need to write HNBU_BOARDTYPE to change it if it is different.
+	 */
+	{HNBU_CHIPID,		0xffffffff, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"},
+	{HNBU_BOARDREV,		0xffffffff, 3, "2boardrev"},
+	{HNBU_PAPARMS,		0xffffffff, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"},
+	{HNBU_AA,		0xffffffff, 3, "1aa2g 1aa5g"},
+	{HNBU_AA,		0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */
+	{HNBU_AG,		0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"},
+	{HNBU_BOARDFLAGS,	0xffffffff, 13, "4boardflags 4boardflags2 4boardflags3"},
+	{HNBU_LEDS,		0xffffffff, 17, "1ledbh0 1ledbh1 1ledbh2 1ledbh3 1ledbh4 1ledbh5 "
+	"1ledbh6 1ledbh7 1ledbh8 1ledbh9 1ledbh10 1ledbh11 1ledbh12 1ledbh13 1ledbh14 1ledbh15"},
+	{HNBU_CCODE,		0xffffffff, 4, "2ccode 1cctl"},
+	{HNBU_CCKPO,		0xffffffff, 3, "2cckpo"},
+	{HNBU_OFDMPO,		0xffffffff, 5, "4ofdmpo"},
+	{HNBU_PAPARMS5G,	0xffffffff, 23, "2pa1b0 2pa1b1 2pa1b2 2pa1lob0 2pa1lob1 2pa1lob2 "
+	"2pa1hib0 2pa1hib1 2pa1hib2 1pa1itssit "
+	"1pa1maxpwr 1pa1lomaxpwr 1pa1himaxpwr"},
+	{HNBU_RDLID,		0xffffffff, 3, "2rdlid"},
+	{HNBU_RSSISMBXA2G, 0xffffffff, 3, "0rssismf2g 0rssismc2g "
+	"0rssisav2g 0bxa2g"}, /* special case */
+	{HNBU_RSSISMBXA5G, 0xffffffff, 3, "0rssismf5g 0rssismc5g "
+	"0rssisav5g 0bxa5g"}, /* special case */
+	{HNBU_XTALFREQ,		0xffffffff, 5, "4xtalfreq"},
+	{HNBU_TRI2G,		0xffffffff, 2, "1tri2g"},
+	{HNBU_TRI5G,		0xffffffff, 4, "1tri5gl 1tri5g 1tri5gh"},
+	{HNBU_RXPO2G,		0xffffffff, 2, "1rxpo2g"},
+	{HNBU_RXPO5G,		0xffffffff, 2, "1rxpo5g"},
+	{HNBU_BOARDNUM,		0xffffffff, 3, "2boardnum"},
+	{HNBU_MACADDR,		0xffffffff, 7, "6macaddr"},	/* special case */
+	{HNBU_RDLSN,		0xffffffff, 3, "2rdlsn"},
+	{HNBU_BOARDTYPE,	0xffffffff, 3, "2boardtype"},
+	{HNBU_LEDDC,		0xffffffff, 3, "2leddc"},
+	{HNBU_RDLRNDIS,		0xffffffff, 2, "1rdlndis"},
+	{HNBU_CHAINSWITCH,	0xffffffff, 5, "1txchain 1rxchain 2antswitch"},
+	{HNBU_REGREV,		0xffffffff, 2, "1regrev"},
+	{HNBU_FEM,		0x000007fe, 5, "0antswctl2g 0triso2g 0pdetrange2g 0extpagain2g "
+	"0tssipos2g 0antswctl5g 0triso5g 0pdetrange5g 0extpagain5g 0tssipos5g"}, /* special case */
+	{HNBU_PAPARMS_C0,	0x000007fe, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 "
+	"2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 2pa5gw1a0 2pa5gw2a0 "
+	"2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 2pa5ghw1a0 2pa5ghw2a0"},
+	{HNBU_PAPARMS_C1,	0x000007fe, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 "
+	"2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 2pa5gw1a1 2pa5gw2a1 "
+	"2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 2pa5ghw1a1 2pa5ghw2a1"},
+	{HNBU_PO_CCKOFDM,	0xffffffff, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo "
+	"4ofdm5ghpo"},
+	{HNBU_PO_MCS2G,		0xffffffff, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 "
+	"2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"},
+	{HNBU_PO_MCS5GM,	0xffffffff, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 "
+	"2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"},
+	{HNBU_PO_MCS5GLH,	0xffffffff, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 "
+	"2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 "
+	"2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 "
+	"2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"},
+	{HNBU_CCKFILTTYPE,	0xffffffff, 2, "1cckdigfilttype"},
+	{HNBU_PO_CDD,		0xffffffff, 3, "2cddpo"},
+	{HNBU_PO_STBC,		0xffffffff, 3, "2stbcpo"},
+	{HNBU_PO_40M,		0xffffffff, 3, "2bw40po"},
+	{HNBU_PO_40MDUP,	0xffffffff, 3, "2bwduppo"},
+	{HNBU_RDLRWU,		0xffffffff, 2, "1rdlrwu"},
+	{HNBU_WPS,		0xffffffff, 3, "1wpsgpio 1wpsled"},
+	{HNBU_USBFS,		0xffffffff, 2, "1usbfs"},
+	{HNBU_ELNA2G,           0xffffffff, 2, "1elna2g"},
+	{HNBU_ELNA5G,           0xffffffff, 2, "1elna5g"},
+	{HNBU_CUSTOM1,		0xffffffff, 5, "4customvar1"},
+	{OTP_RAW,		0xffffffff, 0, ""},	/* special case */
+	{HNBU_OFDMPO5G,		0xffffffff, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"},
+	{HNBU_USBEPNUM,		0xffffffff, 3, "2usbepnum"},
+	{HNBU_CCKBW202GPO,	0xffffffff, 5, "2cckbw202gpo 2cckbw20ul2gpo"},
+	{HNBU_LEGOFDMBW202GPO,	0xffffffff, 9, "4legofdmbw202gpo 4legofdmbw20ul2gpo"},
+	{HNBU_LEGOFDMBW205GPO,	0xffffffff, 25, "4legofdmbw205glpo 4legofdmbw20ul5glpo "
+	"4legofdmbw205gmpo 4legofdmbw20ul5gmpo 4legofdmbw205ghpo 4legofdmbw20ul5ghpo"},
+	{HNBU_MCS2GPO,	0xffffffff, 13,	"4mcsbw202gpo 4mcsbw20ul2gpo 4mcsbw402gpo"},
+	{HNBU_MCS5GLPO,	0xffffffff, 13,	"4mcsbw205glpo 4mcsbw20ul5glpo 4mcsbw405glpo"},
+	{HNBU_MCS5GMPO,	0xffffffff, 13,	"4mcsbw205gmpo 4mcsbw20ul5gmpo 4mcsbw405gmpo"},
+	{HNBU_MCS5GHPO,	0xffffffff, 13,	"4mcsbw205ghpo 4mcsbw20ul5ghpo 4mcsbw405ghpo"},
+	{HNBU_MCS32PO,	0xffffffff, 3,	"2mcs32po"},
+	{HNBU_LEG40DUPPO, 	0xffffffff, 3,	"2legofdm40duppo"},
+	{HNBU_TEMPTHRESH, 	0xffffffff, 7,	"1tempthresh 0temps_period 0temps_hysteresis "
+	"1tempoffset 1tempsense_slope 0tempcorrx 0tempsense_option "
+	"1phycal_tempdelta"}, /* special case */
+	{HNBU_MUXENAB,		0xffffffff, 2,	"1muxenab"},
+	{HNBU_FEM_CFG,		0xfffff800, 5,	"0femctrl 0papdcap2g 0tworangetssi2g 0pdgain2g "
+	"0epagain2g 0tssiposslope2g 0gainctrlsph 0papdcap5g 0tworangetssi5g 0pdgain5g 0epagain5g "
+	"0tssiposslope5g"}, /* special case */
+	{HNBU_ACPA_C0,		0xfffff800, 39,	"2subband5gver 2maxp2ga0 2*3pa2ga0 "
+	"1*4maxp5ga0 2*12pa5ga0"},
+	{HNBU_ACPA_C1,		0xfffff800, 37,	"2maxp2ga1 2*3pa2ga1 1*4maxp5ga1 2*12pa5ga1"},
+	{HNBU_ACPA_C2,		0xfffff800, 37,	"2maxp2ga2 2*3pa2ga2 1*4maxp5ga2 2*12pa5ga2"},
+	{HNBU_MEAS_PWR,		0xfffff800, 5,	"1measpower 1measpower1 1measpower2 2rawtempsense"},
+	{HNBU_PDOFF,		0xfffff800, 13,	"2pdoffset40ma0 2pdoffset40ma1 2pdoffset40ma2 "
+	"2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"},
+	{HNBU_ACPPR_2GPO,	0xfffff800, 5,	"2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo"},
+	{HNBU_ACPPR_5GPO,	0xfffff800, 31,	"4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo "
+	"4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5glpo 2mcslr5gmpo 2mcslr5ghpo"},
+	{HNBU_ACPPR_SBPO,	0xfffff800, 33,	"2sb20in40hrpo 2sb20in80and160hr5glpo "
+	"2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo "
+	"2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo "
+	"2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo "
+	"2dot11agduphrpo 2dot11agduplrpo"},
+	{HNBU_NOISELVL,		0xfffff800, 16, "1noiselvl2ga0 1noiselvl2ga1 1noiselvl2ga2 "
+	"1*4noiselvl5ga0 1*4noiselvl5ga1 1*4noiselvl5ga2"},
+	{HNBU_RXGAIN_ERR,	0xfffff800, 16, "1rxgainerr2ga0 1rxgainerr2ga1 1rxgainerr2ga2 "
+	"1*4rxgainerr5ga0 1*4rxgainerr5ga1 1*4rxgainerr5ga2"},
+	{HNBU_AGBGA,		0xfffff800, 7, "1agbg0 1agbg1 1agbg2 1aga0 1aga1 1aga2"},
+	{HNBU_UUID, 		0xffffffff, 17,	"16uuid"},
+	{HNBU_WOWLGPIO,		0xffffffff, 2,  "1wowl_gpio"},
+	{HNBU_ACRXGAINS_C0,	0xfffff800, 5, "0rxgains5gtrelnabypa0 0rxgains5gtrisoa0 "
+	"0rxgains5gelnagaina0 0rxgains2gtrelnabypa0 0rxgains2gtrisoa0 0rxgains2gelnagaina0 "
+	"0rxgains5ghtrelnabypa0 0rxgains5ghtrisoa0 0rxgains5ghelnagaina0 0rxgains5gmtrelnabypa0 "
+	"0rxgains5gmtrisoa0 0rxgains5gmelnagaina0"},	/* special case */
+	{HNBU_ACRXGAINS_C1,	0xfffff800, 5, "0rxgains5gtrelnabypa1 0rxgains5gtrisoa1 "
+	"0rxgains5gelnagaina1 0rxgains2gtrelnabypa1 0rxgains2gtrisoa1 0rxgains2gelnagaina1 "
+	"0rxgains5ghtrelnabypa1 0rxgains5ghtrisoa1 0rxgains5ghelnagaina1 0rxgains5gmtrelnabypa1 "
+	"0rxgains5gmtrisoa1 0rxgains5gmelnagaina1"},	/* special case */
+	{HNBU_ACRXGAINS_C2,	0xfffff800, 5, "0rxgains5gtrelnabypa2 0rxgains5gtrisoa2 "
+	"0rxgains5gelnagaina2 0rxgains2gtrelnabypa2 0rxgains2gtrisoa2 0rxgains2gelnagaina2 "
+	"0rxgains5ghtrelnabypa2 0rxgains5ghtrisoa2 0rxgains5ghelnagaina2 0rxgains5gmtrelnabypa2 "
+	"0rxgains5gmtrisoa2 0rxgains5gmelnagaina2"},	/* special case */
+	{HNBU_TXDUTY, 		0xfffff800, 9,	"2tx_duty_cycle_ofdm_40_5g "
+	"2tx_duty_cycle_thresh_40_5g 2tx_duty_cycle_ofdm_80_5g 2tx_duty_cycle_thresh_80_5g"},
+	{HNBU_PDOFF_2G,		0xfffff800, 3,	"0pdoffset2g40ma0 0pdoffset2g40ma1 "
+	"0pdoffset2g40ma2 0pdoffset2g40mvalid"},
+	{HNBU_ACPA_CCK,		0xfffff800, 7,	"2*3pa2gccka0"},
+	{HNBU_ACPA_40,		0xfffff800, 25,	"2*12pa5gbw40a0"},
+	{HNBU_ACPA_80,		0xfffff800, 25,	"2*12pa5gbw80a0"},
+	{HNBU_ACPA_4080,	0xfffff800, 49,	"2*12pa5gbw4080a0 2*12pa5gbw4080a1"},
+	{HNBU_SUBBAND5GVER,	0xfffff800, 3,	"2subband5gver"},
+	{HNBU_PAPARAMBWVER,	0xfffff800, 2,	"1paparambwver"},
+	{0xFF,			0xffffffff, 0, ""}
+};
+
+#endif /* _bcmsrom_tbl_h_ */
diff --git a/src/include/bcmutils.h b/src/include/bcmutils.h
new file mode 100644
index 0000000..82f3cde
--- /dev/null
+++ b/src/include/bcmutils.h
@@ -0,0 +1,1075 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmutils.h 457888 2014-02-25 03:34:39Z $
+ */
+
+#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))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef PKTQ_LOG
+#include <wlioctl.h>
+#endif
+
+
+#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;	
+};
+
+
+#ifdef BCMDRIVER
+#include <osl.h>
+
+#define GPIO_PIN_NOTDEFINED 	0x20	
+
+
+#ifndef SPINWAIT_POLL_PERIOD
+#define SPINWAIT_POLL_PERIOD	10
+#endif
+
+#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; \
+	} \
+}
+
+
+#define PKTQ_LEN_MAX            0xFFFF  
+#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;
+
+#ifdef PKTQ_LOG
+typedef struct {
+	uint32 requested;    
+	uint32 stored;	     
+	uint32 saved;	     
+	uint32 selfsaved;    
+	uint32 full_dropped; 
+	uint32 dropped;      
+	uint32 sacrificed;   
+	uint32 busy;         
+	uint32 retry;        
+	uint32 ps_retry;     
+	uint32 suppress;     
+	uint32 retry_drop;   
+	uint32 max_avail;    
+	uint32 max_used;     
+	uint32 queue_capacity; 
+	uint32 rtsfail;        
+	uint32 acked;          
+	uint32 txrate_succ;    
+	uint32 txrate_main;    
+	uint32 throughput;     
+	uint32 airtime;        
+	uint32  _logtime;      
+} pktq_counters_t;
+
+typedef struct {
+	uint32                  _prec_log;
+	pktq_counters_t*        _prec_cnt[PKTQ_MAX_PREC];     
+} pktq_log_t;
+#endif 
+
+
+#define PKTQ_COMMON	\
+	uint16 num_prec;        			\
+	uint16 hi_prec;         	\
+	uint16 max;             					\
+	uint16 len;             
+
+
+struct pktq {
+	PKTQ_COMMON
+	
+	struct pktq_prec q[PKTQ_MAX_PREC];
+#ifdef PKTQ_LOG
+	pktq_log_t*      pktqlog;
+#endif
+};
+
+
+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);
+
+#ifdef BCMPKTPOOL
+#define POOL_ENAB(pool)		((pool) && (pool)->inited)
+#if defined(BCM4329C0)
+#define SHARED_POOL		(pktpool_shared_ptr)
+#else
+#define SHARED_POOL		(pktpool_shared)
+#endif 
+#else 
+#define POOL_ENAB(bus)		0
+#define SHARED_POOL		((struct pktpool *)NULL)
+#endif 
+
+#ifdef BCMFRAGPOOL
+#define SHARED_FRAG_POOL	(pktpool_shared_lfrag)
+#endif
+#define SHARED_RXFRAG_POOL	(pktpool_shared_rxlfrag)
+
+
+#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 int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg, void* pkt);
+typedef struct {
+	pktpool_cb_extn_t cb;
+	void *arg;
+} pktpool_cbextn_info_t;
+
+
+#ifdef BCMDBG_POOL
+
+#define POOL_IDLE	0
+#define POOL_RXFILL	1
+#define POOL_RXDH	2
+#define POOL_RXD11	3
+#define POOL_TXDH	4
+#define POOL_TXD11	5
+#define POOL_AMPDU	6
+#define POOL_TXENQ	7
+
+typedef struct {
+	void *p;
+	uint32 cycles;
+	uint32 dur;
+} pktpool_dbg_t;
+
+typedef struct {
+	uint8 txdh;	
+	uint8 txd11;	
+	uint8 enq;	
+	uint8 rxdh;	
+	uint8 rxd11;	
+	uint8 rxfill;	
+	uint8 idle;	
+} pktpool_stats_t;
+#endif 
+
+typedef struct pktpool {
+	bool inited;            
+	uint8 type;             
+	uint8 id;               
+	bool istx;              
+
+	void * freelist;        
+	uint16 avail;           
+	uint16 len;             
+	uint16 maxlen;          
+	uint16 plen;            
+
+	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];
+	pktpool_cbextn_info_t cbext;
+#ifdef BCMDBG_POOL
+	uint8 dbg_cbcnt;
+	pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX];
+	uint16 dbg_qlen;
+	pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1];
+#endif
+} pktpool_t;
+
+#if defined(BCM4329C0)
+extern pktpool_t *pktpool_shared_ptr;
+#else
+extern pktpool_t *pktpool_shared;
+#ifdef BCMFRAGPOOL
+extern pktpool_t *pktpool_shared_lfrag;
+#endif
+extern pktpool_t *pktpool_shared_rxlfrag;
+#endif 
+
+
+extern int pktpool_attach(osl_t *osh, uint32 total_pools);
+extern int pktpool_dettach(osl_t *osh); 
+
+extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx, uint8 type);
+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 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);
+int pktpool_hostaddr_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg);
+#define POOLPTR(pp)         ((pktpool_t *)(pp))
+#define POOLID(pp)          (POOLPTR(pp)->id)
+
+#define POOLSETID(pp, ppid) (POOLPTR(pp)->id = (ppid))
+
+#define pktpool_len(pp)     (POOLPTR(pp)->len)
+#define pktpool_avail(pp)   (POOLPTR(pp)->avail)
+#define pktpool_plen(pp)    (POOLPTR(pp)->plen)
+#define pktpool_maxlen(pp)  (POOLPTR(pp)->maxlen)
+
+
+
+#define PKTPOOL_INVALID_ID          (0)
+#define PKTPOOL_MAXIMUM_ID          (15)
+
+
+extern pktpool_t *pktpools_registry[PKTPOOL_MAXIMUM_ID + 1];
+
+
+#define PKTPOOL_ID2PTR(id)          (pktpools_registry[id])
+#define PKTPOOL_PTR2ID(pp)          (POOLID(pp))
+
+
+#ifdef BCMDBG_POOL
+extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_start_trigger(pktpool_t *pktp, void *p);
+extern int pktpool_dbg_dump(pktpool_t *pktp);
+extern int pktpool_dbg_notify(pktpool_t *pktp);
+extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats);
+#endif 
+
+
+
+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_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
+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		
+
+
+
+#define DSCP_AF11	0x0A
+#define DSCP_AF12	0x0C
+#define DSCP_AF13	0x0E
+
+#define DSCP_AF21	0x12
+#define DSCP_AF22	0x14
+#define DSCP_AF23	0x16
+
+#define DSCP_AF31	0x1A
+#define DSCP_AF32	0x1C
+#define DSCP_AF33	0x1E
+
+#define DSCP_EF		0x2E
+
+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 int BCMROMFN(bcm_atoipv4)(const char *p, struct ipv4_addr *ip);
+
+
+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);
+#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	1000
+
+#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(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
+	defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
+extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len);
+#endif 
+#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_USAGE_ERROR                -44     
+#define BCME_IOCTL_ERROR                -45     
+#define BCME_SERIAL_PORT_ERR            -46     
+#define BCME_DISABLED			-47     
+#define BCME_DECERR				-48		
+#define BCME_ENCERR				-49		
+#define BCME_MICERR				-50		
+#define BCME_REPLAY				-51		
+#define BCME_IE_NOTFOUND		-52		
+#define BCME_LAST			BCME_IE_NOTFOUND
+
+#define BCME_NOTENABLED BCME_DISABLED
+
+
+#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",		\
+	"WLCMD usage error",		\
+	"WLCMD ioctl error",		\
+	"RWL serial port error", 	\
+	"Disabled",			\
+	"Decrypt error", \
+	"Encrypt error", \
+	"MIC error", \
+	"Replay", \
+	"IE not found", \
+}
+
+#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 DELTA(curr, prev) ((curr) > (prev) ? ((curr) - (prev)) : \
+	(0xffffffff - (prev) + (curr) + 1))
+#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))
+#define ROUNDUP(x, y)		((((x) + ((y) - 1)) / (y)) * (y))
+#define ROUNDDN(p, align)	((p) & ~((align) - 1))
+#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)
+#else
+#  if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 8))
+
+#    define	OFFSETOF(type, member)	__builtin_offsetof(type, member)
+#  else
+#    define	OFFSETOF(type, member)	((uint)(uintptr)&((type *)0)->member)
+#  endif 
+#endif 
+#endif 
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a)		(sizeof(a) / sizeof(a[0]))
+#endif
+
+#ifndef ARRAYLAST 
+#define ARRAYLAST(a)		(&a[ARRAYSIZE(a)-1])
+#endif
+
+
+extern void *_bcmutils_dummy_fn;
+#define REFERENCE_FUNCTION(f)	(_bcmutils_dummy_fn = (void *)(f))
+
+
+#ifndef setbit
+#ifndef NBBY		
+#define	NBBY	8	
+#endif 
+#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
+extern void setbit(void *array, uint bit);
+extern void clrbit(void *array, uint bit);
+extern bool isset(const void *array, uint bit);
+extern bool isclr(const void *array, uint bit);
+#else
+#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
+#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)
+
+extern void bcm_bitprint32(const uint32 u32);
+
+
+
+#define DECLARE_MAP_API(NB, RSH, LSH, OFF, MSK)                     \
+static INLINE void setbit##NB(void *ptr, uint32 ix, uint32 val)     \
+{                                                                   \
+	uint32 *addr = (uint32 *)ptr;                                   \
+	uint32 *a = addr + (ix >> RSH);               \
+	uint32 pos = (ix & OFF) << LSH;       \
+	uint32 mask = (MSK << pos);                                     \
+	uint32 tmp = *a & ~mask;                                        \
+	*a = tmp | (val << pos);                                        \
+}                                                                   \
+static INLINE uint32 getbit##NB(void *ptr, uint32 ix)               \
+{                                                                   \
+	uint32 *addr = (uint32 *)ptr;                                   \
+	uint32 *a = addr + (ix >> RSH);                                 \
+	uint32 pos = (ix & OFF) << LSH;                                 \
+	return ((*a >> pos) & MSK);                                     \
+}
+
+DECLARE_MAP_API(2,  4, 1, 15U, 0x0003) 
+DECLARE_MAP_API(4,  3, 2,  7U, 0x000F) 
+
+
+
+#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]
+#if !defined(SIMPLE_MAC_PRINT)
+#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5]
+#else
+#define MACDBG				"%02x:%02x:%02x"
+#define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5]
+#endif 
+
+
+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;
+
+
+#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(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \
+	defined(WLMSG_ASSOC)
+
+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(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \
+	defined(WLMSG_ASSOC) || defined(WLMEDIA_PEAKRATE)
+extern int bcm_format_hex(char *str, const void *bytes, int 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);
+
+
+
+
+typedef struct bcm_tlv {
+	uint8	id;
+	uint8	len;
+	uint8	data[1];
+} bcm_tlv_t;
+
+#define BCM_TLV_MAX_DATA_SIZE (255)
+
+#define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data))
+
+
+#define bcm_valid_tlv(elt, buflen) (\
+	 ((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \
+	 ((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->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 bcm_tlv_t *bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type,
+	int type_len);
+
+extern uint8 *bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst);
+extern uint8 *bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst,
+	int dst_maxlen);
+
+extern uint8 *bcm_copy_tlv(const void *src, uint8 *dst);
+extern uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen);
+
+
+extern const char *bcmerrorstr(int bcmerror);
+
+
+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);
+
+
+
+
+
+static const uint8 
+_CSBTBL[256] =
+{
+#	define B2(n)    n,     n + 1,     n + 1,     n + 2
+#	define B4(n) B2(n), B2(n + 1), B2(n + 1), B2(n + 2)
+#	define B6(n) B4(n), B4(n + 1), B4(n + 1), B4(n + 2)
+	B6(0), B6(0 + 1), B6(0 + 1), B6(0 + 2)
+};
+
+static INLINE uint32 
+bcm_cntsetbits(const uint32 u32)
+{
+	
+	const uint8 * p = (const uint8 *)&u32;
+	return (_CSBTBL[p[0]] + _CSBTBL[p[1]] + _CSBTBL[p[2]] + _CSBTBL[p[3]]);
+}
+
+
+static INLINE int 
+C_bcm_count_leading_zeros(uint32 u32)
+{
+	int shifts = 0;
+	while (u32) {
+		shifts++; u32 >>= 1;
+	}
+	return (32U - shifts);
+}
+
+#ifdef BCMDRIVER
+
+
+#if defined(__arm__)
+
+#if defined(__ARM_ARCH_7M__) 
+#define __USE_ASM_CLZ__
+#endif 
+
+#if defined(__ARM_ARCH_7R__) 
+#define __USE_ASM_CLZ__
+#endif 
+
+#endif 
+
+static INLINE int
+bcm_count_leading_zeros(uint32 u32)
+{
+#if defined(__USE_ASM_CLZ__)
+	int zeros;
+	__asm__ volatile("clz    %0, %1 \n" : "=r" (zeros) : "r"  (u32));
+	return zeros;
+#else	
+	return C_bcm_count_leading_zeros(u32);
+#endif  
+}
+
+
+struct bcm_mwbmap;	
+
+#define BCM_MWBMAP_INVALID_HDL	((struct bcm_mwbmap *)NULL)
+#define BCM_MWBMAP_INVALID_IDX	((uint32)(~0U))
+
+
+extern struct bcm_mwbmap * bcm_mwbmap_init(osl_t * osh, uint32 items_max);
+
+
+extern void bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl);
+
+
+extern uint32 bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl);
+
+
+extern void bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+
+extern void bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+
+extern uint32 bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl);
+
+
+extern bool bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+
+extern void bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl);
+
+extern void bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl);
+
+#endif 
+
+extern void bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
+
+void bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset);
+void bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset);
+
+#ifdef __cplusplus
+	}
+#endif
+
+#ifdef DEBUG_COUNTER
+#define CNTR_TBL_MAX 10
+typedef struct _counter_tbl_t {
+	char name[16];				
+	uint32 prev_log_print;		
+	uint log_print_interval;	
+	uint needed_cnt;			
+	uint32 cnt[CNTR_TBL_MAX];		
+	bool enabled;				
+} counter_tbl_t;
+
+
+void counter_printlog(counter_tbl_t *ctr_tbl);
+#endif 
+
+#endif	
diff --git a/src/include/brcm_nl80211.h b/src/include/brcm_nl80211.h
new file mode 100644
index 0000000..f804fb9
--- /dev/null
+++ b/src/include/brcm_nl80211.h
@@ -0,0 +1,38 @@
+/*
+ * Definitions for nl80211 testmode access to host driver
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: brcm_nl80211.h 454792 2014-02-11 20:40:19Z $
+ *
+ */
+
+#ifndef _brcm_nl80211_h_
+#define _brcm_nl80211_h_
+
+struct bcm_nlmsg_hdr {
+	uint cmd;	/* common ioctl definition */
+	uint len;	/* attached buffer length */
+	uint offset;	/* user buffer offset */
+	uint set;	/* get or set request optional */
+	uint magic;	/* magic number for verification */
+};
+
+enum bcmnl_attrs {
+	BCM_NLATTR_UNSPEC,
+
+	BCM_NLATTR_LEN,
+	BCM_NLATTR_DATA,
+
+	__BCM_NLATTR_AFTER_LAST,
+	BCM_NLATTR_MAX = __BCM_NLATTR_AFTER_LAST - 1
+};
+
+struct nl_prv_data {
+	int err;			/* return result */
+	void *data;			/* ioctl return buffer pointer */
+	uint len;			/* ioctl return buffer length */
+	struct bcm_nlmsg_hdr *nlioc;	/* bcm_nlmsg_hdr header pointer */
+};
+
+#endif /* _brcm_nl80211_h_ */
diff --git a/src/include/dhdioctl.h b/src/include/dhdioctl.h
new file mode 100644
index 0000000..89bf3de
--- /dev/null
+++ b/src/include/dhdioctl.h
@@ -0,0 +1,121 @@
+/*
+ * Definitions for ioctls to access DHD iovars.
+ * Based on wlioctl.h (for Broadcom 802.11abg driver).
+ * (Moves towards generic ioctls for BCM drivers/iovars.)
+ *
+ * Definitions subject to change without notice.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: dhdioctl.h 454792 2014-02-11 20:40:19Z $
+ */
+
+#ifndef _dhdioctl_h_
+#define	_dhdioctl_h_
+
+#include <typedefs.h>
+
+
+/* require default structure packing */
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+
+/* Linux network driver ioctl encoding */
+typedef struct dhd_ioctl {
+	uint cmd;	/* common ioctl definition */
+	void *buf;	/* pointer to user buffer */
+	uint len;	/* length of user buffer */
+	bool set;	/* get or set request (optional) */
+	uint used;	/* bytes read or written (optional) */
+	uint needed;	/* bytes needed (optional) */
+	uint driver;	/* to identify target driver */
+} dhd_ioctl_t;
+
+/* Underlying BUS definition */
+enum {
+	BUS_TYPE_USB = 0, /* for USB dongles */
+	BUS_TYPE_SDIO, /* for SDIO dongles */
+	BUS_TYPE_PCIE /* for PCIE dongles */
+};
+
+/* per-driver magic numbers */
+#define DHD_IOCTL_MAGIC		0x00444944
+
+/* bump this number if you change the ioctl interface */
+#define DHD_IOCTL_VERSION	1
+
+#define	DHD_IOCTL_MAXLEN	8192		/* max length ioctl buffer required */
+#define	DHD_IOCTL_SMLEN		256		/* "small" length ioctl buffer required */
+
+/* common ioctl definitions */
+#define DHD_GET_MAGIC				0
+#define DHD_GET_VERSION				1
+#define DHD_GET_VAR				2
+#define DHD_SET_VAR				3
+
+/* message levels */
+#define DHD_ERROR_VAL	0x0001
+#define DHD_TRACE_VAL	0x0002
+#define DHD_INFO_VAL	0x0004
+#define DHD_DATA_VAL	0x0008
+#define DHD_CTL_VAL	0x0010
+#define DHD_TIMER_VAL	0x0020
+#define DHD_HDRS_VAL	0x0040
+#define DHD_BYTES_VAL	0x0080
+#define DHD_INTR_VAL	0x0100
+#define DHD_LOG_VAL	0x0200
+#define DHD_GLOM_VAL	0x0400
+#define DHD_EVENT_VAL	0x0800
+#define DHD_BTA_VAL	0x1000
+#if 0 && (NDISVER >= 0x0630) && 1
+#define DHD_SCAN_VAL	0x2000
+#else
+#define DHD_ISCAN_VAL	0x2000
+#endif
+#define DHD_ARPOE_VAL	0x4000
+#define DHD_REORDER_VAL	0x8000
+#define DHD_WL_VAL		0x10000
+#define DHD_NOCHECKDIED_VAL		0x20000 /* UTF WAR */
+#define DHD_WL_VAL2		0x40000
+#define DHD_PNO_VAL		0x80000
+
+#ifdef SDTEST
+/* For pktgen iovar */
+typedef struct dhd_pktgen {
+	uint version;		/* To allow structure change tracking */
+	uint freq;		/* Max ticks between tx/rx attempts */
+	uint count;		/* Test packets to send/rcv each attempt */
+	uint print;		/* Print counts every <print> attempts */
+	uint total;		/* Total packets (or bursts) */
+	uint minlen;		/* Minimum length of packets to send */
+	uint maxlen;		/* Maximum length of packets to send */
+	uint numsent;		/* Count of test packets sent */
+	uint numrcvd;		/* Count of test packets received */
+	uint numfail;		/* Count of test send failures */
+	uint mode;		/* Test mode (type of test packets) */
+	uint stop;		/* Stop after this many tx failures */
+} dhd_pktgen_t;
+
+/* Version in case structure changes */
+#define DHD_PKTGEN_VERSION 2
+
+/* Type of test packets to use */
+#define DHD_PKTGEN_ECHO		1 /* Send echo requests */
+#define DHD_PKTGEN_SEND 	2 /* Send discard packets */
+#define DHD_PKTGEN_RXBURST	3 /* Request dongle send N packets */
+#define DHD_PKTGEN_RECV		4 /* Continuous rx from continuous tx dongle */
+#endif /* SDTEST */
+
+/* Enter idle immediately (no timeout) */
+#define DHD_IDLE_IMMEDIATE	(-1)
+
+/* Values for idleclock iovar: other values are the sd_divisor to use when idle */
+#define DHD_IDLE_ACTIVE	0	/* Do not request any SD clock change when idle */
+#define DHD_IDLE_STOP   (-1)	/* Request SD clock be stopped (and use SD1 mode) */
+
+
+/* require default structure packing */
+#include <packed_section_end.h>
+
+#endif /* _dhdioctl_h_ */
diff --git a/src/include/epivers.h b/src/include/epivers.h
new file mode 100644
index 0000000..fd26ef5
--- /dev/null
+++ b/src/include/epivers.h
@@ -0,0 +1,30 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $
+ *
+*/
+
+#ifndef _epivers_h_
+#define _epivers_h_
+
+#define	EPI_MAJOR_VERSION	1
+
+#define	EPI_MINOR_VERSION	141
+
+#define	EPI_RC_NUMBER		66
+
+#define	EPI_INCREMENTAL_NUMBER	4
+
+#define EPI_BUILD_NUMBER	1
+
+#define	EPI_VERSION		1, 141, 66, 4
+
+#define	EPI_VERSION_NUM		0x018d4204
+
+#define EPI_VERSION_DEV		1.141.66
+
+
+#define	EPI_VERSION_STR		"1.141.66.4 (r655085)"
+
+#endif 
diff --git a/src/include/event_log.h b/src/include/event_log.h
new file mode 100644
index 0000000..35c2ba7
--- /dev/null
+++ b/src/include/event_log.h
@@ -0,0 +1,279 @@
+/*
+ * EVENT_LOG system definitions
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: event_log.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _EVENT_LOG_H_
+#define _EVENT_LOG_H_
+
+
+/* Set a maximum number of sets here.  It is not dynamic for
+ *  efficiency of the EVENT_LOG calls.
+ */
+#define NUM_EVENT_LOG_SETS 4
+#define EVENT_LOG_SET_BUS	0
+#define EVENT_LOG_SET_WL	1
+#define EVENT_LOG_SET_PSM	2
+
+/* Define new event log tags here */
+#define EVENT_LOG_TAG_NULL	0	/* Special null tag */
+#define EVENT_LOG_TAG_TS	1	/* Special timestamp tag */
+#define EVENT_LOG_TAG_BUS_OOB	2
+#define EVENT_LOG_TAG_BUS_STATE	3
+#define EVENT_LOG_TAG_BUS_PROTO	4
+#define EVENT_LOG_TAG_BUS_CTL	5
+#define EVENT_LOG_TAG_BUS_EVENT	6
+#define EVENT_LOG_TAG_BUS_PKT	7
+#define EVENT_LOG_TAG_BUS_FRAME	8
+#define EVENT_LOG_TAG_BUS_DESC	9
+#define EVENT_LOG_TAG_BUS_SETUP	10
+#define EVENT_LOG_TAG_BUS_MISC	11
+#define EVENT_LOG_TAG_AWDL_ERR	12
+#define EVENT_LOG_TAG_AWDL_WARN	13
+#define EVENT_LOG_TAG_AWDL_INFO	14
+#define EVENT_LOG_TAG_AWDL_DEBUG	15
+#define EVENT_LOG_TAG_AWDL_TRACE_TIMER	16
+#define EVENT_LOG_TAG_AWDL_TRACE_SYNC	17
+#define EVENT_LOG_TAG_AWDL_TRACE_CHAN	18
+#define EVENT_LOG_TAG_AWDL_TRACE_DP		19
+#define EVENT_LOG_TAG_AWDL_TRACE_MISC	20
+#define EVENT_LOG_TAG_AWDL_TEST		21
+#define EVENT_LOG_TAG_SRSCAN		22
+#define EVENT_LOG_TAG_PWRSTATS_INFO	23
+#define EVENT_LOG_TAG_AWDL_TRACE_CHANSW	24
+#define EVENT_LOG_TAG_AWDL_TRACE_PEER_OPENCLOSE	25
+#define EVENT_LOG_TAG_UCODE_WATCHDOG 26
+#define EVENT_LOG_TAG_UCODE_FIFO 27
+#define EVENT_LOG_TAG_SCAN_TRACE_LOW	28
+#define EVENT_LOG_TAG_SCAN_TRACE_HIGH	29
+#define EVENT_LOG_TAG_SCAN_ERROR	30
+#define EVENT_LOG_TAG_SCAN_WARN	31
+#define EVENT_LOG_TAG_MPF_ERR	32
+#define EVENT_LOG_TAG_MPF_WARN	33
+#define EVENT_LOG_TAG_MPF_INFO	34
+#define EVENT_LOG_TAG_MPF_DEBUG	35
+#define EVENT_LOG_TAG_MAX 	35
+
+/* Flags for tag control */
+#define EVENT_LOG_TAG_FLAG_NONE		0
+#define EVENT_LOG_TAG_FLAG_LOG		0x80
+#define EVENT_LOG_TAG_FLAG_PRINT	0x40
+#define EVENT_LOG_TAG_FLAG_MASK		0x3f
+
+/* logstrs header */
+#define LOGSTRS_MAGIC   0x4C4F4753
+#define LOGSTRS_VERSION 0x1
+
+/* We make sure that the block size will fit in a single packet
+ *  (allowing for a bit of overhead on each packet
+ */
+#define EVENT_LOG_MAX_BLOCK_SIZE 1400
+#define EVENT_LOG_PSM_BLOCK 0x200
+
+/*
+ * There are multiple levels of objects define here:
+ *   event_log_set - a set of buffers
+ *   event log groups - every event log call is part of just one.  All
+ *                      event log calls in a group are handled the
+ *                      same way.  Each event log group is associated
+ *                      with an event log set or is off.
+ */
+
+#ifndef __ASSEMBLER__
+
+/* On the external system where the dumper is we need to make sure
+ * that these types are the same size as they are on the ARM the
+ * produced them
+ */
+#ifdef EVENT_LOG_DUMPER
+#define _EL_BLOCK_PTR uint32
+#define _EL_TYPE_PTR uint32
+#define _EL_SET_PTR uint32
+#define _EL_TOP_PTR uint32
+#else
+#define _EL_BLOCK_PTR struct event_log_block *
+#define _EL_TYPE_PTR uint32 *
+#define _EL_SET_PTR struct event_log_set **
+#define _EL_TOP_PTR struct event_log_top *
+#endif /* EVENT_LOG_DUMPER */
+
+/* Each event log entry has a type.  The type is the LAST word of the
+ * event log.  The printing code walks the event entries in reverse
+ * order to find the first entry.
+ */
+typedef union event_log_hdr {
+	struct {
+		uint8 tag;		/* Event_log entry tag */
+		uint8 count;		/* Count of 4-byte entries */
+		uint16 fmt_num;		/* Format number */
+	};
+	uint32 t;			/* Type cheat */
+} event_log_hdr_t;
+
+/* Event log sets (a logical circurlar buffer) consist of one or more
+ * event_log_blocks.  The blocks themselves form a logical circular
+ * list.  The log entries are placed in each event_log_block until it
+ * is full.  Logging continues with the next event_log_block in the
+ * event_set until the last event_log_block is reached and then
+ * logging starts over with the first event_log_block in the
+ * event_set.
+ */
+typedef struct event_log_block {
+	_EL_BLOCK_PTR next_block;
+	_EL_BLOCK_PTR prev_block;
+	_EL_TYPE_PTR end_ptr;
+
+	/* Start of packet sent for log tracing */
+	uint16 pktlen;			/* Size of rest of block */
+	uint16 count;			/* Logtrace counter */
+	uint32 timestamp;		/* Timestamp at start of use */
+	uint32 event_logs;
+} event_log_block_t;
+
+/* There can be multiple event_sets with each logging a set of
+ * associated events (i.e, "fast" and "slow" events).
+ */
+typedef struct event_log_set {
+	_EL_BLOCK_PTR first_block; 	/* Pointer to first event_log block */
+	_EL_BLOCK_PTR last_block; 	/* Pointer to last event_log block */
+	_EL_BLOCK_PTR logtrace_block;	/* next block traced */
+	_EL_BLOCK_PTR cur_block;   	/* Pointer to current event_log block */
+	_EL_TYPE_PTR cur_ptr;      	/* Current event_log pointer */
+	uint32 blockcount;		/* Number of blocks */
+	uint16 logtrace_count;		/* Last count for logtrace */
+	uint16 blockfill_count;		/* Fill count for logtrace */
+	uint32 timestamp;		/* Last timestamp event */
+	uint32 cyclecount;		/* Cycles at last timestamp event */
+} event_log_set_t;
+
+/* Top data structure for access to everything else */
+typedef struct event_log_top {
+	uint32 magic;
+#define EVENT_LOG_TOP_MAGIC 0x474C8669 /* 'EVLG' */
+	uint32 version;
+#define EVENT_LOG_VERSION 1
+	uint32 num_sets;
+	uint32 logstrs_size;		/* Size of lognums + logstrs area */
+	uint32 timestamp;		/* Last timestamp event */
+	uint32 cyclecount;		/* Cycles at last timestamp event */
+	_EL_SET_PTR sets; 		/* Ptr to array of <num_sets> set ptrs */
+} event_log_top_t;
+
+/* Data structure of Keeping the Header from logstrs.bin */
+typedef struct {
+	uint32 logstrs_size;    /* Size of the file */
+	uint32 rom_lognums_offset; /* Offset to the ROM lognum */
+	uint32 ram_lognums_offset; /* Offset to the RAM lognum */
+	uint32 rom_logstrs_offset; /* Offset to the ROM logstr */
+	uint32 ram_logstrs_offset; /* Offset to the RAM logstr */
+	/* Keep version and magic last since "header" is appended to the end of logstrs file. */
+	uint32 version;            /* Header version */
+	uint32 log_magic;       /* MAGIC number for verification 'LOGS' */
+} logstr_header_t;
+
+
+#ifndef EVENT_LOG_DUMPER
+
+#ifndef EVENT_LOG_COMPILE
+
+/* Null define if no tracing */
+#define EVENT_LOG(format, ...)
+
+#else  /* EVENT_LOG_COMPILE */
+
+/* The first few are special because they can be done more efficiently
+ * this way and they are the common case.  Once there are too many
+ * parameters the code size starts to be an issue and a loop is better
+ */
+#define _EVENT_LOG0(tag, fmt_num) 			\
+	event_log0(tag, fmt_num)
+#define _EVENT_LOG1(tag, fmt_num, t1) 			\
+	event_log1(tag, fmt_num, t1)
+#define _EVENT_LOG2(tag, fmt_num, t1, t2) 		\
+	event_log2(tag, fmt_num, t1, t2)
+#define _EVENT_LOG3(tag, fmt_num, t1, t2, t3) 		\
+	event_log3(tag, fmt_num, t1, t2, t3)
+#define _EVENT_LOG4(tag, fmt_num, t1, t2, t3, t4) 	\
+	event_log4(tag, fmt_num, t1, t2, t3, t4)
+
+/* The rest call the generic routine that takes a count */
+#define _EVENT_LOG5(tag, fmt_num, ...) event_logn(5, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG6(tag, fmt_num, ...) event_logn(6, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG7(tag, fmt_num, ...) event_logn(7, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG8(tag, fmt_num, ...) event_logn(8, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG9(tag, fmt_num, ...) event_logn(9, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGA(tag, fmt_num, ...) event_logn(10, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGB(tag, fmt_num, ...) event_logn(11, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGC(tag, fmt_num, ...) event_logn(12, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGD(tag, fmt_num, ...) event_logn(13, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGE(tag, fmt_num, ...) event_logn(14, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGF(tag, fmt_num, ...) event_logn(15, tag, fmt_num, __VA_ARGS__)
+
+/* Hack to make the proper routine call when variadic macros get
+ * passed.  Note the max of 15 arguments.  More than that can't be
+ * handled by the event_log entries anyways so best to catch it at compile
+ * time
+ */
+
+#define _EVENT_LOG_VA_NUM_ARGS(F, _1, _2, _3, _4, _5, _6, _7, _8, _9,	\
+			       _A, _B, _C, _D, _E, _F, N, ...) F ## N
+
+#define _EVENT_LOG(tag, fmt, ...)					\
+	static char logstr[] __attribute__ ((section(".logstrs"))) = fmt; \
+	static uint32 fmtnum __attribute__ ((section(".lognums"))) = (uint32) &logstr; \
+	_EVENT_LOG_VA_NUM_ARGS(_EVENT_LOG, ##__VA_ARGS__,		\
+			       F, E, D, C, B, A, 9, 8,			\
+			       7, 6, 5, 4, 3, 2, 1, 0)			\
+	(tag, (int) &fmtnum , ## __VA_ARGS__);				\
+
+
+#define EVENT_LOG_FAST(tag, fmt, ...)					\
+	if (event_log_tag_sets != NULL) {				\
+		uint8 tag_flag = *(event_log_tag_sets + tag);		\
+		if (tag_flag != 0) {					\
+			_EVENT_LOG(tag, fmt , ## __VA_ARGS__);		\
+		}							\
+	}
+
+#define EVENT_LOG_COMPACT(tag, fmt, ...)				\
+	if (1) {							\
+		_EVENT_LOG(tag, fmt , ## __VA_ARGS__);			\
+	}
+
+#define EVENT_LOG(tag, fmt, ...) EVENT_LOG_COMPACT(tag, fmt , ## __VA_ARGS__)
+
+#define EVENT_LOG_IS_LOG_ON(tag) (*(event_log_tag_sets + (tag)) & EVENT_LOG_TAG_FLAG_LOG)
+
+#define EVENT_DUMP	event_log_buffer
+
+extern uint8 *event_log_tag_sets;
+
+extern int event_log_init(si_t *sih);
+extern int event_log_set_init(si_t *sih, int set_num, int size);
+extern int event_log_set_expand(si_t *sih, int set_num, int size);
+extern int event_log_set_shrink(si_t *sih, int set_num, int size);
+extern int event_log_tag_start(int tag, int set_num, int flags);
+extern int event_log_tag_stop(int tag);
+extern int event_log_get(int set_num, int buflen, void *buf);
+extern uint8 * event_log_next_logtrace(int set_num);
+
+extern void event_log0(int tag, int fmtNum);
+extern void event_log1(int tag, int fmtNum, uint32 t1);
+extern void event_log2(int tag, int fmtNum, uint32 t1, uint32 t2);
+extern void event_log3(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3);
+extern void event_log4(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3, uint32 t4);
+extern void event_logn(int num_args, int tag, int fmtNum, ...);
+
+extern void event_log_time_sync(void);
+extern void event_log_buffer(int tag, uint8 *buf, int size);
+
+#endif /* EVENT_LOG_DUMPER */
+
+#endif /* EVENT_LOG_COMPILE */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* _EVENT_LOG_H */
diff --git a/src/include/hndrte_armtrap.h b/src/include/hndrte_armtrap.h
new file mode 100644
index 0000000..83adf38
--- /dev/null
+++ b/src/include/hndrte_armtrap.h
@@ -0,0 +1,70 @@
+/*
+ * HNDRTE arm trap handling.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: hndrte_armtrap.h 261365 2011-05-24 20:42:23Z $
+ */
+
+#ifndef	_hndrte_armtrap_h
+#define	_hndrte_armtrap_h
+
+
+/* ARM trap handling */
+
+/* Trap types defined by ARM (see arminc.h) */
+
+/* Trap locations in lo memory */
+#define	TRAP_STRIDE	4
+#define FIRST_TRAP	TR_RST
+#define LAST_TRAP	(TR_FIQ * TRAP_STRIDE)
+
+#if defined(__ARM_ARCH_4T__)
+#define	MAX_TRAP_TYPE	(TR_FIQ + 1)
+#elif defined(__ARM_ARCH_7M__)
+#define	MAX_TRAP_TYPE	(TR_ISR + ARMCM3_NUMINTS)
+#endif	/* __ARM_ARCH_7M__ */
+
+/* The trap structure is defined here as offsets for assembly */
+#define	TR_TYPE		0x00
+#define	TR_EPC		0x04
+#define	TR_CPSR		0x08
+#define	TR_SPSR		0x0c
+#define	TR_REGS		0x10
+#define	TR_REG(n)	(TR_REGS + (n) * 4)
+#define	TR_SP		TR_REG(13)
+#define	TR_LR		TR_REG(14)
+#define	TR_PC		TR_REG(15)
+
+#define	TRAP_T_SIZE	80
+
+#ifndef	_LANGUAGE_ASSEMBLY
+
+#include <typedefs.h>
+
+typedef struct _trap_struct {
+	uint32		type;
+	uint32		epc;
+	uint32		cpsr;
+	uint32		spsr;
+	uint32		r0;	/* a1 */
+	uint32		r1;	/* a2 */
+	uint32		r2;	/* a3 */
+	uint32		r3;	/* a4 */
+	uint32		r4;	/* v1 */
+	uint32		r5;	/* v2 */
+	uint32		r6;	/* v3 */
+	uint32		r7;	/* v4 */
+	uint32		r8;	/* v5 */
+	uint32		r9;	/* sb/v6 */
+	uint32		r10;	/* sl/v7 */
+	uint32		r11;	/* fp/v8 */
+	uint32		r12;	/* ip */
+	uint32		r13;	/* sp */
+	uint32		r14;	/* lr */
+	uint32		pc;	/* r15 */
+} trap_t;
+
+#endif	/* !_LANGUAGE_ASSEMBLY */
+
+#endif	/* _hndrte_armtrap_h */
diff --git a/src/include/hndrte_cons.h b/src/include/hndrte_cons.h
new file mode 100644
index 0000000..33a6cd8
--- /dev/null
+++ b/src/include/hndrte_cons.h
@@ -0,0 +1,60 @@
+/*
+ * Console support for hndrte.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: hndrte_cons.h 427140 2013-10-02 18:07:07Z $
+ */
+#ifndef	_HNDRTE_CONS_H
+#define	_HNDRTE_CONS_H
+
+#include <typedefs.h>
+
+#if defined(RWL_DONGLE) || defined(UART_REFLECTOR)
+/* For Dongle uart tranport max cmd len is 256 bytes + header length (16 bytes)
+ *  In case of ASD commands we are not sure about how much is the command size
+ *  To be on the safe side, input buf len CBUF_LEN is increased to max (512) bytes.
+ */
+#define RWL_MAX_DATA_LEN 	(512 + 8)	/* allow some extra bytes for '/n' termination */
+#define CBUF_LEN	(RWL_MAX_DATA_LEN + 64)  /* allow 64 bytes for header ("rwl...") */
+#else
+#define CBUF_LEN	(128)
+#endif /* RWL_DONGLE || UART_REFLECTOR */
+
+#define LOG_BUF_LEN	1024
+
+typedef struct {
+	uint32		buf;		/* Can't be pointer on (64-bit) hosts */
+	uint		buf_size;
+	uint		idx;
+	uint		out_idx;	/* output index */
+} hndrte_log_t;
+
+typedef struct {
+	/* Virtual UART
+	 *   When there is no UART (e.g. Quickturn), the host should write a complete
+	 *   input line directly into cbuf and then write the length into vcons_in.
+	 *   This may also be used when there is a real UART (at risk of conflicting with
+	 *   the real UART).  vcons_out is currently unused.
+	 */
+	volatile uint	vcons_in;
+	volatile uint	vcons_out;
+
+	/* Output (logging) buffer
+	 *   Console output is written to a ring buffer log_buf at index log_idx.
+	 *   The host may read the output when it sees log_idx advance.
+	 *   Output will be lost if the output wraps around faster than the host polls.
+	 */
+	hndrte_log_t	log;
+
+	/* Console input line buffer
+	 *   Characters are read one at a time into cbuf until <CR> is received, then
+	 *   the buffer is processed as a command line.  Also used for virtual UART.
+	 */
+	uint		cbuf_idx;
+	char		cbuf[CBUF_LEN];
+} hndrte_cons_t;
+
+hndrte_cons_t *hndrte_get_active_cons_state(void);
+
+#endif /* _HNDRTE_CONS_H */
diff --git a/src/include/hndrte_debug.h b/src/include/hndrte_debug.h
new file mode 100644
index 0000000..c305f7e
--- /dev/null
+++ b/src/include/hndrte_debug.h
@@ -0,0 +1,99 @@
+/*
+ * HND Run Time Environment debug info area
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: hndrte_debug.h 342211 2012-07-02 02:23:04Z $
+ */
+
+#ifndef	_HNDRTE_DEBUG_H
+#define	_HNDRTE_DEBUG_H
+
+/* Magic number at a magic location to find HNDRTE_DEBUG pointers */
+#define HNDRTE_DEBUG_PTR_PTR_MAGIC 0x50504244  	/* DBPP */
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+/* Includes only when building dongle code */
+
+
+#define NUM_EVENT_LOG_SETS 4
+
+/* We use explicit sizes here since this gets included from different
+ * systems.  The sizes must be the size of the creating system
+ * (currently 32 bit ARM) since this is gleaned from  dump.
+ */
+
+#ifdef FWID
+extern uint32 gFWID;
+#endif
+
+/* Define pointers for use on other systems */
+#define _HD_EVLOG_P	uint32
+#define _HD_CONS_P	uint32
+#define _HD_TRAP_P	uint32
+
+typedef struct hndrte_debug {
+	uint32	magic;
+#define HNDRTE_DEBUG_MAGIC 0x47424544	/* 'DEBG' */
+
+	uint32	version;		/* Debug struct version */
+#define HNDRTE_DEBUG_VERSION 1
+
+	uint32	fwid;			/* 4 bytes of fw info */
+	char	epivers[32];
+
+	_HD_TRAP_P trap_ptr;		/* trap_t data struct */
+	_HD_CONS_P console;		/* Console  */
+
+	uint32	ram_base;
+	uint32	ram_size;
+
+	uint32	rom_base;
+	uint32	rom_size;
+
+	_HD_EVLOG_P event_log_top;
+
+} hndrte_debug_t;
+
+/*
+ * timeval_t and prstatus_t are copies of the Linux structures.
+ * Included here because we need the definitions for the target processor
+ * (32 bits) and not the definition on the host this is running on
+ * (which could be 64 bits).
+ */
+
+typedef struct             {    /* Time value with microsecond resolution    */
+	uint32 tv_sec;	/* Seconds                                   */
+	uint32 tv_usec;	/* Microseconds                              */
+} timeval_t;
+
+
+/* Linux/ARM 32 prstatus for notes section */
+typedef struct prstatus {
+	  int32 si_signo; 	/* Signal number */
+	  int32 si_code; 	/* Extra code */
+	  int32 si_errno; 	/* Errno */
+	  uint16 pr_cursig; 	/* Current signal.  */
+	  uint16 unused;
+	  uint32 pr_sigpend;	/* Set of pending signals.  */
+	  uint32 pr_sighold;	/* Set of held signals.  */
+	  uint32 pr_pid;
+	  uint32 pr_ppid;
+	  uint32 pr_pgrp;
+	  uint32 pr_sid;
+	  timeval_t pr_utime;	/* User time.  */
+	  timeval_t pr_stime;	/* System time.  */
+	  timeval_t pr_cutime;	/* Cumulative user time.  */
+	  timeval_t pr_cstime;	/* Cumulative system time.  */
+	  uint32 uregs[18];
+	  int32 pr_fpvalid;	/* True if math copro being used.  */
+} prstatus_t;
+
+#ifdef __GNUC__
+extern hndrte_debug_t hndrte_debug_info;
+#endif /* __GNUC__ */
+
+#endif /* !LANGUAGE_ASSEMBLY */
+
+#endif /* _HNDRTE_DEBUG_H */
diff --git a/src/include/miniopt.h b/src/include/miniopt.h
new file mode 100644
index 0000000..6c13070
--- /dev/null
+++ b/src/include/miniopt.h
@@ -0,0 +1,59 @@
+/*
+ * Command line options parser.
+ *
+ * $Copyright Open Broadcom Corporation$
+ * $Id: miniopt.h 241182 2011-02-17 21:50:03Z $
+ */
+
+
+#ifndef MINI_OPT_H
+#define MINI_OPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---- Include Files ---------------------------------------------------- */
+/* ---- Constants and Types ---------------------------------------------- */
+
+#define MINIOPT_MAXKEY	128	/* Max options */
+typedef struct miniopt {
+
+	/* These are persistent after miniopt_init() */
+	const char* name;		/* name for prompt in error strings */
+	const char* flags;		/* option chars that take no args */
+	bool longflags;		/* long options may be flags */
+	bool opt_end;		/* at end of options (passed a "--") */
+
+	/* These are per-call to miniopt() */
+
+	int consumed;		/* number of argv entries cosumed in
+				 * the most recent call to miniopt()
+				 */
+	bool positional;
+	bool good_int;		/* 'val' member is the result of a sucessful
+				 * strtol conversion of the option value
+				 */
+	char opt;
+	char key[MINIOPT_MAXKEY];
+	char* valstr;		/* positional param, or value for the option,
+				 * or null if the option had
+				 * no accompanying value
+				 */
+	uint uval;		/* strtol translation of valstr */
+	int  val;		/* strtol translation of valstr */
+} miniopt_t;
+
+void miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags);
+int miniopt(miniopt_t *t, char **argv);
+
+
+/* ---- Variable Externs ------------------------------------------------- */
+/* ---- Function Prototypes ---------------------------------------------- */
+
+
+#ifdef __cplusplus
+	}
+#endif
+
+#endif  /* MINI_OPT_H  */
diff --git a/src/include/packed_section_end.h b/src/include/packed_section_end.h
new file mode 100644
index 0000000..761838c
--- /dev/null
+++ b/src/include/packed_section_end.h
@@ -0,0 +1,35 @@
+/*
+ * 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 Open Broadcom Corporation$
+ * $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $
+ */
+
+
+
+#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..ba00dbd
--- /dev/null
+++ b/src/include/packed_section_start.h
@@ -0,0 +1,42 @@
+/*
+ * 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 Open Broadcom Corporation$
+ * $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $
+ */
+
+
+
+#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/rwl_wifi.h b/src/include/rwl_wifi.h
new file mode 100644
index 0000000..6fd8902
--- /dev/null
+++ b/src/include/rwl_wifi.h
@@ -0,0 +1,95 @@
+/*
+ * RWL definitions  of
+ * Broadcom 802.11bang Networking Device Driver
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: rwl_wifi.h 393462 2013-03-27 19:48:39Z $
+ *
+ */
+
+#ifndef _rwl_wifi_h_
+#define _rwl_wifi_h_
+
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR) || defined(RFAWARE)
+
+#define RWL_ACTION_WIFI_CATEGORY	127  /* Vendor-specific category value for WiFi */
+#define RWL_WIFI_OUI_BYTE0		0x00 /* BRCM-specific public OUI */
+#define RWL_WIFI_OUI_BYTE1		0x90
+#define RWL_WIFI_OUI_BYTE2		0x4c
+#define RWL_WIFI_ACTION_FRAME_SIZE	sizeof(struct dot11_action_wifi_vendor_specific)
+
+/*
+ * Information about the action frame data fields in the dot11_action_wifi_vendor_specific
+ * cdc structure (1 to 16). This does not include the status flag. Since this
+ * is not directly visible to the driver code, we can't use sizeof(struct cdc_ioctl).
+ * Hence Ref MAC address offset starts from byte 17.
+ * REF MAC ADDR (6 bytes (MAC Address len) from byte 17 to 22)
+ * DUT MAC ADDR (6 bytes after the REF MAC Address byte 23 to 28)
+ * unused (byte 29 to 49)
+ * REF/Client Channel offset (50)
+ * DUT/Server channel offset (51)
+ * ---------------------------------------------------------------------------------------
+ * cdc struct|REF MAC ADDR|DUT_MAC_ADDR|un used|REF Channel|DUT channel|Action frame Data|
+ * 1---------17-----------23-------------------50----------51----------52----------------1040
+ * REF MAC addr after CDC struct without status flag (status flag not used by wifi)
+ */
+
+#define RWL_REF_MAC_ADDRESS_OFFSET	17
+#define RWL_DUT_MAC_ADDRESS_OFFSET	23
+#define RWL_WIFI_CLIENT_CHANNEL_OFFSET	50
+#define RWL_WIFI_SERVER_CHANNEL_OFFSET	51
+
+#ifdef WIFI_REFLECTOR
+#include <bcmcdc.h>
+#define REMOTE_FINDSERVER_CMD 	16
+#define RWL_WIFI_ACTION_CMD		"wifiaction"
+#define RWL_WIFI_ACTION_CMD_LEN		11	/* With the NULL terminator */
+#define REMOTE_SET_CMD 		1
+#define REMOTE_GET_CMD 		2
+#define REMOTE_REPLY 			4
+#define RWL_WIFI_DEFAULT_TYPE           0x00
+#define RWL_WIFI_DEFAULT_SUBTYPE        0x00
+#define RWL_ACTION_FRAME_DATA_SIZE      1024	/* fixed size for the wifi frame data */
+#define RWL_WIFI_CDC_HEADER_OFFSET      0
+#define RWL_WIFI_FRAG_DATA_SIZE         960	/* max size of the frag data */
+#define RWL_DEFAULT_WIFI_FRAG_COUNT 	127 	/* maximum fragment count */
+#define RWL_WIFI_RETRY			5       /* CMD retry count for wifi */
+#define RWL_WIFI_SEND			5	/* WIFI frame sent count */
+#define RWL_WIFI_SEND_DELAY		100	/* delay between two frames */
+#define MICROSEC_CONVERTOR_VAL		1000
+#ifndef IFNAMSIZ
+#define IFNAMSIZ			16
+#endif
+
+typedef struct rem_packet {
+	rem_ioctl_t rem_cdc;
+	uchar message [RWL_ACTION_FRAME_DATA_SIZE];
+} rem_packet_t;
+
+#include <packed_section_start.h>
+struct BWL_PRE_PACKED_STRUCT send_packet {
+	char command [RWL_WIFI_ACTION_CMD_LEN];
+	dot11_action_wifi_vendor_specific_t response;
+} BWL_POST_PACKED_STRUCT;
+#include <packed_section_end.h>
+
+typedef struct send_packet send_packet_t;
+
+#define REMOTE_SIZE     sizeof(rem_ioctl_t)
+#endif /* WIFI_REFLECTOR */
+
+typedef struct rwl_request {
+	struct rwl_request* next_request;
+	struct dot11_action_wifi_vendor_specific action_frame;
+} rwl_request_t;
+
+
+#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
+#endif	/* _rwl_wifi_h_ */
diff --git a/src/include/sbpcmcia.h b/src/include/sbpcmcia.h
new file mode 100644
index 0000000..122687c
--- /dev/null
+++ b/src/include/sbpcmcia.h
@@ -0,0 +1,276 @@
+/*
+ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: sbpcmcia.h 427964 2013-10-07 07:13:33Z $
+ */
+
+#ifndef	_SBPCMCIA_H
+#define	_SBPCMCIA_H
+
+
+
+
+#define	PCMCIA_FCR		(0x700 / 2)
+
+#define	FCR0_OFF		0
+#define	FCR1_OFF		(0x40 / 2)
+#define	FCR2_OFF		(0x80 / 2)
+#define	FCR3_OFF		(0xc0 / 2)
+
+#define	PCMCIA_FCR0		(0x700 / 2)
+#define	PCMCIA_FCR1		(0x740 / 2)
+#define	PCMCIA_FCR2		(0x780 / 2)
+#define	PCMCIA_FCR3		(0x7c0 / 2)
+
+
+
+#define	PCMCIA_COR		0
+
+#define	COR_RST			0x80
+#define	COR_LEV			0x40
+#define	COR_IRQEN		0x04
+#define	COR_BLREN		0x01
+#define	COR_FUNEN		0x01
+
+
+#define	PCICIA_FCSR		(2 / 2)
+#define	PCICIA_PRR		(4 / 2)
+#define	PCICIA_SCR		(6 / 2)
+#define	PCICIA_ESR		(8 / 2)
+
+
+#define PCM_MEMOFF		0x0000
+#define F0_MEMOFF		0x1000
+#define F1_MEMOFF		0x2000
+#define F2_MEMOFF		0x3000
+#define F3_MEMOFF		0x4000
+
+
+#define MEM_ADDR0		(0x728 / 2)
+#define MEM_ADDR1		(0x72a / 2)
+#define MEM_ADDR2		(0x72c / 2)
+
+
+#define PCMCIA_ADDR0		(0x072e / 2)
+#define PCMCIA_ADDR1		(0x0730 / 2)
+#define PCMCIA_ADDR2		(0x0732 / 2)
+
+#define MEM_SEG			(0x0734 / 2)
+#define SROM_CS			(0x0736 / 2)
+#define SROM_DATAL		(0x0738 / 2)
+#define SROM_DATAH		(0x073a / 2)
+#define SROM_ADDRL		(0x073c / 2)
+#define SROM_ADDRH		(0x073e / 2)
+#define	SROM_INFO2		(0x0772 / 2)	
+#define	SROM_INFO		(0x07be / 2)	
+
+
+#define SROM_IDLE		0
+#define SROM_WRITE		1
+#define SROM_READ		2
+#define SROM_WEN		4
+#define SROM_WDS		7
+#define SROM_DONE		8
+
+
+#define	SRI_SZ_MASK		0x03
+#define	SRI_BLANK		0x04
+#define	SRI_OTP			0x80
+
+#if !defined(LINUX_POSTMOGRIFY_REMOVAL)
+
+
+
+#define	CIS_SIZE		PCMCIA_FCR
+
+
+#define CIS_TUPLE_LEN_MAX	0xff
+
+
+
+#define CISTPL_NULL			0x00
+#define	CISTPL_VERS_1		0x15		
+#define	CISTPL_MANFID		0x20		
+#define CISTPL_FUNCID		0x21		
+#define	CISTPL_FUNCE		0x22		
+#define	CISTPL_CFTABLE		0x1b		
+#define	CISTPL_END		0xff		
+
+
+#define CISTPL_FID_SDIO		0x0c		
+
+
+#define	LAN_TECH		1		
+#define	LAN_SPEED		2		
+#define	LAN_MEDIA		3		
+#define	LAN_NID			4		
+#define	LAN_CONN		5		
+
+
+
+#define CFTABLE_REGWIN_2K	0x08		
+#define CFTABLE_REGWIN_4K	0x10		
+#define CFTABLE_REGWIN_8K	0x20		
+
+
+
+#define	CISTPL_BRCM_HNBU	0x80
+
+
+
+#define HNBU_SROMREV		0x00	
+#define HNBU_CHIPID		0x01	
+#define HNBU_BOARDREV		0x02	
+#define HNBU_PAPARMS		0x03	
+#define HNBU_OEM		0x04	
+#define HNBU_CC			0x05	
+#define	HNBU_AA			0x06	
+#define	HNBU_AG			0x07	
+#define HNBU_BOARDFLAGS		0x08	
+#define HNBU_LEDS		0x09	
+#define HNBU_CCODE		0x0a	
+#define HNBU_CCKPO		0x0b	
+#define HNBU_OFDMPO		0x0c	
+#define HNBU_GPIOTIMER		0x0d	
+#define HNBU_PAPARMS5G		0x0e	
+#define HNBU_ANT5G		0x0f	
+#define HNBU_RDLID		0x10	
+#define HNBU_RSSISMBXA2G	0x11	
+#define HNBU_RSSISMBXA5G	0x12	
+#define HNBU_XTALFREQ		0x13	
+#define HNBU_TRI2G		0x14	
+#define HNBU_TRI5G		0x15	
+#define HNBU_RXPO2G		0x16	
+#define HNBU_RXPO5G		0x17	
+#define HNBU_BOARDNUM		0x18	
+#define HNBU_MACADDR		0x19	
+#define HNBU_RDLSN		0x1a	
+#define HNBU_BOARDTYPE		0x1b	
+#define HNBU_LEDDC		0x1c	
+#define HNBU_HNBUCIS		0x1d	
+#define HNBU_PAPARMS_SSLPNPHY	0x1e	
+#define HNBU_RSSISMBXA2G_SSLPNPHY 0x1f 
+#define HNBU_RDLRNDIS		0x20	
+#define HNBU_CHAINSWITCH	0x21	
+#define HNBU_REGREV		0x22	
+#define HNBU_FEM		0x23	
+#define HNBU_PAPARMS_C0		0x24	
+#define HNBU_PAPARMS_C1		0x25	
+#define HNBU_PAPARMS_C2		0x26	
+#define HNBU_PAPARMS_C3		0x27	
+#define HNBU_PO_CCKOFDM		0x28	
+#define HNBU_PO_MCS2G		0x29	
+#define HNBU_PO_MCS5GM		0x2a	
+#define HNBU_PO_MCS5GLH		0x2b	
+#define HNBU_PO_CDD		0x2c	
+#define HNBU_PO_STBC		0x2d	
+#define HNBU_PO_40M		0x2e	
+#define HNBU_PO_40MDUP		0x2f	
+
+#define HNBU_RDLRWU		0x30	
+#define HNBU_WPS		0x31	
+#define HNBU_USBFS		0x32	
+#define HNBU_BRMIN		0x33	
+#define HNBU_BRMAX		0x34	
+#define HNBU_PATCH		0x35	
+#define HNBU_CCKFILTTYPE	0x36	
+#define HNBU_OFDMPO5G		0x37	
+#define HNBU_ELNA2G             0x38
+#define HNBU_ELNA5G             0x39
+#define HNBU_TEMPTHRESH 0x3A 
+#define HNBU_UUID 0x3B 
+
+#define HNBU_USBEPNUM		0x40	
+
+
+#define HNBU_CCKBW202GPO       0x41    
+
+#define HNBU_LEGOFDMBW202GPO    0x42    
+
+#define HNBU_LEGOFDMBW205GPO   0x43    
+
+#define HNBU_MCS2GPO    0x44    
+#define HNBU_MCS5GLPO    0x45    
+#define HNBU_MCS5GMPO    0x46    
+#define HNBU_MCS5GHPO    0x47    
+#define HNBU_MCS32PO	0x48	
+#define HNBU_LEG40DUPPO	0x49 
+
+#define HNBU_PMUREGS	0x4a 
+
+#define HNBU_PATCH2		0x4b	
+
+#define HNBU_USBRDY		0x4c	
+
+#define HNBU_USBREGS	0x4d	
+
+#define HNBU_BLDR_TIMEOUT	0x4e	
+#define HNBU_USBFLAGS		0x4f
+#define HNBU_PATCH_AUTOINC	0x50
+#define HNBU_MDIO_REGLIST	0x51
+#define HNBU_MDIOEX_REGLIST	0x52
+
+#define HNBU_UMANFID		0x53
+#define HNBU_PUBKEY		0x54	
+#define HNBU_WOWLGPIO       0x55   
+#define HNBU_MUXENAB		0x56	
+#define HNBU_GCI_CCR		0x57	
+
+#define HNBU_FEM_CFG		0x58	
+#define HNBU_ACPA_C0		0x59	
+#define HNBU_ACPA_C1		0x5a	
+#define HNBU_ACPA_C2		0x5b	
+#define HNBU_MEAS_PWR		0x5c
+#define HNBU_PDOFF		0x5d
+#define HNBU_ACPPR_2GPO		0x5e	
+#define HNBU_ACPPR_5GPO		0x5f	
+#define HNBU_ACPPR_SBPO		0x60	
+#define HNBU_NOISELVL		0x61
+#define HNBU_RXGAIN_ERR		0x62
+#define HNBU_AGBGA		0x63
+#define HNBU_USBDESC_COMPOSITE	0x64    
+#define HNBU_PATCH_AUTOINC8	0x65	
+#define HNBU_PATCH8		0x66	
+#define HNBU_ACRXGAINS_C0	0x67	
+#define HNBU_ACRXGAINS_C1	0x68	
+#define HNBU_ACRXGAINS_C2	0x69	
+#define HNBU_TXDUTY		0x6a	
+#define HNBU_USBUTMI_CTL        0x6b    
+#define HNBU_PDOFF_2G		0x6c
+#define HNBU_USBSSPHY_UTMI_CTL0 0x6d    
+#define HNBU_USBSSPHY_UTMI_CTL1 0x6e    
+#define HNBU_USBSSPHY_UTMI_CTL2 0x6f    
+#define HNBU_USBSSPHY_SLEEP0    0x70    
+#define HNBU_USBSSPHY_SLEEP1    0x71    
+#define HNBU_USBSSPHY_SLEEP2    0x72    
+#define HNBU_USBSSPHY_SLEEP3    0x73    
+#define HNBU_USBSSPHY_MDIO		0x74	
+#define HNBU_USB30PHY_NOSS		0x75	
+#define HNBU_USB30PHY_U1U2		0x76	
+#define HNBU_USB30PHY_REGS		0x77	
+
+#define HNBU_SROM3SWRGN		0x80	
+#define HNBU_RESERVED		0x81	
+#define HNBU_CUSTOM1		0x82	
+#define HNBU_CUSTOM2		0x83	
+#define HNBU_ACPAPARAM		0x84	
+#define HNBU_ACPA_CCK		0x86	
+#define HNBU_ACPA_40		0x87	
+#define HNBU_ACPA_80		0x88	
+#define HNBU_ACPA_4080		0x89	
+#define HNBU_SUBBAND5GVER	0x8a	
+#define HNBU_PAPARAMBWVER	0x8b	
+
+
+#endif 
+
+
+#define SBTML_INT_ACK		0x40000		
+#define SBTML_INT_EN		0x20000		
+
+
+#define SBTMH_INT_STATUS	0x40000		
+
+#endif	
diff --git a/src/include/sdiovar.h b/src/include/sdiovar.h
new file mode 100644
index 0000000..285ec0b
--- /dev/null
+++ b/src/include/sdiovar.h
@@ -0,0 +1,63 @@
+/*
+ * Structure used by apps whose drivers access SDIO drivers.
+ * Pulled out separately so dhdu and wlu can both use it.
+ *
+ * $ Copyright Open Broadcom Corporation $
+ *
+ * $Id: sdiovar.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _sdiovar_h_
+#define _sdiovar_h_
+
+#include <typedefs.h>
+
+/* require default structure packing */
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+typedef struct sdreg {
+	int func;
+	int offset;
+	int value;
+} sdreg_t;
+
+/* Common msglevel constants */
+#define SDH_ERROR_VAL		0x0001	/* Error */
+#define SDH_TRACE_VAL		0x0002	/* Trace */
+#define SDH_INFO_VAL		0x0004	/* Info */
+#define SDH_DEBUG_VAL		0x0008	/* Debug */
+#define SDH_DATA_VAL		0x0010	/* Data */
+#define SDH_CTRL_VAL		0x0020	/* Control Regs */
+#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
+#define SDH_DMA_VAL		0x0080	/* DMA */
+
+#define NUM_PREV_TRANSACTIONS	16
+
+#ifdef BCMSPI
+/* Error statistics for gSPI */
+struct spierrstats_t {
+	uint32  dna;	/* The requested data is not available. */
+	uint32  rdunderflow;	/* FIFO underflow happened due to current (F2, F3) rd command */
+	uint32  wroverflow;	/* FIFO underflow happened due to current (F1, F2, F3) wr command */
+
+	uint32  f2interrupt;	/* OR of all F2 related intr status bits. */
+	uint32  f3interrupt;	/* OR of all F3 related intr status bits. */
+
+	uint32  f2rxnotready;	/* F2 FIFO is not ready to receive data (FIFO empty) */
+	uint32  f3rxnotready;	/* F3 FIFO is not ready to receive data (FIFO empty) */
+
+	uint32  hostcmddataerr;	/* Error in command or host data, detected by CRC/checksum
+	                         * (optional)
+	                         */
+	uint32  f2pktavailable;	/* Packet is available in F2 TX FIFO */
+	uint32  f3pktavailable;	/* Packet is available in F2 TX FIFO */
+
+	uint32	dstatus[NUM_PREV_TRANSACTIONS];	/* dstatus bits of last 16 gSPI transactions */
+	uint32  spicmd[NUM_PREV_TRANSACTIONS];
+};
+#endif /* BCMSPI */
+
+#include <packed_section_end.h>
+
+#endif /* _sdiovar_h_ */
diff --git a/src/include/trxhdr.h b/src/include/trxhdr.h
new file mode 100644
index 0000000..249527c
--- /dev/null
+++ b/src/include/trxhdr.h
@@ -0,0 +1,74 @@
+/*
+ * TRX image file header format.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: trxhdr.h 349211 2012-08-07 09:45:24Z $
+ */
+
+#ifndef _TRX_HDR_H
+#define _TRX_HDR_H
+
+#include <typedefs.h>
+
+#define TRX_MAGIC	0x30524448	/* "HDR0" */
+#define TRX_MAX_LEN	0x3B0000	/* Max length */
+#define TRX_NO_HEADER	1		/* Do not write TRX header */
+#define TRX_GZ_FILES	0x2     /* Contains up to TRX_MAX_OFFSET individual gzip files */
+#define TRX_EMBED_UCODE	0x8	/* Trx contains embedded ucode image */
+#define TRX_ROMSIM_IMAGE	0x10	/* Trx contains ROM simulation image */
+#define TRX_UNCOMP_IMAGE	0x20	/* Trx contains uncompressed rtecdc.bin image */
+#define TRX_BOOTLOADER		0x40	/* the image is a bootloader */
+
+#define TRX_V1		1
+#define TRX_V1_MAX_OFFSETS	3		/* V1: Max number of individual files */
+
+#ifndef BCMTRXV2
+#define TRX_VERSION	TRX_V1		/* Version 1 */
+#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS
+#endif
+
+/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as
+ * Ver 2 of trx header. To make it generic, trx_header is structure is modified
+ * as below where size of "offsets" field will vary as per the TRX version.
+ * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well.
+ * To make sure, other applications like "dhdl" which are yet to be enhanced to support
+ * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2
+ * is defined.
+ */
+struct trx_header {
+	uint32 magic;		/* "HDR0" */
+	uint32 len;		/* Length of file including header */
+	uint32 crc32;		/* 32-bit CRC from flag_version to end of file */
+	uint32 flag_version;	/* 0:15 flags, 16:31 version */
+#ifndef BCMTRXV2
+	uint32 offsets[TRX_MAX_OFFSET];	/* Offsets of partitions from start of header */
+#else
+	uint32 offsets[1];	/* Offsets of partitions from start of header */
+#endif
+};
+
+#ifdef BCMTRXV2
+#define TRX_VERSION		TRX_V2		/* Version 2 */
+#define TRX_MAX_OFFSET  TRX_V2_MAX_OFFSETS
+
+#define TRX_V2		2
+/* V2: Max number of individual files
+ * To support SDR signature + Config data region
+ */
+#define TRX_V2_MAX_OFFSETS	5
+#define SIZEOF_TRXHDR_V1	(sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32))
+#define SIZEOF_TRXHDR_V2	(sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32))
+#define TRX_VER(trx)		(trx->flag_version>>16)
+#define ISTRX_V1(trx)		(TRX_VER(trx) == TRX_V1)
+#define ISTRX_V2(trx)		(TRX_VER(trx) == TRX_V2)
+/* For V2, return size of V2 size: others, return V1 size */
+#define SIZEOF_TRX(trx)	    (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1)
+#else
+#define SIZEOF_TRX(trx)	    (sizeof(struct trx_header))
+#endif /* BCMTRXV2 */
+
+/* Compatibility */
+typedef struct trx_header TRXHDR, *PTRXHDR;
+
+#endif /* _TRX_HDR_H */
diff --git a/src/include/typedefs.h b/src/include/typedefs.h
new file mode 100644
index 0000000..f4aad17
--- /dev/null
+++ b/src/include/typedefs.h
@@ -0,0 +1,293 @@
+/*
+ * $Copyright Open Broadcom Corporation$
+ * $Id: typedefs.h 453696 2014-02-06 01:10:20Z $
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+#ifdef SITE_TYPEDEFS
+
+
+
+#include "site_typedefs.h"
+
+#else
+
+
+
+#ifdef __cplusplus
+
+#define TYPEDEF_BOOL
+#ifndef FALSE
+#define FALSE	false
+#endif
+#ifndef TRUE
+#define TRUE	true
+#endif
+
+#else	
+
+
+#endif	
+
+#if defined(__LP64__)
+#define TYPEDEF_UINTPTR
+typedef unsigned long long int uintptr;
+#endif
+
+
+
+
+
+#if defined(_NEED_SIZE_T_)
+typedef long unsigned int size_t;
+#endif
+
+
+
+
+
+#if defined(__sparc__)
+#define TYPEDEF_ULONG
+#endif
+
+
+
+#if !defined(LINUX_HYBRID) || defined(LINUX_PORT)
+#define TYPEDEF_UINT
+#ifndef TARGETENV_android
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+#endif 
+#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>
+#ifdef noinline_for_stack
+#define TYPEDEF_BOOL
+#endif
+#endif	
+#endif	
+#endif  
+
+
+
+
+
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif 
+
+
+#if defined(__ICL)
+
+#define TYPEDEF_INT64
+
+#if defined(__STDC__)
+#define TYPEDEF_UINT64
+#endif
+
+#endif 
+
+#if !defined(__DJGPP__)
+
+
+#if defined(__KERNEL__)
+
+
+#if !defined(LINUX_HYBRID) || defined(LINUX_PORT)
+#include <linux/types.h>	
+#endif 
+
+#else
+
+
+#include <sys/types.h>
+
+#endif 
+
+#endif 
+
+
+
+
+#define USE_TYPEDEF_DEFAULTS
+
+#endif 
+
+
+
+
+#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/usbrdl.h b/src/include/usbrdl.h
new file mode 100644
index 0000000..5ceed33
--- /dev/null
+++ b/src/include/usbrdl.h
@@ -0,0 +1,212 @@
+/*
+ * Broadcom USB remote download definitions
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: usbrdl.h 412875 2013-07-16 23:54:25Z $
+ */
+
+#ifndef _USB_RDL_H
+#define _USB_RDL_H
+
+/* Control messages: bRequest values */
+#define DL_GETSTATE		0	/* returns the rdl_state_t struct */
+#define DL_CHECK_CRC		1	/* currently unused */
+#define DL_GO			2	/* execute downloaded image */
+#define DL_START		3	/* initialize dl state */
+#define DL_REBOOT		4	/* reboot the device in 2 seconds */
+#define DL_GETVER		5	/* returns the bootrom_id_t struct */
+#define DL_GO_PROTECTED		6	/* execute the downloaded code and set reset event
+					 * to occur in 2 seconds.  It is the responsibility
+					 * of the downloaded code to clear this event
+					 */
+#define DL_EXEC			7	/* jump to a supplied address */
+#define DL_RESETCFG		8	/* To support single enum on dongle
+					 * - Not used by bootloader
+					 */
+#define DL_DEFER_RESP_OK	9	/* Potentially defer the response to setup
+					 * if resp unavailable
+					 */
+#define DL_CHGSPD		0x0A
+
+#define	DL_HWCMD_MASK		0xfc	/* Mask for hardware read commands: */
+#define	DL_RDHW			0x10	/* Read a hardware address (Ctl-in) */
+#define	DL_RDHW32		0x10	/* Read a 32 bit word */
+#define	DL_RDHW16		0x11	/* Read 16 bits */
+#define	DL_RDHW8		0x12	/* Read an 8 bit byte */
+#define	DL_WRHW			0x14	/* Write a hardware address (Ctl-out) */
+#define DL_WRHW_BLK 	0x13	/* Block write to hardware access */
+
+#define DL_CMD_RDHW		1	/* read data from a backplane address */
+#define DL_CMD_WRHW		2	/* write data to a backplane address */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define	DL_JTCONF		0x15	/* Get JTAG configuration (Ctl_in)
+					 *  Set JTAG configuration (Ctl-out)
+					 */
+#define	DL_JTON			0x16	/* Turn on jtag master (Ctl-in) */
+#define	DL_JTOFF		0x17	/* Turn on jtag master (Ctl-in) */
+#define	DL_RDRJT		0x18	/* Read a JTAG register (Ctl-in) */
+#define	DL_WRJT			0x19	/* Write a hardware address over JTAG (Ctl/Bulk-out) */
+#define	DL_WRRJT		0x1a	/* Write a JTAG register (Ctl/Bulk-out) */
+#define	DL_JTRST		0x1b	/* Reset jtag fsm on jtag DUT (Ctl-in) */
+
+#define	DL_RDJT			0x1c	/* Read a hardware address over JTAG (Ctl-in) */
+#define	DL_RDJT32		0x1c	/* Read 32 bits */
+#define	DL_RDJT16		0x1e	/* Read 16 bits (sz = 4 - low bits) */
+#define	DL_RDJT8		0x1f	/* Read 8 bits */
+
+#define	DL_MRDJT		0x20	/* Multiple read over JTAG (Ctl-out+Bulk-in) */
+#define	DL_MRDJT32		0x20	/* M-read 32 bits */
+#define	DL_MRDJT16		0x22	/* M-read 16 bits (sz = 4 - low bits) */
+#define	DL_MRDJT6		0x23	/* M-read 8 bits */
+#define	DL_MRDIJT		0x24	/* M-read over JTAG (Ctl-out+Bulk-in) with auto-increment */
+#define	DL_MRDIJT32		0x24	/* M-read 32 bits w/ai */
+#define	DL_MRDIJT16		0x26	/* M-read 16 bits w/ai (sz = 4 - low bits) */
+#define	DL_MRDIJT8		0x27	/* M-read 8 bits w/ai */
+#define	DL_MRDDJT		0x28	/* M-read over JTAG (Ctl-out+Bulk-in) with auto-decrement */
+#define	DL_MRDDJT32		0x28	/* M-read 32 bits w/ad */
+#define	DL_MRDDJT16		0x2a	/* M-read 16 bits w/ad (sz = 4 - low bits) */
+#define	DL_MRDDJT8		0x2b	/* M-read 8 bits w/ad */
+#define	DL_MWRJT		0x2c	/* Multiple write over JTAG (Bulk-out) */
+#define	DL_MWRIJT		0x2d	/*	With auto-increment */
+#define	DL_MWRDJT		0x2e	/*	With auto-decrement */
+#define	DL_VRDJT		0x2f	/* Vector read over JTAG (Bulk-out+Bulk-in) */
+#define	DL_VWRJT		0x30	/* Vector write over JTAG (Bulk-out+Bulk-in) */
+#define	DL_SCJT			0x31	/* Jtag scan (Bulk-out+Bulk-in) */
+
+#define	DL_CFRD			0x33	/* Reserved for dmamem use */
+#define	DL_CFWR			0x34	/* Reserved for dmamem use */
+#define DL_GET_NVRAM            0x35    /* Query nvram parameter */
+
+#define	DL_DBGTRIG		0xFF	/* Trigger bRequest type to aid debug */
+
+#define	DL_JTERROR		0x80000000
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* states */
+#define DL_WAITING	0	/* waiting to rx first pkt that includes the hdr info */
+#define DL_READY	1	/* hdr was good, waiting for more of the compressed image */
+#define DL_BAD_HDR	2	/* hdr was corrupted */
+#define DL_BAD_CRC	3	/* compressed image was corrupted */
+#define DL_RUNNABLE	4	/* download was successful, waiting for go cmd */
+#define DL_START_FAIL	5	/* failed to initialize correctly */
+#define DL_NVRAM_TOOBIG	6	/* host specified nvram data exceeds DL_NVRAM value */
+#define DL_IMAGE_TOOBIG	7	/* download image too big (exceeds DATA_START for rdl) */
+
+#define TIMEOUT		5000	/* Timeout for usb commands */
+
+struct bcm_device_id {
+	char	*name;
+	uint32	vend;
+	uint32	prod;
+};
+
+typedef struct {
+	uint32	state;
+	uint32	bytes;
+} rdl_state_t;
+
+typedef struct {
+	uint32	chip;		/* Chip id */
+	uint32	chiprev;	/* Chip rev */
+	uint32  ramsize;    /* Size of RAM */
+	uint32  remapbase;   /* Current remap base address */
+	uint32  boardtype;   /* Type of board */
+	uint32  boardrev;    /* Board revision */
+} bootrom_id_t;
+
+/* struct for backplane & jtag accesses */
+typedef struct {
+	uint32	cmd;		/* tag to identify the cmd */
+	uint32	addr;		/* backplane address for write */
+	uint32	len;		/* length of data: 1, 2, 4 bytes */
+	uint32	data;		/* data to write */
+} hwacc_t;
+
+/* struct for backplane */
+typedef struct {
+	uint32  cmd;            /* tag to identify the cmd */
+	uint32  addr;           /* backplane address for write */
+	uint32  len;            /* length of data: 1, 2, 4 bytes */
+	uint8   data[1];                /* data to write */
+} hwacc_blk_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct {
+	uint32  chip;           /* Chip id */
+	uint32  chiprev;        /* Chip rev */
+	uint32  ccrev;          /* Chipcommon core rev */
+	uint32  siclock;        /* Backplane clock */
+} jtagd_id_t;
+
+/* Jtag configuration structure */
+typedef struct {
+	uint32	cmd;		/* tag to identify the cmd */
+	uint8	clkd;		/* Jtag clock divisor */
+	uint8	disgpio;	/* Gpio to disable external driver */
+	uint8	irsz;		/* IR size for readreg/writereg */
+	uint8	drsz;		/* DR size for readreg/writereg */
+
+	uint8	bigend;		/* Big endian */
+	uint8	mode;		/* Current mode */
+	uint16	delay;		/* Delay between jtagm "simple commands" */
+
+	uint32	retries;	/* Number of retries for jtagm operations */
+	uint32	ctrl;		/* Jtag control reg copy */
+	uint32	ir_lvbase;	/* Bits to add to IR values in LV tap */
+	uint32	dretries;	/* Number of retries for dma operations */
+} jtagconf_t;
+
+/* struct for jtag scan */
+#define MAX_USB_IR_BITS	256
+#define MAX_USB_DR_BITS	3072
+#define USB_IR_WORDS	(MAX_USB_IR_BITS / 32)
+#define USB_DR_WORDS	(MAX_USB_DR_BITS / 32)
+typedef struct {
+	uint32	cmd;		/* tag to identify the cmd */
+	uint32	irsz;		/* IR size in bits */
+	uint32	drsz;		/* DR size in bits */
+	uint32	ts;		/* Terminal state (def, pause, rti) */
+	uint32	data[USB_IR_WORDS + USB_DR_WORDS];	/* IR & DR data */
+} scjt_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* struct for querying nvram params from bootloader */
+#define QUERY_STRING_MAX 32
+typedef struct {
+	uint32  cmd;                    /* tag to identify the cmd */
+	char    var[QUERY_STRING_MAX];  /* param name */
+} nvparam_t;
+
+typedef void (*exec_fn_t)(void *sih);
+
+#define USB_CTRL_IN (USB_TYPE_VENDOR | 0x80 | USB_RECIP_INTERFACE)
+#define USB_CTRL_OUT (USB_TYPE_VENDOR | 0 | USB_RECIP_INTERFACE)
+
+#define USB_CTRL_EP_TIMEOUT 500 /* Timeout used in USB control_msg transactions. */
+
+#define RDL_CHUNK	1500  /* size of each dl transfer */
+
+/* bootloader makes special use of trx header "offsets" array */
+#define TRX_OFFSETS_DLFWLEN_IDX	0	/* Size of the fw; used in uncompressed case */
+#define TRX_OFFSETS_JUMPTO_IDX	1	/* RAM address for jumpto after download */
+#define TRX_OFFSETS_NVM_LEN_IDX	2	/* Length of appended NVRAM data */
+#ifdef BCMTRXV2
+/* The NVRAM region part of trx will be digitally signed in SDR image,
+ * so is the need for new cfg region which could pass parameters
+ * which dones not need to be digitally signed
+ */
+#define TRX_OFFSETS_DSG_LEN_IDX	3	/* Length of digital signature for the first image */
+#define TRX_OFFSETS_CFG_LEN_IDX	4	/* Length of config region, which is not digitally signed */
+#endif /* BCMTRXV2 */
+
+#define TRX_OFFSETS_DLBASE_IDX  0       /* RAM start address for download */
+
+#endif  /* _USB_RDL_H */
diff --git a/src/include/wlc_extlog_idstr.h b/src/include/wlc_extlog_idstr.h
new file mode 100644
index 0000000..f0f3507
--- /dev/null
+++ b/src/include/wlc_extlog_idstr.h
@@ -0,0 +1,117 @@
+/*
+ * EXTLOG Module log ID to log Format String mapping table
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlc_extlog_idstr.h 241182 2011-02-17 21:50:03Z $
+ */
+#ifndef _WLC_EXTLOG_IDSTR_H_
+#define _WLC_EXTLOG_IDSTR_H_
+
+#include "wlioctl.h"
+
+/* Strings corresponding to the IDs defined in wlioctl.h
+ * This file is only included by the apps and not included by the external driver
+ * Formats of pre-existing ids should NOT be changed
+ */
+log_idstr_t extlog_fmt_str[ ] = {
+	{FMTSTR_DRIVER_UP_ID, 0, LOG_ARGTYPE_NULL,
+	"Driver is Up\n"},
+
+	{FMTSTR_DRIVER_DOWN_ID, 0, LOG_ARGTYPE_NULL,
+	"Driver is Down\n"},
+
+	{FMTSTR_SUSPEND_MAC_FAIL_ID, 0, LOG_ARGTYPE_INT,
+	"wlc_suspend_mac_and_wait() failed with psmdebug 0x%08x\n"},
+
+	{FMTSTR_NO_PROGRESS_ID, 0, LOG_ARGTYPE_INT,
+	"No Progress on TX for %d seconds\n"},
+
+	{FMTSTR_RFDISABLE_ID, 0, LOG_ARGTYPE_INT,
+	"Detected a change in RF Disable Input 0x%x\n"},
+
+	{FMTSTR_REG_PRINT_ID, 0, LOG_ARGTYPE_STR_INT,
+	"Register %s = 0x%x\n"},
+
+	{FMTSTR_EXPTIME_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Strong RF interference detected\n"},
+
+	{FMTSTR_JOIN_START_ID, FMTSTRF_USER, LOG_ARGTYPE_STR,
+	"Searching for networks with ssid %s\n"},
+
+	{FMTSTR_JOIN_COMPLETE_ID, FMTSTRF_USER, LOG_ARGTYPE_STR,
+	"Successfully joined network with BSSID %s\n"},
+
+	{FMTSTR_NO_NETWORKS_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"No networks found. Please check if the network exists and is in range\n"},
+
+	{FMTSTR_SECURITY_MISMATCH_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"AP rejected due to security mismatch. Change the security settings and try again...\n"},
+
+	{FMTSTR_RATE_MISMATCH_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"AP rejected due to rate mismatch\n"},
+
+	{FMTSTR_AP_PRUNED_ID, 0, LOG_ARGTYPE_INT,
+	"AP rejected due to reason %d\n"},
+
+	{FMTSTR_KEY_INSERTED_ID, 0, LOG_ARGTYPE_INT,
+	"Inserting keys for algorithm %d\n"},
+
+	{FMTSTR_DEAUTH_ID, FMTSTRF_USER, LOG_ARGTYPE_STR_INT,
+	"Received Deauth from %s with Reason %d\n"},
+
+	{FMTSTR_DISASSOC_ID, FMTSTRF_USER, LOG_ARGTYPE_STR_INT,
+	"Received Disassoc from %s with Reason %d\n"},
+
+	{FMTSTR_LINK_UP_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Link Up\n"},
+
+	{FMTSTR_LINK_DOWN_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Link Down\n"},
+
+	{FMTSTR_RADIO_HW_OFF_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Radio button is turned OFF. Please turn it on...\n"},
+
+	{FMTSTR_RADIO_HW_ON_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Hardware Radio button is turned ON\n"},
+
+	{FMTSTR_EVENT_DESC_ID, 0, LOG_ARGTYPE_INT_STR,
+	"Generated event id %d: (result status) is (%s)\n"},
+
+	{FMTSTR_PNP_SET_POWER_ID, 0, LOG_ARGTYPE_INT,
+	"Device going into power state %d\n"},
+
+	{FMTSTR_RADIO_SW_OFF_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Software Radio is disabled. Please enable it through the UI...\n"},
+
+	{FMTSTR_RADIO_SW_ON_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Software Radio is enabled\n"},
+
+	{FMTSTR_PWD_MISMATCH_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Potential passphrase mismatch. Please try a different one...\n"},
+
+	{FMTSTR_FATAL_ERROR_ID, 0, LOG_ARGTYPE_INT,
+	"Fatal Error: intstatus 0x%x\n"},
+
+	{FMTSTR_AUTH_FAIL_ID, 0, LOG_ARGTYPE_STR_INT,
+	"Authentication to %s Failed with status %d\n"},
+
+	{FMTSTR_ASSOC_FAIL_ID, 0, LOG_ARGTYPE_STR_INT,
+	"Association to %s Failed with status %d\n"},
+
+	{FMTSTR_IBSS_FAIL_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Unable to start IBSS since PeerNet is already active\n"},
+
+	{FMTSTR_EXTAP_FAIL_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Unable to start Ext-AP since PeerNet is already active\n"},
+
+	{FMTSTR_MAX_ID, 0, 0, "\0"}
+};
+
+#endif /* _WLC_EXTLOG_IDSTR_H_ */
diff --git a/src/include/wlioctl.h b/src/include/wlioctl.h
new file mode 100644
index 0000000..bbdf458
--- /dev/null
+++ b/src/include/wlioctl.h
@@ -0,0 +1,4455 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: wlioctl.h 647609 2016-07-06 21:27:18Z $
+ */
+
+#ifndef _wlioctl_h_
+#define	_wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/bcmip.h>
+#include <proto/bcmeth.h>
+#include <proto/bcmip.h>
+#include <proto/bcmevent.h>
+#include <proto/802.11.h>
+#include <proto/802.1d.h>
+#include <bcmwifi_channels.h>
+#include <bcmwifi_rates.h>
+#include <devctrl_if/wlioctl_defs.h>
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#include <bcm_mpool_pub.h>
+#include <bcmcdc.h>
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+#ifndef INTF_NAME_SIZ
+#define INTF_NAME_SIZ	16
+#endif
+
+/* Used to send ioctls over the transport pipe */
+typedef struct remote_ioctl {
+	cdc_ioctl_t	msg;
+	uint32		data_len;
+	char           intf_name[INTF_NAME_SIZ];
+} rem_ioctl_t;
+#define REMOTE_SIZE	sizeof(rem_ioctl_t)
+
+typedef struct {
+	uint32 num;
+	chanspec_t list[1];
+} chanspec_list_t;
+
+/* association decision information */
+typedef struct {
+	bool		assoc_approved;		/* (re)association approved */
+	uint16		reject_reason;		/* reason code for rejecting association */
+	struct		ether_addr   da;
+#if 0 && (NDISVER >= 0x0620)
+	LARGE_INTEGER	sys_time;		/* current system time */
+#else
+	int64		sys_time;		/* current system time */
+#endif
+} assoc_decision_t;
+
+#define ACTION_FRAME_SIZE 1800
+
+typedef struct wl_action_frame {
+	struct ether_addr 	da;
+	uint16 			len;
+	uint32 			packetId;
+	uint8			data[ACTION_FRAME_SIZE];
+} wl_action_frame_t;
+
+#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame)
+
+typedef struct ssid_info
+{
+	uint8		ssid_len;	/* the length of SSID */
+	uint8		ssid[32];	/* SSID string */
+} ssid_info_t;
+
+typedef struct wl_af_params {
+	uint32 			channel;
+	int32 			dwell_time;
+	struct ether_addr 	BSSID;
+	wl_action_frame_t	action_frame;
+} wl_af_params_t;
+
+#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params)
+
+#define MFP_TEST_FLAG_NORMAL	0
+#define MFP_TEST_FLAG_ANY_KEY	1
+typedef struct wl_sa_query {
+	uint32			flag;
+	uint8 			action;
+	uint16 			id;
+	struct ether_addr 	da;
+} wl_sa_query_t;
+
+#endif /*  LINUX_POSTMOGRIFY_REMOVAL */
+
+/* require default structure packing */
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* Legacy structure to help keep backward compatible wl tool and tray app */
+
+#define	LEGACY_WL_BSS_INFO_VERSION	107	/* older version of wl_bss_info struct */
+
+typedef struct wl_bss_info_107 {
+	uint32		version;		/* version field */
+	uint32		length;			/* byte length of data in this record,
+						 * starting at version and including IEs
+						 */
+	struct ether_addr BSSID;
+	uint16		beacon_period;		/* units are Kusec */
+	uint16		capability;		/* Capability information */
+	uint8		SSID_len;
+	uint8		SSID[32];
+	struct {
+		uint	count;			/* # rates in this set */
+		uint8	rates[16];		/* rates in 500kbps units w/hi bit set if basic */
+	} rateset;				/* supported rates */
+	uint8		channel;		/* Channel no. */
+	uint16		atim_window;		/* units are Kusec */
+	uint8		dtim_period;		/* DTIM period */
+	int16		RSSI;			/* receive signal strength (in dBm) */
+	int8		phy_noise;		/* noise (in dBm) */
+	uint32		ie_length;		/* byte length of Information Elements */
+	/* variable length Information Elements */
+} wl_bss_info_107_t;
+
+/*
+ * Per-BSS information structure.
+ */
+
+#define	LEGACY2_WL_BSS_INFO_VERSION	108		/* old version of wl_bss_info struct */
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in wl_scan_results_t)
+ */
+typedef struct wl_bss_info_108 {
+	uint32		version;		/* version field */
+	uint32		length;			/* byte length of data in this record,
+						 * starting at version and including IEs
+						 */
+	struct ether_addr BSSID;
+	uint16		beacon_period;		/* units are Kusec */
+	uint16		capability;		/* Capability information */
+	uint8		SSID_len;
+	uint8		SSID[32];
+	struct {
+		uint	count;			/* # rates in this set */
+		uint8	rates[16];		/* rates in 500kbps units w/hi bit set if basic */
+	} rateset;				/* supported rates */
+	chanspec_t	chanspec;		/* chanspec for bss */
+	uint16		atim_window;		/* units are Kusec */
+	uint8		dtim_period;		/* DTIM period */
+	int16		RSSI;			/* receive signal strength (in dBm) */
+	int8		phy_noise;		/* noise (in dBm) */
+
+	uint8		n_cap;			/* BSS is 802.11N Capable */
+	uint32		nbss_cap;		/* 802.11N BSS Capabilities (based on HT_CAP_*) */
+	uint8		ctl_ch;			/* 802.11N BSS control channel number */
+	uint32		reserved32[1];		/* Reserved for expansion of BSS properties */
+	uint8		flags;			/* flags */
+	uint8		reserved[3];		/* Reserved for expansion of BSS properties */
+	uint8		basic_mcs[MCSSET_LEN];	/* 802.11N BSS required MCS set */
+
+	uint16		ie_offset;		/* offset at which IEs start, from beginning */
+	uint32		ie_length;		/* byte length of Information Elements */
+	/* Add new fields here */
+	/* variable length Information Elements */
+} wl_bss_info_108_t;
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define	WL_BSS_INFO_VERSION	109		/* current version of wl_bss_info struct */
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in wl_scan_results_t)
+ */
+typedef struct wl_bss_info {
+	uint32		version;		/* version field */
+	uint32		length;			/* byte length of data in this record,
+						 * starting at version and including IEs
+						 */
+	struct ether_addr BSSID;
+	uint16		beacon_period;		/* units are Kusec */
+	uint16		capability;		/* Capability information */
+	uint8		SSID_len;
+	uint8		SSID[32];
+	struct {
+		uint	count;			/* # rates in this set */
+		uint8	rates[16];		/* rates in 500kbps units w/hi bit set if basic */
+	} rateset;				/* supported rates */
+	chanspec_t	chanspec;		/* chanspec for bss */
+	uint16		atim_window;		/* units are Kusec */
+	uint8		dtim_period;		/* DTIM period */
+	int16		RSSI;			/* receive signal strength (in dBm) */
+	int8		phy_noise;		/* noise (in dBm) */
+
+	uint8		n_cap;			/* BSS is 802.11N Capable */
+	uint32		nbss_cap;		/* 802.11N+AC BSS Capabilities */
+	uint8		ctl_ch;			/* 802.11N BSS control channel number */
+	uint8		padding1[3];		/* explicit struct alignment padding */
+	uint16		vht_rxmcsmap;	/* VHT rx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
+	uint16		vht_txmcsmap;	/* VHT tx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
+	uint8		flags;			/* flags */
+	uint8		vht_cap;		/* BSS is vht capable */
+	uint8		reserved[2];		/* Reserved for expansion of BSS properties */
+	uint8		basic_mcs[MCSSET_LEN];	/* 802.11N BSS required MCS set */
+
+	uint16		ie_offset;		/* offset at which IEs start, from beginning */
+	uint32		ie_length;		/* byte length of Information Elements */
+	int16		SNR;			/* average SNR of during frame reception */
+	/* Add new fields here */
+	/* variable length Information Elements */
+} wl_bss_info_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+typedef struct wl_bsscfg {
+	uint32  bsscfg_idx;
+	uint32  wsec;
+	uint32  WPA_auth;
+	uint32  wsec_index;
+	uint32  associated;
+	uint32  BSS;
+	uint32  phytest_on;
+	struct ether_addr   prev_BSSID;
+	struct ether_addr   BSSID;
+	uint32  targetbss_wpa2_flags;
+	uint32 assoc_type;
+	uint32 assoc_state;
+} wl_bsscfg_t;
+
+typedef struct wl_if_add {
+	uint32  bsscfg_flags;
+	uint32  if_flags;
+	uint32  ap;
+	struct ether_addr   mac_addr;
+} wl_if_add_t;
+
+typedef struct wl_bss_config {
+	uint32	atim_window;
+	uint32	beacon_period;
+	uint32	chanspec;
+} wl_bss_config_t;
+
+#define WL_BSS_USER_RADAR_CHAN_SELECT	0x1	/* User application will randomly select
+						 * radar channel.
+						 */
+
+#define DLOAD_HANDLER_VER			1	/* Downloader version */
+#define DLOAD_FLAG_VER_MASK		0xf000	/* Downloader version mask */
+#define DLOAD_FLAG_VER_SHIFT	12	/* Downloader version shift */
+
+#define DL_CRC_NOT_INUSE 			0x0001
+
+/* generic download types & flags */
+enum {
+	DL_TYPE_UCODE = 1,
+	DL_TYPE_CLM = 2
+};
+
+/* ucode type values */
+enum {
+	UCODE_FW,
+	INIT_VALS,
+	BS_INIT_VALS
+};
+
+struct wl_dload_data {
+	uint16 flag;
+	uint16 dload_type;
+	uint32 len;
+	uint32 crc;
+	uint8  data[1];
+};
+typedef struct wl_dload_data wl_dload_data_t;
+
+struct wl_ucode_info {
+	uint32 ucode_type;
+	uint32 num_chunks;
+	uint32 chunk_len;
+	uint32 chunk_num;
+	uint8  data_chunk[1];
+};
+typedef struct wl_ucode_info wl_ucode_info_t;
+
+struct wl_clm_dload_info {
+	uint32 ds_id;
+	uint32 clm_total_len;
+	uint32 num_chunks;
+	uint32 chunk_len;
+	uint32 chunk_offset;
+	uint8  data_chunk[1];
+};
+typedef struct wl_clm_dload_info wl_clm_dload_info_t;
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+typedef struct wlc_ssid {
+	uint32		SSID_len;
+	uchar		SSID[DOT11_MAX_SSID_LEN];
+} wlc_ssid_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+#define MAX_PREFERRED_AP_NUM     5
+typedef struct wlc_fastssidinfo {
+	uint32				SSID_channel[MAX_PREFERRED_AP_NUM];
+	wlc_ssid_t		SSID_info[MAX_PREFERRED_AP_NUM];
+} wlc_fastssidinfo_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wnm_url {
+	uint8   len;
+	uint8   data[1];
+} BWL_POST_PACKED_STRUCT wnm_url_t;
+
+typedef struct chan_scandata {
+	uint8		txpower;
+	uint8		pad;
+	chanspec_t	channel;	/* Channel num, bw, ctrl_sb and band */
+	uint32		channel_mintime;
+	uint32		channel_maxtime;
+} chan_scandata_t;
+
+typedef enum wl_scan_type {
+	EXTDSCAN_FOREGROUND_SCAN,
+	EXTDSCAN_BACKGROUND_SCAN,
+	EXTDSCAN_FORCEDBACKGROUND_SCAN
+} wl_scan_type_t;
+
+#define WLC_EXTDSCAN_MAX_SSID		5
+
+typedef struct wl_extdscan_params {
+	int8 		nprobes;		/* 0, passive, otherwise active */
+	int8    	split_scan;		/* split scan */
+	int8		band;			/* band */
+	int8		pad;
+	wlc_ssid_t 	ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */
+	uint32		tx_rate;		/* in 500ksec units */
+	wl_scan_type_t	scan_type;		/* enum */
+	int32 		channel_num;
+	chan_scandata_t channel_list[1];	/* list of chandata structs */
+} wl_extdscan_params_t;
+
+#define WL_EXTDSCAN_PARAMS_FIXED_SIZE 	(sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t))
+
+#define WL_SCAN_PARAMS_SSID_MAX 	10
+
+typedef struct wl_scan_params {
+	wlc_ssid_t ssid;		/* default: {0, ""} */
+	struct ether_addr bssid;	/* default: bcast */
+	int8 bss_type;			/* default: any,
+					 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
+					 */
+	uint8 scan_type;		/* flags, 0 use default */
+	int32 nprobes;			/* -1 use default, number of probes per channel */
+	int32 active_time;		/* -1 use default, dwell time per channel for
+					 * active scanning
+					 */
+	int32 passive_time;		/* -1 use default, dwell time per channel
+					 * for passive scanning
+					 */
+	int32 home_time;		/* -1 use default, dwell time for the home channel
+					 * between channel scans
+					 */
+	int32 channel_num;		/* count of channels and ssids that follow
+					 *
+					 * low half is count of channels in channel_list, 0
+					 * means default (use all available channels)
+					 *
+					 * high half is entries in wlc_ssid_t array that
+					 * follows channel_list, aligned for int32 (4 bytes)
+					 * meaning an odd channel count implies a 2-byte pad
+					 * between end of channel_list and first ssid
+					 *
+					 * if ssid count is zero, single ssid in the fixed
+					 * parameter portion is assumed, otherwise ssid in
+					 * the fixed portion is ignored
+					 */
+	uint16 channel_list[1];		/* list of chanspecs */
+} wl_scan_params_t;
+
+/* size of wl_scan_params not including variable length array */
+#define WL_SCAN_PARAMS_FIXED_SIZE 64
+
+#define ISCAN_REQ_VERSION 1
+
+/* incremental scan struct */
+typedef struct wl_iscan_params {
+	uint32 version;
+	uint16 action;
+	uint16 scan_duration;
+	wl_scan_params_t params;
+} wl_iscan_params_t;
+
+/* 3 fields + size of wl_scan_params, not including variable length array */
+#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t))
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+typedef struct wl_scan_results {
+	uint32 buflen;
+	uint32 version;
+	uint32 count;
+	wl_bss_info_t bss_info[1];
+} wl_scan_results_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* size of wl_scan_results not including variable length array */
+#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t))
+
+/* Used in EXT_STA */
+#define DNGL_RXCTXT_SIZE	45
+
+#if defined(SIMPLE_ISCAN)
+/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */
+#define WLC_IW_ISCAN_MAXLEN   2048
+typedef struct iscan_buf {
+	struct iscan_buf * next;
+	char   iscan_buf[WLC_IW_ISCAN_MAXLEN];
+} iscan_buf_t;
+#endif /* SIMPLE_ISCAN */
+
+#define ESCAN_REQ_VERSION 1
+
+typedef struct wl_escan_params {
+	uint32 version;
+	uint16 action;
+	uint16 sync_id;
+	wl_scan_params_t params;
+} wl_escan_params_t;
+
+#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t))
+
+typedef struct wl_escan_result {
+	uint32 buflen;
+	uint32 version;
+	uint16 sync_id;
+	uint16 bss_count;
+	wl_bss_info_t bss_info[1];
+} wl_escan_result_t;
+
+#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t))
+
+/* incremental scan results struct */
+typedef struct wl_iscan_results {
+	uint32 status;
+	wl_scan_results_t results;
+} wl_iscan_results_t;
+
+/* size of wl_iscan_results not including variable length array */
+#define WL_ISCAN_RESULTS_FIXED_SIZE \
+	(WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results))
+
+#define SCANOL_PARAMS_VERSION	1
+
+typedef struct scanol_params {
+	uint32 version;
+	uint32 flags;	/* offload scanning flags */
+	int32 active_time;	/* -1 use default, dwell time per channel for active scanning */
+	int32 passive_time;	/* -1 use default, dwell time per channel for passive scanning */
+	int32 idle_rest_time;	/* -1 use default, time idle between scan cycle */
+	int32 idle_rest_time_multiplier;
+	int32 active_rest_time;
+	int32 active_rest_time_multiplier;
+	int32 scan_cycle_idle_rest_time;
+	int32 scan_cycle_idle_rest_multiplier;
+	int32 scan_cycle_active_rest_time;
+	int32 scan_cycle_active_rest_multiplier;
+	int32 max_rest_time;
+	int32 max_scan_cycles;
+	int32 nprobes;		/* -1 use default, number of probes per channel */
+	int32 scan_start_delay;
+	uint32 nchannels;
+	uint32 ssid_count;
+	wlc_ssid_t ssidlist[1];
+} scanol_params_t;
+
+typedef struct wl_probe_params {
+	wlc_ssid_t ssid;
+	struct ether_addr bssid;
+	struct ether_addr mac;
+} wl_probe_params_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define WL_MAXRATES_IN_SET		16	/* max # of rates in a rateset */
+typedef struct wl_rateset {
+	uint32	count;			/* # rates in this set */
+	uint8	rates[WL_MAXRATES_IN_SET];	/* rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+typedef struct wl_rateset_args {
+	uint32	count;			/* # rates in this set */
+	uint8	rates[WL_MAXRATES_IN_SET];	/* rates in 500kbps units w/hi bit set if basic */
+	uint8   mcs[MCSSET_LEN];        /* supported mcs index bit map */
+	uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */
+} 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];	/* one for each stream */
+	uint8	txbf_rate_mcs_bcm[TXBF_RATE_MCS_ALL];	/* one for each stream */
+	uint16	txbf_rate_vht[TXBF_RATE_VHT_ALL];	/* one for each stream */
+	uint16	txbf_rate_vht_bcm[TXBF_RATE_VHT_ALL];	/* one for each stream */
+	uint8	txbf_rate_ofdm[TXBF_RATE_OFDM_ALL];	/* bitmap of ofdm rates that enables txbf */
+	uint8	txbf_rate_ofdm_bcm[TXBF_RATE_OFDM_ALL]; /* bitmap of ofdm rates that enables txbf */
+	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_rates_info {
+	wl_rateset_t rs_tgt;
+	uint32 phy_type;
+	int32 bandtype;
+	uint8 cck_only;
+	uint8 rate_mask;
+	uint8 mcsallow;
+	uint8 bw;
+	uint8 txstreams;
+} wl_rates_info_t;
+
+/* uint32 list */
+typedef struct wl_uint32_list {
+	/* in - # of elements, out - # of entries */
+	uint32 count;
+	/* variable length uint32 list */
+	uint32 element[1];
+} wl_uint32_list_t;
+
+/* used for association with a specific BSSID and chanspec list */
+typedef struct wl_assoc_params {
+	struct ether_addr bssid;	/* 00:00:00:00:00:00: broadcast scan */
+	uint16 bssid_cnt;		/* 0: use chanspec_num, and the single bssid,
+					* otherwise count of chanspecs in chanspec_list
+					* AND paired bssids following chanspec_list
+					* also, chanspec_num has to be set to zero
+					* for bssid list to be used
+					*/
+	int32 chanspec_num;		/* 0: all available channels,
+					* otherwise count of chanspecs in chanspec_list
+					*/
+	chanspec_t chanspec_list[1];	/* list of chanspecs */
+} wl_assoc_params_t;
+
+#define WL_ASSOC_PARAMS_FIXED_SIZE 	OFFSETOF(wl_assoc_params_t, chanspec_list)
+
+/* used for reassociation/roam to a specific BSSID and channel */
+typedef wl_assoc_params_t wl_reassoc_params_t;
+#define WL_REASSOC_PARAMS_FIXED_SIZE	WL_ASSOC_PARAMS_FIXED_SIZE
+
+/* used for association to a specific BSSID and channel */
+typedef wl_assoc_params_t wl_join_assoc_params_t;
+#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE	WL_ASSOC_PARAMS_FIXED_SIZE
+
+/* used for join with or without a specific bssid and channel list */
+typedef struct wl_join_params {
+	wlc_ssid_t ssid;
+	wl_assoc_params_t params;	/* optional field, but it must include the fixed portion
+					 * of the wl_assoc_params_t struct when it does present.
+					 */
+} wl_join_params_t;
+
+#ifndef  LINUX_POSTMOGRIFY_REMOVAL
+#define WL_JOIN_PARAMS_FIXED_SIZE 	(OFFSETOF(wl_join_params_t, params) + \
+					 WL_ASSOC_PARAMS_FIXED_SIZE)
+/* scan params for extended join */
+typedef struct wl_join_scan_params {
+	uint8 scan_type;		/* 0 use default, active or passive scan */
+	int32 nprobes;			/* -1 use default, number of probes per channel */
+	int32 active_time;		/* -1 use default, dwell time per channel for
+					 * active scanning
+					 */
+	int32 passive_time;		/* -1 use default, dwell time per channel
+					 * for passive scanning
+					 */
+	int32 home_time;		/* -1 use default, dwell time for the home channel
+					 * between channel scans
+					 */
+} wl_join_scan_params_t;
+
+/* extended join params */
+typedef struct wl_extjoin_params {
+	wlc_ssid_t ssid;		/* {0, ""}: wildcard scan */
+	wl_join_scan_params_t scan;
+	wl_join_assoc_params_t assoc;	/* optional field, but it must include the fixed portion
+					 * of the wl_join_assoc_params_t struct when it does
+					 * present.
+					 */
+} wl_extjoin_params_t;
+#define WL_EXTJOIN_PARAMS_FIXED_SIZE 	(OFFSETOF(wl_extjoin_params_t, assoc) + \
+					 WL_JOIN_ASSOC_PARAMS_FIXED_SIZE)
+
+#define ANT_SELCFG_MAX		4	/* max number of antenna configurations */
+#define MAX_STREAMS_SUPPORTED	4	/* max number of streams supported */
+typedef struct {
+	uint8 ant_config[ANT_SELCFG_MAX];	/* antenna configuration */
+	uint8 num_antcfg;	/* number of available antenna configurations */
+} wlc_antselcfg_t;
+
+typedef struct {
+	uint32 duration;	/* millisecs spent sampling this channel */
+	uint32 congest_ibss;	/* millisecs in our bss (presumably this traffic will */
+				/*  move if cur bss moves channels) */
+	uint32 congest_obss;	/* traffic not in our bss */
+	uint32 interference;	/* millisecs detecting a non 802.11 interferer. */
+	uint32 timestamp;	/* second timestamp */
+} cca_congest_t;
+
+typedef struct {
+	chanspec_t chanspec;	/* Which channel? */
+	uint8 num_secs;		/* How many secs worth of data */
+	cca_congest_t  secs[1];	/* Data */
+} cca_congest_channel_req_t;
+
+/* interference sources */
+enum interference_source {
+	ITFR_NONE = 0,		/* interference */
+	ITFR_PHONE,		/* wireless phone */
+	ITFR_VIDEO_CAMERA,	/* wireless video camera */
+	ITFR_MICROWAVE_OVEN,	/* microwave oven */
+	ITFR_BABY_MONITOR,	/* wireless baby monitor */
+	ITFR_BLUETOOTH,		/* bluetooth */
+	ITFR_VIDEO_CAMERA_OR_BABY_MONITOR,	/* wireless camera or baby monitor */
+	ITFR_BLUETOOTH_OR_BABY_MONITOR,	/* bluetooth or baby monitor */
+	ITFR_VIDEO_CAMERA_OR_PHONE,	/* video camera or phone */
+	ITFR_UNIDENTIFIED	/* interference from unidentified source */
+};
+
+/* structure for interference source report */
+typedef struct {
+	uint32 flags;	/* flags.  bit definitions below */
+	uint32 source;	/* last detected interference source */
+	uint32 timestamp;	/* second timestamp on interferenced flag change */
+} interference_source_rep_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define WLC_CNTRY_BUF_SZ	4		/* Country string is 3 bytes + NUL */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+typedef struct wl_country {
+	char country_abbrev[WLC_CNTRY_BUF_SZ];	/* nul-terminated country code used in
+						 * the Country IE
+						 */
+	int32 rev;				/* revision specifier for ccode
+						 * on set, -1 indicates unspecified.
+						 * on get, rev >= 0
+						 */
+	char ccode[WLC_CNTRY_BUF_SZ];		/* nul-terminated built-in country code.
+						 * variable length, but fixed size in
+						 * struct allows simple allocation for
+						 * expected country strings <= 3 chars.
+						 */
+} wl_country_t;
+
+typedef struct wl_channels_in_country {
+	uint32 buflen;
+	uint32 band;
+	char country_abbrev[WLC_CNTRY_BUF_SZ];
+	uint32 count;
+	uint32 channel[1];
+} wl_channels_in_country_t;
+
+typedef struct wl_country_list {
+	uint32 buflen;
+	uint32 band_set;
+	uint32 band;
+	uint32 count;
+	char country_abbrev[1];
+} wl_country_list_t;
+
+typedef struct wl_rm_req_elt {
+	int8	type;
+	int8	flags;
+	chanspec_t	chanspec;
+	uint32	token;		/* token for this measurement */
+	uint32	tsf_h;		/* TSF high 32-bits of Measurement start time */
+	uint32	tsf_l;		/* TSF low 32-bits */
+	uint32	dur;		/* TUs */
+} wl_rm_req_elt_t;
+
+typedef struct wl_rm_req {
+	uint32	token;		/* overall measurement set token */
+	uint32	count;		/* number of measurement requests */
+	void	*cb;		/* completion callback function: may be NULL */
+	void	*cb_arg;	/* arg to completion callback function */
+	wl_rm_req_elt_t	req[1];	/* variable length block of requests */
+} wl_rm_req_t;
+#define WL_RM_REQ_FIXED_LEN	OFFSETOF(wl_rm_req_t, req)
+
+typedef struct wl_rm_rep_elt {
+	int8	type;
+	int8	flags;
+	chanspec_t	chanspec;
+	uint32	token;		/* token for this measurement */
+	uint32	tsf_h;		/* TSF high 32-bits of Measurement start time */
+	uint32	tsf_l;		/* TSF low 32-bits */
+	uint32	dur;		/* TUs */
+	uint32	len;		/* byte length of data block */
+	uint8	data[1];	/* variable length data block */
+} wl_rm_rep_elt_t;
+#define WL_RM_REP_ELT_FIXED_LEN	24	/* length excluding data block */
+
+#define WL_RPI_REP_BIN_NUM 8
+typedef struct wl_rm_rpi_rep {
+	uint8	rpi[WL_RPI_REP_BIN_NUM];
+	int8	rpi_max[WL_RPI_REP_BIN_NUM];
+} wl_rm_rpi_rep_t;
+
+typedef struct wl_rm_rep {
+	uint32	token;		/* overall measurement set token */
+	uint32	len;		/* length of measurement report block */
+	wl_rm_rep_elt_t	rep[1];	/* variable length block of reports */
+} wl_rm_rep_t;
+#define WL_RM_REP_FIXED_LEN	8
+
+#ifdef BCMCCX
+
+#define LEAP_USER_MAX		32
+#define LEAP_DOMAIN_MAX		32
+#define LEAP_PASSWORD_MAX	32
+
+typedef struct wl_leap_info {
+	wlc_ssid_t ssid;
+	uint8 user_len;
+	uchar user[LEAP_USER_MAX];
+	uint8 password_len;
+	uchar password[LEAP_PASSWORD_MAX];
+	uint8 domain_len;
+	uchar domain[LEAP_DOMAIN_MAX];
+} wl_leap_info_t;
+
+typedef struct wl_leap_list {
+	uint32 buflen;
+	uint32 version;
+	uint32 count;
+	wl_leap_info_t leap_info[1];
+} wl_leap_list_t;
+#endif	/* BCMCCX */
+
+typedef enum sup_auth_status {
+	/* Basic supplicant authentication states */
+	WLC_SUP_DISCONNECTED = 0,
+	WLC_SUP_CONNECTING,
+	WLC_SUP_IDREQUIRED,
+	WLC_SUP_AUTHENTICATING,
+	WLC_SUP_AUTHENTICATED,
+	WLC_SUP_KEYXCHANGE,
+	WLC_SUP_KEYED,
+	WLC_SUP_TIMEOUT,
+	WLC_SUP_LAST_BASIC_STATE,
+
+	/* Extended supplicant authentication states */
+	/* Waiting to receive handshake msg M1 */
+	WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED,
+	/* Preparing to send handshake msg M2 */
+	WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE,
+	/* Waiting to receive handshake msg M3 */
+	WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE,
+	WLC_SUP_KEYXCHANGE_PREP_M4,	/* Preparing to send handshake msg M4 */
+	WLC_SUP_KEYXCHANGE_WAIT_G1,	/* Waiting to receive handshake msg G1 */
+	WLC_SUP_KEYXCHANGE_PREP_G2	/* Preparing to send handshake msg G2 */
+} sup_auth_status_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+typedef struct wl_wsec_key {
+	uint32		index;		/* key index */
+	uint32		len;		/* key length */
+	uint8		data[DOT11_MAX_KEY_SIZE];	/* key data */
+	uint32		pad_1[18];
+	uint32		algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+	uint32		flags;		/* misc flags */
+	uint32		pad_2[2];
+	int		pad_3;
+	int		iv_initialized;	/* has IV been initialized already? */
+	int		pad_4;
+	/* Rx IV */
+	struct {
+		uint32	hi;		/* upper 32 bits of IV */
+		uint16	lo;		/* lower 16 bits of IV */
+	} rxiv;
+	uint32		pad_5[2];
+	struct ether_addr ea;		/* per station */
+} wl_wsec_key_t;
+
+#define WSEC_MIN_PSK_LEN	8
+#define WSEC_MAX_PSK_LEN	64
+
+/* Flag for key material needing passhash'ing */
+#define WSEC_PASSPHRASE		(1<<0)
+
+/* receptacle for WLC_SET_WSEC_PMK parameter */
+typedef struct {
+	ushort	key_len;		/* octets in key material */
+	ushort	flags;			/* key handling qualification */
+	uint8	key[WSEC_MAX_PSK_LEN];	/* PMK material */
+} wsec_pmk_t;
+
+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;
+
+#define WL_STA_ANT_MAX		4	/* max possible rx antennas */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct wl_assoc_info {
+	uint32		req_len;
+	uint32		resp_len;
+	uint32		flags;
+	struct dot11_assoc_req req;
+	struct ether_addr reassoc_bssid; /* used in reassoc's */
+	struct dot11_assoc_resp resp;
+} wl_assoc_info_t;
+
+typedef struct wl_led_info {
+	uint32      index;      /* led index */
+	uint32      behavior;
+	uint8       activehi;
+} wl_led_info_t;
+
+
+/* srom read/write struct passed through ioctl */
+typedef struct {
+	uint	byteoff;	/* byte offset */
+	uint	nbytes;		/* number of bytes */
+	uint16	buf[1];
+} srom_rw_t;
+
+/* similar cis (srom or otp) struct [iovar: may not be aligned] */
+typedef struct {
+	uint32	source;		/* cis source */
+	uint32	byteoff;	/* byte offset */
+	uint32	nbytes;		/* number of bytes */
+	/* data follows here */
+} cis_rw_t;
+
+/* R_REG and W_REG struct passed through ioctl */
+typedef struct {
+	uint32	byteoff;	/* byte offset of the field in d11regs_t */
+	uint32	val;		/* read/write value of the field */
+	uint32	size;		/* sizeof the field */
+	uint	band;		/* band (optional) */
+} rw_reg_t;
+
+/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */
+/* PCL - Power Control Loop */
+typedef struct {
+	uint16	auto_ctrl;	/* WL_ATTEN_XX */
+	uint16	bb;		/* Baseband attenuation */
+	uint16	radio;		/* Radio attenuation */
+	uint16	txctl1;		/* Radio TX_CTL1 value */
+} atten_t;
+
+/* Per-AC retry parameters */
+struct wme_tx_params_s {
+	uint8  short_retry;
+	uint8  short_fallback;
+	uint8  long_retry;
+	uint8  long_fallback;
+	uint16 max_rate;  /* In units of 512 Kbps */
+};
+
+typedef struct wme_tx_params_s wme_tx_params_t;
+
+#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT)
+
+typedef struct wl_plc_nodelist {
+	uint32 count;			/* Number of nodes */
+	struct _node {
+		struct ether_addr ea;	/* Node ether address */
+		uint32 node_type;	/* Node type */
+		uint32 cost;		/* PLC affinity */
+	} node[1];
+} wl_plc_nodelist_t;
+
+typedef struct wl_plc_params {
+	uint32	cmd;			/* Command */
+	uint8	plc_failover;		/* PLC failover control/status */
+	struct	ether_addr node_ea;	/* Node ether address */
+	uint32	cost;			/* Link cost or mac cost */
+} wl_plc_params_t;
+
+/* Used to get specific link/ac parameters */
+typedef struct {
+	int32 ac;
+	uint8 val;
+	struct ether_addr ea;
+} link_val_t;
+
+
+
+typedef struct {
+	uint16			ver;		/* version of this struct */
+	uint16			len;		/* length in bytes of this structure */
+	uint16			cap;		/* sta's advertised capabilities */
+	uint32			flags;		/* flags defined below */
+	uint32			idle;		/* time since data pkt rx'd from sta */
+	struct ether_addr	ea;		/* Station address */
+	wl_rateset_t		rateset;	/* rateset in use */
+	uint32			in;		/* seconds elapsed since associated */
+	uint32			listen_interval_inms; /* Min Listen interval in ms for this STA */
+	uint32			tx_pkts;	/* # of packets transmitted */
+	uint32			tx_failures;	/* # of packets failed */
+	uint32			rx_ucast_pkts;	/* # of unicast packets received */
+	uint32			rx_mcast_pkts;	/* # of multicast packets received */
+	uint32			tx_rate;	/* Rate of last successful tx frame */
+	uint32			rx_rate;	/* Rate of last successful rx frame */
+	uint32			rx_decrypt_succeeds;	/* # of packet decrypted successfully */
+	uint32			rx_decrypt_failures;	/* # of packet decrypted unsuccessfully */
+	uint32			tx_tot_pkts;	/* # of tx pkts (ucast + mcast) */
+	uint32			rx_tot_pkts;	/* # of data packets recvd (uni + mcast) */
+	uint32			tx_mcast_pkts;	/* # of mcast pkts txed */
+	uint64			tx_tot_bytes;	/* data bytes txed (ucast + mcast) */
+	uint64			rx_tot_bytes;	/* data bytes recvd (ucast + mcast) */
+	uint64			tx_ucast_bytes;	/* data bytes txed (ucast) */
+	uint64			tx_mcast_bytes;	/* # data bytes txed (mcast) */
+	uint64			rx_ucast_bytes;	/* data bytes recvd (ucast) */
+	uint64			rx_mcast_bytes;	/* data bytes recvd (mcast) */
+	int8			rssi[WL_STA_ANT_MAX]; /* average rssi per antenna
+										   * of data frames
+										   */
+	int8			nf[WL_STA_ANT_MAX];	/* per antenna noise floor */
+	uint16			aid;		/* association ID */
+	uint16			ht_capabilities;	/* advertised ht caps */
+	uint16			vht_flags;		/* converted vht flags */
+	uint32			tx_pkts_retried; /* # of frames where a retry was necessary */
+	uint32			tx_pkts_retry_exhausted; /* # of frames where a retry was
+											* exhausted
+											*/
+	int8			rx_lastpkt_rssi[WL_STA_ANT_MAX]; /* Per antenna RSSI of last
+								* received data frame.
+								*/
+} sta_info_t;
+
+#define WL_OLD_STAINFO_SIZE	OFFSETOF(sta_info_t, tx_tot_pkts)
+
+#define WL_STA_VER		4
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define	WLC_NUMRATES	16	/* max # of rates in a rateset */
+
+typedef struct wlc_rateset {
+	uint32	count;			/* number of rates in rates[] */
+	uint8	rates[WLC_NUMRATES];	/* rates in 500kbps units w/hi bit set if basic */
+	uint8	htphy_membership;	/* HT PHY Membership */
+	uint8	mcs[MCSSET_LEN];	/* supported mcs index bit map */
+	uint16  vht_mcsmap;		/* supported vht mcs nss bit map */
+} wlc_rateset_t;
+
+/* Used to get specific STA parameters */
+typedef struct {
+	uint32	val;
+	struct ether_addr ea;
+} scb_val_t;
+
+/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */
+typedef struct {
+	uint32 code;
+	scb_val_t ioctl_args;
+} authops_t;
+
+/* channel encoding */
+typedef struct channel_info {
+	int hw_channel;
+	int target_channel;
+	int scan_channel;
+} channel_info_t;
+
+/* For ioctls that take a list of MAC addresses */
+struct maclist {
+	uint count;			/* number of MAC addresses */
+	struct ether_addr ea[1];	/* variable length array of MAC addresses */
+};
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* get pkt count struct passed through ioctl */
+typedef struct get_pktcnt {
+	uint rx_good_pkt;
+	uint rx_bad_pkt;
+	uint tx_good_pkt;
+	uint tx_bad_pkt;
+	uint rx_ocast_good_pkt; /* unicast packets destined for others */
+} get_pktcnt_t;
+
+/* NINTENDO2 */
+#define LQ_IDX_MIN              0
+#define LQ_IDX_MAX              1
+#define LQ_IDX_AVG              2
+#define LQ_IDX_SUM              2
+#define LQ_IDX_LAST             3
+#define LQ_STOP_MONITOR         0
+#define LQ_START_MONITOR        1
+
+/* Get averages RSSI, Rx PHY rate and SNR values */
+typedef struct {
+	int rssi[LQ_IDX_LAST];  /* Array to keep min, max, avg rssi */
+	int snr[LQ_IDX_LAST];   /* Array to keep min, max, avg snr */
+	int isvalid;            /* Flag indicating whether above data is valid */
+} wl_lq_t; /* Link Quality */
+
+typedef enum wl_wakeup_reason_type {
+	LCD_ON = 1,
+	LCD_OFF,
+	DRC1_WAKE,
+	DRC2_WAKE,
+	REASON_LAST
+} wl_wr_type_t;
+
+typedef struct {
+/* Unique filter id */
+	uint32	id;
+
+/* stores the reason for the last wake up */
+	uint8	reason;
+} wl_wr_t;
+
+/* Get MAC specific rate histogram command */
+typedef struct {
+	struct	ether_addr ea;	/* MAC Address */
+	uint8	ac_cat;	/* Access Category */
+	uint8	num_pkts;	/* Number of packet entries to be averaged */
+} wl_mac_ratehisto_cmd_t;	/* MAC Specific Rate Histogram command */
+
+/* Get MAC rate histogram response */
+typedef struct {
+	uint32	rate[DOT11_RATE_MAX + 1];	/* Rates */
+	uint32	mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX];	/* MCS counts */
+	uint32	vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX];	/* VHT counts */
+	uint32	tsf_timer[2][2];	/* Start and End time for 8bytes value */
+} wl_mac_ratehisto_res_t;	/* MAC Specific Rate Histogram Response */
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* Linux network driver ioctl encoding */
+typedef struct wl_ioctl {
+	uint cmd;	/* common ioctl definition */
+	void *buf;	/* pointer to user buffer */
+	uint len;	/* length of user buffer */
+	uint8 set;		/* 1=set IOCTL; 0=query IOCTL */
+	uint used;	/* bytes read or written (optional) */
+	uint needed;	/* bytes needed (optional) */
+} wl_ioctl_t;
+#ifdef CONFIG_COMPAT
+typedef struct compat_wl_ioctl {
+	uint cmd;	/* common ioctl definition */
+	uint32 buf;	/* pointer to user buffer */
+	uint len;	/* length of user buffer */
+	uint8 set;		/* 1=set IOCTL; 0=query IOCTL */
+	uint used;	/* bytes read or written (optional) */
+	uint needed;	/* bytes needed (optional) */
+} compat_wl_ioctl_t;
+#endif /* CONFIG_COMPAT */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+/*
+ * Structure for passing hardware and software
+ * revision info up from the driver.
+ */
+typedef struct wlc_rev_info {
+	uint		vendorid;	/* PCI vendor id */
+	uint		deviceid;	/* device id of chip */
+	uint		radiorev;	/* radio revision */
+	uint		chiprev;	/* chip revision */
+	uint		corerev;	/* core revision */
+	uint		boardid;	/* board identifier (usu. PCI sub-device id) */
+	uint		boardvendor;	/* board vendor (usu. PCI sub-vendor id) */
+	uint		boardrev;	/* board revision */
+	uint		driverrev;	/* driver version */
+	uint		ucoderev;	/* microcode version */
+	uint		bus;		/* bus type */
+	uint		chipnum;	/* chip number */
+	uint		phytype;	/* phy type */
+	uint		phyrev;		/* phy revision */
+	uint		anarev;		/* anacore rev */
+	uint		chippkg;	/* chip package info */
+	uint		nvramrev;	/* nvram revision number */
+} wlc_rev_info_t;
+
+#define WL_REV_INFO_LEGACY_LENGTH	48
+
+#define WL_BRAND_MAX 10
+typedef struct wl_instance_info {
+	uint instance;
+	char brand[WL_BRAND_MAX];
+} wl_instance_info_t;
+
+/* structure to change size of tx fifo */
+typedef struct wl_txfifo_sz {
+	uint16	magic;
+	uint16	fifo;
+	uint16	size;
+} wl_txfifo_sz_t;
+
+/* Transfer info about an IOVar from the driver */
+/* Max supported IOV name size in bytes, + 1 for nul termination */
+#define WLC_IOV_NAME_LEN 30
+typedef struct wlc_iov_trx_s {
+	uint8 module;
+	uint8 type;
+	char name[WLC_IOV_NAME_LEN];
+} wlc_iov_trx_t;
+
+/* bump this number if you change the ioctl interface */
+#define WLC_IOCTL_VERSION	2
+#define WLC_IOCTL_VERSION_LEGACY_IOTYPES	1
+
+#ifdef CONFIG_USBRNDIS_RETAIL
+/* struct passed in for WLC_NDCONFIG_ITEM */
+typedef struct {
+	char *name;
+	void *param;
+} ndconfig_item_t;
+#endif
+
+
+#define WL_PHY_PAVARS_LEN	32	/* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */
+
+#define WL_PHY_PAVAR_VER	1	/* pavars version */
+#define WL_PHY_PAVARS2_NUM	3	/* a1, b0, b1 */
+typedef struct wl_pavars2 {
+	uint16 ver;		/* version of this struct */
+	uint16 len;		/* len of this structure */
+	uint16 inuse;		/* driver return 1 for a1,b0,b1 in current band range */
+	uint16 phy_type;	/* phy type */
+	uint16 bandrange;
+	uint16 chain;
+	uint16 inpa[WL_PHY_PAVARS2_NUM];	/* phy pavars for one band range */
+} wl_pavars2_t;
+
+typedef struct wl_po {
+	uint16	phy_type;	/* Phy type */
+	uint16	band;
+	uint16	cckpo;
+	uint32	ofdmpo;
+	uint16	mcspo[8];
+} wl_po_t;
+
+#define WL_NUM_RPCALVARS 5	/* number of rpcal vars */
+
+typedef struct wl_rpcal {
+	uint16 value;
+	uint16 update;
+} wl_rpcal_t;
+
+typedef struct wl_aci_args {
+	int enter_aci_thresh; /* Trigger level to start detecting ACI */
+	int exit_aci_thresh; /* Trigger level to exit ACI mode */
+	int usec_spin; /* microsecs to delay between rssi samples */
+	int glitch_delay; /* interval between ACI scans when glitch count is consistently high */
+	uint16 nphy_adcpwr_enter_thresh;	/* ADC power to enter ACI mitigation mode */
+	uint16 nphy_adcpwr_exit_thresh;	/* ADC power to exit ACI mitigation mode */
+	uint16 nphy_repeat_ctr;		/* Number of tries per channel to compute power */
+	uint16 nphy_num_samples;	/* Number of samples to compute power on one channel */
+	uint16 nphy_undetect_window_sz;	/* num of undetects to exit ACI Mitigation mode */
+	uint16 nphy_b_energy_lo_aci;	/* low ACI power energy threshold for bphy */
+	uint16 nphy_b_energy_md_aci;	/* mid ACI power energy threshold for bphy */
+	uint16 nphy_b_energy_hi_aci;	/* high ACI power energy threshold for bphy */
+	uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */
+	uint16 nphy_noise_noassoc_glitch_th_dn;
+	uint16 nphy_noise_assoc_glitch_th_up;
+	uint16 nphy_noise_assoc_glitch_th_dn;
+	uint16 nphy_noise_assoc_aci_glitch_th_up;
+	uint16 nphy_noise_assoc_aci_glitch_th_dn;
+	uint16 nphy_noise_assoc_enter_th;
+	uint16 nphy_noise_noassoc_enter_th;
+	uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th;
+	uint16 nphy_noise_noassoc_crsidx_incr;
+	uint16 nphy_noise_assoc_crsidx_incr;
+	uint16 nphy_noise_crsidx_decr;
+} wl_aci_args_t;
+
+#define WL_ACI_ARGS_LEGACY_LENGTH	16	/* bytes of pre NPHY aci args */
+#define	WL_SAMPLECOLLECT_T_VERSION	2	/* version of wl_samplecollect_args_t struct */
+typedef struct wl_samplecollect_args {
+	/* version 0 fields */
+	uint8 coll_us;
+	int cores;
+	/* add'l version 1 fields */
+	uint16 version;     /* see definition of WL_SAMPLECOLLECT_T_VERSION */
+	uint16 length;      /* length of entire structure */
+	int8 trigger;
+	uint16 timeout;
+	uint16 mode;
+	uint32 pre_dur;
+	uint32 post_dur;
+	uint8 gpio_sel;
+	uint8 downsamp;
+	uint8 be_deaf;
+	uint8 agc;		/* loop from init gain and going down */
+	uint8 filter;		/* override high pass corners to lowest */
+	/* add'l version 2 fields */
+	uint8 trigger_state;
+	uint8 module_sel1;
+	uint8 module_sel2;
+	uint16 nsamps;
+	int bitStart;
+	uint32 gpioCapMask;
+} wl_samplecollect_args_t;
+
+#define	WL_SAMPLEDATA_T_VERSION		1	/* version of wl_samplecollect_args_t struct */
+/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */
+#define	WL_SAMPLEDATA_T_VERSION_SPEC_AN 2
+
+typedef struct wl_sampledata {
+	uint16 version;	/* structure version */
+	uint16 size;	/* size of structure */
+	uint16 tag;	/* Header/Data */
+	uint16 length;	/* data length */
+	uint32 flag;	/* bit def */
+} wl_sampledata_t;
+
+
+/* WL_OTA START */
+/* OTA Test Status */
+enum {
+	WL_OTA_TEST_IDLE = 0,	/* Default Idle state */
+	WL_OTA_TEST_ACTIVE = 1,	/* Test Running */
+	WL_OTA_TEST_SUCCESS = 2,	/* Successfully Finished Test */
+	WL_OTA_TEST_FAIL = 3	/* Test Failed in the Middle */
+};
+/* OTA SYNC Status */
+enum {
+	WL_OTA_SYNC_IDLE = 0,	/* Idle state */
+	WL_OTA_SYNC_ACTIVE = 1,	/* Waiting for Sync */
+	WL_OTA_SYNC_FAIL = 2	/* Sync pkt not recieved */
+};
+
+/* Various error states dut can get stuck during test */
+enum {
+	WL_OTA_SKIP_TEST_CAL_FAIL = 1,		/* Phy calibration failed */
+	WL_OTA_SKIP_TEST_SYNCH_FAIL = 2,		/* Sync Packet not recieved */
+	WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL = 3,	/* Cmd flow file download failed */
+	WL_OTA_SKIP_TEST_NO_TEST_FOUND = 4,	/* No test found in Flow file */
+	WL_OTA_SKIP_TEST_WL_NOT_UP = 5,		/* WL UP failed */
+	WL_OTA_SKIP_TEST_UNKNOWN_CALL		/* Unintentional scheduling on ota test */
+};
+
+/* Differentiator for ota_tx and ota_rx */
+enum {
+	WL_OTA_TEST_TX = 0,		/* ota_tx */
+	WL_OTA_TEST_RX = 1,		/* ota_rx */
+};
+
+/* Catch 3 modes of operation: 20Mhz, 40Mhz, 20 in 40 Mhz */
+enum {
+	WL_OTA_TEST_BW_20_IN_40MHZ = 0,	/* 20 in 40 operation */
+	WL_OTA_TEST_BW_20MHZ = 1,		/* 20 Mhz operation */
+	WL_OTA_TEST_BW_40MHZ = 2		/* full 40Mhz operation */
+};
+typedef struct ota_rate_info {
+	uint8 rate_cnt;					/* Total number of rates */
+	uint8 rate_val_mbps[WL_OTA_TEST_MAX_NUM_RATE];	/* array of rates from 1mbps to 130mbps */
+							/* for legacy rates : ratein mbps * 2 */
+							/* for HT rates : mcs index */
+} ota_rate_info_t;
+
+typedef struct ota_power_info {
+	int8 pwr_ctrl_on;	/* power control on/off */
+	int8 start_pwr;		/* starting power/index */
+	int8 delta_pwr;		/* delta power/index */
+	int8 end_pwr;		/* end power/index */
+} ota_power_info_t;
+
+typedef struct ota_packetengine {
+	uint16 delay;           /* Inter-packet delay */
+				/* for ota_tx, delay is tx ifs in micro seconds */
+				/* for ota_rx, delay is wait time in milliseconds */
+	uint16 nframes;         /* Number of frames */
+	uint16 length;          /* Packet length */
+} ota_packetengine_t;
+
+/* Test info vector */
+typedef struct wl_ota_test_args {
+	uint8 cur_test;			/* test phase */
+	uint8 chan;			/* channel */
+	uint8 bw;			/* bandwidth */
+	uint8 control_band;		/* control band */
+	uint8 stf_mode;			/* stf mode */
+	ota_rate_info_t rt_info;	/* Rate info */
+	ota_packetengine_t pkteng;	/* packeteng info */
+	uint8 txant;			/* tx antenna */
+	uint8 rxant;			/* rx antenna */
+	ota_power_info_t pwr_info;	/* power sweep info */
+	uint8 wait_for_sync;		/* wait for sync or not */
+} wl_ota_test_args_t;
+
+typedef struct wl_ota_test_vector {
+	wl_ota_test_args_t test_arg[WL_OTA_TEST_MAX_NUM_SEQ];	/* Test argument struct */
+	uint16 test_cnt;					/* Total no of test */
+	uint8 file_dwnld_valid;					/* File successfully downloaded */
+	uint8 sync_timeout;					/* sync packet timeout */
+	int8 sync_fail_action;					/* sync fail action */
+	struct ether_addr sync_mac;				/* macaddress for sync pkt */
+	struct ether_addr tx_mac;				/* macaddress for tx */
+	struct ether_addr rx_mac;				/* macaddress for rx */
+	int8 loop_test;					/* dbg feature to loop the test */
+} wl_ota_test_vector_t;
+
+
+/* struct copied back form dongle to host to query the status */
+typedef struct wl_ota_test_status {
+	int16 cur_test_cnt;		/* test phase */
+	int8 skip_test_reason;		/* skip test reasoin */
+	wl_ota_test_args_t test_arg;	/* cur test arg details */
+	uint16 test_cnt;		/* total no of test downloaded */
+	uint8 file_dwnld_valid;		/* file successfully downloaded ? */
+	uint8 sync_timeout;		/* sync timeout */
+	int8 sync_fail_action;		/* sync fail action */
+	struct ether_addr sync_mac;	/* macaddress for sync pkt */
+	struct ether_addr tx_mac;	/* tx mac address */
+	struct ether_addr rx_mac;	/* rx mac address */
+	uint8  test_stage;		/* check the test status */
+	int8 loop_test;		/* Debug feature to puts test enfine in a loop */
+	uint8 sync_status;		/* sync status */
+} wl_ota_test_status_t;
+
+/* WL_OTA END */
+
+/* wl_radar_args_t */
+typedef struct {
+	int npulses;	/* required number of pulses at n * t_int */
+	int ncontig;	/* required number of pulses at t_int */
+	int min_pw;	/* minimum pulse width (20 MHz clocks) */
+	int max_pw;	/* maximum pulse width (20 MHz clocks) */
+	uint16 thresh0;	/* Radar detection, thresh 0 */
+	uint16 thresh1;	/* Radar detection, thresh 1 */
+	uint16 blank;	/* Radar detection, blank control */
+	uint16 fmdemodcfg;	/* Radar detection, fmdemod config */
+	int npulses_lp;  /* Radar detection, minimum long pulses */
+	int min_pw_lp; /* Minimum pulsewidth for long pulses */
+	int max_pw_lp; /* Maximum pulsewidth for long pulses */
+	int min_fm_lp; /* Minimum fm for long pulses */
+	int max_span_lp;  /* Maximum deltat for long pulses */
+	int min_deltat; /* Minimum spacing between pulses */
+	int max_deltat; /* Maximum spacing between pulses */
+	uint16 autocorr;	/* Radar detection, autocorr on or off */
+	uint16 st_level_time;	/* Radar detection, start_timing level */
+	uint16 t2_min; /* minimum clocks needed to remain in state 2 */
+	uint32 version; /* version */
+	uint32 fra_pulse_err;	/* sample error margin for detecting French radar pulsed */
+	int npulses_fra;  /* Radar detection, minimum French pulses set */
+	int npulses_stg2;  /* Radar detection, minimum staggered-2 pulses set */
+	int npulses_stg3;  /* Radar detection, minimum staggered-3 pulses set */
+	uint16 percal_mask;	/* defines which period cal is masked from radar detection */
+	int quant;	/* quantization resolution to pulse positions */
+	uint32 min_burst_intv_lp;	/* minimum burst to burst interval for bin3 radar */
+	uint32 max_burst_intv_lp;	/* maximum burst to burst interval for bin3 radar */
+	int nskip_rst_lp;	/* number of skipped pulses before resetting lp buffer */
+	int max_pw_tol;	/* maximum tollerance allowed in detected pulse width for radar detection */
+	uint16 feature_mask; /* 16-bit mask to specify enabled features */
+} wl_radar_args_t;
+
+#define WL_RADAR_ARGS_VERSION 2
+
+typedef struct {
+	uint32 version; /* version */
+	uint16 thresh0_20_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */
+	uint16 thresh1_20_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */
+	uint16 thresh0_40_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */
+	uint16 thresh1_40_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */
+	uint16 thresh0_80_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */
+	uint16 thresh1_80_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */
+	uint16 thresh0_20_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */
+	uint16 thresh1_20_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */
+	uint16 thresh0_40_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */
+	uint16 thresh1_40_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */
+	uint16 thresh0_80_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */
+	uint16 thresh1_80_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */
+#ifdef WL11AC160
+	uint16 thresh0_160_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */
+	uint16 thresh1_160_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */
+	uint16 thresh0_160_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */
+	uint16 thresh1_160_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */
+#endif /* WL11AC160 */
+} wl_radar_thr_t;
+
+#define WL_RADAR_THR_VERSION	2
+
+/* RSSI per antenna */
+typedef struct {
+	uint32	version;		/* version field */
+	uint32	count;			/* number of valid antenna rssi */
+	int8 rssi_ant[WL_RSSI_ANT_MAX];	/* rssi per antenna */
+} wl_rssi_ant_t;
+
+/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */
+typedef struct {
+	uint state;		/* noted by WL_DFS_CACSTATE_XX. */
+	uint duration;		/* time spent in ms in state. */
+	/* as dfs enters ISM state, it removes the operational channel from quiet channel
+	 * list and notes the channel in channel_cleared. set to 0 if no channel is cleared
+	 */
+	chanspec_t chanspec_cleared;
+	/* chanspec cleared used to be a uint, add another to uint16 to maintain size */
+	uint16 pad;
+} wl_dfs_status_t;
+
+/* data structure used in 'radar_status' wl interface, which is use to query radar det status */
+typedef struct {
+	bool detected;
+	int count;
+	bool pretended;
+	uint32 radartype;
+	uint32 timenow;
+	uint32 timefromL;
+	int lp_csect_single;
+	int detected_pulse_index;
+	int nconsecq_pulses;
+	chanspec_t ch;
+	int pw[10];
+	int intv[10];
+	int fm[10];
+} wl_radar_status_t;
+
+#define NUM_PWRCTRL_RATES 12
+
+typedef struct {
+	uint8 txpwr_band_max[NUM_PWRCTRL_RATES];	/* User set target */
+	uint8 txpwr_limit[NUM_PWRCTRL_RATES];		/* reg and local power limit */
+	uint8 txpwr_local_max;				/* local max according to the AP */
+	uint8 txpwr_local_constraint;			/* local constraint according to the AP */
+	uint8 txpwr_chan_reg_max;			/* Regulatory max for this channel */
+	uint8 txpwr_target[2][NUM_PWRCTRL_RATES];	/* Latest target for 2.4 and 5 Ghz */
+	uint8 txpwr_est_Pout[2];			/* Latest estimate for 2.4 and 5 Ghz */
+	uint8 txpwr_opo[NUM_PWRCTRL_RATES];		/* On G phy, OFDM power offset */
+	uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES];	/* Max CCK power for this band (SROM) */
+	uint8 txpwr_bphy_ofdm_max;			/* Max OFDM power for this band (SROM) */
+	uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES];	/* Max power for A band (SROM) */
+	int8  txpwr_antgain[2];				/* Ant gain for each band - from SROM */
+	uint8 txpwr_est_Pout_gofdm;			/* Pwr estimate for 2.4 OFDM */
+} tx_power_legacy_t;
+
+#define WL_TX_POWER_RATES_LEGACY    45
+#define WL_TX_POWER_MCS20_FIRST         12
+#define WL_TX_POWER_MCS20_NUM           16
+#define WL_TX_POWER_MCS40_FIRST         28
+#define WL_TX_POWER_MCS40_NUM           17
+
+typedef struct {
+	uint32 flags;
+	chanspec_t chanspec;                 /* txpwr report for this channel */
+	chanspec_t local_chanspec;           /* channel on which we are associated */
+	uint8 local_max;                 /* local max according to the AP */
+	uint8 local_constraint;              /* local constraint according to the AP */
+	int8  antgain[2];                /* Ant gain for each band - from SROM */
+	uint8 rf_cores;                  /* count of RF Cores being reported */
+	uint8 est_Pout[4];                           /* Latest tx power out estimate per RF
+							  * chain without adjustment
+							  */
+	uint8 est_Pout_cck;                          /* Latest CCK tx power out estimate */
+	uint8 user_limit[WL_TX_POWER_RATES_LEGACY];  /* User limit */
+	uint8 reg_limit[WL_TX_POWER_RATES_LEGACY];   /* Regulatory power limit */
+	uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */
+	uint8 target[WL_TX_POWER_RATES_LEGACY];      /* Latest target power */
+} tx_power_legacy2_t;
+
+/* TX Power index defines */
+#define WL_NUM_RATES_CCK			4 /* 1, 2, 5.5, 11 Mbps */
+#define WL_NUM_RATES_OFDM			8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */
+#define WL_NUM_RATES_MCS_1STREAM	8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */
+#define WL_NUM_RATES_EXTRA_VHT		2 /* Additional VHT 11AC rates */
+#define WL_NUM_RATES_VHT			10
+#define WL_NUM_RATES_MCS32			1
+
+#define WLC_NUM_RATES_CCK       WL_NUM_RATES_CCK
+#define WLC_NUM_RATES_OFDM      WL_NUM_RATES_OFDM
+#define WLC_NUM_RATES_MCS_1_STREAM  WL_NUM_RATES_MCS_1STREAM
+#define WLC_NUM_RATES_MCS_2_STREAM  WL_NUM_RATES_MCS_1STREAM
+#define WLC_NUM_RATES_MCS32     WL_NUM_RATES_MCS32
+#define WL_TX_POWER_CCK_NUM     WL_NUM_RATES_CCK
+#define WL_TX_POWER_OFDM_NUM        WL_NUM_RATES_OFDM
+#define WL_TX_POWER_MCS_1_STREAM_NUM    WL_NUM_RATES_MCS_1STREAM
+#define WL_TX_POWER_MCS_2_STREAM_NUM    WL_NUM_RATES_MCS_1STREAM
+#define WL_TX_POWER_MCS_32_NUM      WL_NUM_RATES_MCS32
+
+#define WL_NUM_2x2_ELEMENTS		4
+#define WL_NUM_3x3_ELEMENTS		6
+
+typedef struct {
+	uint16 ver;				/* version of this struct */
+	uint16 len;				/* length in bytes of this structure */
+	uint32 flags;
+	chanspec_t chanspec;			/* txpwr report for this channel */
+	chanspec_t local_chanspec;		/* channel on which we are associated */
+	uint32     buflen;			/* ppr buffer length */
+	uint8      pprbuf[1];			/* Latest target power buffer */
+} wl_txppr_t;
+
+#define WL_TXPPR_VERSION	1
+#define WL_TXPPR_LENGTH	(sizeof(wl_txppr_t))
+#define TX_POWER_T_VERSION	44
+
+
+typedef struct tx_inst_power {
+	uint8 txpwr_est_Pout[2];			/* Latest estimate for 2.4 and 5 Ghz */
+	uint8 txpwr_est_Pout_gofdm;			/* Pwr estimate for 2.4 OFDM */
+} tx_inst_power_t;
+
+#define WL_NUM_TXCHAIN_MAX	4
+typedef struct wl_txchain_pwr_offsets {
+	int8 offset[WL_NUM_TXCHAIN_MAX];	/* quarter dBm signed offset for each chain */
+} wl_txchain_pwr_offsets_t;
+/* maximum channels returned by the get valid channels iovar */
+#define WL_NUMCHANNELS		64
+
+/*
+ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type,
+ * a one-byte length, and a variable length value.  RSSI type tuple must be present
+ * in the array.
+ *
+ * Types are defined in "join preference types" section.
+ *
+ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple
+ * and must be set to zero.
+ *
+ * Values are defined below.
+ *
+ * 1. RSSI - 2 octets
+ * offset 0: reserved
+ * offset 1: reserved
+ *
+ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below)
+ * offset 0: reserved
+ * offset 1: # of tuples
+ * offset 2: tuple 1
+ * offset 14: tuple 2
+ * ...
+ * offset 2 + 12 * (n - 1) octets: tuple n
+ *
+ * struct wpa_cfg_tuple {
+ *   uint8 akm[DOT11_OUI_LEN+1];     akm suite
+ *   uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite
+ *   uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite
+ * };
+ *
+ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY.
+ *
+ * 3. BAND - 2 octets
+ * offset 0: reserved
+ * offset 1: see "band preference" and "band types"
+ *
+ * 4. BAND RSSI - 2 octets
+ * offset 0: band types
+ * offset 1: +ve RSSI boost value in dB
+ */
+
+struct tsinfo_arg {
+	uint8 octets[3];
+};
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define	NFIFO			6	/* # tx/rx fifopairs */
+#define NREINITREASONCOUNT	8
+#define REINITREASONIDX(_x)	(((_x) < NREINITREASONCOUNT) ? (_x) : 0)
+
+/* version 7001 wl_cnt_t is same as version 7 with exception of phywatchdog is
+ * replaced with rxbcnlossmbss */
+#define	WL_CNT_T_VERSION_7001	7001	/* version 7001 of wl_cnt_t struct */
+/* wl_cnt_t is merged from firmware twig to be in sync */
+#define	WL_CNT_T_VERSION	7	/* current version of wl_cnt_t struct */
+
+typedef struct {
+	uint16	version;	/* see definition of WL_CNT_T_VERSION */
+	uint16	length;		/* length of entire structure */
+
+	/* transmit stat counters */
+	uint32	txframe;	/* tx data frames */
+	uint32	txbyte;		/* tx data bytes */
+	uint32	txretrans;	/* tx mac retransmits */
+	uint32	txerror;	/* tx data errors (derived: sum of others) */
+	uint32	txctl;		/* tx management frames */
+	uint32	txprshort;	/* tx short preamble frames */
+	uint32	txserr;		/* tx status errors */
+	uint32	txnobuf;	/* tx out of buffers errors */
+	uint32	txnoassoc;	/* tx discard because we're not associated */
+	uint32	txrunt;		/* tx runt frames */
+	uint32	txchit;		/* tx header cache hit (fastpath) */
+	uint32	txcmiss;	/* tx header cache miss (slowpath) */
+
+	/* transmit chip error counters */
+	uint32	txuflo;		/* tx fifo underflows */
+	uint32	txphyerr;	/* tx phy errors (indicated in tx status) */
+	uint32	txphycrs;
+
+	/* receive stat counters */
+	uint32	rxframe;	/* rx data frames */
+	uint32	rxbyte;		/* rx data bytes */
+	uint32	rxerror;	/* rx data errors (derived: sum of others) */
+	uint32	rxctl;		/* rx management frames */
+	uint32	rxnobuf;	/* rx out of buffers errors */
+	uint32	rxnondata;	/* rx non data frames in the data channel errors */
+	uint32	rxbadds;	/* rx bad DS errors */
+	uint32	rxbadcm;	/* rx bad control or management frames */
+	uint32	rxfragerr;	/* rx fragmentation errors */
+	uint32	rxrunt;		/* rx runt frames */
+	uint32	rxgiant;	/* rx giant frames */
+	uint32	rxnoscb;	/* rx no scb error */
+	uint32	rxbadproto;	/* rx invalid frames */
+	uint32	rxbadsrcmac;	/* rx frames with Invalid Src Mac */
+	uint32	rxbadda;	/* rx frames tossed for invalid da */
+	uint32	rxfilter;	/* rx frames filtered out */
+
+	/* receive chip error counters */
+	uint32	rxoflo;		/* rx fifo overflow errors */
+	uint32	rxuflo[NFIFO];	/* rx dma descriptor underflow errors */
+
+	uint32	d11cnt_txrts_off;	/* d11cnt txrts value when reset d11cnt */
+	uint32	d11cnt_rxcrc_off;	/* d11cnt rxcrc value when reset d11cnt */
+	uint32	d11cnt_txnocts_off;	/* d11cnt txnocts value when reset d11cnt */
+
+	/* misc counters */
+	uint32	dmade;		/* tx/rx dma descriptor errors */
+	uint32	dmada;		/* tx/rx dma data errors */
+	uint32	dmape;		/* tx/rx dma descriptor protocol errors */
+	uint32	reset;		/* reset count */
+	uint32	tbtt;		/* cnts the TBTT int's */
+	uint32	txdmawar;
+	uint32	pkt_callback_reg_fail;	/* callbacks register failure */
+
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32	txallfrm;	/* total number of frames sent, incl. Data, ACK, RTS, CTS,
+				 * Control Management (includes retransmissions)
+				 */
+	uint32	txrtsfrm;	/* number of RTS sent out by the MAC */
+	uint32	txctsfrm;	/* number of CTS sent out by the MAC */
+	uint32	txackfrm;	/* number of ACK frames sent out */
+	uint32	txdnlfrm;	/* Not used */
+	uint32	txbcnfrm;	/* beacons transmitted */
+	uint32	txfunfl[8];	/* per-fifo tx underflows */
+	uint32	txtplunfl;	/* Template underflows (mac was too slow to transmit ACK/CTS
+				 * or BCN)
+				 */
+	uint32	txphyerror;	/* Transmit phy error, type of error is reported in tx-status for
+				 * driver enqueued frames
+				 */
+	uint32	rxfrmtoolong;	/* Received frame longer than legal limit (2346 bytes) */
+	uint32	rxfrmtooshrt;	/* Received frame did not contain enough bytes for its frame type */
+	uint32	rxinvmachdr;	/* Either the protocol version != 0 or frame type not
+				 * data/control/management
+				 */
+	uint32	rxbadfcs;	/* number of frames for which the CRC check failed in the MAC */
+	uint32	rxbadplcp;	/* parity check of the PLCP header failed */
+	uint32	rxcrsglitch;	/* PHY was able to correlate the preamble but not the header */
+	uint32	rxstrt;		/* Number of received frames with a good PLCP
+				 * (i.e. passing parity check)
+				 */
+	uint32	rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
+	uint32	rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+	uint32	rxcfrmucast;	/* number of received CNTRL frames with good FCS and matching RA */
+	uint32	rxrtsucast;	/* number of unicast RTS addressed to the MAC (good FCS) */
+	uint32	rxctsucast;	/* number of unicast CTS addressed to the MAC (good FCS) */
+	uint32	rxackucast;	/* number of ucast ACKS received (good FCS) */
+	uint32	rxdfrmocast;	/* number of received DATA frames (good FCS and not matching RA) */
+	uint32	rxmfrmocast;	/* number of received MGMT frames (good FCS and not matching RA) */
+	uint32	rxcfrmocast;	/* number of received CNTRL frame (good FCS and not matching RA) */
+	uint32	rxrtsocast;	/* number of received RTS not addressed to the MAC */
+	uint32	rxctsocast;	/* number of received CTS not addressed to the MAC */
+	uint32	rxdfrmmcast;	/* number of RX Data multicast frames received by the MAC */
+	uint32	rxmfrmmcast;	/* number of RX Management multicast frames received by the MAC */
+	uint32	rxcfrmmcast;	/* number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32	rxbeaconmbss;	/* beacons received from member of BSS */
+	uint32	rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32	rxbeaconobss;	/* beacons received from other BSS */
+	uint32	rxrsptmout;	/* Number of response timeouts for transmitted frames
+				 * expecting a response
+				 */
+	uint32	bcntxcancl;	/* transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32	rxf0ovfl;	/* Number of receive fifo 0 overflows */
+	uint32	rxf1ovfl;	/* Number of receive fifo 1 overflows (obsolete) */
+	uint32	rxf2ovfl;	/* Number of receive fifo 2 overflows (obsolete) */
+	uint32	txsfovfl;	/* Number of transmit status fifo overflows (obsolete) */
+	uint32	pmqovfl;	/* Number of PMQ overflows */
+	uint32	rxcgprqfrm;	/* Number of received Probe requests that made it into
+				 * the PRQ fifo
+				 */
+	uint32	rxcgprsqovfl;	/* Rx Probe Request Que overflow in the AP */
+	uint32	txcgprsfail;	/* Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32	txcgprssuc;	/* Tx Probe Response Success (ACK was received) */
+	uint32	prs_timeout;	/* Number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32	rxnack;		/* obsolete */
+	uint32	frmscons;	/* obsolete */
+	uint32	txnack;		/* obsolete */
+	uint32	txglitch_nack;	/* obsolete */
+	uint32	txburst;	/* obsolete */
+
+	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+	uint32	txfrag;		/* dot11TransmittedFragmentCount */
+	uint32	txmulti;	/* dot11MulticastTransmittedFrameCount */
+	uint32	txfail;		/* dot11FailedCount */
+	uint32	txretry;	/* dot11RetryCount */
+	uint32	txretrie;	/* dot11MultipleRetryCount */
+	uint32	rxdup;		/* dot11FrameduplicateCount */
+	uint32	txrts;		/* dot11RTSSuccessCount */
+	uint32	txnocts;	/* dot11RTSFailureCount */
+	uint32	txnoack;	/* dot11ACKFailureCount */
+	uint32	rxfrag;		/* dot11ReceivedFragmentCount */
+	uint32	rxmulti;	/* dot11MulticastReceivedFrameCount */
+	uint32	rxcrc;		/* dot11FCSErrorCount */
+	uint32	txfrmsnt;	/* dot11TransmittedFrameCount (bogus MIB?) */
+	uint32	rxundec;	/* dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill;	/* TKIPLocalMICFailures */
+	uint32	tkipcntrmsr;	/* TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay;	/* TKIPReplays */
+	uint32	ccmpfmterr;	/* CCMPFormatErrors */
+	uint32	ccmpreplay;	/* CCMPReplays */
+	uint32	ccmpundec;	/* CCMPDecryptErrors */
+	uint32	fourwayfail;	/* FourWayHandshakeFailures */
+	uint32	wepundec;	/* dot11WEPUndecryptableCount */
+	uint32	wepicverr;	/* dot11WEPICVErrorCount */
+	uint32	decsuccess;	/* DecryptSuccessCount */
+	uint32	tkipicverr;	/* TKIPICVErrorCount */
+	uint32	wepexcluded;	/* dot11WEPExcludedCount */
+
+	uint32	txchanrej;	/* Tx frames suppressed due to channel rejection */
+	uint32	psmwds;		/* Count PSM watchdogs */
+	uint32	rxbcnlossmbss;	/* Count beacon loss member of BSS (triggered by ucode) */
+
+	/* MBSS counters, AP only */
+	uint32	prq_entries_handled;	/* PRQ entries read in */
+	uint32	prq_undirected_entries;	/*    which were bcast bss & ssid */
+	uint32	prq_bad_entries;	/*    which could not be translated to info */
+	uint32	atim_suppress_count;	/* TX suppressions on ATIM fifo */
+	uint32	bcn_template_not_ready;	/* Template marked in use on send bcn ... */
+	uint32	bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
+	uint32	late_tbtt_dpc;	/* TBTT DPC did not happen in time */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;	/* packets rx at 1Mbps */
+	uint32  rx2mbps;	/* packets rx at 2Mbps */
+	uint32  rx5mbps5;	/* packets rx at 5.5Mbps */
+	uint32  rx6mbps;	/* packets rx at 6Mbps */
+	uint32  rx9mbps;	/* packets rx at 9Mbps */
+	uint32  rx11mbps;	/* packets rx at 11Mbps */
+	uint32  rx12mbps;	/* packets rx at 12Mbps */
+	uint32  rx18mbps;	/* packets rx at 18Mbps */
+	uint32  rx24mbps;	/* packets rx at 24Mbps */
+	uint32  rx36mbps;	/* packets rx at 36Mbps */
+	uint32  rx48mbps;	/* packets rx at 48Mbps */
+	uint32  rx54mbps;	/* packets rx at 54Mbps */
+	uint32  rx108mbps;	/* packets rx at 108mbps */
+	uint32  rx162mbps;	/* packets rx at 162mbps */
+	uint32  rx216mbps;	/* packets rx at 216 mbps */
+	uint32  rx270mbps;	/* packets rx at 270 mbps */
+	uint32  rx324mbps;	/* packets rx at 324 mbps */
+	uint32  rx378mbps;	/* packets rx at 378 mbps */
+	uint32  rx432mbps;	/* packets rx at 432 mbps */
+	uint32  rx486mbps;	/* packets rx at 486 mbps */
+	uint32  rx540mbps;	/* packets rx at 540 mbps */
+
+	/* pkteng rx frame stats */
+	uint32	pktengrxducast; /* unicast frames rxed by the pkteng code */
+	uint32	pktengrxdmcast; /* multicast frames rxed by the pkteng code */
+
+	uint32	rfdisable;	/* count of radio disables */
+	uint32	bphy_rxcrsglitch;	/* PHY count of bphy glitches */
+
+	uint32	txexptime;	/* Tx frames suppressed due to timer expiration */
+
+	uint32	txmpdu_sgi;	/* count for sgi transmit */
+	uint32	rxmpdu_sgi;	/* count for sgi received */
+	uint32	txmpdu_stbc;	/* count for stbc transmit */
+	uint32	rxmpdu_stbc;	/* count for stbc received */
+
+	uint32	rxundec_mcst;	/* dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill_mcst;	/* TKIPLocalMICFailures */
+	uint32	tkipcntrmsr_mcst;	/* TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay_mcst;	/* TKIPReplays */
+	uint32	ccmpfmterr_mcst;	/* CCMPFormatErrors */
+	uint32	ccmpreplay_mcst;	/* CCMPReplays */
+	uint32	ccmpundec_mcst;	/* CCMPDecryptErrors */
+	uint32	fourwayfail_mcst;	/* FourWayHandshakeFailures */
+	uint32	wepundec_mcst;	/* dot11WEPUndecryptableCount */
+	uint32	wepicverr_mcst;	/* dot11WEPICVErrorCount */
+	uint32	decsuccess_mcst;	/* DecryptSuccessCount */
+	uint32	tkipicverr_mcst;	/* TKIPICVErrorCount */
+	uint32	wepexcluded_mcst;	/* dot11WEPExcludedCount */
+
+	uint32	dma_hang;	/* count for stbc received */
+} wl_cnt_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct {
+	uint16  version;    /* see definition of WL_CNT_T_VERSION */
+	uint16  length;     /* length of entire structure */
+
+	/* transmit stat counters */
+	uint32  txframe;    /* tx data frames */
+	uint32  txbyte;     /* tx data bytes */
+	uint32  txretrans;  /* tx mac retransmits */
+	uint32  txerror;    /* tx data errors (derived: sum of others) */
+	uint32  txctl;      /* tx management frames */
+	uint32  txprshort;  /* tx short preamble frames */
+	uint32  txserr;     /* tx status errors */
+	uint32  txnobuf;    /* tx out of buffers errors */
+	uint32  txnoassoc;  /* tx discard because we're not associated */
+	uint32  txrunt;     /* tx runt frames */
+	uint32  txchit;     /* tx header cache hit (fastpath) */
+	uint32  txcmiss;    /* tx header cache miss (slowpath) */
+
+	/* transmit chip error counters */
+	uint32  txuflo;     /* tx fifo underflows */
+	uint32  txphyerr;   /* tx phy errors (indicated in tx status) */
+	uint32  txphycrs;
+
+	/* receive stat counters */
+	uint32  rxframe;    /* rx data frames */
+	uint32  rxbyte;     /* rx data bytes */
+	uint32  rxerror;    /* rx data errors (derived: sum of others) */
+	uint32  rxctl;      /* rx management frames */
+	uint32  rxnobuf;    /* rx out of buffers errors */
+	uint32  rxnondata;  /* rx non data frames in the data channel errors */
+	uint32  rxbadds;    /* rx bad DS errors */
+	uint32  rxbadcm;    /* rx bad control or management frames */
+	uint32  rxfragerr;  /* rx fragmentation errors */
+	uint32  rxrunt;     /* rx runt frames */
+	uint32  rxgiant;    /* rx giant frames */
+	uint32  rxnoscb;    /* rx no scb error */
+	uint32  rxbadproto; /* rx invalid frames */
+	uint32  rxbadsrcmac;    /* rx frames with Invalid Src Mac */
+	uint32  rxbadda;    /* rx frames tossed for invalid da */
+	uint32  rxfilter;   /* rx frames filtered out */
+
+	/* receive chip error counters */
+	uint32  rxoflo;     /* rx fifo overflow errors */
+	uint32  rxuflo[NFIFO];  /* rx dma descriptor underflow errors */
+
+	uint32  d11cnt_txrts_off;   /* d11cnt txrts value when reset d11cnt */
+	uint32  d11cnt_rxcrc_off;   /* d11cnt rxcrc value when reset d11cnt */
+	uint32  d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */
+
+	/* misc counters */
+	uint32  dmade;      /* tx/rx dma descriptor errors */
+	uint32  dmada;      /* tx/rx dma data errors */
+	uint32  dmape;      /* tx/rx dma descriptor protocol errors */
+	uint32  reset;      /* reset count */
+	uint32  tbtt;       /* cnts the TBTT int's */
+	uint32  txdmawar;
+	uint32  pkt_callback_reg_fail;  /* callbacks register failure */
+
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32  txallfrm;   /* total number of frames sent, incl. Data, ACK, RTS, CTS,
+			     * Control Management (includes retransmissions)
+			     */
+	uint32  txrtsfrm;   /* number of RTS sent out by the MAC */
+	uint32  txctsfrm;   /* number of CTS sent out by the MAC */
+	uint32  txackfrm;   /* number of ACK frames sent out */
+	uint32  txdnlfrm;   /* Not used */
+	uint32  txbcnfrm;   /* beacons transmitted */
+	uint32  txfunfl[6]; /* per-fifo tx underflows */
+	uint32	rxtoolate;	/* receive too late */
+	uint32  txfbw;	    /* transmit at fallback bw (dynamic bw) */
+	uint32  txtplunfl;  /* Template underflows (mac was too slow to transmit ACK/CTS
+			     * or BCN)
+			     */
+	uint32  txphyerror; /* Transmit phy error, type of error is reported in tx-status for
+			     * driver enqueued frames
+			     */
+	uint32  rxfrmtoolong;   /* Received frame longer than legal limit (2346 bytes) */
+	uint32  rxfrmtooshrt;   /* Received frame did not contain enough bytes for its frame type */
+	uint32  rxinvmachdr;    /* Either the protocol version != 0 or frame type not
+				 * data/control/management
+			   */
+	uint32  rxbadfcs;   /* number of frames for which the CRC check failed in the MAC */
+	uint32  rxbadplcp;  /* parity check of the PLCP header failed */
+	uint32  rxcrsglitch;    /* PHY was able to correlate the preamble but not the header */
+	uint32  rxstrt;     /* Number of received frames with a good PLCP
+			     * (i.e. passing parity check)
+			     */
+	uint32  rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
+	uint32  rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+	uint32  rxcfrmucast;    /* number of received CNTRL frames with good FCS and matching RA */
+	uint32  rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */
+	uint32  rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */
+	uint32  rxackucast; /* number of ucast ACKS received (good FCS) */
+	uint32  rxdfrmocast;    /* number of received DATA frames (good FCS and not matching RA) */
+	uint32  rxmfrmocast;    /* number of received MGMT frames (good FCS and not matching RA) */
+	uint32  rxcfrmocast;    /* number of received CNTRL frame (good FCS and not matching RA) */
+	uint32  rxrtsocast; /* number of received RTS not addressed to the MAC */
+	uint32  rxctsocast; /* number of received CTS not addressed to the MAC */
+	uint32  rxdfrmmcast;    /* number of RX Data multicast frames received by the MAC */
+	uint32  rxmfrmmcast;    /* number of RX Management multicast frames received by the MAC */
+	uint32  rxcfrmmcast;    /* number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32  rxbeaconmbss;   /* beacons received from member of BSS */
+	uint32  rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32  rxbeaconobss;   /* beacons received from other BSS */
+	uint32  rxrsptmout; /* Number of response timeouts for transmitted frames
+			     * expecting a response
+			     */
+	uint32  bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32  rxf0ovfl;   /* Number of receive fifo 0 overflows */
+	uint32  rxf1ovfl;   /* Number of receive fifo 1 overflows (obsolete) */
+	uint32  rxf2ovfl;   /* Number of receive fifo 2 overflows (obsolete) */
+	uint32  txsfovfl;   /* Number of transmit status fifo overflows (obsolete) */
+	uint32  pmqovfl;    /* Number of PMQ overflows */
+	uint32  rxcgprqfrm; /* Number of received Probe requests that made it into
+			     * the PRQ fifo
+			     */
+	uint32  rxcgprsqovfl;   /* Rx Probe Request Que overflow in the AP */
+	uint32  txcgprsfail;    /* Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32  txcgprssuc; /* Tx Probe Response Success (ACK was received) */
+	uint32  prs_timeout;    /* Number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32  rxnack;
+	uint32  frmscons;
+	uint32  txnack;		/* obsolete */
+	uint32	rxback;		/* blockack rxcnt */
+	uint32	txback;		/* blockack txcnt */
+
+	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+	uint32  txfrag;     /* dot11TransmittedFragmentCount */
+	uint32  txmulti;    /* dot11MulticastTransmittedFrameCount */
+	uint32  txfail;     /* dot11FailedCount */
+	uint32  txretry;    /* dot11RetryCount */
+	uint32  txretrie;   /* dot11MultipleRetryCount */
+	uint32  rxdup;      /* dot11FrameduplicateCount */
+	uint32  txrts;      /* dot11RTSSuccessCount */
+	uint32  txnocts;    /* dot11RTSFailureCount */
+	uint32  txnoack;    /* dot11ACKFailureCount */
+	uint32  rxfrag;     /* dot11ReceivedFragmentCount */
+	uint32  rxmulti;    /* dot11MulticastReceivedFrameCount */
+	uint32  rxcrc;      /* dot11FCSErrorCount */
+	uint32  txfrmsnt;   /* dot11TransmittedFrameCount (bogus MIB?) */
+	uint32  rxundec;    /* dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32  tkipmicfaill;   /* TKIPLocalMICFailures */
+	uint32  tkipcntrmsr;    /* TKIPCounterMeasuresInvoked */
+	uint32  tkipreplay; /* TKIPReplays */
+	uint32  ccmpfmterr; /* CCMPFormatErrors */
+	uint32  ccmpreplay; /* CCMPReplays */
+	uint32  ccmpundec;  /* CCMPDecryptErrors */
+	uint32  fourwayfail;    /* FourWayHandshakeFailures */
+	uint32  wepundec;   /* dot11WEPUndecryptableCount */
+	uint32  wepicverr;  /* dot11WEPICVErrorCount */
+	uint32  decsuccess; /* DecryptSuccessCount */
+	uint32  tkipicverr; /* TKIPICVErrorCount */
+	uint32  wepexcluded;    /* dot11WEPExcludedCount */
+
+	uint32  rxundec_mcst;   /* dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32  tkipmicfaill_mcst;  /* TKIPLocalMICFailures */
+	uint32  tkipcntrmsr_mcst;   /* TKIPCounterMeasuresInvoked */
+	uint32  tkipreplay_mcst;    /* TKIPReplays */
+	uint32  ccmpfmterr_mcst;    /* CCMPFormatErrors */
+	uint32  ccmpreplay_mcst;    /* CCMPReplays */
+	uint32  ccmpundec_mcst; /* CCMPDecryptErrors */
+	uint32  fourwayfail_mcst;   /* FourWayHandshakeFailures */
+	uint32  wepundec_mcst;  /* dot11WEPUndecryptableCount */
+	uint32  wepicverr_mcst; /* dot11WEPICVErrorCount */
+	uint32  decsuccess_mcst;    /* DecryptSuccessCount */
+	uint32  tkipicverr_mcst;    /* TKIPICVErrorCount */
+	uint32  wepexcluded_mcst;   /* dot11WEPExcludedCount */
+
+	uint32  txchanrej;  /* Tx frames suppressed due to channel rejection */
+	uint32  txexptime;  /* Tx frames suppressed due to timer expiration */
+	uint32  psmwds;     /* Count PSM watchdogs */
+	uint32  phywatchdog;    /* Count Phy watchdogs (triggered by ucode) */
+
+	/* MBSS counters, AP only */
+	uint32  prq_entries_handled;    /* PRQ entries read in */
+	uint32  prq_undirected_entries; /*    which were bcast bss & ssid */
+	uint32  prq_bad_entries;    /*    which could not be translated to info */
+	uint32  atim_suppress_count;    /* TX suppressions on ATIM fifo */
+	uint32  bcn_template_not_ready; /* Template marked in use on send bcn ... */
+	uint32  bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
+	uint32  late_tbtt_dpc;  /* TBTT DPC did not happen in time */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;    /* packets rx at 1Mbps */
+	uint32  rx2mbps;    /* packets rx at 2Mbps */
+	uint32  rx5mbps5;   /* packets rx at 5.5Mbps */
+	uint32  rx6mbps;    /* packets rx at 6Mbps */
+	uint32  rx9mbps;    /* packets rx at 9Mbps */
+	uint32  rx11mbps;   /* packets rx at 11Mbps */
+	uint32  rx12mbps;   /* packets rx at 12Mbps */
+	uint32  rx18mbps;   /* packets rx at 18Mbps */
+	uint32  rx24mbps;   /* packets rx at 24Mbps */
+	uint32  rx36mbps;   /* packets rx at 36Mbps */
+	uint32  rx48mbps;   /* packets rx at 48Mbps */
+	uint32  rx54mbps;   /* packets rx at 54Mbps */
+	uint32  rx108mbps;  /* packets rx at 108mbps */
+	uint32  rx162mbps;  /* packets rx at 162mbps */
+	uint32  rx216mbps;  /* packets rx at 216 mbps */
+	uint32  rx270mbps;  /* packets rx at 270 mbps */
+	uint32  rx324mbps;  /* packets rx at 324 mbps */
+	uint32  rx378mbps;  /* packets rx at 378 mbps */
+	uint32  rx432mbps;  /* packets rx at 432 mbps */
+	uint32  rx486mbps;  /* packets rx at 486 mbps */
+	uint32  rx540mbps;  /* packets rx at 540 mbps */
+
+	/* pkteng rx frame stats */
+	uint32  pktengrxducast; /* unicast frames rxed by the pkteng code */
+	uint32  pktengrxdmcast; /* multicast frames rxed by the pkteng code */
+
+	uint32  rfdisable;  /* count of radio disables */
+	uint32  bphy_rxcrsglitch;   /* PHY count of bphy glitches */
+	uint32  bphy_badplcp;
+
+	uint32  txmpdu_sgi; /* count for sgi transmit */
+	uint32  rxmpdu_sgi; /* count for sgi received */
+	uint32  txmpdu_stbc;    /* count for stbc transmit */
+	uint32  rxmpdu_stbc;    /* count for stbc received */
+
+	uint32	rxdrop20s;	/* drop secondary cnt */
+
+} wl_cnt_ver_six_t;
+
+#define	WL_DELTA_STATS_T_VERSION	2	/* current version of wl_delta_stats_t struct */
+
+typedef struct {
+	uint16 version;     /* see definition of WL_DELTA_STATS_T_VERSION */
+	uint16 length;      /* length of entire structure */
+
+	/* transmit stat counters */
+	uint32 txframe;     /* tx data frames */
+	uint32 txbyte;      /* tx data bytes */
+	uint32 txretrans;   /* tx mac retransmits */
+	uint32 txfail;      /* tx failures */
+
+	/* receive stat counters */
+	uint32 rxframe;     /* rx data frames */
+	uint32 rxbyte;      /* rx data bytes */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;	/* packets rx at 1Mbps */
+	uint32  rx2mbps;	/* packets rx at 2Mbps */
+	uint32  rx5mbps5;	/* packets rx at 5.5Mbps */
+	uint32  rx6mbps;	/* packets rx at 6Mbps */
+	uint32  rx9mbps;	/* packets rx at 9Mbps */
+	uint32  rx11mbps;	/* packets rx at 11Mbps */
+	uint32  rx12mbps;	/* packets rx at 12Mbps */
+	uint32  rx18mbps;	/* packets rx at 18Mbps */
+	uint32  rx24mbps;	/* packets rx at 24Mbps */
+	uint32  rx36mbps;	/* packets rx at 36Mbps */
+	uint32  rx48mbps;	/* packets rx at 48Mbps */
+	uint32  rx54mbps;	/* packets rx at 54Mbps */
+	uint32  rx108mbps;	/* packets rx at 108mbps */
+	uint32  rx162mbps;	/* packets rx at 162mbps */
+	uint32  rx216mbps;	/* packets rx at 216 mbps */
+	uint32  rx270mbps;	/* packets rx at 270 mbps */
+	uint32  rx324mbps;	/* packets rx at 324 mbps */
+	uint32  rx378mbps;	/* packets rx at 378 mbps */
+	uint32  rx432mbps;	/* packets rx at 432 mbps */
+	uint32  rx486mbps;	/* packets rx at 486 mbps */
+	uint32  rx540mbps;	/* packets rx at 540 mbps */
+
+	/* phy stats */
+	uint32 rxbadplcp;
+	uint32 rxcrsglitch;
+	uint32 bphy_rxcrsglitch;
+	uint32 bphy_badplcp;
+
+} wl_delta_stats_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+typedef struct {
+	uint32 packets;
+	uint32 bytes;
+} wl_traffic_stats_t;
+
+typedef struct {
+	uint16	version;	/* see definition of WL_WME_CNT_VERSION */
+	uint16	length;		/* length of entire structure */
+
+	wl_traffic_stats_t tx[AC_COUNT];	/* Packets transmitted */
+	wl_traffic_stats_t tx_failed[AC_COUNT];	/* Packets dropped or failed to transmit */
+	wl_traffic_stats_t rx[AC_COUNT];	/* Packets received */
+	wl_traffic_stats_t rx_failed[AC_COUNT];	/* Packets failed to receive */
+
+	wl_traffic_stats_t forward[AC_COUNT];	/* Packets forwarded by AP */
+
+	wl_traffic_stats_t tx_expired[AC_COUNT];	/* packets dropped due to lifetime expiry */
+
+} wl_wme_cnt_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+struct wl_msglevel2 {
+	uint32 low;
+	uint32 high;
+};
+
+typedef struct wl_mkeep_alive_pkt {
+	uint16	version; /* Version for mkeep_alive */
+	uint16	length; /* length of fixed parameters in the structure */
+	uint32	period_msec;
+	uint16	len_bytes;
+	uint8	keep_alive_id; /* 0 - 3 for N = 4 */
+	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
+
+/* TCP Keep-Alive conn struct */
+typedef struct wl_mtcpkeep_alive_conn_pkt {
+	struct ether_addr saddr;		/* src mac address */
+	struct ether_addr daddr;		/* dst mac address */
+	struct ipv4_addr sipaddr;		/* source IP addr */
+	struct ipv4_addr dipaddr;		/* dest IP addr */
+	uint16 sport;				/* src port */
+	uint16 dport;				/* dest port */
+	uint32 seq;				/* seq number */
+	uint32 ack;				/* ACK number */
+	uint16 tcpwin;				/* TCP window */
+} wl_mtcpkeep_alive_conn_pkt_t;
+
+/* TCP Keep-Alive interval struct */
+typedef struct wl_mtcpkeep_alive_timers_pkt {
+	uint16 interval;		/* interval timer */
+	uint16 retry_interval;		/* retry_interval timer */
+	uint16 retry_count;		/* retry_count */
+} wl_mtcpkeep_alive_timers_pkt_t;
+
+typedef struct wake_info {
+	uint32 wake_reason;
+	uint32 wake_info_len;		/* size of packet */
+	uchar  packet[1];
+} wake_info_t;
+
+typedef struct wake_pkt {
+	uint32 wake_pkt_len;		/* size of packet */
+	uchar  packet[1];
+} wake_pkt_t;
+
+
+#define WL_MTCPKEEP_ALIVE_VERSION		1
+
+#ifdef WLBA
+
+#define WLC_BA_CNT_VERSION  1   /* current version of wlc_ba_cnt_t */
+
+/* block ack related stats */
+typedef struct wlc_ba_cnt {
+	uint16  version;    /* WLC_BA_CNT_VERSION */
+	uint16  length;     /* length of entire structure */
+
+	/* transmit stat counters */
+	uint32 txpdu;       /* pdus sent */
+	uint32 txsdu;       /* sdus sent */
+	uint32 txfc;        /* tx side flow controlled packets */
+	uint32 txfci;       /* tx side flow control initiated */
+	uint32 txretrans;   /* retransmitted pdus */
+	uint32 txbatimer;   /* ba resend due to timer */
+	uint32 txdrop;      /* dropped packets */
+	uint32 txaddbareq;  /* addba req sent */
+	uint32 txaddbaresp; /* addba resp sent */
+	uint32 txdelba;     /* delba sent */
+	uint32 txba;        /* ba sent */
+	uint32 txbar;       /* bar sent */
+	uint32 txpad[4];    /* future */
+
+	/* receive side counters */
+	uint32 rxpdu;       /* pdus recd */
+	uint32 rxqed;       /* pdus buffered before sending up */
+	uint32 rxdup;       /* duplicate pdus */
+	uint32 rxnobuf;     /* pdus discarded due to no buf */
+	uint32 rxaddbareq;  /* addba req recd */
+	uint32 rxaddbaresp; /* addba resp recd */
+	uint32 rxdelba;     /* delba recd */
+	uint32 rxba;        /* ba recd */
+	uint32 rxbar;       /* bar recd */
+	uint32 rxinvba;     /* invalid ba recd */
+	uint32 rxbaholes;   /* ba recd with holes */
+	uint32 rxunexp;     /* unexpected packets */
+	uint32 rxpad[4];    /* future */
+} wlc_ba_cnt_t;
+#endif /* WLBA */
+
+/* structure for per-tid ampdu control */
+struct ampdu_tid_control {
+	uint8 tid;			/* tid */
+	uint8 enable;			/* enable/disable */
+};
+
+/* struct for per-tid, per-mode ampdu control */
+struct ampdu_tid_control_mode {
+	struct ampdu_tid_control control[NUMPRIO]; /* tid will be 0xff for not used element */
+	char mode_name[8]; /* supported mode : AIBSS */
+};
+
+/* structure for identifying ea/tid for sending addba/delba */
+struct ampdu_ea_tid {
+	struct ether_addr ea;		/* Station address */
+	uint8 tid;			/* tid */
+};
+/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */
+struct ampdu_retry_tid {
+	uint8 tid;	/* tid */
+	uint8 retry;	/* retry value */
+};
+
+/* structure for dpt iovars */
+typedef struct dpt_iovar {
+	struct ether_addr ea;		/* Station address */
+	uint8 mode;			/* mode: depends on iovar */
+	uint32 pad;			/* future */
+} dpt_iovar_t;
+
+#define	DPT_FNAME_LEN		48	/* Max length of friendly name */
+
+typedef struct dpt_status {
+	uint8 status;			/* flags to indicate status */
+	uint8 fnlen;			/* length of friendly name */
+	uchar name[DPT_FNAME_LEN];	/* friendly name */
+	uint32 rssi;			/* RSSI of the link */
+	sta_info_t sta;			/* sta info */
+} dpt_status_t;
+
+/* structure for dpt list */
+typedef struct dpt_list {
+	uint32 num;			/* number of entries in struct */
+	dpt_status_t status[1];		/* per station info */
+} dpt_list_t;
+
+/* structure for dpt friendly name */
+typedef struct dpt_fname {
+	uint8 len;			/* length of friendly name */
+	uchar name[DPT_FNAME_LEN];	/* friendly name */
+} dpt_fname_t;
+
+#define BDD_FNAME_LEN       32  /* Max length of friendly name */
+typedef struct bdd_fname {
+	uint8 len;          /* length of friendly name */
+	uchar name[BDD_FNAME_LEN];  /* friendly name */
+} bdd_fname_t;
+
+/* structure for addts arguments */
+/* For ioctls that take a list of TSPEC */
+struct tslist {
+	int count;			/* number of tspecs */
+	struct tsinfo_arg tsinfo[1];	/* variable length array of tsinfo */
+};
+
+#ifdef WLTDLS
+/* structure for tdls iovars */
+typedef struct tdls_iovar {
+	struct ether_addr ea;		/* Station address */
+	uint8 mode;			/* mode: depends on iovar */
+	chanspec_t chanspec;
+	uint32 pad;			/* future */
+} tdls_iovar_t;
+
+#define TDLS_WFD_IE_SIZE		512
+/* structure for tdls wfd ie */
+typedef struct tdls_wfd_ie_iovar {
+	struct ether_addr ea;		/* Station address */
+	uint8 mode;
+	uint16 length;
+	uint8 data[TDLS_WFD_IE_SIZE];
+} tdls_wfd_ie_iovar_t;
+#endif /* WLTDLS */
+
+/* structure for addts/delts arguments */
+typedef struct tspec_arg {
+	uint16 version;			/* see definition of TSPEC_ARG_VERSION */
+	uint16 length;			/* length of entire structure */
+	uint flag;			/* bit field */
+	/* TSPEC Arguments */
+	struct tsinfo_arg tsinfo;	/* TS Info bit field */
+	uint16 nom_msdu_size;		/* (Nominal or fixed) MSDU Size (bytes) */
+	uint16 max_msdu_size;		/* Maximum MSDU Size (bytes) */
+	uint min_srv_interval;		/* Minimum Service Interval (us) */
+	uint max_srv_interval;		/* Maximum Service Interval (us) */
+	uint inactivity_interval;	/* Inactivity Interval (us) */
+	uint suspension_interval;	/* Suspension Interval (us) */
+	uint srv_start_time;		/* Service Start Time (us) */
+	uint min_data_rate;		/* Minimum Data Rate (bps) */
+	uint mean_data_rate;		/* Mean Data Rate (bps) */
+	uint peak_data_rate;		/* Peak Data Rate (bps) */
+	uint max_burst_size;		/* Maximum Burst Size (bytes) */
+	uint delay_bound;		/* Delay Bound (us) */
+	uint min_phy_rate;		/* Minimum PHY Rate (bps) */
+	uint16 surplus_bw;		/* Surplus Bandwidth Allowance (range 1.0 to 8.0) */
+	uint16 medium_time;		/* Medium Time (32 us/s periods) */
+	uint8 dialog_token;		/* dialog token */
+} tspec_arg_t;
+
+/* tspec arg for desired station */
+typedef	struct tspec_per_sta_arg {
+	struct ether_addr ea;
+	struct tspec_arg ts;
+} tspec_per_sta_arg_t;
+
+/* structure for max bandwidth for each access category */
+typedef	struct wme_max_bandwidth {
+	uint32	ac[AC_COUNT];	/* max bandwidth for each access category */
+} wme_max_bandwidth_t;
+
+#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t))
+
+/* current version of wl_tspec_arg_t struct */
+#define	TSPEC_ARG_VERSION		2	/* current version of wl_tspec_arg_t struct */
+#define TSPEC_ARG_LENGTH		55	/* argument length from tsinfo to medium_time */
+#define TSPEC_DEFAULT_DIALOG_TOKEN	42	/* default dialog token */
+#define TSPEC_DEFAULT_SBW_FACTOR	0x3000	/* default surplus bw */
+
+
+#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE  80
+#define WLC_WOWL_MAX_KEEPALIVE	2
+
+/* Packet lifetime configuration per ac */
+typedef struct wl_lifetime {
+	uint32 ac;	        /* access class */
+	uint32 lifetime;    /* Packet lifetime value in ms */
+} wl_lifetime_t;
+
+/* Channel Switch Announcement param */
+typedef struct wl_chan_switch {
+	uint8 mode;		/* value 0 or 1 */
+	uint8 count;		/* count # of beacons before switching */
+	chanspec_t chspec;	/* chanspec */
+	uint8 reg;		/* regulatory class */
+	uint8 frame_type;		/* csa frame type, unicast or broadcast */
+} wl_chan_switch_t;
+
+enum {
+	PFN_LIST_ORDER,
+	PFN_RSSI
+};
+
+enum {
+	DISABLE,
+	ENABLE
+};
+
+enum {
+	OFF_ADAPT,
+	SMART_ADAPT,
+	STRICT_ADAPT,
+	SLOW_ADAPT
+};
+
+#define SORT_CRITERIA_BIT		0
+#define AUTO_NET_SWITCH_BIT		1
+#define ENABLE_BKGRD_SCAN_BIT		2
+#define IMMEDIATE_SCAN_BIT		3
+#define	AUTO_CONNECT_BIT		4
+#define	ENABLE_BD_SCAN_BIT		5
+#define ENABLE_ADAPTSCAN_BIT		6
+#define IMMEDIATE_EVENT_BIT		8
+#define SUPPRESS_SSID_BIT		9
+#define ENABLE_NET_OFFLOAD_BIT		10
+/* report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_BIT		11
+
+#define SORT_CRITERIA_MASK	0x0001
+#define AUTO_NET_SWITCH_MASK	0x0002
+#define ENABLE_BKGRD_SCAN_MASK	0x0004
+#define IMMEDIATE_SCAN_MASK	0x0008
+#define AUTO_CONNECT_MASK	0x0010
+
+#define ENABLE_BD_SCAN_MASK	0x0020
+#define ENABLE_ADAPTSCAN_MASK	0x00c0
+#define IMMEDIATE_EVENT_MASK	0x0100
+#define SUPPRESS_SSID_MASK	0x0200
+#define ENABLE_NET_OFFLOAD_MASK	0x0400
+/* report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_MASK	0x0800
+
+#define PFN_VERSION			2
+#define PFN_SCANRESULT_VERSION		1
+#define MAX_PFN_LIST_COUNT		16
+
+#define PFN_COMPLETE			1
+#define PFN_INCOMPLETE			0
+
+#define DEFAULT_BESTN			2
+#define DEFAULT_MSCAN			0
+#define DEFAULT_REPEAT			10
+#define DEFAULT_EXP			2
+
+#define PFN_PARTIAL_SCAN_BIT		0
+#define PFN_PARTIAL_SCAN_MASK		1
+
+/* PFN network info structure */
+typedef struct wl_pfn_subnet_info {
+	struct ether_addr BSSID;
+	uint8	channel; /* channel number only */
+	uint8	SSID_len;
+	uint8	SSID[32];
+} wl_pfn_subnet_info_t;
+
+typedef struct wl_pfn_net_info {
+	wl_pfn_subnet_info_t pfnsubnet;
+	int16	RSSI; /* receive signal strength (in dBm) */
+	uint16	timestamp; /* age in seconds */
+} wl_pfn_net_info_t;
+
+typedef struct wl_pfn_lnet_info {
+	wl_pfn_subnet_info_t pfnsubnet; /* BSSID + channel + SSID len + SSID */
+	uint16	flags; /* partial scan, etc */
+	int16	RSSI; /* receive signal strength (in dBm) */
+	uint32	timestamp; /* age in miliseconds */
+	uint16	rtt0; /* estimated distance to this AP in centimeters */
+	uint16	rtt1; /* standard deviation of the distance to this AP in centimeters */
+} wl_pfn_lnet_info_t;
+
+typedef struct wl_pfn_lscanresults {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	wl_pfn_lnet_info_t netinfo[1];
+} wl_pfn_lscanresults_t;
+
+typedef struct wl_pfn_scanresults {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	wl_pfn_net_info_t netinfo[1];
+} wl_pfn_scanresults_t;
+
+/* PFN data structure */
+typedef struct wl_pfn_param {
+	int32 version;			/* PNO parameters version */
+	int32 scan_freq;		/* Scan frequency */
+	int32 lost_network_timeout;	/* Timeout in sec. to declare
+								* discovered network as lost
+								*/
+	int16 flags;			/* Bit field to control features
+							* of PFN such as sort criteria auto
+							* enable switch and background scan
+							*/
+	int16 rssi_margin;		/* Margin to avoid jitter for choosing a
+							* PFN based on RSSI sort criteria
+							*/
+	uint8 bestn; /* number of best networks in each scan */
+	uint8 mscan; /* number of scans recorded */
+	uint8 repeat; /* Minimum number of scan intervals
+				     *before scan frequency changes in adaptive scan
+				     */
+	uint8 exp; /* Exponent of 2 for maximum scan interval */
+	int32 slow_freq; /* slow scan period */
+} wl_pfn_param_t;
+
+typedef struct wl_pfn_bssid {
+	struct ether_addr  macaddr;
+	/* Bit4: suppress_lost, Bit3: suppress_found */
+	uint16             flags;
+} wl_pfn_bssid_t;
+#define WL_PFN_SUPPRESSFOUND_MASK	0x08
+#define WL_PFN_SUPPRESSLOST_MASK	0x10
+#define WL_PFN_RSSI_MASK		0xff00
+#define WL_PFN_RSSI_SHIFT		8
+
+typedef struct wl_pfn_cfg {
+	uint32	reporttype;
+	int32	channel_num;
+	uint16	channel_list[WL_NUMCHANNELS];
+	uint32	flags;
+} wl_pfn_cfg_t;
+#define WL_PFN_REPORT_ALLNET    0
+#define WL_PFN_REPORT_SSIDNET   1
+#define WL_PFN_REPORT_BSSIDNET  2
+
+#define WL_PFN_CFG_FLAGS_PROHIBITED	0x00000001	/* Accept and use prohibited channels */
+#define WL_PFN_CFG_FLAGS_RESERVED	0xfffffffe	/* Remaining reserved for future use */
+
+typedef struct wl_pfn {
+	wlc_ssid_t		ssid;			/* ssid name and its length */
+	int32			flags;			/* bit2: hidden */
+	int32			infra;			/* BSS Vs IBSS */
+	int32			auth;			/* Open Vs Closed */
+	int32			wpa_auth;		/* WPA type */
+	int32			wsec;			/* wsec value */
+} wl_pfn_t;
+
+typedef struct wl_pfn_list {
+	uint32		version;
+	uint32		enabled;
+	uint32		count;
+	wl_pfn_t	pfn[1];
+} wl_pfn_list_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct pfn_olmsg_params_t {
+	wlc_ssid_t ssid;
+	uint32	cipher_type;
+	uint32	auth_type;
+	uint8	channels[4];
+} BWL_POST_PACKED_STRUCT pfn_olmsg_params;
+
+#define WL_PFN_HIDDEN_BIT		2
+#define WL_PFN_HIDDEN_MASK		0x4
+
+#ifndef BESTN_MAX
+#define BESTN_MAX			3
+#endif
+
+#ifndef MSCAN_MAX
+#define MSCAN_MAX			90
+#endif
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* Service discovery */
+typedef struct {
+	uint8	transaction_id;	/* Transaction id */
+	uint8	protocol;	/* Service protocol type */
+	uint16	query_len;	/* Length of query */
+	uint16	response_len;	/* Length of response */
+	uint8	qrbuf[1];
+} wl_p2po_qr_t;
+
+typedef struct {
+	uint16			period;			/* extended listen period */
+	uint16			interval;		/* extended listen interval */
+} wl_p2po_listen_t;
+
+/* ANQP offload */
+
+#define ANQPO_MAX_QUERY_SIZE		256
+typedef struct {
+	uint16 max_retransmit;		/* ~0 use default, max retransmit on no ACK from peer */
+	uint16 response_timeout;	/* ~0 use default, msec to wait for resp after tx packet */
+	uint16 max_comeback_delay;	/* ~0 use default, max comeback delay in resp else fail */
+	uint16 max_retries;			/* ~0 use default, max retries on failure */
+	uint16 query_len;			/* length of ANQP query */
+	uint8 query_data[1];		/* ANQP encoded query (max ANQPO_MAX_QUERY_SIZE) */
+} wl_anqpo_set_t;
+
+typedef struct {
+	uint16 channel;				/* channel of the peer */
+	struct ether_addr addr;		/* addr of the peer */
+} wl_anqpo_peer_t;
+
+#define ANQPO_MAX_PEER_LIST			64
+typedef struct {
+	uint16 count;				/* number of peers in list */
+	wl_anqpo_peer_t peer[1];	/* max ANQPO_MAX_PEER_LIST */
+} wl_anqpo_peer_list_t;
+
+#define ANQPO_MAX_IGNORE_SSID		64
+typedef struct {
+	bool is_clear;				/* set to clear list (not used on GET) */
+	uint16 count;				/* number of SSID in list */
+	wlc_ssid_t ssid[1];			/* max ANQPO_MAX_IGNORE_SSID */
+} wl_anqpo_ignore_ssid_list_t;
+
+#define ANQPO_MAX_IGNORE_BSSID		64
+typedef struct {
+	bool is_clear;				/* set to clear list (not used on GET) */
+	uint16 count;				/* number of addr in list */
+	struct ether_addr bssid[1];	/* max ANQPO_MAX_IGNORE_BSSID */
+} wl_anqpo_ignore_bssid_list_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+struct toe_ol_stats_t {
+	/* Num of tx packets that don't need to be checksummed */
+	uint32 tx_summed;
+
+	/* Num of tx packets where checksum is filled by offload engine */
+	uint32 tx_iph_fill;
+	uint32 tx_tcp_fill;
+	uint32 tx_udp_fill;
+	uint32 tx_icmp_fill;
+
+	/*  Num of rx packets where toe finds out if checksum is good or bad */
+	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;
+
+	/* Num of tx packets in which csum error is injected */
+	uint32 tx_tcp_errinj;
+	uint32 tx_udp_errinj;
+	uint32 tx_icmp_errinj;
+
+	/* Num of rx packets in which csum error is injected */
+	uint32 rx_tcp_errinj;
+	uint32 rx_udp_errinj;
+	uint32 rx_icmp_errinj;
+};
+
+/* Arp offload statistic counts */
+struct arp_ol_stats_t {
+	uint32  host_ip_entries;	/* Host IP table addresses (more than one if multihomed) */
+	uint32  host_ip_overflow;	/* Host IP table additions skipped due to overflow */
+
+	uint32  arp_table_entries;	/* ARP table entries */
+	uint32  arp_table_overflow;	/* ARP table additions skipped due to overflow */
+
+	uint32  host_request;		/* ARP requests from host */
+	uint32  host_reply;		/* ARP replies from host */
+	uint32  host_service;		/* ARP requests from host serviced by ARP Agent */
+
+	uint32  peer_request;		/* ARP requests received from network */
+	uint32  peer_request_drop;	/* ARP requests from network that were dropped */
+	uint32  peer_reply;		/* ARP replies received from network */
+	uint32  peer_reply_drop;	/* ARP replies from network that were dropped */
+	uint32  peer_service;		/* ARP request from host serviced by ARP Agent */
+};
+
+/* NS offload statistic counts */
+struct nd_ol_stats_t {
+	uint32  host_ip_entries;    /* Host IP table addresses (more than one if multihomed) */
+	uint32  host_ip_overflow;   /* Host IP table additions skipped due to overflow */
+	uint32  peer_request;       /* NS requests received from network */
+	uint32  peer_request_drop;  /* NS requests from network that were dropped */
+	uint32  peer_reply_drop;    /* NA replies from network that were dropped */
+	uint32  peer_service;       /* NS request from host serviced by firmware */
+};
+
+/*
+ * Keep-alive packet offloading.
+ */
+
+/* NAT keep-alive packets format: specifies the re-transmission period, the packet
+ * length, and packet contents.
+ */
+typedef struct wl_keep_alive_pkt {
+	uint32	period_msec;	/* Retransmission period (0 to disable packet re-transmits) */
+	uint16	len_bytes;	/* Size of packet to transmit (0 to disable packet re-transmits) */
+	uint8	data[1];	/* Variable length packet to transmit.  Contents should include
+				 * entire ethernet packet (enet header, IP header, UDP header,
+				 * and UDP payload) in network byte order.
+				 */
+} wl_keep_alive_pkt_t;
+
+#define WL_KEEP_ALIVE_FIXED_LEN		OFFSETOF(wl_keep_alive_pkt_t, data)
+
+
+/*
+ * Dongle pattern matching filter.
+ */
+
+#define MAX_WAKE_PACKET_CACHE_BYTES 128 /* Maximum cached wake packet */
+
+#define MAX_WAKE_PACKET_BYTES	    (DOT11_A3_HDR_LEN +			    \
+				     DOT11_QOS_LEN +			    \
+				     sizeof(struct dot11_llc_snap_header) + \
+				     ETHER_MAX_DATA)
+
+typedef struct pm_wake_packet {
+	uint32	status;		/* Is the wake reason a packet (if all the other field's valid) */
+	uint32	pattern_id;	/* Pattern ID that matched */
+	uint32	original_packet_size;
+	uint32	saved_packet_size;
+	uchar	packet[MAX_WAKE_PACKET_CACHE_BYTES];
+} pm_wake_packet_t;
+
+/* Packet filter types. Currently, only pattern matching is supported. */
+typedef enum wl_pkt_filter_type {
+	WL_PKT_FILTER_TYPE_PATTERN_MATCH=0,	/* Pattern matching filter */
+	WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH=1, /* Magic packet match */
+	WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH=2,	/* A pattern list (match all to match filter) */
+	WL_PKT_FILTER_TYPE_ENCRYPTED_PATTERN_MATCH=3, /* SECURE WOWL magic / net pattern match */
+	WL_PKT_FILTER_TYPE_APF_MATCH=4, /* Android packet filter match */
+	WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT=5, /* Pattern matching filter with timeout event */
+} wl_pkt_filter_type_t;
+
+#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t
+
+/* String mapping for types that may be used by applications or debug */
+#define WL_PKT_FILTER_TYPE_NAMES \
+	{ "PATTERN", WL_PKT_FILTER_TYPE_PATTERN_MATCH },       \
+	{ "MAGIC",   WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH }, \
+	{ "PATLIST", WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH }, \
+	{ "SECURE WOWL", WL_PKT_FILTER_TYPE_ENCRYPTED_PATTERN_MATCH }, \
+	{ "APF", WL_PKT_FILTER_TYPE_APF_MATCH }, \
+	{ "PATTERN TIMEOUT", WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT }
+
+/* Pattern matching filter. Specifies an offset within received packets to
+ * start matching, the pattern to match, the size of the pattern, and a bitmask
+ * that indicates which bits within the pattern should be matched.
+ */
+typedef struct wl_pkt_filter_pattern {
+	uint32	offset;		/* Offset within received packet to start pattern matching.
+				 * Offset '0' is the first byte of the ethernet header.
+				 */
+	uint32	size_bytes;	/* Size of the pattern.  Bitmask must be the same size. */
+	uint8   mask_and_pattern[1]; /* Variable length mask and pattern data.  mask starts
+				      * at offset 0.  Pattern immediately follows mask.
+				      */
+} wl_pkt_filter_pattern_t;
+
+/* A pattern list is a numerically specified list of modified pattern structures. */
+typedef struct wl_pkt_filter_pattern_listel {
+	uint16 rel_offs;	/* Offset to begin match (relative to 'base' below) */
+	uint16 base_offs;	/* Base for offset (defined below) */
+	uint16 size_bytes;	/* Size of mask/pattern */
+	uint16 match_flags;	/* Addition flags controlling the match */
+	uint8  mask_and_data[1]; /* Variable length mask followed by data, each size_bytes */
+} wl_pkt_filter_pattern_listel_t;
+
+typedef struct wl_pkt_filter_pattern_list {
+	uint8 list_cnt;		/* Number of elements in the list */
+	uint8 PAD1[1];		/* Reserved (possible version: reserved) */
+	uint16 totsize;		/* Total size of this pattern list (includes this struct) */
+	wl_pkt_filter_pattern_listel_t patterns[1]; /* Variable number of list elements */
+} wl_pkt_filter_pattern_list_t;
+
+typedef struct wl_pkt_filter_pattern_timeout {
+	uint32	offset;	/* Offset within received packet to start pattern matching.
+					 * Offset '0' is the first byte of the ethernet header.
+					 */
+	uint32	size_bytes;	/* Size of the pattern. Bitmask must be the same size. */
+	uint32	timeout;	/* Timeout(seconds) */
+	uint8	mask_and_pattern[1]; /* Variable length mask and pattern data.
+								 * mask starts at offset 0. Pattern
+								 * immediately follows mask.
+								*/
+} wl_pkt_filter_pattern_timeout_t;
+
+/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
+typedef struct wl_pkt_filter {
+	uint32	id;		/* Unique filter id, specified by app. */
+	uint32	type;		/* Filter type (WL_PKT_FILTER_TYPE_xxx). */
+	uint32	negate_match;	/* Negate the result of filter matches */
+	union {			/* Filter definitions */
+		wl_pkt_filter_pattern_t pattern;	/* Pattern matching filter */
+		wl_pkt_filter_pattern_list_t patlist; /* List of patterns to match */
+		wl_pkt_filter_pattern_timeout_t pattern_timeout; /* Pattern timeout event filter */
+	} u;
+} wl_pkt_filter_t;
+
+/* IOVAR "tcp_keep_set" parameter. Used to install tcp keep_alive stuff. */
+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)
+#define WL_PKT_FILTER_PATTERN_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_list_t, patterns)
+#define WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN	\
+			OFFSETOF(wl_pkt_filter_pattern_listel_t, mask_and_data)
+#define WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN	\
+			OFFSETOF(wl_pkt_filter_pattern_timeout_t, mask_and_pattern)
+
+/* IOVAR "pkt_filter_enable" parameter. */
+typedef struct wl_pkt_filter_enable {
+	uint32	id;		/* Unique filter id */
+	uint32	enable;		/* Enable/disable bool */
+} wl_pkt_filter_enable_t;
+
+/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */
+typedef struct wl_pkt_filter_list {
+	uint32	num;		/* Number of installed packet filters */
+	wl_pkt_filter_t	filter[1];	/* Variable array of packet filters. */
+} wl_pkt_filter_list_t;
+
+#define WL_PKT_FILTER_LIST_FIXED_LEN	  OFFSETOF(wl_pkt_filter_list_t, filter)
+
+/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */
+typedef struct wl_pkt_filter_stats {
+	uint32	num_pkts_matched;	/* # filter matches for specified filter id */
+	uint32	num_pkts_forwarded;	/* # packets fwded from dongle to host for all filters */
+	uint32	num_pkts_discarded;	/* # packets discarded by dongle for all filters */
+} wl_pkt_filter_stats_t;
+
+/* IOVAR "pkt_filter_ports" parameter.  Configure TCP/UDP port filters. */
+typedef struct wl_pkt_filter_ports {
+	uint8 version;		/* Be proper */
+	uint8 reserved;		/* Be really proper */
+	uint16 count;		/* Number of ports following */
+	/* End of fixed data */
+	uint16 ports[1];	/* Placeholder for ports[<count>] */
+} wl_pkt_filter_ports_t;
+
+#define WL_PKT_FILTER_PORTS_FIXED_LEN	OFFSETOF(wl_pkt_filter_ports_t, ports)
+
+#define WL_PKT_FILTER_PORTS_VERSION	0
+#define WL_PKT_FILTER_PORTS_MAX		128
+
+#define RSN_KCK_LENGTH 16
+#define RSN_KEK_LENGTH 16
+#define RSN_REPLAY_LEN 8
+typedef struct _gtkrefresh {
+	uchar	KCK[RSN_KCK_LENGTH];
+	uchar	KEK[RSN_KEK_LENGTH];
+	uchar	ReplayCounter[RSN_REPLAY_LEN];
+} gtk_keyinfo_t, *pgtk_keyinfo_t;
+
+/* Sequential Commands ioctl */
+typedef struct wl_seq_cmd_ioctl {
+	uint32 cmd;		/* common ioctl definition */
+	uint32 len;		/* length of user buffer */
+} wl_seq_cmd_ioctl_t;
+
+#define WL_SEQ_CMD_ALIGN_BYTES	4
+
+/* These are the set of get IOCTLs that should be allowed when using
+ * IOCTL sequence commands. These are issued implicitly by wl.exe each time
+ * it is invoked. We never want to buffer these, or else wl.exe will stop working.
+ */
+#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \
+	(((cmd) == WLC_GET_MAGIC)		|| \
+	 ((cmd) == WLC_GET_VERSION)		|| \
+	 ((cmd) == WLC_GET_AP)			|| \
+	 ((cmd) == WLC_GET_INSTANCE))
+
+typedef struct wl_pkteng {
+	uint32 flags;
+	uint32 delay;			/* Inter-packet delay */
+	uint32 nframes;			/* Number of frames */
+	uint32 length;			/* Packet length */
+	uint8  seqno;			/* Enable/disable sequence no. */
+	struct ether_addr dest;		/* Destination address */
+	struct ether_addr src;		/* Source address */
+} wl_pkteng_t;
+
+typedef struct wl_pkteng_stats {
+	uint32 lostfrmcnt;		/* RX PER test: no of frames lost (skip seqno) */
+	int32 rssi;			/* RSSI */
+	int32 snr;			/* signal to noise ratio */
+	uint16 rxpktcnt[NUM_80211_RATES+1];
+	uint8 rssi_qdb;			/* qdB portion of the computed rssi */
+} wl_pkteng_stats_t;
+
+
+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;		/* Size of the mask in #of bytes */
+	uint32		    offset;		/* Pattern byte offset in packet */
+	uint32		    patternoffset;	/* Offset of start of pattern in the structure */
+	uint32		    patternsize;	/* Size of the pattern itself in #of bytes */
+	uint32		    id;			/* id */
+	uint32		    reasonsize;		/* Size of the wakeup reason code */
+	wowl_pattern_type_t type;		/* Type of pattern */
+	/* Mask follows the structure above */
+	/* Pattern follows the mask is at 'patternoffset' from the start */
+} 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;	/* Whether PCI PMECSR PMEStatus bit was set */
+	uint32	ucode_wakeind;	/* What wakeup-event indication was set by ucode */
+} wl_wowl_wakeind_t;
+
+typedef struct {
+	uint32		pktlen;		    /* size of packet */
+	void		*sdu;
+} tcp_keepalive_wake_pkt_infop_t;
+
+/* per AC rate control related data structure */
+typedef struct wl_txrate_class {
+	uint8		init_rate;
+	uint8		min_rate;
+	uint8		max_rate;
+} wl_txrate_class_t;
+
+/* structure for Overlap BSS scan arguments */
+typedef struct wl_obss_scan_arg {
+	int16	passive_dwell;
+	int16	active_dwell;
+	int16	bss_widthscan_interval;
+	int16	passive_total;
+	int16	active_total;
+	int16	chanwidth_transition_delay;
+	int16	activity_threshold;
+} wl_obss_scan_arg_t;
+
+#define WL_OBSS_SCAN_PARAM_LEN	sizeof(wl_obss_scan_arg_t)
+
+/* RSSI event notification configuration. */
+typedef struct wl_rssi_event {
+	uint32 rate_limit_msec;		/* # of events posted to application will be limited to
+					 * one per specified period (0 to disable rate limit).
+					 */
+	uint8 num_rssi_levels;		/* Number of entries in rssi_levels[] below */
+	int8 rssi_levels[MAX_RSSI_LEVELS];	/* Variable number of RSSI levels. An event
+						 * will be posted each time the RSSI of received
+						 * beacons/packets crosses a level.
+						 */
+} wl_rssi_event_t;
+
+typedef struct wl_action_obss_coex_req {
+	uint8 info;
+	uint8 num;
+	uint8 ch_list[1];
+} wl_action_obss_coex_req_t;
+
+
+/* IOVar parameter block for small MAC address array with type indicator */
+#define WL_IOV_MAC_PARAM_LEN  4
+
+#define WL_IOV_PKTQ_LOG_PRECS 16
+
+typedef struct {
+	uint32 num_addrs;
+	char   addr_type[WL_IOV_MAC_PARAM_LEN];
+	struct ether_addr ea[WL_IOV_MAC_PARAM_LEN];
+} wl_iov_mac_params_t;
+
+/* This is extra info that follows wl_iov_mac_params_t */
+typedef struct {
+	uint32 addr_info[WL_IOV_MAC_PARAM_LEN];
+} wl_iov_mac_extra_params_t;
+
+/* Combined structure */
+typedef struct {
+	wl_iov_mac_params_t params;
+	wl_iov_mac_extra_params_t extra_params;
+} wl_iov_mac_full_params_t;
+
+/* Parameter block for PKTQ_LOG statistics */
+#define PKTQ_LOG_COUNTERS_V4 \
+	/* packets requested to be stored */ \
+	uint32 requested; \
+	/* packets stored */ \
+	uint32 stored; \
+	/* packets saved, because a lowest priority queue has given away one packet */ \
+	uint32 saved; \
+	/* packets saved, because an older packet from the same queue has been dropped */ \
+	uint32 selfsaved; \
+	/* packets dropped, because pktq is full with higher precedence packets */ \
+	uint32 full_dropped; \
+	 /* packets dropped because pktq per that precedence is full */ \
+	uint32 dropped; \
+	/* packets dropped, in order to save one from a queue of a highest priority */ \
+	uint32 sacrificed; \
+	/* packets droped because of hardware/transmission error */ \
+	uint32 busy; \
+	/* packets re-sent because they were not received */ \
+	uint32 retry; \
+	/* packets retried again (ps pretend) prior to moving power save mode */ \
+	uint32 ps_retry; \
+	 /* suppressed packet count */ \
+	uint32 suppress; \
+	/* packets finally dropped after retry limit */ \
+	uint32 retry_drop; \
+	/* the high-water mark of the queue capacity for packets - goes to zero as queue fills */ \
+	uint32 max_avail; \
+	/* the high-water mark of the queue utilisation for packets - ('inverse' of max_avail) */ \
+	uint32 max_used; \
+	 /* the maximum capacity of the queue */ \
+	uint32 queue_capacity; \
+	/* count of rts attempts that failed to receive cts */ \
+	uint32 rtsfail; \
+	/* count of packets sent (acked) successfully */ \
+	uint32 acked; \
+	/* running total of phy rate of packets sent successfully */ \
+	uint32 txrate_succ; \
+	/* running total of phy 'main' rate */ \
+	uint32 txrate_main; \
+	/* actual data transferred successfully */ \
+	uint32 throughput; \
+	/* time difference since last pktq_stats */ \
+	uint32 time_delta;
+
+typedef struct {
+	PKTQ_LOG_COUNTERS_V4
+} pktq_log_counters_v04_t;
+
+/* v5 is the same as V4 with extra parameter */
+typedef struct {
+	PKTQ_LOG_COUNTERS_V4
+	/* cumulative time to transmit */
+	uint32 airtime;
+} pktq_log_counters_v05_t;
+
+typedef struct {
+	uint8                num_prec[WL_IOV_MAC_PARAM_LEN];
+	pktq_log_counters_v04_t  counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
+	uint32               counter_info[WL_IOV_MAC_PARAM_LEN];
+	uint32               pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
+	char                 headings[1];
+} pktq_log_format_v04_t;
+
+typedef struct {
+	uint8                num_prec[WL_IOV_MAC_PARAM_LEN];
+	pktq_log_counters_v05_t  counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
+	uint32               counter_info[WL_IOV_MAC_PARAM_LEN];
+	uint32               pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
+	char                 headings[1];
+} pktq_log_format_v05_t;
+
+
+typedef struct {
+	uint32               version;
+	wl_iov_mac_params_t  params;
+	union {
+		pktq_log_format_v04_t v04;
+		pktq_log_format_v05_t v05;
+	} pktq_log;
+} wl_iov_pktq_log_t;
+
+/* PKTQ_LOG_AUTO, PKTQ_LOG_DEF_PREC flags introduced in v05, they are ignored by v04 */
+#define PKTQ_LOG_AUTO     (1 << 31)
+#define PKTQ_LOG_DEF_PREC (1 << 30)
+
+/*
+ * SCB_BS_DATA iovar definitions start.
+ */
+#define SCB_BS_DATA_STRUCT_VERSION	1
+
+/* The actual counters maintained for each station */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	/* The following counters are a subset of what pktq_stats provides per precedence. */
+	uint32 retry;          /* packets re-sent because they were not received */
+	uint32 retry_drop;     /* packets finally dropped after retry limit */
+	uint32 rtsfail;        /* count of rts attempts that failed to receive cts */
+	uint32 acked;          /* count of packets sent (acked) successfully */
+	uint32 txrate_succ;    /* running total of phy rate of packets sent successfully */
+	uint32 txrate_main;    /* running total of phy 'main' rate */
+	uint32 throughput;     /* actual data transferred successfully */
+	uint32 time_delta;     /* time difference since last pktq_stats */
+	uint32 airtime;        /* cumulative total medium access delay in useconds */
+} BWL_POST_PACKED_STRUCT iov_bs_data_counters_t;
+
+/* The structure for individual station information. */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	struct ether_addr	station_address;	/* The station MAC address */
+	uint16			station_flags;		/* Bit mask of flags, for future use. */
+	iov_bs_data_counters_t	station_counters;	/* The actual counter values */
+} BWL_POST_PACKED_STRUCT iov_bs_data_record_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16	structure_version;	/* Structure version number (for wl/wlu matching) */
+	uint16	structure_count;	/* Number of iov_bs_data_record_t records following */
+	iov_bs_data_record_t	structure_record[1];	/* 0 - structure_count records */
+} BWL_POST_PACKED_STRUCT iov_bs_data_struct_t;
+
+/* Bitmask of options that can be passed in to the iovar. */
+enum {
+	SCB_BS_DATA_FLAG_NO_RESET = (1<<0)	/* Do not clear the counters after reading */
+};
+/*
+ * SCB_BS_DATA iovar definitions end.
+ */
+
+typedef struct wlc_extlog_cfg {
+	int max_number;
+	uint16 module;	/* bitmap */
+	uint8 level;
+	uint8 flag;
+	uint16 version;
+} wlc_extlog_cfg_t;
+
+typedef struct log_record {
+	uint32 time;
+	uint16 module;
+	uint16 id;
+	uint8 level;
+	uint8 sub_unit;
+	uint8 seq_num;
+	int32 arg;
+	char str[MAX_ARGSTR_LEN];
+} log_record_t;
+
+typedef struct wlc_extlog_req {
+	uint32 from_last;
+	uint32 num;
+} wlc_extlog_req_t;
+
+typedef struct wlc_extlog_results {
+	uint16 version;
+	uint16 record_len;
+	uint32 num;
+	log_record_t logs[1];
+} wlc_extlog_results_t;
+
+typedef struct log_idstr {
+	uint16	id;
+	uint16	flag;
+	uint8	arg_type;
+	const char	*fmt_str;
+} log_idstr_t;
+
+#define FMTSTRF_USER		1
+
+/* flat ID definitions
+ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will
+ * affect backward compatibility with pre-existing apps
+ */
+typedef enum {
+	FMTSTR_DRIVER_UP_ID = 0,
+	FMTSTR_DRIVER_DOWN_ID = 1,
+	FMTSTR_SUSPEND_MAC_FAIL_ID = 2,
+	FMTSTR_NO_PROGRESS_ID = 3,
+	FMTSTR_RFDISABLE_ID = 4,
+	FMTSTR_REG_PRINT_ID = 5,
+	FMTSTR_EXPTIME_ID = 6,
+	FMTSTR_JOIN_START_ID = 7,
+	FMTSTR_JOIN_COMPLETE_ID = 8,
+	FMTSTR_NO_NETWORKS_ID = 9,
+	FMTSTR_SECURITY_MISMATCH_ID = 10,
+	FMTSTR_RATE_MISMATCH_ID = 11,
+	FMTSTR_AP_PRUNED_ID = 12,
+	FMTSTR_KEY_INSERTED_ID = 13,
+	FMTSTR_DEAUTH_ID = 14,
+	FMTSTR_DISASSOC_ID = 15,
+	FMTSTR_LINK_UP_ID = 16,
+	FMTSTR_LINK_DOWN_ID = 17,
+	FMTSTR_RADIO_HW_OFF_ID = 18,
+	FMTSTR_RADIO_HW_ON_ID = 19,
+	FMTSTR_EVENT_DESC_ID = 20,
+	FMTSTR_PNP_SET_POWER_ID = 21,
+	FMTSTR_RADIO_SW_OFF_ID = 22,
+	FMTSTR_RADIO_SW_ON_ID = 23,
+	FMTSTR_PWD_MISMATCH_ID = 24,
+	FMTSTR_FATAL_ERROR_ID = 25,
+	FMTSTR_AUTH_FAIL_ID = 26,
+	FMTSTR_ASSOC_FAIL_ID = 27,
+	FMTSTR_IBSS_FAIL_ID = 28,
+	FMTSTR_EXTAP_FAIL_ID = 29,
+	FMTSTR_MAX_ID
+} log_fmtstr_id_t;
+
+#ifdef DONGLEOVERLAYS
+typedef struct {
+	uint32 flags_idx;	/* lower 8 bits: overlay index; upper 24 bits: flags */
+	uint32 offset;		/* offset into overlay region to write code */
+	uint32 len;			/* overlay code len */
+	/* overlay code follows this struct */
+} wl_ioctl_overlay_t;
+#endif /* DONGLEOVERLAYS */
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* 11k Neighbor Report element */
+typedef struct nbr_element {
+	uint8 id;
+	uint8 len;
+	struct ether_addr bssid;
+	uint32 bssid_info;
+	uint8 reg;
+	uint8 channel;
+	uint8 phytype;
+	uint8 pad;
+} nbr_element_t;
+
+/* no default structure packing */
+#include <packed_section_end.h>
+
+typedef struct keepalives_max_idle {
+	uint16  keepalive_count;        /* nmbr of keepalives per bss_max_idle period */
+	uint8   mkeepalive_index;       /* mkeepalive_index for keepalive frame to be used */
+	uint8   PAD;			/* to align next field */
+	uint16  max_interval;           /* seconds */
+} keepalives_max_idle_t;
+
+#define PM_IGNORE_BCMC_PROXY_ARP (1 << 0)
+#define PM_IGNORE_BCMC_ALL_DMS_ACCEPTED (1 << 1)
+
+/* require strict packing */
+#include <packed_section_start.h>
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+/* Structures and constants used for "vndr_ie" IOVar interface */
+#define VNDR_IE_CMD_LEN		4	/* length of the set command string:
+					 * "add", "del" (+ NUL)
+					 */
+
+#define VNDR_IE_INFO_HDR_LEN	(sizeof(uint32))
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 pktflag;			/* bitmask indicating which packet(s) contain this IE */
+	vndr_ie_t vndr_ie_data;		/* vendor IE data */
+} BWL_POST_PACKED_STRUCT vndr_ie_info_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	int iecount;			/* number of entries in the vndr_ie_list[] array */
+	vndr_ie_info_t vndr_ie_list[1];	/* variable size list of vndr_ie_info_t structs */
+} BWL_POST_PACKED_STRUCT vndr_ie_buf_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	char cmd[VNDR_IE_CMD_LEN];	/* vndr_ie IOVar set command : "add", "del" + NUL */
+	vndr_ie_buf_t vndr_ie_buffer;	/* buffer containing Vendor IE list information */
+} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t;
+
+/* tag_ID/length/value_buffer tuple */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8	id;
+	uint8	len;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT tlv_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 pktflag;			/* bitmask indicating which packet(s) contain this IE */
+	tlv_t ie_data;		/* IE data */
+} BWL_POST_PACKED_STRUCT ie_info_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	int iecount;			/* number of entries in the ie_list[] array */
+	ie_info_t ie_list[1];	/* variable size list of ie_info_t structs */
+} BWL_POST_PACKED_STRUCT ie_buf_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	char cmd[VNDR_IE_CMD_LEN];	/* ie IOVar set command : "add" + NUL */
+	ie_buf_t ie_buffer;	/* buffer containing IE list information */
+} BWL_POST_PACKED_STRUCT ie_setbuf_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 pktflag;		/* bitmask indicating which packet(s) contain this IE */
+	uint8 id;		/* IE type */
+} BWL_POST_PACKED_STRUCT ie_getbuf_t;
+
+/* structures used to define format of wps ie data from probe requests */
+/* passed up to applications via iovar "prbreq_wpsie" */
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr {
+	struct ether_addr staAddr;
+	uint16 ieLen;
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data {
+	sta_prbreq_wps_ie_hdr_t hdr;
+	uint8 ieData[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list {
+	uint32 totLen;
+	uint8 ieDataList[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t;
+
+
+#ifdef WLMEDIA_TXFAILEVENT
+typedef BWL_PRE_PACKED_STRUCT struct {
+	char   dest[ETHER_ADDR_LEN]; /* destination MAC */
+	uint8  prio;            /* Packet Priority */
+	uint8  flags;           /* Flags           */
+	uint32 tsf_l;           /* TSF timer low   */
+	uint32 tsf_h;           /* TSF timer high  */
+	uint16 rates;           /* Main Rates      */
+	uint16 txstatus;        /* TX Status       */
+} BWL_POST_PACKED_STRUCT txfailinfo_t;
+#endif /* WLMEDIA_TXFAILEVENT */
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 flags;
+	chanspec_t chanspec;			/* txpwr report for this channel */
+	chanspec_t local_chanspec;		/* channel on which we are associated */
+	uint8 local_max;			/* local max according to the AP */
+	uint8 local_constraint;			/* local constraint according to the AP */
+	int8  antgain[2];			/* Ant gain for each band - from SROM */
+	uint8 rf_cores;				/* count of RF Cores being reported */
+	uint8 est_Pout[4];			/* Latest tx power out estimate per RF chain */
+	uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */
+	uint8 est_Pout_cck;			/* Latest CCK tx power out estimate */
+	uint8 tx_power_max[4];		/* Maximum target power among all rates */
+	uint tx_power_max_rate_ind[4];		/* Index of the rate with the max target power */
+	int8 clm_limits[WL_NUMRATES];		/* regulatory limits - 20, 40 or 80MHz */
+	int8 clm_limits_subchan1[WL_NUMRATES];	/* regulatory limits - 20in40 or 40in80 */
+	int8 clm_limits_subchan2[WL_NUMRATES];	/* regulatory limits - 20in80MHz */
+	int8 sar;					/* SAR limit for display by wl executable */
+	int8 channel_bandwidth;		/* 20, 40 or 80 MHz bandwidth? */
+	uint8 version;				/* Version of the data format wlu <--> driver */
+	uint8 display_core;			/* Displayed curpower core */
+	int8 target_offsets[4];		/* Target power offsets for current rate per core */
+	uint32 last_tx_ratespec;	/* Ratespec for last transmition */
+	uint   user_target;		/* user limit */
+	uint32 board_limit_len;		/* length of board limit buffer */
+	uint32 target_len;		/* length of target power buffer */
+	int8 SARLIMIT[MAX_STREAMS_SUPPORTED];
+	uint8  pprdata[1];		/* ppr serialization buffer */
+} BWL_POST_PACKED_STRUCT tx_pwr_rpt_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	struct ipv4_addr	ipv4_addr;
+	struct ether_addr nexthop;
+} BWL_POST_PACKED_STRUCT ibss_route_entry_t;
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 num_entry;
+	ibss_route_entry_t route_entry[1];
+} BWL_POST_PACKED_STRUCT ibss_route_tbl_t;
+
+#define MAX_IBSS_ROUTE_TBL_ENTRY	64
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define TXPWR_TARGET_VERSION  0
+typedef BWL_PRE_PACKED_STRUCT struct {
+	int32 version;		/* version number */
+	chanspec_t chanspec;	/* txpwr report for this channel */
+	int8 txpwr[WL_STA_ANT_MAX]; /* Max tx target power, in qdb */
+	uint8 rf_cores;		/* count of RF Cores being reported */
+} BWL_POST_PACKED_STRUCT txpwr_target_max_t;
+
+#define BSS_PEER_INFO_PARAM_CUR_VER	0
+/* Input structure for IOV_BSS_PEER_INFO */
+typedef BWL_PRE_PACKED_STRUCT	struct {
+	uint16			version;
+	struct	ether_addr ea;	/* peer MAC address */
+} BWL_POST_PACKED_STRUCT bss_peer_info_param_t;
+
+#define BSS_PEER_INFO_CUR_VER		0
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16			version;
+	struct ether_addr	ea;
+	int32			rssi;
+	uint32			tx_rate;	/* current tx rate */
+	uint32			rx_rate;	/* current rx rate */
+	wl_rateset_t		rateset;	/* rateset in use */
+	uint32			age;		/* age in seconds */
+} BWL_POST_PACKED_STRUCT bss_peer_info_t;
+
+#define BSS_PEER_LIST_INFO_CUR_VER	0
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16			version;
+	uint16			bss_peer_info_len;	/* length of bss_peer_info_t */
+	uint32			count;			/* number of peer info */
+	bss_peer_info_t		peer_info[1];		/* peer info */
+} BWL_POST_PACKED_STRUCT bss_peer_list_info_t;
+
+#define BSS_PEER_LIST_INFO_FIXED_LEN OFFSETOF(bss_peer_list_info_t, peer_info)
+
+#define AIBSS_BCN_FORCE_CONFIG_VER_0	0
+
+/* structure used to configure AIBSS beacon force xmit */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16  version;
+	uint16	len;
+	uint32 initial_min_bcn_dur;	/* dur in ms to check a bcn in bcn_flood period */
+	uint32 min_bcn_dur;	/* dur in ms to check a bcn after bcn_flood period */
+	uint32 bcn_flood_dur; /* Initial bcn xmit period in ms */
+} BWL_POST_PACKED_STRUCT aibss_bcn_force_config_t;
+
+#define AIBSS_TXFAIL_CONFIG_VER_0    0
+
+/* structure used to configure aibss tx fail event */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16  version;
+	uint16  len;
+	uint32 bcn_timeout;     /* dur in seconds to receive 1 bcn */
+	uint32 max_tx_retry;     /* no of consecutive no acks to send txfail event */
+} BWL_POST_PACKED_STRUCT aibss_txfail_config_t;
+
+/* no strict structure packing */
+#include <packed_section_end.h>
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+	/* Global ASSERT Logging */
+#define ASSERTLOG_CUR_VER	0x0100
+#define MAX_ASSRTSTR_LEN	64
+
+	typedef struct assert_record {
+		uint32 time;
+		uint8 seq_num;
+		char str[MAX_ASSRTSTR_LEN];
+	} assert_record_t;
+
+	typedef struct assertlog_results {
+		uint16 version;
+		uint16 record_len;
+		uint32 num;
+		assert_record_t logs[1];
+	} assertlog_results_t;
+
+#define LOGRRC_FIX_LEN	8
+#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type))
+
+#ifdef BCMWAPI_WAI
+#define IV_LEN 16
+	struct wapi_sta_msg_t
+	{
+		uint16	msg_type;
+		uint16	datalen;
+		uint8	vap_mac[6];
+		uint8	reserve_data1[2];
+		uint8	sta_mac[6];
+		uint8	reserve_data2[2];
+		uint8	gsn[IV_LEN];
+		uint8	wie[256];
+	};
+#endif /* BCMWAPI_WAI */
+
+	/* chanim acs record */
+	typedef struct {
+		bool valid;
+		uint8 trigger;
+		chanspec_t selected_chspc;
+		int8 bgnoise;
+		uint32 glitch_cnt;
+		uint8 ccastats;
+		uint timestamp;
+	} chanim_acs_record_t;
+
+	typedef struct {
+		chanim_acs_record_t acs_record[CHANIM_ACS_RECORD];
+		uint8 count;
+		uint timestamp;
+	} wl_acs_record_t;
+
+	typedef struct chanim_stats {
+		uint32 glitchcnt;               /* normalized as per second count */
+		uint32 badplcp;                 /* normalized as per second count */
+		uint8 ccastats[CCASTATS_MAX];   /* normalized as 0-255 */
+		int8 bgnoise;			/* background noise level (in dBm) */
+		chanspec_t chanspec;
+		uint32 timestamp;
+		uint32 bphy_glitchcnt;          /* normalized as per second count */
+		uint32 bphy_badplcp;            /* normalized as per second count */
+		uint8 chan_idle;                /* normalized as 0~255 */
+	} chanim_stats_t;
+
+#define WL_CHANIM_STATS_VERSION 2
+
+typedef struct {
+	uint32 buflen;
+	uint32 version;
+	uint32 count;
+	chanim_stats_t stats[1];
+} wl_chanim_stats_t;
+
+#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats)
+
+/* Noise measurement metrics. */
+#define NOISE_MEASURE_KNOISE	0x1
+
+/* scb probe parameter */
+typedef struct {
+	uint32 scb_timeout;
+	uint32 scb_activity_time;
+	uint32 scb_max_probe;
+} wl_scb_probe_t;
+
+/* structure/defines for selective mgmt frame (smf) stats support */
+
+#define SMFS_VERSION 1
+/* selected mgmt frame (smf) stats element */
+typedef struct wl_smfs_elem {
+	uint32 count;
+	uint16 code;  /* SC or RC code */
+} wl_smfs_elem_t;
+
+typedef struct wl_smf_stats {
+	uint32 version;
+	uint16 length;	/* reserved for future usage */
+	uint8 type;
+	uint8 codetype;
+	uint32 ignored_cnt;
+	uint32 malformed_cnt;
+	uint32 count_total; /* count included the interested group */
+	wl_smfs_elem_t elem[1];
+} wl_smf_stats_t;
+
+#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem);
+
+enum {
+	SMFS_CODETYPE_SC,
+	SMFS_CODETYPE_RC
+};
+
+typedef enum smfs_type {
+	SMFS_TYPE_AUTH,
+	SMFS_TYPE_ASSOC,
+	SMFS_TYPE_REASSOC,
+	SMFS_TYPE_DISASSOC_TX,
+	SMFS_TYPE_DISASSOC_RX,
+	SMFS_TYPE_DEAUTH_TX,
+	SMFS_TYPE_DEAUTH_RX,
+	SMFS_TYPE_MAX
+} smfs_type_t;
+
+#ifdef PHYMON
+
+#define PHYMON_VERSION 1
+
+typedef struct wl_phycal_core_state {
+	/* Tx IQ/LO calibration coeffs */
+	int16 tx_iqlocal_a;
+	int16 tx_iqlocal_b;
+	int8 tx_iqlocal_ci;
+	int8 tx_iqlocal_cq;
+	int8 tx_iqlocal_di;
+	int8 tx_iqlocal_dq;
+	int8 tx_iqlocal_ei;
+	int8 tx_iqlocal_eq;
+	int8 tx_iqlocal_fi;
+	int8 tx_iqlocal_fq;
+
+	/* Rx IQ calibration coeffs */
+	int16 rx_iqcal_a;
+	int16 rx_iqcal_b;
+
+	uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */
+	uint32 papd_epsilon_table[64]; /* PAPD epsilon table */
+	int16 papd_epsilon_offset; /* PAPD epsilon offset */
+	uint8 curr_tx_pwrindex; /* Tx power index */
+	int8 idle_tssi; /* Idle TSSI */
+	int8 est_tx_pwr; /* Estimated Tx Power (dB) */
+	int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */
+	uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */
+	uint16 init_gaincode; /* initgain required for ACI */
+	int8 estirr_tx;
+	int8 estirr_rx;
+
+} wl_phycal_core_state_t;
+
+typedef struct wl_phycal_state {
+	int version;
+	int8 num_phy_cores; /* number of cores */
+	int8 curr_temperature; /* on-chip temperature sensor reading */
+	chanspec_t chspec; /* channspec for this state */
+	bool aci_state; /* ACI state: ON/OFF */
+	uint16 crsminpower; /* crsminpower required for ACI */
+	uint16 crsminpowerl; /* crsminpowerl required for ACI */
+	uint16 crsminpoweru; /* crsminpoweru required for ACI */
+	wl_phycal_core_state_t phycal_core[1];
+} wl_phycal_state_t;
+
+#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core)
+#endif /* PHYMON */
+
+/* discovery state */
+typedef struct wl_p2p_disc_st {
+	uint8 state;	/* see state */
+	chanspec_t chspec;	/* valid in listen state */
+	uint16 dwell;	/* valid in listen state, in ms */
+} wl_p2p_disc_st_t;
+
+/* scan request */
+typedef struct wl_p2p_scan {
+	uint8 type;		/* 'S' for WLC_SCAN, 'E' for "escan" */
+	uint8 reserved[3];
+	/* scan or escan parms... */
+} wl_p2p_scan_t;
+
+/* i/f request */
+typedef struct wl_p2p_if {
+	struct ether_addr addr;
+	uint8 type;	/* see i/f type */
+	chanspec_t chspec;	/* for p2p_ifadd GO */
+} wl_p2p_if_t;
+
+/* i/f query */
+typedef struct wl_p2p_ifq {
+	uint bsscfgidx;
+	char ifname[BCM_MSG_IFNAME_MAX];
+} wl_p2p_ifq_t;
+
+/* OppPS & CTWindow */
+typedef struct wl_p2p_ops {
+	uint8 ops;	/* 0: disable 1: enable */
+	uint8 ctw;	/* >= 10 */
+} wl_p2p_ops_t;
+
+/* absence and presence request */
+typedef struct wl_p2p_sched_desc {
+	uint32 start;
+	uint32 interval;
+	uint32 duration;
+	uint32 count;	/* see count */
+} wl_p2p_sched_desc_t;
+
+typedef struct wl_p2p_sched {
+	uint8 type;	/* see schedule type */
+	uint8 action;	/* see schedule action */
+	uint8 option;	/* see schedule option */
+	wl_p2p_sched_desc_t desc[1];
+} wl_p2p_sched_t;
+
+typedef struct wl_bcmdcs_data {
+	uint reason;
+	chanspec_t chspec;
+} wl_bcmdcs_data_t;
+
+
+/* NAT configuration */
+typedef struct {
+	uint32 ipaddr;		/* interface ip address */
+	uint32 ipaddr_mask;	/* interface ip address mask */
+	uint32 ipaddr_gateway;	/* gateway ip address */
+	uint8 mac_gateway[6];	/* gateway mac address */
+	uint32 ipaddr_dns;	/* DNS server ip address, valid only for public if */
+	uint8 mac_dns[6];	/* DNS server mac address,  valid only for public if */
+	uint8 GUID[38];		/* interface GUID */
+} nat_if_info_t;
+
+typedef struct {
+	uint op;		/* operation code */
+	bool pub_if;		/* set for public if, clear for private if */
+	nat_if_info_t if_info;	/* interface info */
+} nat_cfg_t;
+
+typedef struct {
+	int state;	/* NAT state returned */
+} nat_state_t;
+
+
+#define BTA_STATE_LOG_SZ	64
+
+/* BTAMP Statemachine states */
+enum {
+	HCIReset = 1,
+	HCIReadLocalAMPInfo,
+	HCIReadLocalAMPASSOC,
+	HCIWriteRemoteAMPASSOC,
+	HCICreatePhysicalLink,
+	HCIAcceptPhysicalLinkRequest,
+	HCIDisconnectPhysicalLink,
+	HCICreateLogicalLink,
+	HCIAcceptLogicalLink,
+	HCIDisconnectLogicalLink,
+	HCILogicalLinkCancel,
+	HCIAmpStateChange,
+	HCIWriteLogicalLinkAcceptTimeout
+};
+
+typedef struct flush_txfifo {
+	uint32 txfifobmp;
+	uint32 hwtxfifoflush;
+	struct ether_addr ea;
+} flush_txfifo_t;
+
+enum {
+	SPATIAL_MODE_2G_IDX = 0,
+	SPATIAL_MODE_5G_LOW_IDX,
+	SPATIAL_MODE_5G_MID_IDX,
+	SPATIAL_MODE_5G_HIGH_IDX,
+	SPATIAL_MODE_5G_UPPER_IDX,
+	SPATIAL_MODE_MAX_IDX
+};
+
+#define WLC_TXCORE_MAX	4	/* max number of txcore supports */
+#define WLC_SUBBAND_MAX	4	/* max number of sub-band supports */
+typedef struct {
+	uint8	band2g[WLC_TXCORE_MAX];
+	uint8	band5g[WLC_SUBBAND_MAX][WLC_TXCORE_MAX];
+} sar_limit_t;
+
+/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */
+typedef struct wl_mempool_stats {
+	int	num;		/* Number of memory pools */
+	bcm_mp_stats_t s[1];	/* Variable array of memory pool stats. */
+} wl_mempool_stats_t;
+
+typedef struct {
+	uint32 ipaddr;
+	uint32 ipaddr_netmask;
+	uint32 ipaddr_gateway;
+} nwoe_ifconfig_t;
+
+/* Traffic management priority classes */
+typedef enum trf_mgmt_priority_class {
+	trf_mgmt_priority_low           = 0,        /* Maps to 802.1p BK */
+	trf_mgmt_priority_medium        = 1,        /* Maps to 802.1p BE */
+	trf_mgmt_priority_high          = 2,        /* Maps to 802.1p VI */
+	trf_mgmt_priority_nochange	= 3,	    /* do not update the priority */
+	trf_mgmt_priority_invalid       = (trf_mgmt_priority_nochange + 1)
+} trf_mgmt_priority_class_t;
+
+/* Traffic management configuration parameters */
+typedef struct trf_mgmt_config {
+	uint32  trf_mgmt_enabled;                           /* 0 - disabled, 1 - enabled */
+	uint32  flags;                                      /* See TRF_MGMT_FLAG_xxx defines */
+	uint32  host_ip_addr;                               /* My IP address to determine subnet */
+	uint32  host_subnet_mask;                           /* My subnet mask */
+	uint32  downlink_bandwidth;                         /* In units of kbps */
+	uint32  uplink_bandwidth;                           /* In units of kbps */
+	uint32  min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES];  /* Minimum guaranteed tx bandwidth */
+	uint32  min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES];  /* Minimum guaranteed rx bandwidth */
+} trf_mgmt_config_t;
+
+/* Traffic management filter */
+typedef struct trf_mgmt_filter {
+	struct ether_addr           dst_ether_addr;         /* His L2 address */
+	uint32                      dst_ip_addr;            /* His IP address */
+	uint16                      dst_port;               /* His L4 port */
+	uint16                      src_port;               /* My L4 port */
+	uint16                      prot;                   /* L4 protocol (only TCP or UDP) */
+	uint16                      flags;                  /* TBD. For now, this must be zero. */
+	trf_mgmt_priority_class_t   priority;               /* Priority for filtered packets */
+	uint32                      dscp;                   /* DSCP */
+} trf_mgmt_filter_t;
+
+/* Traffic management filter list (variable length) */
+typedef struct trf_mgmt_filter_list     {
+	uint32              num_filters;
+	trf_mgmt_filter_t   filter[1];
+} trf_mgmt_filter_list_t;
+
+/* Traffic management global info used for all queues */
+typedef struct trf_mgmt_global_info {
+	uint32  maximum_bytes_per_second;
+	uint32  maximum_bytes_per_sampling_period;
+	uint32  total_bytes_consumed_per_second;
+	uint32  total_bytes_consumed_per_sampling_period;
+	uint32  total_unused_bytes_per_sampling_period;
+} trf_mgmt_global_info_t;
+
+/* Traffic management shaping info per priority queue */
+typedef struct trf_mgmt_shaping_info {
+	uint32  gauranteed_bandwidth_percentage;
+	uint32  guaranteed_bytes_per_second;
+	uint32  guaranteed_bytes_per_sampling_period;
+	uint32  num_bytes_produced_per_second;
+	uint32  num_bytes_consumed_per_second;
+	uint32  num_queued_packets;                         /* Number of packets in queue */
+	uint32  num_queued_bytes;                           /* Number of bytes in queue */
+} trf_mgmt_shaping_info_t;
+
+/* Traffic management shaping info array */
+typedef struct trf_mgmt_shaping_info_array {
+	trf_mgmt_global_info_t   tx_global_shaping_info;
+	trf_mgmt_shaping_info_t  tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
+	trf_mgmt_global_info_t   rx_global_shaping_info;
+	trf_mgmt_shaping_info_t  rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
+} trf_mgmt_shaping_info_array_t;
+
+
+/* Traffic management statistical counters */
+typedef struct trf_mgmt_stats {
+	uint32  num_processed_packets;      /* Number of packets processed */
+	uint32  num_processed_bytes;        /* Number of bytes processed */
+	uint32  num_discarded_packets;      /* Number of packets discarded from queue */
+} trf_mgmt_stats_t;
+
+/* Traffic management statisics array */
+typedef struct trf_mgmt_stats_array {
+	trf_mgmt_stats_t  tx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
+	trf_mgmt_stats_t  rx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
+} trf_mgmt_stats_array_t;
+
+typedef struct powersel_params {
+	/* LPC Params exposed via IOVAR */
+	int32		tp_ratio_thresh;  /* Throughput ratio threshold */
+	uint8		rate_stab_thresh; /* Thresh for rate stability based on nupd */
+	uint8		pwr_stab_thresh; /* Number of successes before power step down */
+	uint8		pwr_sel_exp_time; /* Time lapse for expiry of database */
+} powersel_params_t;
+
+typedef struct lpc_params {
+	/* LPC Params exposed via IOVAR */
+	uint8		rate_stab_thresh; /* Thresh for rate stability based on nupd */
+	uint8		pwr_stab_thresh; /* Number of successes before power step down */
+	uint8		lpc_exp_time; /* Time lapse for expiry of database */
+	uint8		pwrup_slow_step; /* Step size for slow step up */
+	uint8		pwrup_fast_step; /* Step size for fast step up */
+	uint8		pwrdn_slow_step; /* Step size for slow step down */
+} lpc_params_t;
+
+/* tx pkt delay statistics */
+#define	SCB_RETRY_SHORT_DEF	7	/* Default Short retry Limit */
+#define WLPKTDLY_HIST_NBINS	16	/* number of bins used in the Delay histogram */
+
+/* structure to store per-AC delay statistics */
+typedef struct scb_delay_stats {
+	uint32 txmpdu_lost;	/* number of MPDUs lost */
+	uint32 txmpdu_cnt[SCB_RETRY_SHORT_DEF]; /* retry times histogram */
+	uint32 delay_sum[SCB_RETRY_SHORT_DEF]; /* cumulative packet latency */
+	uint32 delay_min;	/* minimum packet latency observed */
+	uint32 delay_max;	/* maximum packet latency observed */
+	uint32 delay_avg;	/* packet latency average */
+	uint32 delay_hist[WLPKTDLY_HIST_NBINS];	/* delay histogram */
+} scb_delay_stats_t;
+
+/* structure for txdelay event */
+typedef struct txdelay_event {
+	uint8	status;
+	int		rssi;
+	chanim_stats_t		chanim_stats;
+	scb_delay_stats_t	delay_stats[AC_COUNT];
+} txdelay_event_t;
+
+/* structure for txdelay parameters */
+typedef struct txdelay_params {
+	uint16	ratio;	/* Avg Txdelay Delta */
+	uint8	cnt;	/* Sample cnt */
+	uint8	period;	/* Sample period */
+	uint8	tune;	/* Debug */
+} txdelay_params_t;
+
+enum {
+	WNM_SERVICE_DMS = 1,
+	WNM_SERVICE_FMS = 2,
+	WNM_SERVICE_TFS = 3
+};
+
+/* Definitions for WNM/NPS TCLAS */
+typedef struct wl_tclas {
+	uint8 user_priority;
+	uint8 fc_len;
+	dot11_tclas_fc_t fc;
+} wl_tclas_t;
+
+#define WL_TCLAS_FIXED_SIZE	OFFSETOF(wl_tclas_t, fc)
+
+typedef struct wl_tclas_list {
+	uint32 num;
+	wl_tclas_t tclas[1];
+} wl_tclas_list_t;
+
+/* Definitions for WNM/NPS Traffic Filter Service */
+typedef struct wl_tfs_req {
+	uint8 tfs_id;
+	uint8 tfs_actcode;
+	uint8 tfs_subelem_id;
+	uint8 send;
+} wl_tfs_req_t;
+
+typedef struct wl_tfs_filter {
+	uint8 status;			/* Status returned by the AP */
+	uint8 tclas_proc;		/* TCLAS processing value (0:and, 1:or)  */
+	uint8 tclas_cnt;		/* count of all wl_tclas_t in tclas array */
+	uint8 tclas[1];			/* VLA of wl_tclas_t */
+} wl_tfs_filter_t;
+#define WL_TFS_FILTER_FIXED_SIZE	OFFSETOF(wl_tfs_filter_t, tclas)
+
+typedef struct wl_tfs_fset {
+	struct ether_addr ea;		/* Address of AP/STA involved with this filter set */
+	uint8 tfs_id;			/* TFS ID field chosen by STA host */
+	uint8 status;			/* Internal status TFS_STATUS_xxx */
+	uint8 actcode;			/* Action code DOT11_TFS_ACTCODE_xxx */
+	uint8 token;			/* Token used in last request frame */
+	uint8 notify;			/* Notify frame sent/received because of this set */
+	uint8 filter_cnt;		/* count of all wl_tfs_filter_t in filter array */
+	uint8 filter[1];		/* VLA of wl_tfs_filter_t */
+} wl_tfs_fset_t;
+#define WL_TFS_FSET_FIXED_SIZE		OFFSETOF(wl_tfs_fset_t, filter)
+
+enum {
+	TFS_STATUS_DISABLED = 0,	/* TFS filter set disabled by user */
+	TFS_STATUS_DISABLING = 1,	/* Empty request just sent to AP */
+	TFS_STATUS_VALIDATED = 2,	/* Filter set validated by AP (but maybe not enabled!) */
+	TFS_STATUS_VALIDATING = 3,	/* Filter set just sent to AP */
+	TFS_STATUS_NOT_ASSOC = 4,	/* STA not associated */
+	TFS_STATUS_NOT_SUPPORT = 5,	/* TFS not supported by AP */
+	TFS_STATUS_DENIED = 6,		/* Filter set refused by AP (=> all sets are disabled!) */
+};
+
+typedef struct wl_tfs_status {
+	uint8 fset_cnt;			/* count of all wl_tfs_fset_t in fset array */
+	wl_tfs_fset_t fset[1];		/* VLA of wl_tfs_fset_t */
+} wl_tfs_status_t;
+
+typedef struct wl_tfs_set {
+	uint8 send;			/* Immediatly register registered sets on AP side */
+	uint8 tfs_id;			/* ID of a specific set (existing or new), or nul for all */
+	uint8 actcode;			/* Action code for this filter set */
+	uint8 tclas_proc;		/* TCLAS processing operator for this filter set */
+} wl_tfs_set_t;
+
+typedef struct wl_tfs_term {
+	uint8 del;			/* Delete internal set once confirmation received */
+	uint8 tfs_id;			/* ID of a specific set (existing), or nul for all */
+} wl_tfs_term_t;
+
+
+#define DMS_DEP_PROXY_ARP (1 << 0)
+
+/* Definitions for WNM/NPS Directed Multicast Service */
+enum {
+	DMS_STATUS_DISABLED = 0,	/* DMS desc disabled by user */
+	DMS_STATUS_ACCEPTED = 1,	/* Request accepted by AP */
+	DMS_STATUS_NOT_ASSOC = 2,	/* STA not associated */
+	DMS_STATUS_NOT_SUPPORT = 3,	/* DMS not supported by AP */
+	DMS_STATUS_DENIED = 4,		/* Request denied by AP */
+	DMS_STATUS_TERM = 5,		/* Request terminated by AP */
+	DMS_STATUS_REMOVING = 6,	/* Remove request just sent */
+	DMS_STATUS_ADDING = 7,		/* Add request just sent */
+	DMS_STATUS_ERROR = 8,		/* Non compliant AP behvior */
+	DMS_STATUS_IN_PROGRESS = 9, /* Request just sent */
+	DMS_STATUS_REQ_MISMATCH = 10 /* Conditions for sending DMS req not met */
+};
+
+typedef struct wl_dms_desc {
+	uint8 user_id;
+	uint8 status;
+	uint8 token;
+	uint8 dms_id;
+	uint8 tclas_proc;
+	uint8 mac_len;		/* length of all ether_addr in data array, 0 if STA */
+	uint8 tclas_len;	/* length of all wl_tclas_t in data array */
+	uint8 data[1];		/* VLA of 'ether_addr' and 'wl_tclas_t' (in this order ) */
+} wl_dms_desc_t;
+
+#define WL_DMS_DESC_FIXED_SIZE	OFFSETOF(wl_dms_desc_t, data)
+
+typedef struct wl_dms_status {
+	uint32 cnt;
+	wl_dms_desc_t desc[1];
+} wl_dms_status_t;
+
+typedef struct wl_dms_set {
+	uint8 send;
+	uint8 user_id;
+	uint8 tclas_proc;
+} wl_dms_set_t;
+
+typedef struct wl_dms_term {
+	uint8 del;
+	uint8 user_id;
+} wl_dms_term_t;
+
+typedef struct wl_service_term {
+	uint8 service;
+	union {
+		wl_dms_term_t dms;
+	} u;
+} wl_service_term_t;
+
+/* Definitions for WNM/NPS BSS Transistion */
+typedef struct wl_bsstrans_req {
+	uint16 tbtt;			/* time of BSS to end of life, in unit of TBTT */
+	uint16 dur;			/* time of BSS to keep off, in unit of minute */
+	uint8 reqmode;			/* request mode of BSS transition request */
+	uint8 unicast;			/* request by unicast or by broadcast */
+} wl_bsstrans_req_t;
+
+enum {
+	BSSTRANS_RESP_AUTO = 0,		/* Currently equivalent to ENABLE */
+	BSSTRANS_RESP_DISABLE = 1,	/* Never answer BSS Trans Req frames */
+	BSSTRANS_RESP_ENABLE = 2,	/* Always answer Req frames with preset data */
+	BSSTRANS_RESP_WAIT = 3,		/* Send ind, wait and/or send preset data (NOT IMPL) */
+	BSSTRANS_RESP_IMMEDIATE = 4	/* After an ind, set data and send resp (NOT IMPL) */
+};
+
+typedef struct wl_bsstrans_resp {
+	uint8 policy;
+	uint8 status;
+	uint8 delay;
+	struct ether_addr target;
+} wl_bsstrans_resp_t;
+
+/* "wnm_bsstrans_resp" argument programming behavior after BSSTRANS Req reception */
+enum {
+	WL_BSSTRANS_RESP_ROAM_ALWAYS = 0,	/* Roam (or disassociate) in all cases */
+	WL_BSSTRANS_RESP_ROAM_IF_MODE = 1,	/* Roam only if requested by Request Mode field */
+	WL_BSSTRANS_RESP_ROAM_IF_PREF = 2,	/* Roam only if Preferred BSS provided */
+	WL_BSSTRANS_RESP_WAIT = 3		/* Wait for deauth and send Accepted status */
+};
+
+/* Definitions for WNM/NPS TIM Broadcast */
+typedef struct wl_timbc_offset {
+	int16 offset;		/* offset in us */
+	uint16 fix_intv;	/* override interval sent from STA */
+	uint16 rate_override;	/* use rate override to send high rate TIM broadcast frame */
+	uint8 tsf_present;	/* show timestamp in TIM broadcast frame */
+} wl_timbc_offset_t;
+
+typedef struct wl_timbc_set {
+	uint8 interval;		/* Interval in DTIM wished or required. */
+	uint8 flags;		/* Bitfield described below */
+	uint16 rate_min;	/* Minimum rate required for High/Low TIM frames. Optionnal */
+	uint16 rate_max;	/* Maximum rate required for High/Low TIM frames. Optionnal */
+} wl_timbc_set_t;
+
+enum {
+	WL_TIMBC_SET_TSF_REQUIRED = 1,	/* Enable TIMBC only if TSF in TIM frames */
+	WL_TIMBC_SET_NO_OVERRIDE = 2,	/* ... if AP does not override interval */
+	WL_TIMBC_SET_PROXY_ARP = 4,	/* ... if AP support Proxy ARP */
+	WL_TIMBC_SET_DMS_ACCEPTED = 8	/* ... if all DMS desc have been accepted */
+};
+
+typedef struct wl_timbc_status {
+	uint8 status_sta;		/* Status from internal state machine (check below) */
+	uint8 status_ap;		/* From AP response frame (check 8.4.2.86 from 802.11) */
+	uint8 interval;
+	uint8 pad;
+	int32 offset;
+	uint16 rate_high;
+	uint16 rate_low;
+} wl_timbc_status_t;
+
+enum {
+	WL_TIMBC_STATUS_DISABLE = 0,		/* TIMBC disabled by user */
+	WL_TIMBC_STATUS_REQ_MISMATCH = 1,	/* AP settings do no match user requirements */
+	WL_TIMBC_STATUS_NOT_ASSOC = 2,		/* STA not associated */
+	WL_TIMBC_STATUS_NOT_SUPPORT = 3,	/* TIMBC not supported by AP */
+	WL_TIMBC_STATUS_DENIED = 4,		/* Req to disable TIMBC sent to AP */
+	WL_TIMBC_STATUS_ENABLE = 5		/* TIMBC enabled */
+};
+
+/* Definitions for PM2 Dynamic Fast Return To Sleep */
+typedef struct wl_pm2_sleep_ret_ext {
+	uint8 logic;			/* DFRTS logic: see WL_DFRTS_LOGIC_* below */
+	uint16 low_ms;			/* Low FRTS timeout */
+	uint16 high_ms;			/* High FRTS timeout */
+	uint16 rx_pkts_threshold;	/* switching threshold: # rx pkts */
+	uint16 tx_pkts_threshold;	/* switching threshold: # tx pkts */
+	uint16 txrx_pkts_threshold;	/* switching threshold: # (tx+rx) pkts */
+	uint32 rx_bytes_threshold;	/* switching threshold: # rx bytes */
+	uint32 tx_bytes_threshold;	/* switching threshold: # tx bytes */
+	uint32 txrx_bytes_threshold;	/* switching threshold: # (tx+rx) bytes */
+} wl_pm2_sleep_ret_ext_t;
+
+#define WL_DFRTS_LOGIC_OFF	0	/* Feature is disabled */
+#define WL_DFRTS_LOGIC_OR	1	/* OR all non-zero threshold conditions */
+#define WL_DFRTS_LOGIC_AND	2	/* AND all non-zero threshold conditions */
+
+/* Values for the passive_on_restricted_mode iovar.  When set to non-zero, this iovar
+ * disables automatic conversions of a channel from passively scanned to
+ * actively scanned.  These values only have an effect for country codes such
+ * as XZ where some 5 GHz channels are defined to be passively scanned.
+ */
+#define WL_PASSACTCONV_DISABLE_NONE	0	/* Enable permanent and temporary conversions */
+#define WL_PASSACTCONV_DISABLE_ALL	1	/* Disable permanent and temporary conversions */
+#define WL_PASSACTCONV_DISABLE_PERM	2	/* Disable only permanent conversions */
+
+/* Definitions for Reliable Multicast */
+#define WL_RMC_CNT_VERSION	   1
+#define WL_RMC_MAX_CLIENT	   32
+#define WL_RMC_FLAG_INBLACKLIST	   1
+#define WL_RMC_FLAG_ACTIVEACKER	   2
+#define WL_RMC_FLAG_RELMCAST	   4
+#define WL_RMC_MAX_TABLE_ENTRY     4
+
+#define WL_RMC_VER		   1
+#define WL_RMC_INDEX_ACK_ALL       255
+#define WL_RMC_NUM_OF_MC_STREAMS   4
+#define WL_RMC_MAX_TRS_PER_GROUP   1
+#define WL_RMC_MAX_TRS_IN_ACKALL   1
+#define WL_RMC_ACK_MCAST0          0x02
+#define WL_RMC_ACK_MCAST_ALL       0x01
+#define WL_RMC_ACTF_TIME_MIN       300	 /* time in ms */
+#define WL_RMC_ACTF_TIME_MAX       20000 /* time in ms */
+#define WL_RMC_ARTMO_MIN           350	 /* time in ms */
+#define WL_RMC_ARTMO_MAX           40000	 /* time in ms */
+
+/* RMC events in action frames */
+enum rmc_opcodes {
+	RELMCAST_ENTRY_OP_DISABLE = 0,   /* Disable multi-cast group */
+	RELMCAST_ENTRY_OP_DELETE  = 1,   /* Delete multi-cast group */
+	RELMCAST_ENTRY_OP_ENABLE  = 2,   /* Enable multi-cast group */
+	RELMCAST_ENTRY_OP_ACK_ALL = 3    /* Enable ACK ALL bit in AMT */
+};
+
+/* RMC operational modes */
+enum rmc_modes {
+	WL_RMC_MODE_RECEIVER    = 0,	 /* Receiver mode by default */
+	WL_RMC_MODE_TRANSMITTER = 1,	 /* Transmitter mode using wl ackreq */
+	WL_RMC_MODE_INITIATOR   = 2	 /* Initiator mode using wl ackreq */
+};
+
+/* Each RMC mcast client info */
+typedef struct wl_relmcast_client {
+	uint8 flag;			/* status of client such as AR, R, or blacklisted */
+	int16 rssi;			/* rssi value of RMC client */
+	struct ether_addr addr;		/* mac address of RMC client */
+} wl_relmcast_client_t;
+
+/* RMC Counters */
+typedef struct wl_rmc_cnts {
+	uint16  version;		/* see definition of WL_CNT_T_VERSION */
+	uint16  length;			/* length of entire structure */
+	uint16	dupcnt;			/* counter for duplicate rmc MPDU */
+	uint16	ackreq_err;		/* counter for wl ackreq error    */
+	uint16	af_tx_err;		/* error count for action frame transmit   */
+	uint16	null_tx_err;		/* error count for rmc null frame transmit */
+	uint16	af_unicast_tx_err;	/* error count for rmc unicast frame transmit */
+	uint16	mc_no_amt_slot;		/* No mcast AMT entry available */
+	uint16	mc_no_glb_slot;		/* No mcast entry available in global table */
+	uint16	mc_not_mirrored;	/* mcast group is not mirrored */
+	uint16	mc_existing_tr;		/* mcast group is already taken by transmitter */
+	uint16	mc_exist_in_amt;	/* mcast group is already programmed in amt */
+	uint16	mc_not_exist_in_gbl;	/* mcast group is not in global table */
+	uint16	mc_not_exist_in_amt;	/* mcast group is not in AMT table */
+	uint16	mc_utilized;		/* mcast addressed is already taken */
+	uint16	mc_taken_other_tr;	/* multi-cast addressed is already taken */
+	uint32	rmc_rx_frames_mac;      /* no of mc frames received from mac */
+	uint32	rmc_tx_frames_mac;      /* no of mc frames transmitted to mac */
+	uint32	mc_null_ar_cnt;         /* no. of times NULL AR is received */
+	uint32	mc_ar_role_selected;	/* no. of times took AR role */
+	uint32	mc_ar_role_deleted;	/* no. of times AR role cancelled */
+	uint32	mc_noacktimer_expired;  /* no. of times noack timer expired */
+} wl_rmc_cnts_t;
+
+/* RMC Status */
+typedef struct wl_relmcast_st {
+	uint8         ver;		/* version of RMC */
+	uint8         num;		/* number of clients detected by transmitter */
+	wl_relmcast_client_t clients[WL_RMC_MAX_CLIENT];
+	uint16        err;		/* error status (used in infra) */
+	uint16        actf_time;	/* action frame time period */
+} wl_relmcast_status_t;
+
+/* Entry for each STA/node */
+typedef struct wl_rmc_entry {
+	/* operation on multi-cast entry such add,
+	 * delete, ack-all
+	 */
+	int8    flag;
+	struct ether_addr addr;		/* multi-cast group mac address */
+} wl_rmc_entry_t;
+
+/* RMC table */
+typedef struct wl_rmc_entry_table {
+	uint8   index;			/* index to a particular mac entry in table */
+	uint8   opcode;			/* opcodes or operation on entry */
+	wl_rmc_entry_t entry[WL_RMC_MAX_TABLE_ENTRY];
+} wl_rmc_entry_table_t;
+
+/* Transmitter Info */
+typedef struct wl_rmc_trans_info {
+	struct ether_addr addr;		/* transmitter mac */
+	uint32 time_val;		/* timer val in case aging of entry is required */
+	uint16 seq;			/* last seq number of packet received from transmitter */
+	uint16 artmo;
+} wl_rmc_trans_info_t;
+
+/* Multicast Group */
+typedef struct wl_rmc_grp_entry {
+	struct ether_addr   mcaddr;	/* multi-cast group mac */
+	struct ether_addr   ar;		/* active receiver for the group */
+	wl_rmc_trans_info_t tr_info[WL_RMC_MAX_TRS_PER_GROUP];
+} wl_rmc_grp_entry_t;
+
+/* RMC ACKALL Table */
+typedef struct wl_rmc_ackall_entry {
+	struct ether_addr   ar;		/* active receiver for the entry */
+	wl_rmc_trans_info_t tr_info[WL_RMC_NUM_OF_MC_STREAMS];
+} wl_rmc_ackall_entry_t;
+
+/* RMC Peers Table */
+typedef struct wl_rmc_gbl_table {
+	uint8     activeMask;		/* mask to denote the entry(s) that are active */
+	wl_rmc_ackall_entry_t ackAll;   /* structure to keep info related to ACK all */
+	wl_rmc_grp_entry_t mc_entry[WL_RMC_NUM_OF_MC_STREAMS];
+} wl_rmc_gbl_table_t;
+
+/* To update vendor specific ie for RMC */
+typedef struct wl_rmc_vsie {
+	uint8	oui[DOT11_OUI_LEN];
+	uint16	payload;	/* IE Data Payload */
+} wl_rmc_vsie_t;
+
+typedef struct wl_proxd_iovar {
+	uint16	method;		/* Proxmity Detection method */
+	uint16	mode;		/* Mode (neutral, initiator, target) */
+} wl_proxd_iovar_t;
+
+/* structures for proximity detection parameters */
+typedef struct wl_proxd_params_rssi_method {
+	chanspec_t	chanspec;	/* chanspec for home channel */
+	uint16		interval;	/* interval between neighbor finding attempts (in TU) */
+	uint16		duration;	/* duration of neighbor finding attempts (in ms) */
+	int16		rssi_thresh;	/* RSSI threshold (in dBm) */
+	int16		tx_power;	/* tx power of Proximity Detection frames (in dBm) */
+	uint16		tx_rate;	/* tx rate of Proximity Detection frames
+					 * (in 500kbps units)
+					 */
+	uint16		timeout;	/* state machine wait timeout of the frames (in ms) */
+	uint16		maxconvergtmo;	/* max wait converge timeout (in ms) */
+} wl_proxd_params_rssi_method_t;
+
+typedef struct wl_proxd_params_iovar {
+	uint16	method;			/* Proxmity Detection method */
+	union {
+		wl_proxd_params_rssi_method_t rssi_params;
+	} u;				/* Method specific optional parameters */
+} wl_proxd_params_iovar_t;
+
+enum {
+	RSSI_REASON_UNKNOW,
+	RSSI_REASON_LOWRSSI,
+	RSSI_REASON_NSYC,
+	RSSI_REASON_TIMEOUT
+};
+
+enum {
+	RSSI_STATE_POLL,
+	RSSI_STATE_TPAIRING,
+	RSSI_STATE_IPAIRING,
+	RSSI_STATE_THANDSHAKE,
+	RSSI_STATE_IHANDSHAKE,
+	RSSI_STATE_CONFIRMED,
+	RSSI_STATE_PIPELINE,
+	RSSI_STATE_NEGMODE,
+	RSSI_STATE_MONITOR,
+	RSSI_STATE_LAST
+};
+
+typedef struct wl_proxd_status_iovar {
+	uint8			mode;
+	uint8			peermode;
+	uint8			state;
+	uint8			reason;
+	uint32			txcnt;
+	uint32			rxcnt;
+	struct ether_addr	peer;
+	int16			hi_rssi;
+	int16			low_rssi;
+} wl_proxd_status_iovar_t;
+
+#ifdef NET_DETECT
+typedef struct net_detect_adapter_features {
+	bool	wowl_enabled;
+	bool	net_detect_enabled;
+	bool	nlo_enabled;
+} net_detect_adapter_features_t;
+
+typedef enum net_detect_bss_type {
+	nd_bss_any = 0,
+	nd_ibss,
+	nd_ess
+} net_detect_bss_type_t;
+
+typedef struct net_detect_profile {
+	wlc_ssid_t		ssid;
+	net_detect_bss_type_t   bss_type;	/* Ignore for now since Phase 1 is only for ESS */
+	uint32			cipher_type;	/* DOT11_CIPHER_ALGORITHM enumeration values */
+	uint32			auth_type;	/* DOT11_AUTH_ALGORITHM enumeration values */
+} net_detect_profile_t;
+
+typedef struct net_detect_profile_list {
+	uint32			num_nd_profiles;
+	net_detect_profile_t	nd_profile[0];
+} net_detect_profile_list_t;
+
+typedef struct net_detect_config {
+	bool			    nd_enabled;
+	uint32			    scan_interval;
+	uint32			    wait_period;
+	bool			    wake_if_connected;
+	bool			    wake_if_disconnected;
+	net_detect_profile_list_t   nd_profile_list;
+} net_detect_config_t;
+
+typedef enum net_detect_wake_reason {
+	nd_reason_unknown,
+	nd_net_detected,
+	nd_wowl_event,
+	nd_ucode_error
+} net_detect_wake_reason_t;
+
+typedef struct net_detect_wake_data {
+	net_detect_wake_reason_t    nd_wake_reason;
+	uint32			    nd_wake_date_length;
+	uint8			    nd_wake_data[0];	    /* Wake data (currently unused) */
+} net_detect_wake_data_t;
+
+#endif /* NET_DETECT */
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+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		enable;
+	uint32		mode; /* STA/AP interface */
+	struct ether_addr ea;
+} wlc_dwds_config_t;
+
+typedef struct wl_el_set_params_s {
+	uint8 set;	/* Set number */
+	uint32 size;	/* Size to make/expand */
+} wl_el_set_params_t;
+
+typedef struct wl_el_tag_params_s {
+	uint16 tag;
+	uint8 set;
+	uint8 flags;
+} wl_el_tag_params_t;
+
+/* Video Traffic Interference Monitor config */
+#define INTFER_VERSION		1
+typedef struct wl_intfer_params {
+	uint16 version;			/* version */
+	uint8 period;			/* sample period */
+	uint8 cnt;			/* sample cnt */
+	uint8 txfail_thresh;	/* non-TCP txfail threshold */
+	uint8 tcptxfail_thresh;	/* tcptxfail threshold */
+} wl_intfer_params_t;
+
+typedef struct wl_staprio_cfg {
+	struct ether_addr ea;	/* mac addr */
+	uint8 prio;		/* scb priority */
+} wl_staprio_cfg_t;
+
+typedef enum wl_stamon_cfg_cmd_type {
+	STAMON_CFG_CMD_DEL = 0,
+	STAMON_CFG_CMD_ADD = 1
+} wl_stamon_cfg_cmd_type_t;
+
+typedef struct wlc_stamon_sta_config {
+	wl_stamon_cfg_cmd_type_t cmd; /* 0 - delete, 1 - add */
+	struct ether_addr ea;
+} wlc_stamon_sta_config_t;
+
+/* Received Beacons lengths information */
+#define WL_LAST_BCNS_INFO_FIXED_LEN		OFFSETOF(wlc_bcn_len_hist_t, bcnlen_ring)
+typedef struct wlc_bcn_len_hist {
+	uint16	ver;				/* version field */
+	uint16	cur_index;			/* current pointed index in ring buffer */
+	uint32	max_bcnlen;		/* Max beacon length received */
+	uint32	min_bcnlen;		/* Min beacon length received */
+	uint32	ringbuff_len;		/* Length of the ring buffer 'bcnlen_ring' */
+	uint32	bcnlen_ring[1];	/* ring buffer storing received beacon lengths */
+} wlc_bcn_len_hist_t;
+
+/* WDS net interface types */
+#define WL_WDSIFTYPE_NONE  0x0 /* The interface type is neither WDS nor DWDS. */
+#define WL_WDSIFTYPE_WDS   0x1 /* The interface is WDS type. */
+#define WL_WDSIFTYPE_DWDS  0x2 /* The interface is DWDS type. */
+
+typedef struct wl_bssload_static {
+	bool is_static;
+	uint16 sta_count;
+	uint8 chan_util;
+	uint16 aac;
+} wl_bssload_static_t;
+
+
+#ifdef SR_DEBUG
+typedef  struct /* pmu_reg */{
+	uint32  pmu_control;
+	uint32  pmu_capabilities;
+	uint32  pmu_status;
+	uint32  res_state;
+	uint32  res_pending;
+	uint32  pmu_timer1;
+	uint32  min_res_mask;
+	uint32  max_res_mask;
+	uint32  pmu_chipcontrol1[4];
+	uint32  pmu_regcontrol[5];
+	uint32  pmu_pllcontrol[5];
+	uint32  pmu_rsrc_up_down_timer[31];
+	uint32  rsrc_dep_mask[31];
+}  pmu_reg_t;
+
+typedef struct {
+	uint32 pmu_min_res_val;
+	uint16 pmu_flag;
+} pmu_min_res_t;
+
+#endif /* SR_DEBUG */
+
+typedef enum event_msgs_ext_command {
+	EVENTMSGS_NONE          =       0,
+	EVENTMSGS_SET_BIT       =       1,
+	EVENTMSGS_RESET_BIT     =       2,
+	EVENTMSGS_SET_MASK      =       3
+} event_msgs_ext_command_t;
+
+#define EVENTMSGS_VER 1
+#define EVENTMSGS_EXT_STRUCT_SIZE      OFFSETOF(eventmsgs_ext_t, mask[0])
+
+/* len - for SET it would be mask size from the application to the firmware
+ * for GET it would be actual firmware mask size
+ * maxgetsize - is only used for GET. indicate max mask size that the
+ * application can read from the firmware
+ */
+typedef struct eventmsgs_ext
+{
+	uint8   ver;
+	uint8   command;
+	uint8   len;
+	uint8   maxgetsize;
+	uint8   mask[1];
+} eventmsgs_ext_t;
+
+#ifdef TBTT_OFFSET_STAT
+/* XXX: tbtt offset stat is only for primary STA and non-p2p link */
+typedef struct {
+	uint32 tbtt_offset_avg;
+	uint32 tbtt_offset_min;
+	uint32 tbtt_offset_max;
+} tbtt_offset_stat_t;
+#endif /* TBTT_OFFSET_STAT */
+
+#endif /* _wlioctl_h_ */
diff --git a/src/makefiles/RelPath.mk b/src/makefiles/RelPath.mk
new file mode 100644
index 0000000..8aa3cee
--- /dev/null
+++ b/src/makefiles/RelPath.mk
@@ -0,0 +1,81 @@
+ifdef _RELPATH_MK_
+$(if $D,$(info =-= Avoiding redundant include ($(MAKEFILE_LIST))))
+else
+unexport _RELPATH_MK_	# in case of make -e
+_RELPATH_MK_ := 1
+
+# Protection against process recursion when this file is
+# included by setting MAKEFILES.
+ifneq (,$(filter %$(notdir $(lastword $(MAKEFILE_LIST))),$(MAKEFILES)))
+MAKEFILES := $(filter-out %$(notdir $(lastword $(MAKEFILE_LIST))),$(MAKEFILES))
+ifndef MAKEFILES
+unexport MAKEFILES
+endif
+endif
+
+# Usage: $(call relpath,[<from-dir>,]<to-dir>)
+# Returns the relative path from <from-dir> to <to-dir>; <from-dir>
+# may be elided in which case it defaults to $(CURDIR).
+
+_rp_space :=
+_rp_space +=
+_rp_uname_s := $(shell uname -s)
+
+# Utility functions.
+_rp_compose = $(subst ${_rp_space},$(strip $1),$(strip $2))
+_rp_endlist = $(wordlist $1,$(words $2),$2)
+_rp_canonpath = $(if $(findstring CYGWIN,$(_rp_uname_s)),$(shell cygpath -a -u $1),$(abspath $1))
+
+# ----relpath(): Self-recursive function which compares the first element
+#                of two given paths, then calls itself with the next two
+#                elements, and so on, until a difference is found.  At each
+#                step, if the first element of both paths matches, that
+#                element is produced.
+----relpath = $(if $(filter $(firstword $1),$(firstword $2)), \
+                $(firstword $1) \
+                $(call $0,$(call _rp_endlist,2,$1),$(call _rp_endlist,2,$2)) \
+               )
+# ---relpath():  This function removes $1 from the front of both $2 and
+#                $3 (removes common path prefix) and generates a relative
+#                path between the locations given by $2 and $3, by replacing
+#                each remaining element of $2 (after common prefix removal)
+#                with '..', then appending the remainder of $3 (after common
+#                prefix removal) to the string of '..'s
+---relpath  = $(foreach e,$(subst /, ,$(patsubst $(if $1,/)$1/%,%,$2)),..) \
+              $(if $3,$(patsubst $(if $1,/)$1/%,%,$3))
+# --relpath():   This function runs the output of ----relpath() through
+#                ---relpath(), and turns the result into an actual relative
+#                path string, separated by '/'.
+--relpath   = $(call _rp_compose,/, \
+                $(call -$0,$(call _rp_compose,/,$(call --$0,$3,$4)),$1,$2) \
+               )
+# -relpath():    This function makes a determination about the two given
+#                paths -- does one strictly prefix the other?  If so, this
+#                function produces a relative path between the two inputs,
+#                without calling --relpath() and taking the "long road".
+#                If $1 prefixes $2, the result is the remainder of $2 after
+#                removing $1.  If $2 prefixes $1, the result is the remainder
+#                of $1 after removing $2, but with each element in that
+#                remainder converted to '..'.
+-relpath    = $(if $(filter $1,$2),., \
+                $(if $(filter $1/%,$2), \
+                 $(patsubst $1/%,%,$2), \
+                 $(if $(filter $2/%,$1), \
+                   $(call _rp_compose,/, \
+                     $(foreach e,$(subst /, ,$(patsubst $2/%,%,$1)),..) \
+                    ), \
+                   $(call -$0,$1,$2,$(subst /, ,$1),$(subst /, ,$2)) \
+                  ) \
+                ) \
+              )
+
+# relpath():     This function loops over each element in $2, calculating
+#                the relative path from $1 to each element of $2.
+relpath     = $(if $1,,$(error Error: missing first parameter to $0))$(strip \
+                $(if $2, \
+                  $(foreach d,$2,$(call -$0,$(call _rp_canonpath,$1),$(call _rp_canonpath,$d))), \
+                  $(foreach d,$1,$(call -$0,$(call _rp_canonpath,${CURDIR}),$(call _rp_canonpath,$d))) \
+                 ) \
+               )
+
+endif #_RELPATH_MK_
diff --git a/src/makefiles/WLAN_Common.mk b/src/makefiles/WLAN_Common.mk
new file mode 100644
index 0000000..6009766
--- /dev/null
+++ b/src/makefiles/WLAN_Common.mk
@@ -0,0 +1,389 @@
+ifdef _WLAN_COMMON_MK
+$(if $D,$(info Info: Avoiding redundant include ($(MAKEFILE_LIST))))
+else	# _WLAN_COMMON_MK
+_WLAN_COMMON_MK := 1
+unexport _WLAN_COMMON_MK	# in case of make -e
+
+################################################################
+# Summary and Namespace Rules
+################################################################
+#   This is a special makefile fragment intended for common use.
+# The most important design principle is that it be used only to
+# define variables and functions in a tightly controlled namespace.
+# If a make include file is used to set rules, pattern rules,
+# or well known variables like CFLAGS, it can have unexpected
+# effects on the including makefile, with the result that people
+# either stop including it or stop changing it.
+# Therefore, the only way to keep this a file which can be
+# safely included by any GNU makefile and extended at will is
+# to allow it only to set variables and only in its own namespace.
+#   The namespace is "WLAN_CamelCase" for normal variables,
+# "wlan_lowercase" for functions, and WLAN_UPPERCASE for boolean
+# "constants" (these are all really just make variables; only the
+# usage patterns differ).
+#   Internal (logically file-scoped) variables are prefixed with "-"
+# and have no other namespace restrictions.
+#   Every variable defined here should match one of these patterns.
+
+################################################################
+# Enforce required conditions
+################################################################
+
+ifneq (,$(filter 3.7% 3.80,$(MAKE_VERSION)))
+$(error $(MAKE): Error: version $(MAKE_VERSION) too old, 3.81+ required)
+endif
+
+################################################################
+# Derive including makefile since it's a little tricky.
+################################################################
+
+WLAN_Makefile := $(abspath $(lastword $(filter-out $(lastword $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
+
+################################################################
+# Shiny new ideas, can be enabled via environment for testing.
+################################################################
+
+ifdef WLAN_MakeBeta
+$(info Info: BUILDING WITH "WLAN_MakeBeta" ENABLED!)
+SHELL := /bin/bash
+#export SHELLOPTS ?= pipefail
+#.SUFFIXES:
+#MAKEFLAGS += -r
+endif
+
+################################################################
+# Allow a makefile to force this file into all child makes.
+################################################################
+
+ifdef WLAN_StickyCommon
+export MAKEFILES := $(MAKEFILES) $(abspath $(lastword $(MAKEFILE_LIST)))
+endif
+
+################################################################
+# Host type determination
+################################################################
+
+_common-uname-s := $(shell uname -s)
+
+# Typically this will not be tested explicitly; it's the default condition.
+WLAN_HOST_TYPE := unix
+
+ifneq (,$(filter Linux,$(_common-uname-s)))
+  WLAN_LINUX_HOST := 1
+else ifneq (,$(filter CYGWIN%,$(_common-uname-s)))
+  WLAN_CYGWIN_HOST := 1
+  WLAN_WINDOWS_HOST := 1
+else ifneq (,$(filter Darwin,$(_common-uname-s)))
+  WLAN_MACOS_HOST := 1
+  WLAN_BSD_HOST := 1
+else ifneq (,$(filter FreeBSD NetBSD,$(_common-uname-s)))
+  WLAN_BSD_HOST := 1
+else ifneq (,$(filter SunOS%,$(_common-uname-s)))
+  WLAN_SOLARIS_HOST := 1
+endif
+
+################################################################
+# Utility variables
+################################################################
+
+empty :=
+space := $(empty) $(empty)
+comma := ,
+
+################################################################
+# Utility functions
+################################################################
+
+# Provides enhanced-format messages from make logic.
+wlan_die = $(error Error: $1)
+wlan_warning = $(warning Warning: $1)
+wlan_info = $(info Info: $1)
+
+# Debug function to enable make verbosity.
+wlan_dbg = $(if $D,$(call wlan_info,$1))
+
+# Debug function to expose values of the listed variables.
+wlan_dbgv = $(foreach _,$1,$(call wlan_dbg,$_=$($_)))
+
+# Make-time assertion.
+define wlan_assert
+ifeq (,$(findstring clean,$(MAKECMDGOALS)))
+$(if $1,,$(call wlan_die,$2))
+endif
+endef
+
+# Checks for the presence of an option in an option string
+# like "aaa-bbb-ccc-ddd".
+wlan_opt = $(if $(findstring -$1-,-$2-),1,0)
+
+# Compares two dotted numeric strings (e.g 2.3.16.1) for $1 >= $2
+define wlan_version_ge
+$(findstring TRUE,$(shell bash -c 'sort -cu -t. -k1,1nr -k2,2nr -k3,3nr -k4,4nr <(echo -e "$2\n$1") 2>&1 || echo TRUE'))
+endef
+
+# This is a useful macro to wrap around a compiler command line,
+# e.g. "$(call wlan_cc,<command-line>). It organizes flags in a
+# readable way while taking care not to change any ordering
+# which matters. It also provides a hook for externally
+# imposed C flags which can be passed in from the top level.
+# This would be the best place to add a check for
+# command line length. Requires a $(strlen) function;
+# GMSL has one.
+define wlan_cc
+$(filter-out -D% -I%,$1) $(filter -D%,$1) $(filter -I%,$1) $(WLAN_EXTERNAL_CFLAGS)
+endef
+
+# Applies the standard cygpath translation for a path on Cygwin.
+define wlan_cygpath
+$(if $(WLAN_CYGWIN_HOST),$(shell cygpath -m $1),$1)
+endef
+
+################################################################
+# Standard make variables
+################################################################
+
+# This points to the root of the build tree, currently known to
+# be 2 levels above the directory of this file.
+ifndef WLAN_TreeBaseA
+ifdef WLAN_CYGWIN_HOST
+WLAN_TreeBaseA := $(shell cygpath -m -a $(dir $(lastword $(MAKEFILE_LIST)))../..)
+else
+WLAN_TreeBaseA := $(subst \,/,$(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..))
+endif
+endif
+
+# We've observed a bug, or at least a surprising behavior, in emake which
+# causes the $(realpath) above to fail so this fallback is used.
+ifndef WLAN_TreeBaseA
+WLAN_TreeBaseA := $(shell cd $(dir $(lastword $(MAKEFILE_LIST)))../.. && pwd)
+endif
+
+# Export these values so they can be used by scripts or nmake/pmake makefiles.
+export WLAN_TreeBaseA
+
+# We may eventually remove this and require an
+# explict absolute-vs-relative choice.
+export WLAN_TreeBase := $(WLAN_TreeBaseA)
+
+# Pick up the "relpath" make function.
+include $(WLAN_TreeBaseA)/src/makefiles/RelPath.mk
+
+# This is a relativized version of $(WLAN_TreeBaseA).
+export WLAN_TreeBaseR = $(call relpath,$(WLAN_TreeBaseA))
+
+# For compatibility, due to the prevalence of $(SRCBASE)
+WLAN_SrcBaseA := $(WLAN_TreeBaseA)/src
+WLAN_SrcBaseR  = $(patsubst %/,%,$(dir $(WLAN_TreeBaseR)))
+
+# Show makefile list before we start including things.
+$(call wlan_dbgv, CURDIR MAKEFILE_LIST)
+
+################################################################
+# Pick up the "universal settings file" containing
+# the list of all available software components.
+################################################################
+
+include $(WLAN_TreeBaseA)/src/tools/release/WLAN.usf
+
+################################################################
+# Calculate paths to requested components.
+################################################################
+
+# This uses pattern matching to pull component paths from
+# their basenames (e.g. src/wl/xyz => xyz).
+# It also strips out component paths which don't currently exist.
+# This may be required due to our "partial-source" build styles
+# and the fact that linux mkdep throws an error when a directory
+# specified with -I doesn't exist.
+define _common-component-names-to-rel-paths
+$(strip \
+  $(patsubst $(WLAN_TreeBaseA)/%,%,$(wildcard $(addprefix $(WLAN_TreeBaseA)/,\
+  $(sort $(foreach name,$(if $1,$1,$(WLAN_COMPONENT_PATHS)),$(filter %/$(name),$(WLAN_COMPONENT_PATHS))))))))
+endef
+
+# If WLAN_ComponentsInUse is unset it defaults to the full set (for now, anyway - TODO).
+# It's also possible to request the full set with a literal '*'.
+ifeq (,$(WLAN_ComponentsInUse))
+  WLAN_ComponentsInUse		:= $(sort $(notdir $(WLAN_COMPONENT_PATHS)))
+  # $(call wlan_die,no SW component request)
+else ifeq (*,$(WLAN_ComponentsInUse))
+  WLAN_ComponentsInUse		:= $(sort $(notdir $(WLAN_COMPONENT_PATHS)))
+  $(call wlan_info,all SW components requested ("$(WLAN_ComponentsInUse)"))
+else
+  WLAN_ComponentsInUse		:= $(sort $(WLAN_ComponentsInUse))
+endif
+WLAN_ComponentPathsInUse	:= $(call _common-component-names-to-rel-paths,$(WLAN_ComponentsInUse))
+
+# Test that all requested components exist.
+ifneq ($(sort $(WLAN_ComponentsInUse)),$(notdir $(WLAN_ComponentPathsInUse)))
+# TODO - turned off until old branches support this infrastructure.
+#  $(call wlan_warning,bogus component request: "$(sort $(WLAN_ComponentsInUse))" != "$(notdir $(WLAN_ComponentPathsInUse))")
+endif
+
+# Loop through all components in use. If an xyz.mk file exists at the base of
+# component xyz's subtree, include it and use its contents to modify the list
+# of include and src dirs. Otherwise, use the defaults for that component.
+# Also generate a WLAN_ComponentBaseDir_xyz variable for each component "xyz".
+WLAN_ComponentIncPathsInUse :=
+WLAN_ComponentSrcPathsInUse :=
+$(foreach _path,$(WLAN_ComponentPathsInUse), \
+  $(if $(wildcard $(WLAN_TreeBaseA)/$(_path)/$(notdir $(_path)).mk),$(eval include $(WLAN_TreeBaseA)/$(_path)/$(notdir $(_path)).mk)) \
+  $(eval $(notdir $(_path))_IncDirs ?= include) \
+  $(eval $(notdir $(_path))_SrcDirs ?= src) \
+  $(eval WLAN_ComponentIncPathsInUse += $(addprefix $(_path)/,$($(notdir $(_path))_IncDirs))) \
+  $(eval WLAN_ComponentSrcPathsInUse += $(addprefix $(_path)/,$($(notdir $(_path))_SrcDirs))) \
+  $(eval WLAN_ComponentBaseDir_$$(notdir $(_path)) := $$(WLAN_TreeBaseA)/$(_path)) \
+)
+
+# Phy specific subdirs
+ifeq ($(findstring phymods,$(WLAN_ComponentsInUse)),phymods)
+PHY_TOP_DIR = src/wl/phymods
+PHY_CMN_DIR_LIST = dbg
+PHY_1OFF_DIR_LIST =
+PHY_TYPE_LIST = cmn
+PHY_MOD_LIST = core radar
+PHY_MOD_SRC_DIRS = $(foreach PHY_CMN_DIR,$(PHY_CMN_DIR_LIST),$(PHY_TOP_DIR)/cmn/$(PHY_CMN_DIR)/src)
+PHY_MOD_SRC_DIRS += $(foreach PHY_1OFF_DIR,$(PHY_1OFF_DIR_LIST),$(PHY_TOP_DIR)/$(PHY_1OFF_DIR)/src)
+PHY_MOD_SRC_DIRS += $(foreach PHY_TYPE,$(PHY_TYPE_LIST),\
+	$(foreach PHY_MOD,$(PHY_MOD_LIST),$(PHY_TOP_DIR)/$(PHY_TYPE)/$(PHY_MOD)/src))
+PHY_MOD_INC_DIRS = $(foreach PHY_CMN_DIR,$(PHY_CMN_DIR_LIST),$(PHY_TOP_DIR)/cmn/$(PHY_CMN_DIR)/include)
+PHY_MOD_INC_DIRS += $(foreach PHY_1OFF_DIR,$(PHY_1OFF_DIR_LIST),$(PHY_TOP_DIR)/$(PHY_1OFF_DIR)/include)
+PHY_MOD_INC_DIRS += $(foreach PHY_TYPE,$(PHY_TYPE_LIST),\
+	$(foreach PHY_MOD,$(PHY_MOD_LIST),$(PHY_TOP_DIR)/$(PHY_TYPE)/$(PHY_MOD)/include))
+PHY_MOD_INC_DIRS += $(foreach PHY_DIR,$(PHY_MOD_SRC_DIRS),$(PHY_DIR))
+else
+PHY_MOD_SRC_DIRS =
+PHY_MOD_INC_DIRS =
+endif
+
+# Global include/source path
+WLAN_StdSrcDirs = src/shared src/wl/sys src/wl/phy src/bcmcrypto
+WLAN_StdSrcDirs += $(PHY_MOD_SRC_DIRS)
+WLAN_StdIncDirs = src/include src/common/include src/common/include/devctrl_if
+WLAN_StdIncDirs += $(PHY_MOD_INC_DIRS)
+
+WLAN_SrcIncDirs = src/shared src/wl/sys src/wl/ndis/include src/wl/phy src/bcmcrypto
+WLAN_SrcIncDirs += src/wl/keymgmt/src src/wl/iocv/src
+WLAN_SrcIncDirs += $(PHY_MOD_SRC_DIRS)
+
+export WLAN_StdSrcDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_StdSrcDirs))
+export WLAN_StdIncDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_StdIncDirs))
+export WLAN_SrcIncDirsR  = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_SrcIncDirs))
+export WLAN_StdIncPathR	 = $(addprefix -I,$(WLAN_StdIncDirsR))
+export WLAN_IncDirsR	 = $(WLAN_StdIncDirsR) $(WLAN_SrcIncDirsR)
+export WLAN_IncPathR	 = $(addprefix -I,$(WLAN_IncDirsR))
+
+export WLAN_StdSrcDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_StdSrcDirs))
+export WLAN_StdIncDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_StdIncDirs))
+export WLAN_SrcIncDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_SrcIncDirs))
+export WLAN_StdIncPathA	 = $(addprefix -I,$(WLAN_StdIncDirsA))
+export WLAN_IncDirsA	 = $(WLAN_StdIncDirsA) $(WLAN_SrcIncDirsA)
+export WLAN_IncPathA	 = $(addprefix -I,$(WLAN_IncDirsA))
+
+# Public convenience macros based on WLAN_ComponentPathsInUse list.
+export WLAN_ComponentSrcDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_ComponentSrcPathsInUse))
+export WLAN_ComponentIncDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_ComponentIncPathsInUse))
+export WLAN_ComponentIncPathR	 = $(addprefix -I,$(WLAN_ComponentIncDirsR))
+
+export WLAN_ComponentSrcDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_ComponentSrcPathsInUse))
+export WLAN_ComponentIncDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_ComponentIncPathsInUse))
+export WLAN_ComponentIncPathA	 = $(addprefix -I,$(WLAN_ComponentIncDirsA))
+
+export WLAN_ComponentSrcDirs	 = $(WLAN_ComponentSrcDirsA)
+export WLAN_ComponentIncDirs	 = $(WLAN_ComponentIncDirsA)
+export WLAN_ComponentIncPath	 = $(WLAN_ComponentIncPathA)
+
+# Dump a representative sample of derived variables in debug mode.
+$(call wlan_dbgv, WLAN_TreeBaseA WLAN_TreeBaseR WLAN_SrcBaseA WLAN_SrcBaseR \
+    WLAN_ComponentPathsInUse WLAN_ComponentIncPath WLAN_ComponentIncPathR \
+    WLAN_ComponentSrcDirs WLAN_ComponentSrcDirsR)
+
+# Special case for Windows to reflect CL in the build log if used.
+ifdef WLAN_WINDOWS_HOST
+ifdef CL
+$(info Info: CL=$(CL))
+endif
+endif
+
+# A big hammer for debugging each shell invocation.
+# Warning: this can get lost if a sub-makefile sets SHELL explicitly, and
+# if so the parent should add $WLAN_ShellDebugSHELL to the call.
+ifeq ($D,2)
+WLAN_ShellDebug := 1
+endif
+ifdef WLAN_ShellDebug
+ORIG_SHELL := $(SHELL)
+SHELL = $(strip $(warning Shell: ORIG_SHELL=$(ORIG_SHELL) PATH=$(PATH))$(ORIG_SHELL)) -x
+WLAN_ShellDebugSHELL := SHELL='$$(warning Shell: ORIG_SHELL=$$(ORIG_SHELL) PATH=$$(PATH))$(ORIG_SHELL) -x'
+endif
+
+# Variables of general utility.
+WLAN_Perl := perl
+WLAN_Python := python
+WLAN_WINPFX ?= Z:
+
+# These macros are used to stash an extra copy of generated source files,
+# such that when a source release is made those files can be reconstituted
+# from the stash during builds. Required if the generating tools or inputs
+# are not shipped.
+define wlan_copy_to_gen
+  $(if $(WLAN_COPY_GEN),&& mkdir -p $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$(dir $(abspath $1))) && \
+    cp -pv $1 $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$(abspath $1).GEN))
+endef
+
+################################################################
+# CLM function; generates a rule to run ClmCompiler iff the XML exists.
+# USAGE: $(call WLAN_GenClmCompilerRule,target-dir,src-base[,flags[,ext]])
+#   This macro uses GNU make's eval function to generate an
+# explicit rule to generate a particular CLM data file each time
+# it's called. Make variables which should be evaluated during eval
+# processing get one $, those which must defer till "runtime" get $$.
+#   The CLM "base flags" are the default minimal set, the "ext flags"
+# are those which must be present for all release builds.
+# The "clm_compiled" phony target is provided for makefiles which need
+# to defer some other processing until CLM data is ready, and "clm_clean"
+# and "CLM_DATA_FILES" make it easier for internal client makefiles to
+# clean up CLM data (externally, this is treated as source and not removed).
+#   The outermost conditional allows this rule to become a no-op
+# in external settings where there is no XML input file while allowing
+# it to turn back on automatically if an XML file is provided.
+#   A vpath is used to find the XML input because this file is not allowed
+# to be present in external builds. Use of vpath allows it to be "poached"
+# from the internal build as necessary.
+#   There are a few ways to set ClmCompiler flags: passing them as the $3
+# parameter (preferred) or by overriding CLMCOMPDEFFLAGS. Additionally,
+# when the make variable CLM_TYPE is defined it points to a config file
+# for the compiler. The CLMCOMPEXTFLAGS variable contains "external flags"
+# which must be present for all external builds. It can be forced to "" for
+# debug builds.
+# Note: the .c file is listed with and without a path due to the way the
+# Linux kernel Makefiles generate .depend data.
+#   The undocumented $5 parameter has been used for dongle testing
+# against variant XML but its semantics are subject to change.
+CLMCOMPDEFFLAGS ?= --region '\#a/0' --region '\#r/0' --full_set
+CLMCOMPEXTFLAGS := --obfuscate
+define WLAN_GenClmCompilerRule
+$(eval\
+.PHONY: clm_compiled clm_clean
+vpath wlc_clm_data$4.c $1 $$(abspath $1)
+ifneq (,$(wildcard $(addsuffix /wl/clm/private/wlc_clm_data.xml,$2 $2/../../src $2/../../../src)))
+  vpath wlc_clm_data.xml $(wildcard $(addsuffix /wl/clm/private,$5 $2 $2/../../src $2/../../../src))
+  vpath %.clm $(addsuffix /wl/clm/types,$2 $2/../../src $2/../../../src)
+  $$(sort $1/wlc_clm_data$4.c ./wlc_clm_data$4.c): \
+      wlc_clm_data.xml $2/wl/clm/include/wlc_clm_data.h $$(wildcard $2/wl/clm/bin/ClmCompiler.py) $$(if $$(CLM_TYPE),$$(CLM_TYPE).clm) ; \
+    $$(strip $$(abspath $$(<D)/../../../tools/build/ClmCompiler) \
+      $$(if $$(CLM_TYPE),--config_file $$(lastword $$^) $3,$$(if $3,$3,$$(CLMCOMPDEFFLAGS))) \
+      $(CLMCOMPEXTFLAGS) $$< $$@ $$(call wlan_copy_to_gen,$$@,$2))
+else
+  vpath %.GEN $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$1) $(sort $(patsubst %/,%,$(dir $(wildcard $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$(dir $1))*/*.GEN))))
+  $1/%: %.GEN ; cp -pv $$< $$@
+endif
+  clm_compiled: $1/wlc_clm_data$4.c
+  clm_clean:: ; $$(RM) $1/wlc_clm_data$4.c
+  CLM_DATA_FILES += $1/wlc_clm_data$4.c
+)
+endef
+
+################################################################
+
+endif	# _WLAN_COMMON_MK
diff --git a/src/shared/bcm_app_utils.c b/src/shared/bcm_app_utils.c
new file mode 100644
index 0000000..430e6ea
--- /dev/null
+++ b/src/shared/bcm_app_utils.c
@@ -0,0 +1,229 @@
+/*
+ * Misc utility routines used by kernel or app-level.
+ * Contents are wifi-specific, used by any kernel or app-level
+ * software that might want wifi things as it grows.
+ *
+ * $Copyright Open Broadcom Corporation$
+ * $Id: bcm_app_utils.c 315295 2012-02-16 06:55:23Z $
+ */
+
+#include <typedefs.h>
+
+#ifdef BCMDRIVER
+#include <osl.h>
+#include <bcmutils.h>
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#else /* BCMDRIVER */
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+#endif /* BCMDRIVER */
+#include <bcmwifi_channels.h>
+
+#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
+#include <bcmstdlib.h> 	/* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
+#endif
+
+#include <bcmutils.h>
+#include <wlioctl.h>
+
+cca_congest_channel_req_t *
+cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg,
+	bool percent);
+
+int
+cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer);
+
+/* 	Take an array of measurments representing a single channel over time and return
+	a summary. Currently implemented as a simple average but could easily evolve
+	into more cpomplex alogrithms.
+*/
+cca_congest_channel_req_t *
+cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg, bool percent)
+{
+	int sec;
+	cca_congest_t totals;
+
+	totals.duration  = 0;
+	totals.congest_ibss  = 0;
+	totals.congest_obss  = 0;
+	totals.interference  = 0;
+	avg->num_secs = 0;
+
+	for (sec = 0; sec < input->num_secs; sec++) {
+		if (input->secs[sec].duration) {
+			totals.duration += input->secs[sec].duration;
+			totals.congest_ibss += input->secs[sec].congest_ibss;
+			totals.congest_obss += input->secs[sec].congest_obss;
+			totals.interference += input->secs[sec].interference;
+			avg->num_secs++;
+		}
+	}
+	avg->chanspec = input->chanspec;
+
+	if (!avg->num_secs || !totals.duration)
+		return (avg);
+
+	if (percent) {
+		avg->secs[0].duration = totals.duration / avg->num_secs;
+		avg->secs[0].congest_ibss = totals.congest_ibss * 100/totals.duration;
+		avg->secs[0].congest_obss = totals.congest_obss * 100/totals.duration;
+		avg->secs[0].interference = totals.interference * 100/totals.duration;
+	} else {
+		avg->secs[0].duration = totals.duration / avg->num_secs;
+		avg->secs[0].congest_ibss = totals.congest_ibss / avg->num_secs;
+		avg->secs[0].congest_obss = totals.congest_obss / avg->num_secs;
+		avg->secs[0].interference = totals.interference / avg->num_secs;
+	}
+
+	return (avg);
+}
+
+static void
+cca_info(uint8 *bitmap, int num_bits, int *left, int *bit_pos)
+{
+	int i;
+	for (*left = 0, i = 0; i < num_bits; i++) {
+		if (isset(bitmap, i)) {
+			(*left)++;
+			*bit_pos = i;
+		}
+	}
+}
+
+static uint8
+spec_to_chan(chanspec_t chspec)
+{
+	uint8 center_ch, edge, primary, sb;
+
+	center_ch = CHSPEC_CHANNEL(chspec);
+
+	if (CHSPEC_IS20(chspec)) {
+		return center_ch;
+	} else {
+		/* the lower edge of the wide channel is half the bw from
+		 * the center channel.
+		 */
+		if (CHSPEC_IS40(chspec)) {
+			edge = center_ch - CH_20MHZ_APART;
+		} else {
+			/* must be 80MHz (until we support more) */
+			ASSERT(CHSPEC_IS80(chspec));
+			edge = center_ch - CH_40MHZ_APART;
+		}
+
+		/* find the channel number of the lowest 20MHz primary channel */
+		primary = edge + CH_10MHZ_APART;
+
+		/* select the actual subband */
+		sb = (chspec & WL_CHANSPEC_CTL_SB_MASK) >> WL_CHANSPEC_CTL_SB_SHIFT;
+		primary = primary + sb * CH_20MHZ_APART;
+
+		return primary;
+	}
+}
+
+#define CCA_THRESH_MILLI	14
+#define CCA_THRESH_INTERFERE	6
+
+/*
+	Take an array of measumrements representing summaries of different channels.
+	Return a recomended channel.
+	Interference is evil, get rid of that first.
+	Then hunt for lowest Other bss traffic.
+	Don't forget that channels with low duration times may not have accurate readings.
+	For the moment, do not overwrite input array.
+*/
+int
+cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer)
+{
+	uint8 bitmap[CEIL(MAX_CCA_CHANNELS, NBBY)];	/* 38 Max channels needs 5 bytes  = 40 */
+	int i, left, winner;
+	uint32 min_obss = 1 << 30;
+
+	ASSERT(num_chans < MAX_CCA_CHANNELS);
+	for (i = 0; i < (int)sizeof(bitmap); i++)
+		bitmap[i] = 0;
+
+	/* Initially, all channels are up for consideration */
+	for (i = 0; i < num_chans; i++) {
+		if (input[i]->chanspec)
+			setbit(bitmap, i);
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left)
+		return CCA_ERRNO_TOO_FEW;
+
+	/* Filter for 2.4 GHz Band */
+	if (flags & CCA_FLAG_2G_ONLY) {
+		for (i = 0; i < num_chans; i++) {
+			if (!CHSPEC_IS2G(input[i]->chanspec))
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left)
+		return CCA_ERRNO_BAND;
+
+	/* Filter for 5 GHz Band */
+	if (flags & CCA_FLAG_5G_ONLY) {
+		for (i = 0; i < num_chans; i++) {
+			if (!CHSPEC_IS5G(input[i]->chanspec))
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left)
+		return CCA_ERRNO_BAND;
+
+	/* Filter for Duration */
+	if (!(flags & CCA_FLAG_IGNORE_DURATION)) {
+		for (i = 0; i < num_chans; i++) {
+			if (input[i]->secs[0].duration < CCA_THRESH_MILLI)
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left)
+		return CCA_ERRNO_DURATION;
+
+	/* Filter for 1 6 11 on 2.4 Band */
+	if (flags &  CCA_FLAGS_PREFER_1_6_11) {
+		int tmp_channel = spec_to_chan(input[i]->chanspec);
+		int is2g = CHSPEC_IS2G(input[i]->chanspec);
+		for (i = 0; i < num_chans; i++) {
+			if (is2g && tmp_channel != 1 && tmp_channel != 6 && tmp_channel != 11)
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left)
+		return CCA_ERRNO_PREF_CHAN;
+
+	/* Toss high interference interference */
+	if (!(flags & CCA_FLAG_IGNORE_INTERFER)) {
+		for (i = 0; i < num_chans; i++) {
+			if (input[i]->secs[0].interference > CCA_THRESH_INTERFERE)
+				clrbit(bitmap, i);
+		}
+		cca_info(bitmap, num_chans, &left, &i);
+		if (!left)
+			return CCA_ERRNO_INTERFER;
+	}
+
+	/* Now find lowest obss */
+	winner = 0;
+	for (i = 0; i < num_chans; i++) {
+		if (isset(bitmap, i) && input[i]->secs[0].congest_obss < min_obss) {
+			winner = i;
+			min_obss = input[i]->secs[0].congest_obss;
+		}
+	}
+	*answer = input[winner]->chanspec;
+
+	return 0;
+}
diff --git a/src/shared/bcmutils.c b/src/shared/bcmutils.c
new file mode 100644
index 0000000..524bdb6
--- /dev/null
+++ b/src/shared/bcmutils.c
@@ -0,0 +1,3102 @@
+/*
+ * Driver O/S-independent utility routines
+ *
+ * $Copyright Open Broadcom Corporation$
+ * $Id: bcmutils.c 461404 2014-03-12 01:59:36Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <stdarg.h>
+#ifdef BCMDRIVER
+
+#include <osl.h>
+#include <bcmutils.h>
+#if defined(BCMNVRAM)
+#include <siutils.h>
+#include <bcmnvram.h>
+#endif
+
+#else /* !BCMDRIVER */
+
+#include <stdio.h>
+#include <string.h>
+#include <bcmutils.h>
+
+#if defined(BCMEXTSUP)
+#include <bcm_osl.h>
+#endif
+
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+
+#endif /* !BCMDRIVER */
+
+#include <bcmendian.h>
+#include <bcmdevs.h>
+#include <proto/ethernet.h>
+#include <proto/vlan.h>
+#include <proto/bcmip.h>
+#include <proto/802.1d.h>
+#include <proto/802.11.h>
+
+
+void *_bcmutils_dummy_fn = NULL;
+
+
+#ifdef CUSTOM_DSCP_TO_PRIO_MAPPING
+#define CUST_IPV4_TOS_PREC_MASK 0x3F
+#define DCSP_MAX_VALUE 64
+extern uint dhd_dscpmap_enable;
+/* 0:BE,1:BK,2:RESV(BK):,3:EE,:4:CL,5:VI,6:VO,7:NC */
+int dscp2priomap[DCSP_MAX_VALUE]=
+{
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	2, 0, 0, 0, 0, 0, 0, 0,
+	3, 0, 0, 0, 0, 0, 0, 0,
+	4, 0, 0, 0, 0, 0, 0, 0,
+	5, 0, 0, 0, 0, 0, 0, 0,
+	6, 0, 0, 0, 0, 0, 0, 0,
+	7, 0, 0, 0, 0, 0, 0, 0
+};
+#endif /* CUSTOM_DSCP_TO_PRIO_MAPPING */
+
+#ifdef BCMDRIVER
+
+
+
+/* copy a pkt buffer chain into a buffer */
+uint
+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
+{
+	uint n, ret = 0;
+
+	if (len < 0)
+		len = 4096;	/* "infinite" */
+
+	/* skip 'offset' bytes */
+	for (; p && offset; p = PKTNEXT(osh, p)) {
+		if (offset < (uint)PKTLEN(osh, p))
+			break;
+		offset -= PKTLEN(osh, p);
+	}
+
+	if (!p)
+		return 0;
+
+	/* copy the data */
+	for (; p && len; p = PKTNEXT(osh, p)) {
+		n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
+		bcopy(PKTDATA(osh, p) + offset, buf, n);
+		buf += n;
+		len -= n;
+		ret += n;
+		offset = 0;
+	}
+
+	return ret;
+}
+
+/* copy a buffer into a pkt buffer chain */
+uint
+pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
+{
+	uint n, ret = 0;
+
+
+	/* skip 'offset' bytes */
+	for (; p && offset; p = PKTNEXT(osh, p)) {
+		if (offset < (uint)PKTLEN(osh, p))
+			break;
+		offset -= PKTLEN(osh, p);
+	}
+
+	if (!p)
+		return 0;
+
+	/* copy the data */
+	for (; p && len; p = PKTNEXT(osh, p)) {
+		n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
+		bcopy(buf, PKTDATA(osh, p) + offset, n);
+		buf += n;
+		len -= n;
+		ret += n;
+		offset = 0;
+	}
+
+	return ret;
+}
+
+
+
+/* return total length of buffer chain */
+uint BCMFASTPATH
+pkttotlen(osl_t *osh, void *p)
+{
+	uint total;
+	int len;
+
+	total = 0;
+	for (; p; p = PKTNEXT(osh, p)) {
+		len = PKTLEN(osh, p);
+		total += len;
+#ifdef BCMLFRAG
+		if (BCMLFRAG_ENAB()) {
+			if (PKTISFRAG(osh, p)) {
+				total += PKTFRAGTOTLEN(osh, p);
+			}
+		}
+#endif
+	}
+
+	return (total);
+}
+
+/* return the last buffer of chained pkt */
+void *
+pktlast(osl_t *osh, void *p)
+{
+	for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p))
+		;
+
+	return (p);
+}
+
+/* count segments of a chained packet */
+uint BCMFASTPATH
+pktsegcnt(osl_t *osh, void *p)
+{
+	uint cnt;
+
+	for (cnt = 0; p; p = PKTNEXT(osh, p)) {
+		cnt++;
+#ifdef BCMLFRAG
+		if (BCMLFRAG_ENAB()) {
+			if (PKTISFRAG(osh, p)) {
+				cnt += PKTFRAGTOTNUM(osh, p);
+			}
+		}
+#endif
+	}
+
+	return cnt;
+}
+
+
+/* count segments of a chained packet */
+uint BCMFASTPATH
+pktsegcnt_war(osl_t *osh, void *p)
+{
+	uint cnt;
+	uint8 *pktdata;
+	uint len, remain, align64;
+
+	for (cnt = 0; p; p = PKTNEXT(osh, p)) {
+		cnt++;
+		len = PKTLEN(osh, p);
+		if (len > 128) {
+			pktdata = (uint8 *)PKTDATA(osh, p);	/* starting address of data */
+			/* Check for page boundary straddle (2048B) */
+			if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff))
+				cnt++;
+
+			align64 = (uint)((uintptr)pktdata & 0x3f);	/* aligned to 64B */
+			align64 = (64 - align64) & 0x3f;
+			len -= align64;		/* bytes from aligned 64B to end */
+			/* if aligned to 128B, check for MOD 128 between 1 to 4B */
+			remain = len % 128;
+			if (remain > 0 && remain <= 4)
+				cnt++;		/* add extra seg */
+		}
+	}
+
+	return cnt;
+}
+
+uint8 * BCMFASTPATH
+pktdataoffset(osl_t *osh, void *p,  uint offset)
+{
+	uint total = pkttotlen(osh, p);
+	uint pkt_off = 0, len = 0;
+	uint8 *pdata = (uint8 *) PKTDATA(osh, p);
+
+	if (offset > total)
+		return NULL;
+
+	for (; p; p = PKTNEXT(osh, p)) {
+		pdata = (uint8 *) PKTDATA(osh, p);
+		pkt_off = offset - len;
+		len += PKTLEN(osh, p);
+		if (len > offset)
+			break;
+	}
+	return (uint8*) (pdata+pkt_off);
+}
+
+
+/* given a offset in pdata, find the pkt seg hdr */
+void *
+pktoffset(osl_t *osh, void *p,  uint offset)
+{
+	uint total = pkttotlen(osh, p);
+	uint len = 0;
+
+	if (offset > total)
+		return NULL;
+
+	for (; p; p = PKTNEXT(osh, p)) {
+		len += PKTLEN(osh, p);
+		if (len > offset)
+			break;
+	}
+	return p;
+}
+
+/*
+ * osl multiple-precedence packet queue
+ * hi_prec is always >= the number of the highest non-empty precedence
+ */
+void * BCMFASTPATH
+pktq_penq(struct pktq *pq, int prec, void *p)
+{
+	struct pktq_prec *q;
+
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+	/* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */
+	ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p)));
+
+	ASSERT(!pktq_full(pq));
+	ASSERT(!pktq_pfull(pq, prec));
+
+	q = &pq->q[prec];
+
+	PKTSETLINK(p, NULL);
+	if (q->head)
+		PKTSETLINK(q->tail, p);
+	else
+		q->head = p;
+
+	q->tail = p;
+	q->len++;
+
+	pq->len++;
+
+	if (pq->hi_prec < prec)
+		pq->hi_prec = (uint8)prec;
+
+	return p;
+}
+
+void * BCMFASTPATH
+pktq_penq_head(struct pktq *pq, int prec, void *p)
+{
+	struct pktq_prec *q;
+
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+	/* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */
+	ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p)));
+
+	ASSERT(!pktq_full(pq));
+	ASSERT(!pktq_pfull(pq, prec));
+
+	q = &pq->q[prec];
+
+	PKTSETLINK(p, NULL);
+	if (q->head == NULL)
+		q->tail = p;
+
+	PKTSETLINK(p, q->head);
+	q->head = p;
+	q->len++;
+
+	pq->len++;
+
+	if (pq->hi_prec < prec)
+		pq->hi_prec = (uint8)prec;
+
+	return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq(struct pktq *pq, int prec)
+{
+	struct pktq_prec *q;
+	void *p;
+
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+
+	q = &pq->q[prec];
+
+	if ((p = q->head) == NULL)
+		return NULL;
+
+	if ((q->head = PKTLINK(p)) == NULL)
+		q->tail = NULL;
+
+	q->len--;
+
+	pq->len--;
+
+	PKTSETLINK(p, NULL);
+
+	return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
+{
+	struct pktq_prec *q;
+	void *p;
+
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+
+	q = &pq->q[prec];
+
+	if (prev_p == NULL)
+		return NULL;
+
+	if ((p = PKTLINK(prev_p)) == NULL)
+		return NULL;
+
+	q->len--;
+
+	pq->len--;
+
+	PKTSETLINK(prev_p, PKTLINK(p));
+	PKTSETLINK(p, NULL);
+
+	return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg)
+{
+	struct pktq_prec *q;
+	void *p, *prev = NULL;
+
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+
+	q = &pq->q[prec];
+	p = q->head;
+
+	while (p) {
+		if (fn == NULL || (*fn)(p, arg)) {
+			break;
+		} else {
+			prev = p;
+			p = PKTLINK(p);
+		}
+	}
+	if (p == NULL)
+		return NULL;
+
+	if (prev == NULL) {
+		if ((q->head = PKTLINK(p)) == NULL) {
+			q->tail = NULL;
+		}
+	} else {
+		PKTSETLINK(prev, PKTLINK(p));
+		if (q->tail == p) {
+			q->tail = prev;
+		}
+	}
+
+	q->len--;
+
+	pq->len--;
+
+	PKTSETLINK(p, NULL);
+
+	return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq_tail(struct pktq *pq, int prec)
+{
+	struct pktq_prec *q;
+	void *p, *prev;
+
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+
+	q = &pq->q[prec];
+
+	if ((p = q->head) == NULL)
+		return NULL;
+
+	for (prev = NULL; p != q->tail; p = PKTLINK(p))
+		prev = p;
+
+	if (prev)
+		PKTSETLINK(prev, NULL);
+	else
+		q->head = NULL;
+
+	q->tail = prev;
+	q->len--;
+
+	pq->len--;
+
+	return p;
+}
+
+void
+pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg)
+{
+	struct pktq_prec *q;
+	void *p, *prev = NULL;
+
+	q = &pq->q[prec];
+	p = q->head;
+	while (p) {
+		if (fn == NULL || (*fn)(p, arg)) {
+			bool head = (p == q->head);
+			if (head)
+				q->head = PKTLINK(p);
+			else
+				PKTSETLINK(prev, PKTLINK(p));
+			PKTSETLINK(p, NULL);
+			PKTFREE(osh, p, dir);
+			q->len--;
+			pq->len--;
+			p = (head ? q->head : PKTLINK(prev));
+		} else {
+			prev = p;
+			p = PKTLINK(p);
+		}
+	}
+
+	if (q->head == NULL) {
+		ASSERT(q->len == 0);
+		q->tail = NULL;
+	}
+}
+
+bool BCMFASTPATH
+pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
+{
+	struct pktq_prec *q;
+	void *p;
+
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+
+	if (!pktbuf)
+		return FALSE;
+
+	q = &pq->q[prec];
+
+	if (q->head == pktbuf) {
+		if ((q->head = PKTLINK(pktbuf)) == NULL)
+			q->tail = NULL;
+	} else {
+		for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
+			;
+		if (p == NULL)
+			return FALSE;
+
+		PKTSETLINK(p, PKTLINK(pktbuf));
+		if (q->tail == pktbuf)
+			q->tail = p;
+	}
+
+	q->len--;
+	pq->len--;
+	PKTSETLINK(pktbuf, NULL);
+	return TRUE;
+}
+
+void
+pktq_init(struct pktq *pq, int num_prec, int max_len)
+{
+	int prec;
+
+	ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
+
+	/* pq is variable size; only zero out what's requested */
+	bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
+
+	pq->num_prec = (uint16)num_prec;
+
+	pq->max = (uint16)max_len;
+
+	for (prec = 0; prec < num_prec; prec++)
+		pq->q[prec].max = pq->max;
+}
+
+void
+pktq_set_max_plen(struct pktq *pq, int prec, int max_len)
+{
+	ASSERT(prec >= 0 && prec < pq->num_prec);
+
+	if (prec < pq->num_prec)
+		pq->q[prec].max = (uint16)max_len;
+}
+
+void * BCMFASTPATH
+pktq_deq(struct pktq *pq, int *prec_out)
+{
+	struct pktq_prec *q;
+	void *p;
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+		pq->hi_prec--;
+
+	q = &pq->q[prec];
+
+	if ((p = q->head) == NULL)
+		return NULL;
+
+	if ((q->head = PKTLINK(p)) == NULL)
+		q->tail = NULL;
+
+	q->len--;
+
+	pq->len--;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	PKTSETLINK(p, NULL);
+
+	return p;
+}
+
+void * BCMFASTPATH
+pktq_deq_tail(struct pktq *pq, int *prec_out)
+{
+	struct pktq_prec *q;
+	void *p, *prev;
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	for (prec = 0; prec < pq->hi_prec; prec++)
+		if (pq->q[prec].head)
+			break;
+
+	q = &pq->q[prec];
+
+	if ((p = q->head) == NULL)
+		return NULL;
+
+	for (prev = NULL; p != q->tail; p = PKTLINK(p))
+		prev = p;
+
+	if (prev)
+		PKTSETLINK(prev, NULL);
+	else
+		q->head = NULL;
+
+	q->tail = prev;
+	q->len--;
+
+	pq->len--;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	PKTSETLINK(p, NULL);
+
+	return p;
+}
+
+void *
+pktq_peek(struct pktq *pq, int *prec_out)
+{
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+		pq->hi_prec--;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	return (pq->q[prec].head);
+}
+
+void *
+pktq_peek_tail(struct pktq *pq, int *prec_out)
+{
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	for (prec = 0; prec < pq->hi_prec; prec++)
+		if (pq->q[prec].head)
+			break;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	return (pq->q[prec].tail);
+}
+
+void
+pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg)
+{
+	int prec;
+
+	/* Optimize flush, if pktq len = 0, just return.
+	 * pktq len of 0 means pktq's prec q's are all empty.
+	 */
+	if (pq->len == 0) {
+		return;
+	}
+
+	for (prec = 0; prec < pq->num_prec; prec++)
+		pktq_pflush(osh, pq, prec, dir, fn, arg);
+	if (fn == NULL)
+		ASSERT(pq->len == 0);
+}
+
+/* Return sum of lengths of a specific set of precedences */
+int
+pktq_mlen(struct pktq *pq, uint prec_bmp)
+{
+	int prec, len;
+
+	len = 0;
+
+	for (prec = 0; prec <= pq->hi_prec; prec++)
+		if (prec_bmp & (1 << prec))
+			len += pq->q[prec].len;
+
+	return len;
+}
+
+/* Priority peek from a specific set of precedences */
+void * BCMFASTPATH
+pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
+{
+	struct pktq_prec *q;
+	void *p;
+	int prec;
+
+	if (pq->len == 0)
+	{
+		return NULL;
+	}
+	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+		pq->hi_prec--;
+
+	while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
+		if (prec-- == 0)
+			return NULL;
+
+	q = &pq->q[prec];
+
+	if ((p = q->head) == NULL)
+		return NULL;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	return p;
+}
+/* Priority dequeue from a specific set of precedences */
+void * BCMFASTPATH
+pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
+{
+	struct pktq_prec *q;
+	void *p;
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+		pq->hi_prec--;
+
+	while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0))
+		if (prec-- == 0)
+			return NULL;
+
+	q = &pq->q[prec];
+
+	if ((p = q->head) == NULL)
+		return NULL;
+
+	if ((q->head = PKTLINK(p)) == NULL)
+		q->tail = NULL;
+
+	q->len--;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	pq->len--;
+
+	PKTSETLINK(p, NULL);
+
+	return p;
+}
+
+#endif /* BCMDRIVER */
+
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
+const unsigned char bcm_ctype[] = {
+
+	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 0-7 */
+	_BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
+	_BCM_C,	/* 8-15 */
+	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 16-23 */
+	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 24-31 */
+	_BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,		/* 32-39 */
+	_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 40-47 */
+	_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,			/* 48-55 */
+	_BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 56-63 */
+	_BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
+	_BCM_U|_BCM_X, _BCM_U, /* 64-71 */
+	_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,			/* 72-79 */
+	_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,			/* 80-87 */
+	_BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 88-95 */
+	_BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
+	_BCM_L|_BCM_X, _BCM_L, /* 96-103 */
+	_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
+	_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
+	_BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* 128-143 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* 144-159 */
+	_BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
+	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,	/* 160-175 */
+	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
+	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,	/* 176-191 */
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,	/* 192-207 */
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L,	/* 208-223 */
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,	/* 224-239 */
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
+};
+
+ulong
+BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base)
+{
+	ulong result, last_result = 0, value;
+	bool minus;
+
+	minus = FALSE;
+
+	while (bcm_isspace(*cp))
+		cp++;
+
+	if (cp[0] == '+')
+		cp++;
+	else if (cp[0] == '-') {
+		minus = TRUE;
+		cp++;
+	}
+
+	if (base == 0) {
+		if (cp[0] == '0') {
+			if ((cp[1] == 'x') || (cp[1] == 'X')) {
+				base = 16;
+				cp = &cp[2];
+			} else {
+				base = 8;
+				cp = &cp[1];
+			}
+		} else
+			base = 10;
+	} else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
+		cp = &cp[2];
+	}
+
+	result = 0;
+
+	while (bcm_isxdigit(*cp) &&
+	       (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
+		result = result*base + value;
+		/* Detected overflow */
+		if (result < last_result && !minus)
+			return (ulong)-1;
+		last_result = result;
+		cp++;
+	}
+
+	if (minus)
+		result = (ulong)(-(long)result);
+
+	if (endp)
+		*endp = DISCARD_QUAL(cp, char);
+
+	return (result);
+}
+
+int
+BCMROMFN(bcm_atoi)(const char *s)
+{
+	return (int)bcm_strtoul(s, NULL, 10);
+}
+
+/* return pointer to location of substring 'needle' in 'haystack' */
+char *
+BCMROMFN(bcmstrstr)(const char *haystack, const char *needle)
+{
+	int len, nlen;
+	int i;
+
+	if ((haystack == NULL) || (needle == NULL))
+		return DISCARD_QUAL(haystack, char);
+
+	nlen = strlen(needle);
+	len = strlen(haystack) - nlen + 1;
+
+	for (i = 0; i < len; i++)
+		if (memcmp(needle, &haystack[i], nlen) == 0)
+			return DISCARD_QUAL(&haystack[i], char);
+	return (NULL);
+}
+
+char *
+BCMROMFN(bcmstrcat)(char *dest, const char *src)
+{
+	char *p;
+
+	p = dest + strlen(dest);
+
+	while ((*p++ = *src++) != '\0')
+		;
+
+	return (dest);
+}
+
+char *
+BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size)
+{
+	char *endp;
+	char *p;
+
+	p = dest + strlen(dest);
+	endp = p + size;
+
+	while (p != endp && (*p++ = *src++) != '\0')
+		;
+
+	return (dest);
+}
+
+
+/****************************************************************************
+* Function:   bcmstrtok
+*
+* Purpose:
+*  Tokenizes a string. This function is conceptually similiar to ANSI C strtok(),
+*  but allows strToken() to be used by different strings or callers at the same
+*  time. Each call modifies '*string' by substituting a NULL character for the
+*  first delimiter that is encountered, and updates 'string' to point to the char
+*  after the delimiter. Leading delimiters are skipped.
+*
+* Parameters:
+*  string      (mod) Ptr to string ptr, updated by token.
+*  delimiters  (in)  Set of delimiter characters.
+*  tokdelim    (out) Character that delimits the returned token. (May
+*                    be set to NULL if token delimiter is not required).
+*
+* Returns:  Pointer to the next token found. NULL when no more tokens are found.
+*****************************************************************************
+*/
+char *
+bcmstrtok(char **string, const char *delimiters, char *tokdelim)
+{
+	unsigned char *str;
+	unsigned long map[8];
+	int count;
+	char *nextoken;
+
+	if (tokdelim != NULL) {
+		/* Prime the token delimiter */
+		*tokdelim = '\0';
+	}
+
+	/* Clear control map */
+	for (count = 0; count < 8; count++) {
+		map[count] = 0;
+	}
+
+	/* Set bits in delimiter table */
+	do {
+		map[*delimiters >> 5] |= (1 << (*delimiters & 31));
+	}
+	while (*delimiters++);
+
+	str = (unsigned char*)*string;
+
+	/* Find beginning of token (skip over leading delimiters). Note that
+	 * there is no token iff this loop sets str to point to the terminal
+	 * null (*str == '\0')
+	 */
+	while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) {
+		str++;
+	}
+
+	nextoken = (char*)str;
+
+	/* Find the end of the token. If it is not the end of the string,
+	 * put a null there.
+	 */
+	for (; *str; str++) {
+		if (map[*str >> 5] & (1 << (*str & 31))) {
+			if (tokdelim != NULL) {
+				*tokdelim = *str;
+			}
+
+			*str++ = '\0';
+			break;
+		}
+	}
+
+	*string = (char*)str;
+
+	/* Determine if a token has been found. */
+	if (nextoken == (char *) str) {
+		return NULL;
+	}
+	else {
+		return nextoken;
+	}
+}
+
+
+#define xToLower(C) \
+	((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
+
+
+/****************************************************************************
+* Function:   bcmstricmp
+*
+* Purpose:    Compare to strings case insensitively.
+*
+* Parameters: s1 (in) First string to compare.
+*             s2 (in) Second string to compare.
+*
+* Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
+*             t1 > t2, when ignoring case sensitivity.
+*****************************************************************************
+*/
+int
+bcmstricmp(const char *s1, const char *s2)
+{
+	char dc, sc;
+
+	while (*s2 && *s1) {
+		dc = xToLower(*s1);
+		sc = xToLower(*s2);
+		if (dc < sc) return -1;
+		if (dc > sc) return 1;
+		s1++;
+		s2++;
+	}
+
+	if (*s1 && !*s2) return 1;
+	if (!*s1 && *s2) return -1;
+	return 0;
+}
+
+
+/****************************************************************************
+* Function:   bcmstrnicmp
+*
+* Purpose:    Compare to strings case insensitively, upto a max of 'cnt'
+*             characters.
+*
+* Parameters: s1  (in) First string to compare.
+*             s2  (in) Second string to compare.
+*             cnt (in) Max characters to compare.
+*
+* Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
+*             t1 > t2, when ignoring case sensitivity.
+*****************************************************************************
+*/
+int
+bcmstrnicmp(const char* s1, const char* s2, int cnt)
+{
+	char dc, sc;
+
+	while (*s2 && *s1 && cnt) {
+		dc = xToLower(*s1);
+		sc = xToLower(*s2);
+		if (dc < sc) return -1;
+		if (dc > sc) return 1;
+		s1++;
+		s2++;
+		cnt--;
+	}
+
+	if (!cnt) return 0;
+	if (*s1 && !*s2) return 1;
+	if (!*s1 && *s2) return -1;
+	return 0;
+}
+
+/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
+int
+BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea)
+{
+	int i = 0;
+	char *ep;
+
+	for (;;) {
+		ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16);
+		p = ep;
+		if (!*p++ || i == 6)
+			break;
+	}
+
+	return (i == 6);
+}
+
+int
+BCMROMFN(bcm_atoipv4)(const char *p, struct ipv4_addr *ip)
+{
+
+	int i = 0;
+	char *c;
+	for (;;) {
+		ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0);
+		if (*c++ != '.' || i == IPV4_ADDR_LEN)
+			break;
+		p = c;
+	}
+	return (i == IPV4_ADDR_LEN);
+}
+#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
+
+
+#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
+/* registry routine buffer preparation utility functions:
+ * parameter order is like strncpy, but returns count
+ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
+ */
+ulong
+wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen)
+{
+	ulong copyct = 1;
+	ushort i;
+
+	if (abuflen == 0)
+		return 0;
+
+	/* wbuflen is in bytes */
+	wbuflen /= sizeof(ushort);
+
+	for (i = 0; i < wbuflen; ++i) {
+		if (--abuflen == 0)
+			break;
+		*abuf++ = (char) *wbuf++;
+		++copyct;
+	}
+	*abuf = '\0';
+
+	return copyct;
+}
+#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
+
+char *
+bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
+{
+	static const char hex[] =
+	  {
+		  '0', '1', '2', '3', '4', '5', '6', '7',
+		  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+	  };
+	const uint8 *octet = ea->octet;
+	char *p = buf;
+	int i;
+
+	for (i = 0; i < 6; i++, octet++) {
+		*p++ = hex[(*octet >> 4) & 0xf];
+		*p++ = hex[*octet & 0xf];
+		*p++ = ':';
+	}
+
+	*(p-1) = '\0';
+
+	return (buf);
+}
+
+char *
+bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
+{
+	snprintf(buf, 16, "%d.%d.%d.%d",
+	         ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
+	return (buf);
+}
+
+char *
+bcm_ipv6_ntoa(void *ipv6, char *buf)
+{
+	/* Implementing RFC 5952 Sections 4 + 5 */
+	/* Not thoroughly tested */
+	uint16 tmp[8];
+	uint16 *a = &tmp[0];
+	char *p = buf;
+	int i, i_max = -1, cnt = 0, cnt_max = 1;
+	uint8 *a4 = NULL;
+	memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if (a[i]) {
+			if (cnt > cnt_max) {
+				cnt_max = cnt;
+				i_max = i - cnt;
+			}
+			cnt = 0;
+		} else
+			cnt++;
+	}
+	if (cnt > cnt_max) {
+		cnt_max = cnt;
+		i_max = i - cnt;
+	}
+	if (i_max == 0 &&
+		/* IPv4-translated: ::ffff:0:a.b.c.d */
+		((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
+		/* IPv4-mapped: ::ffff:a.b.c.d */
+		(cnt_max == 5 && a[5] == 0xffff)))
+		a4 = (uint8*) (a + 6);
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if ((uint8*) (a + i) == a4) {
+			snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
+			break;
+		} else if (i == i_max) {
+			*p++ = ':';
+			i += cnt_max - 1;
+			p[0] = ':';
+			p[1] = '\0';
+		} else {
+			if (i)
+				*p++ = ':';
+			p += snprintf(p, 8, "%x", ntoh16(a[i]));
+		}
+	}
+
+	return buf;
+}
+#ifdef BCMDRIVER
+
+void
+bcm_mdelay(uint ms)
+{
+	uint i;
+
+	for (i = 0; i < ms; i++) {
+		OSL_DELAY(1000);
+	}
+}
+
+
+
+
+
+#if defined(DHD_DEBUG)
+/* pretty hex print a pkt buffer chain */
+void
+prpkt(const char *msg, osl_t *osh, void *p0)
+{
+	void *p;
+
+	if (msg && (msg[0] != '\0'))
+		printf("%s:\n", msg);
+
+	for (p = p0; p; p = PKTNEXT(osh, p))
+		prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p));
+}
+#endif	
+
+/* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
+ * Also updates the inplace vlan tag if requested.
+ * For debugging, it returns an indication of what it did.
+ */
+uint BCMFASTPATH
+pktsetprio(void *pkt, bool update_vtag)
+{
+	struct ether_header *eh;
+	struct ethervlan_header *evh;
+	uint8 *pktdata;
+	int priority = 0;
+	int rc = 0;
+
+	pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
+	ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
+
+	eh = (struct ether_header *) pktdata;
+
+	if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
+		uint16 vlan_tag;
+		int vlan_prio, dscp_prio = 0;
+
+		evh = (struct ethervlan_header *)eh;
+
+		vlan_tag = ntoh16(evh->vlan_tag);
+		vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+
+		if (evh->ether_type == hton16(ETHER_TYPE_IP)) {
+			uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
+			uint8 tos_tc = IP_TOS46(ip_body);
+			dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+		}
+
+		/* DSCP priority gets precedence over 802.1P (vlan tag) */
+		if (dscp_prio != 0) {
+			priority = dscp_prio;
+			rc |= PKTPRIO_VDSCP;
+		} else {
+			priority = vlan_prio;
+			rc |= PKTPRIO_VLAN;
+		}
+		/*
+		 * If the DSCP priority is not the same as the VLAN priority,
+		 * then overwrite the priority field in the vlan tag, with the
+		 * DSCP priority value. This is required for Linux APs because
+		 * the VLAN driver on Linux, overwrites the skb->priority field
+		 * with the priority value in the vlan tag
+		 */
+		if (update_vtag && (priority != vlan_prio)) {
+			vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
+			vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
+			evh->vlan_tag = hton16(vlan_tag);
+			rc |= PKTPRIO_UPD;
+		}
+	} else if (eh->ether_type == hton16(ETHER_TYPE_IP)) {
+		uint8 *ip_body = pktdata + sizeof(struct ether_header);
+		uint8 tos_tc = IP_TOS46(ip_body);
+		uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
+		switch (dscp) {
+		case DSCP_EF:
+			priority = PRIO_8021D_VO;
+			break;
+		case DSCP_AF31:
+		case DSCP_AF32:
+		case DSCP_AF33:
+			priority = PRIO_8021D_CL;
+			break;
+		case DSCP_AF21:
+		case DSCP_AF22:
+		case DSCP_AF23:
+		case DSCP_AF11:
+		case DSCP_AF12:
+		case DSCP_AF13:
+			priority = PRIO_8021D_EE;
+			break;
+		default:
+#ifndef CUSTOM_DSCP_TO_PRIO_MAPPING
+			priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+#else
+			if (dhd_dscpmap_enable) {
+				priority = (int)dscp2priomap[((tos_tc >> IPV4_TOS_DSCP_SHIFT)
+					& CUST_IPV4_TOS_PREC_MASK)];
+			}
+			else {
+				priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+			}
+#endif /* CUSTOM_DSCP_TO_PRIO_MAPPING */
+			break;
+		}
+
+		rc |= PKTPRIO_DSCP;
+	}
+
+	ASSERT(priority >= 0 && priority <= MAXPRIO);
+	PKTSETPRIO(pkt, priority);
+	return (rc | priority);
+}
+
+
+static char bcm_undeferrstr[32];
+static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
+
+/* Convert the error codes into related error strings  */
+const char *
+bcmerrorstr(int bcmerror)
+{
+	/* check if someone added a bcmerror code but forgot to add errorstring */
+	ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
+
+	if (bcmerror > 0 || bcmerror < BCME_LAST) {
+		snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
+		return bcm_undeferrstr;
+	}
+
+	ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
+
+	return bcmerrorstrtable[-bcmerror];
+}
+
+
+
+/* iovar table lookup */
+const bcm_iovar_t*
+bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
+{
+	const bcm_iovar_t *vi;
+	const char *lookup_name;
+
+	/* skip any ':' delimited option prefixes */
+	lookup_name = strrchr(name, ':');
+	if (lookup_name != NULL)
+		lookup_name++;
+	else
+		lookup_name = name;
+
+	ASSERT(table != NULL);
+
+	for (vi = table; vi->name; vi++) {
+		if (!strcmp(vi->name, lookup_name))
+			return vi;
+	}
+	/* ran to end of table */
+
+	return NULL; /* var name not found */
+}
+
+int
+bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
+{
+	int bcmerror = 0;
+
+	/* length check on io buf */
+	switch (vi->type) {
+	case IOVT_BOOL:
+	case IOVT_INT8:
+	case IOVT_INT16:
+	case IOVT_INT32:
+	case IOVT_UINT8:
+	case IOVT_UINT16:
+	case IOVT_UINT32:
+		/* all integers are int32 sized args at the ioctl interface */
+		if (len < (int)sizeof(int)) {
+			bcmerror = BCME_BUFTOOSHORT;
+		}
+		break;
+
+	case IOVT_BUFFER:
+		/* buffer must meet minimum length requirement */
+		if (len < vi->minlen) {
+			bcmerror = BCME_BUFTOOSHORT;
+		}
+		break;
+
+	case IOVT_VOID:
+		if (!set) {
+			/* Cannot return nil... */
+			bcmerror = BCME_UNSUPPORTED;
+		} else if (len) {
+			/* Set is an action w/o parameters */
+			bcmerror = BCME_BUFTOOLONG;
+		}
+		break;
+
+	default:
+		/* unknown type for length check in iovar info */
+		ASSERT(0);
+		bcmerror = BCME_UNSUPPORTED;
+	}
+
+	return bcmerror;
+}
+
+#endif	/* BCMDRIVER */
+
+
+uint8 *
+bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst)
+{
+	uint8 *new_dst = dst;
+	bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst;
+
+	/* dst buffer should always be valid */
+	ASSERT(dst);
+
+	/* data len must be within valid range */
+	ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE));
+
+	/* source data buffer pointer should be valid, unless datalen is 0
+	 * meaning no data with this TLV
+	 */
+	ASSERT((data != NULL) || (datalen == 0));
+
+	/* only do work if the inputs are valid
+	 * - must have a dst to write to AND
+	 * - datalen must be within range AND
+	 * - the source data pointer must be non-NULL if datalen is non-zero
+	 * (this last condition detects datalen > 0 with a NULL data pointer)
+	 */
+	if ((dst != NULL) &&
+	    ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) &&
+	    ((data != NULL) || (datalen == 0))) {
+
+	        /* write type, len fields */
+		dst_tlv->id = (uint8)type;
+	        dst_tlv->len = (uint8)datalen;
+
+		/* if data is present, copy to the output buffer and update
+		 * pointer to output buffer
+		 */
+		if (datalen > 0) {
+
+			memcpy(dst_tlv->data, data, datalen);
+		}
+
+		/* update the output destination poitner to point past
+		 * the TLV written
+		 */
+		new_dst = dst + BCM_TLV_HDR_SIZE + datalen;
+	}
+
+	return (new_dst);
+}
+
+uint8 *
+bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen)
+{
+	uint8 *new_dst = dst;
+
+	if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) {
+
+		/* if len + tlv hdr len is more than destlen, don't do anything
+		 * just return the buffer untouched
+		 */
+		if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) {
+
+			new_dst = bcm_write_tlv(type, data, datalen, dst);
+		}
+	}
+
+	return (new_dst);
+}
+
+uint8 *
+bcm_copy_tlv(const void *src, uint8 *dst)
+{
+	uint8 *new_dst = dst;
+	const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
+	uint totlen;
+
+	ASSERT(dst && src);
+	if (dst && src) {
+
+		totlen = BCM_TLV_HDR_SIZE + src_tlv->len;
+		memcpy(dst, src_tlv, totlen);
+		new_dst = dst + totlen;
+	}
+
+	return (new_dst);
+}
+
+
+uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen)
+{
+	uint8 *new_dst = dst;
+	const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
+
+	ASSERT(src);
+	if (src) {
+		if (bcm_valid_tlv(src_tlv, dst_maxlen)) {
+			new_dst = bcm_copy_tlv(src, dst);
+		}
+	}
+
+	return (new_dst);
+}
+
+
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
+/*******************************************************************************
+ * crc8
+ *
+ * Computes a crc8 over the input data using the polynomial:
+ *
+ *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ *
+ * The caller provides the initial value (either CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data.  When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream.  When checking, a final
+ * return value of CRC8_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint8 crc8_table[256] = {
+    0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+    0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+    0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+    0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+    0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+    0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+    0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+    0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+    0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+    0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+    0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+    0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+    0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+    0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+    0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+    0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+    0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+    0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+    0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+    0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+    0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+    0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+    0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+    0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+    0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+    0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+    0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+    0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+    0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+    0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+    0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+    0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
+};
+
+#define CRC_INNER_LOOP(n, c, x) \
+	(c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
+
+uint8
+BCMROMFN(hndcrc8)(
+	uint8 *pdata,	/* pointer to array of data to process */
+	uint  nbytes,	/* number of input data bytes to process */
+	uint8 crc	/* either CRC8_INIT_VALUE or previous return value */
+)
+{
+	/* hard code the crc loop instead of using CRC_INNER_LOOP macro
+	 * to avoid the undefined and unnecessary (uint8 >> 8) operation.
+	 */
+	while (nbytes-- > 0)
+		crc = crc8_table[(crc ^ *pdata++) & 0xff];
+
+	return crc;
+}
+
+/*******************************************************************************
+ * crc16
+ *
+ * Computes a crc16 over the input data using the polynomial:
+ *
+ *       x^16 + x^12 +x^5 + 1
+ *
+ * The caller provides the initial value (either CRC16_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data.  When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream.  When checking, a final
+ * return value of CRC16_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint16 crc16_table[256] = {
+    0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
+    0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
+    0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
+    0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
+    0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
+    0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
+    0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
+    0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
+    0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
+    0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
+    0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
+    0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
+    0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
+    0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
+    0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
+    0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
+    0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
+    0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
+    0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
+    0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
+    0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
+    0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
+    0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
+    0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
+    0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
+    0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
+    0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
+    0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
+    0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
+    0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
+    0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
+    0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
+};
+
+uint16
+BCMROMFN(hndcrc16)(
+    uint8 *pdata,  /* pointer to array of data to process */
+    uint nbytes, /* number of input data bytes to process */
+    uint16 crc     /* either CRC16_INIT_VALUE or previous return value */
+)
+{
+	while (nbytes-- > 0)
+		CRC_INNER_LOOP(16, crc, *pdata++);
+	return crc;
+}
+
+static const uint32 crc32_table[256] = {
+    0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+    0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+    0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+    0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+    0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+    0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+    0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+    0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+    0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+    0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+    0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+    0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+    0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+    0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+    0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+    0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+    0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+    0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+    0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+    0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+    0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+    0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+    0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+    0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+    0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+    0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+    0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+    0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+    0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+    0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+    0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+    0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+    0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+    0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+    0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+    0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+    0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+    0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+    0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+    0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+    0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+    0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+    0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+    0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+    0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+    0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+    0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+    0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+    0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+    0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+    0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+    0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+    0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+    0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+    0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+    0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+    0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+    0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+    0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+    0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+    0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+    0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+    0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+    0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+/*
+ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if
+ * accumulating over multiple pieces.
+ */
+uint32
+BCMROMFN(hndcrc32)(uint8 *pdata, uint nbytes, uint32 crc)
+{
+	uint8 *pend;
+	pend = pdata + nbytes;
+	while (pdata < pend)
+		CRC_INNER_LOOP(32, crc, *pdata++);
+
+	return crc;
+}
+
+#ifdef notdef
+#define CLEN 	1499 	/*  CRC Length */
+#define CBUFSIZ 	(CLEN+4)
+#define CNBUFS		5 /* # of bufs */
+
+void
+testcrc32(void)
+{
+	uint j, k, l;
+	uint8 *buf;
+	uint len[CNBUFS];
+	uint32 crcr;
+	uint32 crc32tv[CNBUFS] =
+		{0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
+
+	ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL);
+
+	/* step through all possible alignments */
+	for (l = 0; l <= 4; l++) {
+		for (j = 0; j < CNBUFS; j++) {
+			len[j] = CLEN;
+			for (k = 0; k < len[j]; k++)
+				*(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff;
+		}
+
+		for (j = 0; j < CNBUFS; j++) {
+			crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE);
+			ASSERT(crcr == crc32tv[j]);
+		}
+	}
+
+	MFREE(buf, CBUFSIZ*CNBUFS);
+	return;
+}
+#endif /* notdef */
+
+/*
+ * Advance from the current 1-byte tag/1-byte length/variable-length value
+ * triple, to the next, returning a pointer to the next.
+ * If the current or next TLV is invalid (does not fit in given buffer length),
+ * NULL is returned.
+ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented
+ * by the TLV parameter's length if it is valid.
+ */
+bcm_tlv_t *
+BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen)
+{
+	int len;
+
+	/* validate current elt */
+	if (!bcm_valid_tlv(elt, *buflen)) {
+		return NULL;
+	}
+
+	/* advance to next elt */
+	len = elt->len;
+	elt = (bcm_tlv_t*)(elt->data + len);
+	*buflen -= (TLV_HDR_LEN + len);
+
+	/* validate next elt */
+	if (!bcm_valid_tlv(elt, *buflen)) {
+		return NULL;
+	}
+
+	return elt;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+bcm_tlv_t *
+BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key)
+{
+	bcm_tlv_t *elt;
+	int totlen;
+
+	elt = (bcm_tlv_t*)buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= TLV_HDR_LEN) {
+		int len = elt->len;
+
+		/* validate remaining totlen */
+		if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
+
+			return (elt);
+		}
+
+		elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
+		totlen -= (len + TLV_HDR_LEN);
+	}
+
+	return NULL;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag.  Stop parsing when we see an element whose ID is greater
+ * than the target key.
+ */
+bcm_tlv_t *
+BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key)
+{
+	bcm_tlv_t *elt;
+	int totlen;
+
+	elt = (bcm_tlv_t*)buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= TLV_HDR_LEN) {
+		uint id = elt->id;
+		int len = elt->len;
+
+		/* Punt if we start seeing IDs > than target key */
+		if (id > key) {
+			return (NULL);
+		}
+
+		/* validate remaining totlen */
+		if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
+			return (elt);
+		}
+
+		elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
+		totlen -= (len + TLV_HDR_LEN);
+	}
+	return NULL;
+}
+#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
+
+#if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
+	defined(DHD_DEBUG)
+int
+bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
+{
+	int i, slen = 0;
+	uint32 bit, mask;
+	const char *name;
+	mask = bd->mask;
+	if (len < 2 || !buf)
+		return 0;
+
+	buf[0] = '\0';
+
+	for (i = 0;  (name = bd->bitfield[i].name) != NULL; i++) {
+		bit = bd->bitfield[i].bit;
+		if ((flags & mask) == bit) {
+			if (len > (int)strlen(name)) {
+				slen = strlen(name);
+				strncpy(buf, name, slen+1);
+			}
+			break;
+		}
+	}
+	return slen;
+}
+
+int
+bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
+{
+	int i;
+	char* p = buf;
+	char hexstr[16];
+	int slen = 0, nlen = 0;
+	uint32 bit;
+	const char* name;
+
+	if (len < 2 || !buf)
+		return 0;
+
+	buf[0] = '\0';
+
+	for (i = 0; flags != 0; i++) {
+		bit = bd[i].bit;
+		name = bd[i].name;
+		if (bit == 0 && flags != 0) {
+			/* print any unnamed bits */
+			snprintf(hexstr, 16, "0x%X", flags);
+			name = hexstr;
+			flags = 0;	/* exit loop */
+		} else if ((flags & bit) == 0)
+			continue;
+		flags &= ~bit;
+		nlen = strlen(name);
+		slen += nlen;
+		/* count btwn flag space */
+		if (flags != 0)
+			slen += 1;
+		/* need NULL char as well */
+		if (len <= slen)
+			break;
+		/* copy NULL char but don't count it */
+		strncpy(p, name, nlen + 1);
+		p += nlen;
+		/* copy btwn flag space and NULL char */
+		if (flags != 0)
+			p += snprintf(p, 2, " ");
+	}
+
+	/* indicate the str was too short */
+	if (flags != 0) {
+		if (len < 2)
+			p -= 2 - len;	/* overwrite last char */
+		p += snprintf(p, 2, ">");
+	}
+
+	return (int)(p - buf);
+}
+
+/* print bytes formatted as hex to a string. return the resulting string length */
+int
+bcm_format_hex(char *str, const void *bytes, int len)
+{
+	int i;
+	char *p = str;
+	const uint8 *src = (const uint8*)bytes;
+
+	for (i = 0; i < len; i++) {
+		p += snprintf(p, 3, "%02X", *src);
+		src++;
+	}
+	return (int)(p - str);
+}
+#endif 
+
+/* pretty hex print a contiguous buffer */
+void
+prhex(const char *msg, uchar *buf, uint nbytes)
+{
+	char line[128], *p;
+	int len = sizeof(line);
+	int nchar;
+	uint i;
+
+	if (msg && (msg[0] != '\0'))
+		printf("%s:\n", msg);
+
+	p = line;
+	for (i = 0; i < nbytes; i++) {
+		if (i % 16 == 0) {
+			nchar = snprintf(p, len, "  %04d: ", i);	/* line prefix */
+			p += nchar;
+			len -= nchar;
+		}
+		if (len > 0) {
+			nchar = snprintf(p, len, "%02x ", buf[i]);
+			p += nchar;
+			len -= nchar;
+		}
+
+		if (i % 16 == 15) {
+			printf("%s\n", line);		/* flush line */
+			p = line;
+			len = sizeof(line);
+		}
+	}
+
+	/* flush last partial line */
+	if (p != line)
+		printf("%s\n", line);
+}
+
+static const char *crypto_algo_names[] = {
+	"NONE",
+	"WEP1",
+	"TKIP",
+	"WEP128",
+	"AES_CCM",
+	"AES_OCB_MSDU",
+	"AES_OCB_MPDU",
+#ifdef BCMCCX
+	"CKIP",
+	"CKIP_MMH",
+	"WEP_MMH",
+	"NALG",
+#else
+	"NALG",
+	"UNDEF",
+	"UNDEF",
+	"UNDEF",
+#endif /* BCMCCX */
+	"WAPI",
+	"PMK",
+	"BIP",
+	"AES_GCM",
+	"AES_CCM256",
+	"AES_GCM256",
+	"BIP_CMAC256",
+	"BIP_GMAC",
+	"BIP_GMAC256",
+	"UNDEF"
+};
+
+const char *
+bcm_crypto_algo_name(uint algo)
+{
+	return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR";
+}
+
+
+char *
+bcm_chipname(uint chipid, char *buf, uint len)
+{
+	const char *fmt;
+
+	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
+	snprintf(buf, len, fmt, chipid);
+	return buf;
+}
+
+/* Produce a human-readable string for boardrev */
+char *
+bcm_brev_str(uint32 brev, char *buf)
+{
+	if (brev < 0x100)
+		snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
+	else
+		snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff);
+
+	return (buf);
+}
+
+#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */
+
+/* dump large strings to console */
+void
+printbig(char *buf)
+{
+	uint len, max_len;
+	char c;
+
+	len = strlen(buf);
+
+	max_len = BUFSIZE_TODUMP_ATONCE;
+
+	while (len > max_len) {
+		c = buf[max_len];
+		buf[max_len] = '\0';
+		printf("%s", buf);
+		buf[max_len] = c;
+
+		buf += max_len;
+		len -= max_len;
+	}
+	/* print the remaining string */
+	printf("%s\n", buf);
+	return;
+}
+
+/* routine to dump fields in a fileddesc structure */
+uint
+bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array,
+	char *buf, uint32 bufsize)
+{
+	uint  filled_len;
+	int len;
+	struct fielddesc *cur_ptr;
+
+	filled_len = 0;
+	cur_ptr = fielddesc_array;
+
+	while (bufsize > 1) {
+		if (cur_ptr->nameandfmt == NULL)
+			break;
+		len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
+		               read_rtn(arg0, arg1, cur_ptr->offset));
+		/* check for snprintf overflow or error */
+		if (len < 0 || (uint32)len >= bufsize)
+			len = bufsize - 1;
+		buf += len;
+		bufsize -= len;
+		filled_len += len;
+		cur_ptr++;
+	}
+	return filled_len;
+}
+
+uint
+bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
+{
+	uint len;
+
+	len = strlen(name) + 1;
+
+	if ((len + datalen) > buflen)
+		return 0;
+
+	strncpy(buf, name, buflen);
+
+	/* append data onto the end of the name string */
+	memcpy(&buf[len], data, datalen);
+	len += datalen;
+
+	return len;
+}
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a uint16.
+ */
+
+#define QDBM_OFFSET 153		/* Offset for first entry */
+#define QDBM_TABLE_LEN 40	/* Table size */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
+
+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm: 	+0 	+1 	+2 	+3 	+4 	+5 	+6 	+7 */
+/* 153: */      6683,	7079,	7499,	7943,	8414,	8913,	9441,	10000,
+/* 161: */      10593,	11220,	11885,	12589,	13335,	14125,	14962,	15849,
+/* 169: */      16788,	17783,	18836,	19953,	21135,	22387,	23714,	25119,
+/* 177: */      26607,	28184,	29854,	31623,	33497,	35481,	37584,	39811,
+/* 185: */      42170,	44668,	47315,	50119,	53088,	56234,	59566,	63096
+};
+
+uint16
+BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm)
+{
+	uint factor = 1;
+	int idx = qdbm - QDBM_OFFSET;
+
+	if (idx >= QDBM_TABLE_LEN) {
+		/* clamp to max uint16 mW value */
+		return 0xFFFF;
+	}
+
+	/* scale the qdBm index up to the range of the table 0-40
+	 * where an offset of 40 qdBm equals a factor of 10 mW.
+	 */
+	while (idx < 0) {
+		idx += 40;
+		factor *= 10;
+	}
+
+	/* return the mW value scaled down to the correct factor of 10,
+	 * adding in factor/2 to get proper rounding.
+	 */
+	return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
+}
+
+uint8
+BCMROMFN(bcm_mw_to_qdbm)(uint16 mw)
+{
+	uint8 qdbm;
+	int offset;
+	uint mw_uint = mw;
+	uint boundary;
+
+	/* handle boundary case */
+	if (mw_uint <= 1)
+		return 0;
+
+	offset = QDBM_OFFSET;
+
+	/* move mw into the range of the table */
+	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+		mw_uint *= 10;
+		offset -= 40;
+	}
+
+	for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
+		boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] -
+		                                    nqdBm_to_mW_map[qdbm])/2;
+		if (mw_uint < boundary) break;
+	}
+
+	qdbm += (uint8)offset;
+
+	return (qdbm);
+}
+
+
+uint
+BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint length)
+{
+	uint bitcount = 0, i;
+	uint8 tmp;
+	for (i = 0; i < length; i++) {
+		tmp = bitmap[i];
+		while (tmp) {
+			bitcount++;
+			tmp &= (tmp - 1);
+		}
+	}
+	return bitcount;
+}
+
+#ifdef BCMDRIVER
+
+/* Initialization of bcmstrbuf structure */
+void
+bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
+{
+	b->origsize = b->size = size;
+	b->origbuf = b->buf = buf;
+}
+
+/* Buffer sprintf wrapper to guard against buffer overflow */
+int
+bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	va_start(ap, fmt);
+
+	r = vsnprintf(b->buf, b->size, fmt, ap);
+
+	/* Non Ansi C99 compliant returns -1,
+	 * Ansi compliant return r >= b->size,
+	 * bcmstdlib returns 0, handle all
+	 */
+	/* r == 0 is also the case when strlen(fmt) is zero.
+	 * typically the case when "" is passed as argument.
+	 */
+	if ((r == -1) || (r >= (int)b->size)) {
+		b->size = 0;
+	} else {
+		b->size -= r;
+		b->buf += r;
+	}
+
+	va_end(ap);
+
+	return r;
+}
+
+void
+bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len)
+{
+	int i;
+
+	if (msg != NULL && msg[0] != '\0')
+		bcm_bprintf(b, "%s", msg);
+	for (i = 0; i < len; i ++)
+		bcm_bprintf(b, "%02X", buf[i]);
+	if (newline)
+		bcm_bprintf(b, "\n");
+}
+
+void
+bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
+{
+	int i;
+
+	for (i = 0; i < num_bytes; i++) {
+		num[i] += amount;
+		if (num[i] >= amount)
+			break;
+		amount = 1;
+	}
+}
+
+int
+bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
+{
+	int i;
+
+	for (i = nbytes - 1; i >= 0; i--) {
+		if (arg1[i] != arg2[i])
+			return (arg1[i] - arg2[i]);
+	}
+	return 0;
+}
+
+void
+bcm_print_bytes(const char *name, const uchar *data, int len)
+{
+	int i;
+	int per_line = 0;
+
+	printf("%s: %d \n", name ? name : "", len);
+	for (i = 0; i < len; i++) {
+		printf("%02x ", *data++);
+		per_line++;
+		if (per_line == 16) {
+			per_line = 0;
+			printf("\n");
+		}
+	}
+	printf("\n");
+}
+
+/* Look for vendor-specific IE with specified OUI and optional type */
+bcm_tlv_t *
+bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len)
+{
+	bcm_tlv_t *ie;
+	uint8 ie_len;
+
+	ie = (bcm_tlv_t*)tlvs;
+
+	/* make sure we are looking at a valid IE */
+	if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
+		return NULL;
+	}
+
+	/* Walk through the IEs looking for an OUI match */
+	do {
+		ie_len = ie->len;
+		if ((ie->id == DOT11_MNG_PROPR_ID) &&
+		    (ie_len >= (DOT11_OUI_LEN + type_len)) &&
+		    !bcmp(ie->data, voui, DOT11_OUI_LEN))
+		{
+			/* compare optional type */
+			if (type_len == 0 ||
+			    !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
+				return (ie);		/* a match */
+			}
+		}
+	} while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
+
+	return NULL;
+}
+
+#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
+	defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
+#define SSID_FMT_BUF_LEN	((4 * DOT11_MAX_SSID_LEN) + 1)
+
+int
+bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
+{
+	uint i, c;
+	char *p = buf;
+	char *endp = buf + SSID_FMT_BUF_LEN;
+
+	if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
+
+	for (i = 0; i < ssid_len; i++) {
+		c = (uint)ssid[i];
+		if (c == '\\') {
+			*p++ = '\\';
+			*p++ = '\\';
+		} else if (bcm_isprint((uchar)c)) {
+			*p++ = (char)c;
+		} else {
+			p += snprintf(p, (endp - p), "\\x%02X", c);
+		}
+	}
+	*p = '\0';
+	ASSERT(p < endp);
+
+	return (int)(p - buf);
+}
+#endif 
+
+#endif /* BCMDRIVER */
+
+/*
+ * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
+ * also accepts nvram files which are already in the format of <var1>=<value>\0\<var2>=<value2>\0
+ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
+ * Shortens buffer as needed and pads with NULs.  End of buffer is marked by two NULs.
+*/
+
+unsigned int
+process_nvram_vars(char *varbuf, unsigned int len)
+{
+	char *dp;
+	bool findNewline;
+	int column;
+	unsigned int buf_len, n;
+	unsigned int pad = 0;
+
+	dp = varbuf;
+
+	findNewline = FALSE;
+	column = 0;
+
+	for (n = 0; n < len; n++) {
+		if (varbuf[n] == '\r')
+			continue;
+		if (findNewline && varbuf[n] != '\n')
+			continue;
+		findNewline = FALSE;
+		if (varbuf[n] == '#') {
+			findNewline = TRUE;
+			continue;
+		}
+		if (varbuf[n] == '\n') {
+			if (column == 0)
+				continue;
+			*dp++ = 0;
+			column = 0;
+			continue;
+		}
+		*dp++ = varbuf[n];
+		column++;
+	}
+	buf_len = (unsigned int)(dp - varbuf);
+	if (buf_len % 4) {
+		pad = 4 - buf_len % 4;
+		if (pad && (buf_len + pad <= len)) {
+			buf_len += pad;
+		}
+	}
+
+	while (dp < varbuf + n)
+		*dp++ = 0;
+
+	return buf_len;
+}
+
+/* calculate a * b + c */
+void
+bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c)
+{
+#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;}
+	uint32 r1, r0;
+	uint32 a1, a0, b1, b0, t, cc = 0;
+
+	a1 = a >> 16;
+	a0 = a & 0xffff;
+	b1 = b >> 16;
+	b0 = b & 0xffff;
+
+	r0 = a0 * b0;
+	FORMALIZE(r0);
+
+	t = (a1 * b0) << 16;
+	FORMALIZE(t);
+
+	r0 += t;
+	FORMALIZE(r0);
+
+	t = (a0 * b1) << 16;
+	FORMALIZE(t);
+
+	r0 += t;
+	FORMALIZE(r0);
+
+	FORMALIZE(c);
+
+	r0 += c;
+	FORMALIZE(r0);
+
+	r0 |= (cc % 2) ? 0x80000000 : 0;
+	r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2);
+
+	*r_high = r1;
+	*r_low = r0;
+}
+
+/* calculate a / b */
+void
+bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
+{
+	uint32 a1 = a_high, a0 = a_low, r0 = 0;
+
+	if (b < 2)
+		return;
+
+	while (a1 != 0) {
+		r0 += (0xffffffff / b) * a1;
+		bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
+	}
+
+	r0 += a0 / b;
+	*r = r0;
+}
+
+#ifndef setbit /* As in the header file */
+#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
+/* Set bit in byte array. */
+void
+setbit(void *array, uint bit)
+{
+	((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY);
+}
+
+/* Clear bit in byte array. */
+void
+clrbit(void *array, uint bit)
+{
+	((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY));
+}
+
+/* Test if bit is set in byte array. */
+bool
+isset(const void *array, uint bit)
+{
+	return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY)));
+}
+
+/* Test if bit is clear in byte array. */
+bool
+isclr(const void *array, uint bit)
+{
+	return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0);
+}
+#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */
+#endif /* setbit */
+
+void
+bcm_bitprint32(const uint32 u32)
+{
+	int i;
+	for (i = NBITS(uint32) - 1; i >= 0; i--) {
+		isbitset(u32, i) ? printf("1") : printf("0");
+		if ((i % NBBY) == 0) printf(" ");
+	}
+	printf("\n");
+}
+
+#ifdef BCMDRIVER
+/*
+ * Hierarchical Multiword bitmap based small id allocator.
+ *
+ * Multilevel hierarchy bitmap. (maximum 2 levels)
+ * First hierarchy uses a multiword bitmap to identify 32bit words in the
+ * second hierarchy that have at least a single bit set. Each bit in a word of
+ * the second hierarchy represents a unique ID that may be allocated.
+ *
+ * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
+ * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
+ * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
+ * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
+ *                       non-zero bitmap word carrying at least one free ID.
+ * BCM_MWBMAP_SHIFT_OP:  Used in MOD, DIV and MUL operations.
+ * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
+ *
+ * Design Notes:
+ * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
+ * bits are computed each time on allocation and deallocation, requiring 4
+ * array indexed access and 3 arithmetic operations. When not defined, a runtime
+ * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
+ * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
+ * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
+ * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
+ *
+ * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
+ * size is fixed. No intention to support larger than 4K indice allocation. ID
+ * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
+ * with savings in not having to use an indirect access, had it been dynamically
+ * allocated.
+ */
+#define BCM_MWBMAP_ITEMS_MAX    (4 * 1024)  /* May increase to 16K */
+
+#define BCM_MWBMAP_BITS_WORD    (NBITS(uint32))
+#define BCM_MWBMAP_WORDS_MAX    (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
+#define BCM_MWBMAP_WDMAP_MAX    (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
+#define BCM_MWBMAP_SHIFT_OP     (5)
+#define BCM_MWBMAP_MODOP(ix)    ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
+#define BCM_MWBMAP_DIVOP(ix)    ((ix) >> BCM_MWBMAP_SHIFT_OP)
+#define BCM_MWBMAP_MULOP(ix)    ((ix) << BCM_MWBMAP_SHIFT_OP)
+
+/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
+#define BCM_MWBMAP_PTR(hdl)		((struct bcm_mwbmap *)(hdl))
+#define BCM_MWBMAP_HDL(ptr)		((void *)(ptr))
+
+#if defined(BCM_MWBMAP_DEBUG)
+#define BCM_MWBMAP_AUDIT(mwb) \
+	do { \
+		ASSERT((mwb != NULL) && \
+		       (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
+		bcm_mwbmap_audit(mwb); \
+	} while (0)
+#define MWBMAP_ASSERT(exp)		ASSERT(exp)
+#define MWBMAP_DBG(x)           printf x
+#else   /* !BCM_MWBMAP_DEBUG */
+#define BCM_MWBMAP_AUDIT(mwb)   do {} while (0)
+#define MWBMAP_ASSERT(exp)		do {} while (0)
+#define MWBMAP_DBG(x)
+#endif  /* !BCM_MWBMAP_DEBUG */
+
+
+typedef struct bcm_mwbmap {     /* Hierarchical multiword bitmap allocator    */
+	uint16 wmaps;               /* Total number of words in free wd bitmap    */
+	uint16 imaps;               /* Total number of words in free id bitmap    */
+	int16  ifree;               /* Count of free indices. Used only in audits */
+	uint16 total;               /* Total indices managed by multiword bitmap  */
+
+	void * magic;               /* Audit handle parameter from user           */
+
+	uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of            */
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+	int8   wd_count[BCM_MWBMAP_WORDS_MAX];  /* free id running count, 1st lvl */
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+
+	uint32 id_bitmap[0];        /* Second level bitmap                        */
+} bcm_mwbmap_t;
+
+/* Incarnate a hierarchical multiword bitmap based small index allocator. */
+struct bcm_mwbmap *
+BCMATTACHFN(bcm_mwbmap_init)(osl_t *osh, uint32 items_max)
+{
+	struct bcm_mwbmap * mwbmap_p;
+	uint32 wordix, size, words, extra;
+
+	/* Implementation Constraint: Uses 32bit word bitmap */
+	MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
+	MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
+	MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
+	MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
+
+	ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
+
+	/* Determine the number of words needed in the multiword bitmap */
+	extra = BCM_MWBMAP_MODOP(items_max);
+	words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
+
+	/* Allocate runtime state of multiword bitmap */
+	/* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
+	size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
+	mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
+	if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
+		ASSERT(0);
+		goto error1;
+	}
+	memset(mwbmap_p, 0, size);
+
+	/* Initialize runtime multiword bitmap state */
+	mwbmap_p->imaps = (uint16)words;
+	mwbmap_p->ifree = (int16)items_max;
+	mwbmap_p->total = (uint16)items_max;
+
+	/* Setup magic, for use in audit of handle */
+	mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
+
+	/* Setup the second level bitmap of free indices */
+	/* Mark all indices as available */
+	for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
+		mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+		mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+	}
+
+	/* Ensure that extra indices are tagged as un-available */
+	if (extra) { /* fixup the free ids in last bitmap and wd_count */
+		uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
+		*bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+		mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+	}
+
+	/* Setup the first level bitmap hierarchy */
+	extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
+	words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
+
+	mwbmap_p->wmaps = (uint16)words;
+
+	for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
+		mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
+	if (extra) {
+		uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
+		*bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
+	}
+
+	return mwbmap_p;
+
+error1:
+	return BCM_MWBMAP_INVALID_HDL;
+}
+
+/* Release resources used by multiword bitmap based small index allocator. */
+void
+BCMATTACHFN(bcm_mwbmap_fini)(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
+	                     + (sizeof(uint32) * mwbmap_p->imaps));
+	return;
+}
+
+/* Allocate a unique small index using a multiword bitmap index allocator.    */
+uint32
+bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 wordix, bitmap;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	/* Start with the first hierarchy */
+	for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
+
+		bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
+
+		if (bitmap != 0U) {
+
+			uint32 count, bitix, *bitmap_p;
+
+			bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+			/* clear all except trailing 1 */
+			bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
+			MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
+			              bcm_count_leading_zeros(bitmap));
+			bitix    = (BCM_MWBMAP_BITS_WORD - 1)
+			         - bcm_count_leading_zeros(bitmap); /* use asm clz */
+			wordix   = BCM_MWBMAP_MULOP(wordix) + bitix;
+
+			/* Clear bit if wd count is 0, without conditional branch */
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+			count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+			mwbmap_p->wd_count[wordix]--;
+			count = mwbmap_p->wd_count[wordix];
+			MWBMAP_ASSERT(count ==
+			              (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+			MWBMAP_ASSERT(count >= 0);
+
+			/* clear wd_bitmap bit if id_map count is 0 */
+			bitmap = (count == 0) << bitix;
+
+			MWBMAP_DBG((
+			    "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
+			    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
+
+			*bitmap_p ^= bitmap;
+
+			/* Use bitix in the second hierarchy */
+			bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+			bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
+			MWBMAP_ASSERT(bitmap != 0U);
+
+			/* clear all except trailing 1 */
+			bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
+			MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
+			              bcm_count_leading_zeros(bitmap));
+			bitix    = BCM_MWBMAP_MULOP(wordix)
+			         + (BCM_MWBMAP_BITS_WORD - 1)
+			         - bcm_count_leading_zeros(bitmap); /* use asm clz */
+
+			mwbmap_p->ifree--; /* decrement system wide free count */
+			MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
+
+			MWBMAP_DBG((
+			    "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
+			    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
+			    mwbmap_p->ifree));
+
+			*bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
+
+			return bitix;
+		}
+	}
+
+	ASSERT(mwbmap_p->ifree == 0);
+
+	return BCM_MWBMAP_INVALID_IDX;
+}
+
+/* Force an index at a specified position to be in use */
+void
+bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 count, wordix, bitmap, *bitmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(bitix < mwbmap_p->total);
+
+	/* Start with second hierarchy */
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap   = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
+	bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+	ASSERT((*bitmap_p & bitmap) == bitmap);
+
+	mwbmap_p->ifree--; /* update free count */
+	ASSERT(mwbmap_p->ifree >= 0);
+
+	MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
+	           bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
+	           mwbmap_p->ifree));
+
+	*bitmap_p ^= bitmap; /* mark as in use */
+
+	/* Update first hierarchy */
+	bitix    = wordix;
+
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+	count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+	mwbmap_p->wd_count[bitix]--;
+	count = mwbmap_p->wd_count[bitix];
+	MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+	MWBMAP_ASSERT(count >= 0);
+
+	bitmap   = (count == 0) << BCM_MWBMAP_MODOP(bitix);
+
+	MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
+	           BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
+	           (*bitmap_p) ^ bitmap, count));
+
+	*bitmap_p ^= bitmap; /* mark as in use */
+
+	return;
+}
+
+/* Free a previously allocated index back into the multiword bitmap allocator */
+void
+bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 wordix, bitmap, *bitmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(bitix < mwbmap_p->total);
+
+	/* Start with second level hierarchy */
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
+	bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+	ASSERT((*bitmap_p & bitmap) == 0U);	/* ASSERT not a double free */
+
+	mwbmap_p->ifree++; /* update free count */
+	ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
+
+	MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
+	           bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
+	           mwbmap_p->ifree));
+
+	*bitmap_p |= bitmap; /* mark as available */
+
+	/* Now update first level hierarchy */
+
+	bitix    = wordix;
+
+	wordix   = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
+	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
+	bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+	mwbmap_p->wd_count[bitix]++;
+#endif
+
+#if defined(BCM_MWBMAP_DEBUG)
+	{
+		uint32 count;
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+		count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
+#else  /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+		count = mwbmap_p->wd_count[bitix];
+		MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+
+		MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
+
+		MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
+		            bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
+	}
+#endif /* BCM_MWBMAP_DEBUG */
+
+	*bitmap_p |= bitmap;
+
+	return;
+}
+
+/* Fetch the toal number of free indices in the multiword bitmap allocator */
+uint32
+bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(mwbmap_p->ifree >= 0);
+
+	return mwbmap_p->ifree;
+}
+
+/* Determine whether an index is inuse or free */
+bool
+bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 wordix, bitmap;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(bitix < mwbmap_p->total);
+
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
+
+	return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
+}
+
+/* Debug dump a multiword bitmap allocator */
+void
+bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
+{
+	uint32 ix, count;
+	bcm_mwbmap_t * mwbmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p,
+	       mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
+	for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
+		printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
+		bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
+		printf("\n");
+	}
+	for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+		count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+		count = mwbmap_p->wd_count[ix];
+		MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+		printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
+		bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
+		printf("\n");
+	}
+
+	return;
+}
+
+/* Audit a hierarchical multiword bitmap */
+void
+bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
+
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
+
+		bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+		for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
+			if ((*bitmap_p) & (1 << bitix)) {
+				idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+				count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+				count = mwbmap_p->wd_count[idmap_ix];
+				ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+				ASSERT(count != 0U);
+				free_cnt += count;
+			}
+		}
+	}
+
+	ASSERT(free_cnt == mwbmap_p->ifree);
+}
+/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
+
+#endif /* BCMDRIVER */
+
+/* calculate a >> b; and returns only lower 32 bits */
+void
+bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
+{
+	uint32 a1 = a_high, a0 = a_low, r0 = 0;
+
+	if (b == 0) {
+		r0 = a_low;
+		*r = r0;
+		return;
+	}
+
+	if (b < 32) {
+		a0 = a0 >> b;
+		a1 = a1 & ((1 << b) - 1);
+		a1 = a1 << (32 - b);
+		r0 = a0 | a1;
+		*r = r0;
+		return;
+	} else {
+		r0 = a1 >> (b - 32);
+		*r = r0;
+		return;
+	}
+
+}
+
+/* calculate a + b where a is a 64 bit number and b is a 32 bit number */
+void
+bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset)
+{
+	uint32 r1_lo = *r_lo;
+	(*r_lo) += offset;
+	if (*r_lo < r1_lo)
+		(*r_hi) ++;
+}
+
+/* calculate a - b where a is a 64 bit number and b is a 32 bit number */
+void
+bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset)
+{
+	uint32 r1_lo = *r_lo;
+	(*r_lo) -= offset;
+	if (*r_lo > r1_lo)
+		(*r_hi) --;
+}
+
+#ifdef DEBUG_COUNTER
+#if (OSL_SYSUPTIME_SUPPORT == TRUE)
+void counter_printlog(counter_tbl_t *ctr_tbl)
+{
+	uint32 now;
+
+	if (!ctr_tbl->enabled)
+		return;
+
+	now = OSL_SYSUPTIME();
+
+	if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) {
+		uint8 i = 0;
+		printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print);
+
+		for (i = 0; i < ctr_tbl->needed_cnt; i++) {
+			printf(" %u", ctr_tbl->cnt[i]);
+		}
+		printf("\n");
+
+		ctr_tbl->prev_log_print = now;
+		bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint));
+	}
+}
+#else
+/* OSL_SYSUPTIME is not supported so no way to get time */
+#define counter_printlog(a) do {} while (0)
+#endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
+#endif /* DEBUG_COUNTER */
diff --git a/src/shared/bcmwifi/include/bcmwifi_channels.h b/src/shared/bcmwifi/include/bcmwifi_channels.h
new file mode 100644
index 0000000..6da2e25
--- /dev/null
+++ b/src/shared/bcmwifi/include/bcmwifi_channels.h
@@ -0,0 +1,300 @@
+/*
+ * 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 Open Broadcom Corporation$
+ *
+ * $Id: bcmwifi_channels.h 309193 2012-01-19 00:03:57Z $
+ */
+
+#ifndef	_bcmwifi_channels_h_
+#define	_bcmwifi_channels_h_
+
+
+
+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 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_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 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 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 CHSPEC_CHANNEL(chspec)	((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
+#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)
+
+#ifdef WL11N_20MHZONLY
+
+#define CHSPEC_IS10(chspec)	0
+#define CHSPEC_IS20(chspec)	1
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec)	0
+#endif
+#ifndef CHSPEC_IS80
+#define CHSPEC_IS80(chspec)	0
+#endif
+#ifndef CHSPEC_IS160
+#define CHSPEC_IS160(chspec)	0
+#endif
+#ifndef CHSPEC_IS8080
+#define CHSPEC_IS8080(chspec)	0
+#endif
+
+#else 
+
+#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
+
+#endif 
+
+#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)
+
+
+#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))
+
+#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))
+
+#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))
+
+#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))
+
+
+#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	
+
+
+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 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 chan1_80Mhz, uint8 chan2_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);
+
+
+#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..b95da33
--- /dev/null
+++ b/src/shared/bcmwifi/include/bcmwifi_rates.h
@@ -0,0 +1,422 @@
+/*
+ * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates
+ *
+ * $Copyright Open Broadcom Corporation$
+ *
+ * $Id: bcmwifi_rates.h 5187 2012-06-29 06:17:50Z $
+ */
+
+#ifndef _bcmwifi_rates_h_
+#define _bcmwifi_rates_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+
+#define WL_RATESET_SZ_DSSS		4
+#define WL_RATESET_SZ_OFDM		8
+#define WL_RATESET_SZ_HT_MCS	8
+#define WL_RATESET_SZ_VHT_MCS	10
+
+#define WL_TX_CHAINS_MAX	3
+
+#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_160,
+	WL_TX_BW_20IN40,
+	WL_TX_BW_20IN80,
+	WL_TX_BW_40IN80,
+	WL_TX_BW_20IN160,
+	WL_TX_BW_40IN160,
+	WL_TX_BW_80IN160,
+	WL_TX_BW_ALL
+} 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_t;
+
+
+
+typedef enum wl_tx_nss {
+	WL_TX_NSS_1 = 1,
+	WL_TX_NSS_2,
+	WL_TX_NSS_3
+} 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_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_1X2_DSSS_1         = 22,
+	WL_RATE_1X2_DSSS_2         = 23,
+	WL_RATE_1X2_DSSS_5_5       = 24,
+	WL_RATE_1X2_DSSS_11        = 25,
+
+	WL_RATE_1X2_CDD_OFDM_6     = 26,
+	WL_RATE_1X2_CDD_OFDM_9     = 27,
+	WL_RATE_1X2_CDD_OFDM_12    = 28,
+	WL_RATE_1X2_CDD_OFDM_18    = 29,
+	WL_RATE_1X2_CDD_OFDM_24    = 30,
+	WL_RATE_1X2_CDD_OFDM_36    = 31,
+	WL_RATE_1X2_CDD_OFDM_48    = 32,
+	WL_RATE_1X2_CDD_OFDM_54    = 33,
+
+	WL_RATE_1X2_CDD_MCS0       = 34,
+	WL_RATE_1X2_CDD_MCS1       = 35,
+	WL_RATE_1X2_CDD_MCS2       = 36,
+	WL_RATE_1X2_CDD_MCS3       = 37,
+	WL_RATE_1X2_CDD_MCS4       = 38,
+	WL_RATE_1X2_CDD_MCS5       = 39,
+	WL_RATE_1X2_CDD_MCS6       = 40,
+	WL_RATE_1X2_CDD_MCS7       = 41,
+
+	WL_RATE_1X2_VHT0SS1        = 34,
+	WL_RATE_1X2_VHT1SS1        = 35,
+	WL_RATE_1X2_VHT2SS1        = 36,
+	WL_RATE_1X2_VHT3SS1        = 37,
+	WL_RATE_1X2_VHT4SS1        = 38,
+	WL_RATE_1X2_VHT5SS1        = 39,
+	WL_RATE_1X2_VHT6SS1        = 40,
+	WL_RATE_1X2_VHT7SS1        = 41,
+	WL_RATE_1X2_VHT8SS1        = 42,
+	WL_RATE_1X2_VHT9SS1        = 43,
+
+	
+	WL_RATE_2X2_STBC_MCS0      = 44,
+	WL_RATE_2X2_STBC_MCS1      = 45,
+	WL_RATE_2X2_STBC_MCS2      = 46,
+	WL_RATE_2X2_STBC_MCS3      = 47,
+	WL_RATE_2X2_STBC_MCS4      = 48,
+	WL_RATE_2X2_STBC_MCS5      = 49,
+	WL_RATE_2X2_STBC_MCS6      = 50,
+	WL_RATE_2X2_STBC_MCS7      = 51,
+
+	WL_RATE_2X2_STBC_VHT0SS1   = 44,
+	WL_RATE_2X2_STBC_VHT1SS1   = 45,
+	WL_RATE_2X2_STBC_VHT2SS1   = 46,
+	WL_RATE_2X2_STBC_VHT3SS1   = 47,
+	WL_RATE_2X2_STBC_VHT4SS1   = 48,
+	WL_RATE_2X2_STBC_VHT5SS1   = 49,
+	WL_RATE_2X2_STBC_VHT6SS1   = 50,
+	WL_RATE_2X2_STBC_VHT7SS1   = 51,
+	WL_RATE_2X2_STBC_VHT8SS1   = 52,
+	WL_RATE_2X2_STBC_VHT9SS1   = 53,
+
+	WL_RATE_2X2_SDM_MCS8       = 54,
+	WL_RATE_2X2_SDM_MCS9       = 55,
+	WL_RATE_2X2_SDM_MCS10      = 56,
+	WL_RATE_2X2_SDM_MCS11      = 57,
+	WL_RATE_2X2_SDM_MCS12      = 58,
+	WL_RATE_2X2_SDM_MCS13      = 59,
+	WL_RATE_2X2_SDM_MCS14      = 60,
+	WL_RATE_2X2_SDM_MCS15      = 61,
+
+	WL_RATE_2X2_VHT0SS2        = 54,
+	WL_RATE_2X2_VHT1SS2        = 55,
+	WL_RATE_2X2_VHT2SS2        = 56,
+	WL_RATE_2X2_VHT3SS2        = 57,
+	WL_RATE_2X2_VHT4SS2        = 58,
+	WL_RATE_2X2_VHT5SS2        = 59,
+	WL_RATE_2X2_VHT6SS2        = 60,
+	WL_RATE_2X2_VHT7SS2        = 61,
+	WL_RATE_2X2_VHT8SS2        = 62,
+	WL_RATE_2X2_VHT9SS2        = 63,
+
+	
+
+	
+	WL_RATE_1X3_DSSS_1         = 64,
+	WL_RATE_1X3_DSSS_2         = 65,
+	WL_RATE_1X3_DSSS_5_5       = 66,
+	WL_RATE_1X3_DSSS_11        = 67,
+
+	WL_RATE_1X3_CDD_OFDM_6     = 68,
+	WL_RATE_1X3_CDD_OFDM_9     = 69,
+	WL_RATE_1X3_CDD_OFDM_12    = 70,
+	WL_RATE_1X3_CDD_OFDM_18    = 71,
+	WL_RATE_1X3_CDD_OFDM_24    = 72,
+	WL_RATE_1X3_CDD_OFDM_36    = 73,
+	WL_RATE_1X3_CDD_OFDM_48    = 74,
+	WL_RATE_1X3_CDD_OFDM_54    = 75,
+
+	WL_RATE_1X3_CDD_MCS0       = 76,
+	WL_RATE_1X3_CDD_MCS1       = 77,
+	WL_RATE_1X3_CDD_MCS2       = 78,
+	WL_RATE_1X3_CDD_MCS3       = 79,
+	WL_RATE_1X3_CDD_MCS4       = 80,
+	WL_RATE_1X3_CDD_MCS5       = 81,
+	WL_RATE_1X3_CDD_MCS6       = 82,
+	WL_RATE_1X3_CDD_MCS7       = 83,
+
+	WL_RATE_1X3_VHT0SS1        = 76,
+	WL_RATE_1X3_VHT1SS1        = 77,
+	WL_RATE_1X3_VHT2SS1        = 78,
+	WL_RATE_1X3_VHT3SS1        = 79,
+	WL_RATE_1X3_VHT4SS1        = 80,
+	WL_RATE_1X3_VHT5SS1        = 81,
+	WL_RATE_1X3_VHT6SS1        = 82,
+	WL_RATE_1X3_VHT7SS1        = 83,
+	WL_RATE_1X3_VHT8SS1        = 84,
+	WL_RATE_1X3_VHT9SS1        = 85,
+
+	
+	WL_RATE_2X3_STBC_MCS0      = 86,
+	WL_RATE_2X3_STBC_MCS1      = 87,
+	WL_RATE_2X3_STBC_MCS2      = 88,
+	WL_RATE_2X3_STBC_MCS3      = 89,
+	WL_RATE_2X3_STBC_MCS4      = 90,
+	WL_RATE_2X3_STBC_MCS5      = 91,
+	WL_RATE_2X3_STBC_MCS6      = 92,
+	WL_RATE_2X3_STBC_MCS7      = 93,
+
+	WL_RATE_2X3_STBC_VHT0SS1   = 86,
+	WL_RATE_2X3_STBC_VHT1SS1   = 87,
+	WL_RATE_2X3_STBC_VHT2SS1   = 88,
+	WL_RATE_2X3_STBC_VHT3SS1   = 89,
+	WL_RATE_2X3_STBC_VHT4SS1   = 90,
+	WL_RATE_2X3_STBC_VHT5SS1   = 91,
+	WL_RATE_2X3_STBC_VHT6SS1   = 92,
+	WL_RATE_2X3_STBC_VHT7SS1   = 93,
+	WL_RATE_2X3_STBC_VHT8SS1   = 94,
+	WL_RATE_2X3_STBC_VHT9SS1   = 95,
+
+	WL_RATE_2X3_SDM_MCS8       = 96,
+	WL_RATE_2X3_SDM_MCS9       = 97,
+	WL_RATE_2X3_SDM_MCS10      = 98,
+	WL_RATE_2X3_SDM_MCS11      = 99,
+	WL_RATE_2X3_SDM_MCS12      = 100,
+	WL_RATE_2X3_SDM_MCS13      = 101,
+	WL_RATE_2X3_SDM_MCS14      = 102,
+	WL_RATE_2X3_SDM_MCS15      = 103,
+
+	WL_RATE_2X3_VHT0SS2        = 96,
+	WL_RATE_2X3_VHT1SS2        = 97,
+	WL_RATE_2X3_VHT2SS2        = 98,
+	WL_RATE_2X3_VHT3SS2        = 99,
+	WL_RATE_2X3_VHT4SS2        = 100,
+	WL_RATE_2X3_VHT5SS2        = 101,
+	WL_RATE_2X3_VHT6SS2        = 102,
+	WL_RATE_2X3_VHT7SS2        = 103,
+	WL_RATE_2X3_VHT8SS2        = 104,
+	WL_RATE_2X3_VHT9SS2        = 105,
+
+	
+	WL_RATE_3X3_SDM_MCS16      = 106,
+	WL_RATE_3X3_SDM_MCS17      = 107,
+	WL_RATE_3X3_SDM_MCS18      = 108,
+	WL_RATE_3X3_SDM_MCS19      = 109,
+	WL_RATE_3X3_SDM_MCS20      = 110,
+	WL_RATE_3X3_SDM_MCS21      = 111,
+	WL_RATE_3X3_SDM_MCS22      = 112,
+	WL_RATE_3X3_SDM_MCS23      = 113,
+
+	WL_RATE_3X3_VHT0SS3        = 106,
+	WL_RATE_3X3_VHT1SS3        = 107,
+	WL_RATE_3X3_VHT2SS3        = 108,
+	WL_RATE_3X3_VHT3SS3        = 109,
+	WL_RATE_3X3_VHT4SS3        = 110,
+	WL_RATE_3X3_VHT5SS3        = 111,
+	WL_RATE_3X3_VHT6SS3        = 112,
+	WL_RATE_3X3_VHT7SS3        = 113,
+	WL_RATE_3X3_VHT8SS3        = 114,
+	WL_RATE_3X3_VHT9SS3        = 115,
+
+
+	
+
+	
+
+	WL_RATE_1X2_TXBF_OFDM_6    = 116,
+	WL_RATE_1X2_TXBF_OFDM_9    = 117,
+	WL_RATE_1X2_TXBF_OFDM_12   = 118,
+	WL_RATE_1X2_TXBF_OFDM_18   = 119,
+	WL_RATE_1X2_TXBF_OFDM_24   = 120,
+	WL_RATE_1X2_TXBF_OFDM_36   = 121,
+	WL_RATE_1X2_TXBF_OFDM_48   = 122,
+	WL_RATE_1X2_TXBF_OFDM_54   = 123,
+
+	WL_RATE_1X2_TXBF_MCS0      = 124,
+	WL_RATE_1X2_TXBF_MCS1      = 125,
+	WL_RATE_1X2_TXBF_MCS2      = 126,
+	WL_RATE_1X2_TXBF_MCS3      = 127,
+	WL_RATE_1X2_TXBF_MCS4      = 128,
+	WL_RATE_1X2_TXBF_MCS5      = 129,
+	WL_RATE_1X2_TXBF_MCS6      = 130,
+	WL_RATE_1X2_TXBF_MCS7      = 131,
+
+	WL_RATE_1X2_TXBF_VHT0SS1   = 124,
+	WL_RATE_1X2_TXBF_VHT1SS1   = 125,
+	WL_RATE_1X2_TXBF_VHT2SS1   = 126,
+	WL_RATE_1X2_TXBF_VHT3SS1   = 127,
+	WL_RATE_1X2_TXBF_VHT4SS1   = 128,
+	WL_RATE_1X2_TXBF_VHT5SS1   = 129,
+	WL_RATE_1X2_TXBF_VHT6SS1   = 130,
+	WL_RATE_1X2_TXBF_VHT7SS1   = 131,
+	WL_RATE_1X2_TXBF_VHT8SS1   = 132,
+	WL_RATE_1X2_TXBF_VHT9SS1   = 133,
+
+	
+
+	WL_RATE_2X2_TXBF_SDM_MCS8  = 134,
+	WL_RATE_2X2_TXBF_SDM_MCS9  = 135,
+	WL_RATE_2X2_TXBF_SDM_MCS10 = 136,
+	WL_RATE_2X2_TXBF_SDM_MCS11 = 137,
+	WL_RATE_2X2_TXBF_SDM_MCS12 = 138,
+	WL_RATE_2X2_TXBF_SDM_MCS13 = 139,
+	WL_RATE_2X2_TXBF_SDM_MCS14 = 140,
+	WL_RATE_2X2_TXBF_SDM_MCS15 = 141,
+
+	WL_RATE_2X2_TXBF_VHT0SS2   = 134,
+	WL_RATE_2X2_TXBF_VHT1SS2   = 135,
+	WL_RATE_2X2_TXBF_VHT2SS2   = 136,
+	WL_RATE_2X2_TXBF_VHT3SS2   = 137,
+	WL_RATE_2X2_TXBF_VHT4SS2   = 138,
+	WL_RATE_2X2_TXBF_VHT5SS2   = 139,
+	WL_RATE_2X2_TXBF_VHT6SS2   = 140,
+	WL_RATE_2X2_TXBF_VHT7SS2   = 141,
+
+
+	
+
+	
+
+	WL_RATE_1X3_TXBF_OFDM_6    = 142,
+	WL_RATE_1X3_TXBF_OFDM_9    = 143,
+	WL_RATE_1X3_TXBF_OFDM_12   = 144,
+	WL_RATE_1X3_TXBF_OFDM_18   = 145,
+	WL_RATE_1X3_TXBF_OFDM_24   = 146,
+	WL_RATE_1X3_TXBF_OFDM_36   = 147,
+	WL_RATE_1X3_TXBF_OFDM_48   = 148,
+	WL_RATE_1X3_TXBF_OFDM_54   = 149,
+
+	WL_RATE_1X3_TXBF_MCS0      = 150,
+	WL_RATE_1X3_TXBF_MCS1      = 151,
+	WL_RATE_1X3_TXBF_MCS2      = 152,
+	WL_RATE_1X3_TXBF_MCS3      = 153,
+	WL_RATE_1X3_TXBF_MCS4      = 154,
+	WL_RATE_1X3_TXBF_MCS5      = 155,
+	WL_RATE_1X3_TXBF_MCS6      = 156,
+	WL_RATE_1X3_TXBF_MCS7      = 157,
+
+	WL_RATE_1X3_TXBF_VHT0SS1   = 150,
+	WL_RATE_1X3_TXBF_VHT1SS1   = 151,
+	WL_RATE_1X3_TXBF_VHT2SS1   = 152,
+	WL_RATE_1X3_TXBF_VHT3SS1   = 153,
+	WL_RATE_1X3_TXBF_VHT4SS1   = 154,
+	WL_RATE_1X3_TXBF_VHT5SS1   = 155,
+	WL_RATE_1X3_TXBF_VHT6SS1   = 156,
+	WL_RATE_1X3_TXBF_VHT7SS1   = 157,
+	WL_RATE_1X3_TXBF_VHT8SS1   = 158,
+	WL_RATE_1X3_TXBF_VHT9SS1   = 159,
+
+	
+
+	WL_RATE_2X3_TXBF_SDM_MCS8  = 160,
+	WL_RATE_2X3_TXBF_SDM_MCS9  = 161,
+	WL_RATE_2X3_TXBF_SDM_MCS10 = 162,
+	WL_RATE_2X3_TXBF_SDM_MCS11 = 163,
+	WL_RATE_2X3_TXBF_SDM_MCS12 = 164,
+	WL_RATE_2X3_TXBF_SDM_MCS13 = 165,
+	WL_RATE_2X3_TXBF_SDM_MCS14 = 166,
+	WL_RATE_2X3_TXBF_SDM_MCS15 = 167,
+
+	WL_RATE_2X3_TXBF_VHT0SS2   = 160,
+	WL_RATE_2X3_TXBF_VHT1SS2   = 161,
+	WL_RATE_2X3_TXBF_VHT2SS2   = 162,
+	WL_RATE_2X3_TXBF_VHT3SS2   = 163,
+	WL_RATE_2X3_TXBF_VHT4SS2   = 164,
+	WL_RATE_2X3_TXBF_VHT5SS2   = 165,
+	WL_RATE_2X3_TXBF_VHT6SS2   = 166,
+	WL_RATE_2X3_TXBF_VHT7SS2   = 167,
+	WL_RATE_2X3_TXBF_VHT8SS2   = 168,
+	WL_RATE_2X3_TXBF_VHT9SS2   = 169,
+
+	
+
+	WL_RATE_3X3_TXBF_SDM_MCS16 = 170,
+	WL_RATE_3X3_TXBF_SDM_MCS17 = 171,
+	WL_RATE_3X3_TXBF_SDM_MCS18 = 172,
+	WL_RATE_3X3_TXBF_SDM_MCS19 = 173,
+	WL_RATE_3X3_TXBF_SDM_MCS20 = 174,
+	WL_RATE_3X3_TXBF_SDM_MCS21 = 175,
+	WL_RATE_3X3_TXBF_SDM_MCS22 = 176,
+	WL_RATE_3X3_TXBF_SDM_MCS23 = 177,
+
+	WL_RATE_3X3_TXBF_VHT0SS3   = 170,
+	WL_RATE_3X3_TXBF_VHT1SS3   = 171,
+	WL_RATE_3X3_TXBF_VHT2SS3   = 172,
+	WL_RATE_3X3_TXBF_VHT3SS3   = 173,
+	WL_RATE_3X3_TXBF_VHT4SS3   = 174,
+	WL_RATE_3X3_TXBF_VHT5SS3   = 175,
+	WL_RATE_3X3_TXBF_VHT6SS3   = 176,
+	WL_RATE_3X3_TXBF_VHT7SS3   = 177
+} clm_rates_t;
+
+
+#define WL_NUMRATES 178
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif 
diff --git a/src/shared/bcmwifi/src/bcmwifi_channels.c b/src/shared/bcmwifi/src/bcmwifi_channels.c
new file mode 100644
index 0000000..d00fec4
--- /dev/null
+++ b/src/shared/bcmwifi/src/bcmwifi_channels.c
@@ -0,0 +1,989 @@
+/*
+ * Misc utility routines used by kernel or app-level.
+ * Contents are wifi-specific, used by any kernel or app-level
+ * software that might want wifi things as it grows.
+ *
+ * $Copyright Open Broadcom Corporation$
+ * $Id: bcmwifi_channels.c 309193 2012-01-19 00:03:57Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmutils.h>
+
+#ifdef BCMDRIVER
+#include <osl.h>
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+#endif 
+
+#include <bcmwifi_channels.h>
+
+#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
+#include <bcmstdlib.h> 	
+#endif
+
+
+
+
+
+
+static const char *wf_chspec_bw_str[] =
+{
+	"5",
+	"10",
+	"20",
+	"40",
+	"80",
+	"160",
+	"80+80",
+	"na"
+};
+
+static const uint8 wf_chspec_bw_mhz[] =
+{5, 10, 20, 40, 80, 160, 160};
+
+#define WF_NUM_BW \
+	(sizeof(wf_chspec_bw_mhz)/sizeof(uint8))
+
+
+static const uint8 wf_5g_40m_chans[] =
+{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159};
+#define WF_NUM_5G_40M_CHANS \
+	(sizeof(wf_5g_40m_chans)/sizeof(uint8))
+
+
+static const uint8 wf_5g_80m_chans[] =
+{42, 58, 106, 122, 138, 155};
+#define WF_NUM_5G_80M_CHANS \
+	(sizeof(wf_5g_80m_chans)/sizeof(uint8))
+
+
+static const uint8 wf_5g_160m_chans[] =
+{50, 114};
+#define WF_NUM_5G_160M_CHANS \
+	(sizeof(wf_5g_160m_chans)/sizeof(uint8))
+
+
+
+static uint
+bw_chspec_to_mhz(chanspec_t chspec)
+{
+	uint bw;
+
+	bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT;
+	return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]);
+}
+
+
+static uint8
+center_chan_to_edge(uint bw)
+{
+	
+	return (uint8)(((bw - 20) / 2) / 5);
+}
+
+
+static uint8
+channel_low_edge(uint center_ch, uint bw)
+{
+	return (uint8)(center_ch - center_chan_to_edge(bw));
+}
+
+
+static int
+channel_to_sb(uint center_ch, uint ctl_ch, uint bw)
+{
+	uint lowest = channel_low_edge(center_ch, bw);
+	uint sb;
+
+	if ((ctl_ch - lowest) % 4) {
+		
+		return -1;
+	}
+
+	sb = ((ctl_ch - lowest) / 4);
+
+	
+	if (sb >= (bw / 20)) {
+		
+		return -1;
+	}
+
+	return sb;
+}
+
+
+static uint8
+channel_to_ctl_chan(uint center_ch, uint bw, uint sb)
+{
+	return (uint8)(channel_low_edge(center_ch, bw) + sb * 4);
+}
+
+
+static int
+channel_80mhz_to_id(uint ch)
+{
+	uint i;
+	for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) {
+		if (ch == wf_5g_80m_chans[i])
+			return i;
+	}
+
+	return -1;
+}
+
+
+char *
+wf_chspec_ntoa(chanspec_t chspec, char *buf)
+{
+	const char *band;
+	uint ctl_chan;
+
+	if (wf_chspec_malformed(chspec))
+		return NULL;
+
+	band = "";
+
+	
+	if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) ||
+	    (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
+		band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";
+
+	
+	ctl_chan = wf_chspec_ctlchan(chspec);
+
+	
+	if (CHSPEC_IS20(chspec)) {
+		snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
+	} else if (!CHSPEC_IS8080(chspec)) {
+		const char *bw;
+		const char *sb = "";
+
+		bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];
+
+#ifdef CHANSPEC_NEW_40MHZ_FORMAT
+		
+		if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
+			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
+		}
+
+		snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
+#else
+		
+		if (CHSPEC_IS40(chspec)) {
+			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
+			snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
+		} else {
+			snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
+		}
+#endif 
+
+	} else {
+		
+		uint chan1 = (chspec & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT;
+		uint chan2 = (chspec & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT;
+
+		
+		chan1 = (chan1 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan1] : 0;
+		chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0;
+
+		
+		snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2);
+	}
+
+	return (buf);
+}
+
+static int
+read_uint(const char **p, unsigned int *num)
+{
+	unsigned long val;
+	char *endp = NULL;
+
+	val = strtoul(*p, &endp, 10);
+	
+	if (endp == *p)
+		return 0;
+
+	
+	*p = endp;
+	
+	*num = (unsigned int)val;
+
+	return 1;
+}
+
+
+chanspec_t
+wf_chspec_aton(const char *a)
+{
+	chanspec_t chspec;
+	uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb;
+	uint num, ctl_ch;
+	uint ch1, ch2;
+	char c, sb_ul = '\0';
+	int i;
+
+	bw = 20;
+	chspec_sb = 0;
+	chspec_ch = ch1 = ch2 = 0;
+
+	
+	if (!read_uint(&a, &num))
+		return 0;
+
+	
+	c = tolower((int)a[0]);
+	if (c == 'g') {
+		a ++; 
+
+		
+		if (num == 2)
+			chspec_band = WL_CHANSPEC_BAND_2G;
+		else if (num == 5)
+			chspec_band = WL_CHANSPEC_BAND_5G;
+		else
+			return 0;
+
+		
+		if (!read_uint(&a, &ctl_ch))
+			return 0;
+
+		c = tolower((int)a[0]);
+	}
+	else {
+		
+		ctl_ch = num;
+		chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ?
+		               WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+	}
+
+	if (c == '\0') {
+		
+		chspec_bw = WL_CHANSPEC_BW_20;
+		goto done_read;
+	}
+
+	a ++; 
+
+	
+	if (c == 'u' || c == 'l') {
+		sb_ul = c;
+		chspec_bw = WL_CHANSPEC_BW_40;
+		goto done_read;
+	}
+
+	
+	if (c != '/')
+		return 0;
+
+	
+	if (!read_uint(&a, &bw))
+		return 0;
+
+	
+	if (bw == 20) {
+		chspec_bw = WL_CHANSPEC_BW_20;
+	} else if (bw == 40) {
+		chspec_bw = WL_CHANSPEC_BW_40;
+	} else if (bw == 80) {
+		chspec_bw = WL_CHANSPEC_BW_80;
+	} else if (bw == 160) {
+		chspec_bw = WL_CHANSPEC_BW_160;
+	} else {
+		return 0;
+	}
+
+	
+
+	c = tolower((int)a[0]);
+
+	
+	if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) {
+		if (c == 'u' || c == 'l') {
+			a ++; 
+			sb_ul = c;
+			goto done_read;
+		}
+	}
+
+	
+	if (c == '+') {
+		
+		static const char *plus80 = "80/";
+
+		
+		chspec_bw = WL_CHANSPEC_BW_8080;
+
+		a ++; 
+
+		
+		for (i = 0; i < 3; i++) {
+			if (*a++ != *plus80++) {
+				return 0;
+			}
+		}
+
+		
+		if (!read_uint(&a, &ch1))
+			return 0;
+
+		
+		if (a[0] != '-')
+			return 0;
+		a ++; 
+
+		
+		if (!read_uint(&a, &ch2))
+			return 0;
+	}
+
+done_read:
+	
+	while (a[0] == ' ') {
+		a ++;
+	}
+
+	
+	if (a[0] != '\0')
+		return 0;
+
+	
+
+	
+	if (sb_ul != '\0') {
+		if (sb_ul == 'l') {
+			chspec_ch = UPPER_20_SB(ctl_ch);
+			chspec_sb = WL_CHANSPEC_CTL_SB_LLL;
+		} else if (sb_ul == 'u') {
+			chspec_ch = LOWER_20_SB(ctl_ch);
+			chspec_sb = WL_CHANSPEC_CTL_SB_LLU;
+		}
+	}
+	
+	else if (chspec_bw == WL_CHANSPEC_BW_20) {
+		chspec_ch = ctl_ch;
+		chspec_sb = WL_CHANSPEC_CTL_SB_NONE;
+	}
+	
+	else if (chspec_bw != WL_CHANSPEC_BW_8080) {
+		
+		const uint8 *center_ch = NULL;
+		int num_ch = 0;
+		int sb = -1;
+
+		if (chspec_bw == WL_CHANSPEC_BW_40) {
+			center_ch = wf_5g_40m_chans;
+			num_ch = WF_NUM_5G_40M_CHANS;
+		} else if (chspec_bw == WL_CHANSPEC_BW_80) {
+			center_ch = wf_5g_80m_chans;
+			num_ch = WF_NUM_5G_80M_CHANS;
+		} else if (chspec_bw == WL_CHANSPEC_BW_160) {
+			center_ch = wf_5g_160m_chans;
+			num_ch = WF_NUM_5G_160M_CHANS;
+		} else {
+			return 0;
+		}
+
+		for (i = 0; i < num_ch; i ++) {
+			sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+			if (sb >= 0) {
+				chspec_ch = center_ch[i];
+				chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+				break;
+			}
+		}
+
+		
+		if (sb < 0) {
+			return 0;
+		}
+	}
+	
+	else {
+		int ch1_id = 0, ch2_id = 0;
+		int sb;
+
+		ch1_id = channel_80mhz_to_id(ch1);
+		ch2_id = channel_80mhz_to_id(ch2);
+
+		
+		if (ch1 >= ch2 || ch1_id < 0 || ch2_id < 0)
+			return 0;
+
+		
+		chspec_ch = (((uint16)ch1_id << WL_CHANSPEC_CHAN1_SHIFT) |
+			((uint16)ch2_id << WL_CHANSPEC_CHAN2_SHIFT));
+
+		
+
+		
+		sb = channel_to_sb(ch1, ctl_ch, bw);
+		if (sb < 0) {
+			
+			sb = channel_to_sb(ch2, ctl_ch, bw);
+			if (sb < 0) {
+				
+				return 0;
+			}
+			
+			sb += 4;
+		}
+
+		chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+	}
+
+	chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb);
+
+	if (wf_chspec_malformed(chspec))
+		return 0;
+
+	return chspec;
+}
+
+
+bool
+wf_chspec_malformed(chanspec_t chanspec)
+{
+	uint chspec_bw = CHSPEC_BW(chanspec);
+	uint chspec_ch = CHSPEC_CHANNEL(chanspec);
+
+	
+	if (CHSPEC_IS2G(chanspec)) {
+		
+		if (chspec_bw != WL_CHANSPEC_BW_20 &&
+		    chspec_bw != WL_CHANSPEC_BW_40) {
+			return TRUE;
+		}
+	} else if (CHSPEC_IS5G(chanspec)) {
+		if (chspec_bw == WL_CHANSPEC_BW_8080) {
+			uint ch1_id, ch2_id;
+
+			
+			ch1_id = CHSPEC_CHAN1(chanspec);
+			ch2_id = CHSPEC_CHAN2(chanspec);
+			if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS)
+				return TRUE;
+
+			
+			if (ch2_id <= ch1_id)
+				return TRUE;
+		} else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 ||
+		           chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) {
+
+			if (chspec_ch > MAXCHANNEL) {
+				return TRUE;
+			}
+		} else {
+			
+			return TRUE;
+		}
+	} else {
+		
+		return TRUE;
+	}
+
+	
+	if (chspec_bw == WL_CHANSPEC_BW_20) {
+		if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL)
+			return TRUE;
+	} else if (chspec_bw == WL_CHANSPEC_BW_40) {
+		if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU)
+			return TRUE;
+	} else if (chspec_bw == WL_CHANSPEC_BW_80) {
+		if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+bool
+wf_chspec_valid(chanspec_t chanspec)
+{
+	uint chspec_bw = CHSPEC_BW(chanspec);
+	uint chspec_ch = CHSPEC_CHANNEL(chanspec);
+
+	if (wf_chspec_malformed(chanspec))
+		return FALSE;
+
+	if (CHSPEC_IS2G(chanspec)) {
+		
+		if (chspec_bw == WL_CHANSPEC_BW_20) {
+			if (chspec_ch >= 1 && chspec_ch <= 14)
+				return TRUE;
+		} else if (chspec_bw == WL_CHANSPEC_BW_40) {
+			if (chspec_ch >= 3 && chspec_ch <= 11)
+				return TRUE;
+		}
+	} else if (CHSPEC_IS5G(chanspec)) {
+		if (chspec_bw == WL_CHANSPEC_BW_8080) {
+			uint16 ch1, ch2;
+
+			ch1 = wf_5g_80m_chans[CHSPEC_CHAN1(chanspec)];
+			ch2 = wf_5g_80m_chans[CHSPEC_CHAN2(chanspec)];
+
+			
+			if (ch2 > ch1 + CH_80MHZ_APART)
+				return TRUE;
+		} else {
+			const uint8 *center_ch;
+			uint num_ch, i;
+
+			if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) {
+				center_ch = wf_5g_40m_chans;
+				num_ch = WF_NUM_5G_40M_CHANS;
+			} else if (chspec_bw == WL_CHANSPEC_BW_80) {
+				center_ch = wf_5g_80m_chans;
+				num_ch = WF_NUM_5G_80M_CHANS;
+			} else if (chspec_bw == WL_CHANSPEC_BW_160) {
+				center_ch = wf_5g_160m_chans;
+				num_ch = WF_NUM_5G_160M_CHANS;
+			} else {
+				
+				return FALSE;
+			}
+
+			
+			if (chspec_bw == WL_CHANSPEC_BW_20) {
+				
+				for (i = 0; i < num_ch; i ++) {
+					if (chspec_ch == (uint)LOWER_20_SB(center_ch[i]) ||
+					    chspec_ch == (uint)UPPER_20_SB(center_ch[i]))
+						break; 
+				}
+
+				if (i == num_ch) {
+					
+					if (chspec_ch == 165)
+						i = 0;
+
+					
+					if (chspec_ch == 34 || chspec_ch == 38 ||
+					    chspec_ch == 42 || chspec_ch == 46)
+						i = 0;
+				}
+			} else {
+				
+				for (i = 0; i < num_ch; i ++) {
+					if (chspec_ch == center_ch[i])
+						break; 
+				}
+			}
+
+			if (i < num_ch) {
+				
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+
+uint8
+wf_chspec_ctlchan(chanspec_t chspec)
+{
+	uint center_chan;
+	uint bw_mhz;
+	uint sb;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+
+	
+	if (CHSPEC_IS20(chspec)) {
+		return CHSPEC_CHANNEL(chspec);
+	} else {
+		sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+
+		if (CHSPEC_IS8080(chspec)) {
+			bw_mhz = 80;
+
+			if (sb < 4) {
+				center_chan = CHSPEC_CHAN1(chspec);
+			}
+			else {
+				center_chan = CHSPEC_CHAN2(chspec);
+				sb -= 4;
+			}
+
+			
+			center_chan = wf_5g_80m_chans[center_chan];
+		}
+		else {
+			bw_mhz = bw_chspec_to_mhz(chspec);
+			center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
+		}
+
+		return (channel_to_ctl_chan(center_chan, bw_mhz, sb));
+	}
+}
+
+
+chanspec_t
+wf_chspec_ctlchspec(chanspec_t chspec)
+{
+	chanspec_t ctl_chspec = chspec;
+	uint8 ctl_chan;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+
+	
+	if (!CHSPEC_IS20(chspec)) {
+		ctl_chan = wf_chspec_ctlchan(chspec);
+		ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20;
+		ctl_chspec |= CHSPEC_BAND(chspec);
+	}
+	return ctl_chspec;
+}
+
+
+uint16
+wf_channel2chspec(uint ctl_ch, uint bw)
+{
+	uint16 chspec;
+	const uint8 *center_ch = NULL;
+	int num_ch = 0;
+	int sb = -1;
+	int i = 0;
+
+	chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+
+	chspec |= bw;
+
+	if (bw == WL_CHANSPEC_BW_40) {
+		center_ch = wf_5g_40m_chans;
+		num_ch = WF_NUM_5G_40M_CHANS;
+		bw = 40;
+	} else if (bw == WL_CHANSPEC_BW_80) {
+		center_ch = wf_5g_80m_chans;
+		num_ch = WF_NUM_5G_80M_CHANS;
+		bw = 80;
+	} else if (bw == WL_CHANSPEC_BW_160) {
+		center_ch = wf_5g_160m_chans;
+		num_ch = WF_NUM_5G_160M_CHANS;
+		bw = 160;
+	} else if (bw == WL_CHANSPEC_BW_20) {
+		chspec |= ctl_ch;
+		return chspec;
+	} else {
+		return 0;
+	}
+
+	for (i = 0; i < num_ch; i ++) {
+		sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+		if (sb >= 0) {
+			chspec |= center_ch[i];
+			chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT);
+			break;
+		}
+	}
+
+	
+	if (sb < 0) {
+		return 0;
+	}
+
+	return chspec;
+}
+
+
+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec)
+{
+	chanspec_t chspec40 = chspec;
+	uint center_chan;
+	uint sb;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+
+	if (CHSPEC_IS80(chspec)) {
+		center_chan = CHSPEC_CHANNEL(chspec);
+		sb = CHSPEC_CTL_SB(chspec);
+
+		if (sb == WL_CHANSPEC_CTL_SB_UL) {
+			
+			sb = WL_CHANSPEC_CTL_SB_L;
+			center_chan += CH_20MHZ_APART;
+		} else if (sb == WL_CHANSPEC_CTL_SB_UU) {
+			
+			sb = WL_CHANSPEC_CTL_SB_U;
+			center_chan += CH_20MHZ_APART;
+		} else {
+			
+			
+			center_chan -= CH_20MHZ_APART;
+		}
+
+		
+		chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
+		            sb | center_chan);
+	}
+
+	return chspec40;
+}
+
+
+int
+wf_mhz2channel(uint freq, uint start_factor)
+{
+	int ch = -1;
+	uint base;
+	int offset;
+
+	
+	if (start_factor == 0) {
+		if (freq >= 2400 && freq <= 2500)
+			start_factor = WF_CHAN_FACTOR_2_4_G;
+		else if (freq >= 5000 && freq <= 6000)
+			start_factor = WF_CHAN_FACTOR_5_G;
+	}
+
+	if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
+		return 14;
+
+	base = start_factor / 2;
+
+	
+	if ((freq < base) || (freq > base + 1000))
+		return -1;
+
+	offset = freq - base;
+	ch = offset / 5;
+
+	
+	if (offset != (ch * 5))
+		return -1;
+
+	
+	if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
+		return -1;
+
+	return ch;
+}
+
+
+int
+wf_channel2mhz(uint ch, uint start_factor)
+{
+	int freq;
+
+	if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) ||
+	    (ch > 200))
+		freq = -1;
+	else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
+		freq = 2484;
+	else
+		freq = ch * 5 + start_factor / 2;
+
+	return freq;
+}
+
+
+
+chanspec_t
+wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan1, uint8 chan2)
+{
+	int sb = 0;
+	uint16 chanspec = 0;
+	int chan1_id = 0, chan2_id = 0;
+
+	
+	sb = channel_to_sb(chan1, primary_20mhz, 80);
+	if (sb < 0) {
+		
+		sb = channel_to_sb(chan2, primary_20mhz, 80);
+		if (sb < 0) {
+			
+			return INVCHANSPEC;
+		}
+		
+		sb += 4;
+	}
+	chan1_id = channel_80mhz_to_id(chan1);
+	chan2_id = channel_80mhz_to_id(chan2);
+	if (chan1_id == -1 || chan2_id == -1)
+		return INVCHANSPEC;
+
+	chanspec = (chan1_id << WL_CHANSPEC_CHAN1_SHIFT)|
+		(chan2_id << WL_CHANSPEC_CHAN2_SHIFT)|
+		(sb << WL_CHANSPEC_CTL_SB_SHIFT)|
+		(WL_CHANSPEC_BW_8080)|
+		(WL_CHANSPEC_BAND_5G);
+
+	return chanspec;
+
+}
+
+
+static uint8
+wf_chspec_get80Mhz_ch(uint8 chan_80Mhz_id)
+{
+	if (chan_80Mhz_id < WF_NUM_5G_80M_CHANS)
+		return wf_5g_80m_chans[chan_80Mhz_id];
+
+	return 0;
+}
+
+
+
+uint8
+wf_chspec_primary80_channel(chanspec_t chanspec)
+{
+	uint8 chan1 = 0, chan2 = 0, primary_20mhz = 0, primary80_chan = 0;
+	int sb = 0;
+
+	primary_20mhz = wf_chspec_ctlchan(chanspec);
+
+	if (CHSPEC_IS80(chanspec))	{
+		primary80_chan = CHSPEC_CHANNEL(chanspec);
+	}
+	else if (CHSPEC_IS8080(chanspec)) {
+		chan1 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
+		chan2 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
+
+		
+		sb = channel_to_sb(chan1, primary_20mhz, 80);
+		if (sb < 0) {
+			
+			sb = channel_to_sb(chan2, primary_20mhz, 80);
+			if (!(sb < 0)) {
+				primary80_chan = chan2;
+			}
+		}
+		else {
+			primary80_chan = chan1;
+		}
+	}
+	else if (CHSPEC_IS160(chanspec)) {
+		chan1 = CHSPEC_CHANNEL(chanspec);
+		sb = channel_to_sb(chan1, primary_20mhz, 160);
+		if (!(sb < 0)) {
+		    
+			if (sb < 4) {
+				primary80_chan = chan1 - CH_40MHZ_APART;
+			}
+			
+			else
+			{
+				primary80_chan = chan1 + CH_40MHZ_APART;
+			}
+		}
+	}
+	else {
+		
+		primary80_chan = -1;
+	}
+	return primary80_chan;
+}
+
+
+uint8
+wf_chspec_secondary80_channel(chanspec_t chanspec)
+{
+	uint8 chan1 = 0, chan2 = 0, primary_20mhz = 0, secondary80_chan = 0;
+	int sb = 0;
+
+	primary_20mhz = wf_chspec_ctlchan(chanspec);
+	if (CHSPEC_IS80(chanspec)) {
+		secondary80_chan = -1;
+	}
+	else if (CHSPEC_IS8080(chanspec)) {
+		chan1 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
+		chan2 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
+
+		
+		sb = channel_to_sb(chan1, primary_20mhz, 80);
+		if (sb < 0) {
+			
+			sb = channel_to_sb(chan2, primary_20mhz, 80);
+			if (!(sb < 0)) {
+				secondary80_chan = chan1;
+			}
+		}
+		else {
+			secondary80_chan = chan2;
+		}
+	}
+	else if (CHSPEC_IS160(chanspec)) {
+		chan1 = CHSPEC_CHANNEL(chanspec);
+		sb = channel_to_sb(chan1, primary_20mhz, 160);
+		if (!(sb < 0)) {
+		    
+			if (sb < 4) {
+				secondary80_chan = chan1 + CH_40MHZ_APART;
+			}
+			
+			else
+			{
+				secondary80_chan = chan1 - CH_40MHZ_APART;
+			}
+		}
+	}
+	else {
+		
+		secondary80_chan  = -1;
+	}
+	return secondary80_chan;
+}
+
+
+chanspec_t
+wf_chspec_primary80_chspec(chanspec_t chspec)
+{
+	chanspec_t chspec80;
+	uint center_chan, chan1 = 0, chan2 = 0;
+	uint sb;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+	if (CHSPEC_IS8080(chspec)) {
+		chan1 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+		chan2 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+
+		sb = CHSPEC_CTL_SB(chspec);
+
+		if (sb < 4) {
+			
+			center_chan = chan1;
+		}
+		else
+		{
+			
+			center_chan = chan2;
+			sb -= 4;
+		}
+		
+		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 |sb | center_chan);
+	}
+	else if (CHSPEC_IS160(chspec)) {
+		center_chan = CHSPEC_CHANNEL(chspec);
+		sb = CHSPEC_CTL_SB(chspec);
+
+		if (sb < 4) {
+			
+			center_chan -= CH_40MHZ_APART;
+		}
+		else
+		{
+			
+			center_chan += CH_40MHZ_APART;
+			sb -= 4;
+		}
+		
+		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+	}
+	else
+	{
+		chspec80 = INVCHANSPEC;
+	}
+	return chspec80;
+}
diff --git a/src/shared/miniopt.c b/src/shared/miniopt.c
new file mode 100644
index 0000000..57ffa1b
--- /dev/null
+++ b/src/shared/miniopt.c
@@ -0,0 +1,145 @@
+/*
+ * Description.
+ *
+ * $Copyright Open Broadcom Corporation$
+ * $Id: miniopt.c 310902 2012-01-26 19:45:33Z $
+ */
+
+/* ---- Include Files ---------------------------------------------------- */
+
+#include <typedefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <miniopt.h>
+
+
+/* ---- Public Variables ------------------------------------------------- */
+/* ---- Private Constants and Types -------------------------------------- */
+
+
+
+/* ---- Private Variables ------------------------------------------------ */
+/* ---- Private Function Prototypes -------------------------------------- */
+/* ---- Functions -------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------- */
+void
+miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags)
+{
+	static const char *null_flags = "";
+
+	memset(t, 0, sizeof(miniopt_t));
+	t->name = name;
+	if (flags == NULL)
+		t->flags = null_flags;
+	else
+		t->flags = flags;
+	t->longflags = longflags;
+}
+
+
+/* ----------------------------------------------------------------------- */
+int
+miniopt(miniopt_t *t, char **argv)
+{
+	int keylen;
+	char *p, *eq, *valstr, *endptr = NULL;
+	int err = 0;
+
+	t->consumed = 0;
+	t->positional = FALSE;
+	memset(t->key, 0, MINIOPT_MAXKEY);
+	t->opt = '\0';
+	t->valstr = NULL;
+	t->good_int = FALSE;
+	valstr = NULL;
+
+	if (*argv == NULL) {
+		err = -1;
+		goto exit;
+	}
+
+	p = *argv++;
+	t->consumed++;
+
+	if (!t->opt_end && !strcmp(p, "--")) {
+		t->opt_end = TRUE;
+		if (*argv == NULL) {
+			err = -1;
+			goto exit;
+		}
+		p = *argv++;
+		t->consumed++;
+	}
+
+	if (t->opt_end) {
+		t->positional = TRUE;
+		valstr = p;
+	}
+	else if (!strncmp(p, "--", 2)) {
+		eq = strchr(p, '=');
+		if (eq == NULL && !t->longflags) {
+			fprintf(stderr,
+				"%s: missing \" = \" in long param \"%s\"\n", t->name, p);
+			err = 1;
+			goto exit;
+		}
+		keylen = eq ? (eq - (p + 2)) : (int)strlen(p) - 2;
+		if (keylen > 63) keylen = 63;
+		memcpy(t->key, p + 2, keylen);
+
+		if (eq) {
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr,
+				        "%s: missing value after \" = \" in long param \"%s\"\n",
+				        t->name, p);
+				err = 1;
+				goto exit;
+			}
+		}
+	}
+	else if (!strncmp(p, "-", 1)) {
+		t->opt = p[1];
+		if (strlen(p) > 2) {
+			fprintf(stderr,
+				"%s: only single char options, error on param \"%s\"\n",
+				t->name, p);
+			err = 1;
+			goto exit;
+		}
+		if (strchr(t->flags, t->opt)) {
+			/* this is a flag option, no value expected */
+			valstr = NULL;
+		} else {
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"%s: missing value parameter after \"%s\"\n", t->name, p);
+				err = 1;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+			t->consumed++;
+		}
+	} else {
+		t->positional = TRUE;
+		valstr = p;
+	}
+
+	/* parse valstr as int just in case */
+	if (valstr) {
+		t->uval = (uint)strtoul(valstr, &endptr, 0);
+		t->val = (int)t->uval;
+		t->good_int = (*endptr == '\0');
+	}
+
+	t->valstr = valstr;
+
+exit:
+	if (err == 1)
+		t->opt = '?';
+
+	return err;
+}
diff --git a/src/tools/Wifi_ASD_test/Makefile b/src/tools/Wifi_ASD_test/Makefile
new file mode 100644
index 0000000..455777c
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/Makefile
@@ -0,0 +1,37 @@
+ifndef  SRCBASE

+        SRCBASE = ../..

+endif

+

+include ../../Makerules

+include Makefile.inc

+

+

+

+ifneq ($(findstring x86,$(TARGETARCH)), x86)

+		DIRS= ${LIB}

+	else

+		DIRS= ${LIB} ${CA} ${CLI}

+endif

+

+# Make exception for android

+ifneq ($(findstring android_ndk,$(TARGETARCH)), )

+	DIRS= ${LIB}

+endif

+

+all:

+	for i in ${DIRS}; do \

+		$(MAKE) -C $$i || exit 1; \

+	done

+

+clean:

+	for i in ${DIRS}; do \

+		$(MAKE) -C $$i clean || exit 1; \

+	done

+	rm -rf ./dut/x86_mmx ./dut/arm_le

+

+release_bins:

+	for i in ${DIRS}; do \

+		$(MAKE) -C $$i release_bins; \

+	done

+

+.phony: all clean release_bins

diff --git a/src/tools/Wifi_ASD_test/Makefile.inc b/src/tools/Wifi_ASD_test/Makefile.inc
new file mode 100755
index 0000000..ba21556
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/Makefile.inc
@@ -0,0 +1,42 @@
+ifndef  SRCBASE
+        SRCBASE = ../..
+endif
+
+#include ../../Makerules
+
+LIB=lib
+CA=ca
+CLI=cli
+UCC=ucc
+MAKE=make
+
+CFLAGS = -g -O2 -D_REENTRANT -DWFA_WMM_EXT -DWFA_WMM_AC -DWFA_WMM_VOICE  -DWFA_WMM_PS_EXT -Wall -I../inc $(GCINCS) -I$(SRCBASE)/wl/exe
+CFLAGS += $(GCFLAGS)
+
+# include when DUT becomes test bed
+#CFLAGS += -DWFA_STA_TB
+ifeq ($(TARGETENV), android)
+CFLAGS += -DTARGETENV_android
+endif
+
+ifeq ($(TARGETENV), android_ndk_r6b)
+CFLAGS += -DTARGETENV_android
+CFLAGS += -fno-short-enums
+endif
+
+CALIBS = ../lib/$(TARGETARCH)/libwfa_ca.a -lpthread 
+RANLIB := $(if $(findstring android,$(TARGETENV)),$(TARGET_PREFIX))ranlib
+
+LIBWFA_NAME_CA =./$(TARGETARCH)/libwfa_ca.a
+LIBWFA_NAME =./$(TARGETARCH)/libwfa.a
+
+
+LIB_OBJS = ./$(TARGETARCH)/wfa_sock.o ./$(TARGETARCH)/wfa_tg.o ./$(TARGETARCH)/wfa_miscs_linux.o ./$(TARGETARCH)/wfa_cs.o ./$(TARGETARCH)/wfa_ca_resp.o ./$(TARGETARCH)/wfa_tlv.o ./$(TARGETARCH)/wfa_cmdtbl.o ./$(TARGETARCH)/wfa_cmdproc.o ./$(TARGETARCH)/wfa_miscs.o ./$(TARGETARCH)/wfa_thr.o ./$(TARGETARCH)/wfa_wmmps.o ./$(TARGETARCH)/wfa_wmmps_linux.o ../dut/$(TARGETARCH)/wfa_dut.o ../dut/$(TARGETARCH)/wfa_dut_init.o ./$(TARGETARCH)/wfa_typestr.o 
+
+
+LIB_OBJS_CA = wfa_sock.o wfa_tlv.o wfa_ca.o wfa_ca_resp.o wfa_cmdproc.o wfa_miscs.o wfa_miscs_linux.o wfa_cmdtbl.o wfa_thr.o wfa_wmmps.o wfa_wmmps_linux.o wfa_typestr.o 
+
+
+CLEANFILES = core core.* *.core.* *.o *.a
+
+INSTALL_DIR ?= apps
diff --git a/src/tools/Wifi_ASD_test/ca/Makefile b/src/tools/Wifi_ASD_test/ca/Makefile
new file mode 100644
index 0000000..13c862b
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/ca/Makefile
@@ -0,0 +1,24 @@
+ifndef  SRCBASE

+        SRCBASE = ../../..

+endif

+

+include ../../../Makerules

+include ../Makefile.inc

+

+# This should be one of values recognized in src/Makerules

+

+PROGS = wfa_ca

+

+all: ${PROGS}

+

+wfa_ca: wfa_ca.o wfa_ca_linux.o

+	${CC} ${CFLAGS} -DDEBUG=1 -o $@ wfa_ca.o wfa_ca_linux.o ${CALIBS}

+

+clean:

+	rm -f ${PROGS} ${CLEANFILES}

+

+release_bins:

+	@mkdir -p $(INSTALL_DIR)

+	install ${PROGS} $(INSTALL_DIR)

+

+.phony: all clean release_bins

diff --git a/src/tools/Wifi_ASD_test/ca/wfa_ca.c b/src/tools/Wifi_ASD_test/ca/wfa_ca.c
new file mode 100644
index 0000000..deeb131
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/ca/wfa_ca.c
@@ -0,0 +1,450 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN

+ *.AN

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+

+

+/*

+ * File: wfa_ca.c

+ *       This is the main program for Control Agent.

+ *

+ * Revision History:

+ *   2006/06/01 -- BETA Release by qhu

+ *   2006/06/13 -- 00.02 Release by qhu

+ *   2006/06/30 -- 00.10 Release by qhu

+ *   2006/07/10 -- 01.00 Release by qhu

+ *   2006/09/01 -- 01.05 Release by qhu

+ *   2007/01/11 -- 01.10 released by qhu

+ *   2007/02/15 -- WMM beta released by qhu, mkaroshi

+ *   2007/03/21 -- 01.40 WPA2 and Official WMM Beta release by qhu

+ *   2007/04/20 -- 02.00 WPA2 and Official WMM release by qhu

+ *   2007/08/15 --  02.10 WMM-Power Save release by qhu

+ *   2007/10/10 --  02.20 Voice SOHO beta -- qhu

+ *   2007/11/07 -- 02.30 Voice HSO -- qhu

+ *      -- on the calls wfaCtrlSend(), the string len is replaced with strlen()

+ */

+#include <stdio.h>      /* for printf() and fprintf() */

+#include <stdlib.h>     /* for atoi() and exit() */

+#include <string.h>

+

+#include "wfa_debug.h"

+#include "wfa_main.h"

+#include "wfa_types.h"

+#include "wfa_tlv.h"

+#include "wfa_tg.h"

+#include "wfa_cmds.h"

+#include "wfa_sock.h"

+#include "wfa_miscs.h"

+#include "wfa_ca.h"

+#include "wfa_agtctrl.h"

+#include "wfa_agt.h"

+#include "wfa_rsp.h"

+#include "wfa_wmmps.h"

+

+

+#define MAC_ADDR_LEN		18

+#define DEVICE_NAME_LEN		20

+#define TRANSPORT_TYPE_LEN	10

+#define SERVER_IP_LEN		20

+#define INTERFACE_NAME_LEN	31

+#define RESPONSE_SIZE		256

+

+char gnetIf[WFA_BUFF_32]; /* specify the interface to use */

+int adj_latency;          /* adjust sleep time due to latency */

+int isExit = 1;

+int gRegSec = 1;         /* regularly periodical timeout */

+int gtimeOut = 0;        /* timeout value for select call in usec */

+int gSock = -1,xcSockfd = -1, gtgSend, gtgRecv, gtgTransac;

+int rwl_wifi_flag = 0;	/*Flag to check wheather the transport is wifi */

+BYTE *xcCmdBuf = NULL, *parmsVal = NULL, *trafficBuf = NULL, *respBuf = NULL;

+

+/* stream table */

+tgStream_t *gStreams;

+struct timeval *toutvalp;

+

+#ifdef WFA_WMM_EXT

+/*

+ * Thread Synchronize flags

+ */

+tgWMM_t wmm_thr[WFA_THREADS_NUM];

+extern void *wfa_wmm_thread(void *thr_param);

+extern void *wfa_wmmps_thread();

+BOOL gtgStartSync = 0;       /* flag to sync End2End Time handshaking */

+BOOL gtgFinishSync = 0;      /* flag to sync End2End Time handshaking */

+double min_rttime = 0xFFFFFFFF;

+

+#ifdef WFA_WMM_PS_EXT

+BOOL       gtgWmmPS = 0;

+unsigned long psTxMsg[WFA_BUFF_512];

+unsigned long psRxMsg[WFA_BUFF_512];

+extern int psSockfd ;

+extern struct apts_msg apts_msgs[];

+extern void BUILD_APTS_MSG(int msg, unsigned long *txbuf);

+extern int wfaWmmPowerSaveProcess(int sockfd);

+void *g_wl_handle = NULL;

+

+int wl_set(void *wl, int cmd, void *buf, int len)

+{

+	return 0;

+}

+#endif /* WFA_WMM_PS_EXT */

+#endif /* WFA_WMM_EXT */

+

+

+#ifndef DONE

+#define DONE 1

+#endif

+

+extern typeNameStr_t nameLocalStr[];

+/* For integration */

+extern dutCommandRespFuncPtr wfaCmdRespProcFuncTbl[];

+extern void buildDutCommandRespProcessTable(void);

+extern typeNameStr_t nameStr[];

+extern char gRespStr[];

+extern sockfd_t gCaSockfd;

+extern unsigned short wfa_defined_debug;

+extern char* rwl_client_path;

+extern xcCommandFuncPtr gWfaCmdFuncTbl[]; /* command process functions */

+extern char gCmdStr[];

+extern dutCmdResponse_t gGenericResp;

+extern int clock_drift_ps;

+extern int error_check(int errno_defined);

+/*

+ * the output format can be redefined for file output.

+ */

+int

+main(int argc, char *argv[])

+{

+	char command[WFA_BUFF_1K], respStr[WFA_BUFF_128], cmdName[WFA_BUFF_32];

+	char *pcmdStr, *trafficPath;

+	unsigned short myport;

+	int maxfdn1 = -1, nfds, i, isFound, DutCmd, nbytes = 0, tag, slen;

+	int cmdLen = WFA_BUFF_1K, respLen = 0;

+	int errno_defined;

+	int length_client_path;

+	sockfd_t tmsockfd;

+	BYTE xcCmdBuf[WFA_BUFF_1K], xcCmdTag, pcmdBuf[WFA_BUFF_1K];

+	BYTE *respBuf = NULL, *parmsVal = NULL;

+	FILE* fp = NULL;

+	fd_set sockSet;

+	char *rwl_exe_path;

+	rwl_exe_path = malloc(WFA_BUFF_1K);

+	

+/* CA assumes that wl.exe will be stored in the current working directory */

+	get_rwl_exe_path(rwl_exe_path, WFA_BUFF_1K);

+	if (argc < 3) {

+		DPRINT_ERR(WFA_ERR, "Usage: %s <control agent IP (Win XP)/interface(linux) > <control port no> <--socket/--dongle/--wifi> <serverIp  port/clientComport/serverMacaddr>\n", argv[0]);

+		return 0;

+	}

+

+    /* isdigit() is not working with the build server tagged build 

+	 * so isdigit is replaced with isNumber() function call */

+

+	if (isNumber(argv[2]) == FALSE) {

+		DPRINT_ERR(WFA_ERR, "incorrect port number\n");

+		return 0;

+	}

+

+	myport = atoi(argv[2]);

+

+	/* interface_validation call checks isString() for linux and

+	 * isIPV4() for win32 OS

+	 */

+	if (interface_validation(argv[1]) == FALSE) {

+		DPRINT_ERR(WFA_ERR, "incorrect network interface\n");

+		return 0;

+	}

+

+	if((errno_defined = Start_Socket_Service()) != 0){

+		DPRINT_ERR(WFA_ERR, "Start_Socket_Service failed\n");

+		return 0;

+	}

+

+	strncpy(gnetIf, argv[1], INTERFACE_NAME_LEN); /* For integration */

+

+	if ((rwl_client_path = malloc(WFA_BUFF_256))== NULL) {

+		DPRINT_ERR(WFA_ERR, "malloc failed\r\n");

+		if((errno_defined = Stop_Socket_Service()) != 0){

+			DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+		}

+		return 0;

+	}

+

+	/* get the command line args to get the rwl exe working on different

+	 * transport links - socket/dongle/wifi */

+

+	argv += 3;

+	strcpy(rwl_client_path, rwl_exe_path);

+	while (*argv) {

+		strncat(rwl_client_path, " ", 1);

+		strncat(rwl_client_path, *argv, strlen(*argv));

+		*argv++;

+	}

+	length_client_path = strlen(rwl_client_path);

+	/* Look for wifi transport */

+	if(strstr(rwl_client_path, "--wifi") != NULL) {

+		rwl_wifi_flag = 1; 

+	} else {

+		rwl_wifi_flag = 0;

+	}

+	/* Allocate buffers */

+	if ((parmsVal = malloc(MAX_PARMS_BUFF))== NULL) {

+		DPRINT_ERR(WFA_ERR, "malloc failed allocating parmsVal\n");

+		if((errno_defined = Stop_Socket_Service()) != 0){

+			DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+		}

+		return 0;

+	}

+

+	if ((respBuf = malloc(WFA_BUFF_512))== NULL) {

+		DPRINT_ERR(WFA_ERR, "malloc failed allocating respBuf\n");

+		if((errno_defined = Stop_Socket_Service()) != 0){

+			DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+		}

+		free(parmsVal);

+		return 0;

+	}

+	DPRINT_INFO(WFA_OUT, "rwl_client_path = %s\n", rwl_client_path);

+	

+	

+	/* Create TCP socket for getting the commands from tc_cli */

+	if ((tmsockfd = wfaCreateTCPServSock(myport))== -1) {

+		DPRINT_ERR(WFA_ERR, "Failed to open socket\n");

+	    if((errno_defined = Stop_Socket_Service()) != 0){

+			DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+		}

+		return 0;

+	}

+

+	maxfdn1 = tmsockfd + 1;

+	FD_ZERO(&sockSet);

+

+	for (;;)

+	{

+		FD_ZERO(&sockSet);

+		FD_SET(tmsockfd, &sockSet);

+		maxfdn1 = tmsockfd + 1;

+

+		if (gCaSockfd != -1) {

+			FD_SET(gCaSockfd, &sockSet);

+			if (maxfdn1 < (int)gCaSockfd)

+				maxfdn1 = gCaSockfd + 1;

+		}

+		/*

+		* The timer will be set for transaction traffic if no echo is back

+		* The timeout from the select call force to send a new packet

+		*/

+		nfds = 0;

+		if ((nfds = select(maxfdn1, &sockSet, NULL, NULL, NULL)) < 0) {

+			if (error_check(errno_defined))

+				continue;

+			else

+				DPRINT_WARNING(WFA_WNG, "select error %i", errno_defined);

+		}

+

+		DPRINT_INFO(WFA_OUT, "new event \n");

+

+		if (FD_ISSET(tmsockfd, &sockSet)) {

+			gCaSockfd = wfaAcceptTCPConn(tmsockfd);

+			DPRINT_INFO(WFA_OUT, "accept new connection\n");

+				FD_SET(gCaSockfd, &sockSet);

+		}

+

+

+		if (gCaSockfd > 0 && FD_ISSET(gCaSockfd, &sockSet)) {

+			memset(xcCmdBuf, 0, WFA_BUFF_1K);

+			memset(gRespStr, 0, WFA_BUFF_512);

+			nbytes = wfaCtrlRecv(gCaSockfd, xcCmdBuf);

+			if (nbytes <= 0) {

+				asd_shutDown(gCaSockfd);

+				asd_closeSocket(gCaSockfd);

+				gCaSockfd = -1;

+				continue;

+			}

+

+			memset(respStr, 0, WFA_BUFF_128);

+			sprintf(respStr, "status,RUNNING\r\n");

+			wfaCtrlSend(gCaSockfd, (BYTE *)respStr, strlen(respStr));

+			/* WFA Comment :having this is for slowing down unexpected 

+			 * output result on CLI command sometimes 

+			 */

+			asd_sleep(1);

+			DPRINT_INFO(WFA_OUT, "%s\n", respStr);

+			DPRINT_INFO(WFA_OUT, "message %s %i\n", xcCmdBuf, nbytes);

+			slen = (int )strlen((char *)xcCmdBuf);

+			strncpy(command, (char*)xcCmdBuf, strlen((char*)xcCmdBuf));

+		   /* The carriage return and newline character need to be

+			* removed before sending the command to the DUT for the TCL 

+			* scripts to run correctly.

+			*/

+			strtok(command, "\r\n");

+			DPRINT_INFO(WFA_OUT, "last %x last-1  %x last-2 %x last-3 %x\n", cmdName[slen], cmdName[slen-1], cmdName[slen-2], cmdName[slen-3]);

+

+			xcCmdBuf[slen-3] = '\0';

+

+			isFound = 0;

+			DutCmd = 0;

+			/* tokenize for the command name. Rest of the command buffer

+		 	 * is copied to pcmdStr for command processing later.

+		 	 */

+			memcpy(cmdName, strtok_r((char *)xcCmdBuf, ",", (char **)&pcmdStr), 32);

+			i = 0;

+			/* Check if we need to execute the command using rwl client */

+			while (nameStr[i].type != -1) {

+				if ((strcmp(nameStr[i].name, cmdName) == 0)) {

+					DutCmd = 1; /* Execute the command on the server e.g tg commands */

+					break;

+				}

+				i++;

+			}

+

+			/* Search for the command to be executed using rwl client */

+			if (!DutCmd) {

+				i = 0;

+				while (nameLocalStr[i].type != -1) {

+					if ((strcmp(nameLocalStr[i].name, cmdName) == 0)) {

+						/* Found a command to be executed using rwl client */

+						isFound = 1;

+						break;

+					}

+					i++;

+				}

+			} /* !DutCmd */

+

+			DPRINT_INFO(WFA_OUT, "cmdName is %s\n", cmdName);

+

+			memset(pcmdBuf, 0, WFA_BUFF_1K);

+

+			/* Check for the valid command and the valid arguements for the command 

+			 * and return STATUS INVLID for commands that do not exist or if the arguements

+			 * for the command are invalid.

+			 */

+			if ((!isFound && !DutCmd)

+				|| (DutCmd && (nameStr[i].cmdProcFunc(pcmdStr, pcmdBuf, &cmdLen)==FALSE))

+			    || (!DutCmd && (nameLocalStr[i].cmdProcFunc(pcmdStr, pcmdBuf, &cmdLen)==FALSE))) {

+					asd_sleep(1);

+					sprintf(respStr, "status,INVALID\r\n");

+					wfaCtrlSend(gCaSockfd, (BYTE *)respStr, WFA_BUFF_128);/* Buffer size modified from strlen(respStr) on 21/11/07 */

+					DPRINT_WARNING(WFA_WNG, "Incorrect command syntax\n");

+					continue;

+			} 

+		   /*

+			* Decode the command that is parsed above to find the actual function pointer

+			* that needs to be executed. (decode for xcCmdTag )

+			* Commands that use rwl client are processed here.

+			*/

+			if (!DutCmd && isFound) {

+				/* reset two commond storages used by control functions */

+				wfaDecodeTLV(pcmdBuf, cmdLen, &xcCmdTag, &cmdLen, parmsVal);

+				memset(respBuf, 0, WFA_BUFF_512);

+				respLen = 0;

+

+				/* reset two commond storages used by control functions */

+				memset(gCmdStr, 0, WFA_CMD_STR_SZ);

+				/* command process function defined in wfa_cs.c or wfa_tg.c */

+				gWfaCmdFuncTbl[xcCmdTag](cmdLen, parmsVal, &respLen, (BYTE *)respBuf);

+

+				tag = ((wfaTLV *)respBuf)->tag;

+

+				DPRINT_INFO(WFA_OUT, "bytes=%i,%i,%x %x %x %x \n", ((wfaTLV *)respBuf)->tag,((wfaTLV *)respBuf)->len, *(respBuf+4), *(respBuf+5), *(respBuf+6), *(respBuf+7));

+

+				DPRINT_INFO(WFA_OUT, "tag %i \n", tag-WFA_STA_COMMANDS_END);

+

+				/* Response for the executed command is updated using the below function pointer

+				 * table

+				 */

+				if ((tag != 0 && tag < WFA_STA_RESPONSE_END) &&

+					wfaCmdRespProcFuncTbl[tag-WFA_STA_COMMANDS_END] != NULL) {

+					wfaCmdRespProcFuncTbl[tag-WFA_STA_COMMANDS_END](respBuf);

+				} else {

+					DPRINT_WARNING(WFA_WNG, "function not defined\n");

+					memset(respBuf, 0, sizeof (respBuf));

+					memset(pcmdBuf, 0, sizeof (pcmdBuf));

+				}

+			} else {

+				/* Commands that need to be executed at DUT are processed here

+				 * TG commands for example

+				 */

+				 /*In case of Multiple streams the commands will have space after each 

+				  * streamid. So Look for \n for the end of command.

+				  */

+				strtok(command, "\n");

+				trafficPath = malloc(WFA_BUFF_1K);

+				strcpy(trafficPath, rwl_client_path);

+

+				/* e.g wl --socket <IP Addr> <Port no> asd ca_get_version */

+				strncat(trafficPath, " asd ", 5);

+				strncat(trafficPath, command, strlen(command));

+				strncat(trafficPath, " > ", 3);

+				if ((fp = asd_cmd_exec(trafficPath)) == NULL)

+				continue;

+				memset(trafficPath, 0, WFA_BUFF_1K);

+

+				if (fread(trafficPath, sizeof(char), RESPONSE_SIZE, fp) <= 0)

+					strcpy(trafficPath, "status,ERROR\r\n");

+				

+				DPRINT_INFO(WFA_OUT, "%s %d\n", trafficPath, strlen(trafficPath));

+

+				wfaCtrlSend(gCaSockfd, (BYTE *)trafficPath, strlen(trafficPath));

+				file_cleanup(fp);

+												

+				memset(command, 0, strlen(command));

+				free(trafficPath);

+

+			} /* DutCmd */

+		} /* done with  if(gCaSockfd) */

+	} /* for */

+    if((errno_defined = Stop_Socket_Service()) != 0){

+		DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+	}

+	asd_closeSocket(gCaSockfd);

+	return 0;

+}

diff --git a/src/tools/Wifi_ASD_test/ca/wfa_ca_linux.c b/src/tools/Wifi_ASD_test/ca/wfa_ca_linux.c
new file mode 100755
index 0000000..1ac0e65
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/ca/wfa_ca_linux.c
@@ -0,0 +1,78 @@
+/*

+ * Linux port of asd command line utility

+ *

+ * Copyright 2002, Broadcom Corporation

+ * All Rights Reserved.

+ *

+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;

+ * the contents of this file may not be disclosed to third parties, copied or

+ * duplicated in any form, in whole or in part, without the prior written

+ * permission of Broadcom Corporation.

+ *

+ */

+

+#include <stdio.h> 

+#include <stdlib.h> 

+#include <string.h>

+

+#include "wfa_debug.h"

+#include "wfa_main.h"

+#include "wfa_types.h"

+#include "wfa_tlv.h"

+#include "wfa_tg.h"

+#include "wfa_cmds.h"

+#include "wfa_miscs.h"

+#include "wfa_sock.h"

+#include "wfa_ca.h"

+#include "wfa_agtctrl.h"

+#include "wfa_agt.h"

+#include "wfa_rsp.h"

+#include "wfa_wmmps.h"

+

+void

+get_rwl_exe_path(char *rwl_exe_path, int exe_path_len)

+{

+	strncpy(rwl_exe_path,  "./wl", exe_path_len);

+}

+

+int

+error_check(int errno_defined)

+{

+	if (errno == EINTR)

+		return TRUE;

+	else

+		return FALSE;

+}

+

+FILE*

+asd_cmd_exec(char * trafficPath)

+{

+	/* Execute the command through "wl" on the DUT,

+	 * read the response into trafficPath and return the response

+	 */

+	FILE *fp;

+	strncat(trafficPath,TEMP_FILE_PATH, strlen(TEMP_FILE_PATH));

+	system(trafficPath);

+	if ((fp = fopen(TEMP_FILE_PATH, "r+")) == NULL) {

+		DPRINT_ERR(WFA_ERR, "failed to open temp_file_path\n");

+		free(trafficPath);

+	}

+	return fp;

+}

+void

+file_cleanup(FILE *fp)

+{

+	char *trafficPath;

+	trafficPath = malloc(WFA_BUFF_1K);

+	fclose(fp);

+	strcpy(trafficPath,"rm -f ");

+	strncat(trafficPath,TEMP_FILE_PATH, strlen(TEMP_FILE_PATH));

+	exec_process(trafficPath);

+	free(trafficPath);

+}

+

+int

+interface_validation(char *interfac)

+{

+	return isString(interfac);

+}

diff --git a/src/tools/Wifi_ASD_test/ca/wfa_ca_win32.c b/src/tools/Wifi_ASD_test/ca/wfa_ca_win32.c
new file mode 100755
index 0000000..4f7274b
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/ca/wfa_ca_win32.c
@@ -0,0 +1,77 @@
+/*

+ * Windows port of asd command line utility

+ *

+ * Copyright 2002, Broadcom Corporation

+ * All Rights Reserved.

+ *

+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;

+ * the contents of this file may not be disclosed to third parties, copied or

+ * duplicated in any form, in whole or in part, without the prior written

+ * permission of Broadcom Corporation.

+ *

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h> 

+

+#include "wfa_debug.h"

+#include "wfa_sock.h"

+#include "wfa_main.h"

+#include "wfa_types.h"

+#include "wfa_tlv.h"

+#include "wfa_tg.h"

+#include "wfa_cmds.h"

+#include "wfa_miscs.h"

+#include "wfa_ca.h"

+#include "wfa_agtctrl.h"

+#include "wfa_agt.h"

+#include "wfa_rsp.h"

+#include "wfa_wmmps.h"

+

+void

+get_rwl_exe_path(char *rwl_exe_path, int exe_path_len)

+{

+	char *trafficPath;

+	trafficPath = malloc(WFA_BUFF_1K);

+	if(GetCurrentDirectory(WFA_BUFF_128,trafficPath) == 0) {

+		DPRINT_ERR(WFA_ERR, "Failed to get the Current path\n");

+		free(trafficPath);

+		exit(1);

+	}

+	_snprintf(rwl_exe_path, exe_path_len, " \"%s/wl\" ", trafficPath);

+	free(trafficPath);

+}

+

+int

+error_check(int unused_err)

+{

+	DPRINT_ERR(WFA_ERR, "Doing error check %d\n", unused_err);

+	if (WSAGetLastError() == WSAEINTR)

+		return TRUE;

+	else

+		return FALSE;

+}

+

+FILE*

+asd_cmd_exec(char *trafficPath)

+{

+	FILE *fp;

+	if((fp = asd_Config(trafficPath,TEMP_FILE_PATH)) == NULL){

+		DPRINT_ERR(WFA_ERR, "Command Execution Failed\n");

+		free(trafficPath);

+	}

+	return fp;

+}

+

+void

+file_cleanup(FILE *fp)

+{

+	Cleanup_File(fp);

+}

+

+int

+interface_validation(char *interfac)

+{

+	return isIpV4Addr(interfac);

+}

diff --git a/src/tools/Wifi_ASD_test/cli/Makefile b/src/tools/Wifi_ASD_test/cli/Makefile
new file mode 100644
index 0000000..7e487e7
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/cli/Makefile
@@ -0,0 +1,25 @@
+ifndef  SRCBASE
+        SRCBASE = ../../..
+endif
+
+include ../../../Makerules
+include ../Makefile.inc
+
+PROGS = ca_cli tc_cli 
+
+all: ${PROGS}
+
+ca_cli: ca_cli.o 
+	${CC} ${CFLAGS} -o $@ ca_cli.o ${CALIBS}
+
+tc_cli: tc_cli.o
+	${CC} ${CFLAGS} -o $@ tc_cli.o ${CALIBS}
+
+clean:
+	rm -f ${PROGS} ${CLEANFILES}
+
+release_bins:
+	@mkdir -p $(INSTALL_DIR)
+	install ${PROGS} $(INSTALL_DIR)
+
+.phony: all clean release_bins
diff --git a/src/tools/Wifi_ASD_test/cli/ca_cli.c b/src/tools/Wifi_ASD_test/cli/ca_cli.c
new file mode 100644
index 0000000..92d0281
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/cli/ca_cli.c
@@ -0,0 +1,213 @@
+

+/****************************************************************************

+ *  (c) Copyright 2006 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ * License is granted only to Wi-Fi Alliance members and designated Wi-Fi

+ * contractors ("Authorized Licensees").  Authorized Licensees are hereby

+ * granted the limited right to use this software solely for noncommercial

+ * applications and solely for testing Wi-Fi equipment. Authorized Licensees

+ * may embed this software into their proprietary equipment and distribute this

+ * software with such equipment under a license with at least the same

+ * restrictions as contained in this License, including, without limitation,

+ * the disclaimer of warranty and limitation of liability, below.  Other than

+ * expressly granted herein, this License is not transferable or sublicensable,

+ * and it does not extend to and may not be used with non-Wi-Fi applications.

+ *

+ * Commercial derivative works of this software or applications that use the

+ * Wi-Fi scripts generated by this software are NOT AUTHORIZED without specific

+ * prior written permission from Wi-Fi Alliance.

+ *

+ * Non-Commercial derivative works of this software for internal use are

+ * authorized and are limited by the same restrictions; provided, however,

+ * that the Authorized Licensee shall provide Wi-Fi with a copy of such

+ * derivative works under a perpetual, payment-free license to use, modify,

+ * and distribute such derivative works for purposes of testing Wi-Fi equipment.

+ *

+ * Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ * or promote products that are derived from or that use this software without

+ * specific prior written permission from Wi-Fi Alliance.

+ *

+ * THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESSED OR

+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ * OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE,

+ * ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ * (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE GOODS

+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF THE USE

+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+******************************************************************************

+ */

+

+

+/*

+ * File: ca_cli.c

+ *       This is the main program for sending a text string based command to

+ *       Control Agent (see reference document).

+ *

+ *  Revision History:

+ *         06/30/2006   -- 00.10 Release by qhu

+ *         09/01/2006   -- 01.05 Release by qhu

+ *         03/30/2007   -- 01.40 WPA2 and Official WMM Beta Release by qhu

+ *         04/20/2007   -- 02.00 WPA2 and Official WMM Release by qhu

+ */

+ /*

+ *       All the buffer size changed from 512 to MAX_CMD_BUFF(1024)

+ *

+ */

+

+#ifndef WIN32

+#include <sys/socket.h>

+#include <arpa/inet.h>

+#include <unistd.h>

+#include <errno.h>

+#endif

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+

+

+#include "wfa_types.h"

+#include "wfa_debug.h"

+#include "wfa_sock.h"

+#include "wfa_main.h"

+#include "wfa_tlv.h"

+#include "wfa_tg.h"

+#include "wfa_ca_resp.h"

+#include "wfa_cmds.h"

+#include "wfa_miscs.h"

+

+#define WFA_ENV_AGENT_IPADDR "WFA_ENV_CA_IPADDR"

+#define WFA_ENV_CA_PORT      "WFA_ENV_CA_PORT"

+

+extern int xcCmdProcGetVersion(unsigned char *parms);

+unsigned short wfa_defined_debug = WFA_DEBUG_ERR;

+int sock;

+

+char gnetIf[32];

+int gtgTransac;

+

+int

+main(int argc, char *argv[])

+{

+	struct sockaddr_in servAddr;

+	unsigned short servPort;

+	char *servIP = NULL, *tstr = NULL;

+	int bytesRcvd;

+	char cmdName[MAX_CMD_BUFF]; /* Modified as per BRCM ASD 1.3 */

+	int isFound = 0;

+	int done, errno;

+	int byteSent;

+	int rspCnt = 0;

+	BYTE caCmdBuf[MAX_CMD_BUFF]; /* Modified as per BRCM ASD 1.3 */

+	memset(caCmdBuf, 0, 512);

+	if ((argc != 2))

+	{

+		DPRINT_ERR(WFA_ERR, "Usage: %s <command string>\n", argv[0]);

+		exit(1);

+	}

+

+	if ((tstr = getenv("WFA_ENV_CA_IPADDR")) == NULL)

+	{

+		DPRINT_ERR(WFA_ERR, "Environment variable WFA_ENV_CA_IPADDR not set\n");

+		exit(1);

+	}

+

+	if (isIpV4Addr(tstr) == FALSE){

+		DPRINT_ERR(WFA_ERR, "incorrect IP number\n");

+		exit(1);

+	}

+

+	servIP = tstr;

+

+

+	if ((tstr = getenv("WFA_ENV_CA_PORT")) == NULL)

+	{

+		DPRINT_ERR(WFA_ERR, "Environment variable WFA_ENV_CA_PORT not set\n");

+		exit(1);

+	}

+

+	if (isNumber(tstr) == FALSE){

+		DPRINT_ERR(WFA_ERR, "incorrect port number\n");

+		exit(1);

+	}

+	

+	if((errno = Start_Socket_Service()) != 0){

+		DPRINT_ERR(WFA_ERR, "Start_Socket_Service failed\n");

+		return 0;

+	}

+

+	servPort = atoi(tstr);

+

+	if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)

+	{

+		DPRINT_ERR(WFA_ERR, "socket() failed");

+		if((errno = Stop_Socket_Service()) != 0){

+			DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+		}

+		return 0;

+	}

+

+	memset(&servAddr, 0, sizeof(servAddr));

+	servAddr.sin_family      = AF_INET;

+	servAddr.sin_addr.s_addr = inet_addr(servIP);

+	servAddr.sin_port        = htons(servPort);

+

+	if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)

+	{

+		DPRINT_ERR(WFA_ERR, "connect() failed");

+		if((errno = Stop_Socket_Service()) != 0){

+			DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+		}

+		return 0;

+	}

+

+	isFound = 0;

+

+	memset(cmdName, 0, MAX_CMD_BUFF);

+

+	memcpy(cmdName, argv[1], MAX_CMD_BUFF); /* Modified as per BRCM ASD 1.3 */

+

+	strcat(cmdName, " \r\n");

+

+	byteSent = wfaCtrlSend(sock, (BYTE *)cmdName, strlen(cmdName));

+	/* Modified as per BRCM ASD 1.3 */

+	memset(caCmdBuf, 0, MAX_CMD_BUFF);

+	bytesRcvd = recv(sock, caCmdBuf, MAX_CMD_BUFF, 0); /* Modified as per BRCM ASD 1.3 */

+	rspCnt++;

+	asd_sleep(1);

+	done = 1;

+	while (done)

+	{

+		printf("=======Response======\n");

+		printf("%s\n", caCmdBuf);

+		asd_sleep(1);

+		if (strncmp("status,COMPLETE", (char *)caCmdBuf, 15) == 0 ||

+			strncmp("status,INVALID", (char *)caCmdBuf, 14) == 0 ||

+			strncmp("status,ERROR", (char *)caCmdBuf, 12) == 0)

+		{

+			break;

+		}

+

+		if (rspCnt == 3)

+			break;

+

+

+		memset(caCmdBuf, 0, MAX_CMD_BUFF);

+		bytesRcvd = recv(sock, caCmdBuf, MAX_CMD_BUFF, 0);

+		/* Modified as per BRCM ASD 1.3 */

+		rspCnt++;

+	}

+	asd_closeSocket(sock);

+

+		/* Tell the user that we could not find a usable */

+	/* WinSock DLL.                                  */

+	if((errno = Stop_Socket_Service()) != 0){

+		DPRINT_ERR(WFA_ERR, "Stop_Socket_Service failed\n");

+	}

+		return 0;

+}

diff --git a/src/tools/Wifi_ASD_test/cli/tc_cli.c b/src/tools/Wifi_ASD_test/cli/tc_cli.c
new file mode 100644
index 0000000..e669d3f
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/cli/tc_cli.c
@@ -0,0 +1,209 @@
+/****************************************************************************
+ *  (c) Copyright 2006 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ * License is granted only to Wi-Fi Alliance members and designated Wi-Fi
+ * contractors ("Authorized Licensees").  Authorized Licensees are hereby
+ * granted the limited right to use this software solely for noncommercial
+ * applications and solely for testing Wi-Fi equipment. Authorized Licensees
+ * may embed this software into their proprietary equipment and distribute this
+ * software with such equipment under a license with at least the same
+ * restrictions as contained in this License, including, without limitation,
+ * the disclaimer of warranty and limitation of liability, below.  Other than
+ * expressly granted herein, this License is not transferable or sublicensable,
+ * and it does not extend to and may not be used with non-Wi-Fi applications.
+ *
+ * Commercial derivative works of this software or applications that use the
+ * Wi-Fi scripts generated by this software are NOT AUTHORIZED without specific
+ * prior written permission from Wi-Fi Alliance.
+ *
+ * Non-Commercial derivative works of this software for internal use are
+ * authorized and are limited by the same restrictions; provided, however,
+ * that the Authorized Licensee shall provide Wi-Fi with a copy of such
+ * derivative works under a perpetual, payment-free license to use, modify,
+ * and distribute such derivative works for purposes of testing Wi-Fi equipment.
+ *
+ * Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ * or promote products that are derived from or that use this software without
+ * specific prior written permission from Wi-Fi Alliance.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESSED OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE,
+ * ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+******************************************************************************
+ */
+
+
+/*
+ * File: tc_cli.c
+ *       This is the main program for sending a text string based command to
+ *       Control Agent (see reference document).
+ *
+ *    Revision History:
+ *        06/30/2006 -- 00.10 Release by qhu
+ *        09/01/2006 -- 01.01 Release by qhu
+ *        03/30/2007 -- 01.41 WPA2 and Official WMM Beta Release by qhu
+ *        04/20/2007 -- 02.00 WPA2 and Official WMM Release by qhu
+ */
+#ifndef WIN32
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "wfa_debug.h"
+#include "wfa_main.h"
+#include "wfa_types.h"
+#include "wfa_tlv.h"
+#include "wfa_tg.h"
+#include "wfa_ca_resp.h"
+#include "wfa_cmds.h"
+#include "wfa_miscs.h"
+#include "wfa_sock.h"
+
+#define WFA_ENV_TC_IPADDR "WFA_ENV_TC_IPADDR"
+#define WFA_ENV_TC_PORT      "WFA_ENV_TC_PORT"
+
+unsigned short wfa_defined_debug = WFA_DEBUG_ERR;
+
+extern int xcCmdProcGetVersion(unsigned char *parms);
+int sock;
+char gnetIf[32];
+int gtgTransac;
+
+int main(int argc, char *argv[])
+{
+	struct sockaddr_in servAddr;
+	unsigned short servPort;
+	char *servIP = NULL, *tstr = NULL;
+	int bytesRcvd;
+	char cmdName[512];
+	int isFound = 0;
+	int done;
+	int byteSent;
+	int rspCnt = 0;
+
+	BYTE caCmdBuf[512];
+
+	/* Fixed buffer size by ISAAC EZER in Epson */
+	int MAX_MESSAGE = 512;
+
+	int MAX_RECEIVE = 512;
+
+#ifdef WIN32
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	int err;
+	memset(caCmdBuf, 0, 512);
+	wVersionRequested = MAKEWORD(1, 1);
+	err = WSAStartup(wVersionRequested, &wsaData);
+	if (err != 0) {
+		/* Tell the user that we could not find a usable */
+		/* WinSock DLL.                                  */
+		return;
+	}
+#endif
+
+
+	if ((argc != 2))
+	{
+		fprintf(stderr, "Usage: %s <command string>\n", argv[0]);
+		exit(1);
+	}
+
+	if ((tstr = getenv("WFA_ENV_TC_IPADDR")) == NULL)
+	{
+		printf("Environment variable WFA_ENV_TC_IPADDR not set\n");
+		exit(1);
+	}
+
+	if (isIpV4Addr(tstr) == FALSE)
+		return FALSE;
+
+	servIP = tstr;
+
+
+	if ((tstr = getenv("WFA_ENV_TC_PORT")) == NULL)
+		printf("Environment variable WFA_ENV_TC_PORT not set\n");
+
+	if (isNumber(tstr) == FALSE)
+		return FALSE;
+
+	servPort = atoi(tstr);
+
+	if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+	{
+		perror("socket() failed");
+		exit(1);
+	}
+
+	memset(&servAddr, 0, sizeof(servAddr));
+	servAddr.sin_family      = AF_INET;
+	servAddr.sin_addr.s_addr = inet_addr(servIP);
+	servAddr.sin_port        = htons(servPort);
+
+	if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
+	{
+		perror("connect() failed");
+		exit(1);
+	}
+
+	isFound = 0;
+
+	memcpy(cmdName, argv[1], MAX_MESSAGE);
+
+	/* Fixed by ISAAC - EZER */
+	strcat(cmdName, " \r\n");
+	byteSent = wfaCtrlSend(sock, (BYTE *)cmdName, MAX_MESSAGE);
+
+	memset(caCmdBuf, '\0', sizeof(caCmdBuf));
+
+	bytesRcvd = recv(sock, caCmdBuf, MAX_RECEIVE, 0);
+	done = 1;
+	while (done)
+	{
+
+		printf("=======Response======\n");
+		printf("%s\n", caCmdBuf);
+
+		if (strncmp("status,COMPLETE", (char *)caCmdBuf, 15) == 0 ||
+			strncmp("status,INVALID", (char *)caCmdBuf, 14) == 0 ||
+			strncmp("status,ERROR", (char *)caCmdBuf, 12) == 0)
+			break;
+
+		if (rspCnt == 3)
+			break;
+
+		/* ISAAC EZER - I modified this section */
+
+		bytesRcvd = recv(sock, caCmdBuf, MAX_RECEIVE, 0);
+		rspCnt++;
+
+		if (bytesRcvd == -1)
+		{
+			perror("Error receiving message from Test Console.\n");
+			break;
+		}
+	}
+	asd_closeSocket(sock);
+
+		/* Tell the user that we could not find a usable */
+	/* WinSock DLL.                                  */
+#ifdef WIN32
+	WSACleanup();
+#endif
+	exit(0);
+}
diff --git a/src/tools/Wifi_ASD_test/dut/Makefile b/src/tools/Wifi_ASD_test/dut/Makefile
new file mode 100644
index 0000000..751340d
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/dut/Makefile
@@ -0,0 +1,16 @@
+ifndef  SRCBASE
+        SRCBASE = ../../../
+endif
+
+include ../../../Makerules
+include ../Makefile.inc
+
+DUT_OBJ= ./$(TARGETARCH)/wfa_dut.o ./$(TARGETARCH)/wfa_dut_init.o
+all: ${DUT_OBJ}
+
+$(TARGETARCH)/%.o: %.c
+	@mkdir -p $(TARGETARCH)
+	$(CC) -c $(CFLAGS) -o $@ $^
+
+clean:
+	rm -f ${PROGS} ${CLEANFILES}
diff --git a/src/tools/Wifi_ASD_test/dut/wfa_dut.c b/src/tools/Wifi_ASD_test/dut/wfa_dut.c
new file mode 100644
index 0000000..6b76126
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/dut/wfa_dut.c
@@ -0,0 +1,1035 @@
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ * License is granted only to Wi-Fi Alliance members and designated
+ * contractors (“Authorized Licensees”).  Authorized Licensees are granted
+ * the non-exclusive, worldwide, limited right to use, copy, import, export
+ * and distribute this software:
+ * (i) solely for noncommercial applications and solely for testing Wi-Fi
+ * equipment; and
+ * (ii) solely for the purpose of embedding the software into Authorized
+ * Licensee’s proprietary equipment and software products for distribution to
+ * its customers under a license with at least the same restrictions as
+ * contained in this License, including, without limitation, the disclaimer of
+ * warranty and limitation of liability, below.  The distribution rights
+ * granted in clause (ii), above, include distribution to third party
+ * companies who will redistribute the Authorized Licensee’s product to their
+ * customers with or without such third party’s private label. Other than
+ * expressly granted herein, this License is not transferable or sublicensable,
+ * and it does not extend to and may not be used with non-Wi-Fi applications.
+ * Wi-Fi Alliance reserves all rights not expressly granted herein.
+ *
+ * Except as specifically set forth above, commercial derivative works of
+ * this software or applications that use the Wi-Fi scripts generated by this
+ * software are NOT AUTHORIZED without specific prior written permission from
+ * Wi-Fi Alliance. Non-Commercial derivative works of this software for
+ * internal use are authorized and are limited by the same restrictions;
+ * provided, however, that the Authorized Licensee shall provide Wi-Fi Alliance
+ * with a copy of such derivative works under a perpetual, payment-free license
+ * to use, modify, and distribute such derivative works for purposes of testing
+ * Wi-Fi equipment.
+ * Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ * or promote products that are derived from or that use this software without
+ * specific prior written permission from Wi-Fi Alliance.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE,
+ * ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ****************************************************************************
+ */
+
+/*
+ * File: wfa_dut.c - The main program for DUT agent.
+ *       This is the top level of traffic control. It initializes a local TCP
+ *       socket for command and control link and waits for a connect request
+ *       from a Control Agent. Once the the connection is established, it
+ *       will process the commands from the Control Agent. For details, please
+ *       reference the architecture documents.
+ *
+ * Revision History:
+ *       2006/03/10  -- Initially created by qhu.
+ *       2006/06/01  -- BETA Release by qhu
+ *       2006/06/13  -- 00.02 Release by qhu
+ *       2006/06/30  -- 00.10 Official Release 00.10 by qhu
+ *       2006/07/10  -- 01.00 Official Release 01.00 by qhu
+ *       2006/09/01 --  01.05 Release by qhu
+ *       2006/10/20 --  bug fix 1. replace MAX_TRAFFIC_BUG_SZ with MAX_UDP_LEN
+ *                      that could cause crash by mismatch buf size
+ *       2006/10/26 --  01.06 replace all hardcoded buff sizes with global macro
+ *       2007/01/11 --  01.10 released by qhu
+ *       2007/02/15 --  WMM-Extention Beta released by qhu, mkaroshi
+ *       2007/03/30 --  01.40 WPA2 and Official WMM Beta Release by qhu
+ *       2007/04/20 --  02.00 WPA2 and Official WMM Release by qhu
+ *       2007/08/15 --  02.10 WMM-Power Save release by qhu
+ *       2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *       2007/11/07 --  02.30 Voice HSO -- qhu
+ *
+ */
+
+#ifndef WIN32
+#include <pthread.h>
+#include <signal.h>
+#include <time.h>
+#include <semaphore.h>
+#endif
+
+#include "wfa_debug.h"
+#include "wfa_main.h"
+#include "wfa_types.h"
+#include "wfa_sock.h"
+#include "wfa_tlv.h"
+#include "wfa_tg.h"
+#include "wfa_miscs.h"
+#include "wfa_agt.h"
+#include "wfa_rsp.h"
+#include "wfa_wmmps.h"
+#include "wfa_cmds.h"
+#include "wfa_agtctrl.h"
+#include "wfa_ca.h"
+
+
+char gRespStr[WFA_BUFF_1K], gnetIf[WFA_BUFF_32], gCmdStr[WFA_BUFF_512];
+char* rwl_client_path;
+
+unsigned short wfa_defined_debug = WFA_DEBUG_ERR | WFA_DEBUG_WARNING;
+unsigned short dfd_lvl = WFA_DEBUG_DEFAULT | WFA_DEBUG_ERR;
+
+
+int respLen = -1, tag = -1, ret_status = -1, bytesRcvd = -1, gRegSec, gtimeOut, adj_latency, g_pthrCreate =1, IPTVprof = 0, clock_drift_ps;  
+int gTCPsock = 0;
+/* the agent local Socket, Agent Control socket and baseline test socket*/
+int gagtSockfd =-1 , gxcSockfd =-1, gCaSockfd = -1, btSockfd=-1 , psSockfd =-1, btRecvSockfd = -1, gTcpRecvSockfd = -1;
+/* the WMM traffic streams socket fds - Socket Handler table */
+int tgSockfds[WFA_MAX_TRAFFIC_STREAMS];
+int e2eCnt;
+int rwl_wifi_flag;
+
+unsigned long psTxMsg[WFA_BUFF_512], psRxMsg[WFA_BUFF_512];
+
+double min_rttime ;
+
+/* Global flags for synchronizing the TG functions */
+
+BOOL       gtgSend ;         /* flag to sync Send traffic */
+BOOL       gtgRecv ;         /* flag to sync Recv traffic */
+BOOL       gtgTransac ;      /* flag to sync Transaction traffic */
+BOOL       gtgWmmPS ;
+BOOL       gtgStartSync ;       /* flag to sync End2End Time handshaking */
+BOOL       gtgFinishSync;      /* flag to sync End2End Time handshaking */
+volatile int gTransactrunLoop;
+extern struct apts_msg apts_msgs[];
+void tmout_stop_send(int);
+int wfaWmmPowerSaveProcess(int sockfd);
+
+#ifdef WIN32
+HANDLE thr_flag_cond;
+HANDLE thr_stop_cond;
+xcCommandFuncPtr gWfaCmdFuncTbl[]; /* command process functions */
+dutCommandRespFuncPtr wfaCmdRespProcFuncTbl[]; /* command process functions */
+typeNameStr_t nameStr[];
+extern HANDLE g_recvEvent[] ;
+extern HANDLE g_IPTVSndThr[];
+extern HANDLE send_event;
+extern int usedThread ;
+HANDLE g_RecvhThread;
+HANDLE g_IPTVRecvhThread[WFA_MAX_TRAFFIC_STREAMS];
+void wfaRecvStart();
+extern HANDLE g_hRecvEvent ;
+extern DWORD Win32_tmout_stop_send(LPVOID num ) ;
+void wfaSetIPTVThreadPrio(HANDLE tid, short class);
+void wfaIPTVRecvStart(LPVOID tblidx);
+void  SendIPTVFile(LPVOID strid);
+extern void wfaTxSleepTime(int profile, int rate, int *sleepTime, int *throttledRate);
+extern BYTE Send_dutResp[];
+#else
+extern xcCommandFuncPtr gWfaCmdFuncTbl[]; /* command process functions */
+extern dutCommandRespFuncPtr wfaCmdRespProcFuncTbl[]; /* command process functions */
+extern typeNameStr_t nameStr[];
+#define THREAD_SLEEP_TIME	1000
+pthread_t Thread1 = -1;
+void wfaIPTVRecvStart(void* tblidx);
+void  SendIPTVFile(void* strid);
+extern void wfaSetThreadPrio(int tid, int class);
+#endif
+
+dutCmdResponse_t gGenericResp;
+tgStream_t *findStreamProfile(int);
+tgStream_t *gStreams;         /* streams' buffers             */
+tgSyncTime_t gtgStartSyncTime;  /* End2End Start Sync record  */
+tgSyncTime_t gtgFinishSyncTime; /* End2End Finish Sync Record */
+tgE2EStats_t *e2eStats;
+
+#ifdef WFA_WMM_EXT
+#ifndef WIN32
+extern void *wfa_wmm_thread(void *thr_param);
+extern void *wfa_wmmps_thread();/* Added as per BRCM ASD 2.1 */
+sem_t sem_wmm;
+sem_t sem_wmm_resp;
+sem_t sem_gtgrecv;
+sem_t sem_iptv_gtgrecv[WFA_MAX_TRAFFIC_STREAMS];
+#else
+extern void Uapsd_Recv_Thread(void *thr_param);
+#endif
+tgWMM_t wmm_thr[WFA_THREADS_NUM];
+wfaWmmPS_t wmmps_info;
+#endif
+
+int wfa_estimate_timer_latency();
+void wfaRecvThrCreate(void);
+extern int wfaTGSetPrio(int sockfd, int tgClass);
+void  wfaSentStatsResp( BYTE *buf);
+void wfaIPTVRecvThrCreate(int  );
+
+#ifdef WIN32
+void  SendFile(LPVOID strid);
+#else
+void  SendFile(void);
+#endif
+void bcmWfaInit(void); /* Added as per BRCM 1.3 ASD */
+
+int maxfdn1 = -1;
+
+
+fd_set    sockSet;         /* Set of socket descriptors for select()     */
+struct sockfds fds;
+
+/* streams' buffers */
+extern BYTE      *xcCmdBuf, *parmsVal , *trafficBuf, *respBuf ;
+extern struct timeval *toutvalp;
+extern char gRespStr[];
+extern int isString(char *);
+extern int isNumber(char *);
+extern unsigned short wfa_defined_debug;
+
+#ifndef DONE
+#define DONE 1
+#endif
+
+
+/* This is the main function that gets called from wl server 
+ * command buffer (e.g) ca_get_version and length of the command.
+ * This is replacement of earlier main() function in the DUT
+ * However some of the earlier main function code is moved into 
+ * different functions
+ */
+int remote_asd_exec(unsigned char* command, int* cmd_len)
+{
+	int cmdLen = WFA_BUFF_1K, index, isFound; 
+	BYTE      xcCmdTag, pcmdBuf[WFA_BUFF_1K];
+	char *pcmdStr;
+	char tempbuf[WFA_BUFF_256], cmdName[WFA_BUFF_32]; 
+
+	DPRINT_INFO(WFA_OUT, " received: command %s. len %d.\n", command, *cmd_len);
+
+	maxfdn1 = gagtSockfd + 1;
+
+	/* set socket file descriptors. For baseline, there are only
+	* three sockets required. They are an agent main socket,
+	* Control Agent link socket and Traffic Generator Socket.
+	*/
+	fds.agtfd = &gagtSockfd;
+	fds.tgfd = &btSockfd;
+	/*btRecvSockfd added to receive the traffic for all the profiles 
+	* and also support the Bi-directional profiles
+	*/
+	fds.tgRevfd = &btRecvSockfd;
+	fds.cafd = &gCaSockfd;
+	fds.wmmfds = tgSockfds;
+
+#ifdef WFA_WMM_PS_EXT
+	fds.psfd = &psSockfd;
+#endif
+#ifndef WIN32
+	sem_init(&sem_wmm,0,0);
+	sem_init(&sem_wmm_resp,0,0);
+	sem_init(&sem_gtgrecv,0,0);
+	for(index=0; index < WFA_MAX_TRAFFIC_STREAMS; index++) {
+		sem_init(&sem_iptv_gtgrecv[index],0,0);
+	}
+#endif
+	DPRINT_INFO(WFA_OUT, "gtgsend = %d, gtgrecv = %d,  btSockfd = %d, btRecvSockfd = %d \n", gtgSend, gtgRecv, btSockfd, btRecvSockfd);
+
+
+	/* Receive the asd command here and then tokenize for the command name. Rest of the
+	* command buffer is copied to pcmdStr for command processing later.
+	*/
+	memset(xcCmdBuf, 0, WFA_BUFF_1K);
+	/*Look for the \n  for the end of command*/ 
+	strtok((char *)command, "\n");
+	DPRINT_INFO(WFA_OUT, "message %s. %d\n", command, strlen((char *)command));
+	strcpy(tempbuf, (char *)command);
+	strtok(tempbuf, ",");
+	memcpy(cmdName, strtok_r((char *)command, ",", (char **)&pcmdStr), strlen(tempbuf));
+	/* The cmdName is appended with '\0' to get rid of the '\r\n' in the command*/
+	cmdName[strlen(tempbuf)] = '\0';
+	index = 0;
+	isFound = 0;
+	DPRINT_INFO(WFA_OUT, "cmdName %s\n pcmdStr is %s.\n", cmdName, pcmdStr);
+	/* To check for the command that needs to be executed 
+	* we loop through a function pointer table and mark that as found.
+	*/
+	while (nameStr[index].type != -1) {
+		if (strcmp(nameStr[index].name, cmdName) == 0) {
+			isFound = 1;
+			break;
+		}
+		index++;
+	}
+
+	memset(pcmdBuf, 0, WFA_BUFF_1K);
+
+	/* If the command is not found or if the arguments are invalid, we return
+	* with invalid response. Otherwise, call for command proc functions where
+	* the parsing and encoding of the commands take place.  
+	* The function definitions are found in wfa_cmdproc.c file
+	*/
+	if (!isFound || (nameStr[index].cmdProcFunc(pcmdStr, pcmdBuf, &cmdLen) == FALSE)) {
+		asd_sleep(1);
+		sprintf(gRespStr, "status,INVALID\n");
+		DPRINT_INFO(WFA_OUT, "Incorrect command syntax\n");
+		*cmd_len = strlen(gRespStr);
+		memcpy(command, gRespStr, *cmd_len);
+		return -1;
+	}
+
+	/* Decode the command to get the tag of the command */
+	wfaDecodeTLV(pcmdBuf, cmdLen, &xcCmdTag, &cmdLen, parmsVal);
+	memset(respBuf, 0, WFA_BUFF_512);
+	respLen = 0;
+
+	DPRINT_INFO(WFA_OUT, "total %i cmdLen %i tag %i\n", cmdLen, cmdLen, xcCmdTag);
+
+	/* reset two command storages used by control functions */
+	memset(gCmdStr, 0, WFA_CMD_STR_SZ);
+	memset(&gGenericResp, 0, sizeof(dutCmdResponse_t));
+	memset(gRespStr, 0, WFA_BUFF_1K);
+
+	/* command process function defined in wfa_cs.c OR wfa_tg.c */
+	gWfaCmdFuncTbl[xcCmdTag](cmdLen, parmsVal, &respLen, (BYTE *)respBuf);
+	
+	wfaSetSockFiDesc(&sockSet, &maxfdn1, &fds);
+
+	/* If command is other than traffic send command then the reply goes 
+	* from function pointer table in wfaCmdRespProcFuncTbl
+	* gRespStr variable gets updated there.
+	*/
+
+	tag = ((wfaTLV *)respBuf)->tag;
+	memcpy(&ret_status, respBuf+4, 4);
+	DPRINT_INFO(WFA_OUT, "bytes=%i, %i,%i,%x %x %x %x \n", bytesRcvd, ((wfaTLV *)respBuf)->tag,((wfaTLV *)respBuf)->len, *(respBuf+4), *(respBuf+5), *(respBuf+6), *(respBuf+7));
+	DPRINT_INFO(WFA_OUT, "tag %i \n", tag-WFA_STA_COMMANDS_END);
+	if ((tag != 0 && tag < WFA_STA_RESPONSE_END) &&  \
+		wfaCmdRespProcFuncTbl[tag-WFA_STA_COMMANDS_END] != NULL) {
+			wfaCmdRespProcFuncTbl[tag-WFA_STA_COMMANDS_END](respBuf);
+	}	
+	
+	/*Update the command with response buffer and cmd_Len with the response length */
+	*cmd_len = strlen(gRespStr);
+	memset(command, 0, *cmd_len);
+	strncpy((char *)command, gRespStr, (size_t)strlen(gRespStr));
+	DPRINT_INFO(WFA_OUT, " %s\n", command);
+	return 0;
+}
+
+/* Dut receive is moved into this thread for waiting for the 
+ * UDP packets to arrive in case of file transfer/Multicast (TG)
+ */
+void wfaRecvStart()
+{
+	int sn, n;
+	struct timeval ttval;
+#ifndef WIN32
+	struct timeval currTimeVal;
+#else
+	unsigned long nonblocking = 1;
+	SYSTEMTIME currTimeVal;
+#endif
+
+#ifdef WFA_DUT_SYNC
+	int traffic_start_drift;
+#endif
+
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+	/*Receiver for WMMPS traffic*/
+	if(gtgWmmPS > 0){
+		while (gtgWmmPS > 0) 
+			if(psSockfd > 0 && FD_ISSET(psSockfd, &sockSet))
+				wfaWmmPowerSaveProcess(psSockfd);
+
+#ifdef WIN32
+		if(SetEvent(g_hRecvEvent) == 0){
+				DPRINT_INFO(WFA_OUT, "ResetEvent failure %d \n", GetLastError());
+		}
+		while ((WaitForSingleObject(g_RecvhThread, INFINITE) != WAIT_OBJECT_0));
+		if(g_hRecvEvent != NULL)
+			CloseHandle(g_hRecvEvent);
+#endif /* WIN32 */
+	}
+		
+#endif
+#endif
+	/* calling accept for tcp conection */ 
+	if(gTCPsock == 1 && btRecvSockfd == -1)
+		btRecvSockfd = wfaAcceptTCPConn(gTcpRecvSockfd);
+	
+#ifdef WIN32
+#else
+	/*Recieve the traffic untill the user stops the traffic and resets gtgRecv flag*/
+	while (gtgRecv)
+#endif
+	{
+		int i = gtgRecv?gtgRecv:gtgTransac;
+		memset(trafficBuf, 0 , sizeof(trafficBuf));
+		n = wfaRecvFile(btRecvSockfd, i, (char  *)trafficBuf);
+		/* If it is testing transaction, once it receives a packet
+		* send a new one right away.
+		*/
+		if(n > 0)
+		{
+			if(gtgTransac != 0)
+			{
+				memset(respBuf, 0, WFA_BUFF_512);
+				respLen = 0;
+
+				if(wfaSendShortFile(btRecvSockfd, gtgTransac,
+					trafficBuf, n, respBuf, &respLen) == DONE)
+				{
+					DPRINT_INFO(WFA_OUT,"Inform to stop\n");
+				}
+			}
+		}
+
+		if ((IPTVprof == 1)  && (n !=0 )) { 
+			sn = bigEndianBuff2Int(&((tgHeader_t *)trafficBuf)->hdr[8]);
+			ttval.tv_sec = bigEndianBuff2Int(&((tgHeader_t *)trafficBuf)->hdr[12]);
+			ttval.tv_usec = bigEndianBuff2Int(&((tgHeader_t *)trafficBuf)->hdr[16]);
+#ifndef WIN32
+			gettimeofday(&currTimeVal, NULL);
+#else
+			GetSystemTime(&currTimeVal);
+#endif
+
+#ifdef WFA_DUT_SYNC
+			/*
+			* If this is the beginning of the test from packet 10,
+			* re-adjust the clock for drifting
+			*/
+			if (sn >= 10 && sn < 15)
+			{
+				double bdftime = wfa_timeval2double(&currTimeVal) - gtgStartSyncTime.dut_time;
+
+				if (bdftime > 10.00)
+				{
+					//Set the clock to the TM clock again (with delay)
+					currTimeVal.tv_sec = ttval.tv_sec;
+					currTimeVal.tv_usec = ttval.tv_usec + gtgStartSyncTime.dtime/2 * 1000000;
+					// plus drift
+					traffic_start_drift = clock_drift_ps * bdftime;
+					currTimeVal.tv_usec += traffic_start_drift;
+					if(currTimeVal.tv_usec < 0)
+					{
+						currTimeVal.tv_sec -=1;
+						currTimeVal.tv_usec += 1000000;
+					}
+					else if(currTimeVal.tv_usec >= 1000000)
+					{
+						currTimeVal.tv_sec += 1;
+						currTimeVal.tv_usec -= 1000000;
+					}
+					// clock reset
+					settimeofday(&currTimeVal, NULL);
+				}
+			}
+#endif
+			/*
+			* take the end2end stats
+			*/
+			if (e2eCnt < 6000)
+			{
+				tgE2EStats_t *ep = &e2eStats[e2eCnt++];
+				ep->seqnum = sn;
+				ep->rsec = ttval.tv_sec;
+				ep->rusec = ttval.tv_usec;
+#ifndef WIN32
+				ep->lsec = currTimeVal.tv_sec;
+				ep->lusec = currTimeVal.tv_usec;
+#else
+				ep->lsec = currTimeVal.wSecond;;
+				ep->lusec = currTimeVal.wMilliseconds * 1000; 
+#endif
+				if(ep->lusec  < 0)
+				{
+					ep->lsec -=1;
+					ep->lusec += 1000000;
+				}
+				else if(ep->lusec >= 1000000)
+				{
+					ep->lsec += 1;
+					ep->lusec -= 1000000;
+				}
+			}
+		} /* if(IPTVprof) */
+	}/* while (gtgRecv) */ 
+#ifndef WIN32
+	/* Sending signal to wfaTGRecvStop to close the socket
+	 * since the receive is complete
+	 */
+	sem_post(&sem_gtgrecv);
+
+	if ((pthread_kill(Thread1, 0)) < 0)
+		DPRINT_INFO(WFA_OUT,"\nRecvStart thread kill failed\n");
+#endif
+	if(btRecvSockfd != -1){
+		DPRINT_INFO(WFA_OUT, "cloasing the recv socket \n");
+		asd_closeSocket( btRecvSockfd);
+		btRecvSockfd = -1;
+	}
+
+}
+
+/*Create the thread for receiving the traffic from the TG in the case if File transfer, Multicast and Transaction profiles*/
+void wfaRecvThrCreate(void)
+{
+#ifndef WIN32
+	//pthread_t Thread1 = -1;
+	int thrId = -1;
+	/* Start the thread to receive */
+	if((thrId = pthread_create(&Thread1, NULL, (void *)wfaRecvStart, NULL)) != 0)
+	{
+		DPRINT_ERR(WFA_OUT, "Error created Recv Thread\n");
+		return;
+	}
+	DPRINT_INFO(WFA_OUT, "Created thread %d\n", thrId);
+#else
+	DWORD RecvGenericThread;
+	g_RecvhThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)wfaRecvStart, NULL, 0, &RecvGenericThread);
+
+	if (g_RecvhThread == NULL){
+		DPRINT_INFO(WFA_OUT, "g_RecvhThread not created\n");
+	} else {
+		DPRINT_INFO(WFA_OUT, "thread priority = %d\n", GetThreadPriority(g_RecvhThread));
+		SetThreadPriority(g_RecvhThread, THREAD_PRIORITY_NORMAL + 1);
+	}
+#endif
+}
+
+
+/* Called by send commands of TG */
+#ifdef WIN32
+void  SendFile(LPVOID strid)
+#else
+void  SendFile(void)
+#endif
+{
+#ifdef WIN32
+	DWORD errnum = 0;
+	unsigned long nonBlocking = 1;
+	int sleepTime = 0;
+	int throttledRate = 0;
+	int counter = -1;
+	int throttled_est_cost;
+	int act_sleep_time;
+	tgProfile_t *theProf = NULL;
+#else
+	struct timeval lstime;
+#endif
+
+	int asn = 1, bytesrecv, i;
+
+	int nfds;
+	struct timeval *tovalp;
+	fd_set socketSet;
+	tgStream_t *myStream = NULL;
+	/*
+	* If the profile is set for file transfer, this will run to
+	* complete (blocking).
+	*/
+#ifdef WIN32
+	gtgSend = (BOOL)strid;
+#endif
+	if (gtgSend != 0 && gtgTransac == 0) {
+
+		memset(respBuf, 0, WFA_BUFF_512);
+		respLen = 0;
+		myStream = findStreamProfile(gtgSend);
+
+		if (myStream->profile.startdelay > 0 && myStream->profile.startdelay  < 50) {
+			DPRINT_INFO(WFA_OUT, "sleeping for %d\n", myStream->profile.startdelay);
+			asd_sleep(myStream->profile.startdelay);
+		}
+#ifndef WIN32
+		signal(SIGALRM, tmout_stop_send);
+		alarm(myStream->profile.duration);
+#endif
+		DPRINT_INFO(WFA_OUT, "sendlongfile btsockfd = %d gtgsend = %d\n", btSockfd, gtgSend);
+		/* For frame rate of zero pump data at high speed. */
+		if (myStream->profile.rate != 0) 
+			wfaSendLongFile(btSockfd, gtgSend, respBuf, &respLen );
+		else
+			wfaImprovePerfSendLongFile(btSockfd, gtgSend, respBuf, &respLen );
+
+		if(btSockfd != -1){
+			asd_closeSocket(btSockfd);
+			btSockfd= -1;
+		}
+	}
+	/* For transaction test, if it times out without receive a packet,
+	* here it should initiate/send the next transac packet and count
+	* a packet loss for the previous one
+	*/
+	if (gtgTransac != 0 ) {
+		gTransactrunLoop = 1;
+		memset(respBuf, 0, WFA_BUFF_512);
+		respLen = 0;
+		myStream = findStreamProfile(gtgSend);
+
+		if (myStream->profile.startdelay > 0 && myStream->profile.startdelay  < 50) {
+			DPRINT_INFO(WFA_OUT, "sleeping for %d\n", myStream->profile.startdelay);
+			asd_sleep(myStream->profile.startdelay);
+		}
+#ifdef WIN32
+	theProf = &myStream->profile;
+	if(theProf->duration != 0)
+	{
+		DPRINT_INFO(WFA_OUT, "duration %i\n", theProf->duration);
+		/*
+		*  use this to decide periodical interval sleep time and frames to send
+		*  int the each interval.
+		*  Each device should adopt a own algorithm for better performance
+		*/
+		wfaTxSleepTime(theProf->profile, theProf->rate, &sleepTime, &throttledRate);
+		
+		/*
+		 * Here assumes it takes 20 usec to send a packet and 20 usec to receive one
+		 * Must estimate the cost per packet
+		 * reused concept in SendLongFile in wfa_tg.c
+		 */
+		throttled_est_cost = throttledRate * 40;  // MUST estimate the cost per ppk
+		act_sleep_time = sleepTime - throttled_est_cost;
+		if (act_sleep_time <= 0)
+			act_sleep_time = sleepTime;
+
+		DPRINT_INFO(WFA_OUT, "sleep time %i act_sleep_time %i\n", sleepTime, act_sleep_time);
+	}
+#endif
+
+		while(gTransactrunLoop)
+		{
+			tovalp = NULL;    
+			if(gtimeOut != 0 || gRegSec != 0) {
+				/*
+				* The timer will be set for transaction traffic if no echo is back
+				* The timeout from the select call force to send a new packet
+				*/
+				tovalp = wfaSetTimer(gRegSec, gtimeOut*1000, toutvalp);
+			}
+
+			nfds = 0;
+			FD_ZERO(&socketSet);
+#ifndef WIN32
+			FD_SET(btSockfd, &socketSet);
+#else
+			FD_SET((u_int)btSockfd, &socketSet);
+#endif
+			if ( (nfds = select(maxfdn1, &socketSet, NULL, NULL, tovalp)) < 0) {
+#ifndef WIN32 
+				if (errno == EINTR)
+#else
+				if (WSAGetLastError() == WSAEINTR)
+#endif                  
+					continue;             /* back to for() */
+				else
+#ifndef WIN32
+					DPRINT_WARNING(WFA_WNG, "select error: %i", errno);
+#else
+					DPRINT_WARNING(WFA_WNG, "select error: %i", WSAGetLastError());
+#endif
+			}
+			bytesrecv = 0;
+#ifdef WFA_WMM_EXT
+#ifndef WIN32
+			/*
+			* handle end to end time syc
+			*/
+			gettimeofday(&lstime, NULL);
+			/* If your device is BIG ENDIAN, you need to
+			* modify the the function calls
+			*/
+			int2BuffBigEndian(asn++, &((tgHeader_t *)trafficBuf)->hdr[8]);
+			int2BuffBigEndian(lstime.tv_sec, &((tgHeader_t *)trafficBuf)->hdr[12]);
+			int2BuffBigEndian(lstime.tv_usec, &((tgHeader_t *)trafficBuf)->hdr[16]);
+#endif
+#endif
+			memset(respBuf, 0, WFA_BUFF_512);
+			respLen = 0;
+			/* Careful: Since gtgTransac can change outside the scope of this thread 
+			 * as 0 we still need to check for this. Otherwise we will end up getting 
+			 * no statistics. 
+			 */
+#ifdef WIN32
+			/*
+			 * counter is kept to check the number of frames sending
+			 * If the number of frames sent more than expected (rate*duration)
+			 * do nothing till time out
+			 */
+			counter++;
+			if (counter >= theProf->duration * theProf->rate)
+				continue;
+#endif
+			if(gtgTransac != 0) {
+				if(wfaSendShortFile(btSockfd, gtgTransac,
+					trafficBuf, 0, respBuf, &respLen) == DONE) {
+				}
+			}
+
+			memset(trafficBuf, 0, sizeof(trafficBuf));
+			respLen = 0;
+
+			i = gtgRecv?gtgRecv:gtgTransac;
+#ifdef WIN32
+			/* Unblock the socket to make wfaRecvFile() non-blocking call in the case of
+			 * Transaction Profile*/				
+			if(ioctlsocket(btSockfd, FIONBIO, &nonBlocking) != 0) {
+				DPRINT_INFO(WFA_OUT, "Non-Blocking socket failed\n");
+			}
+#endif			
+			if(i!=0) {
+				bytesrecv = wfaRecvFile(btSockfd, i, (char*)trafficBuf);
+				if(bytesrecv  == 0){
+					DPRINT_INFO(WFA_OUT, "No packets received\n");
+				}
+			}
+#ifdef WIN32
+			/*
+			 * Sleep added to reduce the amount of frame sending
+			 * by dut in case of transaction rpofile
+			 */
+			usleep(act_sleep_time);
+#endif
+		} // While
+		if(btSockfd != -1){
+			asd_closeSocket(btSockfd);
+			btSockfd = -1;
+		}
+	} // gtgTransac
+}
+
+void wfa_dut_deinit()
+{
+#ifdef WFA_WMM_EXT
+	int cntThr;
+#endif
+
+	/* free the buffer that are  used in DUT */
+	free(gStreams);
+	free(trafficBuf);
+	free(toutvalp);
+	free(respBuf);
+	free(xcCmdBuf);
+	free(parmsVal);
+	free(e2eStats);
+
+	/* Close sockets */
+	asd_closeSocket(gagtSockfd);
+	asd_closeSocket(btSockfd);
+	asd_closeSocket(btRecvSockfd);
+
+#ifdef WFA_WMM_EXT
+	for(cntThr = 0; cntThr < WFA_MAX_TRAFFIC_STREAMS; cntThr++)
+	{
+		if( tgSockfds[cntThr] != -1 )
+		{
+			asd_closeSocket(tgSockfds[cntThr]);
+			tgSockfds[cntThr] = -1;
+		}
+	}
+#ifdef WFA_WMM_PS_EXT
+	asd_closeSocket(psSockfd);
+#endif /* WFA_WMM_PS_EXT */
+
+#endif /* WFA_WMM_EXT */
+}
+
+/*Create the thread for receiving the WMM traffic from the TG*/
+void wfaIPTVRecvThrCreate(int tblIndex)
+{
+#ifndef WIN32
+	pthread_t Thread1 = -1;
+	int thrId = -1;
+	pthread_attr_t attr;
+	struct sched_param  param;
+	pthread_attr_init(&attr);
+	pthread_attr_getschedparam(&attr, &param);
+	/* Recv thread priority decreased */
+	param.sched_priority = 10;
+	pthread_attr_setschedparam(&attr, &param);
+	/* Start the thread to receive */
+	if((thrId = pthread_create(&Thread1, &attr, (void *)wfaIPTVRecvStart, &tblIndex)) != 0)
+	{
+		DPRINT_ERR(WFA_OUT, "Error created Recv Thread\n");
+		return;
+	}
+	sleep(1);
+	DPRINT_INFO(WFA_OUT, "Created thread %d\n", thrId);
+	return;
+#else
+	DWORD RecvGenericThread;
+	/*Create the thread event for multiple streams and hold the thread handles in the array*/
+	g_IPTVRecvhThread[tblIndex] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)wfaIPTVRecvStart, (LPVOID)tblIndex, 0, &RecvGenericThread);
+	if (g_IPTVRecvhThread[tblIndex] == NULL){
+		DPRINT_INFO(WFA_OUT, "g_RecvhThread not created\n");
+	} else {
+		DPRINT_INFO(WFA_OUT, "thread priority = %d\n", GetThreadPriority(g_IPTVRecvhThread[tblIndex]));
+		SetThreadPriority(g_IPTVRecvhThread[tblIndex], THREAD_PRIORITY_NORMAL+1);
+	}
+#endif
+}
+
+
+/* This is the receive thread function that receives the traffic in the case of 
+ * IPTV. In the case of multiple streams the the receive happens on multiple sockets
+ * and waits on multiple events to stop the receive operation.
+ */
+#ifdef WIN32
+void wfaIPTVRecvStart(LPVOID tblidx)
+#else
+void wfaIPTVRecvStart(void* tblidx)
+#endif
+{
+	int sn, n;
+	struct timeval ttval;
+#ifndef WIN32
+	struct timeval currTimeVal;
+#else
+	unsigned long nonblocking = 1;
+	SYSTEMTIME currTimeVal;
+#endif
+
+#ifdef WFA_DUT_SYNC
+	int traffic_start_drift;
+#endif
+	int index;
+#ifdef WIN32
+	index = (int)tblidx ;
+#else
+	index  = *(int*)tblidx ;
+#endif	  
+#ifdef WIN32  
+	DPRINT_INFO(WFA_OUT, "g_recvEvent[index] %i , tblindex = %d, streamid = %d\n ", g_recvEvent[index], 
+		index, gStreams[index].id);
+#endif
+
+#ifdef WIN32	
+	/* Each Stream in the WMM is associated with particular event.
+	* Wait for the particular event to be signalled for that corresponding 
+	* stream.
+	*/
+	if (ioctlsocket(tgSockfds[index], FIONBIO, &nonblocking) != 0)
+		DPRINT_ERR(WFA_OUT, "Error in blocking socket\n");
+
+		while ((WaitForSingleObject(g_recvEvent[index],0) != WAIT_OBJECT_0))
+#else
+	/*Recieve the traffic untill the user stops the traffic and resets gtgRecv flag*/
+	while (gtgRecv)
+#endif
+	{		
+		memset(trafficBuf, 0 , sizeof(trafficBuf));
+		n = wfaRecvFile(tgSockfds[index], gStreams[index].id, (char  *)trafficBuf);
+		if ((IPTVprof == 1)  && (n !=0 )) { 
+			sn = bigEndianBuff2Int(&((tgHeader_t *)trafficBuf)->hdr[8]);
+			ttval.tv_sec = bigEndianBuff2Int(&((tgHeader_t *)trafficBuf)->hdr[12]);
+			ttval.tv_usec = bigEndianBuff2Int(&((tgHeader_t *)trafficBuf)->hdr[16]);
+#ifndef WIN32
+			gettimeofday(&currTimeVal, NULL);
+#else
+			GetSystemTime(&currTimeVal);
+#endif
+			/*
+			* take the end2end stats
+			*/
+			if (e2eCnt < 6000)
+			{
+				tgE2EStats_t *ep = &e2eStats[e2eCnt++];
+				ep->seqnum = sn;
+				ep->rsec = ttval.tv_sec;
+				ep->rusec = ttval.tv_usec;
+#ifndef WIN32
+				ep->lsec = currTimeVal.tv_sec;
+				ep->lusec = currTimeVal.tv_usec;
+#else
+				ep->lsec = currTimeVal.wSecond;;
+				ep->lusec = currTimeVal.wMilliseconds * 1000; 
+#endif
+				if(ep->lusec  < 0)
+				{
+					ep->lsec -=1;
+					ep->lusec += 1000000;
+				}
+				else if(ep->lusec >= 1000000)
+				{
+					ep->lsec += 1;
+					ep->lusec -= 1000000;
+				}
+			}
+		} /* if(IPTVprof) */
+	}/* while (gtgRecv) */
+#ifndef WIN32
+	/* Sending signal to wfaTGRecvStop to close the socket
+	 * since the receive is complete
+	 */	
+	sem_post(&sem_iptv_gtgrecv[index]);
+
+	pthread_exit(NULL);
+#endif
+	if(tgSockfds[index] != -1){
+		asd_closeSocket(tgSockfds[index]);
+		tgSockfds[index] = -1;
+	}
+	return ;
+}
+
+/*
+ * 	wfaSetThreadPrio():
+ *  Set thread priorities for different threads depending on the traffic-class 
+ * Voice- Highest Priority
+ * Video- One lower than highest
+ * BackGround- 2 lower than highest
+ * Best-Effort-3 Lower than highest
+ *  
+ */
+#ifdef WIN32
+void wfaSetIPTVThreadPrio(HANDLE tid, short class)
+{
+	DWORD thrPriority;
+
+	switch(class)
+	{
+	case TG_WMM_AC_VO:
+		thrPriority = THREAD_PRIORITY_NORMAL-3;
+		break;
+	case TG_WMM_AC_BK:
+		thrPriority = THREAD_PRIORITY_NORMAL-1;
+		break;
+	case TG_WMM_AC_BE:
+		thrPriority = THREAD_PRIORITY_NORMAL;
+		break;
+	case TG_WMM_AC_VI:
+		thrPriority = THREAD_PRIORITY_NORMAL-2;
+	default:
+		/* default */
+		;
+	}
+	DPRINT_INFO(WFA_OUT, " thrPriority = %d\n", thrPriority );
+
+	SetThreadPriority(tid, thrPriority);
+}
+#endif
+
+/* Thread function that is called when we want to send the WMM traffic.
+ * This thread function sets the TOS bits for the traffic class, sets the priority 
+ * depending on traffic class and then sends the WMM streams
+ */
+#ifdef WIN32
+void  SendIPTVFile(LPVOID strid)
+#else
+void  SendIPTVFile(void * strid)
+#endif
+{
+	tgStream_t *myStream = NULL;
+	tgProfile_t *theProfile;
+	int status = STATUS_COMPLETE;
+	int mySock = -1;
+	int streamid;
+#ifdef WIN32
+	streamid = (int)strid;
+#else
+	streamid = *(int*)strid;
+#endif
+	/*
+	* If the profile is set for file transfer, this will run to
+	* complete (blocking).
+	*/
+	DPRINT_INFO(WFA_OUT, "streamid WMM %d , strid = %d\n", streamid, (int)strid);		
+	memset(respBuf, 0, WFA_BUFF_512);
+	respLen = 0;
+	myStream = findStreamProfile(streamid);
+	if(myStream == NULL)
+	{
+		status = STATUS_INVALID;
+		return ;
+	}
+
+	theProfile = &myStream->profile;
+	if(theProfile == NULL)
+	{
+		status = STATUS_INVALID;
+		return ;
+	}
+
+	mySock = wfaCreateUDPSock(theProfile->sipaddr, theProfile->sport);
+	mySock = wfaConnectUDPPeer(mySock, theProfile->dipaddr, theProfile->dport);
+	/*
+	* Set packet/socket priority TOS field
+	*/
+	wfaTGSetPrio(mySock, theProfile->trafficClass);
+#ifdef WIN32
+	wfaSetIPTVThreadPrio(GetCurrentThread(),theProfile->trafficClass);
+#else
+	wfaSetThreadPrio(pthread_self(), theProfile->trafficClass);
+#endif
+	DPRINT_INFO(WFA_OUT, "mySock %d , index =%d\n", mySock, myStream->tblidx);
+
+	if (theProfile->startdelay > 0 && theProfile->startdelay  < 50) {
+		DPRINT_INFO(WFA_OUT, "sleeping for %d\n", theProfile->startdelay);
+		asd_sleep(theProfile->startdelay);
+	}
+	DPRINT_INFO(WFA_OUT, "sendlongfile mySock = %d gtgsend = %d\n", mySock, streamid);
+
+	if (theProfile->rate != 0) 
+		wfaSendLongFile(mySock, streamid, respBuf, &respLen );
+	else
+		wfaImprovePerfSendLongFile(mySock, streamid, respBuf, &respLen );
+
+	if(mySock != -1) {
+		asd_closeSocket(mySock);
+	}
+}
+
+/* This function is specific to IPTV. 
+ * We take the response from all the streams and update the buffer
+ * will all the statistics.
+ */
+
+void  wfaSentStatsResp( BYTE *buf)
+{
+	int i;
+	tgStream_t *allStreams = gStreams;
+	dutCmdResponse_t *sendStatsResp = (dutCmdResponse_t *)buf;
+
+	if(sendStatsResp == NULL)
+		return;
+
+	for(i = 0; i < WFA_MAX_TRAFFIC_STREAMS; i++) {
+		if((allStreams->id != 0) && (allStreams->profile.direction == DIRECT_SEND)) {
+			sendStatsResp->status = STATUS_COMPLETE;
+			sendStatsResp->streamId = allStreams->id;
+			memcpy(&sendStatsResp->cmdru.stats, &allStreams->stats, sizeof(tgStats_t));
+
+			sendStatsResp++;
+		}
+		allStreams++;
+	}
+
+	return;
+}
diff --git a/src/tools/Wifi_ASD_test/dut/wfa_dut.h b/src/tools/Wifi_ASD_test/dut/wfa_dut.h
new file mode 100644
index 0000000..948b25c
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/dut/wfa_dut.h
@@ -0,0 +1,47 @@
+
+/****************************************************************************
+ *  (c) Copyright 2006 Wi-Fi Alliance.  All Rights Reserved 
+ *
+ * 
+ *  LICENSE
+ *
+ * License is granted only to Wi-Fi Alliance members and designated Wi-Fi 
+ * contractors ("Authorized Licensees").  Authorized Licensees are hereby 
+ * granted the limited right to use this software solely for noncommercial 
+ * applications and solely for testing Wi-Fi equipment. Authorized Licensees 
+ * may embed this software into their proprietary equipment and distribute this
+ * software with such equipment under a license with at least the same 
+ * restrictions as contained in this License, including, without limitation, 
+ * the disclaimer of warranty and limitation of liability, below.  Other than 
+ * expressly granted herein, this License is not transferable or sublicensable, 
+ * and it does not extend to and may not be used with non-Wi-Fi applications.
+ *
+ * Commercial derivative works of this software or applications that use the 
+ * Wi-Fi scripts generated by this software are NOT AUTHORIZED without specific
+ * prior written permission from Wi-Fi Alliance.
+ *
+ * Non-Commercial derivative works of this software for internal use are 
+ * authorized and are limited by the same restrictions; provided, however, 
+ * that the Authorized Licensee shall provide Wi-Fi with a copy of such 
+ * derivative works under a perpetual, payment-free license to use, modify, 
+ * and distribute such derivative works for purposes of testing Wi-Fi equipment.
+ *
+ * Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse 
+ * or promote products that are derived from or that use this software without 
+ * specific prior written permission from Wi-Fi Alliance.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESSED OR 
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ * OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE, 
+ * ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+ * (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+ 
+
+#define WFA_DUT_AGENT
diff --git a/src/tools/Wifi_ASD_test/dut/wfa_dut_init.c b/src/tools/Wifi_ASD_test/dut/wfa_dut_init.c
new file mode 100644
index 0000000..086418e
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/dut/wfa_dut_init.c
@@ -0,0 +1,160 @@
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ * License is granted only to Wi-Fi Alliance members and designated
+ * contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ * the non-exclusive, worldwide, limited right to use, copy, import, export
+ * and distribute this software:
+ * (i) solely for noncommercial applications and solely for testing Wi-Fi
+ * equipment; and
+ * (ii) solely for the purpose of embedding the software into Authorized
+ * Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ * its customers under a license with at least the same restrictions as
+ * contained in this License, including, without limitation, the disclaimer of
+ * warranty and limitation of liability, below..AN  The distribution rights
+ * granted in clause (ii), above, include distribution to third party
+ * companies who will redistribute the Authorized Licensee$B!G(Bs product to their
+ * customers with or without such third party$B!G(Bs private label. Other than
+ * expressly granted herein, this License is not transferable or sublicensable,
+ * and it does not extend to and may not be used with non-Wi-Fi applications..AN 
+ * Wi-Fi Alliance reserves all rights not expressly granted herein..AN 
+ *
+ * Except as specifically set forth above, commercial derivative works of
+ * this software or applications that use the Wi-Fi scripts generated by this
+ * software are NOT AUTHORIZED without specific prior written permission from
+ * Wi-Fi Alliance..AN Non-Commercial derivative works of this software for
+ * internal use are authorized and are limited by the same restrictions;
+ * provided, however, that the Authorized Licensee shall provide Wi-Fi Alliance
+ * with a copy of such derivative works under a perpetual, payment-free license
+ * to use, modify, and distribute such derivative works for purposes of testing
+ * Wi-Fi equipment.
+ * Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ * or promote products that are derived from or that use this software without
+ * specific prior written permission from Wi-Fi Alliance.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ * ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ****************************************************************************
+ *
+ *  Revision History:
+ *       2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *       2007/11/07 --  02.30 Voice HSO -- qhu
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef WIN32
+#include <pthread.h>
+#include <time.h>
+#endif
+#include "wfa_debug.h"
+#include "wfa_main.h"
+#include "wfa_types.h"
+#include "wfa_sock.h"
+#include "wfa_tg.h"
+#include "wfa_miscs.h"
+
+extern tgStream_t *gStreams;
+extern tgE2EStats_t *e2eStats;
+extern int adj_latency;           /* adjust sleep time due to latency */
+extern int        gagtSockfd;
+#ifdef WFA_WMM_EXT
+extern tgWMM_t wmm_thr[];
+extern void *wfa_wmm_thread(void *thr_param);
+extern void init_thr_flag();
+extern int wfa_estimate_timer_latency();
+#endif /* WFA_WMM_EXT */
+
+#define LOCAL_PORT 11000
+
+void wfa_dut_init(BYTE **tBuf, BYTE **rBuf, BYTE **paBuf, BYTE **cBuf, struct timeval **timerp)
+{
+    /* allocate the traffic stream table */
+    gStreams = (tgStream_t *) malloc(WFA_MAX_TRAFFIC_STREAMS*sizeof(tgStream_t));
+    if(gStreams == NULL)
+    {
+        DPRINT_ERR(WFA_ERR, "Failed to malloc theStreams\n");
+        exit(1);
+    }
+
+    /* a buffer used to carry receive and send test traffic */
+    *tBuf = (BYTE *) malloc(MAX_UDP_LEN+1); /* alloc a traffic buffer */
+    if(*tBuf == NULL)
+    {
+        DPRINT_ERR(WFA_ERR, "Failed to malloc traffic buffer\n");
+        exit(1);
+    }
+
+    /* a buffer used for response of control command */
+    *rBuf = (BYTE *)malloc(WFA_BUFF_512);
+    if(*rBuf == NULL)
+    {
+        DPRINT_ERR(WFA_ERR, "Failed to malloc response buffer\n");
+        exit(1);
+    }
+
+    /* timer used in select call */
+    *timerp = malloc(sizeof(struct timeval));
+    if(*timerp == NULL)
+    {
+        DPRINT_ERR(WFA_ERR, "Failed to malloc timer val\n");
+        exit(1);
+    }
+
+    /* control command buf */
+    *cBuf = malloc(WFA_BUFF_1K);
+    if(*cBuf == NULL)
+    {
+        DPRINT_ERR(WFA_ERR, "Failed to malloc control command buf\n");
+        exit(1);
+    }
+
+    /* parameters buff */
+    *paBuf = malloc(MAX_PARMS_BUFF);
+    if(*paBuf == NULL)
+    {
+        DPRINT_ERR(WFA_ERR, "Failed to malloc parms value buff\n");
+        exit(1);
+    }
+#ifndef WIN32
+#ifdef WFA_WMM_EXT
+    /* allocate for End2End stats */
+    init_thr_flag();
+#endif /* WFA_WMM_EXT   */
+#endif /* WIN32 */
+
+	e2eStats = malloc(6144*sizeof(tgE2EStats_t));
+    if(e2eStats == NULL)
+    {
+       DPRINT_ERR(WFA_ERR, "Failed to malloc e2eStats\n");
+       exit(1);
+    }
+
+
+#ifdef WIN32
+	adj_latency = wfa_Win_estimate_timer_latency() + 4000; /* four more mini */
+#else    
+	adj_latency = wfa_estimate_timer_latency() + 4000; /* four more mini */
+#endif
+
+    /* 4create listening TCP socket */
+    gagtSockfd = wfaCreateTCPServSock(LOCAL_PORT);
+
+	if(gagtSockfd == -1)
+    {
+       DPRINT_ERR(WFA_ERR, "Failed to open socket\n");
+       exit(1);
+    }
+}
diff --git a/src/tools/Wifi_ASD_test/inc/wfa_agt.h b/src/tools/Wifi_ASD_test/inc/wfa_agt.h
new file mode 100644
index 0000000..602a74f
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_agt.h
@@ -0,0 +1,58 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+#ifndef WFA_AGT_H

+#define WFA_AGT_H

+

+typedef int (*xcCommandFuncPtr)(int len, BYTE *parms, int *respLen, BYTE *respBuf);

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_agtctrl.h b/src/tools/Wifi_ASD_test/inc/wfa_agtctrl.h
new file mode 100644
index 0000000..8494e0f
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_agtctrl.h
@@ -0,0 +1,70 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */ 

+

+#ifndef WFA_AGTCTRL_H

+#define WFA_AGTCTRL_H

+

+typedef int (*commandStrProcFuncPtr)(char *, BYTE *, int *);

+

+typedef struct type_name_str_table

+{

+     int type;

+     char name[32];

+     commandStrProcFuncPtr cmdProcFunc;

+} typeNameStr_t;

+

+extern int buildCommandProcessTable(void);

+

+typedef int (*dutCommandRespFuncPtr)(BYTE *cmdBuf);

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_ca.h b/src/tools/Wifi_ASD_test/inc/wfa_ca.h
new file mode 100644
index 0000000..65bd02b
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_ca.h
@@ -0,0 +1,113 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+ 

+

+#ifndef _WFA_CA_H_

+#define _WFA_CA_H_

+

+#define ENCRYPT_NONE         0

+#define ENCRYPT_WEP          1

+#define ENCRYPT_TKIP         2

+#define ENCRYPT_AESCCMP      3

+#define WMMAC_UPLINK         0

+#define WMMAC_DOWNLINK       1

+#define WMMAC_BIDIR          3

+#define GROUP_WMMAC          0

+#define GROUP_WMMCONF        1

+#define WMMAC_ADDTS          0

+#define WMMAC_DELTS          1

+#define WMMAC_AC_BE          0

+#define WMMAC_AC_BK          1

+#define WMMAC_AC_VI          2

+#define WMMAC_AC_VO          3

+

+extern int wfaStaAssociate(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaIsConnected(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaGetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaVerifyIpConnection(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaGetMacAddress(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetMacAddress(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+

+extern int wfaStaGetBSSID(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaGetStats(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaSetEncryption(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetEapTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetPSK(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaDeviceGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaDeviceListIF(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetEapTTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetEapSim(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetPEAP(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetEapSIM(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetPEAP(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetUAPSD(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetIBSS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaDebugSet(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetMode(int, BYTE *, int *, BYTE *);

+extern int wfaStaSetWMM(int, BYTE *, int *, BYTE *);

+extern int wfaStaSendNeigreq(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetSystime(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSet11n(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetRifsTest(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetWireless(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSendAddba(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSendCoexistMgmt(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetDisconnect(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetEapFAST(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaSetEapAKA(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaResetDefault(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);

+extern int wfaStaReAssociate(int, BYTE*, int*, BYTE*);

+extern int wfaStaSetPwrSave(int, BYTE *, int *, BYTE *);

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_ca_resp.h b/src/tools/Wifi_ASD_test/inc/wfa_ca_resp.h
new file mode 100644
index 0000000..e70ba47
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_ca_resp.h
@@ -0,0 +1,108 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN

+ *.AN

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE

+ ******************************************************************************

+ */

+

+

+#ifndef WFA_CA_RESP_H

+#define WFA_CA_RESP_H

+

+typedef int (*dutCommandRespFuncPtr)(BYTE *cmdBuf);

+

+int caCmdNotDefinedYet(BYTE *cmdBuf);

+int wfaStaVerifyIpConnectResp(BYTE *cmdBuf);

+int wfaStaSetIpConfigResp(BYTE *cmdBuf);

+int wfaStaIsConnectedResp(BYTE *cmdBuf);

+int wfaStaGetIpConfigResp(BYTE *cmdBuf);

+int wfaGetVersionResp(BYTE *cmdBuf);

+int wfaStaGetInfoResp(BYTE *cmdBuf);

+int wfaTrafficAgentConfigResp(BYTE *cmdBuf);

+int wfaTrafficAgentSendResp(BYTE *cmdBuf);

+int wfaTrafficAgentRecvStartResp(BYTE *cmdBuf);

+int wfaTrafficAgentRecvStopResp(BYTE *cmdBuf);

+int wfaTrafficAgentResetResp(BYTE *cmdBuf);

+int wfaTrafficAgentPingStartResp(BYTE *cmdBuf);

+int wfaTrafficAgentPingStopResp(BYTE *cmdBuf);

+int wfaStaGetMacAddressResp(BYTE *cmdBuf);

+int wfaStaGetBSSIDResp(BYTE *cmdBuf);

+int wfaStaSetEncryptionResp(BYTE *cmdBuf);

+int wfaStaSetEapTLSResp(BYTE *cmdBuf);

+int wfaStaSetPSKResp(BYTE *cmdBuf);

+int wfaStaSetEapTTLSResp(BYTE *cmdBuf);

+int wfaStaSetEapSIMResp(BYTE *cmdBuf);

+int wfaStaSetEapPEAPResp(BYTE *cmdBuf);

+int wfaStaAssociateResp(BYTE *cmdBuf);

+int wfaStaSetIBSSResp(BYTE *cmdBuf);

+int wfaStaGetStatsResp(BYTE *cmdBuf);

+int wfaDeviceGetInfoResp(BYTE *cmdBuf);

+int wfaDeviceListIFResp(BYTE *cmdBuf);

+int wfaStaDebugSetResp(BYTE *cmdBuf);

+void wfaStaDebugHexDump(BYTE *cmdBuf);

+int wfaStaSetModeResp(BYTE *cmdBuf);

+int wfaStaSetWMMResp(BYTE *cmdBuf);

+

+int wfaStaSetUAPSDResp(BYTE *cmdBuf); /* Added as per BRCM 1.3 ASD */

+int wfaStaSendNeigreqResp(BYTE *cmdBuf);

+int wfaStaSetSystimeResp(BYTE *cmdBuf);

+int wfaStaSet11nResp(BYTE *cmdBuf);

+int wfaStaSetRifsTestResp(BYTE *cmdBuf);

+int wfaStaSetWirelessResp(BYTE *cmdBuf);

+int wfaStaSendAddbaResp(BYTE *cmdBuf);

+int wfaStaSendCoexistMgmtResp(BYTE *cmdBuf);

+int wfaStaDisconnectResp(BYTE *cmdBuf);

+int wfaStaSetEapFASTResp(BYTE *cmdBuf);

+int wfaStaSetEapAKAResp(BYTE *cmdBuf);

+int wfaStaResetDefaultResp(BYTE * cmdBuf);

+int wfaStaSetPwrsaveResp(BYTE *cmdBuf);

+int wfaStaReassociateResp(BYTE *cmdBuf);

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_cmds.h b/src/tools/Wifi_ASD_test/inc/wfa_cmds.h
new file mode 100644
index 0000000..48354d1
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_cmds.h
@@ -0,0 +1,380 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE

+ ******************************************************************************

+ */

+ 

+

+/*

+ * wfa_cmds.h:

+ *   definitions of command types.

+ */

+#ifndef _WFA_CMDS_H

+#define _WFA_CMDS_H

+

+typedef struct _tg_ping_start

+{

+    char dipaddr[IPV4_ADDRESS_STRING_LEN];  /* destination/remote ip address */

+    int  frameSize;

+    int  frameRate;

+    int  duration;

+    int  type;

+    int  qos;

+} tgPingStart_t;

+

+typedef struct ca_sta_set_ip_config

+{

+    char intf[WFA_IF_NAME_LEN];

+    int isDhcp;

+    char ipaddr[WFA_IP_ADDR_STR_LEN];

+    char mask[WFA_IP_MASK_STR_LEN];

+    char defGateway[WFA_IP_ADDR_STR_LEN];

+    char pri_dns[WFA_IP_ADDR_STR_LEN];

+    char sec_dns[WFA_IP_ADDR_STR_LEN];

+} caStaSetIpConfig_t;

+

+typedef struct ca_sta_verify_ip_connection

+{

+   char dipaddr[WFA_IP_ADDR_STR_LEN];

+   int timeout;

+} caStaVerifyIpConnect_t;

+

+typedef struct ca_sta_set_encryption

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   int encpType;

+   char keys[4][32];  /* 26 hex */

+   int activeKeyIdx;

+} caStaSetEncryption_t;

+

+typedef struct ca_sta_set_mode

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   char mode;

+   int encpType;

+   int channel;

+   char keys[4][32];  /* 26 hex */

+   int activeKeyIdx;

+} caStaSetMode_t;

+

+

+typedef struct ca_sta_set_psk

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   BYTE passphrase[64];

+   char keyMgmtType[8];  /* WPA-PSK */

+   int encpType;    /* TKIP    */

+} caStaSetPSK_t;

+

+typedef struct ca_sta_set_eaptls

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   char keyMgmtType[8];

+   char encrptype[8];

+   char trustedRootCA[128];

+   char clientCertificate[128];

+} caStaSetEapTLS_t;

+

+typedef struct ca_sta_set_eapttls

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   char username[32];

+   char passwd[16];

+   char keyMgmtType[8];

+   char encrptype[8];

+   char trustedRootCA[32];

+   char clientCertificate[32];

+} caStaSetEapTTLS_t;

+

+typedef struct ca_sta_set_eapsim

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   char username[32];

+   char passwd[16];

+   char keyMgmtType[8];

+   char encrptype[8];

+} caStaSetEapSIM_t;

+

+typedef struct ca_sta_set_eappeap

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   char username[32];

+   char passwd[16];

+   char keyMgmtType[8];

+   char encrptype[8];

+   char trustedRootCA[32];

+   char innerEAP[16];

+   int peapVersion;

+} caStaSetEapPEAP_t;

+typedef struct ca_sta_set_eapfast

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   char username[32];

+   char passwd[16];

+   char keyMgmtType[8];

+   char encrptype[9];

+   char trustedRootCA[32];

+   char innerEAP[16];

+   char	validateServer;

+   char pacFileName[32];

+} caStaSetEapFAST_t;

+

+typedef struct ca_sta_set_eapaka

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   char username[32];

+   char passwd[96];

+   char keyMgmtType[8];

+   char encrptype[9];

+   char	tripletCount;

+   char tripletSet[3][96];

+} caStaSetEapAKA_t;

+

+typedef struct ca_sta_set_uapsd

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   int maxSPLength;

+   BYTE acBE;

+   BYTE acBK;

+   BYTE acVI;

+   BYTE acVO;

+} caStaSetUAPSD_t;

+

+typedef struct ca_sta_set_ibss

+{

+   char intf[WFA_IF_NAME_LEN];

+   char ssid[WFA_SSID_NAME_LEN];

+   int channel;

+   int encpType;

+   char keys[4][32];

+   int activeKeyIdx;

+} caStaSetIBSS_t;

+

+typedef struct sta_get_testdata

+{

+   int type;

+   int next;     /* sequence number, 0 is the last one */

+} caStaGetTestData_t;

+

+typedef struct sta_debug_set

+{

+   unsigned short level;

+   unsigned short state;

+} staDebugSet_t;

+typedef struct config

+{

+   BYTE wmm;

+   int  rts_thr ;

+   int  frag_thr ;

+} wmmconf_t;

+

+typedef struct wmm_tsinfo

+{

+unsigned int Reserved1 :1;

+unsigned int TID       :4;

+unsigned int direction :2;

+unsigned int dummy1    :1;

+unsigned int dummy2    :1;

+unsigned int Reserved2 :1;

+unsigned int PSB       :1;

+unsigned int UP        :3;

+unsigned int Reserved3 :2;

+unsigned int Reserved4 :1;

+unsigned int Reserved5 :7;

+}wmmtsinfo_t;

+typedef struct wmm_tspec

+{

+wmmtsinfo_t      tsinfo;

+BOOL Fixed;//The MSDU Fixed Bit

+unsigned short size;//The MSDU Size

+unsigned short maxsize;//MAximum MSDU Size

+unsigned int   min_srvc;//The minimum Service Interval

+unsigned int   max_srvc;//The maximum Service Interval

+unsigned int inactivity;//Inactivity Interval

+unsigned int suspension;//The Suspension Interval

+unsigned int srvc_strt_tim;//The Service Start Time

+unsigned int mindatarate;//The Minimum Data Rate

+unsigned int meandatarate;//The Minimum Data Rate

+unsigned int peakdatarate;//The Minimum Data Rate

+unsigned int burstsize;//The Maximum Burst Size

+unsigned int delaybound;//The Delay Bound

+unsigned int PHYrate;//The minimum PHY Rate

+float sba;//The Surplus Bandwidth Allownce

+unsigned short medium_time;//The medium time

+

+}wmmtspec_t;

+typedef struct wmmac_addts

+{

+   BYTE       dialog_token;

+   BYTE       accesscat;

+   wmmtspec_t tspec;

+} wmmacadd_t;

+

+typedef struct ca_sta_set_wmm

+{

+   char intf[WFA_IF_NAME_LEN];

+   BYTE group;

+   BYTE action;

+   BYTE       send_trig;

+   char       dipaddr[WFA_IP_ADDR_STR_LEN];

+   BYTE       trig_ac;

+   union _action

+   {

+       wmmconf_t   config;

+       wmmacadd_t  addts;

+       BYTE        delts;

+   } actions;

+} caStaSetWMM_t;

+

+typedef struct ca_sta_set_pwrsave

+{

+   char intf[WFA_IF_NAME_LEN];

+   int mode;

+} caStaSetPwrSave_t;

+

+typedef struct ca_sta_reset_default

+{

+   char intf[WFA_IF_NAME_LEN];

+   char prog[WFA_DEFAULT_PROG_NAME];

+} caStaResetDefault_t;

+

+typedef struct ca_dev_info

+{

+   BYTE fw;

+} caDevInfo_t;

+

+typedef struct sta_time {

+	int month;

+	int date;

+	int year;

+	int hours;

+	int minutes;

+	int seconds;

+} caStaTime_t;

+

+#ifdef WFA_STA_TB

+typedef struct sta_set_11n {

+	short int intolerant_40;

+	short int addba_reject;

+	short int ampdu;

+	short int amsdu;

+	short int greenfield;

+	short int sgi20;

+	short int stbc_rx;

+	short int width; /* if auto set it to -1 */

+	short int mcs_fixedrate;

+	short int mcs32; /* Ignore as of now */

+	short int smps;

+	int txsp_stream;

+	int rxsp_stream;

+} caStaSet11n_t;

+

+typedef struct coexist_mgmt

+{

+	char Mhz[INTOLERANT_LEN];

+	char bss[INTOLERANT_LEN];

+	char ChnlRepo[CHNL_LIST];

+} caStaSendCoexistmgmt_t;

+#endif  /* WFA_STA_TB */

+typedef struct dut_commands

+{

+   char intf[WFA_IF_NAME_LEN];

+   char mac[WFA_MAC_ADDR_STR_LEN];

+   union _cmds

+   {

+       int streamId;

+       int iftype;

+       tgProfile_t profile;

+       tgPingStart_t startPing;

+       char ssid[WFA_SSID_NAME_LEN];

+       char bssid[WFA_MAC_ADDR_STR_LEN];

+       caStaSetIpConfig_t ipconfig;

+       caStaVerifyIpConnect_t verifyIp;

+       caStaSetEncryption_t wep;       

+       caStaSetPSK_t        psk;

+       caStaSetEapTLS_t     tls;

+       caStaSetEapTTLS_t    ttls;

+       caStaSetEapSIM_t     sim;

+       caStaSetEapPEAP_t    peap;

+       caStaSetUAPSD_t      uapsd;

+       caStaSetIBSS_t       ibss;

+       caStaGetTestData_t   tdata;

+       caStaSetWMM_t        setwmm;

+       staDebugSet_t        dbg;

+       caDevInfo_t          dev;

+       caStaTime_t	    stime;

+#ifdef WFA_STA_TB       

+       short int action_rifs;

+       short int tid;

+       char wireless_band[WIRELESS_BAND];

+       caStaSet11n_t	    set11n;

+       caStaSendCoexistmgmt_t	coexistmgmt;

+#endif   

+   } cmdsu;    

+} dutCommand_t;

+

+extern int buildCommandProcessTable(void);

+#ifdef WIN32

+extern BOOL IPProperties(caStaSetIpConfig_t*, DWORD*);

+extern void ResetIP(caStaSetIpConfig_t * );

+

+#endif

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_debug.h b/src/tools/Wifi_ASD_test/inc/wfa_debug.h
new file mode 100644
index 0000000..ea0062b
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_debug.h
@@ -0,0 +1,79 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+ 

+

+#ifndef WFA_DEBUG_H

+#define WFA_DEBUG_H

+

+#define WFA_ERR         stderr  /* error: can be redefined to a log file */

+#define WFA_OUT         stdout  /* info:  can be redefined to a log file */

+#define WFA_WNG         stdout  /* warning: can be redefined to a log file */

+

+#define WFA_DEBUG_DEFAULT          0x0001

+#define WFA_DEBUG_ERR              0x0001

+#define WFA_DEBUG_INFO             0x0002

+#define WFA_DEBUG_WARNING          0x0004

+

+#define WFA_DEBUG 1

+

+#define DPRINT_ERR      fprintf(WFA_ERR, "File %s, Line %ld: ", \

+                               __FILE__, (long)__LINE__); \

+                        fprintf 

+

+#define DPRINT_INFO     if(wfa_defined_debug & WFA_DEBUG_INFO) \

+                            fprintf

+

+#define DPRINT_WARNING  if(wfa_defined_debug & WFA_DEBUG_WARNING) \

+                            fprintf

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_main.h b/src/tools/Wifi_ASD_test/inc/wfa_main.h
new file mode 100644
index 0000000..8890cd0
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_main.h
@@ -0,0 +1,104 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+ 

+

+#ifndef _WFA_MAIN_H

+#define _WFA_MAIN_H

+

+#define WFA_MAX_TRAFFIC_STREAMS            6

+

+/* maximum number of streams to support */

+#define WFA_MAX_WMM_STREAMS            4 

+

+#define MAX_CMD_BUFF        1024 

+#define MAX_PARMS_BUFF      512 

+

+#define MAX_TRAFFIC_BUF_SZ  1536

+

+#define WFA_BUFF_32         32

+#define WFA_BUFF_64         64

+#define WFA_BUFF_128        128

+#define WFA_BUFF_256        256

+#define WFA_BUFF_512        512

+#define WFA_BUFF_1K         1024

+

+#define WFA_CMD_STR_SZ      512 

+

+/* WMM TRAFFIC CLASS LEVEL */

+#define WFA_TRAFFIC_CLASS_NUM   6

+

+/* Threads to handle WMM traffic */

+#define WFA_THREADS_NUM         6

+

+char* path;

+

+enum tg_port

+{

+    UDP_PORT_BE1 = 0,

+    UDP_PORT_BE2 = 1,

+    UDP_PORT_BK1 = 2,

+    UDP_PORT_BK2 = 3,

+    UDP_PORT_VI1 = 4,

+    UDP_PORT_VI2 = 5,

+    UDP_PORT_VO1 = 6,

+    UDP_PORT_VO2 = 7,

+    UDP_PORT_ND1 = 8,

+    UDP_PORT_ND2 = 9

+};

+

+#ifndef WIN32

+#define min(a,b)        ((a) < (b) ? (a) : (b))

+#define max(a,b)        ((a) > (b) ? (a) : (b))

+#endif

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_miscs.h b/src/tools/Wifi_ASD_test/inc/wfa_miscs.h
new file mode 100644
index 0000000..f011c08
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_miscs.h
@@ -0,0 +1,176 @@
+
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN 
+ *.AN 
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN 
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN 
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+ 
+
+#ifndef _WFA_MISCS_H_
+#define _WFA_MISCS_H_
+
+#ifdef WIN32
+#define inline __inline
+#define uint unsigned int 
+#define PING_STATUS_FILE_PATH	"temp\\RWL\\pingstatus.txt"
+ULONG exitcode ;
+extern int wfa_Winitime_diff(SYSTEMTIME *t1,SYSTEMTIME *t2);
+extern int ChangeGateWay(GateWay);
+extern int GetPingStat(FILE* pFile, const wchar_t* lpszSearchString , unsigned int *pos,unsigned int *sent, const char* delim) ;
+extern int GetStats(FILE* pFile, const wchar_t* lpszSearchString , unsigned int *pos, const char* delim) ;
+extern int FileSearch(FILE* pFile, const wchar_t* lpszSearchString, unsigned int *pos) ;
+extern unsigned int uGetLocalIP(void);
+extern char* GetHostName(char* buf, int len) ;
+extern char* GetDutIP(char* );
+extern DWORD PingStart( );
+extern char * strtok_r(char *s1, const char *s2, char **lasts);
+extern int strncasecmp(const char *s1, const char *s2, unsigned int length);
+extern int strcasecmp(const char *s1, const char *s2);
+extern FILE* asd_Config(char* , char*);
+extern HANDLE processHandle;
+extern HANDLE processThread;
+extern int wfa_Win_estimate_timer_latency();
+typedef unsigned long GateWay;   //new gateway
+#endif/*WIN32*/
+extern int wfaTGSetPrio(int sockfd, int tgClass);
+
+/* 802.1x Defines */
+#define KEY_FILE                "key.pem"
+#define TTLS_innerEAP           "mschapv2"
+#define AES_ENCPTYPE            "aes"
+#define AES_LEN                 0x4
+/* defines for EAP types */
+#define BCM_DEFAULT_SEC_MODE	0x0
+#define BCM_EAP_TYPE_TLS	0x1
+#define BCM_EAP_TYPE_TTLS	0x2
+#define BCM_EAP_TYPE_SIM	0x3
+#define BCM_EAP_TYPE_PEAP	0x4
+#define BCM_EAP_TYPE_FAST	0x5
+#define BCM_EAP_TYPE_AKA	0x6
+
+#define STD_ERR 2
+#define TEMP_FILE_PATH "tempr.txt"
+#define TEMP_STD_ERR_FILE "temp_err.dat"
+#define TEMP_STD_OUT_FILE "temp_out.dat"
+
+#if defined(WIN32)
+#define DUP _dup
+#define DUP2 _dup2
+#else
+#define DUP dup
+#define DUP2 dup2
+#endif 
+
+#ifndef WIN32
+#define S_N_PRINTF snprintf
+#else
+#define S_N_PRINTF _snprintf
+#endif
+extern int Start_Socket_Service();
+extern int Stop_Socket_Service();
+extern int isString(char *);
+extern int isNumber(char *);
+extern int isIpV4Addr(char *);
+extern inline double wfa_timeval2double(struct timeval *tval);
+extern inline void wfa_double2timeval(struct timeval *tval, double dval);
+extern inline double wfa_ftime_diff(struct timeval *t1, struct timeval *t2);
+extern int wfa_itime_diff(struct timeval *t1, struct timeval *t2);
+void p_error(char *errorString);
+/* OS abstraction APIs*/
+extern void asd_sleep(int sleepTime);
+extern void uapsd_sleep(int sleepTime);
+extern void asd_closeSocket(int Sockfd);
+extern void asd_shutDown(int Sockfd);
+extern void exec_process(char* command);
+extern int exec_wmmCmd(char* command);
+extern int asd_Config_wmm(char *strFunct, char *strstrParams);
+extern inline void int2BuffBigEndian(int val, char *buf);
+extern inline int bigEndianBuff2Int(char *buff);
+extern char* rwl_client_path;
+extern int rwl_wifi_flag;
+extern int gagtSockfd;
+extern void Cleanup_File(FILE *fp);
+extern unsigned short wfa_defined_debug;
+extern void GetWirelessAdapter(char *adapter_name);
+extern void get_rwl_exe_path(char *rwl_exe_path, int exe_path_len);
+extern FILE *asd_cmd_exec(char * trafficPath);
+extern int interface_validation(char *interfac);
+extern void file_cleanup(FILE *fp);
+extern FILE *asd_Config(char *strFunct, char *strstrParams);
+extern int exec_process_cnclient(char *buf, char *rwl_client_path, int rwl_wifi_flag);
+
+/*
+ * Following declarations are separated for LINUX and ANDROID
+ * The default path given for Linux are not taken in Android
+ */
+#ifndef WIN32
+#ifdef TARGETENV_android
+#define SH_PATH "/data/busybox/sh"
+#define PING_PATH "/data/busybox/ping"
+#define IFCONFIG_PATH "/data/busybox/ifconfig"
+#define ROUTE_PATH "/data/busybox/route"
+#define DHCLIENT_PATH "/data/busybox/dhclient"
+#define TMP_FILE_PATH "/data/local/temp.txt"
+#define RESOLV_FILE_PATH "/data/local/resolv.conf.bak"
+#define PINGOUT_FILE_PATH "/data/local/pingout.txt" 
+#define SPOUT_FILE_PATH "/data/local/spout.txt" 
+#else
+#define PING_PATH "/bin/ping"
+#define SH_PATH "/bin/sh"
+#define IFCONFIG_PATH "/sbin/ifconfig"
+#define ROUTE_PATH "/sbin/route"
+#define DHCLIENT_PATH "/sbin/dhclient"
+#define TMP_FILE_PATH "/tmp/temp.txt"
+#define RESOLV_FILE_PATH "/tmp/resolv.conf.bak"
+#define PINGOUT_FILE_PATH "/tmp/pingout.txt" 
+#define SPOUT_FILE_PATH "/tmp/spout.txt" 
+#endif
+#endif
+#endif/*_WFA_MISCS_H_*/
diff --git a/src/tools/Wifi_ASD_test/inc/wfa_rsp.h b/src/tools/Wifi_ASD_test/inc/wfa_rsp.h
new file mode 100644
index 0000000..1ccd8c2
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_rsp.h
@@ -0,0 +1,127 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+

+

+#ifndef WFA_RSP_H

+#define WFA_RSP_H

+

+#ifdef WFA_WMM_VOICE

+#define WFA_INFO_BUFSIZE       128   /* used to upload test data */

+#else

+#define WFA_INFO_BUFSIZE       128 

+#endif

+typedef struct _tg_ping_stop_resp

+{

+    int sendCnt;

+    int repliedCnt;

+} tgPingStopResp_t;

+

+typedef struct ca_sta_get_ipconfig_resp

+{

+    int isDhcp;

+    char ipaddr[WFA_IP_ADDR_STR_LEN];

+    char mask[WFA_IP_MASK_STR_LEN];

+    char dns[WFA_MAX_DNS_NUM][WFA_IP_ADDR_STR_LEN];

+} caStaGetIpConfigResp_t;

+

+typedef struct ca_sta_get_stats_resp

+{

+   int status;

+   int txFrames;

+   int rxFrames;

+   int txMulticast;

+   int rxMulticast;

+   int fcsErrors ;

+   int txRetries;

+} caStaGetStatsResp_t;

+

+typedef struct ca_device_get_info_resp

+{

+   char vendor[16];

+   char model[16];

+   char version[16];

+   char firmware[16];

+} caDeviceGetInfoResp_t;

+

+typedef struct ca_device_list_if_resp

+{

+   int status;

+#define IF_80211   1

+#define IF_ETH     2

+   int iftype;

+   char ifs[3][16];

+} caDeviceListIFResp_t;

+

+

+

+typedef struct dut_cmd_response

+{

+   int status;

+   int streamId;

+   union _cmdru

+   {

+       tgStats_t stats;

+       tgPingStopResp_t pingStp;

+       caStaGetIpConfigResp_t getIfconfig;

+       caStaGetStatsResp_t ifStats;

+       caDeviceGetInfoResp_t devInfo;

+       caDeviceListIFResp_t ifList;

+       char version[WFA_VERSION_LEN];

+       char info[WFA_INFO_BUFSIZE];

+       char bssid[WFA_MAC_ADDR_STR_LEN];

+       char mac[WFA_MAC_ADDR_STR_LEN];       

+       int connected;

+   } cmdru;

+}dutCmdResponse_t;

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_sock.h b/src/tools/Wifi_ASD_test/inc/wfa_sock.h
new file mode 100644
index 0000000..12a05a0
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_sock.h
@@ -0,0 +1,157 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+ 

+

+#ifndef _WFA_SOCK_H

+#define _WFA_SOCK_H

+

+

+#ifndef WIN32

+#include <stdio.h>      /* for printf() and fprintf() */

+#include <sys/socket.h> /* for socket(), bind(), and connect() */

+#include <arpa/inet.h>  /* for sockaddr_in and inet_ntoa() */

+#include <stdlib.h>     /* for atoi() and exit() */

+#include <string.h>     /* for memset() */

+#include <unistd.h>     /* for close() */

+#include <sys/time.h>       /* for struct timeval {} */

+#include <fcntl.h>          /* for fcntl() */

+#include <errno.h>

+#include <typedefs.h>   /* for android compilation */

+#else

+#include <winsock2.h>

+#include <ws2tcpip.h>

+#include <stdio.h>      /* for printf() and fprintf() */

+#include <stdlib.h>     /* for atoi() and exit() */

+#include <string.h>     /* for memset() */

+

+typedef int socklen_t;

+#ifndef MSG_DONTWAIT

+#define MSG_DONTWAIT 0

+#endif

+#endif

+#include <wlioctl.h>

+#define MAX_UDP_LEN     2048

+

+#ifdef WIN32 

+typedef SOCKET sockfd_t;

+#else

+typedef int sockfd_t;

+#endif 

+struct sockfds

+{

+   sockfd_t *agtfd;      /* dut agent main socket fd */

+   sockfd_t *cafd;       /* sock fd to control agent */

+   sockfd_t *tgfd;       /* traffic agent fd         */

+   sockfd_t *tgRevfd;	/*traffic Recv Fd */

+   sockfd_t *wmmfds;     /* wmm stream ids           */

+   sockfd_t *psfd;       /* wmm-ps socket id         */

+};

+

+#ifdef WIN32 

+

+#ifndef IFNAMSIZ

+#define IFNAMSIZ	16

+#endif

+

+

+struct ifmap {

+          unsigned int mem_start;

+          unsigned int mem_end;

+          unsigned short base_addr;

+          unsigned char irq;

+          unsigned char dma;

+          unsigned char port;

+  };

+

+struct ifreq {

+    char    ifr_name[IFNAMSIZ];/* Interface name */

+    union {

+            SOCKADDR_IN ifr_addr;

+            SOCKADDR_IN ifr_dstaddr;

+            SOCKADDR_IN ifr_broadaddr;

+            SOCKADDR_IN ifr_netmask;

+            SOCKADDR_IN ifr_hwaddr;

+            short   ifr_flags;

+            int     ifr_ifindex;

+            int     ifr_metric;

+            int     ifr_mtu;

+            struct ifmap ifr_map;

+            char    ifr_slave[IFNAMSIZ];

+            char    ifr_newname[IFNAMSIZ];

+            char *  ifr_data;

+    };

+};

+

+

+

+#endif

+

+

+extern int wfaCreateTCPServSock(unsigned short sport);

+extern int wfaCreateUDPSock(char *sipaddr, unsigned short sport);

+extern int wfaAcceptTCPConn(int servSock);

+extern int wfaConnectUDPPeer(int sock, char *dipaddr, unsigned short dport);

+extern int wfaConnectTCPPeer(unsigned short sport, char *dipaddr, unsigned short dport);

+extern void wfaSetSockFiDesc(fd_set *sockset, int *, struct sockfds *);

+extern int wfaCtrlSend(int sock, unsigned char *buf, int bufLen);

+extern int wfaCtrlRecv(int sock, unsigned char *buf);

+extern int wfaTrafficSendTo(int sock, char *buf, int bufLen, struct sockaddr *to);

+extern int wfaTrafficRecv(int sock, char *buf, struct sockaddr *from);

+extern int wfaGetifAddr(char *ifname, struct sockaddr_in *sa);

+extern struct timeval *wfaSetTimer(int, int, struct timeval *);

+extern int wfaSetSockMcastRecvOpt(int, char*);

+extern int wfaSetSockMcastSendOpt(int);

+extern int wfaSetProcPriority(int);

+

+

+#endif /* _WFA_SOCK_H */

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_tg.h b/src/tools/Wifi_ASD_test/inc/wfa_tg.h
new file mode 100644
index 0000000..045bd21
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_tg.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN 
+ *.AN 
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN 
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN 
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+ 
+ /*
+ * wfa_tg.h:
+ *   Definitions used in Traffic Generator Modules
+ */
+#ifndef _WFA_TG_H
+#define _WFA_TG_H
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <pthread.h>
+#include <bcmendian.h>
+#else
+#include <windows.h>
+#ifdef WFA_WMM_EXT
+#ifndef WIN32
+#include "sched.h"
+#include "semaphore.h"
+#endif /* !WIN32 */
+#endif /* WFA_WMM_EXT */
+
+#define usleep(x)	Sleep(x)
+#define sleep(x)	Sleep(x)
+#endif /* !WIN32 */
+
+/* maximum number of streams to support */
+//#define WFA_MAX_WMM_STREAMS            4 
+#define IPV4_ADDRESS_STRING_LEN    16
+
+#define  MAX_PROFILE_NUM        6
+#define  MINISECONDS            1000
+#define  MICROSECONDS           1000000
+#define  NANOSECONDS            1000000000
+#define  LINUX_TIMER_RES        20000000      /* 20 MINSECONDS */
+#define  CA_RESPONSE_BUF_SIZE   128
+
+/* Profile Key words */
+#define KW_PROFILE                 1 
+#define KW_DIRECTION               2
+#define KW_DIPADDR                 3
+#define KW_DPORT                   4
+#define KW_SIPADDR                 5
+#define KW_SPORT                   6
+#define KW_FRATE                   7
+#define KW_DURATION                8
+#define KW_PLOAD                   9
+#define KW_TCLASS                  10
+#define KW_STREAMID                11
+#define KW_COMPLETE                12
+#define KW_ERROR                   13
+#define KW_STARTDELAY              14
+#define KW_NUMFRAME                15
+#define KW_USESYNCCLOCK            16
+#define KW_USERPRIORITY            17
+
+/* Profile Types */
+#define PROF_FILE_TX               1
+#define PROF_MCAST                 2
+#define PROF_IPTV                  3
+#define PROF_TRANSC                4
+#define PROF_START_SYNC            5      /* this will be outdated */
+#define PROF_CALI_RTD              6
+#define PROF_UAPSD                 7
+#define PROF_FILE_TX_TCP           8
+#define PROF_TRANSC_TCP            9
+#define PROF_LAST                  10
+
+/* Traffic Classes */
+//#define TRAFFIC_CLASS_VO           1
+//#define TRAFFIC_CLASS_VI           2
+//#define TRAFFIC_CLASS_BK           3 
+//#define TRAFFIC_CLASS_BE           4
+
+
+/* Traffic Directions */
+#define DIRECT_SEND                1 
+#define DIRECT_RECV                2 
+
+#define TG_PROTO_TCP               0 
+#define TG_PROTO_UDP               1
+
+#define TG_WMM_AC_UP0         12     /* User Priority 0 */
+#define TG_WMM_AC_UP1         13     /*               1 */
+#define TG_WMM_AC_UP2         14     /*               2 */
+#define TG_WMM_AC_UP3         15     /*               3 */
+#define TG_WMM_AC_UP4         16     /*               4 */
+#define TG_WMM_AC_UP5         17     /*               5 */
+#define TG_WMM_AC_UP6         18     /*               6 */
+#define TG_WMM_AC_UP7         19     /*               7 */
+#define TG_WMM_AC_BE          1      /* Best Effort */
+#define TG_WMM_AC_BK          2      /* Background  */
+#define TG_WMM_AC_VI          3      /* Video       */
+#define TG_WMM_AC_VO          4      /* Voice       */
+#define TG_WMM_AC_UAPSD       5      /* UAPSD        */
+
+/* wmm defs */
+#define TOS_VO7     0xE0         // 111 0  0000 (7)  AC_VO tos/dscp values
+#define TOS_VO      0xD0         // 110 0  0000 (6)  AC_VO tos/dscp values
+//Atheros Madwifi use 0x88 for UPSD/Voice
+//#define TOS_VO      0x88       // 110 0  0000 (6)  AC_VO tos/dscp values
+
+#define TOS_VI      0xA0         // 101 0  0000 (5)  AC_VI
+#define TOS_VI4     0x80         // 100 0  0000 (4)  AC_VI
+
+#define TOS_BE      0x00         // 000 0  0000 (0)  AC_BE
+#define TOS_EE      0x60         // 011 0  0000 (3)  AC_BE
+
+#define TOS_BK      0x20         // 001 0  0000 (1)  AC_BK
+#define TOS_LE      0x40         // 010 0  0000 (2)  AC_BK
+
+#define AC_CLASS_MAX_THREAD        5
+
+#define WFA_UDP_ECHO_STREAM_ID    0xFFFF
+#define WFA_UDP_ECHO_PORT         07
+
+#define WFA_PING_ICMP_ECHO         0
+#define WFA_PING_UDP_ECHO          1
+
+typedef struct _tg_profile
+{
+    int  profile;                           /* profile id                    */
+    int  direction;
+    char dipaddr[IPV4_ADDRESS_STRING_LEN];  /* destination/remote ip address */
+    unsigned short  dport;
+    char sipaddr[IPV4_ADDRESS_STRING_LEN];  /* source/local ip address       */
+    unsigned short  sport;
+    int  rate;
+    int  duration;
+    int  pksize;
+    short trafficClass;      /* VO, VI, BK, BE */
+    int  startdelay;
+} tgProfile_t;
+
+typedef struct _tg_stats
+{
+    int txFrames;
+    int rxFrames;
+    int txPayloadBytes;
+    int rxPayloadBytes;
+    int outOfSequenceFrames; 
+    int lostPkts;                 /* voice over wi-fi */
+    unsigned long jitter;         /* voice over wi-fi */
+} tgStats_t;
+
+typedef struct _tg_stream
+{
+    int id;
+    int sockfd;
+    int tblidx;
+    int lastPktSN;        /* use for Jitter calculation */
+    int rxTimeLast;       /* use for pkLost             */
+    int fmInterval;       
+    int state;            /* indicate if the stream being active */
+    tgProfile_t profile;
+    tgStats_t stats;
+} tgStream_t;
+
+typedef struct _traffic_header
+{
+   char hdr[20];   /* always wfa */
+} tgHeader_t;
+
+#ifdef WFA_WMM_EXT
+typedef struct _tg_wmm
+{
+    int thr_flag;    /* this is used to indicate stream id */
+    int stop_flag;    /* this is used to indicate stream id */
+#ifndef WIN32
+	int thr_id;
+	pthread_t thr;
+    pthread_cond_t thr_flag_cond;
+    pthread_cond_t thr_stop_cond;
+    pthread_mutex_t thr_flag_mutex;
+    pthread_mutex_t thr_stop_mutex;
+#else
+	HANDLE thr_id;
+#endif /*!WIN32 */
+}tgWMM_t;
+
+typedef int (*StationStateFunctionPtr)( char, int,int *); //PS,sleep period,state
+
+typedef struct station_state_table
+{
+StationStateFunctionPtr statefunc;
+char                    pw_offon;
+int                     sleep_period;
+} StationProcStatetbl_t;
+
+typedef int (*stationRecvStateFunctionPtr)(unsigned int *, int,int * ); //Recieved message buffer, length,state
+
+typedef struct console_rcv_state_table
+{
+stationRecvStateFunctionPtr statefunc;
+} StationRecvProcStatetbl_t;
+#endif /* WFA_WMM_EXT */
+
+typedef struct _tg_thr_data
+{
+   int tid;
+#ifdef WFA_WMM_PS_EXT
+   /* In case of XP CA the library does not get compiled with WFA_WMM_PS_EXT 
+    * Hence StationProcStatetbl_t definition will not be known to XP.
+    */
+   StationProcStatetbl_t  *state;
+#endif  /* WFA_WMM_PS_EXT */
+   int state_num;   
+} tgThrData_t;
+
+typedef struct _tg_sync_time
+{
+   double dut_time;
+   double tm_time;
+   double dtime;
+}tgSyncTime_t;
+
+typedef struct _e2e_stats
+{
+   int seqnum;
+   int lsec;
+   int lusec;
+   int rsec;
+   int rusec;
+} tgE2EStats_t;
+
+extern int wfaTGConfig(int len, BYTE *buf, int *respLen, BYTE *respBuf);
+extern int wfaSendLongFile(int fromSockfd, int streamId, BYTE *respBuf, int *respLen);
+
+extern int wfaImprovePerfSendLongFile(int fromSockfd, int streamId, BYTE *respBuf, int *respLen);
+
+extern int wfaRecvFile(int mySockfi, int profId, char *buf);
+extern int wfaTGRecvStart(int len, BYTE *parms, int *respLen, BYTE *respBuf);
+extern int wfaTGRecvStop(int len, BYTE *parms, int *respLen, BYTE *respBuf);
+extern int wfaTGSendStart(int len, BYTE *parms, int *respLen, BYTE *respBuf);
+extern int wfaTGReset(int len, BYTE *parms, int *respLen, BYTE *respBuf);
+extern int wfaSendShortFile(int fromSockfd, int profId, BYTE *buf, int size, BYTE *respBuf, int *respLen);
+extern int wfaFlushSockQueue(int profId);
+extern int wfaTGSendPing(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);
+extern int wfaTGStopPing(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf);
+
+#endif /* _WFA_TG_H */
diff --git a/src/tools/Wifi_ASD_test/inc/wfa_tlv.h b/src/tools/Wifi_ASD_test/inc/wfa_tlv.h
new file mode 100644
index 0000000..055563e
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_tlv.h
@@ -0,0 +1,311 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+ 

+

+/*

+ * File: wfa_tlv.h

+ *  definitions for each of command types. 

+ *  format:

+ *  ---------------------------------------------------

+ *  |  tag   | length |   value   

+ *  --------------------------------------------------- 

+ *   2 bytes   2bytes    defined by length 

+ */

+#ifndef _WFA_TLV_H

+#define _WFA_TLV_H

+

+#include "wfa_types.h"

+

+#define INTEGER_1 0x0001            /* byte */

+#define INTEGER_2 0x0002            /* word */

+#define OCTET_STRING 0x0003         /* string */

+

+typedef struct _wfatlvHdr 

+{

+    WORD tag;   /* tag/type */

+    WORD len;   /* value length */

+} wfaTLV;

+

+#define WFA_TLV_HDR_LEN sizeof(wfaTLV)

+#ifndef WIN32

+/* Commands */

+#define WFA_GET_VERSION_TLV                                         0x01

+

+/* Generic TRAFFIC GENERATOR Commands */

+#define WFA_TRAFFIC_SEND_PING_TLV     (WFA_GET_VERSION_TLV + 0x01) 

+#define WFA_TRAFFIC_STOP_PING_TLV     (WFA_TRAFFIC_SEND_PING_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_CONFIG_TLV  (WFA_TRAFFIC_STOP_PING_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_SEND_TLV    (WFA_TRAFFIC_AGENT_CONFIG_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_RECV_START_TLV (WFA_TRAFFIC_AGENT_SEND_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_RECV_STOP_TLV (WFA_TRAFFIC_AGENT_RECV_START_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_RESET_TLV (WFA_TRAFFIC_AGENT_RECV_STOP_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_STATUS_TLV (WFA_TRAFFIC_AGENT_RESET_TLV + 0x01) /* 9 */

+

+/* STATION/DUT Commands */

+#define WFA_STA_GET_IP_CONFIG_TLV    (WFA_TRAFFIC_AGENT_STATUS_TLV + 0x01)

+#define WFA_STA_SET_IP_CONFIG_TLV    (WFA_STA_GET_IP_CONFIG_TLV + 0x01)

+#define WFA_STA_GET_MAC_ADDRESS_TLV  (WFA_STA_SET_IP_CONFIG_TLV + 0x01)

+#define WFA_STA_SET_MAC_ADDRESS_TLV  (WFA_STA_GET_MAC_ADDRESS_TLV + 0x01) 

+#define WFA_STA_IS_CONNECTED_TLV     (WFA_STA_SET_MAC_ADDRESS_TLV + 0x01) 

+#define WFA_STA_VERIFY_IP_CONNECTION_TLV  (WFA_STA_IS_CONNECTED_TLV + 0x01)

+#define WFA_STA_GET_BSSID_TLV        (WFA_STA_VERIFY_IP_CONNECTION_TLV + 0x01)

+#define WFA_STA_GET_STATS_TLV        (WFA_STA_GET_BSSID_TLV + 0x01)  /* 17 */ 

+#define WFA_STA_SET_ENCRYPTION_TLV   (WFA_STA_GET_STATS_TLV + 0x01)

+#define WFA_STA_SET_PSK_TLV          (WFA_STA_SET_ENCRYPTION_TLV + 0x01)

+#define WFA_STA_SET_EAPTLS_TLV       (WFA_STA_SET_PSK_TLV + 0x01)

+#define WFA_STA_SET_UAPSD_TLV        (WFA_STA_SET_EAPTLS_TLV + 0x01)

+#define WFA_STA_ASSOCIATE_TLV        (WFA_STA_SET_UAPSD_TLV + 0x01)

+#define WFA_STA_SET_EAPTTLS_TLV      (WFA_STA_ASSOCIATE_TLV + 0x01)

+#define WFA_STA_SET_EAPSIM_TLV       (WFA_STA_SET_EAPTTLS_TLV + 0x01)

+#define WFA_STA_SET_PEAP_TLV         (WFA_STA_SET_EAPSIM_TLV + 0x01)

+#define WFA_STA_SET_IBSS_TLV         (WFA_STA_SET_PEAP_TLV + 0x01)

+#define WFA_STA_GET_INFO_TLV         (WFA_STA_SET_IBSS_TLV + 0x01)

+#define WFA_DEVICE_GET_INFO_TLV      (WFA_STA_GET_INFO_TLV + 0x01)  

+#define WFA_DEVICE_LIST_IF_TLV       (WFA_DEVICE_GET_INFO_TLV + 0x01)  /* 29 */

+

+#define WFA_STA_DEBUG_SET_TLV        (WFA_DEVICE_LIST_IF_TLV + 0x01)  /* 30 */

+#define WFA_STA_SET_MODE_TLV         (WFA_STA_DEBUG_SET_TLV + 0x01) /* 31 */

+#define WFA_STA_SET_WMM_TLV          (WFA_STA_SET_MODE_TLV + 0x01) /* 32 */

+#define WFA_STA_SEND_NEIGREQ_TLV	 (WFA_STA_SET_WMM_TLV + 0x01) /* 33 */

+#define WFA_STA_SET_SYSTIME_TLV		 (WFA_STA_SEND_NEIGREQ_TLV + 0x01)

+#define WFA_STA_SET_11N_TLV			 (WFA_STA_SET_SYSTIME_TLV + 0x01)

+#define WFA_STA_SET_RIFS_TEST_TLV	 (WFA_STA_SET_11N_TLV + 0x01)

+#define WFA_STA_SET_WIRELESS_TLV	 (WFA_STA_SET_RIFS_TEST_TLV + 0x01)

+#define WFA_STA_SEND_ADDBA_TLV		 (WFA_STA_SET_WIRELESS_TLV + 0x01)

+#define WFA_STA_SEND_COEXIST_MGMT_TLV	 (WFA_STA_SEND_ADDBA_TLV + 0x01)

+#define WFA_STA_DISCONNECT_TLV	 (WFA_STA_SEND_COEXIST_MGMT_TLV + 0x01)

+#define WFA_STA_SET_EAPFAST_TLV	 (WFA_STA_DISCONNECT_TLV + 0x01)

+#define WFA_STA_SET_EAPAKA_TLV	 (WFA_STA_SET_EAPFAST_TLV + 0x01)

+#define WFA_STA_REASSOCIATE_TLV          (WFA_STA_SET_EAPAKA_TLV + 0x01)    /* 43 */

+#define WFA_STA_SET_PWRSAVE_TLV          (WFA_STA_REASSOCIATE_TLV + 0x01)   /* 44 */

+#define WFA_STA_RESET_DEFAULT_TLV        (WFA_STA_SET_PWRSAVE_TLV + 0x01)   /* 45 */

+#define WFA_STA_COMMANDS_END             (WFA_STA_RESET_DEFAULT_TLV + 0x01) /* 46 */

+

+

+/* Version response */

+#define WFA_GET_VERSION_RESP_TLV  (WFA_STA_COMMANDS_END +       0x01) /* 47 */

+

+/* Generic Traffic Generator Responses */

+#define WFA_TRAFFIC_SEND_PING_RESP_TLV (WFA_GET_VERSION_RESP_TLV +  0x01) 

+#define WFA_TRAFFIC_STOP_PING_RESP_TLV (WFA_TRAFFIC_SEND_PING_RESP_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_CONFIG_RESP_TLV (WFA_TRAFFIC_STOP_PING_RESP_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_SEND_RESP_TLV (WFA_TRAFFIC_AGENT_CONFIG_RESP_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV (WFA_TRAFFIC_AGENT_SEND_RESP_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV (WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_RESET_RESP_TLV (WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV + 0x01)

+#define WFA_TRAFFIC_AGENT_STATUS_RESP_TLV (WFA_TRAFFIC_AGENT_RESET_RESP_TLV + 0x01)

+

+/* STATION/DUT Responses */

+#define WFA_STA_GET_IP_CONFIG_RESP_TLV (WFA_TRAFFIC_AGENT_STATUS_RESP_TLV + 0x01)  

+#define WFA_STA_SET_IP_CONFIG_RESP_TLV (WFA_STA_GET_IP_CONFIG_RESP_TLV + 0x01)

+#define WFA_STA_GET_MAC_ADDRESS_RESP_TLV (WFA_STA_SET_IP_CONFIG_RESP_TLV + 0x01)

+#define WFA_STA_SET_MAC_ADDRESS_RESP_TLV (WFA_STA_GET_MAC_ADDRESS_RESP_TLV + 0x01) /* 59 */ 

+#define WFA_STA_IS_CONNECTED_RESP_TLV (WFA_STA_SET_MAC_ADDRESS_RESP_TLV + 0x01) 

+#define WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV  (WFA_STA_IS_CONNECTED_RESP_TLV + 0x01) /* 61 */

+#define WFA_STA_GET_BSSID_RESP_TLV (WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV + 0x01)  /* 62 */

+#define WFA_STA_GET_STATS_RESP_TLV (WFA_STA_GET_BSSID_RESP_TLV + 0x01) 

+#define WFA_STA_SET_ENCRYPTION_RESP_TLV (WFA_STA_GET_STATS_RESP_TLV + 0x01)

+#define WFA_STA_SET_PSK_RESP_TLV (WFA_STA_SET_ENCRYPTION_RESP_TLV + 0x01)

+#define WFA_STA_SET_EAPTLS_RESP_TLV (WFA_STA_SET_PSK_RESP_TLV + 0x01)

+#define WFA_STA_SET_UAPSD_RESP_TLV (WFA_STA_SET_EAPTLS_RESP_TLV + 0x01)

+#define WFA_STA_ASSOCIATE_RESP_TLV (WFA_STA_SET_UAPSD_RESP_TLV + 0x01)

+#define WFA_STA_SET_EAPTTLS_RESP_TLV   (WFA_STA_ASSOCIATE_RESP_TLV + 0x01)

+#define WFA_STA_SET_EAPSIM_RESP_TLV   (WFA_STA_SET_EAPTTLS_RESP_TLV + 0x01)

+#define WFA_STA_SET_PEAP_RESP_TLV      (WFA_STA_SET_EAPSIM_RESP_TLV + 0x01)

+#define WFA_STA_SET_IBSS_RESP_TLV         (WFA_STA_SET_PEAP_RESP_TLV + 0x01)

+#define WFA_STA_GET_INFO_RESP_TLV      (WFA_STA_SET_IBSS_RESP_TLV + 0x01)

+#define WFA_DEVICE_GET_INFO_RESP_TLV  (WFA_STA_GET_INFO_RESP_TLV + 0x01)

+#define WFA_DEVICE_LIST_IF_RESP_TLV (WFA_DEVICE_GET_INFO_RESP_TLV + 0x01) 

+

+#define WFA_STA_DEBUG_SET_RESP_TLV  (WFA_DEVICE_LIST_IF_RESP_TLV + 0x01)

+#define WFA_STA_SET_MODE_RESP_TLV   (WFA_STA_DEBUG_SET_RESP_TLV + 0x01) /* 77 */

+#define WFA_STA_SET_WMM_RESP_TLV   (WFA_STA_SET_MODE_RESP_TLV + 0x01)   /* 78 */

+#define WFA_STA_SEND_NEIGREQ_RESP_TLV (WFA_STA_SET_WMM_RESP_TLV + 0x01) /* neighbor request */

+#define WFA_STA_SET_SYSTIME_RESP_TLV		 (WFA_STA_SEND_NEIGREQ_RESP_TLV + 0x01)

+#define WFA_STA_SET_11N_RESP_TLV			 (WFA_STA_SET_SYSTIME_RESP_TLV + 0x01)

+#define WFA_STA_SET_RIFS_TEST_RESP_TLV	 (WFA_STA_SET_11N_RESP_TLV + 0x01)

+#define WFA_STA_SET_WIRELESS_RESP_TLV	 (WFA_STA_SET_RIFS_TEST_RESP_TLV + 0x01)

+#define WFA_STA_SEND_ADDBA_RESP_TLV		 (WFA_STA_SET_WIRELESS_RESP_TLV + 0x01)

+#define WFA_STA_SEND_COEXIST_MGMT_RESP_TLV	 (WFA_STA_SEND_ADDBA_RESP_TLV + 0x01)

+#define WFA_STA_DISCONNECT_RESP_TLV	 (WFA_STA_SEND_COEXIST_MGMT_RESP_TLV + 0x01)

+#define WFA_STA_SET_EAPFAST_RESP_TLV	 (WFA_STA_DISCONNECT_RESP_TLV + 0x01)

+#define WFA_STA_SET_EAPAKA_RESP_TLV	 (WFA_STA_SET_EAPFAST_RESP_TLV + 0x01)

+#define WFA_STA_REASSOCIATE_RESP_TLV      (WFA_STA_SET_EAPAKA_RESP_TLV + 0x01)         /* 72 */

+#define WFA_STA_SET_PWRSAVE_RESP_TLV      (WFA_STA_REASSOCIATE_RESP_TLV + 0x01)        /* 73 */

+#define WFA_STA_RESET_DEFAULT_RESP_TLV    (WFA_STA_SET_PWRSAVE_RESP_TLV + 0x01)

+#define WFA_STA_RESPONSE_END              (WFA_STA_RESET_DEFAULT_RESP_TLV + 0x01)

+

+#else

+//Hardcode these value MindTree to avoid compilation issues

+#define WFA_GET_VERSION_TLV                                         0x01

+

+#define WFA_TRAFFIC_SEND_PING_TLV    0x02 

+#define WFA_TRAFFIC_STOP_PING_TLV     0x03

+#define WFA_TRAFFIC_AGENT_CONFIG_TLV  0x04

+#define WFA_TRAFFIC_AGENT_SEND_TLV    0x05

+#define WFA_TRAFFIC_AGENT_RECV_START_TLV 0x06

+#define WFA_TRAFFIC_AGENT_RECV_STOP_TLV 0x07

+#define WFA_TRAFFIC_AGENT_RESET_TLV 0x08

+#define WFA_TRAFFIC_AGENT_STATUS_TLV 0x09 /* 9 */

+

+/* STATION/DUT Commands */

+#define WFA_STA_GET_IP_CONFIG_TLV    0x0a

+#define WFA_STA_SET_IP_CONFIG_TLV    0x0b

+#define WFA_STA_GET_MAC_ADDRESS_TLV  0x0c

+#define WFA_STA_SET_MAC_ADDRESS_TLV  0x0d

+#define WFA_STA_IS_CONNECTED_TLV     0x0e 

+#define WFA_STA_VERIFY_IP_CONNECTION_TLV  0x0f

+#define WFA_STA_GET_BSSID_TLV        0x10

+#define WFA_STA_GET_STATS_TLV        0x11  /* 17 */ 

+#define WFA_STA_SET_ENCRYPTION_TLV   0x12

+#define WFA_STA_SET_PSK_TLV          0x13

+#define WFA_STA_SET_EAPTLS_TLV       0x14

+#define WFA_STA_SET_UAPSD_TLV        0x15

+#define WFA_STA_ASSOCIATE_TLV        0x16

+#define WFA_STA_SET_EAPTTLS_TLV      0x17

+#define WFA_STA_SET_EAPSIM_TLV       0x18

+#define WFA_STA_SET_PEAP_TLV         0x19

+#define WFA_STA_SET_IBSS_TLV         0x1a

+#define WFA_STA_GET_INFO_TLV         0x1b

+#define WFA_DEVICE_GET_INFO_TLV      0x1c 

+#define WFA_DEVICE_LIST_IF_TLV       0x1d  /* 29 */

+

+#define WFA_STA_DEBUG_SET_TLV        0x1e  /* 30 */

+#define WFA_STA_SET_MODE_TLV         0x1f  /* 31 */

+#define WFA_STA_SET_WMM_TLV          0x20  /* 32 */

+#define WFA_STA_SEND_NEIGREQ_TLV     0x21  /* 33 */

+#define WFA_STA_SET_SYSTIME_TLV		 0x22

+#define WFA_STA_SET_11N_TLV			 0x23

+#define WFA_STA_SET_RIFS_TEST_TLV	 0x24

+#define WFA_STA_SET_WIRELESS_TLV	 0x25

+#define WFA_STA_SEND_ADDBA_TLV		 0x26

+#define WFA_STA_SEND_COEXIST_MGMT_TLV	 0x27

+#define WFA_STA_DISCONNECT_TLV	 0x28

+#define WFA_STA_SET_EAPFAST_TLV	 0x29

+#define WFA_STA_SET_EAPAKA_TLV	 0x2a

+#define WFA_STA_REASSOCIATE_TLV      0x2b

+#define WFA_STA_SET_PWRSAVE_TLV      0x2c

+#define WFA_STA_RESET_DEFAULT_TLV    0x2d

+#define WFA_STA_COMMANDS_END         0x2e  /* 46 */

+

+

+/* Version response */

+#define WFA_GET_VERSION_RESP_TLV     0x2f  /* 47 */

+

+/* Generic Traffic Generator Responses */

+#define WFA_TRAFFIC_SEND_PING_RESP_TLV 0x30

+#define WFA_TRAFFIC_STOP_PING_RESP_TLV 0x31

+#define WFA_TRAFFIC_AGENT_CONFIG_RESP_TLV 0x32

+#define WFA_TRAFFIC_AGENT_SEND_RESP_TLV 0x33

+#define WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV 0x34

+#define WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV 0x35

+#define WFA_TRAFFIC_AGENT_RESET_RESP_TLV 0x36

+#define WFA_TRAFFIC_AGENT_STATUS_RESP_TLV 0x37

+

+/* STATION/DUT Responses */

+#define WFA_STA_GET_IP_CONFIG_RESP_TLV 0x38

+#define WFA_STA_SET_IP_CONFIG_RESP_TLV 0x39

+#define WFA_STA_GET_MAC_ADDRESS_RESP_TLV 0x3a

+#define WFA_STA_SET_MAC_ADDRESS_RESP_TLV 0x3b /* 59 */ 

+#define WFA_STA_IS_CONNECTED_RESP_TLV 0x3c

+#define WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV  0x40 /* 61 */

+#define WFA_STA_GET_BSSID_RESP_TLV 0x3e /* 62 */

+#define WFA_STA_GET_STATS_RESP_TLV 0x3f

+#define WFA_STA_SET_ENCRYPTION_RESP_TLV 0x40

+#define WFA_STA_SET_PSK_RESP_TLV 0x41

+#define WFA_STA_SET_EAPTLS_RESP_TLV 0x42

+#define WFA_STA_SET_UAPSD_RESP_TLV 0x43

+#define WFA_STA_ASSOCIATE_RESP_TLV 0x44

+#define WFA_STA_SET_EAPTTLS_RESP_TLV   0x45

+#define WFA_STA_SET_EAPSIM_RESP_TLV    0x46

+#define WFA_STA_SET_PEAP_RESP_TLV      0x47

+#define WFA_STA_SET_IBSS_RESP_TLV      0x48

+#define WFA_STA_GET_INFO_RESP_TLV      0x49

+#define WFA_DEVICE_GET_INFO_RESP_TLV   0x4a

+#define WFA_DEVICE_LIST_IF_RESP_TLV 0x4b

+

+#define WFA_STA_DEBUG_SET_RESP_TLV       0x4c

+#define WFA_STA_SET_MODE_RESP_TLV        0x4d /* 77 */

+#define WFA_STA_SET_WMM_RESP_TLV         0x4e /* 78 */

+#define WFA_STA_SEND_NEIGREQ_RESP_TLV    0x4f

+#define WFA_STA_SET_SYSTIME_RESP_TLV     0x50

+#define WFA_STA_SET_11N_RESP_TLV         0x51

+#define WFA_STA_SET_RIFS_TEST_RESP_TLV   0x52

+#define WFA_STA_SET_WIRELESS_RESP_TLV    0x53

+#define WFA_STA_SEND_ADDBA_RESP_TLV      0x54

+#define WFA_STA_SEND_COEXIST_MGMT_RESP_TLV 0x55

+#define WFA_STA_DISCONNECT_RESP_TLV      0x56

+#define WFA_STA_SET_EAPFAST_RESP_TLV     0x57

+#define WFA_STA_SET_EAPAKA_RESP_TLV      0x58

+#define WFA_STA_REASSOCIATE_RESP_TLV     0x59

+#define WFA_STA_SET_PWRSAVE_RESP_TLV     0x5a

+#define WFA_STA_RESET_DEFAULT_RESP_TLV   0x5b

+#define WFA_STA_RESPONSE_END             0x5c

+#define WFA_TLV_END WFA_STA_RESPONSE_END 

+#endif //MindTree

+

+#define WFA_TLV_HEAD_LEN 1+2

+

+extern WORD wfaGetTag(BYTE *tlv_data);

+extern void wfaSetTag(BYTE *tlv_data, BYTE new_tag);

+extern WORD wfaGetTLVLen(BYTE *tlv_data);

+extern WORD wfaGetValueLen(BYTE *tlv_data);

+extern BOOL wfaGetValue(BYTE *pstr, int value_len, BYTE *tlv_data);

+extern BOOL wfaIsValidTag(BYTE the_tag);

+extern void wfaAliasByTag(BYTE the_tag, char *aliasStr);

+extern BOOL wfaDecodeTLV(BYTE *tlv_data, int tlv_len, BYTE *ptlv_tag, int *ptlv_val_len, BYTE *ptlv_value);

+extern BOOL wfaEncodeTLV(WORD the_tag, WORD the_len, BYTE *the_value, BYTE *tlv_data);

+

+extern WORD wfaGetValueType(BYTE the_tag, BYTE *tlv_data);

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_types.h b/src/tools/Wifi_ASD_test/inc/wfa_types.h
new file mode 100644
index 0000000..00217fa
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_types.h
@@ -0,0 +1,111 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+ /* Revision History:

+  *             11/07/07 02.30 Voice HSO -- qhu

+  *                  -- change FALSE to -1 -- a bug reported by rmaeder

+  *                     socket may be a 0

+  */

+

+/*

+ * wfa_types.h:

+ *   Defines general types and enum 

+ */

+#ifndef _WFA_TYPES_H

+#define _WFA_TYPES_H 

+

+#define WFA_IF_NAME_LEN 16

+#define WFA_VERSION_LEN 16

+#define WFA_SSID_NAME_LEN 64

+#define WFA_IP_ADDR_STR_LEN  16

+#define WFA_IP_MASK_STR_LEN  16

+#define WFA_MAX_DNS_NUM      2

+#define WFA_MAC_ADDR_STR_LEN 20

+#define WFA_DEFAULT_PROG_NAME 16

+

+#define IF_80211   1

+#define IF_ETH     2

+/* only if test bed */

+#ifdef WFA_STA_TB

+#define INTOLERANT_LEN	5

+#define CHNL_LIST	20

+#define WIRELESS_BAND	10

+#endif

+

+/* WMM-AC APSD defines*/

+#ifdef WFA_WMM_AC

+#define DIR_NONE  0

+#define DIR_UP    1

+#define DIR_DOWN  2

+#define DIR_BIDIR 3

+#endif

+

+typedef unsigned short WORD;

+typedef unsigned char BYTE;

+

+enum _response_staus

+{

+       STATUS_RUNNING = 0x0001,

+       STATUS_INVALID = 0x0002,

+       STATUS_ERROR = 0x0003,

+       STATUS_COMPLETE = 0x0004,

+};

+

+typedef int BOOL;

+

+#ifndef    TRUE

+    #define    FALSE       -1

+    #define    TRUE        0

+    #define    DONE        1

+#endif

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_ver.h b/src/tools/Wifi_ASD_test/inc/wfa_ver.h
new file mode 100644
index 0000000..403bc1f
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_ver.h
@@ -0,0 +1,64 @@
+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+ 

+

+#ifndef WFA_VER_H

+#define WFA_VER_H

+

+/* 

+ * Voice Personel support E2E 

+ * 11N support

+ */

+#define WFA_SYSTEM_VER      "03.00"        

+

+#endif

diff --git a/src/tools/Wifi_ASD_test/inc/wfa_wmmps.h b/src/tools/Wifi_ASD_test/inc/wfa_wmmps.h
new file mode 100644
index 0000000..628dee8
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/inc/wfa_wmmps.h
@@ -0,0 +1,244 @@
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN 
+ *.AN 
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN 
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN 
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+
+/*
+ * * APTS messages/tests
+ * */
+#ifndef _WFA_WMMPS_H_
+#define _WFA_WMMPS_H_
+#define B_D		1
+#define	B_H	        2	
+#define B_B             3
+#define B_M             4
+#define M_D             5
+#define B_Z             6
+#define M_Y             7
+#define	L_1		8
+#define	A_Y		9		// active mode version of M_Y
+#define	B_W		10		// 
+#define	A_J		11		// Active test of sending 4 down
+#define M_V             12
+#define M_U             13
+#define A_U             14
+#define M_L             15
+#define B_K             16
+#define M_B             17
+#define M_K             18
+#define M_W             19
+#ifdef WFA_WMM_AC
+#define ATC1            20
+#define ATC2            21
+#define ATC3            22
+#define ATC4            23
+#define ATC5            24
+#define ATC6            25
+#define ATC7            26
+#define ATC8            27
+#define ATC9            28
+#define ATC10           29
+#define ATC11           30
+#define STC1            31
+#define STC2            32
+#define STC3            33
+#define LAST_TEST       STC3
+#else
+#define LAST_TEST       M_W
+#endif /* WFA_WMM_AC */
+#define	APTS_DEFAULT	(LAST_TEST + 0x01)		// message codes
+#define	APTS_HELLO	(APTS_DEFAULT + 0x01)
+#define	APTS_BCST	(APTS_HELLO + 0x01)
+#define	APTS_CONFIRM	(APTS_BCST + 0x01)
+#define	APTS_STOP	(APTS_CONFIRM + 0x01)
+#define APTS_CK_BE      (APTS_STOP + 0x01)
+#define APTS_CK_BK      (APTS_CK_BE + 0x01)
+#define APTS_CK_VI      (APTS_CK_BK + 0x01)
+#define APTS_CK_VO      (APTS_CK_VI + 0x01)
+#define APTS_RESET      (APTS_CK_VO + 0x01)
+#define APTS_RESET_RESP (APTS_RESET + 0x01)
+#define APTS_RESET_STOP (APTS_RESET_RESP + 0x01)
+#define APTS_LAST       99
+//#define WFA_THREADS_NUM         1
+#define	MAXRETRY	3
+#define	MAXHELLO	20
+#define MAX_STOPS 10
+#define	NTARG	32		    // number of target names
+#define EQ(a,b)     (strcmp(a,b)==0)
+
+#define PORT            12345          // use a common port for sending/receiving
+#define   LII  2000000
+#ifdef WFA_WMM_AC
+/*Listen Inteval for station,to be changed to the actual value*/
+#define   lis_int  500000
+#define   becon_int  100000
+#endif
+#define NTARG           32
+
+#define WFA_DEFAULT_CODEC_SEC         0
+#define WFA_DEFAULT_CODEC_USEC        10000
+
+#define WFA_WMMPS_UDP_PORT            12345        // it must sync with console
+
+/* wmm defs */
+#define TOS_VO7     0xE0                // 111 0  0000 (7)  AC_VO tos/dscp values
+#define TOS_VO      0xD0                // 110 0  0000 (6)  AC_VO tos/dscp values
+//Atheros Madwifi use 0x88 for UPSD/Voice
+//#define TOS_VO      0x88               // 110 0  0000 (6)  AC_VO tos/dscp values
+
+#define TOS_VI      0xA0                // 101 0  0000 (5)  AC_VI
+#define TOS_VI4     0x80                // 100 0  0000 (4)  AC_VI
+
+#define TOS_BE      0x00                // 000 0  0000 (0)  AC_BE
+#define TOS_EE      0x60                // 011 0  0000 (3)  AC_BE
+
+#define TOS_BK      0x20                // 001 0  0000 (1)  AC_BK
+#define TOS_LE      0x40                // 010 0  0000 (2)  AC_BK
+
+
+/*
+ * * power management
+ * */
+#define PS_ON    1
+#define PS_OFF   0
+#define P_ON    1
+#define P_OFF   0
+
+#ifndef WIN32
+#if WFA_DEBUG
+#define PRINTF(s,args...) printf(s,## args)
+#else
+#define PRINTF(s,args...) ;
+#endif /* WFA_DEBUG */
+#else
+#define PRINTF
+#endif /* !WIN32 */
+
+extern int wl_set (void* wl,int cmd, void* buf,int len);
+extern int WmmpsTrafficRecv(int sock, char *buf, struct sockaddr *from);
+/*
+ * * internal table
+ * */
+struct apts_msg {                       //
+    char *name;                     // name of test
+    int cmd;                        // msg num
+    int param0;                     // number of packet exchanges
+    int param1;                     // number of uplink frames
+    int param2;                     // number of downlink frames
+    int param3;
+};
+
+/*
+ * * Wait/Timer states
+ * */
+typedef enum {
+    WFA_WAIT_NEXT_CODEC,
+    WFA_WAIT_FOR_AP_RESPONSE,
+    WFA_WAIT_STAUT_00,
+    WFA_WAIT_STAUT_01,
+    WFA_WAIT_STAUT_02,
+    WFA_WAIT_STAUT_03,
+    WFA_WAIT_STAUT_04,
+    WFA_WAIT_STAUT_0E,
+    WFA_WAIT_STAUT_VOLOAD,
+    WFA_WAIT_STAUT_SEQ,
+} WAIT_MODE;
+
+typedef struct wfa_wmmps
+{
+    int my_sta_id;
+    int my_group_cookie;
+    int my_cookie;
+    int thr_flag;
+    int sta_state;
+    int sta_test;
+    int wait_state;
+    int nextsleep;
+    int nsent;
+    int msgno;
+    int ps_thread;
+    int rcv_state;
+    int dscp;
+    int reset;
+    int streamid;
+    tgThrData_t *tdata;
+    struct sockaddr_in psToAddr;
+#ifndef WIN32
+    pthread_t thr;
+    pthread_cond_t thr_flag_cond;
+    pthread_mutex_t thr_flag_mutex;
+#endif
+}wfaWmmPS_t;
+
+
+
+int WfaStaSndHello(char,int,int *state);
+int WfaStaSndConfirm(char,int,int *state);
+int WfaStaSndVO(char,int,int *state);
+int WfaStaSndVOCyclic(char,int,int *state);
+int WfaStaSnd2VO(char,int,int *state);
+int WfaStaWaitStop(char,int,int *state);
+int WfaStaSndVI(char,int,int *state);
+int WfaStaSndBE(char,int,int *state);
+int WfaStaSndBK(char,int,int *state);
+int WfaStaSndVIE(char,int,int *state);
+//int WfaStaSndVO(char,int,int *state);
+int WfaStaSndBEE(char,int,int *state);
+int WfaStaSnd2VOE(char,int,int *state);
+void create_apts_msg(int msg, unsigned int txbuf[],int id);
+int WfaRcvStop(unsigned int *,int ,int *);
+int WfaRcvVO(unsigned int *,int ,int *);
+int WfaRcvProc(unsigned int *,int ,int *);
+int WfaRcvVOCyclic(unsigned int *,int ,int *);
+int WfaRcvVI(unsigned int *,int ,int *);
+int WfaRcvBE(unsigned int *,int ,int *);
+int WfaRcvBK(unsigned int *,int ,int *);
+#endif
diff --git a/src/tools/Wifi_ASD_test/lib/Makefile b/src/tools/Wifi_ASD_test/lib/Makefile
new file mode 100644
index 0000000..9495713
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/Makefile
@@ -0,0 +1,36 @@
+ifndef  SRCBASE
+        SRCBASE = ../../..
+endif
+
+include ../../../Makerules
+include ../Makefile.inc
+
+
+all:    ${LIB_OBJS}
+
+		$(AR) crv ${LIBWFA_NAME} $?
+		$(AR) crv ${LIBWFA_NAME_CA} $?
+
+#add dut lib to this ranlib for normal ASD (without RWL)
+		${RANLIB} ${LIBWFA_NAME} ${LIBWFA_NAME_CA}
+
+vpath %.c $(SRCBASE)/tools/Wifi_ASD_test/dut
+
+
+../dut/$(TARGETARCH)/%.o: %.c
+	@mkdir -p ../dut/$(TARGETARCH)
+	$(CC) -c $(CFLAGS) -o $@ $^
+
+$(TARGETARCH)/%.o: %.c
+	@mkdir -p $(TARGETARCH)
+	$(CC) -c $(CFLAGS) -o $@ $^
+
+clean:
+		rm -f ${PROGS} ${CLEANFILES}
+		rm -rf x86_mmx arm_le
+
+release_bins:
+	@mkdir -p $(INSTALL_DIR)/$(TARGETARCH)
+	install ${LIBWFA_NAME} ${LIBWFA_NAME_CA} $(INSTALL_DIR)/$(TARGETARCH)
+
+.phony: all clean release_bins
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_ca.c b/src/tools/Wifi_ASD_test/lib/wfa_ca.c
new file mode 100644
index 0000000..c736987
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_ca.c
@@ -0,0 +1,1539 @@
+

+/****************************************************************************

+ *  (c) Copyright 2006 Wi-Fi Alliance.  All Rights Reserved 

+ *

+ * 

+ *  LICENSE

+ *

+ * License is granted only to Wi-Fi Alliance members and designated Wi-Fi 

+ * contractors ("Authorized Licensees").  Authorized Licensees are hereby 

+ * granted the limited right to use this software solely for noncommercial 

+ * applications and solely for testing Wi-Fi equipment. Authorized Licensees 

+ * may embed this software into their proprietary equipment and distribute this

+ * software with such equipment under a license with at least the same 

+ * restrictions as contained in this License, including, without limitation, 

+ * the disclaimer of warranty and limitation of liability, below.  Other than 

+ * expressly granted herein, this License is not transferable or sublicensable, 

+ * and it does not extend to and may not be used with non-Wi-Fi applications.

+ *

+ * Commercial derivative works of this software or applications that use the 

+ * Wi-Fi scripts generated by this software are NOT AUTHORIZED without specific

+ * prior written permission from Wi-Fi Alliance.

+ *

+ * Non-Commercial derivative works of this software for internal use are 

+ * authorized and are limited by the same restrictions; provided, however, 

+ * that the Authorized Licensee shall provide Wi-Fi with a copy of such 

+ * derivative works under a perpetual, payment-free license to use, modify, 

+ * and distribute such derivative works for purposes of testing Wi-Fi equipment.

+ *

+ * Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse 

+ * or promote products that are derived from or that use this software without 

+ * specific prior written permission from Wi-Fi Alliance.

+ * 

+ * THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESSED OR 

+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 

+ * OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE, 

+ * ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT, 

+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+ * (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE GOODS 

+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 

+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 

+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF THE USE 

+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ ******************************************************************************

+ */

+ 

+

+/* 

+ *   File: wfa_ca.c

+ *   This file contains all implementation for the dut setup and control 

+ *   functions, such as network interfaces, ip address and wireless specific

+ *   setup with its supplicant.

+ *

+ *   The current implementation is to show how these functions

+ *   should be defined in order to support the Agent Control/Test Manager 

+ *   control commands. To simplify the current work and avoid any GPL licenses,

+ *   the functions mostly invoke shell commands by calling linux system call,

+ *   system("<commands>"). 

+ *

+ *   It depends on the differnt device and platform, vendors can choice their

+ *   own ways to interact its systems, supplicants and process these commands

+ *   such as using the native APIs.

+ *

+ *   Revision History:

+ *        2006/03/10  -- initially created by qhu

+ *        2006/06/01  -- BETA Release by qhu

+ *        2006/06/13  -- 00.02 Release by qhu

+ *        2006/06/30  -- 00.10 Release by qhu

+ *        2006/07/10  -- 01.00 Release by qhu

+ *        2006/09/01  -- 01.05 Release by qhu

+ *        2006/10/26  -- 01.06 Release by qhu

+ *                       replace hardcoded buff size with gloabal macro

+ *        2006/12/02  -- 

+ *                       bugs: 1. fixes incorrect order of getipconfig.sh 

+ *                                input parameters reported by p.schwann

+ *                             2. will add a new network for wap_cli command

+ *                                in case the network id 0 not present, 

+ *                                recommended by c.benson

+ *                                the solution is to reimplement with calling 

+ *                                native C API

+ *        2007/01/11  -- 01.10 release by qhu

+ *        

+ */ 

+#include <stdio.h>

+#include <unistd.h>

+#include <string.h>

+#include <stdlib.h>

+#include <sys/socket.h>

+#include <arpa/inet.h>

+#include <linux/types.h>

+#include <linux/socket.h>

+#include <iwlib.h>

+#include <wireless.h>

+

+#include "wfa_debug.h"

+#include "wfa_ver.h"

+#include "wfa_main.h"

+#include "wfa_types.h"

+#include "wfa_ca.h"

+#include "wfa_tlv.h"

+#include "wfa_sock.h"

+#include "wfa_tg.h"

+#include "wfa_cmds.h"

+#include "wfa_rsp.h"

+

+/*

+ * atheros wireless interface madwifi driver include files

+ * You may remove them if using other device interface

+ */

+#include "xtn/compat.h"

+#include "xtn/_ieee80211.h"

+#include "xtn/ieee80211_crypto.h"

+#include "xtn/ieee80211.h"

+#include "xtn/ieee80211_ioctl.h"

+#include "xtn/if_athioctl.h"

+

+#define CERTIFICATES_PATH    "/etc/wpa_supplicant"

+

+extern unsigned short wfa_defined_debug;

+

+/* error code */

+#define BCM_OK			0

+#define BCM_BAD			1

+

+#define BCM_SSID_LEN_MAX	32

+#define BCM_SSID_MAX		32

+

+/* defines for BSS types */

+#define BCM_BSS_INVALID		0

+#define	BCM_BSS_INDEPENDENT	1

+#define BCM_BSS_INFRA		3

+#define	BCM_BSS_AUTO		4

+

+/* defines for WPA AITHENTICATION */

+#define BCM_WPA_AUTH_DISABLED	0x0

+#define BCM_WPA_AUTH_NONE	0x1

+#define BCM_WPA_AUTH_8021X	0x2

+#define BCM_WPA_AUTH_PSK	0x4

+#define BCM_WPA2_AUTH_8021X	0x40

+#define BCM_WPA2_AUTH_PSK	0x80

+

+#define BCM_WEP_KEY_SIZE_MAX	32

+

+#define BCM_PRI_KEY_BAD		(-1)

+

+typedef struct bcmSsidObj

+{

+	char ssidStr[BCM_SSID_LEN_MAX];

+	int bssType;

+	int channel;

+	int wsec;

+	int auth; /* 802.11 authentication : default 0 for open. */

+	int wpa_auth; /* WPA authentication: default 1 for WPA-NONE */

+	int uapsd;

+	char keys[4][BCM_WEP_KEY_SIZE_MAX]; /* wl addwep */

+	int primary_key;

+	BYTE passphrase[64]; /* wl set_pmk */

+	int powerSave;

+	/* UAPSD */

+	int maxSPLength;

+	int acBE;

+	int acBK;

+	int acVI;

+	int acVO;

+} bcmSsidObj_t;

+

+typedef struct bcmSsidObjTbl

+{

+	bcmSsidObj_t ssidObj[BCM_SSID_MAX];

+	uint addCnt;

+	uint delCnt;

+	uint entries;

+} bcmSsidObjTbl_t;

+

+bcmSsidObjTbl_t bsotbl;

+int bcmSsidIsGood(char *ssidStr);

+bcmSsidObj_t *bcmWfaSsidTblFreeEntry();

+bcmSsidObj_t *bcmWfaSsidTblSsidFind(char *ssidStr);

+bcmSsidObj_t *bcmWfaSsidObjTblAdd(char *ssidStr);

+void bcmWfaSsidObjTblDel(char *ssidStr);

+void bcmWfaSsidObjPrint(bcmSsidObj_t *bso);

+void bcmWfaSsidObjTblPrint(void);

+

+/*

+ * agtCmdProcGetVersion(): response "ca_get_version" command to controller

+ *  input:  cmd --- not used

+ *          valLen -- not used

+ *  output: parms -- a buffer to store the version info response.

+ */

+int agtCmdProcGetVersion(int len, BYTE *parms, int *respLen, BYTE *respBuf)

+{

+    dutCmdResponse_t getverResp;

+

+    DPRINT_INFO(WFA_OUT, "entering agtCmdProcGetVersion ...\n");

+

+    getverResp.status = STATUS_COMPLETE;

+    strncpy(getverResp.cmdru.version, WFA_SYSTEM_VER, 8);

+

+    wfaEncodeTLV(WFA_GET_VERSION_RESP_TLV, sizeof(getverResp), (BYTE *)&getverResp, respBuf);

+

+    *respLen = WFA_TLV_HDR_LEN + sizeof(getverResp);

+

+    return TRUE;

+}

+

+extern int gxcSockfd;

+

+/*

+ * wfaStaAssociate():

+ *    The function is to force the station wireless I/F to re/associate 

+ *    with the AP.

+ */

+int wfaStaAssociate(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	int ret = 0;

+	int retVal = TRUE;

+	dutCommand_t *assoc = (dutCommand_t *)caCmdBuf;

+	char cmdStr[WFA_CMD_STR_SZ];

+	int imode; /* 0 for ibss, 1 for infrastructure */

+	char ssidTarget[WFA_SSID_NAME_LEN];

+	bcmSsidObj_t *bso;

+	int idx;

+

+	bcopy(assoc->cmdsu.ssid, ssidTarget, WFA_SSID_NAME_LEN);

+

+	bso = bcmWfaSsidTblSsidFind(ssidTarget);

+	if (!bso) {

+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {

+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);

+			retVal = FALSE;

+			goto exit;

+		}

+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {

+			bcmWfaSsidObjPrint(bso);

+		}

+

+	}

+	imode = (bso->bssType == BCM_BSS_INDEPENDENT) ? 0 : 1;

+

+	sprintf(cmdStr, "/tmp/ASD/wl disassoc");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl down");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	/* handle WEP keys */

+	for(idx = 0; idx < 4; idx++) {

+		if(bso->keys[idx][0] != '\0') {

+			sprintf(cmdStr, "/tmp/ASD/wl addwep %d %s", idx, bso->keys[idx]);

+		} else {

+			sprintf(cmdStr, "/tmp/ASD/wl rmwep %d", idx);

+		}

+		system(cmdStr);

+		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+	}

+

+	/* set primary key */

+	if(bso->primary_key != BCM_PRI_KEY_BAD) {

+		sprintf(cmdStr, "/tmp/ASD/wl primary_key %d", bso->primary_key);

+		system(cmdStr);

+		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+	}

+

+	if ((!imode) && bso->channel){

+		sprintf(cmdStr, "/tmp/ASD/wl channel %d", bso->channel);

+		system(cmdStr);

+		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+	}

+

+	sprintf(cmdStr, "/tmp/ASD/wl infra %d", imode);

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	/* security */

+	sprintf(cmdStr, "/tmp/ASD/wl wsec %d", bso->wsec);

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	if(bso->passphrase[0] != '\0') {

+		sprintf(cmdStr, "/tmp/ASD/wl set_pmk %s", bso->passphrase); 

+		system(cmdStr);

+		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+	}

+

+	sprintf(cmdStr, "/tmp/ASD/wl auth %d", bso->auth);

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl wpa_auth %d", bso->wpa_auth);

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	/* Power Save */

+	sprintf(cmdStr, "/tmp/ASD/wl wme_apsd_sta %d %d %d %d %d",

+		bso->maxSPLength, bso->acBE, bso->acBK, bso->acVI, bso->acVO);

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl up");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl ssid '%s'", ssidTarget);

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+exit:

+	ret = STATUS_COMPLETE;

+	wfaEncodeTLV(WFA_STA_ASSOCIATE_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + 4;

+	return retVal; 

+}

+

+/*

+ * wfaStaIsConnected():

+ *    The function is to check whether the station's wireless I/F has 

+ *    already connected to an AP.

+ */

+int wfaStaIsConnected(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	char cmdStr[WFA_CMD_STR_SZ];

+	FILE *tmpfd;

+	dutCmdResponse_t staConnectResp;

+

+	DPRINT_INFO(WFA_OUT, "Entering isConnected ...\n"); 

+

+	/* Associated gets long response */

+	if ((tmpfd = popen("/tmp/ASD/wl assoc | wc -l", "r")) == NULL){

+		printf("wc -l failed\n");

+	}

+	fgets(cmdStr, sizeof(cmdStr), tmpfd);

+	pclose(tmpfd);

+

+	/* Short response means not associated */

+	if (atoi(cmdStr) <= 2)

+		staConnectResp.cmdru.connected = 0;

+	else

+		staConnectResp.cmdru.connected = 1;

+

+	/*

+	 * Report back the status: Complete or Failed.

+	 */

+	staConnectResp.status = STATUS_COMPLETE;

+

+	wfaEncodeTLV(WFA_STA_IS_CONNECTED_RESP_TLV, sizeof(staConnectResp), 

+		(BYTE *)&staConnectResp, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + sizeof(staConnectResp);

+	return TRUE;

+}

+

+/*

+ * wfaStaGetIpConfig():

+ * This function is to retriev the ip info including

+ *     1. dhcp enable

+ *     2. ip address

+ *     3. mask 

+ *     4. primary-dns

+ *     5. secondary-dns

+ *

+ *     The current implementation is to use a script to find these information

+ *     and store them in a file. 

+ */

+int wfaStaGetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+    int i;

+    dutCommand_t *getIpConf = (dutCommand_t *)caCmdBuf;

+    dutCmdResponse_t ipconfigResp; 

+    char *ifname = getIpConf->intf;

+    caStaGetIpConfigResp_t *ifinfo = &ipconfigResp.cmdru.getIfconfig;

+

+    FILE *tmpfd;

+    char string[256];

+

+    /* Dhcp */

+    if ((tmpfd = popen("ps ax | grep -v grep | grep dhcli | wc -l", "r")) == NULL){

+	printf("wc -l failed\n");

+    }

+    fgets(string, sizeof(string), tmpfd);

+    pclose(tmpfd);

+    if (atoi(string) >= 1)

+       ifinfo->isDhcp = 1;

+    else

+       ifinfo->isDhcp = 0;

+

+    /* ipaddr */

+    sprintf(string, "ifconfig %s | grep 'inet addr' |  cut -d: -f2 | cut -d' ' -f1", ifname);

+    if ((tmpfd = popen(string, "r")) == NULL){

+	printf("ifconfig addr failed\n");

+    }

+    ifinfo->ipaddr[0] = 0;

+    fgets(ifinfo->ipaddr, WFA_IP_ADDR_STR_LEN, tmpfd);

+    ifinfo->ipaddr[strlen(ifinfo->ipaddr) - 1] = 0; /* Purge newline */

+    pclose(tmpfd);

+    if(ifinfo->ipaddr[0] == 0) 

+       strncpy(ifinfo->ipaddr, "none", 15);

+

+    /* mask */

+    sprintf(string, "ifconfig %s | grep 'inet addr' |  cut -d: -f4", ifname);

+    if ((tmpfd = popen(string, "r")) == NULL){

+	printf("ifconfig mask failed\n");

+    }

+    ifinfo->mask[0] = 0;

+    fgets(ifinfo->mask, WFA_IP_MASK_STR_LEN, tmpfd);

+    ifinfo->mask[strlen(ifinfo->mask) - 1] = 0; /* Purge newline */

+    pclose(tmpfd);

+

+    if(ifinfo->mask[0] == 0) 

+       strcpy(ifinfo->mask, "none");

+

+    /* dns */

+    if ((tmpfd = popen("cat /etc/resolv.conf | grep nameserver | awk '{print $2}'", "r")) == NULL){

+	printf("resolve.conf failed\n");

+    }

+    for (i = 0; i < WFA_MAX_DNS_NUM; i++){

+	    fgets(ifinfo->dns[i], WFA_MAC_ADDR_STR_LEN, tmpfd);

+	    if (ifinfo->dns[i][0])

+	        ifinfo->dns[i][strlen(ifinfo->dns[i]) - 1] = 0; /* Purge newline */

+	    else

+    		strcpy(ifinfo->dns[i], "NOTDEF");

+    }

+    pclose(tmpfd);

+

+     /*

+      * Report back the results

+      */

+     ipconfigResp.status = STATUS_COMPLETE;

+     wfaEncodeTLV(WFA_STA_GET_IP_CONFIG_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)&ipconfigResp, respBuf);   

+

+     *respLen = WFA_TLV_HDR_LEN + sizeof(caStaGetIpConfigResp_t);

+

+     DPRINT_INFO(WFA_OUT, "%i %i %s %s %s %s %i\n", ipconfigResp.status, 

+        ifinfo->isDhcp, ifinfo->ipaddr, ifinfo->mask, 

+            ifinfo->dns[0], ifinfo->dns[1], *respLen);

+

+     return TRUE;

+}

+

+/*

+ * wfaStaSetIpConfig():

+ *   The function is to set the ip configuration to a wireless I/F.

+ *   1. IP address

+ *   2. Mac address

+ *   3. default gateway

+ *   4. dns nameserver (pri and sec).  

+ */

+int wfaStaSetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   dutCommand_t *setIpConf = (dutCommand_t *)caCmdBuf;

+   char cmds[128];

+   int ret = 0;

+   caStaSetIpConfig_t *ipconfig = &setIpConf->cmdsu.ipconfig;

+

+   DPRINT_INFO(WFA_OUT, "entering wfaStaSetIpConfig ...\n");

+

+   /*

+    * Use command 'ifconfig' to configure the interface ip address, mask.

+    * (Linux specific).

+    */

+   if (!strlen(ipconfig->intf) || !strlen(ipconfig->ipaddr)){

+	   ret = STATUS_ERROR;

+	   wfaEncodeTLV(WFA_STA_SET_IP_CONFIG_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+	   *respLen = WFA_TLV_HDR_LEN + 4;

+	   return TRUE;

+   }

+   sprintf(cmds, "%s %s %s ", IFCONFIG_PATH, ipconfig->intf, ipconfig->ipaddr);

+   if (strlen(ipconfig->mask))

+   	sprintf(&cmds[strlen(cmds)], "netmask %s ", ipconfig->mask);

+   system(cmds);

+   DPRINT_INFO(WFA_OUT, "%s\n", "doing ifconfig");

+

+   /* use command 'route add' to set set gatewway (linux specific) */ 

+   if(ipconfig->defGateway[0]) {

+      sprintf(cmds, "%s add default gw %s > /dev/null 2>&1", ROUTE_PATH, ipconfig->defGateway);

+      system(cmds);

+      DPRINT_INFO(WFA_OUT, "%s\n", "doing route add");

+   }

+

+   /* set dns (linux specific) */

+   if (ipconfig->pri_dns[0]){

+	   sprintf(cmds, "cp /etc/resolv.conf /tmp/resolv.conf.bk");

+	   system(cmds);

+	   sprintf(cmds, "echo nameserv %s > /etc/resolv.conf", ipconfig->pri_dns);

+	   system(cmds);

+	   sprintf(cmds, "echo nameserv %s >> /etc/resolv.conf", ipconfig->sec_dns);

+	   system(cmds);

+   }

+

+   ret = STATUS_COMPLETE;

+   wfaEncodeTLV(WFA_STA_SET_IP_CONFIG_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+   *respLen = WFA_TLV_HDR_LEN + 4;

+   return TRUE;

+}

+

+/*

+ * wfaStaVerifyIpConnection():

+ * The function is to verify if the station has IP connection with an AP by

+ * send ICMP/pings to the AP.

+ */ 

+int wfaStaVerifyIpConnection(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   dutCommand_t *verip = (dutCommand_t *)caCmdBuf;

+   char cmdStr[WFA_CMD_STR_SZ];

+   FILE *tmpfile;

+   dutCmdResponse_t verifyIpResp;

+   dutCommand_t vvv;

+

+   

+   DPRINT_INFO(WFA_OUT, "Entering wfaStaVerifyIpConnection ...\n");

+   memcpy(&vvv, caCmdBuf, sizeof(dutCommand_t));

+

+   /* set timeout value in case not set */

+   if(verip->cmdsu.verifyIp.timeout <= 0)

+        verip->cmdsu.verifyIp.timeout = 10;

+   

+   /* execute the ping command  and pipe the result to a tmp file */

+   sprintf(cmdStr, "ping %s -c 3 -W %d | grep '100%%'", verip->cmdsu.verifyIp.dipaddr,  verip->cmdsu.verifyIp.timeout);

+

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   if (strlen(verip->cmdsu.verifyIp.dipaddr) == 0 || ((tmpfile = popen(cmdStr, "r")) == NULL)){

+      int status = STATUS_ERROR;

+      wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, 4, (BYTE *)&status, respBuf);   

+      *respLen = WFA_TLV_HDR_LEN + 4;

+

+      DPRINT_ERR(WFA_ERR, "Could not execute %s\n", cmdStr);

+      return FALSE;

+   }

+

+   verifyIpResp.status = STATUS_COMPLETE;

+

+   if (fgets(cmdStr, sizeof(cmdStr), tmpfile) == NULL){

+      verifyIpResp.cmdru.connected = 1;

+   } else{

+      verifyIpResp.cmdru.connected = 0;

+   }

+   pclose(tmpfile);

+   

+

+   wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)&verifyIpResp, respBuf);   

+

+   *respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);

+   

+   return TRUE;

+}

+

+/*

+ * wfaStaGetMacAddress()

+ *    This function is to retrieve the MAC address of a wireless I/F.

+ */

+int wfaStaGetMacAddress(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	dutCmdResponse_t getmacResp;

+	FILE *tmpfd;

+

+	DPRINT_INFO(WFA_OUT, "Entering wfaStaGetMacAddress ...\n");

+

+	if ((tmpfd = popen("/tmp/ASD/wl dump | grep perm | awk '{print $4}'", "r")) == NULL){

+		int status = STATUS_ERROR;

+		wfaEncodeTLV(WFA_STA_GET_MAC_ADDRESS_RESP_TLV, 4, (BYTE *)&status, respBuf);   

+		*respLen = WFA_TLV_HDR_LEN + 4;

+

+		DPRINT_ERR(WFA_ERR, "Pipe open for wl dump failed\n");

+		return FALSE;

+	}

+	fgets(getmacResp.cmdru.mac, sizeof(getmacResp.cmdru.mac), tmpfd);

+	getmacResp.cmdru.mac[strlen(getmacResp.cmdru.mac) - 1] = 0;		/* Get rid of NL */

+	printf("get_mac_addr: returning mac :%s:\n", getmacResp.cmdru.mac);

+	pclose (tmpfd);

+	getmacResp.status = STATUS_COMPLETE;

+ 

+	wfaEncodeTLV(WFA_STA_GET_MAC_ADDRESS_RESP_TLV, sizeof(getmacResp), 

+		(BYTE *)&getmacResp, respBuf);   

+

+	*respLen = WFA_TLV_HDR_LEN + sizeof(getmacResp);

+	return TRUE;

+}

+

+/*

+ *   wfaStaGetBSSID():

+ *     This function is to retrieve BSSID of a specific wireless I/F.

+ */ 

+int wfaStaGetBSSID(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	char cmdStr[WFA_CMD_STR_SZ];

+	FILE *tmpfd;

+	dutCmdResponse_t bssidResp;

+

+	/* Associated gets long response */

+	if ((tmpfd = popen("/tmp/ASD/wl assoc | wc -l", "r")) == NULL){

+		printf("wc -l failed\n");

+	}

+	fgets(cmdStr, sizeof(cmdStr), tmpfd);

+	pclose(tmpfd);

+

+	/* Short response means not associated */

+	if (atoi(cmdStr) <= 2){

+		strcpy(bssidResp.cmdru.bssid, "00:00:00:00:00:00");

+	} else {

+		if ((tmpfd = popen("/tmp/ASD/wl bssid", "r")) == NULL){

+			printf("bassid failed\n");

+		}

+		fgets(cmdStr, sizeof(cmdStr), tmpfd);

+		pclose(tmpfd);

+		cmdStr[17] = 0;	/* Get rid of CR or NL */

+		strcpy(bssidResp.cmdru.bssid, cmdStr);

+	}

+	bssidResp.status = STATUS_COMPLETE; 

+

+	wfaEncodeTLV(WFA_STA_GET_BSSID_RESP_TLV, sizeof(bssidResp), 

+		(BYTE *)&bssidResp, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + sizeof(bssidResp);

+	return TRUE;

+}

+

+/*

+ * wfaStaGetStats():

+ * The function is to retrieve the statistics of the I/F's layer 2 txFrames, 

+ * rxFrames, txMulticast, rxMulticast, fcsErrors/crc, and txRetries.

+ * Currently there is not definition how to use these info. 

+ */

+int wfaStaGetStats(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	int ret = 0;

+	caStaGetStatsResp_t statsResp;

+	FILE *fd;

+	char cmdStr[256];

+

+	DPRINT_INFO(WFA_OUT, "Entering wfaStaGetStats ...\n");

+

+	if ((fd = popen("/tmp/ASD/wl dump stats | grep txframe | awk '{print $2,\"\\n\",$10}'", "r")) == NULL){

+		DPRINT_ERR(WFA_ERR, "Couldn't get txframe stats\n");

+		goto wfaStaGetStats_error;

+	} else {

+		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 1: tx frame */

+		statsResp.txFrames =  atoi(cmdStr);

+		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 2: rx frame */

+		statsResp.rxFrames =  atoi(cmdStr);

+		pclose(fd);

+	}

+

+	if ((fd = popen("/tmp/ASD/wl dump stats | grep txmulti | awk '{print $4, \"\\n\", $6 + $8}'", "r")) == NULL){

+		DPRINT_ERR(WFA_ERR, "Couldn't get d11_txmulti stats\n");

+		goto wfaStaGetStats_error;

+	} else {

+		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 1: txmulti */

+		statsResp.txMulticast = atoi(cmdStr);

+		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 2: d11_txretry + d11_txretrie */

+		statsResp.txRetries = atoi(cmdStr);

+		pclose(fd);

+	}

+

+	if ((fd = popen("/tmp/ASD/wl dump stats | grep rxdfrmmcast | awk '{print $6 + $8}'", "r")) == NULL){

+		DPRINT_ERR(WFA_ERR, "Couldn't get rxdfrmmcast stats\n");

+		goto wfaStaGetStats_error;

+	} else {

+		fgets(cmdStr, sizeof(cmdStr), fd);	/* data + mngment mcast frames */

+		statsResp.rxMulticast = atoi(cmdStr);

+		pclose(fd);

+	}

+

+	if ((fd = popen("/tmp/ASD/wl dump stats | grep rxbadfcs | awk '{print $8}'", "r")) == NULL){

+		DPRINT_ERR(WFA_ERR, "Couldn't get rxbadfcs  stats\n");

+		goto wfaStaGetStats_error;

+	} else {

+		fgets(cmdStr, sizeof(cmdStr), fd);

+		statsResp.fcsErrors = atoi(cmdStr);

+		pclose(fd);

+	}

+

+	statsResp.status = STATUS_COMPLETE;

+	wfaEncodeTLV(WFA_STA_GET_STATS_RESP_TLV, sizeof(statsResp), (BYTE *)&statsResp, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + sizeof(statsResp);

+	return TRUE;

+

+wfaStaGetStats_error:

+	ret = STATUS_ERROR;

+	wfaEncodeTLV(WFA_STA_GET_STATS_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + 4;

+	return FALSE;

+}

+

+/*

+ * wfaSetEncryption():

+ *   The function is to set the wireless interface with WEP or none.

+ *   Input parameters: 

+ *     1. I/F

+ *     2. ssid

+ *     3. encpType - wep or none

+ *     Optional:

+ *     4. key1

+ *     5. key2

+ *     6. key3

+ *     7. key4

+ *     8. activeKey Index : 1, 2, 3, or 4

+ */

+int wfaSetEncryption(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	int ret = 0;

+	int retVal = TRUE;

+	caStaSetEncryption_t *setEncryp = (caStaSetEncryption_t *)caCmdBuf;

+	int idx;

+	bcmSsidObj_t *bso;

+	char * ssidStr;

+

+	DPRINT_INFO(WFA_OUT, "wfaSetEncryption()\n");

+

+	/* Save the settings for when we need them */

+

+	ssidStr = setEncryp->ssid;

+

+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {

+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {

+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);

+			retVal = FALSE;

+			goto exit;

+		}

+	}

+

+	/* set Key management to NONE (NO WPA) for plaintext or WEP */

+	bso->wpa_auth = BCM_WPA_AUTH_DISABLED;

+

+	for(idx = 0; idx < 4; idx++) {

+		if(setEncryp->keys[idx][0] != '\0') {

+			strcpy(bso->keys[idx], setEncryp->keys[idx]);

+		} else {

+			bzero(bso->keys[idx], BCM_WEP_KEY_SIZE_MAX);

+		}

+	}

+

+	if ((setEncryp->activeKeyIdx > 0) && (setEncryp->activeKeyIdx < 5)) {

+		/* move the index range from (1 to 4) to (0 to 3) */

+		bso->primary_key = setEncryp->activeKeyIdx - 1;

+	}

+

+	bso->wsec = (!setEncryp->encpType) ? 0 : 1;

+

+	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {

+		bcmWfaSsidObjPrint(bso);

+	}

+

+exit:	

+	ret = STATUS_COMPLETE;

+	wfaEncodeTLV(WFA_STA_SET_ENCRYPTION_RESP_TLV, 4, (BYTE *)&ret, respBuf);

+	*respLen = WFA_TLV_HDR_LEN + 4;

+	

+	return retVal;

+}

+

+/*

+ * wfaStaSetEapTLS():

+ *   This is to set

+ *   1. ssid

+ *   2. encrypType - tkip or aes-ccmp

+ *   3. keyManagementType - wpa or wpa2

+ *   4. trustedRootCA

+ *   5. clientCertificate

+ */

+int wfaStaSetEapTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   int ret = 0;

+   caStaSetEapTLS_t *setTLS = (caStaSetEapTLS_t *)caCmdBuf;

+   char cmdStr[WFA_CMD_STR_SZ];

+   char *ifname = setTLS->intf;

+

+   DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEapTLS ...\n");

+

+   /*

+    * need to store the trustedROOTCA and clientCertificate into a file first.

+    */

+   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   /* ssid */

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setTLS->ssid);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   /* key management */

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   /* protocol WPA */

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap TLS", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ca_cert '\"%s\"'", ifname, setTLS->trustedRootCA);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"wifi-user@wifilabs.local\"'", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 private_key '\"%s/%s\"'", ifname, CERTIFICATES_PATH, setTLS->clientCertificate);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 private_key_passwd '\"wifi\"'", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   ret = STATUS_COMPLETE;

+   wfaEncodeTLV(WFA_STA_SET_EAPTLS_RESP_TLV, 4, (BYTE *)&ret, respBuf);

+   *respLen = WFA_TLV_HDR_LEN + 4;

+

+   return TRUE;

+}

+

+/*

+ * The function is to set 

+ *   1. ssid

+ *   2. passPhrase

+ *   3. keyMangementType - wpa/wpa2

+ *   4. encrypType - tkip or aes-ccmp

+ */

+int wfaStaSetPSK(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	int ret = 0;

+	int retVal = TRUE;

+	caStaSetPSK_t *setPSK = (caStaSetPSK_t *)caCmdBuf;

+	bcmSsidObj_t *bso;

+	char *ssidStr;

+

+	DPRINT_INFO(WFA_OUT, "wfaStaSetPSK()");

+

+	ssidStr = setPSK->ssid;

+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {

+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {

+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);

+			retVal = FALSE;

+			goto exit;

+		}

+	}

+

+	if (!strcmp(setPSK->keyMgmtType, "wpa")) {

+		bso->wpa_auth = BCM_WPA_AUTH_PSK; /* WPA-PSK/WPA-Personal */

+	} else if (!strcmp(setPSK->keyMgmtType, "wpa2")) {

+		bso->wpa_auth = BCM_WPA2_AUTH_PSK; /* WPA2-PSK/WPA2-Personal */

+	} else {

+		DPRINT_ERR(WFA_OUT, "invalid key_mgmt %s", setPSK->keyMgmtType); 

+		retVal = FALSE;

+		goto exit;

+	}

+

+	DPRINT_INFO(WFA_OUT, "wpa_auth %d\n", bso->wpa_auth);

+

+	if (setPSK->encpType == ENCRYPT_TKIP) {

+		bso->wsec = 3;

+	} else if (setPSK->encpType == ENCRYPT_AESCCMP) {

+		bso->wsec = 7;

+	} else {

+		DPRINT_ERR(WFA_OUT, "invalid encpType %d", setPSK->encpType); 

+		goto exit;

+	}

+	DPRINT_INFO(WFA_OUT, "encpType %d wsec %d\n", setPSK->encpType, bso->wsec);

+

+	strcpy((char *)bso->passphrase, (char *)setPSK->passphrase);

+	bso->auth = 0;

+

+	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {

+		bcmWfaSsidObjPrint(bso);

+	}

+

+	retVal = TRUE;

+

+exit:	

+	ret = STATUS_COMPLETE;

+	wfaEncodeTLV(WFA_STA_SET_PSK_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + 4;

+	

+	return retVal; 

+}

+

+/*

+ * wfaStaGetInfo(): 

+ * Get vendor specific information in name/value pair by a wireless I/F.

+ */

+int wfaStaGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   dutCmdResponse_t infoResp;

+   dutCommand_t *getInfo = (dutCommand_t *)caCmdBuf;

+

+   /*

+    * Normally this is called to retrieve the vendor information

+    * from a interface, no implement yet

+    */

+   sprintf(infoResp.cmdru.info, "interface,%s,vendor,XXX,cardtype,802.11a/b/g", getInfo->intf);

+   

+   infoResp.status = STATUS_COMPLETE;

+   wfaEncodeTLV(WFA_STA_GET_INFO_RESP_TLV, sizeof(infoResp), (BYTE *)&infoResp, respBuf);   

+   *respLen = WFA_TLV_HDR_LEN + sizeof(infoResp);

+

+    DPRINT_INFO(WFA_OUT, "%s\n", infoResp.cmdru.info);

+

+   return TRUE;

+}

+

+/*

+ * wfaStaSetEapTTLS():

+ *   This is to set

+ *   1. ssid

+ *   2. username

+ *   3. passwd

+ *   4. encrypType - tkip or aes-ccmp

+ *   5. keyManagementType - wpa or wpa2

+ *   6. trustedRootCA

+ */

+int wfaStaSetEapTTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   int ret = 0;

+   char cmdStr[WFA_CMD_STR_SZ];

+   caStaSetEapTTLS_t *setTTLS = (caStaSetEapTTLS_t *)caCmdBuf;

+   char *ifname = setTTLS->intf;

+

+   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setTTLS->ssid);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"%s\"'", ifname, setTTLS->username);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 password '\"%s\"'", ifname, setTTLS->passwd);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+/* This may not need to set. if it is not set, default to take all */

+//   sprintf(cmdStr, "wpa_cli -i %s set_network 0 pairwise '\"%s\"", ifname, setTTLS->encrptype);

+//   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap TTLS", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ca_cert '\"%s/%s\"'", ifname, CERTIFICATES_PATH, setTTLS->trustedRootCA);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 anonymous_identity '\"anonymous\"'", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 phase2 '\"auth=MSCHAPV2\"'", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   ret = STATUS_COMPLETE;

+   wfaEncodeTLV(WFA_STA_SET_EAPTTLS_RESP_TLV, 4, (BYTE *)&ret, respBuf);

+   *respLen = WFA_TLV_HDR_LEN + 4;

+

+   return TRUE;

+}

+

+/*

+ * wfaStaSetEapSIM():

+ *   This is to set

+ *   1. ssid

+ *   2. user name

+ *   3. passwd

+ *   4. encrypType - tkip or aes-ccmp

+ *   5. keyMangementType - wpa or wpa2

+ */

+int wfaStaSetEapSIM(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   int ret = 0;

+   char cmdStr[WFA_CMD_STR_SZ];

+   caStaSetEapSIM_t *setSIM = (caStaSetEapSIM_t *)caCmdBuf;

+   char *ifname = setSIM->intf;

+

+   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setSIM->ssid);

+   system(cmdStr);

+

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"%s\"'", ifname, setSIM->username);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 pairwise '\"%s\"'", ifname, setSIM->encrptype);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap SIM", ifname);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);

+   system(cmdStr);

+

+   ret = STATUS_COMPLETE;

+   wfaEncodeTLV(WFA_STA_SET_EAPSIM_RESP_TLV, 4, (BYTE *)&ret, respBuf);

+   *respLen = WFA_TLV_HDR_LEN + 4;

+

+   return ret;

+}

+

+/*

+ * wfaStaSetPEAP()

+ *   This is to set

+ *   1. ssid

+ *   2. user name

+ *   3. passwd

+ *   4. encryType - tkip or aes-ccmp

+ *   5. keyMgmtType - wpa or wpa2

+ *   6. trustedRootCA

+ *   7. innerEAP

+ *   8. peapVersion

+ */

+int wfaStaSetPEAP(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   int ret = 0;

+   char cmdStr[WFA_CMD_STR_SZ];

+   caStaSetEapPEAP_t *setPEAP = (caStaSetEapPEAP_t *)caCmdBuf;

+   char *ifname = setPEAP->intf;

+

+   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);

+   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setPEAP->ssid);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap PEAP", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 anonymous_identity '\"anonymous\"' ", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"%s\"'", ifname, setPEAP->username);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 password '\"%s\"'", ifname, setPEAP->passwd);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ca_cert '\"%s/%s\"'", ifname, CERTIFICATES_PATH, setPEAP->trustedRootCA);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   /* if this not set, default to set support all */

+   //sprintf(cmdStr, "wpa_cli -i %s set_network 0 pairwise '\"%s\"'", ifname, setPEAP->encrptype);

+   //system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 phase1 '\"peaplabel=%i\"'", ifname, setPEAP->peapVersion);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s set_network 0 phase2 '\"auth=%s\"'", ifname, setPEAP->innerEAP);

+   system(cmdStr);

+   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+//   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);

+//   system(cmdStr);

+

+   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);

+   system(cmdStr);

+

+   ret = STATUS_COMPLETE;

+   wfaEncodeTLV(WFA_STA_SET_PEAP_RESP_TLV, 4, (BYTE *)&ret, respBuf);

+   *respLen = WFA_TLV_HDR_LEN + 4;

+

+   return TRUE;

+}

+

+/*

+ * wfaStaSetUAPSD()

+ *    This is to set

+ *    1. maxSPLength - 0,1,2,or 4 

+ *    2. acBE

+ *    3. acBK

+ *    4. acVI

+ *    5. acVO

+ */

+int wfaStaSetUAPSD(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	int ret = 0;

+	int retVal = TRUE;

+	caStaSetUAPSD_t *uapsd = (caStaSetUAPSD_t *)caCmdBuf;

+	bcmSsidObj_t *bso;

+	char *ssidStr;

+

+	DPRINT_INFO(WFA_OUT, "maxSPLength %d acBE %d acBK %d acVI %d acVO %d\n",

+		uapsd->maxSPLength, uapsd->acBE, uapsd->acBK, uapsd->acVI, uapsd->acVO);

+

+	ssidStr = uapsd->ssid;

+

+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {

+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {

+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);

+			retVal = FALSE;

+			goto exit;

+		}

+	}

+

+	bso->maxSPLength = uapsd->maxSPLength;

+	bso->acBE = uapsd->acBE;

+	bso->acBK = uapsd->acBK;

+	bso->acVI = uapsd->acVI;

+	bso->acVO = uapsd->acVO;

+

+exit:

+	ret = STATUS_COMPLETE;

+	wfaEncodeTLV(WFA_STA_SET_UAPSD_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + 4;

+

+	return retVal;

+}

+

+/*

+ * wfaStaSetIBSS()

+ *    This is to set

+ *    1. ssid

+ *    2. channel

+ *    3. encrypType - none or wep

+ *    optional

+ *    4. key1

+ *    5. key2

+ *    6. key3

+ *    7. key4

+ *    8. activeIndex - 1, 2, 3, or 4

+ */

+

+/* Not sure what the intention is, but I am using this routine

+ * as storing info only, no action.  Action is taken when we actually associate */

+int wfaStaSetIBSS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	int ret;

+	int retVal = TRUE;

+	caStaSetIBSS_t *setIBSS = (caStaSetIBSS_t *)caCmdBuf;

+	bcmSsidObj_t *bso;

+	int idx;

+	char *ssidStr;

+	

+	DPRINT_INFO(WFA_OUT, "wfaStaSetIBSS()\n");

+

+	/* Save the settings for when we need them */

+

+	ssidStr = setIBSS->ssid;

+

+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {

+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {

+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);

+			retVal = FALSE;

+			goto exit;

+		}

+	}

+

+	bso->bssType = BCM_BSS_INDEPENDENT;

+

+	if (setIBSS->channel) {

+		bso->channel = setIBSS->channel;

+	}

+

+	bso->wsec = (!setIBSS->encpType) ? 0 : 1;

+

+	for(idx = 0; idx < 4; idx++) {

+		if(setIBSS->keys[idx][0] != '\0') {

+			strcpy(bso->keys[idx], setIBSS->keys[idx]);

+		} else {

+			bzero(bso->keys[idx], BCM_WEP_KEY_SIZE_MAX);

+		}

+	}

+

+	if ((setIBSS->activeKeyIdx > 0) && (setIBSS->activeKeyIdx < 5)) {

+		/* move the index range from (1 to 4) to (0 to 3) */

+		bso->primary_key = setIBSS->activeKeyIdx - 1;

+	}

+

+	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {

+		bcmWfaSsidObjPrint(bso);

+	}

+

+exit:

+	ret = STATUS_COMPLETE;

+	wfaEncodeTLV(WFA_STA_SET_IBSS_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+	*respLen = WFA_TLV_HDR_LEN + 4;

+	

+	return retVal;

+}

+

+int wfaDeviceGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+	caDeviceGetInfoResp_t dinfo;

+	char cmdStr[WFA_CMD_STR_SZ];

+	FILE *fd;

+

+	if ((fd = popen("/tmp/ASD/wl ver | awk '{print $7}'", "r")) == NULL){

+		printf("Couldn't open either /tmp/ASD/wl or awk\n");

+		dinfo.status = STATUS_ERROR;

+	} else {

+		memset(&dinfo, 0, sizeof(dinfo));

+

+		fgets(cmdStr, sizeof(cmdStr), fd);	/* Ignore first line */

+		fgets(cmdStr, sizeof(cmdStr), fd);

+		cmdStr[strlen(cmdStr) - 1] = 0;		/* Get rid of NL */

+		pclose(fd);

+

+	   dinfo.status = STATUS_COMPLETE;

+	   sprintf(dinfo.vendor, "%.16s", "Broadcom");

+

+	   sprintf(dinfo.version, "%.16s", cmdStr);

+	   sprintf(dinfo.model, "%.8s", "BRCM");

+

+	   DPRINT_INFO(WFA_OUT, "Entering wfaDeviceGetInfo ...\n");

+

+	   DPRINT_INFO(WFA_OUT, "status %i vendor %s model %s version %s\n", dinfo.status, dinfo.vendor, dinfo.model, dinfo.version);

+

+	   wfaEncodeTLV(WFA_DEVICE_GET_INFO_RESP_TLV, sizeof(dinfo), (BYTE *)&dinfo, respBuf);   

+	   *respLen = WFA_TLV_HDR_LEN + sizeof(dinfo);

+

+   }

+   return TRUE;

+

+}

+

+/*

+ * This funciton is to retrieve a list of interfaces and return

+ * the list back to Agent control.

+ * 

+ */

+int wfaDeviceListIF(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   int ret;

+   dutCommand_t *ifList = (dutCommand_t *)caCmdBuf;

+   caDeviceListIFResp_t ifListResp;

+

+   switch(ifList->cmdsu.iftype)

+   {

+      case IF_80211:

+      ifListResp.status = STATUS_COMPLETE;

+      ifListResp.iftype = IF_80211; 

+      strcpy(ifListResp.ifs[0], "eth1");

+      strcpy(ifListResp.ifs[1], "NULL");

+      strcpy(ifListResp.ifs[2], "NULL");

+      break;

+      case IF_ETH:

+      ifListResp.status = STATUS_COMPLETE;

+      ifListResp.iftype = IF_ETH; 

+      strcpy(ifListResp.ifs[0], "eth0");

+      strcpy(ifListResp.ifs[1], "NULL");

+      strcpy(ifListResp.ifs[2], "NULL");

+      break;

+      default:

+      {

+         ret = STATUS_ERROR;

+         wfaEncodeTLV(WFA_DEVICE_LIST_IF_RESP_TLV, 4, (BYTE *)&ret, respBuf);   

+         *respLen = WFA_TLV_HDR_LEN + 4;

+

+         return TRUE; 

+      }

+   }

+   

+   wfaEncodeTLV(WFA_DEVICE_LIST_IF_RESP_TLV, sizeof(ifListResp), (BYTE *)&ifListResp, respBuf);   

+   *respLen = WFA_TLV_HDR_LEN + sizeof(ifListResp);

+

+   return TRUE;

+}

+

+int wfaStaDebugSet(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)

+{

+   dutCmdResponse_t debugResp;

+   dutCommand_t *debugSet = (dutCommand_t *)caCmdBuf;

+

+   DPRINT_INFO(WFA_OUT, "Entering wfaStaDebugSet ...\n");

+

+   if(debugSet->cmdsu.dbg.state == 1) /* enable */

+      wfa_defined_debug |= debugSet->cmdsu.dbg.level;

+   else

+      wfa_defined_debug = (~debugSet->cmdsu.dbg.level & wfa_defined_debug);

+

+   debugResp.status = STATUS_COMPLETE;

+   wfaEncodeTLV(WFA_STA_GET_INFO_RESP_TLV, sizeof(debugResp), (BYTE *)&debugResp, respBuf);   

+   *respLen = WFA_TLV_HDR_LEN + sizeof(debugResp);

+

+    DPRINT_INFO(WFA_OUT, "%s\n", debugResp.cmdru.info);

+

+   return TRUE;

+}

+

+int bcmSsidIsGood(char *ssidStr)

+{

+	int ssidLen = strlen(ssidStr);

+

+	if ((ssidLen == 0) || (ssidLen > BCM_SSID_LEN_MAX)) {

+		return (FALSE);

+	} else {

+		return (TRUE);

+	}

+}

+

+bcmSsidObj_t *bcmWfaSsidTblFreeEntry()

+{

+	bcmSsidObj_t *bso;

+	int idx;

+

+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidTblFreeEntry\n");

+

+	for (idx = 0; idx < BCM_SSID_MAX; idx++) {

+		bso = &bsotbl.ssidObj[idx];

+		if (bcmSsidIsGood(bso->ssidStr) == FALSE) {

+			return bso;

+		}

+	}

+

+	DPRINT_ERR(WFA_OUT, "bcmWfaSsidTblFreeEntry: no free entry available.\n");

+	return (NULL);

+}

+

+bcmSsidObj_t *bcmWfaSsidTblSsidFind(char *ssidStr)

+{

+	bcmSsidObj_t *bso;

+	bcmSsidObj_t *bsoFound= NULL;

+	int idx;

+

+	if (bcmSsidIsGood(ssidStr) == FALSE) {

+		return (NULL);

+	}

+

+	for (idx = 0; idx < BCM_SSID_MAX; idx++) {

+		bso = &bsotbl.ssidObj[idx];

+		if (bcmSsidIsGood(ssidStr) == FALSE) {

+			continue;

+		}

+		

+		if (strcmp(ssidStr, bso->ssidStr)) {

+			continue;

+		} else {

+			bsoFound = bso;

+			break;

+		}

+	}

+

+	return (bsoFound);

+}

+

+bcmSsidObj_t *bcmWfaSsidObjTblAdd(char *ssidStr)

+{

+	bcmSsidObj_t *bso;

+

+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd: ssidStr %s\n", ssidStr);

+

+	if (bcmSsidIsGood(ssidStr) == FALSE) {

+		return (NULL);

+	}

+

+	if ((bso = bcmWfaSsidTblSsidFind(ssidStr))) {

+		DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s): ssid already exists\n", ssidStr);

+		return (bso);

+	}

+

+	if (!(bso = bcmWfaSsidTblFreeEntry())) {

+		DPRINT_INFO(WFA_OUT, "no free entry\n");

+		return (NULL);

+	}	

+

+	strcpy(bso->ssidStr, ssidStr);

+	bso->bssType = BCM_BSS_INFRA; /* init it to infrastructure bss */

+	bso->primary_key = BCM_PRI_KEY_BAD; /* init it to bad one */

+

+	bsotbl.addCnt++;

+	bsotbl.entries++;

+

+	return (bso);

+}

+

+void bcmWfaSsidObjTblDel(char *ssidStr)

+{

+	bcmSsidObj_t *bso;

+

+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblDel: ssidStr %s\n", ssidStr);

+

+	bso = bcmWfaSsidTblSsidFind(ssidStr);

+	if (bso == NULL) {

+		return;

+	}

+

+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblDel: deleting bso %p\n", bso);

+

+	bzero(bso, sizeof(bcmSsidObj_t));

+	bsotbl.delCnt++;

+	bsotbl.entries--;

+}

+

+void bcmWfaSsidObjPrint(bcmSsidObj_t *bso)

+{

+	int idx;

+	

+	if (bcmSsidIsGood(bso->ssidStr) == FALSE) {

+		fprintf(WFA_OUT, "bso %p is blank.\n", bso);

+		return;

+	}

+	

+	fprintf(WFA_OUT, "bso %p\n", bso);

+	fprintf(WFA_OUT, "\tssid %s", bso->ssidStr);

+	fprintf(WFA_OUT, "\tbssType %d\n", bso->bssType);

+	fprintf(WFA_OUT, "\tchannel %d\n", bso->channel);

+	fprintf(WFA_OUT, "\twsec %d\n", bso->wsec);

+	fprintf(WFA_OUT, "\tauth %d\n", bso->auth);

+	fprintf(WFA_OUT, "\twpa_auth %d\n", bso->wpa_auth);

+	fprintf(WFA_OUT, "\tpowerSave %d\n", bso->powerSave);

+	fprintf(WFA_OUT, "\tuapsd %d\n", bso->uapsd);

+	

+	for (idx = 0; idx < 4; idx++) {

+		fprintf(WFA_OUT, "\tkeys[%d] : %s\n", idx, bso->keys[idx]);

+	}

+	fprintf(WFA_OUT, "\tprimary_key %d\n", bso->primary_key);

+	fprintf(WFA_OUT, "\tpassphrase : %s\n", bso->passphrase);

+}

+

+void bcmWfaSsidObjTblPrint(void)

+{

+	int idx;

+

+	fprintf(WFA_OUT, "entries %d addCnt %d delCnt %d\n",

+		bsotbl.entries, bsotbl.addCnt, bsotbl.delCnt);

+	for (idx = 0; idx < BCM_SSID_MAX; idx++) {

+		bcmWfaSsidObjPrint(&bsotbl.ssidObj[idx]);

+	}

+}

+

+void bcmWfaInit(void)

+{

+	char cmdStr[WFA_CMD_STR_SZ];

+#ifdef BCMWFA_TEST

+	int idx;

+	char ssidStr[64];

+	bcmSsidObj_t *bso;

+#endif /* def BCMWFA_TEST */

+

+	bzero(&bsotbl, sizeof(bsotbl));

+	sprintf(cmdStr, "/tmp/ASD/wl down");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl ap 0"); /* not AP */

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl radio on"); /* not AP */

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl wsec 0");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl auth 0");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl wpa_auth 0");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl sup_wpa 1"); /* enable in-driver supplicant */

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+	sprintf(cmdStr, "/tmp/ASD/wl up");

+	system(cmdStr);

+	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

+

+#ifdef BCMWFA_TEST

+	bcmWfaSsidObjTblPrint();

+

+	fprintf(WFA_OUT, "add SSIDs\n");

+	for (idx = 0; idx < 2 * WFA_SSID_NAME_LEN; idx++) {

+		sprintf(ssidStr, "ssid_%d", idx);

+		fprintf(WFA_OUT, "adding %s\n", ssidStr);

+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {

+			fprintf(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidStr);

+		}

+	}

+	bcmWfaSsidObjTblPrint();

+

+	fprintf(WFA_OUT, "add SSIDs again\n");

+	for (idx = 0; idx < 2 * WFA_SSID_NAME_LEN; idx++) {

+		sprintf(ssidStr, "ssid_%d", idx);

+		fprintf(WFA_OUT, "ssid %s\n", ssidStr);

+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {

+			fprintf(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidStr);

+		}

+	}

+	bcmWfaSsidObjTblPrint();

+

+	fprintf(WFA_OUT, "delete SSIDs\n");

+	for (idx = 2 * WFA_SSID_NAME_LEN; idx >= 0; idx--) {

+		sprintf(ssidStr, "ssid_%d", idx);

+		bcmWfaSsidObjTblDel(ssidStr);

+	}

+	bcmWfaSsidObjTblPrint();

+

+	fprintf(WFA_OUT, "delete SSIDs again\n");

+	for (idx = 2 * WFA_SSID_NAME_LEN; idx >= 0; idx--) {

+		sprintf(ssidStr, "ssid_%d", idx);

+		bcmWfaSsidObjTblDel(ssidStr);

+	}

+	bcmWfaSsidObjTblPrint();

+#endif /* def BCMWFA_TEST */

+}

diff --git a/src/tools/Wifi_ASD_test/lib/wfa_ca_resp.c b/src/tools/Wifi_ASD_test/lib/wfa_ca_resp.c
new file mode 100644
index 0000000..cbaa987
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_ca_resp.c
@@ -0,0 +1,1506 @@
+

+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN

+ *.AN

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+/*

+ *       File: wfa_ca_resp.c

+ *       All functions are desginated to handle the command responses from

+ *       a DUT and inform TM the command status.

+ *       They will be called by Control Agent.

+ *

+ *       Revision History:

+ *        2006/03/10    -- initially created by qhu

+ *        2006/06/01    -- BETA release by qhu

+ *        2006/06/13    -- 00.02 release by qhu

+ *        2006/06/30    -- 00.10 Release by qhu

+ *        2006/07/10  -- 01.00 Release by qhu

+ *        2006/07/01  -- 01.05 Release by qhu

+ *        2006/10/26  -- 01.06 release by qhu

+ *        2007/01/11  -- 01.10 Released by qhu

+ *        2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi

+ *        2007/03/30  -- 02.40 WPA2 and Official WMM Beta release by qhu

+ *        2007/04/20  -- 02.40 WPA2 and Official WMM release by qhu

+ *        2007/08/15 --  02.10 WMM-Power Save release by qhu

+ *        2007/10/10 --  02.20 Voice SOHO beta -- qhu

+ *        2007/11/07 --  02.30 Voice HSO -- qhu

+ *

+ */

+

+ /* NOTE: The response for the commands are not sent using 

+  * wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr)) in case of RWL

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#ifndef WIN32

+#include <sys/socket.h>

+#endif

+#include "wfa_debug.h"

+#include "wfa_sock.h"

+#include "wfa_types.h"

+#include "wfa_tg.h"

+#include "wfa_main.h"

+#include "wfa_tlv.h"

+#include "wfa_miscs.h"

+#include "wfa_ca.h"

+#include "wfa_rsp.h"

+#include "wfa_ca_resp.h"

+

+

+extern unsigned short wfa_defined_debug;

+

+

+char gRespStr[WFA_BUFF_512];

+

+dutCommandRespFuncPtr wfaCmdRespProcFuncTbl[WFA_STA_RESPONSE_END - WFA_STA_COMMANDS_END] =

+{

+    caCmdNotDefinedYet,

+    wfaGetVersionResp,                   /* WFA_GET_VERSION_RESP_TLV - WFA_STA_COMMANDS_END                  (1) */

+    wfaTrafficAgentPingStartResp,        /* WFA_TRAFFIC_SEND_PING_RESP_TLV - WFA_STA_COMMANDS_END            (2) */

+    wfaTrafficAgentPingStopResp,         /* WFA_TRAFFIC_STOP_PING_RESP_TLV - WFA_STA_COMMANDS_END            (3) */

+    wfaTrafficAgentConfigResp,           /* WFA_TRAFFIC_AGENT_CONFIG_RESP_TLV - WFA_STA_COMMANDS_END         (4) */

+    wfaTrafficAgentSendResp,             /* WFA_TRAFFIC_AGENT_SEND_RESP_TLV - WFA_STA_COMMANDS_END           (5) */

+    wfaTrafficAgentRecvStartResp,        /* WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV - WFA_STA_COMMANDS_END     (6) */

+    wfaTrafficAgentRecvStopResp,         /* WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV - WFA_STA_COMMANDS_END      (7) */

+    wfaTrafficAgentResetResp,            /* WFA_TRAFFIC_AGENT_RESET_RESP_TLV - WFA_STA_COMMANDS_END          (8) */

+    caCmdNotDefinedYet,                  /* WFA_TRAFFIC_AGENT_STATUS_RESP_TLV - WFA_STA_COMMANDS_END         (9) */

+

+    wfaStaGetIpConfigResp,               /* WFA_STA_GET_IP_CONFIG_RESP_TLV - WFA_STA_COMMANDS_END           (10) */

+    wfaStaSetIpConfigResp,               /* WFA_STA_SET_IP_CONFIG_RESP_TLV - WFA_STA_COMMANDS_END           (11) */

+    wfaStaGetMacAddressResp,             /* WFA_STA_GET_MAC_ADDRESS_RESP_TLV - WFA_STA_COMMANDS_END         (12) */

+    caCmdNotDefinedYet,                  /* WFA_STA_SET_MAC_ADDRESS_RESP_TLV - WFA_STA_COMMANDS_END         (13) */

+    wfaStaIsConnectedResp,               /* WFA_STA_IS_CONNECTED_RESP_TLV - WFA_STA_COMMANDS_END            (14) */

+    wfaStaVerifyIpConnectResp,           /* WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV - WFA_STA_COMMANDS_END    (15) */

+    wfaStaGetBSSIDResp,                  /* WFA_STA_GET_BSSID_RESP_TLV - WFA_STA_COMMANDS_END               (16) */

+    wfaStaGetStatsResp,                  /* WFA_STA_GET_STATS_RESP_TLV - WFA_STA_COMMANDS_END               (17) */

+    wfaStaSetEncryptionResp,             /* WFA_STA_SET_ENCRYPTION_RESP_TLV - WFA_STA_COMMANDS_END          (18) */

+    wfaStaSetPSKResp,                    /* WFA_STA_SET_PSK_RESP_TLV - WFA_STA_COMMANDS_END                 (19) */

+    wfaStaSetEapTLSResp,                 /* WFA_STA_SET_EAPTLS_RESP_TLV - WFA_STA_COMMANDS_END              (20) */

+

+    /* Start: Modified as per BRCM 1.3 ASD */

+    wfaStaSetUAPSDResp,                  /* WFA_STA_SET_UAPSD_RESP_TLV - WFA_STA_COMMANDS_END               (21) */

+    /* End: Modified as per BRCM 1.3 ASD */

+

+

+    wfaStaAssociateResp,                 /* WFA_STA_ASSOCIATE_RESP_TLV - WFA_STA_COMMANDS_END               (22) */

+    wfaStaSetEapTLSResp,                 /* WFA_STA_SET_EAPTTLS_RESP_TLV - WFA_STA_COMMANDS_END             (23) */

+    wfaStaSetEapSIMResp,                 /* WFA_STA_SET_EAPSIM_RESP_TLV - WFA_STA_COMMANDS_END              (24) */

+    wfaStaSetEapPEAPResp,                /* WFA_STA_SET_PEAP_RESP_TLV - WFA_STA_COMMANDS_END                (25) */

+    wfaStaSetIBSSResp,                   /* WFA_STA_SET_IBSS_RESP_TLV - WFA_STA_COMMANDS_END                (26) */

+    wfaStaGetInfoResp,                   /* WFA_STA_GET_INFO_RESP_TLV - WFA_STA_COMMANDS_END                (27) */

+    wfaDeviceGetInfoResp,                /* WFA_DEVICE_GET_INFO_RESP_TLV - WFA_STA_COMMANDS_END             (28) */

+    wfaDeviceListIFResp,                 /* WFA_DEVICE_LIST_IF_RESP_TLV - WFA_STA_COMMANDS_END              (29) */

+    wfaStaDebugSetResp,                  /* WFA_STA_DEBUG_SET_RESP_TLV - WFA_STA_COMMANDS_END               (30) */

+    wfaStaSetModeResp,                   /* WFA_STA_SET_MODE_RESP_TLV - WFA_STA_COMMANDS_END                (31) */

+    wfaStaSetWMMResp,                    /* WFA_STA_SET_WMM_RESP_TLV - WFA_STA_COMMANDS_END                 (32) */

+    wfaStaSendNeigreqResp,               /* WFA_STA_SEND_NEIGREQ_RESP_TLV - WFA_STA_COMMANDS_END            (33) */

+    wfaStaSetSystimeResp,		 /* WFA_STA_SET_SYSTIME_TLV - WFA_STA_COMMANDS_END                  (34) */

+    wfaStaSet11nResp,			 /* WFA_STA_SET_11N_TLV - WFA_STA_COMMANDS_END			    (35) */

+    wfaStaSetRifsTestResp,		 /* WFA_STA_SET_RIFS_TEST_TLV - WFA_STA_COMMANDS_END		    (36) */

+    wfaStaSetWirelessResp,		 /* WFA_STA_SET_WIRELESS_TLV - WFA_STA_COMMANDS_END		    (37) */

+    wfaStaSendAddbaResp,		 /* WFA_STA_SEND_ADDBA_TLV - WFA_STA_COMMANDS_END		    (38) */

+    wfaStaSendCoexistMgmtResp,		 /* WFA_STA_SEND_COEXIST_MGMT_TLV - WFA_STA_COMMANDS_END            (39) */

+    wfaStaDisconnectResp,		 /* WFA_STA_SEND_DISCONNECT_TLV - WFA_STA_COMMANDS_END		    (40) */

+    wfaStaSetEapFASTResp,		 /* WFA_STA_SET_EAP_FAST_TLV - WFA_STA_COMMANDS_END	    	    (41) */

+    wfaStaSetEapAKAResp,		 /* WFA_STA_SET_EAP_AKA_TLV - WFA_STA_COMMANDS_END	    	    (42) */

+    wfaStaReassociateResp,                   /* WFA_STA_REASSOCIATE_RESP_TLV - WFA_STA_COMMANDS_END             (41) */

+    wfaStaSetPwrsaveResp,                   /* WFA_STA_SET_PWRSAVE_RESP_TLV - WFA_STA_CMMANDS_END              (42) */

+    wfaStaResetDefaultResp                   /* WFA_STA_RESET_DEFAULT_RESP_TLV - WFA_STA_COMMANDS_END           (43) */

+};

+

+extern int gSock, gCaSockfd, gxcSockfd;

+

+

+int caCmdNotDefinedYet(BYTE *cmdBuf)

+{

+    int done;

+

+    sprintf(gRespStr, "status,ERROR,Command Not Defined\r\n");

+    /* make sure if getting send error, will close the socket */

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    done = 0;

+    return done;

+}

+

+int wfaStaVerifyIpConnectResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *verifyResp = (dutCmdResponse_t *)(cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaVerifyIpConnectResp\n");

+    switch(verifyResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,connected,%i\r\n", verifyResp->cmdru.connected);

+        DPRINT_INFO(WFA_OUT, "%s", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        DPRINT_INFO(WFA_OUT, "%s", gRespStr);

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+	printf("%s\n",gRespStr);

+    return done;

+}

+

+

+int wfaStaSetIpConfigResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setIpConfigResp = (dutCmdResponse_t *)(cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetIpConfigResp ...\n");

+

+    switch(setIpConfigResp->status)

+    {

+       case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, "status,COMPLETE\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    return done;

+}

+

+int wfaStaIsConnectedResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *connectedResp = (dutCmdResponse_t *)(cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaIsConnectedResp ...\n");

+    switch(connectedResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,connected,%i\r\n", connectedResp->cmdru.connected);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        break;

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    return done;

+}

+

+int wfaStaGetIpConfigResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *getIpConfigResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaGetIpConfigResp ...\n");

+    switch(getIpConfigResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        break;

+

+        case STATUS_COMPLETE:

+        if(strlen(getIpConfigResp->cmdru.getIfconfig.dns[0]) == 0)

+                *getIpConfigResp->cmdru.getIfconfig.dns[0] = '\0';

+        if(strlen(getIpConfigResp->cmdru.getIfconfig.dns[1]) == 0)

+                *getIpConfigResp->cmdru.getIfconfig.dns[1] = '\0';

+

+        sprintf(gRespStr, "status,COMPLETE,dhcp,%i,ip,%s,mask,%s,primary-dns,%s,secondary-dns,%s\r\n", getIpConfigResp->cmdru.getIfconfig.isDhcp,

+                      getIpConfigResp->cmdru.getIfconfig.ipaddr,

+                      getIpConfigResp->cmdru.getIfconfig.mask,

+                      getIpConfigResp->cmdru.getIfconfig.dns[0],

+                      getIpConfigResp->cmdru.getIfconfig.dns[1]);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID,dhcp,NOTDEF,ip,NOTDEF,mask,NOTDEF,primary-dns,NOTDEF,secondary-dns,NOTDEF\r\n");

+    }

+    printf("%s\n",gRespStr);

+    return done;

+}

+

+int wfaGetVersionResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *getverResp =(dutCmdResponse_t *)(cmdBuf + 4);

+

+    switch(getverResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,version,%s\r\n", getverResp->cmdru.version);

+        break;

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    return done ;

+}

+

+int wfaStaGetInfoResp(BYTE *cmdBuf)

+{

+    dutCmdResponse_t *infoResp = (dutCmdResponse_t *)(cmdBuf + 4);

+    int done = 0;

+

+    switch(infoResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "sta Get info running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,%s\r\n", infoResp->cmdru.info);

+        DPRINT_INFO(WFA_OUT, "info: %s\n", infoResp->cmdru.info);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+	printf("%s\n",gRespStr);

+    return done;

+}

+

+int wfaStaGetTestDataResp(BYTE *cmdBuf)

+{

+    dutCmdResponse_t *dataResp = (dutCmdResponse_t *)(cmdBuf + 4);

+    int done = 0;

+

+    switch(dataResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "get test data running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    printf("%s\n",gRespStr);

+    return done;

+}

+

+int wfaTrafficAgentConfigResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *agtConfigResp = (dutCmdResponse_t *)(cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaTrafficAgentConfigResp ...\n");

+    switch(agtConfigResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,streamID,%i\r\n", agtConfigResp->streamId);

+        break;

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    return done;

+}

+

+int wfaTrafficAgentSendResp(BYTE *cmdBuf)

+{

+    /* Bug, fixed on 19th Dec 2007 */

+    int done=0,i;

+    char copyBuf[64];

+    int errorStatus = 0;

+	BYTE *dutRsp = cmdBuf+4;

+    BYTE *startRsp = dutRsp;

+    wfaTLV *ptlv = (wfaTLV *)cmdBuf;

+    int len = ptlv->len;

+    int numStreams = len/sizeof(dutCmdResponse_t);

+	dutCmdResponse_t statResp[WFA_MAX_TRAFFIC_STREAMS];

+

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaTrafficAgentSendResp ...%d\n", numStreams);

+

+	for(i=0; i<numStreams; i++)

+    {

+        dutRsp = startRsp + i * sizeof(dutCmdResponse_t);

+        memcpy(&statResp[i], dutRsp, sizeof(dutCmdResponse_t));

+    }

+    for(i=0; i<numStreams; i++)

+    {

+	   	if(statResp[i].status!= STATUS_COMPLETE)

+	        {

+	        

+	   		    errorStatus = 1;

+	        }

+    }

+

+    if(errorStatus)

+    {

+   	sprintf(gRespStr, "status,ERROR");

+    }

+    else

+    {

+   	sprintf(gRespStr, "status,COMPLETE,streamID,");

+   	for(i=0; i<numStreams; i++)

+        {

+            sprintf(copyBuf, " %i", statResp[i].streamId);

+     	    strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+   	}

+

+   	strncat(gRespStr, ",txFrames,", 10);

+   	for(i=0; i<numStreams; i++)

+        {

+   	    sprintf(copyBuf, "%i ", statResp[i].cmdru.stats.txFrames);

+   	    strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+   	}

+

+      	strncat(gRespStr, ",rxFrames,", 10);

+       	for(i=0; i<numStreams; i++)

+        {

+       	    sprintf(copyBuf, "%i ", statResp[i].cmdru.stats.rxFrames);

+       	    strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+       	}

+

+       	strncat(gRespStr, ",txPayloadBytes,", 16);

+       	for(i=0; i<numStreams; i++)

+        {

+       	    sprintf(copyBuf, "%i ", statResp[i].cmdru.stats.txPayloadBytes);

+       	    strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+

+        strncat(gRespStr, ",rxPayloadBytes,", 16);

+        for(i=0; i<numStreams; i++)

+        {

+       	    sprintf(copyBuf, "%i ", statResp[i].cmdru.stats.rxPayloadBytes);

+            strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+        strncat(gRespStr, ",outOfSequenceFrames,", 21);

+        for(i=0; i<numStreams; i++)

+        {

+       	    sprintf(copyBuf, "%i ", statResp[i].cmdru.stats.outOfSequenceFrames);

+	    strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+

+	printf("jitter %lu\n", statResp[i].cmdru.stats.jitter);

+        strncat(gRespStr, "\r\n", 4);

+    }

+    return done;

+}

+

+int wfaTrafficAgentRecvStartResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *recvStartResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaTrafficAgentRecvStartResp ...\n");

+    switch(recvStartResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "Send command is running\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+

+    return done;

+}

+

+int wfaTrafficAgentRecvStopResp(BYTE *cmdBuf)

+{

+    /* Bug, fixed on 19th Dec, 2007 */

+    int done=0;

+    int i = 0;

+    int errorStatus = 0;

+    char copyBuf[64];

+	

+    BYTE *dutRsp = cmdBuf+4;

+    BYTE *startRsp = dutRsp;

+    wfaTLV *ptlv = (wfaTLV *)cmdBuf;

+    int len = ptlv->len;

+    int numStreams = len/sizeof(dutCmdResponse_t);

+	dutCmdResponse_t statResp[WFA_MAX_TRAFFIC_STREAMS];

+    DPRINT_INFO(WFA_OUT, "Entering wfaTrafficAgentRecvStopResp ...\n");

+

+    

+    for(i=0; i<numStreams; i++)

+    {

+        dutRsp = startRsp + i * sizeof(dutCmdResponse_t);

+        memcpy(&statResp[i], dutRsp, sizeof(dutCmdResponse_t));

+    }

+    for(i=0; i<numStreams; i++)

+    {

+        if(statResp[i].status != STATUS_COMPLETE)

+            errorStatus = 1;

+    }

+    if(errorStatus)

+    {

+        sprintf(gRespStr, "status,ERROR");

+    }

+    else

+    {

+        sprintf(gRespStr, "status,COMPLETE,streamID,");

+        for(i=0; i<numStreams; i++)

+        {

+            sprintf(copyBuf, " %d", statResp[i].streamId);

+            strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+        strncat(gRespStr, ",txFrames,", 10);

+        for(i=0; i<numStreams; i++)

+        {

+            sprintf(copyBuf, " %d", statResp[i].cmdru.stats.txFrames);

+            strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+        strncat(gRespStr, ",rxFrames,", 10);

+        for(i=0; i<numStreams; i++)

+        {

+            sprintf(copyBuf, " %d", statResp[i].cmdru.stats.rxFrames);

+            strcat(gRespStr, copyBuf);

+        }

+	strncat(gRespStr, ",txPayloadBytes,", 16);

+	for(i=0; i<numStreams; i++)

+        {

+            sprintf(copyBuf, " %d", statResp[i].cmdru.stats.txPayloadBytes);

+            strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+        strncat(gRespStr, ",rxPayloadBytes,", 16);

+        for(i=0; i<numStreams; i++)

+        {

+            sprintf(copyBuf, " %d", statResp[i].cmdru.stats.rxPayloadBytes);

+            strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+        strncat(gRespStr, ",outOfSequenceFrames,", 21);

+        for(i=0; i<numStreams; i++)

+        {

+            sprintf(copyBuf, " %d", statResp[i].cmdru.stats.outOfSequenceFrames);

+            strncat(gRespStr, copyBuf, sizeof(copyBuf) - 1);

+        }

+        strncat(gRespStr, "\r\n", 4);

+    }

+    return done;

+}

+

+int wfaTrafficAgentResetResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *resetResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaTrafficAgentResetResp ...\n");

+    switch(resetResp->status)

+    {

+        case STATUS_RUNNING:

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+		     printf("Inform to stop\n");

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    return done;

+}

+

+int wfaTrafficAgentPingStartResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *staPingResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaTrafficAgentPingStartResp ...\n");

+

+    switch(staPingResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent ping start  running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,streamID,%i\r\n", staPingResp->streamId);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+    }

+    DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    return done;

+}

+

+int wfaTrafficAgentPingStopResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *stpResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(stpResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent ping stop running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        {

+            sprintf(gRespStr, "status,COMPLETE,sent,%d,replies,%d\r\n",

+                 stpResp->cmdru.pingStp.sendCnt,

+                 stpResp->cmdru.pingStp.repliedCnt);

+                 DPRINT_INFO(WFA_OUT, "%s\n", gRespStr);

+             break;

+        }

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    DPRINT_INFO(WFA_OUT, "%s\n", gRespStr);

+    return done;

+}

+

+int wfaStaGetMacAddressResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *getmacResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaGetMacAddressResp ...\n");

+    switch(getmacResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,mac,%s\r\n", getmacResp->cmdru.mac);

+        printf("status,COMPLETE,mac,%s\r\n", getmacResp->cmdru.mac);

+        break;

+

+        case STATUS_ERROR:

+        printf("status,ERROR\n");

+        sprintf(gRespStr, "status,COMPLETE,mac,00:00:00:00:00:00\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,COMPLETE,mac,00:00:00:00:00:00\r\n");

+        printf("unknown status\n");

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    printf("%s\n", gRespStr);

+    return done;

+}

+

+int wfaStaGetBSSIDResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *getBssidResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaGetBSSIDResp ...\n");

+    switch(getBssidResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,bssid,%s\r\n", getBssidResp->cmdru.bssid);

+        printf("status,COMPLETE,bssid,%s\r\n", getBssidResp->cmdru.bssid);

+        break;

+        case STATUS_ERROR:

+        printf("status,ERROR\n");

+        sprintf(gRespStr, "status,COMPLETE,mac,00:00:00:00:00:00\r\n");

+        break;

+        default:

+        sprintf(gRespStr, "status,COMPLETE,mac,00:00:00:00:00:00\r\n");

+        printf("unknown status\n");

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    printf("%s\n", gRespStr);

+    return done;

+}

+

+int wfaStaSetEncryptionResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *getBssidResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEncryptionResp ...\n");

+    switch(getBssidResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        printf("status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        printf("status,ERROR\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    return done;

+}

+

+int wfaStaSetEapTLSResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setEapTLSResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEapTLSResp ...\n");

+    switch(setEapTLSResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    return done;

+

+}

+

+int wfaStaSetPSKResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setPSKResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetPSKResp ...\n");

+    switch(setPSKResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    return done;

+}

+

+

+/* Start: Added as per BRCM 1.3 ASD */

+

+int wfaStaSetUAPSDResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setUAPSDResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetUAPSDResp ...\n");

+

+    switch(setUAPSDResp->status)

+    {

+		case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "STA set UAPSD running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+		default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, sizeof(gRespStr));

+    return done;

+}

+/* End: Added as per BRCM 1.3 ASD */

+

+

+

+int wfaStaSetEapTTLSResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setEapTTLSResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEapTTLSResp ...\n");

+    switch(setEapTTLSResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+   wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+   return done;

+}

+

+int wfaStaSetEapPEAPResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setEapPeapResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEapPEAPResp ...\n");

+    switch(setEapPeapResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    return done;

+}

+

+int wfaStaSetEapSIMResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setEapSIMResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEapSIMResp ...\n");

+    switch(setEapSIMResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    return done;

+}

+

+int wfaStaAssociateResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *assocResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaAssociateResp ...\n");

+    switch(assocResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+	sprintf(gRespStr, "status,ERROR\r\n");

+	DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+	break;

+

+	default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetIBSSResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setIBSSResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetIBSSResp ...\n");

+    switch(setIBSSResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+    return done;

+}

+

+int wfaStaGetStatsResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *getStatsResp = (dutCmdResponse_t *) (cmdBuf + 4);

+    caStaGetStatsResp_t *stats = &getStatsResp->cmdru.ifStats;

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaGetStatsResp ...\n");

+

+    switch(getStatsResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE,txFrames,%i,rxFrames,%i,txMulticast,%i,rxMulticast,%i,fcsErrors,%i,txRetries,%i\r\n",

+           stats->txFrames, stats->rxFrames, stats->txMulticast, stats->rxMulticast, stats->fcsErrors, stats->txRetries);

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaDeviceGetInfoResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *devInfoResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+	

+

+    caDeviceGetInfoResp_t *dinfo = &devInfoResp->cmdru.devInfo;

+

+    switch(devInfoResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        if(dinfo->firmware[0] != '\0' || dinfo->firmware[0] != '\n')

+            sprintf(gRespStr, "status,COMPLETE,firmware,%s\r\n", dinfo->firmware);

+        else

+            sprintf(gRespStr, "status,COMPLETE,vendor,%s,model,%s,version,%s\r\n",

+                dinfo->vendor, dinfo->model, dinfo->version);

+

+        DPRINT_INFO(WFA_OUT, "%s\n", gRespStr);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaDeviceListIFResp(BYTE *cmdBuf)

+{

+    int done=0, i;

+    dutCmdResponse_t *devListIfResp = (dutCmdResponse_t *) (cmdBuf + 4);

+    caDeviceListIFResp_t *ifResp = &devListIfResp->cmdru.ifList;

+

+    switch(devListIfResp->status)

+    {

+       case STATUS_RUNNING:

+       DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+       done = 1;

+       break;

+

+       case STATUS_COMPLETE:

+       if(ifResp->iftype == IF_80211)

+       {

+          sprintf(gRespStr, "status,COMPLETE,interfaceType,802.11,interfaceID");

+          DPRINT_INFO(WFA_OUT, "%s\n", gRespStr);

+          DPRINT_INFO(WFA_OUT, "%s\n", ifResp->ifs[0]);

+       }

+       else if(ifResp->iftype == IF_ETH)

+          sprintf(gRespStr, "status,COMPLETE,interfaceType,Ethernet,interfaceID");

+

+       for(i=0; i<1; i++)

+       {

+         if(ifResp->ifs[i][0] != '\0')

+         {

+            strncat(gRespStr,",", 4);

+            strncat(gRespStr, ifResp->ifs[i], sizeof(ifResp->ifs[i]));

+            strncat(gRespStr, "\r\n", 4);

+         }

+       }

+

+       DPRINT_INFO(WFA_OUT, "%s\n", gRespStr);

+       break;

+

+       default:

+       sprintf(gRespStr, "status,INVALID\r\n");

+       DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+     return done;

+}

+

+int wfaStaDebugSetResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *debugResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaDebugSetResp ...\n");

+    switch(debugResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetModeResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *getBssidResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetModeResp ...\n");

+    switch(getBssidResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        printf("status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        printf("status,ERROR\r\n");

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+   }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+   return done;

+}

+

+int wfaStaSetWMMResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *setwmmResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(setwmmResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "wfaStaSetWMM running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        sprintf(gRespStr, "status,COMPLETE\r\n");

+        printf("status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        case STATUS_ERROR:

+        sprintf(gRespStr, "status,ERROR\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        default:

+        sprintf(gRespStr, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+   }

+   wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+   return done;

+}

+

+int wfaStaSendNeigreqResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *neigreqResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaDebugSetResp ...\n");

+    switch(neigreqResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+       S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetSystimeResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *systimeResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(systimeResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSet11nResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *set11nResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(set11nResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetRifsTestResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *testResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(testResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetWirelessResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *wirelessResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(wirelessResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSendAddbaResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *addbaResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(addbaResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSendCoexistMgmtResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *mgmtResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(mgmtResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaDisconnectResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *DisconnectResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    switch(DisconnectResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetEapFASTResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *eapfastResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaEapFASTSetResp ...\n");

+    switch(eapfastResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetEapAKAResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *eapakaResp = (dutCmdResponse_t *) (cmdBuf + 4);

+

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaEapAKASetResp ...\n");

+    switch(eapakaResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaReassociateResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *reassocResp = (dutCmdResponse_t *) (cmdBuf + 4);

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaReassociateResp ...\n");

+    switch(reassocResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+    

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaSetPwrsaveResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *pwrsaveResp = (dutCmdResponse_t *) (cmdBuf + 4);

+    

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaSetPwrsaveResp ...\n");

+    switch(pwrsaveResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

+int wfaStaResetDefaultResp(BYTE *cmdBuf)

+{

+    int done=0;

+    dutCmdResponse_t *resetResp = (dutCmdResponse_t *) (cmdBuf + 4);

+    DPRINT_INFO(WFA_OUT, "Entering wfaStaResetDefaultResp ...\n");

+    switch(resetResp->status)

+    {

+        case STATUS_RUNNING:

+        DPRINT_INFO(WFA_OUT, "traffic agent config running ...\n");

+        done = 1;

+        break;

+

+        case STATUS_COMPLETE:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,COMPLETE\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+        break;

+        

+        default:

+        S_N_PRINTF(gRespStr, WFA_BUFF_512, "status,INVALID\r\n");

+        DPRINT_INFO(WFA_OUT, " %s\n", gRespStr);

+    }

+    wfaCtrlSend(gCaSockfd, (BYTE *)gRespStr, strlen(gRespStr));

+

+    return done;

+}

+

diff --git a/src/tools/Wifi_ASD_test/lib/wfa_cmdproc.c b/src/tools/Wifi_ASD_test/lib/wfa_cmdproc.c
new file mode 100644
index 0000000..e5315a9
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_cmdproc.c
@@ -0,0 +1,3036 @@
+
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN
+ *.AN
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+/*
+ *      File: wfa_cmdproc.c
+ *      Library functions to handle all string command parsing and convert it
+ *      to an internal format for DUT. They should be called by Control Agent
+ *      and Test console while receiving commands from CLI or TM
+ *
+ *      Revision History:
+ *        2006/03/10  -- initially created by qhu
+ *        2006/06/01    -- BETA release by qhu
+ *        2006/06/13    -- 00.02 release by qhu
+ *        2006/06/30    -- 00.10 Release by qhu
+ *        2006/07/10  -- 01.00 Release by qhu
+ *        2006/08/30  -- add some print statements by Isaac in Epson.
+ *        2006/09/01  -- 01.05 release by qhu
+ *        2006/10/26    -- 01.06 release by qhu
+ *        2006/12/02    -- bug fix reported by p.schwan
+ *        2007/01/11    -- 01.10 release by qhu
+ *        2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi
+ *        2007/03/30  -- 01.40 WPA2 and Official WMM Beta Release by qhu
+ *        2007/04/20  -- 02.00 WPA2 and Official WMM Release by qhu
+ *        2007/08/15 --  02.10 WMM-Power Save release by qhu
+ *        2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *        2007/11/07 --  02.30 Voice HSO -- qhu
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#endif
+#include "wfa_debug.h"
+#include "wfa_types.h"
+#include "wfa_tlv.h"
+#include "wfa_tg.h"
+#include "wfa_ca.h"
+#include "wfa_cmds.h"
+#include "wfa_miscs.h"
+#include "wfa_agtctrl.h"
+
+extern int gSock;
+extern void printProfile(tgProfile_t *);
+extern unsigned short wfa_defined_debug;
+
+/* command KEY WORD String table */
+typeNameStr_t keywordStr[] =
+{
+    { KW_PROFILE,      "profile",       NULL},
+    { KW_DIRECTION,    "direction",     NULL},
+    { KW_DIPADDR,      "destination",       NULL},
+    { KW_DPORT,        "destinationport",         NULL},
+    { KW_SIPADDR,      "source",       NULL},
+    { KW_SPORT,        "sourceport",         NULL},
+    { KW_FRATE,        "framerate",     NULL},
+    { KW_DURATION,     "duration",      NULL},
+    { KW_PLOAD,        "payloadsize",   NULL},
+    { KW_TCLASS,       "trafficClass",  NULL},    /* It is to indicate WMM traffic pattern */
+    { KW_STREAMID,     "streamid",      NULL},
+    { KW_STARTDELAY,   "startdelay",    NULL},     /* It is used to schedule multi-stream test such as WMM */
+    { KW_NUMFRAME,     "numframes",     NULL},
+    { KW_USESYNCCLOCK, "useSyncClock",  NULL},
+    { KW_USERPRIORITY, "userpriority",  NULL}
+};
+
+/* profile type string table */
+typeNameStr_t profileStr[] =
+{
+    { PROF_FILE_TX, "file_transfer", NULL},
+    { PROF_MCAST,   "multicast",     NULL},
+    { PROF_IPTV,    "iptv",          NULL},       /* This is used for WMM, confused? */
+    { PROF_TRANSC,  "transaction",   NULL},
+    { PROF_START_SYNC,    "start_sync",    NULL},
+    { PROF_CALI_RTD,    "cali_rtd",  NULL},
+    { PROF_UAPSD,  "uapsd",   NULL},
+    { PROF_FILE_TX_TCP, "file_transfer_tcp", NULL},
+    { PROF_TRANSC_TCP, "transaction_tcp", NULL}
+};
+
+/* direction string table */
+typeNameStr_t direcStr[] =
+{
+    { DIRECT_SEND,  "send",          NULL},
+    { DIRECT_RECV,  "receive",       NULL}
+};
+
+/*
+ * cmdProcNotDefinedYet(): a dummy function
+ */
+int cmdProcNotDefinedYet(char *pcmdStr, char *buf, int len)
+{
+    DPRINT_INFO(WFA_OUT,"The command processing function not defined.\n");
+
+    /* need to send back a response */
+
+    return (TRUE);
+}
+
+extern unsigned short wfa_defined_debug;
+
+/*
+ *  xcCmdProcGetVersion(): process the command get_version string from TM
+ *                         to convert it into a internal format
+ *  input:        pcmdStr -- a string pointer to the command string
+ */
+int xcCmdProcGetVersion(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    DPRINT_INFO(WFA_OUT, "start xcCmdProcGetVersion ...\n");
+
+    if(aBuf == NULL)
+      return FALSE;
+
+    /* encode the tag without values */
+    wfaEncodeTLV(WFA_GET_VERSION_TLV, 0, NULL, aBuf);
+
+    *aLen = 4;
+
+    return TRUE;
+}
+
+/*
+ *  xcCmdProcAgentConfig(): process the command traffic_agent_config string
+ *                          from TM to convert it into a internal format
+ *  input:        pcmdStr -- a string pointer to the command string
+ */
+int xcCmdProcAgentConfig(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    char *str;
+    int i = 0, j=0, kwcnt = 0;
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+    tgProfile_t tgpf;
+    tgProfile_t *pf = &tgpf;
+    int userPrio = 0;
+
+    DPRINT_INFO(WFA_OUT, "start xcCmdProcAgentConfig ...\n");
+    DPRINT_INFO(WFA_OUT, "params:  %s\n", pcmdStr);
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    while((str = strtok_r(NULL, ",", (char **)&pcmdStr)) != NULL)
+    {
+       DPRINT_INFO(WFA_OUT,"key word %s\n", str);
+       for(i = 0; i<sizeof(keywordStr); i++)
+       {
+          if(strcasecmp(str, keywordStr[i].name) == 0)
+          {
+              switch(keywordStr[i].type)
+              {
+              case  KW_PROFILE:
+              str = strtok_r(NULL, ",", (char **)&pcmdStr);
+              if(isString(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect profile keyword format\n");
+                 return FALSE;
+              }
+
+              for(j = 0; j < PROF_LAST; j++)
+                 if(strcasecmp(str, profileStr[j].name) == 0)
+                 {
+                     pf->profile = profileStr[j].type;
+                 }
+
+              DPRINT_INFO(WFA_OUT, "profile type %i\n", pf->profile);
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_DIRECTION:
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isString(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect direction keyword format\n");
+                 return FALSE;
+              }
+
+              if(strcasecmp(str, "send") == 0)
+              {
+                  pf->direction = DIRECT_SEND;
+              }
+              else if(strcasecmp(str, "receive") == 0)
+              {
+                  pf->direction = DIRECT_RECV;
+              }
+              else
+                  DPRINT_INFO(WFA_OUT,"Don't know direction\n");
+
+              DPRINT_INFO(WFA_OUT, "direction %i\n", pf->direction);
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_DIPADDR: /* dest ip address */
+              memcpy(pf->dipaddr, strtok_r(NULL, ",", &pcmdStr), IPV4_ADDRESS_STRING_LEN);
+              if(isIpV4Addr(pf->dipaddr) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect ipaddr format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "dipaddr %s\n", pf->dipaddr);
+
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_DPORT:
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect port number format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "dport %s\n", str);
+              pf->dport = atoi(str);
+
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_SIPADDR:
+              memcpy(pf->sipaddr, strtok_r(NULL, ",", &pcmdStr), IPV4_ADDRESS_STRING_LEN);
+
+              if(isIpV4Addr(pf->sipaddr) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect ipaddr format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "sipaddr %s\n", pf->sipaddr);
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_SPORT:
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect port number format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "sport %s\n", str);
+              pf->sport = atoi(str);
+
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_FRATE:
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect frame rate format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "framerate %s\n", str);
+              pf->rate = atoi(str);
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_DURATION:
+              str = strtok_r(NULL, ",", &pcmdStr);
+		if (strlen(str)) {
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect duration format\n");
+                 	return FALSE;
+              	}
+	      }
+		else
+		{
+			DPRINT_ERR(WFA_ERR, "No duration specified\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "duration %s\n", str);
+              pf->duration = atoi(str);
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_PLOAD:
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect payload format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "payload %s\n", str);
+              pf->pksize = atoi(str);
+              kwcnt++;
+              str = NULL;
+              break;
+
+	      case KW_STARTDELAY:
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect startDelay format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "startDelay %s\n", str);
+              pf->startdelay = atoi(str);
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_TCLASS:
+              str = strtok_r(NULL, ",", &pcmdStr);
+
+              /* if user priority is used, tclass is ignored. */
+              if(userPrio == 1)
+	          break;
+
+              if(strcasecmp(str, "voice") == 0)
+              {
+                 pf->trafficClass = TG_WMM_AC_VO;
+              }
+              else if(strcasecmp(str, "Video") == 0)
+              {
+                 pf->trafficClass = TG_WMM_AC_VI;
+              }
+              else if(strcasecmp(str, "Background") == 0)
+              {
+                 pf->trafficClass = TG_WMM_AC_BK;
+              }
+              else if(strcasecmp(str, "BestEffort") == 0)
+              {
+                 pf->trafficClass = TG_WMM_AC_BE;
+              }
+              else
+              {
+                 pf->trafficClass = TG_WMM_AC_BE;
+              }
+              
+              kwcnt++;
+              str = NULL;
+              break;
+
+	      case KW_USERPRIORITY:
+              str = strtok_r(NULL, ",", &pcmdStr);  
+
+              if( strcasecmp(str, "6") == 0 )
+              {
+                 pf->trafficClass = TG_WMM_AC_UP6; 
+              }
+              else if( strcasecmp(str, "7") == 0 )
+              {
+                 pf->trafficClass = TG_WMM_AC_UP7; 
+              }
+              else if( strcasecmp(str, "5") == 0 )
+              {
+                 pf->trafficClass = TG_WMM_AC_UP5; 
+              } 
+              else if( strcasecmp(str, "4") == 0 )
+              {
+                 pf->trafficClass = TG_WMM_AC_UP4; 
+              } 
+              else if( strcasecmp(str, "1") == 0 )
+              {
+                 pf->trafficClass = TG_WMM_AC_UP1; 
+              } 
+              else if( strcasecmp(str, "2") == 0 )
+              {
+                 pf->trafficClass = TG_WMM_AC_UP2; 
+              } 
+              else if( strcasecmp(str, "0") == 0 )
+              {
+                 pf->trafficClass = TG_WMM_AC_UP0; 
+              }
+              else if( strcasecmp(str, "3") == 0)
+              {
+                 pf->trafficClass = TG_WMM_AC_UP3; 
+              }
+
+              /* if User Priority is used */
+              userPrio = 1;
+
+              kwcnt++;
+              str = NULL;
+              break;
+
+              case KW_STREAMID:
+              kwcnt++;
+              break;
+
+	      case KW_NUMFRAME:
+	      DPRINT_INFO(WFA_OUT,"Number of Frame\n");
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect numframe format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "num frame %s\n", str);
+              DPRINT_INFO(WFA_OUT,"num frame %s\n", str);
+              kwcnt++;
+              str = NULL;
+	      break;
+
+	      case KW_USESYNCCLOCK:
+              str = strtok_r(NULL, ",", &pcmdStr);
+              if(isNumber(str) == FALSE)
+              {
+                 DPRINT_ERR(WFA_ERR, "Incorrect sync clock format\n");
+                 return FALSE;
+              }
+              DPRINT_INFO(WFA_OUT, "sync clock %s\n", str);
+              DPRINT_INFO(WFA_OUT,"sync clock %s\n", str);
+              kwcnt++;
+              str = NULL;
+	      break;
+
+              default:
+                ;
+              } /* switch */
+
+              if(str==NULL)
+                  break;
+           } 
+           
+       } /* for */
+    } /* while */
+
+
+    printProfile(pf);
+    hdr->tag =  WFA_TRAFFIC_AGENT_CONFIG_TLV;
+    hdr->len = sizeof(tgProfile_t);
+
+    memcpy(aBuf+4, pf, sizeof(tgpf));
+
+    *aLen = 4+sizeof(tgProfile_t);
+
+    return TRUE;
+}
+
+/*
+ * xcCmdProcAgentSend(): Process and send the Control command
+ *                       "traffic_agent_send"
+ * input - pcmdStr  parameter string pointer
+ * return - TRUE or FALSE;
+ */
+int xcCmdProcAgentSend(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+    char *str, *sid;
+    int strid;
+    int id_cnt = 0;
+
+    if(aBuf == NULL)
+      return FALSE;
+
+    memset(aBuf, 0, 512);
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcAgentSend ...\n");
+    /* there is only one stream for baseline. Will support
+     * multiple streams later.
+     */
+    str = strtok_r(NULL, ",", &pcmdStr);
+
+    if(str == NULL || str[0] == '\0')
+       return FALSE;
+
+    /* take the stream ids */
+    if(strcasecmp(str, "streamid") != 0)
+    {
+       DPRINT_ERR(WFA_ERR, "invalid type name\n");
+       return FALSE;
+    }
+
+    /*
+     * To handle there are multiple stream ids such as WMM
+     */
+    while(1)
+    {
+        sid = strtok_r (NULL, " ", &pcmdStr);
+        if(sid == NULL)
+           break;
+
+        if(isNumber(sid) == FALSE)
+           continue;
+
+        strid = atoi(sid);
+        DPRINT_INFO(WFA_OUT,"id %i\n", strid);
+        id_cnt++;
+
+        memcpy(aBuf+4*id_cnt, (char *)&strid, 4);
+    }
+
+    hdr->tag =  WFA_TRAFFIC_AGENT_SEND_TLV;
+    hdr->len = 4*id_cnt;  /* multiple 4s if more streams */
+
+    *aLen = 4 + 4*id_cnt;
+
+#ifdef DEBUG
+     {
+              int i;
+              for(i = 0; i< *aLen; i++)
+                 DPRINT_INFO(WFA_OUT,"%x ", aBuf[i]);
+
+              DPRINT_INFO(WFA_OUT,"\n");
+     }
+#endif
+
+
+    return TRUE;
+}
+
+/*
+ * xcCmdProcAgentReset(): Process and send the Control command
+ *                       "traffic_agent_reset"
+ * input - pcmdStr  parameter string pointer
+ * return - TRUE or FALSE;
+ */
+int xcCmdProcAgentReset(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcAgentReset ...\n");
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    hdr->tag =  WFA_TRAFFIC_AGENT_RESET_TLV;
+    hdr->len = 0;  /* multiple 4s if more streams */
+
+    *aLen = 4;
+
+    return TRUE;
+}
+
+/*
+ * xcCmdProcAgentRecvStart(): Process and send the Control command
+ *                       "traffic_agent_receive_start"
+ * input - pcmdStr  parameter string pointer
+ * return - TRUE or FALSE;
+ */
+int xcCmdProcAgentRecvStart(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+    char *str, *sid;
+    int strid;
+    int id_cnt = 0;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcAgentRecvStart ...%s\n", pcmdStr);
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    /* there is only one stream for baseline. Will support
+     * multiple streams later.
+     */
+    str = strtok_r(NULL, ",", &pcmdStr);
+
+    if(str == NULL || str[0] == '\0')
+    {
+       DPRINT_ERR(WFA_ERR, "Null string\n");
+       return FALSE;
+    }
+
+
+    if(strcasecmp(str, "streamid") != 0)
+    {
+       DPRINT_ERR(WFA_ERR, "invalid type name\n");
+       return FALSE;
+    }
+
+    while(1)
+    {
+        sid = strtok_r (NULL, " ", &pcmdStr);
+        if(sid == NULL)
+           break;
+
+        if(isNumber(sid) == FALSE)
+           continue;
+
+        strid = atoi(sid);
+        id_cnt++;
+
+        memcpy(aBuf+4*id_cnt, (char *)&strid, 4);
+    }
+
+    hdr->tag =  WFA_TRAFFIC_AGENT_RECV_START_TLV;
+    hdr->len = 4*id_cnt;  /* multiple 4s if more streams */
+
+    *aLen = 4 + 4*id_cnt;
+
+#ifdef DEBUG
+     {
+              int i;
+              for(i = 0; i< *aLen; i++)
+                 DPRINT_INFO(WFA_OUT,"%x ", aBuf[i]);
+
+              DPRINT_INFO(WFA_OUT,"\n");
+     }
+#endif
+    return TRUE;
+}
+
+/*
+ * xcCmdProcAgentRecvStop(): Process and send the Control command
+ *                       "traffic_agent_receive_stop"
+ * input - pcmdStr  parameter string pointer
+ * return - TRUE or FALSE;
+ */
+int xcCmdProcAgentRecvStop(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+    char *str, *sid;
+    int strid;
+    int id_cnt = 0;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcAgentRecvStop ...\n");
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    /* there is only one stream for baseline. Will support
+     * multiple streams later.
+     */
+    str = strtok_r(NULL, ",", &pcmdStr);
+
+    if(str == NULL || str[0] == '\0')
+       return FALSE;
+
+    if(strcasecmp(str, "streamid") != 0)
+    {
+       DPRINT_ERR(WFA_ERR, "invalid type name\n");
+       return FALSE;
+    }
+    while(1)
+    {
+        sid = strtok_r (NULL, " ", &pcmdStr);
+        if(sid == NULL)
+           break;
+        if(isNumber(sid) == FALSE)
+           continue;
+
+        strid = atoi(sid);
+        id_cnt++;
+
+        memcpy(aBuf+4*id_cnt, (char *)&strid, 4);
+    }
+
+    hdr->tag =  WFA_TRAFFIC_AGENT_RECV_STOP_TLV;
+    hdr->len = 4*id_cnt;  /* multiple 4s if more streams */
+
+    *aLen = 4 + 4*id_cnt;
+
+    return TRUE;
+}
+
+int xcCmdProcAgentSendPing(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+    tgPingStart_t *staping = (tgPingStart_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    staping->type = 0;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "destination") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(staping->dipaddr, str, 15);
+            DPRINT_INFO(WFA_OUT, "destination %s\n", staping->dipaddr);
+        }
+        if(strcasecmp(str, "frameSize") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            staping->frameSize=atoi(str);
+            DPRINT_INFO(WFA_OUT, "framesize %i\n", staping->frameSize);
+        }
+        if(strcasecmp(str, "frameRate") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            staping->frameRate=atoi(str);
+            DPRINT_INFO(WFA_OUT, "framerate %i\n", staping->frameRate);
+        }
+        if(strcasecmp(str, "duration") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            staping->duration=atoi(str);
+            DPRINT_INFO(WFA_OUT, "duration %i\n", staping->duration);
+        }
+        if(strcasecmp(str, "type") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            if(strcasecmp(str, "udp") == 0)
+                staping->type = 1;
+            else
+                staping->type = 0;
+        }
+    }
+
+    hdr->tag =  WFA_TRAFFIC_SEND_PING_TLV;
+    hdr->len = sizeof(tgPingStart_t);
+
+    *aLen = hdr->len + 4;
+
+    return TRUE;
+}
+
+int xcCmdProcAgentStopPing(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+    char *str;
+    int strid;
+    str = strtok_r(NULL, ",", &pcmdStr);
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    if(str == NULL || str[0] == '\0')
+       return FALSE;
+
+    if(strcasecmp(str, "streamid") == 0)
+       str = strtok_r(NULL, ",", &pcmdStr);
+    else
+    {
+       DPRINT_ERR(WFA_ERR, "invalid type name\n");
+       return FALSE;
+    }
+
+    if(isNumber(str) == FALSE)
+      return FALSE;
+
+    strid = atoi(str);
+
+    memcpy(aBuf+4, (char *)&strid, 4);
+
+    hdr->tag =  WFA_TRAFFIC_STOP_PING_TLV;
+    hdr->len = 4;  /* multiple 4s if more streams */
+
+    *aLen = 8;
+
+    return TRUE;
+}
+
+int xcCmdProcStaGetIpConfig(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    int slen;
+    char *str = NULL;
+    dutCommand_t getipconf;
+    memset(&getipconf, 0, sizeof(dutCommand_t));
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcStaGetIpConfig ...\n");
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    str = strtok_r(NULL, ",", &pcmdStr);
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL)
+        return FALSE;
+
+
+    slen = strlen(str);
+    memcpy(getipconf.intf, str, slen);
+    wfaEncodeTLV(WFA_STA_GET_IP_CONFIG_TLV, sizeof(dutCommand_t), (BYTE *)&getipconf, aBuf);
+
+    *aLen = 4+sizeof(getipconf);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetIpConfig(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t staSetIpConfig;
+    char *str;
+    caStaSetIpConfig_t *setip; 
+    memset(&staSetIpConfig, 0, sizeof(staSetIpConfig)); 
+    setip = (caStaSetIpConfig_t *)&staSetIpConfig.cmdsu.ipconfig;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setip->intf, str, 15);
+            DPRINT_INFO(WFA_OUT, "interface %s\n", setip->intf);
+        }
+        else if(strcasecmp(str, "dhcp") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setip->isDhcp = atoi(str);
+            DPRINT_INFO(WFA_OUT, "dhcp %i\n", setip->isDhcp);
+        }
+        else if(strcasecmp(str, "ip") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setip->ipaddr, str, 15);
+            DPRINT_INFO(WFA_OUT, "ip %s\n", setip->ipaddr);
+        }
+        else if(strcasecmp(str, "mask") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setip->mask, str, 15);
+            DPRINT_INFO(WFA_OUT, "mask %s\n", setip->mask);
+        }
+        else if(strcasecmp(str, "defaultGateway") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setip->defGateway, str, 15);
+            DPRINT_INFO(WFA_OUT, "gw %s\n", setip->defGateway);
+        }
+        else if(strcasecmp(str, "primary-dns") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setip->pri_dns, str, 15);
+            DPRINT_INFO(WFA_OUT, "dns p %s\n", setip->pri_dns);
+        }
+        else if(strcasecmp(str, "secondary-dns") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setip->sec_dns, str, 15);
+            DPRINT_INFO(WFA_OUT, "dns s %s\n", setip->sec_dns);
+        }
+        else
+        {
+            DPRINT_ERR(WFA_ERR, "invalid command\n");
+            return FALSE;
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_IP_CONFIG_TLV, sizeof(staSetIpConfig), (BYTE *)&staSetIpConfig, aBuf);
+
+    *aLen = 4+sizeof(staSetIpConfig);
+
+    return TRUE;
+}
+
+int xcCmdProcStaGetMacAddress(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    int slen;
+    char *str = NULL;
+    dutCommand_t getmac;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcStaGetMacAddress ...\n");
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    memset(&getmac, 0, sizeof(getmac));
+    str = strtok_r(NULL, ",", &pcmdStr);
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL)
+        return FALSE;
+
+    slen = strlen(str);
+    memcpy(getmac.intf, str, slen);
+    wfaEncodeTLV(WFA_STA_GET_MAC_ADDRESS_TLV, sizeof(getmac), (BYTE *)&getmac, aBuf);
+
+    *aLen = 4+sizeof(getmac);
+
+    return TRUE;
+}
+
+
+int xcCmdProcStaIsConnected(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    int slen;
+    char *str = NULL;
+    dutCommand_t isconnected;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcStaIsConnected\n");
+
+    memset(&isconnected, 0, sizeof(isconnected));
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    str = strtok_r(NULL, ",", &pcmdStr);
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL)
+        return FALSE;
+
+    slen = strlen(str);
+    memcpy(isconnected.intf, str, slen);
+    wfaEncodeTLV(WFA_STA_IS_CONNECTED_TLV, sizeof(isconnected), (BYTE *)&isconnected, aBuf);
+
+    *aLen = 4+sizeof(isconnected);
+
+    return TRUE;
+}
+
+int xcCmdProcStaVerifyIpConnection(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+    dutCommand_t *verifyip = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcStaVerifyIpConnection ...\n");
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(verifyip->intf, str);
+            verifyip->intf[15]='\0';
+            DPRINT_INFO(WFA_OUT, "interface %s %i\n", verifyip->intf, strlen(verifyip->intf));
+        }
+        else if(strcasecmp(str, "destination") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(verifyip->cmdsu.verifyIp.dipaddr, str, 15);
+            DPRINT_INFO(WFA_OUT, "ip %s\n", verifyip->cmdsu.verifyIp.dipaddr);
+        }
+        else if(strcasecmp(str, "timeout") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            verifyip->cmdsu.verifyIp.timeout = atoi(str);
+            DPRINT_INFO(WFA_OUT, "timeout %i\n", verifyip->cmdsu.verifyIp.timeout);
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_TLV, sizeof(verifyip), (BYTE *)&verifyip, aBuf);
+
+    hdr->tag =  WFA_STA_VERIFY_IP_CONNECTION_TLV;
+    hdr->len = sizeof(dutCommand_t);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaGetBSSID(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    int slen;
+    char *str = NULL;
+    dutCommand_t getbssid;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcStaGetBSSID ...\n");
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    memset(&getbssid, 0, sizeof(getbssid));
+    str = strtok_r(NULL, ",", &pcmdStr);
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL)
+        return FALSE;
+
+    slen = strlen(str);
+    memcpy(getbssid.intf, str, slen-1);
+    getbssid.intf[slen-1] = '\0';
+    wfaEncodeTLV(WFA_STA_GET_BSSID_TLV, sizeof(getbssid), (BYTE *)&getbssid, aBuf);
+
+    *aLen = 4+sizeof(getbssid);
+
+    return TRUE;
+}
+
+
+int xcCmdProcStaGetStats(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    int slen;
+    char *str = NULL;
+    dutCommand_t getstats;
+
+    DPRINT_INFO(WFA_OUT, "Entering xcCmdProcStaGetStats ...\n");
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    memset(&getstats, 0, sizeof(getstats));
+    str = strtok_r(NULL, ",", &pcmdStr);
+    /* need to check if the parameter name is called interface */
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL)
+        return FALSE;
+
+    slen = strlen(str);
+    memcpy(getstats.intf, str, slen-1);
+    getstats.intf[slen-1] = '\0';
+    wfaEncodeTLV(WFA_STA_GET_STATS_TLV, sizeof(getstats), (BYTE *)&getstats, aBuf);
+
+    *aLen = 4+sizeof(getstats);
+
+    return TRUE;
+}
+
+
+int  xcCmdProcStaSetEncryption(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetEncryption_t *setencryp = (caStaSetEncryption_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setencryp->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setencryp->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            if(strcasecmp(str, "wep") == 0)
+               setencryp->encpType = ENCRYPT_WEP;
+            else
+               setencryp->encpType = 0;
+        }
+        else if(strcasecmp(str, "key1") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setencryp->keys[0], str, 26);
+            DPRINT_INFO(WFA_OUT, "%s\n", setencryp->keys[0]);
+            setencryp->activeKeyIdx = 0;
+        }
+        else if(strcasecmp(str, "key2") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setencryp->keys[1], str, 26);
+            DPRINT_INFO(WFA_OUT, "%s\n", setencryp->keys[1]);
+        }
+        else if(strcasecmp(str, "key3") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setencryp->keys[2], str, 26);
+            DPRINT_INFO(WFA_OUT, "%s\n", setencryp->keys[2]);
+        }
+        else if(strcasecmp(str, "key4") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setencryp->keys[3], str, 26);
+            DPRINT_INFO(WFA_OUT, "%s\n", setencryp->keys[3]);
+        }
+        else if(strcasecmp(str, "activeKey") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setencryp->activeKeyIdx =  atoi(str);
+        }
+        else
+        {
+            DPRINT_INFO(WFA_WNG, "Incorrect Command, check syntax\n");
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_ENCRYPTION_TLV, sizeof(caStaSetEncryption_t), (BYTE *)setencryp, aBuf);
+
+    *aLen = 4+sizeof(caStaSetEncryption_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetPSK(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetPSK_t *setencryp = (caStaSetPSK_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setencryp->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setencryp->ssid, str, 64);
+            DPRINT_INFO(WFA_OUT, "ssid %s\n", setencryp->ssid);
+        }
+        else if(strcasecmp(str, "passPhrase") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setencryp->passphrase, str, 64);
+        }
+        else if(strcasecmp(str, "keyMgmtType") == 0)
+        {
+            str=strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setencryp->keyMgmtType, str, 7);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+
+            if(strcasecmp(str, "tkip") == 0)
+               setencryp->encpType = ENCRYPT_TKIP;
+            else if(strcasecmp(str, "aes-ccmp") == 0)
+               setencryp->encpType = ENCRYPT_AESCCMP;
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_PSK_TLV, sizeof(caStaSetPSK_t), (BYTE *)setencryp, aBuf);
+
+    *aLen = 4+sizeof(caStaSetPSK_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetEapTLS(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetEapTLS_t *setsec = (caStaSetEapTLS_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "keyMgmtType") == 0)
+        {
+            str=strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->keyMgmtType, str, 7);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+       	    strncpy(setsec->encrptype, str, 8);
+	}
+        else if(strcasecmp(str, "trustedRootCA") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->trustedRootCA, str);
+        }
+        else if(strcasecmp(str, "clientCertificate") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->clientCertificate, str);
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_EAPTLS_TLV, sizeof(caStaSetEapTLS_t), (BYTE *)setsec, aBuf);
+
+    *aLen = 4+sizeof(caStaSetEapTLS_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetEapTTLS(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetEapTTLS_t *setsec = (caStaSetEapTTLS_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "username") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->username, str);
+        }
+        else if(strcasecmp(str, "password") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->passwd, str);
+        }
+        else if(strcasecmp(str, "keyMgmtType") == 0)
+        {
+            str=strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->keyMgmtType, str, 7);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->encrptype, str, 8);
+        }
+        else if(strcasecmp(str, "trustedRootCA") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->trustedRootCA, str);
+        }
+        else if(strcasecmp(str, "clientCertificate") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->clientCertificate, str);
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_EAPTTLS_TLV, sizeof(caStaSetEapTTLS_t), (BYTE *)setsec, aBuf);
+
+    *aLen = 4+sizeof(caStaSetEapTTLS_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetEapSIM(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetEapSIM_t *setsec = (caStaSetEapSIM_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "username") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->username, str);
+        }
+        else if(strcasecmp(str, "password") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->passwd, str);
+        }
+        else if(strcasecmp(str, "keyMgmtType") == 0)
+        {
+            str=strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->keyMgmtType, str, 7);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->encrptype, str, 8); 
+	}
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_EAPSIM_TLV, sizeof(caStaSetEapSIM_t), (BYTE *)setsec, aBuf);
+
+    *aLen = 4+sizeof(caStaSetEapSIM_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetPEAP(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetEapPEAP_t *setsec = (caStaSetEapPEAP_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "username") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->username, str);
+        }
+        else if(strcasecmp(str, "password") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->passwd, str);
+        }
+        else if(strcasecmp(str, "keyMgmtType") == 0)
+        {
+            str=strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->keyMgmtType, str, 7);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->encrptype, str, 8); 
+	}
+        else if(strcasecmp(str, "innerEAP") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->innerEAP, str);
+        }
+        else if(strcasecmp(str, "peapVersion") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setsec->peapVersion = atoi(str);
+        }
+    }
+
+
+    wfaEncodeTLV(WFA_STA_SET_PEAP_TLV, sizeof(caStaSetEapPEAP_t), (BYTE *)setsec, aBuf);
+
+    *aLen = 4+sizeof(caStaSetEapPEAP_t);
+
+    return TRUE;
+}
+
+
+int xcCmdProcStaSetIBSS(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetIBSS_t *setibss = (caStaSetIBSS_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setibss->intf, str, 15);
+            DPRINT_INFO(WFA_OUT, "interface %s\n", setibss->intf);
+
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setibss->ssid, str, 64);
+            DPRINT_INFO(WFA_OUT, "ssid %s\n", setibss->ssid);
+        }
+        else if(strcasecmp(str, "channel") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setibss->channel = atoi(str);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            if(strcasecmp(str, "wep") == 0)
+               setibss->encpType = ENCRYPT_WEP;
+            else
+               setibss->encpType = 0;
+        }
+        else if(strcasecmp(str, "key1") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setibss->keys[0], str, 26);
+            setibss->activeKeyIdx = 0;
+        }
+        else if(strcasecmp(str, "key2") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setibss->keys[1], str, 26);
+			setibss->activeKeyIdx = 1;
+        }
+        else if(strcasecmp(str, "key3") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setibss->keys[2], str, 26);
+			setibss->activeKeyIdx = 2;
+        }
+        else if(strcasecmp(str, "key4") == 0)
+        {
+			DPRINT_INFO(WFA_OUT,"in key 4\n");
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setibss->keys[3], str, 26);
+			setibss->activeKeyIdx = 3;
+        }
+        else if(strcasecmp(str, "activeKey") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setibss->activeKeyIdx = atoi(str);
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_IBSS_TLV, sizeof(caStaSetIBSS_t), (BYTE *)setibss, aBuf);
+
+    *aLen = 4+sizeof(caStaSetIBSS_t);
+
+    return TRUE;
+}
+
+int xcCmdProcDeviceGetInfo(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *dutCmd = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    caDevInfo_t *dinfo = &dutCmd->cmdsu.dev;
+    char *str;
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+    dinfo->fw = 0;
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL && str[0] == '\0')
+    {
+        if(strcasecmp(str, "firmware") == 0)
+        {
+            dinfo->fw = 1;
+        }
+    }
+
+    wfaEncodeTLV(WFA_DEVICE_GET_INFO_TLV, 0, NULL, aBuf);
+
+    *aLen = 4;
+
+    return TRUE;
+}
+
+int xcCmdProcStaGetInfo(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    char *str;
+    dutCommand_t *getInfo = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL || str[0] == '\0')
+         return FALSE;
+
+    if(strcasecmp(str, "interface") == 0)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        strncpy(getInfo->intf, str, 15);
+        DPRINT_INFO(WFA_OUT, "interface %s\n", getInfo->intf);
+
+    }
+
+    wfaEncodeTLV(WFA_STA_GET_INFO_TLV, sizeof(dutCommand_t), (BYTE *)getInfo, aBuf);
+
+    *aLen = 4 + sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaGetTestData(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    char *str;
+    dutCommand_t *dutCmd = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    caStaGetTestData_t *tdp = &dutCmd->cmdsu.tdata;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL || str[0] == '\0')
+         return FALSE;
+
+    if(strcasecmp(str, "testdata") == 0)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+	if(strcasecmp(str, "voice") == 0)
+	{
+	    tdp->type = 1;
+            DPRINT_INFO(WFA_OUT, "testdata voice %i\n", tdp->type);
+	}
+    }
+
+    wfaEncodeTLV(WFA_STA_GET_INFO_TLV, sizeof(dutCommand_t), (BYTE *)dutCmd, aBuf);
+
+    *aLen = 4 + sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaAssociate(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *setassoc = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setassoc->intf, str, 15);
+            DPRINT_INFO(WFA_OUT, "interface %s\n", setassoc->intf);
+
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+	    if(str != NULL){
+            strncpy(setassoc->cmdsu.ssid, str, 64);
+            DPRINT_INFO(WFA_OUT, "ssid %s\n", setassoc->cmdsu.ssid);
+	    }
+        }
+   }
+
+    wfaEncodeTLV(WFA_STA_ASSOCIATE_TLV, sizeof(dutCommand_t), (BYTE *)setassoc, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaReAssociate(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *setassoc = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+   
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy(setassoc->intf, str, 15);
+            DPRINT_INFO(WFA_OUT, "interface %s\n", setassoc->intf);
+
+        }
+        else if(strcasecmp(str, "bssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy(setassoc->cmdsu.bssid, str, 64);
+            DPRINT_INFO(WFA_OUT, "bssid %s\n", setassoc->cmdsu.bssid);
+        }
+   }
+
+    wfaEncodeTLV(WFA_STA_REASSOCIATE_TLV, sizeof(dutCommand_t), (BYTE *)setassoc, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcDeviceListIF(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *getdevlist = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    #ifdef DEBUG
+    int i;
+    #endif
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    str = strtok_r(NULL, ",", &pcmdStr);
+    if(str == NULL || str[0] == '\0')
+       return FALSE;
+
+    if(strcasecmp(str, "interfaceType") == 0)
+    {
+         str = strtok_r(NULL, ",", &pcmdStr);
+         if(strcmp(str, "802.11") == 0)
+             getdevlist->cmdsu.iftype = IF_80211;
+
+         DPRINT_INFO(WFA_OUT, "interface type %i\n", getdevlist->cmdsu.iftype);
+    }
+
+    wfaEncodeTLV(WFA_DEVICE_LIST_IF_TLV, sizeof(dutCommand_t), (BYTE *)getdevlist, aBuf);
+
+    *aLen = 4 + sizeof(dutCommand_t);
+
+#if DEBUG
+               for(i = 0; i< *aLen; i++)
+                 DPRINT_INFO(WFA_OUT,"%x ", aBuf[i]);
+
+               DPRINT_INFO(WFA_OUT,"\n");
+#endif
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetUAPSD(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetUAPSD_t *setuapsd = (caStaSetUAPSD_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+    memset(setuapsd, 0, sizeof(caStaSetUAPSD_t)); /* Added as per BRCM 1.3 ASD */
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setuapsd->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setuapsd->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "maxSPlength") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setuapsd->maxSPLength = atoi(str);
+        }
+        else if(strcasecmp(str, "acBE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setuapsd->acBE = atoi(str);
+        }
+        else if(strcasecmp(str, "acBK") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setuapsd->acBK = atoi(str);
+
+        }
+        else if(strcasecmp(str, "acVI") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setuapsd->acVI = atoi(str);
+
+        }
+        else if(strcasecmp(str, "acVO") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setuapsd->acVO = atoi(str);
+        }
+  }
+
+/* Start: Added as per BRCM 1.3 ASD */
+    wfaEncodeTLV(WFA_STA_SET_UAPSD_TLV, sizeof(caStaSetUAPSD_t), (BYTE *)setuapsd, aBuf);
+	*aLen = 4+sizeof(caStaSetUAPSD_t);
+/* End: Added as per BRCM 1.3 ASD */
+
+
+    return TRUE;
+}
+
+int xcCmdProcStaDebugSet(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *debugSet = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "level") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            if(atoi(str) == WFA_DEBUG_INFO || WFA_DEBUG_WARNING)
+            {
+                debugSet->cmdsu.dbg.level = atoi(str);
+                DPRINT_INFO(WFA_OUT, "dbg level %i\n", debugSet->cmdsu.dbg.level);
+            }
+            else
+                return FALSE;  /* not support */
+
+        }
+        else if(strcasecmp(str, "enable") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            DPRINT_INFO(WFA_OUT,"enable %i\n", atoi(str));
+            switch(atoi(str)) /* enable */
+            {
+            case 1:
+               debugSet->cmdsu.dbg.state = 1;
+               DPRINT_INFO(WFA_OUT,"enable\n");
+               break;
+            case 0:
+               debugSet->cmdsu.dbg.state = 0;
+               DPRINT_INFO(WFA_OUT,"disable\n");
+               break;
+            default:
+               DPRINT_INFO(WFA_OUT,"wrong\n");
+               return FALSE;  /* command invalid */
+            }
+         }
+    }
+
+    wfaEncodeTLV(WFA_STA_DEBUG_SET_TLV, sizeof(dutCommand_t), (BYTE *)debugSet, aBuf);
+
+    *aLen = 4 + sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetMode(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetMode_t *setmode = (caStaSetMode_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+       return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+           break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+           strncpy(setmode->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+           strncpy(setmode->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+           if(strcasecmp(str, "wep") == 0)
+              setmode->encpType = ENCRYPT_WEP;
+           else
+              setmode->encpType = 0;
+        }
+        else if(strcasecmp(str, "key1") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+           strncpy((char *)setmode->keys[0], str, 26);
+           DPRINT_INFO(WFA_OUT, "%s\n", setmode->keys[0]);
+           setmode->activeKeyIdx = 0;
+        }
+        else if(strcasecmp(str, "key2") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setmode->keys[1], str, 26);
+            DPRINT_INFO(WFA_OUT, "%s\n", setmode->keys[1]);
+        }
+        else if(strcasecmp(str, "key3") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setmode->keys[2], str, 26);
+            DPRINT_INFO(WFA_OUT, "%s\n", setmode->keys[2]);
+        }
+        else if(strcasecmp(str, "key4") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy((char *)setmode->keys[3], str, 26);
+            DPRINT_INFO(WFA_OUT, "%s\n", setmode->keys[3]);
+        }
+        else if(strcasecmp(str, "activeKey") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setmode->activeKeyIdx =  atoi(str);
+        }
+        else if(strcasecmp(str, "mode") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            DPRINT_INFO(WFA_OUT,"\r\n mode is %s\n",str);
+            if(strcasecmp(str, "adhoc") == 0)
+               setmode->mode = 1;
+            else
+               setmode->mode = 0;
+        }
+        else if(strcasecmp(str, "channel") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setmode->channel = atoi(str);
+        }
+        else
+        {
+            DPRINT_INFO(WFA_WNG, "Incorrect Command, check syntax\n");
+            DPRINT_INFO(WFA_OUT,"\r\n mode is %s\n",str);
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_MODE_TLV, sizeof(caStaSetMode_t), (BYTE *)setmode, aBuf);
+    *aLen = 4+sizeof(caStaSetMode_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetPwrSave(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetPwrSave_t *setps = (caStaSetPwrSave_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+           break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+           strncpy(setps->intf, str, 15);
+        }
+        else if(strcasecmp(str, "mode") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+	    if(strcasecmp(str,"on") == 0)
+	       setps->mode = 2;
+	    else if(strcasecmp(str,"off") == 0)
+	       setps->mode = 0;
+	    else
+           return FALSE;
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_PWRSAVE_TLV, sizeof(caStaSetPwrSave_t), (BYTE *)setps, aBuf);
+    *aLen = 4+sizeof(caStaSetPwrSave_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetWMM(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetWMM_t *setwmm = (caStaSetWMM_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    wfaTLV *hdr = (wfaTLV *)aBuf;
+
+    DPRINT_INFO(WFA_OUT, "start xcCmdProcStaSetWMM ...\n");
+    DPRINT_INFO(WFA_OUT, "params:  %s\n", pcmdStr);
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+    /* Some default values, in case they are not specified*/
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy(setwmm->intf, str, 15);
+        }
+        else if(strcasecmp(str, "GROUP") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+	    if(strcasecmp(str,"WMMAC") == 0)
+              setwmm->group = GROUP_WMMAC;
+	    else if(strcasecmp(str,"WMM-CONFIG") == 0)
+            {
+                setwmm->group = GROUP_WMMCONF;
+                setwmm->actions.config.frag_thr = 2346;
+                setwmm->actions.config.rts_thr = 2346;
+                setwmm->actions.config.wmm = 1;
+            }
+        }
+        else if(strcasecmp(str, "ACTION") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+	    if(strcasecmp(str,"addts") == 0)
+            {
+                /* Put default values for the tspec element */
+	        setwmm->action = WMMAC_ADDTS;
+                setwmm->actions.addts.accesscat = WMMAC_AC_BE;
+                setwmm->actions.addts.tspec.tsinfo.dummy1 = 1;
+                setwmm->actions.addts.tspec.tsinfo.dummy2 = 0;
+            }
+	    else if(strcasecmp(str,"delts") == 0)
+	        setwmm->action = WMMAC_DELTS;
+	    DPRINT_INFO(WFA_OUT,"action is %d\n",setwmm->action);
+        }
+        else if(strcasecmp(str, "RTS_thr") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.config.rts_thr = atoi(str);
+        }
+        else if(strcasecmp(str, "wmm") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+	    if(atoi(str) != 0)
+            setwmm->actions.config.wmm = 1;
+	    else
+            setwmm->actions.config.wmm = 0;
+        }
+        else if(strcasecmp(str, "Frag_thr") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.config.frag_thr = atoi(str);
+        }
+        else if(strcasecmp(str, "DIALOG_TOKEN") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.dialog_token = atoi(str);
+        }
+        else if(strcasecmp(str, "TID") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            if(setwmm->action == WMMAC_ADDTS) 
+               setwmm->actions.addts.tspec.tsinfo.TID  = atoi(str);
+            else
+               setwmm->actions.delts = atoi(str);
+        }
+        else if(strcasecmp(str, "SENDTRIG") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+	    	if(strcasecmp(str,"true") == 0)
+            	   setwmm->send_trig=1;
+			else
+            	   setwmm->send_trig=0;
+        }
+        else if(strcasecmp(str, "DEST") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setwmm->dipaddr, str, 15);
+        }
+        else if(strcasecmp(str, "trigac") == 0)
+        {
+       	    str = strtok_r(NULL, ",", &pcmdStr);
+	    if(strcasecmp(str,"VO") == 0)
+                setwmm->trig_ac= TG_WMM_AC_VO;
+            else if(strcasecmp(str,"VI") == 0)
+                setwmm->trig_ac= TG_WMM_AC_VI;
+            else if(strcasecmp(str,"BE") == 0)
+                setwmm->trig_ac= TG_WMM_AC_BE;
+            else if(strcasecmp(str,"BK") == 0)
+                setwmm->trig_ac= TG_WMM_AC_BK;
+        }
+        else if(strcasecmp(str, "DIRECTION") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+	    if(strcasecmp(str,"UP") == 0)
+               setwmm->actions.addts.tspec.tsinfo.direction = WMMAC_UPLINK;
+	    else if(strcasecmp(str,"DOWN") == 0)
+               setwmm->actions.addts.tspec.tsinfo.direction = WMMAC_DOWNLINK;
+	    else if(strcasecmp(str,"BIDI") == 0)
+               setwmm->actions.addts.tspec.tsinfo.direction = WMMAC_BIDIR;
+        }
+        else if(strcasecmp(str, "PSB") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+	    if(strcasecmp(str,"UAPSD") == 0)
+                setwmm->actions.addts.tspec.tsinfo.PSB = 1;
+	    else
+                setwmm->actions.addts.tspec.tsinfo.PSB = 0;
+        }
+        else if(strcasecmp(str, "UP") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.tsinfo.UP = atoi(str);
+        }
+        else if(strcasecmp(str, "Fixed") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            if(strcasecmp(str, "true") == 0)
+               setwmm->actions.addts.tspec.Fixed = 1;
+            else
+               setwmm->actions.addts.tspec.Fixed = 0;
+        }
+        else if(strcasecmp(str, "SIZE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.size = atoi(str);
+        }
+        else if(strcasecmp(str, "MAXSIZE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.maxsize = atoi(str);
+        }
+        else if(strcasecmp(str, "MIN_SRVC_INTRVL") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.min_srvc = atoi(str);
+        }
+        else if(strcasecmp(str, "MAX_SRVC_INTRVL") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.max_srvc = atoi(str);
+        }
+        else if(strcasecmp(str, "INACTIVITY") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.inactivity = atoi(str);
+        }
+        else if(strcasecmp(str, "SUSPENSION") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.suspension = atoi(str);
+        }
+        else if(strcasecmp(str, "SRVCSTARTTIME") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.srvc_strt_tim = atoi(str);
+        }
+        else if(strcasecmp(str, "MINDATARATE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.mindatarate = atoi(str);
+        }
+        else if(strcasecmp(str, "MEANDATARATE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.meandatarate = atoi(str);
+        }
+        else if(strcasecmp(str, "PEAKDATARATE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.peakdatarate = atoi(str);
+        }
+        else if(strcasecmp(str, "BURSTSIZE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.burstsize = atoi(str);
+        }
+        else if(strcasecmp(str, "DELAYBOUND") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.delaybound = atoi(str);
+        }
+        else if(strcasecmp(str, "PHYRATE") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.PHYrate = atoi(str);
+        }
+        else if(strcasecmp(str, "SBA") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.sba = (float)atof(str);
+        }
+        else if(strcasecmp(str, "MEDIUM_TIME") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            setwmm->actions.addts.tspec.medium_time = atoi(str);
+        }
+        else if(strcasecmp(str, "ACCESSCAT") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+	    if(strcasecmp(str,"VO") == 0)
+               setwmm->actions.addts.accesscat = WMMAC_AC_VO;
+	    else if(strcasecmp(str,"VI") == 0)
+               setwmm->actions.addts.accesscat = WMMAC_AC_VI;
+	    else if(strcasecmp(str,"BE") == 0)
+               setwmm->actions.addts.accesscat = WMMAC_AC_BE;
+	    else if(strcasecmp(str,"BK") == 0)
+               setwmm->actions.addts.accesscat = WMMAC_AC_BK;
+        }
+    }
+    if (setwmm->action == WMMAC_ADDTS) {
+        DPRINT_INFO(WFA_OUT, "ADDTS AC PARAMS: dialog id: %d, TID: %d, DIRECTION: %d, PSB: %d, UP: %d,\
+        Fixed %d, MSDU Size: %d, Max MSDU Size %d, MIN SERVICE INTERVAL: %d, MAX SERVICE INTERVAL: %d\
+        ,INACTIVITY: %d,SUSPENSION %d,SERVICE START TIME: %d,MIN DATARATE: %d,MEAN DATA RATE: %d\
+        , PEAK DATA RATE: %d,BURSTSIZE: %d,DELAY BOUND: %d,PHYRATE: %d, SPLUSBW: %f,MEDIUM TIME: %d, ACCESSCAT: %d\n"\
+        ,setwmm->actions.addts.dialog_token,setwmm->actions.addts.tspec.tsinfo.TID\
+        ,setwmm->actions.addts.tspec.tsinfo.direction,setwmm->actions.addts.tspec.tsinfo.PSB,setwmm->actions.addts.tspec.tsinfo.UP\
+        ,setwmm->actions.addts.tspec.Fixed,setwmm->actions.addts.tspec.size, setwmm->actions.addts.tspec.maxsize,\
+        setwmm->actions.addts.tspec.min_srvc,\
+        setwmm->actions.addts.tspec.max_srvc,setwmm->actions.addts.tspec.inactivity,setwmm->actions.addts.tspec.suspension,\
+        setwmm->actions.addts.tspec.srvc_strt_tim,setwmm->actions.addts.tspec.mindatarate,setwmm->actions.addts.tspec.meandatarate\
+        ,setwmm->actions.addts.tspec.peakdatarate,setwmm->actions.addts.tspec.burstsize,\
+        setwmm->actions.addts.tspec.delaybound,setwmm->actions.addts.tspec.PHYrate,setwmm->actions.addts.tspec.sba,\
+        setwmm->actions.addts.tspec.medium_time,setwmm->actions.addts.accesscat);
+    }
+    else
+        DPRINT_INFO(WFA_OUT, "DELTS AC PARAMS: TID:  %d\n", setwmm->actions.delts);
+
+    hdr->tag =  WFA_STA_SET_WMM_TLV;   
+    hdr->len = sizeof(caStaSetWMM_t);
+
+    memcpy(aBuf+4, setwmm, sizeof(caStaSetWMM_t));
+
+    *aLen = 4+sizeof(caStaSetWMM_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaNeigreq(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *neigreq = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+    for(;;)
+    {
+	str = strtok_r(NULL, ",", &pcmdStr);
+	if(str == NULL || str[0] == '\0')
+		break;
+
+	if(strcasecmp(str, "mac") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		strncpy(neigreq->mac, str, WFA_MAC_ADDR_STR_LEN);
+		DPRINT_INFO(WFA_OUT, "mac %s\n", neigreq->mac);
+	}
+        else if(strcasecmp(str, "ssid") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str != NULL)
+		{
+			strncpy(neigreq->cmdsu.ssid, str, WFA_SSID_NAME_LEN);
+			DPRINT_INFO(WFA_OUT, "ssid %s\n", neigreq->cmdsu.ssid);
+		}
+        }
+   }
+
+    wfaEncodeTLV(WFA_STA_SEND_NEIGREQ_TLV, sizeof(dutCommand_t), (BYTE *)neigreq, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+
+int xcCmdProcStaSetSystime(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *systime = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    int temp;
+    if(aBuf == NULL)
+    return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+     {
+	str = strtok_r(NULL, ",", &pcmdStr);
+	if(str == NULL || str[0] == '\0')
+		break;
+
+	if(strcasecmp(str, "month") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		temp = atoi(str);
+		/*
+		 * If month is more than 2 character then error
+		 * If it is 2 character and less than 10 and first char is not 0 like '1b'
+		 * 'b7' etc. All possible errors input taken care
+		 */
+		if ((temp > 12 || temp < 1) || (strlen(str) > 2) ||
+		(strlen(str) == 2 && temp < 10 && str[0] != '0'))
+		{
+			DPRINT_ERR(WFA_OUT, "Wrong month input \n");
+			return FALSE;
+		}
+		systime->cmdsu.stime.month = temp;
+		DPRINT_INFO(WFA_OUT, "month %d\n", systime->cmdsu.stime.month);
+        }
+	else if(strcasecmp(str, "date") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		temp = atoi(str);
+		if ((temp > 31 || temp < 1) || (strlen(str) > 2) ||
+		(strlen(str) == 2 && temp < 10 && str[0] != '0'))
+		{
+			DPRINT_ERR(WFA_OUT, "Wrong date input \n");
+			return FALSE;
+		}
+		/* In case of Linux there is no invalid date, all dates will be accepted and it will
+		 * set to next corresponding valid date
+		 * In case of win32 system will return error while setting bad date
+		 */
+		systime->cmdsu.stime.date = temp;
+		DPRINT_INFO(WFA_OUT, "date %d\n", systime->cmdsu.stime.date);
+	}
+	else if(strcasecmp(str, "year") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		temp = atoi(str);
+		/*
+		 * Unix date start from 1970, so lower limit kept
+		 */
+		if (temp < 1970 || strlen(str) > 4)
+		{
+			DPRINT_ERR(WFA_OUT, "Wrong year input\n");
+			return FALSE;
+		}
+		systime->cmdsu.stime.year = temp;
+		DPRINT_INFO(WFA_OUT, "year %d\n", systime->cmdsu.stime.year);
+        }
+	else if(strcasecmp(str, "hours") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		temp = atoi(str);
+		if ((temp > 23 || temp < 0) || (strlen(str) > 2) ||
+		(strlen(str) == 2 && temp < 10 && str[0] != '0'))
+		{
+			DPRINT_ERR(WFA_OUT, "Wrong hours input \n");
+			return FALSE;
+		}
+		systime->cmdsu.stime.hours = temp;
+		DPRINT_INFO(WFA_OUT, "hours %d\n", systime->cmdsu.stime.hours);
+	}
+	else if(strcasecmp(str, "minutes") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		temp = atoi(str);
+		if ((temp > 59 || temp < 0) || (strlen(str) > 2) ||
+		(strlen(str) == 2 && temp < 10 && str[0] != '0'))
+		{
+			DPRINT_ERR(WFA_OUT, "Wrong minutes input \n");
+			return FALSE;
+		}
+		systime->cmdsu.stime.minutes = temp;
+		DPRINT_INFO(WFA_OUT, "minutes %d\n", systime->cmdsu.stime.minutes);
+        }
+	else if(strcasecmp(str, "seconds") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		temp = atoi(str);
+		if ((temp > 59 || temp < 0) || (strlen(str) > 2) ||
+		(strlen(str) == 2 && temp < 10 && str[0] != '0'))
+		{
+			DPRINT_ERR(WFA_OUT, "Wrong seconds input \n");
+			return FALSE;
+		}
+		systime->cmdsu.stime.seconds = temp;
+		DPRINT_INFO(WFA_OUT, "seconds %d\n", systime->cmdsu.stime.seconds);
+        }
+   }
+
+    wfaEncodeTLV(WFA_STA_SET_SYSTIME_TLV, sizeof(dutCommand_t), (BYTE *)systime, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+#ifdef WFA_STA_TB
+
+int xcCmdProcStaSet11n(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *Set11n = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    int smps;
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+	
+    for(;;)
+    {
+	str = strtok_r(NULL, ",", &pcmdStr);
+	if(str == NULL || str[0] == '\0')
+		break;
+	/* 1 is for disable and 2 is for enable, as all values set to 0 initially */
+	if(strcasecmp(str, "40_intolerant") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+		Set11n->cmdsu.set11n.intolerant_40 = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			Set11n->cmdsu.set11n.intolerant_40 = 1;
+		else 
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "40_intolerant %d\n", Set11n->cmdsu.set11n.intolerant_40);
+	}
+	else if(strcasecmp(str, "addba_reject") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+			Set11n->cmdsu.set11n.addba_reject = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			Set11n->cmdsu.set11n.addba_reject = 1;
+		else
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "addba_reject %d\n", Set11n->cmdsu.set11n.addba_reject);
+	}
+	else if(strcasecmp(str, "ampdu") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+			Set11n->cmdsu.set11n.ampdu = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			Set11n->cmdsu.set11n.ampdu = 1;
+		else
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "ampdu %d\n", Set11n->cmdsu.set11n.ampdu);
+	}
+	else if(strcasecmp(str, "amsdu") == 0)
+	{	
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+			Set11n->cmdsu.set11n.amsdu = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			Set11n->cmdsu.set11n.amsdu = 1;
+		else
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "amsdu %d\n", Set11n->cmdsu.set11n.amsdu);
+	}
+	else if(strcasecmp(str, "greenfield") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+			Set11n->cmdsu.set11n.greenfield = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			Set11n->cmdsu.set11n.greenfield = 1;
+		else
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "greenfield %d\n", Set11n->cmdsu.set11n.greenfield);
+	}
+	else if(strcasecmp(str, "sgi20") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+			Set11n->cmdsu.set11n.sgi20 = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			Set11n->cmdsu.set11n.sgi20 = 1;
+		else
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "sgi20 %d\n", Set11n->cmdsu.set11n.sgi20);
+	}  
+	else if(strcasecmp(str, "stbc_rx") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		Set11n->cmdsu.set11n.stbc_rx = atoi(str);
+		DPRINT_INFO(WFA_OUT, "stbc_rx %d\n", Set11n->cmdsu.set11n.stbc_rx);
+	}
+	else if(Set11n->cmdsu.set11n.stbc_rx == 0)
+	{
+		Set11n->cmdsu.set11n.stbc_rx = -1;
+	}
+	else if(strcasecmp(str, "width") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "auto") == 0)
+			Set11n->cmdsu.set11n.width = -1;
+		else
+			Set11n->cmdsu.set11n.width = atoi(str);
+		DPRINT_INFO(WFA_OUT, "width %d\n", Set11n->cmdsu.set11n.width);
+	}
+	else if(strcasecmp(str, "mcs32") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+			Set11n->cmdsu.set11n.mcs32 = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			Set11n->cmdsu.set11n.mcs32 = 1;
+		else
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "mcs32 %d\n", Set11n->cmdsu.set11n.mcs32);
+	}
+	else if(strcasecmp(str, "smps") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		smps = atoi(str);
+		smps++;
+		Set11n->cmdsu.set11n.smps = smps;
+		DPRINT_INFO(WFA_OUT, "smps %d\n", Set11n->cmdsu.set11n.smps);
+	}
+	else if(strcasecmp(str, "txsp_stream") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		Set11n->cmdsu.set11n.txsp_stream = atoi(str);
+		DPRINT_INFO(WFA_OUT, "txsp_stream %d\n", Set11n->cmdsu.set11n.txsp_stream);
+	}
+	else if(strcasecmp(str, "rxsp_stream") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		Set11n->cmdsu.set11n.rxsp_stream = atoi(str);
+		DPRINT_INFO(WFA_OUT, "rxsp_stream %d\n", Set11n->cmdsu.set11n.rxsp_stream);
+	}
+	else if(strcasecmp(str, "mcs_fixedrate") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		Set11n->cmdsu.set11n.mcs_fixedrate = atoi(str);
+		if((Set11n->cmdsu.set11n.mcs_fixedrate > 31) || (Set11n->cmdsu.set11n.mcs_fixedrate < 0))
+			return FALSE;
+		DPRINT_INFO(WFA_OUT, "mcs_fixedrate %d\n", Set11n->cmdsu.set11n.mcs_fixedrate);
+	}
+	else
+	{
+		/* done to ignore mcs if it is not set */
+		Set11n->cmdsu.set11n.mcs_fixedrate = -1;
+	}
+   }
+
+    wfaEncodeTLV(WFA_STA_SET_11N_TLV, sizeof(dutCommand_t), (BYTE *)Set11n, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetRIFSTest(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *rifstest = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    if(aBuf == NULL)
+	return FALSE;
+
+    memset(aBuf, 0, *aLen);
+    for(;;)
+    {
+	str = strtok_r(NULL, ",", &pcmdStr);
+	if(str == NULL || str[0] == '\0')
+		break;
+	if(strcasecmp(str, "interface") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		strncpy(rifstest->intf, str, WFA_IF_NAME_LEN);
+		DPRINT_INFO(WFA_OUT, "interface %s\n", rifstest->intf);
+	}
+	if(strcasecmp(str, "action") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "enable") == 0)
+			rifstest->cmdsu.action_rifs = 2;
+		else if(strcasecmp(str, "disable") == 0)
+			rifstest->cmdsu.action_rifs = 1;
+		else
+		{
+			DPRINT_ERR(WFA_OUT, "not a proper action id\n");
+			return FALSE;
+		}
+		DPRINT_INFO(WFA_OUT, "action %d\n", rifstest->cmdsu.action_rifs);
+	}
+    }
+    wfaEncodeTLV(WFA_STA_SET_RIFS_TEST_TLV, sizeof(dutCommand_t), (BYTE *)rifstest, aBuf);
+
+    *aLen = 4 + sizeof(dutCommand_t);
+    return TRUE;
+}
+
+int xcCmdProcStaSetWireless(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *wireless = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+	str = strtok_r(NULL, ",", &pcmdStr);
+	if(str == NULL || str[0] == '\0')
+		break;
+
+	if(strcasecmp(str, "interface") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		strncpy(wireless->intf, str, WFA_IF_NAME_LEN);
+		DPRINT_INFO(WFA_OUT, "interface %s\n", wireless->intf);
+        }
+	else if(strcasecmp(str, "band") == 0)
+	{
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		strncpy(wireless->cmdsu.wireless_band, str, strlen(str));
+		DPRINT_INFO(WFA_OUT, "band %s\n", wireless->cmdsu.wireless_band);			
+	}
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_WIRELESS_TLV, sizeof(dutCommand_t), (BYTE *)wireless, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSendAddba(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *addba = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		strncpy(addba->intf, str, WFA_IF_NAME_LEN);
+		DPRINT_INFO(WFA_OUT, "interface %s\n", addba->intf);
+        }
+        else if(strcasecmp(str, "tid") == 0)
+        {
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		addba->cmdsu.tid = atoi(str);
+		DPRINT_INFO(WFA_OUT, "tid %d\n", addba->cmdsu.tid);
+	}
+    }
+
+    wfaEncodeTLV(WFA_STA_SEND_ADDBA_TLV, sizeof(dutCommand_t), (BYTE *)addba, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSendCoexistMGMT(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *coexist = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+	str = strtok_r(NULL, ",", &pcmdStr);
+	if(str == NULL || str[0] == '\0')
+		break;
+        if(strcasecmp(str, "interface") == 0)
+        {
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		strncpy(coexist->intf, str, WFA_IF_NAME_LEN);
+		DPRINT_INFO(WFA_OUT, "interface %s\n", coexist->intf);
+        }
+        else if(strcasecmp(str, "type") == 0)
+        {
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		if(strcasecmp(str, "MHz") == 0)
+		{
+			str = strtok_r(NULL, ",", &pcmdStr);
+			if(str == NULL || str[0] == '\0')
+				return FALSE;
+			if(strcasecmp(str, "value") == 0)
+			{
+				str = strtok_r(NULL, ",", &pcmdStr);
+				if(str == NULL || str[0] == '\0')
+					return FALSE;
+				strncpy(coexist->cmdsu.coexistmgmt.Mhz, str, 1);
+			}
+		}
+		else if(strcasecmp(str, "BSS") == 0)
+		{
+			str = strtok_r(NULL, ",", &pcmdStr);
+			if(str == NULL || str[0] == '\0')
+				return FALSE;
+			if(strcasecmp(str, "value") == 0)
+			{
+				str = strtok_r(NULL, ",", &pcmdStr);
+				if(str == NULL || str[0] == '\0')
+					return FALSE;
+				strncpy(coexist->cmdsu.coexistmgmt.bss, str, 1);
+			}
+		}
+		else if(strcasecmp(str, "ChnlRepo") == 0)
+		{
+			str = strtok_r(NULL, ",", &pcmdStr);
+			if(str == NULL || str[0] == '\0')
+				return FALSE;
+			if(strcasecmp(str, "value") == 0)
+			{
+				str = strtok_r(NULL, ",", &pcmdStr);
+				if(str == NULL || str[0] == '\0')
+					return FALSE;
+				strncpy(coexist->cmdsu.coexistmgmt.ChnlRepo, str, strlen(str));
+			}
+		}			
+	}
+    }
+
+    wfaEncodeTLV(WFA_STA_SEND_COEXIST_MGMT_TLV, sizeof(dutCommand_t), (BYTE *)coexist, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+    return TRUE;
+}
+
+int xcCmdProcStaDisconnect(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    dutCommand_t *disconnect = (dutCommand_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+    if(aBuf == NULL)
+        return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+	str = strtok_r(NULL, ",", &pcmdStr);
+	if(str == NULL || str[0] == '\0')
+		break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+		str = strtok_r(NULL, ",", &pcmdStr);
+		if(str == NULL || str[0] == '\0')
+			return FALSE;
+		strncpy(disconnect->intf, str, WFA_IF_NAME_LEN);
+		DPRINT_INFO(WFA_OUT, "intf %s\n", disconnect->intf);
+        }
+   }
+
+    wfaEncodeTLV(WFA_STA_DISCONNECT_TLV, sizeof(dutCommand_t), (BYTE *)disconnect, aBuf);
+
+    *aLen = 4+sizeof(dutCommand_t);
+
+    return TRUE;
+}
+
+#endif /* WFA_STA_TB */
+
+int xcCmdProcStaResetDefault(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaResetDefault_t *reset = (caStaResetDefault_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+
+    if(aBuf == NULL)
+       return FALSE;
+
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+           break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+           strncpy(reset->intf, str, 15);
+        }
+        else if(strcasecmp(str, "program") == 0)
+        {
+           str = strtok_r(NULL, ",", &pcmdStr);
+           strncpy(reset->prog, str, 16);
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_RESET_DEFAULT_TLV, sizeof(caStaResetDefault_t), (BYTE *)reset, aBuf);
+    *aLen = 4+sizeof(caStaResetDefault_t);
+
+    return TRUE;
+}
+
+int xcCmdProcStaSetEapFAST(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetEapFAST_t *setsec = (caStaSetEapFAST_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+   
+    if(aBuf == NULL)
+       return FALSE;
+   
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy(setsec->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy(setsec->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "username") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->username, str);
+        }
+        else if(strcasecmp(str, "password") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->passwd, str);
+        }
+        else if(strcasecmp(str, "keyMgmtType") == 0)
+        {
+            str=strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->keyMgmtType, str, 7);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->encrptype, str, 8);
+        }
+        else if(strcasecmp(str, "trustedRootCA") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->trustedRootCA, str,31);
+        }
+        else if(strcasecmp(str, "innerEAP") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->innerEAP, str);
+        }
+        else if(strcasecmp(str, "validateServer") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            if(strcasecmp(str, "yes") == 0)
+            {
+               setsec->validateServer=1;
+            }
+            else if(strcasecmp(str, "no") == 0)
+            {
+               setsec->validateServer=0;
+            }
+        }
+        else if(strcasecmp(str, "pacFile") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->pacFileName, str);
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_EAPFAST_TLV, sizeof(caStaSetEapFAST_t), (BYTE *)setsec, aBuf);
+
+    *aLen = 4+sizeof(caStaSetEapFAST_t);
+
+    return TRUE;
+}
+
+
+int xcCmdProcStaSetEapAKA(char *pcmdStr, BYTE *aBuf, int *aLen)
+{
+    caStaSetEapAKA_t *setsec = (caStaSetEapAKA_t *) (aBuf+sizeof(wfaTLV));
+    char *str;
+   
+    if(aBuf == NULL)
+        return FALSE;
+   
+    memset(aBuf, 0, *aLen);
+
+    for(;;)
+    {
+        str = strtok_r(NULL, ",", &pcmdStr);
+        if(str == NULL || str[0] == '\0')
+            break;
+
+        if(strcasecmp(str, "interface") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy(setsec->intf, str, 15);
+        }
+        else if(strcasecmp(str, "ssid") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy(setsec->ssid, str, 64);
+        }
+        else if(strcasecmp(str, "username") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->username, str);
+        }
+        else if(strcasecmp(str, "password") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strcpy(setsec->passwd, str);
+        }
+        else if(strcasecmp(str, "keyMgmtType") == 0)
+        {
+            str=strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->keyMgmtType, str, 7);
+        }
+        else if(strcasecmp(str, "encpType") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);
+            strncpy(setsec->encrptype, str, 8);
+        }
+        else if(strcasecmp(str, "triplet1") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy((char *)setsec->tripletSet[0], str, 63);
+            DPRINT_INFO(WFA_OUT, "Triplet1 : %s\n", setsec->tripletSet[0]);
+            setsec->tripletCount = 1;
+        }
+        else if(strcasecmp(str, "triplet2") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy((char *)setsec->tripletSet[1], str, 63);
+            DPRINT_INFO(WFA_OUT, "Triplet2 : %s\n", setsec->tripletSet[1]);
+            setsec->tripletCount=2;
+        }
+        else if(strcasecmp(str, "triplet3") == 0)
+        {
+            str = strtok_r(NULL, ",", &pcmdStr);  
+            strncpy((char *)setsec->tripletSet[2], str, 63);
+            DPRINT_INFO(WFA_OUT, "Triplet1 : %s\n", setsec->tripletSet[2]);
+            setsec->tripletCount = 3;
+        }
+    }
+
+    wfaEncodeTLV(WFA_STA_SET_EAPAKA_TLV, sizeof(caStaSetEapAKA_t), (BYTE *)setsec, aBuf);
+
+    *aLen = 4+sizeof(caStaSetEapAKA_t);
+
+    return TRUE;
+}
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_cmdtbl.c b/src/tools/Wifi_ASD_test/lib/wfa_cmdtbl.c
new file mode 100644
index 0000000..fbb6de0
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_cmdtbl.c
@@ -0,0 +1,167 @@
+

+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+/*

+ * File: wfa_cmdtbl.c 

+ *   The file contains a predefined function array. The command process and

+ *   execution functions of a DUT traffic generator and control will be 

+ *   registered in the array/table by the order of the defined commands TLV  

+ *   values.

+ *

+ *   Revision History:

+ *      2006/03/10 -- initially created by qhu

+ *      2006/06/01 -- BETA release by qhu

+ *      2006/06/13 -- 00.02 release by qhu

+ *      2006/06/30 -- 00.10 Release by qhu

+ *      2006/07/10 -- 01.00 Release by qhu

+ *      2006/09/01 -- 01.05 Release by qhu

+ *      2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi

+ *      2007/03/30 -- 01.40 WPA2 and Official WMM Beta release by qhu

+ *      2007/04/20 -- 02.00 WPA2 and Official WMM release by qhu

+ *      2007/08/15 --  02.10 WMM-Power Save release by qhu

+ *      2007/10/10 --  02.20 Voice SOHO beta -- qhu

+ *      2007/11/07 --  02.30 Voice HSO -- qhu

+ *

+ */

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#ifndef WIN32

+#include <sys/socket.h>

+#endif

+#include "wfa_debug.h"

+#include "wfa_sock.h"

+#include "wfa_types.h"

+#include "wfa_main.h"

+#include "wfa_tlv.h"

+#include "wfa_tg.h"

+#include "wfa_miscs.h"

+#include "wfa_ca.h"

+#include "wfa_agt.h"

+#include "wfa_rsp.h"

+

+/* extern defined variables */

+extern int gxcSockfd, btSockfd;

+

+int NotDefinedYet(int len, unsigned char *params, int *respLen, BYTE *respBuf);

+extern int agtCmdProcGetVersion(int len, BYTE *parms, int *respLen, BYTE *respBuf);

+

+extern unsigned short wfa_defined_debug;

+

+/* globally define the function table */

+xcCommandFuncPtr gWfaCmdFuncTbl[WFA_STA_COMMANDS_END] =

+{

+    /* Traffic Agent Commands */

+    NotDefinedYet,            /*    None                               (0) */

+    agtCmdProcGetVersion,     /*    WFA_GET_VERSION_TLV                (1) */ 

+    wfaTGSendPing,            /*    WFA_TRAFFIC_SEND_PING_TLV          (2) */

+    wfaTGStopPing,            /*    WFA_TRAFFIC_STOP_PING_TLV          (3) */

+    wfaTGConfig,              /*    WFA_TRAFFIC_AGENT_CONFIG_TLV       (4) */

+    wfaTGSendStart,           /*    WFA_TRAFFIC_AGENT_SEND_TLV         (5) */

+    wfaTGRecvStart,           /*    WFA_TRAFFIC_AGENT_RECV_START_TLV   (6) */

+    wfaTGRecvStop,            /*    WFA_TRAFFIC_AGENT_RECV_STOP_TLV    (7) */

+    wfaTGReset,               /*    WFA_TRAFFIC_AGENT_RESET_TLV        (8) */

+    NotDefinedYet,            /*    WFA_TRAFFIC_AGENT_STATUS_TLV       (9) */

+

+    /* Control and Configuration Commands */ 

+    wfaStaGetIpConfig,        /*    WFA_STA_GET_IP_CONFIG_TLV          (10)*/

+    wfaStaSetIpConfig,        /*    WFA_STA_SET_IP_CONFIG_TLV          (11)*/

+    wfaStaGetMacAddress,      /*    WFA_STA_GET_MAC_ADDRESS_TLV        (12)*/

+    NotDefinedYet,            /*    WFA_STA_SET_MAC_ADDRESS_TLV        (13)*/

+    wfaStaIsConnected,        /*    WFA_STA_IS_CONNECTED_TLV           (14)*/

+    wfaStaVerifyIpConnection, /*    WFA_STA_VERIFY_IP_CONNECTION_TLV   (15)*/

+    wfaStaGetBSSID,           /*    WFA_STA_GET_BSSID_TLV              (16)*/

+    wfaStaGetStats,           /*    WFA_STA_GET_STATS_TLV              (17)*/

+    wfaSetEncryption,         /*    WFA_STA_SET_ENCRYPTION_TLV         (18)*/

+    wfaStaSetPSK,             /*    WFA_STA_SET_PSK_TLV                (19)*/

+    wfaStaSetEapTLS,          /*    WFA_STA_SET_EAPTLS_TLV             (20)*/

+    wfaStaSetUAPSD,           /*    WFA_STA_SET_UAPSD_TLV              (21)*/

+    wfaStaAssociate,          /*    WFA_STA_ASSOCIATE_TLV              (22)*/

+    wfaStaSetEapTTLS,         /*    WFA_STA_SET_EAPTTLS_TLV            (23)*/

+    wfaStaSetEapSIM,          /*    WFA_STA_SET_EAPSIM_TLV             (24)*/

+    wfaStaSetPEAP,            /*    WFA_STA_SET_PEAP_TLV               (25)*/

+    wfaStaSetIBSS,            /*    WFA_STA_SET_IBSS_TLV               (26)*/

+    wfaStaGetInfo,            /*    WFA_STA_GET_INFO_TLV               (27)*/

+    wfaDeviceGetInfo,         /*    WFA_DEVICE_GET_INFO_TLV            (28)*/

+    wfaDeviceListIF,          /*    WFA_DEVICE_LIST_IF_TLV]            (29)*/ 

+    wfaStaDebugSet,           /*    WFA_STA_DEBUG_SET                  (30)*/

+    wfaStaSetMode,            /*    WFA_STA_SET_MODE                   (31)*/

+    wfaStaSetWMM,             /*    WFA_STA_SET_WMM                    (32)*/

+    wfaStaSendNeigreq,	      /*    WFA_STA_SEND_NEIGREQ	       (33)*/

+    wfaStaSetSystime,	      /*    WFA_STA_SET_SYSTIME		       (34)*/

+    wfaStaSet11n,	      /*    WFA_STA_SET_11N		       (35)*/

+    wfaStaSetRifsTest,	      /*    WFA_STA_SET_RIFS_TEST	       (36)*/

+    wfaStaSetWireless,	      /*    WFA_STA_SET_WIRELESS	       (37)*/

+    wfaStaSendAddba,	      /*    WFA_STA_SEND_ADDBA		       (38)*/

+    wfaStaSendCoexistMgmt,    /*    WFA_STA_SEND_COEXIST_MGMT	       (39)*/

+    wfaStaSetDisconnect,      /*    WFA_STA_SET_DISCONNECT	       (40)*/

+    wfaStaSetEapFAST,         /*    WFA_STA_SET_EAPFAST_TLV            (41)*/

+    wfaStaSetEapAKA,          /*    WFA_STA_SET_EAPAKA_TLV             (42)*/

+    wfaStaReAssociate,        /*    WFA_STA_REASSOCIATE                (41)*/

+    wfaStaSetPwrSave,         /*    WFA_STA_SET_PWRSAVE                (42)*/

+    wfaStaResetDefault,       /*    WFA_STA_RESET_DEFAULT              (43)*/

+};

+    

+

+/*

+ * NotDefinedYet(): a dummy function

+ */

+int NotDefinedYet(int len, unsigned char *params, int *respLen, BYTE *respBuf)

+{

+    DPRINT_WARNING(WFA_WNG, "The command processing function not defined.\n");

+

+

+    /* need to send back a response */

+

+    return TRUE;

+}

diff --git a/src/tools/Wifi_ASD_test/lib/wfa_cs.c b/src/tools/Wifi_ASD_test/lib/wfa_cs.c
new file mode 100755
index 0000000..d084c41
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_cs.c
@@ -0,0 +1,3139 @@
+/****************************************************************************
+*  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+*
+*
+*  LICENSE
+*
+*  License is granted only to Wi-Fi Alliance members and designated
+*  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+*  the non-exclusive, worldwide, limited right to use, copy, import, export
+*  and distribute this software:
+*  (i) solely for noncommercial applications and solely for testing Wi-Fi
+*  equipment; and
+*  (ii) solely for the purpose of embedding the software into Authorized
+*  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+*  its customers utipnder a license with at least the same restrictions as
+*  contained in this License, including, without limitation, the disclaimer of
+*  warranty and limitation of liability, below..AN  The distribution rights
+*  granted in clause
+*  (ii), above, include distribution to third party companies who will
+*  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+*  without such third party$B!G(Bs private label. Other than expressly granted
+*  herein, this License is not transferable or sublicensable, and it does not
+*  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+*  reserves all rights not expressly granted herein..AN
+*.AN
+*  Except as specifically set forth above, commercial derivative works of
+*  this software or applications that use the Wi-Fi scripts generated by this
+*  software are NOT AUTHORIZED without specific prior written permission from
+*  Wi-Fi Alliance.
+*.AN
+*  Non-Commercial derivative works of this software for internal use are
+*  authorized and are limited by the same restrictions; provided, however,
+*  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+*  such derivative works under a perpetual, payment-free license to use,
+*  modify, and distribute such derivative works for purposes of testing Wi-Fi
+*  equipment.
+*.AN
+*  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+*  or promote products that are derived from or that use this software without
+*  specific prior written permission from Wi-Fi Alliance.
+*
+*  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+*  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+*  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+*  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+*  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+*  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+*  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+*  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+*  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+*   File: wfa_cs.c -- configuration and setup
+*   This file contains all implementation for the dut setup and control
+*   functions, such as network interfaces, ip address and wireless specific
+*   setup with its supplicant.
+*
+*   The current implementation is to show how these functions
+*   should be defined in order to support the Agent Control/Test Manager
+*   control commands. To simplify the current work and avoid any GPL licenses,
+*   the functions mostly invoke shell commands by calling linux system call,
+*   system("<commands>").
+*
+*   It depends on the differnt device and platform, vendors can choice their
+*   own ways to interact its systems, supplicants and process these commands
+*   such as using the native APIs.
+*
+*   Revision History:
+*        2006/03/10  -- initially created by qhu
+*        2006/06/01  -- BETA Release by qhu
+*        2006/06/13  -- 00.02 Release by qhu
+*        2006/06/30  -- 00.10 Release by qhu
+*        2006/07/10  -- 01.00 Release by qhu
+*        2006/09/01  -- 01.05 Release by qhu
+*        2006/10/26  -- 01.06 Released by qhu
+*                       replace hardcoded buf size with macro
+*        2006/12/02  -- bugs: 1. fixes incorrect order of getipconfig.sh
+*                                input parameters reported by p.schwann
+*                             2. will add a new network for wap_cli command
+*                                in case the network id 0 not present,
+*                                recommended by c.benson
+*                                the solution is to reimplement with calling
+*                                native C API
+*        2007/01/11  -- 01.10 released by qhu
+*        2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi
+*        2007/03/18  -- add file close statements
+*        2007/03/21  -- rename the file to avoid the confusion.
+*        2007/03/30  -- 01.40 WPA2 and Official WMM Beta Release by qhu
+*        2007/04/20  -- 02.00 WPA2 and Official WMM Release by qhu
+*        2007/08/15 --  02.10 WMM-Power Save release by qhu
+*        2007/10/10 --  02.20 Voice SOHO beta -- qhu
+*        2007/11/07 --  02.30 Voice HSO -- qhu
+*
+*/
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <poll.h>
+#include <bcmendian.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <iphlpapi.h>
+#endif
+
+#include "wfa_debug.h"
+#include "wfa_ver.h"
+#include "wfa_main.h"
+#include "wfa_types.h"
+#include "wfa_ca.h"
+#include "wfa_tlv.h"
+#include "wfa_sock.h"
+#include "wfa_tg.h"
+#include "wfa_cmds.h"
+#include "wfa_rsp.h"
+#include "wfa_miscs.h"
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+#include "wfa_wmmps.h"
+#endif
+#endif
+
+#define CERTIFICATES_PATH    "/etc/wpa_supplicant"
+#define TSPEC_VER 2
+#define TSPEC_BUF_SIZE 15
+#define MAX_TOKENS 15
+#define BYTE_0 0
+#define BYTE_1 1
+#define BYTE_2 2 
+#define TID_INDEX 4 
+#define NO_TSINFO 1 
+#define TID_MISMATCH 2 
+
+/* Some device may only support UDP ECHO, activate this line */
+//#define WFA_PING_UDP_ECHO_ONLY 1
+
+
+int g_serv_sock_desc;
+
+/* Start --> Modified as per BRCM 1.3 ASD */
+
+/* error code */
+#define BCM_OK			0
+#define BCM_BAD			1
+
+#define BCM_SSID_LEN_MAX	32
+#define BCM_SSID_MAX		32
+
+/* defines for BSS types */
+#define BCM_BSS_INVALID		0
+#define	BCM_BSS_INDEPENDENT	1
+#define BCM_BSS_INFRA		3
+#define	BCM_BSS_AUTO		4
+
+/* defines for WPA AITHENTICATION */
+#define BCM_WPA_AUTH_DISABLED	0x0
+#define BCM_WPA_AUTH_NONE	0x1
+#define BCM_WPA_AUTH_8021X	0x2
+#define BCM_WPA_AUTH_PSK	0x4
+#define BCM_WPA2_AUTH_8021X	0x40
+#define BCM_WPA2_AUTH_PSK	0x80
+
+#define BCM_WEP_KEY_SIZE_MAX	32
+#define BCM_8021X_ASSOC_TIMEOUT	3600
+#define BCM_PRI_KEY_BAD		(-1)
+
+typedef union bcmEapObj {
+	caStaSetEapTLS_t setEapTLS;
+	caStaSetEapTTLS_t setEapTTLS;
+	caStaSetEapSIM_t setEapSIM;
+	caStaSetEapPEAP_t setEapPEAP;
+	caStaSetEapFAST_t setEapFAST;
+	caStaSetEapAKA_t setEapAKA;
+} bcmEapObj_t;
+
+typedef struct bcmSsidObj
+{
+	char ssidStr[BCM_SSID_LEN_MAX + 1];
+	int bssType;
+	int channel;
+	int wsec;
+	int auth; /* 802.11 authentication : default 0 for open. */
+	int wpa_auth; /* WPA authentication: default 1 for WPA-NONE */
+	int uapsd;
+	char keys[4][BCM_WEP_KEY_SIZE_MAX]; /* wl addwep */
+	int primary_key;
+	BYTE passphrase[64]; /* wl set_pmk */
+	int powerSave;
+	/* UAPSD */
+	int maxSPLength;
+	int acBE;
+	int acBK;
+	int acVI;
+	int acVO;
+	/* EAP Types*/
+	bcmEapObj_t eapObj;  
+	int eapType;
+} bcmSsidObj_t;
+
+typedef struct bcmSsidObjTbl
+{
+	bcmSsidObj_t ssidObj[BCM_SSID_MAX];
+	uint addCnt;
+	uint delCnt;
+	uint entries;
+} bcmSsidObjTbl_t;
+
+bcmSsidObjTbl_t bsotbl;
+int bcmSsidIsGood(char *ssidStr);
+bcmSsidObj_t *bcmWfaSsidTblFreeEntry();
+bcmSsidObj_t *bcmWfaSsidTblSsidFind(char *ssidStr);
+bcmSsidObj_t *bcmWfaSsidObjTblAdd(char *ssidStr);
+void bcmWfaSsidObjTblDel(char *ssidStr);
+void bcmWfaSsidObjPrint(bcmSsidObj_t *bso);
+void bcmWfaSsidObjTblPrint(void);
+
+/* End --> Modified as per BRCM 1.3 ASD */
+
+/* Since the two definitions are used all over the CA function */
+char gCmdStr[WFA_CMD_STR_SZ];
+dutCmdResponse_t gGenericResp;
+
+/*
+* agtCmdProcGetVersion(): response "ca_get_version" command to controller
+*  input:  cmd --- not used
+*          valLen -- not used
+*  output: parms -- a buffer to store the version info response.
+*/
+
+int agtCmdProcGetVersion(int len, BYTE *parms, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t *getverResp = &gGenericResp;
+
+	DPRINT_INFO(WFA_OUT, "entering agtCmdProcGetVersion ...\n");
+
+	getverResp->status = STATUS_COMPLETE;
+	strncpy(getverResp->cmdru.version, WFA_SYSTEM_VER, 8);
+
+	wfaEncodeTLV(WFA_GET_VERSION_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)getverResp, respBuf);
+
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+	return TRUE;
+}
+
+/*
+* wfaStaAssociate():
+*    The function is to force the station wireless I/F to re/associate
+*    with the AP.
+*/
+int wfaStaAssociate(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	int retVal = TRUE;
+	dutCommand_t *assoc = (dutCommand_t *)caCmdBuf;
+	dutCmdResponse_t *staAssocResp = &gGenericResp;
+	/* Start: Modified as per BRCM 1.3 ASD */
+	int imode; /* 0 for ibss, 1 for infrastructure */
+	char ssidTarget[WFA_SSID_NAME_LEN];
+	bcmSsidObj_t *bso;
+	int idx;
+	char identity[WFA_BUFF_128],dummy[WFA_BUFF_128];
+
+	DPRINT_INFO(WFA_OUT, "entering wfaStaAssociate ...\n");
+	/* use 'ifconfig' command to bring down the interface (linux specific) */
+
+	memcpy(ssidTarget, assoc->cmdsu.ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			retVal = FALSE;
+			goto exit;
+		}
+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+			bcmWfaSsidObjPrint(bso);
+		}
+
+	}
+	imode = (bso->bssType == BCM_BSS_INDEPENDENT) ? 0 : 1;
+	sprintf(gCmdStr, "%s disassoc", rwl_client_path);
+	exec_process(gCmdStr);
+
+        asd_sleep(3); 
+	/*Default case will be non-802.1x associations*/
+	switch (bso->eapType) {
+		case BCM_EAP_TYPE_TLS:
+				strncpy(identity,bso->eapObj.setEapTLS.clientCertificate,sizeof(identity));
+		        	/* For EAPTLS, identity is taken as the file name of the Client certificate
+			         * since we do not have any username information in this mode
+			 	 */
+				printf("\n %s\n",identity);
+				strtok_r(identity,".",(char **)&dummy);
+				printf("\n %s\n",identity);
+				S_N_PRINTF(gCmdStr,sizeof(gCmdStr),"%s sh cnClient -A %s -ssid %s -%s -%s -tls "
+				"-usercert %s %s -identity %s -validate %s -timeout %d %s ", rwl_client_path,	
+				bso->eapObj.setEapTLS.intf, bso->eapObj.setEapTLS.ssid, 
+				bso->eapObj.setEapTLS.keyMgmtType, bso->eapObj.setEapTLS.encrptype, 
+				bso->eapObj.setEapTLS.clientCertificate, KEY_FILE, identity, 
+				bso->eapObj.setEapTLS.trustedRootCA, BCM_8021X_ASSOC_TIMEOUT, "%"); 
+				retVal = exec_process_cnclient(gCmdStr, rwl_client_path, rwl_wifi_flag);
+				break;
+		case BCM_EAP_TYPE_TTLS:
+				S_N_PRINTF(gCmdStr,sizeof(gCmdStr),"%s sh cnClient -A %s -ssid %s -%s -%s -ttls-%s "
+				"-user %s -password %s -identity %s -validate %s -timeout %d %s  ", rwl_client_path, 
+				bso->eapObj.setEapTTLS.intf, bso->eapObj.setEapTTLS.ssid, 
+				bso->eapObj.setEapTTLS.keyMgmtType, bso->eapObj.setEapTTLS.encrptype, TTLS_innerEAP, 
+				bso->eapObj.setEapTTLS.username, bso->eapObj.setEapTTLS.passwd, 
+				bso->eapObj.setEapTTLS.username, bso->eapObj.setEapTTLS.trustedRootCA, 
+				BCM_8021X_ASSOC_TIMEOUT, "%");
+				retVal = exec_process_cnclient(gCmdStr, rwl_client_path, rwl_wifi_flag);
+				break;
+		case BCM_EAP_TYPE_SIM:
+				S_N_PRINTF(gCmdStr,sizeof(gCmdStr),"%s sh cnClient -A %s -ssid %s -%s -%s -sim %s "
+				"-scpin %s -timeout %d %s ", rwl_client_path, bso->eapObj.setEapSIM.intf,
+				bso->eapObj.setEapSIM.ssid, bso->eapObj.setEapSIM.keyMgmtType, 
+				bso->eapObj.setEapSIM.encrptype, bso->eapObj.setEapSIM.username, 
+				bso->eapObj.setEapSIM.passwd, BCM_8021X_ASSOC_TIMEOUT, "%");
+				retVal = exec_process_cnclient(gCmdStr, rwl_client_path, rwl_wifi_flag);
+				break;
+		case BCM_EAP_TYPE_PEAP:
+				S_N_PRINTF(gCmdStr,sizeof(gCmdStr),"%s sh cnClient -A %s -ssid %s -%s -%s -peap-%s "
+				"-user %s -password %s -identity %s -timeout %d %s ", rwl_client_path, 
+				bso->eapObj.setEapPEAP.intf, bso->eapObj.setEapPEAP.ssid, 
+				bso->eapObj.setEapPEAP.keyMgmtType, bso->eapObj.setEapPEAP.encrptype, 
+				bso->eapObj.setEapPEAP.innerEAP, bso->eapObj.setEapPEAP.username,
+				bso->eapObj.setEapPEAP.passwd, bso->eapObj.setEapPEAP.username, 
+				BCM_8021X_ASSOC_TIMEOUT, "%");
+				retVal = exec_process_cnclient(gCmdStr, rwl_client_path, rwl_wifi_flag);
+				break;
+		case BCM_EAP_TYPE_FAST:
+				S_N_PRINTF(gCmdStr,sizeof(gCmdStr),"%s sh cnClient -A %s -ssid %s -%s -%s -fast-%s "
+				"-user %s -password %s -identity %s -validate %s -timeout %d %s ", rwl_client_path, 
+				bso->eapObj.setEapFAST.intf, bso->eapObj.setEapFAST.ssid, 
+				bso->eapObj.setEapFAST.keyMgmtType, bso->eapObj.setEapFAST.encrptype, 
+				bso->eapObj.setEapFAST.innerEAP, bso->eapObj.setEapFAST.username,
+				bso->eapObj.setEapFAST.passwd, bso->eapObj.setEapFAST.username,
+				bso->eapObj.setEapFAST.trustedRootCA, BCM_8021X_ASSOC_TIMEOUT, "%");
+				retVal = exec_process_cnclient(gCmdStr, rwl_client_path, rwl_wifi_flag);
+				break;
+		case BCM_EAP_TYPE_AKA:
+				S_N_PRINTF(gCmdStr,sizeof(gCmdStr),"%s sh cnClient -A %s -ssid %s -%s -%s -eap-aka "
+				"-user %s -password %s -identity %s -timeout %d %s ", rwl_client_path, 
+				bso->eapObj.setEapAKA.intf, bso->eapObj.setEapAKA.ssid, 
+				bso->eapObj.setEapAKA.keyMgmtType, bso->eapObj.setEapAKA.encrptype, 
+				bso->eapObj.setEapAKA.username,	bso->eapObj.setEapAKA.passwd, 
+				bso->eapObj.setEapAKA.username,BCM_8021X_ASSOC_TIMEOUT, "%");
+				retVal = exec_process_cnclient(gCmdStr, rwl_client_path, rwl_wifi_flag);
+				break;
+		default:	
+			/* Run the commands in the batching mode in case of wifi transport*/
+			if(rwl_wifi_flag) {
+				asd_sleep(1);
+				sprintf(gCmdStr, "%s seq_start", rwl_client_path);
+				exec_process(gCmdStr);
+			}
+	
+
+			asd_sleep(1);
+			if ((!imode) && bso->channel){
+				sprintf(gCmdStr, "%s channel %d", rwl_client_path, bso->channel);
+				exec_process(gCmdStr);
+			}
+
+			sprintf(gCmdStr, "%s infra %d", rwl_client_path, imode);
+			exec_process(gCmdStr);
+
+			/*Execute the command wme_apsd_sta only if the driver is down*/
+			sprintf(gCmdStr, "%s wme_apsd_sta %d %d %d %d %d", rwl_client_path, 
+			bso->maxSPLength, bso->acBE, bso->acBK, bso->acVI, bso->acVO);
+			exec_process(gCmdStr);
+
+			asd_sleep(3);
+			sprintf(gCmdStr, "%s up", rwl_client_path);
+			exec_process(gCmdStr);
+	
+			if(rwl_wifi_flag) {
+				sprintf(gCmdStr, "%s seq_stop", rwl_client_path);
+				exec_process(gCmdStr);
+			}
+
+			asd_sleep(2);
+			/* handle WEP keys */
+			for(idx = 0; idx < 4; idx++) {
+				if(bso->keys[idx][0] != '\0') {
+					sprintf(gCmdStr, "%s addwep %d %s", rwl_client_path, idx, bso->keys[idx]);
+				} else {
+					sprintf(gCmdStr, "%s rmwep %d", rwl_client_path, idx);
+				}
+				exec_process(gCmdStr);
+			}
+
+			/* set primary key */
+			if(bso->primary_key != BCM_PRI_KEY_BAD) {
+				sprintf(gCmdStr, "%s primary_key %d", rwl_client_path, bso->primary_key);
+				exec_process(gCmdStr);
+			}
+
+			/* security */
+			sprintf(gCmdStr, "%s wsec %d", rwl_client_path, bso->wsec);
+			exec_process(gCmdStr);
+
+			if(bso->passphrase[0] != '\0') {
+				sprintf(gCmdStr, "%s set_pmk %s", rwl_client_path, bso->passphrase);
+				exec_process(gCmdStr);
+			}
+	
+			if(bso->wpa_auth == BCM_WPA_AUTH_PSK) {
+				sprintf(gCmdStr, "%s sup_wpa 1", rwl_client_path );
+				exec_process(gCmdStr);	
+			} else if(bso->wpa_auth == BCM_WPA2_AUTH_PSK) {
+				sprintf(gCmdStr, "%s sup_wpa 2", rwl_client_path );
+				exec_process(gCmdStr);	
+			}
+
+			sprintf(gCmdStr, "%s auth %d", rwl_client_path, bso->auth);
+			exec_process(gCmdStr);
+
+			sprintf(gCmdStr, "%s wpa_auth %d", rwl_client_path, bso->wpa_auth);
+			exec_process(gCmdStr);
+
+			sprintf(gCmdStr, "%s ssid %s", rwl_client_path, ssidTarget);
+			exec_process(gCmdStr);
+	}
+/*
+ * Then report back to control PC for completion.
+ * This does not have failed/error status. The result only tells
+ * a completion.
+ */
+exit:
+	/* End: Modified as per BRCM 1.3 ASD   */
+
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	if(retVal == TRUE)
+		staAssocResp->status = STATUS_COMPLETE;
+	else
+		staAssocResp->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_ASSOCIATE_RESP_TLV, 4, (BYTE *)staAssocResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+	return retVal;  /* Modified as per BRCM 1.3 ASD   */
+}
+
+/*
+ * wfaStaReAssociate():
+ *    The function is to force the station wireless I/F to re/associate 
+ *    with the AP.
+ */
+int wfaStaReAssociate(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+   dutCommand_t *assoc = (dutCommand_t *)caCmdBuf;
+   dutCmdResponse_t *staAssocResp = &gGenericResp;
+
+   DPRINT_INFO(WFA_OUT, "entering wfaStaAssociate ...\n");
+   sprintf(gCmdStr, "%s mpc 0", rwl_client_path);
+   exec_process(gCmdStr);
+   sprintf(gCmdStr, "%s up", rwl_client_path);
+   exec_process(gCmdStr);
+   /* "wl reassoc" command is not able to associate completly and receives an Auto IP */
+   sprintf(gCmdStr, "%s reassoc %s", rwl_client_path, assoc->cmdsu.bssid);
+   exec_process(gCmdStr);
+   
+   staAssocResp->status = STATUS_COMPLETE;
+   wfaEncodeTLV(WFA_STA_ASSOCIATE_RESP_TLV, 4, (BYTE *)staAssocResp, respBuf);   
+   *respLen = WFA_TLV_HDR_LEN + 4;
+
+   return TRUE; 
+}
+
+/*
+* wfaStaGetIpConfig():
+* This function is to retriev the ip info including
+*     1. dhcp enable
+*     2. ip address
+*     3. mask
+*     4. primary-dns
+*     5. secondary-dns
+*
+*     The current implementation is to use a script to find these information
+*     and store them in a file.
+*/
+
+int wfaStaGetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	int   i = 0;
+#ifdef WIN32
+	int slen;
+	DWORD dwStatus;
+	IP_ADAPTER_INFO AdapterInfo[16];	// Allocate information for up to 16 NICs
+	PIP_ADAPTER_INFO pAdapterInfo;
+	DWORD dwBufLen = sizeof(AdapterInfo);	// Save the memory size of buffer
+#endif
+
+	dutCommand_t *getIpConf = (dutCommand_t *)caCmdBuf;
+	dutCmdResponse_t *ipconfigResp = &gGenericResp;
+	char *ifname = getIpConf->intf;
+	caStaGetIpConfigResp_t *ifinfo = &ipconfigResp->cmdru.getIfconfig;
+#ifndef WIN32 
+	FILE *shell_fpt;
+	DPRINT_INFO(WFA_OUT,"Entering staGetIpConfig...\n");
+	/* Start: Modified as per BRCM 1.3 ASD */
+	/* Dhcp */
+	sprintf(gCmdStr,"ps ax | grep -v grep | grep dhcli | wc -l >%s 2>&1", TMP_FILE_PATH);
+
+	system(gCmdStr);
+
+	shell_fpt = fopen(TMP_FILE_PATH, "rb");
+	fread(gCmdStr, sizeof(char), 20, shell_fpt);
+	fclose(shell_fpt);
+
+	remove(TMP_FILE_PATH);
+	if (atoi(gCmdStr) >= 1)
+		ifinfo->isDhcp = 1;
+	else
+		ifinfo->isDhcp = 0;
+	/* ipaddr */
+	sprintf(gCmdStr, "%s %s | grep 'inet addr' |  cut -d: -f2 | cut -d' ' -f1>%s 2>&1",
+	IFCONFIG_PATH, ifname, TMP_FILE_PATH);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+
+	system(gCmdStr);
+
+	shell_fpt = fopen(TMP_FILE_PATH, "rb");
+	ifinfo->ipaddr[0] = 0;
+	fread(ifinfo->ipaddr, sizeof(char), 20, shell_fpt);
+	ifinfo->ipaddr[strlen(ifinfo->ipaddr) - 1] = 0; /* Purge newline */
+	if(ifinfo->ipaddr[0] == 0)
+		strncpy(ifinfo->ipaddr, "none", 15);
+	fclose(shell_fpt);
+
+	remove(TMP_FILE_PATH);
+	/* mask */
+	sprintf(gCmdStr, "%s %s | grep 'inet addr' |  cut -d: -f4 >%s 2>&1",
+	IFCONFIG_PATH, ifname, TMP_FILE_PATH);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+
+	system(gCmdStr);
+
+	shell_fpt = fopen(TMP_FILE_PATH, "rb");
+	ifinfo->mask[0] = 0;
+	fread(ifinfo->mask, sizeof(char), 20, shell_fpt);
+	ifinfo->mask[strlen(ifinfo->mask) - 1] = 0; /* Purge newline */
+	if(ifinfo->mask[0] == 0)
+		strcpy(ifinfo->mask, "none");
+	fclose(shell_fpt);
+
+	remove(TMP_FILE_PATH);
+	/* dns */
+	sprintf(gCmdStr, "cat /etc/resolv.conf | grep nameserver | awk '{print $2}'>%s 2>&1", TMP_FILE_PATH);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+
+	system(gCmdStr);
+
+	shell_fpt = fopen(TMP_FILE_PATH, "rb");
+	for (i = 0; i < WFA_MAX_DNS_NUM; i++){
+		fgets(ifinfo->dns[i], WFA_IP_ADDR_STR_LEN, shell_fpt);
+		if (ifinfo->dns[i][0])
+			ifinfo->dns[i][strlen(ifinfo->dns[i]) - 1] = 0; /* Purge newline */
+		else
+			strcpy(ifinfo->dns[i], "NOTDEF");
+	}
+
+	fclose(shell_fpt);
+
+	remove(TMP_FILE_PATH);
+	/* End: Modified as per BRCM 1.3 ASD */
+
+#else
+	/* The eth1 interface name in WinCE is BCMSDDHD1 and 
+	* the eth0 interface name is VMINI1. The command that comes in from Linux CA
+	* will send the eth0 or eth1 interface, which is then translated to WinCE 
+	* specific interface name to get the Adapters information*/
+	if(!strcmp(getIpConf->intf, "eth1")) {
+		strcpy(getIpConf->intf , "BCMSDDHD1");
+	} else if(!strcmp(getIpConf->intf, "eth0"))	{
+		strcpy(getIpConf->intf , "VMINI1");
+	} 
+	/* Get the network interface information */
+	dwStatus = GetAdaptersInfo(// Call GetAdapterInfo
+		AdapterInfo,// [out] buffer to receive data
+		&dwBufLen);// [in] size of receive data buffer
+
+	pAdapterInfo= AdapterInfo;// Contains pointer to current adapter info
+
+	while(pAdapterInfo){
+		if(strcmp(pAdapterInfo->AdapterName, getIpConf->intf)==0){
+			/*Check if DHCP Enabled*/
+			if(pAdapterInfo->DhcpEnabled)
+				ifinfo->isDhcp = 1;
+			else
+				ifinfo->isDhcp = 0;
+
+			/*IP Address */
+			strcpy(ifinfo->ipaddr, pAdapterInfo->IpAddressList.IpAddress.String);
+			ifinfo->ipaddr[15]='\0';
+
+			/*Subnet mask*/
+			strcpy(ifinfo->mask,pAdapterInfo->IpAddressList.IpMask.String);
+			slen = strlen(ifinfo->mask);
+			ifinfo->mask[slen+1] = '\0';
+
+			/*Primary DNS*/
+			strcpy(ifinfo->dns[0], pAdapterInfo->PrimaryWinsServer.IpAddress.String);
+			slen = strlen(ifinfo->dns[0]);
+
+			/*Secondary DNS*/
+			strcpy(ifinfo->dns[1], pAdapterInfo->SecondaryWinsServer.IpAddress.String);
+			slen = strlen(ifinfo->dns[1]);
+		}
+		pAdapterInfo = pAdapterInfo->Next;
+	}
+#endif
+	/*
+	* Report back the results
+	*/
+	ipconfigResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_GET_IP_CONFIG_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)ipconfigResp, respBuf);
+
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+	DPRINT_INFO(WFA_OUT, "%i %i %s %s %s %s %i\n", ipconfigResp->status,
+		ifinfo->isDhcp, ifinfo->ipaddr, ifinfo->mask,
+		ifinfo->dns[0], ifinfo->dns[1], *respLen);
+	return TRUE;
+}
+
+/*
+* wfaStaSetIpConfig():
+*   The function is to set the ip configuration to a wireless I/F.
+*   1. IP address
+*   2. Mac address
+*   3. default gateway
+*   4. dns nameserver (pri and sec).
+*
+* Set the IP address and the mask value only if the the DHCP(ipconfig->isDhcp) 
+* is disabled. Otherwise enable the DHCP for the network interface.
+*/
+int wfaStaSetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCommand_t *setIpConf = (dutCommand_t *)caCmdBuf;
+	caStaSetIpConfig_t *ipconfig = &setIpConf->cmdsu.ipconfig;
+	dutCmdResponse_t *staSetIpResp = &gGenericResp;
+
+#ifndef WIN32
+	pid_t pid;
+	int status;
+	DPRINT_INFO(WFA_OUT, "interface = %s, ipaddr = %s, dhcp = %d\r\n",ipconfig->intf,ipconfig->ipaddr,ipconfig->isDhcp);
+	/* Start: Modified as per BRCM 1.3 ASD */
+	if(!ipconfig->isDhcp)
+	{
+		if (!strlen(ipconfig->intf) || !strlen(ipconfig->ipaddr) || !strlen(ipconfig->mask))
+		{
+			staSetIpResp->status = STATUS_ERROR;
+			wfaEncodeTLV(WFA_STA_SET_IP_CONFIG_RESP_TLV, 4, (BYTE *)staSetIpResp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+			return TRUE; /* changed to be FALSE? */
+		}
+		sprintf(gCmdStr, "killall -9 dhclient");
+		exec_process(gCmdStr);
+		sprintf(gCmdStr, "%s %s %s ", IFCONFIG_PATH, ipconfig->intf, ipconfig->ipaddr);
+		if (strlen(ipconfig->mask))
+			sprintf(&gCmdStr[strlen(gCmdStr)], "netmask %s ", ipconfig->mask);
+		exec_process(gCmdStr);
+		DPRINT_INFO(WFA_OUT, "%s\n", "doing ifconfig");
+		/* End: Modified as per BRCM 1.3 ASD */
+
+		/* use command 'route add' to set set gatewway (linux specific) */
+		if(ipconfig->defGateway[0] != '\0')
+		{
+			sprintf(gCmdStr, "%s add default gw %s > /dev/null 2>&1", ROUTE_PATH, ipconfig->defGateway);
+			exec_process(gCmdStr);
+			DPRINT_INFO(WFA_OUT, "%s\n", "doing route add");
+		}
+
+		/* set dns (linux specific) */
+
+		/* Start: Modified as per BRCM 1.3 ASD */
+                /* if somedata is given as primary-dns then we'll display it
+                   else we'll show it as NOTDEF */ 
+		if(strcmp(ipconfig->pri_dns, "\0"))
+		{
+			/* set dns (linux specific) */
+			sprintf(gCmdStr, "cp /etc/resolv.conf /tmp/resolv.conf.bk");
+			exec_process(gCmdStr);
+			sprintf(gCmdStr, "echo nameserver %s > /etc/resolv.conf", ipconfig->pri_dns);
+			exec_process(gCmdStr);
+                        /* if no secondary-dns is given along with primary-dns
+                           then we'll have to show it as NOTDEF */ 
+                        if(strcmp(ipconfig->sec_dns, "\0"))        
+			    sprintf(gCmdStr, "echo nameserver %s >> /etc/resolv.conf", ipconfig->sec_dns);
+                        else
+			    sprintf(gCmdStr, "echo nameserver %s >> /etc/resolv.conf", "NOTDEF");
+			exec_process(gCmdStr);
+		}
+                /* In case,no primary or secondary dns is given,it will print them as
+                   NOTDEF */   
+                else
+                {
+                                    
+			sprintf(gCmdStr, "cp /etc/resolv.conf /tmp/resolv.conf.bk");
+			exec_process(gCmdStr);
+			sprintf(gCmdStr, "echo nameserver %s > /etc/resolv.conf", "NOTDEF");
+			exec_process(gCmdStr);
+			sprintf(gCmdStr, "echo nameserver %s >> /etc/resolv.conf", "NOTDEF");
+			exec_process(gCmdStr);
+		}
+	}
+	else
+	{
+		/* dhcp is enabled */
+		sprintf(gCmdStr, "killall -9 dhclient");
+		exec_process(gCmdStr);
+		/* Wait for couple of seconds for dhclient to exit cleanly */
+		asd_sleep(2);
+		if((pid = fork()) == 0)
+		{
+			close(gagtSockfd);
+			close(g_serv_sock_desc);
+			sprintf(gCmdStr, "%s %s",DHCLIENT_PATH, ipconfig->intf);
+			/* execl("/sbin/dhclient",gCmdStr,NULL);*/
+			exec_process(gCmdStr);
+			_exit(0);
+		}
+		wait(&status);
+	}
+	/* End: Modified as per BRCM 1.3 ASD */
+#endif
+
+	/*
+	* report status
+	*/
+	staSetIpResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_IP_CONFIG_RESP_TLV, 4, (BYTE *)staSetIpResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/*
+* wfaStaVerifyIpConnection():
+* The function is to verify if the station has IP connection with an AP by
+* send ICMP/pings to the AP.
+*/
+
+int wfaStaVerifyIpConnection(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCommand_t *verip = (dutCommand_t *)caCmdBuf;
+	dutCmdResponse_t *verifyIpResp = &gGenericResp;
+
+
+#ifdef WIN32
+	char tempip[30];
+#else
+	char *tempip;
+	FILE *shell_fpt;
+#endif
+
+#ifndef WFA_PING_UDP_ECHO_ONLY
+
+	DPRINT_INFO(WFA_OUT, "Entering wfaStaVerifyIpConnection ...\n");
+#ifndef WIN32 
+	tempip = (char*)malloc(30);
+#endif
+	/* set timeout value in case not set */
+	if(verip->cmdsu.verifyIp.timeout <= 0)
+	{
+		verip->cmdsu.verifyIp.timeout = 10;
+	}
+
+	if (strlen(verip->cmdsu.verifyIp.dipaddr) == 0 )
+	{
+		verifyIpResp->status = STATUS_ERROR;
+		wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, 4, (BYTE *)&verifyIpResp, respBuf);
+		*respLen = WFA_TLV_HDR_LEN + 4;
+		DPRINT_ERR(WFA_ERR, "Could not execute %s\n", gCmdStr);
+		return FALSE;
+	}
+
+	strcpy(tempip,verip->cmdsu.verifyIp.dipaddr);
+
+	strtok(tempip,". ");
+	strtok(tempip,". ");
+	strtok(tempip,". ");
+	strtok(tempip,". ");
+
+	if( atoi(tempip) >= 255 )
+	{
+		verifyIpResp->status = STATUS_ERROR;
+		wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, 4, (BYTE *)&verifyIpResp, respBuf);
+		*respLen = WFA_TLV_HDR_LEN + 4;
+		return TRUE;
+	}
+
+#ifndef WIN32
+	/* Start: Modified as per BRCM 1.3 ASD */
+	/* execute the ping command  and pipe the result to a tmp file */
+	memset(gCmdStr, 0, sizeof(gCmdStr));
+	sprintf(gCmdStr, "%s -c 3 -q %s >>%s", PING_PATH, verip->cmdsu.verifyIp.dipaddr, PINGOUT_FILE_PATH);	
+	exec_process(gCmdStr);
+
+	asd_sleep(1);
+	verifyIpResp->status = STATUS_COMPLETE;
+	sprintf(gCmdStr, "cat %s | grep transmitted | awk '{print $4}'>%s 2>&1",
+	PINGOUT_FILE_PATH, TMP_FILE_PATH);
+
+	if (system(gCmdStr) < 0) {
+		DPRINT_ERR(WFA_ERR, "\n Not able to execute verify ip cmd\n");
+		verifyIpResp->cmdru.connected = 0;
+	} 
+
+
+	shell_fpt = fopen(TMP_FILE_PATH, "rb");
+
+	if (shell_fpt == NULL) {
+		DPRINT_ERR(WFA_ERR, "\nShell Cmd:File open error\n");
+		verifyIpResp->cmdru.connected = 0;
+	}
+
+	fread(gCmdStr, sizeof(char), 20, shell_fpt);
+	fclose(shell_fpt);
+
+	remove(TMP_FILE_PATH);
+	remove(PINGOUT_FILE_PATH);
+	if(atoi(gCmdStr) == 0)
+		verifyIpResp->cmdru.connected = 0;
+	else
+		verifyIpResp->cmdru.connected = 1;
+
+	printf("\ngCmdStr is:%s\n", gCmdStr);
+#ifdef DEBUG
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+#endif
+	/* End: Modified as per BRCM 1.3 ASD */
+#else
+#endif
+
+#else
+	int btSockfd;
+	struct pollfd fds[2];
+	int timeout = 2000;
+	char anyBuf[64];
+	struct sockaddr_in toAddr;
+	int done = 1, cnt = 0, ret, nbytes;
+
+	verifyIpResp->status = STATUS_COMPLETE;
+	verifyIpResp->cmdru.connected = 0;
+
+	btSockfd = wfaCreateUDPSock("127.0.0.1", WFA_UDP_ECHO_PORT);
+
+	if(btSockfd == -1)
+	{
+		verifyIpResp->status = STATUS_ERROR;
+		wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, 4, (BYTE *)verifyIpResp, respBuf);
+		*respLen = WFA_TLV_HDR_LEN + 4;
+		return FALSE;
+	}
+
+	toAddr.sin_family = AF_INET;
+	toAddr.sin_addr.s_addr = inet_addr(verip->cmdsu.verifyIp.dipaddr);
+	toAddr.sin_port = htons(WFA_UDP_ECHO_PORT);
+
+	while(done)
+	{
+		wfaTrafficSendTo(btSockfd, (char *)anyBuf, 64, (struct sockaddr *)&toAddr);
+		cnt++;
+
+		fds[0].fd = btSockfd;
+		fds[0].events = POLLIN | POLLOUT;
+
+		ret = poll(fds, 1, timeout);
+		switch(ret)
+		{
+		case 0:
+			/* it is time out, count a packet lost*/
+			break;
+		case -1:
+			/* it is an error */
+		default:
+			{
+				switch(fds[0].revents)
+				{
+				case POLLIN:
+				case POLLPRI:
+				case POLLOUT:
+					nbytes = wfaTrafficRecv(btSockfd, (char *)anyBuf, (struct sockaddr *)&toAddr);
+					if(nbytes != 0)
+						verifyIpResp->cmdru.connected = 1;
+					done = 0;
+					break;
+				default:
+					/* errors but not care */
+					;
+				}
+			}
+		}
+		if(cnt == 3)
+		{
+			done = 0;
+		}
+	}
+#endif
+
+	wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)verifyIpResp, respBuf);
+
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+	return TRUE;
+}
+
+/*
+* wfaSetEncryption():
+*   The function is to set the wireless interface with WEP or none.
+*   Input parameters:
+*     1. I/F
+*     2. ssid
+*     3. encpType - wep or none
+*     Optional:
+*     4. key1
+*     5. key2
+*     6. key3
+*     7. key4
+*     8. activeKey Index
+*/
+
+int wfaSetEncryption(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetEncryption_t *setEncryp = (caStaSetEncryption_t *)caCmdBuf;
+	dutCmdResponse_t *setEncrypResp = &gGenericResp;
+	int idx; /* Modified as per BRCM 1.3 ASD */
+	/* Start: Modified as per BRCM 1.3 ASD */
+	int retVal = TRUE;
+	bcmSsidObj_t *bso;
+	char * ssidStr;
+
+	DPRINT_INFO(WFA_OUT, "wfaSetEncryption()\n");
+
+	/* Save the settings for when we need them */
+
+	ssidStr = setEncryp->ssid;
+
+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
+			retVal = FALSE;
+			goto exit;
+		}
+	}
+
+	/* set Key management to NONE (NO WPA) for plaintext or WEP */
+	bso->wpa_auth = BCM_WPA_AUTH_DISABLED;
+
+	for(idx = 0; idx < 4; idx++) {
+		if(setEncryp->keys[idx][0] != '\0') {
+			strcpy(bso->keys[idx], setEncryp->keys[idx]);
+		} else {
+			memset(bso->keys[idx],0,BCM_WEP_KEY_SIZE_MAX);
+		}
+	}
+
+	if ((setEncryp->activeKeyIdx > 0) && (setEncryp->activeKeyIdx < 5)) {
+		/* move the index range from (1 to 4) to (0 to 3) */
+		bso->primary_key = setEncryp->activeKeyIdx - 1;
+	}
+
+	bso->wsec = (!setEncryp->encpType) ? 0 : 1;
+
+	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+		bcmWfaSsidObjPrint(bso);
+	}
+
+exit:
+	/* End: Modified as per BRCM 1.3 ASD */
+
+	setEncrypResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_ENCRYPTION_RESP_TLV, 4, (BYTE *)setEncrypResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return retVal; /* Modified as per BRCM 1.3 ASD */
+}
+
+
+int wfaSetEncryption1(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetEncryption_t *setEncryp = (caStaSetEncryption_t *)caCmdBuf;
+	dutCmdResponse_t *setEncrypResp = &gGenericResp;
+	int idx;
+	/* Start: Modified as per BRCM 1.3 ASD */
+	int retVal = TRUE;
+	bcmSsidObj_t *bso;
+	char * ssidStr;
+
+	DPRINT_INFO(WFA_OUT, "wfaSetEncryption1()\n");
+
+	/* Save the settings for when we need them */
+
+	ssidStr = setEncryp->ssid;
+	/* SetSSID */
+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
+			retVal = FALSE;
+			goto exit;
+		}
+	}
+
+	/* set Key management to NONE (NO WPA) for plaintext or WEP */
+	bso->wpa_auth = BCM_WPA_AUTH_DISABLED;
+
+	for(idx = 0; idx < 4; idx++) {
+		if(setEncryp->keys[idx][0] != '\0') {
+			strcpy(bso->keys[idx], setEncryp->keys[idx]);
+		} else {
+			memset(bso->keys[idx], 0, BCM_WEP_KEY_SIZE_MAX);
+		}
+	}
+
+	if ((setEncryp->activeKeyIdx > 0) && (setEncryp->activeKeyIdx < 5)) {
+		/* move the index range from (1 to 4) to (0 to 3) */
+		bso->primary_key = setEncryp->activeKeyIdx - 1;
+	}
+
+	bso->wsec = (!setEncryp->encpType) ? 0 : 1;
+
+	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+		bcmWfaSsidObjPrint(bso);
+	}
+
+exit:
+	/* End: Modified as per BRCM 1.3 ASD */
+
+	setEncrypResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_ENCRYPTION_RESP_TLV, 4, (BYTE *)setEncrypResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return retVal; /* Modified as per BRCM 1.3 ASD */
+}
+
+
+/*
+* wfaStaSetEapTLS():
+*   This is to set
+*   1. ssid
+*   2. encrypType - tkip or aes-ccmp
+*   3. keyManagementType - wpa or wpa2
+*   4. trustedRootCA
+*   5. clientCertificate
+*/
+int wfaStaSetEapTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetEapTLS_t *setTLS = (caStaSetEapTLS_t *)caCmdBuf;
+	dutCmdResponse_t *setEapTlsResp = &gGenericResp;
+	bcmSsidObj_t *bso;
+	char ssidTarget[WFA_SSID_NAME_LEN];
+
+	DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEapTLS ...\n");
+
+	memcpy(ssidTarget, setTLS->ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			return FALSE;
+		}
+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+			bcmWfaSsidObjPrint(bso);
+		}
+
+	}
+	memcpy(&(bso->eapObj.setEapTLS), setTLS, sizeof(caStaSetEapTLS_t));
+	bso->eapType = BCM_EAP_TYPE_TLS;
+
+	if(strstr(bso->eapObj.setEapTLS.encrptype,"aes-ccmp"))
+		strncpy(bso->eapObj.setEapTLS.encrptype, AES_ENCPTYPE, AES_LEN) ;
+	setEapTlsResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_EAPTLS_RESP_TLV, 4, (BYTE *)setEapTlsResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+	return TRUE;
+}
+
+/*
+* The function is to set
+*   1. ssid
+*   2. passPhrase
+*   3. keyMangementType - wpa/wpa2
+*   4. encrypType - tkip or aes-ccmp
+*/
+
+int wfaStaSetPSK(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetPSK_t *setPSK = (caStaSetPSK_t *)caCmdBuf;
+	dutCmdResponse_t *setPskResp = &gGenericResp;
+
+	/* Start: Modified as per BRCM 1.3 ASD */
+	int retVal = TRUE;
+	bcmSsidObj_t *bso;
+	char *ssidStr;
+
+	DPRINT_INFO(WFA_OUT, "wfaStaSetPSK()");
+
+	ssidStr = setPSK->ssid;
+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
+			retVal = FALSE;
+			goto exit;
+		}
+	}
+
+	if (!strcmp(setPSK->keyMgmtType, "wpa")) {
+		bso->wpa_auth = BCM_WPA_AUTH_PSK; /* WPA-PSK/WPA-Personal */
+	} else if (!strcmp(setPSK->keyMgmtType, "wpa2")) {
+		bso->wpa_auth = BCM_WPA2_AUTH_PSK; /* WPA2-PSK/WPA2-Personal */
+	} else {
+		DPRINT_ERR(WFA_OUT, "invalid key_mgmt %s", setPSK->keyMgmtType);
+		retVal = FALSE;
+		goto exit;
+	}
+
+	DPRINT_INFO(WFA_OUT, "wpa_auth %d\n", bso->wpa_auth);
+
+	if (setPSK->encpType == ENCRYPT_TKIP) {
+		bso->wsec = 3;
+	} else if (setPSK->encpType == ENCRYPT_AESCCMP) {
+		bso->wsec = 7;
+	} else {
+		DPRINT_ERR(WFA_OUT, "invalid encpType %d", setPSK->encpType);
+		goto exit;
+	}
+	DPRINT_INFO(WFA_OUT, "encpType %d wsec %d\n", setPSK->encpType, bso->wsec);
+
+
+	strncpy((char *)bso->passphrase, (char *)setPSK->passphrase, 64);
+	bso->auth = 0;
+
+	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+		bcmWfaSsidObjPrint(bso);
+	}
+
+	retVal = TRUE;
+
+exit:
+	/* End: Modified as per BRCM 1.3 ASD */
+
+	setPskResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_PSK_RESP_TLV, 4, (BYTE *)setPskResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return retVal; /*  Modified as per BRCM 1.3 ASD */
+}
+
+
+/*
+* wfaStaGetInfo():
+* Get vendor specific information in name/value pair by a wireless I/F.
+*/
+int wfaStaGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t infoResp;
+	dutCommand_t *getInfo = (dutCommand_t *)caCmdBuf;
+	FILE *tmpfd;
+	DPRINT_INFO(WFA_OUT, "Entering wfaStaGetInfo.....\n");
+	/*
+	* Normally this is called to retrieve the vendor information
+	* from a interface, no implement yet
+	*/
+#ifndef WIN32
+	S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s nmode &> %s", rwl_client_path, TEMP_FILE_PATH);
+#else
+	S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s nmode > %s 2>&1", rwl_client_path, TEMP_FILE_PATH);
+#endif
+	exec_process(gCmdStr);
+	if((tmpfd = fopen(TEMP_FILE_PATH, "r")) == NULL){
+		infoResp.status = STATUS_ERROR;
+		wfaEncodeTLV(WFA_STA_GET_INFO_RESP_TLV, 4, (BYTE *)&infoResp, respBuf);
+		*respLen = WFA_TLV_HDR_LEN + 4;
+		return TRUE;
+	}
+	fgets(gCmdStr, sizeof(gCmdStr), tmpfd);
+	Cleanup_File(tmpfd);
+/*
+ * If it is n mode supported card then it wont reply Unsupported or error 
+ */
+	if (((strstr(gCmdStr, "Unsupported")) != NULL) ||
+	 ((strstr(gCmdStr, "error")) != NULL)) {
+		S_N_PRINTF(infoResp.cmdru.info, sizeof(infoResp.cmdru.info), "interface,%s,vendor,Broadcom,cardtype,802.11a/b/g", getInfo->intf);
+	}
+	else {
+		S_N_PRINTF(infoResp.cmdru.info, sizeof(infoResp.cmdru.info), "interface,%s,vendor,Broadcom,cardtype,802.11a/b/g/n", getInfo->intf);
+	}
+	infoResp.status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_GET_INFO_RESP_TLV, sizeof(infoResp), (BYTE *)&infoResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(infoResp);
+	return TRUE;
+}
+
+int wfaStaGetTestData(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	//    dutCmdResponse_t dataResp;
+	//    dutCommand_t *testData = (dutCommand_t *)caCmdBuf;
+
+	/*
+	* This is to trasfer the test log (file) back to console
+	* It has not decided to use in-band or out of band. Will be updated
+	* in a new release soon.
+	*/
+
+	return TRUE;
+}
+
+/*
+* wfaStaSetEapTTLS():
+*   This is to set
+*   1. ssid
+*   2. username
+*   3. passwd
+*   4. encrypType - tkip or aes-ccmp
+*   5. keyManagementType - wpa or wpa2
+*   6. trustedRootCA
+*/
+int wfaStaSetEapTTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+
+	caStaSetEapTTLS_t *setTTLS = (caStaSetEapTTLS_t *)caCmdBuf;
+	dutCmdResponse_t *setEapTtlsResp = &gGenericResp;
+	bcmSsidObj_t *bso;
+	char ssidTarget[WFA_SSID_NAME_LEN];
+
+	memcpy(ssidTarget, setTTLS->ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			return FALSE;
+			
+		}
+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+			bcmWfaSsidObjPrint(bso);
+		}
+
+	}
+		
+	memcpy(&(bso->eapObj.setEapTTLS), setTTLS, sizeof(caStaSetEapTTLS_t));
+	bso->eapType = BCM_EAP_TYPE_TTLS;
+
+	if(strstr(bso->eapObj.setEapTTLS.encrptype,"aes-ccmp"))
+			strncpy(bso->eapObj.setEapTTLS.encrptype, AES_ENCPTYPE, AES_LEN) ;
+	setEapTtlsResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_EAPTTLS_RESP_TLV, 4, (BYTE *)setEapTtlsResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/*
+* wfaStaSetEapSIM():
+*   This is to set
+*   1. ssid
+*   2. user name
+*   3. passwd
+*   4. encrypType - tkip or aes-ccmp
+*   5. keyMangementType - wpa or wpa2
+*/
+int wfaStaSetEapSIM(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetEapSIM_t *setSIM = (caStaSetEapSIM_t *)caCmdBuf;
+	dutCmdResponse_t *setEapSimResp = &gGenericResp;
+	bcmSsidObj_t *bso;
+	char ssidTarget[WFA_SSID_NAME_LEN];
+
+	memcpy(ssidTarget, setSIM->ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			return FALSE;
+		}
+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+			bcmWfaSsidObjPrint(bso);
+		}
+
+	}
+	
+	memcpy(&(bso->eapObj.setEapSIM), setSIM, sizeof(caStaSetEapSIM_t));
+	bso->eapType = BCM_EAP_TYPE_SIM;
+
+	if(strstr(bso->eapObj.setEapSIM.encrptype,"aes-ccmp"))
+			strncpy(bso->eapObj.setEapSIM.encrptype, AES_ENCPTYPE, AES_LEN) ;
+	setEapSimResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_EAPSIM_RESP_TLV, 4, (BYTE *)setEapSimResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/*
+* wfaStaSetPEAP()
+*   This is to set
+*   1. ssid
+*   2. user name
+*   3. passwd
+*   4. encryType - tkip or aes-ccmp
+*   5. keyMgmtType - wpa or wpa2
+*   6. trustedRootCA
+*   7. innerEAP
+*   8. peapVersion
+*/
+int wfaStaSetPEAP(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetEapPEAP_t *setPEAP = (caStaSetEapPEAP_t *)caCmdBuf;
+	dutCmdResponse_t *setPeapResp = &gGenericResp;
+	bcmSsidObj_t *bso;
+	char ssidTarget[WFA_SSID_NAME_LEN];
+
+	memcpy(ssidTarget, setPEAP->ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			return FALSE;
+		}
+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+			bcmWfaSsidObjPrint(bso);
+		}
+
+	}
+	
+	memcpy(&(bso->eapObj.setEapPEAP), setPEAP, sizeof(caStaSetEapPEAP_t));
+	bso->eapType = BCM_EAP_TYPE_PEAP;
+
+	if(strstr(bso->eapObj.setEapPEAP.encrptype,"aes-ccmp"))
+			strncpy(bso->eapObj.setEapPEAP.encrptype, AES_ENCPTYPE, AES_LEN) ;
+	setPeapResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_PEAP_RESP_TLV, 4, (BYTE *)setPeapResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/*
+* wfaStaSetUAPSD()
+*    This is to set
+*    1. maxSPLength - 0,1,2,or 4
+*    2. acBE
+*    3. acBK
+*    4. acVI
+*    5. acVO
+*/
+int wfaStaSetUAPSD(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	int retVal = TRUE;
+	caStaSetUAPSD_t *setUAPSD = (caStaSetUAPSD_t *)caCmdBuf;
+	/* char *ifname = setUAPSD->intf; */ /* Removed as per BRCM 1.3 ASD */
+	dutCmdResponse_t *setUAPSDResp = &gGenericResp;
+	/* Start: Modified as per BRCM 1.3 ASD */
+	bcmSsidObj_t *bso;
+	char *ssidStr;
+
+	DPRINT_INFO(WFA_OUT, "Entering StaSetUAPSD ...\n");
+	DPRINT_INFO(WFA_OUT, "maxSPLength %d acBE %d acBK %d acVI %d acVO %d\n",
+		setUAPSD->maxSPLength, setUAPSD->acBE, setUAPSD->acBK, setUAPSD->acVI, setUAPSD->acVO);
+
+	ssidStr = setUAPSD->ssid;
+
+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
+			retVal = FALSE;
+			goto exit;
+		}
+	}
+	
+	if (rwl_wifi_flag) {
+		/* Use the batching mode */
+		asd_sleep(1);
+		sprintf (gCmdStr,"%s seq_start",rwl_client_path);
+		exec_process (gCmdStr);
+	}
+	
+	/* Get the driver down */
+	sprintf (gCmdStr,"%s down",rwl_client_path);
+	exec_process (gCmdStr);
+	bso->maxSPLength = setUAPSD->maxSPLength;
+	bso->acBE = setUAPSD->acBE;
+	bso->acBK = setUAPSD->acBK;
+	bso->acVI = setUAPSD->acVI;
+	bso->acVO = setUAPSD->acVO;
+	
+	sprintf(gCmdStr,"%s wme_apsd_sta %d %d %d %d %d",rwl_client_path,
+			bso->maxSPLength,bso->acBE,bso->acBK,bso->acVI,bso->acVO);
+	exec_process(gCmdStr);
+	/* Get the driver up*/
+	sprintf (gCmdStr,"%s up",rwl_client_path);
+	exec_process (gCmdStr);
+	
+	sleep (1);
+	/* Setting up ssid */
+	sprintf (gCmdStr,"%s join %s",rwl_client_path,setUAPSD->ssid);
+	exec_process(gCmdStr);
+	
+	if (rwl_wifi_flag) {
+		/* End the batching sequence */
+		asd_sleep(1);
+		sprintf (gCmdStr,"%s seq_stop",rwl_client_path);
+		exec_process (gCmdStr);
+	}
+	
+exit:
+	/* End: Modified as per BRCM 1.3 ASD */
+	setUAPSDResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_UAPSD_RESP_TLV, 4, (BYTE *)setUAPSDResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+	return retVal; /* Modified as per BRCM 1.3 ASD */
+}
+
+
+/*
+* This funciton is to retrieve a list of interfaces and return
+* the list back to Agent control.
+*
+*/
+int wfaDeviceListIF(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t *infoResp = &gGenericResp;
+	dutCommand_t *ifList = (dutCommand_t *)caCmdBuf;
+	caDeviceListIFResp_t *ifListResp = &infoResp->cmdru.ifList;
+#ifndef WIN32
+	char adapter [10];
+#endif
+	DPRINT_INFO(WFA_OUT, "Entering wfaDeviceListIF ...\n");
+
+	switch(ifList->cmdsu.iftype)
+	{
+	case IF_80211:
+		infoResp->status = STATUS_COMPLETE;
+		ifListResp->iftype = IF_80211;
+		/*In case of the WinCE the wireless interface is BCMSDDHD1*/
+#ifndef WIN32
+		GetWirelessAdapter(adapter);
+
+		strcpy(ifListResp->ifs[0], adapter);
+#else
+		strcpy(ifListResp->ifs[0], "BCMSDDHD1");
+#endif
+		strcpy(ifListResp->ifs[1], "NULL");
+		strcpy(ifListResp->ifs[2], "NULL");
+		break;
+
+	case IF_ETH:
+		infoResp->status = STATUS_COMPLETE;
+		ifListResp->iftype = IF_ETH;
+		/*In case of the WinCE the ethernet interface is VMINI1*/
+#ifndef WIN32
+		strcpy(ifListResp->ifs[1], "eth0	");
+#else
+		strcpy(ifListResp->ifs[1], "VMINI1");
+#endif
+		strcpy(ifListResp->ifs[1], "NULL");
+		strcpy(ifListResp->ifs[2], "NULL");
+		break;
+	default:
+		{
+			infoResp->status = STATUS_ERROR;
+			wfaEncodeTLV(WFA_DEVICE_LIST_IF_RESP_TLV, 4, (BYTE *)infoResp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+
+			return TRUE;
+		}
+	}
+
+	wfaEncodeTLV(WFA_DEVICE_LIST_IF_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)infoResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+	return TRUE;
+}
+
+int wfaStaDebugSet(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t *debugResp = &gGenericResp;
+	dutCommand_t *debugSet = (dutCommand_t *)caCmdBuf;
+
+	DPRINT_INFO(WFA_OUT, "Entering wfaStaDebugSet ...\n");
+
+	if(debugSet->cmdsu.dbg.state == 1) /* enable */
+		wfa_defined_debug |= debugSet->cmdsu.dbg.level;
+	else
+		wfa_defined_debug = (~debugSet->cmdsu.dbg.level & wfa_defined_debug);
+
+	debugResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_GET_INFO_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)debugResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+	return TRUE;
+}
+
+
+
+/*
+* wfaStaSetIBSS()
+*    This is to set
+*    1. ssid
+*    2. channel
+*    3. encrypType - none or wep
+*    optional
+*    4. key1
+*    5. key2
+*    6. key3
+*    7. key4
+*    8. activeIndex - 1, 2, 3, or 4
+*/
+int wfaStaSetIBSS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetIBSS_t *setIBSS = (caStaSetIBSS_t *)caCmdBuf;
+	dutCmdResponse_t *setIbssResp = &gGenericResp;
+
+	/* Start: Modified as per BRCM 1.3 ASD */
+	int retVal = TRUE;
+	bcmSsidObj_t *bso;
+	int idx;
+	char *ssidStr;
+
+	DPRINT_INFO(WFA_OUT, "wfaStaSetIBSS()\n");
+
+	/* Save the settings for when we need them */
+
+	ssidStr = setIBSS->ssid;
+
+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
+			retVal = FALSE;
+			goto exit;
+		}
+	}
+
+	bso->bssType = BCM_BSS_INDEPENDENT;
+
+	if (setIBSS->channel) {
+		bso->channel = setIBSS->channel;
+	}
+
+	bso->wsec = (!setIBSS->encpType) ? 0 : 1;
+
+	for(idx = 0; idx < 4; idx++) {
+		if(setIBSS->keys[idx][0] != '\0') {
+			strcpy(bso->keys[idx], setIBSS->keys[idx]);
+		} else {
+			memset(bso->keys[idx],0, BCM_WEP_KEY_SIZE_MAX);
+		}
+	}
+
+	if ((setIBSS->activeKeyIdx > 0) && (setIBSS->activeKeyIdx < 5)) {
+		/* move the index range from (1 to 4) to (0 to 3) */
+		bso->primary_key = setIBSS->activeKeyIdx - 1;
+	}
+
+	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+		bcmWfaSsidObjPrint(bso);
+	}
+exit:
+	/* End: Modified as per BRCM 1.3 ASD */
+
+	setIbssResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_IBSS_RESP_TLV, 4, (BYTE *)setIbssResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return retVal; /* Modified as per BRCM 1.3 ASD */
+}
+
+/*
+*  wfaSetMode():
+*  The function is to set the wireless interface with a given mode (possible
+*  adhoc)
+*  Input parameters:
+*    1. I/F
+*    2. ssid
+*    3. mode adhoc or managed
+*    4. encType
+*    5. channel
+*    6. key(s)
+*    7. active  key
+*/
+int wfaStaSetMode(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetMode_t *setmode = (caStaSetMode_t *)caCmdBuf;
+	dutCmdResponse_t *SetModeResp = &gGenericResp;
+	int i;
+	bcmSsidObj_t *bso;
+	char *ssidStr;
+	int retVal = TRUE;
+
+	DPRINT_INFO(WFA_OUT,"Entering wfaStaSetMode\r\n");
+
+	ssidStr = setmode->ssid;
+	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
+			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
+			retVal = FALSE;
+			goto exit;
+		}
+		else
+		{
+			//DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd added: (%s)\n", ssidStr);
+		}
+	}
+
+	if (setmode->channel) {
+		bso->channel = setmode->channel;
+		/* Set the channel */
+		sprintf(gCmdStr, "%s channel %d",rwl_client_path, setmode->channel);
+		exec_process(gCmdStr);
+	}
+
+	/* destroy the interface */
+	sprintf(gCmdStr, "%s disassoc", rwl_client_path);
+	exec_process(gCmdStr);
+
+	/* re-create the interface in the given mode */
+	if(setmode->mode)
+	{
+		bso->bssType = BCM_BSS_INDEPENDENT;
+		sprintf(gCmdStr, "%s infra %d", rwl_client_path, setmode->mode);
+		exec_process(gCmdStr);
+		sprintf(gCmdStr, "%s join %s imode ibss", rwl_client_path, setmode->ssid);
+		exec_process(gCmdStr);
+	}
+	else
+	{
+		sprintf(gCmdStr, "%s infra %d", rwl_client_path, setmode->mode);
+		exec_process(gCmdStr);
+		sprintf(gCmdStr, "%s join %s", rwl_client_path, setmode->ssid);
+		exec_process(gCmdStr);
+	}
+	bso->wsec = (!setmode->encpType) ? 0 : 1;
+	asd_sleep(3);
+	sprintf(gCmdStr, "%s wsec %d", rwl_client_path, bso->wsec);
+	exec_process(gCmdStr);
+
+	if(setmode->encpType == ENCRYPT_WEP) {
+		for (i = 0; i < 4; i++) {
+			if (setmode->keys[i][0] != '\0') {
+				strcpy(bso->keys[i], setmode->keys[i]);
+				sprintf(gCmdStr, "%s addwep  %d %s", rwl_client_path, i, setmode->keys[i]);
+				exec_process(gCmdStr);
+			}
+			else {
+				memset(bso->keys[i],0, BCM_WEP_KEY_SIZE_MAX);
+			}
+		}
+		/* set active key */
+		if ((setmode->activeKeyIdx > 0) && (setmode->activeKeyIdx < 5)) {
+			/* move the index range from (1 to 4) to (0 to 3) */
+			bso->primary_key = setmode->activeKeyIdx - 1;
+			sprintf(gCmdStr, "%s primary_key %d", rwl_client_path, bso->primary_key);
+			exec_process(gCmdStr);
+		}
+	}
+exit:
+
+	SetModeResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_SET_MODE_RESP_TLV, 4, (BYTE *)SetModeResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/* Following functions are specific to Win XP CA or Linux CA */
+/*
+* wfaStaGetMacAddress()
+*    This function is to retrieve the MAC address of a wireless I/F.
+*/
+int wfaStaGetMacAddress(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t *getmacResp = &gGenericResp;
+
+	FILE *tmpfd;
+
+	DPRINT_INFO(WFA_OUT, "Entering wfaStaGetMacAddress ...\n");
+
+	/* Start: Modifed as per BRCM 1.3 ASD*/
+#ifndef WIN32
+	/* Modified on 28/12/07 after getting wl dump error in 4325*/
+	//sprintf(gCmdStr, "ifconfig %s|grep HWaddr|cut -f3 -dr", ifname);
+	sprintf(gCmdStr, "%s cur_etheraddr", rwl_client_path);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+#else
+	strcpy(gCmdStr,rwl_client_path);
+	strcat(gCmdStr," cur_etheraddr >");
+#endif
+	if((tmpfd = asd_Config(gCmdStr,TEMP_FILE_PATH)) == NULL){
+		getmacResp->status = STATUS_ERROR;
+		wfaEncodeTLV(WFA_STA_GET_MAC_ADDRESS_RESP_TLV, 4, (BYTE *)getmacResp, respBuf);
+		*respLen = WFA_TLV_HDR_LEN + 4;
+		DPRINT_ERR(WFA_ERR, "Failed to get mac address\n");
+		return FALSE;
+	}
+	fgets(gCmdStr, 15, tmpfd);
+	/*End:Modified on 28/12/07 after getting wl dump error in 4325 */
+	fgets(getmacResp->cmdru.mac, sizeof(getmacResp->cmdru.mac), tmpfd);
+	getmacResp->cmdru.mac[strlen(getmacResp->cmdru.mac) - 1] = 0;		/* Get rid of NL */
+	printf("get_mac_addr: returning mac :%s:\n", getmacResp->cmdru.mac);
+	Cleanup_File(tmpfd);
+
+	getmacResp->status = STATUS_COMPLETE;
+
+	wfaEncodeTLV(WFA_STA_GET_MAC_ADDRESS_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)getmacResp, respBuf);
+
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+	return TRUE;
+}
+
+int wfaStaSetPwrSave(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+   caStaSetPwrSave_t *setps = (caStaSetPwrSave_t *)caCmdBuf;
+   dutCmdResponse_t *SetPSResp = &gGenericResp;
+
+   sprintf(gCmdStr, "%s PM %d", rwl_client_path, setps->mode);
+   exec_process(gCmdStr);
+   
+   SetPSResp->status = STATUS_COMPLETE;
+   wfaEncodeTLV(WFA_STA_SET_PWRSAVE_RESP_TLV, 4, (BYTE *)SetPSResp, respBuf);
+   *respLen = WFA_TLV_HDR_LEN + 4;
+
+   return TRUE;
+}
+
+/*
+* wfaStaIsConnected():
+*    The function is to check whether the station's wireless I/F has
+*    already connected to an AP.
+*/
+int wfaStaIsConnected(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	/* Removed as per BRCM 1.3 ASD */
+	FILE *tmpfd;
+	dutCmdResponse_t *staConnectResp = &gGenericResp;
+	
+#ifdef WIN32
+   unsigned int  position;
+#endif
+	DPRINT_INFO(WFA_OUT, "Entering isConnected ...\n");
+
+	/* Start: Added as per BRCM 1.3 ASD */
+	/* Associated gets long response */
+#ifndef WIN32
+	sprintf(gCmdStr, "%s assoc | wc -l", rwl_client_path);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+#else
+	strcpy(gCmdStr, rwl_client_path);
+	strcat(gCmdStr, " assoc >");
+#endif
+	if((tmpfd = asd_Config(gCmdStr,TEMP_FILE_PATH)) == NULL){
+		staConnectResp->status = STATUS_ERROR;
+		printf("assoc failed\n");
+		wfaEncodeTLV(WFA_STA_IS_CONNECTED_RESP_TLV, 4, (BYTE *)staConnectResp, respBuf);
+		*respLen = WFA_TLV_HDR_LEN + 4;
+		DPRINT_ERR(WFA_ERR, "isconnected failed\n");
+		return FALSE;
+	}
+	
+#ifndef WIN32
+	fgets(gCmdStr, sizeof(gCmdStr), tmpfd);
+	/* Short response means not associated */
+	if (atoi(gCmdStr) <= 2)
+		staConnectResp->cmdru.connected = 0;
+	else
+		staConnectResp->cmdru.connected = 1;
+	/* End: Added as per BRCM 1.3 ASD */
+#else
+	if((FileSearch(tmpfd, L"Not associated", &position))!= -1)
+	    staConnectResp->cmdru.connected = 0;
+	else
+		staConnectResp->cmdru.connected = 1;
+#endif
+	/*
+	* Report back the status: Complete or Failed.
+	*/
+	Cleanup_File(tmpfd);
+	staConnectResp->status = STATUS_COMPLETE;
+
+	wfaEncodeTLV(WFA_STA_IS_CONNECTED_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)staConnectResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+	return TRUE;
+}
+
+/*
+* wfaStaGetStats():
+* The function is to retrieve the statistics of the I/F's layer 2 txFrames,
+* rxFrames, txMulticast, rxMulticast, fcsErrors/crc, and txRetries.
+* Currently there is not definition how to use these info.
+*/
+int wfaStaGetStats(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t *statsResp = &gGenericResp;
+	FILE *fd; /* Added as per BRCM 1.3 ASD */
+	caStaGetStatsResp_t *castatsResp = &statsResp->cmdru.ifStats; /* Added as per BRCM 1.3 ASD */
+#ifdef WIN32
+   char cmdStr[256];
+   unsigned int position;
+#endif
+   DPRINT_INFO(WFA_OUT, "Entering wfaStaGetStats ...\n");
+#ifndef WIN32
+	/* Start: Modified as per BRCM 1.3 ASD */
+	sprintf(gCmdStr, "%s counters | grep txframe | awk '{print $2,\"\\n\",$10}'", rwl_client_path);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+	/* wl dump replaced with wl counters to get statistics */
+	if ((fd = popen(gCmdStr, "r")) == NULL){
+		DPRINT_ERR(WFA_ERR, "Couldn't get txframe stats\n");
+		goto wfaStaGetStats_error;
+	} else {
+		fgets(gCmdStr, sizeof(gCmdStr), fd);	/* line 1: tx frame */
+		castatsResp->txFrames =  atoi(gCmdStr);
+		fgets(gCmdStr, sizeof(gCmdStr), fd);	/* line 2: rx frame */
+		castatsResp->rxFrames =  atoi(gCmdStr);
+		pclose(fd);
+	}
+
+	sprintf(gCmdStr, "%s counters | grep d11_txmulti | awk '{print $4,\"\\n\",$8}' ", rwl_client_path);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+	if ((fd = popen(gCmdStr,"r")) == NULL){
+		DPRINT_ERR(WFA_ERR, "Couldn't get d11_txmulti stats\n");
+		goto wfaStaGetStats_error;
+	} else {
+		fgets(gCmdStr, sizeof(gCmdStr), fd);
+		castatsResp->txMulticast = atoi(gCmdStr);
+		fgets(gCmdStr, sizeof(gCmdStr), fd);
+		castatsResp->txRetries = atoi(gCmdStr);
+		pclose(fd);
+	}
+	sprintf(gCmdStr, "%s counters | grep d11_rxmulti | awk '{print $4}'", rwl_client_path);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+	if ((fd = popen(gCmdStr ,"r")) == NULL){
+		DPRINT_ERR(WFA_ERR, "Couldn't get rxMultiFrame stats\n");
+		goto wfaStaGetStats_error;
+	} else {
+		fgets(gCmdStr, sizeof(gCmdStr), fd);
+		castatsResp->rxMulticast = atoi(gCmdStr);
+		pclose(fd);
+	}
+
+	sprintf(gCmdStr, "%s counters | grep rxbadfcs | awk '{print $8}'", rwl_client_path);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+	if ((fd = popen(gCmdStr, "r")) == NULL){
+		DPRINT_ERR(WFA_ERR, "Couldn't get rxbadfcs  stats\n");
+		goto wfaStaGetStats_error;
+	} else {
+		fgets(gCmdStr, sizeof(gCmdStr), fd);
+		castatsResp->fcsErrors = atoi(gCmdStr);
+		pclose(fd);
+	}
+#else
+	strcpy(cmdStr,rwl_client_path);
+	strcat(cmdStr," counters >");
+	/*Open the file to read the statistics*/
+	if((fd = asd_Config(cmdStr,TEMP_FILE_PATH)) == NULL){
+		DPRINT_ERR(WFA_ERR, "Couldn't get rxbadfcs  stats\n");
+		goto wfaStaGetStats_error;
+	}
+	else {
+
+		GetStats(fd, L"txframe ", &position," ");
+		castatsResp->txFrames =  position;
+		
+		GetStats(fd, L"rxframe ", &position," ");
+		castatsResp->rxFrames =position;
+		
+		GetStats(fd, L"d11_txmulti ", &position," ");
+		castatsResp->txMulticast =position;
+		
+		GetStats(fd, L"d11_rxmulti ", &position," ");
+		castatsResp->rxMulticast = position;
+		
+		GetStats(fd, L"d11_txretrie ", &position," ");
+		castatsResp->txRetries = position;
+		
+		GetStats(fd, L"rxbadfcs ", &position," ");
+		castatsResp->fcsErrors= position ;
+	}
+		Cleanup_File(fd);
+#endif
+	/* End: Modified as per BRCM 1.3 ASD */
+	statsResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_STA_GET_STATS_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)statsResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+	return TRUE;
+
+wfaStaGetStats_error:
+	statsResp->status = STATUS_ERROR;
+	wfaEncodeTLV(WFA_STA_GET_STATS_RESP_TLV, 4, (BYTE *)statsResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+	return FALSE;
+}
+
+int wfaDeviceGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t *infoResp = &gGenericResp;
+	/*a vendor can fill in the proper info or anything non-disclosure */
+	caDeviceGetInfoResp_t dinfo = {"WFA Lab", "DemoUnit", WFA_SYSTEM_VER};
+	/* Start: Modified as per BRCM 1.3 ASD */
+	FILE *fd;
+
+#ifndef WIN32
+	/* get the 7th word in the string(1st line ignored( as it contains the value
+	 * for dinfo.version */
+	sprintf(gCmdStr,"%s ver | awk '{print $7}'", rwl_client_path);
+#ifdef DEBUG
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+#endif
+#else
+	strcpy(gCmdStr,rwl_client_path);
+	strcat(gCmdStr," ver >");
+#endif
+	if((fd = asd_Config(gCmdStr,TEMP_FILE_PATH)) == NULL){
+		printf("Error executing ver\n");
+		infoResp->status = STATUS_ERROR;
+	}
+	else {
+#ifndef WIN32
+		fgets(gCmdStr, sizeof(gCmdStr), fd);	/* Ignore first line */
+		fgets(gCmdStr, sizeof(gCmdStr), fd);
+		gCmdStr[strlen(gCmdStr) - 1] = 0;		/* Get rid of NL */
+#else
+		/* The string next to version contains value for dinfo.version */
+		while ((fscanf(fd, "%s\n", gCmdStr)) != EOF) {
+			if (strncmp(gCmdStr, "version", sizeof("version")) == 0) {
+				fscanf(fd, "%s\n", gCmdStr);
+				break;
+			}
+		}
+#endif
+	}
+	Cleanup_File(fd);
+	memset(&dinfo, 0, sizeof(dinfo));
+	infoResp->status = STATUS_COMPLETE;
+	sprintf(dinfo.vendor, "%.16s", "Broadcom");
+	sprintf(dinfo.version, "%.16s", gCmdStr);
+	sprintf(dinfo.model, "%.16s", "BRCM");
+	
+	DPRINT_INFO(WFA_OUT, "Entering wfaDeviceGetInfo ...\n");
+	DPRINT_INFO(WFA_OUT, "status,%i,vendor,%s,model,%s,version %s\n", infoResp->status,
+			dinfo.vendor,dinfo.model, dinfo.version);
+	memcpy(&infoResp->cmdru.devInfo, &dinfo, sizeof(caDeviceGetInfoResp_t));
+
+	infoResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_DEVICE_GET_INFO_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)infoResp, respBuf);
+
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+	/* End: Modified as per BRCM 1.3 ASD */
+	return TRUE;
+}
+
+/*
+*   wfaStaGetBSSID():
+*     This function is to retrieve BSSID of a specific wireless I/F.
+*/
+int wfaStaGetBSSID(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	FILE *tmpfd;
+	dutCmdResponse_t *bssidResp = &gGenericResp;
+	DPRINT_INFO(WFA_OUT, "Entering wfaStaGetBSSID ...\n");
+
+#ifndef WIN32
+	/* Start: Modified for BRCM 1.3 ASD */
+	/* Associated gets long response */
+	sprintf(gCmdStr, "%s assoc | wc -l", rwl_client_path);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+#else
+	memset(gCmdStr, 0, sizeof(gCmdStr));
+	strcpy(gCmdStr, rwl_client_path);
+	strcat(gCmdStr, " bssid >");
+#endif
+
+	if((tmpfd = asd_Config(gCmdStr,TEMP_FILE_PATH)) == NULL){
+		printf("BSSID failed\n");
+		bssidResp->status = STATUS_ERROR;
+		wfaEncodeTLV(WFA_STA_GET_BSSID_RESP_TLV, 4, (BYTE *)bssidResp, respBuf);
+		*respLen = WFA_TLV_HDR_LEN + 4;
+	}
+	fgets(gCmdStr, sizeof(gCmdStr), tmpfd);
+	Cleanup_File(tmpfd);
+
+#ifndef WIN32
+	/* Short response means not associated */
+	if (atoi(gCmdStr) <= 2) {
+		strcpy(bssidResp->cmdru.bssid, "00:00:00:00:00:00");
+	} else {
+		sprintf(gCmdStr, "%s bssid", rwl_client_path);
+		DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+		if ((tmpfd = popen(gCmdStr, "r")) == NULL){
+			printf("bssid failed\n");
+		}
+		fgets(gCmdStr, sizeof(gCmdStr), tmpfd);
+		pclose(tmpfd);
+		gCmdStr[17] = 0;	/* Get rid of CR or NL */
+		strcpy(bssidResp->cmdru.bssid, gCmdStr);
+	}
+#else
+	gCmdStr[17] = 0;	/* Get rid of CR or NL */
+	if (gCmdStr[2] != ':'){
+		strcpy(bssidResp->cmdru.bssid, "00:00:00:00:00:00");
+	}
+	else {
+		strcpy(bssidResp->cmdru.bssid, gCmdStr);
+	}
+#endif
+	bssidResp->status = STATUS_COMPLETE;
+	/* End Modified as per BRCM 1.3 ASD */
+	wfaEncodeTLV(WFA_STA_GET_BSSID_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)bssidResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+	return TRUE;
+}
+
+/*
+ *     exec_addts():
+ *     This function will call ./wl cac_addts
+ */
+int
+exec_addts(caStaSetWMM_t *setwmm) 
+{
+	char pwr_save_str[TSPEC_BUF_SIZE], direction[TSPEC_BUF_SIZE];
+	int stat;
+
+	DPRINT_INFO(WFA_OUT, "ADDTS AC PARAMS: \n \
+		dialog id: %d, \t TID: %d, \t DIRECTION: %d, \n \
+		PSB: %d, \t UP: %d, \t Fixed %d, \n \
+		MSDU Size: %d, \t Max MSDU Size %d, \n \
+		MIN SERVICE INTERVAL: %d, \t MAX SERVICE INTERVAL: %d, \n \
+		INACTIVITY: %d, \t SUSPENSION %d, \n \
+		SERVICE START TIME: %d, \t MIN DATARATE: %d, \n \
+		MEAN DATA RATE: %d, \t PEAK DATA RATE: %d, \n \
+		BURSTSIZE: %d, \t DELAY BOUND: %d, \t PHYRATE: %d, \n \
+		SPLUSBW: %f, \t MEDIUM TIME: %d,  \t ACCESSCAT: %d\n", \
+		setwmm->actions.addts.dialog_token, \
+		setwmm->actions.addts.tspec.tsinfo.TID, \
+		setwmm->actions.addts.tspec.tsinfo.direction, \
+		setwmm->actions.addts.tspec.tsinfo.PSB, \
+		setwmm->actions.addts.tspec.tsinfo.UP, \
+		setwmm->actions.addts.tspec.Fixed, \
+		setwmm->actions.addts.tspec.size, \
+		setwmm->actions.addts.tspec.maxsize, \
+		setwmm->actions.addts.tspec.min_srvc, \
+		setwmm->actions.addts.tspec.max_srvc, \
+		setwmm->actions.addts.tspec.inactivity, \
+		setwmm->actions.addts.tspec.suspension, \
+		setwmm->actions.addts.tspec.srvc_strt_tim, \
+		setwmm->actions.addts.tspec.mindatarate, \
+		setwmm->actions.addts.tspec.meandatarate, \
+		setwmm->actions.addts.tspec.peakdatarate, \
+		setwmm->actions.addts.tspec.burstsize, \
+		setwmm->actions.addts.tspec.delaybound, \
+		setwmm->actions.addts.tspec.PHYrate, \
+		setwmm->actions.addts.tspec.sba, \
+		setwmm->actions.addts.tspec.medium_time, \
+		setwmm->actions.addts.accesscat);
+
+	if (setwmm->actions.addts.tspec.tsinfo.direction == WMMAC_UPLINK)
+		S_N_PRINTF(direction, sizeof(direction), "uplink");
+	else if (setwmm->actions.addts.tspec.tsinfo.direction == WMMAC_DOWNLINK)
+		S_N_PRINTF(direction, sizeof(direction), "downlink");
+	else if (setwmm->actions.addts.tspec.tsinfo.direction == WMMAC_BIDIR)
+		S_N_PRINTF(direction, sizeof(direction), "bi-directional");
+			
+	if (setwmm->actions.addts.tspec.tsinfo.PSB == 1)
+		S_N_PRINTF(pwr_save_str, sizeof(pwr_save_str), "U-APSD");
+	else if (setwmm->actions.addts.tspec.tsinfo.PSB == 0)
+		S_N_PRINTF(pwr_save_str, sizeof(pwr_save_str), "legacy");
+
+	if(setwmm->send_trig) {
+		int Sockfd;
+    		struct sockaddr_in psToAddr;
+		unsigned int TxMsg[512];
+       		Sockfd = wfaCreateUDPSock(setwmm->dipaddr, 12346);
+		memset(&psToAddr, 0, sizeof(psToAddr));
+		psToAddr.sin_family = AF_INET;
+		psToAddr.sin_addr.s_addr = inet_addr(setwmm->dipaddr);
+		psToAddr.sin_port = htons(12346);
+		usleep(becon_int);
+   		wfaTGSetPrio(Sockfd, setwmm->trig_ac);
+		printf("\r\nSending dummy Hello to %s\n",setwmm->dipaddr);
+       		create_apts_msg(APTS_HELLO, TxMsg,0);
+		wfaTrafficSendTo(Sockfd, (char *)TxMsg, 256, (struct sockaddr *)&psToAddr);
+		asd_closeSocket(Sockfd);
+	}
+
+	S_N_PRINTF(gCmdStr, sizeof(gCmdStr), "%s cac_addts %d %d %d %s %s %d %d %d" \
+		" %d %d %d %d %d %d %d %d %d %d %d %d", \
+		rwl_client_path, \
+		TSPEC_VER, \
+		setwmm->actions.addts.dialog_token, \
+		setwmm->actions.addts.tspec.tsinfo.TID, \
+		direction, \
+		pwr_save_str, \
+		setwmm->actions.addts.tspec.tsinfo.UP, \
+		setwmm->actions.addts.tspec.size, \
+		setwmm->actions.addts.tspec.Fixed, \
+		setwmm->actions.addts.tspec.maxsize, \
+		setwmm->actions.addts.tspec.min_srvc, \
+		setwmm->actions.addts.tspec.max_srvc, \
+		setwmm->actions.addts.tspec.inactivity, \
+		setwmm->actions.addts.tspec.suspension, \
+		setwmm->actions.addts.tspec.mindatarate, \
+		setwmm->actions.addts.tspec.meandatarate, \
+		setwmm->actions.addts.tspec.peakdatarate, \
+		setwmm->actions.addts.tspec.burstsize, \
+		setwmm->actions.addts.tspec.delaybound, \
+		(int)setwmm->actions.addts.tspec.sba, \
+		setwmm->actions.addts.tspec.PHYrate);
+	if ((stat = exec_wmmCmd(gCmdStr))  != 0) {
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/*
+ *     exec_delts():
+ *     This function will call ./wl cac_delts
+ */
+
+int
+exec_delts(caStaSetWMM_t *setwmm) 
+{
+	char *token_buf = NULL;
+	char temp_buf[WFA_BUFF_128], tsinfo_buf[MAX_TOKENS][TSPEC_BUF_SIZE], temp_resp[WFA_BUFF_128];
+	int token_count, stat, nbyte = 0, tsinfo_flag;
+	FILE *output_fp, *error_fp;
+
+	DPRINT_INFO(WFA_OUT, "DELTS AC PARAMS: TID: %d\n", setwmm->actions.delts);
+	S_N_PRINTF(gCmdStr, sizeof(gCmdStr), "%s cac_tslist", rwl_client_path);
+
+	/* Execute the command "wl cac_tslist" */
+	if ((stat = asd_Config_wmm(gCmdStr, TEMP_STD_OUT_FILE)) != 0) {
+		if ((error_fp = fopen(TEMP_STD_ERR_FILE, "r")) == NULL) {
+			DPRINT_ERR(WFA_ERR, "Error in reading error message. \n");
+		}
+		memset(temp_resp, 0, sizeof(temp_resp));
+       		fgets(temp_resp, sizeof(temp_resp), error_fp);
+		DPRINT_ERR(WFA_ERR, "Error in executing wl cac_tslist :: %s \n", temp_resp);
+		return FALSE;
+	}
+
+	tsinfo_flag = NO_TSINFO;
+	if ((output_fp = fopen(TEMP_STD_OUT_FILE, "r")) == NULL) {
+		printf("\nTEMP_STD_OUT_FILE::File open error\n");
+		return FALSE;
+	}
+	else {
+		while ((feof(output_fp) == 0)) {
+			if (fseek(output_fp, nbyte, SEEK_SET) < 0) {
+   				tsinfo_flag = NO_TSINFO;
+				return FALSE;
+			}
+			memset(temp_resp, 0, sizeof(temp_resp));
+       			fgets(temp_resp, sizeof(temp_resp), output_fp);
+			nbyte = nbyte + strlen(temp_resp);
+
+       			/* Get the wl cac_tslist results in temp_resp */
+
+			if (strlen(temp_resp) == 0) {
+				DPRINT_ERR(WFA_ERR, "temp_resp length 0. Can't execute wl cac_delts \n");
+   				tsinfo_flag = NO_TSINFO;
+				break;
+			}
+
+			token_buf = (char *)strtok_r(temp_resp, " ", (char **) temp_buf);
+			token_count = 0;
+			while (token_buf != NULL) {
+				token_buf = (char *)strtok_r(NULL, " ", (char **) temp_buf);
+				if (token_buf != NULL) {
+					S_N_PRINTF(tsinfo_buf[token_count], 
+						sizeof(tsinfo_buf[token_count]), "%s", token_buf);
+					token_count++;
+				}
+			}
+			/* if tid of cac_tslist matches with tid of sta_set_wmm then delts is performed */	
+			if (atoi(tsinfo_buf[TID_INDEX]) == setwmm->actions.delts) {
+				S_N_PRINTF(gCmdStr, sizeof(gCmdStr), "%s cac_delts %d %s %s %s", \
+					rwl_client_path, TSPEC_VER, tsinfo_buf[BYTE_0], \
+					tsinfo_buf[BYTE_1], tsinfo_buf[BYTE_2]);
+				/* Execute wl cac_delts  */
+				if ((stat = exec_wmmCmd(gCmdStr)) != 0) {
+					return FALSE;
+				}
+				return TRUE;
+			}
+			else {
+   				tsinfo_flag = TID_MISMATCH;
+			}
+		} /* End of while */
+		fclose(output_fp);	
+		if (tsinfo_flag == NO_TSINFO) {
+			DPRINT_ERR(WFA_ERR, "Error. Cannot Execute wl cac_delts \n");
+			return FALSE;
+		}
+		else if (tsinfo_flag == TID_MISMATCH) {
+			DPRINT_ERR(WFA_ERR, "tid did not match. Can't Execute wl cac_delts \n");
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+
+/*
+ *  wfaStaSetWMM():
+ *  The function is to set the WMM related parameters at the DUT.
+ *  Currently the function is used for GROUPS WMM-AC and WMM general configuration for setting
+ *  RTS Threshhold, Fragmentation threshold and wmm (ON/OFF)
+ *  It is expected that this function will set all the WMM related parametrs for a particular GROUP.
+*/
+
+int wfaStaSetWMM(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetWMM_t *setwmm = (caStaSetWMM_t *)caCmdBuf;
+	char *ifname = setwmm->intf;
+	dutCmdResponse_t *setwmmResp = &gGenericResp;
+	int stat;
+        int Sockfd;
+        struct sockaddr_in psToAddr;
+        unsigned int TxMsg[512];
+
+	switch(setwmm->group)
+	{
+	case GROUP_WMMAC:
+            if (setwmm->send_trig)
+            {
+                Sockfd = wfaCreateUDPSock(setwmm->dipaddr, 12346);
+                memset(&psToAddr, 0, sizeof(psToAddr));
+                psToAddr.sin_family = AF_INET;
+                psToAddr.sin_addr.s_addr = inet_addr(setwmm->dipaddr);
+                psToAddr.sin_port = htons(12346);
+                switch (setwmm->trig_ac)
+                {
+
+                case WMMAC_AC_VO:
+                    wfaTGSetPrio(Sockfd, 7);
+                    create_apts_msg(APTS_CK_VO, TxMsg, 0);
+                    printf("\r\nSending AC_VO trigger packet\n");
+                break;
+
+                case WMMAC_AC_VI:
+                    wfaTGSetPrio(Sockfd, 5);
+                    create_apts_msg(APTS_CK_VI, TxMsg, 0);
+                    printf("\r\nSending AC_VI trigger packet\n");
+                break;
+
+                case WMMAC_AC_BK:
+                    wfaTGSetPrio(Sockfd, 2);
+                    create_apts_msg(APTS_CK_BK, TxMsg, 0);
+                    printf("\r\nSending AC_BK trigger packet\n");
+                break;
+
+                default:
+                case WMMAC_AC_BE:
+                    wfaTGSetPrio(Sockfd, 0);
+                    create_apts_msg(APTS_CK_BE, TxMsg, 0);
+                    printf("\r\nSending AC_BE trigger packet\n");
+                break;
+                }
+                sendto(Sockfd, TxMsg, 256, 0, (struct sockaddr *)&psToAddr,
+                sizeof(struct sockaddr));
+		asd_closeSocket(Sockfd);
+                usleep(1000000);
+            }
+            else if (setwmm->action == WMMAC_ADDTS) {
+                if ((stat = exec_addts(setwmm)) == FALSE) {
+                    setwmmResp->status = STATUS_ERROR;
+                    break;
+                }
+            }
+            else if (setwmm->action == WMMAC_DELTS) {
+                if ((stat = exec_delts(setwmm))  == FALSE) {
+                    setwmmResp->status = STATUS_ERROR;
+                    break;
+                }
+            }
+            setwmmResp->status = STATUS_COMPLETE;
+        break;
+
+        case GROUP_WMMCONF:
+            S_N_PRINTF(gCmdStr, sizeof(gCmdStr), "iwconfig %s rts_thr %d", \
+                ifname,setwmm->actions.config.rts_thr);
+            exec_process(gCmdStr);
+            S_N_PRINTF(gCmdStr, sizeof(gCmdStr), "iwconfig %s frag_thr %d", \
+                ifname,setwmm->actions.config.frag_thr);
+            exec_process(gCmdStr);
+            S_N_PRINTF(gCmdStr, sizeof(gCmdStr), "iwpriv %s wmm %d", \
+                ifname,setwmm->actions.config.wmm);
+            exec_process(gCmdStr);
+            setwmmResp->status = STATUS_COMPLETE;
+        break;
+
+        default:
+            DPRINT_ERR(WFA_ERR, "The group %d is not supported\n",setwmm->group);
+	    setwmmResp->status = STATUS_ERROR;
+	break;
+	}
+
+	wfaEncodeTLV(WFA_STA_SET_WMM_RESP_TLV, 4, (BYTE *)setwmmResp, respBuf);
+	DPRINT_INFO(WFA_OUT, "tag is %d\n",WFA_STA_SET_WMM_RESP_TLV);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+	return TRUE;
+}
+
+/* Start: Added BCM functions as per BRCM 1.3 ASD */
+int bcmSsidIsGood(char *ssidStr)
+{
+	int ssidLen = strlen(ssidStr);
+
+	if ((ssidLen == 0) || (ssidLen > BCM_SSID_LEN_MAX)) {
+		return (FALSE);
+	} else {
+		return (TRUE);
+	}
+}
+
+bcmSsidObj_t *bcmWfaSsidTblFreeEntry()
+{
+	bcmSsidObj_t *bso;
+	int idx;
+
+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidTblFreeEntry\n");
+
+	for (idx = 0; idx < BCM_SSID_MAX; idx++) {
+		bso = &bsotbl.ssidObj[idx];
+		if (bcmSsidIsGood(bso->ssidStr) == FALSE) {
+			return bso;
+		}
+	}
+
+	DPRINT_ERR(WFA_OUT, "bcmWfaSsidTblFreeEntry: no free entry available.\n");
+	return (NULL);
+}
+
+bcmSsidObj_t *bcmWfaSsidTblSsidFind(char *ssidStr)
+{
+	bcmSsidObj_t *bso;
+	bcmSsidObj_t *bsoFound= NULL;
+	int idx;
+
+	if (bcmSsidIsGood(ssidStr) == FALSE) {
+		return (NULL);
+	}
+
+	for (idx = 0; idx < BCM_SSID_MAX; idx++) {
+		bso = &bsotbl.ssidObj[idx];
+		if (bcmSsidIsGood(ssidStr) == FALSE) {
+			continue;
+		}
+
+		if (strcmp(ssidStr, bso->ssidStr)) {
+			continue;
+		} else {
+			bsoFound = bso;
+			break;
+		}
+	}
+
+	return (bsoFound);
+}
+
+bcmSsidObj_t *bcmWfaSsidObjTblAdd(char *ssidStr)
+{
+	bcmSsidObj_t *bso;
+	int idx;
+
+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd: ssidStr %s\n", ssidStr);
+
+	if (bcmSsidIsGood(ssidStr) == FALSE) {
+		return (NULL);
+	}
+
+	if ((bso = bcmWfaSsidTblSsidFind(ssidStr))) {
+		DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s): ssid already exists\n", ssidStr);
+		return (bso);
+	}
+
+	if (!(bso = bcmWfaSsidTblFreeEntry())) {
+		DPRINT_INFO(WFA_OUT, "no free entry\n");
+		return (NULL);
+	}
+
+	memset(bso,0, sizeof(bcmSsidObj_t));
+	strcpy(bso->ssidStr, ssidStr);
+	bso->bssType = BCM_BSS_INFRA; /* init it to infrastructure bss */
+	bso->primary_key = BCM_PRI_KEY_BAD; /* init it to bad one */
+	bso->eapType = BCM_DEFAULT_SEC_MODE; /* init to non-eap mode */ 
+
+	for (idx = 0; idx < 4; idx++) {
+		S_N_PRINTF (bso->keys[idx], 2, "%s", "\0");
+	}
+
+	bsotbl.addCnt++;
+	bsotbl.entries++;
+
+	return (bso);
+}
+
+void bcmWfaSsidObjTblDel(char *ssidStr)
+{
+	bcmSsidObj_t *bso;
+
+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblDel: ssidStr %s\n", ssidStr);
+
+	bso = bcmWfaSsidTblSsidFind(ssidStr);
+	if (bso == NULL) {
+		return;
+	}
+
+	DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblDel: deleting bso %p\n", bso);
+	memset(bso,0, sizeof(bcmSsidObj_t));
+	bsotbl.delCnt++;
+	bsotbl.entries--;
+}
+
+void bcmWfaSsidObjPrint(bcmSsidObj_t *bso)
+{
+	int idx;
+
+	if (bcmSsidIsGood(bso->ssidStr) == FALSE) {
+		fprintf(WFA_OUT, "bso %p is blank.\n", bso);
+		return;
+	}
+
+	fprintf(WFA_OUT, "bso %p\n", bso);
+	fprintf(WFA_OUT, "\tssid %s", bso->ssidStr);
+	fprintf(WFA_OUT, "\tbssType %d\n", bso->bssType);
+	fprintf(WFA_OUT, "\tchannel %d\n", bso->channel);
+	fprintf(WFA_OUT, "\twsec %d\n", bso->wsec);
+	fprintf(WFA_OUT, "\tauth %d\n", bso->auth);
+	fprintf(WFA_OUT, "\twpa_auth %d\n", bso->wpa_auth);
+	fprintf(WFA_OUT, "\tpowerSave %d\n", bso->powerSave);
+	fprintf(WFA_OUT, "\tuapsd %d\n", bso->uapsd);
+
+	for (idx = 0; idx < 4; idx++) {
+		fprintf(WFA_OUT, "\tkeys[%d] : %s\n", idx, bso->keys[idx]);
+	}
+	fprintf(WFA_OUT, "\tprimary_key %d\n", bso->primary_key);
+	fprintf(WFA_OUT, "\tpassphrase : %s\n", bso->passphrase);
+}
+
+void bcmWfaSsidObjTblPrint(void)
+{
+	int idx;
+
+	fprintf(WFA_OUT, "entries %d addCnt %d delCnt %d\n",
+		bsotbl.entries, bsotbl.addCnt, bsotbl.delCnt);
+	for (idx = 0; idx < BCM_SSID_MAX; idx++) {
+		bcmWfaSsidObjPrint(&bsotbl.ssidObj[idx]);
+	}
+}
+
+/*Do the initialisation for the driver */
+void bcmWfaInit(void)
+{
+	memset(&bsotbl,0, sizeof(bsotbl));
+
+	sprintf(gCmdStr, "%s ap 0", rwl_client_path); /* not AP */
+	exec_process(gCmdStr);
+
+	sprintf(gCmdStr, "%s radio on", rwl_client_path); /* not AP */
+	exec_process(gCmdStr);
+
+	sprintf(gCmdStr, "%s wsec 0", rwl_client_path);
+	exec_process(gCmdStr);
+
+	sprintf(gCmdStr, "%s auth 0", rwl_client_path);
+	exec_process(gCmdStr);
+
+	sprintf(gCmdStr, "%s wpa_auth 0", rwl_client_path);
+	exec_process(gCmdStr);
+
+	sprintf(gCmdStr, "%s sup_wpa 1", rwl_client_path); /* enable in-driver supplicant */
+	exec_process(gCmdStr);
+
+	/* Driver should not be made up explicitly  
+	 * as we need to execute uapsd command in the beginning. 
+	 */
+}
+
+/*
+ * Implementing set systemtime
+ */
+
+int wfaStaSetSystime(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	int retVal = TRUE;
+	dutCmdResponse_t *SetSystime = &gGenericResp;
+	dutCommand_t *systime = (dutCommand_t *)caCmdBuf;
+#ifndef WIN32
+	char *month[]= {"NULL","JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
+#else
+	SYSTEMTIME newtime;
+	int err;
+#endif
+	DPRINT_INFO(WFA_OUT, "Entering set systime ...\n");
+#ifndef WIN32
+	S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "date -s \"%d %s %d %d:%d:%d\"", systime->cmdsu.stime.date, month[systime->cmdsu.stime.month],
+		systime->cmdsu.stime.year, systime->cmdsu.stime.hours, systime->cmdsu.stime.minutes, systime->cmdsu.stime.seconds);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+	exec_process(gCmdStr);
+#else
+	newtime.wDay = systime->cmdsu.stime.date;
+	newtime.wMonth = systime->cmdsu.stime.month;
+	newtime.wYear = systime->cmdsu.stime.year;
+	newtime.wHour = systime->cmdsu.stime.hours;
+	newtime.wMinute = systime->cmdsu.stime.minutes;
+	newtime.wSecond = systime->cmdsu.stime.seconds;
+	if ((err = SetLocalTime(&newtime)) == 0) {
+		DPRINT_ERR(WFA_OUT, "error at set system time % d\n", GetLastError());
+		retVal = FALSE;
+	}
+#endif /* WIN32 */
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	if(retVal == TRUE)
+		SetSystime->status = STATUS_COMPLETE;
+	else
+		SetSystime->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_SET_SYSTIME_RESP_TLV, 4, (BYTE *)SetSystime, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+	return TRUE;
+}
+
+/*
+ * Part of sigma 11n implementation.
+ * Implementing set 1n functionalities
+ */
+int wfaStaSet11n(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+#ifdef WFA_STA_TB
+	int retVal = TRUE; 
+	FILE *tmpfd;
+	dutCmdResponse_t *Set11nresp = &gGenericResp;
+	dutCommand_t *Set11n = (dutCommand_t *)caCmdBuf;
+	DPRINT_INFO(WFA_OUT, "Entering set 11n ...\n");
+	/* Run the commands in the batching mode in case of wifi transport*/
+	if(rwl_wifi_flag) {
+		asd_sleep(1);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s seq_start", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s down", rwl_client_path);
+	exec_process(gCmdStr);
+	/*
+	 * Showing unsupported yet to be implemented
+	 * wl mimo_bw_cap need to be implemented by brcm
+	 */
+	if (Set11n->cmdsu.set11n.width == 20) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s mimo_bw_cap 0", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else if((Set11n->cmdsu.set11n.width) == 40 || (Set11n->cmdsu.set11n.width == -1)) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s mimo_bw_cap 1", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	if (Set11n->cmdsu.set11n.addba_reject == 2) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s ampdu 0", rwl_client_path);
+		exec_process(gCmdStr);
+	}		
+	else if(Set11n->cmdsu.set11n.addba_reject == 1) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s ampdu 1", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	if (Set11n->cmdsu.set11n.ampdu == 2) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s amsdu 0", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s ampdu 1", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else if(Set11n->cmdsu.set11n.ampdu == 1) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s ampdu 0", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	if (Set11n->cmdsu.set11n.amsdu == 2) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s amsdu 1", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else if(Set11n->cmdsu.set11n.amsdu == 1) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s amsdu 0", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	if (Set11n->cmdsu.set11n.greenfield == 2) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s mimo_preamble 1", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else if(Set11n->cmdsu.set11n.greenfield == 1) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s mimo_preamble 0", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	if (Set11n->cmdsu.set11n.stbc_rx == 0) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s stbc_tx 0", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s stbc_rx 0", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else if (Set11n->cmdsu.set11n.stbc_rx > 0) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s stbc_tx 1", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s stbc_rx 1", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s nrate -m 5 -w 2", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s up", rwl_client_path);
+	exec_process(gCmdStr);
+	if(rwl_wifi_flag) {
+		asd_sleep(1);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s seq_stop", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	if (Set11n->cmdsu.set11n.intolerant_40 == 2) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s obss_coex 1", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s intol40 1", rwl_client_path);
+		exec_process(gCmdStr);
+	}		
+	else if(Set11n->cmdsu.set11n.intolerant_40 == 1) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s obss_coex 0", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s intol40 0", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+
+	if (Set11n->cmdsu.set11n.sgi20 == 2) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s sgi_tx %d", rwl_client_path, -1);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s sgi_rx %d", rwl_client_path, 3);
+		exec_process(gCmdStr);
+	}
+	else if(Set11n->cmdsu.set11n.sgi20 == 1) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s sgi_tx %d", rwl_client_path, 0);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s sgi_rx %d", rwl_client_path, 0);
+		exec_process(gCmdStr);
+	}
+	/*
+	 * SMPS related commands can be ignored as of now till
+	 * mimo_ps command gets implemented
+	 */
+	if (Set11n->cmdsu.set11n.smps == 1) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s mimo_ps 1", rwl_client_path); /* dynamic */
+		exec_process(gCmdStr);
+	}
+	else if(Set11n->cmdsu.set11n.smps == 2) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s mimo_ps 0", rwl_client_path); /* static */
+		exec_process(gCmdStr);
+	}
+	else if(Set11n->cmdsu.set11n.smps == 3) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s mimo_ps 3", rwl_client_path); /* no limit */
+		exec_process(gCmdStr);
+	}
+	if ((Set11n->cmdsu.set11n.mcs_fixedrate >= 0) && (Set11n->cmdsu.set11n.mcs_fixedrate <= 31)) {
+
+#ifndef WIN32
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s nrate -m %d &> %s", rwl_client_path, Set11n->cmdsu.set11n.mcs_fixedrate, TEMP_FILE_PATH);
+#else
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s nrate -m %d > %s 2>&1", rwl_client_path, Set11n->cmdsu.set11n.mcs_fixedrate, TEMP_FILE_PATH);
+#endif
+		exec_process(gCmdStr);
+		if((tmpfd = fopen(TEMP_FILE_PATH, "r")) == NULL){
+			Set11nresp->status = STATUS_ERROR;	
+			wfaEncodeTLV(WFA_STA_SET_11N_RESP_TLV, 4, (BYTE *)Set11nresp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+			return TRUE;
+		}
+		fgets(gCmdStr, sizeof(gCmdStr), tmpfd);
+		Cleanup_File(tmpfd);
+/*
+ * wl rate is issued to check if the 11N supported chip is SISO or MIMO.
+ * If the response is 72Mbps then it is SISO,
+ * Checking if wl returning saying not in range, then invalid
+ */
+		if ((strstr(gCmdStr, "Range")) != NULL) {
+			DPRINT_INFO(WFA_OUT, "This card Doesnt Support this range\n");
+			Set11nresp->status = STATUS_INVALID;	
+			wfaEncodeTLV(WFA_STA_SET_11N_RESP_TLV, 4, (BYTE *)Set11nresp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+			return TRUE;
+		}
+
+	}
+
+
+
+	/*
+	 * Then report back to control PC for completion.
+	 * This does not have failed/error status. The result only tells
+	 * a completion.
+	 */
+	if(retVal == TRUE)
+		Set11nresp->status = STATUS_COMPLETE;
+	else
+		Set11nresp->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_SET_11N_RESP_TLV, 4, (BYTE *)Set11nresp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+#endif /* WFA_STA_TB */
+	return TRUE;
+}
+
+/*
+ * Part of sigma 11n implementation.
+ * Implementing RIFS test
+ */
+
+int wfaStaSetRifsTest(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+#ifdef WFA_STA_TB
+	int retVal = TRUE;
+	dutCmdResponse_t *RIFStest = &gGenericResp;
+	dutCommand_t *rifstest = (dutCommand_t *)caCmdBuf;
+	if(rifstest->cmdsu.action_rifs == 2) { /* enabled */
+		if(rwl_wifi_flag) {
+			asd_sleep(1);
+			S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s seq_start", rwl_client_path);
+			exec_process(gCmdStr);
+		}
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s down", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s ampdu 0", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s up", rwl_client_path);
+		exec_process(gCmdStr);
+		if(rwl_wifi_flag) {
+			asd_sleep(1);
+			S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s seq_stop", rwl_client_path);
+			exec_process(gCmdStr);
+		}
+		/*
+		 * nrate support 0-7 in SISO
+		 * nrate support 0-31 in MIMO
+		 */
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s nrate -m 12", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s rifs 1", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else if(rifstest->cmdsu.action_rifs == 1) { /* disable */
+		if(rwl_wifi_flag) {
+			asd_sleep(1);
+			S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s seq_start", rwl_client_path);
+			exec_process(gCmdStr);
+		}
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s down", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s up", rwl_client_path);
+		exec_process(gCmdStr);
+		if(rwl_wifi_flag) {
+			asd_sleep(1);
+			S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s seq_stop", rwl_client_path);
+			exec_process(gCmdStr);
+		}
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s rifs 0", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s band b", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s rate -1", rwl_client_path);
+		exec_process(gCmdStr);
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s band auto", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	if(retVal == TRUE)
+		RIFStest->status = STATUS_COMPLETE;
+	else
+		RIFStest->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_SET_RIFS_TEST_RESP_TLV, 4, (BYTE *)RIFStest, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+#endif /* WFA_STA_TB */
+	return TRUE;
+}
+
+/*
+ * Part of sigma 11n implementation.
+ * Implementing set wireless utility
+ */
+
+int wfaStaSetWireless(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+#ifdef WFA_STA_TB
+	int retVal = TRUE;
+	dutCmdResponse_t *SetWireless = &gGenericResp;
+	dutCommand_t *wireless = (dutCommand_t *)caCmdBuf;
+	if(strcasecmp(wireless->cmdsu.wireless_band, "2.4") == 0) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s band b", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else if(strcasecmp(wireless->cmdsu.wireless_band, "5") == 0) {
+		/*
+		 * Band a setting doesnt supported
+		 * Gives error -13
+		 */
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s band a", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s band auto", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	if(retVal == TRUE)
+		SetWireless->status = STATUS_COMPLETE;
+	else
+		SetWireless->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_SET_WIRELESS_RESP_TLV, 4, (BYTE *)SetWireless, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+#endif /* WFA_STA_TB */
+	return TRUE;
+}
+
+int wfaStaResetDefault(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+   caStaResetDefault_t *reset = (caStaResetDefault_t *)caCmdBuf;
+   dutCmdResponse_t *ResetResp = &gGenericResp;
+
+   /* need to implement based on program, defaults for each program set. */
+   S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s prog %s ", rwl_client_path, reset->prog);
+   exec_process(gCmdStr);
+
+   ResetResp->status = STATUS_COMPLETE;
+   wfaEncodeTLV(WFA_STA_RESET_DEFAULT_RESP_TLV, 4, (BYTE *)ResetResp, respBuf);
+   *respLen = WFA_TLV_HDR_LEN + 4;
+
+   return TRUE;
+}
+
+/*
+ * Part of sigma 11n implementation.
+ * Implementing send addba
+ */
+
+int wfaStaSendAddba(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+#ifdef WFA_STA_TB
+	int retVal = TRUE;
+	dutCmdResponse_t *SendAddba = &gGenericResp;
+	dutCommand_t *addba = (dutCommand_t *)caCmdBuf;
+	FILE *tmpfd;
+	char mac[WFA_MAC_ADDR_STR_LEN];
+	if(addba->cmdsu.tid) {
+#ifndef WIN32
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s bssid", rwl_client_path);
+#else
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s bssid >", rwl_client_path);
+#endif
+		if((tmpfd = asd_Config(gCmdStr,TEMP_FILE_PATH)) == NULL) {
+			DPRINT_ERR(WFA_OUT, "Error executing ssid\n");
+			SendAddba->status = STATUS_ERROR;	
+			wfaEncodeTLV(WFA_STA_SEND_ADDBA_RESP_TLV, 4, (BYTE *)SendAddba, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+			return TRUE;
+		}
+		else {
+			while((fscanf(tmpfd, "%s\n", gCmdStr)) != EOF) {
+				memset(mac, 0, WFA_MAC_ADDR_STR_LEN);
+				strncpy(mac, gCmdStr, strlen(gCmdStr));
+			}
+		}
+		Cleanup_File(tmpfd);
+		if (mac[2] != ':') /* if STA is not associated */
+		strcpy(mac, "00:00:00:00:00:00");
+		DPRINT_INFO(WFA_OUT, "MAC %s\n", mac);
+		/*
+		 * If STA not associated then error -2 displays
+		 */
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s ampdu_send_addba %d %s",
+			rwl_client_path, addba->cmdsu.tid, mac);
+		exec_process(gCmdStr);
+
+	}
+	else
+		retVal = FALSE;
+
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	if(retVal == TRUE)
+		SendAddba->status = STATUS_COMPLETE;
+	else
+		SendAddba->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_SEND_ADDBA_RESP_TLV, 4, (BYTE *)SendAddba, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+#endif /* WFA_STA_TB */
+	return TRUE;
+}
+
+
+/*
+ * Part of sigma 11n implementation.
+ * Implementing sending coexist management
+ */
+
+int wfaStaSendCoexistMgmt(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+#ifdef WFA_STA_TB
+	int retVal = FALSE; /* changed to make sure one of BSS or MHZ value presnt */
+	dutCmdResponse_t *CoexistMgmt = &gGenericResp;
+	dutCommand_t *coexist = (dutCommand_t *)caCmdBuf;
+	int mhz, bss;
+	/*
+	 * Either of BSS, MHZ value should be present in the option
+	 */
+	if (coexist->cmdsu.coexistmgmt.Mhz[0] != '\0') {
+		mhz = atoi(coexist->cmdsu.coexistmgmt.Mhz);
+		retVal = TRUE;
+	}
+	else {
+		mhz = 0;
+	}
+	if (coexist->cmdsu.coexistmgmt.bss[0] != '\0') {
+		bss = atoi(coexist->cmdsu.coexistmgmt.bss);
+		retVal = TRUE;
+	}
+	else {
+		bss = 0;
+	}
+	if (bss > 1 || bss < 0 || mhz >1 || mhz < 0) {
+		/* they can only have 0/1 */
+		DPRINT_INFO(WFA_OUT, "BSS or MHz can have value 1/0\n");
+		retVal = FALSE;
+	}
+	/*
+	 * This command also yet to be implemented from brcm
+	 */
+	if (coexist->cmdsu.coexistmgmt.ChnlRepo[0] != '\0' && 
+		coexist->cmdsu.coexistmgmt.ChnlRepo) {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s obss_coex_action -i %d -w %d -c %s", rwl_client_path, mhz, bss,
+			coexist->cmdsu.coexistmgmt.ChnlRepo);
+	}
+	else {
+		S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s obss_coex_action -i %d -w %d", rwl_client_path, mhz, bss);
+	}
+	if (retVal == TRUE)
+		exec_process(gCmdStr);
+	else
+		DPRINT_INFO(WFA_OUT, "should enter atleast one option in MHZ or BSS\n");
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	if(retVal == TRUE)
+		CoexistMgmt->status = STATUS_COMPLETE;
+	else
+		CoexistMgmt->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_SEND_COEXIST_MGMT_RESP_TLV, 4, (BYTE *)CoexistMgmt, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+#endif /* WFA_STA_TB */
+	return TRUE;
+}
+
+/*
+ * Part of sigma 11n implementation.
+ * Implementing disconnect
+ */
+
+int wfaStaSetDisconnect(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+#ifdef WFA_STA_TB
+	int retVal = TRUE;
+	dutCmdResponse_t *Disconnect = &gGenericResp;
+	dutCommand_t *discon = (dutCommand_t *)caCmdBuf;
+	DPRINT_INFO(WFA_OUT, "Entering set disconnect...\n");
+	DPRINT_INFO(WFA_OUT, "interface entered %s\n", discon->intf);
+
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s disassoc", rwl_client_path);
+	exec_process(gCmdStr);
+	if(retVal == TRUE)
+		Disconnect->status = STATUS_COMPLETE;
+	else
+		Disconnect->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_DISCONNECT_RESP_TLV, 4, (BYTE *)Disconnect, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+#endif /* WFA_STA_TB */
+	return TRUE;
+}
+
+/*
+ * Part of sigma 11n implementation.
+ * Implementing sending neighborhood request
+ */
+
+int wfaStaSendNeigreq(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{	
+#ifdef WFA_STA_TB
+	int retVal = TRUE;
+	dutCmdResponse_t *SendNeigreq = &gGenericResp;
+	dutCommand_t *neigreq = (dutCommand_t *)caCmdBuf;
+	char ssidTarget[WFA_SSID_NAME_LEN];
+	bcmSsidObj_t *bso;
+	DPRINT_INFO(WFA_OUT, "Entering send neighbourhood request ...\n");
+	memcpy(ssidTarget, neigreq->cmdsu.ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			return FALSE;
+		}
+	}
+	/* 
+	 * wl rrm_nbr_req need to have support for ssid parameter, currently it takes 
+	 * something else which is not recommended by wi-fi
+	 */
+	S_N_PRINTF(gCmdStr, WFA_CMD_STR_SZ, "%s rrm_nbr_req %s", rwl_client_path, ssidTarget);
+	DPRINT_INFO(WFA_OUT, "%s\n", gCmdStr);
+	exec_process(gCmdStr);
+	/*
+	* Then report back to control PC for completion.
+	* This does not have failed/error status. The result only tells
+	* a completion.
+	*/
+	if(retVal == TRUE)
+		SendNeigreq->status = STATUS_COMPLETE;
+	else
+		SendNeigreq->status = STATUS_ERROR;	
+	wfaEncodeTLV(WFA_STA_SEND_NEIGREQ_RESP_TLV, 4, (BYTE *)SendNeigreq, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+#endif /* WFA_STA_TB */
+	return TRUE;
+}
+
+/*
+* wfaStaSetFAST()
+*   This is to set
+*   1. ssid
+*   2. user name
+*   3. passwd
+*   4. encryType - tkip or aes-ccmp
+*   5. keyMgmtType - wpa or wpa2
+*   6. trustedRootCA
+*   7. innerEAP
+*   8. validateserver
+*   9. PACfile
+*/
+int wfaStaSetEapFAST(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetEapFAST_t *setFAST = (caStaSetEapFAST_t *)caCmdBuf;
+	int retVal = TRUE;
+	dutCmdResponse_t *setFastResp = &gGenericResp;
+	bcmSsidObj_t *bso;
+	char ssidTarget[WFA_SSID_NAME_LEN];
+
+	memcpy(ssidTarget, setFAST->ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			retVal = FALSE;
+		}
+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+			bcmWfaSsidObjPrint(bso);
+		}
+
+	}
+	
+	memcpy(&(bso->eapObj.setEapFAST), setFAST, sizeof(caStaSetEapFAST_t));
+	bso->eapType = BCM_EAP_TYPE_FAST;
+
+	if(strstr(bso->eapObj.setEapFAST.encrptype,"aes-ccmp"))
+			strncpy(bso->eapObj.setEapFAST.encrptype, AES_ENCPTYPE, AES_LEN) ;
+	if(retVal == TRUE)
+		setFastResp->status = STATUS_COMPLETE;
+	else
+		setFastResp->status = STATUS_ERROR;
+	wfaEncodeTLV(WFA_STA_SET_EAPFAST_RESP_TLV, 4, (BYTE *)setFastResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/*
+* wfaStaSetEapAKA()
+*   This is to set
+*   1. ssid
+*   2. user name
+*   3. passwd
+*   4. encryType - tkip or aes-ccmp
+*   5. keyMgmtType - wpa or wpa2
+*/
+int wfaStaSetEapAKA(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	caStaSetEapAKA_t *setAKA = (caStaSetEapAKA_t *)caCmdBuf;
+	dutCmdResponse_t *setAkaResp = &gGenericResp;
+	bcmSsidObj_t *bso;
+	int retVal = TRUE;
+	char ssidTarget[WFA_SSID_NAME_LEN];
+
+	memcpy(ssidTarget, setAKA->ssid, WFA_SSID_NAME_LEN);
+	bso = bcmWfaSsidTblSsidFind(ssidTarget);
+	if (!bso) {
+		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
+			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
+			retVal = FALSE;
+		}
+		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
+			bcmWfaSsidObjPrint(bso);
+		}
+
+	}
+	
+	memcpy(&(bso->eapObj.setEapAKA), setAKA, sizeof(caStaSetEapAKA_t));
+	bso->eapType = BCM_EAP_TYPE_AKA;
+
+	if(strstr(bso->eapObj.setEapAKA.encrptype,"aes-ccmp"))
+			strncpy(bso->eapObj.setEapAKA.encrptype, AES_ENCPTYPE, AES_LEN) ;
+	if(retVal == TRUE)
+		setAkaResp->status = STATUS_COMPLETE;
+	else
+		setAkaResp->status = STATUS_ERROR;
+	wfaEncodeTLV(WFA_STA_SET_EAPAKA_RESP_TLV, 4, (BYTE *)setAkaResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_miscs.c b/src/tools/Wifi_ASD_test/lib/wfa_miscs.c
new file mode 100644
index 0000000..9dbfa48
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_miscs.c
@@ -0,0 +1,307 @@
+ 
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors (.$B!H.(BAuthorized Licensees.$B!I.(B)...A.N  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee.$B!G.(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below...A.N  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee.$B!G.(Bs product to their customers with or
+ *  without such third party.$B!G.(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications...A.N  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein...A.N 
+ *..A.N 
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *..A.N 
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *..A.N 
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A..A.N PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+
+/*
+ * File: wfa_miscs.c - misc functions for agents.
+ * 
+ *       Revision History:
+ *          2006/03/10 -- initially created by qhu
+ *          2006/06/01 -- BETA release by qhu
+ *          2006/06/13 -- 00.02 release by qhu
+ *          2006/06/30 -- 00.10 Release by qhu
+ *          2006/07/10 -- 01.00 Release by qhu
+ *          2006/09/01 -- 01.05 Release by qhu
+ *          2007/01/11 -- 01.10 Released by qhu
+ *          2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi
+ *          2007/03/30 -- 01.40 WPA2 and Official WMM Beta Release by qhu
+ *          2007/04/20 -- 02.00 WPA2 and Official WMM Release by qhu
+ *          2007/08/15 --  02.10 WMM-Power Save release by qhu
+ *          2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *          2007/11/07 --  02.30 Voice HSO -- qhu
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wfa_debug.h"
+#include "wfa_sock.h"
+#include "wfa_main.h"
+#include "wfa_types.h"
+#include "wfa_tg.h"
+#include "wfa_miscs.h"
+#include "wfa_cmds.h"
+#ifdef WIN32
+#include "io.h"
+#endif /* #ifdef WIN32 */
+#include "stdlib.h"
+
+#ifndef SIOCGIWNAME
+#define SIOCGIWNAME 0x8B01
+#endif
+
+extern unsigned short wfa_defined_debug;
+extern tgStream_t *theStreams;
+extern char PingStr[];
+tgStream_t *findStreamProfile(int id);
+
+/*
+ * printProfile(): a debugging function to display a profile info based on
+ *                 a streamId
+ */
+
+void printProfile(tgProfile_t *pf)
+{
+	DPRINT_INFO(WFA_OUT, "profile type %i direction %i Dest ipAddr %s Dest port %i So ipAddr %s So port %i rate %i duration %i pksize %i\n", pf->profile, pf->direction, pf->dipaddr, pf->dport, pf->sipaddr, pf->sport, pf->rate, pf->duration, pf->pksize);
+}
+
+
+int isString(char *str)
+{
+	if(*str == '\0')
+		return FALSE;
+
+	if((str[0] >= 'a' && str[0] <= 'z') 
+		|| (str[0] > 'A' && str[0] < 'Z'))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+int isNumber(char *str)
+{
+	if(*str == '\0')
+		return FALSE;
+
+	if (str[0] >= '0' && str[0] <= '9')
+		return TRUE;
+	else
+		return FALSE;
+}
+
+int isIpV4Addr(char *str)
+{
+	int dots = 0;
+	char *tmpstr = str;
+
+	if(*str == '\0')
+		return FALSE;
+
+	while(*tmpstr != '\0')
+	{
+		if(*tmpstr == '.')
+		{
+			dots++;
+		}
+
+		tmpstr++;
+	}
+
+	if(dots <3)
+		return FALSE;
+	else
+		return TRUE;
+}
+
+
+
+inline double wfa_timeval2double(struct timeval *tval)
+{
+	return ((double) tval->tv_sec + (double) tval->tv_usec*1e-6);
+}
+
+inline void wfa_double2timeval(struct timeval *tval, double dval)
+{
+	tval->tv_sec = (long int) dval;
+	tval->tv_usec = (long int) ((dval - tval->tv_sec) * 1000000);
+}
+
+inline double wfa_ftime_diff(struct timeval *t1, struct timeval *t2)
+{
+	double dtime;
+
+	dtime = wfa_timeval2double(t2) - wfa_timeval2double(t1);
+	return dtime ;
+}
+
+int wfa_itime_diff(struct timeval *t1, struct timeval *t2)
+{
+	int dtime;
+	int sec = t2->tv_sec - t1->tv_sec;
+	int usec = t2->tv_usec - t1->tv_usec;
+
+	if(usec < 0)
+	{
+		sec -=1;
+		usec += 1000000;
+	}
+
+	dtime = sec*1000000 + usec;
+	return dtime;
+}
+
+
+/*
+ * THe following two functions are converting Little Endian to Big Endian. 
+ * If your machine is already a Big Endian, you may flag it out.
+ */
+inline void int2BuffBigEndian(int val, char *buf)
+{
+	char *littleEn = (char *)&val;
+
+	buf[0] = littleEn[3];
+	buf[1] = littleEn[2];
+	buf[2] = littleEn[1];
+	buf[3] = littleEn[0];
+}
+
+int bigEndianBuff2Int(char *buff)
+{
+	int val;
+	char *strval = (char *)&val;
+
+	strval[0] = buff[3];
+	strval[1] = buff[2];
+	strval[2] = buff[1];
+	strval[3] = buff[0];
+
+	return val;
+}
+
+
+/*
+ * The following functions will execute the function by calling asd_Config
+ * and results are captured in strstrParams. 
+ * The stderr is captured in temporary file. 
+ */
+
+int
+asd_Config_wmm(char *strFunct, char *strstrParams)
+{
+	FILE *pipe_fp, *err_fp;
+	char temp[280];
+	int stat, err_file_size, newErrFd;
+
+	if ((err_fp = fopen(TEMP_STD_ERR_FILE, "w+")) == NULL) {
+		DPRINT_ERR(WFA_ERR, "\nFile open error\n");
+		return -1;
+	}
+	newErrFd = DUP(STD_ERR);
+
+	if ((stat = DUP2(fileno(err_fp), STD_ERR)) == -1)  {
+		DPRINT_ERR(WFA_ERR, "Error in dup2(fd, STD_ERR) \n");
+		return 0;
+	}
+
+	sprintf(strFunct, "%s > %s", strFunct, strstrParams);
+
+	/* Execute the command */
+	if((pipe_fp = asd_Config(strFunct, strstrParams)) == NULL){
+		DPRINT_ERR(WFA_ERR, "asd_Config_wmm:: Error in executing asd_Config\n");
+		return -1;
+	}
+	fflush(stderr);	
+	fgets(temp, sizeof(temp), pipe_fp);
+	Cleanup_File(pipe_fp);
+
+	/* obtain error file size */
+	if (fseek(err_fp, 0, SEEK_END) < 0)
+		return -1;
+	err_file_size = ftell(err_fp);
+	fclose(err_fp);	
+
+	if ((stat = DUP2(newErrFd, STD_ERR)) == -1) {
+		DPRINT_ERR(WFA_ERR, "Error in dup2(newErrFd, STD_ERR) \n");
+		return 0;
+	}
+
+	return err_file_size;
+}
+
+/*
+ * The following functions will execute the function by calling exec_process
+ * The stderr is captured in temporary file. 
+ */
+
+int
+exec_wmmCmd(char* command)
+{
+	int newErrFd, stat, file_size;
+	FILE *fp;
+
+	fp = fopen(TEMP_STD_ERR_FILE, "w+");
+	if ((newErrFd = DUP(STD_ERR)) == -1) {
+		DPRINT_ERR(WFA_ERR, "\nError in dup(2)\n");
+		return newErrFd;
+	}
+
+	if ((stat = DUP2(fileno(fp), STD_ERR)) == -1) {
+		DPRINT_ERR(WFA_ERR, "\nError in dup2(fd, 2)\n");
+		return stat;
+	}
+
+	exec_process(command);
+
+	/* obtain file size */
+	fflush(stderr);	
+	if (fseek(fp, 0, SEEK_END) < 0)
+		file_size = 0;
+	file_size = ftell(fp);
+	fclose(fp);	
+
+	if ((stat = DUP2(newErrFd, STD_ERR)) == -1) {
+		DPRINT_ERR(WFA_ERR, "\nError in dup2(newErrFd, 2)\n");
+		return stat;
+	}
+	return file_size;
+}
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_miscs_linux.c b/src/tools/Wifi_ASD_test/lib/wfa_miscs_linux.c
new file mode 100755
index 0000000..fc9f794
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_miscs_linux.c
@@ -0,0 +1,260 @@
+/*
+ * Linux port of asd command line utility
+ *
+ * Copyright 2002, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied or
+ * duplicated in any form, in whole or in part, without the prior written
+ * permission of Broadcom Corporation.
+ *
+ */
+#include <arpa/inet.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "wfa_debug.h"
+#include "wfa_main.h"
+#include "wfa_types.h"
+#include "wfa_tg.h"
+#include "wfa_miscs.h"
+#include "wfa_cmds.h"
+
+#ifndef SIOCGIWNAME
+#define SIOCGIWNAME 0x8B01
+#endif
+extern unsigned short wfa_defined_debug;
+extern tgStream_t *theStreams;
+extern char PingStr[];
+tgStream_t *findStreamProfile(int id);
+void
+asd_sleep(int SleepTime)
+{
+
+	sleep(SleepTime);
+
+}
+
+void
+uapsd_sleep(int SleepTime)
+{
+
+	usleep(SleepTime);
+
+}
+
+void
+asd_closeSocket(int sockfd)
+{
+	close(sockfd);
+
+}
+void
+asd_shutDown(int Sockfd)
+{
+	shutdown(Sockfd, SHUT_WR);
+
+}
+void
+exec_process(char* command)
+{
+	system(command);
+}
+
+int
+Start_Socket_Service()
+{
+	return 0;
+}
+int
+Stop_Socket_Service()
+{
+	return 0;
+}
+
+void 
+wfaGetSockOpt(int sockfd, int* tosval, socklen_t* size)
+{
+	getsockopt(sockfd, IPPROTO_IP, IP_TOS, tosval, size);
+}
+
+int
+wfaSetSockOpt(int sockfd, int* tosval, int size)
+{
+	int sockOpt;
+	sockOpt = setsockopt(sockfd, IPPROTO_IP, IP_TOS, tosval, size);
+	return sockOpt;
+}
+
+int
+wfa_estimate_timer_latency()
+{
+	struct timeval t1, t2, tp2;
+	int sleep=20000; /* two miniseconds */
+	int latency =0;
+
+	gettimeofday(&t1, NULL);
+	usleep(sleep);
+
+	gettimeofday(&t2, NULL); 
+
+	tp2.tv_usec = t1.tv_usec + 20000;
+	if( tp2.tv_usec >= 1000000)
+	{
+		tp2.tv_sec = t1.tv_sec +1;
+		tp2.tv_usec -= 1000000;
+	}
+	else
+		tp2.tv_sec = t1.tv_sec;
+
+	return latency = (t2.tv_sec - tp2.tv_sec) * 1000000 + (t2.tv_usec - tp2.tv_usec); 
+}
+
+/* This function returns the wireless adapter in Linux systems. 
+ * This is for getting wireless adapter name programmatically */
+void
+GetWirelessAdapter(char *adapter_name)
+{
+	char	buf[1024];
+	struct	ifconf ifc;
+	struct	ifreq *ifr;
+	int	sck;
+	int	nInterfaces;
+	int	i;
+	struct utsname name;
+	uname(&name);
+	/* Checking for x86 architecture */
+	if (!strcmp(name.machine, "i386") || !strcmp(name.machine, "i686") || !strcmp(name.machine, "i586")) {
+			
+		/* Get a socket handle. */
+		sck = socket(AF_INET, SOCK_DGRAM, 0);
+		if (sck < 0) {
+			perror("socket");
+			return ;
+		}
+
+		/* Query available interfaces. */
+		ifc.ifc_len = sizeof(buf);
+		ifc.ifc_buf = buf;
+		if (ioctl(sck, SIOCGIFCONF, &ifc) < 0) {
+			perror("ioctl(SIOCGIFCONF)");
+			close (sck);
+			return ;
+		}
+
+		/* Iterate through the list of interfaces. */
+		ifr = ifc.ifc_req;
+		nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
+		for (i = 0; i < nInterfaces; i++) {
+			struct ifreq *item = &ifr[i];
+			if (ioctl(sck, SIOCGIWNAME, item) == 0) {
+				strncpy(adapter_name,item->ifr_name, sizeof(item->ifr_name));
+				close(sck);
+				return;
+			}
+		}
+		close (sck);
+	}
+#ifdef TARGETENV_android
+	else { /* If its android */
+		strncpy (adapter_name, "eth0", 15);
+	}
+#else
+	else { /* If its ARM */ 
+		strncpy (adapter_name,"eth1", 15);
+	}
+#endif
+	return;
+
+}
+
+
+
+FILE*
+asd_Config(char *strFunct, char *strstrParams)
+{
+	FILE* fp = NULL;
+	if ((fp = popen(strFunct, "r")) == NULL) {
+		printf("popen failed\n");
+		return NULL;
+	}
+	return fp;
+}
+void
+Cleanup_File(FILE* fp)
+{
+	pclose(fp);
+}
+
+int exec_process_cnclient (char *buf, char *rwl_client_path, int rwl_wifi_flag)
+{
+	int pid, status,timeout_count = 30;
+	FILE *tmpfd;
+	char gCmdStr[WFA_CMD_STR_SZ];
+
+	if (rwl_wifi_flag) {
+		pid = fork();
+		if (pid == 0) {
+			if ((status=execl (SH_PATH, "sh", "-c", buf, NULL)) == -1)
+				exit (1);		
+		}
+		/*The server can be in different channel after association
+		 *Hence we issue a findserver and then find out if it has
+		 *been associated to return the right status
+		 */	
+		asd_sleep(3);
+		sprintf(gCmdStr, "%s findserver", rwl_client_path);
+		pid = fork();
+		if (pid == 0) {
+			if ((status=execl (SH_PATH, "sh", "-c", gCmdStr, NULL)) == -1)
+				exit (1);		
+		}
+		waitpid(pid,&status,0);
+	}
+	else {
+		pid = fork();
+		if (pid == 0) {
+			if ((status=execl (SH_PATH, "sh", "-c", buf, NULL)) == -1)
+				exit (1);		
+		}
+		waitpid(pid,&status,0);
+	}
+	/* while cnClient associates in the child, parent looks 
+	 * for association if it has happened
+	 * If it has not associated within a loop of 30, it comes out
+	 * as not associated
+	 */ 
+	while(timeout_count > 0){
+		sprintf(gCmdStr, "%s assoc | wc -l", rwl_client_path);
+		if((tmpfd = asd_Config(gCmdStr,TEMP_FILE_PATH)) == NULL){
+			DPRINT_ERR(WFA_ERR, "\nassoc failed\n");
+			return FALSE;
+			}
+		fgets(gCmdStr, sizeof(gCmdStr), tmpfd);
+		/* Short response means not associated */
+		if (atoi(gCmdStr) > 2)
+			break;
+		/* End: Added as per BRCM 1.3 ASD */
+		Cleanup_File(tmpfd);
+		asd_sleep(1);
+		timeout_count--;
+	}
+	if(timeout_count)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+void p_error(char *errorString)
+{
+	perror(errorString);
+}
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_miscs_win32.c b/src/tools/Wifi_ASD_test/lib/wfa_miscs_win32.c
new file mode 100755
index 0000000..f7acd69
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_miscs_win32.c
@@ -0,0 +1,609 @@
+/*
+ * Windows port of asd command line utility
+ *
+ * Copyright 2002, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied or
+ * duplicated in any form, in whole or in part, without the prior written
+ * permission of Broadcom Corporation.
+ *
+ */
+
+#include <Winsock2.h>
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tchar.h>
+
+
+#include "wfa_debug.h"
+#include "wfa_sock.h"
+#include "wfa_main.h"
+#include "wfa_types.h"
+#include "wfa_tg.h"
+#include "wfa_miscs.h"
+#include "wfa_cmds.h"
+
+#ifndef SIOCGIWNAME
+#define SIOCGIWNAME 0x8B01
+#endif
+
+#define RECV_OFFSET 22
+
+extern unsigned short wfa_defined_debug;
+extern tgStream_t *theStreams;
+extern char PingStr[];
+tgStream_t *findStreamProfile(int id);
+HANDLE processHandle = NULL;
+HANDLE processThread = NULL; 
+
+void
+asd_sleep(int SleepTime)
+{
+
+	Sleep(SleepTime * 1000);
+
+}
+
+void
+uapsd_sleep(int SleepTime)
+{
+
+	usleep(SleepTime/1000);
+
+}
+
+void 
+asd_closeSocket(int sockfd)
+{
+	closesocket(sockfd);
+
+}
+
+void
+asd_shutDown(int Sockfd)
+{
+
+	shutdown(Sockfd, SD_SEND);
+}
+
+void 
+wfaGetSockOpt(int sockfd, int* tosval, socklen_t* size)
+{
+	getsockopt(sockfd, IPPROTO_IP, IP_TOS, (char FAR*)tosval, size);
+}
+
+int 
+wfaSetSockOpt(int sockfd, int* tosval, int size)
+{
+	int sockOpt;
+	sockOpt = setsockopt(sockfd, IPPROTO_IP, IP_TOS, (char FAR*)tosval, size);
+	return sockOpt;
+}
+
+int
+exec_process_cnclient (char *buf, char *rwl_client_path, int rwl_wifi_flag)
+{
+	unsigned int  position;
+	char gCmdStr[WFA_CMD_STR_SZ];
+	int timeout_count = 30;
+	FILE *tmpfd;
+	/* Create Process related variables */
+	PROCESS_INFORMATION ProcessInfo;
+	char Args[WFA_BUFF_512];
+	TCHAR pDefaultCMD[WFA_BUFF_512];
+	STARTUPINFO StartupInfo;
+	
+	if (rwl_wifi_flag){
+		/*The server can be in different channel after association
+		 *Hence we issue a findserver and then find out if it has
+		 *been associated to return the right status
+		 */	
+	
+		memset(Args, 0, WFA_BUFF_512);
+		sprintf(Args, "%s", (const char *)buf);
+		memset(&ProcessInfo, 0, sizeof(ProcessInfo));
+		memset(&StartupInfo, 0, sizeof(StartupInfo));
+		StartupInfo.cb = sizeof(StartupInfo);
+		/*  "/C" option - Do the command and EXIT the command processor */
+		_tcscpy(pDefaultCMD, _T("cmd.exe /C "));
+		_tcscat(pDefaultCMD, Args);
+		if(!CreateProcess(NULL,(LPTSTR)pDefaultCMD, NULL,NULL,FALSE,FALSE,NULL,NULL,
+			&StartupInfo,&ProcessInfo)){
+				processHandle = ProcessInfo.hProcess;
+				processThread = ProcessInfo.hThread; 
+				return FALSE;
+		}
+		asd_sleep(3);
+		sprintf(gCmdStr, "%s findserver", rwl_client_path);
+		exec_process(gCmdStr);
+	}
+	else {
+		exec_process(buf);
+	}
+	
+	/* while cnClient associates in the child, parent looks 
+	 * for association if it has happened
+	 * If it has not associated within a loop of 30, it comes out
+	 * as not associated
+	 */ 
+	while(timeout_count > 0){
+		strcpy(gCmdStr, rwl_client_path);
+		strcat(gCmdStr, " assoc >");
+		if((tmpfd = asd_Config(gCmdStr,TEMP_FILE_PATH)) == NULL){
+			DPRINT_ERR(WFA_ERR, "\nassoc failed\n");
+			return FALSE;
+			}
+		if((FileSearch(tmpfd, L"Not associated", &position))== -1) {
+			Cleanup_File(tmpfd);
+			break;
+		}
+		Cleanup_File(tmpfd);
+		asd_sleep(1);
+		timeout_count--;
+	}
+	if(timeout_count)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+void
+exec_process(char* command)
+{
+	char wl_cmd[WFA_BUFF_256];
+	memset(wl_cmd,0,sizeof(wl_cmd));
+	strncpy(wl_cmd, command, strlen(command));
+	DPRINT_INFO(WFA_OUT,"%s\n",wl_cmd);
+	asd_Config(wl_cmd," ");
+}
+
+int
+Start_Socket_Service()
+{
+	int err = 0;
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	/* Initialize winsock library */
+	wVersionRequested = MAKEWORD( 2, 2 );
+	err = WSAStartup(wVersionRequested, &wsaData);
+	return err;
+}
+
+int
+Stop_Socket_Service()
+{
+	return WSACleanup();
+}
+
+char * strtok_r(char *s1, const char *s2, char **lasts)
+{
+	char *ret;
+
+	if (s1 == NULL)
+		s1 = *lasts;
+
+	while(*s1 && strchr(s2, *s1))
+		++s1;
+
+	if(*s1 == '\0')
+		return NULL;
+
+	ret = s1;
+
+	while(*s1 && !strchr(s2, *s1))
+		++s1;
+
+	if(*s1)
+		*s1++ = '\0';
+
+	*lasts = s1;
+
+	return ret;
+} 
+
+int strcasecmp(const char *s1, const char *s2)
+{
+	const unsigned char *us1 = (const unsigned char *)s1;
+	const unsigned char *us2 = (const unsigned char *)s2;
+
+	while (tolower(*us1) == tolower(*us2)) {
+		if (*us1++ == '\0')
+			return (0);
+		us2++;
+	}
+	return (tolower(*us1) - tolower(*us2));
+}
+
+int strncasecmp(const char *s1,const char *s2, unsigned int length)
+{
+	unsigned char u1, u2;
+
+	for (; length != 0; length--, s1++, s2++) {
+		u1 = (unsigned char) *s1;
+		u2 = (unsigned char) *s2;
+
+		if (tolower(u1) != tolower(u1)) {
+			return tolower(u1) - tolower(u1);
+		}
+		if (u1 == '\0') {
+			return 0;
+		}
+	}
+	return 0;
+}
+
+__inline int wmemcmp(const wchar_t *_S1, const wchar_t *_S2, size_t _N)
+        {for (; 0 < _N; ++_S1, ++_S2, --_N)
+                if (*_S1 != *_S2)
+                        return (*_S1 < *_S2 ? -1 : +1);
+        return (0); }
+__inline wchar_t *wmemcpy(wchar_t *_S1, const wchar_t *_S2, size_t _N)
+        {wchar_t *_Su1 = _S1;
+        for (; 0 < _N; ++_Su1, ++_S2, --_N)
+                *_Su1 = *_S2;
+        return (_S1); }
+__inline wchar_t *wmemmove(wchar_t *_S1, const wchar_t *_S2, size_t _N)
+        {wchar_t *_Su1 = _S1;
+        if (_S2 < _Su1 && _Su1 < _S2 + _N)
+                for (_Su1 += _N, _S2 += _N; 0 < _N; --_N)
+                        *--_Su1 = *--_S2;
+        else
+                for (; 0 < _N; --_N)
+                        *_Su1++ = *_S2++;
+        return (_S1); }
+__inline wchar_t *wmemset(wchar_t *_S, wchar_t _C, size_t _N)
+        {wchar_t *_Su = _S;
+        for (; 0 < _N; ++_Su, --_N)
+                *_Su = _C;
+        return (_S); }
+
+int GetPingStat(FILE* pFile, const wchar_t* lpszSearchString , unsigned int *recv,unsigned int *sent, const char* delim) 
+{ 
+	unsigned long ulFileSize, ulBufferSize; 
+	wchar_t lpBuffer[WFA_BUFF_512];
+	char mbsbuffer[WFA_BUFF_512], str[WFA_BUFF_128];
+	unsigned int *ulCurrentPosition, *ulReceived, *ulsent;
+	int retval;
+
+	ulCurrentPosition=recv;
+	ulReceived= recv;
+	ulsent = sent; 
+
+	//make sure we were passed a valid, if it isn't return -1 
+	if ((!pFile)||(!lpszSearchString)) { 
+		return -1; 
+	} 
+
+	//get the size of the file 
+	fseek(pFile,0,SEEK_END); 
+
+	ulFileSize=ftell(pFile); 
+
+	fseek(pFile,0,SEEK_SET); 
+
+	//if the file is empty return -1 
+	if (!ulFileSize) { 
+		return -1; 
+	} 
+
+	//get the length of the string we're looking for, this is 
+	//the size the buffer will need to be 
+	ulBufferSize=wcslen(lpszSearchString); 
+
+	if (ulBufferSize>ulFileSize) { 
+		return -1; 
+	} 
+
+	*ulCurrentPosition=0; 
+
+	//this is where the actual searching will happen, what happens 
+	//here is we set the file pointer to the current position 
+	//is incrimented by one each pass, then we read the size of 
+	//the buffer into the buffer and compare it with the string 
+	//we're searching for, if the string is found we return the 
+	//position at which it is found 
+	while (*ulCurrentPosition<ulFileSize-ulBufferSize) { 
+		fseek(pFile,*ulCurrentPosition,SEEK_SET); 
+		wmemset(lpBuffer, 0, WFA_BUFF_512);
+		//read ulBufferSize bytes from the file 
+		fread(mbsbuffer,1,ulBufferSize,pFile); 
+
+		retval = mbstowcs(lpBuffer, mbsbuffer, strlen(mbsbuffer)); 
+
+		//if the data read matches the string we're looking for
+		//read from the offset where recieve data starts 
+		if (!wmemcmp(lpBuffer, lpszSearchString, ulBufferSize)) { 
+			fread(str, 1, RECV_OFFSET, pFile);
+			*ulReceived = atoi(str);
+			strtok(str, (const char*)ulReceived);
+			//fread(str,1,ulBufferSize,pFile);
+			//strtok(str, delim);
+			*ulsent= atoi(str);
+			//return the position the string was found at 
+			return *ulCurrentPosition; 
+		} 
+
+		++*ulCurrentPosition; 
+	} 
+	return -1;
+} 
+
+int GetStats(FILE* pFile, const wchar_t* lpszSearchString , unsigned int *pos, const char* delim) 
+{ 
+
+	char* lpBuffer;
+	char* str;
+    char mbsString[128];
+	unsigned long ulFileSize, ulBufferSize; 	
+	unsigned int *ulCurrentPosition;
+	ulCurrentPosition = pos;
+
+	memset(mbsString, 0, 128);
+	/* convert the wide character search string to multibyte */
+	wcstombs(mbsString,lpszSearchString, wcslen(lpszSearchString) );
+	/* make sure we were passed a valid, if it isn't return -1 */
+	if ((!pFile)||(!lpszSearchString)) { 
+		return -1; 
+	} 
+
+	/* get the size of the file */
+	fseek(pFile,0,SEEK_END); 
+
+	ulFileSize=ftell(pFile); 
+
+	fseek(pFile,0,SEEK_SET); 
+
+	/* if the file is empty return -1 */
+	if (!ulFileSize) { 
+		return -1; 
+	} 
+
+	/* get the length of the string we're looking for, this is 
+	 * the size the buffer will need to be */
+	ulBufferSize=wcslen(lpszSearchString); 
+
+	if (ulBufferSize>ulFileSize) { 
+		return -1; 
+	} 
+    /* allocate the memory for the buffer */
+     lpBuffer=(char*)malloc(strlen(mbsString)); 
+	 str = (char*)malloc(strlen(mbsString));
+	/* if malloc() returned a null pointer (which probably means 
+     * there is not enough memory) then return -1  */
+	 if (!lpBuffer ) 
+    { 
+        return -1; 
+    } 
+	*ulCurrentPosition=0; 
+
+	/* this is where the actual searching will happen, what happens 
+	 * here is we set the file pointer to the current position 
+	 * is incrimented by one each pass, then we read the size of 
+	 * the buffer into the buffer and compare it with the string 
+	 * we're searching for, if the string is found we return the 
+	 * position at which it is found */
+
+	while (*ulCurrentPosition<ulFileSize-ulBufferSize) { 
+		fseek(pFile,*ulCurrentPosition,SEEK_SET); 
+		/* if the data read matches the string we're looking for */
+		fread(lpBuffer,1,ulBufferSize,pFile); 
+		if (!memcmp(lpBuffer,mbsString,ulBufferSize)) 
+        { 
+			fread(str,1,ulBufferSize,pFile);
+			strtok(str, delim);
+			*ulCurrentPosition = atoi(str);
+
+			/* free the buffer */
+			if(lpBuffer != NULL || str != NULL){
+				free(lpBuffer); 
+				free(str);
+			}
+			/* return the position the string was found at */
+			return *ulCurrentPosition; 
+		} 
+        /* incriment the current position by one */
+		++*ulCurrentPosition; 
+    } 
+
+    /* if we made it this far the string was not found in the file 
+     * so we free the buffer */
+    if(lpBuffer != NULL || str != NULL){
+			free(str);
+            free(lpBuffer); 
+	} 
+	return -1;
+} 
+
+int FileSearch(FILE* pFile, const wchar_t* lpszSearchString , unsigned int *pos) 
+{ 
+	
+	char* lpBuffer;
+	 char mbsString[128];
+	unsigned long ulFileSize = 0, ulBufferSize;
+	unsigned long *ulCurrentPosition;
+	ulCurrentPosition= pos;
+	memset(mbsString, 0, 128);
+	/* convert the wide character search string to multibyte */
+	wcstombs(mbsString,lpszSearchString, wcslen(lpszSearchString) );
+	/* make sure we were passed a valid, if it isn't return -1 */
+	if ((!pFile)||(!lpszSearchString)) { 
+		return -1; 
+	} 
+
+	/* get the size of the file */
+	fseek(pFile,0,SEEK_END); 
+
+	ulFileSize=ftell(pFile); 
+
+	fseek(pFile,0,SEEK_SET); 
+
+	/* if the file is empty return -1 */
+	if (!ulFileSize) { 
+		return -1; 
+	} 
+
+	/* get the length of the string we're looking for, this is 
+	 * the size the buffer will need to be */
+	ulBufferSize=wcslen(lpszSearchString); 
+
+	if (ulBufferSize > ulFileSize) { 
+		return -1; 
+	} 
+
+    /* allocate the memory for the buffer */
+     lpBuffer=(char*)malloc(strlen(mbsString)); 
+	/* if malloc() returned a null pointer (which probably means 
+     * there is not enough memory) then return -1 */
+
+	 if (!lpBuffer ) 
+    { 
+        return -1; 
+    } 
+	*ulCurrentPosition=0; 
+
+	/* this is where the actual searching will happen, what happens 
+	 * here is we set the file pointer to the current position 
+	 * is incrimented by one each pass, then we read the size of 
+	 * the buffer into the buffer and compare it with the string 
+	 * we're searching for, if the string is found we return the 
+	 * position at which it is found */
+	while (*ulCurrentPosition<ulFileSize-ulBufferSize) { 
+		fseek(pFile,*ulCurrentPosition,SEEK_SET); 
+		/* if the data read matches the string we're looking for */
+		  fread(lpBuffer,1,ulBufferSize,pFile); 
+		if (!memcmp(lpBuffer,mbsString,ulBufferSize)) 
+		{ 
+			/* free the buffer */
+			if(lpBuffer != NULL)
+            free(lpBuffer); 
+			/* return the position the string was found at */
+			return *ulCurrentPosition; 
+		} 
+
+		/* incriment the current position by one */
+		++*ulCurrentPosition; 
+	} 
+    /* if we made it this far the string was not
+     * found in the file so we free the buffer */
+    if(lpBuffer != NULL)
+            free(lpBuffer); 
+	return -1;
+} 
+
+unsigned int uGetLocalIP()
+{
+	char szHostName[WFA_BUFF_256];
+	struct hostent*	HostData;
+
+	GetHostName(szHostName, WFA_BUFF_256);
+	HostData = gethostbyname(szHostName);
+	if (HostData == NULL)
+		return 0;
+
+	return *((unsigned int*)HostData->h_addr);
+}
+
+char* GetHostName(char* buf, int len) 
+{
+	if (gethostname(buf, len) == SOCKET_ERROR)
+		return NULL;
+	return buf;
+}
+
+int wfa_Winitime_diff(SYSTEMTIME *t1, SYSTEMTIME *t2)
+{
+	int dtime;
+	int sec = t2->wSecond - t1->wSecond;
+	int msec = (t2->wMilliseconds - t1->wMilliseconds);
+
+	if(msec < 0)
+	{
+		sec -=1;
+		msec += 1000;
+	}
+
+	dtime = sec*1000 + msec;
+	return dtime;
+}
+
+int wfa_Win_estimate_timer_latency()
+{
+	SYSTEMTIME t1, t2, tp2;
+	int sleep =2;
+	int latency =0;
+
+	GetSystemTime(&t1);
+	usleep(sleep);
+
+	GetSystemTime(&t2); 
+
+	tp2.wMilliseconds = t1.wMilliseconds  +20;
+	if( tp2.wMilliseconds >= 1000) {
+		tp2.wSecond = t1.wSecond +1;
+		tp2.wMilliseconds -= 1000;
+	}
+	else
+		tp2.wSecond = t1.wSecond;
+
+	return latency = (t2.wSecond - tp2.wSecond)  + (t2.wMilliseconds - tp2.wMilliseconds); 
+}
+
+
+FILE* asd_Config(char *strFunct, char *strstrParams)
+{
+	FILE* fp = NULL;
+	PROCESS_INFORMATION ProcessInfo;
+	char Args[WFA_BUFF_512];
+	TCHAR pDefaultCMD[WFA_BUFF_512];
+	STARTUPINFO StartupInfo;
+	ULONG rc;
+
+	Args[0]= 0;
+	memset(Args, 0, WFA_BUFF_512);
+	sprintf(Args, "%s %s", (const char *)strFunct, (const char *)strstrParams);
+	memset(&ProcessInfo, 0, sizeof(ProcessInfo));
+	memset(&StartupInfo, 0, sizeof(StartupInfo));
+	StartupInfo.cb = sizeof(StartupInfo);
+	/*  "/C" option - Do the command and EXIT the command processor */
+	_tcscpy(pDefaultCMD, _T("cmd.exe /C "));
+	_tcscat(pDefaultCMD, Args);
+
+	if(!CreateProcess(NULL,(LPTSTR)pDefaultCMD, NULL,NULL,FALSE,FALSE,NULL,NULL,&StartupInfo,&ProcessInfo))
+	{
+		processHandle = ProcessInfo.hProcess;
+		processThread = ProcessInfo.hThread; 
+		printf("CreateProcess function failed\n");
+		return NULL;
+	}
+
+	WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
+	if(!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
+		rc = 0;
+
+	CloseHandle(ProcessInfo.hThread);
+	CloseHandle(ProcessInfo.hProcess);
+	if(strlen(strstrParams) > 1){
+		if((fp = fopen(TEMP_FILE_PATH, "r+")) == NULL){
+			printf("fopen failed\n");
+			return NULL;
+		}
+	}
+	return fp;
+}
+
+void Cleanup_File(FILE* fp)
+{
+	fclose(fp);
+	if (!DeleteFile(TEMP_FILE_PATH)) {
+		printf("DeleteFile Failed with error:%d\n",GetLastError());
+	}
+}
+
+void p_error(char *errorString)
+{
+	printf("%s %d",errorString, GetLastError());
+}
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_sock.c b/src/tools/Wifi_ASD_test/lib/wfa_sock.c
new file mode 100644
index 0000000..d60566d
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_sock.c
@@ -0,0 +1,594 @@
+
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN
+ *.AN
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+
+/*
+ *    File: wfa_sock.c
+ *    library functions for TCP and UDP socket creations and handling
+ *    They are common library and shared by DUT, TC and CA.
+ *
+ *    Revision History:
+ *       2006/03/10  -- initially created by qhu
+ *       2006/06/01  -- BETA release by qhu
+ *       2006/06/13  -- 00.02 release by qhu
+ *       2006/06/30  -- 00.10 Release by qhu
+ *       2006/07/10 -- 01.00 Release by qhu
+ *       2006/09/01 -- 01.05 Release by qhu
+ *       2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi
+ *       2007/03/30 -- 01.40 WPA2 and Official WMM Beta Release by qhu
+ *       2007/04/20 -- 02.00 WPA2 and Official WMM Release by qhu
+ *       2007/08/15 --  02.10 WMM-Power Save release by qhu
+ *       2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *       2007/11/07 --  02.30 Voice HSO -- qhu
+ *          -- add a compilation flags to wmmfds and wmmps to setFileDesc()
+ *             that match the defintions in wfa_dut.c reported by rmaeder.
+ *
+ */
+#ifndef WIN32
+#include <pthread.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <bcmendian.h>
+#ifdef TARGETENV_android
+#include <asm/mman.h>
+#else
+#include <sys/mman.h>
+#endif
+#endif
+
+
+#include "wfa_debug.h"
+#include "wfa_types.h"
+#include "wfa_main.h"
+#include "wfa_sock.h"
+#include "wfa_miscs.h"
+
+int wfaGetifAddr(char *ifname, struct sockaddr_in *sa);
+
+extern unsigned short wfa_defined_debug;
+
+extern BOOL gtgTransac;
+extern char gnetIf[];
+
+#ifndef MAXPENDING
+#define MAXPENDING 2    /* Maximum outstanding connection requests */
+#endif
+#ifdef TARGETENV_android
+/* These functions are defined inside sys/mman.h for linux
+ * For android we are defining here as dummy
+ */
+int mlockall(int flags)
+{
+	return 0;
+}
+int munlockall(void)
+{
+	return 0;
+}
+#endif
+
+/*
+ * wfaCreateTCPServSock(): initially create a TCP socket
+ * intput:   port -- TCP socket port to listen
+ * return:   socket id;
+ */
+int wfaCreateTCPServSock(unsigned short port)
+{
+    int sock;                        /* socket to create */
+    struct sockaddr_in servAddr; /* Local address */
+    const int on = 1;
+
+    /* Create socket for incoming connections */
+    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+    {
+        DPRINT_ERR(WFA_ERR, "createTCPServSock socket() failed");
+        return FALSE;
+    }
+
+    /* Construct local address structure */
+    memset(&servAddr, 0, sizeof(servAddr));
+    servAddr.sin_family = AF_INET;        /* Internet address family */
+    servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
+    servAddr.sin_port = htons(port);              /* Local port */
+
+    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
+    /* Bind to the local address */
+    if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
+    {
+        DPRINT_ERR(WFA_ERR, "bind() failed");
+        return FALSE;
+    }
+
+    /* Mark the socket so it will listen for incoming connections */
+    if (listen(sock, MAXPENDING) < 0)
+    {
+        DPRINT_ERR(WFA_ERR, "listen() failed");
+        return FALSE;
+    }
+
+    return sock;
+}
+
+/*
+ * wfaCreateUDPSock(): create a UDP socket
+ * input:
+       ipaddr -- local ip address for test traffic
+       port -- UDP port to receive and send
+ * return:    socket id
+ */
+int wfaCreateUDPSock(char *ipaddr, unsigned short port)
+{
+    int udpsock;                        /* socket to create */
+    struct sockaddr_in servAddr; /* Local address */
+#ifdef WIN32
+    if((udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+#else
+    if((udpsock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+#endif
+    {
+        DPRINT_ERR(WFA_ERR, "createUDPSock socket() failed");
+        return FALSE;
+    }
+
+	memset(&servAddr, 0, sizeof(servAddr));
+    servAddr.sin_family      = AF_INET;
+    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    DPRINT_INFO(WFA_OUT, "UDP port %i\n", port);
+    servAddr.sin_port        = htons(port);
+
+   bind(udpsock, (struct sockaddr *) &servAddr, sizeof(servAddr));
+
+    return udpsock;
+}
+
+int wfaSetSockMcastSendOpt(int sockfd)
+{
+#ifdef WIN32
+     int ttlval = 64;
+	 DPRINT_INFO(WFA_OUT, "MCAST: McastSendOpt: sockfd = %d\r\n",sockfd);
+	return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttlval, sizeof(int));
+
+#else
+	unsigned char ttlval = 1;
+	return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttlval, sizeof(ttlval));
+
+#endif
+
+}
+
+int wfaSetSockMcastRecvOpt(int sockfd, char *mcastgroup)
+{
+    struct ip_mreq mcreq;
+    int so;
+
+    mcreq.imr_multiaddr.s_addr = inet_addr(mcastgroup);
+#ifdef WIN32
+    mcreq.imr_interface.s_addr = INADDR_ANY;
+#else
+    mcreq.imr_interface.s_addr = htonl(INADDR_ANY);
+#endif
+#ifdef DEBUG
+    DPRINT_INFO(WFA_OUT, "MCAST: McastRecvOpt: mcastgroup = %s\r\n",mcastgroup);
+#endif
+      so = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+                  (void *)&mcreq, sizeof(mcreq));
+    return so;
+}
+
+int wfaConnectUDPPeer(int mysock, char *daddr, unsigned short dport)
+{
+    struct sockaddr_in peerAddr;
+
+    memset(&peerAddr, 0, sizeof(peerAddr));
+    peerAddr.sin_family = AF_INET;
+#ifndef WIN32
+	inet_aton(daddr, &peerAddr.sin_addr);
+#else
+	peerAddr.sin_addr.s_addr  =   inet_addr(daddr);
+#endif
+
+    peerAddr.sin_port   = htons(dport);
+
+    connect(mysock, (struct sockaddr *)&peerAddr, sizeof(peerAddr));
+    return mysock;
+}
+
+int wfaConnectTCPPeer(unsigned short sport, char *daddr, unsigned short dport)
+{
+    int tcpsock;                        /* socket to create */
+    struct sockaddr_in servAddr; /* Local address */
+    struct sockaddr_in peerAddr; /* peer address */
+#ifdef WIN32
+    if((tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+#else
+    if((tcpsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+#endif
+    {
+        DPRINT_ERR(WFA_ERR, "wfaConnectTCPPeer socket() failed");
+        return FALSE;
+    }
+
+    memset(&servAddr, 0, sizeof(servAddr));
+    servAddr.sin_family = AF_INET;
+    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    servAddr.sin_port = htons(sport);
+
+    if(bind(tcpsock, (struct sockaddr *) &servAddr, sizeof(servAddr)) == -1)
+    {
+        DPRINT_ERR(WFA_ERR, "createTCPPeer bind() failed");
+        return FALSE;
+    }
+
+
+    memset(&peerAddr, 0, sizeof(peerAddr));
+    peerAddr.sin_family = AF_INET;
+     
+#ifndef WIN32
+    inet_aton(daddr, &peerAddr.sin_addr);
+#else
+    peerAddr.sin_addr.s_addr = inet_addr(daddr);
+#endif
+    peerAddr.sin_port = htons(dport);
+
+    if(connect(tcpsock, (struct sockaddr *)&peerAddr, sizeof(peerAddr)) == -1)
+    {
+        DPRINT_ERR(WFA_ERR, "wfaConnectTCPPeer connect() failed");
+        return FALSE;
+    }
+    return tcpsock;
+}
+
+/*
+ * acceptTCPConn(): handle and accept any incoming socket connection request.
+ * input:        serSock -- the socket id to listen
+ * return:       the connected socket id.
+ */
+int wfaAcceptTCPConn(int servSock)
+{
+    int clntSock;                /* Socket descriptor for client */
+    struct sockaddr_in clntAddr; /* Client address */
+    unsigned int clntLen;        /* Length of client address data structure */
+
+    /* Set the size of the in-out parameter */
+    clntLen = sizeof(clntAddr);
+
+    /* Wait for a client to connect */
+    if ((clntSock = accept(servSock, (struct sockaddr *) &clntAddr,
+           &clntLen)) < 0)
+    {
+        DPRINT_ERR(WFA_ERR, "accept() failed");
+        exit(1);
+    }
+
+    /* clntSock is connected to a client! */
+    return clntSock;
+}
+
+struct timeval *wfaSetTimer(int secs, int usecs, struct timeval *tv)
+{
+   struct timeval *mytv;
+
+   if(gtgTransac != 0)
+   {
+      tv->tv_sec = secs ;             /* timeout (secs.) */
+      tv->tv_usec = usecs;            /* 0 microseconds */
+   }
+   else
+   {
+      tv->tv_sec =  0;
+      tv->tv_usec = 0;                /* 0 microseconds */
+   }
+
+   if(tv->tv_sec == 0 && tv->tv_usec == 0)
+      mytv = NULL;
+   else
+      mytv = tv;
+
+   return mytv;
+}
+
+/* this only set four file descriptors, the main agent fd, control agent
+ * port fd and traffic generation fd, traffic generator fd.
+ */
+void wfaSetSockFiDesc(fd_set *fdset, int *maxfdn1, struct sockfds *fds)
+{
+
+    int i;
+
+
+    FD_ZERO(fdset);
+    if(fdset != NULL)
+       FD_SET(*fds->agtfd, fdset);
+
+    /* if the traffic generator socket port valid */
+    if(*fds->tgfd > 0)
+    {
+         FD_SET(*fds->tgfd, fdset);
+         *maxfdn1 = max(*maxfdn1-1, (int)*fds->tgfd) + 1;
+    }
+
+	/* if the traffic generator socket Recv port valid */
+    if(*fds->tgRevfd > 0)
+    {
+		FD_SET(*fds->tgRevfd, fdset);
+         *maxfdn1 = max(*maxfdn1-1, (int)*fds->tgRevfd) + 1;
+    }
+
+
+    /* if the control agent socket fd valid */
+    if(*fds->cafd >0)
+    {
+        FD_SET(*fds->cafd, fdset);
+         *maxfdn1 = max(*maxfdn1-1, (int)*fds->cafd) + 1;
+    }
+
+    /* if any of wmm traffic stream socket fd valid */
+    for(i = 0; i < WFA_MAX_TRAFFIC_STREAMS; i++)
+    {
+        if(fds->wmmfds[i] > 0)
+        {
+            if(fds->wmmfds[i] > FD_SETSIZE)
+            {
+           //    DPRINT_INFO(WFA_OUT, "Size greater than FD_SETSIZE\r\n");
+            }
+            FD_SET(fds->wmmfds[i], fdset);
+            *maxfdn1 = max(*maxfdn1-1, (int)fds->wmmfds[i]) +1;
+        }
+    }
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+    /* if the power save socket port valid */
+    if(*fds->psfd > 0)
+    {
+         FD_SET(*fds->psfd, fdset);
+         *maxfdn1 = max(*maxfdn1-1, (int)*fds->psfd) + 1;
+    }
+#endif
+
+#endif
+    return;
+}
+
+/*
+ * wfaCtrlSend(): Send control message/response through
+ *                control link.
+ *  Note: the function used to wfaTcpSend().
+ */
+int wfaCtrlSend(int sock, unsigned char *buf, int bufLen)
+{
+    int bytesSent = 0;
+
+    if(bufLen == 0)
+        return FALSE;
+    if(buf == NULL)
+	DPRINT_INFO(WFA_OUT, "wfaCtrlSend: Buffer null\r\n");
+	
+    bytesSent = send(sock, buf, bufLen, 0);
+
+    if(bytesSent == -1)
+    {
+       DPRINT_WARNING(WFA_WNG, "Error sending tcp packet\n");
+    }
+
+    return bytesSent;
+}
+
+/*
+ * wfaCtrlRecv(): Receive control message/response through
+ *                control link.
+ *  Note: the function used to wfaTcpRecv().
+ */
+int wfaCtrlRecv(int sock, unsigned char *buf)
+{
+   int bytesRecvd = 0;
+
+   bytesRecvd = recv(sock, buf, WFA_BUFF_1K-1, 0);
+
+   return bytesRecvd;
+}
+
+/*
+ * wfaTrafficSendTo(): Send Traffic through through traffic interface.
+ *  Note: the function used to wfaUdpSendTo().
+ */
+int wfaTrafficSendTo(int sock, char *buf, int bufLen, struct sockaddr *to)
+{
+   int bytesSent;
+
+   bytesSent = sendto(sock, buf, bufLen, MSG_DONTWAIT, to, sizeof(struct sockaddr));
+
+   return bytesSent;
+}
+
+/*
+ * wfaTrafficRecv(): Receive Traffic through through traffic interface.
+ *  Note: the function used to wfaRecvSendTo().
+ */
+int wfaTrafficRecv(int sock, char *buf, struct sockaddr *from)
+{
+   int bytesRecvd =0;
+   socklen_t  addrLen;
+
+#ifdef WIN32
+   struct sockaddr_in recFrom;
+#endif
+
+   /* get current flags setting */
+#ifndef WIN32
+   int ioflags = fcntl(sock, F_GETFL, 0);
+
+#ifdef TARGETENV_android
+if (gtgTransac)
+usleep(50);
+#endif
+
+   /* set only BLOCKING flag to non-blocking */
+   fcntl(sock, F_SETFL, ioflags | O_NONBLOCK);
+
+   bytesRecvd = recvfrom(sock, buf, MAX_UDP_LEN, 0, from, &addrLen);
+#ifdef TARGETENV_android
+if (errno == EAGAIN && gtgTransac)
+usleep(50);
+#endif /* TARGETENV_android */
+
+#else
+
+	memset(&recFrom, 0, sizeof(recFrom));
+	addrLen = sizeof(recFrom);
+	bytesRecvd = recvfrom(sock, buf, MAX_UDP_LEN, 0, (struct sockaddr *)&recFrom, &addrLen);
+#endif
+
+   return bytesRecvd;
+}
+
+int wfaGetifAddr(char *ifname, struct sockaddr_in *sa)
+{
+    struct ifreq ifr;
+    int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+
+    if(fd < 0)
+    {
+       DPRINT_ERR(WFA_ERR, "socket open error\n");
+       return FALSE;
+    }
+
+    strncpy(ifr.ifr_name, ifname, strlen(ifname));
+#ifndef WIN32
+    ifr.ifr_addr.sa_family = AF_INET;
+    if(ioctl(fd, SIOCGIFADDR, &ifr) == 0)
+    {
+         memcpy(sa, (struct sockaddr_in *)&ifr.ifr_addr, sizeof(struct sockaddr_in));
+    }
+    else
+    {
+         return FALSE;
+    }
+
+#else
+	ifr.ifr_addr.sin_family = AF_INET;
+	memcpy(sa, (struct sockaddr_in *)&ifr.ifr_addr, sizeof(struct sockaddr_in));
+#endif
+
+    asd_closeSocket(fd);
+    return FALSE;
+}
+
+/*
+ * wfaSetProcPriority():
+ * With the linux 2.6 kernel, it allows an application process dynamically
+ * adjust its running priority level. In order to achieve higher control of
+ * packet sending/receiving and timer response, it is helpful to raise the
+ * process priority level over others and lower it back once it finishes.
+ *
+ * This is purely used for performance tuning purpose and not required to
+ * port if it is not needed.
+ */
+int wfaSetProcPriority(int set)
+{
+#ifndef WIN32
+    int maxprio, currprio;
+    struct sched_param schp;
+
+    memset(&schp, 0, sizeof(schp));
+    sched_getparam(0, &schp);
+
+    currprio = schp.sched_priority;
+
+    if(set != 0)
+    {
+        if(geteuid() == 0)
+        {
+           maxprio = sched_get_priority_max(SCHED_FIFO);
+           if(maxprio == -1)
+           {
+              return FALSE;
+           }
+
+           schp.sched_priority = maxprio;
+           if(sched_setscheduler(0, SCHED_FIFO, &schp) != 0)
+           {
+           }
+        }
+
+        if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
+        {
+
+        }
+    }
+    else
+    {
+        if(geteuid() == 0)
+        {
+           schp.sched_priority = 0;
+           if(sched_setscheduler(0, SCHED_OTHER, &schp) != 0)
+           {
+           }
+        }
+
+        munlockall();
+    }
+    return currprio;
+#else
+	return 0;
+#endif
+
+}
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_tg.c b/src/tools/Wifi_ASD_test/lib/wfa_tg.c
new file mode 100644
index 0000000..850444e
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_tg.c
@@ -0,0 +1,2474 @@
+
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN
+ *.AN
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+/*
+ *    File: wfa_tg.c
+ *    Library functions for traffic generator.
+ *    They are shared with both TC and DUT agent.
+ *
+ *    Revision History:
+ *       2006/03/10 -- initially created by qhu
+ *       2006/06/01 -- BETA release by qhu
+ *       2006/06/13 -- 00.02 release by qhu
+ *       2006/06/30 -- 00.10 Release by qhu
+ *       2006/07/10 -- 01.00 Release by qhu
+ *       2006/08/01 -- 01.03 fix ping result unreachable caused by random output
+ *                           timing. Add 2 seconds wait-time.
+ *                           change priority level to 40 max while traffic
+ *                           sending/receiving and 60 min for normal state.
+ *       2006/09/01 -- 01.05 Release by qhu
+ *       2006/10/26 -- 01.06 released by qhu
+ *       2006/10.20 -- bug fixes report by n. ojannen
+ *       2006/12/30 -- bug fix. a potential race condition for transaction test, *                     reported by c.benson.
+ *       2006/01/11 -- 01.10 released by qhu
+ *       2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi
+ *       2007/03/15  -- develop a better rate control method for sendLong
+ *                      a major bug fix for File receive that opens socket with
+ *                      source port. It should be destination port. This was
+ *                      an early mistake because of interpretation.
+ *       2007/03/30 -- 01.40 WPA2 and Official WMM Beta Release by qhu
+ *       2007/04/20 -- 02.00 WPA2 and Official WMM Release by qhu
+ *       2007/08/15 --  02.10 WMM-Power Save release by qhu
+ *       2007/10/10 -- 02.20 Voice SOHO beta -- qhu
+ *       2007/11/07 -- 02.30 Voice HSO -- qhu
+ *           -- revise the code for traffic throttled control
+ *           -- take care of EAGAIN error return by socket sendto() -- suggested
+ *              by tterhaar
+ */
+#ifndef WIN32
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <semaphore.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#endif /* !WIN32 */
+#include "wfa_debug.h"
+#include "wfa_ver.h"
+#include "wfa_main.h"
+#include "wfa_tlv.h"
+#include "wfa_tg.h"
+#include "wfa_cmds.h"
+#include "wfa_sock.h"
+#include "wfa_rsp.h"
+#include "wfa_wmmps.h"
+#include "wfa_types.h"
+#include "wfa_miscs.h"
+
+
+int usedThread = 0;
+BYTE Send_dutResp[WFA_BUFF_512];
+extern void wfaSentStatsResp(BYTE*);
+#ifndef WIN32
+tgWMM_t wmm_thr[WFA_THREADS_NUM];
+extern sem_t sem_wmm;
+extern sem_t sem_wmm_resp;
+extern sem_t sem_gtgrecv;
+extern sem_t sem_iptv_gtgrecv[WFA_MAX_TRAFFIC_STREAMS];
+int gnumStreams;
+pthread_t thrid[WFA_MAX_TRAFFIC_STREAMS];
+#else
+extern HANDLE thr_flag_cond;
+DWORD   dwpingThread;
+DWORD dwGenericThread;
+HANDLE	pinghThread = NULL;
+HANDLE hTimerThread = NULL;
+HANDLE hThread1 = NULL;
+HANDLE hThread2 = NULL;
+HANDLE g_hRecvEvent = NULL;
+HANDLE send_event = NULL;
+extern HANDLE g_RecvhThread;
+extern HANDLE g_IPTVRecvhThread[WFA_MAX_TRAFFIC_STREAMS];
+HANDLE g_recvEvent[WFA_MAX_TRAFFIC_STREAMS];
+DWORD dwGenericThread2;
+DWORD dwGenericThread1;
+DWORD dwIPTVThread;
+HANDLE g_TGSndThr[WFA_MAX_TRAFFIC_STREAMS];
+extern ULONG exitcode;
+extern HANDLE processHandle;
+extern void SendIPTVFile(LPVOID);
+#endif /* !WIN32 */
+extern tgStream_t *gStreams;
+extern BOOL gtgRecv;
+extern BOOL gtgSend;
+extern BOOL gtgTransac;
+extern int btSockfd;
+extern int btRecvSockfd;
+extern int gTcpRecvSockfd;
+extern int gTCPsock;
+extern int gtimeOut;
+extern int gRegSec;
+extern int isExit;
+extern int adj_latency;
+
+extern tgStream_t *findStreamProfile(int);
+extern int wfaTrafficSendTo(int, char *, int, struct sockaddr *);
+extern int wfaTrafficRecv(int, char *, struct sockaddr *);
+extern unsigned short wfa_defined_debug;
+extern int tgSockfds[];
+
+extern int wfaTGSetPrio(int sockfd, int tgClass);
+extern double min_rttime;
+extern tgSyncTime_t gtgFinishSyncTime;
+extern BOOL gtgStartSync;
+extern BOOL gtgFinishSync;
+extern tgE2EStats_t *e2eStats;
+extern int e2eCnt;
+extern void wfaRecvThrCreate(void);
+extern void wfaIPTVRecvThrCreate(int);
+extern void SendFile(void);
+extern int IPTVprof;
+
+
+extern tgSyncTime_t gtgStartSyncTime;
+#ifdef WFA_WMM_EXT
+extern tgWMM_t wmm_thr[];
+
+#ifdef WFA_WMM_PS_EXT
+extern int gtgWmmPS;
+extern wfaWmmPS_t wmmps_info;
+extern int psSockfd;
+extern unsigned long psTxMsg[];
+extern unsigned long psRxMsg[];
+extern int gtgPsPktRecvd;
+
+dutCmdResponse_t gGenericResp;
+
+extern void wfaSetDUTPwrMgmt(int mode);
+void wmmps_wait_state_proc();
+
+#endif /* WFA_WMM_PS_EXT */
+
+#endif /* WFA_WMM_EXT */
+
+static int runLoop = 0;
+extern volatile int gTransactrunLoop;
+static int streamId = 0;
+static int totalTranPkts = 0, sentTranPkts = 0;
+static int slotCnt = 0;
+
+int clock_drift_ps = 0;  // drift(usec) per second
+char e2eResults[32];
+
+extern dutCmdResponse_t gGenericResp;
+
+#ifdef WIN32
+unsigned int  Timerid;
+extern DWORD Win32_tmout_stop_send(LPVOID num ) ;
+extern DWORD PingStart();
+char PingStr[WFA_BUFF_512];
+
+#ifndef MAX_UDP_LEN
+#define MAX_UDP_LEN	2048
+#endif	/*MAX_UDP_LEN*/
+
+#define HIGH_FRAME_RATE_VAL 500
+#define SLEEP_DENOMINATOR 5
+#endif	/*WIN32*/
+
+/* Some devices may only support UDP ECHO and do not have ICMP level ping */
+// #define WFA_PING_UDP_ECHO_ONLY     1
+
+/*
+ * Each packet will have the header in the data field
+ */
+
+void wfa_syncd_time(tgSyncTime_t *startTime, tgSyncTime_t *finishTime)
+{
+#ifdef WFA_WMM_EXT
+#ifndef WIN32
+	DPRINT_INFO(WFA_OUT, "finish tm time %f start tm time %f\n", finishTime->tm_time, startTime->tm_time);
+	DPRINT_INFO(WFA_OUT, "finish dut time %f  startTime dut time %f \n", finishTime->dut_time, startTime->dut_time);
+
+	if(startTime->dtime > finishTime->dtime)
+		startTime->dtime = finishTime->dtime;
+
+	DPRINT_INFO(WFA_OUT, "roundtrip delay time (usec): %i\n", (int) (1000000 * startTime->dtime));
+
+	clock_drift_ps = 1000000*( (finishTime->tm_time - startTime->tm_time)-(finishTime->dut_time - startTime->dut_time) ) /
+		(finishTime->dut_time - startTime->dut_time);
+
+	DPRINT_INFO(WFA_OUT, "drift per second %i\n", clock_drift_ps);
+#endif /* !WIN32 */
+#endif /* !WFA_WMM_EXT */
+}
+
+#ifndef WIN32
+/* this is to stop sending packets by timer       */
+void tmout_stop_send(int num)
+{
+#ifdef WFA_WMM_EXT
+	int i;
+#endif /* WFA_WMM_EXT */
+	DPRINT_INFO(WFA_OUT, "timer fired, stop sending traffic\n");
+
+	/*
+	*  After runLoop reset, all sendLong will stop
+	*/
+	runLoop = 0;
+	gTransactrunLoop = 0;
+
+#ifdef WFA_WMM_EXT
+	/*
+	* once usedThread is reset, WMM tests using multithread is ended
+	* the threads will be reused for the next test.
+	*/
+	usedThread--;
+	//if(usedThread == 0)
+		sem_post(&sem_wmm_resp);
+#endif /* WFA_WMM_EXT */
+
+	/*
+	* once the stream table slot count is reset, it implies that the test
+	* is done. When the next set profile command comes in, it will reset/clean
+	* the stream table.
+	*/
+	slotCnt = 0;
+
+	/*
+	* The test is for DT3 transaction test.
+	* Timeout to stop it.
+	*/
+	if(gtgTransac != 0)
+	{
+		gtgSend = 0;
+		gtgRecv = 0;
+		gtgTransac = 0;
+		asd_closeSocket(btSockfd);
+		btSockfd = -1;
+#ifdef WFA_WMM_EXT
+		/* Voice End 2 End Sync */
+		min_rttime = 0xFFFFFFFF;
+		if(gtgStartSync != 0)
+		{
+			gtgStartSync = 0;
+			DPRINT_INFO(WFA_OUT, "stopping StartSync\n");
+		}
+
+		if(gtgFinishSync != 0)
+		{
+			/* derive the clock drift */
+			wfa_syncd_time(&gtgStartSyncTime, &gtgFinishSyncTime);
+
+			gtgFinishSync = 0;
+			DPRINT_INFO(WFA_OUT, "stoping Finish Sync\n");
+		}
+#endif /* WFA_WMM_EXT */
+	}
+
+#ifdef WFA_WMM_EXT
+	/*
+	* all WMM streams also stop
+	*/
+	for(i=0; i<WFA_TRAFFIC_CLASS_NUM; i++)
+	{
+		wmm_thr[i].thr_flag = 0;
+	}
+#endif /* WFA_WMM_EXT */
+	/* all alarms need to reset */
+
+	alarm(0);
+}
+#endif /* !WIN32 */
+/*
+ * findStreamProfile(): search existing stream profile by stream id
+ * input: id - stream id;
+ * return: matched stream profile
+ */
+tgStream_t *findStreamProfile(int id)
+{
+	int i;
+	tgStream_t *myStream = gStreams;
+
+	for(i = 0; i< WFA_MAX_TRAFFIC_STREAMS; i++)
+	{
+		if(myStream->id == id)
+			return myStream;
+
+		myStream++;
+	}
+
+	return NULL;
+}
+
+/*
+ * wfaTGSendPing(): Instruct Traffic Generator to send ping packets
+ *
+ */
+int wfaTGSendPing(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	int totalpkts;
+
+	char cmdStr[WFA_BUFF_128];
+
+	int streamid = ++streamId;
+	float interval;      /* it could be subseconds/100s minisecond */
+	tgPingStart_t *staPing = (tgPingStart_t *)caCmdBuf;
+	dutCmdResponse_t *spresp = &gGenericResp;
+
+#ifdef WFA_PING_UDP_ECHO_ONLY
+	tgStream_t *myStream = NULL;
+#endif
+	DPRINT_INFO(WFA_OUT, "Entering wfaTSendPing ...\n");
+	if(staPing->frameSize == 0)
+		staPing->frameSize = 100;
+
+	if(staPing->frameRate == 0)
+		staPing->frameRate = 1;
+
+	interval = (float)1/staPing->frameRate;
+
+	if(staPing->duration == 0)
+		staPing->duration = 30;
+
+	switch(staPing->type)
+	{
+	case WFA_PING_ICMP_ECHO:
+#ifndef WFA_PING_UDP_ECHO_ONLY
+		totalpkts = staPing->duration * staPing->frameRate;
+
+#ifndef WIN32
+		sprintf(cmdStr, "echo streamid=%i > %s; %s -c %i -s %i -q  %s >> %s 2>/dev/null&",
+			streamid, SPOUT_FILE_PATH, PING_PATH,  totalpkts, staPing->frameSize, staPing->dipaddr, SPOUT_FILE_PATH);
+		system(cmdStr);
+
+#endif
+
+		spresp->status = STATUS_COMPLETE;
+		spresp->streamId = streamid;
+#else
+		DPRINT_INFO(WFA_OUT, "Only support UDP ECHO\n");
+#endif
+		break;
+
+	case WFA_PING_UDP_ECHO:
+		{
+#ifdef WFA_PING_UDP_ECHO_ONLY
+			/*
+			* Make this like a transaction testing
+			* Then make it a profile and run it
+			*/
+			myStream = &gStreams[slotCnt++];
+			memset(myStream, 0, sizeof(tgStream_t));
+			memcpy(&myStream->profile, caCmdBuf, len);
+			myStream->id = streamid; /* the id start from 1 */
+			myStream->tblidx = slotCnt-1;
+
+			btSockfd = wfaCreateUDPSock("127.0.0.1", WFA_UDP_ECHO_PORT);
+			if((btSockfd = wfaConnectUDPPeer(btSockfd, staPing->dipaddr, WFA_UDP_ECHO_PORT)) > 0)
+			{
+				gtgTransac = streamid;
+				gtgSend = streamid;
+				totalTranPkts = 512;
+				sentTranPkts = 0;
+
+				/*
+				* the framerate here is used to derive the timeout
+				* value for waiting transaction echo responses.
+				*/
+				gtimeOut = MINISECONDS/staPing->frameRate;  /* in msec */
+				gRegSec = 0;
+
+				/* set to longest time */
+				if(staPing->duration == 0)
+					staPing->duration = 3600;
+			}
+#else
+			DPRINT_INFO(WFA_OUT, "Doesn't support UDP Echo\n");
+#endif
+			break;
+		}
+	default:
+		{
+			spresp->status = STATUS_INVALID;
+			spresp->streamId = streamid;
+		}
+	}
+
+
+	wfaEncodeTLV(WFA_TRAFFIC_SEND_PING_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)spresp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+	return TRUE;
+}
+
+/*
+ * tgStopPing(): Instruct Traffic Generator to stop ping packets
+ *
+ */
+int wfaTGStopPing(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	int streamid = (int )(caCmdBuf+4);
+	dutCmdResponse_t *stpResp = &gGenericResp;
+	FILE *tmpfile = NULL;
+	tgStream_t *myStream;
+#ifndef WIN32
+	char strout[WFA_BUFF_256];
+#else
+	FILE *stptmpFile = NULL;
+	unsigned int  position =0, recbfping =0, sentbfping =0, received =0, sent =0;
+#endif
+	stpResp->status = STATUS_COMPLETE;
+
+	DPRINT_INFO(WFA_OUT, "Entering wfaTStopPing ...\n");
+	if(( gtgTransac == streamid) && (gtgSend == streamid))
+	{
+		gtgTransac =0;
+		gtgSend = 0;
+		gtimeOut = 0;
+		gtgRecv = 0;
+#ifndef WIN32
+		alarm(0);
+#endif
+		gRegSec = 1;
+		myStream = findStreamProfile(streamid);
+		if(myStream == NULL)
+		{
+			stpResp->status = STATUS_INVALID;
+		}
+
+		stpResp->cmdru.pingStp.sendCnt = myStream->stats.txFrames;
+		stpResp->cmdru.pingStp.repliedCnt = myStream->stats.rxFrames;
+	}
+	else
+	{
+#ifndef WIN32
+		/* Ping will be stopped after the specified duration which will
+		* be specified by the user at the time send ping. For some reason popen with grep 
+		* does not work well in Intel PXA with Linux
+		* Use system() call for such things and avoid using popen
+		*/
+
+		sprintf(strout, "cat %s |grep transmitted | awk '{print $1,$4}' >%s 2>&1",
+		SPOUT_FILE_PATH, TMP_FILE_PATH);
+
+		system(strout);
+
+		tmpfile = fopen(TMP_FILE_PATH, "rb");
+
+		if (tmpfile == NULL) {
+			DPRINT_ERR(WFA_ERR, "\nShell Cmd:File open error\n");
+			stpResp->status = STATUS_COMPLETE;
+
+			wfaEncodeTLV(WFA_TRAFFIC_STOP_PING_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)stpResp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+			return TRUE;
+		}
+		DPRINT_INFO(WFA_OUT,"\nCmdStr is:%s\n", strout);      
+		fgets(strout, sizeof(strout), tmpfile);
+		stpResp->cmdru.pingStp.sendCnt = atoi(strout);
+		fgets(strout, sizeof(strout), tmpfile);
+		stpResp->cmdru.pingStp.repliedCnt = atoi(strout); 
+		fclose(tmpfile);
+
+		remove(TMP_FILE_PATH);
+#else
+		if(exitcode ){
+			TerminateProcess(processHandle, exitcode);
+		}
+
+		tmpfile = fopen("temp\\RWL\\pingstats.txt", "r+");
+		if(tmpfile == NULL)
+		{
+			stpResp->status = STATUS_COMPLETE;
+
+			wfaEncodeTLV(WFA_TRAFFIC_STOP_PING_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)stpResp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+			return FALSE;
+		}
+
+		GetStats(tmpfile, L"Sent =", &position, " ");
+		stpResp->cmdru.pingStp.sendCnt = position;
+		GetStats(tmpfile, L"Received =", &position, " ");
+		stpResp->cmdru.pingStp.repliedCnt = position;
+		fclose(tmpfile);
+#endif
+	}
+	wfaEncodeTLV(WFA_TRAFFIC_STOP_PING_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)stpResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+	return TRUE;
+}
+
+/*
+ * wfaTGConfig: store the traffic profile setting that will be used to
+ *           instruct traffic generation.
+ * input: cmd -- not used
+ * response: send success back to controller
+ * return: success or fail
+ * Note: the profile storage is a global space.
+ */
+int wfaTGConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
+{
+	int ret = FALSE;
+	tgStream_t *myStream = NULL;
+	dutCmdResponse_t *confResp = &gGenericResp;
+
+	DPRINT_INFO(WFA_OUT, "slotCnt = %d\n", slotCnt);
+	/* if the stream table over maximum, reset it */
+	if(slotCnt == WFA_MAX_TRAFFIC_STREAMS)
+		slotCnt = 0;
+	if(slotCnt == 0)
+	{
+		memset(gStreams, 0, WFA_MAX_TRAFFIC_STREAMS*sizeof(tgStream_t));
+	}
+
+	DPRINT_INFO(WFA_OUT,  "entering tcConfig ...\n");
+	myStream = &gStreams[slotCnt++];
+	memset(myStream, 0, sizeof(tgStream_t));
+	memcpy(&myStream->profile, caCmdBuf, len);
+	myStream->id = ++streamId; /* the id start from 1 */
+	myStream->tblidx = slotCnt-1;
+
+	DPRINT_INFO(WFA_OUT, "profile %i direction %i dest ip %s dport %i source %s sport %i rate %i duration %i size %i class %i delay %i\n", myStream->profile.profile, myStream->profile.direction, myStream->profile.dipaddr, myStream->profile.dport, myStream->profile.sipaddr, myStream->profile.sport, myStream->profile.rate, myStream->profile.duration, myStream->profile.pksize, myStream->profile.trafficClass, myStream->profile.startdelay);
+
+	confResp->status = STATUS_COMPLETE;
+	confResp->streamId = myStream->id;
+	wfaEncodeTLV(WFA_TRAFFIC_AGENT_CONFIG_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)confResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
+
+
+	return ret;
+}
+
+/*
+ * wfaTGRecvStart: instruct traffic generator to start receiving
+ *                 based on a profile
+ * input:      cmd -- not used
+ * response:   inform controller for "running"
+ * return:     success or failed
+ *
+ * In this function we create the UDP sockets for receiving the traffic and then
+ * set the global flag gtgRecv to indicate the receive thread to receive the incoming traffic.
+ * In the case of IPTV profile we multiple Create Events for multiple streams 
+ */
+
+int wfaTGRecvStart(int len, BYTE *parms, int *respLen, BYTE *respBuf)
+{
+	int status = STATUS_COMPLETE, i;
+	int numStreams = len/4;
+	int streamid, so;
+	tgProfile_t *theProfile;
+	tgStream_t *myStream;
+
+	DPRINT_INFO(WFA_OUT, "entering tgRecvStart %i\n", numStreams);
+
+	/*
+	* The function wfaSetProcPriority called here is to enhance the real-time
+	* performance for packet receiving. It is only for tuning and optional
+	* to implement
+	*/
+	//wfaSetProcPriority(60);
+	for(i=0; i<numStreams; i++) {
+		memcpy(&streamid, parms+(4*i), 4); /* changed from 2 to 4, bug reported by n.ojanen */
+
+		myStream = findStreamProfile(streamid);
+		if(myStream == NULL)
+		{
+			status = STATUS_INVALID;
+			return status;
+		}
+
+		theProfile = &myStream->profile;
+		if(theProfile == NULL)
+		{
+			status = STATUS_INVALID;
+			return status;
+		}
+
+		/* calculate the frame interval which is used to derive its jitter */
+		if(theProfile->rate != 0 && theProfile->rate < 5000)
+			myStream->fmInterval = 1000000/theProfile->rate; /* in ms */
+		else
+			myStream->fmInterval = 0;
+
+		if(theProfile->direction != DIRECT_RECV)
+		{
+			status = STATUS_INVALID;
+			return status;
+		}
+
+		memset(&myStream->stats, 0, sizeof(tgStats_t));
+		switch(theProfile->profile)
+		{
+		case PROF_FILE_TX:
+			status = STATUS_COMPLETE;
+			btRecvSockfd = wfaCreateUDPSock(theProfile->dipaddr, theProfile->dport);
+			if(btRecvSockfd > 0) {
+				gtgRecv = streamid;
+#ifdef WIN32
+				/*Create receive event which is initially non-signalled and 
+				* later  reset the state of the signal when we call the command 
+				* WfaRecvStop() */
+				if((g_hRecvEvent = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0) {
+					DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+
+				}
+#endif
+				/*Creating a thread for receiving traffic in case of File_Transfer, Transac,Multicast */
+				wfaRecvThrCreate();				
+			}
+			else
+			{
+				status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4, (BYTE *)&status, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+
+				return TRUE;
+			}
+
+			break;
+		case PROF_FILE_TX_TCP:
+			gTCPsock = 1;
+			status = STATUS_COMPLETE;
+			gTcpRecvSockfd = wfaCreateTCPServSock(theProfile->dport);
+			if(gTcpRecvSockfd > 0) {
+				gtgRecv = streamid;
+#ifdef WIN32
+				/*Create receive event which is initially non-signalled and
+				 * later  reset the state of the signal when we call the command
+				 * WfaRecvStop() */
+				if((g_hRecvEvent = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0) {
+					DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+				}
+#endif
+				/*Creating a thread for receiving traffic in case of File_Transfer, Transac,Multicast */
+				wfaRecvThrCreate();
+			}
+			else
+			{
+				status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4, (BYTE *)&status, respBuf);
+				respLen = WFA_TLV_HDR_LEN + 4;
+				return TRUE;
+			}
+			break;
+
+		case PROF_MCAST:
+			status = STATUS_COMPLETE;
+			btRecvSockfd = wfaCreateUDPSock(theProfile->dipaddr, theProfile->dport);
+			DPRINT_INFO(WFA_OUT, "MCAST: RecvStart: btRecvSockfd = %d\r\n",btRecvSockfd);
+			if(btRecvSockfd > 0)
+			{
+#ifdef WIN32
+				/*Create receive event which is initially non-signalled and 
+				* later  automatically reset the state of the signal
+				* when the receive thread exits.  */
+				if((g_hRecvEvent = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0){
+					DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+				}
+#endif				
+				gtgRecv = streamid;
+				/*Creating a thread for receiving traffic in case of File_Transfer, Transac,Multicast */
+				wfaRecvThrCreate();
+
+			}
+			else
+			{
+				status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4, (BYTE *)&status, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+				return TRUE;
+			}
+			DPRINT_INFO(WFA_OUT, "MCAST: RecvStart:before McastRecvOpt: btRecvSockfd = %d\r\n",btRecvSockfd);
+			/* set multicast socket option for receiver */
+			DPRINT_INFO(WFA_OUT, "MCAST: RecvStart: McastRecvOpt: theProfile->dipaddr = %s\r\n",theProfile->dipaddr);
+			so = wfaSetSockMcastRecvOpt(btRecvSockfd, theProfile->dipaddr);
+			if(so < 0)
+			{
+				DPRINT_INFO(WFA_OUT, "MCAST: RecvStart: McastRecvOpt: so<0: btRecvSockfd = %d\r\n",btRecvSockfd);
+				asd_closeSocket(btRecvSockfd);
+				gtgRecv = 0;
+				btRecvSockfd = -1;
+				status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4, (BYTE *)&status, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+
+				return TRUE;
+			}
+
+			break;
+
+		case PROF_IPTV:
+			status = STATUS_COMPLETE;
+			/*Create multiple streams and get the socket values in the array*/
+			tgSockfds[myStream->tblidx] = wfaCreateUDPSock(theProfile->dipaddr, theProfile->dport);
+			DPRINT_INFO(WFA_OUT, "sock fd prof iptv = %d , streamid = %d\n", tgSockfds[myStream->tblidx], streamid);
+			if(tgSockfds[myStream->tblidx] > 0){
+#ifdef WIN32	
+				/* Create multiple event for different recv streams and get
+				* the values in the array of recv handles, Which will be later used in 
+				* WfaRecvStop() to signal the recv thread to stop the recv process. */		  
+				if((g_recvEvent[myStream->tblidx] = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0){
+					DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+
+				}
+
+				DPRINT_INFO(WFA_OUT, "recvstart g_recvEvent[myStream->tblidx] = %i\r\n", g_recvEvent[myStream->tblidx]);
+#endif
+				gtgRecv = streamid;
+				/*Create a thread to receive IPTV traffic.  */
+				wfaIPTVRecvThrCreate(myStream->tblidx);
+		 }
+			else
+			{
+				status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4, (BYTE *)&status, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+				return TRUE;
+			}
+			break;
+
+		case PROF_TRANSC:
+		case PROF_START_SYNC:
+		case PROF_CALI_RTD:  /* Calibrate roundtrip delay */
+			status = STATUS_COMPLETE;
+			btRecvSockfd = wfaCreateUDPSock(theProfile->sipaddr, theProfile->sport);
+			totalTranPkts = 0xFFFFFFF0;
+			sentTranPkts = 0;
+			if(btRecvSockfd > 0)
+			{
+				gtgTransac = streamid;
+				gtgRecv = streamid;
+#ifdef WIN32               
+				if((g_hRecvEvent = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0){
+					DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+
+				}
+#endif
+				/*Creating a thread for receiving traffic in case of File_Transfer, Transac,Multicast */
+				wfaRecvThrCreate();
+			}
+			else
+			{
+				status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4, (BYTE *)&status, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+				return TRUE;
+			}
+
+			break;
+
+		case PROF_TRANSC_TCP:
+			gTCPsock = 1;
+			status = STATUS_COMPLETE;
+			gTcpRecvSockfd = wfaCreateTCPServSock(theProfile->dport);
+			if(gTcpRecvSockfd > 0)
+			{
+				gtgTransac = streamid;
+				gtgRecv = streamid;
+#ifdef WIN32               
+				if((g_hRecvEvent = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0){
+					DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+				}
+#endif
+				/*Creating a thread for receiving traffic in case of File_Transfer, Transac,Multicast */
+				wfaRecvThrCreate();
+			}
+			else
+			{
+				status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4, (BYTE *)&status, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+				return TRUE;
+			}
+			break;
+
+		case PROF_UAPSD:
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+		     status = STATUS_COMPLETE;
+			 psSockfd = wfaCreateUDPSock(theProfile->dipaddr, WFA_WMMPS_UDP_PORT);
+
+			 wmmps_info.sta_state = 0;
+			 wmmps_info.wait_state = WFA_WAIT_STAUT_00;
+#ifdef WIN32              
+			 init_wmmps_thr(); 
+				if((g_hRecvEvent = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0){
+					DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+
+				}
+#endif
+			 memset(&wmmps_info.psToAddr, 0, sizeof(wmmps_info.psToAddr));
+			 wmmps_info.psToAddr.sin_family = AF_INET;
+			 wmmps_info.psToAddr.sin_addr.s_addr = inet_addr(theProfile->sipaddr);
+			 wmmps_info.psToAddr.sin_port = htons(theProfile->sport);
+			 wmmps_info.reset = 0;
+			
+			 wmm_thr[usedThread].thr_flag = streamid;
+			 wmmps_info.streamid = streamid;
+#ifndef WIN32
+			 pthread_mutex_lock(&wmm_thr[usedThread].thr_flag_mutex);
+			 pthread_cond_signal(&wmm_thr[usedThread].thr_flag_cond);
+			 gtgWmmPS = streamid;;
+			 pthread_mutex_unlock(&wmm_thr[usedThread].thr_flag_mutex);
+			 usedThread++;
+#else
+			 SetEvent(thr_flag_cond);
+			 gtgWmmPS = streamid;
+#endif /* WIN32 */
+			 gtimeOut = MINISECONDS/10;  /* in msec */
+			 gRegSec = 0;
+			 
+			 /* Create the receiver thread */
+		     wfaRecvThrCreate();
+#endif   /* WFA_WMM_PS_EXT */
+#endif   /* WFA_WMM_EXT */
+			break;
+		}
+	}
+
+	/* encode a TLV for response for "complete/error ..." */
+	wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, 4,
+		(BYTE *)&status, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/*
+ * tgRecvStop: instruct traffic generator to stop receiving based on a profile
+ * input:      cmd -- not used
+ * response:   inform controller for "complete"
+ * return:     success or failed
+ *
+ * In this function we will reset the gtgRecv flag, close the UDP sockets opened in the
+ * receive start to stop receiving the traffic from TG. We also kill the thread that was created
+ * in receive start*/
+int wfaTGRecvStop(int len, BYTE *parms, int *respLen, BYTE *respBuf)
+{
+	int status = STATUS_COMPLETE, i, j;
+	int numStreams = len/4;
+	int streamid;
+	tgProfile_t *theProfile;
+	tgStream_t *myStream=NULL;
+	dutCmdResponse_t statResp;
+	BYTE dutRspBuf[WFA_BUFF_1K];
+	int id_cnt = 0;
+	FILE *e2eoutp = NULL;
+#ifndef WIN32
+	struct timeval currtime;
+#else
+	SYSTEMTIME currtime;
+#endif
+
+	DPRINT_INFO(WFA_OUT, "entering tgRecvStop\n");
+
+	memset(dutRspBuf, 0, WFA_BUFF_1K);
+
+	for(i=0; i<numStreams; i++)
+	{
+		memcpy(&streamid, parms+(4*i), 4);
+		myStream = findStreamProfile(streamid);
+		if(myStream == NULL)
+		{
+			status = STATUS_INVALID;
+			wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, 4, (BYTE *)&status, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+			return TRUE;
+		}
+
+		theProfile = &myStream->profile;
+		if(theProfile == NULL)
+		{
+			status = STATUS_INVALID;
+			wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, 4, (BYTE *)&status, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+
+			return TRUE;
+		}
+
+		if(theProfile->direction != DIRECT_RECV)
+		{
+			status = STATUS_INVALID;
+			wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, 4, (BYTE *)&status, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+
+			return TRUE;
+		}
+		/* reset its flags , close sockets */
+		gtgRecv = 0;
+		switch(theProfile->profile)
+		{
+		case PROF_FILE_TX:
+		case PROF_FILE_TX_TCP:
+#ifdef WIN32
+			/*Set the recv event and signal the recv thread function to stop
+			* Receiving the File transfer Traffic, also close the handle of the event*/
+			if(SetEvent(g_hRecvEvent) == 0) {
+				DPRINT_INFO(WFA_OUT, "ResetEvent failure %d \n", GetLastError());
+			}
+			while ((WaitForSingleObject(g_RecvhThread, INFINITE) != WAIT_OBJECT_0));
+			if(g_hRecvEvent != NULL)
+				CloseHandle(g_hRecvEvent);
+
+#else
+			/* Waiting for signal from wfaRecvStart once the receive 
+			 * operation is complete in order to close the socket 
+			 */
+			sem_wait(&sem_gtgrecv);
+#endif
+			if(gTcpRecvSockfd != -1) {
+				gTCPsock = 0;
+				asd_closeSocket(gTcpRecvSockfd);
+				gTcpRecvSockfd = -1;
+			}
+			if(btRecvSockfd != -1) {
+				asd_closeSocket(btRecvSockfd);
+				btRecvSockfd = -1;
+			}
+			break;
+
+		case PROF_MCAST:
+#ifdef WIN32
+			/* Set the recv event and signal the recv thread function to stop
+			* Receiving the Multicast Traffic, also close the handle of the event*/
+			if(SetEvent(g_hRecvEvent) == 0) {
+				DPRINT_INFO(WFA_OUT, "ResetEvent failure %d \n", GetLastError());
+			}
+			while ((WaitForSingleObject(g_RecvhThread, INFINITE) != WAIT_OBJECT_0));
+			if(g_hRecvEvent != NULL)
+				CloseHandle(g_hRecvEvent);
+#else
+			/* Waiting for signal from wfaRecvStart once the receive 
+			 * operation is complete in order to close the socket 
+			 */
+			sem_wait(&sem_gtgrecv);
+#endif
+			if(btRecvSockfd != -1){
+				asd_closeSocket(btRecvSockfd);
+				btRecvSockfd = -1;
+			}
+			break;
+
+		case PROF_IPTV:
+			IPTVprof = 0;
+#ifdef WIN32
+			/* Set the recv event and signal the recv thread function to stop
+			* Receiving the IPTV traffic in the case of multiple streams,
+			* also close the handles of the multiple events*/
+			if(SetEvent(g_recvEvent[myStream->tblidx]) == 0) {
+				DPRINT_INFO(WFA_OUT, "ResetEvent failure %d \n", GetLastError());
+			}
+			while ((WaitForSingleObject(g_IPTVRecvhThread[myStream->tblidx], INFINITE) != WAIT_OBJECT_0));
+			if(g_recvEvent[myStream->tblidx] != NULL)
+				CloseHandle(g_recvEvent[myStream->tblidx]);
+#else
+			/* Waiting for signal from wfaIPTVRecvStart once the receive 
+			 * operation is complete in order to close the socket 
+			 */
+			sem_wait(&sem_iptv_gtgrecv[myStream->tblidx]);
+#endif
+			if(tgSockfds[myStream->tblidx] != -1){
+				asd_closeSocket(tgSockfds[myStream->tblidx]);
+				tgSockfds[myStream->tblidx] = -1;
+			}
+			/* the following to report the result. There will be a
+			* solution to send it back to TM
+			*/
+			//#endif
+			break;
+
+		case PROF_TRANSC:
+		case PROF_TRANSC_TCP:
+		case PROF_START_SYNC:
+		case PROF_CALI_RTD:  /* Calibrate roundtrip delay */
+			gtgTransac = 0;
+#ifdef WIN32
+			/* Set the recv event and signal the recv thread function to stop
+			* Receiving the Transaction Traffic, also close the handle of the event*/
+			if(SetEvent(g_hRecvEvent) == 0){
+				DPRINT_INFO(WFA_OUT, "ResetEvent failure %d \n", GetLastError());
+			}
+			while ((WaitForSingleObject(g_RecvhThread, INFINITE) != WAIT_OBJECT_0));
+			if(g_hRecvEvent != NULL)
+				CloseHandle(g_hRecvEvent);
+#else
+			/* Waiting for signal from wfaRecvStart once the receive 
+			 * operation is complete in order to close the socket 
+			 */
+			sem_wait(&sem_gtgrecv);
+#endif
+			if(gTcpRecvSockfd != -1) {
+				gTCPsock = 0;
+				asd_closeSocket(gTcpRecvSockfd);
+				gTcpRecvSockfd = -1;
+			}
+			if(btRecvSockfd != -1){
+				asd_closeSocket(btRecvSockfd);
+				btRecvSockfd = -1;
+			}
+			break;
+		case PROF_UAPSD:
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+			gtgWmmPS = 0;
+			gtgPsPktRecvd = 0;
+
+			if(psSockfd != -1)
+			{
+				asd_closeSocket(psSockfd);
+				psSockfd = -1;
+			}
+
+			memset(&wmmps_info, 0, sizeof(wfaWmmPS_t));
+
+			wfaSetDUTPwrMgmt(PS_OFF);
+#endif /* WFA_WMM_PS_EXT */
+#endif /* WFA_WMM_EXT */
+			break;
+		}
+		/* encode a TLV for response for "complete/error ..." */
+		statResp.status = STATUS_COMPLETE;
+		statResp.streamId = streamid;
+		DPRINT_INFO(WFA_OUT, "stream Id %i rx %i total %i\n", streamid, myStream->stats.rxFrames, myStream->stats.rxPayloadBytes);
+		memcpy(&statResp.cmdru.stats, &myStream->stats, sizeof(tgStats_t));
+		memcpy((dutRspBuf + i * sizeof(dutCmdResponse_t)), (BYTE *)&statResp, sizeof(dutCmdResponse_t));
+		id_cnt++;
+		memset(myStream, 0, sizeof(tgStream_t));
+	}
+
+	wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, (WORD)(id_cnt * sizeof(dutCmdResponse_t)), dutRspBuf, respBuf);
+
+	/* done here */
+	*respLen = WFA_TLV_HDR_LEN + numStreams * sizeof(dutCmdResponse_t);
+	return TRUE;
+}
+
+/*
+ * wfaTGSendStart: instruct traffic generator to start sending based on a profile
+ * input:      cmd -- not used
+ * response:   inform controller for "running"
+ * return:     success or failed
+ *
+ * In this function we will create the UDP sockets to send the traffic
+ * and set the global flag gtgSend, increment usedThread for each stream
+ * also set the socket option and type ofservice bits (TOS) in 
+ * the case of Multicast profiles . We also
+ * Call the thread Win32_tmout_stop_send() which sleeps for the duration specified in the profile
+ * and then stops the sending of the traffic by resetting the  runloop, decrement usedThread .
+ */
+int wfaTGSendStart(int len, BYTE *parms, int *respLen, BYTE *respBuf)
+{
+	int i=0, streamid=0, so;
+	int numStreams = len/4;
+	tgProfile_t *theProfile;
+	tgStream_t *myStream = NULL;
+	dutCmdResponse_t sendResp;
+#ifdef WIN32
+	DWORD errnum;
+#endif
+#ifdef WFA_DUT_SYNC
+#ifndef WIN32
+	pthread_attr_t ptAttr;
+	int ptPolicy;
+
+	struct sched_param ptSchedParam;
+	struct timeval btime;
+#else
+	SYSTEMTIME btime;
+#endif
+#endif
+	dutCmdResponse_t staSendResp;
+
+
+#ifdef WIN32
+	/*Create an event which will wait for the traffic streams to complete the send operation */
+	if((send_event = CreateEvent(NULL, FALSE, TRUE, NULL)) == 0){
+		DPRINT_INFO(WFA_OUT, "CreateEvent Failed = %d\r\n", GetLastError());
+	}
+#else
+
+	gnumStreams =  numStreams;
+#endif
+	DPRINT_INFO(WFA_OUT, "Entering tgSendStart for %i streams ...\n", numStreams);
+
+
+	for(i=0; i<numStreams; i++)
+	{
+		memcpy(&streamid, parms+(4*i), 4);
+		myStream = findStreamProfile(streamid);
+		if(myStream == NULL)
+		{
+			staSendResp.status = STATUS_INVALID;
+			wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+			return TRUE;
+		}
+
+		theProfile = &myStream->profile;
+		if(theProfile == NULL)
+		{
+			staSendResp.status = STATUS_INVALID;
+			wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+
+			return TRUE;
+		}
+
+		if(theProfile->direction != DIRECT_SEND)
+		{
+			staSendResp.status = STATUS_INVALID;
+			wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+			*respLen = WFA_TLV_HDR_LEN + 4;
+
+			return TRUE;
+		}
+
+		/*
+		* need to reset the stats
+		*/
+		memset(&myStream->stats, 0, sizeof(tgStats_t));
+		/* Here increment the usedThread for every time we wish to send a stream 
+		* so as to maintain the count of streams that are running at the same time.
+		*/
+		switch(theProfile->profile)
+		{
+		case PROF_FILE_TX:
+			btSockfd = wfaCreateUDPSock(theProfile->sipaddr, theProfile->sport);
+			if((btSockfd=wfaConnectUDPPeer(btSockfd, theProfile->dipaddr, theProfile->dport)) > 0)
+			{
+				gtgSend = streamid;
+				usedThread++;
+#ifndef WIN32
+				SendFile();
+#else
+				g_TGSndThr[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendFile, (LPVOID)streamid, 0, &dwIPTVThread);
+				if(g_TGSndThr[i] == NULL){
+				errnum = GetLastError();
+				DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+				return TRUE;
+			} 
+#endif
+			}
+			else
+			{
+				gtgSend = 0;
+				staSendResp.status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+
+				return TRUE;
+			}
+
+			break;
+		case PROF_FILE_TX_TCP:
+			if((btSockfd=wfaConnectTCPPeer(theProfile->sport, theProfile->dipaddr, theProfile->dport)) > 0)
+			{
+				gtgSend = streamid;
+				usedThread++;
+#ifndef WIN32
+				SendFile();
+#else
+				g_TGSndThr[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendFile, (LPVOID)streamid, 0, &dwIPTVThread);
+				if(g_TGSndThr[i] == NULL){
+					errnum = GetLastError();
+					DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+					return TRUE;
+				}
+#endif
+			}
+			else
+			{
+				gtgSend = 0;
+				staSendResp.status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+				return TRUE;
+			}
+			break;
+		case PROF_MCAST:
+			btSockfd = wfaCreateUDPSock(theProfile->sipaddr, theProfile->sport);
+			if(btSockfd > 0)
+			{
+				gtgSend = streamid;
+				usedThread ++;
+			}
+			else
+			{
+				staSendResp.status = STATUS_ERROR;
+
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+
+				return TRUE;
+			}
+
+			so = wfaSetSockMcastSendOpt(btSockfd);
+			if (so < 0)
+			{
+#ifdef WIN32
+				DPRINT_INFO(WFA_OUT,  "setsockopt for mcast: %d\n",WSAGetLastError());
+#endif
+				gtgSend = 0;
+				asd_closeSocket(btSockfd);
+				btSockfd = -1;
+				staSendResp.status = STATUS_ERROR;
+
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+
+				return TRUE;
+			}
+#ifndef WIN32
+				SendFile();
+#else
+				g_TGSndThr[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendFile, (LPVOID)gtgSend, 0, &dwIPTVThread);
+				if(g_TGSndThr[i] == NULL){
+				errnum = GetLastError();
+				DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+				return TRUE;
+			} 
+#endif
+			break;
+		case PROF_IPTV:
+
+			IPTVprof = 1;
+			gtgSend = streamid;
+			usedThread++;
+#ifndef WIN32
+
+			/*
+			* singal the thread to Sending WMM traffic
+			*/
+			wmm_thr[usedThread].thr_flag = streamid;
+			pthread_mutex_lock(&wmm_thr[usedThread].thr_flag_mutex);
+			pthread_cond_signal(&wmm_thr[usedThread].thr_flag_cond);
+			pthread_mutex_unlock(&wmm_thr[usedThread].thr_flag_mutex);
+#else
+			/* Create thread to send the IPTV stream, and store the handle of the thread in the array of the handles.
+			* New thread is created everytime in the case of multiple streams, to send the traffic simultaneously.
+			*/
+			g_TGSndThr[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendIPTVFile, (LPVOID)streamid, 0, &dwIPTVThread);
+			DPRINT_INFO(WFA_OUT, "Thread create Handle %x\n", g_TGSndThr[i]);
+			if(g_TGSndThr[i] == NULL){
+				errnum = GetLastError();
+				DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+				return TRUE;
+			} 
+
+#endif
+			DPRINT_INFO(WFA_OUT, "wfa_wmm_thread: myProfile->startdelay %i\n", theProfile->startdelay);
+			/* if delay is too long, it must be something wrong */
+			DPRINT_INFO(WFA_OUT, "sleep for %d\n", theProfile->startdelay);
+
+
+#ifdef WFA_DUT_SYNC
+			//reset clock by estimate drift
+			gettimeofday(&btime, NULL);
+
+			DPRINT_INFO(WFA_OUT, "btime.tv_sec %u, btime.tv_usec %u last sync time %f\n", (unsigned int) btime.tv_sec, (unsigned int) btime.tv_usec, gtgStartSyncTime.dut_time);
+
+			double bdftime = wfa_timeval2double(&btime) - (gtgStartSyncTime.dut_time);
+			traf_start_drift = clock_drift_ps * bdftime;
+
+			DPRINT_INFO(WFA_OUT, "time gap %lf traf_start_drift %i\n", bdftime, traf_start_drift);
+
+			if(abs(traf_start_drift) > 50)
+			{
+				DPRINT_INFO(WFA_OUT, "traf_start_drift %i\n", traf_start_drift);
+
+				btime.tv_usec += traf_start_drift;
+				if(btime.tv_usec < 0)
+				{
+					btime.tv_sec -= 1;
+					btime.tv_usec +=1000000;
+				}
+				else if(btime.tv_usec >=1000000)
+				{
+					btime.tv_sec +=1;
+					btime.tv_usec -= 1000000;
+				}
+
+				// clock get reset
+				settimeofday(&btime, NULL);
+
+				// ajust the sync time for the next run.
+				gtgStartSyncTime.dut_time = wfa_timeval2double(&btime);
+				clock_drift_ppk = (double) clock_drift_ps / (double) theProfile->rate;
+			}
+#endif
+			break;
+
+		case PROF_TRANSC:
+			{
+				btSockfd = wfaCreateUDPSock(theProfile->sipaddr, theProfile->sport);
+				if((btSockfd = wfaConnectUDPPeer(btSockfd, theProfile->dipaddr, theProfile->dport)) > 0)
+				{
+					gtgTransac = streamid;
+					gtgSend = streamid;
+					totalTranPkts = theProfile->rate * theProfile->duration;
+					sentTranPkts = 0;
+					/*
+					* the framerate here is used to derive the timeout
+					* value for waiting transaction echo responses.
+					*/
+					if(theProfile->rate == 0){
+						gtimeOut = MINISECONDS;  /* in msec */     
+					} else {
+						gtimeOut = MINISECONDS/theProfile->rate;  /* in msec */
+					}
+					gRegSec = 0;
+					usedThread++;
+				}
+				else
+				{
+					staSendResp.status = STATUS_ERROR;
+					wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+					*respLen = WFA_TLV_HDR_LEN + 4;
+
+					return TRUE;
+				}
+
+				/* set duration for the test */
+#ifndef WIN32
+				signal(SIGALRM, tmout_stop_send);
+				alarm(theProfile->duration);
+#else
+				if(hThread1 != NULL){
+					CloseHandle(hThread1);
+				}
+				hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Win32_tmout_stop_send, (LPVOID)(theProfile->duration *1000), 0, &dwGenericThread1);
+				if(hThread1 == NULL){
+					errnum = GetLastError();
+					DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+					return TRUE;
+				}
+#endif
+#ifndef WIN32
+				SendFile();
+#else
+				g_TGSndThr[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendFile, (LPVOID)gtgSend, 0, &dwIPTVThread);
+				if(g_TGSndThr[i] == NULL){
+				errnum = GetLastError();
+				DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+				return TRUE;
+				} 
+#endif
+			}
+			break;
+		case PROF_TRANSC_TCP:
+			if((btSockfd=wfaConnectTCPPeer(theProfile->dport, theProfile->dipaddr, theProfile->dport)) > 0)
+			{
+				gtgTransac = streamid;
+				gtgSend = streamid;
+				totalTranPkts = theProfile->rate * theProfile->duration;
+				sentTranPkts = 0;
+				/*
+				 * the framerate here is used to derive the timeout
+				 * value for waiting transaction echo responses.
+				 */
+				if(theProfile->rate == 0){
+					gtimeOut = MINISECONDS;  /* in msec */     
+				} else {
+					gtimeOut = MINISECONDS/theProfile->rate;  /* in msec */
+				}
+				gRegSec = 0;
+				usedThread++;
+			}
+			else
+			{
+				staSendResp.status = STATUS_ERROR;
+				wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
+				*respLen = WFA_TLV_HDR_LEN + 4;
+				return TRUE;
+			}
+
+			/* set duration for the test */
+#ifndef WIN32
+			signal(SIGALRM, tmout_stop_send);
+			alarm(theProfile->duration);
+#else
+			if(hThread1 != NULL){
+				CloseHandle(hThread1);
+			}
+			hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Win32_tmout_stop_send, (LPVOID)(theProfile->duration *1000), 0, &dwGenericThread1);
+			if(hThread1 == NULL){
+				errnum = GetLastError();
+				DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+				return TRUE;
+			}
+#endif
+#ifndef WIN32
+			SendFile();
+#else
+			g_TGSndThr[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendFile, (LPVOID)gtgSend, 0, &dwIPTVThread);
+			if(g_TGSndThr[i] == NULL){
+				errnum = GetLastError();
+				DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+				return TRUE;
+			} 
+#endif
+			break;
+#ifdef WFA_WMM_EXT
+		case PROF_START_SYNC:
+		case PROF_CALI_RTD:
+			{
+				DPRINT_INFO(WFA_OUT, "profile port %i\n", theProfile->sport);
+				btSockfd = wfaCreateUDPSock(theProfile->sipaddr, theProfile->sport);
+				if((btSockfd = wfaConnectUDPPeer(btSockfd, theProfile->dipaddr, theProfile->dport)) > 0)
+				{
+					gtgTransac = streamid;
+					gtgSend = streamid;
+					totalTranPkts = theProfile->rate * theProfile->duration;
+					sentTranPkts = 0;
+					if(theProfile->profile == PROF_START_SYNC)
+						gtgStartSync = streamid;
+					else if(theProfile->profile == PROF_CALI_RTD)
+						gtgFinishSync = streamid;
+
+					/*
+					* the framerate here is used to derive the timeout
+					* value for waiting transaction echo responses.
+					*/
+					gtimeOut = MINISECONDS/theProfile->rate;  /* in msec */
+				}
+				else
+				{
+					DPRINT_INFO(WFA_OUT, "connection failed\n");
+				}
+
+				/* set duration for the test */
+#ifndef WIN32
+				signal(SIGALRM, tmout_stop_send);
+				alarm(theProfile->duration+1);
+#else
+				if(hThread2 != NULL){
+					CloseHandle(hThread2);
+				}
+				hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Win32_tmout_stop_send, (LPVOID)((theProfile->duration+1) *1000), 0, &dwGenericThread2);
+				if(hThread2 == NULL){
+					errnum = GetLastError();
+					DPRINT_INFO(WFA_OUT, "Could not create the thread1\n");
+					return TRUE;
+				}
+#endif
+			}
+			break;
+#endif
+		default :
+			DPRINT_INFO(WFA_OUT, "No profile match findStreams problem\n");	
+		}
+	}
+
+#ifdef WIN32	
+	/* Wait fo the event to be signalled from the timeout function, after all
+	*  the threads have finished sending the traffic. 
+	* 
+	*/
+	
+		Sleep(theProfile->duration*1000);
+		if(SetEvent(send_event)== 0 ){
+			DPRINT_INFO(WFA_OUT, "SetEvent failure %d \n", GetLastError());
+		}
+		for(i = 0; i < numStreams; i++)
+		while ((WaitForSingleObject(g_TGSndThr[i], INFINITE) != WAIT_OBJECT_0));
+		if(IPTVprof == 1) {
+			memset(Send_dutResp, 0, WFA_BUFF_512);
+			wfaSentStatsResp(Send_dutResp);
+		}
+	
+
+	if(send_event != NULL) {
+		CloseHandle(send_event);
+		send_event = NULL;		 
+	}
+
+#else
+	sem_wait(&sem_wmm_resp);
+	if(IPTVprof) {
+		sem_wait(&sem_wmm);
+		memset(Send_dutResp, 0, WFA_BUFF_512);
+		wfaSentStatsResp(Send_dutResp);
+	} 
+#endif
+	/* update the response */
+	if(! IPTVprof) {
+		memset(Send_dutResp, 0, WFA_BUFF_512);
+		sendResp.status = STATUS_COMPLETE;
+		sendResp.streamId = myStream->id;
+		memcpy(&sendResp.cmdru.stats, &myStream->stats, sizeof(tgStats_t));
+		memcpy(Send_dutResp , (BYTE*)&sendResp, sizeof(dutCmdResponse_t));
+	}
+	wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, (WORD)(numStreams* sizeof(dutCmdResponse_t)),Send_dutResp, (BYTE*)respBuf);
+
+	/* done here */
+	*respLen = WFA_TLV_HDR_LEN + numStreams * sizeof(dutCmdResponse_t);
+
+	DPRINT_INFO(WFA_OUT, "Leaving send start Check btsockfd = %d\n", btSockfd);
+	return TRUE;
+}
+
+int wfaTGReset(int len, BYTE *parms, int *respLen, BYTE *respBuf)
+{
+	dutCmdResponse_t *resetResp = &gGenericResp;
+
+	gtgRecv = 0;
+	gtgSend = 0;
+	/* need to reset all traffic socket fds */
+	if(btSockfd != -1 ) {
+		asd_closeSocket(btSockfd);
+		btSockfd = -1;
+	}
+
+	if (btRecvSockfd != -1) {
+		asd_closeSocket(btRecvSockfd);
+		btRecvSockfd = -1;
+	}
+
+	/* reset the timer alarm if it was armed */
+#ifndef WIN32
+	alarm(0);
+#endif
+
+	/* just reset the flags for the command */
+	usedThread = 0;
+	gtgTransac = 0;
+	totalTranPkts = 0;
+	gtimeOut = 0;
+	gRegSec = 1; /* mewly added */
+	IPTVprof = 0;
+	runLoop = 0;
+	gTransactrunLoop = 0;
+
+#ifdef WFA_WMM_EXT
+	e2eCnt = 0;
+	/* changed now */
+	memset(e2eStats, 0, 6000*sizeof(tgE2EStats_t));
+
+	/* Start : Modified as per BRCM 1.3 ASD */
+
+#ifdef WFA_WMM_PS_EXT
+	gtgWmmPS = 0;
+	gtgPsPktRecvd = 0;
+
+	if(psSockfd != -1)
+	{
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+	}
+
+	memset(&wmmps_info, 0, sizeof(wfaWmmPS_t));
+
+	wfaSetDUTPwrMgmt(PS_OFF);
+#endif /* WFA_WMM_EXT */
+
+	/* End : Modified as per BRCM 1.3 ASD */
+
+
+#endif
+
+	/* Also need to clean up WMM streams NOT DONE YET!*/
+	slotCnt = 0;             /* reset stream profile container */
+
+
+	/* encode a TLV for response for "complete ..." */
+	resetResp->status = STATUS_COMPLETE;
+	wfaEncodeTLV(WFA_TRAFFIC_AGENT_RESET_RESP_TLV, 4,
+		(BYTE *)resetResp, respBuf);
+	*respLen = WFA_TLV_HDR_LEN + 4;
+
+	return TRUE;
+}
+
+/*
+ * calculate the sleep time for different frame rate
+ * It should be done according the device
+ * This is just one way to adjust the packet delivery speed. If you find
+ * you device does not meet the test requirements, you MUST re-adjust
+ * the method.
+ */
+
+/* The HZ value could be found in the build header file */
+/* 100 -> 10ms, 1000 -> 1ms , etc                       */
+#define WFA_KERNEL_MIN_TIMER_RES   100   /* HZ Value for 10 ms */
+
+void wfaTxSleepTime(int profile, int rate, int *sleepTime, int *throttledRate)
+{
+	*sleepTime=0;     /* in microseconds */
+	/* calculate the sleep time based on frame rate */
+
+	/*
+	* Framerate is still required for Multicast traffic
+	* Sleep and hold for a timeout.
+	*
+	* For WMM traffic, the framerate must also need for VO and VI.
+	* the framerate 500, OS may not handle it precisely.
+	*/
+	switch(profile)
+	{
+		/*
+		* Vendor must find ways to better adjust the speed for their own device
+		*/
+	case PROF_MCAST:
+	case PROF_IPTV:
+	case PROF_FILE_TX:
+	case PROF_FILE_TX_TCP:
+	case PROF_TRANSC:
+	case PROF_TRANSC_TCP:
+		if(rate >=100 || rate == 0)
+		{
+			/*
+			* this sleepTime indeed is now being used for time period
+			* to send packets in the throttled Rate.
+			* The idea here is that in each fixed 50 minisecond period,
+			* The device will send rate/20 (rate = packets / second),
+			* then go sleep for rest of time.
+			*/
+#ifndef WIN32
+			*sleepTime = 50000; /* fixed 50 miniseconds */
+#else
+			*sleepTime = 50; /* CHANGED FROM 50000 TO 50 fixed 50 miniseconds */
+#endif
+			*throttledRate = (rate?rate:3000)/20;
+			DPRINT_INFO(WFA_OUT, "Sleep time %i, throttledRate %i\n", *sleepTime, *throttledRate);
+		}
+		else if (rate > 0 && rate <= 50) /* typically for voice */
+		{
+			*throttledRate = 1;
+#ifndef WIN32
+			*sleepTime = 1000*1000/rate;
+#else
+			*sleepTime = 1000/rate;
+#endif
+		}
+		break;
+	default:
+		DPRINT_ERR(WFA_ERR, "Incorrect profile\n");
+	}
+}
+
+#ifndef WIN32
+#define WFA_TIME_DIFF(before, after, rtime, dtime) \
+             dtime = rtime + (after.tv_sec*1000000 + after.tv_usec) - (before.tv_sec*1000000 + before.tv_usec);
+#else
+#define WFA_TIME_DIFF(before, after, rtime, dtime) \
+             dtime = rtime + (after.wSecond +after.wMilliseconds ) - (before.wSecond + before.wMilliseconds );
+#endif
+
+void buzz_time(int delay)
+{
+#ifndef WIN32
+	struct timeval now, stop;
+#else
+	SYSTEMTIME now, stop;
+#endif
+	int diff;
+	int remain_time = 0;
+
+#ifndef WIN32
+	gettimeofday(&stop, 0);
+
+	stop.tv_usec += delay;
+	if(stop.tv_usec > 1000000)
+	{
+		stop.tv_usec -=1000000;
+		stop.tv_sec +=1;
+	}
+#else
+	GetSystemTime(&stop);
+	stop.wMilliseconds +=delay;
+	if(stop.wMilliseconds > 1000)
+	{
+		stop.wMilliseconds -=1000;
+		stop.wSecond+=1;
+	}
+#endif
+
+	do
+	{
+#ifndef WIN32
+		gettimeofday(&now, 0);
+		WFA_TIME_DIFF(now, stop, remain_time, diff);
+#else
+		GetSystemTime(&now);
+		WFA_TIME_DIFF(stop, now, remain_time, diff);
+#endif
+
+	} while(diff>0);
+}
+
+/**************************************************/
+/* the actually functions to send/receive packets */
+/**************************************************/
+
+/* This is going to be a blocking SEND till it finishes */
+int wfaSendLongFile(int mySockfd, int streamid, BYTE *aRespBuf, int *aRespLen)
+{
+	tgProfile_t           *theProf = NULL;
+	tgStream_t            *myStream = NULL;
+	struct sockaddr_in    toAddr;
+	char                  *packBuf;
+	int  packLen;
+	int  bytesSent;
+	dutCmdResponse_t sendResp;
+	int sleepTime = 0;
+	int throttledRate = 0;
+	int errsv;
+#ifndef WIN32
+	struct timeval before, after, stime;
+#else
+	SYSTEMTIME before, after, stime;
+#endif
+	int difftime = 0;
+	int counter = 0;
+	int throttled_est_cost;
+	int act_sleep_time;
+
+	DPRINT_INFO(WFA_OUT, "Entering sendLongFile %i\n", streamid);
+
+	/* find the profile */
+	myStream = findStreamProfile(streamid);
+	if(myStream == NULL)
+	{
+		return FALSE;
+	}
+
+	theProf = &myStream->profile;
+
+	if(theProf == NULL)
+	{
+		return FALSE;
+	}
+
+	packLen = theProf->pksize;
+
+	/* allocate a buf */
+	packBuf = (char *)malloc(packLen);
+	memset(packBuf, 1, packLen);
+
+	/* fill in the header */
+	strncpy(packBuf, "1345678", sizeof(tgHeader_t));
+
+	/* initialize the destination address */
+	memset(&toAddr, 0, sizeof(toAddr));
+	toAddr.sin_family = AF_INET;
+	toAddr.sin_addr.s_addr = inet_addr(theProf->dipaddr);
+	toAddr.sin_port = htons(theProf->dport);
+
+	/* if a frame rate and duration are defined, then we know
+	* interval for each packet and how many packets it needs to
+	* send.
+	*/
+
+	if(theProf->duration != 0)
+	{
+		DPRINT_INFO(WFA_OUT, "duration %i\n", theProf->duration);
+		/*
+		*  use this to decide periodical interval sleep time and frames to send
+		*  int the each interval.
+		*  Each device should adopt a own algorithm for better performance
+		*/
+		wfaTxSleepTime(theProf->profile, theProf->rate, &sleepTime, &throttledRate);
+		/*
+		* alright, we need to raise the priority level of the process
+		* to improve the real-time performance of packet sending.
+		* Since this is for tuning purpose, it is optional implementation.
+		*/
+		//wfaSetProcPriority(60);
+
+		//interval = 1*1000000/theProf->rate ; // in usec;
+
+		// Here assumes it takes 20 usec to send a packet
+		throttled_est_cost = throttledRate * 20;  // MUST estimate the cost per ppk
+		act_sleep_time = sleepTime - adj_latency - throttled_est_cost;
+		if (act_sleep_time <= 0)
+			act_sleep_time = sleepTime;
+
+		DPRINT_INFO(WFA_OUT, "sleep time %i act_sleep_time %i\n", sleepTime, act_sleep_time);
+
+		runLoop=1;
+#ifndef WIN32
+	while (runLoop)
+#else
+	while ((WaitForSingleObject(send_event,0) != WAIT_OBJECT_0))
+#endif		
+		{
+			counter++;
+			/* fill in the counter */
+			int2BuffBigEndian(counter, &((tgHeader_t *)packBuf)->hdr[8]);
+
+
+			/*
+			* the following code is only used to slow down
+			* over fast traffic flooding the buffer and cause
+			* packet drop or the other end not able to receive due to
+			* some limitations, purely for experiment purpose.
+			* each implementation needs some fine tune to it.
+			*/
+			if(counter ==1)
+			{
+#ifndef WIN32
+				gettimeofday(&before, NULL);
+
+				before.tv_usec += sleepTime;
+				if(before.tv_usec > 1000000)
+				{
+					before.tv_usec -= 1000000;
+					before.tv_sec +=1;
+				}
+#else
+				GetSystemTime(&before);
+				before.wMilliseconds +=sleepTime;
+				if(before.wMilliseconds > 1000)
+				{
+					before.wMilliseconds -= 1000;
+					before.wMilliseconds += 1;
+
+				}
+#endif
+			}
+
+			if(throttledRate != 0)
+			{
+				if(counter%throttledRate == 0)
+				{
+					// sleep that much time
+#ifndef WIN32
+					usleep(act_sleep_time);
+					gettimeofday(&after, NULL);
+					difftime = wfa_itime_diff(&after, &before);
+#else
+					/* In case of win32 for higher frame rate we are sleeping 
+					 * less to meet the required Tx frame rate efficiency.
+					 */
+					
+					if (theProf->rate > HIGH_FRAME_RATE_VAL)
+						usleep(act_sleep_time / SLEEP_DENOMINATOR);
+					else
+						usleep(act_sleep_time);
+					GetSystemTime(&after);
+					difftime = wfa_Winitime_diff(&before,&after );
+#endif
+					// burn the rest to absort latency
+					if(difftime >0)
+						buzz_time(difftime);
+#ifndef WIN32
+					before.tv_usec += sleepTime;
+					if(before.tv_usec > 1000000)
+					{
+						before.tv_usec -= 1000000;
+						before.tv_sec +=1;
+					}
+				}
+			} // otherwise, it floods
+#else
+					before.wMilliseconds += sleepTime;
+					if(before.wMilliseconds > 1000)
+					{
+						before.wMilliseconds -= 1000;
+						before.wSecond +=1;
+					}
+				}
+			} // otherwise, it floods
+#endif
+
+			/*
+			* Fill the timestamp to the header.
+			*/
+#ifndef WIN32
+			gettimeofday(&stime, NULL);
+
+			int2BuffBigEndian(stime.tv_sec, &((tgHeader_t *)packBuf)->hdr[12]);
+			int2BuffBigEndian(stime.tv_usec, &((tgHeader_t *)packBuf)->hdr[16]);
+#else
+			GetSystemTime(&stime);
+			int2BuffBigEndian(stime.wSecond, &((tgHeader_t *)packBuf)->hdr[12]);
+			int2BuffBigEndian(stime.wMilliseconds , &((tgHeader_t *)packBuf)->hdr[16]);
+#endif
+
+			if(theProf->profile == PROF_FILE_TX_TCP || theProf->profile == PROF_TRANSC_TCP)
+				bytesSent =  wfaCtrlSend(mySockfd, (unsigned char*)packBuf, packLen);
+			else
+				bytesSent = wfaTrafficSendTo(mySockfd, packBuf, packLen, (struct sockaddr *)&toAddr);
+
+			if(bytesSent != -1)
+			{
+				myStream->stats.txPayloadBytes += bytesSent;
+				myStream->stats.txFrames++ ;
+			}
+			else
+			{
+#ifndef WIN32
+				errsv = errno;
+				switch(errsv)
+				{
+				case EAGAIN:
+				case ENOBUFS:
+					//DPRINT_INFO(WFA_OUT, "send error\n");
+					usleep(50);            
+					counter-- ;
+					//myStream->stats.txFrames--;
+
+					break;
+				case ECONNRESET:
+					runLoop = 0;
+					break;
+				case EPIPE:
+					runLoop = 0;
+					break;
+				default:
+					{
+						DPRINT_INFO(WFA_OUT, "Packet sent error\n");
+					}
+				}
+#else
+				errsv = WSAGetLastError();
+
+				switch(errsv)
+				{
+				case WSATRY_AGAIN:
+				case WSAENOBUFS:
+					DPRINT_INFO(WFA_OUT, "send error\n");
+					usleep(1);             /* hold for 1 ms */
+					counter-- ;
+					// myStream->stats.txFrames--;
+
+					break;
+				case WSAECONNRESET:
+					runLoop = 0;
+					break;
+				case WSAESHUTDOWN:
+					runLoop = 0;
+					break;
+				default:
+					DPRINT_INFO(WFA_OUT, "Packet sent error\n");
+					break;
+				}
+#endif
+			}
+		}
+
+	/*
+	 * lower back to an original level if the process is raised previously
+	 * It is optional.
+	 */
+	//wfaSetProcPriority(30);
+	}
+	else /* invalid parameters */
+	{
+		/* encode a TLV for response for "invalid ..." */
+		sendResp.status = STATUS_INVALID;
+			memcpy(Send_dutResp , (BYTE*)&sendResp, sizeof(dutCmdResponse_t));
+		return DONE;
+	}
+
+	gtgSend = 0;
+
+	/* free the buffer */
+	free(packBuf);
+
+	/* Populate the statistics of the sent response in Send_dutResp . In the case of multiple streams 
+	* Send_dutResp buffer will have all the response at the end of the send process of all the streams.
+	*/
+	sendResp.status = STATUS_COMPLETE;
+	sendResp.streamId = myStream->id;
+	memcpy(&sendResp.cmdru.stats, &myStream->stats, sizeof(tgStats_t));
+	memcpy(Send_dutResp , (BYTE*)&sendResp, sizeof(dutCmdResponse_t));
+#ifndef WIN32
+	gnumStreams = gnumStreams -1;
+	if(IPTVprof == 1) {
+		    if(gnumStreams == 0)
+		       sem_post(&sem_wmm);
+
+	}
+#endif
+    return DONE;
+}
+
+/* this only sends one packet a time */
+int wfaSendShortFile(int mySockfd, int streamid, BYTE *sendBuf, int pksize, BYTE *aRespBuf, int *aRespLen)
+{
+	BYTE *packBuf = sendBuf;
+	struct sockaddr_in toAddr;
+	tgProfile_t *theProf;
+	tgStream_t *myStream;
+	int packLen, bytesSent=-1;
+	dutCmdResponse_t sendResp;
+	int errsv;
+	DPRINT_INFO(WFA_OUT, "---------SendShortFile----------:%d\r\n", mySockfd);
+	if(mySockfd == -1)
+	{
+		/* stop */
+		gtgTransac = 0;
+		gtimeOut = 0;
+		gtgRecv = 0;
+		gtgSend = 0;
+		DPRINT_INFO(WFA_OUT, "stop short traffic\n");
+
+		myStream = findStreamProfile(streamid);
+		if(myStream != NULL)
+		{
+			sendResp.status = STATUS_COMPLETE;
+			sendResp.streamId = streamid;
+			memcpy(&sendResp.cmdru.stats, &myStream->stats, sizeof(tgStats_t));
+			memcpy(Send_dutResp , (BYTE*)&sendResp, sizeof(dutCmdResponse_t));
+
+		}
+
+		return DONE;
+	}
+
+	/* find the profile */
+	myStream = findStreamProfile(streamid);
+
+	theProf = &myStream->profile;
+	if(theProf == NULL) {
+		return FALSE;
+	}
+
+	if(pksize == 0)
+		packLen = theProf->pksize;
+	else
+		packLen = pksize;
+
+	memset(&toAddr, 0, sizeof(toAddr));
+	toAddr.sin_family = AF_INET;
+	toAddr.sin_addr.s_addr = inet_addr(theProf->sipaddr);
+	toAddr.sin_port = htons(theProf->sport);
+
+	if(gtgRecv && gtgTransac)
+	{
+		toAddr.sin_addr.s_addr = inet_addr(theProf->sipaddr);
+		toAddr.sin_port = htons(theProf->sport);
+	}
+	else if(gtgSend && gtgTransac)
+	{
+		toAddr.sin_addr.s_addr = inet_addr(theProf->dipaddr);
+		toAddr.sin_port = htons(theProf->dport);
+	}
+
+	int2BuffBigEndian(myStream->stats.txFrames, &((tgHeader_t *)packBuf)->hdr[8]);
+
+	if(mySockfd != -1)
+	{
+		if(theProf->profile == PROF_FILE_TX_TCP || theProf->profile == PROF_TRANSC_TCP)
+			bytesSent = wfaCtrlSend(mySockfd, (unsigned char*)packBuf, packLen);
+		else
+			bytesSent = wfaTrafficSendTo(mySockfd, (char *)packBuf, packLen, (struct sockaddr *)&toAddr);
+	}
+
+
+	if(bytesSent > 0)
+	{
+		myStream->stats.txFrames++;
+		myStream->stats.txPayloadBytes += bytesSent;
+	}
+	else if(bytesSent == -1)
+	{
+#ifndef WIN32
+		errsv = errno;
+		switch(errsv)
+		{
+		case EAGAIN:
+		case ENOBUFS:
+			DPRINT_ERR(WFA_ERR, "send error\n");
+			usleep(1000);             /* hold for 1 ms */
+			// myStream->stats.txFrames--;
+			break;
+		default:
+			break;
+		}
+#else
+		errsv = WSAGetLastError();
+		switch(errsv)
+		{
+		case WSATRY_AGAIN:
+		case WSAENOBUFS:
+			usleep(1);             /* hold for 1 ms */
+			//	myStream->stats.txFrames--;
+			break;
+		default:
+			DPRINT_INFO(WFA_OUT, "sendto: ");
+			DPRINT_ERR(WFA_ERR, "send error\n");
+			break;
+		}
+
+#endif
+	}
+	sentTranPkts++;
+	DPRINT_INFO(WFA_OUT, "SendShortFile: sentTranPkts = %d\r\n",sentTranPkts);
+	return DONE;
+}
+
+/* In this function we always receive from a specified IP address and Port. We change the receive
+ * socket from blocking to non-blocking */
+int wfaRecvFile(int mySockfd, int streamid, char *recvBuf)
+{
+	/* how many packets are received */
+	char *packBuf = recvBuf;
+	struct sockaddr_in fromAddr;
+	tgProfile_t *theProf;
+	tgStream_t *myStream;
+	int bytesRecvd;
+#ifndef WIN32
+	int ioflags;
+#endif
+	int lostPkts;
+
+	/* find the profile */
+	myStream = findStreamProfile(streamid);
+
+	theProf = &myStream->profile;
+	if(theProf == NULL)
+	{
+		return FALSE;
+	}
+
+	memset(packBuf, 0, MAX_UDP_LEN);
+
+	memset(&fromAddr, 0, sizeof(fromAddr));
+	fromAddr.sin_family = AF_INET;
+	fromAddr.sin_addr.s_addr = inet_addr(theProf->dipaddr);
+	fromAddr.sin_port = htons(theProf->dport);
+
+	if(gtgRecv && gtgTransac)
+	{
+		fromAddr.sin_addr.s_addr = inet_addr(theProf->sipaddr);
+		fromAddr.sin_port = htons(theProf->sport);
+	}
+	else if(gtgSend && gtgTransac)
+	{
+		fromAddr.sin_addr.s_addr = inet_addr(theProf->dipaddr);
+		fromAddr.sin_port = htons(theProf->dport);
+	}
+
+	/* get current flags setting */
+#ifndef WIN32
+	ioflags = fcntl(mySockfd, F_GETFL, 0);
+
+	/* set only BLOCKING flag to non-blocking */
+	fcntl(mySockfd, F_SETFL, ioflags | O_NONBLOCK);
+
+#endif
+
+	/* it is always to receive at least one packet, in case more in the
+	queue, just pick them up.
+	*/
+	if(theProf->profile == PROF_FILE_TX_TCP || theProf->profile == PROF_TRANSC_TCP)
+		bytesRecvd = wfaCtrlRecv(mySockfd, (unsigned char*)packBuf);
+	else
+		bytesRecvd = wfaTrafficRecv(mySockfd, packBuf, (struct sockaddr *)&fromAddr);
+
+	if(bytesRecvd > 0)
+	{
+		myStream->stats.rxFrames++;
+		myStream->stats.rxPayloadBytes +=bytesRecvd;
+#ifdef WIN32
+		/* 
+		 * This sleep is added to avoid driver crash at Dut side when TG sends
+		 * traffic at unlimited frame rate for longer duration
+		 */
+		if (myStream->stats.rxFrames % 20 == 0)
+			usleep(1);
+#endif
+		/*
+		*  Get the lost packet count
+		*/
+		lostPkts =bigEndianBuff2Int(&((tgHeader_t *)packBuf)->hdr[8]) - 1 - myStream->lastPktSN;
+		myStream->stats.lostPkts += lostPkts;
+		myStream->lastPktSN = bigEndianBuff2Int(&((tgHeader_t *)packBuf)->hdr[8]);
+	}
+	return (bytesRecvd);
+}
+
+/* This is going to be a blocking SEND till it finishes 
+ * The code is optimized for to achieve higher through put
+ * by using hardcoded header buffers
+ */
+int wfaImprovePerfSendLongFile(int mySockfd, int streamid, BYTE *aRespBuf, int *aRespLen)
+{
+	tgProfile_t           *theProf = NULL;
+	tgStream_t            *myStream = NULL;
+	struct sockaddr_in    toAddr;
+	char                  *packBuf;
+	int  packLen;
+	int  bytesSent;
+	dutCmdResponse_t sendResp;
+	int errsv;
+#ifdef WIN32
+	SYSTEMTIME stime;
+#else
+	struct timeval stime;
+#endif
+
+	int counter = 0;
+
+	/* find the profile */
+	myStream = findStreamProfile(streamid);
+	if(myStream == NULL)
+	{
+		return FALSE;
+	}
+
+	theProf = &myStream->profile;
+
+	if(theProf == NULL || theProf->duration == 0) /* invalid parameters */
+	{
+		/* encode a TLV for response for "invalid ..." */
+		sendResp.status = STATUS_INVALID;
+		memcpy(Send_dutResp , (BYTE*)&sendResp, sizeof(dutCmdResponse_t));
+		return DONE;
+	}
+
+	packLen = theProf->pksize;
+
+	/* allocate a buf */
+	packBuf = (char *)malloc(packLen);
+	memset(packBuf, 1, packLen);
+
+	/* fill in the header */
+	strncpy(packBuf, "1345678", sizeof(tgHeader_t));
+
+	/* initialize the destination address */
+	memset(&toAddr, 0, sizeof(toAddr));
+	toAddr.sin_family = AF_INET;
+	toAddr.sin_addr.s_addr = inet_addr(theProf->dipaddr);
+	toAddr.sin_port = htons(theProf->dport);
+
+	/* if a frame rate and duration are defined, then we know
+	* interval for each packet and how many packets it needs to
+	* send.
+	*/
+
+	runLoop=1;
+	/*
+	* Fill the hardcoded timestamp to the header.
+	*/
+#ifndef WIN32
+	gettimeofday(&stime, NULL);
+	int2BuffBigEndian(stime.tv_sec, &((tgHeader_t *)packBuf)->hdr[12]);
+	int2BuffBigEndian(stime.tv_usec, &((tgHeader_t *)packBuf)->hdr[16]);
+#else
+	GetSystemTime(&stime);
+	int2BuffBigEndian(stime.wSecond, &((tgHeader_t *)packBuf)->hdr[12]);
+	int2BuffBigEndian(stime.wMilliseconds , &((tgHeader_t *)packBuf)->hdr[16]);
+#endif
+
+#ifndef WIN32
+	while (runLoop)
+#else
+	while ((WaitForSingleObject(send_event,0) != WAIT_OBJECT_0))
+#endif
+	{
+		counter++;
+		/* fill in the counter */
+		int2BuffBigEndian(counter, &((tgHeader_t *)packBuf)->hdr[8]);
+		/*
+		* the following code is only used to slow down
+		* over fast traffic flooding the buffer and cause
+		* packet drop or the other end not able to receive due to
+		* some limitations, purely for experiment purpose.
+		* each implementation needs some fine tune to it.
+		*/
+		if(theProf->profile == PROF_FILE_TX_TCP || theProf->profile == PROF_TRANSC_TCP)
+			bytesSent =  wfaCtrlSend(mySockfd, (unsigned char*)packBuf, packLen);
+		else
+			bytesSent = wfaTrafficSendTo(mySockfd, packBuf, packLen, (struct sockaddr *)&toAddr);
+
+		if(bytesSent > 0)
+		{
+			myStream->stats.txPayloadBytes += bytesSent;
+			myStream->stats.txFrames++ ;
+		}
+		else if(bytesSent == -1)
+		{
+#ifndef WIN32
+			errsv = errno;
+			switch(errsv)
+			{
+			case EAGAIN:
+			case ENOBUFS:
+				//DPRINT_INFO(WFA_OUT, "send error\n");
+				usleep(50);            
+				counter-- ;
+				//myStream->stats.txFrames--;
+
+				break;
+			case ECONNRESET:
+				runLoop = 0;
+				break;
+			case EPIPE:
+				runLoop = 0;
+				break;
+			default:
+				{
+					DPRINT_INFO(WFA_OUT, "Packet sent error\n");
+				}
+			}
+#else
+			errsv = WSAGetLastError();
+
+			switch(errsv)
+			{
+			case WSATRY_AGAIN:
+			case WSAENOBUFS:
+				DPRINT_INFO(WFA_OUT, "send error\n");
+				usleep(1);             /* hold for 1 ms */
+				counter-- ;
+				break;
+			case WSAECONNRESET:
+				runLoop = 0;
+				break;
+			case WSAESHUTDOWN:
+				runLoop = 0;
+				break;
+			default:
+				DPRINT_INFO(WFA_OUT, "Packet sent error\n");
+				break;
+			}
+#endif
+		}
+#ifdef WIN32
+		/* In case of win32 we are sleeping after every 20 frame sent.
+		 * This is to avoid driver hang in case of windows mobile
+		 */
+		if (myStream->stats.txFrames % 20 == 0)
+			usleep(1);
+#endif
+	}
+	gtgSend = 0;
+
+	/* free the buffer */
+	free(packBuf);
+
+	/* Populate the statistics of the sent response in Send_dutResp . In the case of multiple streams 
+	* Send_dutResp buffer will have all the response at the end of the send process of all the streams.
+	*/
+	sendResp.status = STATUS_COMPLETE;
+	sendResp.streamId = myStream->id;
+	memcpy(&sendResp.cmdru.stats, &myStream->stats, sizeof(tgStats_t));
+	memcpy(Send_dutResp , (BYTE*)&sendResp, sizeof(dutCmdResponse_t));
+
+#ifndef WIN32
+	gnumStreams = gnumStreams -1;
+	if(IPTVprof == 1) {
+		    if(gnumStreams == 0)
+		       sem_post(&sem_wmm);
+
+	}
+#endif
+	return DONE;
+}
+
+#ifdef WIN32
+DWORD Win32_tmout_stop_send(LPVOID num )
+{
+	int i;
+
+	Sleep((DWORD)num);
+	DPRINT_INFO(WFA_OUT,  "timer fired, stop sending traffic\n");
+	/*
+	*  After runLoop reset, all sendLong will stop
+	*/
+	runLoop = 0;
+	/*Reset to stop sending the short file*/
+	gTransactrunLoop = 0; 
+	/*
+	* Decrement the usedThread everytime the timeout function is called .
+	*/
+	--usedThread ;
+
+	if(usedThread ==0 && IPTVprof == 1) {
+		asd_sleep(1);
+		/* Set the event when there are no more streams to send the traffic */
+		if(SetEvent(send_event)== 0 ){
+			DPRINT_INFO(WFA_OUT, "SetEvent failure %d \n", GetLastError());
+		}
+		/*
+		 * all WMM streams also stop
+		 */
+		for(i=0; i<WFA_TRAFFIC_CLASS_NUM; i++)
+		{
+			if(g_TGSndThr[i] != NULL){
+				CloseHandle(g_TGSndThr[i]);
+				g_TGSndThr[i] = NULL;
+			}	
+		}
+	}
+	/*
+	* once the stream table slot count is reset, it implies that the test
+	* is done. When the next set profile command comes in, it will reset/clean
+	* the stream table.
+	*/
+	slotCnt = 0;
+
+	/*
+	* The test is for DT3 transaction test.
+	* Timeout to stop it.
+	*/
+	if(gtgTransac != 0)
+	{
+		gtgTransac = 0;
+		gtgSend = 0;
+		gtimeOut = 0;
+		gRegSec = 1;
+		gtgRecv = 0;
+	}
+
+	return 0;
+}
+
+#endif
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_thr.c b/src/tools/Wifi_ASD_test/lib/wfa_thr.c
new file mode 100755
index 0000000..d0604bb
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_thr.c
@@ -0,0 +1,347 @@
+
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN
+ *.AN
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+/*       Revision History:
+ *       2006/11/10  -- initial created by qhu
+ *       2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi
+ *       2007/03/30  -- 01.40 WPA2 and Official WMM Beta Release by qhu
+ *       2007/04/20 -- 02.00 WPA2 and Official WMM Release by qhu
+ *       2007/08/15 --  02.10 WMM-Power Save release by qhu
+ *       2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *       2007/11/07 --  02.30 Voice HSO -- qhu
+ *
+ */
+
+/*
+ * For MADWIFI driver, the TOS to 11E queue mapping as:
+ *    0x08, 0x20            ----> WME_AC_BK;
+ *    0x28, 0xa0            ----> WMC_AC_VI;
+ *    0x30, 0xe0 0x88, 0xb8 ----> WME_AC_VO
+ *      here 0x88 for UPSD, will be implemented later
+ *    all other/default     ----> WME_AC_BE;
+ */
+
+
+#include <stdio.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#endif /* !WIN32 */
+#include <wfa_debug.h>
+
+#include "wfa_types.h"
+#include "wfa_main.h"
+#include "wfa_tg.h"
+#include "wfa_debug.h"
+#include "wfa_tlv.h"
+#include "wfa_sock.h"
+#include "wfa_rsp.h"
+#include "wfa_wmmps.h"
+#include "wfa_miscs.h"
+#include "wfa_ca_resp.h"
+/*
+ * external global thread sync variables
+ */
+#ifdef WIN32
+extern HANDLE thr_flag_cond;
+extern HANDLE thr_stop_cond;
+extern void Win32_tmout_stop_send(LPVOID num ) ;
+#endif /* WIN32 */
+
+#ifdef WFA_WMM_EXT
+extern tgWMM_t wmm_thr[];
+#endif /* WFA_WMM_EXT */
+
+extern tgStream_t *findStreamProfile(int id);
+extern int gxcSockfd;
+extern int wfaSetProcPriority(int);
+extern tgStream_t *gStreams;
+extern int IPTVprof;
+extern int resetsnd;
+
+#ifdef WFA_WMM_PS_EXT
+extern int gtgWmmPS;
+extern int psSockfd;
+extern int **ac_seq;
+int num_hello = 0;
+int num_stops = 0;
+extern wfaWmmPS_t wmmps_info;
+extern void wfaSetDUTPwrMgmt(int mode);
+extern void BUILD_APTS_MSG(int msg, unsigned long *txbuf);
+extern void wmmps_wait_state_proc();
+extern void mpx(char *m,void *buf_v,int len);
+extern unsigned int psTxMsg[];
+extern unsigned int psRxMsg[];
+int msgsize = 256;
+extern StationProcStatetbl_t stationProcStatetbl[LAST_TEST+1][11];
+#endif /* WFA_WMM_PS_EXT */
+
+extern void wfaGetSockOpt(int sockfd, int* tosval, socklen_t* size);
+extern int wfaSetSockOpt(int sockfd, int* tosval, int size);
+void tmout_stop_send(int num) ;
+
+/*
+ * wfaTGSetPrio(): This depends on the network interface card.
+ *               So you might want to remap according to the driver
+ *               provided.
+ *               The current implementation is to set the TOS/DSCP bits
+ *               in the IP header
+ */
+int wfaTGSetPrio(int sockfd, int tgUserPriority)
+{
+	int tosval;
+
+	socklen_t size = sizeof(tosval);
+
+	wfaGetSockOpt(sockfd, &tosval, &size);
+
+	switch(tgUserPriority)
+	{
+	case TG_WMM_AC_BK:
+		tosval = TOS_BK;
+		break;
+	case TG_WMM_AC_VI:
+		tosval = TOS_VI;
+		break;
+	case TG_WMM_AC_UAPSD:
+		tosval = 0x88;
+		break;
+	case TG_WMM_AC_VO:
+		tosval = TOS_VO;
+		break;
+	case TG_WMM_AC_BE:
+		tosval = TOS_BE;
+	default:
+		tosval = 0x00;
+		/* default */
+		;
+	}
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+	psTxMsg[1] = tosval;
+#endif /* WFA_WMM_PS_EXT*/
+#endif /* WFA_WMM_EXT*/
+
+	if(wfaSetSockOpt(sockfd, &tosval, sizeof(tosval)) != 0)
+	{
+		DPRINT_ERR(WFA_ERR, "Failed to set IP_TOS\n");
+	}
+	return (tosval == 0xE0)?0xD8:tosval;
+}
+
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+/*
+ * sender(): This is a generic function to send a packed for the given dsc 
+ *               (ac:VI/VO/BE/BK), before sending the packet the function
+ *               puts the station into the PS mode indicated by psave and 
+ *               sends the packet after sleeping for sllep_period
+ */
+int sender(char psave,int sleep_period,int dsc)
+{
+   int r;
+   PRINTF("\nsleeping for %d",sleep_period);
+   wfaSetDUTPwrMgmt(psave);
+   uapsd_sleep(sleep_period);
+   PRINTF("\nAfter create sending %d\n",dsc);
+   create_apts_msg(APTS_DEFAULT, psTxMsg,wmmps_info.my_sta_id);
+   wfaTGSetPrio(psSockfd, dsc);
+   PRINTF("\nAfter create");
+   PRINTF("\nlock met");
+   r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+   return r;
+}
+
+/*
+ * wfaStaSndConfirm(): This function sends the confirm packet
+ *                which is sent after the console sends the
+ *                test name to the station
+ */
+int WfaStaSndConfirm(char psave,int sleep_period,int *state)
+{
+   int r;
+   static int num_hello=0;
+   wfaSetDUTPwrMgmt(psave);
+   if(!num_hello)
+      create_apts_msg(APTS_CONFIRM, psTxMsg,0);
+   r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+   (*state)++;
+
+   return 0;
+}
+
+/*
+ * WfaStaSndVO(): This function sends a AC_VO packet
+ *                after the time specified by sleep_period
+ *                and advances to the next state for the given test case
+ */
+int WfaStaSndVO(char psave,int sleep_period,int *state)
+{
+   int r;
+   static int en=1;
+   PRINTF("\r\nEnterring WfastasndVO %d",en++);
+   if ((r=sender(psave,sleep_period,TG_WMM_AC_VO))>=0)
+      (*state)++;
+   else
+      PRINTF("\r\nError\n");
+
+   return 0;
+}
+
+/*
+ * WfaStaSnd2VO(): This function sends two AC_VO packets
+ *                after the time specified by sleep_period
+ *                and advances to the next state for the given test case
+ */
+int WfaStaSnd2VO(char psave,int sleep_period,int *state)
+{
+   int r;
+   static int en=1;
+
+   PRINTF("\r\nEnterring WfastasndVO %d",en++);
+   if ((r=sender(psave,sleep_period,TG_WMM_AC_VO))>=0)
+   {
+	   r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+       mpx("STA msg",psTxMsg,64);
+       (*state)++;
+   }
+   else
+      PRINTF("\r\nError\n");
+
+   return 0;
+}
+
+/*
+ * WfaStaSndVI(): This function sends a AC_VI packet
+ *                after the time specified by sleep_period
+ *                and advances to the next state for the given test case
+ */
+int WfaStaSndVI(char psave,int sleep_period,int *state)
+{
+   int r;
+   static int en=1;
+
+   PRINTF("\r\nEnterring WfastasndVI %d",en++);
+   if ((r=sender(psave,sleep_period,TG_WMM_AC_VI))>=0)
+      (*state)++;
+
+   return 0;
+}
+
+/*
+ * WfaStaSndBE(): This function sends a AC_BE packet
+ *                after the time specified by sleep_period
+ *                and advances to the next state for the given test case
+ */
+int WfaStaSndBE(char psave,int sleep_period,int *state)
+{
+   int r;
+   static int en=1;
+
+   PRINTF("\r\nEnterring WfastasndBE %d",en++);
+   if ((r=sender(psave,sleep_period,TG_WMM_AC_BE))>=0)
+      (*state)++;
+
+   return 0;
+}
+/*
+ * WfaStaSndBK(): This function sends a AC_BK packet
+ *                after the time specified by sleep_period
+ *                and advances to the next state for the given test case
+ */
+int WfaStaSndBK(char psave,int sleep_period,int *state)
+{
+   int r;
+   static int en=1;
+
+   PRINTF("\r\nEnterring WfastasndBK %d",en++);
+   if ((r=sender(psave,sleep_period,TG_WMM_AC_BK))>=0)
+      (*state)++;
+
+   return 0;
+}
+
+/*
+ * WfaStaSndVOCyclic(): The function is the traffic generator for the L.1 test
+ *                      caseThis function sends 3000 AC_VO packet
+ *                      after the time specified by sleep_period (20ms)
+ */
+int WfaStaSndVOCyclic(char psave,int sleep_period,int *state)
+{
+   int i;
+   static int en=1;
+
+   for(i=0;i<3000;i++)
+   {
+       PRINTF("\r\nEnterring WfastasndVOCyclic %d",en++);
+       sender(psave,sleep_period,TG_WMM_AC_VO);
+       if(!(i%50))
+       {
+         PRINTF(".");
+         fflush(stdout);
+       }
+   }
+   (*state)++;
+   return 0;
+}
+#endif /* WFA_WMM_PS_EXT */
+#endif /* WFA_WMM_EXT */
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_tlv.c b/src/tools/Wifi_ASD_test/lib/wfa_tlv.c
new file mode 100644
index 0000000..30fa568
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_tlv.c
@@ -0,0 +1,204 @@
+ 

+/****************************************************************************

+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved

+ *

+ *

+ *  LICENSE

+ *

+ *  License is granted only to Wi-Fi Alliance members and designated

+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted

+ *  the non-exclusive, worldwide, limited right to use, copy, import, export

+ *  and distribute this software:

+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi

+ *  equipment; and

+ *  (ii) solely for the purpose of embedding the software into Authorized

+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to

+ *  its customers under a license with at least the same restrictions as

+ *  contained in this License, including, without limitation, the disclaimer of

+ *  warranty and limitation of liability, below..AN  The distribution rights

+ *  granted in clause

+ *  (ii), above, include distribution to third party companies who will

+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or

+ *  without such third party$B!G(Bs private label. Other than expressly granted

+ *  herein, this License is not transferable or sublicensable, and it does not

+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance

+ *  reserves all rights not expressly granted herein..AN 

+ *.AN 

+ *  Except as specifically set forth above, commercial derivative works of

+ *  this software or applications that use the Wi-Fi scripts generated by this

+ *  software are NOT AUTHORIZED without specific prior written permission from

+ *  Wi-Fi Alliance.

+ *.AN 

+ *  Non-Commercial derivative works of this software for internal use are

+ *  authorized and are limited by the same restrictions; provided, however,

+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of

+ *  such derivative works under a perpetual, payment-free license to use,

+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi

+ *  equipment.

+ *.AN 

+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse

+ *  or promote products that are derived from or that use this software without

+ *  specific prior written permission from Wi-Fi Alliance.

+ *

+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR

+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,

+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,

+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE

+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF

+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************

+ */

+

+/*

+ * file: wfa_tlv.c

+ * The file contains all TLV process functions, including Encode, Decode, etc

+ * TLV stands for Tag, Length, Value.

+ *

+ *   Revision History:

+ *      2006/03/10 -- initially created by qhu

+ *      2006/06/01 -- BETA release by qhu

+ *      2006/06/13 -- 00.02 release by qhu

+ *      2006/06/30 -- 00.10 Release by qhu

+ *      2006/07/10 -- 01.00 Release by qhu

+ *      2006/09/01 -- 01.05 Release by qhu

+ *      2007/02/15  -- WMM Extension Beta released by qhu, mkaroshi

+ *      2007/03/30 -- 01.40 WPA2 and Official WMM Beta Release by qhu

+ *      2007/04/20 -- 02.00 WPA2 and Official WMM Release by qhu

+ *      2007/08/15 --  02.10 WMM-Power Save release by qhu

+ *      2007/10/10 --  02.20 Voice SOHO beta -- qhu

+ *      2007/11/07 -- 02.30 Voice HSO -- qhu

+ *          -- make sure the the data len must be less than buffer size, 

+ *             a potential bug reported by rmaeder and ydror

+ *

+ */

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include "wfa_main.h"

+#include "wfa_debug.h"

+#include "wfa_types.h"

+#include "wfa_tlv.h"

+

+extern unsigned short wfa_defined_debug;

+

+/*

+ * wfaEncodeTLV(): Encoding a packet to TLV format 

+ * input: the_tag - packet type

+ *        the_len - the value length

+ *        the_value - the value buffer

+ *

+ * output: tlv_data - encoded TLV packet buffer. Caller must allocate the buffer

+ */

+BOOL wfaEncodeTLV(WORD the_tag, WORD the_len, BYTE *the_value, BYTE *tlv_data)

+{

+   void *data = tlv_data;

+

+   ((wfaTLV *)data)->tag = the_tag;

+   ((wfaTLV *)data)->len = the_len;

+   if(the_value != NULL && the_len != 0)

+      memcpy(((BYTE*)data+4), (BYTE *)the_value, the_len);

+

+   return TRUE;

+}

+

+/*

+ * wfaDecodeTLV(); Decoding a TLV format into actually values

+ * input:  tlv_data - the TLV format packet buffer

+ *         tlv_len  - the total length of the TLV

+ * output: ptag - the TLV type

+ *         pval_len - the value length

+ *         pvalue - value buffer, caller must allocate the buffer

+ */

+

+BOOL wfaDecodeTLV(BYTE *tlv_data, int tlv_len, BYTE *ptag, int *pval_len, BYTE *pvalue)

+{ 

+   wfaTLV *data = (wfaTLV *)tlv_data;

+ 

+   if(pvalue == NULL)

+   {

+       DPRINT_ERR(WFA_ERR, "Parm buf invalid\n");

+       return FALSE;

+   }

+   *ptag = (BYTE)data->tag; 

+   *pval_len = data->len;

+

+   if(tlv_len < *pval_len)

+       return FALSE;

+

+   if(*pval_len != 0 && *pval_len < MAX_PARMS_BUFF)

+   {

+      memcpy(pvalue, tlv_data+4, *pval_len);

+   }

+

+   return TRUE;

+}

+

+/*

+ * wfaGetTLVTag(): the individual function to retrieve a TLV type.

+ * input: tlv_data - TLV buffer

+ * return: the TLV type.

+ */

+

+WORD wfaGetTLVTag(BYTE *tlv_data)

+{

+   wfaTLV *ptlv = (wfaTLV *)tlv_data;

+

+   if(ptlv != NULL)

+      return ptlv->tag;

+   

+   return TRUE;

+}

+

+/*

+ * wfaSetTLVTag(): the individual function to set TLV type.

+ * input: new_tag - the new TLV type.

+ * Output: tlv_data - a TLV buffer, caller must allocate this buffer.

+ */

+

+BOOL wfaSetTLVTag(BYTE new_tag, BYTE *tlv_data)

+{

+   wfaTLV *ptlv = (wfaTLV *)tlv_data;

+

+   if(tlv_data == NULL)

+      return FALSE;

+

+   ptlv->tag = new_tag;

+

+   return TRUE;

+}

+

+/*

+ * wfaGetTLVLen(): retrieve a TLV value length

+ * input: tlv_data - a TLV buffer

+ * return: the value length.

+ */

+

+WORD wfaGetTLVLen(BYTE *tlv_data)

+{

+   wfaTLV *ptlv = (wfaTLV *)tlv_data;

+

+   if(tlv_data == NULL)

+     return FALSE;

+

+   return ptlv->len;

+}

+

+/*

+ * wfaGetTLVValue(): retrieve a TLV value

+ * input: value_len - TLV value length

+ *        tlv_data - a TLV data buffer

+ * output: pvalue - the value buffer, caller must allocate it.

+ */

+

+BOOL wfaGetTLVvalue(int value_len, BYTE *tlv_data, BYTE *pvalue)

+{

+    if(tlv_data == NULL)

+      return FALSE;

+

+    memcpy(pvalue, tlv_data+WFA_TLV_HEAD_LEN, value_len);

+

+    return TRUE;

+}

diff --git a/src/tools/Wifi_ASD_test/lib/wfa_typestr.c b/src/tools/Wifi_ASD_test/lib/wfa_typestr.c
new file mode 100644
index 0000000..9c144cb
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_typestr.c
@@ -0,0 +1,193 @@
+
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved
+ *
+ *
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated
+ *  contractors ($B!H(BAuthorized Licensees$B!I(B)..AN  Authorized Licensees are granted
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export
+ *  and distribute this software:
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi
+ *  equipment; and
+ *  (ii) solely for the purpose of embedding the software into Authorized
+ *  Licensee$B!G(Bs proprietary equipment and software products for distribution to
+ *  its customers under a license with at least the same restrictions as
+ *  contained in this License, including, without limitation, the disclaimer of
+ *  warranty and limitation of liability, below..AN  The distribution rights
+ *  granted in clause
+ *  (ii), above, include distribution to third party companies who will
+ *  redistribute the Authorized Licensee$B!G(Bs product to their customers with or
+ *  without such third party$B!G(Bs private label. Other than expressly granted
+ *  herein, this License is not transferable or sublicensable, and it does not
+ *  extend to and may not be used with non-Wi-Fi applications..AN  Wi-Fi Alliance
+ *  reserves all rights not expressly granted herein..AN
+ *.AN
+ *  Except as specifically set forth above, commercial derivative works of
+ *  this software or applications that use the Wi-Fi scripts generated by this
+ *  software are NOT AUTHORIZED without specific prior written permission from
+ *  Wi-Fi Alliance.
+ *.AN
+ *  Non-Commercial derivative works of this software for internal use are
+ *  authorized and are limited by the same restrictions; provided, however,
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of
+ *  such derivative works under a perpetual, payment-free license to use,
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi
+ *  equipment.
+ *.AN
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse
+ *  or promote products that are derived from or that use this software without
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A.AN PARTICULAR PURPOSE,
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT,
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************
+ */
+/*
+ *  wfa_typestr.c:
+ *  global array of the mapping of command types, command strings
+ *  to attached processing function
+ *
+ *     Revision History:
+ *       2006/03/10 -- initially created by qhu
+ *       2006/06/01 -- BETA release by qhu
+ *       2006/06/13 -- 00.02 release by qhu
+ *       2006/06/30 -- 00.10 Release by qhu
+ *       2006/07/10 -- 01.00 Release by qhu
+ *       2006/09/01 -- 01.05 Release by qhu
+ *       2007/03/30 -- 01.40 WPA2 and Official WMM Beta Release by qhu
+ *       2007/04/20 -- 02.00 WPA2 and Official WMM Release by qhu
+ *       2007/08/15 --  02.10 WMM-Power Save release by qhu
+ *       2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *       2007/11/07 --  02.30 Voice HSO -- qhu
+ */
+#include <stdio.h>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include "wfa_types.h"
+#include "wfa_tlv.h"
+#include "wfa_tg.h"
+#include "wfa_cmds.h"
+#include "wfa_agtctrl.h"
+
+extern int cmdProcNotDefinedYet(char *, BYTE *, int *);
+extern int xcCmdProcGetVersion(char *, BYTE *, int *);
+extern int xcCmdProcAgentConfig(char *, BYTE *, int *);
+extern int xcCmdProcAgentSend(char *, BYTE *, int *);
+extern int xcCmdProcAgentRecvStart(char *, BYTE *, int *);
+extern int xcCmdProcAgentRecvStop(char *, BYTE *, int *);
+extern int xcCmdProcAgentReset(char *, BYTE *, int *);
+extern int xcCmdProcStaGetIpConfig(char *, BYTE *, int *);
+extern int xcCmdProcStaSetIpConfig(char *, BYTE *, int *);
+extern int xcCmdProcStaGetMacAddress(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaIsConnected(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaVerifyIpConnection(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaGetBSSID(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaGetStats(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetEncryption(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetPSK(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetEapTLS(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetEapTTLS(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetEapSIM(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetPEAP(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetIBSS(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcDeviceGetInfo(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcDeviceListIF(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaAssociate(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetUAPSD(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaGetInfo(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcAgentSendPing(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcAgentStopPing(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaDebugSet(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetMode(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetWMM(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetSystime(char *pcmdStr, BYTE *, int *);
+#ifdef WFA_STA_TB
+extern int xcCmdProcStaNeigreq(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSet11n(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetRIFSTest(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetWireless(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSendAddba(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSendCoexistMGMT(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaDisconnect(char *pcmdStr, BYTE *, int *);
+#endif
+extern int xcCmdProcStaSetEapFAST(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetEapAKA(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaReAssociate(char *pcmStr, BYTE *, int *);
+extern int xcCmdProcStaResetDefault(char *pcmdStr, BYTE *, int *);
+extern int xcCmdProcStaSetPwrSave(char *pcmdStr, BYTE *, int *);
+
+/*
+ * Initialize a command name table to its defined type and process function
+ * These commands get executed at the DUT side.
+ */
+typeNameStr_t nameStr[] =
+{
+   {0,                   "NO_USED_STRING", NULL},
+   {WFA_GET_VERSION_TLV, "ca_get_version", xcCmdProcGetVersion},
+   {WFA_TRAFFIC_SEND_PING_TLV, "traffic_send_ping", xcCmdProcAgentSendPing},
+   {WFA_TRAFFIC_STOP_PING_TLV, "traffic_stop_ping", xcCmdProcAgentStopPing},
+   {WFA_TRAFFIC_AGENT_CONFIG_TLV, "traffic_agent_config", xcCmdProcAgentConfig},
+   {WFA_TRAFFIC_AGENT_SEND_TLV, "traffic_agent_send", xcCmdProcAgentSend},
+   {WFA_TRAFFIC_AGENT_RESET_TLV, "traffic_agent_reset", xcCmdProcAgentReset},
+   {WFA_TRAFFIC_AGENT_RECV_START_TLV, "traffic_agent_receive_start", xcCmdProcAgentRecvStart},
+   {WFA_TRAFFIC_AGENT_RECV_STOP_TLV, "traffic_agent_receive_stop", xcCmdProcAgentRecvStop},
+   {WFA_STA_GET_IP_CONFIG_TLV, "sta_get_ip_config", xcCmdProcStaGetIpConfig},
+   {WFA_DEVICE_LIST_IF_TLV, "device_list_interfaces", xcCmdProcDeviceListIF},
+   {WFA_STA_SET_IP_CONFIG_TLV, "sta_set_ip_config", xcCmdProcStaSetIpConfig},
+   {WFA_STA_VERIFY_IP_CONNECTION_TLV, "sta_verify_ip_connection", xcCmdProcStaVerifyIpConnection},
+   {WFA_STA_SET_SYSTIME_TLV, "sta_set_systime", xcCmdProcStaSetSystime},
+   {WFA_STA_SET_EAPFAST_TLV, "sta_set_eapfast", xcCmdProcStaSetEapFAST},
+   {WFA_STA_SET_EAPAKA_TLV, "sta_set_eapaka", xcCmdProcStaSetEapAKA},
+   {-1, "", NULL}
+};
+
+
+/* functions to  be executed from  RWL server 
+ * These control commands get executed from CA which calls Rwl client with the 
+ * required transport options
+ */
+typeNameStr_t nameLocalStr[] =
+{
+   {0,                   "NO_USED_STRING", NULL},
+   {WFA_STA_ASSOCIATE_TLV, "sta_associate", xcCmdProcStaAssociate},
+   {WFA_STA_IS_CONNECTED_TLV, "sta_is_connected", xcCmdProcStaIsConnected},
+   {WFA_STA_GET_MAC_ADDRESS_TLV, "sta_get_mac_address", xcCmdProcStaGetMacAddress},
+   {WFA_STA_GET_BSSID_TLV, "sta_get_bssid", xcCmdProcStaGetBSSID},
+   {WFA_STA_GET_STATS_TLV, "sta_get_stats", xcCmdProcStaGetStats},
+   {WFA_STA_GET_INFO_TLV, "sta_get_info", xcCmdProcStaGetInfo},
+   {WFA_STA_SET_MODE_TLV, "sta_set_mode", xcCmdProcStaSetMode},
+   {WFA_STA_SET_WMM_TLV, "sta_set_wmm", xcCmdProcStaSetWMM},
+   {WFA_DEVICE_GET_INFO_TLV, "device_get_info", xcCmdProcDeviceGetInfo},
+   {WFA_STA_SET_ENCRYPTION_TLV, "sta_set_encryption", xcCmdProcStaSetEncryption},
+   {WFA_STA_SET_PSK_TLV, "sta_set_psk", xcCmdProcStaSetPSK},
+   {WFA_STA_SET_EAPTLS_TLV, "sta_set_eaptls", xcCmdProcStaSetEapTLS},
+   {WFA_STA_SET_EAPTTLS_TLV, "sta_set_eapttls", xcCmdProcStaSetEapTTLS},
+   {WFA_STA_SET_EAPSIM_TLV, "sta_set_eapsim", xcCmdProcStaSetEapSIM},
+   {WFA_STA_SET_UAPSD_TLV, "sta_set_uapsd", xcCmdProcStaSetUAPSD}, /* Added as per BRCM 1.3 ASD */
+   {WFA_STA_SET_IBSS_TLV, "sta_set_ibss", xcCmdProcStaSetIBSS},
+   {WFA_STA_SET_PEAP_TLV, "sta_set_peap", xcCmdProcStaSetPEAP},
+   {WFA_STA_DEBUG_SET_TLV, "sta_debug_set", xcCmdProcStaDebugSet},
+#ifdef WFA_STA_TB   
+   {WFA_STA_SEND_NEIGREQ_TLV, "sta_send_neigreq", xcCmdProcStaNeigreq},
+   {WFA_STA_SET_11N_TLV, "sta_set_11n", xcCmdProcStaSet11n},
+   {WFA_STA_SET_RIFS_TEST_TLV, "sta_set_rifs_test", xcCmdProcStaSetRIFSTest},
+   {WFA_STA_SET_WIRELESS_TLV, "sta_set_wireless", xcCmdProcStaSetWireless},
+   {WFA_STA_SEND_ADDBA_TLV, "sta_send_addba", xcCmdProcStaSendAddba},
+   {WFA_STA_SEND_COEXIST_MGMT_TLV, "sta_send_coexist_mgmt", xcCmdProcStaSendCoexistMGMT},
+   {WFA_STA_DISCONNECT_TLV, "sta_disconnect", xcCmdProcStaDisconnect}, 
+#endif   
+   {WFA_STA_REASSOCIATE_TLV, "sta_reassociate", xcCmdProcStaReAssociate},
+   {WFA_STA_RESET_DEFAULT_TLV, "sta_reset_default", xcCmdProcStaResetDefault},
+   {WFA_STA_SET_PWRSAVE_TLV, "sta_set_pwrsave", xcCmdProcStaSetPwrSave},
+   {-1, "", NULL}
+};
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_wmmps.c b/src/tools/Wifi_ASD_test/lib/wfa_wmmps.c
new file mode 100644
index 0000000..b4f4d74
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_wmmps.c
@@ -0,0 +1,737 @@
+/****************************************************************************
+ *  (c) Copyright 2007 Wi-Fi Alliance.  All Rights Reserved 
+ *
+ * 
+ *  LICENSE
+ *
+ *  License is granted only to Wi-Fi Alliance members and designated 
+ *  contractors (“Authorized Licensees”).  Authorized Licensees are granted 
+ *  the non-exclusive, worldwide, limited right to use, copy, import, export 
+ *  and distribute this software: 
+ *  (i) solely for noncommercial applications and solely for testing Wi-Fi 
+ *  equipment; and 
+ *  (ii) solely for the purpose of embedding the software into Authorized 
+ *  Licensee’s proprietary equipment and software products for distribution to 
+ *  its customers under a license with at least the same restrictions as 
+ *  contained in this License, including, without limitation, the disclaimer of 
+ *  warranty and limitation of liability, below.  The distribution rights 
+ *  granted in clause 
+ *  (ii), above, include distribution to third party companies who will 
+ *  redistribute the Authorized Licensee’s product to their customers with or 
+ *  without such third party’s private label. Other than expressly granted 
+ *  herein, this License is not transferable or sublicensable, and it does not 
+ *  extend to and may not be used with non-Wi-Fi applications.  Wi-Fi Alliance 
+ *  reserves all rights not expressly granted herein. 
+ * 
+ *  Except as specifically set forth above, commercial derivative works of 
+ *  this software or applications that use the Wi-Fi scripts generated by this 
+ *  software are NOT AUTHORIZED without specific prior written permission from 
+ *  Wi-Fi Alliance.
+ * 
+ *  Non-Commercial derivative works of this software for internal use are 
+ *  authorized and are limited by the same restrictions; provided, however, 
+ *  that the Authorized Licensee shall provide Wi-Fi Alliance with a copy of 
+ *  such derivative works under a perpetual, payment-free license to use, 
+ *  modify, and distribute such derivative works for purposes of testing Wi-Fi 
+ *  equipment.
+ * 
+ *  Neither the name of the author nor "Wi-Fi Alliance" may be used to endorse 
+ *  or promote products that are derived from or that use this software without 
+ *  specific prior written permission from Wi-Fi Alliance.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY WI-FI ALLIANCE "AS IS" AND ANY EXPRESS OR 
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ *  OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE, 
+ *  ARE DISCLAIMED. IN NO EVENT SHALL WI-FI ALLIANCE BE LIABLE FOR ANY DIRECT, 
+ *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+ *  (INCLUDING, BUT NOT LIMITED TO, THE COST OF PROCUREMENT OF SUBSTITUTE 
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+ *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE) ARISING IN ANY WAY OUT OF 
+ *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*    Revision History:
+ *    2007/07/25  -- Initial created by qhu
+ *    2007/08/15  -- 02.10 WMM-Power Save Released by qhu
+ *    2007/10/10 --  02.20 Voice SOHO beta -- qhu
+ *    2007/11/07 --  02.30 Voice HSO -- qhu
+ *    2007/12/10 --  02.32 no change
+ *    2008/02/07 --  02.40 Upgrade the new WMM-PS method.
+ *    2008/03/20 --  02.41 [Bug #18] In some devices, "num_hello" reaches its 
+ *                         upper limit, causing other tests to reset. The
+ *                         counter now resets at the completion of each test.
+ *                         Affected Function(s): wfaRcvProc()
+ *
+ *                         [None] Print message too long and frequent. Remove
+ *                         trace messages for L1.
+ *
+ */
+
+#ifdef WFA_WMM_EXT
+#ifdef WFA_WMM_PS_EXT
+
+#ifndef WIN32
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+#endif /* !WIN32 */
+
+#include "wfa_debug.h"
+#include "wfa_sock.h"
+#include "wfa_types.h"
+#include "wfa_tg.h"
+#include "wfa_ca.h"
+#include "wfa_wmmps.h"
+#include "wfa_miscs.h"
+#include "wfa_main.h"
+
+extern int psSockfd;
+extern int num_hello;
+extern tgWMM_t wmm_thr[];
+
+extern unsigned int psTxMsg[512];
+extern unsigned int psRxMsg[512];
+extern int msgsize;
+
+int resetsnd=0;
+int reset_recd=0;
+int resetrcv=0;
+int num_retry=0;
+int gtgPsPktRecvd = 0;                    // need to reset
+
+extern wfaWmmPS_t wmmps_info;
+extern void *g_wl_handle;
+
+extern int wfaTGSetPrio(int sockfd, int tgClass);
+void wmmps_wait_state_proc();
+void wfaSetDUTPwrMgmt(int mode);
+
+/* APTS messages*/
+struct apts_msg apts_msgs[] ={
+	{0, -1},
+	{"B.D", B_D},	
+	{"B.H", B_H},
+	{"B.B", B_B},
+	{"B.M", B_M},	
+	{"M.D", M_D},	
+	{"B.Z", B_Z},	
+	{"M.Y", M_Y},	
+	{"L.1", L_1},	
+	{"A.Y", A_Y},	
+	{"B.W", B_W},	
+	{"A.J", A_J},	
+	{"M.V", M_V},	
+	{"M.U", M_U},	
+	{"A.U", A_U},	
+	{"M.L", M_L},	
+	{"B.K", B_K},	
+	{"M.B", M_B},	
+	{"M.K", M_K},	
+	{"M.W", M_W},	
+#ifdef WFA_WMM_AC
+	{"ATC1", ATC1},	
+	{"ATC2", ATC2},	
+	{"ATC3", ATC3},	
+	{"ATC4", ATC4},	
+	{"ATC5", ATC5},	
+	{"ATC6", ATC6},	
+	{"ATC7", ATC7},	
+	{"ATC8", ATC8},	
+	{"ATC9", ATC9},	
+	{"ATC10", ATC10},	
+	{"ATC11", ATC11},	
+	{"STC1", STC1},	
+	{"STC2", STC2},	
+	{"STC3", STC3},	
+#endif
+	{"APTS TX         ", APTS_DEFAULT },
+	{"APTS Hello      ", APTS_HELLO },
+	{"APTS Broadcast  ", APTS_BCST },
+	{"APTS Confirm    ", APTS_CONFIRM},
+	{"APTS STOP       ", APTS_STOP},
+	{"APTS CK BE      ", APTS_CK_BE },
+	{"APTS CK BK      ", APTS_CK_BK },
+	{"APTS CK VI      ", APTS_CK_VI },
+	{"APTS CK VO      ", APTS_CK_VO },
+	{"APTS RESET      ", APTS_RESET },
+	{"APTS RESET RESP ", APTS_RESET_RESP },
+	{"APTS RESET STOP ", APTS_RESET_STOP },
+	{0, 0 }		// APTS_LAST
+};
+/* The DUT recv table for each of the test cases*/
+StationRecvProcStatetbl_t stationRecvProcStatetbl[LAST_TEST+1][6] = 
+{
+         {WfaRcvStop,0,0,0,0,0},
+ /*B.D*/ {WfaRcvProc,WfaRcvVO,WfaRcvStop,0,0,0},
+ /*B.H*/ {WfaRcvProc,WfaRcvVO,WfaRcvVO,WfaRcvStop,0,0},
+ /*B.B*/ {WfaRcvProc,WfaRcvStop,0,0,0,0},
+ /*B.M*/ {WfaRcvProc,WfaRcvStop,0,0,0,0},
+ /*M.D*/ {WfaRcvProc,WfaRcvBE,WfaRcvBK,WfaRcvVI,WfaRcvVO,WfaRcvStop},
+ /*B.Z*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvStop,0,0},
+ /*M.Y*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvBE,WfaRcvStop,0},
+ /*L.1*/ {WfaRcvProc,WfaRcvVOCyclic,0,0,0,0},
+ /*A.Y*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvBE,WfaRcvStop,0},
+ /*B.W*/ {WfaRcvProc,WfaRcvBE,WfaRcvVI,WfaRcvBE,WfaRcvVI,WfaRcvStop},
+ /*A.J*/ {WfaRcvProc,WfaRcvVO,WfaRcvVI,WfaRcvBE,WfaRcvBK,WfaRcvStop},
+ /*M.V*/ {WfaRcvProc,WfaRcvBE,WfaRcvVI,WfaRcvStop,0,0},
+ /*M.U*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvVO,WfaRcvVO,WfaRcvStop},
+ /*A.U*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvVO,WfaRcvStop,0},
+ /*M.L*/ {WfaRcvProc,WfaRcvBE,WfaRcvStop,0,0,0},
+ /*B.K*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvStop,0,0},
+ /*M.B*/ {WfaRcvProc,WfaRcvStop,0,0,0,0},
+ /*M.K*/ {WfaRcvProc,WfaRcvBE,WfaRcvVI,WfaRcvStop,0,0},
+ /*M.W*/ {WfaRcvProc,WfaRcvBE,WfaRcvBE,WfaRcvBE,WfaRcvVI,WfaRcvStop}
+#ifdef WFA_WMM_AC
+ /*ATC1*/ ,{WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvStop},
+ /*ATC2*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvBE,WfaRcvStop},
+ /*ATC3*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvBE,WfaRcvStop},
+ /*ATC4*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvVO,WfaRcvVO,WfaRcvStop},
+ /*ATC5*/ {WfaRcvProc,WfaRcvVI,WfaRcvVO,WfaRcvStop},
+ /*ATC6*/ {WfaRcvProc,WfaRcvVO,WfaRcvVI,WfaRcvVI,WfaRcvStop},
+ /*ATC7*/ {WfaRcvProc,WfaRcvVO,WfaRcvVI,WfaRcvBE,WfaRcvBK,WfaRcvStop},
+ /*ATC8*/ {WfaRcvProc,WfaRcvVO,WfaRcvVI,WfaRcvStop},
+ /*ATC9*/ {WfaRcvProc,WfaRcvVO,WfaRcvVI,WfaRcvBE,WfaRcvBK,WfaRcvStop},
+ /*ATC10*/{WfaRcvProc,WfaRcvVO,WfaRcvVI,WfaRcvBE,WfaRcvBK,WfaRcvStop},
+ /*ATC11*/{WfaRcvProc,WfaRcvVO,WfaRcvVO,WfaRcvVI,WfaRcvVO,WfaRcvStop},
+ /*STC1*/ {WfaRcvProc,WfaRcvVI,WfaRcvBE,WfaRcvStop},
+ /*STC2*/ {WfaRcvProc,WfaRcvBE,WfaRcvVI,WfaRcvStop},
+ /*STC3*/ {WfaRcvProc,WfaRcvBE,WfaRcvBK,WfaRcvVI,WfaRcvVO,WfaRcvStop}
+#endif
+};
+/* The DUT send table for each of the test cases*/
+
+StationProcStatetbl_t stationProcStatetbl[LAST_TEST+1][11] = {
+/* Dummy*/{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}},
+/* B.D*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+  {WfaStaSndVO,P_ON,LII / 2}   ,{WfaStaSndVO,P_ON,LII / 2}        ,{WfaStaWaitStop,P_ON,LII / 2},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* B.H*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVO,P_ON,LII / 2}   ,{WfaStaSndVO,P_ON,LII / 2}        ,{WfaStaWaitStop,P_ON,LII / 2},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* B.B*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVO,P_ON,LII / 2}   ,{WfaStaSndVI,P_ON,LII / 2}        ,{WfaStaSndBE,P_ON,LII / 2}     ,{WfaStaSndBK,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2},{0,0,0},{0,0,0},{0,0,0}},
+
+/* B.M*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,30000000},{WfaStaWaitStop,P_ON,LII / 2}     ,{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},	
+
+/* M.D*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndVI,P_ON,LII / 2}        ,{WfaStaSndVI,P_ON,LII / 2}     ,{WfaStaSndVI,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2},{0,0,0},{0,0,0},{0,0,0}},
+
+/* B.Z*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+  {WfaStaSndVO,P_ON,LII / 2 }  ,{WfaStaWaitStop,P_ON,LII / 2}     ,{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* M.Y*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+  {WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndVO,P_ON,LII / 2}        ,{WfaStaSndBE,P_ON,LII / 2}     ,{WfaStaSndBE,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2},{0,0,0},{0,0,0},{0,0,0}},
+
+/* L.1*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+  {WfaStaSndVOCyclic,P_ON,20000},{WfaStaWaitStop,P_ON,LII / 2 }},
+
+/* A.Y*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+  {WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndVO,P_ON,LII / 2}        ,{WfaStaSndBE,P_ON,LII / 2}     ,{WfaStaSndBE,P_OFF,LII / 2}    ,{WfaStaSndBE,P_ON,LII / 2}   ,{WfaStaWaitStop,P_ON,LII / 2},{0,0,0},{0,0,0}}, 
+
+/* B.W*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndVI,P_ON,LII / 2}        ,{WfaStaSndVI,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* A.J*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVO,P_ON,LII / 2}   ,{WfaStaSndVO,P_OFF,LII / 2},{WfaStaWaitStop	,P_ON,LII / 2},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* M.V*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndBE,P_ON,LII / 2}        ,{WfaStaSndVI,P_ON,LII / 2}    ,{WfaStaWaitStop	,P_ON,LII / 2} ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* M.U*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+  {WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndBE,P_ON,LII / 2}        ,{WfaStaSnd2VO,P_ON,LII / 2}   ,{WfaStaWaitStop	,P_ON,LII / 2} ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* A.U*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,LII / 2}  ,{WfaStaSndBE,P_OFF,LII / 2}      ,{WfaStaSndBE,P_ON,LII / 2}    ,{WfaStaSndBE,P_OFF,LII / 2}   ,{WfaStaSndVO,P_ON,LII / 2}   ,{WfaStaSndVO,P_OFF,LII / 2} ,{WfaStaWaitStop ,P_ON,LII / 2},{0,0,0}},
+
+/* M.L*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndBE,P_ON,LII / 2}   ,{WfaStaWaitStop,P_ON,LII / 2}     ,{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* B.K*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndBE,P_ON,LII / 2}        ,{WfaStaSndVI,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* M.B*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVO,P_ON,LII / 2}   ,{WfaStaSndVI,P_ON,LII / 2}        ,{WfaStaSndBE,P_ON,LII / 2}     ,{WfaStaSndBK,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2} ,{0,0,0},{0,0,0},{0,0,0}},
+
+/* M.K*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndBE,P_ON,LII / 2}        ,{WfaStaSndVI,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+
+/* M.W*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,LII / 2}   ,{WfaStaSndBE,P_ON,LII / 2}        ,{WfaStaSndVI,P_ON,LII / 2}    ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}}
+#ifdef WFA_WMM_AC
+/* ATC1*/  ,{{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVO,P_ON,1000000}   ,{WfaStaWaitStop,P_ON,LII / 2}     ,{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+/* ATC2*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,1000000}   ,{WfaStaSndVO,P_ON,1000000}        ,{WfaStaSndBE,P_ON,1000000}    ,{WfaStaSndBE,P_ON,1000000}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* ATC3*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,becon_int}   ,{WfaStaSndVO,P_ON,1000000}      ,{WfaStaSndBE,P_ON,1000000}    ,{WfaStaSndBE,P_ON,1000000}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* ATC4*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,lis_int}   ,{WfaStaSndBE,P_ON,1000000}        ,{WfaStaSndVO,P_ON,1000000}    ,{WfaStaSndVO,P_ON,1}        ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* ATC5*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, 1},
+{WfaStaSndVI,P_ON,lis_int}   ,{WfaStaSndVO,P_ON,lis_int+2*becon_int}        ,{WfaStaSndVO,P_ON,becon_int}    ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+/* ATC6*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,becon_int}   ,{WfaStaSndVO,P_ON,lis_int}        ,{WfaStaSndVI,P_ON,becon_int}  ,{WfaStaSndVO,P_ON,becon_int}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* ATC7*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,becon_int}   ,{WfaStaSndVO,P_ON,lis_int}        ,{WfaStaSndVI,P_ON,becon_int}  ,{WfaStaSndVO,P_ON,becon_int}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* ATC8*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVO,P_ON,lis_int}   ,{WfaStaSndVI,P_ON,lis_int+2*becon_int}        ,{WfaStaSndVI,P_ON,becon_int}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+/* ATC9*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndBE,P_ON,becon_int}   ,{WfaStaSndVO,P_ON,lis_int}        ,{WfaStaSndBE,P_ON,becon_int}  ,{WfaStaSndVI,P_ON,becon_int}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* ATC10*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,becon_int}   ,{WfaStaSndBE,P_ON,lis_int}        ,{WfaStaSndVI,P_ON,becon_int}  ,{WfaStaSndBE,P_ON,becon_int}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* ATC11*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndBE,P_ON,becon_int}   ,{WfaStaSndVI,P_ON,lis_int}        ,{WfaStaSndBE,P_ON,becon_int}  ,{WfaStaSndVO,P_ON,lis_int}  ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0}},
+/* STC1*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,becon_int}   ,{WfaStaSndBE,P_ON,1000000}        ,{WfaStaSndVI,P_ON,1000000}    ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+/* STC2*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,becon_int}   ,{WfaStaSndBE,P_ON,1000000}        ,{WfaStaSndVO,P_ON,1000000}    ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
+/* STC3*/  {{WfaStaSndHello,P_OFF, 1000000},{WfaStaSndConfirm,P_ON, LII / 2},
+{WfaStaSndVI,P_ON,becon_int}   ,{WfaStaSndVI,P_ON,becon_int}        ,{WfaStaSndVI,P_ON,becon_int} ,{WfaStaWaitStop,P_ON,LII / 2}  ,{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}
+#endif
+
+};
+
+int ac_seq[APTS_LAST][6] ={
+   {0,      0,      0,      0,      0},
+   {0},
+   {0},
+   {0},
+   {0},
+   {0},
+   {0},
+   {0},
+   {0},
+   {0},
+   {0}, // APTS_TESTS
+   {0}, // B.D
+   {0}, // B.2
+   {0}, // B.H
+   {0}, // B.4
+   {0}, // B_5
+   {0, 0, 0, 0, 0}, // B_6
+   {TG_WMM_AC_VO, TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_BK, 0}, // B.B B_B - 4 exchanges: 1 uplink, 0 downlink
+   {0}, // B.E
+   {0}, // B.G
+   {0}, // B.I
+   {0}, // M.D
+   {0}, // M.G
+   {0}, // M.I
+   {0}, // B.Z  1, 1, 1, 0},	// 1 special exchange for Broadcast testing
+   {TG_WMM_AC_VI, TG_WMM_AC_VO, TG_WMM_AC_BE, TG_WMM_AC_BE, 0}, //  M.Y  M_Y 2 special exchange for Broadcast testing
+   {0}, // L.1
+   {0}, // DLOAD
+   {0}, // ULOAD
+   {0}, // "APTS PASS"
+   {0}, // "APTS FAIL"
+   //{TOS_VI, TOS_VO, TOS_BE, TOS_BE, 0}, //  A.Y A_Y special exchange for Broadcast testing
+   {TG_WMM_AC_VI, TG_WMM_AC_VO, TG_WMM_AC_BE, TG_WMM_AC_BE, TG_WMM_AC_BE}, //  A.Y A_Y special exchange for Broadcast testing
+   {0}, //  B.W  2 special exchange for Broadcast testing
+   {0}, //  A.J
+   {TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_VI, TG_WMM_AC_VI, TG_WMM_AC_VI}, //  M.V M_V
+   {TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_VO, TG_WMM_AC_VO, TG_WMM_AC_VO}, //  M.U M_U
+   {TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_BE, TG_WMM_AC_BE, TG_WMM_AC_VO, TG_WMM_AC_VO},  //  A.U A_U
+   {0}, //  M.L M_L
+   {TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_VI, TG_WMM_AC_VI, 0}, // B.K B_K
+   {TG_WMM_AC_VO, TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_BK, 0}, // M.B M_B - 4 exchanges: 1 uplink, 0 downlink
+   {TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_VI, TG_WMM_AC_VI, 0}, // M.K M_K
+   {TG_WMM_AC_VI, TG_WMM_AC_BE, TG_WMM_AC_VI, TG_WMM_AC_VI, 0} //  M.W M_W   special exchange for Broadcast testing
+};
+/* Generic function to create a meassage, it also fills in the AC as part of
+** the payload
+** */
+void create_apts_msg(int msg, unsigned int txbuf[],int id)
+{
+	struct apts_msg *t;
+
+	t = &apts_msgs[msg];
+	txbuf[ 0] = wmmps_info.my_cookie;
+	txbuf[ 1] = wmmps_info.dscp;
+	txbuf[ 2] = 0;
+	txbuf[ 3] = 0;
+	txbuf[ 4] = 0;
+	txbuf[ 5] = 0; 
+	//txbuf[ 6] = t->param0; 
+	//txbuf[ 7] = t->param1; 
+	//txbuf[ 8] = t->param2; 
+	txbuf[ 9] = id;
+	txbuf[ 10] = t->cmd; 
+	strcpy((char *)&txbuf[11], t->name);
+	PRINTF("create_apts_msg (%s) %d\n", t->name,t->cmd);
+}
+
+void print_hex_string(char* buf, int len)
+{
+    int i;
+
+    if (len==0) { printf("<empty string>"); return; }
+
+    for (i = 0; i < len; i++) {
+        printf("%02x ", *((unsigned char *)buf + i));
+	if ((i&0xf)==15) printf("\n   ");
+    }
+    if ((i&0xf))
+	printf("\n");
+}
+
+/* trace print*/
+void mpx(char *m, void *buf_v, int len)
+{
+    char *buf = buf_v;
+
+    printf("%s   MSG: %s\n   ", m, &buf[44] );
+    print_hex_string(buf, len);
+}
+
+/* function to validate the AC of the payload recd to ensure the correct
+** message sequence*/
+int receiver(unsigned int *rmsg,int length,int tos,unsigned int type)
+{
+	int r=1;
+	int new_dscp=rmsg[1];
+
+	if((new_dscp != tos)||(rmsg[10] != type)) {
+		PRINTF("\r\n dscp recd is %d msg type is %d\n",new_dscp,rmsg[10]);
+		r=-6;
+	}
+	return r;
+}
+
+/* WfaRcvProc: This function receives the test case name
+** after sending the initial hello packet, on receiving a
+** valid test case it advances onto the next receive state
+*/
+int WfaRcvProc(unsigned int *rmsg,int length,int *state)
+{
+	int sta_test;
+	int usedThread = wmmps_info.ps_thread;
+	num_hello=0;
+	sta_test = wmmps_info.sta_test = rmsg[10];
+	mpx("STA recv\n", rmsg, 64);
+	if(!((sta_test >=B_D)&&(sta_test <= LAST_TEST)))
+		return -1;
+	wmmps_info.my_sta_id = rmsg[9];
+	/* Pthread mutex Lock & Unlock mechanisms are only used in case of Linux 
+	 * since Linux uses six threads for WMM to 3 RX and 3 TX. This is as per the 
+	 * original design of Wifi. The same threads are used for WMMPS recv.
+	 * In case of Win CE for WMMPS we create a single thread that does wmmps recv.
+	 * For WMM the threads are created dynamically based on the no of streams.
+	 */
+#ifndef WIN32
+	pthread_mutex_lock(&wmm_thr[usedThread].thr_flag_mutex);
+#endif /*!WIN32 */
+
+	wmm_thr[usedThread].thr_flag = wmmps_info.streamid;
+
+#ifndef WIN32
+	pthread_mutex_unlock(&wmm_thr[usedThread].thr_flag_mutex);
+#endif /*!WIN32 */
+
+	(*state)++;
+
+	return 0;
+}
+
+/* WfaStaResetAll: This function resets the whole communication with
+** the console (in the event of a wrong message received for the test case)
+** resulting into resending of all the packets from the scratch, there is an
+** upper bound for the resets a max of three*/
+void WfaStaResetAll()
+{
+	int r;
+	PRINTF("Entering Reset\n");
+	num_retry++;
+	if(num_retry > MAXRETRY)
+	{
+		create_apts_msg(APTS_RESET_STOP, psTxMsg,wmmps_info.my_sta_id);
+		wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
+		r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+		mpx("STA msg",psTxMsg,64);
+		printf("Too many retries\n");
+		exit(-8);
+	}
+	if(!reset_recd)
+	{
+		create_apts_msg(APTS_RESET, psTxMsg,wmmps_info.my_sta_id);
+		wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
+		psTxMsg[1] = TOS_BE;
+		r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+		mpx("STA msg",psTxMsg,64);
+	}
+	else
+	{
+		create_apts_msg(APTS_RESET_RESP, psTxMsg,wmmps_info.my_sta_id);
+		wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
+		r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+		mpx("STA msg",psTxMsg,64);
+		reset_recd=0;
+	}
+
+	resetsnd=1;
+	resetrcv=1;
+}
+
+/* WfaRcvVO: A function expected to receive a AC_VO packet from
+** the console, if it does not reeive a valid VO, it prints out 
+** an error message*/
+int WfaRcvVO(unsigned int *rmsg,int length,int *state)
+{
+    int r;
+
+	if ((r=receiver(rmsg,length,TOS_VO,APTS_DEFAULT))>=0)
+        (*state)++;
+    else
+    {
+        PRINTF("\nBAD REC in VO%d\n",r);
+        //WfaStaResetAll();
+    }
+    return 0;
+}
+
+/* WfaRcvVI: A function expected to receive a AC_VI packet from
+** the console, if does not reeive a valid VI it prints out 
+** an error message. 
+*/
+
+int WfaRcvVI(unsigned int *rmsg,int length,int *state)
+{
+    int r;
+
+    if ((r=receiver(rmsg,length,TOS_VI,APTS_DEFAULT))>=0)
+        (*state)++;
+    else
+        PRINTF("\nBAD REC in VI%d\n",r);
+
+    return 0;
+}
+
+/* WfaRcvBE: A function expected to receive a AC_BE packet from
+** the console, if does not reeive a valid BE it prints out 
+** an error message
+*/
+
+int WfaRcvBE(unsigned int *rmsg,int length,int *state)
+{
+    int r;
+    if ((r=receiver(rmsg,length,TOS_BE,APTS_DEFAULT))>=0)
+        (*state)++;
+    else
+    {
+        PRINTF("\nBAD REC in BE%d\n",r);
+    }
+    return 0;
+}
+
+/* WfaRcvBK: A function expected to receive a AC_BK packet from
+** the console, if does not reeive a valid BK it prints out 
+** an error message
+*/
+
+int WfaRcvBK(unsigned int *rmsg,int length,int *state)
+{
+    int r;
+
+    if ((r=receiver(rmsg,length,TOS_BK,APTS_DEFAULT))>=0)
+        (*state)++;
+    else
+        PRINTF("\nBAD REC in BK%d\n",r);
+
+    return 0;
+}
+
+void BUILD_APTS_MSG(int msg, unsigned long *txbuf)
+{   
+    struct apts_msg *t;
+
+    t = &apts_msgs[msg];
+    txbuf[0] = wmmps_info.msgno++;
+    txbuf[1] = 0;
+    txbuf[2] = 0;
+    txbuf[3] = 0;
+    txbuf[4] = 0;
+    txbuf[5] = 0;
+    txbuf[6] = t->param0;
+    txbuf[7] = t->param1;
+    txbuf[8] = t->param2;
+    txbuf[9] = t->param3;
+    txbuf[10] = t->cmd;
+    strcpy((char *)&txbuf[11], t->name); 
+}
+
+void send_txmsg(int new_prio_class)
+{
+	int r;
+	int new_dscp = 0;
+
+	if(new_prio_class > -1)
+		new_dscp = wfaTGSetPrio(psSockfd, new_prio_class);
+
+	psTxMsg[0] = wmmps_info.msgno++;
+	psTxMsg[1] = new_dscp;
+	psTxMsg[2] = wmmps_info.my_group_cookie;
+	psTxMsg[3] = wmmps_info.my_cookie;
+	psTxMsg[4] = wmmps_info.my_sta_id;
+
+	if(psTxMsg[10] == APTS_DEFAULT)
+	{
+		psTxMsg[13] = (wmmps_info.msgno%10) + 0x20202030; 
+	}
+
+	r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, 200+(wmmps_info.msgno%200), (struct sockaddr *) &wmmps_info.psToAddr);
+	wmmps_info.nsent++;
+}
+
+/*
+ * This needs to adopt to the specific platform you port to.
+ */
+void wfaSetDUTPwrMgmt(int mode)
+{
+	static int curr_mode;
+
+	if(curr_mode == mode)
+	{
+		return;
+	}
+	wl_set (g_wl_handle,WLC_SET_PM,&mode,sizeof(int));
+
+	curr_mode = mode;
+}
+
+int wfaWmmPowerSaveProcess(int sockfd)
+{
+	int rbytes = 0;
+	int sta_test;
+	struct sockaddr from;
+	int len;
+	StationRecvProcStatetbl_t  *rcvstatarray;
+	StationRecvProcStatetbl_t  func;
+	int *rcv_state;
+	len=sizeof(from);
+	rbytes = WmmpsTrafficRecv(sockfd,(char *)psRxMsg, (struct sockaddr *)&from);
+	if(rbytes < 0)
+	{
+		p_error("receive error");
+		return rbytes;
+	}
+	sta_test = wmmps_info.sta_test;
+	if(sta_test != L_1)
+		mpx("RX msg",psRxMsg,64);
+	if(psRxMsg[10] == APTS_STOP)
+		PRINTF("\r\n stop recd\n");
+	if(psRxMsg[10] == APTS_RESET)
+	{
+		reset_recd=1;
+		//wmmps_info.ps_thread = 1;
+		WfaStaResetAll();
+		return 0;
+	}
+	//If reset signal is there for the receiving thread and station has sent the
+	//reset message (i.e. !reset_recd) then ignore all the messages till an
+	//APTS_RESET_RESP has been received.
+
+	if(resetrcv)
+	{
+		wmmps_info.rcv_state = 0;
+		if((!reset_recd)&&(psRxMsg[10] != APTS_RESET_RESP))
+			return 0;
+		else
+		{
+			resetrcv = 0;
+			reset_recd = 0;
+		}
+	}
+	sta_test = wmmps_info.sta_test;
+	wmmps_info.my_cookie = psRxMsg[0];
+	rcv_state = &(wmmps_info.rcv_state);
+	rcvstatarray = stationRecvProcStatetbl[sta_test];
+	func = rcvstatarray[*(rcv_state)];
+	func.statefunc(psRxMsg,rbytes,rcv_state);
+	return TRUE;
+}
+
+void wmmps_wait_state_proc()
+{
+	int ttypes[4], i, rbytes;
+
+	for(i = 0; i<4; i++)
+	{
+		ttypes[i] = 0xFF;
+	}
+
+	switch(wmmps_info.wait_state)
+	{
+	case WFA_WAIT_NEXT_CODEC:
+		ttypes[0] = -1;
+		wmmps_info.wait_state = WFA_WAIT_NEXT_CODEC;
+		break;
+
+	case WFA_WAIT_FOR_AP_RESPONSE:
+		wmmps_info.wait_state = WFA_WAIT_NEXT_CODEC;
+		break;
+
+	case WFA_WAIT_STAUT_00:
+		rbytes = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, 200+(wmmps_info.msgno%200), (struct sockaddr *)&wmmps_info.psToAddr);
+		wmmps_info.nextsleep = 1000000;   /* one second */
+		break;
+
+	case WFA_WAIT_STAUT_02:
+		ttypes[0] = TOS_VO;
+		wmmps_info.nextsleep = 1000000;  // 1 sec 
+		return;
+		break;
+
+	case WFA_WAIT_STAUT_04:
+		ttypes[0] = TOS_BE;
+		ttypes[1] = TOS_VO;
+		break;
+
+	case WFA_WAIT_STAUT_0E:
+		ttypes[0] = TOS_VO;
+		ttypes[1] = TOS_VO;
+		break;
+
+	case WFA_WAIT_STAUT_VOLOAD:
+		ttypes[0] = TOS_VO;
+		break;
+
+	case WFA_WAIT_STAUT_SEQ:
+		if( wmmps_info.nsent < 0 || wmmps_info.nsent > sizeof(ac_seq[wmmps_info.sta_test]) )
+			wmmps_info.nsent = 0;
+
+		if(( wmmps_info.sta_test == A_Y && wmmps_info.nsent == 3)
+			|| (wmmps_info.sta_test == A_U && wmmps_info.nsent == 1)
+			|| (wmmps_info.sta_test == A_U && wmmps_info.nsent == 3)
+			|| (wmmps_info.sta_test == A_U && wmmps_info.nsent == 5))
+		{
+			wfaSetDUTPwrMgmt(PS_OFF);
+			wmmps_info.nextsleep = 100000;   // 100 ms
+		}
+
+		if((wmmps_info.sta_test == A_Y && wmmps_info.nsent == 4)
+			|| (wmmps_info.sta_test == A_U && wmmps_info.nsent == 2)
+			|| (wmmps_info.sta_test == A_U && wmmps_info.nsent == 4))
+		{
+			wfaSetDUTPwrMgmt(PS_ON);
+			wmmps_info.nextsleep = 100000;   // 100 ms
+		}
+
+		ttypes[0] = ac_seq[wmmps_info.sta_test][wmmps_info.nsent];
+		printf("ttypes 0x%x\n", ttypes[0]);
+
+		// do we need sample time for one sec?
+		wmmps_info.nextsleep = 1000000;
+		break;
+
+	default:
+		printf("unknown wait state\n");
+	}
+
+	i=0;
+	while(ttypes[i] != 0xFF)
+		send_txmsg(ttypes[i++]);
+}
+#endif /* WFA_WMM_PS_EXT */
+#endif /* WFA_WMM_EXT    */
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_wmmps_linux.c b/src/tools/Wifi_ASD_test/lib/wfa_wmmps_linux.c
new file mode 100755
index 0000000..b810e07
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_wmmps_linux.c
@@ -0,0 +1,398 @@
+/*
+* Windows port of asd command line utility
+*
+* Copyright 2002, Broadcom Corporation
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+* the contents of this file may not be disclosed to third parties, copied or
+* duplicated in any form, in whole or in part, without the prior written
+* permission of Broadcom Corporation.
+*
+*/
+
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+
+#include "wfa_sock.h"
+#include "wfa_types.h"
+#include "wfa_tg.h"
+#include "wfa_ca.h"
+#include "wfa_wmmps.h"
+#include "wfa_miscs.h"
+#include "wfa_main.h"
+#include "wfa_debug.h"
+#include "wfa_tlv.h"
+
+extern int psSockfd;
+extern int msgsize;
+extern int resetsnd;
+extern int gtgWmmPS;
+extern int num_stops;
+extern int num_hello;
+extern tgWMM_t wmm_thr[];
+extern wfaWmmPS_t wmmps_info;
+extern unsigned int psTxMsg[512];
+tgThrData_t tdata[WFA_THREADS_NUM]; 
+
+extern void tmout_stop_send(int num);
+extern void wfaSetDUTPwrMgmt(int mode);
+extern void wfaSetThreadPrio(int tid, int class);
+extern void mpx(char *m, void *buf_v, int len);
+extern int wfaTGSetPrio(int sockfd, int tgClass);
+extern tgStream_t *findStreamProfile(int id);
+extern StationProcStatetbl_t stationProcStatetbl[LAST_TEST+1][11];
+extern int receiver(unsigned int *rmsg,int length,int tos,unsigned int type);
+
+/* WfaRcvVOCyclic: This is meant for the L1 test case. The function
+** receives the VO packets from the console */
+int WfaRcvVOCyclic(unsigned int *rmsg,int length,int *state)
+{
+	int r;
+	tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
+
+	if(rmsg[10] != APTS_STOP)
+	{
+		if ((r=receiver(rmsg,length,TOS_VO,APTS_DEFAULT))>=0);
+		else
+			PRINTF("\nBAD REC in VO%d\n",r);
+	}
+	else
+	{
+		pthread_mutex_lock(&my_wmm->thr_stop_mutex);
+		while(!my_wmm->stop_flag)
+		{
+			pthread_cond_wait(&my_wmm->thr_stop_cond, &my_wmm->thr_stop_mutex);
+		}
+		pthread_mutex_unlock(&my_wmm->thr_stop_mutex);
+		my_wmm->stop_flag = 0;
+		gtgWmmPS = 0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+		signal(SIGALRM, SIG_IGN);
+		wfaSetDUTPwrMgmt(PS_OFF);
+		uapsd_sleep(1);
+	}
+
+	return 0;
+}
+/* WfaRcvStop: This function receives the stop message from the
+** console, it waits for the sending thread to have sent the stop before
+** quitting*/
+int WfaRcvStop(unsigned int *rmsg,int length,int *state)
+{
+	tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
+
+	my_wmm->stop_flag = 0;
+	PRINTF("\r\nEnterring Wfarcvstop\n");
+	if(rmsg[10] != APTS_STOP)
+	{
+		//PRINTF("\nBAD REC in rcvstop%d\n",r);
+		//WfaStaResetAll();
+	}
+	else
+	{
+		pthread_mutex_lock(&my_wmm->thr_stop_mutex);
+		while(!my_wmm->stop_flag)
+		{
+			printf("\r\n stuck\n");
+			pthread_cond_wait(&my_wmm->thr_stop_cond, &my_wmm->thr_stop_mutex);
+		}
+		num_stops=0;
+		pthread_mutex_unlock(&my_wmm->thr_stop_mutex);
+		my_wmm->stop_flag = 0;
+		gtgWmmPS = 0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+		signal(SIGALRM, SIG_IGN);
+		wfaSetDUTPwrMgmt(PS_OFF);
+		uapsd_sleep(1);
+	}
+	return 0;
+}
+
+
+/*
+* wfaStaSndHello(): This function sends a Hello packet 
+*                and sleeps for sleep_period, the idea is
+*                to keep sending hello packets till the console
+*                responds, the function keeps a check on the MAX
+*                Hellos and if number of Hellos exceed that it quits
+*/
+int WfaStaSndHello(char psave,int sleep_period,int *state)
+{
+	int r;
+	tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
+	if(!(num_hello++))
+		create_apts_msg(APTS_HELLO, psTxMsg,0);
+
+	r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+	uapsd_sleep(sleep_period);
+	pthread_mutex_lock(&my_wmm->thr_flag_mutex);
+	if(my_wmm->thr_flag)
+	{
+		(*state)++;
+		num_hello=0;
+		my_wmm->thr_flag=0;
+	}
+	pthread_mutex_unlock(&my_wmm->thr_flag_mutex);
+	if(num_hello > MAXHELLO)
+	{
+		DPRINT_ERR(WFA_ERR, "Too many Hellos sent\n");
+		gtgWmmPS = 0;
+		num_hello=0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+		signal(SIGALRM, SIG_IGN);
+	} 
+	return 0;
+}
+
+/*
+* WfaStaWaitStop(): This function sends the stop packet on behalf of the
+*                   station, the idea is to keep sending the Stop
+*                   till a stop is recd from the console,the functions
+*                   quits after stop threshold reaches.
+*/
+int WfaStaWaitStop(char psave,int sleep_period,int *state)
+{
+	int r;
+	int myid=wmmps_info.ps_thread;
+	PRINTF("\n Entering Sendwait");
+	uapsd_sleep(sleep_period);
+	if(!num_stops)
+	{
+		wfaSetDUTPwrMgmt(psave);
+		wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
+	}
+
+	num_stops++;
+	create_apts_msg(APTS_STOP, psTxMsg,wmmps_info.my_sta_id);
+	r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+	mpx("STA msg",psTxMsg,64);
+
+	wmm_thr[myid].stop_flag = 1;
+	pthread_mutex_lock(&wmm_thr[myid].thr_stop_mutex);
+	pthread_cond_signal(&wmm_thr[myid].thr_stop_cond);
+	pthread_mutex_unlock(&wmm_thr[myid].thr_stop_mutex);
+	if(num_stops > MAX_STOPS)
+	{
+		DPRINT_ERR(WFA_ERR, "Too many stops sent\n");
+		gtgWmmPS = 0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+		signal(SIGALRM, SIG_IGN);
+	}
+	wfaSetDUTPwrMgmt(PS_OFF);
+	return 0;
+}
+
+void * wfa_wmm_thread(void *thr_param)
+{
+	int myId = ((tgThrData_t *)thr_param)->tid;
+	tgWMM_t *my_wmm = &wmm_thr[myId];
+	tgStream_t *myStream = NULL;
+	tgThrData_t *tdata =(tgThrData_t *) thr_param;
+	int myStreamId;
+	int mySock = -1; 
+	int status, respLen;
+	tgProfile_t *myProfile;
+	StationProcStatetbl_t  curr_state;
+
+	BYTE respBuf[WFA_BUFF_1K];
+	pthread_attr_t tattr;
+
+	pthread_attr_init(&tattr);
+	pthread_attr_setschedpolicy(&tattr, SCHED_RR);
+	while(1)
+	{
+		pthread_mutex_lock(&my_wmm->thr_flag_mutex);
+		/* it needs to reset the thr_flag to wait again */
+		while(!my_wmm->thr_flag)
+		{
+			/*
+			* in normal situation, the signal indicates the thr_flag changed to
+			* a valid number (stream id), then it will go out the loop and do
+			* work.
+			*/
+			pthread_cond_wait(&my_wmm->thr_flag_cond, &my_wmm->thr_flag_mutex);
+		}
+		sleep(2);
+		pthread_mutex_unlock(&my_wmm->thr_flag_mutex);
+
+		myStreamId = my_wmm->thr_flag;
+		my_wmm->thr_flag = 0;
+		/* use the flag as a stream id to file the profile */
+		myStream = findStreamProfile(myStreamId);
+		myProfile = &myStream->profile;
+
+		if(myProfile == NULL)
+		{
+			status = STATUS_INVALID;
+			wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&status, respBuf);
+			respLen = WFA_TLV_HDR_LEN+4;
+			/*
+			* send it back to control agent.
+			*/
+			continue;
+		}
+
+		switch(myProfile->direction)
+		{
+		case DIRECT_SEND:
+			mySock = wfaCreateUDPSock(myProfile->sipaddr, myProfile->sport);
+			mySock = wfaConnectUDPPeer(mySock, myProfile->dipaddr, myProfile->dport);
+			/*
+			* Set packet/socket priority TOS field
+			*/
+			wfaTGSetPrio(mySock, myProfile->trafficClass);
+
+			/*
+			* set a proper priority
+			*/
+			wfaSetThreadPrio(myId, myProfile->trafficClass);
+#ifdef DEBUG
+			printf("wfa_wmm_thread: myProfile->startdelay %i\n", myProfile->startdelay);
+#endif /* DEBUG */
+			/* if delay is too long, it must be something wrong */
+			if(myProfile->startdelay > 0 && myProfile->startdelay < 50)
+			{
+				asd_sleep(myProfile->startdelay);
+			}
+
+			/*
+			* set timer fire up
+			*/
+			signal(SIGALRM, tmout_stop_send);
+			alarm(myProfile->duration);
+
+			/* Whenever frameRate is 0,sending data at the maximum possible rate */	
+			if (myProfile->rate != 0) 
+				wfaSendLongFile(mySock, myStreamId, respBuf, &respLen );
+			else
+				wfaImprovePerfSendLongFile(mySock, myStreamId, respBuf, &respLen );
+
+			memset(respBuf, 0, WFA_BUFF_1K);
+			if (mySock != -1) {
+				asd_closeSocket(mySock);
+				mySock = -1;
+			}
+
+			/*
+			* uses thread 0 to pack the items and ships it to CA.
+			*/
+			if(myId == 0) {
+				//		wfaSentStatsResp(gxcSockfd, respBuf);
+				printf("respBuf = %s    sent from thr\n", respBuf);
+			}
+			break;
+
+		case DIRECT_RECV:
+#ifdef WFA_WMM_PS_EXT
+			if(myProfile->profile == PROF_UAPSD)
+			{
+				wmmps_info.sta_test = B_D;
+				wmmps_info.ps_thread = myId;
+				wmmps_info.rcv_state = 0;
+				wmmps_info.tdata = tdata;
+				wmmps_info.dscp = wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
+				tdata->state_num=0;
+				/*
+				* default timer value
+				*/
+
+				while(gtgWmmPS>0)
+				{
+					if(resetsnd)
+					{
+						tdata->state_num = 0;
+						resetsnd = 0;
+					}
+
+					tdata->state =  stationProcStatetbl[wmmps_info.sta_test];
+					curr_state = tdata->state[tdata->state_num];
+					curr_state.statefunc(curr_state.pw_offon,curr_state.sleep_period,&(tdata->state_num));
+				}
+			}
+			break;
+#endif /* WFA_WMM_PS_EXT */
+		default:
+			DPRINT_ERR(WFA_ERR, "Unknown covered case\n");
+		}
+	}
+}
+
+void init_thr_flag()
+{
+	int cntThr = 0;
+	pthread_attr_t ptAttr;
+	int ptPolicy;
+
+	struct sched_param ptSchedParam;
+	pthread_attr_init(&ptAttr);
+
+	ptSchedParam.sched_priority = 10;
+	pthread_attr_setschedparam(&ptAttr, &ptSchedParam);
+	pthread_attr_getschedpolicy(&ptAttr, &ptPolicy);
+	pthread_attr_setschedpolicy(&ptAttr, SCHED_RR);
+	pthread_attr_getschedpolicy(&ptAttr, &ptPolicy);
+	/*
+	* Create multiple threads for WMM Stream processing.
+	*/
+	for(cntThr = 0; cntThr< WFA_THREADS_NUM; cntThr++)
+	{
+		tdata[cntThr].tid = cntThr;
+		pthread_mutex_init(&wmm_thr[cntThr].thr_flag_mutex, NULL);
+		pthread_cond_init(&wmm_thr[cntThr].thr_flag_cond, NULL);
+
+		wmm_thr[cntThr].thr_id = pthread_create(&wmm_thr[cntThr].thr,
+			&ptAttr, wfa_wmm_thread, &tdata[cntThr]);
+
+		sleep(1);
+		wmm_thr[cntThr].thr_flag = 0;
+	}
+}
+
+/*
+ * wfaSetThreadPrio():
+ *    Set thread priorities
+ *    It is an optional experiment if you decide not necessary.
+ */
+void wfaSetThreadPrio(int tid, int class)
+{
+	struct sched_param tschedParam;
+	pthread_attr_t tattr;
+	pthread_attr_init(&tattr);
+	pthread_attr_setschedpolicy(&tattr, SCHED_RR);
+
+	switch(class)
+	{
+	case TG_WMM_AC_BK:
+		tschedParam.sched_priority = 70-3;
+		break;
+	case TG_WMM_AC_VI:
+		tschedParam.sched_priority = 70-1;
+		break;
+	case TG_WMM_AC_VO:
+		tschedParam.sched_priority = 70;
+		break;
+	case TG_WMM_AC_BE:
+		tschedParam.sched_priority = 70-2;
+	default:
+		/* default */
+		;
+	}
+
+	pthread_attr_setschedparam(&tattr, &tschedParam);
+}
+
+int WmmpsTrafficRecv(int sock, char *buf, struct sockaddr *from)
+{
+	int bytesRecvd;
+	socklen_t  addrLen;
+	bytesRecvd = recvfrom(sock, buf, MAX_UDP_LEN, 0, from, &addrLen);
+	return bytesRecvd;
+}
diff --git a/src/tools/Wifi_ASD_test/lib/wfa_wmmps_win32.c b/src/tools/Wifi_ASD_test/lib/wfa_wmmps_win32.c
new file mode 100755
index 0000000..ecc1fc1
--- /dev/null
+++ b/src/tools/Wifi_ASD_test/lib/wfa_wmmps_win32.c
@@ -0,0 +1,237 @@
+/*
+ * Windows port of asd command line utility
+ *
+ * Copyright 2002, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied or
+ * duplicated in any form, in whole or in part, without the prior written
+ * permission of Broadcom Corporation.
+ *
+ */
+
+#include "wfa_sock.h"
+#include "wfa_types.h"
+#include "wfa_tg.h"
+#include "wfa_ca.h"
+#include "wfa_wmmps.h"
+#include "wfa_miscs.h"
+#include "wfa_main.h"
+#include "wfa_debug.h"
+
+extern int psSockfd;
+extern int msgsize;
+extern int resetsnd;
+extern int gtgWmmPS;
+extern int num_stops;
+extern int num_hello;
+extern tgWMM_t wmm_thr[];
+tgThrData_t tdata[WFA_THREADS_NUM]; 
+extern HANDLE thr_flag_cond;
+extern HANDLE thr_stop_cond;
+extern wfaWmmPS_t wmmps_info;
+extern unsigned int psTxMsg[512];
+
+extern void wfaSetDUTPwrMgmt(int mode);
+extern void mpx(char *m, void *buf_v, int len);
+extern int wfaTGSetPrio(int sockfd, int tgClass);
+extern StationProcStatetbl_t stationProcStatetbl[LAST_TEST+1][11];
+extern int receiver(unsigned int *rmsg,int length,int tos,unsigned int type);
+
+/* WfaRcvVOCyclic: This is meant for the L1 test case. The function
+** receives the VO packets from the console */
+int WfaRcvVOCyclic(unsigned int *rmsg,int length,int *state)
+{
+	int r;
+	tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
+
+	if(rmsg[10] != APTS_STOP)
+	{
+		if ((r=receiver(rmsg,length,TOS_VO,APTS_DEFAULT))>=0);
+		else
+			PRINTF("\nBAD REC in VO%d\n",r);
+	}
+	else
+	{
+		while(!my_wmm->stop_flag)
+		{
+			while(WaitForSingleObject(thr_stop_cond, 0)!=WAIT_OBJECT_0);
+		}
+		ResetEvent(thr_stop_cond);
+		my_wmm->stop_flag = 0;
+		gtgWmmPS = 0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+		wfaSetDUTPwrMgmt(PS_OFF);
+		uapsd_sleep(1);
+	}
+	return 0;
+}
+
+
+/* WfaRcvStop: This function receives the stop message from the
+** console, it waits for the sending thread to have sent the stop before
+** quitting*/
+int WfaRcvStop(unsigned int *rmsg,int length,int *state)
+{
+	tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
+	my_wmm->stop_flag = 0;
+	PRINTF("\r\nEnterring Wfarcvstop\n");
+	if(rmsg[10] != APTS_STOP)
+	{
+		//PRINTF("\nBAD REC in rcvstop%d\n",r);
+		//WfaStaResetAll();
+	}
+	else
+	{
+		while(!my_wmm->stop_flag)
+		{
+			while(WaitForSingleObject(thr_stop_cond, 0)!=WAIT_OBJECT_0);
+		}
+		num_stops=0;
+		ResetEvent(thr_stop_cond);
+		my_wmm->stop_flag = 0;
+		gtgWmmPS = 0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+		wfaSetDUTPwrMgmt(PS_OFF);
+		uapsd_sleep(1);
+	}
+	return 0;
+}
+
+/*
+ * wfaStaSndHello(): This function sends a Hello packet 
+ *                and sleeps for sleep_period, the idea is
+ *                to keep sending hello packets till the console
+ *                responds, the function keeps a check on the MAX
+ *                Hellos and if number of Hellos exceed that it quits
+ */
+int WfaStaSndHello(char psave,int sleep_period,int *state)
+{
+	int r;
+	tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
+	if(!(num_hello++))
+		create_apts_msg(APTS_HELLO, psTxMsg,0);
+
+	r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+	uapsd_sleep(sleep_period);
+	if(my_wmm->thr_flag)
+	{
+		(*state)++;
+		num_hello=0;
+		my_wmm->thr_flag=0;
+	}
+	if(num_hello > MAXHELLO)
+	{
+		DPRINT_ERR(WFA_ERR, "Too many Hellos sent\n");
+		gtgWmmPS = 0;
+		num_hello=0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+	} 
+	return 0;
+}
+
+/*
+ * WfaStaWaitStop(): This function sends the stop packet on behalf of the
+ *                   station, the idea is to keep sending the Stop
+ *                   till a stop is recd from the console,the functions
+ *                   quits after stop threshold reaches.
+ */
+int WfaStaWaitStop(char psave,int sleep_period,int *state)
+{
+	int r;
+	int myid=wmmps_info.ps_thread;
+	PRINTF("\n Entering Sendwait");
+	uapsd_sleep(sleep_period);
+	if(!num_stops)
+	{
+		wfaSetDUTPwrMgmt(psave);
+		wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
+	}
+
+	num_stops++;
+	create_apts_msg(APTS_STOP, psTxMsg,wmmps_info.my_sta_id);
+	r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
+	mpx("STA msg",psTxMsg,64);
+
+	wmm_thr[myid].stop_flag = 1;
+	SetEvent(thr_stop_cond);
+	if(num_stops > MAX_STOPS)
+	{
+		DPRINT_ERR(WFA_ERR, "Too many stops sent\n");
+		gtgWmmPS = 0;
+		asd_closeSocket(psSockfd);
+		psSockfd = -1;
+	}
+	wfaSetDUTPwrMgmt(PS_OFF);
+	return 0;
+}
+
+void Uapsd_Recv_Thread(LPVOID *thr_param)
+{
+	int myId = ((tgThrData_t *)thr_param)->tid;
+	tgWMM_t *my_wmm = &wmm_thr[myId];
+	tgStream_t *myStream = NULL;
+	tgThrData_t *tdata =(tgThrData_t *) thr_param;
+	StationProcStatetbl_t  curr_state;
+	while(!my_wmm->thr_flag)
+	{
+		while(WaitForSingleObject(thr_flag_cond, 0)!=WAIT_OBJECT_0);
+	}
+	ResetEvent(thr_flag_cond);
+	my_wmm->thr_flag = 0;
+	wmmps_info.sta_test = B_D;
+	wmmps_info.ps_thread = myId;
+	wmmps_info.rcv_state = 0;
+	wmmps_info.tdata = tdata;
+	wmmps_info.dscp = wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
+	tdata->state_num=0;
+	/*
+	* default timer value
+	*/
+	while(gtgWmmPS>0)
+	{
+		if(resetsnd)
+		{
+			tdata->state_num = 0;
+			resetsnd = 0;
+		}
+		tdata->state =  stationProcStatetbl[wmmps_info.sta_test];
+		curr_state = tdata->state[tdata->state_num];
+		curr_state.statefunc(curr_state.pw_offon,curr_state.sleep_period,&(tdata->state_num));
+	}
+
+}
+
+void init_wmmps_thr()
+{
+	int cntThr = 0;
+	DWORD UAPSDThread;
+	/*Create the thread event for multiple streams and hold the thread handles in the array*/
+	thr_flag_cond = CreateEvent(NULL, FALSE, TRUE, NULL);
+	thr_stop_cond = CreateEvent(NULL, FALSE, TRUE, NULL);
+	for(cntThr = 0; cntThr< 1; cntThr++)
+	{
+		tdata[cntThr].tid = cntThr;
+		wmm_thr[cntThr].thr_id = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Uapsd_Recv_Thread, (LPVOID) &tdata[cntThr], 0, &UAPSDThread);
+		if (wmm_thr[cntThr].thr_id == NULL){
+			printf("CreateThread Failed:%d\n",WSAGetLastError());
+		}
+		sleep(1);
+		wmm_thr[cntThr].thr_flag = 0;
+	}
+}
+
+int WmmpsTrafficRecv(int sock, char *buf, struct sockaddr *from)
+{
+	int bytesRecvd;
+	socklen_t  addrLen;
+	struct sockaddr_in recFrom;
+	memset(&recFrom, 0, sizeof(recFrom));
+	addrLen = sizeof(recFrom);
+	bytesRecvd = recvfrom(sock, buf, MAX_UDP_LEN, 0, (struct sockaddr *)&recFrom, &addrLen);
+	return bytesRecvd;
+}
diff --git a/src/tools/release/WLAN.usf b/src/tools/release/WLAN.usf
new file mode 100644
index 0000000..9b2ef12
--- /dev/null
+++ b/src/tools/release/WLAN.usf
@@ -0,0 +1,34 @@
+##
+## This is a common config file that is used mainly by modules
+## or brand makefiles. The ".usf" suffix stands for "universal
+## settings file". The important feature is that this file is
+## both legal makefile and shell syntax, and could be parsed as
+## a properties file by any language (Perl, Python, Java, ...)
+## which understands properties.
+##
+## Rules: Each line is either an assignment, a comment, or blank.
+## Assignments MUST be of the form "foo=bar" (no spaces) and
+## comments have a leading "#" character.
+##
+## It can be included by common templates like WLAN_Common.mk,
+## or by brand makefiles, or sourced by build scripts.
+##
+## $Id: WLAN.usf 429692 2013-10-15 19:51:40Z jqliu $
+##
+
+# Current list of components
+# This list is used in module makefiles to set vpath search
+# paths and include paths
+
+WLAN_COMPONENT_PATHS=src/shared/bcmwifi src/wl/clm src/wl/lwip src/wl/plqmr src/wl/ppr src/wl/rel_mcast src/wl/gas src/wl/encode src/wl/olpc src/wl/keymgmt src/wl/iocv src/wl/dump src/wl/phymods/cmn/hal src/wl/phymods
+
+# This is a staging area for generated content that need to be shared
+# between build step and packaging step. E.g when CLM data files
+# need to be packaged, they are first staged to $(WLAN_GEN_BASEDIR)
+# and packaged from there.
+
+WLAN_GEN_BASEDIR=generated
+
+# This is the conventional Windows mount point for network files.
+
+WLAN_WINPFX=Z:
diff --git a/src/tools/wlm/Makefile b/src/tools/wlm/Makefile
new file mode 100644
index 0000000..d351485
--- /dev/null
+++ b/src/tools/wlm/Makefile
@@ -0,0 +1,86 @@
+#
+# Makefile for mfgapi_test.cpp
+# $Id: Makefile 382637 2013-02-03 04:34:52Z $
+#
+#	There are total five options for make:
+#
+#		make		: This is to make mfgapi_test.exe, wlmSampleTests.exe, and wlm.lib
+#		make exe	: This is to make mfgapi_test.exe and wlmSampleTests.exe
+#		make lib	: This is to make wlm.lib only
+#		make clean	: This is to remove mfgtest_api.exe and wlmSampleTests.exe
+#		make cleanall	: This is to remove mfgtest_api.exe, wlmSampleTests.exe, wlm.lib and all of its object files
+#
+#
+
+UNAME = $(shell uname)
+
+SRCBASE = ../..
+WLM_DIR = wl/exe
+
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+TARGET_TEST = mfgapi_test.exe
+TARGET_SAMPLE = wlmSampleTests.exe
+WLM_LIB = wlm.lib
+WLM_DLL = wlm.dll
+REL_WLM_DIR = $(WLM_DIR)/obj/wlm/free
+WLM_MAKE = GNUmakefile.wlm_dll
+C_DEFINES += -mno-cygwin -DWIN32
+else
+TARGET_TEST = mfgapi_test
+TARGET_SAMPLE = wlmSampleTests
+WLM_LIB = wlm.so
+REL_WLM_DIR = $(WLM_DIR)/wlm/x86
+WLM_MAKE = GNUmakefile
+C_DEFINES += -DLINUX
+endif
+
+SOURCE = mfgapi_test.cpp
+SOURCE_SAMPLE = wlmSampleTests.c
+
+vpath %.h $(SRCBASE)/$(WLM_DIR)
+
+CC = gcc
+CXX = g++
+
+C_DEFINES += -Wall -Wextra -Werror
+ANSI_C90 = -ansi -pedantic
+
+INCLUDES = $(SRCBASE)/$(WLM_DIR) $(SRCBASE)/include $(SRCBASE)/common/include
+CPPFLAGS = $(patsubst %,-I%,$(subst ;, ,$(INCLUDES)))
+
+all: lib $(TARGET_SAMPLE)
+
+test: lib $(TARGET_TEST)
+
+lib: $(SRCBASE)/$(REL_WLM_DIR)/$(WLM_LIB)
+
+$(TARGET_TEST): $(SOURCE) wlm.h
+	@echo "Compiling - $(TARGET_TEST)"
+	$(CXX) $(C_DEFINES) $(CPPFLAGS) $(SOURCE) $(SRCBASE)/$(REL_WLM_DIR)/$(WLM_LIB) -o $(TARGET_TEST)
+
+$(SRCBASE)/$(REL_WLM_DIR)/$(WLM_LIB):
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+	$(MAKE) -C $(SRCBASE)/$(WLM_DIR) OTHER_SOURCES="" debug
+	$(MAKE) -C $(SRCBASE)/$(WLM_DIR) -f $(WLM_MAKE)
+	cp -f $(SRCBASE)/$(REL_WLM_DIR)/$(WLM_DLL) .
+else
+	$(MAKE) -C $(SRCBASE)/$(WLM_DIR) -f $(WLM_MAKE) wlm
+	cp -f $(SRCBASE)/$(REL_WLM_DIR)/$(WLM_LIB) .
+endif
+
+$(TARGET_SAMPLE): $(SOURCE_SAMPLE) wlm.h
+	@echo "Compiling - $(TARGET_SAMPLE)"
+	$(CC) $(C_DEFINES) $(CPPFLAGS) $(ANSI_C90) $(SOURCE_SAMPLE) $(SRCBASE)/$(REL_WLM_DIR)/$(WLM_LIB) -o $(TARGET_SAMPLE)
+
+clean:
+	rm -f $(TARGET_TEST) $(TARGET_SAMPLE)
+
+cleanall:
+	rm -f $(TARGET_TEST) $(TARGET_SAMPLE) $(WLM_LIB)
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+	rm -rf $(SRCBASE)/$(REL_WLM_DIR)
+else
+	rm -f $(SRCBASE)/$(REL_WLM_DIR)/*.o $(SRCBASE)/$(REL_WLM_DIR)/$(WLM_LIB)
+endif
+
+.PHONY : all exe lib clean cleanall
diff --git a/src/tools/wlm/wlmSampleTests.c b/src/tools/wlm/wlmSampleTests.c
new file mode 100644
index 0000000..e40bdc3
--- /dev/null
+++ b/src/tools/wlm/wlmSampleTests.c
@@ -0,0 +1,506 @@
+/* wlmSampleTests.cpp : Sample test program which uses the 
+ * 		Wireless LAN Manufacturing (WLM) Test Library.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlmSampleTests.c 241182 2011-02-17 21:50:03Z $
+ *
+ * The sample tests allow users/customers to understand how WLM
+ * Test Library is used to create manufacturing tests.
+ * Users/customers may copy and modify the sample tests	as
+ * required to meet their specific manufacturing test requirements.
+ *
+ * The sample tests can run in the following configurations:
+ *	direct - on same device as the DUT (default).
+ *  socket - as a client to the server DUT over Ethernet.
+ *  serial - as a client to the server DUT over serial.
+ *  wifi   - as a client to the server DUT over 802.11.
+ *  dongle - as a client to the server DUT over serial (to dongle UART).
+ * See printUsage() (i.e. --help) for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "wlm.h"
+
+/* --------------------------------------------------------------- */
+typedef struct
+{
+	int count;		/* number of tests run */
+	int passed;		/* number of tests passed */
+	int failed;		/* number of tests failed */
+} TestLog;
+
+static TestLog testLog;
+
+#define TEST_INITIALIZE()						\
+{												\
+	memset(&testLog, 0, sizeof(testLog));		\
+}
+
+#define TEST(condition, error)					\
+	testLog.count++;							\
+	if ((condition)) {							\
+		testLog.passed++;						\
+	}											\
+	else {										\
+		testLog.failed++;						\
+		printf("\n*** FAIL *** - %s():%d - %s\n\n",	\
+			__FUNCTION__, __LINE__, error);		\
+	}
+
+#define TEST_FATAL(condition, error)			\
+	testLog.count++;							\
+	if ((condition)) {							\
+		testLog.passed++;						\
+	}											\
+	else {										\
+		testLog.failed++;						\
+		printf("\n*** FAIL *** - %s():%d - %s\n\n",	\
+			__FUNCTION__, __LINE__, error);		\
+		exit(-1);								\
+	}
+
+#define TEST_FINALIZE()							\
+{												\
+	int percent = testLog.count ?				\
+		testLog.passed * 100 / testLog.count : 0; \
+	printf("\n\n");								\
+	printf("Test Summary:\n\n");				\
+	printf("Tests    %d\n", testLog.count);		\
+	printf("Pass     %d\n", testLog.passed);	\
+	printf("Fail     %d\n\n", testLog.failed);	\
+	printf("%d%%\n\n", percent);				\
+	printf("-----------------------------------\n\n");	\
+}
+
+/* --------------------------------------------------------------- */
+
+static void delay(unsigned int msec)
+{
+	clock_t start_tick = clock();
+	clock_t end_tick = start_tick + msec * CLOCKS_PER_SEC / 1000;
+
+	while (clock() < end_tick) {
+		/* do nothing */
+	}
+}
+
+static void testDutInit()
+{
+	TEST(wlmMinPowerConsumption(TRUE), "unable disable sleep mode");
+	TEST(wlmCountryCodeSet(WLM_COUNTRY_ALL), "unable to set country code");
+	TEST(wlmGlacialTimerSet(99999), "unable to set glacial timer");
+	TEST(wlmFastTimerSet(99999), "unable to set fast timer");
+	TEST(wlmSlowTimerSet(99999), "unable to set slow timer");
+	TEST(wlmScanSuppress(1), "unable to set scansuppress");
+}
+
+static void testVersion()
+{
+	char buffer[1024];
+	TEST(wlmVersionGet(buffer, 1024), "wlmVersionGet failed");
+	printf("version info: %s\n", buffer);
+}
+
+/* Set transmit power and transmit packets expecting ack response.
+ * Reduce transmit power and repeat.
+ */
+static void testTransmit()
+{
+	int i;
+	int txPower = 17000;	/* power in milli-dB */
+
+	for (i = 0; i < 8; i++) {
+		int power;
+		unsigned int txPacketCount = 50;
+		unsigned int beforeAckCount, afterAckCount, ackCount;
+
+		TEST(wlmTxPowerSet(txPower), "wlmTxPowerSet failed");
+		TEST(wlmTxPowerGet(&power), "wlmTxPowerGet failed");
+		TEST(power == txPower, "Tx power not set correctly");
+
+		TEST(wlmTxGetAckedPackets(&beforeAckCount), "wlmTxGetAckedPackets failed");
+
+		TEST(wlmTxPacketStart(100, txPacketCount, 1024, "00:11:22:33:44:55", TRUE, TRUE),
+			"wlmTxPacketStart failed");
+
+		afterAckCount = beforeAckCount;
+		TEST(wlmTxGetAckedPackets(&afterAckCount), "wlmTxGetAckedPackets failed");
+
+		/* another pkteng is required to send ACKs else no ACKs will be received
+		 *  i.e.   'wl pkteng_start 00:11:22:33;44:55 rxwithack'
+		 */
+		ackCount = afterAckCount - beforeAckCount;
+		printf("Packets tx=%d, ack=%d\n", txPacketCount, ackCount);
+		TEST(ackCount > 0, "no ACK packets received");
+
+		/* reduce tx power */
+		txPower -= 1000;
+	}
+
+	TEST(wlmTxPacketStop(), "wlmTxPacketStop failed");
+
+	/* set tx power back to default */
+	TEST(wlmTxPowerSet(-1), "wlmTxPowerSet failed");
+}
+
+/* Batch the commands to set transmit power and transmit packets,
+ * reduce transmit power and repeat.
+ *
+ * During the batching sequence, only 'set' functions can be invoked.
+ * 'get' functions are not supported by command batching.
+ */
+static void testBatchingTransmit(int clientBatching)
+{
+	int i, count = 8;
+	int txPower = 17000;	/* power in milli-dB */
+	unsigned int txPacketCount = 50;
+	unsigned int beforeAckCount, afterAckCount, ackCount;
+
+	TEST(wlmTxGetAckedPackets(&beforeAckCount), "wlmTxGetAckedPackets failed");
+
+	/* start command batching */
+	TEST(wlmSequenceStart(clientBatching), "wlmSequenceStart failed");
+
+		for (i = 0; i < count; i++) {
+
+		TEST(wlmTxPowerSet(txPower), "wlmTxPowerSet failed");
+
+		TEST(wlmTxPacketStart(100, txPacketCount, 1024, "00:11:22:33:44:55", TRUE, TRUE),
+			"wlmTxPacketStart failed");
+
+		/* reduce tx power */
+		txPower -= 1000;
+	}
+
+	TEST(wlmTxPacketStop(), "wlmTxPacketStop failed");
+
+	/* stop command batching */
+	TEST(wlmSequenceStop(), "wlmSequenceStop failed");
+
+	afterAckCount = beforeAckCount;
+	TEST(wlmTxGetAckedPackets(&afterAckCount), "wlmTxGetAckedPackets failed");
+
+	/* requires pkteng to send ACKs else no ACKs will be received
+	 *  i.e. 'wl pkteng_start 00:11:22:33;44:55 rxwithack'
+	 */
+	ackCount = afterAckCount - beforeAckCount;
+	printf("Packets tx=%d, ack=%d\n", txPacketCount * count, ackCount);
+	TEST(ackCount > 0, "no ACK packets received");
+
+	/* set tx power back to default */
+	TEST(wlmTxPowerSet(-1), "wlmTxPowerSet failed");
+}
+
+/* Batch transmit commands on the client */
+static void testClientBatchingTransmit()
+{
+	testBatchingTransmit(TRUE);
+}
+
+/* Batch transmit commands on the server */
+static void testServerBatchingTransmit()
+{
+	/* batch commands on server */
+	testBatchingTransmit(FALSE);
+}
+
+/* Test receiving of packets by waiting for an expected number
+ * of packets or a timeout.
+ */
+static void testReceive()
+{
+	unsigned int beforeRxPacketCount, afterRxPacketCount, rxPacketCount;
+	unsigned int rxPacketExpected = 50;
+	unsigned int maxTimeout = 500; 	/* milliseconds */
+	int rssi = 0;
+
+	TEST(wlmRxGetReceivedPackets(&beforeRxPacketCount), "wlmRxGetReceivedPackets failed");
+	TEST(wlmRxPacketStart("00:11:22:33:44:55", FALSE, TRUE, rxPacketExpected, maxTimeout),
+		"wlmRxPacketStart failed");
+
+	afterRxPacketCount = beforeRxPacketCount;
+	TEST(wlmRxGetReceivedPackets(&afterRxPacketCount), "wlmRxGetReceivedPackets failed");
+
+	/* requires another pkteng to send packets else no packets will be received
+	 *  i.e. 'wl pkteng_start 00:11:22:33:44:55 tx 100 1024 0'
+	 */
+	rxPacketCount = afterRxPacketCount - beforeRxPacketCount;
+	printf("Packets rx=%d\n", rxPacketCount);
+	TEST(rxPacketCount > 0, "no packets received");
+
+	TEST(wlmRssiGet(&rssi), "wlmRssiGet failed");
+	printf("RSSI=%d\n", rssi);
+	TEST(rssi != 0, "no RSSI");
+
+	TEST(wlmRxPacketStop(), "wlmRxPacketStop failed");
+}
+
+/* Test joining a network, get and compare the SSID */
+static int testJoinNetwork(char *ssid, WLM_AUTH_MODE authMode,
+	WLM_ENCRYPTION encryption, const char *key)
+{
+	char bssidBuf[256];
+	int isAssociated;
+	char ssidBuf[256];
+
+	/* make sure not currently associated */
+	TEST(wlmDisassociateNetwork(), "wlmDisassociateNetwork failed");
+
+	TEST(wlmSecuritySet(WLM_TYPE_OPEN, authMode, encryption, key),
+		"wlmSecuritySet failed");
+	TEST(wlmJoinNetwork(ssid, WLM_MODE_BSS), "wlmJoinNetwork failed");
+	/* delay to allow network association */
+	delay(5000);
+	TEST(wlmBssidGet(bssidBuf, 256), "wlmBssidGet failed");
+	isAssociated = strlen(bssidBuf) == 0 ? FALSE : TRUE;
+	if (isAssociated) {
+		TEST(wlmSsidGet(ssidBuf, 256), "wlmSsidGet failed");
+		printf("associated to SSID=%s BSSID=%s\n", ssidBuf, bssidBuf);
+		TEST(strcmp(ssid, ssidBuf) == 0, "SSID does not match");
+	}
+	else {
+		printf("failed to associate to SSID=%s using key=%s\n", ssid, key ? key : "");
+	}
+
+	TEST(wlmDisassociateNetwork(), "wlmDisassociateNetwork failed");
+
+	return isAssociated;
+}
+
+/* Test joining a network */
+static void testJoinNetworkNone()
+{
+	/* requires an AP with the SSID, authentication, and encryption 
+	 * configured to match these settings
+	 */
+	TEST(testJoinNetwork("WLM_NONE", WLM_WPA_AUTH_DISABLED, WLM_ENCRYPT_NONE, 0),
+		"testJoinNetworkNone failed");
+}
+
+/* Test joining a WEP network */
+static void testJoinNetworkWep()
+{
+	/* requires an AP with the SSID, authentication, and encryption 
+	 * configured to match these settings
+	 */
+	TEST(testJoinNetwork("WLM_WEP", WLM_WPA_AUTH_DISABLED, WLM_ENCRYPT_WEP,
+		"2222222222444444444466666666668888888888"),
+		"testJoinNetworkWep failed");
+}
+
+/* Test joining a WPA TKIP network */
+static void testJoinNetworkWpaTkip()
+{
+	/* requires an AP with the SSID, authentication, and encryption 
+	 * configured to match these settings
+	 */
+	TEST(testJoinNetwork("WLM_WPA_TKIP", WLM_WPA_AUTH_PSK, WLM_ENCRYPT_TKIP,
+		"helloworld"), "testJoinNetworkWpaTkip failed");
+}
+
+/* Test joining a WPA AES network */
+static void testJoinNetworkWpaAes()
+{
+	/* requires an AP with the SSID, authentication, and encryption 
+	 * configured to match these settings
+	 */
+	TEST(testJoinNetwork("WLM_WPA_AES", WLM_WPA_AUTH_PSK, WLM_ENCRYPT_AES,
+		"helloworld"), "testJoinNetworkWpaAes failed");
+}
+
+/* Test joining a WPA2 TKIP network */
+static void testJoinNetworkWpa2Tkip()
+{
+	/* requires an AP with the SSID, authentication, and encryption 
+	 * configured to match these settings
+	 */
+	TEST(testJoinNetwork("WLM_WPA2_TKIP", WLM_WPA2_AUTH_PSK, WLM_ENCRYPT_TKIP,
+		"helloworld"), "testJoinNetworkWpa2Tkip failed");
+}
+
+/* Test joining a WPA2 AES network */
+static void testJoinNetworkWpa2Aes()
+{
+	/* requires an AP with the SSID, authentication, and encryption 
+	 * configured to match these settings
+	 */
+	TEST(testJoinNetwork("WLM_WPA2_AES", WLM_WPA2_AUTH_PSK, WLM_ENCRYPT_AES,
+		"helloworld"), "testJoinNetworkWpa2Aes failed");
+}
+
+static void printUsage(void)
+{
+	printf("\nUsage: wlmSampleTests [--socket <IP address> [server port] | "
+		"--serial <serial port> | --wifi <MAC address> | "
+		"--dongle <serial port>] [--linux | --linuxdut]]\n\n");
+	printf("--socket - Ethernet between client and server (running 'wl_server_socket')\n");
+	printf("      IP address - IP address of server (e.g. 10.200.30.10)\n");
+	printf("      server port - Server port number (default 8000)\n\n");
+	printf("--serial - Serial between client and server (running 'wl_server_serial')\n");
+	printf("      serial port - Client serial port (e.g. 1 for COM1)\n\n");
+	printf("--wifi - 802.11 between client and server (running 'wl_server_wifi')\n");
+	printf("         (external dongle only, NIC not supported)\n");
+	printf("      MAC address - MAC address of wifi interface on dongle "
+		"(e.g. 00:11:22:33:44:55)\n\n");
+	printf("--dongle - Serial between client and dongle UART (running 'wl_server_dongle')\n");
+	printf("      serial port - Client serial port (e.g. COM1 or /dev/ttyS0)\n\n");
+	printf("--linux|linuxdut - Server DUT running Linux\n");
+}
+
+int main(int argc, char **argv)
+{
+	WLM_DUT_INTERFACE dutInterface = WLM_DUT_LOCAL;
+	char *interfaceName = 0;
+	WLM_DUT_SERVER_PORT dutServerPort = WLM_DEFAULT_DUT_SERVER_PORT;
+	WLM_DUT_OS dutOs = WLM_DUT_OS_WIN32;
+
+	(void)argc;
+
+	while (*++argv) {
+
+		if (strncmp(*argv, "--help", strlen(*argv)) == 0) {
+			printUsage();
+			exit(0);
+		}
+
+		if (strncmp(*argv, "--socket", strlen(*argv)) == 0) {
+			int port;
+
+			dutInterface = WLM_DUT_SOCKET;
+			if (!*++argv) {
+				printf("IP address required\n");
+				printUsage();
+				exit(-1);
+			}
+			interfaceName = *argv;
+			if (*++argv && (sscanf(*argv, "%d", &port) == 1)) {
+				dutServerPort = (WLM_DUT_SERVER_PORT)port;
+			}
+			else {
+				/* optional parameter */
+				--argv;
+			}
+		}
+
+		if (strncmp(*argv, "--serial", strlen(*argv)) == 0) {
+			dutInterface = WLM_DUT_SERIAL;
+			if (!*++argv) {
+				printf("serial port required\n");
+				printUsage();
+				exit(-1);
+			}
+			interfaceName = *argv;
+		}
+
+		if (strncmp(*argv, "--wifi", strlen(*argv)) == 0) {
+			dutInterface = WLM_DUT_WIFI;
+			if (!*++argv) {
+				printf("MAC address required\n");
+				printUsage();
+				exit(-1);
+			}
+			interfaceName = *argv;
+		}
+
+		if (strncmp(*argv, "--dongle", strlen(*argv)) == 0) {
+			unsigned int i;
+			char buffer[256];
+
+			dutInterface = WLM_DUT_DONGLE;
+			if (!*++argv) {
+				printf("COM port required\n");
+				printUsage();
+				exit(-1);
+			}
+			if (!(sscanf(*argv, "COM%u", &i) == 1 ||
+				sscanf(*argv, "/dev/tty%s", buffer) == 1)) {
+				printf("serial port invalid\n");
+				printUsage();
+				exit(-1);
+			}
+			interfaceName = *argv;
+		}
+
+		if ((strncmp(*argv, "--linux", strlen(*argv)) == 0) ||
+			strncmp(*argv, "--linuxdut", strlen(*argv)) == 0) {
+			dutOs = WLM_DUT_OS_LINUX;
+		}
+	}
+
+	TEST_INITIALIZE();
+
+	TEST_FATAL(wlmApiInit(), "wlmApiInit failed");
+
+	TEST_FATAL(wlmSelectInterface(dutInterface, interfaceName,
+		dutServerPort, dutOs), "wlmSelectInterface failed");
+
+	printf("\n");
+	switch (dutInterface) {
+		case WLM_DUT_LOCAL:
+			printf("Test running against local DUT.\n");
+			break;
+		case WLM_DUT_SOCKET:
+			printf("Test running over Ethernet to remote DUT IP=%s.\n", interfaceName);
+			break;
+		case WLM_DUT_SERIAL:
+			printf("Test running over serial from port %s\n", interfaceName);
+			break;
+		case WLM_DUT_WIFI:
+			printf("Test running over 802.11 to remote DUT MAC=%s.\n", interfaceName);
+			break;
+		case WLM_DUT_DONGLE:
+			printf("Test running over serial from %s to remote dongle UART\n",
+				interfaceName);
+			break;
+		default:
+			printf("Invalid interface\n");
+			exit(-1);
+			break;
+	}
+	switch (dutOs) {
+		case WLM_DUT_OS_LINUX:
+			printf("Test running against Linux DUT.\n");
+			break;
+		case WLM_DUT_OS_WIN32:
+			printf("Test running against Win32 DUT.\n");
+			break;
+		default:
+			printf("Invalid DUT OS\n");
+			exit(-1);
+			break;
+	}
+	printf("\n");
+
+	/* packet engine requires MPC to be disabled and WLAN interface up */
+	TEST(wlmMinPowerConsumption(FALSE), "wlmMinPowerConsuption failed");
+	TEST(wlmEnableAdapterUp(TRUE), "wlmEnableAdapterUp failed");
+	/* invoke test cases */
+	testDutInit();
+	testVersion();
+	testTransmit();
+	testClientBatchingTransmit();
+	testServerBatchingTransmit();
+	testReceive();
+	testJoinNetworkNone();
+	testJoinNetworkWep();
+	testJoinNetworkWpaTkip();
+	testJoinNetworkWpaAes();
+	testJoinNetworkWpa2Tkip();
+	testJoinNetworkWpa2Aes();
+
+	TEST_FATAL(wlmApiCleanup(), "wlmApiCleanup failed");
+
+	TEST_FINALIZE();
+	return 0;
+}
diff --git a/src/tools/wlm/wlmSampleTests.sln b/src/tools/wlm/wlmSampleTests.sln
new file mode 100644
index 0000000..7f6452f
--- /dev/null
+++ b/src/tools/wlm/wlmSampleTests.sln
@@ -0,0 +1,20 @@
+

+Microsoft Visual Studio Solution File, Format Version 9.00

+# Visual Studio 2005

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wlmSampleTests", "wlmSampleTests.vcproj", "{47974405-93E8-4133-BE1F-22F6BA3CAA4E}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Release|Win32 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{47974405-93E8-4133-BE1F-22F6BA3CAA4E}.Debug|Win32.ActiveCfg = Debug|Win32

+		{47974405-93E8-4133-BE1F-22F6BA3CAA4E}.Debug|Win32.Build.0 = Debug|Win32

+		{47974405-93E8-4133-BE1F-22F6BA3CAA4E}.Release|Win32.ActiveCfg = Release|Win32

+		{47974405-93E8-4133-BE1F-22F6BA3CAA4E}.Release|Win32.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/src/tools/wlm/wlmSampleTests.vcproj b/src/tools/wlm/wlmSampleTests.vcproj
new file mode 100755
index 0000000..2fc2468
--- /dev/null
+++ b/src/tools/wlm/wlmSampleTests.vcproj
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="wlmSampleTests"
+	ProjectGUID="{47974405-93E8-4133-BE1F-22F6BA3CAA4E}"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\wl\exe"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				DisableLanguageExtensions="false"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../wl/exe/obj/wlm/checked/wlm.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				Description="Copy dll to working directory"
+				CommandLine="copy ..\..\wl\exe\obj\wlm\checked\wlm.dll ."
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\wl\exe"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
+				RuntimeLibrary="2"
+				DisableLanguageExtensions="false"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../wl/exe/obj/wlm/free/wlm.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				Description="Copy dll to working directory"
+				CommandLine="copy ..\..\wl\exe\obj\wlm\free\wlm.dll ."
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\wlmSampleTests.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/src/wl/exe/GNUmakefile b/src/wl/exe/GNUmakefile
new file mode 100644
index 0000000..66bda37
--- /dev/null
+++ b/src/wl/exe/GNUmakefile
@@ -0,0 +1,464 @@
+#
+# GNUmakefile for wl/exe
+#
+# Copyright (c) 2000, Broadcom Corp.
+# $Id: GNUmakefile 561503 2015-06-04 23:18:46Z $
+
+WLAN_ComponentsInUse := bcmwifi ppr hal
+include ../../makefiles/WLAN_Common.mk
+
+ifndef	SRCBASE
+    SRCBASE := $(WLAN_SrcBaseR)
+endif
+
+UNAME = $(shell uname)
+
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+
+#-----------------------------------------------------------------
+# Windows build, don't include Makerules due to all: conflict
+
+include ../../GNUmakefile.inc
+
+# MfgTest XP and WIN7 WLU DLL builds are built from other standalone Makefiles
+# from App and MfgTest teams
+# To build XP WLU DLL (output is in obj/*/mfg_dll/{free,checked}/...)
+#    $(MAKE) -C src/wl/exe -f GNUmakefile.wlu_dll
+# To build Win7/Vista WLU DLL (output is in obj/*/mfg_dll/{Release,Debug}/...)
+#    $(MAKE) -C src/wl/exe/win7
+
+else # UNAME
+
+#-----------------------------------------------------------------
+# Linux build
+#
+
+# This should be one of values recognized in src/Makerules
+# 2) not windows, need to include first to pick up TARGETENV dependent vars
+include $(SRCBASE)/Makerules
+
+# GNU make function to do compilation and dependency generation
+# in one step.
+define CompileAndMakedep
+$(strip $1 -c -MMD -MF $(@D)/.$(@F).depend -MP $2)
+endef
+
+ifdef CROSS_COMPILE
+    $(warning CROSS_COMPILE=$(CROSS_COMPILE))
+    CC := $(CROSS_COMPILE)gcc
+    LD := $(CROSS_COMPILE)ld
+    NM := $(CROSS_COMPILE)nm
+    AR := $(CROSS_COMPILE)ar
+
+#    LDFLAGS := -static
+endif
+ifdef ARCH
+    TARGETARCH := $(ARCH)
+endif
+
+CFLAGS += $(EXTRA_PLATFORM_CFLAGS)
+
+# Use newer 11ac ratespec for wl command line
+CFLAGS += -DD11AC_IOTYPES
+
+# Use opaque PPR structures
+CFLAGS += -DPPR_API
+
+#ifdef WLCNT
+  CFLAGS += -DWLCNT
+#endif
+
+#ifdef WIFI_ACT_FRAME
+  CFLAGS += -DWIFI_ACT_FRAME
+#endif
+
+#ifdef WLEXTLOG
+  CFLAGS += -DWLEXTLOG
+#endif
+
+ifeq ($(WLTEST),1)
+    CFLAGS += -DSERDOWNLOAD -DEVENT_LOG_COMPILE
+endif
+
+ifeq ($(OLYMPIC_RWL),1)
+    CFLAGS += -DOLYMPIC_RWL
+endif
+
+ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le android android_ndk_r6b freebsd"),)
+
+#ifdef WLBTAMP
+  CFLAGS += -DWLBTAMP
+#endif
+
+#ifdef WLP2P
+  CFLAGS += -DWLP2P
+#endif
+
+#ifdef WLMCHAN
+  CFLAGS += -DWLMCHAN
+#endif
+
+#ifdef WLTDLS
+ CFLAGS += -DWLTDLS
+#endif
+
+#ifdef WLNDOE
+  CFLAGS += -DWLNDOE
+#endif
+
+#ifdef WLP2PO
+  CFLAGS += -DWLP2PO
+#endif
+
+#ifdef WLANQPO
+  CFLAGS += -DWLANQPO
+#endif
+
+#ifdef SR_DEBUG
+  CFLAGS += -DSR_DEBUG
+#endif
+
+#ifdef UC_FATAL
+  CFLAGS += -DUC_FATAL
+#endif
+
+#ifdef TBTT_OFFSET_STAT
+  CFLAGS += -DTBTT_OFFSET_STAT
+#endif
+
+#ifdef TRAFFIC_MGMT
+  CFLAGS += -DTRAFFIC_MGMT
+#endif
+
+# netlink driver interface
+ifeq ($(NL80211),1)
+  CFLAGS += -DNL80211
+endif
+
+#ifdef WLWNM
+ CFLAGS += -DWLWNM
+#endif
+
+# extra warnings
+ifneq ($(filter mips_be arm_le arm_android arm_android_ndk_r6b,$(TARGETARCH)),)
+CFLAGS += -Wextra -Wall
+else
+CFLAGS += -Wextra -Wall -Werror
+endif
+CFLAGS += -DWLPFN -DWLPFN_AUTO_CONNECT -DWLOFFLD -DLINUX
+ifeq ($(findstring $(TARGETENV), "freebsd"),)
+CFLAGS += -DLINUX
+endif
+CFLAGS += -DWLC_HIGH
+CFLAGS += -I$(SRCBASE)/wl/sys -I$(SRCBASE)/wl/phy
+CFLAGS += $(WLAN_ComponentIncPathR)
+
+# Discard any "MMX" or other qualifications on x86 so that
+# any TARGETARCH containing x86 is just "x86"
+ifeq ($(findstring x86_mmx,$(TARGETARCH)),x86_mmx)
+	TARGETARCH = x86
+endif
+
+ASD        ?= 0
+ifneq ($(ASD),1)
+  override ASD:=
+endif
+ifneq ($(ASD),1)
+  NOASDDIR    = _noasd
+endif
+
+RWL        ?= 1
+ifeq ($(RWL),0)
+  override RWL:=
+endif
+
+RWL_DONGLE        ?= 1
+RWL_SOCKET        ?= 1
+RWL_WIFI          ?= 1
+RWL_SERIAL        ?= 1
+
+ifneq ($(RWL_DONGLE),0)
+RWL_SERVERS += $(SERVER_DONGLE)
+endif
+ifneq ($(RWL_SOCKET),0)
+RWL_SERVERS += $(SERVER_SOCKET)
+endif
+ifneq ($(RWL_WIFI),0)
+RWL_SERVERS += $(SERVER_WIFI)
+endif
+ifneq ($(RWL_SERIAL),0)
+RWL_SERVERS += $(SERVER_SERIAL)
+endif
+# $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files
+ifneq ($(findstring $(TARGETENV), "freebsd"),)
+WL_OBJS      := wlu.o wlu_common.o wlu_bsd.o wlu_cmd.o wlu_iov.o wlu_rates_matrix.o miniopt.o bcmutils.o bcmwifi_channels.o bcm_app_utils.o wlc_ppr.o
+else
+WL_OBJS      := wlu.o wlu_common.o wlu_linux.o bcmutils.o bcmwifi_channels.o wlu_cmd.o wlu_iov.o wlu_client_shared.o wlu_pipe_linux.o wlu_pipe.o miniopt.o bcm_app_utils.o wlu_rates_matrix.o wlc_ppr.o
+endif
+SERVER_OBJS  := wlu_server_linux.o wlu_pipe_linux.o wlu_pipe.o wlu_server_shared.o shellproc_linux.o
+WLM_OBJS     := $(WL_OBJS) wlm.o
+WLHIGHSTUB_OBJS := wlhighstub.o bcm_rpc_char.o bcm_rpc.o linux_rpc_osl.o
+WLHIGHSTUB_OBJS += wlc_low_stubs.o bcm_xdr.o
+
+# include build settings for nl80211 support
+ifeq ($(NL80211),1)
+include netlink.inc
+endif
+
+# Prefix obj/<type>/TARGETARCH to produced .obj files
+WL_OBJS      := $(WL_OBJS:%.o=obj/wl$(NOASDDIR)/$(TARGETARCH)/%.o)
+DONGLE_OBJS  := $(SERVER_OBJS:%.o=obj/dongle$(NOASDDIR)/$(TARGETARCH)/%.o)
+SOCKET_OBJS  := $(SERVER_OBJS:%.o=obj/socket$(NOASDDIR)/$(TARGETARCH)/%.o)
+WIFI_OBJS    := $(SERVER_OBJS:%.o=obj/wifi$(NOASDDIR)/$(TARGETARCH)/%.o)
+SERIAL_OBJS  := $(SERVER_OBJS:%.o=obj/serial$(NOASDDIR)/$(TARGETARCH)/%.o)
+WLM_OBJS     := $(WLM_OBJS:%.o=obj/wlm/$(TARGETARCH)/%.o)
+WLHIGHSTUB_OBJS  := $(WLHIGHSTUB_OBJS:%.o=obj/wlhighstub/$(TARGETARCH)/%.o)
+
+# Derive a final list of all known objects.
+OBJS         := $(WL_OBJS) $(DONGLE_OBJS) $(SOCKET_OBJS) $(WIFI_OBJS) $(SERIAL_OBJS) $(WLM_OBJS) $(WLHIGHSTUB_OBJS)
+
+# Make a list of dependency files, one per object file.
+DEPENDS      := $(join $(dir $(OBJS)),$(addprefix .,$(addsuffix .depend,$(notdir $(OBJS)))))
+
+# Include any dependency files which currently exist.
+-include $(DEPENDS)
+
+# TODO: Move final built objects to respective TARGETARCH dirs as well
+# Final exe names
+ifneq ($(TARGETARCH),x86)
+	ARCH_SFX   = $(TARGETARCH)
+endif
+WL_EXE       := wl$(ARCH_SFX)
+SERVER_SOCKET = socket$(NOASDDIR)/$(TARGETARCH)/wl_server_socket$(ARCH_SFX)
+SERVER_DONGLE = dongle$(NOASDDIR)/$(TARGETARCH)/wl_server_dongle$(ARCH_SFX)
+SERVER_WIFI   = wifi$(NOASDDIR)/$(TARGETARCH)/wl_server_wifi$(ARCH_SFX)
+SERVER_SERIAL = serial$(NOASDDIR)/$(TARGETARCH)/wl_server_serial$(ARCH_SFX)
+WLM_SO       := wlm/$(TARGETARCH)/wlm$(ARCH_SFX).so
+WLHIGHSTUB   := obj/wlhighstub/$(TARGETARCH)/wlhighstub$(ARCH_SFX)
+
+# ASD specific flags
+ifeq ($(ASD),1)
+  ASD_CFLAGS := -DRWLASD
+  ASD_CFLAGS += -I../../tools/Wifi_ASD_test/inc
+ifneq ($(filter mips_be arm_android arm_android_ndk_r6b x86_android_ndk_r6b,$(TARGETARCH)),)
+  ASD_LDFLAGS:= -L../../tools/Wifi_ASD_test/lib/$(TARGETARCH) -lwfa
+else
+  ASD_LDFLAGS:= -L../../tools/Wifi_ASD_test/lib/$(TARGETARCH) -lwfa -lpthread
+endif
+endif # ASD
+
+INSTALL_DIR ?= apps
+
+vpath %.c $(SRCBASE)/shared $(SRCBASE)/wl/sys $(SRCBASE)/wl/phy $(WLAN_StdSrcDirsR) $(WLAN_ComponentSrcDirsR)
+
+all:  build_deps
+
+# Build servers for all but mips_be
+ifeq ($(filter mips_be,$(TARGETARCH)),)
+all:  $(WL_EXE) servers
+else
+all: $(WL_EXE)
+endif
+
+build_deps:
+ifeq ($(ASD),1)
+	$(MAKE) -C ../../tools/Wifi_ASD_test
+endif # ASD
+
+wlm: $(WLM_SO)
+
+servers: $(RWL_SERVERS)
+
+# Handle creation of directories for objects mentioned below.
+$(addprefix obj/,$(addsuffix $(NOASDDIR)/$(TARGETARCH),wl dongle socket wifi serial) $(addsuffix /$(TARGETARCH),wlm wlhighstub)):
+	@mkdir -pv $@
+
+# Compilation targets
+obj/wl$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/wl$(NOASDDIR)/$(TARGETARCH)
+ifneq ($(RWL),)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_SOCKET -DRWL_DONGLE -DRWL_WIFI -DRWL_SERIAL -o $@ $<)
+else
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -o $@ $<)
+endif
+
+obj/dongle$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/dongle$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_DONGLE -o $@ $<)
+
+obj/socket$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/socket$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_SOCKET -o $@ $<)
+
+obj/wifi$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/wifi$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_WIFI -o $@ $<)
+
+obj/serial$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/serial$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_SERIAL -o $@ $<)
+
+obj/wlm/$(TARGETARCH)/%.o: %.c | obj/wlm/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_DONGLE -DRWL_SOCKET -DRWL_WIFI -DRWL_SERIAL -DWLMSO -fPIC -o $@ $<)
+
+obj/wlhighstub/$(TARGETARCH)/%.o: %.c | obj/wlhighstub/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -o $@ $<)
+
+$(WLHIGHSTUB): $(WLHIGHSTUB_OBJS)
+	@mkdir -pv $(@D)
+
+# Final link targets
+$(WL_EXE): $(WL_OBJS)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(LIBS))
+
+# net_priv target is for building the dhd with NET_ADMIN privilege (i.e. to avoid running as root)
+# note: The 'setcap' command is availble from the libcap2-bin package
+# note: linux kernel < 2.6.33 doesn't support Security File Capabilities by default
+net_priv: $(WL_EXE)
+	sudo setcap CAP_NET_ADMIN=eip $^
+
+$(SERVER_DONGLE): $(DONGLE_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(SERVER_SOCKET): $(SOCKET_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(SERVER_WIFI): $(WIFI_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(SERVER_SERIAL): $(SERIAL_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(WLM_SO): $(WLM_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -shared -o $@ $^)
+
+
+wldefs: wlmain.o
+	$(CC) $(LDFLAGS) -o $@ $<
+
+.PHONY: all clean wlm release_bins net_priv
+
+release_bins:
+	@mkdir -p $(INSTALL_DIR)
+	install -pv $(WL_EXE) $(INSTALL_DIR)
+ifeq ($(filter mips_be,$(TARGETARCH)),)
+	install -pv $(SERVER_SOCKET) $(INSTALL_DIR)
+	install -pv $(SERVER_DONGLE) $(INSTALL_DIR)
+	install -pv $(SERVER_WIFI) $(INSTALL_DIR)
+	install -pv $(SERVER_SERIAL) $(INSTALL_DIR)
+endif
+ifeq ($(ASD),1)
+	$(MAKE) -C ../../tools/Wifi_ASD_test release_bins
+endif #ASD
+
+clean::
+	rm -fv $(WL_EXE) $(WL_OBJS) $(SERVER_SOCKET) $(SERVER_DONGLE) $(SERVER_WIFI) $(SERVER_SERIAL) $(SOCKET_OBJS) $(SERIAL_OBJS) $(WIFI_OBJS) $(DONGLE_OBJS) $(WLM_SO) $(WLM_OBJS) $(SERVER_SERIAL) $(DEPENDS)
+
+endif # TARGETENV linux
+
+#-----------------------------------------------------------------
+# MacOS build
+#
+
+ifeq ($(TARGETENV), macos)
+
+include $(SRCBASE)/Makerules.env
+
+.PHONY: all everything clean wl wl_server_socket wl_server_wifi wl_dongle
+
+PROJTGT	:= wl
+BUILD	:= xcodebuild
+PROJECT	:= wl.xcodeproj
+OBJDIR	:= $(TARGETENV)/$(MACOS_VER)
+
+all: wl wl_server_socket
+
+everything: wl wl_server_socket wl_server_wifi wl_dongle
+
+clean::
+	rm -rf $(OBJDIR) build
+
+wl wl_server_socket wl_server_wifi: | $(OBJDIR)
+
+#
+# dongle wl is located at ./build/Debug/wl
+#
+wl_dongle:
+	$(BUILD) -project $(PROJECT) -target $(PROJTGT) -configuration Debug build
+
+WL_EXE		:= $(OBJDIR)/wl
+SERVER_SOCKET	:= $(OBJDIR)/socket/wl_server_socket
+SERVER_WIFI	:= $(OBJDIR)/wifi/wl_server_wifi
+
+WL_OBJS := $(addprefix $(OBJDIR)/,wlu.o wlu_common.o wlu_macos.o bcmutils.o bcmwifi_channels.o wlu_cmd.o wlu_iov.o miniopt.o bcm_app_utils.o wlu_rates_matrix.o wlc_ppr.o)
+SERVER_OBJS := wlu_server_macos.o  wlu_pipe_linux.o wlu_pipe.o wlu_server_shared.o shellproc_linux.o
+SOCKET_OBJS := $(SERVER_OBJS:%.o=$(OBJDIR)/socket/%.o)
+WIFI_OBJS := $(SERVER_OBJS:%.o=$(OBJDIR)/wifi/%.o)
+
+# Derive a final list of all known objects.
+OBJS         := $(WL_OBJS) $(SOCKET_OBJS) $(WIFI_OBJS)
+
+# Create the sub-directories needed to hold object files.
+$(sort $(dir $(OBJS))):
+	@mkdir -pv $@
+
+# Make a list of dependency files, one per object file.
+DEPENDS      := $(join $(dir $(OBJS)),$(addprefix .,$(addsuffix .depend,$(notdir $(OBJS)))))
+
+# Include any dependency files which currently exist.
+-include $(DEPENDS)
+
+vpath %.c .. $(SRCBASE)/shared $(SRCBASE)/wl/sys $(SRCBASE)/wl/phy $(WLAN_StdSrcDirsR) $(WLAN_ComponentSrcDirsR)
+
+MACOS_VER ?:= $(shell sw_vers -productVersion)
+
+ifneq (,$(findstring 10.9,$(MACOS_VER)))
+        SDKROOT := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
+        GCDEFS  := $(GCDEFS) -DRDR_5905993 -DWLP2P -DWLMCHAN -DWLAWDL -DWLOFFLD -DPPR_API -I/usr/include -I/Library/Developer/CommandLineTools/usr/include -I$(SDKROOT)/System/Library/Frameworks/Kernel.framework/Versions/A/PrivateHeaders/IOKit/apple80211 -I$(SDKROOT)/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/ -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include
+else
+ifneq (,$(findstring 10.8.3,$(MACOS_VER)))
+        SDKROOT := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
+        GCDEFS  := $(GCDEFS) -DRDR_5905993 -DWLP2P -DWLMCHAN -DWLAWDL -DWLOFFLD -DPPR_API -I/usr/include -I/Library/Developer/CommandLineTools/usr/include -I$(SDKROOT)/System/Library/Frameworks/Kernel.framework/Versions/A/PrivateHeaders/IOKit/apple80211 -I$(SDKROOT)/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/ -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include
+else
+ifneq (,$(findstring 10.8,$(MACOS_VER)))
+	GCDEFS	:= $(GCDEFS) -DRDR_5905993 -DWLP2P -DWLMCHAN -DWLAWDL -DWLOFFLD -DPPR_API -I/usr/include -I/System/Library/Frameworks/Kernel.framework/Versions/A/PrivateHeaders/IOKit/apple80211
+else
+ifneq (,$(findstring 10.7,$(MACOS_VER)))
+	GCDEFS	:= $(GCDEFS) -DRDR_5905993 -DWLP2P -DWLMCHAN -DWLOFFLD -DPPR_API
+else
+ifneq (,$(findstring 10.6,$(MACOS_VER)))
+	GCDEFS	:= $(GCDEFS) -DRDR_5905993 -DWLP2P -DWLMCHAN -DWLOFFLD -DPPR_API
+endif
+endif
+endif
+endif
+endif
+
+$(OBJDIR)/%.o: %.c | $(OBJDIR)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -o $@ $<)
+
+wl: $(OBJDIR)/wl
+$(OBJDIR)/wl: $(WL_OBJS)
+ifneq ($(findstring $(MACOS_VER), 10.8 10.9),)
+	$(CC) -L/usr/lib $(LDFLAGS) -o $@ $^
+else
+	$(CC) $(LDFLAGS) -o $@ $^
+endif
+
+wl_server_socket: $(SERVER_SOCKET)
+$(SERVER_SOCKET): $(SOCKET_OBJS)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^)
+
+$(OBJDIR)/socket/%.o: %.c | $(OBJDIR)/socket
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -DRWL_SOCKET -DREMOTE_WL -o $@ $<)
+
+wl_server_wifi: $(SERVER_WIFI)
+$(SERVER_WIFI): $(WIFI_OBJS)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^)
+
+$(OBJDIR)/wifi/%.o: %.c | $(OBJDIR)/wifi
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -DRWL_WIFI -DREMOTE_WL -o $@ $<)
+
+endif # TARGETENV macos
+
+endif # UNAME
diff --git a/src/wl/exe/shellproc_linux.c b/src/wl/exe/shellproc_linux.c
new file mode 100644
index 0000000..d607d90
--- /dev/null
+++ b/src/wl/exe/shellproc_linux.c
@@ -0,0 +1,697 @@
+/*
+ * Remote shell command execution (common for all transports) for linux
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: shellproc_linux.c 377604 2013-01-08 09:10:28Z $
+ */
+
+/* Linux remote shell command execution
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include "wlu_remote.h"
+#include <sys/poll.h>
+#include <malloc.h>
+#include <miniopt.h>
+#include <sys/utsname.h>
+#define ASYNC_RESP     0
+#define MAX_SHELL_ASYNC_RESP  128  /* Support for maximum 5 async process */
+#define MAX_ASYNC_FILE_LENGTH 50
+#define MAX_PID_CMD_LENGTH    20
+#define MAX_PID_RESP_LENTH    50
+#define MAX_SHELL_CMD_LENTH   256
+#define PID_TOKEN_SIZE	      50
+#define PID_SEARCH_CMD_SIZE   100
+#define ASYNC_SHELL_CHAR "%"  /* Async process identifier from the client */
+#define FILE_PERMISSION	 777
+
+#define DEFAULT_SHELL_TIMEOUT	0 /* Default TimeOut Value for synchronous shell commands */
+#define SHELL_RETURNVALUE_SIZE	2 /* Size of Return Value of the shell command */
+#define SHELL_ASYNCCMD_ID	1 /* To identify if it is an async command */
+#define REBOOT_MSG      "Rebooting AP  ...\n"
+
+/* Function prototypes */
+
+static int rwl_get_file_size(char *file_name);
+static int remote_shell_async_exec(char *buf_ptr);
+static int remote_shell_sync_exec(char *cmd_buf_ptr, void *wl);
+
+
+/* Data structure to hold async shell information */
+typedef struct remote_shell_async {
+	pid_t PID;
+	char file_name[MAX_ASYNC_FILE_LENGTH];
+} remote_shell_async_t;
+
+remote_shell_async_t g_async_resp[MAX_SHELL_ASYNC_RESP];
+
+extern int g_shellsync_pid;
+
+extern unsigned char g_return_stat;
+extern void rwl_chld_handler(int num);
+extern int set_ctrlc;
+extern void handle_ctrlc(int unused);
+
+/* Global variable to store the timeout value for the shell commands */
+static int g_shellsync_timeout = DEFAULT_SHELL_TIMEOUT;
+char globalbuffer[MAX_SHELL_CMD_LENTH];
+
+/* Wait for process termination.
+ * This function returns immediately if the child has
+ * already exited (zombie process)
+ */
+static void
+sigchld_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+
+	while (waitpid(-1, NULL, WNOHANG) > 0);
+}
+
+/* Create a main directory \tmp\RWL\ for the shell response files */
+int
+rwl_create_dir(void)
+{
+	if (mkdir(SHELL_RESP_PATH, FILE_PERMISSION) < 0) {
+		if (errno != EEXIST)
+			return BCME_ERROR;
+	}
+
+	return SUCCESS;
+}
+
+/* Main function for shell command execution */
+int
+remote_shell_execute(char* buf_ptr, void *wl)
+{
+	char *async_cmd_flag;
+	int msg_len;
+
+	/* Check for the "%" token in the buffer from client
+	 * If "%" token is present, execute asynchronous process
+	 * else, execute synchronous shell process
+	 */
+	async_cmd_flag = strstr((char*)buf_ptr, ASYNC_SHELL_CHAR);
+
+	if ((async_cmd_flag != NULL) && (!strcmp(async_cmd_flag, ASYNC_SHELL_CHAR))) {
+		g_shellsync_pid = SHELL_ASYNCCMD_ID;
+		msg_len = remote_shell_async_exec(buf_ptr);
+	}
+	else {
+		msg_len = remote_shell_sync_exec(buf_ptr, wl);
+		strcpy(buf_ptr, globalbuffer);
+	}
+	return msg_len;
+}
+
+/* Function to get the shell response from the file */
+int
+remote_shell_async_get_resp(char* shell_fname, char* buf_ptr, int msg_len)
+{
+	int sts = 0;
+	FILE *shell_fpt;
+
+	shell_fpt = fopen(shell_fname, "rb");
+
+	if (shell_fpt == NULL) {
+		DPRINT_ERR(ERR, "\nShell Cmd:File open error\n");
+		return sts;
+	}
+
+	/* If there is any response from the shell, Read the file and
+	 * update the buffer for the shell response
+	 * else Just send the return value of the command executed
+	 */
+	if (g_shellsync_pid != SHELL_ASYNCCMD_ID) {
+		if (msg_len)
+			sts  = fread(buf_ptr, sizeof(char), msg_len, shell_fpt);
+		fscanf(shell_fpt, "%2x", &sts);
+	}
+	else
+		sts  = fread(buf_ptr, sizeof(char), MAX_SHELL_CMD_LENTH, shell_fpt);
+
+	fclose(shell_fpt);
+
+	remove(shell_fname);
+
+	DPRINT_DBG(OUTPUT, "\n Resp buff from shell cmdis %s\n", buf_ptr);
+
+	return sts;
+}
+
+/*
+ * Function to get the shell response length
+ * by opening the file containing the shell response
+ * and get the total file size.
+ * For a given input file name it returns File size.
+ */
+static int
+rwl_get_file_size(char *file_name)
+{
+	FILE *shell_fpt;
+	int filesize = 0;
+
+	shell_fpt = fopen(file_name, "rb");
+
+	if (shell_fpt == NULL) {
+		DPRINT_DBG(OUTPUT, "\nShell Cmd:File open error\n");
+		return filesize;
+	}
+
+	/* obtain file size */
+	if (fseek(shell_fpt, 0, SEEK_END) < 0)
+		return filesize;
+
+	filesize = ftell(shell_fpt);
+	fclose(shell_fpt);
+
+	return filesize;
+}
+
+/*
+ * Function for executing asynchronous shell comamnd
+ * Stores the results in async temp file and returns the PID
+ */
+static int
+remote_shell_async_exec(char *buf_ptr)
+{
+	int PID_val = 0, val, msg_len, sts;
+	FILE *fpt;
+	int async_count = 0; /* counter needs to be initialized */
+	struct sigaction sa;
+	char pid_search_cmd[MAX_PID_CMD_LENGTH];
+	char pid_resp_buf[MAX_PID_RESP_LENTH];
+	char temp_async_file_name[MAX_ASYNC_FILE_LENGTH];
+	pid_t pid;
+	char *pid_token, next_pid[PID_TOKEN_SIZE][PID_TOKEN_SIZE];
+	struct utsname name;
+
+	/* Call the signal handler for reaping defunct or zombie process */
+	sa.sa_handler = sigchld_handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_RESTART;
+	if (sigaction(SIGCHLD, &sa, NULL) == -1) {
+		perror("sigaction:");
+	}
+
+	/* Store the async file name if that async process is not killed.
+	 * Async file name: async_temp_0...5
+	 */
+	for (val = 0; val < MAX_SHELL_ASYNC_RESP; val++) {
+		if (g_async_resp[val].PID > 0) {
+			async_count++;
+		} else {
+			sprintf(g_async_resp[val].file_name, "%s%d", "async_temp_", val);
+			break;
+		}
+	}
+	sprintf(temp_async_file_name, "%s%s", SHELL_RESP_PATH,
+		g_async_resp[val].file_name);
+
+	DPRINT_DBG(OUTPUT, "\nasync_count:%d\n", async_count);
+	if (async_count >= MAX_SHELL_ASYNC_RESP) {
+		sprintf(buf_ptr, "\n%s\n", "Exceeded max async process forking");
+		return BCME_ERROR;
+	}
+
+	/* Open a child process. The fork will return the PID of the child process
+	 * (i.e) defunct process PID in parent's thread of execution. Zero is returned
+	 * for child's thread of execution.
+	 */
+	if ((pid = fork()) == 0) {
+		/* Redirect the async process output to the async file
+		 * Then after the client executes the kill command for that
+		 * async process, the file will give the status of async process
+		 */
+		strtok(buf_ptr, ASYNC_SHELL_CHAR); /* Remove % character from the command buf */
+		uname(&name);
+		/*
+		* Checking for mips architecture
+		* different command for mips and x86
+		*/
+		if (strncmp(name.machine, "mips", sizeof(name.machine)) != 0) {
+			strcat(buf_ptr, "&> "); /* buf_ptr is now "ping 127.0.0.1&> " */
+			strcat(buf_ptr, temp_async_file_name); /* Add path \tmp\RWL\async_temp_* */
+		}
+		else {
+			strcat(buf_ptr, " > "); /* buf_ptr is now "ping 127.0.0.1> " */
+			strcat(buf_ptr, temp_async_file_name); /* Add path \tmp\RWL\async_temp_* */
+			strcat(buf_ptr, " 2>&1 &");
+		}
+		if ((sts = execl(SH_PATH, "sh", "-c", buf_ptr, NULL)) == -1) {
+			sprintf(buf_ptr, "%s\n", "Not able to execute shell cmd");
+			return BCME_ERROR;
+		}
+		exit(0);
+	} /* end of fork */
+
+	if (pid < 0) {
+		perror("\nFork error:");
+		sprintf(buf_ptr, "%s\n", "Forking async process failed");
+		return BCME_ERROR;
+	}
+
+	/* Find the PID of the running process (for ex: ping)
+	 * pidof -s options returns latest PID of the command.
+	 */
+	strtok(buf_ptr, " ");
+
+	uname(&name);
+	/* Checking for mips architecture */
+	if (strncmp(name.machine, "mips", sizeof(name.machine)) != 0)
+		sprintf(pid_search_cmd, "pidof -s %s", buf_ptr);
+	else
+		sprintf(pid_search_cmd, "pidof %s", buf_ptr);
+
+	sleep(1);
+
+	/* Execute the command e.g "pidof ping" */
+	if ((fpt = popen(pid_search_cmd, "r")) == NULL) {
+		sprintf(buf_ptr, "%s\n", "Can't return PID");
+		return BCME_ERROR;
+	}
+
+	/* Get the PID and copy the PID in buf_ptr to send to the client */
+	fgets(pid_resp_buf, sizeof(pid_resp_buf), fpt);
+
+	/* Checking for mips architecture */
+	if (strncmp(name.machine, "mips", sizeof(name.machine)) != 0) {
+		PID_val = atoi(pid_resp_buf);
+	}
+	else {
+		/* code to extract the correct PID */
+		pid_token = strtok_r(pid_resp_buf, " ", (char **)next_pid);
+		/* the pid buffer will terminate with a '\n' */
+		while (pid_token != NULL && *pid_token != '\n') {
+			PID_val = atoi(pid_token);
+			pid_token = strtok_r(NULL, " ", (char **)next_pid);
+		}
+	}
+	if (PID_val == 0) {
+		msg_len = rwl_get_file_size(temp_async_file_name);
+		remote_shell_async_get_resp(temp_async_file_name, buf_ptr, msg_len);
+
+	} else {
+		g_async_resp[val].PID = PID_val;
+		/* Update PID value in buffer to send it to client */
+		sprintf(buf_ptr, "%d", PID_val);
+		msg_len = strlen(buf_ptr);
+	}
+
+	pclose(fpt);
+	/* In async case, the PID value will be copied to the input buffer only
+	 * and there is no need of getting the response from the file. So return
+	 * value can be -1.
+	 */
+	return msg_len;
+}
+
+/* Process for 'kill' command.
+ * Kill command can also be used from the client to get the
+ * result of asynchronous command and actually kill the mentioned process
+ */
+static int
+remote_kill_cmd_exec(char *cmd_buf_ptr)
+{
+	char file_name[MAX_ASYNC_FILE_LENGTH];
+	int  PID_val = 0, val, msg_len;
+	FILE *fpt;
+	char *pid_token, next_pid[PID_TOKEN_SIZE][PID_TOKEN_SIZE];
+
+	system(cmd_buf_ptr);
+
+	/* Parse the PID val from the kill command.
+	 */
+	pid_token = strtok_r(cmd_buf_ptr, " ", (char **)next_pid);
+	while (pid_token != NULL && *pid_token != '\n') {
+		/* to extract the PID from the kill command */
+		PID_val = atoi(pid_token);
+		pid_token = strtok_r(NULL, " ", (char **)next_pid);
+	}
+
+	/* Check for the matching PID from the async structure and
+	 * give the last 256 bytes statistics of the async process
+	 * that was running
+	 */
+	for (val = 0; val < MAX_SHELL_ASYNC_RESP; ++val) {
+		if (g_async_resp[val].PID == PID_val) {
+			/* We found a match here. Hence get the response now from the
+			 * corresponding async response file
+			 */
+			sprintf(file_name, "%s%s", SHELL_RESP_PATH, g_async_resp[val].file_name);
+			msg_len = rwl_get_file_size(file_name);
+			if (msg_len > 0) {
+				if ((fpt = fopen(file_name, "rb")) == NULL) {
+					DPRINT_DBG(OUTPUT, "\nShell Cmd:File open error\n");
+					return BCME_ERROR;
+				}
+
+				if (fseek(fpt, 0, SEEK_SET) < 0) {
+					fclose(fpt);
+					return BCME_ERROR;
+				}
+
+				if (fread(cmd_buf_ptr, sizeof(char), MAX_SHELL_CMD_LENTH,
+					fpt) <= 0) {
+					sprintf(cmd_buf_ptr, "%s\n", "Shell Resp:Reading error");
+					fclose(fpt);
+					return BCME_ERROR;
+				}
+
+			fclose(fpt);
+			}
+			else
+				sprintf(cmd_buf_ptr, "ed %d: No Response\n", PID_val);
+			remove(g_async_resp[val].file_name);
+
+			g_async_resp[val].PID = 0;
+			break;
+		}
+	}
+	return MAX_SHELL_CMD_LENTH;
+}
+
+/* Handle --timeout command line option for linux servers */
+int
+shell_timeout_cmd(char *cmd_buf_ptr, char *sync_file_name)
+{
+	char *token1, *token2, *nexttoken;
+	FILE* fp;
+	int msg_len;
+
+	token1 = strtok_r(cmd_buf_ptr, "--timeout ", &nexttoken);
+	if (token1)
+		token2 = strtok_r(NULL, token1, &nexttoken);
+	if (token1 == NULL || atoi(token1) <= 0 || token2 == NULL) {
+		fp = fopen(sync_file_name, "w+");
+		fprintf(fp, "Usage: ./wl --<transport> <ip/mac> sh"
+			"--timeout <timeout value> <shell command>\n");
+		fprintf(fp, "Eg: ./wl --socket 172.22.65.226 sh --timeout 15 ls\n");
+		fflush(fp);
+		msg_len = rwl_get_file_size(sync_file_name);
+		strcpy(cmd_buf_ptr, sync_file_name);
+		fclose(fp);
+		strcpy(globalbuffer, sync_file_name);
+		printf("Fix timeout problem in socket!!!!!\n");
+		return msg_len;
+	}
+	else
+		g_shellsync_timeout = atoi(token1);
+	return BCME_OK;
+}
+
+/* Handle synchronous shell commands here */
+static int
+remote_shell_sync_exec(char *cmd_buf_ptr, void *wl)
+{
+	char *kill_cmd_token;
+	char sync_file_name[] = TEMPLATE;
+	int fd, msg_len;
+	char cmd[(strlen(cmd_buf_ptr) + 1)];
+	int pid, status, pid_final;
+	char buf[SHELL_RESP_SIZE], cmd_find_lastpid[PID_SEARCH_CMD_SIZE];
+	int nbytes = 0;
+	int child_status;
+	static int sent_once = 0;
+	struct utsname name;
+	FILE *fpt;
+
+	/* Default Size of Return Value of the shell command is 2bytes */
+
+	kill_cmd_token =  strstr(cmd_buf_ptr, "kill");
+
+	/* Synchronous Kill command processing is handled separately */
+	if (kill_cmd_token != NULL) {
+		msg_len = remote_kill_cmd_exec(cmd_buf_ptr);
+		remote_tx_response(wl, cmd_buf_ptr, msg_len);
+		return 0;
+	}
+
+
+	/* Process synchronous command other than kill command */
+	if ((fd = mkstemp(sync_file_name)) < 0) {
+		perror("mkstemp failed");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		sprintf(cmd_buf_ptr, "%s\n", "mkstemp failed");
+		return BCME_ERROR;
+	}
+
+	close(fd);
+
+	strcpy(cmd, cmd_buf_ptr);
+	/* Synchronous timeout command processing is handled separately */
+	if (strstr(cmd_buf_ptr, "--timeout") != NULL) {
+		if ((msg_len = shell_timeout_cmd (cmd, sync_file_name) > 0)) {
+			/* Signal end of command output */
+			g_rem_ptr->msg.len = 0;
+			g_rem_ptr->msg.cmd = g_return_stat;
+			remote_tx_response(wl, NULL, 0);
+			return msg_len;
+		} else {
+			/* Parse out --timeout <val> since command is successful
+			 * point buffer to the shell command
+			 */
+			strcpy(cmd, cmd_buf_ptr);
+			strtok_r(cmd, " ", &cmd_buf_ptr);
+			strcpy(cmd, cmd_buf_ptr);
+			strtok_r(cmd, " ", &cmd_buf_ptr);
+		}
+	}
+
+	/* Schedule an ALARM in case of timeout value of SHELL_TIMEOUT seconds */
+	/* Defalut time out only in case of Non socket transport */
+	alarm(g_shellsync_timeout);
+	/* registering the relevant signals to handle end of child process,
+	 * the ctrl+c event on the server side and the kill command on the
+	 * server process
+	 */
+	signal(SIGCHLD, rwl_chld_handler);
+	signal(SIGINT, handle_ctrlc);
+	signal(SIGTERM, handle_ctrlc);
+
+	/* Set g_sig_chld before forking */
+	g_sig_chld = 1;
+
+	if (strcmp("reboot", cmd_buf_ptr) == 0) { /* reboot command */
+		memset(buf, 0, sizeof(buf));
+		strncpy(buf, REBOOT_MSG, sizeof(REBOOT_MSG));
+		remote_tx_response(wl, buf, 0);
+
+		/* Signal end of command output */
+		g_rem_ptr->msg.len = 0;
+		g_rem_ptr->msg.cmd = 0;
+		remote_tx_response(wl, NULL, 0);
+		sleep(1);
+
+		/* Clean up the temp file */
+		remove(sync_file_name);
+	}
+
+	if ((pid = fork()) == 0) {
+		close(STDOUT_FILENO);
+		fd = open(sync_file_name, O_WRONLY|O_SYNC);
+		/* Redirect stdin to dev/null. This handles un usual commands like
+		 * sh cat from the client side
+		 */
+		close(STDIN_FILENO);
+		open("/dev/null", O_RDONLY);
+		close(STDERR_FILENO);
+		fcntl(fd, F_DUPFD, STDERR_FILENO);
+		if ((status = execl(SH_PATH, "sh", "-c", cmd_buf_ptr, NULL)) == -1) {
+			perror("Exec error");
+
+		}
+	} /* end of fork */
+
+	g_shellsync_pid = pid;
+	/* The g_return_stat is being set for short commands */
+	waitpid(g_shellsync_pid, &child_status, WNOHANG);
+	if (WIFEXITED(child_status))
+		g_return_stat = WEXITSTATUS(child_status);
+	else
+		g_return_stat = 1;
+
+	/* Read file in the interim from a temp file and send back the results */
+	fd = open(sync_file_name, O_RDONLY|O_SYNC);
+
+	while (1) {
+		/* read file in the interim and send back the results */
+		nbytes = read(fd, buf, SHELL_RESP_SIZE);
+		g_rem_ptr->msg.len = nbytes;
+		if (nbytes > 0) {
+			remote_tx_response(wl, buf, 0);
+#ifdef RWL_SERIAL
+			/* usleep introduced for flooding of data over serial port */
+			usleep(1);
+#endif
+		}
+		if (get_ctrlc_header(wl) >= 0) {
+			if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG) {
+				uname(&name);
+				/* Checking for mips architecture
+				 * The mips machine responds differently to
+				 * execl command. so the pid is incremented
+				 * to kill the right command.
+				 */
+				if (strncmp(name.machine, "mips", sizeof(name.machine)) == 0)
+					pid++;
+				if (strncmp(name.machine, "armv5tel", sizeof(name.machine)) == 0) {
+					snprintf(cmd_find_lastpid, sizeof(cmd_find_lastpid),
+						"ps | awk \'PRINT $1\' | tail -n 1");
+					if ((fpt = popen(cmd_find_lastpid, "r")) == NULL) {
+						sprintf(buf, "%s\n", "Can't return PID");
+						return BCME_ERROR;
+					}
+					fgets(cmd_find_lastpid, sizeof(cmd_find_lastpid), fpt);
+					pid_final = atoi(cmd_find_lastpid);
+					while (pid <= pid_final) {
+						kill(pid, SIGKILL);
+						pid++;
+					}
+					pclose(fpt);
+				}
+				else {
+					kill(pid, SIGKILL);
+				}
+				break;
+			}
+		}
+		if (get_ctrlc_header(wl) >= 0) {
+			if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG) {
+				uname(&name);
+				/* Checking for mips architecture
+				 * The mips machine responds differently to
+				 * execl command. so the pid is incremented
+				 * to kill the right command.
+				 */
+				if (strncmp(name.machine, "mips", sizeof(name.machine)) == 0) {
+					pid++;
+					kill(pid, SIGKILL);
+				}
+				/* Checking for arm architecture
+				 * The multiple commands would not work
+				 * for ctrl+C. So we kill the processes
+				 * spawned after the parent. This method has
+				 * its own limitations but the busybox in pxa
+				 * doesnot have many options to implement it better
+				 */
+				else {
+					if (strncmp(name.machine, "armv5tel",
+					sizeof(name.machine)) == 0) {
+						/* The command below is used to get the
+						 * PIDs and they are killed
+						 */
+						snprintf(cmd_find_lastpid,
+							sizeof(cmd_find_lastpid),
+							"ps | awk \'PRINT $1\' | tail -n 1");
+						if ((fpt = popen(cmd_find_lastpid, "r")) == NULL) {
+							sprintf(buf, "%s\n", "Can't return PID");
+							return BCME_ERROR;
+						}
+						fgets(cmd_find_lastpid, sizeof(cmd_find_lastpid),
+						fpt);
+						pid_final = atoi(cmd_find_lastpid);
+						while (pid <= pid_final) {
+							kill(pid, SIGKILL);
+							pid++;
+						}
+						pclose(fpt);
+					}
+					/* In the case of x86, on receiving ctrl+C
+					 * the child PIDs are obtained by searching
+					 * the parent PID to obtain the PIDs of the
+					 * and kill them
+					 */
+					else {
+						while (pid != 0) {
+							/* The commad below is used to get the
+							 * child PIDs by using their parent PID
+							 */
+							snprintf(cmd_find_lastpid,
+							sizeof(cmd_find_lastpid),
+							"ps al | awk \"{ if (\\$4 == %d)"
+							" {print \\$3}}\"| head -n 1",
+							g_shellsync_pid);
+							if ((fpt = popen(cmd_find_lastpid, "r"))
+								== NULL) {
+								sprintf(buf, "%s\n",
+									"Can't return PID");
+								return BCME_ERROR;
+							}
+							fgets(cmd_find_lastpid,
+								sizeof(cmd_find_lastpid),
+								fpt);
+							pid = atoi(cmd_find_lastpid);
+							if (pid == 0)
+								kill(g_shellsync_pid, SIGKILL);
+							else
+								kill(pid, SIGKILL);
+							pclose(fpt);
+						}
+					}
+				}
+				break;
+			}
+		}
+		if (set_ctrlc == 1) {
+			g_rem_ptr->msg.len = 0;
+			g_rem_ptr->msg.cmd = g_return_stat;
+			remote_tx_response(wl, NULL, g_return_stat);
+			unlink(sync_file_name);
+			kill(0, SIGKILL);
+		}
+		/* It is possible that the child would have exited
+		 * However we did not get a chance to read the file
+		 * In this case go once again and check the file
+		 */
+		if (!sent_once && !g_sig_chld) {
+			sent_once = 1;
+			continue;
+		}
+
+		if (!(g_sig_chld || nbytes))
+			break;
+	}
+	wait(NULL);
+	close(fd);
+
+	/* Signal end of command output */
+	g_rem_ptr->msg.len = 0;
+	g_rem_ptr->msg.cmd = g_return_stat;
+
+	remote_tx_response(wl, NULL, g_return_stat);
+	/* Cancel the time out alarm if any */
+	alarm(0);
+	sent_once = 0;
+	/* Clean up the temp file */
+	unlink(sync_file_name);
+	g_shellsync_timeout = DEFAULT_SHELL_TIMEOUT;
+	signal(SIGINT, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+
+	return BCME_OK;
+}
diff --git a/src/wl/exe/uamp.mk b/src/wl/exe/uamp.mk
new file mode 100644
index 0000000..78ba224
--- /dev/null
+++ b/src/wl/exe/uamp.mk
@@ -0,0 +1,62 @@
+#
+# GNUmakefile for wl/exe
+#
+# Copyright (c) 2000, Broadcom Corp.
+# $Id: uamp.mk 403251 2013-05-20 05:15:55Z $
+
+ifndef	SRCBASE
+	SRCBASE = ../..
+endif
+
+UNAME = $(shell uname)
+
+
+#-----------------------------------------------------------------
+# Linux build
+#
+
+# This should be one of values recognized in src/Makerules
+# 2) not windows, need to include first to pick up TARGETENV dependent vars
+include $(SRCBASE)/Makerules
+
+# Discard any "MMX" or other qualifications on x86 so that
+# any TARGETARCH containing x86 is just "x86"
+ifeq ($(findstring x86,$(TARGETARCH)),x86)
+        TARGETARCH = x86
+endif
+
+# $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files
+UAMP_OBJS      := uamp_linux.o
+
+# Prefix obj/<type>/TARGETARCH to produced .obj files
+UAMP_OBJS      := $(UAMP_OBJS:%.o=obj/uamp/$(TARGETARCH)/%.o)
+
+# TODO: Move final built objects to respective TARGETARCH dirs as well
+# Final exe names
+ARCH_SFX     := $(if $(findstring x86,$(TARGETARCH)),,$(TARGETARCH))
+UAMP_EXE       := uamp$(ARCH_SFX)
+
+# extra warnings
+CFLAGS += -Wextra $(CUSTOM_FLAGS)
+
+CFLAGS += -DLINUX -DWLBTAMP
+
+LDFLAGS += -pthread -lrt
+
+vpath %.c $(SRCBASE)/wl/sys $(WLAN_StdSrcDirsA) $(WLAN_ComponentSrcDirs)
+
+.PHONY: all
+all: $(UAMP_EXE)
+
+# Compilation targets
+obj/uamp/$(TARGETARCH)/%.o: %.c
+	@mkdir -pv $(@D)
+	$(CC) -c $(CFLAGS) -o $@ $^
+
+# Final link targets
+$(UAMP_EXE): $(UAMP_OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ 
+
+.PHONY: clean
+clean:
+	 rm -fv $(UAMP_EXE) $(UAMP_OBJS)
diff --git a/src/wl/exe/wlm.c b/src/wl/exe/wlm.c
new file mode 100644
index 0000000..013f8af
--- /dev/null
+++ b/src/wl/exe/wlm.c
@@ -0,0 +1,2266 @@
+/*
+ * Wlm (Wireless LAN Manufacturing) test library.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlm.c 425281 2013-09-23 17:40:45Z $
+ */
+
+#if defined(WIN32)
+#include <windows.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <bcmcdc.h>      // cdc_ioctl_t used in wlu_remote.h
+#if defined(WIN32)
+#include <bcmstdlib.h>
+#endif
+#include <bcmendian.h>
+#include <bcmutils.h>    // ARRAYSIZE, bcmerrorstr()
+#include <bcmsrom_fmt.h> // SROM4_WORDS
+#include <bcmsrom_tbl.h> // pavars_t
+#include <wlioctl.h>
+#if defined(WIN32)
+#include <epictrl.h>     // ADAPTER
+#endif
+#include <proto/ethernet.h>	 // ETHER_ADDR_LEN
+
+#include <sys/socket.h>
+#include <proto/bcmip.h> // ipv4_addr
+#include <arpa/inet.h>	// struct sockaddr_in
+#include <string.h>
+#include <signal.h>
+
+#include "wlu_remote.h"  // wl remote type defines (ex: NO_REMOTE)
+#include "wlu_pipe.h"    // rwl_open_pipe()
+#include "wlu.h"         // wl_ether_atoe()
+#include "wlm.h"
+#include "wlc_ppr.h"
+
+/* IOCTL swapping mode for Big Endian host with Little Endian dongle.  Default to off */
+#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 htodenum(i) (i)
+#define dtohenum(i) (i)
+
+#if defined(WIN32)
+static HANDLE irh;
+int adapter;
+#else
+static void * irh;
+#define HANDLE void *
+#endif
+
+#define MAX_INTERFACE_NAME_LENGTH     128
+static char interfaceName[MAX_INTERFACE_NAME_LENGTH + 1] = {0};
+static WLM_BAND curBand = WLM_BAND_AUTO;
+static int ioctl_version;
+
+extern int wl_os_type_get_rwl(void);
+extern void wl_os_type_set_rwl(int os_type);
+extern int wl_ir_init_rwl(HANDLE *irh);
+extern int wl_ir_init_adapter_rwl(HANDLE *irh, int adapter);
+extern void wl_close_rwl(int remote_type, HANDLE irh);
+extern int rwl_init_socket(void);
+
+extern int wlu_get(void *wl, int cmd, void *buf, int len);
+extern int wlu_set(void *wl, int cmd, void *buf, int len);
+
+extern int wlu_iovar_get(void *wl, const char *iovar, void *outbuf, int len);
+extern int wlu_iovar_set(void *wl, const char *iovar, void *param, int paramlen);
+extern int wlu_iovar_getint(void *wl, const char *iovar, int *pval);
+extern int wlu_iovar_setint(void *wl, const char *iovar, int val);
+
+extern int wlu_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr);
+extern int wlu_var_setbuf(void *wl, const char *iovar, void *param, int param_len);
+extern int wlu_var_getbuf_med(void *wl, const char *iovar, void *param, int parmlen, void **bufptr);
+extern int wlu_var_setbuf_med(void *wl, const char *iovar, void *param, int param_len);
+extern int wlu_var_getbuf_sm(void *wl, const char *iovar, void *param, int parmlen, void **bufptr);
+extern int wlu_var_setbuf_sm(void *wl, const char *iovar, void *param, int param_len);
+
+extern int wl_seq_batch_in_client(bool enable);
+extern int wl_seq_start(void *wl, cmd_t *cmd, char **argv);
+extern int wl_seq_stop(void *wl, cmd_t *cmd, char **argv);
+
+static int wlmPhyTypeGet(void);
+
+static const char *
+wlmLastError(void)
+{
+	static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
+	static char errorString[256];
+	int bcmerror;
+
+	if (wlu_iovar_getint(irh, "bcmerror", &bcmerror))
+		return "Failed to retrieve error";
+
+	if (bcmerror > 0 || bcmerror < BCME_LAST) {
+		sprintf(errorString, "Undefined error (%d)", bcmerror);
+	} else {
+		sprintf(errorString, "%s (%d)", bcmerrorstrtable[-bcmerror], bcmerror);
+	}
+
+	return errorString;
+}
+
+int wlmWLMVersionGet(const char **buffer)
+{
+	*buffer = WLM_VERSION_STR;
+	return TRUE;
+}
+
+int wlmApiInit(void)
+{
+	curBand = WLM_BAND_AUTO;
+	return TRUE;
+}
+
+int wlmApiCleanup(void)
+{
+	wl_close_rwl(rwl_get_remote_type(), irh);
+	irh = 0;
+	return TRUE;
+}
+
+int wlmSelectInterface(WLM_DUT_INTERFACE ifType, char *ifName,
+	WLM_DUT_SERVER_PORT dutServerPort, WLM_DUT_OS dutOs)
+{
+	int val;
+
+	/* close previous handle */
+	if (irh != NULL) {
+		wlmApiCleanup();
+	}
+
+	switch (ifType) {
+		case WLM_DUT_LOCAL:
+			rwl_set_remote_type(NO_REMOTE);
+			break;
+		case WLM_DUT_SERIAL:
+			rwl_set_remote_type(REMOTE_SERIAL);
+			break;
+		case WLM_DUT_SOCKET:
+			rwl_set_remote_type(REMOTE_SOCKET);
+			break;
+		case WLM_DUT_WIFI:
+			rwl_set_remote_type(REMOTE_WIFI);
+			break;
+		case WLM_DUT_DONGLE:
+			rwl_set_remote_type(REMOTE_DONGLE);
+			break;
+		default:
+			/* ERROR! Unknown interface! */
+			return FALSE;
+	}
+
+	if (ifName) {
+		strncpy(interfaceName, ifName, MAX_INTERFACE_NAME_LENGTH);
+		interfaceName[MAX_INTERFACE_NAME_LENGTH] = 0;
+	}
+
+	switch (dutOs) {
+		case WLM_DUT_OS_LINUX:
+			wl_os_type_set_rwl(LINUX_OS);
+			break;
+		case WLM_DUT_OS_WIN32:
+			wl_os_type_set_rwl(WIN32_OS);
+			break;
+		default:
+			/* ERROR! Unknown OS! */
+			return FALSE;
+	}
+
+	switch (rwl_get_remote_type()) {
+		struct ipv4_addr temp;
+		case REMOTE_SOCKET:
+			if (!wl_atoip(interfaceName, &temp)) {
+				printf("wlmSelectInterface: IP address invalid\n");
+				return FALSE;
+			}
+			rwl_set_server_ip(interfaceName);
+			rwl_set_server_port(dutServerPort);
+			rwl_init_socket();
+			break;
+		case REMOTE_SERIAL:
+			rwl_set_serial_port_name(interfaceName); /* x (port number) or /dev/ttySx */
+			if ((irh = rwl_open_pipe(rwl_get_remote_type(),
+				rwl_get_serial_port_name(), 0, 0)) == NULL) {
+				printf("wlmSelectInterface: rwl_open_pipe failed\n");
+				return FALSE;
+			}
+			break;
+		case REMOTE_DONGLE:
+			rwl_set_serial_port_name(interfaceName); /* COMx or /dev/ttySx */
+			if ((irh = rwl_open_pipe(rwl_get_remote_type(), "\0", 0, 0)) == NULL) {
+				printf("wlmSelectInterface: rwl_open_pipe failed\n");
+				return FALSE;
+			}
+			break;
+		case REMOTE_WIFI:
+			if (!wl_ether_atoe(interfaceName,
+				(struct ether_addr *)rwl_get_wifi_mac())) {
+				printf("wlmSelectInterface: ethernet MAC address invalid\n");
+				return FALSE;
+			}
+			/* intentionally no break here to pass through to NO_REMOTE case */
+		case NO_REMOTE:
+#if defined(WIN32)
+			adapter = atoi(interfaceName);
+			if (adapter == 0)
+				adapter = -1;
+
+			if (wl_ir_init_adapter_rwl(&irh, adapter) != 0) {
+				printf("wlmSelectInterface: Adapter %d init failed\n", adapter);
+				return FALSE;
+			}
+#else
+			if (wl_ir_init_rwl(&irh) != 0) {
+				printf("wlmSelectInterface: initialize failed\n");
+				return FALSE;
+			}
+#endif
+			break;
+		default:
+			/* ERROR! Invalid interface!
+			 * NOTE: API should not allow code to come here.
+			 */
+			return FALSE;
+	}
+
+	/* Query the IOCTL API version */
+	if (wlu_get(irh, WLC_GET_VERSION, &val, sizeof(int)) < 0) {
+		printf("wlmSelectInterface: IOCTL Version query failed\n");
+		return FALSE;
+	}
+
+	ioctl_version = dtoh32(val);
+	if (ioctl_version != WLC_IOCTL_VERSION &&
+	    ioctl_version != 1) {
+		printf("wlmSelectInterface: Version mismatch, please upgrade."
+		       "Got %d, expected %d or 1\n",
+		        ioctl_version, WLC_IOCTL_VERSION);
+		return FALSE;
+	}
+
+
+	return TRUE;
+}
+
+int wlmVersionGet(char *buf, int len)
+{
+	if (buf == 0) {
+		printf("wlmVersionGet: buffer invalid\n");
+		return FALSE;
+	}
+
+	memset(buf, 0, sizeof(buf));
+
+	/* query for 'ver' to get version info */
+	if (wlu_iovar_get(irh, "ver", buf, (len < WLC_IOCTL_SMLEN) ? len : WLC_IOCTL_SMLEN)) {
+		printf("wlmVersionGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmEnableAdapterUp(int enable)
+{
+	/*  Enable/disable adapter  */
+	if (enable)
+	{
+		if (wlu_set(irh, WLC_UP, NULL, 0)) {
+			printf("wlmEnableAdapterUp: %s\n", wlmLastError());
+			return FALSE;
+		}
+	}
+	else {
+		if (wlu_set(irh, WLC_DOWN, NULL, 0)) {
+			printf("wlmEnableAdapterUp: %s\n", wlmLastError());
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+int wlmIsAdapterUp(int *up)
+{
+	/*  Get 'isup' - check if adapter is up */
+	up = dtoh32(up);
+	if (wlu_get(irh, WLC_GET_UP, up, sizeof(int))) {
+		printf("wlmIsAdapterUp: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmMinPowerConsumption(int enable)
+{
+	if (wlu_iovar_setint(irh, "mpc", enable)) {
+		printf("wlmMinPowerConsumption: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmMimoPreambleGet(int* type)
+{
+	if (wlu_iovar_getint(irh, "mimo_preamble", type)) {
+		printf("wlmMimoPreambleGet(): %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmMimoPreambleSet(int type)
+{
+	if (wlu_iovar_setint(irh, "mimo_preamble", type)) {
+		printf("wlmMimoPreambleSet(): %s\n", wlmLastError());
+		return FALSE;
+	}
+	return  TRUE;
+}
+
+int wlmChannelSet(int channel)
+{
+
+	/* Check band lock first before set  channel */
+	if ((channel <= 14) && (curBand != WLM_BAND_2G)) {
+		curBand = WLM_BAND_2G;
+	} else if ((channel > 14) && (curBand != WLM_BAND_5G)) {
+		curBand = WLM_BAND_5G;
+	}
+
+	/* Set 'channel' */
+	channel = htod32(channel);
+	if (wlu_set(irh, WLC_SET_CHANNEL, &channel, sizeof(channel))) {
+		printf("wlmChannelSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRateSet(WLM_RATE rate)
+{
+	char aname[] = "a_rate";
+	char bgname[] = "bg_rate";
+	char *name;
+
+	switch (curBand) {
+	        case WLM_BAND_AUTO :
+			printf("wlmRateSet: must set channel or band lock first \n");
+			return FALSE;
+	        case WLM_BAND_DUAL :
+			printf("wlmRateSet: must set channel or band lock first\n");
+			return FALSE;
+		case WLM_BAND_5G :
+			name = (char *)aname;
+			break;
+		case WLM_BAND_2G :
+			name = (char *)bgname;
+			break;
+		default :
+			return FALSE;
+	}
+
+	rate = htod32(rate);
+	if (wlu_iovar_setint(irh, name, rate)) {
+		printf("wlmRateSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmLegacyRateSet(WLM_RATE rate)
+{
+	uint32 nrate = 0;
+
+	if (ioctl_version == 1) {
+		nrate |= (rate & OLD_NRATE_RATE_MASK);
+		nrate |= (OLD_NRATE_STF_SISO << OLD_NRATE_STF_SHIFT) & OLD_NRATE_STF_MASK;
+	} else {
+		nrate = WL_RSPEC_ENCODE_RATE;	/* 11abg */
+		nrate |= (rate & WL_RSPEC_RATE_MASK);
+	}
+
+	if (wlu_iovar_setint(irh, "nrate", (int)nrate)) {
+		printf("wlmMcsRateSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return  TRUE;
+}
+
+int wlmMcsRateSet(WLM_MCS_RATE mcs_rate, WLM_STF_MODE stf_mode)
+{
+	uint32 nrate = 0;
+	uint stf;
+
+	if (mcs_rate > 32) {
+		printf("wlmMcsRateSet: MCS %d out of range\n", mcs_rate);
+		return FALSE;
+	}
+
+	if (ioctl_version == 1) {
+		nrate |= mcs_rate;
+		nrate |= OLD_NRATE_MCS_INUSE;
+
+		if (!stf_mode) {
+			stf = 0;
+			if (mcs_rate <= HIGHEST_SINGLE_STREAM_MCS ||
+			    mcs_rate == 32)
+				stf = OLD_NRATE_STF_SISO;	/* SISO */
+			else
+				stf = OLD_NRATE_STF_SDM;	/* SDM */
+		} else
+			stf = stf_mode;
+
+		nrate |= (stf << OLD_NRATE_STF_SHIFT) & OLD_NRATE_STF_MASK;
+	} else {
+		nrate = WL_RSPEC_ENCODE_HT;	/* 11n HT */
+		nrate |= mcs_rate;
+
+		/* decode WLM stf value into tx expansion and STBC */
+		if (stf_mode == WLM_STF_MODE_CDD) {
+			nrate |= (1 << WL_RSPEC_TXEXP_SHIFT);
+		} else if (stf_mode == WLM_STF_MODE_STBC) {
+			nrate |= WL_RSPEC_STBC;
+		}
+	}
+
+	if (wlu_iovar_setint(irh, "nrate", (int)nrate)) {
+		printf("wlmMcsRateSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return  TRUE;
+}
+
+int wlmPreambleSet(WLM_PREAMBLE preamble)
+{
+	preamble = htod32(preamble);
+
+	if (wlu_set(irh, WLC_SET_PLCPHDR, &preamble, sizeof(preamble))) {
+		printf("wlmPreambleSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmBandSet(WLM_BAND band)
+{
+	band = htod32(band);
+
+	if (wlu_set(irh, WLC_SET_BAND, (void *)&band, sizeof(band))) {
+		printf("wlmBandSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	curBand = band;
+
+	return TRUE;
+}
+
+int wlmGetBandList(WLM_BAND * bands)
+{
+	unsigned int list[3];
+	unsigned int i;
+
+	if (wlu_get(irh, WLC_GET_BANDLIST, list, sizeof(list))) {
+		printf("wlmGetBandList: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	list[0] = dtoh32(list[0]);
+	list[1] = dtoh32(list[1]);
+	list[2] = dtoh32(list[2]);
+
+	/* list[0] is count, followed by 'count' bands */
+
+	if (list[0] > 2)
+		list[0] = 2;
+
+	for (i = 1, *bands = (WLM_BAND)0; i <= list[0]; i++)
+		*bands |= list[i];
+
+	return TRUE;
+}
+
+int wlmGmodeSet(WLM_GMODE gmode)
+{
+	/*  Set 'gmode' - select mode in 2.4G band */
+	gmode = htod32(gmode);
+
+	if (wlu_set(irh, WLC_SET_GMODE, (void *)&gmode, sizeof(gmode))) {
+		printf("wlmGmodeSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRxAntSet(int antenna)
+{
+	/*  Set 'antdiv' - select receive antenna */
+	antenna = htod32(antenna);
+
+	if (wlu_set(irh, WLC_SET_ANTDIV, &antenna, sizeof(antenna))) {
+		printf("wlmRxAntSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmTxAntSet(int antenna)
+{
+	/*  Set 'txant' - select transmit antenna */
+	antenna = htod32(antenna);
+
+	if (wlu_set(irh, WLC_SET_TXANT, &antenna, sizeof(antenna))) {
+		printf("wlmTxAntSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmEstimatedPowerGet(int *estPower, int chain)
+{
+	int mimo;
+	int is2g;
+
+	size_t pprsize = ppr_ser_size_by_bw(ppr_get_max_bw());
+	/* Allocate memory for structure and 2 serialisation buffer */
+	tx_pwr_rpt_t *ppr_wl = (tx_pwr_rpt_t *)malloc(sizeof(tx_pwr_rpt_t) + pprsize*2);
+	uint8 *ppr_ser;
+	if (ppr_wl == NULL)
+		return FALSE;
+
+	ppr_ser = ppr_wl->pprdata;
+	memset(ppr_wl, 0, sizeof(tx_pwr_rpt_t) + pprsize*2);
+	ppr_wl->board_limit_len  = pprsize;
+	ppr_wl->target_len       = pprsize;
+	ppr_wl->version          = TX_POWER_T_VERSION;
+	/* init allocated mem for serialisation */
+	ppr_init_ser_mem_by_bw(ppr_ser, ppr_get_max_bw(), ppr_wl->board_limit_len);
+	ppr_ser += ppr_wl->board_limit_len;
+	ppr_init_ser_mem_by_bw(ppr_ser, ppr_get_max_bw(), ppr_wl->target_len);
+
+
+	if (wlu_get(irh, WLC_CURRENT_PWR, ppr_wl, sizeof(tx_pwr_rpt_t) + pprsize*2) < 0) {
+		printf("wlmEstimatedPowerGet: %s\n", wlmLastError());
+		free(ppr_wl);
+		return FALSE;
+	}
+	ppr_wl->flags = dtoh32(ppr_wl->flags);
+	ppr_wl->chanspec = dtohchanspec(ppr_wl->chanspec);
+	mimo = (ppr_wl->flags & WL_TX_POWER_F_MIMO);
+
+	/* value returned is in units of quarter dBm, need to multiply by 250 to get milli-dBm */
+	if (mimo) {
+		*estPower = ppr_wl->est_Pout[chain] * 250;
+	} else {
+		*estPower = ppr_wl->est_Pout[0] * 250;
+	}
+
+	if (ioctl_version == 1) {
+		is2g = LCHSPEC_IS2G(ppr_wl->chanspec);
+	} else {
+		is2g = CHSPEC_IS2G(ppr_wl->chanspec);
+	}
+
+	if (!mimo && is2g) {
+		*estPower = ppr_wl->est_Pout_cck * 250;
+	}
+
+	free(ppr_wl);
+	return TRUE;
+}
+
+int wlmTxPowerGet(int *power)
+{
+	int val;
+
+	if ((wlu_iovar_getint(irh, "qtxpower", &val)) < 0) {
+		printf("wlmTxPowerGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	val &= ~WL_TXPWR_OVERRIDE;
+
+	/* value returned is in units of quarter dBm, need to multiply by 250 to get milli-dBm */
+	*power = val * 250;
+	return TRUE;
+}
+
+int wlmTxPowerSet(int powerValue)
+{
+	int newValue = 0;
+
+	if (powerValue == -1) {
+		newValue = 127;		/* Max val of 127 qdbm */
+	} else {
+		/* expected to be in units of quarter dBm */
+		newValue = powerValue / 250;
+		newValue |= WL_TXPWR_OVERRIDE;
+	}
+
+	if (wlu_iovar_setint(irh, "qtxpower", newValue)) {
+		printf("wlmTxPowerSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int wlmPhyTypeGet(void)
+{
+
+	int phytype = PHY_TYPE_NULL;
+
+	if (wlu_get(irh, WLC_GET_PHYTYPE, &phytype, sizeof(int)) < 0) {
+	        printf("wlmPhyTypeGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return phytype;
+}
+
+int wlmPaParametersGet(WLM_BANDRANGE bandrange,
+	unsigned int *a1, unsigned int *b0, unsigned int *b1)
+{
+	uint16 inpa[WL_PHY_PAVARS_LEN];
+	void *ptr = NULL;
+	uint16 *outpa;
+	int i = 0;
+	int phytype = PHY_TYPE_NULL;
+
+	*a1 = 0;
+	*b0 = 0;
+	*b1 = 0;
+
+	/* Do not rely on user to have knowledge of phytype */
+	phytype = wlmPhyTypeGet();
+	if (phytype != PHY_TYPE_NULL) {
+		inpa[i++] = phytype;
+		inpa[i++] = bandrange;
+		inpa[i++] = 0;  /* Fix me: default with chain 0 for all SISO system */
+	} else {
+		printf("wlmPaParametersGet: unknow Phy type\n");
+		return FALSE;
+	}
+
+	if (wlu_var_getbuf_sm(irh, "pavars", inpa, WL_PHY_PAVARS_LEN * sizeof(uint16), &ptr)) {
+		printf("wlmPaParametersGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	outpa = (uint16 *)ptr;
+	*b0 = outpa[i++];
+	*b1 = outpa[i++];
+	*a1 = outpa[i++];
+
+	return TRUE;
+}
+
+int wlmPaParametersSet(WLM_BANDRANGE bandrange,
+	unsigned int a1, unsigned int b0, unsigned int b1)
+{
+	uint16 inpa[WL_PHY_PAVARS_LEN];
+	int i = 0;
+	int phytype = PHY_TYPE_NULL;
+
+	/* Do not rely on user to have knowledge of phy type */
+	phytype = wlmPhyTypeGet();
+	if (phytype != PHY_TYPE_NULL) {
+		inpa[i++] = phytype;
+		inpa[i++] = bandrange;
+		inpa[i++] = 0;  /* Fix me: default with chain 0 for all SISO system */
+	} else {
+	        printf("wlmPaParametersSet: unknow Phy type\n");
+		return FALSE;
+	}
+
+	inpa[i++] = b0;
+	inpa[i++] = b1;
+	inpa[i++] = a1;
+
+	if (wlu_var_setbuf_sm(irh, "pavars", inpa, WL_PHY_PAVARS_LEN * sizeof(uint16))) {
+		printf("wlmPaParametersSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+int wlmMIMOPaParametersGet(WLM_BANDRANGE bandrange, int chain,
+	unsigned int *a1, unsigned int *b0, unsigned int *b1)
+{
+	uint16 inpa[WL_PHY_PAVARS_LEN];
+	void *ptr = NULL;
+	uint16 *outpa;
+	int i = 0;
+	int phytype = PHY_TYPE_NULL;
+
+	/* Do not rely on user to have knowledge of phytype */
+	phytype = wlmPhyTypeGet();
+	if (phytype != PHY_TYPE_NULL) {
+		inpa[i++] = phytype;
+		inpa[i++] = bandrange;
+		inpa[i++] = chain;
+	} else {
+		printf("wlmMIMOPaParametersGet: unknow Phy type\n");
+		return FALSE;
+	}
+
+	if (wlu_var_getbuf_sm(irh, "pavars", inpa, WL_PHY_PAVARS_LEN * sizeof(uint16), &ptr)) {
+		printf("wlmMIMOPaParametersGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	outpa = (uint16 *)ptr;
+	*a1 = outpa[i++];
+	*b0 = outpa[i++];
+	*b1 = outpa[i++];
+
+	return TRUE;
+}
+
+int wlmMIMOPaParametersSet(WLM_BANDRANGE bandrange, int chain,
+	unsigned int a1, unsigned int b0, unsigned int b1)
+{
+	uint16 inpa[WL_PHY_PAVARS_LEN];
+	int i = 0;
+	int phytype = PHY_TYPE_NULL;
+
+	/* Do not rely on user to have knowledge of phy type */
+	phytype = wlmPhyTypeGet();
+	if (phytype != PHY_TYPE_NULL) {
+	        inpa[i++] = phytype;
+		inpa[i++] = bandrange;
+		inpa[i++] = chain;
+	} else {
+	        printf("wlmMIMOPaParametersSet: unknow Phy type\n");
+		return FALSE;
+	}
+
+	inpa[i++] = a1;
+	inpa[i++] = b0;
+	inpa[i++] = b1;
+
+	if (wlu_var_setbuf_sm(irh, "pavars", inpa, WL_PHY_PAVARS_LEN * sizeof(uint16))) {
+		printf("wlmMIMOPaParametersSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmMacAddrGet(char *macAddr, int length)
+{
+	struct ether_addr ea = {{0, 0, 0, 0, 0, 0}};
+
+	/* query for 'cur_etheraddr' to get MAC address */
+	if (wlu_iovar_get(irh, "cur_etheraddr", &ea, ETHER_ADDR_LEN) < 0) {
+		printf("wlmMacAddrGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	strncpy(macAddr, wl_ether_etoa(&ea), length);
+
+	return TRUE;
+}
+
+int wlmMacAddrSet(const char* macAddr)
+{
+	struct ether_addr ea;
+
+	if (!wl_ether_atoe(macAddr, &ea)) {
+		printf("wlmMacAddrSet: MAC address invalid: %s\n", macAddr);
+		return FALSE;
+	}
+
+	/*  Set 'cur_etheraddr' to set MAC address */
+	if (wlu_iovar_set(irh, "cur_etheraddr", (void *)&ea, ETHER_ADDR_LEN)) {
+		printf("wlmMacAddrSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmEnableCarrierTone(int enable, int channel)
+{
+	int val = channel;
+
+	if (!enable) {
+		val = 0;
+	}
+	else {
+		wlmEnableAdapterUp(1);
+		if (wlu_set(irh, WLC_OUT, NULL, 0) < 0) {
+		printf("wlmEnableCarrierTone: %s\n", wlmLastError());
+		return FALSE;
+		}
+	}
+	val = htod32(val);
+	if (wlu_set(irh, WLC_FREQ_ACCURACY, &val, sizeof(int)) < 0) {
+		printf("wlmEnableCarrierTone: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmEnableEVMTest(int enable, WLM_RATE rate, int channel)
+{
+	int val[3] = {0};
+	val[1] = WLM_RATE_1M; /* default value */
+	if (enable) {
+		val[0] = htod32(channel);
+		val[1] = htod32(rate);
+		wlmEnableAdapterUp(1);
+		if (wlu_set(irh, WLC_OUT, NULL, 0) < 0) {
+			printf("wlmEnableEVMTest: %s\n", wlmLastError());
+			return FALSE;
+		}
+	}
+	if (wlu_set(irh, WLC_EVM, val, sizeof(val)) < 0) {
+		printf("wlmEnableEVMTest: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmTxPacketStart(unsigned int interPacketDelay,
+	unsigned int numPackets, unsigned int packetLength,
+	const char* destMac, int withAck, int syncMode)
+{
+	wl_pkteng_t pkteng;
+
+	if (!wl_ether_atoe(destMac, (struct ether_addr *)&pkteng.dest)) {
+		printf("wlmTxPacketStart: destMac invalid\n");
+		return FALSE;
+	}
+
+	pkteng.flags = withAck ? WL_PKTENG_PER_TX_WITH_ACK_START : WL_PKTENG_PER_TX_START;
+
+	if (syncMode)
+		pkteng.flags |= WL_PKTENG_SYNCHRONOUS;
+	else
+		pkteng.flags &= ~WL_PKTENG_SYNCHRONOUS;
+
+	pkteng.delay = interPacketDelay;
+	pkteng.length = packetLength;
+	pkteng.nframes = numPackets;
+
+	pkteng.seqno = 0;			/* not used */
+	pkteng.src = ether_null;	/* implies current ether addr */
+
+	if (wlu_var_setbuf(irh, "pkteng", &pkteng, sizeof(pkteng))) {
+		printf("wlmTxPacketStart: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmTxPacketStop(void)
+{
+	wl_pkteng_t pkteng;
+
+	memset(&pkteng, 0, sizeof(pkteng));
+	pkteng.flags = WL_PKTENG_PER_TX_STOP;
+
+	if (wlu_var_setbuf(irh, "pkteng", &pkteng, sizeof(pkteng)) < 0) {
+		printf("wlmTxPacketStop: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRxPacketStart(const char* srcMac, int withAck,
+	int syncMode, unsigned int numPackets, unsigned int timeout)
+{
+	wl_pkteng_t pkteng;
+
+	if (!wl_ether_atoe(srcMac, (struct ether_addr *)&pkteng.dest)) {
+		printf("wlmRxPacketStart: srcMac invalid\n");
+		return FALSE;
+	}
+
+	pkteng.flags = withAck ? WL_PKTENG_PER_RX_WITH_ACK_START : WL_PKTENG_PER_RX_START;
+
+	if (syncMode) {
+		pkteng.flags |= WL_PKTENG_SYNCHRONOUS;
+		pkteng.nframes = numPackets;
+		pkteng.delay = timeout;
+	}
+	else {
+		pkteng.flags &= ~WL_PKTENG_SYNCHRONOUS;
+		pkteng.length = 0;
+	}
+
+	if (wlu_var_setbuf(irh, "pkteng", &pkteng, sizeof(pkteng))) {
+		printf("wlmRxPacketStart: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRxPacketStop(void)
+{
+	wl_pkteng_t pkteng;
+
+	memset(&pkteng, 0, sizeof(pkteng));
+	pkteng.flags = WL_PKTENG_PER_RX_STOP;
+
+	if (wlu_var_setbuf(irh, "pkteng", &pkteng, sizeof(pkteng)) < 0) {
+		printf("wlmRxPacketStop: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmTxGetAckedPackets(unsigned int *count)
+{
+	wl_cnt_t *cnt;
+
+	if (wlu_var_getbuf(irh, "counters", NULL, 0, (void **)&cnt)) {
+		printf("wlmTxGetAckedPackets: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	*count = dtoh32(cnt->rxackucast);
+
+	return TRUE;
+}
+
+int wlmRxGetReceivedPackets(unsigned int *count)
+{
+	wl_cnt_t *cnt;
+
+	if (wlu_var_getbuf_med(irh, "counters", NULL, 0, (void **)&cnt)) {
+		printf("wlmRxGetReceivedPackets: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	cnt->version = dtoh16(cnt->version);
+	cnt->length = dtoh16(cnt->version);
+
+	/* current wl_cnt_t version is 7 */
+	if (cnt->version == WL_CNT_T_VERSION) {
+		*count = dtoh32(cnt->pktengrxducast);
+	} else {
+		*count = dtoh32(cnt->rxdfrmucastmbss);
+	}
+
+	return TRUE;
+}
+
+int wlmRssiGet(int *rssi)
+{
+	wl_pkteng_stats_t *cnt;
+
+	if (wlu_var_getbuf(irh, "pkteng_stats", NULL, 0, (void **)&cnt)) {
+		printf("wlmRssiGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	*rssi = dtoh32(cnt->rssi);
+
+	return TRUE;
+}
+
+
+
+int wlmSequenceStart(int clientBatching)
+{
+	if (wl_seq_batch_in_client((bool)clientBatching)) {
+		printf("wlmSequenceStart: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	if (wl_seq_start(irh, 0, 0)) {
+		printf("wlmSequenceStart: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmSequenceStop(void)
+{
+	if (wl_seq_stop(irh, 0, 0)) {
+		printf("wlmSequenceStop: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmSequenceDelay(int msec)
+{
+	if (wlu_iovar_setint(irh, "seq_delay", msec)) {
+		printf("wlmSequenceDelay: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmSequenceErrorIndex(int *index)
+{
+	if (wlu_iovar_getint(irh, "seq_error_index", index)) {
+		printf("wlmSequenceErrorIndex: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmDeviceImageWrite(const char* byteStream, int length, WLM_IMAGE_TYPE imageType)
+{
+	srom_rw_t *srt;
+	char buffer[WLC_IOCTL_MAXLEN] = {0};
+
+	char *bufp;
+	char *cisp, *cisdata;
+	cis_rw_t cish;
+
+	if (byteStream == NULL) {
+		printf("wlmDeviceImageWrite: Buffer is invalid!\n");
+		return FALSE;
+	}
+	if (length > SROM_MAX+1) {
+	    printf("wlmDeviceImageWrite: Data length should be less than %d bytes\n", SROM_MAX);
+	    return FALSE;
+	}
+
+	switch (imageType) {
+	case WLM_TYPE_SROM:
+		srt = (srom_rw_t *)buffer;
+		memcpy(srt->buf, byteStream, length);
+
+		if (length == SROM4_WORDS * 2) {
+			if ((srt->buf[SROM4_SIGN] != SROM4_SIGNATURE) &&
+			    (srt->buf[SROM8_SIGN] != SROM4_SIGNATURE)) {
+				printf("wlmDeviceImageWrite: Data lacks a REV4 signature!\n");
+			    return FALSE;
+			}
+		} else if ((length != SROM_WORDS * 2) && (length != SROM_MAX)) {
+		    printf("wlmDeviceImageWrite: Data length is invalid!\n");
+		    return FALSE;
+		}
+
+		srt->nbytes = length;
+		if (wlu_set(irh, WLC_SET_SROM, buffer, length + 8)) {
+		    printf("wlmDeviceImageWrite: %s\n", wlmLastError());
+		    return FALSE;
+		}
+
+
+		break;
+	case WLM_TYPE_OTP:
+		bufp = buffer;
+		strcpy(bufp, "ciswrite");
+		bufp += strlen("ciswrite") + 1;
+		cisp = bufp;
+		cisdata = cisp + sizeof(cish);
+		cish.source = htod32(0);
+		memcpy(cisdata, byteStream, length);
+
+		cish.byteoff = htod32(0);
+		cish.nbytes = htod32(length);
+		memcpy(cisp, (char*)&cish, sizeof(cish));
+
+		if (wl_set(irh, WLC_SET_VAR, buffer, (cisp - buffer) + sizeof(cish) + length) < 0) {
+		    printf("wlmDeviceImageWrite: %s\n", wlmLastError());
+		    return FALSE;
+		 }
+		break;
+	case WLM_TYPE_AUTO:
+		if (!wlmDeviceImageWrite(byteStream, length, WLM_TYPE_SROM) &&
+			!wlmDeviceImageWrite(byteStream, length, WLM_TYPE_OTP)) {
+		    printf("wlmDeviceImageWrite: %s\n", wlmLastError());
+		    return FALSE;
+	    }
+	    break;
+	default:
+		printf("wlmDeviceImageWrite: Invalid image type!\n");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmDeviceImageRead(char* byteStream, unsigned int len, WLM_IMAGE_TYPE imageType)
+{
+	srom_rw_t *srt;
+	cis_rw_t *cish;
+	char buf[WLC_IOCTL_MAXLEN] = {0};
+	unsigned int numRead = 0;
+
+	if (byteStream == NULL) {
+		printf("wlmDeviceImageRead: Buffer is invalid!\n");
+		return FALSE;
+	}
+
+	if (len > SROM_MAX) {
+	    printf("wlmDeviceImageRead: byteStream should be less than %d bytes!\n", SROM_MAX);
+	    return FALSE;
+	}
+
+	if (len & 1) {
+			printf("wlmDeviceImageRead: Invalid byte count %d, must be even\n", len);
+			return FALSE;
+	}
+
+	switch (imageType) {
+	case WLM_TYPE_SROM:
+		if (len < 2*SROM4_WORDS) {
+			printf("wlmDeviceImageRead: Buffer not large enough!\n");
+			return FALSE;
+		}
+
+		srt = (srom_rw_t *)buf;
+		srt->byteoff = 0;
+		srt->nbytes = htod32(2 * SROM4_WORDS);
+		/* strlen("cisdump ") = 9 */
+		if (wlu_get(irh, WLC_GET_SROM, buf, 9 + (len < SROM_MAX ? len : SROM_MAX)) < 0) {
+			printf("wlmDeviceImageRead: %s\n", wlmLastError());
+			return FALSE;
+		}
+		memcpy(byteStream, buf + 8, srt->nbytes);
+		numRead = srt->nbytes;
+		break;
+	case WLM_TYPE_OTP:
+		strcpy(buf, "cisdump");
+		/* strlen("cisdump ") = 9 */
+		if (wl_get(irh, WLC_GET_VAR, buf, 9  + (len < SROM_MAX ? len : SROM_MAX)) < 0) {
+		    printf("wlmDeviceImageRead: %s\n", wlmLastError());
+		    return FALSE;
+		}
+
+		cish = (cis_rw_t *)buf;
+		cish->source = dtoh32(cish->source);
+		cish->byteoff = dtoh32(cish->byteoff);
+		cish->nbytes = dtoh32(cish->nbytes);
+
+		if (len < cish->nbytes) {
+			printf("wlmDeviceImageRead: Buffer not large enough!\n");
+			return FALSE;
+		}
+		memcpy(byteStream, buf + sizeof(cis_rw_t), cish->nbytes);
+		numRead = cish->nbytes;
+		break;
+	case WLM_TYPE_AUTO:
+	  numRead = wlmDeviceImageRead(byteStream, len, WLM_TYPE_SROM);
+		if (!numRead) {
+			numRead = wlmDeviceImageRead(byteStream, len, WLM_TYPE_OTP);
+		    printf("wlmDeviceImageRead: %s\n", wlmLastError());
+		    return FALSE;
+	    }
+	    break;
+	default:
+		printf("wlmDeviceImageRead: Invalid image type!\n");
+		return FALSE;
+	}
+	return numRead;
+}
+
+int wlmSecuritySet(WLM_AUTH_TYPE authType, WLM_AUTH_MODE authMode,
+	WLM_ENCRYPTION encryption, const char *key)
+{
+	int length = 0;
+	int wpa_auth;
+	int sup_wpa;
+	int primary_key = 0;
+	wl_wsec_key_t wepKey[4];
+	wsec_pmk_t psk;
+	int wsec;
+
+	if (encryption != WLM_ENCRYPT_NONE && key == 0) {
+		printf("wlmSecuritySet: invalid key\n");
+		return FALSE;
+	}
+
+	if (key) {
+		length = strlen(key);
+	}
+
+	switch (encryption) {
+
+	case WLM_ENCRYPT_NONE:
+		wpa_auth = WPA_AUTH_DISABLED;
+		sup_wpa = 0;
+		break;
+
+	case WLM_ENCRYPT_WEP: {
+		int i;
+		int len = length / 4;
+
+		wpa_auth = WPA_AUTH_DISABLED;
+		sup_wpa = 0;
+
+		if (!(length == 40 || length == 104 || length == 128 || length == 256)) {
+			printf("wlmSecuritySet: invalid WEP key length %d"
+			"       - expect 40, 104, 128, or 256"
+			" (i.e. 10, 26, 32, or 64 for each of 4 keys)\n", length);
+			return FALSE;
+		}
+
+		/* convert hex key string to 4 binary keys */
+		for (i = 0; i < 4; i++) {
+			wl_wsec_key_t *k = &wepKey[i];
+			const char *data = &key[i * len];
+			unsigned int j;
+
+			memset(k, 0, sizeof(*k));
+			k->index = i;
+			k->len = len / 2;
+
+			for (j = 0; j < k->len; j++) {
+				char hex[] = "XX";
+				char *end = NULL;
+				strncpy(hex, &data[j * 2], 2);
+				k->data[j] = (char)strtoul(hex, &end, 16);
+				if (*end != 0) {
+					printf("wlmSecuritySet: invalid WEP key"
+					"       - expect hex values\n");
+					return FALSE;
+				}
+			}
+
+			switch (k->len) {
+			case 5:
+				k->algo = CRYPTO_ALGO_WEP1;
+				break;
+			case 13:
+				k->algo = CRYPTO_ALGO_WEP128;
+				break;
+			case 16:
+				k->algo = CRYPTO_ALGO_AES_CCM;
+				break;
+			case 32:
+				k->algo = CRYPTO_ALGO_TKIP;
+				break;
+			default:
+				/* invalid */
+				return FALSE;
+			}
+
+			k->flags |= WL_PRIMARY_KEY;
+		}
+
+		break;
+	}
+
+	case WLM_ENCRYPT_TKIP:
+	case WLM_ENCRYPT_AES: {
+
+		if (authMode != WLM_WPA_AUTH_PSK && authMode != WLM_WPA2_AUTH_PSK) {
+			printf("wlmSecuritySet: authentication mode must be WPA PSK or WPA2 PSK\n");
+			return FALSE;
+		}
+
+		wpa_auth = authMode;
+		sup_wpa = 1;
+
+		if (length < WSEC_MIN_PSK_LEN || length > WSEC_MAX_PSK_LEN) {
+			printf("wlmSecuritySet: passphrase must be between %d and %d characters\n",
+			WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN);
+			return FALSE;
+		}
+
+		psk.key_len = length;
+		psk.flags = WSEC_PASSPHRASE;
+		memcpy(psk.key, key, length);
+
+		break;
+	}
+
+	case WLM_ENCRYPT_WSEC:
+	case WLM_ENCRYPT_FIPS:
+	default:
+		printf("wlmSecuritySet: encryption not supported\n");
+		return FALSE;
+	}
+
+	if (wlu_iovar_setint(irh, "auth", authType)) {
+		printf("wlmSecuritySet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	if (wlu_iovar_setint(irh, "wpa_auth", wpa_auth)) {
+		printf("wlmSecuritySet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	if (wlu_iovar_setint(irh, "sup_wpa", sup_wpa)) {
+		printf("wlmSecuritySet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	if (encryption == WLM_ENCRYPT_WEP) {
+		int i;
+		for (i = 0; i < 4; i++) {
+			wl_wsec_key_t *k = &wepKey[i];
+			k->index = htod32(k->index);
+			k->len = htod32(k->len);
+			k->algo = htod32(k->algo);
+			k->flags = htod32(k->flags);
+
+			if (wlu_set(irh, WLC_SET_KEY, k, sizeof(*k))) {
+				printf("wlmSecuritySet: %s\n", wlmLastError());
+				return FALSE;
+			}
+		}
+
+		primary_key = htod32(primary_key);
+		if (wlu_set(irh, WLC_SET_KEY_PRIMARY, &primary_key, sizeof(primary_key)) < 0) {
+			printf("wlmSecuritySet: %s\n", wlmLastError());
+			return FALSE;
+		}
+	}
+	else if (encryption == WLM_ENCRYPT_TKIP || encryption == WLM_ENCRYPT_AES) {
+		psk.key_len = htod16(psk.key_len);
+		psk.flags = htod16(psk.flags);
+
+		if (wlu_set(irh, WLC_SET_WSEC_PMK, &psk, sizeof(psk))) {
+			printf("wlmSecuritySet: %s\n", wlmLastError());
+			return FALSE;
+		}
+	}
+
+	wsec = htod32(encryption);
+	if (wlu_set(irh, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0) {
+		printf("wlmSecuritySet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmJoinNetwork(const char* ssid, WLM_JOIN_MODE mode)
+{
+	wlc_ssid_t wlcSsid;
+	int infra = htod32(mode);
+	if (wlu_set(irh, WLC_SET_INFRA, &infra, sizeof(int)) < 0) {
+	    printf("wlmJoinNetwork: %s\n", wlmLastError());
+	    return FALSE;
+	}
+
+	wlcSsid.SSID_len = htod32(strlen(ssid));
+	memcpy(wlcSsid.SSID, ssid, wlcSsid.SSID_len);
+
+	if (wlu_set(irh, WLC_SET_SSID, &wlcSsid, sizeof(wlc_ssid_t)) < 0) {
+		printf("wlmJoinNetwork: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmDisassociateNetwork(void)
+{
+	if (wlu_set(irh, WLC_DISASSOC, NULL, 0) < 0) {
+		printf("wlmDisassociateNetwork: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmSsidGet(char *ssid, int length)
+{
+	wlc_ssid_t wlc_ssid;
+
+	if (length < SSID_FMT_BUF_LEN) {
+		printf("wlmSsidGet: Ssid buffer too short - %d bytes at least\n",
+		SSID_FMT_BUF_LEN);
+		return FALSE;
+	}
+
+	/* query for 'ssid' */
+	if (wlu_get(irh, WLC_GET_SSID, &wlc_ssid, sizeof(wlc_ssid_t))) {
+		printf("wlmSsidGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	wl_format_ssid(ssid, wlc_ssid.SSID, dtoh32(wlc_ssid.SSID_len));
+
+	return TRUE;
+}
+
+int wlmBssidGet(char *bssid, int length)
+{
+	struct ether_addr ea;
+
+	if (length != ETHER_ADDR_LEN) {
+		printf("wlmBssiGet: bssid requires %d bytes", ETHER_ADDR_LEN);
+		return FALSE;
+	}
+
+	if (wlu_get(irh, WLC_GET_BSSID, &ea, ETHER_ADDR_LEN) == 0) {
+		/* associated - format and return bssid */
+		strncpy(bssid, wl_ether_etoa(&ea), length);
+	}
+	else {
+		/* not associated - return empty string */
+		memset(bssid, 0, length);
+	}
+
+	return TRUE;
+}
+
+
+int wlmGlacialTimerSet(int val)
+{
+	if (wlu_iovar_setint(irh, "glacial_timer", val)) {
+		printf("wlmGlacialTimerSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmFastTimerSet(int val)
+{
+	if (wlu_iovar_setint(irh, "fast_timer", val)) {
+		printf("wlmFastTimerSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmSlowTimerSet(int val)
+{
+	if (wlu_iovar_setint(irh, "slow_timer", val)) {
+		printf("wlmGlacialTimerSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+
+int wlmScanSuppress(int on)
+{
+	int val;
+	if (on)
+		val = 1;
+	else
+		val = 0;
+
+	if (wlu_set(irh, WLC_SET_SCANSUPPRESS, &val, sizeof(int))) {
+		printf("wlmSetScansuppress: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmCountryCodeSet(const char * country_name)
+{
+	wl_country_t cspec;
+	int err;
+
+	memset(&cspec, 0, sizeof(cspec));
+	cspec.rev = -1;
+
+	/* arg matched a country name */
+	memcpy(cspec.country_abbrev, country_name, WLC_CNTRY_BUF_SZ);
+	err = 0;
+
+	/* first try the country iovar */
+	if (cspec.rev == -1 && cspec.ccode[0] == '\0')
+		err = wlu_iovar_set(irh, "country", &cspec, WLC_CNTRY_BUF_SZ);
+	else
+		err = wlu_iovar_set(irh, "country", &cspec, sizeof(cspec));
+
+	if (err == 0)
+		return TRUE;
+	return FALSE;
+}
+
+int wlmFullCal(void)
+{
+	if (wlu_var_setbuf(irh, "lpphy_fullcal", NULL, 0)) {
+		printf("wlmLPPY_FULLCAL: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIoctlGet(int cmd, void *buf, int len)
+{
+	if (wlu_get(irh, cmd, buf, len)) {
+		printf("wlmIoctlGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIoctlSet(int cmd, void *buf, int len)
+{
+	if (wlu_set(irh, cmd, buf, len)) {
+		printf("wlmIoctlSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIovarGet(const char *iovar, void *buf, int len)
+{
+	if (wlu_iovar_get(irh, iovar, buf, len)) {
+		printf("wlmIovarGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIovarSet(const char *iovar, void *buf, int len)
+{
+	if (wlu_iovar_set(irh, iovar, buf, len)) {
+		printf("wlmIovarSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIovarIntegerGet(const char *iovar, int *val)
+{
+	if (wlu_iovar_getint(irh, iovar, val)) {
+		printf("wlmIovarIntegerGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIovarIntegerSet(const char *iovar, int val)
+{
+	if (wlu_iovar_setint(irh, iovar, val)) {
+		printf("wlmIovarIntegerSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIovarBufferGet(const char *iovar, void *param, int param_len, void **bufptr)
+{
+	if (wlu_var_getbuf(irh, iovar, param, param_len, bufptr)) {
+		printf("wlmIovarBufferGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmIovarBufferSet(const char *iovar, void *param, int param_len)
+{
+	if (wlu_var_setbuf(irh, iovar, param, param_len)) {
+		printf("wlmIovarBufferSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmCga5gOffsetsSet(char* values, int len)
+{
+	if (len != CGA_5G_OFFSETS_LEN) {
+		printf("wlmCga5gOffsetsSet() requires a %d-value array as a parameter\n",
+		      CGA_5G_OFFSETS_LEN);
+		return FALSE;
+	}
+
+	if ((wlu_var_setbuf(irh, "sslpnphy_cga_5g", values,
+	                    CGA_5G_OFFSETS_LEN * sizeof(int8))) < 0) {
+		printf("wlmCga5gOffsetsSet(): Error setting offset values (%s)\n",  wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmCga5gOffsetsGet(char* buf, int len)
+{
+	if (len != CGA_5G_OFFSETS_LEN) {
+		printf("wlmCga5gOffsetsGet() requires a %d-value array as a parameter\n",
+		       CGA_5G_OFFSETS_LEN);
+		return FALSE;
+	}
+
+	if ((wlu_iovar_get(irh, "sslpnphy_cga_5g", buf, CGA_5G_OFFSETS_LEN * sizeof(int8))) < 0) {
+		printf("wlmCga5gOffsetsGet(): Error setting offset values (%s)\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmCga2gOffsetsSet(char* values, int len)
+{
+	if (len != CGA_2G_OFFSETS_LEN) {
+		printf("wlmCga2gOffsetsSet(): requires a %d-value array as a parameter\n",
+		       CGA_2G_OFFSETS_LEN);
+		return FALSE;
+	}
+
+	if ((wlu_var_setbuf(irh, "sslpnphy_cga_2g", values,
+	                    CGA_2G_OFFSETS_LEN * sizeof(int8))) < 0) {
+		printf("wlmCga2gOffsetsSet(): Error setting offset values (%s)\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+
+}
+
+int wlmCga2gOffsetsGet(char* buf, int len)
+{
+	if (len != CGA_2G_OFFSETS_LEN) {
+		printf("wlmCga2gOffsetsGet(): requires a %d-value array as a parameter\n",
+		       CGA_2G_OFFSETS_LEN);
+		return FALSE;
+	}
+
+	if ((wlu_iovar_get(irh, "sslpnphy_cga_2g", buf, CGA_2G_OFFSETS_LEN * sizeof(int8))) < 0) {
+		printf("wlmCga2gOffsetsGet(): Error setting offset values (%s)\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+int wlmRadioOn(void)
+{
+	int val;
+
+	/* val = WL_RADIO_SW_DISABLE << 16; */
+	val = (1<<0) << 16;
+
+	if (wlu_set(irh, WLC_SET_RADIO, &val, sizeof(int)) < 0) {
+		printf("wlmRadioOn: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRadioOff(void)
+{
+	int val;
+
+	/* val = WL_RADIO_SW_DISABLE << 16 | WL_RADIO_SW_DISABLE; */
+	val = (1<<0) << 16 | (1<<0);
+
+	if (wlu_set(irh, WLC_SET_RADIO, &val, sizeof(int)) < 0) {
+		 printf("wlmRadioOff: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmPMmode(int val)
+{
+	if (val < 0 || val > 2) {
+	        printf("wlmPMmode: setting for PM mode out of range [0,2].\n");
+		/* 0: CAM constant awake mode */
+		/* 1: PS (Power save) mode */
+		/* 2: Fast PS mode */
+	}
+
+	if (wlu_set(irh, WLC_SET_PM, &val, sizeof(int)) < 0) {
+		printf("wlmPMmode: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRoamingOn(void)
+{
+	if (wlu_iovar_setint(irh, "roam_off", 0) < 0) {
+		printf("wlmRoamingOn: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRoamingOff(void)
+{
+	if (wlu_iovar_setint(irh, "roam_off", 1) < 0) {
+		printf("wlmRoamingOff: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRoamTriggerLevelGet(int *val, WLM_BAND band)
+{
+	struct {
+		int val;
+		int band;
+	} x;
+
+	x.band = htod32(band);
+	x.val = -1;
+
+	if (wlu_get(irh, WLC_GET_ROAM_TRIGGER, &x, sizeof(x)) < 0) {
+		printf("wlmRoamTriggerLevelGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	*val = htod32(x.val);
+
+	return TRUE;
+}
+
+int wlmRoamTriggerLevelSet(int val, WLM_BAND band)
+{
+	struct {
+		int val;
+		int band;
+	} x;
+
+	x.band = htod32(band);
+	x.val = htod32(val);
+
+	if (wlu_set(irh, WLC_SET_ROAM_TRIGGER, &x, sizeof(x)) < 0) {
+		printf("wlmRoamTriggerLevelSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmFrameBurstOn(void)
+{
+	int val = 1;
+
+	if (wlu_set(irh, WLC_SET_FAKEFRAG, &val, sizeof(int)) < 0) {
+		printf("wlmFrameBurstOn: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmFrameBurstOff(void)
+{
+	int val = 0;
+
+	if (wlu_set(irh, WLC_SET_FAKEFRAG, &val, sizeof(int)) < 0) {
+		printf("wlmFrameBurstOff: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+int wlmBeaconIntervalSet(int val)
+{
+	val = htod32(val);
+	if (wlu_set(irh, WLC_SET_BCNPRD, &val, sizeof(int)) < 0) {
+		printf("wlmBeaconIntervalSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmAMPDUModeSet(int val)
+{
+	val = htod32(val);
+	if (wlu_iovar_setint(irh, "ampdu", val) < 0) {
+		printf("wlmAMPDUModeSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmMIMOBandwidthCapabilitySet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "mimo_bw_cap", val) < 0) {
+		printf("wlmMIMOBandwidthCapabilitySet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmInterferenceSet(int val)
+{
+	val = htod32(val);
+
+	if (val < 0 || val > 4) {
+		printf("wlmInterferenceSet: interference setting out of range [0, 4]\n");
+		return FALSE;
+	}
+
+	if (wlu_set(irh, WLC_SET_INTERFERENCE_MODE, &val, sizeof(int)) < 0) {
+		printf("wlmInterferenceSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmInterferenceOverrideSet(int val)
+{
+	val = htod32(val);
+
+	if (val < 0 || val > 4) {
+		printf("wlmInterferenceOverrideSet: interference setting out of range [0, 4]\n");
+		return FALSE;
+	}
+
+	if (wlu_set(irh, WLC_SET_INTERFERENCE_OVERRIDE_MODE, &val, sizeof(int)) < 0) {
+		printf("wlmInterferenceOverrideSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmTransmitBandwidthSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "mimo_txbw", val) < 0) {
+		printf("wlmTransmitBadnwidthSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmShortGuardIntervalSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "sgi_tx", val) < 0) {
+		printf("wlmShortGuardIntervalSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmObssCoexSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "obss_coex", val) < 0) {
+		printf("wlmObssCoexSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmPHYPeriodicalCalSet(void)
+{
+	if (wlu_iovar_setint(irh, "phy_percal", 0) < 0) {
+		printf("wlmPHYPeriodicalCalSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmPHYForceCalSet(void)
+{
+	if (wlu_iovar_setint(irh, "phy_forcecal", 0) < 0) {
+		printf("wlmPHYForceCalSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmPHYScramblerUpdateDisable(void)
+{
+	if (wlu_iovar_setint(irh, "phy_scraminit", 0x7f) < 0) {
+		printf("wlmPHYScramblerUpdateDisable: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmPHYScramblerUpdateEnable(void)
+{
+	if (wlu_iovar_setint(irh, "phy_scraminit", -1) < 0) {
+		printf("wlmPHYScramblerUpdateEnable: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmPHYWatchdogSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "phy_watchdog", val) < 0) {
+	        printf("wlmPHYWatchdogSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmTemperatureSensorDisable(void)
+{
+	int val = 1; /* 0 = temp sensor enabled; 1 = temp sensor disabled */
+	if (wlu_iovar_setint(irh, "tempsense_disable", val) < 0) {
+		printf("wlmTempSensorDisable %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmTemperatureSensorEnable(void)
+{
+	int val = 0; /* 0 = temp sensor enabled; 1 = temp sensor disabled */
+	if (wlu_iovar_setint(irh, "tempsense_disable", val) < 0) {
+		printf("wlmTempSensorEnable %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmTransmitCoreSet(int val)
+{	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "txcore", val) < 0) {
+		printf("wlmTransmitCoreSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmPhyTempSenseGet(int *val)
+{
+	if (wlu_iovar_getint(irh, "phy_tempsense", val) < 0) {
+		printf("wlmPhyTempSense: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmOtpFabidGet(int *val)
+{
+	if (wlu_iovar_getint(irh, "otp_fabid", val)) {
+		printf("wlmOtpFabid: %s\n", wlmLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int wlmChannelSpecSet(int channel, int bandwidth, int sideband)
+{
+	chanspec_t chanspec = 0;
+
+	if (channel > 224) {
+		printf("wlmChannelSpecSet: %d is invalid channel\n", channel);
+		return FALSE;
+	} else
+		chanspec |= channel;
+
+	if ((bandwidth != 20) && (bandwidth != 40)) {
+		printf("wlChannelSpecSet: %d is invalid channel bandwidth.\n", bandwidth);
+		return FALSE;
+	}
+
+	if ((sideband != -1) && (sideband != 1) && (sideband != 0)) {
+		printf("wlmChannelSpecSet: %d is invalid channel sideband.\n", sideband);
+		return FALSE;
+	}
+
+	if (ioctl_version == 1) {
+		if (channel > 14)
+			chanspec |= WL_LCHANSPEC_BAND_5G;
+		else
+			chanspec |= WL_LCHANSPEC_BAND_2G;
+
+		if (bandwidth == 20)
+			chanspec |= WL_LCHANSPEC_BW_20;
+		else
+			chanspec |= WL_LCHANSPEC_BW_40;
+
+		if (sideband == -1)
+			chanspec |= WL_LCHANSPEC_CTL_SB_LOWER;
+		else if (sideband == 1)
+			chanspec |= WL_LCHANSPEC_CTL_SB_UPPER;
+		else
+			chanspec |= WL_LCHANSPEC_CTL_SB_NONE;
+	} else {
+		if (channel > 14)
+			chanspec |= WL_CHANSPEC_BAND_5G;
+		else
+			chanspec |= WL_CHANSPEC_BAND_2G;
+
+		if (bandwidth == 20)
+			chanspec |= WL_CHANSPEC_BW_20;
+		else
+			chanspec |= WL_CHANSPEC_BW_40;
+
+		if (sideband == -1)
+			chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
+		else if (sideband == 1)
+			chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
+	}
+
+	if (wlu_iovar_setint(irh, "chanspec", (int) chanspec) < 0) {
+		printf("wlmChannelSpecSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRtsThresholdOverride(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "rtsthresh", val) < 0) {
+	        printf("wlmRtsThresholdOverride: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+int wlmSTBCTxSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "stbc_tx", val) < 0) {
+	        printf("wlmSTBCTxSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+int wlmSTBCRxSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "stbc_rx", val) < 0) {
+	        printf("wlmSTBCRxSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+int wlmTxChainSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "txchain", val) < 0) {
+	        printf("wlmTxChainSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRxChainSet(int val)
+{
+	val = htod32(val);
+
+	if (wlu_iovar_setint(irh, "rxchain", val) < 0) {
+	        printf("wlmRxChainSet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int wlmRxIQEstGet(float *val, int sampleCount, int ant)
+{
+	uint32 rxiq;
+	int sample_count = sampleCount;  /* [0, 16], default: maximum 15 sample counts */
+	int antenna = ant ;       /* [0, 3], default: antenna 0 */
+	int err;
+	uint8 resolution = 1;     /* resolution default to 0.25dB */
+	float x, y;
+
+	/* default: resolution 1 (coarse), samples = 1024 (2^10) and antenna 3 */
+
+	rxiq = (10 << 8) | 3;
+	if ((sample_count < 0) || (sample_count > 16)) {
+		printf("wlmRxIQGet: SampleCount out of range of [0, 15].\n");
+		return FALSE;
+	} else {
+		rxiq = (((sample_count & 0xff) << 8) | (rxiq & 0xff));
+	}
+
+	if ((antenna < 0) || (antenna > 3)) {
+		printf("wlmRxIQGet: Antenna out of range of [0, 3].\n");
+		return FALSE;
+	} else {
+		rxiq = ((rxiq & 0xff00) | (antenna & 0xff));
+	}
+
+	if ((err = wlu_iovar_setint(irh, "phy_rxiqest", (int) rxiq)) < 0) {
+		printf("wlmRxIQGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	if ((err = wlu_iovar_getint(irh, "phy_rxiqest", (int*)&rxiq)) < 0) {
+		printf("wlmRxIQGet: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	if (resolution == 1) {
+		/* fine resolutin power reporting (0.25dB resolution) */
+		if (rxiq >> 20) {
+		} else if (rxiq >> 10) {
+		} else {
+			/* 1-chain specific */
+			int16 tmp;
+			tmp = (rxiq & 0x3ff);
+			tmp = ((int16)(tmp << 6)) >> 6; /* sing extension */
+			if (tmp < 0) {
+				tmp = -1 * tmp;
+			}
+
+			x = (float)(tmp >> 2);
+			y = (float)(tmp & 0x3);
+
+			*val = (x + y * 25 /100) * (-1);
+		}
+	}
+	return TRUE;
+}
+
+int wlmPHYTxPowerIndexGet(unsigned int *val, const char *chipid)
+{
+	uint32 power_index = (uint32)-1;
+	uint32 txpwridx[4] = {0};
+	int chip = atoi(chipid);
+
+	switch (chip) {
+	        case 4329:
+		case 43291:
+			if (wlu_iovar_getint(irh, "sslpnphy_txpwrindex", (int *)&power_index) < 0) {
+				printf("wlmPHYTxPowerIndexGet: %s\n", wlmLastError());
+				return FALSE;
+			}
+			*val = power_index;
+			break;
+	        case 4325:
+				if (wlu_iovar_getint(irh, "lppphy_txpwrindex",
+					(int *)&power_index) < 0) {
+				printf("wlmPHYTxPowerIndexGet: %s\n", wlmLastError());
+				return FALSE;
+			}
+			*val = power_index;
+			break;
+	        default:
+		  if (wlu_iovar_getint(irh, "phy_txpwrindex", (int *)&txpwridx[0]) < 0) {
+			  printf("wlmPHYTxPowerIndexGet: %s\n", wlmLastError());
+			  return FALSE;
+		  }
+		  txpwridx[0] = dtoh32(txpwridx[0]);
+		  *val = txpwridx[0];
+		  break;
+	}
+
+	return TRUE;
+}
+
+int wlmPHYTxPowerIndexSet(unsigned int val, const char *chipid)
+{
+	uint32 power_index;
+	uint32 txpwridx[4] = {0};
+	int chip = atoi(chipid);
+
+	power_index = dtoh32(val);
+	switch (chip) {
+	        case 4329:
+	        case 43291:
+			if (wlu_iovar_setint(irh, "sslpnphy_txpwrindex", power_index) < 0) {
+				printf("wlmPHYTxPowerIndexSet: %s\n", wlmLastError());
+				return FALSE;
+			}
+			break;
+	        case 4325:
+			if (wlu_iovar_setint(irh, "lppphy_txpwrindex", power_index) < 0) {
+				printf("wlmPHYTxPowerIndexSet: %s\n", wlmLastError());
+				return FALSE;
+			}
+			break;
+	        default:
+			txpwridx[0] = (int8) (power_index & 0xff);
+			txpwridx[1] = (int8) ((power_index >> 8) & 0xff);
+			txpwridx[2] = (int8) ((power_index >> 16) & 0xff);
+			txpwridx[3] = (int8) ((power_index >> 24) & 0xff);
+
+			if (wlu_var_setbuf(irh, "phy_txpwrindex", txpwridx, 4*sizeof(uint32)) < 0) {
+				printf("wlmPHYTxPowerIndexSet: %s\n", wlmLastError());
+				return FALSE;
+			}
+			break;
+	}
+
+	return TRUE;
+}
+
+int wlmRIFSEnable(int enable)
+{
+	int val, rifs;
+
+	val = rifs = htod32(enable);
+	if (rifs != 0 && rifs != 1) {
+		printf("wlmRIFSEnable: Usage: input must be 0 or 1\n");
+		return FALSE;
+	}
+
+	if (wlu_set(irh, WLC_SET_FAKEFRAG, &val, sizeof(int)) < 0) {
+		printf("wlmRIFSEnable: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	if (wlu_iovar_setint(irh, "rifs", (int)rifs) < 0) {
+		printf("wlmRIFSEnable: %s\n", wlmLastError());
+		return FALSE;
+	}
+
+	return TRUE;
+}
diff --git a/src/wl/exe/wlm.h b/src/wl/exe/wlm.h
new file mode 100644
index 0000000..9f3458b
--- /dev/null
+++ b/src/wl/exe/wlm.h
@@ -0,0 +1,1116 @@
+/*
+ * Common (OS-independent) portion of
+ * WLM (Wireless LAN Manufacturing) test library.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlm.h 281542 2011-09-02 17:31:19Z $
+ */
+
+#ifndef _wlm_h
+#define _wlm_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+\mainpage mfgtest_api.h
+
+Overview:
+
+The MFG API DLL allows a user to talk to a DUT by providing functions
+that abstract out the lower level details of the driver.
+
+The goal of this API is to make testing easier by providing enough
+functionality for the user to perform various tasks without
+requiring the user to know anything about the driver internals and,
+in addition, any differences there may be between drivers.
+
+*/
+
+#ifndef TRUE
+#define TRUE 	1
+#endif
+#ifndef FALSE
+#define FALSE 	0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define WLM_MAX_FILENAME_LEN 256
+
+#if defined(WIN32)
+#define WLM_FUNCTION __declspec(dllexport)
+#else
+#define WLM_FUNCTION
+#endif /* WIN32 */
+
+/* Supported DUT interfaces. */
+/* Values are used to select the interface used to talk to the DUT. */
+enum {
+	WLM_DUT_LOCAL  = 0,  	/* client and DUT on same device */
+	WLM_DUT_SERIAL = 1,		/* client to DUT via serial */
+	WLM_DUT_SOCKET = 2, 	/* client to DUT via Ethernet */
+	WLM_DUT_WIFI   = 3,   	/* client to DUT via WLAN */
+	WLM_DUT_DONGLE = 4		/* client to DUT dongle via serial */
+};
+typedef int WLM_DUT_INTERFACE;
+
+/* Supported server ports. */
+/* Values are used to configure server port (for WLM_DUT_SOCKET only). */
+enum {
+	WLM_DEFAULT_DUT_SERVER_PORT = 8000	/* default */
+};
+typedef int WLM_DUT_SERVER_PORT;
+
+/* Supported DUT OS. */
+/* Values are used to select the OS of the DUT. */
+enum {
+	WLM_DUT_OS_LINUX = 1,  	/* Linux DUT */
+	WLM_DUT_OS_WIN32 = 2 	/* Win32 DUT */
+};
+typedef int WLM_DUT_OS;
+
+/* Supported join modes. */
+/* Values are used to select the mode used to join a network. */
+enum {
+	WLM_MODE_IBSS = 0,   /* IBSS Mode. (Adhoc) */
+	WLM_MODE_BSS = 1,    /* BSS Mode. */
+	WLM_MODE_AUTO = 2    /* Auto. */
+};
+typedef int WLM_JOIN_MODE;
+
+/* Supported bands. */
+/* Values are used to select the band used for testing. */
+enum {
+	WLM_BAND_AUTO = 0,	/* auto select */
+	WLM_BAND_5G = 1,        /* 5G Band. */
+	WLM_BAND_2G = 2,        /* 2G Band. */
+	WLM_BAND_DUAL = WLM_BAND_2G | WLM_BAND_5G	/* Dual Band. */
+};
+typedef int WLM_BAND;
+
+/* Supported gmode. */
+/* Values are used to select gmode used for testing. */
+enum {
+	WLM_GMODE_LEGACYB = 0,
+	WLM_GMODE_AUTO = 1,
+	WLM_GMODE_GONLY = 2,
+	WLM_GMODE_BDEFERED = 3,
+	WLM_GMODE_PERFORMANCE = 4,
+	WLM_GMODE_LRS = 5
+};
+typedef int WLM_GMODE;
+
+/* Supported legacy rates. */
+/* Values are used to select the rate used for testing. */
+enum {
+	WLM_RATE_AUTO = 0,
+	WLM_RATE_1M = 2,
+	WLM_RATE_2M = 4,
+	WLM_RATE_5M5 = 11,
+	WLM_RATE_6M = 12,
+	WLM_RATE_9M = 18,
+	WLM_RATE_11M = 22,
+	WLM_RATE_12M = 24,
+	WLM_RATE_18M = 36,
+	WLM_RATE_24M = 48,
+	WLM_RATE_36M = 72,
+	WLM_RATE_48M = 96,
+	WLM_RATE_54M = 108
+};
+typedef int WLM_RATE;
+
+/* Supported MCS rates */
+enum {
+	WLM_MCS_RATE_0 = 0,
+	WLM_MCS_RATE_1 = 1,
+	WLM_MCS_RATE_2 = 2,
+	WLM_MCS_RATE_3 = 3,
+	WLM_MCS_RATE_4 = 4,
+	WLM_MCS_RATE_5 = 5,
+	WLM_MCS_RATE_6 = 6,
+	WLM_MCS_RATE_7 = 7,
+	WLM_MCS_RATE_8 = 8,
+	WLM_MCS_RATE_9 = 9,
+	WLM_MCS_RATE_10 = 10,
+	WLM_MCS_RATE_11 = 11,
+	WLM_MCS_RATE_12 = 12,
+	WLM_MCS_RATE_13 = 13,
+	WLM_MCS_RATE_14 = 14,
+	WLM_MCS_RATE_15 = 15,
+	WLM_MCS_RATE_16 = 16,
+	WLM_MCS_RATE_17 = 17,
+	WLM_MCS_RATE_18 = 18,
+	WLM_MCS_RATE_19 = 19,
+	WLM_MCS_RATE_20 = 20,
+	WLM_MCS_RATE_21 = 21,
+	WLM_MCS_RATE_22 = 22,
+	WLM_MCS_RATE_23 = 23,
+	WLM_MCS_RATE_24 = 24,
+	WLM_MCS_RATE_25 = 25,
+	WLM_MCS_RATE_26 = 26,
+	WLM_MCS_RATE_27 = 27,
+	WLM_MCS_RATE_28 = 28,
+	WLM_MCS_RATE_29 = 29,
+	WLM_MCS_RATE_30 = 30,
+	WLM_MCS_RATE_31 = 31,
+	WLM_MCS_RATE_32 = 32
+};
+
+typedef int WLM_MCS_RATE;
+
+/* Supported STF mode */
+enum {
+	WLM_STF_MODE_SISO = 0, 	/* stf mode SISO */
+	WLM_STF_MODE_CDD = 1,  	/* stf mode CDD  */
+	WLM_STF_MODE_STBC = 2,  /* stf mode STBC */
+	WLM_STF_MODE_SDM  = 3	/* stf mode SDM  */
+};
+typedef int WLM_STF_MODE;
+
+
+/* Supported PLCP preambles. */
+/* Values are used to select the preamble used for testing. */
+enum {
+	WLM_PREAMBLE_AUTO = -1,
+	WLM_PREAMBLE_SHORT = 0,
+	WLM_PREAMBLE_LONG = 1
+};
+typedef int WLM_PREAMBLE;
+
+/* Supported MIMO preamble types */
+enum {
+	WLM_MIMO_MIXEDMODE = 0,
+	WLM_MIMO_GREENFIELD = 1
+};
+typedef int WLM_MIMO_PREAMBLE;
+
+enum {
+	WLM_CHAN_FREEQ_RANGE_2G = 0,
+	WLM_CHAN_FREEQ_RANGE_5GL,
+	WLM_CHAN_FREEQ_RANGE_5GM,
+	WLM_CHAN_FREEQ_RANGE_5GH
+};
+typedef int WLM_BANDRANGE;
+
+/* Supported image formats modes. */
+/* Values are used to select the type of image to read/write. */
+enum {
+	WLM_TYPE_AUTO = 0,  /* Auto mode. */
+	WLM_TYPE_SROM = 1,  /* SROM. */
+	WLM_TYPE_OTP = 2    /* OTP. */
+};
+typedef int WLM_IMAGE_TYPE;
+
+/* Supported authentication type. */
+/* Values are used to select the authentication type used to join a network. */
+enum {
+	WLM_TYPE_OPEN = 0,    /* Open */
+    WLM_TYPE_SHARED = 1   /* Shared */
+};
+typedef int WLM_AUTH_TYPE;
+
+/* Supported authentication mode. */
+/* Values are used to select the authentication mode used to join a network. */
+enum {
+	WLM_WPA_AUTH_DISABLED = 0x0000,	/* Legacy (i.e., non-WPA) */
+	WLM_WPA_AUTH_NONE = 0x0001,		/* none (IBSS) */
+	WLM_WPA_AUTH_PSK = 0x0004,		/* Pre-shared key */
+	WLM_WPA2_AUTH_PSK = 0x0080		/* Pre-shared key */
+};
+typedef int WLM_AUTH_MODE;
+
+/* WLAN Security Encryption. */
+/* Values are used to select the type of encryption used for testing. */
+enum {
+	WLM_ENCRYPT_NONE = 0,    /* No encryption. */
+	WLM_ENCRYPT_WEP = 1,     /* WEP encryption. */
+	WLM_ENCRYPT_TKIP = 2,    /* TKIP encryption. */
+	WLM_ENCRYPT_AES = 4,     /* AES encryption. */
+	WLM_ENCRYPT_WSEC = 8,    /* Software WSEC encryption. */
+	WLM_ENCRYPT_FIPS = 0x80  /* FIPS encryption. */
+};
+typedef int WLM_ENCRYPTION;
+
+/* Country abbreviative code */
+#define WLM_COUNTRY_ALL "ALL"	/* Default country code */
+#define WLM_COUNTRY_JAPAN "JP"     /* Japan country code */
+#define WLM_COUNTRY_KOREA "KR"     /* Korea country code */
+
+/* number of 5G channel offsets */
+#define CGA_5G_OFFSETS_LEN 24
+
+/* number of 2G channel offsets */
+#define CGA_2G_OFFSETS_LEN 14
+
+/* Initialization related functions */
+
+
+#define WLM_VERSION_STR "wlm version: 10.02.0 (support 4325, 4329, 4330 and 43236)"
+
+/* Get the WLM version.
+ * param[out] buffer version string for current wlm (dll, lib and dylib)
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmWLMVersionGet(const char **buffer);
+
+/* Performs any initialization required internally by the DLL.
+ * NOTE: This method needs to be called before any other API function.
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmApiInit(void);
+
+/* Performs any cleanup required internally by the DLL.
+ * NOTE: This method needs to be called by the user at the end of the application.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmApiCleanup(void);
+
+/* Selects the interface to use for talking to the DUT
+ *
+ * param[in] ifType The desired interface.
+ * param[in] ifName Expected value depends on ifType:
+ *   For ifType = WLM_DUT_DONGLE, ifName is the COM port to use (ex: "COM1").
+ *   For ifType = WLM_DUT_SOCKET, ifName is the IP address to use
+ *		(ex: "192.168.1.1" or "localhost").
+ * param[in] dutServerPort Server port of DUT (used only for WLM_DUT_SOCKET).
+ * param[in] dutOs Operating system of DUT.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSelectInterface(WLM_DUT_INTERFACE ifType, char *ifName,
+	WLM_DUT_SERVER_PORT dutServerPort, WLM_DUT_OS dutOs);
+
+/* Gets the WLAN driver version.
+ *
+ * param[in] buffer Buffer for the version string.
+ * param[in] length Maximum length of buffer.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmVersionGet(char *buffer, int length);
+
+/* Enables or disables wireless adapter.
+ *
+ * param[in] enable Set to true to bring adapter up, false to bring down.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmEnableAdapterUp(int enable);
+
+/* Check if adapter is currently up.
+ *
+ * param[in] up Return the up/down state of adapter.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmIsAdapterUp(int *up);
+
+/* Enables or disables Minimum Power Consumption (MPC).
+ * MPC will automatically turn off the radio if not associated to a network.
+ *
+ * param[in] enable Set to true to enable MPC, false to disable MPC.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmMinPowerConsumption(int enable);
+
+/* Sets the operating channel of the DUT.
+ *
+ * param[in] channel Desired channel.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmChannelSet(int channel);
+
+/* Sets the operating legacy rate (bg_rate or a_rate) for the DUT.
+ *
+ * param[in] rate Desired rate.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRateSet(WLM_RATE rate);
+
+/* Sets the operating legacy rate (nrate) of the DUT.
+ *
+ * param[in] rate Desired rate.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmLegacyRateSet(WLM_RATE rate);
+
+
+/* Sets the operating mcs rate and STF of the DUT
+ * param[in] Desired mcs rate [0, 7] for SISO (single-in-single-out) device.
+ * param[in] Stf mode, 0=SISO, 1= CDD, 2=STBC, 3=SDM
+ * return - True for sucess, false for failure.
+*/
+WLM_FUNCTION
+int wlmMcsRateSet(WLM_MCS_RATE mcs_rate, WLM_STF_MODE stf_mode);
+
+/* Sets the PLCP preamble.
+ *
+ * param[in] preamble Desired preamble.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPreambleSet(WLM_PREAMBLE preamble);
+
+/* Set the band.
+ *
+ * param[in] The Desired band.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmBandSet(WLM_BAND band);
+
+/* Get available bands.
+ *
+ * param[in] Available bands returned in the form of WLM_BANDs added.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmGetBandList(WLM_BAND * bands);
+
+/* Set gmode.
+ *
+ * param[in] The desired gmode.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmGmodeSet(WLM_GMODE gmode);
+
+/* Sets the receive antenna.
+ *
+ * param[in] antenna Desired antenna.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRxAntSet(int antenna);
+
+/* Sets the transmit antenna.
+ *
+ * param[in] antenna Desired antenna.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTxAntSet(int antenna);
+
+/* Retrieves the current estimated power in milli-dBm.
+ *
+ * param[out] estPower Power value returned.
+ * param[in] chain For MIMO device, specifies which chain to retrieve power value from.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmEstimatedPowerGet(int *estPower, int chain);
+
+/* Retrieves the current TX power in milli-dB.
+ *
+ * param[in] power Power value returned.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTxPowerGet(int *power);
+
+/* Sets the current TX power.
+ *
+ * param[in] powerValue Desired power value. Expected to be in milli-dB. Use -1 to restore default.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTxPowerSet(int powerValue);
+
+/* Retrieves the tx power control parameters for SISO system.
+ *
+ * param[in] bandrange. The desired band range for getting PA parameters.
+ * param[out] b0 PA parameter returned.
+ * param[out] b1 PA parameter returned.
+ * param[out] a1 PA parameter returned.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPaParametersGet(WLM_BANDRANGE bandrange,
+	unsigned int *a1, unsigned int *b0, unsigned int *b1);
+
+/* Sets tx power control parameters for SISO system.
+ *
+ * param[in] bandrange. The desired band range for getting PA parameters.
+ * param[in] b0 PA parameter.
+ * param[in] b1 PA parameter.
+ * param[in] a1 PA parameter.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPaParametersSet(WLM_BANDRANGE bandrange,
+	unsigned int a1, unsigned int b0, unsigned int b1);
+
+/* Retrieves the tx power control parameters for MIMO system.
+ *
+ * param[in] bandrange The desired band range for getting PA parameters.
+ * param[in] chain. The desired tx chain for getting PA parameters
+ * param[out] b0 PA parameter returned.
+ * param[out] b1 PA parameter returned.
+ * param[out] a1 PA parameter returned.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmMIMOPaParametersGet(WLM_BANDRANGE bandrange, int chain,
+	unsigned int *a1, unsigned int *b0, unsigned int *b1);
+
+/* Sets tx power control parameters for MIMO system.
+ *
+ * param[in] bandrange. The desired band range for getting PA parameters.
+ * param[in] chain. The desired tx chain for getting PA parameters.
+ * param[in] b0 PA parameter.
+ * param[in] b1 PA parameter.
+ * param[in] a1 PA parameter.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmMIMOPaParametersSet(WLM_BANDRANGE bandrange, int chain,
+	unsigned int a1, unsigned int b0, unsigned int b1);
+
+/* Retrieves the current MAC address of the device.
+ *
+ * param[in] macAddr MAC address returned.
+ * param[in] length Length of macAddr buffer.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmMacAddrGet(char *macAddr, int length);
+
+/* Sets the MAC address of the device.
+ *
+ * param[in] macAddr The desired MAC address. Expected format is "XX:XX:XX:XX:XX:XX".
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmMacAddrSet(const char* macAddr);
+
+/* Enables or disables output of a carrier tone.
+ *
+ * param[in] enable Set to true to enable carrier tone, false to disable.
+ * param[in] channel Desired channel. Ignored if <i>enable</i> is false.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmEnableCarrierTone(int enable, int channel);
+
+/* Enables or disables an EVM test.
+ *
+ * param[in] enable Set to true to enable EVM test, false to disable.
+ * param[in] channel Desired channel. Ignored if <i>enable</i> is false.
+ * param[in] rate Desired rate. Ignored if <i>enable</i> is false.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmEnableEVMTest(int enable, WLM_RATE rate, int channel);
+
+/* RX/TX related functions */
+
+/* Starts sending packets with supplied parameters.
+ *
+ * param[in] shortPreamble Set to true to use a short preamble, false for a long preamble.
+ * param[in] interPacketDelay Delay between each packet.
+ * param[in] numPackets The number of packets transmitted.
+ * param[in] packetLength Length of packet transmitted.
+ * param[in] destMac The MAC address of the destination.
+ * param[in] withAck Ack response expected for transmitted packet.
+ * param[in] syncMode Enable synchronous mode to transmit packets before returning.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTxPacketStart(unsigned int interPacketDelay,
+	unsigned int numPackets, unsigned int packetLength,
+	const char* destMac, int withAck, int syncMode);
+
+/* Stops sending packets.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTxPacketStop(void);
+
+/* Starts receiving packets with supplied parameters.
+ *
+ * param[in] srcMac The MAC address of the packet source..
+ * param[in] withAck Ack response expected for received packet.
+ * param[in] syncMode Enable synchronous mode to receive packets before returning or timeout.
+ * param[in] numPackets Number of receive packets before returning (sync mode only).
+ * param[in] timeout Maximum timeout in msec (sync mode only).
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRxPacketStart(const char* srcMac, int withAck,
+	int syncMode, unsigned int numPackets, unsigned int timeout);
+
+/* Stops receiving packets.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRxPacketStop(void);
+
+/* Returns number of packets that were ACKed successfully.
+ *
+ * param[in] count Packet count returned.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTxGetAckedPackets(unsigned int *count);
+
+/* Returns number of packets received successfully.
+ *
+ * param[in] count Packet count returned.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRxGetReceivedPackets(unsigned int *count);
+
+/* Returns Receive Signal Strength Indicator (RSSI).
+ *
+ * param[in] rssi RSSI returned.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRssiGet(int *rssi);
+
+/* Sequence related functions */
+
+/* Initiates a command batch sequence.
+ * Any commands issued after calling this function will be queued
+ * instead of being executed. Call sequenceStop() to run queued commands.
+ *
+ * param[in] clientBatching Set to true to batch on client, false to batch on server/DUT.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSequenceStart(int clientBatching);
+
+/* Signals the end of a command batch sequence.
+ * Requires a previous call to sequenceStart(). Any commands
+ * issued after previously calling sequenceStart() will be run.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSequenceStop(void);
+
+/* Sets a delay between commands, in ms.
+ * Requires a previous call to sequenceStart(). Once sequenceStart() is called,
+ * calling sequenceDelay() after a command will insert a delay after the
+ * previous command is complete.
+ *
+ * param[in] msec Amount of time to wait after previous command has complete.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSequenceDelay(int msec);
+
+/* If a command sequence fails at a particular command, the remaining
+ * commands will be aborted. Calling this function, will return the index
+ * of which command failed. NOTE: Index starts at 1.
+ *
+ * param[in] index Failed command index returned.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSequenceErrorIndex(int *index);
+
+/*  Image access (SROM/OTP) functions: */
+
+/* Programs the device with a supplied image. Used to program the SROM/OTP.
+ *
+ * param[in] byteStream A stream of bytes loaded from an image file.
+ * param[in] length The number of bytes to write.
+ * param[in] imageType Use this to force a specific image type (ex: SROM, OTP, etc).
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmDeviceImageWrite(const char* byteStream, int length, WLM_IMAGE_TYPE imageType);
+
+/* Dumps the image from the device. Used to read the SROM/OTP.
+ *
+ * param[out] byteStream A user supplied buffer.
+ * param[in] length The size of the buffer supplied by byteStream.
+ * param[in] imageType Use this to force a specific image type (ex: SROM, OTP, etc).
+ *
+ * return - Size of image in bytes. -1 if size of image is larger than supplied buffer.
+ */
+WLM_FUNCTION
+int wlmDeviceImageRead(char* byteStream, unsigned int length, WLM_IMAGE_TYPE imageType);
+
+/* Network related functions */
+
+/* Set the current wireless security.
+ *
+ * param[in] authType Desired authentication type.
+ * param[in] authMode Desired authentication mode.
+ * param[in] encryption The desired encryption method.
+ * param[in] key The encryption key string (null terminated).
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSecuritySet(WLM_AUTH_TYPE authType, WLM_AUTH_MODE authMode,
+	WLM_ENCRYPTION encryption, const char *key);
+
+/* Joins a  network.
+ *
+ * param[in] ssid The SSID of the network to join.
+ * param[in] mode The mode used for the join.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmJoinNetwork(const char* ssid, WLM_JOIN_MODE mode);
+
+/* Disassociates from a currently joined network.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmDisassociateNetwork(void);
+
+/* Retrieves the current SSID of the AP.
+ *
+ * param[in] ssid SSID returned. SSID may be returned if not associated
+ * (i.e. attempting to associate, roaming).
+ * param[in] length Length of ssid buffer.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSsidGet(char *ssid, int length);
+
+/* Retrieves the current BSSID of the AP.
+ *
+ * param[in] bssid BSSID returned. If the device is not associated, empty string returned.
+ * param[in] length Length of bssid buffer.
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmBssidGet(char *ssid, int length);
+
+/* Set/Get the MIMO Preamble mode
+ * Valid options are:
+ * WLC_N_PREAMBLE_MIXEDMODE 0
+ *  WLC_N_PREAMBLE_GF 1
+ */
+
+WLM_FUNCTION
+int wlmMimoPreambleSet(int type);
+
+WLM_FUNCTION
+int wlmMimoPreambleGet(int* type);
+
+/* Set/Get the CGA coefficients in the 2.4G/5G band
+ * requires an array of 24 uint8s to be set
+ * and a specified length of 24 to get
+ * All of these CGA value query functions only applies to 4329 solution
+ */
+
+WLM_FUNCTION
+int wlmCga5gOffsetsSet(char* values, int len);
+
+WLM_FUNCTION
+int wlmCga5gOffsetsGet(char* buffer, int len);
+
+WLM_FUNCTION
+int wlmCga2gOffsetsSet(char* values, int len);
+
+WLM_FUNCTION
+int wlmCga2gOffsetsGet(char* buffer, int len);
+
+/* Set Glacial Timer
+ * param[in] timer duration in msec
+ *
+ * return - True for success, false for failure.
+*/
+WLM_FUNCTION
+int wlmGlacialTimerSet(int val);
+
+/* Set Fast Timer
+ * param[in] timer duration in msec
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmFastTimerSet(int val);
+
+/* Set Slow Timer
+ * param[in] timer duration in msec
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSlowTimerSet(int val);
+
+/* Enable/Disable Scansuppress
+ * param[in] set to TRUE enables scansuppress, set to false disable scansuppress
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmScanSuppress(int val);
+
+/* Set Country Code
+ * param[in] country code abbrv. Default use WLM_COUNTRY_CODE_ABBRV_ALL
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmCountryCodeSet(const char *country_name);
+
+/* Set fullcal
+ * Trigger lpphy fullcal
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmFullCal(void);
+
+/* Get Receiver IQ Estimation
+ * param[out] estimated rxiq power in dBm at 0.25dBm resolution
+ * param[in] sampel count, 0 to 15
+ * param[in] antenna, 0 to 3
+ * return - True for success, false for failure.
+*/
+WLM_FUNCTION
+int wlmRxIQEstGet(float *val, int sampleCount, int ant);
+
+/* Get PHY txpwrindex
+ * param[out] txpwrindex
+ * param[in] chip id: 4325, 4329, 43291, 4330, 4336 and 43236
+ */
+WLM_FUNCTION
+int wlmPHYTxPowerIndexGet(unsigned int *val, const char *chipid);
+
+/* Set PHY txpwrindex
+ * param[in] txpwrindex
+ * param[in] chip id: 4325, 4329, 43291, 4330, 4336 and 43236
+ */
+WLM_FUNCTION
+int wlmPHYTxPowerIndexSet(unsigned int val, const char *chipid);
+
+/* Enable/Disable RIFS
+ * param[in] Set RIFS mode. 1 = enable ; 0 = disable
+ */
+WLM_FUNCTION
+int wlmRIFSEnable(int enable);
+
+/* Get/Set IOCTL
+ * param[in] cmd IOCTL command.
+ * param[in] buf Get data returned or set data input.
+ * param[in] len Length of buf.
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION int wlmIoctlGet(int cmd, void *buf, int len);
+WLM_FUNCTION int wlmIoctlSet(int cmd, void *buf, int len);
+
+/* Get/Set IOVAR
+ * param[in] iovar IOVAR command.
+ * param[in] buf Get data returned or set data input.
+ * param[in] len Length of buf.
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION int wlmIovarGet(const char *iovar, void *buf, int len);
+WLM_FUNCTION int wlmIovarSet(const char *iovar, void *buf, int len);
+
+/* Get/Set IOVAR integer.
+ * param[in] iovar IOVAR integer command.
+ * param[out/in] val Get integer returned or set integer input.
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION int wlmIovarIntegerGet(const char *iovar, int *val);
+WLM_FUNCTION int wlmIovarIntegerSet(const char *iovar, int val);
+
+/* Get/Set IOVAR using internal buffer.
+ * param[in] iovar IOVAR command.
+ * param[in] param Input parameters.
+ * param[in] param_len Length of parameters.
+ * param[out] bufptr Buffer returning get data.
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION int wlmIovarBufferGet(const char *iovar, void *param, int param_len, void **bufptr);
+WLM_FUNCTION int wlmIovarBufferSet(const char *iovar, void *param, int param_len);
+
+
+
+/* Enables radio
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRadioOn(void);
+
+/* Disable radio .
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRadioOff(void);
+
+/* Set Power Saving Mode
+ * param[in] 0 = CAM, 1 =Power Save, 2 = Fast PS Mode
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPMmode(int val);
+
+/* Enable roaming
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRoamingOff(void);
+
+/* Disable roaming
+ *
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRoamingOn(void);
+
+/* Get roaming trigger level
+ * param[out] roaming trigger level in dBm returned
+ * param[in]  frequency band
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRoamTriggerLevelGet(int *val, WLM_BAND band);
+
+/* Set roaming trigger level
+ * param[in] roaming trigger level in dBm
+ * param[in]  frequence band
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRoamTriggerLevelSet(int val, WLM_BAND band);
+
+/* Set framburst mode on
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmFrameBurstOn(void);
+
+/* Set framburst mode off
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmFrameBurstOff(void);
+
+/* Set beacon interval
+ * param[in] beacon interval in ms
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmBeaconIntervalSet(int val);
+
+/* Set AMPDU mode on/off
+ * param[in] on = 1, off = 0
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmAMPDUModeSet(int val);
+
+/* Set MIMO bandwidth capability
+ * param[in] mimo bandwidth capability. 0 = 20Mhz, 1 =40Mhz
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmMIMOBandwidthCapabilitySet(int val);
+
+/* Set interference on/off
+ * param[in] on = 1, 0ff = 0
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmInterferenceSet(int val);
+
+/* Set interferenceoverride on/off
+ * param[in] on = 1, 0ff = 0
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmInterferenceOverrideSet(int val);
+
+/* Set MIMO transmit banddwith
+ * param[in] auto = -1, 2 = 20Mhz, 3 = 20Mhz upper , 4 =40 Mhz, 5 =40dup (mcs32 only)
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTransmitBandwidthSet(int val);
+
+/* Set MIMO short guard intervaltransmit banddwith
+ * param[in] auto = -1, 1 = on, 0 = off
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmShortGuardIntervalSet(int val);
+
+/* Set MIMO OBSS coex set
+ * param[in] auto = -1, 1 = on, 0 = off
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmObssCoexSet(int val);
+
+/* Set PHY Periodical call
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPHYPeriodicalCalSet(void);
+
+/* Set PHY Force call
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPHYForceCalSet(void);
+
+/* Disable scrambler update
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPHYScramblerUpdateDisable(void);
+
+/* Enable scrambler update
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPHYScramblerUpdateEnable(void);
+
+/* Turn PHY watchdog on/off
+ * param[in] on = 1, off = 0
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPHYWatchdogSet(int val);
+
+/* Disable temperature sensore
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTemperatureSensorDisable(void);
+
+/* Enable temperature sensore
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTemperatureSensorEnable(void);
+
+/* Set transmit core
+ * param[in]
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTransmitCoreSet(int val);
+
+/* Get temperation sensor read
+ * param[out] chip core temperature in F
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmPhyTempSenseGet(int *val);
+
+/* Get chip OTP Fab ID
+ * param[out] chip fab id
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmOtpFabidGet(int *val);
+
+/* Set mimo channnel specifications
+ * param[in] channel
+ * param[in] bandwidth 20 = 20Mhz, 40 = 40Mhz
+ * param[in] sideband 1 = upper, -1 = lower, 0 = none
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmChannelSpecSet(int channel, int bandwidth, int sideband);
+
+/* Set rts threshold
+ * param[in] rts threshold value
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRtsThresholdOverride(int val);
+
+/* Turn STBC Tx mode on/off
+ * param[in] on = 1, off = 0
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSTBCTxSet(int val);
+
+/* Turn STBC Rx mode on/off
+ * param[in] on = 1, off = 0
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmSTBCRxSet(int val);
+
+/* MIMO single stream tx chain selection
+ * param[in] chain 1 = 1, chain 2 = 2
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmTxChainSet(int val);
+
+/* MIMO single stream rx chain selection
+ * param[in] chain 1 = 1, chain 2 = 2
+ * return - True for success, false for failure.
+ */
+WLM_FUNCTION
+int wlmRxChainSet(int val);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _wlm_h */
diff --git a/src/wl/exe/wlu.c b/src/wl/exe/wlu.c
new file mode 100644
index 0000000..b2583e4
--- /dev/null
+++ b/src/wl/exe/wlu.c
@@ -0,0 +1,36330 @@
+/*
+ * Common code for wl command-line swiss-army-knife utility
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu.c 647609 2016-07-06 21:27:18Z $
+ */
+
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#define CLMDOWNLOAD
+
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <typedefs.h>
+#include <epivers.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+#include <proto/802.1d.h>
+#include <proto/802.11e.h>
+#include <proto/wpa.h>
+#include <proto/bcmip.h>
+#include <proto/wps.h>
+
+#include <bcmwifi_rates.h>
+#include "wlu_rates_matrix.h"
+
+#ifdef BCMCCX
+#include <proto/802.11_ccx.h>
+#endif
+#ifdef WLBTAMP
+#include <proto/bt_amp_hci.h>
+#endif
+#include <sdiovar.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmwifi_channels.h>
+#include <bcmsrom_fmt.h>
+#include <bcmsrom_tbl.h>
+#include "wlu_common.h"
+#include "wlu.h"
+#include <bcmcdc.h>
+#if defined(WLPFN)
+#ifndef TARGETENV_android
+#include <unistd.h>
+#endif
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* WLPFN */
+
+#ifdef WLEXTLOG
+#include <wlc_extlog_idstr.h>
+#endif
+
+#include <inttypes.h>
+#include <miniopt.h>
+#include <errno.h>
+
+#if defined CLMDOWNLOAD
+#include <sys/stat.h>
+#include <trxhdr.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef WIN32
+#include <fcntl.h>
+#endif /* WIN32 */
+#endif 
+
+
+#if LCNCONF || SSLPNCONF
+#define MAX_CHUNK_LEN 1456  /* 8 * 7 * 26 */
+#else
+#define MAX_CHUNK_LEN 1408 /* 8 * 8 * 22 */
+#endif
+
+#include <bcm_mpool_pub.h>
+#include <proto/bcmipv6.h>
+
+#ifdef EVENT_LOG_COMPILE
+#define EVENT_LOG_DUMPER
+#include <event_log.h>
+#endif
+
+/* For backwards compatibility, the absense of the define 'NO_FILESYSTEM_SUPPORT'
+ * implies that a filesystem is supported.
+ */
+#if !defined(BWL_NO_FILESYSTEM_SUPPORT)
+#define BWL_FILESYSTEM_SUPPORT
+#endif
+
+cmd_func_t wl_int;
+
+
+static cmd_func_t wl_print_deprecate;
+static cmd_func_t wl_void, wl_rssi, wl_rssi_event, wl_phy_rssi_ant, wl_gmode;
+static cmd_func_t wlu_dump, wlu_mempool, wlu_srdump, wlu_srwrite, wlu_srvar, wl_nvsource;
+static cmd_func_t wlu_ciswrite, wlu_cisupdate, wlu_cisdump, wlu_offloads_stats;
+static cmd_func_t wl_rate, wl_rate_mrate, wl_phy_rate, wl_bss_max;
+static cmd_func_t wl_channel, wl_chanspec, wl_chanim_state, wl_chanim_mode, wl_rclass;
+static cmd_func_t wl_radio, wl_version, wl_list, wl_band, wl_bandlist, wl_phylist;
+static cmd_func_t wl_join, wl_tssi, wl_txpwr, wl_atten, wl_evm, wl_country;
+static cmd_func_t wl_out, wl_txpwr1, wl_country_ie_override;
+static cmd_func_t wl_maclist, wl_get_pktcnt, wl_upgrade;
+static cmd_func_t wl_maclist_1, wl_default_rateset;
+static cmd_func_t wl_rateset, wl_interfere, wl_interfere_override;
+static cmd_func_t wl_radar_args, wl_radar_thrs, wl_dfs_status;
+static cmd_func_t wl_get_txpwr_limit, wl_get_current_power, wl_get_instant_power;
+static cmd_func_t wl_get_current_txppr, wl_get_txpwr_target_max;
+static cmd_func_t wl_var_get, wl_var_getint, wl_var_getinthex, wl_var_getandprintstr;
+static cmd_func_t wl_var_setint, wl_addwep, wl_rmwep;
+static cmd_func_t wl_nvdump, wl_nvget, wl_nvset, wl_sta_info, wl_chan_info;
+static cmd_func_t wl_wme_ac_req, wl_add_ie, wl_del_ie, _wl_list_ie;
+static cmd_func_t wl_wme_apsd_sta, wl_wme_dp, wl_lifetime;
+static cmd_func_t wl_rand, wl_otpw, wl_otpraw, wl_counters, wl_delta_stats;
+static cmd_func_t wl_assoc_info, wl_wme_counters, wl_devpath;
+static cmd_func_t wl_management_info;
+static cmd_func_t wl_eventbitvec, wl_diag, wl_var_void;
+static cmd_func_t wl_auto_channel_sel;
+static cmd_func_t wl_bsscfg_int, wl_bsscfg_enable;
+static cmd_func_t wl_msglevel, wl_plcphdr, wl_reg, wl_macreg, wl_band_elm;
+static cmd_func_t wl_phymsglevel;
+static cmd_func_t wl_rateparam, wl_wepstatus, wl_status, wl_spect;
+static cmd_func_t wl_sup_rateset, wl_scan, wl_send_csa, wl_iscan, wl_escan;
+static cmd_func_t wl_roamparms;
+/* WLOTA_EN START */
+static cmd_func_t wl_ota_loadtest, wl_otatest_status, wl_load_cmd_stream;
+static cmd_func_t wl_ota_teststop;
+/* WLOTA_EN END */
+#ifdef EXTENDED_SCAN
+static cmd_func_t wl_extdscan;
+#endif
+static cmd_func_t wl_dump_chanlist, wl_primary_key, wl_measure_req, wl_send_quiet;
+static cmd_func_t wl_dump_chanspecs, wl_dump_chanspecs_defset, wl_cur_mcsset;
+static cmd_func_t wl_wsec, wl_keys, wl_wsec_test;
+static cmd_func_t wl_channels_in_country;
+static cmd_func_t wl_wpa_auth, wl_tsc, wl_deauth_rc, wl_ssid, wl_bssid, wl_smfstats;
+static cmd_func_t wl_wds_wpa_role_old, wl_wds_wpa_role, wl_set_pmk;
+static cmd_func_t wl_rm_request, wl_rm_report;
+static cmd_func_t wl_join_pref, wl_assoc_pref;
+static cmd_func_t wl_dump_networks, wl_mac, wl_revinfo, wl_iov_mac, wl_iov_pktqlog_params;
+static cmd_func_t wl_cac, wl_tslist, wl_tspec, wl_tslist_ea, wl_tspec_ea, wl_cac_delts_ea;
+static cmd_func_t wl_varstr, wl_var_setintandprintstr;
+static cmd_func_t wl_rifs;
+static cmd_func_t wl_rifs_advert;
+static cmd_func_t wl_test_tssi, wl_test_tssi_offs, wl_phy_rssiant, wl_rxiq;
+static cmd_func_t wl_obss_scan, wl_obss_coex_action;
+static cmd_func_t wl_dump_lq;
+static cmd_func_t wl_monitor_lq;
+static cmd_func_t wl_test_idletssi;
+
+#ifdef WLPFN
+static cmd_func_t wl_pfn_set;
+static cmd_func_t wl_pfn_add;
+static cmd_func_t wl_pfn_add_bssid;
+static cmd_func_t wl_pfn_cfg;
+static cmd_func_t wl_pfn;
+static cmd_func_t wl_pfnbest;
+static cmd_func_t wl_pfn_suspend;
+static cmd_func_t wl_pfnlbest;
+static cmd_func_t wl_pfn_mem;
+static cmd_func_t wl_pfn_event_check;
+static cmd_func_t wl_escan_event_check;
+static cmd_func_t wl_escanresults;
+static cmd_func_t wl_event_filter;
+#endif /* WLPFN */
+
+#ifdef WLP2PO
+static cmd_func_t wl_p2po_listen;
+static cmd_func_t wl_p2po_addsvc;
+static cmd_func_t wl_p2po_delsvc;
+static cmd_func_t wl_p2po_sd_reqresp;
+static cmd_func_t wl_p2po_listen_channel;
+static cmd_func_t wl_p2po_stop;
+static cmd_func_t wl_p2po_results;
+
+#endif	/* WLP2PO */
+
+#ifdef WLANQPO
+static cmd_func_t wl_anqpo_set;
+static cmd_func_t wl_anqpo_stop_query;
+static cmd_func_t wl_anqpo_start_query;
+static cmd_func_t wl_anqpo_ignore_ssid_list;
+static cmd_func_t wl_anqpo_ignore_bssid_list;
+static cmd_func_t wl_anqpo_results;
+#endif	/* WLANQPO */
+static cmd_func_t wl_hs20_ie;
+
+static cmd_func_t wl_wowl_pattern, wl_wowl_wakeind, wl_wowl_pkt, wl_wowl_status;
+static cmd_func_t wl_wowl_wake_reason, wl_wowl_extended_magic;
+static cmd_func_t wl_reassoc;
+
+static cmd_func_t wl_sd_reg, wl_sd_msglevel, wl_sd_blocksize, wl_sd_mode;
+
+static cmd_func_t wl_overlay;
+static cmd_func_t wl_pmkid_info;
+
+#ifdef BCMCCX
+static cmd_func_t wl_leap;
+#endif
+
+static void wl_rate_histo_print(wl_mac_ratehisto_res_t *rate_histo_res);
+static cmd_func_t wl_rate_histo;
+static cmd_func_t wl_mac_rate_histo;
+static cmd_func_t wl_sample_collect;
+static cmd_func_t wlu_reg3args;
+
+static cmd_func_t wl_tpc_lm;
+static cmd_func_t wlu_reg2args;
+static cmd_func_t wme_tx_params;
+static cmd_func_t wme_maxbw_params;
+static cmd_func_t wl_ampdu_tid, wl_ampdu_activate_test;
+static cmd_func_t wl_ampdu_retry_limit_tid;
+static cmd_func_t wl_ampdu_rr_retry_limit_tid;
+static cmd_func_t wl_ampdu_send_addba;
+static cmd_func_t wl_ampdu_send_delba;
+
+static cmd_func_t wl_dpt_deny;
+static cmd_func_t wl_dpt_endpoint;
+static cmd_func_t wl_dpt_pmk;
+static cmd_func_t wl_dpt_fname;
+static cmd_func_t wl_dpt_list;
+#ifdef WLTDLS
+static cmd_func_t wl_tdls_endpoint;
+static cmd_func_t wl_tdls_wfd_ie;
+#endif /* WLTDLS */
+#ifdef WLBTAMP
+static cmd_func_t wl_HCI_cmd;
+static cmd_func_t wl_HCI_ACL_data;
+static cmd_func_t wl_get_btamp_log;
+#endif
+static cmd_func_t wl_actframe;
+
+static cmd_func_t wl_gpioout;
+
+static cmd_func_t wl_bw_cap;
+static cmd_func_t wl_nrate, wl_antsel, wl_txcore;
+static cmd_func_t wl_txcore_pwr_offset;
+#ifdef PLC
+static cmd_func_t wl_plc;
+#endif /* PLC */
+static cmd_func_t wl_txfifo_sz;
+static cmd_func_t wl_pkteng, wl_pkteng_stats;
+
+static cmd_func_t wl_offload_cmpnt;
+static cmd_func_t wl_hostip, wl_arp_stats, wl_toe_stats, wl_nshostip;
+static cmd_func_t wl_mcast_ackmac, wl_mcast_ackreq, wl_mcast_status;
+static cmd_func_t wl_mcast_actf_time, wl_mcast_rssi_thresh, wl_mcast_stats;
+static cmd_func_t wl_mcast_rssi_delta, wl_mcast_vsie, wl_mcast_ar_timeout;
+#ifdef WLOFFLD
+static cmd_func_t wl_ol_notify_bcn_ie;
+#endif
+
+#if defined(WLNDOE) || defined(WLOFFLD)
+static cmd_func_t wl_hostipv6;
+#endif
+#ifdef WLNDOE
+static cmd_func_t wl_ndstatus, wl_hostipv6, wl_solicitipv6, wl_remoteipv6;
+#endif
+static cmd_func_t wl_phy_papdepstbl;
+
+int wl_seq_batch_in_client(bool enable);
+cmd_func_t wl_seq_start;
+cmd_func_t wl_seq_stop;
+
+static cmd_func_t wl_phy_txiqcc, wl_phy_txlocc;
+static cmd_func_t wl_rssi_cal_freq_grp_2g;
+static cmd_func_t wl_phy_rssi_gain_delta_2g, wl_phy_rssi_gain_delta_5g;
+static cmd_func_t wl_phy_rssi_gain_delta_2g_sub;
+static cmd_func_t wl_phy_rxgainerr_2g, wl_phy_rxgainerr_5g;
+static cmd_func_t wl_phytable, wl_phy_pavars, wl_phy_povars;
+static cmd_func_t wl_phy_fem, wl_phy_maxpower, wl_antgain, wl_phy_txpwrindex;
+static cmd_func_t wl_keep_alive;
+static cmd_func_t wl_mkeep_alive;
+static cmd_func_t wl_srchmem;
+static cmd_func_t wl_phy_rpcalvars;
+
+static cmd_func_t wl_pkt_filter_add;
+static cmd_func_t wl_pkt_filter_enable;
+static cmd_func_t wl_pkt_filter_list;
+static cmd_func_t wl_pkt_filter_stats;
+
+#ifdef TRAFFIC_MGMT
+static cmd_func_t wl_trf_mgmt_config;
+static cmd_func_t wl_trf_mgmt_filters_add;
+static cmd_func_t wl_trf_mgmt_filters_addex;
+static cmd_func_t wl_trf_mgmt_filters_remove;
+static cmd_func_t wl_trf_mgmt_filters_removeex;
+static cmd_func_t wl_trf_mgmt_filters_list;
+static cmd_func_t wl_trf_mgmt_filters_clear;
+static cmd_func_t wl_trf_mgmt_bandwidth;
+static cmd_func_t wl_trf_mgmt_flags;
+static cmd_func_t wl_trf_mgmt_stats;
+static cmd_func_t wl_trf_mgmt_stats_clear;
+static cmd_func_t wl_trf_mgmt_shaping_info;
+#endif  /* TRAFFIC_MGMT */
+
+#ifdef CLMDOWNLOAD
+static cmd_func_t wl_clmload;
+#endif /* CLMDOWNLOAD */
+static cmd_func_t wl_ledbh;
+
+#ifdef RWL_WIFI
+/* Function added to support RWL_WIFI Transport */
+static cmd_func_t wl_wifiserver;
+#endif
+
+static cmd_func_t wl_led_blink_sync;
+static cmd_func_t wl_cca_get_stats;
+static cmd_func_t wl_itfr_get_stats;
+static cmd_func_t wl_rrm;
+static cmd_func_t wl_rrm_nbr_req;
+static cmd_func_t wl_rrm_bcn_req;
+static cmd_func_t wl_rrm_chload_req;
+static cmd_func_t wl_rrm_noise_req;
+static cmd_func_t wl_rrm_frame_req;
+static cmd_func_t wl_rrm_stat_req;
+static cmd_func_t wl_rrm_lm_req;
+static cmd_func_t wl_rrm_nbr_list;
+static cmd_func_t wl_rrm_nbr_del_nbr;
+static cmd_func_t wl_rrm_nbr_add_nbr;
+static cmd_func_t wl_wnm;
+static cmd_func_t wl_wnm_bsstq;
+static cmd_func_t wl_tclas_add;
+static cmd_func_t wl_tclas_del;
+static cmd_func_t wl_tclas_list;
+#ifdef WLWNM
+static cmd_func_t wl_wnm_tfsreq_add;
+static cmd_func_t wl_wnm_dms_set;
+static cmd_func_t wl_wnm_dms_status;
+static cmd_func_t wl_wnm_dms_term;
+static cmd_func_t wl_wnm_service_term;
+static cmd_func_t wl_wnm_timbc_offset;
+static cmd_func_t wl_wnm_timbc_set;
+static cmd_func_t wl_wnm_timbc_status;
+static cmd_func_t wl_wnm_maxidle;
+static cmd_func_t wl_wnm_bsstrans_req;
+static cmd_func_t wl_wnm_keepalives_max_idle;
+#endif /* WLWNM */
+static cmd_func_t wl_chanim_acs_record;
+static cmd_func_t wl_chanim_stats;
+static cmd_func_t wl_txdelay_params;
+static cmd_func_t wl_intfer_params;
+
+
+#ifdef WLP2P
+static cmd_func_t wl_p2p_state;
+static cmd_func_t wl_p2p_scan;
+static cmd_func_t wl_p2p_ifadd;
+static cmd_func_t wl_p2p_ifdel;
+static cmd_func_t wl_p2p_ifupd;
+static cmd_func_t wl_p2p_if;
+static cmd_func_t wl_p2p_ops;
+static cmd_func_t wl_p2p_noa;
+#endif
+
+static cmd_func_t wl_rpmt;
+static cmd_func_t wl_spatial_policy, wl_ratetbl_ppr;
+static cmd_func_t wl_sarlimit;
+static cmd_func_t wl_bmon_bssid;
+
+static cmd_func_t wl_ie;
+static cmd_func_t wl_wnm_url;
+
+
+
+#ifdef SR_DEBUG
+static cmd_func_t wl_dump_pmu;
+static cmd_func_t wl_pmu_keep_on;
+#endif /* SR_DEBUG */
+
+#ifdef TBTT_OFFSET_STAT
+static cmd_func_t wl_tbtt_offset_stat;
+#endif /* TBTT_OFFSET_STAT */
+
+static cmd_func_t wl_staprio;
+static cmd_func_t wl_stamon_sta_config;
+static cmd_func_t wl_monitor_promisc_level;
+static cmd_func_t wl_bcnlenhist;
+static cmd_func_t wl_aibss_bcn_force_config;
+
+#if defined(DWDS)
+static cmd_func_t wl_dwds_config;
+#endif
+
+static cmd_func_t wl_bss_peer_info;
+static cmd_func_t wl_aibss_txfail_config;
+
+static void wl_txppr_print(ppr_t *ppr, int cck, uint flags);
+static void wl_txppr_print_bw(ppr_t *ppr, int cck, uint flags, wl_tx_bw_t bw);
+static int8 wl_ppr_get_pwr(ppr_t* pprptr, reg_rate_index_t rate_idx, wl_tx_bw_t bw);
+static void wl_txpwr_array_row_print(ppr_t* pprptr, int8 channel_bandwidth,
+	reg_rate_index_t rate_idx);
+static void wl_txpwr_array_print(ppr_t* pprptr, int8 channel_bandwidth, bool verbose, bool is5G);
+static void wl_txpwr_ppr_print(ppr_t* pprptr, int vb, ppr_rate_type_t type,
+	clm_rate_group_id_t gid, int8 bw, reg_rate_index_t *rate_index, bool is5G);
+static void wl_txpwr_print_row(const char *label, uint8 chains, int8 pwr20,
+	int8 pwr20in40, int8 pwr40, int8 pwr80, int8 pwr20in80, int8 pwr40in80,
+	int8 unsupported_rate, int8 channel_bandwidth, bool verbose);
+static int wl_array_check_val(int8 *pwr, uint count, int8 val);
+static void wl_txpwr_regulatory_array_row_print(int8 *powers, int8 *powers_subchan1,
+	int8 *powers_subchan2, int8 channel_bandwidth, reg_rate_index_t rate_index);
+static void wl_txpwr_regulatory_array_print(int8 *powers, int8 *powers_subchan1,
+	int8 *powers_subchan2, int8 channel_bandwidth, bool verbose);
+static int wl_array_uniform(uint8 *pwr, int start, int count);
+static int wl_parse_rateset(void *wl, wl_rateset_args_t* rs, char **argv);
+static void wl_print_mcsset(char *mcsset);
+static void wl_print_vhtmcsset(uint16 *mcsset);
+
+static void dump_networks(char *buf);
+void dump_bss_info(wl_bss_info_t *bi);
+static void wl_dump_wpa_rsn_ies(uint8* cp, uint len);
+static void wl_rsn_ie_dump(bcm_tlv_t *ie);
+static cmd_func_t wl_power_sel_params;
+
+static cmd_func_t wl_phy_force_vsdb_chans;
+
+int wlu_get(void *wl, int cmd, void *buf, int len);
+int wlu_set(void *wl, int cmd, void *buf, int len);
+
+static int _wl_dump_lq(void *wl);
+
+/* 802.11i/WPA RSN IE parsing utilities */
+typedef struct {
+	uint16 version;
+	wpa_suite_mcast_t *mcast;
+	wpa_suite_ucast_t *ucast;
+	wpa_suite_auth_key_mgmt_t *akm;
+	uint8 *capabilities;
+} rsn_parse_info_t;
+
+static int wl_rsn_ie_parse_info(uint8* buf, uint len, rsn_parse_info_t *rsn);
+static uint wl_rsn_ie_decode_cntrs(uint cntr_field);
+
+static int wl_parse_assoc_params(char **argv, wl_assoc_params_t *params, bool *prescanned);
+static int wl_join_prescanned(void *wl, wl_join_params_t *join_params, uint *join_params_size);
+#define wl_parse_reassoc_params(argv, params) wl_parse_assoc_params(argv, \
+						(wl_assoc_params_t *)(params), NULL)
+
+static int wl_parse_channel_list(char* list_str, uint16* channel_list, int channel_num);
+static int wl_parse_chanspec_list(char* list_str, chanspec_t *chanspec_list, int chanspec_num);
+static chanspec_t wl_chspec_to_driver(chanspec_t chanspec);
+static uint32 wl_chspec32_to_driver(chanspec_t chanspec);
+static chanspec_t wl_chspec_from_driver(chanspec_t chanspec);
+static chanspec_t wl_chspec32_from_driver(uint32 chanspec);
+
+#ifdef EXTENDED_SCAN
+static int wl_parse_extdchannel_list(char* list_str,
+	chan_scandata_t* channel_list, int channel_num);
+#endif
+
+static uint16 wl_qdbm_to_mw(uint8 qdbm);
+static uint8 wl_mw_to_qdbm(uint16 mw);
+
+static int wl_cfg_option(char **argv, const char *fn_name, int *bsscfg_idx, int *consumed);
+static int get_oui_bytes(uchar *oui_str, uchar *oui);
+static int get_ie_data(uchar *data_str, uchar *ie_data, int len);
+static void wl_printrate(int val);
+static int rate_string2int(char *s);
+static char *rate_int2string(char *buf, int val);
+
+static int wl_get_iscan(void *wl, char *buf, uint buf_len);
+int wlu_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr);
+int wlu_var_getbuf_sm(void *wl, const char *iovar, void *param, int param_len, void **bufptr);
+int wlu_var_getbuf_med(void *wl, const char *iovar, void *param, int param_len, void **bufptr);
+int wlu_var_setbuf(void *wl, const char *iovar, void *param, int param_len);
+
+
+int wlu_iovar_get(void *wl, const char *iovar, void *outbuf, int len);
+int wlu_iovar_set(void *wl, const char *iovar, void *param, int paramlen);
+int wlu_iovar_getint(void *wl, const char *iovar, int *pval);
+int wlu_iovar_setint(void *wl, const char *iovar, int val);
+
+static int wl_bssiovar_mkbuf(const char *iovar, int bssidx, void *param,
+	int paramlen, void *bufptr, int buflen, int *perr);
+int wlu_bssiovar_setbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen);
+static int wl_bssiovar_getbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen);
+static int wl_bssiovar_set(void *wl, const char *iovar, int bssidx, void *param, int paramlen);
+int wlu_bssiovar_get(void *wl, const char *iovar, int bssidx, void *outbuf, int len);
+static int wl_bssiovar_setint(void *wl, const char *iovar, int bssidx, int val);
+static int wl_bssiovar_getint(void *wl, const char *iovar, int bssidx, int *pval);
+
+static int wl_vndr_ie(void *wl, const char *command, uint32 pktflag_ok, char **argv);
+static void wl_dump_ie_buf(vndr_ie_buf_t *ie_getbuf);
+static int hexstrtobitvec(const char *cp, uchar *bitvec, int veclen);
+static void wl_join_pref_print_ie(bcm_tlv_t *ie);
+static void wl_join_pref_print_akm(uint8* suite);
+static void wl_join_pref_print_cipher_suite(uint8* suite);
+static void wl_print_tspec(tspec_arg_t *ts);
+static void wl_cac_addts_usage(void);
+static void wl_cac_delts_usage(void);
+
+static cmd_func_t wl_txmcsset;
+static cmd_func_t wl_rxmcsset;
+
+static int wl_mimo_stf(void *wl, cmd_t *cmd, char **argv);
+
+#ifdef WLEXTLOG
+static int wl_extlog(void *wl, cmd_t *cmd, char **argv);
+static int wl_extlog_cfg(void *wl, cmd_t *cmd, char **argv);
+#endif
+
+static int wl_assertlog(void *wl, cmd_t *cmd, char **argv);
+static int wl_tsf(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_config(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_sha256(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_sa_query(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_disassoc(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_deauth(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_assoc(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_auth(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_reassoc(void *wl, cmd_t *cmd, char **argv);
+
+static cmd_func_t wl_scb_bs_data;
+
+static int wl_bssload_static(void *wl, cmd_t *cmd, char **argv);
+
+#ifdef EVENT_LOG_COMPILE
+static int wl_event_log_set_init(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_set_expand(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_set_shrink(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_tag_control(void *wl, cmd_t *cmd, char **argv);
+#endif
+
+static int wl_sleep_ret_ext(void *wl, cmd_t *cmd, char **argv);
+
+static char *ver2str(unsigned int vms, unsigned int vls);
+
+/* some OSes (FC4) have trouble allocating (kmalloc) 128KB worth of memory,
+ * hence keeping WL_DUMP_BUF_LEN below that
+ */
+#if defined(BWL_SMALL_WLU_DUMP_BUF)
+#define WL_DUMP_BUF_LEN (4 * 1024)
+#else
+#define WL_DUMP_BUF_LEN (127 * 1024)
+#endif 
+
+#define CMDLINESZ		80
+
+#define OUI_STR_SIZE	8	/* OUI string size */
+#define MAX_OUI_SIZE	3	/* MAX  OUI size */
+#define MAX_BYTE_CHARS	2	/* MAX num chars */
+#define MAX_DATA_COLS	16	/* MAX data cols */
+#define DIV_QUO(num, div) ((num)/div)  /* Return the quotient of division to avoid floats */
+#define DIV_REM(num, div) (((num%div) * 100)/div) /* Return the remainder of division */
+
+#define RADIO_CORE_SYN                           (0x0 << 12)
+#define RADIO_CORE_TX0                           (0x2 << 12)
+#define RADIO_CORE_TX1                           (0x3 << 12)
+#define RADIO_CORE_RX0                           (0x6 << 12)
+#define RADIO_CORE_RX1                           (0x7 << 12)
+
+#define RADIO_CORE_CR0                           (0x0 << 10)
+#define RADIO_CORE_CR1                           (0x1 << 10)
+#define RADIO_CORE_CR2                           (0x2 << 10)
+#define RADIO_CORE_ALL                           (0x3 << 10)
+
+#define RADIO_2069_CORE_CR0                      (0x0 << 9)
+#define RADIO_2069_CORE_CR1                      (0x1 << 9)
+#define RADIO_2069_CORE_CR2                      (0x2 << 9)
+#define RADIO_2069_CORE_ALL                      (0x3 << 9)
+#define RADIO_2069_CORE_PLL                      (0x4 << 9)
+
+/* IOCtl version read from targeted driver */
+static int ioctl_version;
+
+/* dword align allocation */
+static union {
+	char bufdata[WLC_IOCTL_MAXLEN];
+	uint32 alignme;
+} bufstruct_wlu;
+static char *buf = (char*) &bufstruct_wlu.bufdata;
+
+/* integer output format, default to signed integer */
+static uint8 int_fmt;
+
+
+/*
+ * Country names and abbreviations from ISO 3166
+ */
+typedef struct {
+	const char *name;	/* Long name */
+	const char *abbrev;	/* Abbreviation */
+} cntry_name_t;
+cntry_name_t cntry_names[];	/* At end of this file */
+
+typedef struct {
+	uint value;
+	const char *string;
+} dbg_msg_t;
+
+typedef struct {
+	uint value;
+	const char *string;
+} phy_msg_t;
+
+typedef struct {
+	uint value;
+	const char *string;
+} monitor_promisc_level_msg_t;
+
+#define WL_SCAN_PARAMS_SSID_MAX 10
+#define SCAN_USAGE	"" \
+"\tDefault to an active scan across all channels for any SSID.\n" \
+"\tOptional arg: SSIDs, list of [up to 10] SSIDs to scan (comma or space separated).\n" \
+"\tOptions:\n" \
+"\t-s S, --ssid=S\t\tSSIDs to scan\n" \
+"\t-t ST, --scan_type=ST\t[active|passive|prohibit|offchan|hotspot] scan type\n" \
+"\t--bss_type=BT\t\t[bss/infra|ibss/adhoc] bss type to scan\n" \
+"\t-b MAC, --bssid=MAC\tparticular BSSID MAC address to scan, xx:xx:xx:xx:xx:xx\n" \
+"\t-n N, --nprobes=N\tnumber of probes per scanned channel\n" \
+"\t-a N, --active=N\tdwell time per channel for active scanning\n" \
+"\t-p N, --passive=N\tdwell time per channel for passive scanning\n" \
+"\t-h N, --home=N\t\tdwell time for the home channel between channel scans\n" \
+"\t-c L, --channels=L\tcomma or space separated list of channels to scan" \
+
+#define RATE_2G_USAGE							\
+"\tEither \"auto\", or a simple CCK/DSSS/OFDM rate value:\n"		\
+"\t1 2 5.5 11 6 9 12 18 24 36 48 54\n\n"				\
+"\tOr options to specify legacy, HT, or VHT rate:\n"			\
+"\t-r R, --rate=R        : legacy rate (CCK, DSSS, OFDM)\n"		\
+"\t-h M, --ht=M          : HT MCS index [0-23]\n"			\
+"\t-v M[xS], --vht=M[xS] : VHT MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. 5x2 is MCS=5, Nss=2\n" \
+"\t-c cM[sS]             : VHT (c notation) MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. c5s2 is MCS=5, Nss=2\n" \
+"\t-s S, --ss=S          : VHT Nss [1-8], number of spatial streams, default 1.\n" \
+"\t                      : Only used with -v/--vht when MxS format is not used\n" \
+"\t-x T, --exp=T         : Tx Expansion, number of tx chains (NTx) beyond the minimum\n" \
+"\t                      : required for the space-time-streams, exp = NTx - Nsts\n" \
+"\t--stbc                : Use STBC expansion, otherwise no STBC\n"	\
+"\t-l, --ldpc            : Use LDPC encoding, otherwise no LDPC\n"	\
+"\t-g, --sgi             : SGI, Short Guard Interval, otherwise standard GI\n" \
+"\t-b, --bandwidth       : transmit bandwidth MHz; 20, 40, 80"
+
+#define RATE_5G_USAGE							\
+"\tEither \"auto\", or a simple OFDM rate value:\n"			\
+"\t6 9 12 18 24 36 48 54\n\n"						\
+"\tOr options to specify legacy OFDM, HT, or VHT rate:\n"		\
+"\t-r R, --rate=R        : legacy OFDM rate\n"				\
+"\t-h M, --ht=M          : HT MCS index [0-23]\n"			\
+"\t-v M[xS], --vht=M[xS] : VHT MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. 5x2 is MCS=5, Nss=2\n" \
+"\t-c cM[sS]             : VHT (c notation) MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. c5s2 is MCS=5, Nss=2\n" \
+"\t-s S, --ss=S          : VHT Nss [1-8], number of spatial streams, default 1.\n" \
+"\t                      : Only used with -v/--vht when MxS format is not used\n" \
+"\t-x T, --exp=T         : Tx Expansion, number of tx chains (NTx) beyond the minimum\n" \
+"\t                      : required for the space-time-streams, exp = NTx - Nsts\n" \
+"\t--stbc                : Use STBC expansion, otherwise no STBC\n"	\
+"\t-l, --ldpc            : Use LDPC encoding, otherwise no LDPC\n"	\
+"\t-g, --sgi             : SGI, Short Guard Interval, otherwise standard GI\n" \
+"\t-b, --bandwidth       : transmit bandwidth MHz; 20, 40, 80"
+
+#define MONITOR_PROMISC_LEVEL_USAGE	\
+"\tUsage: wl monitor_promisc_level [<bitmap> | <+|-name>]\n" \
+"\tbitmap values and corresponding name are the following:\n" \
+"\tArgs:\n" \
+"\t\tbit:0:promisc: " \
+"When set, address filter accepts all received frames." \
+"When cleared, the address filter accepts only those frames " \
+"that match the BSSID or local MAC address\n" \
+"\t\tbit:1:ctrl: " \
+"When set, the RX filter accepts all received control frames " \
+"that are accepted by the address filter. " \
+"When cleared, the RX filter rejects all control frames other " \
+"than PS poll frames." \
+"\t\tbit:3:fcs: " \
+"When set, the RX filter forwards received frames with FCS " \
+"errors to the driver." \
+"When cleared, frames with FCS errors are discarded.\n\n" \
+"\tExample: wl monitor_promisc_level +promisc\n" \
+"\tExample: wl monitor_promisc_level 0x2\n" \
+"\tExample: wl monitor_promisc_level 0"
+
+#define WDS_TYPE_USAGE	\
+"\tUsage: wl wds_type -i <ifname>\n" \
+"\tifname is the name of the interface to query the type.\n" \
+"\tReturn values:\n" \
+"\t\t0:The interface type is neither WDS nor DWDS.\n" \
+"\t\t1:The interface is WDS type.\n" \
+"\t\t2:The interface is DWDS type.\n"
+
+/* the default behavior is batching in driver,
+ * to indicate client batching, users should specify --interactive and --clientbatch
+ */
+static bool batch_in_client;
+
+/* If the new command needs to be part of 'wc.exe' tool used for WMM,
+ * be sure to modify wc_cmds[] array as well
+ *
+ * If you add a command, please update wlu_cmd.c cmd2cat to categorize the command.
+ */
+cmd_t wl_cmds[] = {
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "ver", wl_version, -1, -1,
+	"get version information" },
+	{ "cmds", wl_list, -1, -1,
+	"generate a short list of available commands"},
+#endif
+	{ "up",	wl_void, -1, WLC_UP,
+	"reinitialize and mark adapter up (operational)" },
+	{ "down", wl_void, -1, WLC_DOWN,
+	"reset and mark adapter down (disabled)" },
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "out", wl_out, -1, WLC_OUT,
+	"mark adapter down but do not reset hardware(disabled)\n"
+	"\tOn dualband cards, cards must be bandlocked before use."},
+	{ "clk", wl_int, WLC_GET_CLK, WLC_SET_CLK,
+	"set board clock state. return error for set_clk attempt if the driver is not down\n"
+	"\t0: clock off\n"
+	"\t1: clock on" },
+	{ "restart", wl_void, -1, WLC_RESTART,
+	"Restart driver.  Driver must already be down."},
+	{ "reboot", wl_void, -1, WLC_REBOOT,
+	"Reboot platform"},
+	{ "radio", wl_radio, WLC_GET_RADIO, WLC_SET_RADIO,
+	"Set the radio on or off.\n"
+	"\t\"on\" or \"off\"" },
+	{ "dump", wlu_dump, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_stats", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_eventlog", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_cons", wlu_offloads_stats, WLC_GET_VAR, WLC_SET_VAR,
+	"Display the ARM console or issue a command to the ARM console\n"
+	"  Usage: ol_cons [<cmd>]\n"
+	"\t\"?\" - Display the list of active console commands"
+	},
+	{ "ol_wowl_cons", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_clr", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "srclear", wlu_srwrite, -1, WLC_SET_SROM,
+	"Clears first 'len' bytes of the srom, len in decimal or hex\n"
+	"\tUsage: srclear <len>" },
+	{ "srdump", wlu_srdump, WLC_GET_SROM, -1,
+	"print contents of SPROM to stdout" },
+	{ "srwrite", wlu_srwrite, -1, WLC_SET_SROM,
+	"Write the srom: srwrite byteoffset value" },
+	{ "srcrc", wlu_srwrite, WLC_GET_SROM, -1,
+	"Get the CRC for input binary file" },
+	{ "ciswrite", wlu_ciswrite, -1, WLC_SET_VAR,
+	"Write specified <file> to the SDIO CIS source (either SROM or OTP)"},
+	{ "cisupdate", wlu_cisupdate, -1, WLC_SET_VAR,
+	"Write a hex byte stream to specified byte offset to the CIS source (either SROM or OTP)\n"
+	"--preview option allows you to review the update without committing it\n"
+	"\t<byte offset> <hex byte stream> [--preview]" },
+	{ "cisdump", wlu_cisdump, WLC_GET_VAR, -1,
+	"Display the content of the SDIO CIS source\n"
+	"\t-b <file> -- also write raw bytes to <file>\n"
+	"\t<len> -- optional count of bytes to display (must be even)"},
+	{ "cis_source", wl_varint, WLC_GET_VAR, -1,
+	"Display which source is used for the SDIO CIS"},
+	{ "cisconvert", wlu_srvar, -1, -1,
+	"Print CIS tuple for given name=value pair" },
+	{ "rdvar", wlu_srvar, WLC_GET_SROM, -1,
+	"Read a named variable to the srom" },
+	{ "wrvar", wlu_srvar, WLC_GET_SROM, WLC_SET_SROM,
+	"Write a named variable to the srom" },
+	{ "nvram_source", wl_nvsource, WLC_GET_VAR, -1,
+	"Display which source is used for nvram"},
+	{ "nvram_dump", wl_nvdump, WLC_NVRAM_DUMP, -1,
+	"print nvram variables to stdout" },
+	{ "nvset", wl_nvset, -1, WLC_NVRAM_SET,
+	"set an nvram variable\n"
+	"\tname=value (no spaces around \'=\')" },
+	{ "nvget", wl_nvget, WLC_NVRAM_GET, -1,
+	"get the value of an nvram variable" },
+	{ "nvram_get", wl_nvget, WLC_NVRAM_GET, -1,
+	"get the value of an nvram variable" },
+	{ "revinfo", wl_revinfo, WLC_GET_REVINFO, -1,
+	"get hardware revision information" },
+	{ "customvar1", wl_var_getinthex, -1, -1,
+	"print the value of customvar1 in hex format" },
+	{ "msglevel", wl_msglevel, WLC_GET_VAR, WLC_SET_VAR,
+	"set driver console debugging message bitvector\n"
+	"\ttype \'wl msglevel ?\' for values" },
+	{ "phymsglevel", wl_phymsglevel, WLC_GET_VAR, WLC_SET_VAR,
+	"set phy debugging message bitvector\n"
+	"\ttype \'wl phymsglevel ?\' for values" },
+	{ "PM", wl_int, WLC_GET_PM, WLC_SET_PM,
+	"set driver power management mode:\n"
+	"\t0: CAM (constantly awake)\n"
+	"\t1: PS  (power-save)\n"
+	"\t2: FAST PS mode" },
+	{ "wake", wl_int, WLC_GET_WAKE, WLC_SET_WAKE,
+	"set driver power-save mode sleep state:\n"
+	"\t0: core-managed\n"
+	"\t1: awake" },
+	{ "promisc", wl_int, WLC_GET_PROMISC, WLC_SET_PROMISC,
+	"set promiscuous mode ethernet address reception\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "monitor", wl_int, WLC_GET_MONITOR, WLC_SET_MONITOR,
+	"set monitor mode\n"
+	"\t0 - disable\n"
+	"\t1 - enable active monitor mode (interface still operates)" },
+	{ "frag", wl_print_deprecate, -1, -1, "Deprecated. Use fragthresh." },
+	{ "rts", wl_print_deprecate, -1, -1, "Deprecated. Use rtsthresh." },
+	{ "cwmin", wl_int, WLC_GET_CWMIN, WLC_SET_CWMIN,
+	"Set the cwmin.  (integer [1, 255])" },
+	{ "cwmax", wl_int, WLC_GET_CWMAX, WLC_SET_CWMAX,
+	"Set the cwmax.  (integer [256, 2047])" },
+	{ "srl", wl_int, WLC_GET_SRL, WLC_SET_SRL,
+	"Set the short retry limit.  (integer [1, 255])" },
+	{ "lrl", wl_int, WLC_GET_LRL, WLC_SET_LRL,
+	"Set the long retry limit.  (integer [1, 255])" },
+	{ "rate", wl_rate_mrate, WLC_GET_RATE, -1,
+	"force a fixed rate:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "mrate", wl_rate_mrate, -1, -1, /* Deprecated. Use "bg_mrate" or "a_mrate" */
+	"force a fixed multicast rate:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "a_rate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed rate for the A PHY:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "a_mrate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed multicast rate for the A PHY:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "bg_rate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed rate for the B/G PHY:\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "bg_mrate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed multicast rate for the B/G PHY:\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "2g_rate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for data frames in the 2.4G band:\n\n"
+	RATE_2G_USAGE
+	},
+	{ "2g_mrate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for mulitcast/broadcast data frames in the 2.4G band:\n\n"
+	RATE_2G_USAGE
+	},
+	{ "5g_rate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for data frames in the 5G band:\n\n"
+	RATE_5G_USAGE
+	},
+	{ "5g_mrate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for mulitcast/broadcast data frames in the 5G band:\n\n"
+	RATE_5G_USAGE
+	},
+	{ "infra", wl_int, WLC_GET_INFRA, WLC_SET_INFRA,
+	"Set Infrastructure mode: 0 (IBSS) or 1 (Infra BSS)" },
+	{ "ap", wl_int, WLC_GET_AP, WLC_SET_AP,
+	"Set AP mode: 0 (STA) or 1 (AP)" },
+	{ "bssid", wl_bssid, WLC_GET_BSSID, -1,
+	"Get the BSSID value, error if STA and not associated"},
+	{ "bssmax", wl_bss_max, WLC_GET_VAR, -1,
+	"get number of BSSes " },
+	{ "bw_cap", wl_bw_cap, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/set the per-band bandwidth.\n"
+	"Usage: wl bw_cap <2g|5g> [<cap>]\n"
+	"\t2g|5g - Band: 2.4GHz or 5GHz respectively\n"
+	"cap:\n"
+	"\t0x1 - 20MHz\n"
+	"\t0x3 - 20/40MHz\n"
+	"\t0x7 - 20/40/80MHz\n"
+	"\t0xff - Unrestricted" },
+#endif
+	{ "channel", wl_channel, WLC_GET_CHANNEL, WLC_SET_CHANNEL,
+	"Set the channel:\n"
+	"\tvalid channels for 802.11b/g (2.4GHz band) are 1 through 14\n"
+	"\tvalid channels for 802.11a  (5 GHz band) are:\n"
+	"\t\t36, 40, 44, 48, 52, 56, 60, 64,\n"
+	"\t\t100, 104, 108, 112, 116,120, 124, 128, 132, 136, 140,\n"
+	"\t\t149, 153, 157, 161,\n"
+	"\t\t184, 188, 192, 196, 200, 204, 208, 212, 216"},
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "cur_mcsset", wl_cur_mcsset, WLC_GET_VAR, -1,
+	"Get the current mcs set"
+	},
+	{ "clmver", wl_var_getandprintstr, WLC_GET_VAR, -1,
+	"Get version information for CLM data and tools"},
+	{ "roam_channels_in_cache", wl_dump_chanspecs, WLC_GET_VAR, -1,
+	"Get a list of channels in roam cache" },
+	{ "roam_channels_in_hotlist", wl_dump_chanspecs, WLC_GET_VAR, -1,
+	"Get a list of channels in roam hot channel list" },
+	{ "chanspecs", wl_dump_chanspecs, WLC_GET_VAR, -1,
+	"Get all the valid chanspecs (default: all within current locale):\n"
+	"\t-b band (5(a) or 2(b/g))\n"
+	"\t-w bandwidth, 20, 40 or 80\n"
+	"\t[-c country_abbrev]"
+	},
+	{ "chanspecs_defset", wl_dump_chanspecs_defset, WLC_GET_VAR, -1,
+	"Get default chanspecs for current driver settings (default: all within current locale)"
+	},
+	{ "chanspec", wl_chanspec, WLC_GET_VAR, WLC_SET_VAR,
+	"Set current or configured channel:\n"
+	"\t20MHz : [2g|5g]<channel>[/20]\n"
+	"\t40MHz : [2g|5g]<channel>/40[u,l]\n"
+	"\t80MHz :    [5g]<channel>/80\n"
+	"\toptional band 2g or 5g, default to 2g if channel <= 14\n"
+	"\tchannel number (0-200)\n"
+	"\tbandwidth, 20, 40, or 80, default 20\n"
+	"\tprimary sideband for 40MHz on 2g, l=lower, u=upper\n"
+	"OR Set channel with legacy format:\n"
+	"\t-c channel number (0-224)\n"
+	"\t-b band (5(a) or 2(b/g))\n"
+	"\t-w bandwidth 20 or 40\n"
+	"\t-s ctl sideband, -1=lower, 0=none, 1=upper"},
+	{ "rclass", wl_rclass, WLC_GET_VAR, -1,
+	"Get operation class:\n"
+	"\t chanspec \n"},
+	{ "dfs_channel_forced", wl_chanspec, WLC_GET_VAR, WLC_SET_VAR,
+	"Set <channel>[a,b][n][u,l]\n"
+	"\tchannel number (0-224)\n"
+	"\tband a=5G, b=2G, default to 2G if channel <= 14\n"
+	"\tbandwidth, n=10, non for 20 & 40\n"
+	"\tctl sideband, l=lower, u=upper"},
+	{ "tssi", wl_tssi, WLC_GET_TSSI, -1,
+	"Get the tssi value from radio" },
+	{ "txpwr", wl_txpwr, -1, -1, /* Deprecated. Use "txpwr1" */
+	"Set tx power in milliwatts.  Range [1, 84]." },
+	{ "txpwr1", wl_txpwr1, WLC_GET_VAR, WLC_SET_VAR,
+	"Set tx power in in various units. Choose one of (default: dbm): \n"
+	"\t-d dbm units\n"
+	"\t-q quarter dbm units\n"
+	"\t-m milliwatt units\n"
+	"Can be combined with:\n"
+	"\t-o turn on override to disable regulatory and other limitations\n"
+	"Use wl txpwr -1 to restore defaults"},
+	{ "txpathpwr", wl_int, WLC_GET_TX_PATH_PWR, WLC_SET_TX_PATH_PWR,
+	"Turn the tx path power on or off on 2050 radios" },
+	{ "txpwrlimit", wl_get_txpwr_limit, WLC_CURRENT_PWR, -1,
+	"Return current tx power limit" },
+	{ "powerindex", wl_int, WLC_GET_PWRIDX, WLC_SET_PWRIDX,
+	"Set the transmit power for A band(0-63).\n"
+	"\t-1 - default value" },
+	{ "atten", wl_atten, WLC_GET_ATTEN, WLC_SET_ATTEN,
+	"Set the transmit attenuation for B band. Args: bb radio txctl1.\n"
+	"\tauto to revert to automatic control\n"
+	"\tmanual to supspend automatic control" },
+	{ "phyreg", wl_reg, WLC_GET_PHYREG, WLC_SET_PHYREG,
+	"Get/Set a phy register:\n"
+	"\toffset [ value ] [ band ]" },
+	{ "radioreg", wl_reg, WLC_GET_RADIOREG, WLC_SET_RADIOREG,
+	"Get/Set a radio register:\n"
+	"\toffset [ value ] [ band/core ]\n"
+	"HTPHY:\n"
+	"\tGet a radio register: wl radioreg [ offset ] [ cr0/cr1/cr2 ]\n"
+	"\tSet a radio register: wl radioreg [ offset ] [ value ] [ cr0/cr1/cr2/all ]\n"
+	"ACPHY:\n"
+	"\tGet a radio register: wl radioreg [ offset ] [ cr0/cr1/cr2/pll ]\n"
+	"\tSet a radio register: wl radioreg [ offset ] [ value ] [ cr0/cr1/cr2/pll/all ]"},
+	{ "ucflags", wl_reg, WLC_GET_UCFLAGS, WLC_SET_UCFLAGS,
+	"Get/Set ucode flags 1, 2, 3(16 bits each)\n"
+	"\toffset [ value ] [ band ]" },
+	{ "shmem", wl_reg, WLC_GET_SHMEM, WLC_SET_SHMEM,
+	"Get/Set a shared memory location:\n"
+	"\toffset [ value ] [band ]" },
+	{ "macreg", wl_macreg, WLC_R_REG, WLC_W_REG,
+	"Get/Set any mac registers(include IHR and SB):\n"
+	"\tmacreg offset size[2,4] [ value ] [ band ]" },
+	{ "ucantdiv", wl_int, WLC_GET_UCANTDIV, WLC_SET_UCANTDIV,
+	"Enable/disable ucode antenna diversity (1/0 or on/off)" },
+	{ "gpioout", wl_gpioout, -1, -1,
+	"Set any GPIO pins to any value. Use with caution as GPIOs would be "
+	"assigned to chipcommon\n"
+	"\tUsage: gpiomask gpioval"},
+
+	{ "devpath", wl_devpath, WLC_GET_VAR, -1,
+	"print device path" },
+
+	{ "pcieserdesreg", wlu_reg3args, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set SERDES registers: dev offset [val]"},
+	{ "ampdu_activate_test", wl_ampdu_activate_test, -1, WLC_SET_VAR,
+	"actiate" },
+	/* nphy parameter setting is internal only for now */
+	{ "ampdu_tid", wl_ampdu_tid, WLC_GET_VAR, WLC_SET_VAR,
+	"enable/disable per-tid ampdu; usage: wl ampdu_tid <tid> [0/1]" },
+	{ "ampdu_retry_limit_tid", wl_ampdu_retry_limit_tid, WLC_GET_VAR, WLC_SET_VAR,
+	"Set per-tid ampdu retry limit; usage: wl ampdu_retry_limit_tid <tid> [0~31]" },
+	{ "ampdu_rr_retry_limit_tid", wl_ampdu_rr_retry_limit_tid, WLC_GET_VAR, WLC_SET_VAR,
+	"Set per-tid ampdu regular rate retry limit; usage: "
+	"wl ampdu_rr_retry_limit_tid <tid> [0~31]" },
+	{ "ampdu_send_addba", wl_ampdu_send_addba, WLC_GET_VAR, WLC_SET_VAR,
+	"send addba to specified ea-tid; usage: wl ampdu_send_addba <tid> <ea>" },
+	{ "ampdu_send_delba", wl_ampdu_send_delba, WLC_GET_VAR, WLC_SET_VAR,
+	"send delba to specified ea-tid; usage: wl ampdu_send_delba <tid> <ea>" },
+	{ "ampdu_clear_dump", wl_var_void, -1, WLC_SET_VAR,
+	"clear ampdu counters"},
+	{ "ampdu_txq_prof_start", wl_var_void, -1, WLC_SET_VAR,
+	"start sample txq profiling data"},
+	{ "ampdu_txq_prof_dump", wl_var_void, -1, WLC_SET_VAR,
+	"show txq histogram"},
+	{ "ampdu_txq_ss", wl_var_void, -1, WLC_SET_VAR,
+	"take txq snapshot"},
+	{ "dpt_deny", wl_dpt_deny, WLC_GET_VAR, WLC_SET_VAR,
+	"adds/removes ea to dpt deny list\n"
+	"\tusage: wl dpt_deny <add,remove> <ea>" },
+	{ "dpt_endpoint", wl_dpt_endpoint, WLC_GET_VAR, WLC_SET_VAR,
+	"creates/updates/deletes dpt endpoint for ea\n"
+	"\tusage: wl dpt_endpoint <create, update, delete> <ea>" },
+	{ "dpt_pmk", wl_dpt_pmk, -1, WLC_SET_VAR,
+	"sets DPT pre-shared key" },
+	{ "dpt_fname", wl_dpt_fname, WLC_GET_VAR, WLC_SET_VAR,
+	"sets/gets DPT friendly name" },
+	{ "dpt_list", wl_dpt_list, WLC_GET_VAR, -1,
+	"gets status of all dpt peers" },
+#ifdef WLBTAMP
+	{ "HCI_cmd", wl_HCI_cmd, WLC_GET_VAR, WLC_SET_VAR,
+	"carries HCI commands to the driver\n"
+	"\tusage: wl HCI_cmd <command> <args>" },
+	{ "HCI_ACL_data", wl_HCI_ACL_data, WLC_GET_VAR, WLC_SET_VAR,
+	"carries HCI ACL data packet to the driver\n"
+	"\tusage: wl HCI_ACL_data <logical link handle> <data>" },
+	{ "btamp_statelog", wl_get_btamp_log, WLC_GET_VAR, WLC_SET_VAR,
+	"Return state transistion log of BTAMP" },
+#endif /* WLBTAMP */
+	{ "actframe", wl_actframe, -1, WLC_SET_VAR,
+	"Send a Vendor specific Action frame to a channel\n"
+	"\tusage: wl actframe <Dest Mac Addr> <data> channel dwell-time <BSSID>" },
+	{ "antdiv", wl_int, WLC_GET_ANTDIV, WLC_SET_ANTDIV,
+	"Set antenna diversity for rx\n"
+	"\t0 - force use of antenna 0\n"
+	"\t1 - force use of antenna 1\n"
+	"\t3 - automatic selection of antenna diversity" },
+	{ "txant", wl_int, WLC_GET_TXANT, WLC_SET_TXANT,
+	"Set the transmit antenna\n"
+	"\t0 - force use of antenna 0\n"
+	"\t1 - force use of antenna 1\n"
+	"\t3 - use the RX antenna selection that was in force during\n"
+	"\t    the most recently received good PLCP header" },
+	{ "plcphdr", wl_plcphdr, WLC_GET_PLCPHDR, WLC_SET_PLCPHDR,
+	"Set the plcp header.\n"
+	"\t\"long\" or \"auto\" or \"debug\"" },
+	{ "phytype", wl_int, WLC_GET_PHYTYPE, -1,
+	"Get phy type" },
+	{ "rateparam", wl_rateparam, -1, WLC_SET_RATE_PARAMS,
+	"set driver rate selection tunables\n"
+	"\targ 1: tunable id\n"
+	"\targ 2: tunable value" },
+	{ "wepstatus", wl_wepstatus, -1, -1, /* Deprecated. Use "wsec" */
+	"Set or Get WEP status\n"
+	"\twepstatus [on|off]" },
+	{ "primary_key", wl_primary_key, WLC_GET_KEY_PRIMARY, WLC_SET_KEY_PRIMARY,
+	"Set or get index of primary key" },
+	{ "addwep", wl_addwep, -1, WLC_SET_KEY,
+	"Set an encryption key.  The key must be 5, 13 or 16 bytes long, or\n"
+	"\t10, 26, 32, or 64 hex digits long.  The encryption algorithm is\n"
+	"\tautomatically selected based on the key size. keytype is accepted\n"
+	"\tonly when key length is 16 bytes/32 hex digits and specifies\n"
+	"\twhether AES-OCB or AES-CCM encryption is used. Default is ccm.\n"
+	"\tWAPI is selected if key len is 32 and arguments contain wapi.\n"
+	"\taddwep <keyindex> <keydata> [ocb | ccm | wapi] [notx] [xx:xx:xx:xx:xx:xx]" },
+	{ "rmwep", wl_rmwep, -1, WLC_SET_KEY,
+	"Remove the encryption key at the specified key index." },
+	{ "keys", wl_keys, WLC_GET_KEY, -1,
+	"Prints a list of the current WEP keys" },
+	{ "tsc", wl_tsc, WLC_GET_KEY_SEQ, -1,
+	"Print Tx Sequence Couter for key at specified key index." },
+	{ "wsec_test", wl_wsec_test, -1, WLC_SET_WSEC_TEST,
+	"Generate wsec errors\n"
+	"\twsec_test <test_type> <keyindex|xx:xx:xx:xx:xx:xx>\n"
+	"\ttype \'wl wsec_test ?\' for test_types" },
+	{ "tkip_countermeasures", wl_int, -1, WLC_TKIP_COUNTERMEASURES,
+	"Enable or disable TKIP countermeasures (TKIP-enabled AP only)\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "wsec_restrict", wl_bsscfg_int, WLC_GET_WEP_RESTRICT, WLC_SET_WEP_RESTRICT,
+	"Drop unencrypted packets if WSEC is enabled\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "eap", wl_int, WLC_GET_EAP_RESTRICT, WLC_SET_EAP_RESTRICT,
+	"restrict traffic to 802.1X packets until 802.1X authorization succeeds\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "cur_etheraddr", wl_iov_mac, -1, -1,
+	"Get/set the current hw address" },
+	{ "perm_etheraddr", wl_iov_mac, -1, -1,
+	"Get the permanent address from NVRAM" },
+	{ "authorize", wl_mac, -1, WLC_SCB_AUTHORIZE,
+	"restrict traffic to 802.1X packets until 802.1X authorization succeeds" },
+	{ "deauthorize", wl_mac, -1, WLC_SCB_DEAUTHORIZE,
+	"do not restrict traffic to 802.1X packets until 802.1X authorization succeeds" },
+#endif
+	{ "deauthenticate", wl_deauth_rc, -1, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
+	"deauthenticate a STA from the AP with optional reason code (AP ONLY)" },
+	{ "wsec", wl_wsec, WLC_GET_WSEC, WLC_SET_WSEC,
+	"wireless security bit vector\n"
+	"\t1 - WEP enabled\n"
+	"\t2 - TKIP enabled\n"
+	"\t4 - AES enabled\n"
+	"\t8 - WSEC in software\n"
+	"\t0x80 - FIPS enabled\n"
+	"\t0x100 - WAPI enabled\n"
+	"\t0x200 - MFP capable\n"
+	"\t0x400 - MFP required\n"
+	"\t0x800 - MFP use KDF  (SHA256)"
+	},
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "auth", wl_bsscfg_int, WLC_GET_AUTH, WLC_SET_AUTH,
+	"set/get 802.11 authentication type. 0 = OpenSystem, 1= SharedKey, 3=Open/Shared" },
+#endif
+	{ "wpa_auth", wl_wpa_auth, WLC_GET_WPA_AUTH, WLC_SET_WPA_AUTH,
+	"Bitvector of WPA authorization modes:\n"
+	"\t1	WPA-NONE\n"
+	"\t2	WPA-802.1X/WPA-Professional\n"
+	"\t4	WPA-PSK/WPA-Personal\n"
+#ifdef BCMCCX
+	"\t8	CCKM (WPA)\n"
+#endif	/* BCMCCX */
+#if defined(BCMCCX)
+	"\t16	CCKM (WPA2)\n"
+#endif	/* BCMCCX */
+	"\t64	WPA2-802.1X/WPA2-Professional\n"
+	"\t128	WPA2-PSK/WPA2-Personal\n"
+	"\t0	disable WPA"
+	},
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "wpa_cap", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get 802.11i RSN capabilities" },
+	{ "set_pmk", wl_set_pmk, -1, WLC_SET_WSEC_PMK,
+	"Set passphrase for PMK in driver-resident supplicant." },
+	{ "scan", wl_scan, -1, WLC_SCAN,
+	"Initiate a scan.\n" SCAN_USAGE
+	},
+	{ "roamscan_parms", wl_roamparms, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get roam scan parameters\n"
+	"Use standard scan params syntax below,"
+	"but only active/passive/home times, nprobes, and type are used.\n"
+	"All other values are silently discarded.\n"
+	SCAN_USAGE
+	},
+	{ "iscan_s", wl_iscan, -1, WLC_SET_VAR,
+	"Initiate an incremental scan.\n" SCAN_USAGE
+	},
+	{ "iscan_c", wl_iscan, -1, WLC_SET_VAR,
+	"Continue an incremental scan.\n" SCAN_USAGE
+	},
+	{ "scancache_clear", wl_var_void, -1, WLC_SET_VAR,
+	"clear the scan cache"},
+	{ "escan", wl_escan, -1, WLC_SET_VAR,
+	"Start an escan.\n" SCAN_USAGE
+	},
+	{ "escanabort", wl_escan, -1, WLC_SET_VAR,
+	"Abort an escan.\n" SCAN_USAGE
+	},
+#ifdef EXTENDED_SCAN
+	{ "extdscan", wl_extdscan, -1, WLC_SET_VAR,
+	"Initiate an extended scan.\n"
+	"\tDefault to an active scan across all channels for any SSID.\n"
+	"\tOptional args: list of SSIDs to scan.\n"
+	"\tOptions:\n"
+	"\t-s S1 S2 S3, --ssid=S1 S2 S3\t\tSSIDs to scan, comma or space separated\n"
+	"\t-x x, --split_scan=ST\t[split_scan] scan type\n"
+	"\t-t ST, --scan_type=ST\t[background:0/forcedbackground:1/foreground:2] scan type\n"
+	"\t-n N, --nprobes=N\tnumber of probes per scanned channel, per SSID\n"
+	"\t-c L, --channels=L\tcomma or space separated list of channels to scan"},
+#endif
+	{ "passive", wl_int, WLC_GET_PASSIVE_SCAN, WLC_SET_PASSIVE_SCAN,
+	"Puts scan engine into passive mode" },
+	{ "regulatory", wl_int, WLC_GET_REGULATORY, WLC_SET_REGULATORY,
+	"Get/Set regulatory domain mode (802.11d). Driver must be down." },
+	{ "spect", wl_spect, WLC_GET_SPECT_MANAGMENT, WLC_SET_SPECT_MANAGMENT,
+	"Get/Set 802.11h Spectrum Management mode.\n"
+	"\t0 - Off\n"
+	"\t1 - Loose interpretation of 11h spec - may join non-11h APs\n"
+	"\t2 - Strict interpretation of 11h spec - may not join non-11h APs\n"
+	"\t3 - Disable 11h and enable 11d\n"
+	"\t4 - Loose interpretation of 11h+d spec - may join non-11h APs"
+	},
+	{ "scanabort", wl_var_void, -1, WLC_SET_VAR,
+	"Abort a scan." },
+	{ "scanresults", wl_dump_networks, WLC_SCAN_RESULTS, -1,
+	"Return results from last scan." },
+	{ "iscanresults", wl_dump_networks, WLC_GET_VAR, -1,
+	"Return results from last iscan. Specify a buflen (max 8188)\n"
+	"\tto artificially limit the size of the results buffer.\n"
+	"\tiscanresults [buflen]"},
+	{ "assoc",  wl_status, -1, -1,
+	"Print information about current network association.\n"
+	"\t(also known as \"status\")" },
+#endif
+	{ "status", wl_status, -1, -1,
+	"Print information about current network association.\n"
+	"\t(also known as \"assoc\")" },
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "disassoc", wl_void, -1, WLC_DISASSOC,
+	"Disassociate from the current BSS/IBSS." },
+	{ "chanlist", wl_print_deprecate, WLC_GET_VALID_CHANNELS, -1,
+	"Deprecated. Use channels." },
+	{ "channels", wl_dump_chanlist, WLC_GET_VALID_CHANNELS, -1,
+	"Return valid channels for the current settings." },
+	{ "channels_in_country", wl_channels_in_country, WLC_GET_CHANNELS_IN_COUNTRY, -1,
+	"Return valid channels for the country specified.\n"
+	"\tArg 1 is the country abbreviation\n"
+	"\tArg 2 is the band(a or b)"},
+	{ "curpower", wl_get_current_power, WLC_CURRENT_PWR, -1,
+	"Return current tx power settings.\n"
+	"\t-v, --verbose: display the power settings for every "
+	"rate even when every rate in a rate group has the same power." },
+	{ "txpwr_target_max", wl_get_txpwr_target_max, WLC_GET_VAR, -1,
+	"Return current max tx target power settings.\n" },
+	{ "curppr", wl_get_current_txppr, WLC_GET_VAR, -1,
+	"Return current tx power per rate offset."},
+	{ "txinstpwr", wl_get_instant_power, WLC_GET_VAR, -1,
+	"Return tx power based on instant TSSI "},
+	{ "scansuppress", wl_int, WLC_GET_SCANSUPPRESS, WLC_SET_SCANSUPPRESS,
+	"Suppress all scans for testing.\n"
+	"\t0 - allow scans\n"
+	"\t1 - suppress scans" },
+	{ "evm", wl_evm, -1, WLC_EVM,
+	"Start an EVM test on the given channel, or stop EVM test.\n"
+	"\tArg 1 is channel number 1-14, or \"off\" or 0 to stop the test.\n"
+	"\tArg 2 is optional rate (1, 2, 5.5 or 11)"},
+	{ "rateset", wl_rateset, WLC_GET_RATESET, WLC_SET_RATESET,
+	"Returns or sets the supported and basic rateset, (b) indicates basic\n"
+	"\tWith no args, returns the rateset. Args are\n"
+	"\trateset \"default\" | \"all\" | <arbitrary rateset> [-m|-v <list of mcs masks>]\n"
+	"\t\tdefault - driver defaults\n"
+	"\t\tall - all rates are basic rates\n"
+	"\t\tarbitrary rateset - list of rates\n"
+	"\tList of rates are in Mbps and each rate is optionally followed\n"
+	"\tby \"(b)\" or \"b\" for a Basic rate. Example: 1(b) 2b 5.5 11\n"
+	"\tAt least one rate must be Basic for a legal rateset.\n\n"
+	"\t-m  sets HT rates (bitmasks, 00-ff). Least significant bit is MCS0.\n"
+	"\t    example: 'rateset -m 0x3f 0x01' limits rates to MCS0-MCS5 and MCS8\n\n"
+	"\t-v  sets VHT MCS values for each supported count of spatial streams.\n"
+	"\t    example: 'rateset -v 3ff 1ff ff' limits vht rates to MCS 0-9 for 1 stream,\n"
+	"\t                             MCS 0-8 for 2 streams, and MCS 0-7 for 3 streams."
+	},
+	{ "default_rateset", wl_default_rateset, WLC_GET_VAR, -1,
+	"Returns supported rateset of given phy.\n"
+	"\tYou have to insert following Args\n"
+	"\t\tArg 1. Phy Type: have to be one of the following: "
+	"[a, b, g, n, lp, ssn, ht, lcn, lcn40, ac]\n"
+	"\t\tArg 2. Band Type: 2 for 2.4G or 5 for 5G\n"
+	"\t\tArg 3. CCK Only: 1 for CCK Only or 0 for CCK and OFDM rates\n"
+	"\t\tArg 4. Basic Rates: 1 for all rates WITH basic rates or "
+	"0 for all rates WITHOUT basic rates\n"
+	"\t\tArg 5. MCS Rates: 1 for all rates WITH MCS rates or "
+	"0 for all rates WITHOUT MCS rates\n"
+	"\t\tArg 6. Bandwidth: have to be one of the following: [10, 20, 40, 80, 160]\n"
+	"\t\tArg 7. TX/RX Stream: \"tx\" for TX streams or \"rx\" for RX streams\n"
+	"\t\tExample: PHY: AC, Band 2.4G, CCK rates only, With Basec rates, "
+	"WithOut MCS rates, BW: 40 and TX streams\n"
+	"\t\tInput: default_rateset ac 2 0 1 0 40 tx\n"
+	},
+	{ "roam_trigger", wl_band_elm, WLC_GET_ROAM_TRIGGER, WLC_SET_ROAM_TRIGGER,
+	"Get or Set the roam trigger RSSI threshold:\n"
+	"\tGet: roam_trigger [a|b]\n"
+	"\tSet: roam_trigger <integer> [a|b|all]\n"
+	"\tinteger -   0: default\n"
+	"\t            1: optimize bandwidth\n"
+	"\t            2: optimize distance\n"
+	"\t    [-1, -99]: dBm trigger value"},
+	{ "roam_delta",	wl_band_elm, WLC_GET_ROAM_DELTA, WLC_SET_ROAM_DELTA,
+	"Set the roam candidate qualification delta. roam_delta [integer [, a/b]]" },
+	{ "roam_scan_period", wl_int, WLC_GET_ROAM_SCAN_PERIOD, WLC_SET_ROAM_SCAN_PERIOD,
+	"Set the roam candidate qualification delta.  (integer)" },
+	{ "suprates", wl_sup_rateset, WLC_GET_SUP_RATESET_OVERRIDE, WLC_SET_SUP_RATESET_OVERRIDE,
+	"Returns or sets the 11g override for the supported rateset\n"
+	"\tWith no args, returns the rateset. Args are a list of rates,\n"
+	"\tor 0 or -1 to specify an empty rateset to clear the override.\n"
+	"\tList of rates are in Mbps, example: 1 2 5.5 11"},
+	{ "scan_channel_time", wl_int, WLC_GET_SCAN_CHANNEL_TIME, WLC_SET_SCAN_CHANNEL_TIME,
+	"Get/Set scan channel time"},
+	{ "scan_unassoc_time", wl_int, WLC_GET_SCAN_UNASSOC_TIME, WLC_SET_SCAN_UNASSOC_TIME,
+	"Get/Set unassociated scan channel dwell time"},
+	{ "scan_home_time", wl_int, WLC_GET_SCAN_HOME_TIME, WLC_SET_SCAN_HOME_TIME,
+	"Get/Set scan home channel dwell time"},
+	{ "scan_passive_time", wl_int, WLC_GET_SCAN_PASSIVE_TIME, WLC_SET_SCAN_PASSIVE_TIME,
+	"Get/Set passive scan channel dwell time"},
+	{ "scan_nprobes", wl_int, WLC_GET_SCAN_NPROBES, WLC_SET_SCAN_NPROBES,
+	"Get/Set scan parameter for number of probes to use per channel scanned"},
+	{ "prb_resp_timeout", wl_int, WLC_GET_PRB_RESP_TIMEOUT, WLC_SET_PRB_RESP_TIMEOUT,
+	"Get/Set probe response timeout"},
+	{ "channel_qa", wl_int, WLC_GET_CHANNEL_QA, -1,
+	"Get last channel quality measurment"},
+	{ "channel_qa_start", wl_void, -1, WLC_START_CHANNEL_QA,
+	"Start a channel quality measurment"},
+	{ "country", wl_country, WLC_GET_COUNTRY, WLC_SET_COUNTRY,
+	"Select Country Code for driver operational region\n"
+	"\tFor simple country setting: wl country <country>\n"
+	"\tWhere <country> is either a long name or country code from ISO 3166; "
+	"for example \"Germany\" or \"DE\"\n"
+	"\n\tFor a specific built-in country definition: "
+	"wl country <built-in> [<advertised-country>]\n"
+	"\tWhere <built-in> is a country country code followed by '/' and "
+	"regulatory revision number.\n"
+	"\tFor example, \"US/3\".\n"
+	"\tAnd where <advertised-country> is either a long name or country code from ISO 3166.\n"
+	"\tIf <advertised-country> is omitted, it will be the same as the built-in country code.\n"
+	"\n\tUse 'wl country list [band(a or b)]' for the list of supported countries"},
+	{ "country_ie_override", wl_country_ie_override, WLC_GET_VAR, WLC_SET_VAR,
+	"To set/get country ie"},
+	{ "autocountry_default", wl_varstr, WLC_GET_VAR, WLC_SET_VAR,
+	"Select Country Code for use with Auto Contry Discovery"},
+	{ "join", wl_join, -1, -1,
+	"Join a specified network SSID.\n"
+	"\tUsage: join <ssid> [key <0-3>:xxxxx] [imode bss|ibss] "
+	"[amode open|shared|openshared|wpa|wpapsk|wpa2|wpa2psk|wpanone|ftpsk] [options]\n"
+	"\tOptions:\n"
+	"\t-b MAC, --bssid=MAC \tBSSID (xx:xx:xx:xx:xx:xx) to scan and join\n"
+	"\t-c CL, --chanspecs=CL \tchanspecs (comma or space separated list)\n"
+	"\tprescanned \tuses channel and bssid list from scanresults\n"
+	"\t-p, -passive: force passive assoc scan (useful for P2P)"},
+#endif
+	{ "ssid", wl_ssid, WLC_GET_SSID, WLC_SET_SSID,
+	"Set or get a configuration's SSID.\n"
+	"\twl ssid [-C num]|[--cfg=num] [<ssid>]\n"
+	"\tIf the configuration index 'num' is not given, configuraion #0 is assumed and\n"
+	"\tsetting will initiate an assoication attempt if in infrastructure mode,\n"
+	"\tor join/creation of an IBSS if in IBSS mode,\n"
+	"\tor creation of a BSS if in AP mode."},
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+#ifdef BCMCCX
+	{ "leap", wl_leap, WLC_GET_LEAP_LIST, WLC_SET_LEAP_LIST,
+	"Set parameters for LEAP authentication\n"
+	"\tleap <ssid> <username> <password> [domain]" },
+#endif /* BCMCCX */
+	{ "mac", wl_maclist, WLC_GET_MACLIST, WLC_SET_MACLIST,
+	"Set or get the list of source MAC address matches.\n"
+	"\twl mac xx:xx:xx:xx:xx:xx [xx:xx:xx:xx:xx:xx ...]\n"
+	"\tTo Clear the list: wl mac none" },
+	{ "macmode", wl_int, WLC_GET_MACMODE, WLC_SET_MACMODE,
+	"Set the mode of the MAC list.\n"
+	"\t0 - Disable MAC address matching.\n"
+	"\t1 - Deny association to stations on the MAC list.\n"
+	"\t2 - Allow association to stations on the MAC list."},
+	{ "wds", wl_maclist, WLC_GET_WDSLIST, WLC_SET_WDSLIST,
+	"Set or get the list of WDS member MAC addresses.\n"
+	"\tSet using a space separated list of MAC addresses.\n"
+	"\twl wds xx:xx:xx:xx:xx:xx [xx:xx:xx:xx:xx:xx ...]" },
+	{ "lazywds", wl_int, WLC_GET_LAZYWDS, WLC_SET_LAZYWDS,
+	"Set or get \"lazy\" WDS mode (dynamically grant WDS membership to anyone)."},
+	{ "noise", wl_int, WLC_GET_PHY_NOISE, -1,
+	"Get noise (moving average) right after tx in dBm" },
+	{ "fqacurcy", wl_int, -1, WLC_FREQ_ACCURACY,
+	"Manufacturing test: set frequency accuracy mode.\n"
+	"\tfreqacuracy syntax is: fqacurcy <channel>\n"
+	"\tArg is channel number 1-14, or 0 to stop the test." },
+	{ "crsuprs", wl_int, -1, WLC_CARRIER_SUPPRESS,
+	"Manufacturing test: set carrier suppression mode.\n"
+	"\tcarriersuprs syntax is: crsuprs <channel>\n"
+	"\tArg is channel number 1-14, or 0 to stop the test." },
+	{ "longtrain", wl_int, -1, WLC_LONGTRAIN,
+	"Manufacturing test: set longtraining mode.\n"
+	"\tlongtrain syntax is: longtrain <channel>\n"
+	"\tArg is A band channel number or 0 to stop the test." },
+	{ "band", wl_band, WLC_GET_BAND, WLC_SET_BAND,
+	"Returns or sets the current band\n"
+	"\tauto - auto switch between available bands (default)\n"
+	"\ta - force use of 802.11a band\n"
+	"\tb - force use of 802.11b band" },
+	{ "bands", wl_bandlist, WLC_GET_BANDLIST, -1,
+	"Return the list of available 802.11 bands" },
+	{ "phylist", wl_phylist, WLC_GET_PHYLIST, -1,
+	"Return the list of available phytypes" },
+	{ "shortslot", wl_int, WLC_GET_SHORTSLOT, -1,
+	"Get current 11g Short Slot Timing mode. (0=long, 1=short)" },
+	{ "shortslot_override", wl_int, WLC_GET_SHORTSLOT_OVERRIDE, WLC_SET_SHORTSLOT_OVERRIDE,
+	"Get/Set 11g Short Slot Timing mode override. (-1=auto, 0=long, 1=short)" },
+	{ "shortslot_restrict", wl_int, WLC_GET_SHORTSLOT_RESTRICT, WLC_SET_SHORTSLOT_RESTRICT,
+	"Get/Set AP Restriction on associations for 11g Short Slot Timing capable STAs.\n"
+	"\t0 - Do not restrict association based on ShortSlot capability\n"
+	"\t1 - Restrict association to STAs with ShortSlot capability" },
+	{ "ignore_bcns", wl_int, WLC_GET_IGNORE_BCNS, WLC_SET_IGNORE_BCNS,
+	"AP only (G mode): Check for beacons without NONERP element"
+	"(0=Examine beacons, 1=Ignore beacons)" },
+	{ "pktcnt", wl_get_pktcnt, WLC_GET_PKTCNTS, -1,
+	"Get the summary of good and bad packets." },
+	{ "upgrade", wl_upgrade, -1, WLC_UPGRADE,
+	"Upgrade the firmware on an embedded device" },
+	{ "gmode", wl_gmode, WLC_GET_GMODE, WLC_SET_GMODE,
+	"Set the 54g Mode (LegacyB|Auto||GOnly|BDeferred|Performance|LRS)" },
+	{ "gmode_protection", wl_int, WLC_GET_GMODE_PROTECTION, -1,
+	"Get G protection mode. (0=disabled, 1=enabled)" },
+	{ "gmode_protection_control", wl_int, WLC_GET_PROTECTION_CONTROL,
+	WLC_SET_PROTECTION_CONTROL,
+	"Get/Set 11g protection mode control alg."
+	"(0=always off, 1=monitor local association, 2=monitor overlapping BSS)" },
+	{ "gmode_protection_override", wl_int, WLC_GET_GMODE_PROTECTION_OVERRIDE,
+	WLC_SET_GMODE_PROTECTION_OVERRIDE,
+	"Get/Set 11g protection mode override. (-1=auto, 0=disable, 1=enable)" },
+	{ "protection_control", wl_int, WLC_GET_PROTECTION_CONTROL,
+	WLC_SET_PROTECTION_CONTROL,
+	"Get/Set protection mode control alg."
+	"(0=always off, 1=monitor local association, 2=monitor overlapping BSS)" },
+	{ "legacy_erp", wl_int, WLC_GET_LEGACY_ERP, WLC_SET_LEGACY_ERP,
+	"Get/Set 11g legacy ERP inclusion (0=disable, 1=enable)" },
+	{ "scb_timeout", wl_int, WLC_GET_SCB_TIMEOUT, WLC_SET_SCB_TIMEOUT,
+	"AP only: inactivity timeout value for authenticated stas" },
+	{ "assoclist", wl_maclist, WLC_GET_ASSOCLIST, -1,
+	"AP only: Get the list of associated MAC addresses."},
+	{ "isup", wl_int, WLC_GET_UP, -1,
+	"Get driver operational state (0=down, 1=up)"},
+	{ "rssi", wl_rssi, WLC_GET_RSSI, -1,
+	"Get the current RSSI val, for an AP you must specify the mac addr of the STA" },
+	{ "rssi_event", wl_rssi_event, WLC_GET_VAR, WLC_SET_VAR,
+	"Set parameters associated with RSSI event notification\n"
+	"\tusage: wl rssi_event <rate_limit> <rssi_levels>\n"
+	"\trate_limit: Number of events posted to application will be limited"
+	" to 1 per this rate limit. Set to 0 to disable rate limit.\n"
+	"\trssi_levels: Variable number of RSSI levels (maximum 8) "
+	" in increasing order (e.g. -85 -70 -60). An event will be posted"
+	" each time the RSSI of received beacons/packets crosses a level."},
+	{ "fasttimer", wl_print_deprecate, -1, -1,
+	"Deprecated. Use fast_timer."},
+	{ "slowtimer", wl_print_deprecate, -1, -1,
+	"Deprecated. Use slow_timer."},
+	{ "glacialtimer", wl_print_deprecate, -1, -1,
+	"Deprecated. Use glacial_timer."},
+	{ "radar", wl_int, WLC_GET_RADAR, WLC_SET_RADAR,
+	"Enable/Disable radar"},
+	{ "radarargs", wl_radar_args, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set Radar parameters in \n"
+	"\torder as version, npulses, ncontig, min_pw, max_pw, thresh0,\n"
+	"\tthresh1, blank, fmdemodcfg, npulses_lp, min_pw_lp, max_pw_lp,\n"
+	"\tmin_fm_lp, max_span_lp, min_deltat, max_deltat,\n"
+	"\tautocorr, st_level_time, t2_min, fra_pulse_err, npulses_fra,\n"
+	"\tnpulses_stg2, npulses_stg3, percal_mask, quant, \n"
+	"\tmin_burst_intv_lp, max_burst_intv_lp, nskip_rst_lp, max_pw_tol, feature_mask"},
+	{ "radarargs40", wl_radar_args, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set Radar parameters for 40Mhz channel in \n"
+	"\torder as version, npulses, ncontig, min_pw, max_pw, thresh0,\n"
+	"\tthresh1, blank, fmdemodcfg, npulses_lp, min_pw_lp, max_pw_lp,\n"
+	"\tmin_fm_lp, max_span_lp, min_deltat, max_deltat,\n"
+	"\tautocorr, st_level_time, t2_min, fra_pulse_err, npulses_fra,\n"
+	"\tnpulses_stg2, npulses_stg3, percal_mask, quant, \n"
+	"\tmin_burst_intv_lp, max_burst_intv_lp, nskip_rst_lp, max_pw_tol, feature_mask"},
+	{ "radarthrs", wl_radar_thrs, -1, WLC_SET_VAR,
+	"Set Radar threshold for both 20 & 40MHz & 80MHz BW:\n"
+	"\torder as thresh0_20_lo, thresh1_20_lo, thresh0_40_lo, thresh1_40_lo\n"
+	"\tthresh0_80_lo, thresh1_80_lo, thresh0_20_hi, thresh1_20_hi\n"
+	"\tthresh0_40_hi, thresh1_40_hi, thresh0_80_hi, thresh1_80_hi\n"},
+
+	{ "dfs_status", wl_dfs_status, WLC_GET_VAR, -1,
+	"Get dfs status"},
+	{ "interference", wl_interfere, WLC_GET_INTERFERENCE_MODE, WLC_SET_INTERFERENCE_MODE,
+	"Get/Set interference mitigation mode. Choices are:\n"
+	"\t0 = none\n"
+	"\t1 = non wlan\n"
+	"\t2 = wlan manual\n"
+	"\t3 = wlan automatic\n"
+	"\t4 = wlan automatic with noise reduction"},
+	{ "interference_override", wl_interfere_override,
+	WLC_GET_INTERFERENCE_OVERRIDE_MODE,
+	WLC_SET_INTERFERENCE_OVERRIDE_MODE,
+	"Get/Set interference mitigation override. Choices are:\n"
+	"\t0 = no interference mitigation\n"
+	"\t1 = non wlan\n"
+	"\t2 = wlan manual\n"
+	"\t3 = wlan automatic\n"
+	"\t4 = wlan automatic with noise reduction\n"
+	"\t-1 = remove override, override disabled"},
+	{ "frameburst", wl_int, WLC_GET_FAKEFRAG, WLC_SET_FAKEFRAG,
+	"Disable/Enable frameburst mode" },
+	{ "pwr_percent", wl_int, WLC_GET_PWROUT_PERCENTAGE, WLC_SET_PWROUT_PERCENTAGE,
+	"Get/Set power output percentage"},
+	{ "toe", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable tcpip offload feature"},
+	{ "toe_ol", wl_offload_cmpnt, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set tcpip offload components"},
+	{ "toe_stats", wl_toe_stats, WLC_GET_VAR, -1,
+	"Display checksum offload statistics"},
+	{ "toe_stats_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear checksum offload statistics"},
+#endif
+	{ "arpoe", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable arp agent offload feature"},
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "arp_ol", wl_offload_cmpnt, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set arp offload components"},
+	{ "arp_peerage", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set age of the arp entry in minutes"},
+	{ "arp_table_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear arp cache"},
+#ifdef WLOFFLD
+	{ "ol_notify_bcn_ie", wl_ol_notify_bcn_ie, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable IE ID notification"},
+	{ "ol_arp_hostip", wl_hostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a host-ip address or display them"},
+	{ "ol_nd_hostip", wl_hostipv6, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a local host-ipv6 address or display them"},
+#endif
+	{ "arp_hostip", wl_hostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a host-ip address or display them"},
+	{ "arp_hostip_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear all host-ip addresses"},
+	{ "ns_hostip", wl_nshostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a ns-ip address or display then"},
+	{ "ns_hostip_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear all ns-ip addresses"},
+	{ "arp_stats", wl_arp_stats, WLC_GET_VAR, -1,
+	"Display ARP offload statistics"},
+	{ "arp_stats_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear ARP offload statistics"},
+	{ "wet", wl_int, WLC_GET_WET, WLC_SET_WET,
+	"Get/Set wireless ethernet bridging mode"},
+	{ "bi", wl_int, WLC_GET_BCNPRD, WLC_SET_BCNPRD,
+	"Get/Set the beacon period (bi=beacon interval)"},
+	{ "dtim", wl_int, WLC_GET_DTIMPRD, WLC_SET_DTIMPRD,
+	"Get/Set DTIM"},
+	{ "wds_remote_mac", wl_mac, WLC_WDS_GET_REMOTE_HWADDR, -1,
+	"Get WDS link remote endpoint's MAC address"},
+	{ "wds_wpa_role_old", wl_wds_wpa_role_old, WLC_WDS_GET_WPA_SUP, -1,
+	"Get WDS link local endpoint's WPA role (old)"},
+	{ "wds_wpa_role", wl_wds_wpa_role, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set WDS link local endpoint's WPA role"},
+	{ "authe_sta_list", wl_maclist_1, WLC_GET_VAR, -1,
+	"Get authenticated sta mac address list"},
+	{ "autho_sta_list", wl_maclist_1, WLC_GET_VAR, -1,
+	"Get authorized sta mac address list"},
+	{ "measure_req", wl_measure_req, -1, WLC_MEASURE_REQUEST,
+	"Send an 802.11h measurement request.\n"
+	"\tUsage: wl measure_req <type> <target MAC addr>\n"
+	"\tMeasurement types are: TPC, Basic, CCA, RPI\n"
+	"\tTarget MAC addr format is xx:xx:xx:xx:xx:xx"},
+	{ "quiet", wl_send_quiet, -1, WLC_SEND_QUIET,
+	"Send an 802.11h quiet command.\n"
+	"\tUsage: wl quiet <TBTTs until start>, <duration (in TUs)>, <offset (in TUs)>"},
+#endif
+	{ "csa", wl_send_csa, -1, WLC_SET_VAR,
+	"Send an 802.11h channel switch anouncement with chanspec:\n"
+	"\t<mode> <count> <channel>[a,b][n][u,l][frame type]\n"
+	"\tmode (0 or 1)\n"
+	"\tcount (0-254)\n"
+	"\tchannel format:\n"
+	"\t20MHz : [2g|5g]<channel>[/20]\n"
+	"\t40MHz : [2g|5g]<channel>/40[u,l]\n"
+	"\t80MHz :    [5g]<channel>/80\n"
+	"\toptional band 2g or 5g, default to 2g if channel <= 14\n"
+	"\tchannel number (0-200)\n"
+	"\tbandwidth, 20, 40, or 80, default 20\n"
+	"\tprimary sideband for 40MHz on 2g, l=lower, u=upper\n"
+	"\tcsa frame type(optional), default is broadcast if not specified, u=unicast"},
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "constraint", wl_int, -1, WLC_SEND_PWR_CONSTRAINT,
+	"Send an 802.11h Power Constraint IE\n"
+	"\tUsage: wl constraint 1-255 db"},
+	{ "rm_req", wl_rm_request, -1, WLC_SET_VAR,
+	"Request a radio measurement of type basic, cca, or rpi\n"
+	"\tspecify a series of measurement types each followed by options.\n"
+	"\texample: wl rm_req cca -c 1 -d 50 cca -c 6 cca -c 11\n"
+	"\tOptions:\n"
+	"\t-t n  numeric token id for measurement set or measurement\n"
+	"\t-c n  channel\n"
+	"\t-d n  duration in TUs (1024 us)\n"
+	"\t-p    parallel flag, measurement starts at the same time as previous\n"
+	"\n"
+	"\tEach measurement specified uses the same channel and duration as the\n"
+	"\tprevious unless a new channel or duration is specified."},
+	{ "rm_rep", wl_rm_report, WLC_GET_VAR, -1,
+	"Get current radio measurement report"},
+	{ "join_pref", wl_join_pref, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get join target preferences."},
+	{ "assoc_pref", wl_assoc_pref, WLC_GET_ASSOC_PREFER, WLC_SET_ASSOC_PREFER,
+	"Set/Get association preference.\n"
+	"Usage: wl assoc_pref [auto|a|b|g]"},
+	{ "wme", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set WME (Wireless Multimedia Extensions) mode (0=off, 1=on, -1=auto)"},
+	{ "wme_ac", wl_wme_ac_req, WLC_GET_VAR, WLC_SET_VAR,
+	"wl wme_ac ap|sta [be|bk|vi|vo [ecwmax|ecwmin|txop|aifsn|acm <value>] ...]"},
+	{ "wme_apsd", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set APSD (Automatic Power Save Delivery) mode on AP (0=off, 1=on)" },
+	{ "wme_apsd_sta", wl_wme_apsd_sta, WLC_GET_VAR, WLC_SET_VAR,
+	"Set APSD parameters on STA. Driver must be down.\n"
+	"Usage: wl wme_apsd_sta <max_sp_len> <be> <bk> <vi> <vo>\n"
+	"   <max_sp_len>: number of frames per USP: 0 (all), 2, 4, or 6\n"
+	"   <xx>: value 0 to disable, 1 to enable U-APSD per AC" },
+	{ "wme_dp", wl_wme_dp, WLC_GET_VAR, WLC_SET_VAR,
+	"Set AC queue discard policy.\n"
+	"Usage: wl wme_dp <be> <bk> <vi> <vo>\n"
+	"   <xx>: value 0 for newest-first, 1 for oldest-first" },
+	{ "wme_counters", wl_wme_counters, WLC_GET_VAR, -1,
+	"print WMM stats" },
+	{ "wme_clear_counters", wl_var_void, -1, WLC_SET_VAR,
+	"clear WMM counters"},
+	{ "wme_tx_params", wme_tx_params, -1, -1,
+	"wl wme_tx_params [be|bk|vi|vo [short|sfb|long|lfb|max_rate <value>] ...]"},
+	{ "wme_maxbw_params", wme_maxbw_params, WLC_GET_VAR, WLC_SET_VAR,
+	"wl wme_maxbw_params [be|bk|vi|vo <value> ....]"},
+	{ "lifetime", wl_lifetime, WLC_GET_VAR, WLC_SET_VAR,
+	"Set Lifetime parameter (milliseconds) for each ac.\n"
+	"wl lifetime be|bk|vi|vo [<value>]"},
+	{ "reinit", wl_void, -1, WLC_INIT,
+	"Reinitialize device"},
+	{ "sta_info", wl_sta_info, WLC_GET_VAR, -1,
+	"wl sta_info <xx:xx:xx:xx:xx:xx>"},
+	{ "staprio", wl_staprio, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get sta priority \n"
+	"Usage: wl staprio <xx:xx:xx:xx:xx:xx> <prio> \n"
+	"<prio>: 0~3"},
+	{ "pktq_stats", wl_iov_pktqlog_params, WLC_GET_VAR, -1,
+	"Dumps packet queue log info for [C] common, [A] AMPDU, [N] NAR or [P] power save queues\n"
+	"A:, N: or P: are used to prefix a MAC address (a colon : separator is necessary),\n"
+	"or else C: is used alone. The '+' option after the colon gives more details.\n"
+	"Up to 4 parameters may be given, the common queue is default when no parameters\n"
+	"are supplied\n"
+	"Use '/<PREC>' as suffix to restrict to certain prec indices; multiple /<PREC>/<PREC>/..."
+	"can be used\n"
+	"Also, '//' as a suffix to the MAC address or 'C://' will enable automatic logging of\n"
+	"all prec as they are seen.\n"
+	"Full automatic operation is also possible with the shorthand\n"
+	"'A:' (or 'A://'), 'P:' (or 'P://') etc which scans through all known addresses for\n"
+	"those parameters that take a MAC address.\n"
+	"wl pktq_stats [C:[+]]|[A:[+]|P:[+]|N:[+]<xx:xx:xx:xx:xx:xx>][/<PREC>[/<PREC>]][//]..." },
+	{ "bs_data", wl_scb_bs_data, WLC_GET_VAR, -1, "Display per station band steering data\n"
+	"usage: bs_data [options]\n"
+	"  options are:\n"
+	"    -comma    Use commas to separate values rather than blanks.\n"
+	"    -tab      Use <TAB> to separate values rather than blanks.\n"
+	"    -raw      Display raw values as received from driver.\n"
+	"    -noidle   Do not display idle stations\n"
+	"    -noreset  Do not reset counters after reading" },
+	{ "cap", wl_var_getandprintstr, WLC_GET_VAR, -1, "driver capabilities"},
+	{ "malloc_dump", wl_print_deprecate, -1, -1, "Deprecated. Folded under 'wl dump malloc"},
+	{ "chan_info", wl_chan_info, WLC_GET_VAR, -1, "channel info"},
+	{ "add_ie", wl_add_ie, -1, WLC_SET_VAR,
+	"Add a vendor proprietary IE to 802.11 management packets\n"
+	"Usage: wl add_ie <pktflag> length OUI hexdata\n"
+	"<pktflag>: Bit 0 - Beacons\n"
+	"           Bit 1 - Probe Rsp\n"
+	"           Bit 2 - Assoc/Reassoc Rsp\n"
+	"           Bit 3 - Auth Rsp\n"
+	"           Bit 4 - Probe Req\n"
+	"           Bit 5 - Assoc/Reassoc Req\n"
+	"Example: wl add_ie 3 10 00:90:4C 0101050c121a03\n"
+	"         to add this IE to beacons and probe responses" },
+	{ "del_ie", wl_del_ie, -1, WLC_SET_VAR,
+	"Delete a vendor proprietary IE from 802.11 management packets\n"
+	"Usage: wl del_ie <pktflag> length OUI hexdata\n"
+	"<pktflag>: Bit 0 - Beacons\n"
+	"           Bit 1 - Probe Rsp\n"
+	"           Bit 2 - Assoc/Reassoc Rsp\n"
+	"           Bit 3 - Auth Rsp\n"
+	"           Bit 4 - Probe Req\n"
+	"           Bit 5 - Assoc/Reassoc Req\n"
+	"Example: wl del_ie 3 10 00:90:4C 0101050c121a03" },
+	{ "list_ie", _wl_list_ie, WLC_GET_VAR, -1,
+	"Dump the list of vendor proprietary IEs" },
+	{ "rand", wl_rand, WLC_GET_VAR, -1,
+	"Get a 2-byte Random Number from the MAC's PRNG\n"
+	"Usage: wl rand"},
+	{ "otpraw", wl_otpraw, WLC_GET_VAR, WLC_SET_VAR,
+	"Read/Write raw data to on-chip otp\n"
+	"Usage: wl otpraw <offset> <bits> [<data>]"},
+	{ "otpw", wl_otpw, -1, WLC_OTPW,
+	"Write an srom image to on-chip otp\n"
+	"Usage: wl otpw file"},
+	{ "nvotpw", wl_otpw, -1, WLC_NVOTPW,
+	"Write nvram to on-chip otp\n"
+	"Usage: wl nvotpw file"},
+	{ "bcmerrorstr", wl_var_getandprintstr, WLC_GET_VAR, -1, "errorstring"},
+	{ "freqtrack", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set Frequency Tracking Mode (0=Auto, 1=On, 2=OFF)"},
+	{ "eventing", wl_eventbitvec, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get hex filter bitmask for MAC event reporting up to application layer"},
+	{ "event_msgs", wl_eventbitvec, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get hex filter bitmask for MAC event reporting via packet indications"},
+	{ "counters", wl_counters, WLC_GET_VAR, -1,
+	"Return driver counter values" },
+	{ "delta_stats_interval", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the delta statistics interval in seconds (0 to disable)"},
+	{ "delta_stats", wl_delta_stats, WLC_GET_VAR, -1,
+	"get the delta statistics for the last interval" },
+	{ "assoc_info", wl_assoc_info, WLC_GET_VAR, -1,
+	"Returns the assoc req and resp information [STA only]" },
+	{ "beacon_info", wl_management_info, WLC_GET_VAR, -1,
+	"Returns the 802.11 management frame beacon information\n"
+	"Usage: wl beacon_info [-f file] [-r]\n"
+	"\t-f Write beacon data to file\n"
+	"\t-r Raw hex dump of beacon data" },
+	{ "probe_resp_info", wl_management_info, WLC_GET_VAR, -1,
+	"Returns the 802.11 management frame probe response information\n"
+	"Usage: wl probe_resp_info [-f file] [-r]\n"
+	"\t-f Write probe response data to file\n"
+	"\t-r Raw hex dump of probe response data" },
+	{ "autochannel", wl_auto_channel_sel, WLC_GET_CHANNEL_SEL, WLC_START_CHANNEL_SEL,
+	"auto channel selection: \n"
+	"\t1 to issue a channel scanning;\n"
+	"\t2 to set chanspec based on the channel scan result;\n"
+	"\twithout argument to only show the chanspec selected; \n"
+	"\tssid must set to null before this process, RF must be up"},
+	{ "csscantimer", wl_int, WLC_GET_CS_SCAN_TIMER, WLC_SET_CS_SCAN_TIMER,
+	"auto channel scan timer in minutes (0 to disable)" },
+	{ "closed", wl_int, WLC_GET_CLOSED, WLC_SET_CLOSED,
+	"hides the network from active scans, 0 or 1.\n"
+	"\t0 is open, 1 is hide" },
+	{ "pmkid_info", wl_pmkid_info, WLC_GET_VAR, WLC_SET_VAR,
+	"Returns the pmkid table" },
+#endif
+	{ "bss", wl_bsscfg_enable, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get BSS enabled status: up/down"},
+#ifdef BUILD_FEATURE_WIFI_BCM_WL
+	{ "closednet", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get BSS closed network attribute"},
+	{ "ap_isolate", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get AP isolation"},
+	{ "eap_restrict", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get EAP restriction"},
+	{ "diag", wl_diag, WLC_GET_VAR, -1,
+	"diag testindex(1-interrupt, 2-loopback, 3-memory, 4-led);"
+	" precede by 'wl down' and follow by 'wl up'" },
+	{ "reset_d11cnts", wl_var_void, -1, WLC_SET_VAR,
+	"reset 802.11 MIB counters"},
+	{ "staname", wl_varstr, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set station name: \n"
+	"\tMaximum name length is 15 bytes"},
+	{ "apname", wl_varstr, WLC_GET_VAR, -1,
+	"get AP name"},
+	{ "otpdump", wl_var_setintandprintstr, WLC_GET_VAR, -1,
+	"Dump raw otp"},
+	{ "otpstat", wl_var_setintandprintstr, WLC_GET_VAR, -1,
+	"Dump OTP status"},
+	{ "nrate", wl_nrate, WLC_GET_VAR, WLC_SET_VAR,
+	"\"auto\" to clear a rate override, or:\n"
+	"-r legacy rate (CCK, OFDM)\n"
+	"-m HT MCS index\n"
+	"-s stf mode (0=SISO,1=CDD,2=STBC,3=SDM)\n"
+	"-w Override MCS only to support STA's with/without STBC capability"},
+	{ "mimo_txbw", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set mimo txbw (2=20Mhz(lower), 3=20Mhz upper, 4=40Mhz)"},
+	{ "cac_addts", wl_cac, -1, WLC_SET_VAR,
+	"add TSPEC, error if STA is not associated or WME is not enabled\n"
+	"\targ: TSPEC parameter input list"},
+	{ "cac_delts", wl_cac, -1, WLC_SET_VAR,
+	"delete TSPEC, error if STA is not associated or WME is not enabled\n"
+	"\targ: TSINFO for the target tspec"},
+	{ "cac_delts_ea", wl_cac_delts_ea, -1, WLC_SET_VAR,
+	"delete TSPEC, error if STA is not associated or WME is not enabled\n"
+	"\targ1: Desired TSINFO for the target tspec\n"
+	"\targ2: Desired MAC address"},
+	{ "cac_tslist", wl_tslist, WLC_GET_VAR, -1,
+	"Get the list of TSINFO in driver\n"
+	"\teg. 'wl cac_tslist' get a list of TSINFO"},
+	{ "cac_tslist_ea", wl_tslist_ea, WLC_GET_VAR, -1,
+	"Get the list of TSINFO for given STA in driver\n"
+	"\teg. 'wl cac_tslist_ea ea' get a list of TSINFO"},
+	{ "cac_tspec", wl_tspec, WLC_GET_VAR, -1,
+	"Get specific TSPEC with matching TSINFO\n"
+	"\teg. 'wl cac_tspec 0xaa 0xbb 0xcc' where 0xaa 0xbb & 0xcc are TSINFO octets"},
+	{ "cac_tspec_ea", wl_tspec_ea, WLC_GET_VAR, -1,
+	"Get specific TSPEC for given STA with matching TSINFO\n"
+	"\teg. 'wl cac_tspec 0xaa 0xbb 0xcc xx:xx:xx:xx:xx:xx'\n"
+	"\t    where 0xaa 0xbb & 0xcc are TSINFO octets and xx is mac address"},
+
+	{ "sd_cis", wl_var_getandprintstr, WLC_GET_VAR, -1,
+	"dump sdio CIS"},
+	{ "sd_devreg", wl_sd_reg, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set device register across SDIO bus"},
+	{ "sd_drivestrength", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set SDIO bus drive strenth in mA"},
+	{ "sd_hostreg", wl_sd_reg, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set local controller register"},
+	{ "sd_blockmode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set blockmode"},
+	{ "sd_blocksize", wl_sd_blocksize, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set block size for a function"},
+	{ "sd_ints", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set client ints"},
+	{ "sd_dma", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set dma usage"},
+	{ "sd_numints", wl_varint, WLC_GET_VAR, -1,
+	"number of device interrupts"},
+	{ "sd_numlocalints", wl_varint, WLC_GET_VAR, -1,
+	"number of non-device controller interrupts"},
+	{ "sd_divisor", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"set the divisor for SDIO clock generation"},
+	{ "sd_mode", wl_sd_mode, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set SDIO bus mode (spi, sd1, sd4)"},
+	{ "sd_highspeed", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"set the high-speed clocking mode"},
+	{ "sd_msglevel", wl_sd_msglevel, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set debug message level"},
+
+	{ "overlay", wl_overlay, WLC_GET_VAR, WLC_SET_VAR,
+	"overlay virt_addr phy_addr size"},
+	{ "phy_txpwrindex", wl_phy_txpwrindex, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: (set) phy_txpwrindex core0_idx core1_idx core2_idx core3_idx"
+	"       (get) phy_txpwrindex, return format: core0_idx core1_idx core2_idx core3_idx"
+	"Set/Get txpwrindex"
+	},
+	{ "rssi_cal_freq_grp_2g", wl_rssi_cal_freq_grp_2g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: wl_rssi_cal_freq_grp_2g [chan_1_2,chan_3_4,...,chan_13_14]\n"
+	"Each of the variables like - chan_1_2 is a byte"
+	"Upper nibble of this byte is for chan1 and lower for chan2"
+	"MSB of the nibble tells if the channel is used for calibration"
+	"3 LSB's tell which group the channel falls in"
+	"Set/get rssi calibration frequency grouping"
+	},
+	{ "phy_rssi_gain_delta_2gb0", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb0 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb1", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb1 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb2", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb2 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb3", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb3 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb4", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb4 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2g", wl_phy_rssi_gain_delta_2g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2g [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gl", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gl [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gml", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gml [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gmu", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gmu [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gh", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gh [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rxgainerr_2g", wl_phy_rxgainerr_2g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_2g [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gl", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gl [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gm", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gml [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gh", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gmu [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gu", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gh [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_test_tssi", wl_test_tssi, WLC_GET_VAR, -1,
+	"wl phy_test_tssi val"},
+	{ "phy_test_tssi_offs", wl_test_tssi_offs, WLC_GET_VAR, -1,
+	"wl phy_test_tssi_offs val"},
+	{ "phy_rssiant", wl_phy_rssiant, WLC_GET_VAR, -1,
+	"wl phy_rssiant antindex(0-3)"},
+	{ "phy_rssi_ant", wl_phy_rssi_ant, WLC_GET_VAR, WLC_SET_VAR,
+	"Get RSSI per antenna (only gives RSSI of current antenna for SISO PHY)"},
+	{ "lpphy_papdepstbl", wl_phy_papdepstbl, -1, WLC_GET_VAR,
+	"print papd eps table; Usage: wl lpphy_papdepstbl"
+	},
+	{ "phy_test_idletssi", wl_test_idletssi, WLC_GET_VAR, -1,
+	"get idletssi for the given core; wl phy_test_idletssi corenum"},
+	{ "phy_setrptbl", wl_var_void, -1, WLC_SET_VAR,
+	"populate the reciprocity compensation table based on SROM cal content\n\n"
+	"\tusage: wl phy_setrptbl"},
+	{ "phy_forceimpbf", wl_var_void, -1, WLC_SET_VAR,
+	"force the beamformer into implicit TXBF mode and ready to construct steering matrix\n\n"
+	"\tusage: wl phy_forceimpbf"},
+	{ "phy_forcesteer", wl_var_setint, -1, WLC_SET_VAR,
+	"force the beamformer to apply steering matrix when TXBF is turned on\n\n"
+	"\tusage: wl phy_forcesteer 1/0"},
+	{ "lcnphy_papdepstbl", wl_phy_papdepstbl, -1, WLC_GET_VAR,
+	"print papd eps table; Usage: wl lcnphy_papdepstbl"
+	},
+	{ "rifs", wl_rifs, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the rifs status; usage: wl rifs <1/0> (On/Off)"
+	},
+	{ "rifs_advert", wl_rifs_advert, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the rifs mode advertisement status; usage: wl rifs_advert <-1/0> (Auto/Off)"
+	},
+	{ "phy_rxiqest", wl_rxiq, WLC_GET_VAR, -1,
+	"Get phy RX IQ noise in dBm:\n"
+	"\t-s # of samples (2^n)\n"
+	"\t-a antenna select, 0,1 or 3\n"
+	  "\t-r resolution select, 0 (coarse) or 1 (fine)\n"
+	  "\t-f lpf hpc override select, 0 (hpc unchanged) or 1 (overridden to ltrn mode)\n"
+	  "\t-w dig lpf override select, 0 (lpf unchanged) or 1 (overridden to ltrn_lpf mode)"
+	  "\t or 2 (bypass)\n"
+	  "\t-g gain-correction select, 0 (disable), 1(enable full correction) \n"
+	  "\t	2 (enable temperature correction) or 3(verify rssi_gain_delta)\n"
+	  "\t-e extra INITgain in dB on top of default. Valid values = {0, 3, 6, .., 21, 24}\n"
+	  "\t-i gain mode select, 0 (default gain), 1 (fixed high gain) or 4 (fixed low gain). \n"
+	},
+	{ "phy_txiqcc", wl_phy_txiqcc, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_txiqcc [a b]\n"
+	"Set/get the iqcc a, b values"
+	},
+	{ "phy_txlocc", wl_phy_txlocc, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_txlocc [di dq ei eq fi fq]\n"
+	"Set/get locc di dq ei eq fi fq values"
+	},
+	{ "phytable", wl_phytable, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: wl phytable table_id offset width_of_table_element [table_element]\n"
+	"Set/get table element of a table with the given ID at the given offset\n"
+	"Note that table width supplied should be 8 or 16 or 32\n"
+	"table ID, table offset can not be negative"
+	},
+	/* WLOTA_EN START */
+	{ "ota_teststop", wl_ota_teststop, -1, WLC_SET_VAR,
+	"\tUsage: ota_teststop \n"
+	},
+	{ "ota_loadtest", wl_ota_loadtest, -1, WLC_SET_VAR,
+	"\tUsage: ota_loadtest [filename] \n"
+	"\t\tpicks up ota_test.txt if file is not given \n"
+	},
+	{ "ota_stream", wl_load_cmd_stream, -1, WLC_SET_VAR,
+	"\tUsage: wl ota_stream start   : to start the test\n"
+	"\twl ota_stream ota_sync \n"
+	"\twl ota_stream test_setup synchtimeoout(seconds) synchbreak/loop synchmac txmac rxmac \n"
+	"\twl ota_stream ota_tx chan bandwidth contrlchan rates stf txant rxant tx_ifs tx_len"
+	"num_pkt pwrctrl start:delta:end \n"
+	"\twl ota_stream ota_rx chan bandwidth contrlchan -1 stf txant rxant tx_ifs"
+	"tx_len num_pkt \n"
+	"\twl ota_stream stop   : to stop the test\n"
+	},
+	{ "ota_teststatus", wl_otatest_status, WLC_GET_VAR, -1,
+	"\tUsage: otatest_status"
+	"\t\tDisplays current running test details"
+	"\totatest_status n	"
+	"\t\tdisplays test arguments for nth line  \n"
+	},
+	/* WLOTA_EN END */
+	{ "force_vsdb_chans", wl_phy_force_vsdb_chans, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get  channels for forced vsdb mode\n"
+	"usage: wl force_vsdb_chans chan1 chan2\n"
+	"Note: Give chan in the same format as chanspec: eg force_vsdb_chans 1l 48u\n"
+	},
+	{ "pavars", wl_phy_pavars, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get temp PA parameters\n"
+	"usage: wl down\n"
+	"       wl pavars pa2gw0a0=0x1 pa2gw1a0=0x2 pa2gw2a0=0x3 ... \n"
+	"       wl pavars\n"
+	"       wl up\n"
+	"  override the PA parameters after driver attach(srom read), before diver up\n"
+	"  These override values will be propogated to HW when driver goes up\n"
+	"  PA parameters in one band range (2g, 5gl, 5g, 5gh) must all present if\n"
+	"  one of them is specified in the command, otherwise it will be filled with 0"
+	},
+	{ "povars", wl_phy_povars, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get temp power offset\n"
+	"usage: wl down\n"
+	"       wl povars cck2gpo=0x1 ofdm2gpo=0x2 mcs2gpo=0x3 ... \n"
+	"       wl povars\n"
+	"       wl up\n"
+	"  override the power offset after driver attach(srom read), before diver up\n"
+	"  These override values will be propogated to HW when driver goes up\n"
+	"  power offsets in one band range (2g, 5gl, 5g, 5gh) must all present if\n"
+	"  one of them is specified in the command, otherwise it will be filled with 0"
+	"  cck(2g only), ofdm, and mcs(0-7) for NPHY are supported "
+	},
+	{ "rpcalvars", wl_phy_rpcalvars, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get temp RPCAL parameters\n"
+	"usage: wl down\n"
+	"       wl rpcalvars rpcal2g=0x1 \n"
+	"       wl rpcalvars\n"
+	"       wl up\n"
+	"  override the RPCAL parameters after driver attach(srom read), before diver up\n"
+	"  These override values will be propogated to HW when driver goes up\n"
+	"  Only the RPCAL parameter specified in the command is updated, the rest is untouched \n"
+	},
+	{ "fem", wl_phy_fem, WLC_GET_VAR, WLC_SET_VAR,
+	"Set temp fem2g/5g value\n"
+	"usage: wl fem (tssipos2g=0x1 extpagain2g=0x2 pdetrange2g=0x1 triso2g=0x1 antswctl2g=0)\n"
+	"	(tssipos5g=0x1 extpagain5g=0x2 pdetrange5g=0x1 triso5g=0x1 antswctl5g=0)"
+	},
+	{ "antgain", wl_antgain, WLC_GET_VAR, WLC_SET_VAR,
+	"Set temp ag0/1 value\n"
+	"usage: wl antgain ag0=0x1 ag1=0x2"
+	},
+	{ "maxpower", wl_phy_maxpower, WLC_GET_VAR, WLC_SET_VAR,
+	"Set temp maxp2g(5g)a0(a1) value\n"
+	"usage: wl maxpower maxp2ga0=0x1 maxp2ga1=0x2 maxp5ga0=0xff maxp5ga1=0xff\n"
+	"       maxp5gla0=0x3 maxp5gla1=0x4 maxp5gha0=0x5 maxp5gha1=0x6"
+	},
+
+	{ "phy_antsel", wl_antsel, WLC_GET_VAR, -1,
+	"get/set antenna configuration \n"
+	"\tset: -1(AUTO), 0xAB(fixed antenna selection)\n"
+	"\t\twhere A and B is the antenna numbers used for RF chain 1 and 0 respectively\n"
+	"\tquery: <utx>[AUTO] <urx>[AUTO] <dtx>[AUTO] <drx>[AUTO]\n"
+	"\t\twhere utx = TX unicast antenna configuration\n"
+	"\t\t\turx = RX unicast antenna configuration\n"
+	"\t\t\tdtx = TX default (non-unicast) antenna configuration\n"
+	"\t\t\tdrx = RX default (non-unicast) antenna configuration"
+	},
+	{ "txcore", wl_txcore, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: wl txcore -k <CCK core mask> -o <OFDM core mask> -s <1..4> -c <core bitmap>\n"
+	"\t-k CCK core mask\n"
+	"\t-o OFDM core mask\n"
+	"\t-s # of space-time-streams\n"
+	"\t-c active core (bitmask) to be used when transmitting frames"
+	},
+	{ "txcore_override", wl_txcore, WLC_GET_VAR, -1,
+	"Usage: wl txcore_override\n"
+	"\tget the user override of txcore"
+	},
+	{ "txchain_pwr_offset", wl_txcore_pwr_offset, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: wl txchain_pwr_offset [qdBm offsets]\n"
+	"\tGet/Set the current offsets for each core in qdBm (quarter dBm)"
+	},
+	{ "sample_collect", wl_sample_collect, WLC_PHY_SAMPLE_COLLECT, -1,
+	"Optional parameters ACPHY/HTPHY/(NPHY with NREV >= 7) are:\n"
+	"\t-f File name to dump the sample buffer (default \"sample_collect.dat\")\n"
+	"\t-t Trigger condition (default now)\n"
+	"\t\t now, good_fcs, bad_fcs, bad_plcp, crs, crs_glitch, crs_deassert\n"
+	"\t-b PreTrigger duration in us (default 10)\n"
+	"\t-a PostTrigger duration in us (default 10) \n"
+	"\t-m Sample collect mode (default 1) \n"
+	  "\t\tSC_MODE_0_sd_adc\t\t\t0\n"
+	  "\t\tSC_MODE_1_sd_adc_5bits\t\t\t1\n"
+	  "\t\tSC_MODE_2_cic0\t\t\t\t2\n"
+	  "\t\tSC_MODE_3_cic1\t\t\t\t3\n"
+	  "\t\tSC_MODE_4s_rx_farrow_1core\t\t4\n"
+	  "\t\tSC_MODE_4m_rx_farrow\t\t\t5\n"
+	  "\t\tSC_MODE_5_iq_comp\t\t\t6\n"
+	  "\t\tSC_MODE_6_dc_filt\t\t\t7\n"
+	  "\t\tSC_MODE_7_rx_filt\t\t\t8\n"
+	  "\t\tSC_MODE_8_rssi\t\t\t\t9\n"
+	  "\t\tSC_MODE_9_rssi_all\t\t\t10\n"
+	  "\t\tSC_MODE_10_tx_farrow\t\t\t11\n"
+	  "\t\tSC_MODE_11_gpio\t\t\t\t12\n"
+	  "\t\tSC_MODE_12_gpio_trans\t\t\t13\n"
+	  "\t\tSC_MODE_14_spect_ana\t\t\t14\n"
+	  "\t\tSC_MODE_5s_iq_comp\t\t\t15\n"
+	  "\t\tSC_MODE_6s_dc_filt\t\t\t16\n"
+	  "\t\tSC_MODE_7s_rx_filt\t\t\t17\n"
+	  "\t\t HTPHY: 0=adc, 1..3=adc+rssi, 4=gpio\n"
+	"\t\t NPHY: 1=Dual-Core adc[9:2], 2=Core0 adc[9:0], 3=Core1 adc[9:0], gpio=gpio\n"
+	"\t-g GPIO mux select (default 0)\n"
+	"\t\t use only for gpio mode\n"
+	"\t-d Downsample enable (default 0)\n"
+	"\t\t use only for HTPHY\n"
+	"\t-e BeDeaf enable (default 0)\n"
+	"\t-i Timeout in units of 10us. (ACPHY is in 10ms unit) (default 1000)\n"
+	"Optional parameters (NPHY with NREV < 7) are:\n"
+	"\t-f File name to dump the sample buffer (binary format, default \"sample_collect.dat\")\n"
+	"\t-u Sample collect duration in us (default 60)\n"
+	"\t-c Cores to do sample collect, only if BW=40MHz (default both)\n"
+	"Optional parameters LCN40PHY are:\n"
+	"\t-f File name to dump the sample buffer (default \"sample_collect.dat\")\n"
+	"\t-t Trigger condition (default now)\n"
+	"\t\t now\n"
+	"\t-s Trigger State (default 0)\n"
+	"\t-x Module_Sel1 (default 2)\n"
+	"\t-y Module_Sel2 (default 6)\n"
+	"\t-n Number of samples (Max 2048, default 2048)\n"
+	"For (NREV < 7), the NPHY buffer returned has the format:\n"
+	"\tIn 20MHz [(uint16)num_bytes, <I(core0), Q(core0), I(core1), Q(core1)>]\n"
+	"\tIn 40MHz [(uint16)num_bytes(core0), <I(core0), Q(core0)>,\n"
+	"\t\t(uint16)num_bytes(core1), <I(core1), Q(core1)>]"},
+#ifdef PLC
+	{ "plc", wl_plc, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the plc config params; usage: wl plc [[0|1] [node_list]"
+	"[link_affinity|mac_affinity <etheraddr> [<affinity>]]]" },
+#endif /* PLC */
+	{ "txfifo_sz", wl_txfifo_sz, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the txfifo size; usage: wl txfifo_sz <fifonum> <size_in_bytes>" },
+#ifdef WLPFN
+	{ "pfnset", wl_pfn_set, -1, -1,
+	"Configures preferred network offload parameter\n"
+	"\tpfnset syntax is: pfnset [scanfrq xxxxx(30 sec)] [netimeout xxxx(60 sec)]"
+	"[slowfrq xxxx(180 sec)] [bestn (2)|[1-BESTN_MAX]] [mscan (0)|[0-MSCAN_MAX]]"
+	"[bdscan (0)|1] [adapt (off)|[smart, strict, slow]]"
+	"[rssi_delta xxxx(30 dBm)] [sort (listorder)|rssi] [bkgscan (0)|1] [immediateevent (0)|1]"
+	"[immediate 0|(1)] [repeat (10)|[1-20]] [exp (2)|[1-5]] [separate 0|(1)]"},
+	{ "pfnadd", wl_pfn_add, -1, -1,
+	"Adding SSID based preferred networks to monitor and connect\n"
+	"\tpfnadd syntax is: pfnadd ssid <SSID> [hidden (0)|1]"
+	"[imode (bss)|ibss]"
+	"[amode (open)|shared] [wpa_auth (wpadisabled)|wpapsk|wpa2psk|wpanone|any]"
+	"[wsec WEP|TKIP|AES|TKIPAES] [suppress (neither)|found|lost] [rssi <rssi>(0 dBm)]\n"
+	"Up to 16 SSID networks can be added together in one pfnadd\n"
+	"\tTo specify more than one WPA methods, use a number (same format as wpa_auth iovar) "
+	"as the parameter of wpa_auth (e.g. 0x84 for wpapsk and wpa2psk.)"},
+	{ "pfnadd_bssid", wl_pfn_add_bssid, -1, -1,
+	"Adding BSSID based preferred networks to monitor and connect\n"
+	"\tpfnadd_bssid syntax is: pfnadd_bssid bssid <BSSID> [suppress (neither)|found|lost]"
+	"[rssi <rssi>(0 dBm)]\n"
+	"\tUp to 150 BSSIDs can be added together in one pfnadd_bssid\n"},
+	{ "pfncfg", wl_pfn_cfg, -1, -1,
+	"Configures channel list and report type\n"
+	"Usage: pfncfg [channel <list>] [report <type>] [prohibited 1|0]\n"
+	"\treport <type> is ssidonly, bssidonly, or both (default: both)\n"
+	"\tprohibited flag 1: allow and (passively) scan any channel (default 0)"},
+	{ "pfn", wl_pfn, -1, -1,
+	"Enable/disable preferred network off load monitoring\n"
+	"\tpfn syntax is: pfn 0|1"},
+	{ "pfnclear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear the preferred network list\n"
+	"\tpfnclear syntax is: pfnclear"},
+	{ "pfnbest", wl_pfnbest, -1, -1,
+	"Get the best n networks in each of up to m scans, with 16bit timestamp\n"
+	"\tpfnbest syntax is: pfnbest"},
+	{ "pfnlbest", wl_pfnlbest, -1, -1,
+	"Get the best n networks in each scan, up to m scans, with 32bit timestmp\n"
+	"\tpfnbest syntax is: pfnlbest"},
+	{ "pfnsuspend", wl_pfn_suspend, -1, -1,
+	"Suspend/resume pno scan\n"
+	"\tpfnsuspend syntax is: pfnsuspend 0|1"},
+	{ "pfnmem", wl_pfn_mem, -1, -1,
+	"Get supported mscan with given bestn\n"
+	"\tpfnmem syntax is: pfnmscan bestn [1-BESTN_MAX]"},
+	{ "pfneventchk", wl_pfn_event_check, -1, -1,
+	"Listen and prints the preferred network off load event from dongle\n"
+	"\tpfneventchk syntax is: pfneventchk [ifname]"},
+	{ "escan_event_check", wl_escan_event_check, -1, -1,
+	"Listen and prints the escan events from the dongle\n"
+	"\tescan_event_check syntax is: escan_event_check ifname flag\n"
+	"\tflag 1 = sync_id info, 2 = bss info, 4 = state + bss info [default], "
+	"8 = TLV check for IEs"},
+	{ "escanresults", wl_escanresults, -1, WLC_SET_VAR,
+	"Start escan and display results.\n" SCAN_USAGE
+	},
+	{ "event_filter", wl_event_filter, -1, -1,
+	"Set/get event filter\n"
+	"\tevent_filter syntax is: event_filter [value]"},
+#endif /* WLPFN */
+#ifdef WLP2PO
+	{ "p2po_listen", wl_p2po_listen, -1, WLC_SET_VAR,
+	"start listen (with period and interval)\n"
+	"\tusage: p2po_listen [\"period\"] [\"interval\"]\n"
+	},
+	{ "p2po_find", wl_var_void, -1, WLC_SET_VAR,
+	"start discovery\n"
+	},
+	{ "p2po_stop", wl_p2po_stop, -1, WLC_SET_VAR,
+	"stop both P2P listen and P2P device discovery offload(0:stop; 1:pause).\n"
+	"\tusage: p2po_stop <0|1>\n"
+	},
+	{ "p2po_addsvc", wl_p2po_addsvc, -1, WLC_SET_VAR,
+	"add query-service pair\n"
+	"\tusage: p2po_addsvc <protocol> <\"query\"> <\"response\">\n"
+	"\t\t<protocol>: 1 = Bonjour, 2 = UPnP\n"
+	},
+	{ "p2po_delsvc", wl_p2po_delsvc, -1, WLC_SET_VAR,
+	"delete query-service pair\n"
+	"\tusage: p2po_delsvc <protocol> <\"query\">\n"
+	"\t\t<protocol>: 1 = Bonjour, 2 = UPnP, 0 = delete all\n"
+	},
+	{ "p2po_sd_req_resp", wl_p2po_sd_reqresp, -1, WLC_SET_VAR,
+	"find a service\n"
+	"\tusage: p2po_sd_req_resp <protocol> <\"query\">\n"
+	"\t\t<protocol>: 1 = Bonjour, 2 = UPnP\n"
+	},
+	{ "p2po_sd_cancel", wl_var_void, -1, WLC_SET_VAR,
+	"cancel finding a service\n"
+	},
+	{ "p2po_listen_channel", wl_p2po_listen_channel, -1, WLC_SET_VAR,
+	"set listen channel to channel 1, 6, 11, or default\n"
+	"\tusage: p2po_listen_channel <1|6|11|0>\n"
+	},
+	{ "p2po_results", wl_p2po_results, -1, WLC_SET_VAR,
+	"Listens and displays P2PO results.\n"
+	},
+#endif /* WLP2PO */
+#ifdef WLANQPO
+	{ "anqpo_set", wl_anqpo_set, -1, -1,
+	"set ANQP offload parameters\n"
+	"\tusage: anqpo_set [max_retransmit <number>]\n"
+	"\t\t[response_timeout <msec>] [max_comeback_delay <msec>]\n"
+	"\t\t[max_retries <number>] [query \"encoded ANQP query\"]\n"
+	},
+	{ "anqpo_stop_query", wl_anqpo_stop_query, -1, WLC_SET_VAR,
+	"stop ANQP query\n"
+	"\tusage: anqpo_stop_query\n"
+	},
+	{ "anqpo_start_query", wl_anqpo_start_query, -1, WLC_SET_VAR,
+	"start ANQP query to peer(s)\n"
+	"\tusage: anqpo_start_query <channel> <xx:xx:xx:xx:xx:xx>\n"
+	"\t\t[<channel> <xx:xx:xx:xx:xx:xx>]>\n"
+	},
+	{ "anqpo_auto_hotspot", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"automatic ANQP query to maximum number of hotspot APs, default 0 (disabled)\n"
+	"\tusage: anqpo_auto_hotspot [max]\n"
+	},
+	{ "anqpo_ignore_mode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"ignore duplicate SSIDs or BSSIDs, default 0 (SSID)\n"
+	"\tusage: anqpo_ignore_mode [0 (SSID) | 1 (BSSID)]\n"
+	},
+	{ "anqpo_ignore_ssid_list", wl_anqpo_ignore_ssid_list, WLC_GET_VAR, WLC_SET_VAR,
+	"get, clear, set, or append to ANQP offload ignore SSID list\n"
+	"\tusage: wl anqpo_ignore_ssid_list [clear |\n"
+	"\t\tset <ssid1> [ssid2] |\n"
+	"\t\tappend <ssid3> [ssid4]>\n"
+	},
+	{ "anqpo_ignore_bssid_list", wl_anqpo_ignore_bssid_list, WLC_GET_VAR, WLC_SET_VAR,
+	"get, clear, set, or append to ANQP offload ignore BSSID list\n"
+	"\tusage: wl anqpo_ignore_bssid_list [clear |\n"
+	"\t\tset <xx:xx:xx:xx:xx:xx> [xx:xx:xx:xx:xx:xx] |\n"
+	"\t\tappend <xx:xx:xx:xx:xx:xx> [xx:xx:xx:xx:xx:xx]]>\n"
+	},
+	{ "anqpo_results", wl_anqpo_results, -1, WLC_SET_VAR,
+	"Listens and displays ANQP results.\n"
+	},
+#endif /* WLANQPO */
+	{ "hs20_ie", wl_hs20_ie, -1, WLC_SET_VAR,
+	"set hotspot 2.0 indication IE\n"
+	"\tusage: wl hs20_ie <length> <hexdata>\n"
+	},
+	{"rate_histo", wl_rate_histo, -1, WLC_GET_VAR,
+	"Get rate hostrogram"
+	},
+	{ "pkteng_start", wl_pkteng, -1, WLC_SET_VAR,
+	"start packet engine tx usage: wl pkteng_start <xx:xx:xx:xx:xx:xx>"
+	" <tx|txwithack> [(async)|sync] [ipg] [len] [nframes] [src]\n"
+	"\tstart packet engine rx usage: wl pkteng_start <xx:xx:xx:xx:xx:xx>"
+	" <rx|rxwithack> [(async)|sync] [rxframes] [rxtimeout]\n"
+	"\tsync: synchronous mode\n"
+	"\tipg: inter packet gap in us\n"
+	"\tlen: packet length\n"
+	"\tnframes: number of frames; 0 indicates continuous tx test\n"
+	"\tsrc: source mac address\n"
+	"\trxframes: number of receive frames (sync mode only)\n"
+	"\trxtimeout: maximum timout in msec (sync mode only)"},
+	{ "pkteng_stop", wl_pkteng, -1, WLC_SET_VAR,
+	"stop packet engine; usage: wl pkteng_stop <tx|rx>"},
+	{ "pkteng_stats", wl_pkteng_stats, -1, WLC_GET_VAR,
+	"packet engine stats; usage: wl pkteng_stats"},
+	{ "wowl", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable WOWL events\n"
+	"  0   - Clear all events\n"
+	"Bit 0 - Wakeup on Magic Packet\n"
+	"Bit 1 - Wakeup on NetPattern (use 'wl wowl_pattern' to configure pattern)\n"
+	"Bit 2 - Wakeup on loss-of-link due to Disassociation/Deauth\n"
+	"Bit 3 - Wakeup on retrograde tsf\n"
+	"Bit 4 - Wakeup on loss of beacon (use 'wl wowl_bcn_loss' to configure time)"},
+	{ "wowl_bcn_loss", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set #of seconds of beacon loss for wakeup event"},
+	{ "wowl_pattern", wl_wowl_pattern, -1, -1,
+	"usage: wowl_pattern [ [clr | [[ add | del ] offset mask value ]]]\n"
+	"No options -- lists existing pattern list\n"
+	"add -- Adds the pattern to the list\n"
+	"del -- Removes a pattern from the list\n"
+	"clr -- Clear current list\n"
+	"offset -- Starting offset for the pattern\n"
+	"mask -- Mask to be used for pattern. Bit i of mask => byte i of the pattern\n"
+	"value -- Value of the pattern"
+	},
+	/* wowl_keepalive shares structures and functions with "mkeep_alive" */
+	{"wowl_keepalive", wl_mkeep_alive, WLC_GET_VAR, WLC_SET_VAR,
+	"Send specified keep alive packet periodically in wowl mode.\n"
+	"\tUsage: wl wowl_keepalive <index0-1> <period> <packet>\n"
+	"\t\tindex: 0 - 1.\n"
+	"\t\tperiod: Re-transmission period in milli-seconds. 0 to disable packet transmits.\n"
+	"\t\tpacket: Hex packet contents to transmit. The packet contents should include "
+	"the entire ethernet packet (ethernet header, IP header, UDP header, and UDP "
+	"payload) specified in network byte order.\n"
+	"\n\te.g. Send keep alive packet every 30 seconds using id-1:\n"
+	"\twl wowl_keepalive 1 30000 0x0014a54b164f000f66f45b7e08004500001e000040004011c"
+	"52a0a8830700a88302513c413c4000a00000a0d\n" },
+
+	{ "wowl_wakeind", wl_wowl_wakeind, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: wowl_wakeind [clear]\n"
+	"Shows last system wakeup event indications from PCI and D11 cores\n"
+	"clear - Clear the indications"
+	},
+	{ "wowl_status", wl_wowl_status, WLC_GET_VAR, -1,
+	"usage: wowl_status [clear]\n"
+	"Shows last system wakeup setting"
+	},
+	{"wowl_pkt", wl_wowl_pkt, -1, -1,
+	"Send a wakeup frame to wakup a sleeping STA in WAKE mode\n"
+	"Usage: wl wowl_pkt <len> <dst ea | bcast | ucast <STA ea>>"
+	"[ magic [<STA ea>] | net <offset> <pattern> <reason code> ]\n"
+	"e.g. To send bcast magic frame -- "
+	"wl wowl_pkt 102 bcast magic 00:90:4c:AA:BB:CC\n"
+	"     To send ucast magic frame -- "
+	"wl wowl_pkt 102 ucast 00:90:4c:aa:bb:cc magic\n"
+	"     To send a frame with L2 unicast - "
+	"wl wowl_pkt 102 00:90:4c:aa:bb:cc net 0 0x00904caabbcc 0x03\n"
+	" NOTE: offset for netpattern frame starts from \"Dest EA\" of ethernet frame."
+	"So dest ea will be used only when offset is >= 6\n"
+	"     To send a eapol identity frame with L2 unicast - "
+	"wl wowl_pkt 102 00:90:4c:aa:bb:cc eapid id-string"},
+	{"wowl_ext_magic", wl_wowl_extended_magic, WLC_GET_VAR, WLC_SET_VAR,
+	"Set 6-byte extended magic pattern\n"
+	"Usage: wl wowl_ext_magic 0x112233445566"},
+	{ "wme_apsd_trigger", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set Periodic APSD Trigger Frame Timer timeout in ms (0=off)"},
+	{ "wme_autotrigger", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable sending of APSD Trigger frame when all ac are delivery enabled"},
+	{ "reassoc", wl_reassoc, -1, WLC_REASSOC,
+	"Initiate a (re)association request.\n"
+	"\tUsage: wl reassoc <bssid> [options]\n"
+	"\tOptions:\n"
+	"\t-c CL, --chanspecs=CL \tchanspecs (comma or space separated list)"},
+	{ "send_nulldata", wl_iov_mac, -1, -1,
+	"Sed a null frame to the specified hw address" },
+	{ "btc_params", wlu_reg2args, WLC_GET_VAR, WLC_SET_VAR, "g/set BT Coex parameters"},
+	{ "btc_flags", wlu_reg2args, WLC_GET_VAR, WLC_SET_VAR, "g/set BT Coex flags"},
+	{ "obss_scan_params", wl_obss_scan, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get Overlapping BSS scan parameters\n"
+	"Usage: wl obss_scan a b c d e ...; where\n"
+	"\ta-Passive Dwell, {5-1000TU}, default = 100\n"
+	"\tb-Active Dwell, {10-1000TU}, default = 20\n"
+	"\tc-Width Trigger Scan Interval, {10-900sec}, default = 300\n"
+	"\td-Passive Total per Channel, {200-10000TU}, default = 200\n"
+	"\te-Active Total per Channel, {20-1000TU}, default = 20\n"
+	"\tf-Channel Transition Delay Factor, {5-100}, default = 5\n"
+	"\tg-Activity Threshold, {0-100%}, default = 25"},
+	{"mkeep_alive", wl_mkeep_alive, WLC_GET_VAR, WLC_SET_VAR,
+	"Send specified \"mkeep-alive\" packet periodically.\n"
+	"\tUsage: wl mkeep_alive <index0-3> <period> <packet>\n"
+	"\t\tindex: 0 - 3.\n"
+	"\t\tperiod: Re-transmission period in milli-seconds. 0 to disable packet transmits.\n"
+	"\t\tpacket: Hex packet contents to transmit. The packet contents should include "
+	"the entire ethernet packet (ethernet header, IP header, UDP header, and UDP "
+	"payload) specified in network byte order. If no packet is specified, a nulldata frame "
+	"will be sent instead.\n"
+	"\n\te.g. Send keep alive packet every 30 seconds using id-1:\n"
+	"\twl mkeep_alive 1 30000 0x0014a54b164f000f66f45b7e08004500001e000040004011c"
+	"52a0a8830700a88302513c413c4000a00000a0d" },
+	{"keep_alive", wl_keep_alive, -1, -1,
+	"Send specified \"keep-alive\" packet periodically.\n"
+	"\tUsage: wl keep_alive <period> <packet>\n"
+	"\t\tperiod: Re-transmission period in milli-seconds. 0 to disable packet transmits.\n"
+	"\t\tpacket: Hex packet contents to transmit. The packet contents should include "
+	"the entire ethernet packet (ethernet header, IP header, UDP header, and UDP "
+	"payload) specified in network byte order.\n"
+	"\n\te.g. Send keep alive packet every 30 seconds:\n"
+	"\twl keep_alive 30000 0x0014a54b164f000f66f45b7e08004500001e000040004011c"
+	"52a0a8830700a88302513c413c4000a00000a0d" },
+	{ "srchmem", wl_srchmem, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set ucode srch engine memory"},
+	{ "pkt_filter_add", wl_pkt_filter_add, -1, -1,
+	"Install a packet filter.\n"
+	"\tUsage: wl pkt_filter_add <id> <polarity> <type> <offset> <bitmask> <pattern>\n"
+	"\tid:       Integer. User specified id.\n"
+	"\ttype:     0 (Pattern matching filter)\n"
+	"\t          5 (Pattern matching filter with timeout event)\n"
+	"\toffset:   (type 0): Integer offset in received packet to start matching.\n"
+	"\t          (type 5): Integer offset in received packet to start matching.\n"
+	"\tpolarity: Set to 1 to negate match result. 0 is default.\n"
+	"\tbitmask:  Hex bitmask that indicates which bits of 'pattern' to match.\n"
+	"\t          Must be same size as 'pattern'. Bit 0 of bitmask corresponds\n"
+	"\t          to bit 0 of pattern, etc.  If bit N of bitmask is 0, then do\n"
+	"\t          *not* match bit N of the pattern with the received payload. If\n"
+	"\t          bit N of bitmask is 1, then perform match.\n"
+	"\tpattern:  Hex pattern to match. Must be same size as <bitmask>.\n"
+	"\ttimeout:  (type 5): Number of seconds to wait before sending a timeout event when\n"
+	"\t                    a matching pattern packet is not received.\n"},
+	{ "pkt_filter_clear_stats", wl_varint, -1, WLC_SET_VAR,
+	"Clear packet filter statistic counter values.\n"
+	"\tUsage: wl pkt_filter_clear_stats <id>" },
+	{ "pkt_filter_enable", wl_pkt_filter_enable, -1, -1,
+	"Enable/disable a packet filter.\n"
+	"\tUsage: wl pkt_filter_enable <id> <0|1>"},
+	{ "pkt_filter_list", wl_pkt_filter_list, -1, -1,
+	"List installed packet filters.\n"
+	"\tUsage: wl pkt_filter_list [val]\n"
+	"\tval: 0 (disabled filters) 1 (enabled filters)"},
+	{ "pkt_filter_mode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set packet filter match action.\n"
+	"\tUsage: wl pkt_filter_mode <value>\n"
+	"\tvalue: 1 - Forward packet on match, discard on non-match (default).\n"
+	"\t       0 - Discard packet on match, forward on non-match." },
+	{ "pkt_filter_delete", wl_varint, -1, WLC_SET_VAR,
+	"Uninstall a packet filter.\n"
+	"\tUsage: wl pkt_filter_delete <id>"},
+	{ "pkt_filter_stats", wl_pkt_filter_stats, -1, -1,
+	"Retrieve packet filter statistic counter values.\n"
+	"\tUsage: wl pkt_filter_stats <id>"},
+
+#ifdef TRAFFIC_MGMT
+	{"trf_mgmt_config", wl_trf_mgmt_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Sets/gets traffic management configuration.\n"
+	"\tUsage: wl trf_mgmt_config [<enable> \n"
+	"\t                          [<host IP address> <host IP subnet mask> \n"
+	"\t                           <downlink kbps> <uplink kbps> [<flags>]]] \n"
+	"\tenable: 0 - Disable traffic management\n"
+	"\t        1 - Enables traffic management (host IP arguments required)\n"
+	"\tFlag values are the following:\n"
+	"\t0x0001 : Add DSCP values to tx packets\n"
+	"\t0x0002 : Disable traffic shaping...just do priority classification\n"
+	"\nIf no arguments are entered, the current traffic management configuration \n"
+	"is displayed.\n"
+	"\ne.g. Configure traffic management and specify local ip addr. and bandwidth data:\n"
+	"\nwl trf_mgmt_config 1 12.0.0.1 255.0.0.0 5000 650\n"},
+
+	{"trf_mgmt_filters_add", wl_trf_mgmt_filters_add, -1, WLC_SET_VAR,
+	"Adds a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_add [dst_port src_port prot priority]\n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\tpriority    : Priority value (see trf_mgmt_priority_values enum) \n"
+	"\ne.g. Add a tcp wildcard filter:\n"
+	"\nwl trf_mgmt_filters_add 80 0 6 2\n"},
+
+	{"trf_mgmt_filters_addex", wl_trf_mgmt_filters_addex, -1, WLC_SET_VAR,
+	"Adds a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_add flag [dst_port src_port prot priority]\n"
+	"\tUsage: wl trf_mgmt_filter_add flag [dst_mac priority] \n"
+	"\tFlag values are the following:\n"
+	"\t0x0000 : filter on tcp/udp src/dst port\n"
+	"\t0x0001 : filter on destination MAC address\n"
+	"\t0x0010 : do not update the packet priority \n"
+	"\t0x0020 : Tag packets as Favored\n"
+	"\tdst_mac    : Destination MAC address \n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\tpriority    : Priority value (see trf_mgmt_priority_values enum) \n"
+	"\ne.g. Add a tcp wildcard filter for all src/dst ports:\n"
+	"\nwl trf_mgmt_filters_addex 0 0 0 6 2\n"
+	"\ne.g. Add a dst mac address filter\n"
+	"\nwl trf_mgmt_filters_addex 0x31 aa:bb:cc:dd:ee:ff 2\n"},
+
+	{"trf_mgmt_filters_remove", wl_trf_mgmt_filters_remove, -1, WLC_SET_VAR,
+	"Removes a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_remove [dst_port src_port prot]\n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\ne.g. Remove a tcp wildcard filter:\n"
+	"\nwl trf_mgmt_filters_remove 80 0 6\n"},
+
+	{"trf_mgmt_filters_removeex", wl_trf_mgmt_filters_removeex, -1, WLC_SET_VAR,
+	"Removes a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_remove flag [dst_port src_port prot]\n"
+	"\tUsage: wl trf_mgmt_filter_remove flag [dst_mac]\n"
+	"\tFlag values are the following:\n"
+	"\t0x0000 : filter on tcp/udp src/dst port\n"
+	"\t0x0001 : filter on destination MAC address\n"
+	"\t0x0010 : do not update the packet priority \n"
+	"\t0x0020 : Tag packets as Favored\n"
+	"\tdst_mac    : Destination MAC address \n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\ne.g. Remove a tcp wildcard filter:\n"
+	"\nwl trf_mgmt_filters_removeex 0 80 0 6\n"
+	"\nwl trf_mgmt_filters_removeex 0x31 00:90:4c:52:a8:83\n"},
+
+	{"trf_mgmt_filters_list", wl_trf_mgmt_filters_list, WLC_GET_VAR, -1,
+	"Lists all traffic management filters.\n"
+	"\tUsage: wl trf_mgmt_filter_list\n"},
+
+	{"trf_mgmt_filters_clear", wl_trf_mgmt_filters_clear, -1, WLC_SET_VAR,
+	"Clears all traffic management filters.\n"
+	"\tUsage: wl trf_mgmt_filters_clear\n"},
+
+	{"trf_mgmt_bandwidth", wl_trf_mgmt_bandwidth, WLC_GET_VAR, WLC_SET_VAR,
+	"Sets/gets traffic management bandwidth configuration.\n"
+	"\tUsage: wl trf_mgmt_bandwidth \n"
+	"\t          [downlink uplink min_tx_bk min_tx_be min_tx_vi\n"
+	"\t                          [min_rx_b min_rx_be min_rx_vi]]\n"
+	"\tdownlink   : downlink bandwidth (kbps)\n"
+	"\tuplink     : uplink bandwidth (kbps)\n"
+	"\tmin_tx_bk  : min. guaranteed tx bandwidth percentage for BK (kbps)\n"
+	"\tmin_tx_be  : min. guaranteed tx bandwidth percentage for BE (kbps)\n"
+	"\tmin_tx_vi  : min. guaranteed tx bandwidth percentage for VI (kbps)\n"
+	"\n(min_tx_bo + min_tx_be + min_tx_vi) must equal 100.\n"
+	"\tmin_rx_bk  : min. guaranteed rx bandwidth percentage for BK (kbps)\n"
+	"\tmin_rx_be  : min. guaranteed rx bandwidth percentage for BE (kbps)\n"
+	"\tmin_rx_vi  : min. guaranteed rx bandwidth percentage for VI (kbps)\n"
+	"\n(min_rx_bk + min_rx_be + min_rx_vi) must equal 100."
+	"\nIf no rx gandwidth arguments are entered, tx bandwidth is used for rx."
+	"\nIf no arguments are entered, the current bandwidth configuration is displayed."},
+
+	{"trf_mgmt_flags", wl_trf_mgmt_flags, WLC_GET_VAR, WLC_SET_VAR,
+	"Sets/gets traffic management operational flags.\n"
+	"\tUsage: wl trf_mgmt_flags [flags]\n\n"
+	"\tFlag values are the following:\n"
+	"\t0x0001 : Add DSCP values to tx packets\n"
+	"\t0x0002 : Disable traffic shaping...just do priority classification\n"
+	"\nIf no arguments are entered, the current operational flags are displayed."},
+
+	{"trf_mgmt_stats", wl_trf_mgmt_stats, WLC_GET_VAR, -1,
+	"Gets traffic management statistics.\n"
+	"\tUsage: wl trf_mgmt_stats [index]\n"
+	"\tindex : Queue index \n"},
+
+	{"trf_mgmt_stats_clear", wl_trf_mgmt_stats_clear, -1, WLC_SET_VAR,
+	"Clears traffic management statistics.\n"
+	"\tUsage: wl trf_mgmt_stats_clear\n"},
+
+	{"trf_mgmt_shaping_info", wl_trf_mgmt_shaping_info, WLC_GET_VAR, -1,
+	"Gets traffic management shaping parameters.\n"
+	"\tUsage: wl trf_mgmt_shaping_info [index]\n"
+	"\tindex : Queue index \n"},
+#endif  /* TRAFFIC_MGMT */
+
+	{ "seq_start", wl_seq_start, -1, WLC_SET_VAR,
+	"Initiates command batching sequence. Subsequent IOCTLs will be queued until\n"
+	"seq_stop is received."},
+	{ "seq_stop", wl_seq_stop, -1, WLC_SET_VAR,
+	"Defines the end of command batching sequence. Queued IOCTLs will be executed."},
+	{ "seq_delay", wl_varint, -1, WLC_SET_VAR,
+	"Driver should spin for the indicated amount of time.\n"
+	"It is only valid within the context of batched commands."},
+	{ "seq_error_index", wl_varint, WLC_GET_VAR, -1,
+	"Used to retrieve the index (starting at 1) of the command that failed within a batch"},
+#ifdef CLMDOWNLOAD
+	{ "clmload", wl_clmload, -1, WLC_SET_VAR,
+	"Used to download CLM data onto the dongle"},
+#endif /* CLMDOWNLOAD */
+	{ "bmac_reboot", wl_var_void, -1, WLC_SET_VAR,
+	"Reboot BMAC"},
+#ifdef RWL_WIFI
+	{ "findserver", wl_wifiserver, -1, -1,
+	"Used to find the remote server with proper mac address given by the user,this "
+	"cmd is specific to wifi protocol."},
+#endif
+	{ "txmcsset", wl_txmcsset, WLC_GET_VAR, -1, "get Transmit MCS rateset for 11N device"},
+	{ "rxmcsset", wl_rxmcsset, WLC_GET_VAR, -1, "get Receive MCS rateset for 11N device"},
+	{ "mimo_ss_stf", wl_mimo_stf, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set SS STF mode.\n"
+	"\tUsage: wl mimo_ss_stf <value> <-b a | b>\n"
+	"\tvalue: 0 - SISO; 1 - CDD\n"
+	"\t-b(band): a - 5G; b - 2.4G"},
+#ifdef WLEXTLOG
+	{ "extlog", wl_extlog, WLC_GET_VAR, -1,
+	"get external logs\n"
+	"\tUsage: wl extlog <from_last> <number>\n"
+	"\tfrom_last: 1 - from the last log record; 0 - whole log recrods\n"
+	"\tnumber: number of log records to get, MAX is 32."},
+	{ "extlog_clr", wl_var_void, -1, WLC_SET_VAR, "clear external log records"},
+	{ "extlog_cfg", wl_extlog_cfg, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set external log configuration"},
+#endif
+	{ "assertlog", wl_assertlog, WLC_GET_VAR, -1,
+	"get external assert logs\n"
+	"\tUsage: wl assertlog"},
+	{ "assert_type", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the asset_bypass flag; usage: wl assert_type <1/0> (On/Off)"
+	},
+	{ "ledbh", wl_ledbh, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get led behavior\n"
+	"\tUsage: wl ledbh [0-3] [0-15]"},
+	{ "obss_coex_action", wl_obss_coex_action, -1, WLC_SET_VAR,
+	"send OBSS 20/40 Coexistence Mangement Action Frame\n"
+	"\tUsage: wl obss_coex_action -i <1/0> -w <1/0> -c <channel list>\n"
+	"\t -i: 40MHz intolerate bit; -w: 20MHz width Req bit;\n"
+	"\t -c: channel list, 1 - 14\n"
+	"\t At least one option must be provided"
+	},
+	{"chanim_state", wl_chanim_state, WLC_GET_VAR, -1,
+	"get channel interference state\n"
+	"\tUsage: wl chanim_state channel\n"
+	"\tValid channels: 1 - 14\n"
+	"\treturns: 0 - Acceptable; 1 - Severe"
+	},
+	{"chanim_mode", wl_chanim_mode, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set channel interference measure (chanim) mode\n"
+	"\tUsage: wl chanim_mode <value>\n"
+	"\tvalue: 0 - disabled; 1 - detection only; 2 - detection and avoidance"
+	},
+	{ "ledbh", wl_ledbh, WLC_GET_VAR, WLC_SET_VAR, "set/get led behavior\n"
+	"\tUsage: wl ledbh [0-3] [0-15]"},
+	{ "led_blink_sync", wl_led_blink_sync, WLC_GET_VAR, WLC_SET_VAR, "set/get led_blink_sync\n"
+	"\tUsage: wl led_blink_sync [0-3] [0/1]"},
+#ifdef BCMWAPI_WAI
+	{ "wai_restrict", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get WAI restriction"},
+	{ "wai_rekey", wl_iov_mac, -1, -1,
+	"set rekey event"},
+#endif /* BCMWAPI_WAI */
+
+	{"cca_get_stats", wl_cca_get_stats, WLC_GET_VAR, -1,
+	"Usage: wl cca_stats [-c channel] [-s num seconds][-n]\n"
+	"\t -c channel: Optional. specify channel. 0 = All channels. Default = current channel \n"
+	"\t -n: no analysis of results\n"
+	"\t -s num_seconds: Optional. Default = 10, Max = 60\n"
+	"\t -i: list individual measurements in addition to the averages\n"
+	"\t -curband: Only recommend channels on current band"
+	},
+	{ "itfr_get_stats", wl_itfr_get_stats, WLC_GET_VAR, -1,
+	"get interference source information"
+	},
+	{ "itfr_enab", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set STA interference detection mode(STA only)\n"
+	"\t 0  - disable\n"
+	"\t 1  - enable maual detection\n"
+	"\t 2  - enable auto detection"
+	},
+	{ "itfr_detect", wl_var_void, -1, WLC_SET_VAR,
+	"issue an interference detection request"
+	},
+	{ "smfstats", wl_smfstats, WLC_GET_VAR, WLC_SET_VAR,
+	"get/clear selected management frame (smf) stats"
+	"\twl smfstats [-C num]|[--cfg=num] [auth]|[assoc]|[reassoc]|[clear]\n"
+	"\tclear - to clear the stats" },
+#ifdef RWL_DONGLE
+	{ "dongleset", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable uart driver"
+	},
+#endif
+	{ "manfinfo", wl_var_getandprintstr, WLC_GET_VAR, -1,
+	"show chip package info in OTP"},
+	{ "rrm", wl_rrm, WLC_GET_VAR, WLC_SET_VAR,
+	"enable or disable RRM feature\n"
+	"\tUsage: wl rrm [0/1] to disable/enable RRM feature"},
+	{ "rrm_bcn_req", wl_rrm_bcn_req, -1, WLC_SET_VAR,
+	"send 11k beacon measurement request\n"
+	"\tUsage: wl rrm_bcn_req [bcn mode] [da] [duration] [random int] [channel] [ssid]"
+	" [repetitions]"},
+	{ "rrm_chload_req", wl_rrm_chload_req, -1, WLC_SET_VAR,
+	"send 11k channel load measurement request\n"
+	"\tUsage: wl rrm_chload_req [regulatory] [da] [duration] [random int] [channel]"
+	" [repetitions]"},
+	{ "rrm_noise_req", wl_rrm_noise_req, -1, WLC_SET_VAR,
+	"send 11k noise measurement request\n"
+	"\tUsage: wl rrm_noise_req [regulatory] [da] [duration] [random int] [channel]"
+	" [repetitions] "},
+	{ "rrm_frame_req", wl_rrm_frame_req, -1, WLC_SET_VAR,
+	"send 11k frame measurement request\n"
+	"\tUsage: wl rrm_frame_req [regulatory] [da] [duration] [random int] [channel] [ta]"
+	" [repetitions]"},
+	{ "rrm_stat_req", wl_rrm_stat_req, -1, WLC_SET_VAR,
+	"send 11k stat measurement request\n"
+	"\tUsage: wl rrm_stat_req [da] [random int] [duration] [peer] [group id] [repetitions]"},
+	{ "rrm_lm_req", wl_rrm_lm_req, -1, WLC_SET_VAR,
+	"send 11k link measurement request\n"
+	"\tUsage: wl rrm_lm_req [da]"},
+	{ "rrm_nbr_req", wl_rrm_nbr_req, -1, WLC_SET_VAR,
+	"send 11k neighbor report measurement request\n"
+	"\tUsage: wl rrm_nbr_req [ssid]"},
+	{ "rrm_nbr_list", wl_rrm_nbr_list, WLC_GET_VAR, -1,
+	"get 11k neighbor report list\n"
+	"\tUsage: wl rrm_nbr_list"},
+	{ "rrm_nbr_del_nbr", wl_rrm_nbr_del_nbr, -1, WLC_SET_VAR,
+	"delete node from 11k neighbor report list\n"
+	"\tUsage: wl rrm_nbr_del_nbr [bssid]"},
+	{ "rrm_nbr_add_nbr", wl_rrm_nbr_add_nbr, -1, WLC_SET_VAR,
+	"add node to 11k neighbor report list\n"
+	"\tUsage: wl rrm_nbr_add_nbr [bssid] [bssid info] [regulatory] [channel] [phytype]"},
+	{ "wnm", wl_wnm, WLC_GET_VAR, WLC_SET_VAR,
+	"set driver wnm feature mask\n"
+	"\ttype \'wl msglevel ?\' for values" },
+	{ "wnm_bsstq", wl_wnm_bsstq, -1, WLC_SET_VAR,
+	"send 11v BSS transition management query\n"
+	"\tUsage: wl wnm_bsstq [ssid]"},
+	{ "tclas_add", wl_tclas_add, -1, WLC_SET_VAR,
+	"add tclas frame classifier type entry\n"
+	"\tUsage: wl tclas_add <user priority> <type> <mask> <...>\n"
+	"\ttype 0 eth2:     <src mac> <dst mac> <ether type>\n"
+	"\ttype 1/4 ipv4:   <ver> <src> <dst> <s_port> <d_port> <dscp> <prot>\n"
+	"\ttype 2 802.1Q:   <vlan tag>\n"
+	"\ttype 3 filter:   <offset> <value> <mask>\n"
+	"\ttype 4 ipv6:     <ver> <src> <dst> <s_port> <d_port> <dscp> <nxt_hdr> <flw_lbl>\n"
+	"\ttype 5 802.1D/Q: <802.1Q PCP> <802.1Q CFI> <802.1Q VID>"
+	},
+	{ "tclas_del", wl_tclas_del, -1, WLC_SET_VAR,
+	"delete tclas frame classifier type entry\n"
+	"\tUsage: wl tclas_del [<idx> [<len>]]"
+	},
+	{ "tclas_list", wl_tclas_list, WLC_GET_VAR, -1,
+	"list the added tclas frame classifier type entry\n"
+	"\tUsage: wl tclas_list"
+	},
+#ifdef WLWNM
+	{ "wnm_tfsreq_add", wl_wnm_tfsreq_add, -1, WLC_SET_VAR,
+	"add one tfs request element and send tfs request frame\n"
+	"\tUsage: wl wnm_tfsreq_add <tfs_id> <tfs_action_code> <tfs_subelem_id> <send>\n"
+	"\ttfs_id: a non-zero value (1 ~ 255)\n"
+	"\ttfs_action_code bitfield: 1: delete after match, 2: notify\n"
+	"\ttfs_subelem_id: TFS subelement (0 for none or 1 for previous tclas_add)\n"
+	"\tsend: 0: store element, 1: send all stored elements"
+	},
+	{ "wnm_dms_set", wl_wnm_dms_set, -1, WLC_SET_VAR,
+	"Optionally add pending DMS desc (after tclas_add) and optionally register all desc\n"
+	"on AP side to enable the service (with send=1)"
+	"\tUsage: wl wnm_dms_set <send> [<user_id> [<tc_pro>]]\n"
+	"\t\tsend: 0: store descriptor, 1: send all stored descs/enable DMS on AP\n"
+	"\t\tuser_id: new ID to assign to the created desc (if TCLAS added)\n"
+	"\t\t         or existing ID to enable on AP (if no TCLAS added), 0 for all desc\n"
+	"\t\ttc_pro: TCLAS processing element (if several TCLAS added)"
+	},
+	{ "wnm_dms_status", wl_wnm_dms_status, WLC_GET_VAR, -1,
+	"list all DMS descriptors and provide their internal and AP status\n"
+	"\tUsage: wl wl_wnm_dms_status"
+	},
+	{ "wnm_dms_term", wl_wnm_dms_term, -1, WLC_SET_VAR,
+	"Disable registered DMS des on AP side and optionally discard them\n"
+	"\tUsage: wl wnm_dms_term <del> [<user_id>]\n"
+	"\t\tdel: Discard desc after disabling the service on AP side\n"
+	"\t\tuser_id: desc to disable/delete, 0 for all desc"
+	},
+	{ "wnm_service_term", wl_wnm_service_term, -1, WLC_SET_VAR,
+	"Disable service. Check specific wnm_XXX_term for more info\n"
+	"\tUsage: wl wnm_service_term <srv> <service realted params>\n"
+	"\t\tsrv: 1 for DMS, 2 for FMS, 3 for TFS"
+	},
+	{ "wnm_timbc_offset", wl_wnm_timbc_offset, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set TIM broadcast offset by -32768 period > offset(us) > 32768\n"
+	"CAUTION!! Due to resource limitation, one radio can have only one set of TIMBC offset\n"
+	"setting.  MBSS need to share the same setting\n"
+	"\tUsage: wl wnm_timbc_offset <offset> [<tsf_present> [<fix_interval> [<rate_ovreride>]]]\n"
+	"\t\toffset: in unit of us.  Transmit TIM frame in specific TBTT transmit time time\n"
+	"\t\ttsf_present: can be omitted.  If set to 1, timestamp field will present in TIM frame."
+	"If omitted, default setup to 1\n"
+	"\t\tfix_interval: can be omitted.  If set with non-zero value, override STA request "
+	"interval in TIM Broadcast request.  If omitted, default setup to 0\n"
+	"\t\trate_override: can be omitted.  In unit of 500k, max setup to 108.  If set, override"
+	"override high rate used to transmit TIM broadcast high rate frame"
+	},
+	{ "wnm_timbc_set", wl_wnm_timbc_set, -1, WLC_SET_VAR,
+	"Enable/disable TIM Broadcast. Station will send appropriate request if AP suport TIMBC\n"
+	"\tUsage: wl wnm_timbc_set <interval> [<flags> [<min_rate> [<max_rate>]]]\n"
+	"\t\tinterval: Beacon interval requested for TIM frames, 0 to disable TIM BC\n"
+	"\t\tflags: Bitfield with minimal requirements to keep the service enabled (check doc)\n"
+	"\t\tmin_rate: Minimal rate requirement, in Mbps, for TIM high or low rate frames\n"
+	"\t\tmax_rate: Maximal rate requirement"
+	},
+	{ "wnm_timbc_status", wl_wnm_timbc_status, WLC_GET_VAR, -1,
+	"Retrieve TIM Broadcast configuration set with current AP"
+	},
+	{ "wnm_maxidle", wl_wnm_maxidle, WLC_GET_VAR, WLC_SET_VAR,
+	"setup WNM BSS Max Idle Period interval and option\n"
+	"\tUsage: wl wnm_maxidle <Idle Period> <Option>\n"
+	"\tIdle Period: in unit of 1000TU(1.024s)\n"
+	"\tOption: protected keep alive required(0 ~ 1)"
+	},
+	{ "wnm_bsstrans_query", wl_wnm_bsstq, -1, WLC_SET_VAR,
+	"send 11v BSS transition management query\n"
+	"\tUsage: wl wnm_bsstrans_query [ssid]"},
+	{ "wnm_bsstrans_req", wl_wnm_bsstrans_req, -1, WLC_SET_VAR,
+	"send BSS transition management request frame with BSS termination included bit set\n"
+	"\tUsage: wl wnm_bsstrans_req <reqmode> <tbtt> <dur> [unicast]\n"
+	"\treqmode: request mode of BSS transition request\n"
+	"\ttbtt: time of BSS to end of life, in unit of TBTT, max to 65535\n"
+	"\tdur: time of BSS to keep off, in unit of minute, max to 65535\n"
+	"\tunicast: [1|0] unicast or broadcast to notify STA in BSS.  Default in unicast.\n"
+	},
+	{ "wnm_keepalives_max_idle", wl_wnm_keepalives_max_idle, -1, -1,
+	"\tUsage: wl wnm_keepalives_max_idle <keepalives_per_bss_max_idle> <mkeepalive_index>"
+	" [<max_interval>]\n"
+	"set/get the number of keepalives, mkeep-alive index and max_interval configured"
+	" per BSS-Idle period.\n"},
+#endif /* WLWNM */
+#ifdef WLP2P
+	{ "p2p_ssid", wl_ssid, -1, WLC_SET_VAR,
+	"set WiFi P2P wildcard ssid.\n"
+	"\tUsage: wl p2p_ssid <ssid>"
+	},
+	{ "p2p_state", wl_p2p_state, -1, WLC_SET_VAR,
+	"set WiFi P2P discovery state.\n"
+	"\tUsage: wl p2p_state <state> [<chanspec> <dwell time>]"
+	},
+	{ "p2p_scan", wl_p2p_scan, -1, WLC_SET_VAR,
+	"initiate WiFi P2P scan.\n"
+	"\tUsage: wl p2p_scan S|E <scan parms>\n"
+	SCAN_USAGE
+	},
+	{ "p2p_ifadd", wl_p2p_ifadd, -1, WLC_SET_VAR,
+	"add WiFi P2P interface\n"
+	"\tUsage: wl p2p_ifadd <MAC-address> go|client|dyngo [chanspec]\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_ifdel", wl_p2p_ifdel, -1, WLC_SET_VAR,
+	"delete WiFi P2P interface\n"
+	"\tUsage: wl p2p_ifdel <MAC-address>\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_ifupd", wl_p2p_ifupd, -1, WLC_SET_VAR,
+	"update an interface to WiFi P2P interface\n"
+	"\tUsage: wl p2p_ifupd <MAC-address> go|client\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_if", wl_p2p_if, WLC_GET_VAR, -1,
+	"query WiFi P2P interface bsscfg index\n"
+	"\tUsage: wl p2p_if <MAC-address>\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_noa", wl_p2p_noa, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get WiFi P2P NoA schedule\n"
+	"\tUsage: wl p2p_noa <type> <type-specific-params>\n"
+	"\t\ttype 0: Scheduled Absence (on GO): <type> <action> <action-specific-params>\n"
+	"\t\t\taction -1: Cancel the schedule: <type> <action>\n"
+	"\t\t\taction 0,1,2: <type> <action> <option> <option-specific-params>\n"
+	"\t\t\t\taction 0: Do nothing during absence periods\n"
+	"\t\t\t\taction 1: Sleep during absence periods\n"
+	"\t\t\t\toption 0: <start:tsf> <interval> <duration> <count> ...\n"
+	"\t\t\t\toption 1 [<start-percentage>] <duration-percentage>\n"
+	"\t\t\t\toption 2 <start:tsf-offset> <interval> <duration> <count>\n"
+	"\t\ttype 1: Requested Absence (on GO): \n"
+	"\t\t\taction -1: Cancel the schedule: <type> <action>\n"
+	"\t\t\taction 2: <type> <action> <option> <option-specific-params>\n"
+	"\t\t\t\taction 2: Turn off GO beacons and probe responses during absence period\n"
+	"\t\t\t\toption 2 <start:tsf-offset> <interval> <duration> <count>"
+	},
+	{ "p2p_ops", wl_p2p_ops, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get WiFi P2P OppPS and CTWindow\n"
+	"\tUsage: wl p2p_ops <ops> [<ctw>]\n"
+	"\t\t<ops>:\n"
+	"\t\t\t0: Disable OppPS\n"
+	"\t\t\t1: Enable OppPS\n"
+	"\t\t<ctw>:\n"
+	"\t\t\t10 and up to beacon interval"
+	},
+	{ "p2p_da_override", wl_iov_mac, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set WiFi P2P device interface addr\n"
+	"\tUsage: wl p2p_da_override <MAC-address>\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx\n"
+	"(When MAC-address is set to 00:00:00:00:00:00, default da restored)"
+	},
+#endif /* WLP2P */
+	{ "pm_dur", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Retrieve accumulated PM duration information (GET only)\n"
+	},
+	{ "mpc_dur", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Retrieve accumulated MPC duration information in ms (GET) or clear accumulator (SET)\n"
+	"\tUsage: wl mpc_dur <any-number-to-clear>"},
+	{"chanim_acs_record", wl_chanim_acs_record, WLC_GET_VAR, -1,
+	"get the auto channel scan record. \n"
+	"\t Usage: wl acs_record"
+	},
+	{"chanim_stats", wl_chanim_stats, WLC_GET_VAR, -1,
+	"get chanim stats \n"
+	"\t Usage: wl chanim_stats"
+	},
+	{"txdelay_params", wl_txdelay_params, WLC_GET_VAR, -1,
+	"get chanim stats \n"
+	"\t Usage: wl txdelay_params ratio cnt period tune"
+	},
+	{"intfer_params", wl_intfer_params, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get intfer params \n"
+	"\tUsage: wl intfer_params period (in sec) cnt(0~4) txfail_thresh tcptxfail_thresh\n"
+	"\tperiod=0: disable Driver monitor txfail"
+	},
+	{ "dngl_wd", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"enable or disable dongle keep alive watchdog timer\n"
+	"\tUsage: wl dngl_wd 0\\1 (to turn off\\on)"},
+	{ "tsf", wl_tsf, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get tsf register\n"
+	"\tUsage: wl tsf [<high> <low>]"},
+	{ "tpc_mode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable AP TPC.\n"
+	"Usage: wl tpc_mode <mode> \n"
+	"\t0 - disable, 1 - BSS power control, 2 - AP power control, 3 - Both (1) and (2)"},
+	{ "tpc_period", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set AP TPC periodicity in secs.\n"
+	"Usage: wl tpc_period <secs> "},
+	{ "tpc_lm", wl_tpc_lm, WLC_GET_VAR, -1,
+	"Get current link margins."},
+	{ "mfp_config", wl_mfp_config, -1, WLC_SET_VAR,
+	"Config PMF capability\n"
+	"\tusage: wl mfp 0/disable, 1/capable, 2/requred" },
+	{ "mfp_sha256", wl_mfp_sha256, WLC_GET_VAR, WLC_SET_VAR,
+	"Config SHA256 capability\n"
+	"\tusage: wl sha256 0/disable, 1/enable" },
+	{ "mfp_sa_query", wl_mfp_sa_query, -1, WLC_SET_VAR,
+	"Send a sa query req/resp to a peer\n"
+	"\tusage: wl mfp_sa_query flag action id" },
+	{ "mfp_disassoc", wl_mfp_disassoc, WLC_GET_VAR, WLC_SET_VAR,
+	"send bogus disassoc\n"
+	"\tUsage: wl mfp_disassoc"},
+	{ "mfp_deauth", wl_mfp_deauth, WLC_GET_VAR, WLC_SET_VAR,
+	"send bogus deauth\n"
+	"\tUsage: wl mfp_dedauth"},
+	{ "mfp_assoc", wl_mfp_assoc, WLC_GET_VAR, WLC_SET_VAR,
+	"send assoc\n"
+	"\tUsage: wl mfp_assoc"},
+	{ "mfp_auth", wl_mfp_auth, WLC_GET_VAR, WLC_SET_VAR,
+	"send auth\n"
+	"\tUsage: wl mfp_auth"},
+	{ "mfp_reassoc", wl_mfp_reassoc, WLC_GET_VAR, WLC_SET_VAR,
+	"send reassoc\n"
+	"\tUsage: wl mfp_reassoc"},
+	{ "monitor_lq", wl_monitor_lq, WLC_GET_VAR, WLC_SET_VAR,
+	"Start/Stop monitoring link quality metrics - RSSI and SNR\n"
+	"\tUsage: wl monitor_lq <0: turn off / 1: turn on"},
+	{ "monitor_lq_status", wl_dump_lq, WLC_GET_VAR, -1 /* Set not reqd */,
+	"Returns averaged link quality metrics - RSSI and SNR values"},
+	{ "mac_rate_histo", wl_mac_rate_histo, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: wl mac_rate_histo <mac address> <access category> <num_pkts>\n"
+	"\t(MAC address e.g. 00:11:20:11:33:33)\n"
+	"\t(Access Category(AC) - 0x10:for entire MAC or 0x4:for video AC for this MAC)\n"
+	"\t(num_pkts (optional) - Number of packets to average - max 64 for AC 0x10,"
+	" max 32 for AC 0x4)"
+	},
+	{ "rpmt", wl_rpmt, -1, WLC_SET_VAR, "rpmt <pm1-to> <pm0-to>"},
+#ifdef WLTDLS
+	{ "tdls_endpoint", wl_tdls_endpoint, WLC_GET_VAR, WLC_SET_VAR,
+	"Available TDLS operations to each TDLS peer.\n"
+	"\tusage: wl tdls_endpoint <disc, create, delete, PM, wake, cw> <ea> [chanspec]\n"
+	"\t       [chanspec] only applies to 'cw' operaton.\n\n"
+	"\t       addendum:\n"
+	"\t       wl tdls_endpoint wfd_disc <ea> sends a WFD tunneled Probe Request"},
+	{ "tdls_wfd_ie", wl_tdls_wfd_ie, WLC_GET_VAR, -1,
+	"To set, get and clear additional WFD IE in setup_req and setup_resp\n"
+	"\tTo set2, get2 and clear2 additional WFD IE in tunneled probe_req and probe_resp\n"
+	"\tusage: wl tdls_wfd_ie get  <own|peer_eth_addr#> [ip] [port]\n"
+	"\t       wl tdls_wfd_ie get2 <own|peer_eth_addr#> [alt_mac] [port] [PC_bit]\n"
+	"\t\t       peer_eth_addr#: HH:HH:HH:HH:HH:HH\n"
+	"\t\t       and peer must be TDLS connected (only in case of setup)\n\n"
+	"\t       wl tdls_wfd_ie <clr|clr2> own\n\n"
+	"\t       wl tdls_wfd_ie set  own wfd_ie_hexa_string [ip# [port# [type# [bssid#]]]]\n"
+	"\t       wl tdls_wfd_ie set2 own wfd_ie_hexa_string [alt_mac# [port# [type#]]]\n"
+	"\t\t       wfd_ie_hexa_string: should start with the full WFD IE header\n"
+	"\t\t                           e.g. 0xDDXX506F9A0A...\n"
+	"\t\t       ip#:      XXX.XXX.XXX.XXX\n"
+	"\t\t       alt_mac#: HH:HH:HH:HH:HH:HH\n"
+	"\t\t       port#:    0-65535\n"
+	"\t\t       type#:    0 for source, 1 for primary sink\n"
+	"\t\t       bssid#:   HH:HH:HH:HH:HH:HH"},
+#endif /* WLTDLS */
+	{ "spatial_policy", wl_spatial_policy, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get spatial_policy\n"
+	"\tUsage: wl spatial_policy <-1: auto / 0: turn off / 1: turn on>\n"
+	"\t       to control individual band/sub-band use\n"
+	"\t       wl spatial_policy a b c d e\n"
+	"\t       where a is 2.4G band setting\n"
+	"\t       where b is 5G lower band setting\n"
+	"\t       where c is 5G middle band setting\n"
+	"\t       where d is 5G high band setting\n"
+	"\t       where e is 5G upper band setting"},
+	{ "ie", wl_ie, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get IE\n"
+	"\tUsage: For set: wl ie type length hexdata\n"
+	"\t     For get: wl ie type" },
+	{ "wnm_url", wl_wnm_url, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get wnm session information url\n"
+	"Usage for set: wl wnm_url length urlstring\n"
+	"Usage for get: wl wnm_url" },
+	{ "ratetbl_ppr", wl_ratetbl_ppr, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: For get: wl ratetbl_ppr\n"
+	"\t     For set: wl ratetbl_ppr <rate> <ppr>" },
+	{ "wowl_wakeup_reason", wl_wowl_wake_reason, WLC_GET_VAR, -1 /* Set not reqd */,
+	"Returns pattern id and associated wakeup reason"},
+	{ "mempool", wlu_mempool, WLC_GET_VAR, -1,
+	"Get memory pool statistics" },
+#ifdef SR_DEBUG
+	{ "sr_dump_pmu", wl_dump_pmu, WLC_GET_VAR, WLC_SET_VAR,
+	"Dump value of PMU registers"},
+	{ "sr_pmu_keep_on", wl_pmu_keep_on, WLC_GET_VAR, WLC_SET_VAR,
+	"Keep resource on"},
+	{ "sr_skip", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Skip Save Restore Operation"},
+	{ "sr_power_island", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Keep power islands on/off"},
+#endif /* SR_DEBUG */
+#ifdef UC_FATAL
+	{ "uc_fatal", wl_varint, WLC_GET_VAR, -1,
+	"dump ucode info"},
+#endif /* UC_FATAL */
+#ifdef WLNDOE
+	{ "nd_hostip", wl_hostipv6, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a local host-ipv6 address or display them"},
+	{ "nd_solicitip", wl_solicitipv6, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a local host solicit ipv6 address or display them"},
+	{ "nd_remoteip", wl_remoteipv6, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a local remote ipv6 address or display them"},
+	{ "nd_status", wl_ndstatus, WLC_GET_VAR, -1,
+	"Displays Neighbor Discovery Status"},
+	{ "nd_hostip_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear all host-ip addresses"},
+	{ "nd_macaddr", wl_iov_mac, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/set the MAC address for offload" },
+	{ "nd_status_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear neighbor discovery status"},
+#endif
+	{ "antdiv_bcnloss", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"0	- Disable Rx antenna flip feature based on consecutive beacon loss\n"
+	"\tX - beacon loss count after which Rx ant will be flipped\n"
+	"\tUsage: wl antdiv_bcnloss <beaconloss_count>\n"
+	},
+	{ "lpc_params", wl_power_sel_params, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get Link Power Control params\n"
+	"\tUsage: wl powersel_params <tp_ratio_thresh> <rate_stab_thresh>\n"
+	"\t\t<pwr_stab_thresh> <pwr_sel_exp_time>\n"},
+	{ "mode_reqd", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get operational capabilities required for STA to associate to the BSS "
+	"supported by the interface.\n"
+	"\tUsage: wl [-i ifname] mode_reqd [value]\n"
+	"\t       wl mode_reqd [-C bss_idx ] [value]\n"
+	"\t\t     <ifname> is the name of the interface corresponding to the BSS.\n"
+	"\t\t\t   If the <ifname> is not given, the primary BSS is assumed.\n"
+	"\t\t     <bss_idx> is the the BSS configuration index.\n"
+	"\t\t\t   If the <bss_idx> is not given, configuraion #0 is assumed\n"
+	"\t\t     <value> is the numeric values in the range [0..3]\n"
+	"\t\t     0 - no requirements on joining devices.\n"
+	"\t\t     1 - devices must advertise ERP (11g) capabilities to be allowed to associate\n"
+	"\t\t\t   to a 2.4 GHz BSS.\n"
+	"\t\t     2 - devices must advertise HT (11n) capabilities to be allowed to associate\n"
+	"\t\t\t   to a BSS.\n"
+	"\t\t     3 - devices must advertise VHT (11ac) capabilities to be allowed to associate\n"
+	"\t\t\t   to a BSS.\n"
+	"\tThe command returns an error if the BSS interface is up.\n"
+	"\tThis configuration can only be changed while the BSS interface is down.\n"
+	"\tNote that support for HT implies support for ERP,\n"
+	"\tand support for VHT implies support for HT."},
+	{ "nar_clear_dump", wl_var_void, -1, WLC_SET_VAR,
+	"Clear non-aggregated regulation counters"},
+	{ "sar_limit", wl_sarlimit, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get sar_limit\n"
+	"\tusage: (set) sar_limit <2Gcore0 2Gcore1 2Gcore2 2Gcore3 5G[0]core0 5G[0]core1...>\n"
+	"\t       (get) sar_limit, return sar limit table\n"
+	"\tunit: all input/output values are absolute and in unit of qdbm\n"
+	},
+	{ "bmon_bssid", wl_bmon_bssid, WLC_GET_VAR, WLC_SET_VAR,
+	"Set monitored BSSID\n"
+	"\tusage: bmon_bssid xx:xx:xx:xx:xx:xx 0|1\n"},
+
+#ifdef EVENT_LOG_COMPILE
+	{ "event_log_set_init", wl_event_log_set_init, -1, WLC_SET_VAR,
+	"Initialize an event log set\n"
+	"\tUsage: wl event_log_set_init <set> <size>\n"},
+	{ "event_log_set_expand", wl_event_log_set_expand, -1, WLC_SET_VAR,
+	"Increase the size of an event log set\n"
+	"\tUsage: wl event_log_set_expand <set> <size>\n"},
+	{ "event_log_set_shrink", wl_event_log_set_shrink, -1, WLC_SET_VAR,
+	"Decrease the size of an event log set\n"
+	"\tUsage: wl event_log_set_expand <set>\n"},
+	{ "event_log_tag_control", wl_event_log_tag_control, -1, WLC_SET_VAR,
+	"Modify the state of an event log tag\n"
+	"\tUsage: wl event_log_tag_control <tag> <set> <flags>\n"},
+
+#endif /* EVENT_LOG_COMPILE */
+	{ "rmc_ackmac", wl_mcast_ackmac, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get ACK required multicast mac address\n"
+	"\tusage: wl rmc_ackmac -i [index] -t [multicast mac address]\n"
+	},
+	{ "rmc_ackreq", wl_mcast_ackreq, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get ACK rmc_mode 0 disable, 1 enable transmitter, 2 enable initiator \n"
+	"\tusage: wl rmc_ackreq [mode] \n"
+	},
+	{ "rmc_txrate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get a fixed transmit rate for the reliable multicast:\n"
+	"\tvalid values for 802.11ac are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate\n"
+	},
+	{ "rmc_status", wl_mcast_status, WLC_GET_VAR, -1,
+	"Display reliable multicast client status\n"
+	},
+	{ "rmc_actf_time", wl_mcast_actf_time, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get mcast action frame tx time period in ms\n"
+	"\tusage: wl rmc_actf_time [value] \n"
+	},
+	{ "rmc_ar_timeout", wl_mcast_ar_timeout, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get rmc active receiver timeout in ms\n"
+	"\tusage: wl rmc_ar_timeout [duration in ms] \n"
+	},
+	{ "rmc_rssi_thresh", wl_mcast_rssi_thresh, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get minimum rssi needed for a station to be an active receiver\n"
+	"\tusage: wl rmc_rssi_thresh [value] \n"
+	},
+	{ "rmc_stats", wl_mcast_stats, WLC_GET_VAR, WLC_SET_VAR,
+	"Display/Clear reliable multicast client statistical counters\n"
+	"\tusage: wl rmc_stats [arg] \n"
+	},
+	{ "rmc_rssi_delta", wl_mcast_rssi_delta, WLC_GET_VAR, WLC_SET_VAR,
+	"Display/Set RSSI delta to switch receive leader\n"
+	"\tusage: wl rmc_rssi_delta [arg] \n"
+	},
+	{ "rmc_vsie", wl_mcast_vsie, WLC_GET_VAR, WLC_SET_VAR,
+	"Display/Set vendor specific IE contents\n"
+	"\tusage: wl rmc_vsie [OUI] [Data] \n"
+	},
+	{ "pm2_sleep_ret_ext", wl_sleep_ret_ext, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set Dynamic Fast Return To Sleep params"},
+	{ "sta_monitor", wl_stamon_sta_config, WLC_GET_VAR, WLC_SET_VAR,
+	"wl sta_monitor [<add/del> <xx:xx:xx:xx:xx:xx>]"},
+	{ "monitor_promisc_level", wl_monitor_promisc_level, WLC_GET_VAR, WLC_SET_VAR,
+	"Set a bitmap of different MAC promiscuous level of monitor mode.\n\n"
+	MONITOR_PROMISC_LEVEL_USAGE},
+#if defined(DWDS)
+	{ "dwds_config", wl_dwds_config, -1, WLC_SET_VAR,
+	"wl dwds_config <enable/disable> <sta/ap> <xx:xx:xx:xx:xx:xx>"},
+#endif
+	{ "aibss_bcn_force_config", wl_aibss_bcn_force_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set AIBSS beacon force configuration \n"
+	"wl aibss_bcn_force_config <initial_min_bcn_dur,min_bcn_dur,initial_bcn_flood_dur>\n"},
+	{"bcnlenhist", wl_bcnlenhist, WLC_GET_VAR, -1,
+	"Usage: wl bcnlenhist [0]"},
+	{ "wds_type", wl_varint, WLC_GET_VAR, -1,
+	"Indicate whether the interface to which this IOVAR is sent is of WDS or DWDS type.\n\n"
+	WDS_TYPE_USAGE},
+	{ "bss_peer_info", wl_bss_peer_info, WLC_GET_VAR, -1,
+	"Get BSS peer info of all the peer's in the indivudual interface\n"
+	"\tIf a non-zero MAC address is specified, gets the peer info of the PEER alone\n"
+	"\tUsage: wl bss_peer_info [MAC address]"},
+	{ "bssload_static", wl_bssload_static, WLC_GET_VAR, WLC_SET_VAR,
+	"get or set static BSS load\n"
+	"\tusage: wl bssload_static [off | <sta_count> <chan_util> <acc>]\n"},
+	{ "aibss_txfail_config", wl_aibss_txfail_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get txfail configuration for bcn_timeout and max tx retries\n"
+	"\tUsage: wl aibss_txfail_config [bcn_timeout, max_retry]"},
+#ifdef TBTT_OFFSET_STAT
+	{ "tbtt_offset_stat", wl_tbtt_offset_stat, WLC_GET_VAR, -1,
+	"Get TBTT offset stat (only for STA mode)\n"
+	"\tUsage: wl tbtt_offset_stat\n"},
+#endif /* TBTT_OFFSET_STAT */
+#endif
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+cmd_t wl_varcmd = {"var", wl_varint, -1, -1, "unrecognized name, type -h for help"};
+
+#ifdef WC_TOOL
+/* Include any commands for wc tool used for WMM
+ * These need to be only the command names from port_cmds and wl_cmds array
+ */
+static const char *wc_cmds[] = {
+	"ver", "cmds", "up", "down",
+	"gmode", "listen", "wme", "wme_ac", "wme_apsd",
+	"wme_apsd_sta", "wme_dp"
+};
+#else
+static const char **wc_cmds = NULL;
+#endif /* WC_TOOL */
+
+/* initialize stuff needed before processing the command */
+void
+wl_cmd_init(void)
+{
+	int_fmt = INT_FMT_DEC;
+	g_wlc_idx = -1;
+}
+
+
+void
+wlu_init(void)
+{
+	/* Init global variables at run-time, not as part of the declaration.
+	 * This is required to support init/de-init of the driver. Initialization
+	 * of globals as part of the declaration results in non-deterministic
+	 * behaviour since the value of the globals may be different on the
+	 * first time that the driver is initialized vs subsequent initializations.
+	 */
+	int_fmt = INT_FMT_DEC;
+	g_wlc_idx = -1;
+	batch_in_client = FALSE;
+	init_cmd_batchingmode();
+}
+
+int
+wl_check(void *wl)
+{
+	int ret;
+	int val;
+
+	if ((ret = wlu_get(wl, WLC_GET_MAGIC, &val, sizeof(int))) < 0)
+		return ret;
+
+	/* Detect if IOCTL swapping is necessary */
+	if (val == (int)bcmswap32(WLC_IOCTL_MAGIC))
+	{
+		val = bcmswap32(val);
+		g_swap = TRUE;
+	}
+	if (val != WLC_IOCTL_MAGIC)
+		return -1;
+	if ((ret = wlu_get(wl, WLC_GET_VERSION, &val, sizeof(int))) < 0)
+		return ret;
+	ioctl_version = dtoh32(val);
+	if (ioctl_version != WLC_IOCTL_VERSION &&
+	    ioctl_version != 1) {
+		fprintf(stderr, "Version mismatch, please upgrade. Got %d, expected %d or 1\n",
+		        ioctl_version, WLC_IOCTL_VERSION);
+		return -1;
+	}
+	return 0;
+}
+
+static int
+ARGCNT(char **argv)
+{
+	int i;
+
+	for (i = 0; argv[i] != NULL; i ++)
+		;
+	return i;
+}
+
+/* parse/validate the command line arguments */
+/*
+ * pargv is updated upon return if the first argument is an option.
+ * It remains intact otherwise.
+ */
+int
+wl_option(char ***pargv, char **pifname, int *phelp)
+{
+	char *ifname = NULL;
+	int help = FALSE;
+	int status = CMD_OPT;
+	char **argv = *pargv;
+
+	while (*argv) {
+		/* select different adapter */
+		if (!strcmp(*argv, "-a") || !strcmp(*argv, "-i")) {
+			char *opt = *argv++;
+			ifname = *argv;
+			if (!ifname) {
+				fprintf(stderr,
+					"error: expected interface name after option %s\n", opt);
+				status = CMD_ERR;
+				break;
+			}
+		}
+
+		/* integer output format */
+		else if (!strcmp(*argv, "-d"))
+			int_fmt = INT_FMT_DEC;
+		else if (!strcmp(*argv, "-u"))
+			int_fmt = INT_FMT_UINT;
+		else if (!strcmp(*argv, "-x"))
+			int_fmt = INT_FMT_HEX;
+
+		/* command usage */
+		else if (!strcmp(*argv, "-h") || !strcmp(*argv, "--help"))
+			help = TRUE;
+
+		else if (!strcmp(*argv, "--clientbatch")) {
+			wl_seq_batch_in_client(TRUE);
+		}
+		/* To handle endian mis-matches between wl utility and wl driver */
+		else if (!strcmp(*argv, "--es")) {
+			g_swap = TRUE;
+		}
+		else if (!stricmp(*argv, "-W") || !strcmp(*argv, "--wlc")) {
+			char *opt = *argv++;
+			char *endptr = NULL;
+			if (*argv) {
+				g_wlc_idx = strtol(*argv, &endptr, 0);
+			}
+			if (endptr == *argv) {
+				fprintf(stderr,
+					"error: expected wlc integer index after option %s\n", opt);
+				status = CMD_ERR;
+				/* just to ensure that we trigger error */
+				argv--;
+				break;
+			}
+		}
+		/* start of non wl options */
+		else {
+			status = CMD_WL;
+			break;
+		}
+
+		/* consume the argument */
+		argv ++;
+		break;
+	}
+
+	*phelp = help;
+	*pifname = ifname;
+	*pargv = argv;
+
+	return status;
+}
+
+void
+wl_cmd_usage(FILE *fid, cmd_t *cmd)
+{
+	if (strlen(cmd->name) >= 8)
+		fprintf(fid, "%s\n\t%s\n\n", cmd->name, cmd->help);
+	else
+		fprintf(fid, "%s\t%s\n\n", cmd->name, cmd->help);
+}
+
+static int
+wl_print_deprecate(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(argv);
+
+	wl_cmd_usage(stderr, cmd); /* warning string is in command table */
+	return 0;
+}
+
+/* Dump out short list of commands */
+static int
+wl_list(void *wl, cmd_t *garb, char **argv)
+{
+	cmd_t *cmd;
+	int nrows, i, len;
+	char *list_buf;
+	int letter, col, row, pad;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(garb);
+	UNUSED_PARAMETER(argv);
+
+	for (cmd = wl_cmds, nrows = 0; cmd->name; cmd++)
+		/* Check for wc_cmd */
+		if (wc_cmd_check(cmd->name))
+		    nrows++;
+
+	nrows /= 4;
+	nrows++;
+
+	len = nrows * 80 + 2;
+	list_buf = malloc(len);
+	if (list_buf == NULL) {
+		fprintf(stderr, "Failed to allocate buffer of %d bytes\n", len);
+		return BCME_NOMEM;
+	}
+	for (i = 0; i < len; i++)
+		*(list_buf+i) = 0;
+
+	row = col = 0;
+	for (letter = 'a'; letter < 'z'; letter++) {
+		for (cmd = wl_cmds; cmd->name; cmd++) {
+			/* Check for wc_cmd */
+			if (!wc_cmd_check(cmd->name))
+				continue;
+			if (cmd->name[0] == letter || cmd->name[0] == letter - 0x20) {
+				strcat(list_buf+row*80, cmd->name);
+				pad = 18 * (col + 1) - strlen(list_buf+row*80);
+				if (pad < 1)
+					pad = 1;
+				for (; pad; pad--)
+					strcat(list_buf+row*80, " ");
+				row++;
+				if (row == nrows) {
+					col++; row = 0;
+				}
+			}
+		}
+	}
+	for (row = 0; row < nrows; row++)
+		printf("%s\n", list_buf+row*80);
+
+	printf("\n");
+
+	free(list_buf);
+	return (0);
+}
+
+void
+wl_cmds_usage(FILE *fid, cmd_t *port_cmds)
+{
+	cmd_t *port_cmd;
+	cmd_t *cmd;
+
+	/* print usage of port commands */
+	for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
+		/* Check for wc_cmd */
+		if (wc_cmd_check(port_cmd->name))
+			wl_cmd_usage(fid, port_cmd);
+
+	/* print usage of common commands without port counterparts */
+	for (cmd = wl_cmds; cmd->name; cmd++) {
+		/* search if port counterpart exists */
+		for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
+			if (!strcmp(port_cmd->name, cmd->name))
+				break;
+		/* Also, check for this being a wc_cmd */
+		if ((!port_cmd || !port_cmd->name) && (wc_cmd_check(cmd->name)))
+			wl_cmd_usage(fid, cmd);
+	}
+}
+
+void
+wl_usage(FILE *fid, cmd_t *port_cmds)
+{
+	fprintf(fid, "Usage: %s [-a|i <adapter>]"
+		" [-h] [-d|u|x] [-w|--wlc <index>] <command> [arguments]\n", wlu_av0);
+
+	fprintf(fid, "\n");
+	fprintf(fid, "  -h        this message and command descriptions\n");
+	fprintf(fid, "  -h [cmd]  command description for cmd\n");
+	fprintf(fid, "  -a, -i    adapter name or number\n");
+	fprintf(fid, "  -d        output format signed integer\n");
+	fprintf(fid, "  -u        output format unsigned integer\n");
+	fprintf(fid, "  -x        output format hexdecimal\n");
+	fprintf(fid, "  -w <idx>  index of WLC for RSDB only\n");
+	fprintf(fid, "\n");
+
+	wl_cmds_usage(fid, port_cmds);
+}
+
+void
+wl_printint(int val)
+{
+	switch (int_fmt) {
+	case INT_FMT_UINT:
+		printf("%u\n", val);
+		break;
+	case INT_FMT_HEX:
+		printf("0x%x\n", val);
+		break;
+	case INT_FMT_DEC:
+	default:
+		printf("%d\n", val);
+		break;
+	}
+}
+
+
+/* Common routine to check for an option arg specifying the configuration index.
+ * Takes the syntax -C num, --cfg=num, --config=num, or --configuration=num
+ * Returns BCME_BADARG if there is a command line parsing error.
+ * Returns 0 if no error, and sets *consumed to the number of argv strings
+ * used. Sets *bsscfg_idx to the index to use. Will set *bsscfg_idx to zero if there
+ * was no config arg.
+ */
+static int
+wl_cfg_option(char **argv, const char *fn_name, int *bsscfg_idx, int *consumed)
+{
+	miniopt_t mo;
+	int opt_err;
+
+	*bsscfg_idx = 0;
+	*consumed = 0;
+
+	miniopt_init(&mo, fn_name, NULL, FALSE);
+
+	/* process the first option */
+	opt_err = miniopt(&mo, argv);
+
+	/* check for no args or end of options */
+	if (opt_err == -1)
+		return 0;
+
+	/* check for no options, just a positional arg encountered */
+	if (mo.positional)
+		return 0;
+
+	/* check for error parsing options */
+	if (opt_err == 1)
+		return BCME_USAGE_ERROR;
+
+	/* check for -C, --cfg=X, --config=X, --configuration=X */
+	if (mo.opt == 'C' ||
+	    !strcmp(mo.key, "cfg") ||
+	    !strcmp(mo.key, "config") ||
+	    !strcmp(mo.key, "configuration")) {
+		if (!mo.good_int) {
+			fprintf(stderr,
+			"%s: could not parse \"%s\" as an integer for the configuartion index\n",
+			fn_name, mo.valstr);
+			return BCME_BADARG;
+		}
+		*bsscfg_idx = mo.val;
+		*consumed = mo.consumed;
+	}
+
+	return 0;
+}
+
+static int
+wl_void(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(argv);
+
+	if (cmd->set < 0)
+		return -1;
+	return wlu_set(wl, cmd->set, NULL, 0);
+}
+
+int
+wl_int(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr = NULL;
+
+	if (!*++argv) {
+		if (cmd->get == -1)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+			return ret;
+
+		val = dtoh32(val);
+		wl_printint(val);
+	} else {
+		if (cmd->set == -1)
+			return -1;
+		if (!stricmp(*argv, "on"))
+			val = 1;
+		else if (!stricmp(*argv, "off"))
+			val = 0;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		val = htod32(val);
+		ret = wlu_set(wl, cmd->set, &val, sizeof(int));
+	}
+
+	return ret;
+}
+
+/* Return a new chanspec given a legacy chanspec
+ * Returns INVCHANSPEC on error
+ */
+static chanspec_t
+wl_chspec_from_legacy(chanspec_t legacy_chspec)
+{
+	chanspec_t chspec;
+
+	/* get the channel number */
+	chspec = LCHSPEC_CHANNEL(legacy_chspec);
+
+	/* convert the band */
+	if (LCHSPEC_IS2G(legacy_chspec)) {
+		chspec |= WL_CHANSPEC_BAND_2G;
+	} else {
+		chspec |= WL_CHANSPEC_BAND_5G;
+	}
+
+	/* convert the bw and sideband */
+	if (LCHSPEC_IS20(legacy_chspec)) {
+		chspec |= WL_CHANSPEC_BW_20;
+	} else {
+		chspec |= WL_CHANSPEC_BW_40;
+		if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
+			chspec |= WL_CHANSPEC_CTL_SB_L;
+		} else {
+			chspec |= WL_CHANSPEC_CTL_SB_U;
+		}
+	}
+
+	if (wf_chspec_malformed(chspec)) {
+		fprintf(stderr, "wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
+		        chspec);
+		return INVCHANSPEC;
+	}
+
+	return chspec;
+}
+
+/* Return a legacy chanspec given a new chanspec
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_chspec_to_legacy(chanspec_t chspec)
+{
+	chanspec_t lchspec;
+
+	if (wf_chspec_malformed(chspec)) {
+		fprintf(stderr, "wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
+		        chspec);
+		return INVCHANSPEC;
+	}
+
+	/* get the channel number */
+	lchspec = CHSPEC_CHANNEL(chspec);
+
+	/* convert the band */
+	if (CHSPEC_IS2G(chspec)) {
+		lchspec |= WL_LCHANSPEC_BAND_2G;
+	} else {
+		lchspec |= WL_LCHANSPEC_BAND_5G;
+	}
+
+	/* convert the bw and sideband */
+	if (CHSPEC_IS20(chspec)) {
+		lchspec |= WL_LCHANSPEC_BW_20;
+		lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
+	} else if (CHSPEC_IS40(chspec)) {
+		lchspec |= WL_LCHANSPEC_BW_40;
+		if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
+			lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
+		} else {
+			lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
+		}
+	} else {
+		/* cannot express the bandwidth */
+		char chanbuf[CHANSPEC_STR_LEN];
+		fprintf(stderr,
+		        "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
+		        "to pre-11ac format\n",
+		        wf_chspec_ntoa(chspec, chanbuf), chspec);
+		return INVCHANSPEC;
+	}
+
+	return lchspec;
+}
+
+/* given a chanspec value, do the endian and chanspec version conversion to
+ * a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+static chanspec_t
+wl_chspec_to_driver(chanspec_t chanspec)
+{
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_to_legacy(chanspec);
+		if (chanspec == INVCHANSPEC) {
+			return chanspec;
+		}
+	}
+	chanspec = htodchanspec(chanspec);
+
+	return chanspec;
+}
+
+/* given a chanspec value, do the endian and chanspec version conversion to
+ * a chanspec_t value in a 32 bit integer
+ * Returns INVCHANSPEC on error
+ */
+static uint32
+wl_chspec32_to_driver(chanspec_t chanspec)
+{
+	uint32 val;
+
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_to_legacy(chanspec);
+		if (chanspec == INVCHANSPEC) {
+			return chanspec;
+		}
+	}
+	val = htod32((uint32)chanspec);
+
+	return val;
+}
+
+/* given a chanspec value from the driver, do the endian and chanspec version conversion to
+ * a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+static chanspec_t
+wl_chspec_from_driver(chanspec_t chanspec)
+{
+	chanspec = dtohchanspec(chanspec);
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_from_legacy(chanspec);
+	}
+
+	return chanspec;
+}
+
+/* given a chanspec value from the driver in a 32 bit integer, do the endian and
+ * chanspec version conversion to a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+static chanspec_t
+wl_chspec32_from_driver(uint32 chanspec32)
+{
+	chanspec_t chanspec;
+
+	chanspec = (chanspec_t)dtoh32(chanspec32);
+
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_from_legacy(chanspec);
+	}
+
+	return chanspec;
+}
+
+
+#ifdef CLMDOWNLOAD
+/*
+Generic interface for downloading required data onto the dongle
+*/
+int
+download2dongle(void *wl, uint16 dload_type, unsigned char *dload_buf, int len)
+{
+	struct wl_dload_data *dload_ptr = (struct wl_dload_data *)dload_buf;
+	int err = 0;
+	int dload_data_offset;
+
+	dload_data_offset = OFFSETOF(wl_dload_data_t, data);
+	dload_ptr->flag = (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT);
+	dload_ptr->dload_type = dload_type;
+	dload_ptr->len = htod32(len - dload_data_offset);
+
+	dload_ptr->crc = 0;
+
+	len = len + 8 - (len%8);
+
+	err = wlu_iovar_setbuf(wl, "generic_dload",
+		dload_buf, len, buf, WLC_IOCTL_MEDLEN);
+	return err;
+}
+
+int
+dload_clm(void *wl, uint32 datalen, unsigned char *org_buf, int ds_id)
+{
+	int num_chunks, chunk_len, cumulative_len = 0;
+	int size2alloc;
+	unsigned char *new_buf;
+	wl_clm_dload_info_t *clm_info_ptr;
+	int err = 0, clm_info_offset, chunk_offset;
+
+	clm_info_offset = OFFSETOF(wl_dload_data_t, data);
+	chunk_offset = OFFSETOF(wl_clm_dload_info_t, data_chunk);
+
+	num_chunks = datalen/MAX_CHUNK_LEN;
+	if (datalen % MAX_CHUNK_LEN != 0)
+		num_chunks++;
+	size2alloc = clm_info_offset + chunk_offset + MAX_CHUNK_LEN;
+
+	if ((new_buf = (unsigned char *)malloc(size2alloc)) != NULL) {
+		memset(new_buf, 0, size2alloc);
+		clm_info_ptr = (wl_clm_dload_info_t*)((uint8 *)new_buf + clm_info_offset);
+		clm_info_ptr->num_chunks = num_chunks;
+		clm_info_ptr->clm_total_len = datalen;
+		clm_info_ptr->ds_id = ds_id;
+		do {
+			if (datalen >= MAX_CHUNK_LEN)
+				chunk_len = MAX_CHUNK_LEN;
+			else
+				chunk_len = datalen;
+			memset(new_buf + clm_info_offset + chunk_offset, 0,
+				size2alloc - clm_info_offset - chunk_offset);
+			clm_info_ptr->chunk_len = htod32(chunk_len);
+
+			memcpy(&clm_info_ptr->data_chunk[0], org_buf + cumulative_len, chunk_len);
+			clm_info_ptr->chunk_offset = cumulative_len;
+			cumulative_len += chunk_len;
+
+			err = download2dongle(wl, DL_TYPE_CLM, new_buf,
+				chunk_len + clm_info_offset + chunk_offset);
+
+			datalen = datalen - chunk_len;
+		} while ((datalen > 0) && (err == 0));
+		free(new_buf);
+	} else {
+		err = BCME_NOMEM;
+	}
+
+	return err;
+}
+
+#define CLM_INPUT_FILE_MIN_LEN 32
+int
+process_clm_data(void *wl, char *clmfn, int ds_id)
+{
+	int ret = 0;
+
+	FILE *fp = NULL;
+
+	unsigned int clm_filelen;
+	struct stat filest;
+	unsigned long status = 0;
+	unsigned char *new_buf = NULL;
+	uint32 clm_data_len;
+	unsigned char *new_ptr;
+	int ifd;
+	const char trx_magic_string[] = {'H', 'D', 'R', '0'};
+	const char clm_magic_string[] = {'C', 'L', 'M', ' ', 'D', 'A', 'T', 'A'};
+
+	if (clmfn == NULL) {
+		printf("Reverting any previous %s CLM download\n",
+			ds_id ? "incremental":"base");
+		/* Performing a zero length CLM download reverts the previous download
+		 * of that type.
+		 */
+		clm_data_len = 0;
+	        new_ptr = NULL;
+		goto do_clm_load;
+	}
+
+	/* Open the clm download file */
+	if (!(fp = fopen(clmfn, "rb"))) {
+		fprintf(stderr, "unable to open input file %s\n", clmfn);
+		ret = BCME_BADARG;
+		goto error;
+	}
+
+	ifd = fileno(fp);
+
+	if (fstat(ifd, &filest)) {
+		fprintf(stderr, "fstat on input file %s return error %s\n", clmfn, strerror(errno));
+		ret = BCME_ERROR;
+		goto error;
+	}
+
+	clm_filelen = filest.st_size;
+
+	if (clm_filelen == 0) {
+		fprintf(stderr, "input file %s is empty (i.e. zero length)\n", clmfn);
+		ret = BCME_ERROR;
+		goto error;
+	}
+
+	if ((new_buf = malloc(clm_filelen)) == NULL) {
+		fprintf(stderr, "unable to allocate %u bytes based on input file size!\n",
+			clm_filelen);
+		ret = BCME_NOMEM;
+		goto error;
+	}
+
+	/* We can read the pure CLM binary file or a trx format wrapped CLM binary.
+	 * The CLM download iovar receives the CLM binary file content so any difference
+	 * in processing is limited to our local processing.
+	 *
+	 * The trx wrapped CLM binary was the original approach but it now being phased
+	 * out for the simpler, non-wrapped binary.  To maintain backward compatibility
+	 * for some period of time, wlu is accepting both formats transparently to the
+	 * user.  The two file types are identified by the magic word(s) at the beginning
+	 * of each.  A trx file starts with "HDR0" and a CLM binary starts with "CLM DATA".
+	 */
+
+	status = fread(new_buf, 1, clm_filelen, fp);
+
+	/* Basic sanity check on size. Make sure there is enough for any magic string plus
+	 * a little more for good measure.
+	 */
+	if (status < CLM_INPUT_FILE_MIN_LEN) {
+		fprintf(stderr, "size of input file %s is less than %d bytes."
+			"  This can't be a CLM file!\n", clmfn, CLM_INPUT_FILE_MIN_LEN);
+		ret = BCME_ERROR;
+		goto error;
+	} else if (status != clm_filelen) {
+		fprintf(stderr, "read of input file %s wasn't good based on fstat size %u\n",
+			clmfn, clm_filelen);
+		ret = BCME_ERROR;
+		goto error;
+	}
+
+	/* trx wrapped CLM binary file? Look for the 'HDR0' magic string */
+	if (memcmp(new_buf, trx_magic_string, sizeof(trx_magic_string)) == 0)
+	{
+		struct trx_header *trx;
+
+		/* Extract trx header */
+		trx = (struct trx_header *)new_buf;
+
+		/* The clm binary data follows the trx header and the length is the trx
+		 * header's first offset field.  All other trx header files are unused.
+		 * Note length in the offset doesn't include the trx header or any
+		 * trailing/padding zeroes add by the trx format.
+		 */
+		clm_data_len = trx->offsets[0];
+
+		/* A sanity testing on length value in the trx offset field.  It can't
+		 * indicate the following CLM data is bigger than the actual file.
+		 */
+		if (clm_data_len + sizeof(struct trx_header) > clm_filelen) {
+			fprintf(stderr,
+				"input file %s trx offset[0] is inconsistent"
+				" for being a CLM file\n",
+				clmfn);
+			ret = -1;
+			goto error;
+		}
+		new_ptr = new_buf + sizeof(struct trx_header);
+	} else if (memcmp(new_buf, clm_magic_string, sizeof(clm_magic_string)) == 0) {
+		/* pure CLM binary file?  CLM binary files start with 'CLM DATA' */
+		clm_data_len = clm_filelen;
+		new_ptr = new_buf;
+	} else {
+		fprintf(stderr, "input file is missing trx or CLM binary magic string\n");
+		ret = -1;
+		goto error;
+	}
+
+	printf("Downloading file %s as a %s CLM\n", clmfn, ds_id ? "incremental":"base");
+
+do_clm_load:
+	ret = dload_clm(wl, clm_data_len, new_ptr, ds_id);
+
+error:
+	if (new_buf)
+		free(new_buf);
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+static int
+wl_clmload(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+
+	++argv;
+	if (cmd->set == -1)
+		return -1;
+	{
+		int ds_id = atoi(*argv);
+		char* fname = *++argv;
+
+		if ((ds_id == 0) || (ds_id == 1))
+			ret = process_clm_data(wl, fname, ds_id);
+	}
+	return ret;
+}
+#endif /* CLMDOWNLOAD */
+
+static int
+wl_bsscfg_int(void *wl, cmd_t *cmd, char **argv)
+{
+	char *endptr = NULL;
+	char *val_name;
+	int bsscfg_idx = 0;
+	int val = 0;
+	int consumed;
+	int ret;
+
+	val_name = *argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, val_name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+
+	/* handle a bsscfg int with a legacy ioctl */
+	if (consumed == 0 && cmd->set != WLC_SET_VAR) {
+		/* back up to the orig command and run as an ioctl int */
+		argv--;
+		return wl_int(wl, cmd, argv);
+	}
+
+	argv += consumed;
+
+	if (!*argv) {
+		/* This is a GET */
+		if (cmd->get == -1)
+			return -1;
+
+		if (consumed == 0)
+			ret = wlu_iovar_getint(wl, val_name, &val);
+		else
+			ret = wl_bssiovar_getint(wl, val_name, bsscfg_idx, &val);
+
+		if (ret < 0)
+			return ret;
+
+		wl_printint(val);
+	} else {
+		/* This is a SET */
+		if (cmd->set == -1)
+			return -1;
+
+		if (!stricmp(*argv, "on"))
+			val = 1;
+		else if (!stricmp(*argv, "off"))
+			val = 0;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		if (consumed == 0)
+			ret = wlu_iovar_setint(wl, val_name, val);
+		else
+			ret = wl_bssiovar_setint(wl, val_name, bsscfg_idx, val);
+	}
+
+	return ret;
+}
+
+static int
+wl_bsscfg_enable(void *wl, cmd_t *cmd, char **argv)
+{
+	char *endptr;
+	const char *val_name = "bss";
+	int bsscfg_idx = 0;
+	int val;
+	int consumed;
+	int ret;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the command name */
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, val_name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+
+	argv += consumed;
+	if (consumed == 0) { /* Use the -i parameter if that was present */
+		bsscfg_idx = -1;
+	}
+
+	if (!*argv) {
+		bsscfg_idx = htod32(bsscfg_idx);
+		ret = wlu_iovar_getbuf(wl, val_name, &bsscfg_idx, sizeof(bsscfg_idx),
+		                      buf, WLC_IOCTL_MAXLEN);
+		if (ret < 0)
+			return ret;
+		val = *(int*)buf;
+		val = dtoh32(val);
+		if (val)
+			printf("up\n");
+		else
+			printf("down\n");
+		return 0;
+	} else {
+		struct {
+			int cfg;
+			int val;
+		} bss_setbuf;
+		if (!stricmp(*argv, "ap"))
+			val = 3;
+		else if (!stricmp(*argv, "sta"))
+			val = 2;
+		else if (!stricmp(*argv, "up"))
+			val = 1;
+		else if (!stricmp(*argv, "down"))
+			val = 0;
+		else if (!stricmp(*argv, "del"))
+			val = -1;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+		bss_setbuf.cfg = htod32(bsscfg_idx);
+		bss_setbuf.val = htod32(val);
+
+		return wlu_iovar_set(wl, val_name, &bss_setbuf, sizeof(bss_setbuf));
+	}
+}
+
+/* Get/Set the gmode config */
+static int
+wl_gmode(void *wl, cmd_t *cmd, char **argv)
+{
+	char *endptr = NULL;
+	int ret = 0, val;
+
+	if (!*++argv) {
+		const char *gconfig;
+
+		/* Get the current G mode */
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(val))) < 0)
+			return ret;
+
+		val = dtoh32(val);
+		switch (val) {
+		case GMODE_LEGACY_B:
+			gconfig = "54g Legacy B";
+			break;
+		case GMODE_AUTO:
+			gconfig = "54g Auto";
+			break;
+		case GMODE_ONLY:
+			gconfig = "54g Only";
+			break;
+		case GMODE_PERFORMANCE:
+			gconfig = "54g Performance";
+			break;
+		case GMODE_LRS:
+			gconfig = "54g LRS";
+			break;
+		default:
+			gconfig = "unknown";
+			break;
+		}
+
+		printf("%s (%d)\n", gconfig, val);
+
+	} else {
+		/* Set the new G mode */
+
+		if (!strnicmp(*argv, "legacy", 6))
+			val = GMODE_LEGACY_B;
+		else if (!strnicmp(*argv, "auto", 4))
+			val = GMODE_AUTO;
+		else if (!strnicmp(*argv, "gonly", 5))
+			val = GMODE_ONLY;
+		else if (!strnicmp(*argv, "perf", 4))
+			val = GMODE_PERFORMANCE;
+		else if (!strnicmp(*argv, "lrs", 3))
+			val = GMODE_LRS;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/* Set the gmode configration */
+		val = htod32(val);
+		if ((ret = wlu_set(wl, cmd->set, &val, sizeof(val))))
+			goto done;
+
+	}
+
+done:
+	return (ret);
+}
+
+static dbg_msg_t wl_sd_msgs[] = {
+	{SDH_ERROR_VAL,	"error"},
+	{SDH_TRACE_VAL,	"trace"},
+	{SDH_INFO_VAL,	"info"},
+	{SDH_DATA_VAL,	"data"},
+	{SDH_CTRL_VAL,	"control"}
+};
+
+static int
+wl_sd_msglevel(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val, last_val = 0, msglevel_add = 0, msglevel_del = 0;
+	char *endptr = NULL;
+	int msglevel;
+	dbg_msg_t *dbg_msg = wl_sd_msgs;
+
+	if ((ret = wlu_iovar_getint(wl, cmd->name, &msglevel)) < 0)
+		return (ret);
+
+	if (!*++argv) {
+		printf("0x%x ", msglevel);
+		for (i = 0; (val = dbg_msg[i].value); i++) {
+			if ((msglevel & val) && (val != last_val))
+				printf(" %s", dbg_msg[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			msglevel_del = ~0;	/* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		/* not a plain integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = dbg_msg[i].value); i++)
+				if (stricmp(dbg_msg[i].string, s) == 0)
+					break;
+			if (!val)
+				goto usage;
+		}
+		if (**argv == '-')
+			msglevel_del |= val;
+		else
+			msglevel_add |= val;
+		++argv;
+	}
+
+	msglevel &= ~msglevel_del;
+	msglevel |= msglevel_add;
+
+	return (wlu_iovar_setint(wl, cmd->name, msglevel));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+
+	for (i = 0; (val = dbg_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string);
+		else
+			fprintf(stderr, ", %s", dbg_msg[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+
+	return 0;
+}
+
+static int
+wl_sd_blocksize(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc;
+	char *endptr = NULL;
+	void *ptr = NULL;
+	int func, size;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc < 1 || argc > 2) {
+		printf("required args: function [size] (size 0 means max)\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	func = strtol(argv[1], &endptr, 0);
+	if (*endptr != '\0') {
+		printf("Invaild function: %s\n", argv[1]);
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argc > 1) {
+		size = strtol(argv[2], &endptr, 0);
+		if (*endptr != '\0') {
+			printf("Invalid size: %s\n", argv[1]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if (argc == 1) {
+		func = htod32(func);
+		if ((ret = wlu_var_getbuf(wl, cmd->name, &func, sizeof(func), &ptr)) >= 0)
+			printf("Function %d block size: %d\n", func, dtoh32(*(int*)ptr));
+	} else {
+		printf("Setting function %d block size to %d\n", func, size);
+		size &= 0x0000ffff; size |= (func << 16);
+		size = htod32(size);
+		ret = wlu_var_setbuf(wl, cmd->name, &size, sizeof(size));
+	}
+
+	return (ret);
+}
+
+static int
+wl_sd_mode(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc;
+	int sdmode;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argv[1]) {
+		if (!strcmp(argv[1], "spi")) {
+			strcpy(argv[1], "0");
+		} else if (!strcmp(argv[1], "sd1")) {
+			strcpy(argv[1], "1");
+		} else if (!strcmp(argv[1], "sd4")) {
+			strcpy(argv[1], "2");
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		ret = wl_var_setint(wl, cmd, argv);
+
+	} else {
+		if ((ret = wl_var_get(wl, cmd, argv))) {
+			return (ret);
+		} else {
+			sdmode = dtoh32(*(int32*)buf);
+
+			printf("SD Mode is: %s\n",
+			       sdmode == 0 ? "SPI"
+			       : sdmode == 1 ? "SD1"
+				   : sdmode == 2 ? "SD4" : "Unknown");
+		}
+	}
+
+	return (ret);
+}
+
+static int
+wl_sd_reg(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	sdreg_t sdreg;
+	char *endptr = NULL;
+	uint argc;
+	void *ptr = NULL;
+
+	memset(&sdreg, 0, sizeof(sdreg));
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	/* hostreg: offset [value]; devreg: func offset [value] */
+	if (!strcmp(cmd->name, "sd_hostreg")) {
+		argv++;
+		if (argc < 1) {
+			printf("required args: offset [value]\n");
+			return BCME_USAGE_ERROR;
+		}
+
+	} else if (!strcmp(cmd->name, "sd_devreg")) {
+		argv++;
+		if (argc < 2) {
+			printf("required args: func offset [value]\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		sdreg.func = htod32(strtol(*argv++, &endptr, 0));
+		if (*endptr != '\0') {
+			printf("Bad func.\n");
+			return BCME_USAGE_ERROR;
+		}
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	sdreg.offset = htod32(strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0') {
+		printf("Bad offset\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* third arg: value */
+	if (*argv) {
+		sdreg.value = htod32(strtol(*argv, &endptr, 0));
+		if (*endptr != '\0') {
+			printf("Bad Value\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* no third arg means get, otherwise set */
+	if (!*argv) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, &sdreg, sizeof(sdreg), &ptr)) >= 0)
+			printf("0x%x\n", dtoh32(*(int *)ptr));
+	} else {
+		ret = wlu_var_setbuf(wl, cmd->name, &sdreg, sizeof(sdreg));
+	}
+
+	return (ret);
+}
+
+static int
+wl_overlay(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc;
+	char *endptr = NULL;
+	void *ptr = NULL;
+	int param[3];
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc < 1 || argc > 3) {
+		printf("required args: virt_addr phy_addr size\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	param[0] = strtol(argv[1], &endptr, 0);
+	if (*endptr != '\0' || (param[0] & ~0x003FFE00) != 0) {
+		printf("Invaild virtual address: %s\n", argv[1]);
+		return BCME_BADARG;
+	}
+
+	if (argc == 1) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, param, sizeof(int), &ptr)) >= 0) {
+			wl_hexdump((uchar *)ptr, 512);
+		}
+		return (ret);
+	}
+
+	param[1] = strtol(argv[2], &endptr, 0);
+	if (*endptr != '\0' || (param[1] & ~0x003FFE00) != 0) {
+		printf("Invaild physical Address: %s\n", argv[2]);
+		return BCME_BADARG;
+	}
+
+	if (argc == 3) {
+		param[2] = strtol(argv[3], &endptr, 0);
+		if (*endptr != '\0' || param[2] < 0 || param[2] > 7) {
+			printf("Invaild size: %s\n", argv[3]);
+			return BCME_BADARG;
+		}
+	} else {
+		param[2] = 0;
+	}
+
+	printf("Setting virtual Address 0x%x to physical Address 0x%x, size is %d\n",
+		param[0], param[1], param[2]);
+	ret = wlu_var_setbuf(wl, cmd->name, param, sizeof(param));
+
+	return (ret);
+}
+
+static int
+wl_reg(void *wl, cmd_t *cmd, char **argv)
+{
+	int reg;
+	int ret;
+	struct {
+		int val;
+		int band;
+	} x;
+	char *endptr = NULL;
+	uint argc;
+	bool core_cmd;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: reg offset */
+	if (argc < 1)
+		return BCME_USAGE_ERROR;
+
+	reg = strtol(argv[0], &endptr, 0);
+
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	x.val = 0;
+	x.band = WLC_BAND_AUTO;
+	core_cmd = FALSE;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	/* Second arg: value or band or "radio core" */
+	if (argc >= 2) {
+		if (!stricmp(argv[1], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[1], "b"))
+			x.band = WLC_BAND_2G;
+		else {
+			/* For NPHY Rev >= 3, the 2nd argument can be
+			   the radio core
+			 */
+			if (strcmp(cmd->name, "radioreg") == 0) {
+				if (strcmp(argv[1], "syn") == 0) {
+					reg |= RADIO_CORE_SYN;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "tx0") == 0) {
+					reg |= RADIO_CORE_TX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "tx1") == 0) {
+					reg |= RADIO_CORE_TX1;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "rx0") == 0) {
+					reg |= RADIO_CORE_RX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "rx1") == 0) {
+					reg |= RADIO_CORE_RX1;
+					core_cmd = TRUE;
+				}
+			}
+			/* For HTPHY/ACPHY, the 2nd argument can be
+			   the radio core
+			 */
+			if (strcmp(cmd->name, "radioreg") == 0) {
+				if (phytype == WLC_PHY_TYPE_AC) {
+					if (strcmp(argv[1], "cr0") == 0) {
+						reg |= RADIO_2069_CORE_CR0;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr1") == 0) {
+						reg |= RADIO_2069_CORE_CR1;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr2") == 0) {
+						reg |= RADIO_2069_CORE_CR2;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "pll") == 0) {
+						reg |= RADIO_2069_CORE_PLL;
+						core_cmd = TRUE;
+					}
+				} else {
+					if (strcmp(argv[1], "cr0") == 0) {
+						reg |= RADIO_CORE_CR0;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr1") == 0) {
+						reg |= RADIO_CORE_CR1;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr2") == 0) {
+						reg |= RADIO_CORE_CR2;
+						core_cmd = TRUE;
+					}
+				}
+			}
+			/* If the second argument is a value */
+			if (!core_cmd) {
+				x.val = strtol(argv[1], &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	/* Third arg: band OR "radio core" */
+	if (argc >= 3) {
+		if (!stricmp(argv[2], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[2], "b"))
+			x.band = WLC_BAND_2G;
+		else {
+			/* For NPHY Rev >= 3, the 3rd argument can be
+			   the radio core
+			 */
+			core_cmd = FALSE;
+			if (strcmp(cmd->name, "radioreg") == 0) {
+				if (strcmp(argv[2], "syn") == 0) {
+					reg |= RADIO_CORE_SYN;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "tx0") == 0) {
+					reg |= RADIO_CORE_TX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "tx1") == 0) {
+					reg |= RADIO_CORE_TX1;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "rx0") == 0) {
+					reg |= RADIO_CORE_RX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "rx1") == 0) {
+					reg |= RADIO_CORE_RX1;
+					core_cmd = TRUE;
+				}
+			}
+			/* For HTPHY/ACPHY, the 3rd argument can be
+			   the radio core
+			*/
+			if (phytype == WLC_PHY_TYPE_AC) {
+				if (strcmp(argv[2], "cr0") == 0) {
+					reg |= RADIO_2069_CORE_CR0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "cr1") == 0) {
+					reg |= RADIO_2069_CORE_CR1;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "cr2") == 0) {
+					reg |= RADIO_2069_CORE_CR2;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "pll") == 0) {
+					reg |= RADIO_2069_CORE_PLL;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "all") == 0) {
+					reg |= RADIO_2069_CORE_ALL;
+					core_cmd = TRUE;
+				}
+			} else {
+				if (strcmp(cmd->name, "radioreg") == 0) {
+					if (strcmp(argv[2], "cr0") == 0) {
+						reg |= RADIO_CORE_CR0;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[2], "cr1") == 0) {
+						reg |= RADIO_CORE_CR1;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[2], "cr2") == 0) {
+						reg |= RADIO_CORE_CR2;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[2], "all") == 0) {
+						reg |= RADIO_CORE_ALL;
+						core_cmd = TRUE;
+					}
+				}
+			}
+
+			if (!core_cmd) {
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	x.val = (x.val << 16) | (reg & 0xffff);
+
+	/* issue the get or set ioctl */
+	if ((argc == 1) || ((argc == 2) && ((x.band != WLC_BAND_AUTO) || core_cmd))) {
+		x.band = htod32(x.band);
+		x.val = htod32(x.val);
+		if ((ret = wlu_get(wl, cmd->get, &x, sizeof(x))) < 0)
+			return (ret);
+		printf("0x%04x\n", (uint16)(dtoh32(x.val)));
+	} else {
+		x.band = htod32(x.band);
+		x.val = htod32(x.val);
+		ret = wlu_set(wl, cmd->set, &x, sizeof(x));
+	}
+
+	return (ret);
+}
+
+static int
+wl_gpioout(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 mask;
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	uint32 *int_ptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* Get and print the values */
+	if (argc == 0) {
+		uint32 gpio_cntrl;
+		uint32 gpio_out;
+		uint32 gpio_outen;
+		int ret;
+
+		if ((ret = wlu_iovar_get(wl, "gpioout", buf, sizeof(uint32) *3)) < 0)
+			return ret;
+		gpio_cntrl = dtoh32(((uint32 *)buf)[0]);
+		gpio_out = dtoh32(((uint32 *)buf)[1]);
+		gpio_outen = dtoh32(((uint32 *)buf)[2]);
+
+		printf("gpiocontrol 0x%x gpioout 0x%x gpioouten 0x%x\n", gpio_cntrl,
+		       gpio_out, gpio_outen);
+
+		return 0;
+	}
+
+	/* required arg: mask value */
+	if (argc < 2)
+		return BCME_USAGE_ERROR;
+
+	mask = strtoul(argv[0], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	val = strtoul(argv[1], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	if ((~mask & val) != 0)
+		return BCME_BADARG;
+
+	int_ptr = (uint32 *)buf;
+	mask = htod32(mask);
+	memcpy(int_ptr, (const void *)&mask, sizeof(mask));
+	int_ptr++;
+	val = htod32(val);
+	memcpy(int_ptr, (const void *)&val, sizeof(val));
+
+	return wlu_iovar_set(wl, "gpioout", buf, sizeof(uint32) *2);
+}
+
+static int
+wl_macreg(void *wl, cmd_t *cmd, char **argv)
+{
+	int reg;
+	int size;
+	uint32 val;
+	int ret;
+	char *endptr = NULL;
+	rw_reg_t rwt;
+	uint argc;
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: reg offset */
+	if (argc < 1)
+		return BCME_USAGE_ERROR;
+
+	reg = strtol(argv[0], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	/* required arg: reg size */
+	if (argc < 2)
+		return BCME_USAGE_ERROR;
+
+	size = strtol(argv[1], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	rwt.band = WLC_BAND_AUTO;
+
+	/* Third arg: new value or band */
+	if (argc >= 3) {
+		if (!stricmp(argv[2], "a"))
+			rwt.band = WLC_BAND_5G;
+		else if (!stricmp(argv[2], "b"))
+			rwt.band = WLC_BAND_2G;
+		else {
+			val = strtoul(argv[2], &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+	}
+
+	/* Fourth arg: band */
+	if (argc >= 4) {
+		if (!stricmp(argv[3], "a"))
+			rwt.band = WLC_BAND_5G;
+		else if (!stricmp(argv[3], "b"))
+			rwt.band = WLC_BAND_2G;
+		else
+			return BCME_USAGE_ERROR;
+	}
+
+	if ((argc == 2) || ((argc == 3) && (rwt.band != WLC_BAND_AUTO))) {
+		rwt.band = htod32(rwt.band);
+		rwt.byteoff = htod32(reg);
+		rwt.size = htod32(size);
+		if ((ret = wlu_get(wl, cmd->get, &rwt, sizeof(rw_reg_t))) < 0)
+			return (ret);
+		printf("0x%04x\n", dtoh32(rwt.val));
+	}
+	else {
+		rwt.band = htod32(rwt.band);
+		rwt.byteoff = htod32(reg);
+		rwt.size = htod32(size);
+		rwt.val = htod32(val);
+		ret = wlu_set(wl, cmd->set, &rwt, sizeof(rw_reg_t));
+	}
+
+	return (ret);
+}
+
+/*
+ * get or get a band specific variable
+ * the band can be a/b/all or omitted. "all"(set only)
+ * means all supported bands. blank means current band
+ */
+static int
+wl_band_elm(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct {
+		int val;
+		int band;
+	} x;
+	char *endptr = NULL;
+	uint argc;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	x.val = 0;
+	x.band = WLC_BAND_AUTO;
+
+	/* First arg: value or band */
+	if (argc >= 1) {
+		if (!stricmp(argv[0], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[0], "b"))
+			x.band = WLC_BAND_2G;
+		else if (!stricmp(argv[0], "all"))
+			x.band = WLC_BAND_ALL;
+		else {
+			x.val = strtol(argv[0], &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* Second arg: band */
+	if (argc >= 2) {
+		if (!stricmp(argv[1], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[1], "b"))
+			x.band = WLC_BAND_2G;
+		else if (!stricmp(argv[1], "all"))
+			x.band = WLC_BAND_ALL;
+		else
+			return BCME_USAGE_ERROR;
+	}
+
+	/* issue the get or set ioctl */
+	if ((argc == 0) || ((argc == 1) && (x.band != WLC_BAND_AUTO))) {
+		if (x.band == WLC_BAND_ALL) {
+			printf("band option \"all\" is for set only, not get\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		x.band = htod32(x.band);
+		if ((ret = wlu_get(wl, cmd->get, &x, sizeof(x))) < 0)
+			return (ret);
+
+		printf("%s is 0x%04x(%d)\n", cmd->name, (uint16)(dtoh32(x.val)), dtoh32(x.val));
+	} else {
+		x.band = htod32(x.band);
+		x.val = htod32(x.val);
+		ret = wlu_set(wl, cmd->set, &x, sizeof(x));
+	}
+
+	return (ret);
+}
+
+/* Command may or may not take a MAC address */
+static int
+wl_rssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	scb_val_t scb_val;
+	int32 rssi;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &rssi, sizeof(rssi))) < 0)
+			return ret;
+		printf("%d\n", dtoh32(rssi));
+		return 0;
+	} else {
+		if (!wl_ether_atoe(*argv, &scb_val.ea))
+			return BCME_USAGE_ERROR;
+		if ((ret = wlu_get(wl, cmd->get, &scb_val, sizeof(scb_val))) < 0)
+			return ret;
+		printf("%d\n", dtoh32(scb_val.val));
+		return 0;
+	}
+}
+
+static int
+wl_rssi_event(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	if (!*++argv) {
+		/* get */
+		void *ptr = NULL;
+		wl_rssi_event_t rssi;
+		uint i;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		memcpy(&rssi, ptr, sizeof(rssi));
+		rssi.rate_limit_msec = dtoh32(rssi.rate_limit_msec);
+
+		printf("%d", rssi.rate_limit_msec);
+		for (i = 0; i < rssi.num_rssi_levels; i++) {
+			printf(" %d", rssi.rssi_levels[i]);
+		}
+		printf("\n");
+	} else {
+		/* set */
+		wl_rssi_event_t rssi;
+
+		memset(&rssi, 0, sizeof(wl_rssi_event_t));
+		rssi.rate_limit_msec = atoi(*argv);
+
+		while (*++argv && rssi.num_rssi_levels < MAX_RSSI_LEVELS) {
+			rssi.rssi_levels[rssi.num_rssi_levels++] = atoi(*argv);
+			if (rssi.num_rssi_levels > 1) {
+				if (rssi.rssi_levels[rssi.num_rssi_levels - 1] <=
+					rssi.rssi_levels[rssi.num_rssi_levels - 2]) {
+					/* rssi levels must be in increasing order */
+					return BCME_USAGE_ERROR;
+				}
+			}
+		}
+
+		if (*argv) {
+			/* too many parameters */
+			return BCME_USAGE_ERROR;
+		}
+
+		rssi.rate_limit_msec = htod32(rssi.rate_limit_msec);
+		ret = wlu_var_setbuf(wl, cmd->name, &rssi, sizeof(rssi));
+	}
+	return ret;
+}
+
+static int
+wl_phy_rssi_ant(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	uint i;
+	wl_rssi_ant_t *rssi_ant_p;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		rssi_ant_p = (wl_rssi_ant_t *)ptr;
+		rssi_ant_p->version = dtoh32(rssi_ant_p->version);
+		rssi_ant_p->count = dtoh32(rssi_ant_p->count);
+
+		if (rssi_ant_p->count == 0) {
+			printf("not supported on this chip\n");
+		} else {
+			for (i = 0; i < rssi_ant_p->count; i++)
+				printf("rssi[%d] %d  ", i, rssi_ant_p->rssi_ant[i]);
+			printf("\n");
+		}
+	} else {
+		ret = BCME_USAGE_ERROR;
+	}
+	return ret;
+}
+
+/* Commands that take a MAC address */
+static int
+wl_mac(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ether_addr ea;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &ea, ETHER_ADDR_LEN)) < 0)
+			return ret;
+		printf("%s\n", wl_ether_etoa(&ea));
+		return 0;
+	} else {
+		if (!wl_ether_atoe(*argv, &ea))
+			return BCME_USAGE_ERROR;
+		return wlu_set(wl, cmd->set, &ea, ETHER_ADDR_LEN);
+	}
+}
+
+/* IO variables that take a MAC address */
+static int
+wl_iov_mac(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ether_addr ea = {{0, 0, 0, 0, 0, 0}};
+
+	if (argv[1]) { /* set */
+		if (!wl_ether_atoe(argv[1], &ea)) {
+			printf(" ERROR: no valid ether addr provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		if ((ret = wlu_iovar_set(wl, cmd->name, &ea, ETHER_ADDR_LEN)) < 0) {
+			printf("Error setting variable %s\n", argv[0]);
+			return ret;
+		}
+		return 0;
+	} else { /* get */
+		if ((ret = wlu_iovar_get(wl, cmd->name, &ea, ETHER_ADDR_LEN)) < 0) {
+			printf("Error getting variable %s\n", argv[0]);
+			return ret;
+		}
+		printf("%s %s\n", argv[0], wl_ether_etoa(&ea));
+	}
+
+	return 0;
+}
+
+static void
+wl_txq_prec_dump(wl_iov_pktq_log_t* iov_pktq_log, bool hide_unknown, bool is_aqm)
+{
+#define PREC_DUMPV(v4, v5)  ((iov_pktq_log->version == 4) ? (v4) : (v5))
+
+#define v4hstubL            "prec:   rqstd,  stored,selfsave,   saved,fulldrop, dropped," \
+	                    "sacrficd, retried, rtsfail,rtrydrop, psretry,supprssd,   " \
+	                    "acked,utlisatn,q length,Data Mbits/s,Phy Mbits/s,Rate Mbits/s"
+
+#define v4hstubS            "prec:   rqstd,  stored, dropped, retried, rtsfail,rtrydrop, " \
+	                    "psretry,   acked,utlisatn,q length,Data Mbits/s,Phy Mbits/s"
+
+#define v4fstubL            "  %02u: %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, " \
+	                    "%7u, %7u, %7u, %7u, %8.2f,   %8.2f,    %8.2f"
+
+#define v4fstubS            "  %02u: %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, " \
+	                    "%8.2f,   %8.2f"
+
+#define v4fstubL_aqm        "  %02u: %7u, %7u, %7u, %7u, %7u, %7u, %7u,       -,       -, " \
+	                    "%7u, %7u, %7u, %7u, %7u, %7u, %8.2f,          -,           -"
+
+#define v4fstubS_aqm        "  %02u: %7u, %7u, %7u,       -,       -, %7u, %7u, %7u, %7u, " \
+	                    "%7u, %8.2f,          -"
+
+	const char* v4headingsL = v4hstubL" (+v%d.)\n";
+	const char* v4headingsS = v4hstubS" (+v%d.)\n";
+	const char* v5headingsL = v4hstubL", %%air, %%effcy  (v%d)\n";
+	const char* v5headingsS = v4hstubS", %%air, %%effcy  (v%d)\n";
+
+	const char* v4formL =     v4fstubL"\n";
+	const char* v4formS =     v4fstubS"\n";
+	const char* v4formL_aqm = v4fstubL_aqm"\n";
+	const char* v4formS_aqm = v4fstubS_aqm"\n";
+
+	const char* v5formL =     v4fstubL",  %6.1f,  %5.1f\n";
+	const char* v5formS =     v4fstubS",  %6.1f,  %5.1f\n";
+	const char* v5formL_aqm = v4fstubL_aqm",       -,      -\n";
+	const char* v5formS_aqm = v4fstubS_aqm",       -,      -\n";
+
+	char*  headings;
+	uint8  index;
+	uint8  prec;
+	uint32 prec_mask = 0;
+	char   marker[4] = "[X]";
+	pktq_log_format_v05_t* logv05 = NULL;
+	pktq_log_format_v04_t* logv04 = NULL;
+
+	if (iov_pktq_log->version == 0x04) {
+		logv04 = &iov_pktq_log->pktq_log.v04;
+	}
+	else if (iov_pktq_log->version == 0x05) {
+		logv05 = &iov_pktq_log->pktq_log.v05;
+	}
+	else {
+		fprintf(stderr, "Unknown/unsupported binary format (%x)\n",
+		        iov_pktq_log->version);
+		return;
+	}
+
+	headings = PREC_DUMPV(&logv04->headings[0], &logv05->headings[0]);
+
+	for (index = 0; index < (uint8)iov_pktq_log->params.num_addrs; index++) {
+
+		char* heading_start;
+		char* heading_end;
+		uint32 num_prec = 0;
+
+		prec_mask = PREC_DUMPV(logv04->counter_info[index],
+		                       logv05->counter_info[index]);
+		num_prec = PREC_DUMPV(logv04->num_prec[index],
+		                      logv05->num_prec[index]);
+
+		/* test for 'unknown' data; unknown means either that
+		 * the queue is invalid or else that the logging
+		 * is not active at all.
+		 */
+		if (((prec_mask & 0xFFFF) == 0) && hide_unknown) {
+			continue;
+		}
+
+		if ((num_prec == 0) && hide_unknown) {
+			continue;
+		}
+
+		/* search for string marker - the marker is of the form
+		   "[<index>]" where index is a single ascii numeral
+		*/
+		marker[1] = '0' + index;
+		heading_start = strstr(headings, marker);
+
+		/* The driver may pass back an optional character
+		 * string for additional info
+		 */
+		if (heading_start != NULL) {
+
+			heading_start += strlen(marker);
+			heading_end = strstr(heading_start, marker);
+
+			if (heading_end == NULL) {
+				heading_end = heading_start + strlen(heading_start);
+			}
+			while (heading_start < heading_end) {
+				fputc(*heading_start++, stdout);
+			}
+		}
+
+		/* Note that this is zero if the data is invalid */
+		if (!num_prec) {
+			fprintf(stdout, "Parameter %c:%s not valid\n",
+			        iov_pktq_log->params.addr_type[index] != 0 ?
+			        iov_pktq_log->params.addr_type[index] & 0x7F : ' ',
+			        wl_ether_etoa(&iov_pktq_log->params.ea[index]));
+			continue;
+		}
+
+		/* check for short form or long form (top bit set) */
+		fprintf(stdout,
+		        iov_pktq_log->params.addr_type[index] & 0x80 ?
+		        PREC_DUMPV(v4headingsL, v5headingsL) :
+		        PREC_DUMPV(v4headingsS, v5headingsS),
+		        iov_pktq_log->version);
+
+		for (prec = 0; prec < num_prec; prec++) {
+			float tput = 0.0;
+			float txrate_succ = 0.0;
+			float txrate_main = 0.0;
+			pktq_log_counters_v05_t counters;
+			uint32 try_count = 0;
+			float airuse = 0.0;
+			float efficiency = 0.0;
+
+			if (!(prec_mask & (1 << prec))) {
+				continue;
+			}
+
+			if (iov_pktq_log->version == 5) {
+				counters = logv05->counters[index][prec];
+			}
+			else {
+				/* the following is a trick - it is possible because
+				 * V4 and V5 are both common except that V5 has extra fields
+				 * at the end
+				*/
+				memcpy(&counters, &logv04->counters[index][prec],
+				       sizeof(pktq_log_counters_v04_t));
+				counters.airtime = 0;
+			}
+
+			txrate_succ = (float)counters.txrate_succ * 0.5;
+
+			if (counters.time_delta != 0) {
+				/* convert bytes to bits */
+				tput = (float)counters.throughput;
+				tput *= 8.0;
+
+				if (counters.airtime) {
+					efficiency = 100.0 * tput / (float)counters.airtime;
+				}
+
+				/* converts to rate of bits per us,
+				   because time_delta is in micro-seconds
+				*/
+				tput /= (float)counters.time_delta;
+
+				/* Calculate % airtime */
+				airuse = counters.airtime * 100.0 / (float)counters.time_delta;
+			}
+
+			if (!(is_aqm && (prec & 1))) {
+				uint32 acked = counters.acked;
+
+				try_count = counters.acked + counters.retry;
+
+				if (is_aqm && (prec_mask & (1 << (prec + 1)))) {
+					pktq_log_counters_v05_t hi;
+
+					if (iov_pktq_log->version == 5) {
+						hi = logv05->counters[index][prec + 1];
+					}
+					else {
+						/* the following is a trick - it is possible
+						 * fields V4 and V5 are both common except
+						 * that V5 has extra fields at the end
+						 */
+						memcpy(&hi, &logv04->counters[index][prec + 1],
+						       sizeof(pktq_log_counters_v04_t));
+					}
+
+					acked += hi.acked;
+					try_count += hi.acked + hi.retry;
+
+					if (counters.airtime) {
+						float t = (float)hi.throughput;
+						t /= (float)counters.airtime;
+						efficiency += 100.0 * 8.0 * t;
+					}
+				}
+				if (acked) {
+					txrate_succ /= (float) acked;
+
+					if (counters.txrate_succ) {
+						efficiency /= txrate_succ;
+					}
+					else {
+						efficiency = 0;
+					}
+				}
+				else {
+					txrate_succ = 0;
+					efficiency = 0;
+				}
+			}
+
+			if (try_count) {
+				txrate_main = (float)counters.txrate_main * 0.5;
+				txrate_main /= (float)try_count;
+			}
+
+			if (iov_pktq_log->params.addr_type[index] & 0x80) {
+				/* long form */
+				if (is_aqm && (prec & 1)) {
+					/* aqm format for hi-prec */
+					fprintf(stdout, PREC_DUMPV(v4formL_aqm, v5formL_aqm),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.selfsaved,
+					        counters.saved,
+					        counters.full_dropped,
+					        counters.dropped,
+					        counters.sacrificed,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.suppress,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput);
+				}
+				else {
+					fprintf(stdout, PREC_DUMPV(v4formL, v5formL),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.selfsaved,
+					        counters.saved,
+					        counters.full_dropped,
+					        counters.dropped,
+					        counters.sacrificed,
+					        counters.retry,
+					        counters.rtsfail,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.suppress,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput, txrate_succ,
+					        txrate_main,
+					        airuse, efficiency);
+				}
+			}
+			else {
+				/* short form */
+				if (is_aqm && (prec & 1)) {
+					/* aqm format for hi-prec */
+					fprintf(stdout, PREC_DUMPV(v4formS_aqm, v5formS_aqm),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.dropped,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput);
+				}
+				else {
+					fprintf(stdout, PREC_DUMPV(v4formS, v5formS),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.dropped,
+					        counters.retry,
+					        counters.rtsfail,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput, txrate_succ,
+					        airuse, efficiency);
+				}
+			}
+		}
+		fputs("\n", stdout);
+
+		if (iov_pktq_log->version == 5 &&
+		       (logv05->pspretend_time_delta[index] != (uint32)-1)) {
+
+			fprintf(stdout, "Total time in ps pretend state is %d milliseconds\n\n",
+			        (logv05->pspretend_time_delta[index] + 500)/1000);
+		}
+	}
+}
+
+static int
+wl_scb_bs_data(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 flag_bits = 0;
+	int argn;
+	enum { DISPLAY_COOKED, DISPLAY_RAW } display_mode = DISPLAY_COOKED;
+	iov_bs_data_struct_t *data = (iov_bs_data_struct_t *)buf;
+	char sep = ' ';
+	bool skip_idle = FALSE;
+	float total_throughput = 0.0;
+
+	UNUSED_PARAMETER(cmd);	/* cmd->name should match argv[0] ? */
+
+	if (!argv[0]) {
+		fprintf(stderr, "%s: argv[0] missing\n", __FUNCTION__);
+		return BCME_BADARG;
+	}
+
+	for (argn = 1; argv[argn]; ++argn) {
+		if (!strcmp(argv[argn], "-noreset")) {	/* do not reset counters after reading */
+			flag_bits |= SCB_BS_DATA_FLAG_NO_RESET;
+		} else
+		if (!strcmp(argv[argn], "-raw")) {	/* Display raw counters */
+			display_mode = DISPLAY_RAW;
+		} else
+		if (!strcmp(argv[argn], "-tab")) {	/* Tab separator */
+			sep = '\t';
+		} else
+		if (!strcmp(argv[argn], "-comma")) {	/* Comma separator */
+			sep = ',';
+		} else
+		if (!strcmp(argv[argn], "-noidle")) {	/* Skip idle stations */
+			skip_idle = TRUE;
+		} else
+		if (!strcmp(argv[argn], "-help") || !strcmp(argv[argn], "-h")) {
+			/* Display usage, do not complain about unknown option. */
+			return BCME_USAGE_ERROR;
+		} else {
+			fprintf(stderr, "%s: unknown option: %s\n", argv[0], argv[argn]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	flag_bits = htod32(flag_bits);
+	err = wlu_iovar_getbuf(wl, argv[0], &flag_bits, sizeof(flag_bits), buf, WLC_IOCTL_MAXLEN);
+	if (err) {
+		return (err);
+	}
+
+	data->structure_version = dtoh16(data->structure_version);
+	if (data->structure_version != SCB_BS_DATA_STRUCT_VERSION) {
+		fprintf(stderr, "wlu / wl driver mismatch, expect V%d format, got %d.\n",
+			SCB_BS_DATA_STRUCT_VERSION, data->structure_version);
+		return BCME_IOCTL_ERROR;
+	}
+
+	data->structure_count = dtoh16(data->structure_count);
+	if (data->structure_count == 0) {
+		printf("No stations are currently associated.\n");
+		return BCME_OK;
+	}
+
+	/* Display Column headers - mac address always, then, depending on display mode */
+
+	printf("%17s%c", "Station Address", sep);
+	switch (display_mode) {
+	case DISPLAY_RAW:
+		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+			"retry_drop", "rtsfail", "retry", "txrate_main",
+			"txrate_succ", "acked", "throughput", "time_delta", "airtime");
+		break;
+	case DISPLAY_COOKED:
+		printf("%10s%c%10s%c%10s%c%10s%c%10s\n", "PHY Mbps", sep, "Data Mbps", sep,
+			"Air Use", sep, "Data Use", sep, "Retries");
+		break;
+	}
+
+	/* Convert returned counters to host byte order, and sum up total throughput */
+
+	for (argn = 0; argn < data->structure_count; ++argn) {
+
+		iov_bs_data_record_t *rec;
+		iov_bs_data_counters_t *ctr;
+		float data_rate;
+
+		rec = &data->structure_record[argn];
+		ctr = &rec->station_counters;
+
+#define DEVICE_TO_HOST(xyzzy) ctr->xyzzy = dtoh32(ctr->xyzzy)
+		DEVICE_TO_HOST(retry_drop);
+		DEVICE_TO_HOST(rtsfail);
+		DEVICE_TO_HOST(retry);
+		DEVICE_TO_HOST(txrate_main);
+		DEVICE_TO_HOST(txrate_succ);
+		DEVICE_TO_HOST(acked);
+		DEVICE_TO_HOST(throughput);
+		DEVICE_TO_HOST(time_delta);
+		DEVICE_TO_HOST(airtime);
+#undef DEVICE_TO_HOST
+
+		/* Calculate data rate in bits per second, rather than bytes per second */
+		data_rate = (ctr->time_delta) ?
+			(float)ctr->throughput * 8.0 / (float)ctr->time_delta : 0.0;
+
+		total_throughput += data_rate;
+	}
+
+	for (argn = 0; argn < data->structure_count; ++argn) {
+		iov_bs_data_record_t *rec;
+		iov_bs_data_counters_t *ctr;
+		rec = &data->structure_record[argn];
+		ctr = &rec->station_counters;
+
+		if (skip_idle && (ctr->acked == 0)) continue;
+
+		printf("%17s%c", wl_ether_etoa(&rec->station_address), sep);
+		switch (display_mode) {
+		case DISPLAY_RAW:
+			printf("%9d %9d %9d %9d %9d %9d %9d %9d %9d\n",
+				ctr->retry_drop, ctr->rtsfail, ctr->retry,
+				ctr->txrate_main, ctr->txrate_succ, ctr->acked,
+				ctr->throughput, ctr->time_delta, ctr->airtime);
+			break;
+		case DISPLAY_COOKED:
+			{
+			float data_rate;
+			float phy_rate;
+			float use, air, rtr;
+
+			/* Calculate PHY rate */
+			phy_rate = (ctr->acked) ?
+				(float)ctr->txrate_succ * 0.5 / (float)ctr->acked : 0.0;
+
+			/* Calculate Data rate */
+			data_rate = (ctr->time_delta) ?
+				(float)ctr->throughput * 8.0 / (float)ctr->time_delta : 0.0;
+
+			/* Calculate use percentage amongst throughput from all stations */
+			use = (total_throughput) ? data_rate / total_throughput * 100 : 0.0;
+
+			/* Calculate % airtime */
+			air = (ctr->time_delta) ? ((float)ctr->airtime * 100.0 /
+			          (float) ctr->time_delta) : 0.0;
+
+			/* Calculate retry percentage */
+			rtr = (ctr->acked) ? (float)ctr->retry / (float)ctr->acked * 100 :  0.0;
+
+			printf("%10.1f%c%10.1f%c%9.1f%%%c%9.1f%%%c%9.1f%%\n",
+				phy_rate, sep, data_rate, sep, air, sep, use, sep, rtr);
+			}
+			break;
+		}
+	}
+	return BCME_OK;
+}
+
+/* IO variables that take MAC addresses (with optional single letter prefix)
+ * and output a string buffer
+ */
+static int
+wl_iov_pktqlog_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char** macaddrs = argv + 1;
+
+	wl_iov_mac_full_params_t*  full_params = (wl_iov_mac_full_params_t*)buf;
+	wl_iov_mac_params_t*       params = &full_params->params;
+	wl_iov_mac_extra_params_t* extra_params = &full_params->extra_params;
+
+	wl_iov_mac_params_t       loop_params;
+	wl_iov_mac_extra_params_t loop_extra_params;
+	uint32   index;
+	bool  loop_assoclist = FALSE;
+	struct maclist* maclist = NULL;
+
+	wlc_rev_info_t revinfo;
+	uint32 corerev;
+
+	if (cmd->get < 0)
+		return -1;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+
+	if (ret) {
+		return ret;
+	}
+	corerev = dtoh32(revinfo.corerev);
+
+	memset(full_params, 0, sizeof(*full_params));
+	memset(&loop_params, 0, sizeof(loop_params));
+	memset(&loop_extra_params, 0, sizeof(loop_extra_params));
+
+	/* only pass up to WL_IOV_MAC_PARAM_LEN parameters */
+	while (params->num_addrs < WL_IOV_MAC_PARAM_LEN && *macaddrs) {
+		bool    full_auto = FALSE;
+		char*   ptr = *macaddrs;
+		uint32  bitmask;
+
+		/* is there a prefix character? */
+		if (ptr[1] == ':') {
+			params->addr_type[params->num_addrs] = toupper((int)(ptr[0]));
+
+			/* move ptr to skip over prefix */
+			ptr += 2;
+
+			/* is there the 'long form' option ? */
+			if (ptr[0] == '+') {
+				/* check for + additional info option, set top bit */
+				params->addr_type[params->num_addrs]  |= 0x80;
+				ptr++;
+			}
+			if ((ptr[0] == 0) || (ptr[0] == '/' || ptr[0] == ',')) {
+				/* this is the fully automatic mode */
+				full_auto = TRUE;
+			}
+		}
+
+		/* the prefix C: denotes no given MAC address (to refer to "common") */
+		if ((params->addr_type[params->num_addrs] & 0x7F) == 'C')  {
+			full_auto = FALSE;
+		}
+		else if (full_auto) {
+			loop_assoclist = TRUE;
+			loop_params.addr_type[loop_params.num_addrs] =
+			                     params->addr_type[params->num_addrs];
+		}
+		else if (wl_ether_atoe(ptr, &params->ea[params->num_addrs])) {
+			 /* length of MAC addr string excl end char */
+			ptr += (ETHER_ADDR_STR_LEN - 1);
+		}
+		else {
+			params->addr_type[params->num_addrs] = 0;
+			printf("Bad parameter '%s'\n", *macaddrs);
+			++macaddrs;
+			continue;
+		}
+
+
+		bitmask = 0;
+
+		while (ptr && (ptr[0] == ',' || ptr[0] == '/') &&
+		         ((ptr[1] >= '0' && ptr[1] <= '9') ||
+		         ptr[1] == '/' || ptr[1] == ',')) {
+
+			uint8 prec;
+			char* endptr = 0;
+
+			if (ptr[1] == '/' || ptr[1] == ',') {
+				/* this is the 'auto' setting */
+				bitmask |= PKTQ_LOG_AUTO;
+				ptr += 2;
+			}
+			else {
+				ptr++;
+
+				prec = (uint8)strtoul(ptr, &endptr, 10);
+
+				if (prec <= 15) {
+					bitmask |= (1 << prec);
+				}
+				else {
+					printf("Bad precedence %d (will be ignored)\n",
+					       prec);
+				}
+				ptr = endptr;
+			}
+
+		}
+
+		if (bitmask == 0) {
+			/* PKTQ_LOG_DEF_PREC is ignored in V4, it is used to indicate no prec was
+			 * selected
+			 */
+			bitmask = 0xFFFF | PKTQ_LOG_DEF_PREC;
+		}
+
+		if (full_auto) {
+			loop_extra_params.addr_info[loop_params.num_addrs] = bitmask;
+			loop_params.num_addrs++;
+		}
+		else {
+			extra_params->addr_info[params->num_addrs] = bitmask;
+			params->num_addrs ++;
+		}
+		++macaddrs;
+	}
+
+	while (*macaddrs) {
+		printf("Ignoring excess parameter '%s' (maximum number of params is %d)\n",
+		       *macaddrs, WL_IOV_MAC_PARAM_LEN);
+		++macaddrs;
+	}
+
+	/* if no valid params found, pass default prefix 'C' with no mac address */
+	if (params->num_addrs == 0 && !loop_assoclist)
+	{
+		params->addr_type[0] = 'C';
+		extra_params->addr_info[0] = 0xFFFF;
+		params->num_addrs = 1;
+	}
+
+	if (params->num_addrs) {
+		/* set a "version" indication (ie extra_params present) */
+		params->num_addrs |= (4 << 8);
+
+
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, params,
+		                            sizeof(*params) + sizeof(*extra_params),
+		                            buf, WLC_IOCTL_MAXLEN)) < 0) {
+
+			fprintf(stderr, "Error getting variable %s\n", argv[0]);
+			return ret;
+		}
+
+		wl_txq_prec_dump((wl_iov_pktq_log_t*)buf, FALSE, corerev >= 40);
+
+	}
+	if (!loop_assoclist) {
+		return 0;
+	}
+
+	maclist = malloc(WLC_IOCTL_MEDLEN);
+
+	if (!maclist) {
+		fprintf(stderr, "unable to allocate memory\n");
+		return -ENOMEM;
+	}
+	maclist->count = htod32((WLC_IOCTL_MEDLEN - sizeof(int)) / ETHER_ADDR_LEN);
+
+	if ((ret = wlu_get(wl, WLC_GET_ASSOCLIST, maclist, WLC_IOCTL_MEDLEN)) < 0) {
+		fprintf(stderr, "Cannot get assoclist\n");
+		free(maclist);
+		return ret;
+	}
+	maclist->count = dtoh32(maclist->count);
+
+	if (maclist->count == 0) {
+		fprintf(stderr, "No available addresses in assoclist for automatic operation\n");
+		free(maclist);
+		return 0;
+	}
+
+	for (index = 0; index < loop_params.num_addrs; index++) {
+		uint32 ea_index = 0;
+
+		while (ea_index < maclist->count) {
+
+			memset(full_params, 0, sizeof(*full_params));
+
+			while ((params->num_addrs < WL_IOV_MAC_PARAM_LEN) &&
+			       (ea_index < maclist->count)) {
+
+				params->addr_type[params->num_addrs] = loop_params.addr_type[index];
+				params->ea[params->num_addrs] = maclist->ea[ea_index];
+				extra_params->addr_info[params->num_addrs] =
+					loop_extra_params.addr_info[index] | PKTQ_LOG_AUTO;
+
+				params->num_addrs++;
+				ea_index++;
+			}
+
+			/* set a "version" indication (ie extra_params present) */
+			params->num_addrs |= (4 << 8);
+
+			if ((ret = wlu_iovar_getbuf(wl, cmd->name, params,
+			                            sizeof(*params) + sizeof(*extra_params),
+			                            buf, WLC_IOCTL_MAXLEN)) < 0) {
+				fprintf(stderr, "Error getting %s\n", argv[0]);
+				free(maclist);
+				return ret;
+			}
+
+			wl_txq_prec_dump((wl_iov_pktq_log_t*)buf, TRUE, corerev >= 40);
+		}
+	}
+	free(maclist);
+	return 0;
+}
+
+static int
+wlu_dump(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char *dump_buf;
+	int bcmerr;
+
+	if (cmd->get < 0)
+		return -1;
+
+	dump_buf = malloc(WL_DUMP_BUF_LEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WL_DUMP_BUF_LEN);
+		return BCME_NOMEM;
+	}
+	memset(dump_buf, 0, WL_DUMP_BUF_LEN);
+
+	/* skip the command name */
+	argv++;
+
+	/* If no args given, get the subset of 'wl dump all'
+	 * Otherwise, if args are given, they are the dump section names.
+	 */
+	if (*argv == NULL) {
+		/* query for the 'dump' without any argument */
+		ret = wlu_iovar_getbuf(wl, "dump", NULL, 0, dump_buf, WL_DUMP_BUF_LEN);
+
+		/* if the query is successful, continue on and print the result. */
+
+		/* if the query fails, check for a legacy driver that does not support
+		 * the "dump" iovar, and instead issue a WLC_DUMP ioctl.
+		 */
+		if (ret) {
+			wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+			if (bcmerr == BCME_UNSUPPORTED) {
+				ret = wlu_get(wl, WLC_DUMP, dump_buf, WL_DUMP_BUF_LEN);
+				if (ret) {
+					fprintf(stderr, "dump: error on query of WLC_DUMP\n");
+				}
+			} else {
+				fprintf(stderr, "dump: error on query of dump list\n");
+			}
+		}
+	} else {
+		/* create the dump section name list */
+		while (*argv) {
+			/* add space delimiter if this is not the first section name */
+			if (dump_buf[0] != '\0')
+				strcat(dump_buf, " ");
+
+			strcat(dump_buf, *argv);
+
+			argv++;
+		}
+
+		/* This is a "space" added at end of last argument */
+		strcat(dump_buf, " ");
+
+		ret = wlu_iovar_getbuf(wl, "dump", dump_buf, strlen(dump_buf),
+		                      dump_buf, WL_DUMP_BUF_LEN);
+	}
+
+	if (!ret) {
+		fputs(dump_buf, stdout);
+	}
+
+	free(dump_buf);
+
+	return ret;
+}
+
+static int
+wlu_offloads_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char *dump_buf;
+	int bufsz = WL_DUMP_BUF_LEN;
+	bool cons_cmd = FALSE;
+
+	if (cmd->get < 0)
+		return -1;
+
+	if (!strcmp(cmd->name, "ol_clr"))
+	{
+		ret = wlu_iovar_get(wl, cmd->name, NULL, 0);
+		return ret;
+	}
+
+	if (!strcmp(cmd->name, "ol_cons")) {
+		/* Check for command */
+		if (*(argv + 1)) {
+			argv++;
+			cons_cmd = TRUE;
+			bufsz = CMDLINESZ;
+		}
+	}
+
+	dump_buf = malloc(bufsz);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", bufsz);
+		return -1;
+	}
+	memset(dump_buf, 0, bufsz);
+
+	while (*argv) {
+		/* add space delimiter if this is not the first section name */
+		if (dump_buf[0] != '\0')
+			strcat(dump_buf, " ");
+
+		strcat(dump_buf, *argv);
+
+		argv++;
+	}
+
+	if (cons_cmd) {
+		ret = wlu_iovar_set(wl, cmd->name, dump_buf, bufsz);
+	} else {
+		ret = wlu_iovar_get(wl, cmd->name, dump_buf, bufsz);
+		if (!ret)
+			fputs(dump_buf, stdout);
+	}
+
+	free(dump_buf);
+
+	return ret;
+}
+
+
+static int
+wl_staprio(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_USAGE_ERROR;
+	wl_staprio_cfg_t staprio_cfg;
+	char 	*endptr = NULL;
+
+	if (!*++argv) return -1;
+
+	/* get link mac address */
+	if (!wl_ether_atoe(*argv++, &staprio_cfg.ea))
+		goto error;
+
+	if (argv[0]) {
+		staprio_cfg.prio = (uint8)strtol(argv[0], &endptr, 0);
+		if (*endptr != '\0')
+			goto error;
+
+		if (staprio_cfg.prio > 3) {
+			printf("prio %d out of range [0, 3]\n", staprio_cfg.prio);
+			goto error;
+		}
+		else {
+			printf("Set SCB prio: 0x%x\n", staprio_cfg.prio);
+			ret = wlu_iovar_setbuf(wl, cmd->name, (void *) &staprio_cfg,
+				sizeof(wl_staprio_cfg_t), buf, WLC_IOCTL_MEDLEN);
+		}
+	}
+	else {
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, (void *) &staprio_cfg,
+			sizeof(wl_staprio_cfg_t), buf, WLC_IOCTL_MEDLEN)) >= 0) {
+			printf("SCB prio: 0x%x\n", ((wl_staprio_cfg_t *)buf)->prio);
+		}
+	}
+
+error:
+	return ret;
+}
+
+static int
+wl_aibss_bcn_force_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_USAGE_ERROR;
+	aibss_bcn_force_config_t bcn_config;
+
+	if (!*++argv) {
+		/* Get */
+		memset(&bcn_config, 0, sizeof(aibss_bcn_force_config_t));
+		/* get current rateset */
+		if ((ret = wlu_iovar_get(wl, cmd->name, &bcn_config,
+			sizeof(aibss_bcn_force_config_t))) < 0)
+			goto error;
+
+		printf("AIBSS Initial beacon check duration: %d \r\n"
+				"AIBSS beacon check duration:%d \r\n"
+				"AIBSS beacon flood duration:%d\r\n",
+				bcn_config.initial_min_bcn_dur, bcn_config.min_bcn_dur,
+				bcn_config.bcn_flood_dur);
+	}
+	else {
+		char *p = argv[0];
+		char *endptr = NULL;
+
+		/* Extract the content */
+		if (!p || *p == '\0')
+			goto error;
+
+		bcn_config.initial_min_bcn_dur = strtoul(p, &endptr, 0);
+
+		p = endptr;
+		/* check and skip , */
+		if (*p == '\0' || *++p == '\0')
+			goto error;
+
+		bcn_config.min_bcn_dur = strtoul(p, &endptr, 0);
+
+		p = endptr;
+		/* check and skip , */
+		if (*p == '\0' || *++p == '\0')
+			goto error;
+
+		bcn_config.bcn_flood_dur = strtoul(p, &endptr, 0);
+
+		if (*endptr != '\0')
+			goto error;
+		bcn_config.version = AIBSS_BCN_FORCE_CONFIG_VER_0;
+		bcn_config.len = sizeof(aibss_bcn_force_config_t);
+		ret = wlu_iovar_set(wl, cmd->name, (void *) &bcn_config,
+			sizeof(aibss_bcn_force_config_t));
+	}
+
+error:
+	return ret;
+}
+
+
+static int
+wlu_srdump(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i, nw, nb = 0;
+	uint16 *words = (uint16 *)&buf[8];
+
+	srom_rw_t   *srt;
+
+	/* srom has been expanded a few times, at the moment sromrev11 are the largest */
+	nw = SROM11_WORDS;
+
+	/* allow reading a larger (or any other-size one) if specified */
+	if (*++argv != NULL) {
+		nb = (int)strtol(*argv, NULL, 0);
+		if (nb & 1) {
+			printf("Byte count %d is odd\n", nb);
+			return BCME_BADARG;
+		}
+		nw = nb / 2;
+	}
+
+	srt = (srom_rw_t *)buf;
+	srt->byteoff = htod32(0);
+	srt->nbytes = htod32(2 * nw);
+
+	if (cmd->get < 0)
+		return -1;
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	if (words[SROM11_SIGN] == SROM11_SIGNATURE) {
+		nw = SROM11_WORDS;
+	} else if (words[SROM10_SIGN] == SROM4_SIGNATURE) {
+		nw = SROM10_WORDS;
+	} else {
+		nw = SROM4_WORDS;
+		if ((words[SROM4_SIGN] != SROM4_SIGNATURE) &&
+			(words[SROM8_SIGN] != SROM4_SIGNATURE))
+			nw = nb ? nw : SROM_WORDS;
+	}
+	for (i = 0; i < nw; i++) {
+		if ((i % 8) == 0)
+			printf("\n  srom[%03d]:  ", i);
+		printf("0x%04x  ", words[i]);
+	}
+	printf("\n");
+
+	return 0;
+}
+
+static int
+wlu_srwrite(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#else
+	char *arg;
+	char *endptr;
+	FILE *fp = NULL;
+	int ret = 0, erase, srcrc;
+	uint i, len;
+	srom_rw_t *srt = (srom_rw_t *)buf;
+
+	erase = !strcmp(*argv, "srclear");
+	srcrc = !strcmp(*argv, "srcrc");
+
+	/* We need at least one arg */
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	arg = *argv++;
+
+	if (erase) {
+		if (*argv)
+			return BCME_USAGE_ERROR;
+		len = strtoul(arg, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "error parsing value \"%s\" as an integer for byte count\n",
+			        arg);
+			return BCME_USAGE_ERROR;
+		}
+		srt->byteoff = 0x55aa;
+	} else if (!*argv) {  /* srwrite or srcrc */
+		/* Only one arg, it better be a file name */
+		if (!(fp = fopen(arg, "rb"))) {
+			fprintf(stderr, "%s: No such file or directory\n", arg);
+			return BCME_BADARG;
+		}
+
+		len = fread(srt->buf, 1, SROM_MAX + 1, fp);
+		if ((ret = ferror(fp))) {
+			printf("\nerror %d reading %s\n", ret, arg);
+			ret = BCME_ERROR;
+			goto out;
+		}
+
+		if (!feof(fp)) {
+			printf("\nFile %s is too large\n", arg);
+			ret = BCME_ERROR;
+			goto out;
+		}
+
+		if (len == SROM4_WORDS * 2) {
+			if ((srt->buf[SROM4_SIGN] != SROM4_SIGNATURE) &&
+			    (srt->buf[SROM8_SIGN] != SROM4_SIGNATURE)) {
+				printf("\nFile %s is %d bytes but lacks a REV4/ signature\n",
+				       arg, SROM4_WORDS * 2);
+				ret = BCME_ERROR;
+				goto out;
+			}
+		} else if (len == SROM11_WORDS * 2) {
+			if (srt->buf[SROM11_SIGN] != SROM11_SIGNATURE) {
+				printf("\nFile %s is %d bytes but lacks a REV11/ signature\n",
+				       arg, SROM11_WORDS * 2);
+				ret = BCME_ERROR;
+				goto out;
+			}
+		} else if ((len != SROM_WORDS * 2) && (len != SROM10_WORDS * 2) &&
+			(len != SROM_MAX)) {
+			printf("\nFile %s is %d bytes, not %d or %d or %d or %d bytes\n", arg, len,
+				SROM_WORDS * 2, SROM4_WORDS * 2, SROM10_WORDS, SROM_MAX);
+			ret = BCME_ERROR;
+			goto out;
+		}
+
+		srt->byteoff = 0;
+	} else {
+		if (srcrc) {
+			printf("srcrc only takes one arg\n");
+			ret = BCME_USAGE_ERROR;
+			goto out;
+		}
+
+		/* More than 1 arg, first is offset, rest are data. */
+		srt->byteoff = strtoul(arg, &endptr, 0);
+		if (*endptr != '\0')
+			goto nout;
+
+		i = 0;
+		while ((arg = *argv++) != NULL) {
+			srt->buf[i++] = (uint16)strtoul(arg, &endptr, 0);
+			if (*endptr != '\0') {
+nout:
+				printf("\n%s is not an integer\n", arg);
+				ret = BCME_USAGE_ERROR;
+				goto out;
+			}
+		}
+
+		if (srt->byteoff & 1) {
+			printf("Byte offset (%d) is odd or negative\n", srt->byteoff);
+			ret = BCME_BADARG;
+			goto out;
+		}
+
+		len = 2 * i;
+		if ((srt->byteoff + len) > SROM_MAX) {
+			printf("Data extends past %d bytes\n", SROM_MAX);
+			ret = BCME_BUFTOOLONG;
+			goto out;
+		}
+	}
+	srt->nbytes = len;
+
+	if (srcrc) {
+		srt->byteoff = 0x55ab;	/* Hack for srcrc */
+		if ((ret = wlu_get(wl, cmd->get, buf, len + 8)) == 0)
+			printf("0x%x\n", (uint8)buf[0]);
+	} else {
+		printf("Writing srom. ioctl %d, iolen %d, sroff %d, len %d\n",
+		        cmd->set, len + 8, srt->byteoff, srt->nbytes);
+
+		ret = wlu_set(wl, cmd->set, buf, len + 8);
+	}
+
+out:
+	fflush(stdout);
+	if (fp)
+		fclose(fp);
+	return ret;
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+wlu_ciswrite(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#else
+	char *arg, *bufp;
+	FILE *fp = NULL;
+	int ret = 0;
+	uint32 len;
+
+	cis_rw_t cish;
+	char *cisp, *cisdata;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* We need extacly one arg */
+	if (!*++argv || argv[1])
+		return BCME_USAGE_ERROR;
+
+	/* initialize buffer with iovar */
+	bufp = buf;
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(bufp, "ciswrite");
+	bufp += strlen("ciswrite") + 1;
+	cisp = bufp;
+	cisdata = cisp + sizeof(cish);
+
+	cish.source = htod32(0);
+
+	/* grab the filename arg */
+	arg = *argv;
+	if (!(fp = fopen(arg, "rb"))) {
+		fprintf(stderr, "%s: No such file or directory\n", arg);
+		return BCME_BADARG;
+	}
+
+	len = fread(cisdata, 1, SROM_MAX + 1, fp);
+	if ((ret = ferror(fp))) {
+		printf("\nerror %d reading %s\n", ret, arg);
+		ret = BCME_ERROR;
+		goto out;
+	}
+
+	if (!feof(fp)) {
+		printf("\nFile %s is too large\n", arg);
+		ret = BCME_ERROR;
+		goto out;
+	}
+
+	/* fill in offset and length */
+	cish.byteoff = htod32(0);
+	cish.nbytes = htod32(len);
+	memcpy(cisp, (char*)&cish, sizeof(cish));
+
+	printf("len %d sizeof(cish) %d total %d\n", len, (int)sizeof(cish),
+	       (int)(len + sizeof(cish)));
+	ret = wl_set(wl, WLC_SET_VAR, buf, (cisp - buf) + sizeof(cish) + len);
+	if (ret < 0) {
+		fprintf(stderr, "ciswrite failed: %d\n", ret);
+	}
+
+out:
+	if (fp)
+		fclose(fp);
+
+	return ret;
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+wlu_cisupdate(void *wl, cmd_t *cmd, char **argv)
+{
+	char *bufp, *endptr;
+	int ret = 0;
+	int preview = 0;
+	uint32 off;
+	uint32 len;
+	uint32 updatelen;
+	uint32 i;
+	char hexstr[3];
+	char bytes[SROM_MAX];
+
+	cis_rw_t cish;
+	char *cisp;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* validate arg count */
+	if (!*++argv || !argv[1])
+		return BCME_USAGE_ERROR;
+
+	if (argv[2] && !strcmp(argv[2], "--preview"))
+		preview = 1;
+
+	/* grab byte offset */
+	off = (uint32)strtol(argv[0], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+
+	bufp = argv[1];
+	updatelen = strlen(bufp);
+	if (updatelen % 2) {
+		fprintf(stderr, "cisupdate hex string must contain an even number of digits\n");
+		goto done;
+	}
+	updatelen /= 2;
+
+	/* convert and store hex byte values */
+	for (i = 0; i < updatelen; i++) {
+		hexstr[0] = *bufp;
+		hexstr[1] = *(bufp + 1);
+		if (!isxdigit((int)hexstr[0]) || !isxdigit((int)hexstr[1])) {
+			fprintf(stderr, "cisupdate invalid hex digit(s) in %s\n", argv[1]);
+			goto done;
+		}
+		hexstr[2] = '\0';
+		bytes[i] = (char) strtol(hexstr, NULL, 16);
+		bufp += 2;
+	}
+
+	/* Prepare the read info */
+	cish.source = 0;
+	cish.byteoff = 0;
+	cish.nbytes = 0;
+
+	/* set up the buffer and do the get (+9 allows space for "ciswrite" string later) */
+	memset(buf + 9, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf + 9, "cisdump");
+	bufp = buf + strlen("cisdump") + 1 + 9;
+	memcpy(bufp, (char*)&cish, sizeof(cish));
+	bufp += sizeof(cish);
+	ret = wl_get(wl, WLC_GET_VAR, buf + 9, (bufp - (buf + 9)) + SROM_MAX);
+	if (ret < 0) {
+		fprintf(stderr, "cisupdate failed to read cis: %d\n", ret);
+		goto done;
+	}
+
+	/* pull off the cis_rw_t */
+	bufp = buf + 9;
+	memcpy((char*)&cish, bufp, sizeof(cish));
+	len = dtoh32(cish.nbytes);
+
+	if ((off + updatelen) > len) {
+		fprintf(stderr, "cisupdate offset %d plus update len %d exceeds CIS len %d\n",
+		        off, updatelen, len);
+		goto done;
+	}
+
+	/* move past to the data */
+	bufp += sizeof(cish);
+
+	/* update the bytes */
+	if (cish.source == WLC_CIS_SROM) {
+		for (i = 0; i < updatelen; ++i)
+			bufp[off + i] = bytes[i] & 0xff;
+	} else {
+		for (i = 0; i < updatelen; ++i) {
+			if (~bytes[i] & bufp[off + i]) {
+				fprintf(stderr, "cisupdate: OTP update incompatible:"
+				        " update[%d](0x%02x)->cis[%d](0x%02x)\n",
+				        i,  bytes[i], off + i, bufp[off + i]);
+				goto done;
+			}
+			bufp[off + i] |= bytes[i];
+		}
+	}
+
+	/* initialize buffer with iovar */
+	bufp = buf;
+	strcpy(bufp, "ciswrite");
+	bufp += strlen("ciswrite") + 1;
+	cisp = bufp;
+
+	/* fill in cis_rw_t fields */
+	cish.source = 0;
+	cish.byteoff = 0;
+	cish.nbytes = htod32(len);
+	memcpy(cisp, (char*)&cish, sizeof(cish));
+
+	/* write the data back to the device */
+	printf("offset %d data %s cislen %d\n", off, argv[1], len);
+	if (preview) {
+		bufp += sizeof(cish);
+		for (i = 0; i < len; i++) {
+			if ((i % 8) == 0)
+				printf("\nByte %3d: ", i);
+			printf("0x%02x ", (uint8)bufp[i]);
+		}
+		printf("\n");
+	} else {
+		ret = wl_set(wl, WLC_SET_VAR, buf, (cisp - buf) + sizeof(cish) + len);
+		if (ret < 0) {
+			fprintf(stderr, "cisupdate cis write failed: %d\n", ret);
+		}
+	}
+
+done:
+	return ret;
+}
+
+static int
+wlu_cisdump(void *wl, cmd_t *cmd, char **argv)
+{
+	char *bufp;
+	int i, ret = 0;
+	cis_rw_t cish;
+	uint nbytes = 0;
+	char *fname = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Grab and move past optional output file argument */
+	if ((argv[1] != NULL) && (strcmp(argv[1], "-b") == 0)) {
+		fname = argv[2];
+		argv += 2;
+	}
+
+	/* check for a length argument */
+	if (*++argv != NULL) {
+		nbytes = (int)strtol(*argv, NULL, 0);
+		if (nbytes & 1) {
+			printf("Invalid byte count %d, must be even\n", nbytes);
+			ret = BCME_BADARG;
+			goto done;
+		}
+		if (nbytes > SROM_MAX) {
+			printf("Count %d too large\n", nbytes);
+			ret = BCME_BUFTOOLONG;
+			goto done;
+		}
+	}
+
+	/* Prepare the read info */
+	cish.source = 0;
+	cish.byteoff = 0;
+	cish.nbytes = htod32(nbytes);
+
+	/* set up the buffer and do the get */
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "cisdump");
+	bufp = buf + strlen("cisdump") + 1;
+	memcpy(bufp, (char*)&cish, sizeof(cish));
+	bufp += sizeof(cish);
+	ret = wl_get(wl, WLC_GET_VAR, buf, (bufp - buf) + (nbytes ? nbytes : SROM_MAX));
+	if (ret < 0) {
+		fprintf(stderr, "Failed cisdump request: %d\n", ret);
+		goto done;
+	}
+
+	/* pull off the cis_rw_t */
+	bufp = buf;
+	memcpy((char*)&cish, bufp, sizeof(cish));
+	cish.source = dtoh32(cish.source);
+	cish.byteoff = dtoh32(cish.byteoff);
+	cish.nbytes = dtoh32(cish.nbytes);
+
+	/* move past to the data */
+	bufp += sizeof(cish);
+
+	printf("Source: %d (%s)", cish.source,
+	       (cish.source == WLC_CIS_DEFAULT) ? "Built-in default" :
+	       (cish.source == WLC_CIS_SROM) ? "External SPROM" :
+	       (cish.source == WLC_CIS_OTP) ? "Internal OTP" : "Unknown?");
+	if (!nbytes)
+		printf("\nMaximum length: %d bytes", cish.nbytes);
+	for (i = 0; i < (int)cish.nbytes; i++) {
+		if ((i % 8) == 0)
+			printf("\nByte %3d: ", i);
+		printf("0x%02x ", (uint8)bufp[i]);
+	}
+	printf("\n");
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+	if (fname != NULL) {
+		FILE *fp;
+
+		if (!nbytes)
+			nbytes = cish.nbytes;
+
+		fp = fopen(fname, "wb");
+		if (fp != NULL) {
+			ret = fwrite(bufp, 1, nbytes, fp);
+			if (ret != (int)nbytes) {
+				fprintf(stderr, "Error writing %d bytes to file, rc %d!\n",
+				        (int)nbytes, ret);
+				ret = BCME_ERROR;
+			} else {
+				printf("Wrote %d bytes to %s\n", ret, fname);
+				ret = 0;
+			}
+			fclose(fp);
+		} else {
+			fprintf(stderr, "Problem opening file %s\n", fname);
+			ret = BCME_BADARG;
+		}
+	}
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+
+done:
+	return ret;
+}
+
+/* linux, MacOS, NetBSD: ffs is in the standard C library */
+/* CFE, HNDRTE & IOPOS: Not needed, the code below is ifdef out */
+
+
+/* VX wants prototypes even for static functions. */
+static char* find_pattern(char **argv, const char *pattern, uint *val);
+static char* find_pattern2(char **argv, const char *pattern, uint *val, int vnum);
+static int newtuple(char *b, int *cnt, uint8 tag, const cis_tuple_t *srv);
+static int parsecis(char *b, char **argv, int sromrev);
+static const sromvar_t *srvlookup(const sromvar_t *tab, char *name, int nlen, int sromrev);
+
+/* Find an entry in argv[][] in this form
+ *	name=value, could be pattern=(0x)1234 or pattern=ABC
+ *
+ * If *val is NULL, return the pointer to value.
+ * If *val is not NULL, fill the value into val, return the pointer to name if found,
+ * return NULL if no match found.
+ */
+static char*
+find_pattern(char **argv, const char *pattern, uint *val)
+{
+	char *ret = NULL, *name = NULL, **pargv = argv;
+
+	/* clear val first */
+	if (val)	*val = 0;
+
+	while ((name = *pargv++)) {
+		if ((ret = strstr(name, pattern))) {
+			char *p = ret, *q = NULL;
+
+			/* Extracting the content */
+			p += strlen(pattern);
+
+			/* var name could have same prefix */
+			if (*p++ != '=') {
+				ret = NULL;
+				continue;
+			}
+			if (!val)
+				return (ret+strlen(pattern)+1);
+
+			*val = strtoul(p, &q, 0);
+			if (p == q) {
+				printf("Bad value: %s\n", ret);
+				return NULL;
+			}
+
+			break;
+		}
+	}
+	return ret;
+}
+
+/* Find an entry in argv[][] in this form
+ *	name=value1,value2,...,value(n)
+ *		n is indicated by vnum
+ * 		could be pattern=(0x)1234,... or pattern=ABC,...
+ *
+ * If *val is NULL, return the pointer to value.
+ * If *val is not NULL, fill the value into val, return the pointer to name if found,
+ * return NULL if no match found.
+ */
+static char*
+find_pattern2(char **argv, const char *pattern, uint *val, int vnum)
+{
+	char *ret = NULL, *name = NULL, **pargv = argv;
+	int i;
+
+	while ((name = *pargv++)) {
+		if ((ret = strstr(name, pattern))) {
+			char *p = ret, *q = NULL;
+
+			/* Extracting the content */
+			p += strlen(pattern);
+
+			/* var name could have same prefix */
+			if (*p++ != '=') {
+				ret = NULL;
+				continue;
+			}
+			if (!val)
+				return (ret+strlen(pattern)+1);
+
+			for (i = 0; i < vnum; i ++)
+			{
+				val[i] = strtoul(p, &q, 0);
+
+				if (p == q) {
+					printf("Bad value: %s\n", ret);
+					return NULL;
+				}
+				p = q + 1;	/* skip ',' */
+			}
+			break;
+		}
+	}
+	return ret;
+}
+
+static int
+newtuple(char *b, int *cnt, uint8 tag, const cis_tuple_t *srv)
+{
+	memset(b, 0, srv->len + 2);
+
+	b[0] = tag;
+	b[1] = (char)srv->len;
+	b[2] = (char)srv->tag;
+
+	if (cnt)
+		*cnt += 3;
+	return 0;
+}
+
+/**
+ * When programming OTP or SROM, driver expects to receive a CIS from the wl utility.
+ * This function converts a caller supplied string (in **argv) containing nvram variables pairs into
+ * a CIS (in *b). Caller can dictate the binary CIS contents  by using nvram string 'RAW=...' or
+ * 'RAW1=...'. Function will only create tuples for values in caller supplied nvram string.
+ */
+static int
+parsecis(char *b, char **argv, int sromrev)
+{
+	/* built-in list of known tuples and nvram var(s) associated with a specific tuple */
+	const cis_tuple_t *srv = cis_hnbuvars;
+	char	*cpar = NULL, *p = NULL;
+	char	*par;
+	char	delimit[2] = " \0";
+	int	cnt = 0, i = 0;
+	uint 	sromrev_mask = 0xffffffff;
+
+	if (sromrev > 0 && sromrev <= 31) {
+		sromrev_mask = 1 << sromrev;
+	} else {
+		printf("Invalid sromrev %d.\n", sromrev);
+		return BCME_BADARG;
+	}
+
+	/* Walk through built-in list of tuples, create append buffer */
+	while (srv->tag != 0xFF) {
+		uint val = 0;
+
+		/* Skip srv if not supported in sromrev */
+		if (!(sromrev_mask & srv->revmask)) {
+			srv++;
+			continue;
+		}
+
+		/* Special cases (Raw Data / macaddr / ccode / fem) */
+		if (srv->tag == OTP_RAW) {
+			if ((p = find_pattern(argv, "RAW", &val))) {
+				p += (strlen("RAW") + 1);	/* RAW= */
+				for (;;) {
+					b[cnt++] = (unsigned char) strtoul(p, &p, 16);
+					if (!*p++)
+						break;
+				}
+			}
+		} else if (srv->tag == OTP_RAW1) {
+			if ((p = find_pattern(argv, "RAW1", NULL))) {
+				for (;;) {
+					b[cnt++] = (unsigned char) strtoul(p, &p, 16);
+					if (!*p++)
+						break;
+				}
+			}
+		} else if (srv->tag == OTP_VERS_1) {
+			uint l1 = 1, l2 = 1;
+			char *p2 = NULL;
+
+			if ((p = find_pattern(argv, "manf", NULL)))
+				l1 += strlen(p);
+
+			if ((p2 = find_pattern(argv, "productname", NULL)))
+				l2 += strlen(p2);
+
+			if ((p != NULL) | (p2 != NULL)) {
+				b[cnt++] = CISTPL_VERS_1;
+				b[cnt++] = 2 + l1 + l2;
+				b[cnt++] = 8;
+				b[cnt++] = 0;
+				if (p) {
+					char *q = p;
+					/* Replace '_' by space */
+					while ((q = strchr(q, '_')))
+						*q = ' ';
+					memcpy(&b[cnt], p, l1);
+				} else
+					b[cnt] = '\0';
+				cnt += l1;
+
+				if (p2) {
+					char *q = p2;
+					/* Replace '_' by space */
+					while ((q = strchr(q, '_')))
+						*q = ' ';
+					memcpy(&b[cnt], p2, l2);
+				} else
+					b[cnt] = '\0';
+				cnt += l2;
+			}
+		} else if (srv->tag == OTP_MANFID) {
+			bool found = FALSE;
+			uint manfid = 0, prodid = 0;
+
+			if ((p = find_pattern(argv, "manfid", &manfid)))
+				found = TRUE;
+
+			if ((p = find_pattern(argv, "prodid", &prodid)))
+				found = TRUE;
+
+			if (found) {
+				b[cnt++] = CISTPL_MANFID;
+				b[cnt++] = srv->len;
+				b[cnt++] = (uint8)(manfid & 0xff);
+				b[cnt++] = (uint8)((manfid >> 8) & 0xff);
+				b[cnt++] = (uint8)(prodid & 0xff);
+				b[cnt++] = (uint8)((prodid >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_MACADDR) {
+			if ((p = find_pattern(argv, "macaddr", NULL))) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				if (!wl_ether_atoe(p, (struct ether_addr*)&b[cnt]))
+					printf("Argument does not look like a MAC "
+					"address: %s\n", p);
+				cnt += sizeof(struct ether_addr);
+			}
+		} else if (srv->tag == HNBU_CCODE) {
+			bool found = FALSE;
+			char tmp[3] = "\0\0\0";
+
+			if ((p = find_pattern(argv, "ccode", NULL))) {
+				found = TRUE;
+				tmp[0] = *p++;
+				tmp[1] = *p++;
+			}
+			if ((p = find_pattern(argv, "cctl", &val))) {
+				found = TRUE;
+				tmp[2] = (uint8)val;
+			}
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 3);
+				cnt += 3;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_RSSISMBXA2G) {
+			bool found = FALSE;
+			char tmp[2] = "\0\0";
+
+			if ((p = find_pattern(argv, "rssismf2g", &val))) {
+				found = TRUE;
+				tmp[0] |= val & 0xf;
+			}
+			if ((p = find_pattern(argv, "rssismc2g", &val))) {
+				found = TRUE;
+				tmp[0] |= (val & 0xf) << 4;
+			}
+			if ((p = find_pattern(argv, "rssisav2g", &val))) {
+				found = TRUE;
+				tmp[1] |= val & 0x7;
+			}
+			if ((p = find_pattern(argv, "bxa2g", &val))) {
+				found = TRUE;
+				tmp[1] |= (val & 0x3) << 3;
+			}
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 2);
+				cnt += 2;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_RSSISMBXA5G) {
+			bool found = FALSE;
+			char tmp[2] = "\0\0";
+
+			if ((p = find_pattern(argv, "rssismf5g", &val))) {
+				found = TRUE;
+				tmp[0] |= val & 0xf;
+			}
+			if ((p = find_pattern(argv, "rssismc5g", &val))) {
+				found = TRUE;
+				tmp[0] |= (val & 0xf) << 4;
+			}
+			if ((p = find_pattern(argv, "rssisav5g", &val))) {
+				found = TRUE;
+				tmp[1] |= val & 0x7;
+			}
+			if ((p = find_pattern(argv, "bxa5g", &val))) {
+				found = TRUE;
+				tmp[1] |= (val & 0x3) << 3;
+			}
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 2);
+				cnt += 2;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_FEM) {
+			bool	found = FALSE;
+			uint16	tmp2g = 0, tmp5g = 0;
+
+			if ((p = find_pattern(argv, "antswctl2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_ANTSWLUT_SHIFT) &
+					SROM8_FEM_ANTSWLUT_MASK);
+			}
+			if ((p = find_pattern(argv, "triso2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_TR_ISO_SHIFT) &
+					SROM8_FEM_TR_ISO_MASK);
+			}
+			if ((p = find_pattern(argv, "pdetrange2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_PDET_RANGE_SHIFT) &
+					SROM8_FEM_PDET_RANGE_MASK);
+			}
+			if ((p = find_pattern(argv, "extpagain2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_EXTPA_GAIN_SHIFT) &
+					SROM8_FEM_EXTPA_GAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssipos2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_TSSIPOS_SHIFT) &
+					SROM8_FEM_TSSIPOS_MASK);
+			}
+			if ((p = find_pattern(argv, "antswctl5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_ANTSWLUT_SHIFT) &
+					SROM8_FEM_ANTSWLUT_MASK);
+			}
+			if ((p = find_pattern(argv, "triso5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_TR_ISO_SHIFT) &
+					SROM8_FEM_TR_ISO_MASK);
+			}
+			if ((p = find_pattern(argv, "pdetrange5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_PDET_RANGE_SHIFT) &
+					SROM8_FEM_PDET_RANGE_MASK);
+			}
+			if ((p = find_pattern(argv, "extpagain5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_EXTPA_GAIN_SHIFT) &
+					SROM8_FEM_EXTPA_GAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssipos5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_TSSIPOS_SHIFT) &
+					SROM8_FEM_TSSIPOS_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(tmp2g & 0xff);
+				b[cnt++] = (uint8)((tmp2g >> 8) & 0xff);
+				b[cnt++] = (uint8)(tmp5g & 0xff);
+				b[cnt++] = (uint8)((tmp5g >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_UUID) {
+
+			char *uuidstr = NULL;
+			char nibble[3] = {0, 0, 0};
+
+			if ((uuidstr = find_pattern(argv, "uuid", NULL)) != NULL) {
+
+				/* uuid format 12345678-1234-5678-1234-567812345678 */
+
+				if (strlen(uuidstr) == 36) {
+					newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+					while (*uuidstr != '\0') {
+						if (*uuidstr == '-') {
+							uuidstr++;
+							continue;
+						}
+						nibble[0] = *uuidstr++;
+						nibble[1] = *uuidstr++;
+						b[cnt ++] = (char)strtoul(nibble, NULL, 16);
+					}
+				}
+			}
+
+		} else if (srv->tag == HNBU_TEMPTHRESH) {
+			bool found = FALSE;
+			char tmp[6] = "\0\0\0\0\0\0";
+
+			if ((p = find_pattern(argv, "tempthresh", &val))) {
+				found = TRUE;
+				tmp[0] = val;
+			}
+			if ((p = find_pattern(argv, "temps_period", &val))) {
+				found = TRUE;
+				tmp[1] |= ((val << SROM11_TEMPS_PERIOD_SHIFT) &
+					SROM11_TEMPS_PERIOD_MASK);
+			}
+			if ((p = find_pattern(argv, "temps_hysteresis", &val))) {
+				found = TRUE;
+				tmp[1] |= ((val << SROM11_TEMPS_HYSTERESIS_SHIFT) &
+					SROM11_TEMPS_HYSTERESIS_MASK);
+			}
+			if ((p = find_pattern(argv, "tempoffset", &val))) {
+				found = TRUE;
+				tmp[2] = val;
+			}
+			if ((p = find_pattern(argv, "tempsense_slope", &val))) {
+				found = TRUE;
+				tmp[3] = val;
+			}
+			if ((p = find_pattern(argv, "tempcorrx", &val))) {
+				found = TRUE;
+				tmp[4] |= ((val << SROM11_TEMPCORRX_SHIFT) &
+					SROM11_TEMPCORRX_MASK);
+			}
+			if ((p = find_pattern(argv, "tempsense_option", &val))) {
+				found = TRUE;
+				tmp[4] |= ((val << SROM11_TEMPSENSE_OPTION_SHIFT) &
+					SROM11_TEMPSENSE_OPTION_MASK);
+			}
+			if ((p = find_pattern(argv, "phycal_tempdelta", &val))) {
+				found = TRUE;
+				tmp[5] = val;
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 6);
+				cnt += 6;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_FEM_CFG) {
+			bool found = FALSE;
+			uint16	fem_cfg1 = 0, fem_cfg2 = 0;
+
+			if ((p = find_pattern(argv, "femctrl", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_FEMCTRL_SHIFT) &
+					SROM11_FEMCTRL_MASK);
+			}
+			if ((p = find_pattern(argv, "papdcap2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_PAPDCAP_SHIFT) &
+					SROM11_PAPDCAP_MASK);
+			}
+			if ((p = find_pattern(argv, "tworangetssi2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_TWORANGETSSI_SHIFT) &
+					SROM11_TWORANGETSSI_MASK);
+			}
+			if ((p = find_pattern(argv, "pdgain2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_PDGAIN_SHIFT) &
+					SROM11_PDGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "epagain2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_EPAGAIN_SHIFT) &
+					SROM11_EPAGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssiposslope2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_TSSIPOSSLOPE_SHIFT) &
+					SROM11_TSSIPOSSLOPE_MASK);
+			}
+			if ((p = find_pattern(argv, "gainctrlsph", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_GAINCTRLSPH_SHIFT) &
+					SROM11_GAINCTRLSPH_MASK);
+			}
+			if ((p = find_pattern(argv, "papdcap5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_PAPDCAP_SHIFT) &
+					SROM11_PAPDCAP_MASK);
+			}
+			if ((p = find_pattern(argv, "tworangetssi5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_TWORANGETSSI_SHIFT) &
+					SROM11_TWORANGETSSI_MASK);
+			}
+			if ((p = find_pattern(argv, "pdgain5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_PDGAIN_SHIFT) &
+					SROM11_PDGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "epagain5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_EPAGAIN_SHIFT) &
+					SROM11_EPAGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssiposslope5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_TSSIPOSSLOPE_SHIFT) &
+					SROM11_TSSIPOSSLOPE_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(fem_cfg1 & 0xff);
+				b[cnt++] = (uint8)((fem_cfg1 >> 8) & 0xff);
+				b[cnt++] = (uint8)(fem_cfg2 & 0xff);
+				b[cnt++] = (uint8)((fem_cfg2 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_ACRXGAINS_C0) {
+			bool found = FALSE;
+			uint16	rxgains = 0, rxgains1 = 0;
+
+			if ((p = find_pattern(argv, "rxgains5gtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gtrisoa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRISOA_SHIFT) &
+					SROM11_RXGAINS5GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gelnagaina0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS2GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrisoa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRISOA_SHIFT) &
+					SROM11_RXGAINS2GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gelnagaina0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS2GELNAGAINA_MASK);
+			}
+
+			if ((p = find_pattern(argv, "rxgains5ghtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GHTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghtrisoa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRISOA_SHIFT) &
+					SROM11_RXGAINS5GHTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghelnagaina0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GHELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GMTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrisoa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRISOA_SHIFT) &
+					SROM11_RXGAINS5GMTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmelnagaina0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GMELNAGAINA_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(rxgains & 0xff);
+				b[cnt++] = (uint8)((rxgains >> 8) & 0xff);
+				b[cnt++] = (uint8)(rxgains1 & 0xff);
+				b[cnt++] = (uint8)((rxgains1 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_ACRXGAINS_C1) {
+			bool found = FALSE;
+			uint16	rxgains = 0, rxgains1 = 0;
+
+			if ((p = find_pattern(argv, "rxgains5gtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gtrisoa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRISOA_SHIFT) &
+					SROM11_RXGAINS5GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gelnagaina1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS2GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrisoa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRISOA_SHIFT) &
+					SROM11_RXGAINS2GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gelnagaina1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS2GELNAGAINA_MASK);
+			}
+
+			if ((p = find_pattern(argv, "rxgains5ghtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GHTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghtrisoa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRISOA_SHIFT) &
+					SROM11_RXGAINS5GHTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghelnagaina1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GHELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GMTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrisoa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRISOA_SHIFT) &
+					SROM11_RXGAINS5GMTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmelnagaina1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GMELNAGAINA_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(rxgains & 0xff);
+				b[cnt++] = (uint8)((rxgains >> 8) & 0xff);
+				b[cnt++] = (uint8)(rxgains1 & 0xff);
+				b[cnt++] = (uint8)((rxgains1 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_ACRXGAINS_C2) {
+			bool found = FALSE;
+			uint16	rxgains = 0, rxgains1 = 0;
+
+			if ((p = find_pattern(argv, "rxgains5gtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gtrisoa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRISOA_SHIFT) &
+					SROM11_RXGAINS5GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gelnagaina2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS2GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrisoa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRISOA_SHIFT) &
+					SROM11_RXGAINS2GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gelnagaina2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS2GELNAGAINA_MASK);
+			}
+
+			if ((p = find_pattern(argv, "rxgains5ghtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GHTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghtrisoa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRISOA_SHIFT) &
+					SROM11_RXGAINS5GHTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghelnagaina2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GHELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GMTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrisoa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRISOA_SHIFT) &
+					SROM11_RXGAINS5GMTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmelnagaina2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GMELNAGAINA_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(rxgains & 0xff);
+				b[cnt++] = (uint8)((rxgains >> 8) & 0xff);
+				b[cnt++] = (uint8)(rxgains1 & 0xff);
+				b[cnt++] = (uint8)((rxgains1 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_PDOFF_2G) {
+			bool	found = FALSE;
+			uint16	tmppdoff2g = 0;
+
+			if ((p = find_pattern(argv, "pdoffset2g40ma0", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_A0_SHIFT) &
+					SROM11_PDOFF_2G_40M_A0_MASK);
+			}
+
+			if ((p = find_pattern(argv, "pdoffset2g40ma1", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_A1_SHIFT) &
+					SROM11_PDOFF_2G_40M_A1_MASK);
+			}
+
+			if ((p = find_pattern(argv, "pdoffset2g40ma2", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_A2_SHIFT) &
+					SROM11_PDOFF_2G_40M_A2_MASK);
+			}
+
+			if ((p = find_pattern(argv, "pdoffset2g40mvalid", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_VALID_SHIFT) &
+					SROM11_PDOFF_2G_40M_VALID_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(tmppdoff2g & 0xff);
+				b[cnt++] = (uint8)((tmppdoff2g >> 8) & 0xff);
+			}
+		} else {	/* All other tuples */
+			int	found = FALSE, varlen = 0;
+			char	*cur = &b[cnt];
+			uint	newtp = TRUE;
+
+			/* example srv->params contents: "1aa2g 1aa5g" */
+			par = malloc(strlen(srv->params)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			/* Walk through each parameters in one tuple */
+			strcpy(par, srv->params);
+
+			cpar = strtok (par, delimit);	/* current param */
+			while (cpar) {
+				int	array_sz = 1;
+				val = 0;
+
+				/* Fill the CIS tuple to b but don't commit cnt yet */
+				if (newtp) {
+					newtuple(cur, NULL, CISTPL_BRCM_HNBU, srv);
+					cur += 3;
+					newtp = FALSE;
+				}
+
+				/* the first byte of each parameter indicates its length */
+				varlen = (*cpar++) - '0';
+
+				/* parse array size if any */
+				if (*cpar == '*') {
+					array_sz = 0;
+					while (((*++cpar) >= '0') && (*cpar <= '9'))
+						array_sz = (array_sz * 10) + *cpar - '0';
+				}
+
+				/* Find the parameter in the input argument list */
+				if ((p = find_pattern(argv, cpar, &val)))
+					found = TRUE;
+				else
+					val = 0;
+
+				while (found && array_sz--) {
+					*cur++ = (uint8)(val & 0xff);
+					if (varlen >= 2)
+						*cur++ = (uint8)((val >> 8) & 0xff);
+					if (varlen >= 4) {
+						*cur++ = (uint8)((val >> 16) & 0xff);
+						*cur++ = (uint8)((val >> 24) & 0xff);
+					}
+
+					/* skip the "," if more array elements */
+					if (p && array_sz) {
+						char *q = NULL;
+
+						p = strstr (p, ",");	/* current param */
+						if (p) {
+							p++;
+							val = strtoul(p, &q, strncmp(p, "0x", 2) ?
+								10 : 16);
+						} else {
+							printf("Input array size error!");
+							free(par);
+							return BCME_BADARG;
+						}
+					}
+				}
+
+				/* move to the next parameter string */
+				cpar = strtok(NULL, delimit);
+			}
+			free(par);
+
+			/* commit the tuple if its valid */
+			if (found)
+				cnt += (cur - &b[cnt]);
+		}
+
+		srv++;
+	}
+
+	printf("sromrev %d buffer size %d bytes:\n", sromrev, cnt);
+	for (i = 0; i < cnt; i++) {
+		printf("0x%.02x ", b[i] & 0xff);
+		if (i%8 == 7)	printf("\n");
+	}
+	printf("\n");
+
+	return cnt;
+}
+
+static const sromvar_t *
+srvlookup(const sromvar_t *tab, char *name, int nlen, int sromrev)
+{
+	uint32 srrmask;
+	const sromvar_t *srv = tab;
+
+	srrmask = 1 << sromrev;
+
+	while (srv->name) {
+		if ((strncmp(name, srv->name, nlen) == 0) &&
+		    ((srrmask & srv->revmask) != 0))
+			break;
+		while (srv->flags & SRFL_MORE)
+			srv++;
+		srv++;
+	}
+
+	return srv;
+}
+
+static int
+wl_nvsource(void *wl, cmd_t *cmd, char **argv)
+{
+	int32 val, err;
+
+	if ((err = wl_var_get(wl, cmd, argv)))
+		return (err);
+
+	val = dtoh32(*(int32*)buf);
+
+	switch (val) {
+	case 0:
+		printf("SROM\n");
+		break;
+	case 1:
+		printf("OTP\n");
+		break;
+	case 2:
+		printf("NVRAM\n");
+		break;
+	default:
+		printf("Unrecognized source %d\n", val);
+		break;
+	}
+
+	return 0;
+}
+
+/** read/write caller supplied NVRAM variables in OTP or SROM */
+static int
+wlu_srvar(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, nw, nlen, ro, co, wr, sromrev, shift = 0;
+	bool otp = FALSE;
+	uint32 val32 = 0;
+	char *name, *p, *newval;
+	const sromvar_t *srv;
+	uint16 w, *words = (uint16 *)&buf[8];
+	srom_rw_t   *srt;
+	struct ether_addr ea;
+
+	ro = !strcmp(*argv, "rdvar");
+	wr = !strcmp(*argv, "wrvar");
+	co = !strcmp(*argv, "cisconvert");
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	/* Query the driver on where the cis comes from: OTP or SROM */
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "cis_source");
+	ret = wl_get(wl, WLC_GET_VAR, buf, strlen(buf)+1);
+	if (ret < 0) {
+		; /* printf("Error %x: cannot get cis_source\n", ret); */
+	}
+
+	if (buf[0] == WLC_CIS_OTP)
+		otp = TRUE;
+	if (otp && ro) {
+		/* read caller supplied nvram variable from driver */
+		wl_nvget(wl, cmd, --argv);
+		return ret;
+	}
+
+	/*
+	 * Before OTP can be written, the caller supplied nvram string has to be converted into a
+	 * list of CIS tuples. This CIS format is SROM rev dependent.
+	 */
+	if ((otp && wr) || co) {
+		int cnt = 0, err = 0;
+		uint sromrev = 8;
+		void *p = NULL;
+
+		/* Read all nvram variables from driver and retrieve srom revision from that */
+		if ((err = wlu_var_getbuf(wl, "nvram_dump", NULL, 0, &p)) < 0) {
+			err = wlu_get(wl, WLC_NVRAM_DUMP, &buf[0], WLC_IOCTL_MAXLEN);
+		}
+
+		if (err) {
+			printf("Fail to get sromrev from nvram file!\n");
+			return err;
+		}
+
+		if ((p = strstr(p, "sromrev"))) {
+			char *q = NULL;
+
+			p = (void*)((char*)p + 8);
+			/* for OTP, its either srom rev 10 or 16 */
+			sromrev = strtoul(p, &q, strncmp(p, "0x", 2) ? 10 : 16);
+		} else {
+			printf("sromrev not defined in nvram file!\n");
+			return BCME_ERROR;
+		}
+
+		/* convert caller supplied nvram string (in argv) into a list of tuples (in buf) */
+		if ((cnt = parsecis(buf, argv, sromrev)) <= 0) {
+			printf("CIS parse failure!\n");
+			return BCME_ERROR;
+		}
+
+		/* leave an empty srom_rw_t at the front for backward
+		 * compatibility
+		 */
+		if (!co) {
+			/*
+			 * Pass the CIS containing caller supplied nvram vars to driver so driver
+			 * can write OTP. Driver decides which OTP region (hardware,software) will
+			 * be written, depending on chip type and bus type.
+			 */
+			ret = wlu_iovar_set(wl, "cisvar", buf, cnt); /* IOV_BMAC_CISVAR */
+		}
+		return ret;
+	}
+
+	/* First read the srom and find out the sromrev */
+	srt = (srom_rw_t *)buf;
+	srt->byteoff = htod32(0);
+	srt->nbytes = htod32(2 * SROM4_WORDS);
+
+	if (cmd->get < 0)
+		return -1;
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	if (words[SROM11_SIGN] == SROM11_SIGNATURE) {
+		sromrev = 11;
+
+		srt->byteoff = htod32(0);
+		srt->nbytes = htod32(2 * SROM11_WORDS);
+
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+
+	} else {
+		if ((words[SROM4_SIGN] != SROM4_SIGNATURE) &&
+		    (words[SROM8_SIGN] != SROM4_SIGNATURE))
+			nw = SROM_CRCREV;
+		else
+			nw = SROM4_CRCREV;
+		sromrev = words[nw] & 0xff;
+	}
+
+	if ((sromrev < 2) || (sromrev > SROM_MAXREV)) {
+		return BCME_ERROR;
+	}
+
+	nw = 0;
+	while ((name = *argv++) != NULL) {
+		int off, off_base;
+
+		newval = strchr(name, '=');
+		if (newval)
+			*newval++ = '\0';
+		nlen = strlen(name);
+		if ((nlen == 0) || (nlen > 16)) {
+			printf("Bad variable name: %s\n", name);
+			continue;
+		}
+		off = 0;
+		srv = srvlookup(pci_sromvars, name, nlen + 1, sromrev);
+		if (srv->name == NULL) {
+			int path;
+
+			srv = srvlookup(perpath_pci_sromvars, name, nlen - 1, sromrev);
+			path = name[nlen - 1] - '0';
+			if ((srv->name == NULL) || (path < 0) || (path >= MAX_PATH_SROM)) {
+				printf("Variable %s does not exist in sromrev %d\n",
+				       name, sromrev);
+				continue;
+			}
+			if (sromrev >= 11) {
+				if (path == 0) {
+					off = SROM11_PATH0;
+				} else if (path == 1) {
+					off = SROM11_PATH1;
+				} else if (path == 2) {
+					off = SROM11_PATH2;
+				}
+			} else if (sromrev >= 8) {
+				if (path == 0) {
+					off = SROM8_PATH0;
+				} else if (path == 1) {
+					off = SROM8_PATH1;
+				} else if (path == 2) {
+					off = SROM8_PATH2;
+				} else if (path == 3) {
+					off = SROM8_PATH3;
+				}
+			} else
+				off = (path == 0) ? SROM4_PATH0 : SROM4_PATH1;
+		}
+		off_base = off;
+		off += srv->off;
+
+		if (ro) {
+			/* This code is cheating a bit: it knows that SRFL_ETHADDR means three
+			 * whole words, and SRFL_MORE means 2 whole words (i.e. the masks for
+			 * them are all 0xffff).
+			 */
+			if (srv->flags & SRFL_ETHADDR) {
+				w = words[off];
+				ea.octet[0] = w >> 8;
+				ea.octet[1] = w & 0xff;
+				w = words[off + 1];
+				ea.octet[2] = w >> 8;
+				ea.octet[3] = w & 0xff;
+				w = words[off + 2];
+				ea.octet[4] = w >> 8;
+				ea.octet[5] = w & 0xff;
+			} else if (srv->flags & SRFL_MORE) {
+				val32 = words[off];
+				val32 |= words[srv[1].off] << 16;
+			} else {
+				shift = ffs(srv->mask) - 1;
+				val32 = (words[off] & srv->mask) >> shift;
+			}
+
+			/* OK, print it */
+			if (srv->flags & SRFL_ETHADDR)
+				printf("%s=%s", name, wl_ether_etoa(&ea));
+			else if (srv->flags & SRFL_PRHEX)
+				printf("%s=0x%x", name, val32);
+			else if (srv->flags & SRFL_PRSIGN)
+				printf("%s=%d", name, val32);
+			else
+				printf("%s=%u", name, val32);
+
+			if (srv->flags & SRFL_ARRAY) {
+				do {
+					srv ++;
+					off = off_base + srv->off;
+
+					if (srv->name == NULL)
+						break;
+
+					shift = ffs(srv->mask) - 1;
+					val32 = (words[off] & srv->mask) >> shift;
+
+					if (srv->flags & SRFL_PRHEX)
+						printf(",0x%x", val32);
+					else if (srv->flags & SRFL_PRSIGN)
+						printf(",%d", val32);
+					else
+						printf(",%u", val32);
+				} while (srv->flags & SRFL_ARRAY);
+			}
+			printf("\n");
+
+		} else {	/* wr */
+
+			/* Make the change in the image we read */
+			if (!newval) {
+				printf("wrvar missing value to write for variable %s\n", name);
+				ro = 1;
+				break;
+			}
+
+			/* Cheating again as above */
+			if (srv->flags & SRFL_ETHADDR) {
+				if (!wl_ether_atoe(newval, &ea)) {
+					printf("Argument does not look like a MAC address: %s\n",
+						newval);
+					ret = BCME_USAGE_ERROR;
+					ro = 1;
+					break;
+				}
+				words[off] = (ea.octet[0] << 8) | ea.octet[1];
+				words[off + 1] = (ea.octet[2] << 8) | ea.octet[3];
+				words[off + 2] = (ea.octet[4] << 8) | ea.octet[5];
+				off += 2;
+			} else {
+				val32 = strtoul(newval, &p, 0);
+				if (p == newval) {
+					printf("Bad value: %s for variable %s\n", newval, name);
+					ro = 1;
+					break;
+				}
+
+				if (srv->flags & SRFL_MORE) {
+					words[off] = val32 & 0xffff;
+					words[off + 1] = val32 >> 16;
+					off++;
+				} else {
+					shift = ffs(srv->mask) - 1;
+					words[off] = (((val32 << shift) & srv->mask) |
+						(words[off] & ~srv->mask));
+
+					if (srv->flags & SRFL_ARRAY) {
+						do {
+							srv ++;
+							off = off_base + srv->off;
+
+							if (srv->name == NULL)
+								break;
+
+							newval = p + 1;
+							val32 = strtoul(newval, &p, 0);
+							if (p == newval) {
+								printf(
+								 "Bad value: %s for variable %s\n",
+								 newval, name);
+								ro = 1;
+								break;
+							}
+
+							shift = ffs(srv->mask) - 1;
+							words[off] =
+							 (((val32 << shift) & srv->mask) |
+							 (words[off] & ~srv->mask));
+						} while (srv->flags & SRFL_ARRAY);
+					}
+				}
+			}
+
+			if (off > nw)
+				nw = off;
+		}
+	}
+
+	if (!ro) {
+		/* Now write all the changes */
+		nw++;
+		srt->byteoff = 0;
+		srt->nbytes = htod32(2 * nw);
+		ret = wlu_set(wl, cmd->set, buf, (2 * nw) + 8);
+		if (ret < 0)
+			printf("Error %d writing the srom\n", ret);
+	}
+
+	return ret;
+}
+
+/* All 32bits are used. Please populate wl_msgs2[] with further entries */
+static dbg_msg_t wl_msgs[] = {
+	{WL_ERROR_VAL, 	"error"},
+	{WL_ERROR_VAL, 	"err"},
+	{WL_TRACE_VAL, 	"trace"},
+	{WL_PRHDRS_VAL,	"prhdrs"},
+	{WL_PRPKT_VAL,	"prpkt"},
+	{WL_INFORM_VAL,	"inform"},
+	{WL_INFORM_VAL,	"info"},
+	{WL_INFORM_VAL,	"inf"},
+	{WL_TMP_VAL,	"tmp"},
+	{WL_OID_VAL,	"oid"},
+	{WL_RATE_VAL,	"rate"},
+	{WL_ASSOC_VAL,	"assoc"},
+	{WL_ASSOC_VAL,	"as"},
+	{WL_PRUSR_VAL,	"prusr"},
+	{WL_PS_VAL,	"ps"},
+	{WL_TXPWR_VAL,	"txpwr"},
+	{WL_TXPWR_VAL,	"pwr"},
+	{WL_PORT_VAL,	"port"},
+	{WL_DUAL_VAL,	"dual"},
+	{WL_WSEC_VAL,	"wsec"},
+	{WL_WSEC_DUMP_VAL,	"wsec_dump"},
+	{WL_LOG_VAL,	"log"},
+	{WL_NRSSI_VAL,	"nrssi"},
+	{WL_LOFT_VAL,	"loft"},
+	{WL_REGULATORY_VAL,	"regulatory"},
+	{WL_RADAR_VAL,	"radar"},
+	{WL_MPC_VAL,	"mpc"},
+	{WL_APSTA_VAL,	"apsta"},
+	{WL_DFS_VAL,	"dfs"},
+	{WL_MBSS_VAL,	"mbss"},
+	{WL_CAC_VAL,	"cac"},
+	{WL_AMSDU_VAL,	"amsdu"},
+	{WL_AMPDU_VAL,	"ampdu"},
+	{WL_FFPLD_VAL,  "ffpld"},
+	{0,		NULL}
+};
+
+/* msglevels which use wl_msg_level2 should go here */
+static dbg_msg_t wl_msgs2[] = {
+	{WL_DPT_VAL,  "dpt"},
+	{WL_SCAN_VAL,	"scan"},
+	{WL_WOWL_VAL,	"wowl"},
+	{WL_COEX_VAL,	"coex"},
+	{WL_RTDC_VAL,	"rtdc"},
+	{WL_PROTO_VAL,	"proto"},
+#ifdef WLBTAMP
+	{WL_BTA_VAL,	"bta"},
+#endif
+	{WL_CHANINT_VAL,	"chanim"},
+	{WL_WMF_VAL, "wmf"},
+#ifdef WLP2P
+	{WL_P2P_VAL,	"p2p"},
+#endif
+	{WL_ITFR_VAL,	"itfr"},
+#ifdef WLMCHAN
+	{WL_MCHAN_VAL,	"mchan"},
+#endif
+#ifdef WLTDLS
+	{WL_TDLS_VAL, "tdls"},
+#endif
+	{WL_PSTA_VAL,	"psta"},
+	{WL_MCNX_VAL,	"mcnx"},
+	{WL_PROT_VAL,	"prot"},
+	{WL_TBTT_VAL,	"tbtt"},
+	{WL_NIC_VAL,	"nic"},
+	{WL_TIMESTAMP_VAL, "time"},
+	{WL_PWRSEL_VAL, "lpc"},
+	{WL_TSO_VAL,	"tso"},
+	{WL_MQ_VAL,	"mq"},
+#ifdef WLP2PO
+	{WL_P2PO_VAL, "p2po"},
+#endif
+	{WL_WNM_VAL, "wnm"},
+	{0,		NULL}
+};
+
+static int
+wl_msglevel(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint hval = 0, len, val = 0, found, last_val = 0, msglevel = 0, msglevel2_add = 0;
+	uint msglevel2_del = 0, msglevel_add = 0, msglevel_del = 0, supported = 1;
+	char *endptr = NULL;
+	dbg_msg_t *dbg_msg = wl_msgs, *dbg_msg2 = wl_msgs2;
+	void *ptr = NULL;
+	struct wl_msglevel2 msglevel64, *reply;
+	const char *cmdname = "msglevel";
+
+	UNUSED_PARAMETER(cmd);
+
+	/* but preseve older IOCTL call for older drivers */
+	if ((ret = wlu_var_getbuf_sm(wl, cmdname, &msglevel64, sizeof(msglevel64), &ptr) < 0)) {
+		if ((ret = wlu_get(wl, WLC_GET_MSGLEVEL, &msglevel, sizeof(int))) < 0)
+			return (ret);
+		supported = 0;
+		msglevel = dtoh32(msglevel);
+		if (!*++argv) {
+			printf("0x%x ", msglevel);
+			for (i = 0; (val = dbg_msg[i].value); i++) {
+			if ((msglevel & val) && (val != last_val))
+				printf(" %s", dbg_msg[i].string);
+			last_val = val;
+			}
+		printf("\n");
+		return (0);
+		}
+		while (*argv) {
+			char *s = *argv;
+			if (*s == '+' || *s == '-')
+				s++;
+			else
+				msglevel_del = ~0; /* make the whole list absolute */
+			val = strtoul(s, &endptr, 0);
+			if (val == 0xFFFFFFFF) {
+				fprintf(stderr,
+					"Bits >32 are not supported on this driver version\n");
+				val = 1;
+			}
+			/* not an integer if not all the string was parsed by strtoul */
+			if (*endptr != '\0') {
+				for (i = 0; (val = dbg_msg[i].value); i++)
+					if (stricmp(dbg_msg[i].string, s) == 0)
+						break;
+					if (!val)
+						goto usage;
+			}
+			if (**argv == '-')
+				msglevel_del |= val;
+			else
+				msglevel_add |= val;
+			++argv;
+		}
+		msglevel &= ~msglevel_del;
+		msglevel |= msglevel_add;
+		msglevel = htod32(msglevel);
+		return (wlu_set(wl, WLC_SET_MSGLEVEL, &msglevel, sizeof(int)));
+	} else { /* 64bit message level */
+		reply = (struct wl_msglevel2 *)ptr;
+		reply->low = dtoh32(reply->low);
+		reply->high = dtoh32(reply->high);
+		if (!*++argv) {
+			if (reply->high != 0)
+				printf("0x%x%08x", reply->high, reply->low);
+			else
+				printf("0x%x ", reply->low);
+			for (i = 0; (val = dbg_msg2[i].value); i++) {
+				if (((reply->high & val)) && (val != last_val))
+					printf(" %s", dbg_msg2[i].string);
+				last_val = val;
+				}
+			last_val = 0;
+			for (i = 0; (val = dbg_msg[i].value); i++) {
+				if (((reply->low & val)) && (val != last_val))
+					printf(" %s", dbg_msg[i].string);
+				last_val = val;
+			}
+			printf("\n");
+			return (0);
+		}
+		while (*argv) {
+			char* s = *argv;
+			char t[32];
+			found = 0;
+			if (*s == '+' || *s == '-')
+				s++;
+			else {
+				msglevel_del = ~0;	/* make the whole list absolute */
+				msglevel2_del = ~0;
+			}
+			val = strtoul(s, &endptr, 0);
+			if (val == 0xFFFFFFFF){ /* Assume >32 bit hex passed in */
+				if (!(*s == '0' && *(s+1) == 'x')) {
+					fprintf(stderr,
+					"Msg bits >32 take only numerical input in hex\n");
+					val = 0;
+				} else {
+					char c[32] = "0x";
+					len = strlen(s);
+					hval = strtoul(strncpy(t, s, len-8), &endptr, 0);
+					*endptr = 0;
+					s = s+strlen(t);
+					s = strcat(c, s);
+					val = strtoul(s, &endptr, 0);
+					if (hval == 0xFFFFFFFF) {
+						fprintf(stderr, "Invalid entry for msglevel\n");
+						hval = 0;
+						val = 0;
+					}
+				}
+			}
+			if (*endptr != '\0') {
+				for (i = 0; (val = dbg_msg[i].value); i++) {
+					if (stricmp(dbg_msg[i].string, s) == 0) {
+						found = 1;
+						break;
+					}
+				}
+				if (!found) {
+				for (i = 0; (hval = dbg_msg2[i].value); i++)
+					if (stricmp(dbg_msg2[i].string, s) == 0)
+						break;
+				}
+				if (!val && !hval)
+				      goto usage;
+		      }
+		      if (**argv == '-') {
+				msglevel_del |= val;
+				if (!found)
+					msglevel2_del |= hval;
+		      }
+		      else {
+				msglevel_add |= val;
+				if (!found)
+					msglevel2_add |= hval;
+		      }
+		      ++argv;
+		}
+		reply->low &= ~msglevel_del;
+		reply->high &= ~msglevel2_del;
+		reply->low |= msglevel_add;
+		reply->high |= msglevel2_add;
+		reply->low = htod32(reply->low);
+		reply->high = htod32(reply->high);
+		msglevel64.low = reply->low;
+		msglevel64.high = reply->high;
+		return (wlu_var_setbuf(wl, cmdname, &msglevel64, sizeof(msglevel64)));
+	}
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+
+	for (i = 0; (val = dbg_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string);
+		else
+			fprintf(stderr, ", %s", dbg_msg[i].string);
+		last_val = val;
+	}
+	if (supported) {
+		for (i = 0; (val = dbg_msg2[i].value); i++) {
+			if (val != last_val)
+				fprintf(stderr, "\n0x%x00000000 %s", val, dbg_msg2[i].string);
+			else
+				fprintf(stderr, ", %s", dbg_msg2[i].string);
+			last_val = val;
+		}
+	}
+	fprintf(stderr, "\n");
+	return 0;
+}
+
+#include <phy_dbg_api.h>
+
+static phy_msg_t wl_phy_msgs[] = {
+	{PHYHAL_ERROR,	"error"},
+	{PHYHAL_ERROR, 	"err"},
+	{PHYHAL_TRACE,	"trace"},
+	{PHYHAL_INFORM,	"inform"},
+	{PHYHAL_TMP,	"tmp"},
+	{PHYHAL_TXPWR,	"txpwr"},
+	{PHYHAL_CAL,	"cal"},
+	{PHYHAL_RADAR,	"radar"},
+	{PHYHAL_THERMAL, "thermal"},
+	{PHYHAL_PAPD,	"papd"},
+	{PHYHAL_RXIQ,	"rxiq"},
+	{PHYHAL_FCBS,	"fcbs"},
+	{0,		NULL}
+	};
+
+static int
+wl_phymsglevel(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val = 0, last_val = 0;
+	uint phymsglevel = 0, phymsglevel_add = 0, phymsglevel_del = 0;
+	char *endptr;
+	phy_msg_t *phy_msg = wl_phy_msgs;
+	const char *cmdname = "phymsglevel";
+
+	UNUSED_PARAMETER(cmd);
+	if ((ret = wlu_iovar_getint(wl, cmdname, (int *)&phymsglevel) < 0)) {
+		return ret;
+	}
+	phymsglevel = dtoh32(phymsglevel);
+	if (!*++argv) {
+		printf("0x%x ", phymsglevel);
+		for (i = 0; (val = phy_msg[i].value); i++) {
+			if ((phymsglevel & val) && (val != last_val))
+				printf(" %s", phy_msg[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			phymsglevel_del = ~0; /* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		if (val == 0xFFFFFFFF) {
+			fprintf(stderr,
+				"Bits >32 are not supported on this driver version\n");
+			val = 1;
+		}
+		/* not an integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = phy_msg[i].value); i++)
+				if (stricmp(phy_msg[i].string, s) == 0)
+					break;
+				if (!val)
+					goto usage;
+		}
+		if (**argv == '-')
+			phymsglevel_del |= val;
+		else
+			phymsglevel_add |= val;
+		++argv;
+	}
+	phymsglevel &= ~phymsglevel_del;
+	phymsglevel |= phymsglevel_add;
+	phymsglevel = htod32(phymsglevel);
+	return (wlu_iovar_setint(wl, cmdname, (int)phymsglevel));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+	for (i = 0; (val = phy_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, phy_msg[i].string);
+		else
+			fprintf(stderr, ", %s", phy_msg[i].string);
+		last_val = val;
+	}
+	return 0;
+}
+
+struct d11_mcs_rate_info {
+	uint8 constellation_bits;
+	uint8 coding_q;
+	uint8 coding_d;
+};
+
+static const struct d11_mcs_rate_info wlu_mcs_info[] = {
+	{ 1, 1, 2 }, /* MCS  0: MOD: BPSK,   CR 1/2 */
+	{ 2, 1, 2 }, /* MCS  1: MOD: QPSK,   CR 1/2 */
+	{ 2, 3, 4 }, /* MCS  2: MOD: QPSK,   CR 3/4 */
+	{ 4, 1, 2 }, /* MCS  3: MOD: 16QAM,  CR 1/2 */
+	{ 4, 3, 4 }, /* MCS  4: MOD: 16QAM,  CR 3/4 */
+	{ 6, 2, 3 }, /* MCS  5: MOD: 64QAM,  CR 2/3 */
+	{ 6, 3, 4 }, /* MCS  6: MOD: 64QAM,  CR 3/4 */
+	{ 6, 5, 6 }, /* MCS  7: MOD: 64QAM,  CR 5/6 */
+	{ 8, 3, 4 }, /* MCS  8: MOD: 256QAM, CR 3/4 */
+	{ 8, 5, 6 }  /* MCS  9: MOD: 256QAM, CR 5/6 */
+};
+
+static uint
+wl_mcs2rate(uint mcs, uint nss, uint bw, int sgi)
+{
+	const int ksps = 250; /* kilo symbols per sec, 4 us sym */
+	const int Nsd_20MHz = 52;
+	const int Nsd_40MHz = 108;
+	const int Nsd_80MHz = 234;
+	const int Nsd_160MHz = 468;
+	uint rate;
+
+	if (mcs == 32) {
+		/* just return fixed values for mcs32 instead of trying to parametrize */
+		rate = (sgi == 0) ? 6000 : 6700;
+	} else if (mcs <= 9) {
+		/* This calculation works for 11n HT and 11ac VHT if the HT mcs values
+		 * are decomposed into a base MCS = MCS % 8, and Nss = 1 + MCS / 8.
+		 * That is, HT MCS 23 is a base MCS = 7, Nss = 3
+		 */
+
+		/* find the number of complex numbers per symbol */
+		if (bw == 20) {
+			rate = Nsd_20MHz;
+		} else if (bw == 40) {
+			rate = Nsd_40MHz;
+		} else if (bw == 80) {
+			rate = Nsd_80MHz;
+		} else if (bw == 160) {
+			rate = Nsd_160MHz;
+		} else {
+			rate = 1;
+		}
+
+		/* multiply by bits per number from the constellation in use */
+		rate = rate * wlu_mcs_info[mcs].constellation_bits;
+
+		/* adjust for the number of spatial streams */
+		rate = rate * nss;
+
+		/* adjust for the coding rate given as a quotient and divisor */
+		rate = (rate * wlu_mcs_info[mcs].coding_q) / wlu_mcs_info[mcs].coding_d;
+
+		/* multiply by Kilo symbols per sec to get Kbps */
+		rate = rate * ksps;
+
+		/* adjust the symbols per sec for SGI
+		 * symbol duration is 4 us without SGI, and 3.6 us with SGI,
+		 * so ratio is 10 / 9
+		 */
+		if (sgi) {
+			/* add 4 for rounding of division by 9 */
+			rate = ((rate * 10) + 4) / 9;
+		}
+	} else {
+		rate = 0;
+	}
+
+	return rate;
+}
+
+/* take a wl_ratespec arg and return phy rate in 500Kbps units */
+static int
+wl_ratespec2rate(uint32 rspec)
+{
+	const char* fn_name = "wl_ratespec2rate";
+	int rate = -1;
+	int sgi = ((rspec & WL_RSPEC_SGI) != 0);
+
+	if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_RATE) {
+		rate = (rspec & WL_RSPEC_RATE_MASK);
+	} else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HT) {
+		uint mcs = (rspec & WL_RSPEC_RATE_MASK);
+
+		if (mcs > 32) {
+			fprintf(stderr, "%s: MCS %u out of range (>32) in ratespec 0x%X\n",
+				fn_name, mcs, rspec);
+		} else if (mcs == 32) {
+			rate = wl_mcs2rate(mcs, 1, 40, sgi) / 500;
+		} else {
+			uint nss = 1 + (mcs / 8);
+			mcs = mcs % 8;
+
+			rate = wl_mcs2rate(mcs, nss, 20, sgi) / 500;
+		}
+	} else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_VHT) {
+		uint mcs = (rspec & WL_RSPEC_VHT_MCS_MASK);
+		uint nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+
+		rate = wl_mcs2rate(mcs, nss, 20, sgi) / 500;
+	} else {
+		fprintf(stderr, "%s: expected rate encoding in ratespec 0x%X\n",
+			fn_name, (uint)rspec);
+	}
+
+	return rate;
+}
+
+/* take rate arg in units of 500Kbits/s and print it in units of Mbit/s */
+static void
+wl_printrate(int val)
+{
+	char rate_buf[32];
+
+	printf("%s\n", rate_int2string(rate_buf, val));
+}
+
+/* convert rate string in Mbit/s format, like "11", "5.5", to internal 500 Kbit/s units */
+static int
+rate_string2int(char *s)
+{
+	if (!stricmp(s, "-1"))
+		return (0);
+	if (!stricmp(s, "5.5"))
+		return (11);
+	return (atoi(s) * 2);
+}
+
+/* convert rate internal 500 Kbits/s units to string in Mbits/s format, like "11", "5.5" */
+static char*
+rate_int2string(char *rate_buf, int val)
+{
+	if ((val == -1) || (val == 0))
+		sprintf(rate_buf, "auto");
+	else
+		sprintf(rate_buf, "%d%s Mbps", (val / 2), (val & 1) ? ".5" : "");
+	return (rate_buf);
+}
+
+/* Format a ratespec for "nrate" output
+ * Will handle both current wl_ratespec and legacy (ioctl_version 1) nrate ratespec
+ */
+static void
+wl_nrate_print(uint32 rspec)
+{
+	const char * rspec_auto = "auto";
+	uint encode, rate, txexp = 0, bw_val;
+	const char* stbc = "";
+	const char* ldpc = "";
+	const char* sgi = "";
+	const char* bw = "";
+	int stf;
+
+	if (rspec == 0) {
+		encode = WL_RSPEC_ENCODE_RATE;
+	} else if (ioctl_version == 1) {
+		encode = (rspec & OLD_NRATE_MCS_INUSE) ? WL_RSPEC_ENCODE_HT : WL_RSPEC_ENCODE_RATE;
+		stf = (int)((rspec & OLD_NRATE_STF_MASK) >> OLD_NRATE_STF_SHIFT);
+		rate = (rspec & OLD_NRATE_RATE_MASK);
+
+		if (rspec & OLD_NRATE_OVERRIDE) {
+			if (rspec & OLD_NRATE_OVERRIDE_MCS_ONLY)
+				rspec_auto = "fixed mcs only";
+			else
+				rspec_auto = "fixed";
+		}
+	} else {
+		int siso;
+		encode = (rspec & WL_RSPEC_ENCODING_MASK);
+		rate = (rspec & WL_RSPEC_RATE_MASK);
+		txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
+		stbc  = ((rspec & WL_RSPEC_STBC) != 0) ? " stbc" : "";
+		ldpc  = ((rspec & WL_RSPEC_LDPC) != 0) ? " ldpc" : "";
+		sgi   = ((rspec & WL_RSPEC_SGI)  != 0) ? " sgi"  : "";
+		bw_val = (rspec & WL_RSPEC_BW_MASK);
+
+		if (bw_val == WL_RSPEC_BW_20MHZ) {
+			bw = "bw20";
+		} else if (bw_val == WL_RSPEC_BW_40MHZ) {
+			bw = "bw40";
+		} else if (bw_val == WL_RSPEC_BW_80MHZ) {
+			bw = "bw80";
+		} else if (bw_val == WL_RSPEC_BW_160MHZ) {
+			bw = "bw160";
+		}
+
+		/* initialize stf mode to an illegal value and
+		 * fix to a backward compatable value if possible
+		 */
+		stf = -1;
+		/* for stf calculation, determine if the rate is single stream.
+		 * Legacy rates WL_RSPEC_ENCODE_RATE are single stream, and
+		 * HT rates for mcs 0-7 are single stream
+		 */
+		siso = (encode == WL_RSPEC_ENCODE_RATE) ||
+			((encode == WL_RSPEC_ENCODE_HT) && rate < 8);
+
+		/* calc a value for nrate stf mode */
+		if (txexp == 0) {
+			if ((rspec & WL_RSPEC_STBC) && siso) {
+				/* STF mode STBC */
+				stf = OLD_NRATE_STF_STBC;
+			} else {
+				/* STF mode SISO or SDM */
+				stf = (siso) ? OLD_NRATE_STF_SISO : OLD_NRATE_STF_SDM;
+			}
+		} else if (txexp == 1 && siso) {
+			/* STF mode CDD */
+			stf = OLD_NRATE_STF_CDD;
+		}
+
+		if (rspec & WL_RSPEC_OVERRIDE_RATE) {
+			rspec_auto = "fixed";
+		}
+	}
+
+	if (encode == WL_RSPEC_ENCODE_RATE) {
+		if (rspec == 0) {
+			printf("auto\n");
+		} else {
+			printf("legacy rate %d%s Mbps stf mode %d %s\n",
+			       rate/2, (rate % 2)?".5":"", stf, rspec_auto);
+		}
+	} else if (encode == WL_RSPEC_ENCODE_HT) {
+		printf("mcs index %d stf mode %d %s\n",
+		       rate, stf, rspec_auto);
+	} else {
+		uint vht = (rspec & WL_RSPEC_VHT_MCS_MASK);
+		uint Nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+		printf("vht mcs %d Nss %d Tx Exp %d %s%s%s%s %s\n",
+		       vht, Nss, txexp, bw, stbc, ldpc, sgi, rspec_auto);
+	}
+}
+
+/*
+ * Format a ratespec for output of any of the wl_rate() iovars
+ */
+static char*
+wl_rate_print(char *rate_buf, uint32 rspec)
+{
+	uint encode, rate, txexp, bw_val;
+	const char* stbc;
+	const char* ldpc;
+	const char* sgi;
+	const char* bw;
+
+	encode = (rspec & WL_RSPEC_ENCODING_MASK);
+	rate = (rspec & WL_RSPEC_RATE_MASK);
+	txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
+	bw_val = (rspec & WL_RSPEC_BW_MASK);
+	stbc  = ((rspec & WL_RSPEC_STBC) != 0) ? " stbc" : "";
+	ldpc  = ((rspec & WL_RSPEC_LDPC) != 0) ? " ldpc" : "";
+	sgi   = ((rspec & WL_RSPEC_SGI)  != 0) ? " sgi"  : "";
+
+	if (bw_val == WL_RSPEC_BW_UNSPECIFIED) {
+		bw = "auto";
+	} else if (bw_val == WL_RSPEC_BW_20MHZ) {
+		bw = "20";
+	} else if (bw_val == WL_RSPEC_BW_40MHZ) {
+		bw = "40";
+	} else if (bw_val == WL_RSPEC_BW_80MHZ) {
+		bw = "80";
+	} else if (bw_val == WL_RSPEC_BW_160MHZ) {
+		bw = "160";
+	} else {
+		bw = "???";
+	}
+
+	if ((rspec & ~WL_RSPEC_TXEXP_MASK) == 0) { /* Ignore TxExpansion for NULL rspec check */
+		sprintf(rate_buf, "auto");
+	} else if (encode == WL_RSPEC_ENCODE_RATE) {
+		sprintf(rate_buf, "rate %d%s Mbps Tx Exp %d",
+			rate/2, (rate % 2)?".5":"", txexp);
+	} else if (encode == WL_RSPEC_ENCODE_HT) {
+		sprintf(rate_buf, "ht mcs %d Tx Exp %d BW %s%s%s%s",
+		        rate, txexp, bw, stbc, ldpc, sgi);
+	} else if (encode == WL_RSPEC_ENCODE_VHT) {
+		uint mcs = (rspec & WL_RSPEC_VHT_MCS_MASK);
+		uint Nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+		sprintf(rate_buf, "vht mcs %d Nss %d Tx Exp %d BW %s%s%s%s",
+		        mcs, Nss, txexp, bw, stbc, ldpc, sgi);
+	} else {
+		sprintf(rate_buf, "<unknown encoding for ratespec 0x%08X>", rspec);
+	}
+
+	return rate_buf;
+}
+
+/* handles both "rate" and "mrate", which makes the flow a bit complex */
+static int
+wl_rate_mrate(void *wl, cmd_t *cmd, char **argv)
+{
+	const char* fn_name = "wl_rate_mrate";
+	int error;
+	int val;
+	int band;
+	int list[3];
+	char aname[sizeof("5g_mrate") + 1];
+	char bgname[sizeof("2g_mrate") + 1];
+	char *name;
+
+	sprintf(aname, "5g_%s", cmd->name);
+	sprintf(bgname, "2g_%s", cmd->name);
+
+	if ((error = wlu_get(wl, WLC_GET_BAND, &band, sizeof(uint))) < 0)
+		return error;
+	band = dtoh32(band);
+
+	if ((error = wlu_get(wl, WLC_GET_BANDLIST, list, sizeof(list))) < 0)
+		return error;
+	list[0] = dtoh32(list[0]);
+	list[1] = dtoh32(list[1]);
+	list[2] = dtoh32(list[2]);
+
+	if (!list[0])
+		return BCME_ERROR;
+	else if (list[0] > 2)
+		list[0] = 2;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if ((!strcmp(cmd->name, "rate"))) {
+		/* it is "rate" */
+		if (!*argv) {
+			/* it is "rate" get. handle it here */
+			/* WLC_GET_RATE processing */
+			if ((error = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+				return error;
+
+			val = dtoh32(val);
+			wl_printrate(val);
+			return 0;
+		}
+	}
+
+	switch (band) {
+	case WLC_BAND_AUTO :
+		if (list[0] > 1) {
+			fprintf(stderr,
+			        "%s: driver band must be locked to %s %s, use %s/%s instead\n",
+			        fn_name, (*argv ? "set" : "get"), cmd->name,
+			        bgname, aname);
+			return BCME_BADARG;
+		} else if (list[1] == WLC_BAND_5G)
+			name = (char *)aname;
+		else if (list[1] == WLC_BAND_2G)
+			name = (char *)bgname;
+		else
+			return BCME_ERROR;
+
+		break;
+
+	case WLC_BAND_5G :
+		name = (char *)aname;
+		break;
+
+	case WLC_BAND_2G :
+		name = (char *)bgname;
+		break;
+
+	default :
+		return BCME_ERROR;
+	}
+
+	if (!*argv) {
+		/* it is "mrate" get */
+		if ((error = wlu_iovar_getint(wl, name, &val) < 0))
+			return error;
+
+		val = dtoh32(val);
+
+		if (ioctl_version == 1) {
+			wl_printrate(val);
+		} else {
+			wl_printrate(wl_ratespec2rate((uint32)val));
+		}
+	} else {
+		/* create the ioctl value based on the major ioctl version */
+		if (ioctl_version == 1) {
+			/* for ver=1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are just given as 500 Kbps units
+			 */
+			val = rate_string2int(*argv);
+		} else {
+			/* for ver>1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are a wl_ratespec of a legacy rate.
+			 */
+			val = WL_RSPEC_ENCODE_RATE | rate_string2int(*argv);
+		}
+
+		val = htod32(val);
+
+		error = wlu_iovar_setint(wl, name, val);
+	}
+
+	return error;
+}
+
+/* parse the -v/--vht or -c argument for the wl_rate() command.
+ * return FALSE if the arg does not look like MxS or cMsS, where M and S are single digits
+ * return TRUE if the arg does look like MxS or cMsS, setting mcsp to M, and nssp to S
+ */
+static int
+wl_parse_vht_spec(const char* cp, int* mcsp, int* nssp)
+{
+	char *startp, *endp;
+	char c;
+	int mcs, nss;
+	char sx;
+
+	if (cp == NULL || cp[0] == '\0') {
+		return FALSE;
+	}
+
+	if (cp[0] == 'c') {
+		startp = (char*)cp + 1;
+		sx = 's';
+	}
+	else {
+		startp = (char*)cp;
+		sx = 'x';
+	}
+
+	mcs = (int)strtol(startp, &endp, 10);
+	/* verify MCS 0-9, and next char is 's' or 'x' */
+	if (mcs < 0 || mcs > 9 || endp[0] != sx) {
+		return FALSE;
+	}
+
+	/* grab the char after the 'x'/'s' and convert to value */
+	c = endp[1];
+	nss = 0;
+	if (isdigit((int)c)) {
+		nss = c - '0';
+	}
+
+	/* consume trailing space after digit */
+	cp = &endp[2];
+	while (isspace((int)(*cp))) {
+		cp++;
+	}
+
+	/* check for trailing garbage after digit */
+	if (cp[0] != '\0') {
+		return FALSE;
+	}
+
+	if (nss < 1 || nss > 8) {
+		return FALSE;
+	}
+
+	*mcsp = mcs;
+	*nssp = nss;
+
+	return TRUE;
+}
+
+static int
+wl_rate(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t mo;
+	char *option_name = NULL;
+	char* endp;
+	const int option_name_len = 64;
+	const char* iov_name;
+	const char* fn_name = "wl_rate";
+	bool options = FALSE;
+	bool auto_set = FALSE;
+	bool legacy_set = FALSE, ht_set = FALSE, vht_set = FALSE;
+	int rate, mcs, Nss, tx_exp, bw;
+	bool stbc, ldpc, sgi;
+	int err, opt_err;
+	uint32 rspec = 0;
+
+	/* set default values */
+	rate = 0;
+	mcs = 0;
+	Nss = 0;
+	tx_exp = 0;
+	stbc = FALSE;
+	ldpc = FALSE;
+	sgi = FALSE;
+	bw = 0;
+
+	/* save the command name */
+	iov_name = *argv++;
+
+	if (ioctl_version == 1) {
+		fprintf(stderr,
+			"cmd %s not supported in this version of the driver, ioctl version 1.\n",
+			iov_name);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* process a GET */
+	if (!*argv) {
+		uint32 val = 0;
+		char * rate_str;
+		const int rate_str_len = 64;
+
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, iov_name, (int*)&val)) < 0)
+			return err;
+
+		rate_str = malloc(rate_str_len);
+		if (rate_str == NULL) {
+			fprintf(stderr, "%s: malloc failure for rate string buffer.\n", fn_name);
+			return BCME_NOMEM;
+		}
+		memset(rate_str, 0, rate_str_len);
+
+		wl_rate_print(rate_str, val);
+
+		printf("%s\n", rate_str);
+
+		free(rate_str);
+
+		return 0;
+	}
+
+	/* process a SET */
+
+	/* initialze to common error for the miniopt processing */
+	err = BCME_USAGE_ERROR;
+
+	/* alloc option name for error messages */
+	option_name = malloc(option_name_len);
+	if (option_name == NULL) {
+		fprintf(stderr, "%s: malloc failure for option_name buffer.\n", fn_name);
+		return BCME_NOMEM;
+	}
+	memset(option_name, 0, option_name_len);
+
+	miniopt_init(&mo, fn_name, "lg", TRUE);
+	while ((opt_err = miniopt(&mo, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += mo.consumed;
+
+		/* track whether or not the command line is just a single positional
+		 * parameter of "auto" or a legacy rate, or is using options
+		 */
+		if (!mo.positional) {
+			options = TRUE;	/* command line is using options */
+		}
+		if (mo.positional) {
+			/* command line is using a positional parameter,
+			 * complain if options are also being used
+			 */
+			if (options) {
+				fprintf(stderr,
+				        "%s: cannot mix positional args and options. "
+				        "Got positional arg \"%s\" after options.\n",
+				        fn_name, mo.valstr);
+				goto exit;
+			}
+			/* complain if there are any more parameters since there should only
+			 * be one positional param, "auto" or a legacy rate.
+			 */
+			if (*argv != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected parameter \"%s\" after rate value.\n",
+				        fn_name, *argv);
+				goto exit;
+			}
+			/* test for "auto" to clear the rate override */
+			if (!strcmp(mo.valstr, "auto")) {
+				auto_set = TRUE;
+			} else {
+				/* pretend there was a '-r' option */
+				mo.opt = 'r';
+			}
+		}
+
+		/* format the option name for error messages */
+		if (mo.key[0] != '\0') {
+			/* would like to do the following, but snprintf() is not availble in
+			 * all target builds. Fails in win_mfgtest_wl build.
+			 *
+			 * snprintf(option_name, option_name_len, "--%s", mo.key);
+			 * option_name[option_name_len - 1] = '\0';
+			 */
+			size_t key_len;
+
+			key_len = strlen(mo.key);
+			/* limit key_len to space in str buffer minus the '--' and null */
+			key_len = MIN((uint)(option_name_len - 3), key_len);
+
+			memcpy(option_name, "--", 2);
+			memcpy(option_name + 2, mo.key, key_len);
+			option_name[2 + key_len] = '\0';
+		} else {
+			sprintf(option_name, "-%c", mo.opt);
+		}
+
+		/* Option: -r or --rate */
+		if (mo.opt == 'r' ||
+		    !strcmp(mo.key, "rate")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			/* special case check for "-r 5.5" */
+			if (!strcmp(mo.valstr, "5.5")) {
+				rate = 11;
+			} else if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			} else {
+				rate = mo.val*2;
+			}
+
+			legacy_set = TRUE;
+		}
+		/* Option: -h or --ht */
+		if (mo.opt == 'h' ||
+		    !strcmp(mo.key, "ht")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+
+			mcs = mo.val;
+			ht_set = TRUE;
+		}
+		/* Option: -v or --vht */
+		if (mo.opt == 'v' ||
+		    !strcmp(mo.key, "vht")) {
+			if (mo.valstr == NULL || mo.valstr[0] == 'c') {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			mcs = (int)strtol(mo.valstr, &endp, 10);
+			if (*endp == '\0') {
+				mcs = mo.val;
+				vht_set = TRUE;
+			} else if (wl_parse_vht_spec(mo.valstr, &mcs, &Nss)) {
+				vht_set = TRUE;
+			} else {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+		}
+		/* Option: -c (system team's c notiation: c<MCS>s<Nss>) */
+		if (mo.opt == 'c') {
+			if (mo.valstr == NULL || mo.valstr[0] != 'c') {
+				fprintf(stderr,
+				        "%s: expected a value start with c for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			mcs = (int)strtol(mo.valstr + 1, &endp, 10);
+			if (*endp == '\0') {
+				vht_set = TRUE;
+			} else if (wl_parse_vht_spec(mo.valstr, &mcs, &Nss)) {
+				vht_set = TRUE;
+			} else {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+		}
+		/* Option: -s or --ss */
+		if (mo.opt == 's' ||
+		    !strcmp(mo.key, "ss")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+			Nss = mo.val;
+		}
+		/* Option: -x or --exp */
+		if (mo.opt == 'x' ||
+		    !strcmp(mo.key, "exp")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+			tx_exp = mo.val;
+			if (tx_exp < 0 || tx_exp > 3) {
+				fprintf(stderr,
+				        "%s: tx expansion %d out of range [0-3]\n",
+				        fn_name, tx_exp);
+				err = BCME_RANGE;
+				goto exit;
+			}
+		}
+		/* Option: --stbc */
+		if (!strcmp(mo.key, "stbc")) {
+			if (mo.valstr != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+			stbc = TRUE;
+		}
+		/* Option: -l or --ldpc */
+		if (mo.opt == 'l' ||
+		    !strcmp(mo.key, "ldpc")) {
+			if (mo.valstr != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+			ldpc = TRUE;
+		}
+		/* Option: -g or --sgi */
+		if (mo.opt == 'g' ||
+		    !strcmp(mo.key, "sgi")) {
+			if (mo.valstr != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+			sgi = TRUE;
+		}
+		/* Option: -b or --bandwidth */
+		if (mo.opt == 'b' ||
+		    !strcmp(mo.key, "bandwidth")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+			if (mo.val == 20) {
+				bw = WL_RSPEC_BW_20MHZ;
+			} else if (mo.val == 40) {
+				bw = WL_RSPEC_BW_40MHZ;
+			} else if (mo.val == 80) {
+				bw = WL_RSPEC_BW_80MHZ;
+			} else if (mo.val == 160) {
+				bw = WL_RSPEC_BW_160MHZ;
+			} else {
+				fprintf(stderr,
+				        "%s: unexpected bandwidth specified \"%s\", "
+				        "expected 20, 40, 80, or 160\n",
+				        fn_name, mo.valstr);
+				goto exit;
+			}
+		}
+	}
+
+	/*
+	 * check for necessary use of one of -r/-h/-v or auto
+	 */
+
+	if (!auto_set && !legacy_set && !ht_set && !vht_set) {
+		fprintf(stderr, "%s: must specify one of \"auto\", legacy rate -r/--rate, "
+		        "HT (11n) rate -h/--ht, or VHT (11ac) rate -v/--vht\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/*
+	 * check for incompatible use of -r/-h/-v
+	 */
+
+	if (legacy_set && ht_set) {
+		fprintf(stderr, "%s: cannot use legacy rate -r/--rate and "
+		        "HT rate -h/--ht at the same time\n",
+		        fn_name);
+		goto exit;
+	}
+
+	if (legacy_set && vht_set) {
+		fprintf(stderr, "%s: cannot use legacy rate -r/--rate and "
+		        "HT rate -v/--vht at the same time\n",
+		        fn_name);
+		goto exit;
+	}
+
+	if (ht_set && vht_set) {
+		fprintf(stderr, "%s: cannot use HT rate -h/--ht and "
+		        "HT rate -v/--vht at the same time\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/* Nss can only be used with VHT */
+	if (!vht_set && Nss != 0) {
+		fprintf(stderr, "%s: cannot use -s/--ss option with non VHT rate\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/* STBC, LDPC, SGI can only be used with HT/VHT rates */
+	if ((stbc || ldpc || sgi) && !(ht_set || vht_set)) {
+		fprintf(stderr, "%s: cannot use STBC/LDPC/SGI options with non HT/VHT rates\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/* set the ratespec encoding type and basic rate value */
+	if (auto_set) {
+		rspec = 0;
+	} else if (legacy_set) {
+		rspec = WL_RSPEC_ENCODE_RATE;	/* 11abg */
+		rspec |= rate;
+	} else if (ht_set) {
+		rspec = WL_RSPEC_ENCODE_HT;	/* 11n HT */
+		rspec |= mcs;
+	} else {
+		rspec = WL_RSPEC_ENCODE_VHT;	/* 11ac VHT */
+		if (Nss == 0) {
+			Nss = 1; /* default Nss = 1 if --ss option not given */
+		}
+		rspec |= (Nss << WL_RSPEC_VHT_NSS_SHIFT) | mcs;
+	}
+
+	/* set the other rspec fields */
+	rspec |= (tx_exp << WL_RSPEC_TXEXP_SHIFT);
+	rspec |= bw;
+	rspec |= (stbc ? WL_RSPEC_STBC : 0);
+	rspec |= (ldpc ? WL_RSPEC_LDPC : 0);
+	rspec |= (sgi  ? WL_RSPEC_SGI  : 0);
+
+	err = wlu_iovar_setint(wl, iov_name, (int)rspec);
+
+exit:
+	if (option_name != NULL) {
+		free(option_name);
+	}
+
+	return err;
+}
+
+static int
+wl_wepstatus(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error;
+	const char *name = "wsec";
+	int wsec;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		if ((error = wlu_iovar_getint(wl, name, &val) < 0))
+			return error;
+
+		printf("%d\n", val);
+		return 0;
+	} else {
+		val = atoi(*argv);
+		if ((error = wlu_iovar_getint(wl, name, &wsec) < 0))
+			return error;
+
+		if (val)
+			wsec |= WEP_ENABLED;
+		else
+			wsec &= ~WEP_ENABLED;
+
+		return wlu_iovar_setint(wl, name, wsec);
+	}
+}
+
+static int
+wl_bss_max(void *wl, cmd_t *cmd, char **argv)
+{
+	int val = 1;
+	int error;
+
+	UNUSED_PARAMETER(argv);
+
+	/* Get the CAP variable; search for mbss4 or mbss16 */
+	strcpy(buf, "cap");
+	if ((error = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MEDLEN)) < 0)
+		return (error);
+
+	buf[WLC_IOCTL_MEDLEN] = '\0';
+	if (strstr(buf, "mbss16"))
+		val = 16;
+	else if (strstr(buf, "mbss4"))
+		val = 4;
+
+	printf("%d\n", val);
+	return (0);
+}
+
+static int
+wl_phy_rate(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error;
+	const char *name = cmd->name;
+	static const struct {
+		const char* orig;
+		const char* new;
+	} aliases[] = {
+		{"bg_rate",  "2g_rate"},
+		{"bg_mrate", "2g_mrate"},
+		{"a_rate",   "5g_rate"},
+		{"a_mrate",  "5g_mrate"},
+	};
+
+	/* toss the command name from the args */
+	argv++;
+
+	/* if we are not using the legacy ioctl driver, translate the
+	 * bg_* prefix to 2g_* and a_* to 5g_* iovars
+	 */
+	if (ioctl_version > 1) {
+		int i;
+		for (i = 0; i < 4; i++) {
+			if (!strcmp(name, aliases[i].orig)) {
+				name = aliases[i].new;
+				break;
+			}
+		}
+	}
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+
+		val = dtoh32(val);
+		if (ioctl_version > 1) {
+			wl_printrate(wl_ratespec2rate((uint32)val));
+		} else {
+			wl_printrate(val);
+		}
+	} else {
+		/* create the ioctl value based on the major ioctl version */
+		if (ioctl_version == 1) {
+			/* for ver=1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are just given as 500 Kbps units
+			 */
+			val = rate_string2int(*argv);
+		} else {
+			/* for ver>1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are a wl_ratespec of a legacy rate.
+			 */
+			val = WL_RSPEC_ENCODE_RATE | rate_string2int(*argv);
+		}
+
+
+		val = htod32(val);
+		error = wlu_iovar_setint(wl, name, val);
+	}
+
+	return error;
+}
+
+static int
+wl_nrate(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_nrate";
+	bool mcs_set = FALSE, legacy_set = FALSE, stf_set = FALSE;
+	bool mcs_only = FALSE;
+	int err, opt_err;
+	uint32 val = 0;
+	uint32 rate = 0;
+	uint32 nrate = 0;
+	uint32 mcs = 0;
+	uint stf = 0;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, "nrate", (int*)&val)) < 0)
+			return err;
+
+		/* print a user readable line for the nrate rspec */
+		wl_nrate_print(val);
+
+		return 0;
+	}
+
+	/* check for a single argument of "auto" or -1 */
+	if ((!strcmp(argv[0], "auto") || !strcmp(argv[0], "-1")) &&
+	    argv[1] == NULL) {
+		/* clear the nrate override */
+		err = wlu_iovar_setint(wl, "nrate", 0);
+		goto exit;
+	}
+
+	miniopt_init(&to, fn_name, "w", FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == 'r') {
+			if (!to.good_int) {
+				/* special case check for "-r 5.5" */
+				if (!strcmp(to.valstr, "5.5")) {
+					to.val = 11;
+				} else {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as a rate value\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+			} else
+			      to.val = to.val*2;
+			if (mcs_set) {
+				fprintf(stderr, "%s: cannot use -r and -m\n", fn_name);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			legacy_set = TRUE;
+			rate = to.val;
+		}
+		if (to.opt == 'm') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for mcs\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (legacy_set) {
+				fprintf(stderr, "%s: cannot use -r and -m\n", fn_name);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			mcs_set = TRUE;
+			mcs = to.val;
+		}
+		if (to.opt == 's') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for stf mode\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			stf = to.val;
+			stf_set = TRUE;
+		}
+		if (to.opt == 'w') {
+			mcs_only = TRUE;
+		}
+	}
+
+	if ((mcs_only && !mcs_set) || (mcs_only && (stf_set || legacy_set))) {
+		fprintf(stderr, "%s: can use -w only with -m\n", fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (!stf_set) {
+		if (legacy_set)
+			stf = OLD_NRATE_STF_SISO;	/* SISO */
+		else if (mcs_set) {
+			if ((nrate & OLD_NRATE_RATE_MASK) <= HIGHEST_SINGLE_STREAM_MCS ||
+			    (nrate & OLD_NRATE_RATE_MASK) == 32)
+				stf = OLD_NRATE_STF_SISO;	/* SISO */
+			else
+				stf = OLD_NRATE_STF_SDM;	/* SDM */
+		}
+	}
+
+	if (!legacy_set && !mcs_set) {
+		fprintf(stderr, "%s: you need to set a legacy or mcs rate\n", fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (ioctl_version == 1) {
+		if (legacy_set) {
+			nrate = rate;
+		} else {
+			nrate = mcs;
+			nrate |= OLD_NRATE_MCS_INUSE;
+			if (mcs_only) {
+				nrate |= OLD_NRATE_OVERRIDE_MCS_ONLY;
+			}
+		}
+
+		nrate |= (stf << OLD_NRATE_STF_SHIFT) & OLD_NRATE_STF_MASK;
+	} else {
+		uint tx_exp = 0;
+
+		/* set the ratespec encoding type and basic rate value */
+		if (legacy_set) {
+			nrate = WL_RSPEC_ENCODE_RATE;	/* 11abg */
+			nrate |= rate;
+		} else {
+			nrate = WL_RSPEC_ENCODE_HT;	/* 11n HT */
+			nrate |= mcs;
+		}
+
+		/* decode nrate stf value into tx expansion and STBC */
+		if (stf == OLD_NRATE_STF_CDD) {
+			tx_exp = 1;
+		} else if (stf == OLD_NRATE_STF_STBC) {
+			nrate |= WL_RSPEC_STBC;
+		}
+
+		nrate |= (tx_exp << WL_RSPEC_TXEXP_SHIFT);
+	}
+
+	err = wlu_iovar_setint(wl, "nrate", (int)nrate);
+
+exit:
+	return err;
+}
+
+static int
+wl_assoc_info(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i, req_ies_len = 0, resp_ies_len = 0;
+	wl_assoc_info_t assoc_info;
+	int ret;
+	uint8 *pbuf;
+
+	UNUSED_PARAMETER(argv);
+
+	/* get the generic association information */
+	strcpy(buf, cmd->name);
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+		return ret;
+
+	memcpy(&assoc_info, buf, sizeof(wl_assoc_info_t));
+	assoc_info.req_len = htod32(assoc_info.req_len);
+	assoc_info.resp_len = htod32(assoc_info.resp_len);
+	assoc_info.flags = htod32(assoc_info.flags);
+
+	printf("Assoc req:\n");
+	printf("\tlen 0x%x\n", assoc_info.req_len);
+	if (assoc_info.req_len) {
+		printf("\tcapab  0x%x\n", ltoh16(assoc_info.req.capability));
+		printf("\tlisten 0x%x\n", ltoh16(assoc_info.req.listen));
+		req_ies_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
+		if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
+			printf("\treassoc bssid %s\n",
+				wl_ether_etoa(&assoc_info.reassoc_bssid));
+			req_ies_len -= ETHER_ADDR_LEN;
+		}
+	}
+
+	/* get the association req IE's if there are any */
+	if (req_ies_len) {
+		strcpy(buf, "assoc_req_ies");
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+			return ret;
+
+		printf("assoc req IEs:\n\t");
+		for (i = 1, pbuf = (uint8*)buf; i <= req_ies_len; i++) {
+			printf("0x%02x ", *pbuf++);
+			if (!(i%8))
+				printf("\n\t");
+		}
+	}
+
+	printf("\nAssoc resp:\n");
+	printf("\tlen 0x%x\n", assoc_info.resp_len);
+	if (assoc_info.resp_len) {
+		printf("\tcapab  0x%x\n", ltoh16(assoc_info.resp.capability));
+		printf("\tstatus 0x%x\n", ltoh16(assoc_info.resp.status));
+		printf("\taid    0x%x\n", ltoh16(assoc_info.resp.aid));
+		resp_ies_len = assoc_info.resp_len - sizeof(struct dot11_assoc_resp);
+	}
+
+	/* get the association resp IE's if there are any */
+	if (resp_ies_len) {
+		strcpy(buf, "assoc_resp_ies");
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+			return ret;
+
+		printf("assoc resp IEs:\n\t");
+		for (i = 1, pbuf = (uint8*)buf; i <= resp_ies_len; i++) {
+			printf(" 0x%02x ", *pbuf++);
+			if (!(i%8))
+				printf("\n\t");
+
+		}
+	}
+	printf("\n");
+
+	return 0;
+}
+
+static void dump_management_fields(uint8 *data, int len)
+{
+	int i, tag_len;
+	uint8 tag;
+	char temp[64];
+	uint8 *p;
+
+	while (len > 0) {
+		/* Get the tag */
+		tag = *data;
+		data++; len--;
+
+		/* Get the tag length */
+		tag_len = (int) *data;
+		data++; len--;
+
+		printf("Tag:%d Len:%d - ", tag, tag_len);
+
+		switch (tag) {
+		case DOT11_MNG_SSID_ID:
+			for (i = 0; i < tag_len; i++) {
+				temp[i] = data[i];
+			}
+			if (i < 64) {
+				temp[i] = '\0';
+			}
+			printf("SSID: '%s'\n", temp);
+			break;
+		case DOT11_MNG_FH_PARMS_ID:
+			printf("FH Parameter Set\n");
+			break;
+		case DOT11_MNG_DS_PARMS_ID:
+			printf("DS Parameter Set\n");
+			break;
+		case DOT11_MNG_CF_PARMS_ID:
+			printf("CF Parameter Set\n");
+			break;
+		case DOT11_MNG_RATES_ID:
+			printf("Supported Rates\n");
+			break;
+		case DOT11_MNG_TIM_ID:
+			printf("Traffic Indication Map (TIM)\n");
+			break;
+		case DOT11_MNG_IBSS_PARMS_ID:
+			printf("IBSS Parameter Set\n");
+			break;
+		case DOT11_MNG_COUNTRY_ID:
+			p = data;
+			printf("Country '%c%c%c'\n",
+			       data[0], data[1], data[2]);
+			p += DOT11_MNG_COUNTRY_ID_LEN;
+			while (((data+tag_len) - p) >= DOT11_MNG_COUNTRY_ID_LEN) {
+				printf("Start Channel: %d, Channels: %d, "
+				       "Max TX Power: %d dBm\n",
+				       p[0], p[1], p[2]);
+				p += DOT11_MNG_COUNTRY_ID_LEN;
+			}
+			break;
+		case DOT11_MNG_HOPPING_PARMS_ID:
+			printf("Hopping Pattern Parameters\n");
+			break;
+		case DOT11_MNG_HOPPING_TABLE_ID:
+			printf("Hopping Pattern Table\n");
+			break;
+		case DOT11_MNG_REQUEST_ID:
+			printf("Request\n");
+			break;
+		case DOT11_MNG_QBSS_LOAD_ID:
+			printf("QBSS Load\n");
+			break;
+		case DOT11_MNG_EDCA_PARAM_ID:
+			printf("EDCA Parameter\n");
+			break;
+		case DOT11_MNG_CHALLENGE_ID:
+			printf("Challenge text\n");
+			break;
+		case DOT11_MNG_PWR_CONSTRAINT_ID:
+			printf("Power Constraint\n");
+			break;
+		case DOT11_MNG_PWR_CAP_ID:
+			printf("Power Capability\n");
+			break;
+		case DOT11_MNG_TPC_REQUEST_ID:
+			printf("Transmit Power Control (TPC) Request\n");
+			break;
+		case DOT11_MNG_TPC_REPORT_ID:
+			printf("Transmit Power Control (TPC) Report\n");
+			break;
+		case DOT11_MNG_SUPP_CHANNELS_ID:
+			printf("Supported Channels\n");
+			break;
+		case DOT11_MNG_CHANNEL_SWITCH_ID:
+			printf("Channel Switch Announcement\n");
+			break;
+		case DOT11_MNG_MEASURE_REQUEST_ID:
+			printf("Measurement Request\n");
+			break;
+		case DOT11_MNG_MEASURE_REPORT_ID:
+			printf("Measurement Report\n");
+			break;
+		case DOT11_MNG_QUIET_ID:
+			printf("Quiet\n");
+			break;
+		case DOT11_MNG_IBSS_DFS_ID:
+			printf("IBSS DFS\n");
+			break;
+		case DOT11_MNG_ERP_ID:
+			printf("ERP Information\n");
+			break;
+		case DOT11_MNG_TS_DELAY_ID:
+			printf("TS Delay\n");
+			break;
+		case DOT11_MNG_HT_CAP:
+			printf("HT Capabilities\n");
+			break;
+		case DOT11_MNG_QOS_CAP_ID:
+			printf("QoS Capability\n");
+			break;
+		case DOT11_MNG_NONERP_ID:
+			printf("NON-ERP\n");
+			break;
+		case DOT11_MNG_RSN_ID:
+			printf("RSN\n");
+			break;
+		case DOT11_MNG_EXT_RATES_ID:
+			printf("Extended Supported Rates\n");
+			break;
+		case DOT11_MNG_AP_CHREP_ID:
+			printf("AP Channel Report\n");
+			break;
+		case DOT11_MNG_NEIGHBOR_REP_ID:
+			printf("Neighbor Report\n");
+			break;
+		case DOT11_MNG_MDIE_ID:
+			printf("Mobility Domain\n");
+			break;
+		case DOT11_MNG_FTIE_ID:
+			printf("Fast BSS Transition\n");
+			break;
+		case DOT11_MNG_FT_TI_ID:
+			printf("802.11R Timeout Interval\n");
+			break;
+		case DOT11_MNG_REGCLASS_ID:
+			printf("Regulatory Class\n");
+			break;
+		case DOT11_MNG_EXT_CSA_ID:
+			printf("Extended CSA\n");
+			break;
+		case DOT11_MNG_HT_ADD:
+			printf("HT Information\n");
+			break;
+		case DOT11_MNG_EXT_CHANNEL_OFFSET:
+			printf("Ext Channel\n");
+			break;
+#ifdef BCMWAPI_WAI
+		case DOT11_MNG_WAPI_ID:
+			printf("WAPI\n");
+			break;
+#endif
+		case DOT11_MNG_RRM_CAP_ID:
+			printf("Radio Measurement\n");
+			break;
+		case DOT11_MNG_HT_BSS_COEXINFO_ID:
+			printf("OBSS Coexistence INFO\n");
+			break;
+		case DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID:
+			printf("OBSS Intolerant Channel List\n");
+			break;
+		case DOT11_MNG_HT_OBSS_ID:
+			printf("OBSS HT Info\n");
+			break;
+#ifdef DOT11_MNG_CHANNEL_USAGE
+		case DOT11_MNG_CHANNEL_USAGE:
+			printf("Channel Usage\n");
+			break;
+#endif
+		case DOT11_MNG_LINK_IDENTIFIER_ID:
+			printf("TDLS Link Identifier\n");
+			break;
+		case DOT11_MNG_WAKEUP_SCHEDULE_ID:
+			printf("TDLS Wakeup Schedule\n");
+			break;
+		case DOT11_MNG_CHANNEL_SWITCH_TIMING_ID:
+			printf("TDLS Channel Switch Timing\n");
+			break;
+		case DOT11_MNG_PTI_CONTROL_ID:
+			printf("TDLS PTI Control\n");
+			break;
+		case DOT11_MNG_PU_BUFFER_STATUS_ID:
+			printf("TDLS PU Buffer Status\n");
+			break;
+		case DOT11_MNG_EXT_CAP_ID:
+			printf("Management Ext Capability\n");
+			break;
+		case DOT11_MNG_PROPR_ID:
+			printf("Proprietary\n");
+			break;
+		default:
+			if (tag_len <= len) {
+				printf("Unsupported tag\n");
+			} else {
+				/* Just dump the remaining data */
+				printf("Unsupported tag error/malformed\n");
+				tag_len = len;
+			}
+			break;
+		} /* switch */
+
+		wl_hexdump(data, tag_len);
+
+		data += tag_len;
+		len -= tag_len;
+	} /* while */
+}
+
+static void dump_management_info(uint8 *data, int len)
+{
+	struct dot11_management_header hdr;
+	struct dot11_bcn_prb parms;
+
+	if (len <= (int) (sizeof(hdr)+sizeof(parms))) {
+		/* Management packet invalid */
+		return;
+	}
+
+	memcpy(&hdr, data, sizeof(hdr));
+	data += sizeof(hdr);
+	len -= sizeof(hdr);
+
+	memcpy(&parms, data, sizeof(parms));
+	data += sizeof(parms);
+	len -= sizeof(parms);
+
+	/* 802.11 MAC header */
+	printf("Frame Ctl: 0x%04x\n", ltoh16(hdr.fc));
+	printf("Duration : 0x%04x\n", ltoh16(hdr.durid));
+	printf("Dest addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       hdr.da.octet[0],
+	       hdr.da.octet[1],
+	       hdr.da.octet[2],
+	       hdr.da.octet[3],
+	       hdr.da.octet[4],
+	       hdr.da.octet[5]);
+	printf("Src addr : %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       hdr.sa.octet[0],
+	       hdr.sa.octet[1],
+	       hdr.sa.octet[2],
+	       hdr.sa.octet[3],
+	       hdr.sa.octet[4],
+	       hdr.sa.octet[5]);
+	printf("BSSID    : %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       hdr.bssid.octet[0],
+	       hdr.bssid.octet[1],
+	       hdr.bssid.octet[2],
+	       hdr.bssid.octet[3],
+	       hdr.bssid.octet[4],
+	       hdr.bssid.octet[5]);
+	printf("Seq ctl  : 0x%04x\n", hdr.seq);
+
+	/* 802.11 management frame */
+	printf("Timestamp: 0x%08x%08x\n",
+	       ltoh32(parms.timestamp[0]), ltoh32(parms.timestamp[1]));
+	printf("Beacon Interval: 0x%04x\n", ltoh16(parms.beacon_interval));
+	printf("Capabilities: 0x%04x\n", ltoh32(parms.capability));
+
+	dump_management_fields(data, len);
+}
+
+static int
+wl_management_info(void *wl, cmd_t *cmd, char**argv)
+{
+	int ret = 0;
+	int len;
+	uint8 *data;
+	FILE *fp = NULL;
+	char *fname = NULL;
+	int raw = 0;
+
+	/* Skip the command name */
+	argv++;
+
+	while (*argv) {
+		char *s = *argv;
+
+		if (!strcmp(s, "-f") && argv[1] != NULL) {
+			/* Write packet to a file */
+			fname = argv[1];
+			argv += 2;
+		} else if (!strcmp(s, "-r")) {
+			/* Do a hex dump to console */
+			raw = 1;
+			argv++;
+		} else
+			return BCME_USAGE_ERROR;
+	}
+
+	/* Get the beacon information */
+	strcpy(buf, cmd->name);
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	/*
+	 * Dump out the beacon data. The first word (4 bytes) is the
+	 * length of the management packet followed by the data itself.
+	 */
+	len = dtoh32(*(int *)buf);
+
+	if (len <= 0) {
+		/* Nothing to do */
+		return ret;
+	}
+
+	data = (uint8 *) (buf + sizeof(int));
+	printf("Data: %p Len: %d bytes\n", data, len);
+
+	if (fname != NULL) {
+		/* Write the packet to a file */
+		if ((fp = fopen(fname, "wb")) == NULL) {
+			fprintf(stderr, "Failed to open file %s\n",
+			        fname);
+			ret = BCME_BADARG;
+		} else {
+			ret = fwrite(data, 1, len, fp);
+
+			if (ret != len) {
+				fprintf(stderr,
+				        "Error write %d bytes to file %s, rc %d!\n",
+				        len, fname, ret);
+				ret = -1;
+			}
+		}
+	} else if (raw) {
+		/* Hex dump */
+		wl_hexdump(data, len);
+	} else {
+		/* Print management (w/some decode) */
+		dump_management_info(data, len);
+	}
+
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+static int
+wl_pmkid_info(void *wl, cmd_t *cmd, char**argv)
+{
+	int i, j, ret;
+	pmkid_list_t *pmkid_info;
+
+	if (!*++argv) {
+		strcpy(buf, cmd->name);
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+			return ret;
+
+		pmkid_info = (pmkid_list_t *)buf;
+		pmkid_info->npmkid = dtoh32(pmkid_info->npmkid);
+		printf("\npmkid entries : %d\n", pmkid_info->npmkid);
+
+		for (i = 0; i < (int)pmkid_info->npmkid; i++) {
+			printf("\tPMKID[%d]: %s =",
+				i, wl_ether_etoa(&pmkid_info->pmkid[i].BSSID));
+			for (j = 0; j < WPA2_PMKID_LEN; j++)
+				printf("%02x ", pmkid_info->pmkid[i].PMKID[j]);
+			printf("\n");
+		}
+	}
+	else {
+#ifdef test_pmkid_info
+		char eaddr[6] = {0x0, 0x0, 0x1, 0x2, 0x3, 0x5};
+		char eaddr1[6] = {0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+		char id[WPA2_PMKID_LEN], id1[WPA2_PMKID_LEN];
+		int i, len = (sizeof(uint32) + 2*(sizeof(pmkid_t)));
+
+		/* check that the set uses to "test" cmd */
+		if (strcmp(*argv, "test")) {
+			printf("\t wl pmkid_info only supports `test` a test specific set\n");
+			return BCME_USAGE_ERROR;
+		}
+		if ((pmkid_info = (pmkid_list_t *)malloc(len)) == NULL)	{
+			printf("\tfailed to allocate buffer\n");
+			return BCME_NOMEM;
+		}
+
+		printf("\toverwriting pmkid table with test pattern\n");
+		for (i = 0; i < (int)sizeof(id); i++) {
+			id[i] = i;
+			id1[i] = (i*2);
+		}
+
+		/* "test" - creates two PMKID entries and sets the table to that */
+		pmkid_info->npmkid = htod32(2);
+		memcpy(&pmkid_info->pmkid[0].BSSID.octet[0], &eaddr[0], ETHER_ADDR_LEN);
+		memcpy(&pmkid_info->pmkid[0].PMKID[0], &id[0], WPA2_PMKID_LEN);
+		memcpy(&pmkid_info->pmkid[1].BSSID.octet[0], &eaddr1[0], ETHER_ADDR_LEN);
+		memcpy(&pmkid_info->pmkid[1].PMKID[0], &id1[0], WPA2_PMKID_LEN);
+
+		ret = wlu_var_setbuf(wl, cmd->name, pmkid_info, len);
+
+		free(pmkid_info);
+
+		return ret;
+#else
+		printf("\tset cmd ignored\n");
+#endif /* test_pmkid_info */
+	}
+
+	return 0;
+}
+
+static int
+wl_rateset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_rateset_args_t rs, defrs;
+	int error;
+	uint i;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current rateset */
+		if ((error = wlu_iovar_get(wl, "cur_rateset", &rs, sizeof(rs))) < 0)
+			return (error);
+
+		dump_rateset(rs.rates, dtoh32(rs.count));
+		printf("\n");
+		wl_print_mcsset((char *)rs.mcs);
+		wl_print_vhtmcsset((uint16 *)rs.vht_mcs);
+	} else {
+		/* get default rateset and mcsset */
+		if ((error = wlu_iovar_get(wl, "rateset", &defrs,
+		                           sizeof(wl_rateset_args_t))) < 0)
+			return (error);
+		defrs.count = dtoh32(defrs.count);
+
+		if (!stricmp(*argv, "all")) {
+			for (i = 0; i < defrs.count; i++)
+				defrs.rates[i] |= 0x80;
+			defrs.count = htod32(defrs.count);
+			error = wlu_iovar_set(wl, "rateset", &defrs,
+			                      sizeof(wl_rateset_args_t));
+		}
+		else if (!stricmp(*argv, "default")) {
+			defrs.count = htod32(defrs.count);
+			error = wlu_iovar_set(wl, "rateset", &defrs,
+			                      sizeof(wl_rateset_args_t));
+		}
+		else {	/* arbitrary list */
+			error = wl_parse_rateset(wl, &defrs, argv);
+			if (!error) {
+
+				/* check for common error of no basic rates */
+				for (i = 0; i < defrs.count; i++) {
+					if (defrs.rates[i] & 0x80)
+						break;
+				}
+				if (i < defrs.count) {
+					defrs.count = htod32(defrs.count);
+					error = wlu_iovar_set(wl, "rateset", &defrs,
+						sizeof(wl_rateset_args_t));
+				} else {
+					error = BCME_BADARG;
+					fprintf(stderr,
+					    "Bad Args: at least one rate must be marked Basic\n");
+				}
+			}
+		}
+
+	}
+	return (error);
+}
+
+static int
+wl_default_rateset(void *wl, cmd_t *cmd, char **argv)
+{
+	int error = 0;
+	wl_rates_info_t rates_info;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset((char*)&rates_info.rs_tgt, 0, sizeof(wl_rateset_t));
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse phy type\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* phy_type */
+	if (!stricmp(*argv, "a"))
+		rates_info.phy_type = 0;
+	else if (!stricmp(*argv, "b"))
+		rates_info.phy_type = 2;
+	else if (!stricmp(*argv, "g"))
+		rates_info.phy_type = 2;
+	else if (!stricmp(*argv, "n"))
+		rates_info.phy_type = 4;
+	else if (!stricmp(*argv, "lp"))
+		rates_info.phy_type = 5;
+	else if (!stricmp(*argv, "ssn"))
+		rates_info.phy_type = 6;
+	else if (!stricmp(*argv, "ht"))
+		rates_info.phy_type = 7;
+	else if (!stricmp(*argv, "lcn"))
+		rates_info.phy_type = 8;
+	else if (!stricmp(*argv, "lcn40"))
+		rates_info.phy_type = 10;
+	else if (!stricmp(*argv, "ac"))
+		rates_info.phy_type = 11;
+	else {
+		fprintf(stderr, "Wrong phy type: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse band type\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* band type */
+	if (!stricmp(*argv, "5"))
+		rates_info.bandtype = WLC_BAND_5G;
+	else if (!stricmp(*argv, "2"))
+		rates_info.bandtype = WLC_BAND_2G;
+	else {
+		fprintf(stderr, "Wrong band type: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse cck\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* cck only */
+	if (!stricmp(*argv, "0"))
+		rates_info.cck_only = FALSE;
+	else if (!stricmp(*argv, "1"))
+		rates_info.cck_only = TRUE;
+	else {
+		fprintf(stderr, "Wrong cck: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse basic rates\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* rate_mask */
+	if (!stricmp(*argv, "0"))
+		rates_info.rate_mask = 0x7f;
+	else if (!stricmp(*argv, "1"))
+		rates_info.rate_mask = 0xff;
+	else {
+		fprintf(stderr, "Wrong basic rates: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse mcs\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* mcs */
+	if (!stricmp(*argv, "0"))
+		rates_info.mcsallow = FALSE;
+	else if (!stricmp(*argv, "1"))
+		rates_info.mcsallow = TRUE;
+	else {
+		fprintf(stderr, "Wrong mcs: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse bandwidth\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* channel bandwidth */
+	if (!stricmp(*argv, "10"))
+		rates_info.bw = 10;
+	else if (!stricmp(*argv, "20"))
+		rates_info.bw = 20;
+	else if (!stricmp(*argv, "40"))
+		rates_info.bw = 40;
+	else if (!stricmp(*argv, "80"))
+		rates_info.bw = 80;
+	else if (!stricmp(*argv, "160"))
+		rates_info.bw = 160;
+	else {
+		fprintf(stderr, "Wrong bandwidth: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse tx/rx streams\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* mcs */
+	if (!stricmp(*argv, "tx")) {
+		int txstreams;
+		if ((error = wlu_iovar_getint(wl, "txstreams", &txstreams)) < 0) {
+			fprintf(stderr, "Can't get tx streams\n");
+			return BCME_USAGE_ERROR;
+		}
+		rates_info.txstreams = txstreams;
+	}
+	else if (!stricmp(*argv, "rx")) {
+		int rxstreams;
+		if ((error = wlu_iovar_getint(wl, "rxstreams", &rxstreams)) < 0) {
+			fprintf(stderr, "Can't get rx streams\n");
+			return BCME_USAGE_ERROR;
+		}
+		rates_info.txstreams = rxstreams;
+	}
+	else {
+		fprintf(stderr, "Wrong tx/rx streams: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* get default rates */
+	if ((error = wlu_iovar_getbuf(wl, "default_rateset", NULL, 0, &rates_info,
+		sizeof(wl_rates_info_t)))) {
+		fprintf(stderr, "default_rateset failed\n");
+		return (error);
+	}
+
+	dump_rateset(rates_info.rs_tgt.rates, dtoh32(rates_info.rs_tgt.count));
+
+	return (error);
+}
+
+static int
+wl_sup_rateset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_rateset_args_t rs;
+	bool got_basic;
+	int error;
+	uint i;
+
+	error = 0;
+	memset((char*)&rs, 0, sizeof(wl_rateset_args_t));
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get rateset */
+		if ((error = wlu_get(wl, cmd->get, &rs, sizeof(wl_rateset_t))) < 0)
+			return (error);
+
+		dump_rateset(rs.rates, dtoh32(rs.count));
+		printf("\n");
+	} else {
+		if (!stricmp(*argv, "-1") || !stricmp(*argv, "0")) {
+			/* set an empty rateset */
+			error = wlu_set(wl, cmd->set, &rs, sizeof(wl_rateset_t));
+		}
+		else {	/* set the specified rateset */
+			wl_parse_rateset(wl, &rs, argv);
+			/* check for common error of including a basic rate */
+			got_basic = FALSE;
+			for (i = 0; i < rs.count; i++) {
+				if (rs.rates[i] & 0x80) {
+					rs.rates[i] &= 0x7F;
+					got_basic = TRUE;
+				}
+			}
+			if (got_basic) {
+				fprintf(stderr,
+				"Warning: Basic rate attribute ignored for \"%s\" command\n",
+				cmd->name);
+			}
+			rs.count = htod32(rs.count);
+			error = wlu_set(wl, cmd->set, &rs, sizeof(wl_rateset_t));
+		}
+
+	}
+	return (error);
+}
+
+/*
+ * Parse the rateset command arguments into the passed wl_rateset_args_t structure.
+ *
+ * Returns 0 on success, or an appropriate error code (BCME_USAGE_ERROR, BCME_BADARG).
+ *
+ */
+static int
+wl_parse_rateset(void *wl, wl_rateset_args_t* rs, char **argv)
+{
+	char* endp = NULL;
+	char* arg;
+	int r;
+	int mcs_index = 0;
+	uint32 mcs_mask;
+	int error = 0;
+	wl_rateset_args_t cur_rs;
+	bool mcs_args, vht_args;
+
+	mcs_args = vht_args = FALSE;
+
+	memset(rs, 0, sizeof(*rs));
+
+	while ((arg = *argv++) != NULL) {
+		/* mcs rates */
+		if (!stricmp(arg, "-m")) {
+			mcs_args = TRUE;
+			break;
+		}
+
+		/* vht rates */
+		if (!stricmp(arg, "-v")) {
+			vht_args = TRUE;
+			break;
+		}
+
+		/* Parse legacy rates */
+
+		if (rs->count >= WL_MAXRATES_IN_SET) {
+			fprintf(stderr,
+			"parsing \"%s\", too many rates specified, max is %d rates\n",
+			arg, WL_MAXRATES_IN_SET);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		/* convert the rate number to a 500kbps rate by multiplying by 2 */
+		r = (int)(strtoul(arg, &endp, 0) * 2);
+		if (endp == arg) {
+			fprintf(stderr, "unable to convert the rate parameter \"%s\"\n", arg);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		/* parse a .5 specially */
+		if (!strncmp(endp, ".5", 2)) {
+			r += 1;
+			endp += 2;
+		}
+
+		/* strip trailing space */
+		while (isspace((int)endp[0]))
+			endp++;
+
+		/* check for a basic rate specifier */
+		if (!stricmp(endp, "b") || !stricmp(endp, "(b)")) {
+			r |= 0x80;
+		} else if (endp[0] != '\0') {
+			fprintf(stderr,
+				"unable to convert trailing characters"
+				" \"%s\" in the rate parameter \"%s\"\n",
+				endp, arg);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		/* no legacy rates specified */
+		if ((rs->count == 0) && (r == 0)) {
+			fprintf(stderr, "empty legacy rateset not supported\n");
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		rs->rates[rs->count++] = r;
+	}
+
+	if (error)
+		return error;
+
+	if (!mcs_args && !vht_args && !rs->count)
+		return BCME_USAGE_ERROR; /* Cannot happen, really */
+
+	/*
+	 * If one of the rate sets was not specified, keep its current setting.
+	 */
+
+	error = wlu_iovar_get(wl, "cur_rateset", &cur_rs, sizeof(cur_rs));
+	if (error)
+		return error;
+
+	if (!rs->count) { /* No legacy rates specified -- keep what we have */
+		rs->count = cur_rs.count;
+		memcpy(&rs->rates, &cur_rs.rates, rs->count);
+	}
+
+	if (!mcs_args) { /* No MCS rates specified */
+		memcpy(rs->mcs, cur_rs.mcs, MCSSET_LEN);
+	}
+
+	if (!vht_args) { /* No VHT rates specified, keep current values */
+		memcpy(rs->vht_mcs, cur_rs.vht_mcs,
+		       VHT_CAP_MCS_MAP_NSS_MAX * sizeof(rs->vht_mcs[0]));
+	}
+
+	/* If no more args, return. */
+
+	if (!arg) {
+		return error;
+	}
+
+	/* Parse mcs or VHT rateset values */
+
+	while ((arg = *argv++) != NULL) {
+
+	    if (mcs_args) {
+
+		    if (mcs_index >= MCSSET_LEN) {
+			fprintf(stderr, "parsing \"%s\", too many mcs rates "
+			        "specified, max is %d rates\n", arg, MCSSET_LEN);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		mcs_mask = strtoul(arg, &endp, 16);
+
+		if (endp == arg) {
+			fprintf(stderr, "unable to convert the mcs parameter \"%s\"\n", arg);
+			error = BCME_BADARG;
+			break;
+		}
+
+		/* clear the mcs rates */
+		if (mcs_mask == 0) {
+			memset(rs->mcs, 0, MCSSET_LEN);
+			break;
+		}
+
+		/* copy the mcs rates bitmap octets */
+		rs->mcs[mcs_index++] = mcs_mask;
+
+	    } else { /* vht_args */
+
+		    /*
+		     * Specified as rate masks for Nss=0, Nss=1, etc.
+		     */
+		    if (mcs_index >= VHT_CAP_MCS_MAP_NSS_MAX) {
+			fprintf(stderr,
+				"Error: Too many VHT rate masks specified, max %d\n",
+				VHT_CAP_MCS_MAP_NSS_MAX);
+			error = BCME_USAGE_ERROR;
+			break;
+		    }
+
+		    mcs_mask = strtoul( arg, &endp, 16 ); /* Base 16 for consistency with -m */
+
+		    if ((*arg == '\0') || (*endp != '\0')) {
+			    fprintf(stderr, "Error converting VHT rate mask value '%s'\n", arg);
+			    error = BCME_USAGE_ERROR;
+			    break;
+		    }
+
+		    /*
+		     * Can only specify 0, 0xff, 0x1ff, 0x3ff because of the way the rates
+		     * are encoded in the driver (0-3).
+		     */
+		    if ((mcs_mask != 0x0000) &&   /* vht disabled */
+			(mcs_mask != 0x00ff) &&   /* vht mcs0-7 */
+			(mcs_mask != 0x01ff) &&   /* vht mcs0-8 */
+			(mcs_mask != 0x03ff)) {   /* vht mcs0-9 */
+			    fprintf(stderr, "Error: VHT rate mask must be 0 (disabled),"
+				" 0xff (MCS0-7), 0x1ff (MCS0-8), or 0x3ff (MCS0-9).\n");
+			    error = BCME_BADARG;
+			    break;
+		    }
+
+		    rs->vht_mcs[mcs_index++] = mcs_mask;
+	       }
+	}
+
+	return error;
+}
+
+/*
+ * Get or Set Pwr Sel Params
+ *	wl powersel_params \
+ *		<tp_ratio_thresh> <rate_stab_thresh> <pwr_stab_thresh> <pwr_sel_exp_time>
+ */
+static int
+wl_power_sel_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, argc;
+	powersel_params_t pwrsel_params;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current powersel params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &pwrsel_params,
+			(sizeof(powersel_params_t)))) < 0)
+			return (err);
+
+		printf("- Link Power Control parameters -\n");
+		printf("tp_ratio_thresh\t\t= %d\nrate_stab_thresh\t= %d\n",
+			pwrsel_params.tp_ratio_thresh, pwrsel_params.rate_stab_thresh);
+		printf("pwr_stab_thresh\t\t= %d\npwr_sel_exp_time\t= %d\n",
+			pwrsel_params.pwr_stab_thresh, pwrsel_params.pwr_sel_exp_time);
+	} else {
+		char *endptr;
+		/* Validate num of entries */
+		for (argc = 0; argv[argc]; argc++);
+		if (argc != 4)
+			return BCME_USAGE_ERROR;
+
+		argc = 0;
+		pwrsel_params.tp_ratio_thresh = strtol(argv[argc], &endptr, 0);
+		argc++;
+		pwrsel_params.rate_stab_thresh = strtol(argv[argc], &endptr, 0);
+		argc++;
+		pwrsel_params.pwr_stab_thresh = strtol(argv[argc], &endptr, 0);
+		argc++;
+		pwrsel_params.pwr_sel_exp_time = strtol(argv[argc], &endptr, 0);
+
+		/* Set powersel params */
+		err = wlu_iovar_set(wl, cmd->name, (void *) &pwrsel_params,
+			(sizeof(powersel_params_t)));
+	}
+
+	return err;
+}
+
+/* Set per-band bandwidth */
+static int wl_bw_cap(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	struct {
+		uint32 band;
+		uint32 bw_cap;
+	} param = { 0, 0 };
+	char *s = NULL;
+	void *ptr = NULL;
+
+	/* Skip the command name */
+	argv++;
+
+	if (*argv) {
+		if (!strcmp(*argv, "a") || !strcmp(*argv, "5") || !strcmp(*argv, "5g")) {
+			param.band = WLC_BAND_5G;
+		} else if (!strcmp(*argv, "b") || !strcmp(*argv, "2") || !strcmp(*argv, "2g")) {
+			param.band = WLC_BAND_2G;
+		} else {
+			fprintf(stderr,
+			        "%s: invalid band %s\n",
+			        cmd->name, *argv);
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		argv++;
+
+		if (*argv) {
+			/* Optional 2nd arg is used to set the bandwidth cap */
+			s = NULL;
+
+			param.bw_cap = (uint32) strtoul(*argv, &s, 0);
+			if (s && *s != '\0') {
+				fprintf(stderr, "%s: invalid bandwidth '%s'\n",
+				        cmd->name, *argv);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+	} else {
+		fprintf(stderr, "%s: band unspecified\n", cmd->name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (param.bw_cap == 0) {
+		if ((err = wlu_var_getbuf(wl, cmd->name, &param, sizeof(param), &ptr)) < 0)
+			return err;
+
+		printf("0x%x\n", *((uint32 *)ptr));
+	} else {
+		err = wlu_var_setbuf(wl, cmd->name, &param, sizeof(param));
+	}
+
+exit:
+	return err;
+}
+
+static int
+wl_channel(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	channel_info_t ci;
+
+	if (!*++argv) {
+		memset(&ci, 0, sizeof(ci));
+		if ((ret = wlu_get(wl, cmd->get, &ci, sizeof(channel_info_t))) < 0)
+			return ret;
+		ci.hw_channel = dtoh32(ci.hw_channel);
+		ci.scan_channel = dtoh32(ci.scan_channel);
+		ci.target_channel = dtoh32(ci.target_channel);
+		if (ci.scan_channel) {
+			printf("Scan in progress.\n");
+			printf("current scan channel\t%d\n", ci.scan_channel);
+		} else {
+			printf("No scan in progress.\n");
+		}
+		printf("current mac channel\t%d\n", ci.hw_channel);
+		printf("target channel\t%d\n", ci.target_channel);
+		return 0;
+	} else {
+		ci.target_channel = htod32(atoi(*argv));
+		ret =  wlu_set(wl, cmd->set, &ci.target_channel, sizeof(int));
+		return ret;
+	}
+}
+
+static int
+wl_chanspec(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_chanspec";
+	bool band_set = FALSE, ch_set = FALSE, bw_set = FALSE, ctl_sb_set = FALSE;
+	int err, opt_err;
+	uint32 val = 0;
+	chanspec_t chanspec = 0;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, cmd->name, (int*)&val)) < 0)
+			return err;
+
+		chanspec = wl_chspec32_from_driver(val);
+		wf_chspec_ntoa(chanspec, buf);
+		printf("%s (0x%x)\n", buf, chanspec);
+		return 0;
+	}
+
+
+	chanspec = wf_chspec_aton(*argv);
+	if (chanspec != 0) {
+		val = wl_chspec32_to_driver(chanspec);
+		if (val != INVCHANSPEC) {
+			err = wlu_iovar_setint(wl, cmd->name, val);
+		} else {
+			err = BCME_USAGE_ERROR;
+		}
+	} else {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'c') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" the channel\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val > 224) {
+					fprintf(stderr, "%s: invalid channel %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				chanspec |= to.val;
+				ch_set = TRUE;
+			}
+			if (to.opt == 'b') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for band\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 5) && (to.val != 2)) {
+					fprintf(stderr,
+						"%s: invalid band %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 5)
+					chanspec |= WL_CHANSPEC_BAND_5G;
+				else
+					chanspec |= WL_CHANSPEC_BAND_2G;
+				band_set = TRUE;
+			}
+			if (to.opt == 'w') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" bandwidth\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 20) && (to.val != 40) && (to.val != 80)) {
+					fprintf(stderr,
+						"%s: invalid bandwidth %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 20)
+					chanspec |= WL_CHANSPEC_BW_20;
+				else if (to.val == 40)
+					chanspec |= WL_CHANSPEC_BW_40;
+				else
+					chanspec |= WL_CHANSPEC_BW_80;
+				bw_set = TRUE;
+			}
+			if (to.opt == 's') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" ctl sideband\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 1) && (to.val != 0) && (to.val != -1)) {
+					fprintf(stderr,
+						"%s: invalid ctl sideband %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == -1)
+					chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
+				else if (to.val == 1)
+					chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
+				ctl_sb_set = TRUE;
+			}
+		}
+
+		/* set ctl sb to 20 if not set and 20mhz is selected */
+		if (!ctl_sb_set && CHSPEC_IS20(chanspec)) {
+			ctl_sb_set = TRUE;
+		}
+
+		if (ch_set && band_set && bw_set && ctl_sb_set) {
+			val = wl_chspec32_to_driver(chanspec);
+			if (val != INVCHANSPEC) {
+				err = wlu_iovar_setint(wl, cmd->name, val);
+			} else {
+				err = BCME_USAGE_ERROR;
+			}
+		} else {
+			if (!ch_set)
+				fprintf(stderr, "%s: you need to set a channel,"
+					" '-c <ch>'\n", fn_name);
+			if (!band_set)
+				fprintf(stderr, "%s: you need to set a band,"
+					" '-b <5|2>'\n", fn_name);
+			if (!bw_set)
+				fprintf(stderr, "%s: you need to set a bandwidth,"
+					" '-w <20|40>'\n", fn_name);
+			if (!ctl_sb_set)
+				fprintf(stderr, "%s: you need to set a ctl sideband,"
+					  " '-s <-1|0|1>'\n", fn_name);
+			err = BCME_USAGE_ERROR;
+		}
+	}
+
+	if (!err)
+		printf("Chanspec set to 0x%x\n", chanspec);
+
+exit:
+	return err;
+}
+
+static int
+wl_rclass(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR;
+	chanspec_t chanspec = 0;
+	void *ptr;
+
+	/* toss the command name */
+	argv++;
+
+	if (*argv) {
+		chanspec = wf_chspec_aton(*argv);
+		if (chanspec != 0) {
+			err = wlu_var_getbuf(wl, cmd->name, &chanspec, sizeof(chanspec_t), &ptr);
+
+			if (err)
+				printf("Read rclass fails: chanspec:0x%x\n", chanspec);
+			else
+				printf("rclass=0x%x\n", *((int *)ptr));
+		}
+	}
+
+	return err;
+}
+
+static int
+wl_chanim_state(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 chanspec;
+	int argc = 0;
+	int ret, val;
+
+	argv++;
+
+	/* find the arg count */
+	while (argv[argc])
+		argc++;
+
+	if (argc != 1)
+		return BCME_USAGE_ERROR;
+
+	chanspec = wf_chspec_aton(*argv);
+	chanspec = wl_chspec32_to_driver(chanspec);
+	if (chanspec == INVCHANSPEC) {
+		return BCME_USAGE_ERROR;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &chanspec, sizeof(chanspec),
+	                       buf, WLC_IOCTL_SMLEN);
+	if (ret < 0)
+		return ret;
+	val = *(int*)buf;
+	val = dtoh32(val);
+
+	printf("%d\n", val);
+	return 0;
+}
+
+static int
+wl_chanim_mode(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr;
+	int mode;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_iovar_getint(wl, cmd->name, &mode)) < 0)
+			return ret;
+
+		switch (mode) {
+		case CHANIM_DISABLE:
+			printf("CHANIM mode: disabled.\n");
+			break;
+		case CHANIM_DETECT:
+			printf("CHANIM mode: detect only.\n");
+			break;
+		case CHANIM_EXT:
+			printf("CHANIM mode: external (acsd).\n");
+			break;
+		case CHANIM_ACT:
+			printf("CHANIM mode: detect + act.\n");
+			break;
+		}
+		return 0;
+	} else {
+		mode = CHANIM_DETECT;
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		switch (val) {
+			case 0:
+				mode = CHANIM_DISABLE;
+				break;
+			case 1:
+				mode = CHANIM_DETECT;
+				break;
+			case 2:
+				mode = CHANIM_EXT;
+				break;
+			case 3:
+				mode = CHANIM_ACT;
+				break;
+			default:
+				return BCME_BADARG;
+		}
+
+		mode = htod32(mode);
+		return wlu_iovar_setint(wl, cmd->name, mode);
+	}
+}
+
+int
+wl_ether_atoe(const char *a, struct ether_addr *n)
+{
+	char *c = NULL;
+	int i = 0;
+
+	memset(n, 0, ETHER_ADDR_LEN);
+	for (;;) {
+		n->octet[i++] = (uint8)strtoul(a, &c, 16);
+		if (!*c++ || i == ETHER_ADDR_LEN)
+			break;
+		a = c;
+	}
+	return (i == ETHER_ADDR_LEN);
+}
+char *
+wl_ether_etoa(const struct ether_addr *n)
+{
+	static char etoa_buf[ETHER_ADDR_LEN * 3];
+	char *c = etoa_buf;
+	int i;
+
+	for (i = 0; i < ETHER_ADDR_LEN; i++) {
+		if (i)
+			*c++ = ':';
+		c += sprintf(c, "%02X", n->octet[i] & 0xff);
+	}
+	return etoa_buf;
+}
+
+int
+wl_atoip(const char *a, struct ipv4_addr *n)
+{
+	char *c = NULL;
+	int i = 0;
+
+	for (;;) {
+		n->addr[i++] = (uint8)strtoul(a, &c, 0);
+		if (*c++ != '.' || i == IPV4_ADDR_LEN)
+			break;
+		a = c;
+	}
+	return (i == IPV4_ADDR_LEN);
+}
+
+
+int wl_ipv6_colon(const char *a, char *x)
+{
+	int     i;
+	const char	*t;
+	int     colons = 0;
+	int     double_colons = 0;
+	int     zero_req = 0;
+
+	if (*a == ':' && *(a+1) != ':')
+		return 1;		/* Illegal */
+	t = a;
+	while ((t = strstr(t, "::")) != NULL) {
+		++t;
+	++double_colons;
+	}
+
+	if (double_colons == 0) {
+	strcpy(x, a);			/* No double colon in the address */
+	return 0;
+	}
+
+	if (double_colons > 1) {
+	return 1;			/* Illegal */
+	}
+	t = a;
+	while ((t = strchr(t, ':')) != NULL) {
+		++t;
+		++colons;
+	}
+	zero_req = 8 - colons;
+	if (zero_req) {
+	t = a;
+		while (*t) {
+			if (*t == ':' && *(t+1) == ':') {
+				if (t == a) {
+					*x++ = '0';
+				}
+				*x++ = *t++;
+				for (i = 0; i < zero_req; i++) {
+					*x++ = '0';
+					*x++ = ':';
+				}
+				t++;
+				} else {
+				*x++ = *t++;
+			}
+		}
+	} else {
+		strcpy(x, a);
+	}
+		return 0;
+}
+
+int
+wl_atoipv6(const char *a, struct ipv6_addr *n)
+{
+	char *c = NULL;
+	int i = 0;
+	uint16 *addr16;
+	char x[64];
+	char *t = x;
+
+	memset(x, 0, 64);
+
+	if (wl_ipv6_colon(a, x) == 1) {
+		return 0;
+	}
+
+	for (;;) {
+		addr16 = (uint16 *)&n->addr[i];
+		*addr16 = hton16((uint16)strtoul((char *)t, &c, 16));
+		i += 2;
+		if (*c++ != ':' || i == IPV6_ADDR_LEN)
+			break;
+		t = c;
+	}
+
+	return (i == IPV6_ADDR_LEN);
+}
+
+char *
+wl_ipv6toa(const void *ipv6)
+{
+	/* Implementing RFC 5952 Sections 4 + 5 */
+	/* Not thoroughly tested */
+	uint16 *a = (uint16 *)ipv6;
+
+	/* Returned buffer is from a static circular pool to permit several calls in a printf */
+#define IPV6_BUFFER_CNT	4
+	static char buffer[IPV6_BUFFER_CNT][IPV6_ADDR_LEN * 4];
+	static int idx = 0;
+
+	char *p = buffer[idx++ % IPV6_BUFFER_CNT];
+	int i, i_max = -1, cnt = 0, cnt_max = 1;
+	uint8 *a4 = NULL;
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if (a[i]) {
+			if (cnt > cnt_max) {
+				cnt_max = cnt;
+				i_max = i - cnt;
+			}
+			cnt = 0;
+		} else
+			cnt++;
+	}
+	if (cnt > cnt_max) {
+		cnt_max = cnt;
+		i_max = i - cnt;
+	}
+	if (i_max == 0 &&
+		/* IPv4-translated: ::ffff:0:a.b.c.d */
+		((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
+		/* IPv4-mapped: ::ffff:a.b.c.d */
+		(cnt_max == 5 && a[5] == 0xffff)))
+		a4 = (uint8*) (a + 6);
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if ((uint8*) (a + i) == a4) {
+			sprintf(p, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
+			break;
+		} else if (i == i_max) {
+			*p++ = ':';
+			i += cnt_max - 1;
+			p[0] = ':';
+			p[1] = '\0';
+		} else {
+			if (i)
+				*p++ = ':';
+			p += sprintf(p, "%x", ntoh16(a[i]));
+		}
+	}
+
+	/* Sub-buffer start is found back by rounding p with the sub-buffer size */
+	return buffer[(p - buffer[0]) / sizeof(buffer[0])];
+}
+
+char *
+wl_iptoa(const struct ipv4_addr *n)
+{
+	static char iptoa_buf[IPV4_ADDR_LEN * 4];
+
+	sprintf(iptoa_buf, "%u.%u.%u.%u",
+	        n->addr[0], n->addr[1], n->addr[2], n->addr[3]);
+
+	return iptoa_buf;
+}
+
+int
+wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
+{
+	int i, c;
+	char *p = ssid_buf;
+
+	if (ssid_len > 32)
+		ssid_len = 32;
+
+	for (i = 0; i < ssid_len; i++) {
+		c = (int)ssid[i];
+		if (c == '\\') {
+			*p++ = '\\';
+			*p++ = '\\';
+		} else if (isprint((uchar)c)) {
+			*p++ = (char)c;
+		} else {
+			p += sprintf(p, "\\x%02X", c);
+		}
+	}
+	*p = '\0';
+
+	return p - ssid_buf;
+}
+
+/* pretty hex print a contiguous buffer */
+void
+wl_hexdump(uchar *dump_buf, uint nbytes)
+{
+	char line[256];
+	char* p;
+	uint i;
+
+	if (nbytes == 0) {
+		printf("\n");
+		return;
+	}
+
+	p = line;
+	for (i = 0; i < nbytes; i++) {
+		if (i % 16 == 0 && nbytes > 16) {
+			p += sprintf(p, "%04d: ", i);	/* line prefix */
+		}
+		p += sprintf(p, "%02x ", dump_buf[i]);
+		if (i % 16 == 15) {
+			printf("%s\n", line);		/* flush line */
+			p = line;
+		}
+	}
+
+	/* flush last partial line */
+	if (p != line)
+		printf("%s\n", line);
+}
+
+static int
+wl_plcphdr(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+			return ret;
+		val = dtoh32(val);
+		if (val == WLC_PLCP_AUTO)
+			printf("long");
+		else if (val == WLC_PLCP_SHORT)
+			printf("auto");
+		else if (val == WLC_PLCP_LONG)
+			printf("debug");
+		else
+			printf("unknown");
+		printf("\n");
+		return 0;
+	} else {
+		if (!stricmp(*argv, "long"))
+			val = WLC_PLCP_AUTO;
+		else if (!stricmp(*argv, "auto"))
+			val = WLC_PLCP_SHORT;
+		else if (!stricmp(*argv, "debug"))
+			val = WLC_PLCP_LONG;
+		else
+			return BCME_USAGE_ERROR;
+		val = htod32(val);
+		return wlu_set(wl, cmd->set, &val, sizeof(int));
+	}
+}
+
+/* WLC_GET_RADIO and WLC_SET_RADIO in driver operate on radio_disabled which
+ * is opposite of "wl radio [1|0]".  So invert for user.
+ * In addition, display WL_RADIO_SW_DISABLE and WL_RADIO_HW_DISABLE bits.
+ */
+static int
+wl_radio(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint val;
+	char *endptr = NULL;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+			return ret;
+		val = dtoh32(val);
+		printf("0x%04x\n", val);
+		return 0;
+	} else {
+		if (cmd->set < 0)
+			return -1;
+		if (!stricmp(*argv, "on"))
+			val = WL_RADIO_SW_DISABLE << 16;
+		else if (!stricmp(*argv, "off"))
+			val = WL_RADIO_SW_DISABLE << 16 | WL_RADIO_SW_DISABLE;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+			/* raw bits setting, add the mask if not provided */
+			if ((val >> 16) == 0) {
+				val |= val << 16;
+			}
+		}
+		val = htod32(val);
+		return wlu_set(wl, cmd->set, &val, sizeof(int));
+	}
+}
+
+static char *
+ver2str(unsigned int vms, unsigned int vls)
+{
+	static char verstr[100];
+	unsigned int maj, year, month, day, build;
+
+	maj = (vms >> 16) & 0xFFFF;
+	if (maj > 1000) {
+		/* it is probably a date... */
+		year = (vms >> 16) & 0xFFFF;
+		month = vms & 0xFFFF;
+		day = (vls >> 16) & 0xFFFF;
+		build = vls & 0xFFFF;
+		sprintf(verstr, "%d/%d/%d build %d",
+			month, day, year, build);
+	} else {
+		/* it is a tagged release. */
+		sprintf(verstr, "%d.%d RC%d.%d",
+			(vms>>16)&0xFFFF, vms&0xFFFF,
+			(vls>>16)&0xFFFF, vls&0xFFFF);
+	}
+	return verstr;
+}
+
+
+static int
+wl_version(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int bcmerr = 0;
+	char *p = NULL;
+	char *dump_buf;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	printf("%s\n",
+		ver2str(((EPI_MAJOR_VERSION) << 16) | EPI_MINOR_VERSION,
+		(EPI_RC_NUMBER << 16) | EPI_INCREMENTAL_NUMBER));
+	dump_buf = malloc(WLC_IOCTL_SMLEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WLC_IOCTL_SMLEN);
+		return BCME_NOMEM;
+	}
+	memset(dump_buf, 0, WLC_IOCTL_SMLEN);
+
+	/* query for 'ver' to get version info */
+	ret = wlu_iovar_get(wl, "ver", dump_buf, WLC_IOCTL_SMLEN);
+
+	/* if the query is successful, continue on and print the result. */
+
+	/* if the query fails, check for a legacy driver that does not support
+	 * the "dump" iovar, and instead issue a WLC_DUMP ioctl.
+	 */
+	if (ret) {
+		wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+		if (bcmerr == BCME_UNSUPPORTED) {
+			ret = wlu_get(wl, WLC_DUMP, dump_buf, WLC_IOCTL_SMLEN);
+		}
+	}
+
+	if (ret) {
+		fprintf(stderr, "Error %d on query of driver dump\n", (int)ret);
+		free(dump_buf);
+		return ret;
+	}
+
+	/* keep only the first line from the dump buf output */
+	p = strchr(dump_buf, '\n');
+	if (p)
+		*p = '\0';
+	printf("%s\n", dump_buf);
+
+	free(dump_buf);
+
+	return 0;
+}
+
+static int
+wl_rateparam(void *wl, cmd_t *cmd, char **argv)
+{
+	int val[2];
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	val[0] = htod32(atoi(*argv));
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	val[1] = htod32(atoi(*argv));
+	return wlu_set(wl, cmd->set, val, 2 * sizeof(val));
+}
+
+/* wl scan
+ * -s --ssid=ssid_list
+ * -t T --scan_type=T : [active|passive]
+ * --bss_type=T : [infra|bss|adhoc|ibss]
+ * -b --bssid=
+ * -n --nprobes=
+ * -a --active=
+ * -p --passive=
+ * -h --home=
+ * -c --channels=
+ * ssid_list
+ */
+
+/* Parse a comma-separated list from list_str into ssid array, starting
+ * at index idx.  Max specifies size of the ssid array.  Parses ssids
+ * and returns updated idx; if idx >= max not all fit, the excess have
+ * not been copied.  Returns -1 on empty string, or on ssid too long.
+ */
+static int
+wl_parse_ssid_list(char* list_str, wlc_ssid_t* ssid, int idx, int max)
+{
+	char *str, *ptr;
+
+	if (list_str == NULL)
+		return -1;
+
+	for (str = list_str; str != NULL; str = ptr) {
+		if ((ptr = strchr(str, ',')) != NULL)
+			*ptr++ = '\0';
+
+		if (strlen(str) > DOT11_MAX_SSID_LEN) {
+			fprintf(stderr, "ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN);
+			return -1;
+		}
+		if (strlen(str) == 0)
+			ssid[idx].SSID_len = 0;
+
+		if (idx < max) {
+			strcpy((char*)ssid[idx].SSID, str);
+			ssid[idx].SSID_len = strlen(str);
+		}
+		idx++;
+	}
+
+	return idx;
+}
+
+static int
+wl_scan_prep(void *wl, cmd_t *cmd, char **argv, wl_scan_params_t *params, int *params_size)
+{
+	int val = 0;
+	char key[64];
+	int keylen;
+	char *p, *eq, *valstr, *endptr = NULL;
+	char opt;
+	bool positional_param;
+	bool good_int;
+	bool opt_end;
+	int err = 0;
+	int i;
+
+	int nchan = 0;
+	int nssid = 0;
+	wlc_ssid_t ssids[WL_SCAN_PARAMS_SSID_MAX];
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
+	params->bss_type = DOT11_BSSTYPE_ANY;
+	params->scan_type = 0;
+	params->nprobes = -1;
+	params->active_time = -1;
+	params->passive_time = -1;
+	params->home_time = -1;
+	params->channel_num = 0;
+	memset(ssids, 0, WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t));
+
+	/* skip the command name */
+	argv++;
+
+	opt_end = FALSE;
+	while ((p = *argv) != NULL) {
+		argv++;
+		positional_param = FALSE;
+		memset(key, 0, sizeof(key));
+		opt = '\0';
+		valstr = NULL;
+		good_int = FALSE;
+
+		if (opt_end) {
+			positional_param = TRUE;
+			valstr = p;
+		}
+		else if (!strcmp(p, "--")) {
+			opt_end = TRUE;
+			continue;
+		}
+		else if (!strncmp(p, "--", 2)) {
+			eq = strchr(p, '=');
+			if (eq == NULL) {
+				fprintf(stderr,
+				"wl_scan: missing \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			keylen = eq - (p + 2);
+			if (keylen > 63)
+				keylen = 63;
+			memcpy(key, p + 2, keylen);
+
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr,
+				"wl_scan: missing value after \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr,
+				"wl_scan: only single char options, error on param \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"wl_scan: missing value parameter after \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+		} else {
+			positional_param = TRUE;
+			valstr = p;
+		}
+
+		/* parse valstr as int just in case */
+		if (valstr) {
+			val = (int)strtol(valstr, &endptr, 0);
+			if (*endptr == '\0') {
+				/* not all the value string was parsed by strtol */
+				good_int = TRUE;
+			}
+		}
+
+		if (opt == 's' || !strcmp(key, "ssid") || positional_param) {
+			nssid = wl_parse_ssid_list(valstr, ssids, nssid, WL_SCAN_PARAMS_SSID_MAX);
+			if (nssid < 0) {
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+
+		/* scan_type is a bitmap value and can have multiple options */
+		if (opt == 't' || !strcmp(key, "scan_type")) {
+			if (!strcmp(valstr, "active")) {
+				/* do nothing - scan_type is initialized outside of while loop */
+			} else if (!strcmp(valstr, "passive")) {
+				params->scan_type |= WL_SCANFLAGS_PASSIVE;
+			} else if (!strcmp(valstr, "prohibit")) {
+				params->scan_type |= WL_SCANFLAGS_PROHIBITED;
+			} else if (!strcmp(valstr, "offchan")) {
+				params->scan_type |= WL_SCANFLAGS_OFFCHAN;
+			} else if (!strcmp(valstr, "hotspot")) {
+				params->scan_type |= WL_SCANFLAGS_HOTSPOT;
+			} else {
+				fprintf(stderr,
+				"scan_type value should be \"active\", "
+				"\"passive\", \"prohibit\", \"offchan\" "
+				"or \"hotspot\", but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (!strcmp(key, "bss_type")) {
+			if (!strcmp(valstr, "bss") || !strcmp(valstr, "infra")) {
+				params->bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
+			} else if (!strcmp(valstr, "ibss") || !strcmp(valstr, "adhoc")) {
+				params->bss_type = DOT11_BSSTYPE_INDEPENDENT;
+			} else if (!strcmp(valstr, "any")) {
+				params->bss_type = DOT11_BSSTYPE_ANY;
+			} else {
+				fprintf(stderr,
+				"bss_type value should be "
+				"\"bss\", \"ibss\", or \"any\", but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 'b' || !strcmp(key, "bssid")) {
+			if (!wl_ether_atoe(valstr, &params->bssid)) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an ethernet MAC address\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 'n' || !strcmp(key, "nprobes")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for value nprobes\n", valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->nprobes = val;
+		}
+		if (opt == 'a' || !strcmp(key, "active")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for active dwell time\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->active_time = val;
+		}
+		if (opt == 'p' || !strcmp(key, "passive")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for passive dwell time\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->passive_time = val;
+		}
+		if (opt == 'h' || !strcmp(key, "home")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for home channel dwell time\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->home_time = val;
+		}
+		if (opt == 'c' || !strcmp(key, "channels")) {
+			nchan = wl_parse_channel_list(valstr, params->channel_list,
+			                              WL_NUMCHANNELS);
+			if (nchan == -1) {
+				fprintf(stderr, "error parsing channel list arg\n");
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+	}
+
+	if (nssid > WL_SCAN_PARAMS_SSID_MAX) {
+		fprintf(stderr, "ssid count %d exceeds max of %d\n",
+		        nssid, WL_SCAN_PARAMS_SSID_MAX);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	params->nprobes = htod32(params->nprobes);
+	params->active_time = htod32(params->active_time);
+	params->passive_time = htod32(params->passive_time);
+	params->home_time = htod32(params->home_time);
+
+	for (i = 0; i < nchan; i++) {
+		params->channel_list[i] = htodchanspec(params->channel_list[i]);
+	}
+
+	for (i = 0; i < nssid; i++) {
+		ssids[i].SSID_len = htod32(ssids[i].SSID_len);
+	}
+
+	/* For a single ssid, use the single fixed field */
+	if (nssid == 1) {
+		nssid = 0;
+		memcpy(&params->ssid, &ssids[0], sizeof(ssids[0]));
+	}
+
+	/* Copy ssid array if applicable */
+	if (nssid > 0) {
+		i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
+		i = ROUNDUP(i, sizeof(uint32));
+		if (i + nssid * sizeof(wlc_ssid_t) > (uint)*params_size) {
+			fprintf(stderr, "additional ssids exceed params_size\n");
+			err = BCME_BADARG;
+			goto exit;
+		}
+
+		p = (char*)params + i;
+		memcpy(p, ssids, nssid * sizeof(wlc_ssid_t));
+		p += nssid * sizeof(wlc_ssid_t);
+	} else {
+		p = (char*)params->channel_list + nchan * sizeof(uint16);
+	}
+
+	params->channel_num = htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) |
+	                             (nchan & WL_SCAN_PARAMS_COUNT_MASK));
+	*params_size = p - (char*)params + nssid * sizeof(wlc_ssid_t);
+exit:
+	return err;
+}
+
+
+static int
+wl_roamparms(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+	wl_scan_params_t *params;
+	wl_join_scan_params_t jparms;
+	int err = 0;
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_scan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+	memset(&jparms, 0, sizeof(jparms));
+
+	if (!(argv[1])) {
+	err = wlu_iovar_getbuf(wl, "roamscan_parms", &jparms, sizeof(jparms),
+		buf, WLC_IOCTL_SMLEN);
+		memset(&jparms, 0, sizeof(jparms));
+		memcpy(&jparms, buf, sizeof(jparms));
+
+		printf("Roam Scan Parameters:\n");
+		printf("scan_type: %d\n", jparms.scan_type);
+		printf("nprobes: %d\n", jparms.nprobes);
+		printf("active_time: %d\n", jparms.active_time);
+		printf("passive_time: %d\n", jparms.passive_time);
+		printf("home_time: %d\n", jparms.home_time);
+
+		goto done;
+	}
+
+
+	printf("Setting Roam Scan parameters \n");
+
+
+	err = wl_scan_prep(wl, cmd, argv, params, &params_size);
+
+	if (err)
+		goto done;
+	/* after all of that arg processing we're going to toss some of them
+	 * and only send down the ones relevant to a wl_join__scan_params_t
+	 */
+	jparms.scan_type = params->scan_type;
+	jparms.nprobes = params->nprobes;
+	jparms.active_time = params->active_time;
+	jparms.passive_time = params->passive_time;
+	jparms.home_time = params->home_time;
+
+	err = wlu_iovar_setbuf(wl, "roamscan_parms", &jparms, sizeof(jparms), buf, WLC_IOCTL_SMLEN);
+
+done:
+	free(params);
+	return err;
+}
+static int
+wl_scan(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+	wl_scan_params_t *params;
+	int err = 0;
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_scan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, params, &params_size);
+
+	if (!err) {
+		err = wlu_set(wl, cmd->set, params, params_size);
+	}
+
+	free(params);
+	return err;
+}
+
+extern time_t time(time_t *ptr);
+static int
+wl_escan(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)) +
+	    (WL_NUMCHANNELS * sizeof(uint16));
+	wl_escan_params_t *params;
+	int err = 0;
+	uint16 action = WL_SCAN_ACTION_START;
+
+	if (!stricmp(*argv, "escan"))
+		/* start an escan */
+		action = WL_SCAN_ACTION_START;
+	else if (!stricmp(*argv, "escanabort"))
+		/* abort an escan */
+		action = WL_SCAN_ACTION_ABORT;
+	else {
+		printf("unknown escan command: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_escan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, &params->params, &params_size);
+
+	if (!err) {
+		params->version = htod32(ESCAN_REQ_VERSION);
+		params->action = htod16(action);
+
+		srand((unsigned)time(NULL));
+		params->sync_id = htod16(rand() & 0xffff);
+
+		params_size += OFFSETOF(wl_escan_params_t, params);
+		err = wlu_iovar_setbuf(wl, "escan", params, params_size, buf, WLC_IOCTL_MAXLEN);
+	}
+
+	free(params);
+	return err;
+}
+
+static int
+wl_iscan(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
+	    (WL_NUMCHANNELS * sizeof(uint16));
+	wl_iscan_params_t *params;
+	int err = 0;
+	uint16 action = WL_SCAN_ACTION_START;
+	char **p;
+	uint16 iscan_duration = 0;
+
+	if (!stricmp(*argv, "iscan_s"))
+		action = WL_SCAN_ACTION_START;
+	else if (!stricmp(*argv, "iscan_c"))
+		action = WL_SCAN_ACTION_CONTINUE;
+	else {
+		printf("unknown iscan command: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* look for iscan_duration parameter */
+	p = argv;
+	while (*p != NULL) {
+		if (!strcmp(*p, "-d") || !strncmp(*p, "--duration=", 11)) {
+			char *valptr;
+			int val;
+			char *endptr;
+			if (!strcmp(*p, "-d"))
+				valptr = *(++p);
+			else
+				valptr = *p + 11;
+			val = (int)strtol(valptr, &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr,
+					"could not parse \"%s\" as an int for duration\n",
+					valptr);
+				err = -1;
+				goto exit;
+			}
+			iscan_duration = (uint16) val;
+			break;
+		}
+		++p;
+	}
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_iscan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, &params->params, &params_size);
+
+	if (!err) {
+		params->version = htod32(ISCAN_REQ_VERSION);
+		params->action = htod16(action);
+		params->scan_duration = htod16(iscan_duration);
+		params_size += OFFSETOF(wl_iscan_params_t, params);
+		err = wlu_iovar_setbuf(wl, "iscan", params, params_size, buf, WLC_IOCTL_MAXLEN);
+	}
+
+	free(params);
+exit:
+	return err;
+}
+
+static int
+wl_parse_assoc_params(char **argv, wl_assoc_params_t *params, bool *prescanned)
+{
+	int err = BCME_OK;
+	char *p, *eq, *valstr;
+	char opt;
+	bool opt_end;
+	int keylen;
+	char key[64];
+	int i;
+	bool bssid_set = FALSE;
+	bool ch_set = FALSE;
+
+	opt_end = FALSE;
+
+	while ((p = *argv) != NULL) {
+		argv++;
+		memset(key, 0, sizeof(key));
+		opt = '\0';
+		valstr = NULL;
+
+		if (opt_end) {
+			valstr = p;
+		}
+		else if (!strcmp(p, "--")) {
+			opt_end = TRUE;
+			continue;
+		}
+		else if (!strcmp(p, "prescanned")) {
+			if (prescanned)
+				*prescanned = TRUE;
+			continue;
+		}
+		else if (!strncmp(p, "--", 2)) {
+			eq = strchr(p, '=');
+			if (eq == NULL) {
+				fprintf(stderr, "wl_parse_assoc_params: missing \" = \" in "
+				        "long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			keylen = eq - (p + 2);
+			if (keylen > 63)
+				keylen = 63;
+			memcpy(key, p + 2, keylen);
+
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr, "wl_parse_assoc_params: missing value after "
+				        "\" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr, "wl_parse_assoc_params: only single char options, "
+				        "error on param \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr, "wl_parse_assoc_params: missing value parameter "
+				        "after \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv++;
+		} else {
+			valstr = p;
+		}
+
+		/* handle -o v or --option=val */
+		if (opt == 'b' || !stricmp(key, "bssid")) {
+			if (!wl_ether_atoe(valstr, &params->bssid)) {
+				fprintf(stderr, "could not parse as an ethernet MAC address\n");
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			bssid_set = TRUE;
+		}
+		else if (opt == 'c' || !strcmp(key, "chanspecs")) {
+			params->chanspec_num =
+			     wl_parse_chanspec_list(valstr, params->chanspec_list, WL_NUMCHANNELS);
+			if (params->chanspec_num == -1) {
+				fprintf(stderr, "error parsing chanspec list arg\n");
+				err = BCME_BADARG;
+				goto exit;
+			}
+			ch_set = TRUE;
+		}
+	}
+
+	if (prescanned && *prescanned && (ch_set || bssid_set)) {
+		fprintf(stderr, "cannot use bssid/channel options with prescan option\n");
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	/* prepare the chanspec using the channel number and the user provided options */
+	for (i = 0; i < params->chanspec_num; i++) {
+		chanspec_t chanspec = wl_chspec_to_driver(params->chanspec_list[i]);
+		if (chanspec == INVCHANSPEC) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		params->chanspec_list[i] = chanspec;
+	}
+	params->chanspec_num = htod32(params->chanspec_num);
+
+exit:
+	return err;
+}
+
+/* wl reassoc <bssid>
+ * Options:
+ * -c CL, --chanspecs=CL, where CL is a comma or space separated list of chanspecs
+ */
+static int
+wl_reassoc(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = WL_REASSOC_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(chanspec_t);
+	wl_reassoc_params_t *params;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv == NULL) {
+		fprintf(stderr, "no arguments to wl_reassoc\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	params = (wl_reassoc_params_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	if (!wl_ether_atoe(*argv, &params->bssid)) {
+		fprintf(stderr, "could not parse %s as an Ethernet MAC address\n", *argv);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	/* default to plain old ioctl */
+	params_size = ETHER_ADDR_LEN;
+
+	if (*++argv != NULL) {
+		if ((err = wl_parse_reassoc_params(argv, params)) != BCME_OK) {
+			fprintf(stderr, "could not parse reassociation parameters\n");
+			goto exit;
+		}
+		params_size = WL_REASSOC_PARAMS_FIXED_SIZE +
+		        dtoh32(params->chanspec_num) * sizeof(chanspec_t);
+	}
+
+	err = wlu_set(wl, WLC_REASSOC, params, params_size);
+
+exit:
+	free(params);
+	return err;
+}
+
+#ifdef EXTENDED_SCAN
+/* wl extdscan
+ * -s --ssid=ssid1 ssid2 ssid3
+ * -b --split_scan=0 : [split_scan]
+ * -t --scan_type=0 : [background/forcedbackground/foreground]
+ * -n --nprobes=
+ * -c --channels=
+ */
+static int
+wl_extdscan(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_extdscan_params_t *params;
+	int params_size = WL_EXTDSCAN_PARAMS_FIXED_SIZE +
+		(WL_NUMCHANNELS * sizeof(chan_scandata_t));
+	int val = 0;
+	char *p, *eq, *valstr, *endptr;
+	char opt;
+	bool positional_param;
+	bool good_int;
+	bool opt_end;
+	int err = 0;
+	int keylen;
+	char key[64];
+	int i;
+	int nssid = 0;
+
+	fprintf(stderr, "params alloc size is %d\n", params_size);
+	params = (wl_extdscan_params_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	params->scan_type = EXTDSCAN_FORCEDBACKGROUND_SCAN;
+	params->nprobes = 3;
+	params->band = WLC_BAND_2G;
+	params->split_scan = 0;
+
+	/* skip the command name */
+	argv++;
+
+	if (*argv == NULL) {
+		fprintf(stderr, "no arguments to wl_extdscan\n");
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	opt_end = FALSE;
+	while ((p = *argv) != NULL) {
+		argv++;
+		positional_param = FALSE;
+		memset(key, 0, sizeof(key));
+		opt = '\0';
+		valstr = NULL;
+		good_int = FALSE;
+
+		if (opt_end) {
+			positional_param = TRUE;
+			valstr = p;
+		}
+		else if (!strcmp(p, "--")) {
+			opt_end = TRUE;
+			continue;
+		}
+		else if (!strncmp(p, "--", 2)) {
+			eq = strchr(p, '=');
+			if (eq == NULL) {
+				fprintf(stderr,
+				"wl_extdscan: missing \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			keylen = eq - (p + 2);
+			if (keylen > 63)
+				keylen = 63;
+			memcpy(key, p + 2, keylen);
+
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr,
+				"extdscan: missing value after \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr,
+				"extdscan: only single char options, error on param \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"extdscan: missing value parameter after \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+		} else {
+			positional_param = TRUE;
+			valstr = p;
+		}
+
+		/* parse valstr as int just in case */
+		if (valstr) {
+			val = (int)strtol(valstr, &endptr, 0);
+			if (*endptr == '\0') {
+				/* not all the value string was parsed by strtol */
+				good_int = TRUE;
+			}
+		}
+
+		if (opt == 's' || !strcmp(key, "ssid") || positional_param) {
+			nssid = wl_parse_ssid_list(valstr, params->ssid,
+			                           nssid, WLC_EXTDSCAN_MAX_SSID);
+			if (nssid < 0) {
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+		if (opt == 'b' || !strcmp(key, "band")) {
+			if (!strcmp(valstr, "5G")) {
+				params->band = WLC_BAND_5G;
+			}
+			else if (!strcmp(valstr, "2.4G")) {
+				params->band = WLC_BAND_2G;
+			}
+			else if (!strcmp(valstr, "all")) {
+				params->band = WLC_BAND_ALL;
+			} else {
+				fprintf(stderr,
+				"scan_type value should be \"5G\" "
+				"or \"2.4G\" " "or \"all\" but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 't' || !strcmp(key, "scan_type")) {
+			if (!strcmp(valstr, "background")) {
+				params->scan_type = EXTDSCAN_BACKGROUND_SCAN;
+			} else if (!strcmp(valstr, "fbackground")) {
+				params->scan_type = EXTDSCAN_FORCEDBACKGROUND_SCAN;
+			} else if (!strcmp(valstr, "foreground")) {
+				params->scan_type = EXTDSCAN_FOREGROUND_SCAN;
+			} else {
+				fprintf(stderr,
+				"scan_type value should be \"background\" "
+				"or \"fbackground\" " "or \"foreground\" but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 'n' || !strcmp(key, "nprobes")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for value nprobes\n", valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->nprobes = val;
+		}
+		if (opt == 'x' || !strcmp(key, "split_scan")) {
+			if (val != 0)
+				params->split_scan = 1;
+		}
+		if (opt == 'c' || !strcmp(key, "channels")) {
+			params->channel_num = wl_parse_extdchannel_list(valstr,
+				params->channel_list, WL_NUMCHANNELS);
+			if (params->channel_num == -1) {
+				fprintf(stderr, "error parsing channel list arg\n");
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+	}
+
+	if (nssid > WLC_EXTDSCAN_MAX_SSID) {
+		fprintf(stderr, "ssid count %d exceeds max of %d\n",
+		        nssid, WLC_EXTDSCAN_MAX_SSID);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	params_size = WL_EXTDSCAN_PARAMS_FIXED_SIZE +
+	    (params->channel_num * sizeof(chan_scandata_t));
+
+	fprintf(stderr, "ssid list is %s(%d) %s(%d) %s(%d) %s(%d) %s(%d)\n",
+		(char *)&params->ssid[0].SSID, params->ssid[0].SSID_len,
+		(char *)&params->ssid[1].SSID, params->ssid[1].SSID_len,
+		(char *)&params->ssid[2].SSID, params->ssid[2].SSID_len,
+		(char *)&params->ssid[3].SSID, params->ssid[3].SSID_len,
+		(char *)&params->ssid[4].SSID, params->ssid[4].SSID_len);
+	if (params->split_scan)
+	    fprintf(stderr, "split scan is enabled\n");
+	else
+	   fprintf(stderr, "split scan is not enabled\n");
+
+	fprintf(stderr, "scan type is %d, nprobes are %d, band is %d, channels are %d\n",
+		params->scan_type, params->nprobes, params->band, params->channel_num);
+
+	fprintf(stderr, "params size is %d\n", params_size);
+	params->scan_type = htodenum(params->scan_type);
+	for (i = 0; i < WLC_EXTDSCAN_MAX_SSID; i++) {
+		params->ssid[i].SSID_len = htod32(params->ssid[i].SSID_len);
+	}
+	for (i = 0; i < params->channel_num; i++) {
+		chanspec_t chanspec = params->channel_list[i].channel;
+		chanspec = wl_chspec_to_driver(chanspec);
+		if (chanspec == INVCHANSPEC) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		params->channel_list[i].channel = chanspec;
+		params->channel_list[i].channel_mintime =
+		        htod32(params->channel_list[i].channel_mintime);
+		params->channel_list[i].channel_maxtime =
+		        htod32(params->channel_list[i].channel_maxtime);
+	}
+	params->channel_num = htod32(params->channel_num);
+	err =  wlu_var_setbuf(wl, cmd->name, params, params_size);
+
+exit:
+	free(params);
+	return err;
+}
+
+static int
+wl_parse_extdchannel_list(char* list_str, chan_scandata_t* channel_list, int channel_num)
+{
+	int num;
+	int val;
+	char* str;
+	char* endptr;
+
+	if (list_str == NULL)
+		return -1;
+
+	str = list_str;
+	num = 0;
+	while (*str != '\0') {
+		val = (int)strtol(str, &endptr, 0);
+		if (endptr == str) {
+			fprintf(stderr,
+				"could not parse channel number starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, list_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num == channel_num) {
+			fprintf(stderr, "too many channels (more than %d) in channel list:\n%s\n",
+				channel_num, list_str);
+			return -1;
+		}
+		channel_list->channel = (uint16)val;
+		channel_list++;
+		num++;
+	}
+
+	return num;
+}
+#endif /* EXTENDED_SCAN */
+
+static int
+wl_parse_channel_list(char* list_str, uint16* channel_list, int channel_num)
+{
+	int num;
+	int val;
+	char* str;
+	char* endptr = NULL;
+
+	if (list_str == NULL)
+		return -1;
+
+	str = list_str;
+	num = 0;
+	while (*str != '\0') {
+		val = (int)strtol(str, &endptr, 0);
+		if (endptr == str) {
+			fprintf(stderr,
+				"could not parse channel number starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, list_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num == channel_num) {
+			fprintf(stderr, "too many channels (more than %d) in channel list:\n%s\n",
+				channel_num, list_str);
+			return -1;
+		}
+
+		channel_list[num++] = (uint16)val;
+	}
+
+	return num;
+}
+
+static int
+wl_parse_chanspec_list(char *list_str, chanspec_t *chanspec_list, int chanspec_num)
+{
+	int num = 0;
+	chanspec_t chanspec;
+	char *next, str[8];
+	size_t len;
+
+	if ((next = list_str) == NULL)
+		return BCME_ERROR;
+
+	while ((len = strcspn(next, " ,")) > 0) {
+		if (len >= sizeof(str)) {
+			fprintf(stderr, "string \"%s\" before ',' or ' ' is too long\n", next);
+			return BCME_ERROR;
+		}
+		strncpy(str, next, len);
+		str[len] = 0;
+		chanspec = wf_chspec_aton(str);
+		if (chanspec == 0) {
+			fprintf(stderr, "could not parse chanspec starting at "
+			        "\"%s\" in list:\n%s\n", str, list_str);
+			return BCME_ERROR;
+		}
+		if (num == chanspec_num) {
+			fprintf(stderr, "too many chanspecs (more than %d) in chanspec list:\n%s\n",
+				chanspec_num, list_str);
+			return BCME_ERROR;
+		}
+		chanspec_list[num++] = chanspec;
+		next += len;
+		next += strspn(next, " ,");
+	}
+
+	return num;
+}
+
+/* channel info structure */
+typedef struct {
+	uint	chan;		/* channel number */
+	uint	freq;		/* in Mhz */
+} chan_info_t;
+
+static chan_info_t chan_info[] = {
+	/* B channels */
+	{ 1,	2412},
+	{ 2,	2417},
+	{ 3,	2422},
+	{ 4,	2427},
+	{ 5,	2432},
+	{ 6,	2437},
+	{ 7,	2442},
+	{ 8,	2447},
+	{ 9,	2452},
+	{ 10,	2457},
+	{ 11,	2462},
+	{ 12,	2467},
+	{ 13,	2472},
+	{ 14,	2484},
+
+	/* A channels */
+	/* 11a usa low */
+	{ 36,	5180},
+	{ 40,	5200},
+	{ 44,	5220},
+	{ 48,	5240},
+	{ 52,	5260},
+	{ 56,	5280},
+	{ 60,	5300},
+	{ 64,	5320},
+
+	/* 11a Europe */
+	{ 100,	5500},
+	{ 104,	5520},
+	{ 108,	5540},
+	{ 112,	5560},
+	{ 116,	5580},
+	{ 120,	5600},
+	{ 124,	5620},
+	{ 128,	5640},
+	{ 132,	5660},
+	{ 136,	5680},
+	{ 140,	5700},
+
+	/* 11a usa high */
+	{ 149,	5745},
+	{ 153,	5765},
+	{ 157,	5785},
+	{ 161,	5805},
+
+	/* 11a japan */
+	{ 184,	4920},
+	{ 188,	4940},
+	{ 192,	4960},
+	{ 196,	4980},
+	{ 200,	5000},
+	{ 204,	5020},
+	{ 208,	5040},
+	{ 212,	5060},
+	{ 216,	5080}
+};
+
+uint
+freq2channel(uint freq)
+{
+	int i;
+
+	for (i = 0; i < (int)ARRAYSIZE(chan_info); i++) {
+		if (chan_info[i].freq == freq)
+			return (chan_info[i].chan);
+	}
+	return (0);
+}
+
+void
+dump_rateset(uint8 *rates, uint count)
+{
+	uint i;
+	uint r;
+	bool b;
+
+	printf("[ ");
+	for (i = 0; i < count; i++) {
+		r = rates[i] & 0x7f;
+		b = rates[i] & 0x80;
+		if (r == 0)
+			break;
+		printf("%d%s%s ", (r / 2), (r % 2)?".5":"", b?"(b)":"");
+	}
+	printf("]");
+}
+
+/* Helper routine to print the infrastructure mode while pretty printing the BSS list */
+static const char *
+capmode2str(uint16 capability)
+{
+	capability &= (DOT11_CAP_ESS | DOT11_CAP_IBSS);
+
+	if (capability == DOT11_CAP_ESS)
+		return "Managed";
+	else if (capability == DOT11_CAP_IBSS)
+		return "Ad Hoc";
+	else
+		return "<unknown>";
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+static uint8 *
+wlu_parse_tlvs(uint8 *tlv_buf, int buflen, uint key)
+{
+	uint8 *cp;
+	int totlen;
+
+	cp = tlv_buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= 2) {
+		uint tag;
+		int len;
+
+		tag = *cp;
+		len = *(cp +1);
+
+		/* validate remaining totlen */
+		if ((tag == key) && (totlen >= (len + 2)))
+			return (cp);
+
+		cp += (len + 2);
+		totlen -= (len + 2);
+	}
+
+	return NULL;
+}
+
+static int
+wlu_bcmp(const void *b1, const void *b2, int len)
+{
+	return (memcmp(b1, b2, len));
+}
+
+/* Is this body of this tlvs entry a WPA entry? If */
+/* not update the tlvs buffer pointer/length */
+static bool
+wlu_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, uint *tlvs_len)
+{
+	uint8 *ie = *wpaie;
+
+	/* If the contents match the WPA_OUI and type=1 */
+	if ((ie[1] >= 6) && !wlu_bcmp(&ie[2], WPA_OUI "\x01", 4)) {
+		return TRUE;
+	}
+
+	/* point to the next ie */
+	ie += ie[1] + 2;
+	/* calculate the length of the rest of the buffer */
+	*tlvs_len -= (int)(ie - *tlvs);
+	/* update the pointer to the start of the buffer */
+	*tlvs = ie;
+
+	return FALSE;
+}
+
+static void
+wl_dump_wpa_rsn_ies(uint8* cp, uint len)
+{
+	uint8 *parse = cp;
+	uint parse_len = len;
+	uint8 *wpaie;
+	uint8 *rsnie;
+
+	while ((wpaie = wlu_parse_tlvs(parse, parse_len, DOT11_MNG_WPA_ID)))
+		if (wlu_is_wpa_ie(&wpaie, &parse, &parse_len))
+			break;
+	if (wpaie)
+		wl_rsn_ie_dump((bcm_tlv_t*)wpaie);
+
+	rsnie = wlu_parse_tlvs(cp, len, DOT11_MNG_RSN_ID);
+	if (rsnie)
+		wl_rsn_ie_dump((bcm_tlv_t*)rsnie);
+
+	return;
+}
+
+static void
+wl_rsn_ie_dump(bcm_tlv_t *ie)
+{
+	int i;
+	int rsn;
+	wpa_ie_fixed_t *wpa = NULL;
+	rsn_parse_info_t rsn_info;
+	wpa_suite_t *suite;
+	uint8 std_oui[3];
+	int unicast_count = 0;
+	int akm_count = 0;
+	uint16 capabilities;
+	uint cntrs;
+	int err;
+
+	if (ie->id == DOT11_MNG_RSN_ID) {
+		rsn = TRUE;
+		memcpy(std_oui, WPA2_OUI, WPA_OUI_LEN);
+		err = wl_rsn_ie_parse_info(ie->data, ie->len, &rsn_info);
+	} else {
+		rsn = FALSE;
+		memcpy(std_oui, WPA_OUI, WPA_OUI_LEN);
+		wpa = (wpa_ie_fixed_t*)ie;
+		err = wl_rsn_ie_parse_info((uint8*)&wpa->version, wpa->length - WPA_IE_OUITYPE_LEN,
+		                           &rsn_info);
+	}
+	if (err || rsn_info.version != WPA_VERSION)
+		return;
+
+	if (rsn)
+		printf("RSN:\n");
+	else
+		printf("WPA:\n");
+
+	/* Check for multicast suite */
+	if (rsn_info.mcast) {
+		printf("\tmulticast cipher: ");
+		if (!wlu_bcmp(rsn_info.mcast->oui, std_oui, 3)) {
+			switch (rsn_info.mcast->type) {
+			case WPA_CIPHER_NONE:
+				printf("NONE\n");
+				break;
+			case WPA_CIPHER_WEP_40:
+				printf("WEP64\n");
+				break;
+			case WPA_CIPHER_WEP_104:
+				printf("WEP128\n");
+				break;
+			case WPA_CIPHER_TKIP:
+				printf("TKIP\n");
+				break;
+			case WPA_CIPHER_AES_OCB:
+				printf("AES-OCB\n");
+				break;
+			case WPA_CIPHER_AES_CCM:
+				printf("AES-CCMP\n");
+				break;
+			default:
+				printf("Unknown-%s(#%d)\n", rsn ? "RSN" : "WPA",
+				       rsn_info.mcast->type);
+				break;
+			}
+		}
+#ifdef BCMCCX
+		else if (!wlu_bcmp(rsn_info.mcast->oui, CISCO_AIRONET_OUI, 3)) {
+				switch (rsn_info.mcast->type + CISCO_BASE) {
+				case WPA_CIPHER_CKIP:
+					printf("CKIP\n");
+					break;
+				case WPA_CIPHER_CKIP_MMH:
+					printf("CKIP+CMIC\n");
+					break;
+				case WPA_CIPHER_WEP_MMH:
+					printf("CMIC\n");
+					break;
+				default:
+					break;
+			}
+		}
+#endif /* BCMCCX */
+		else {
+			printf("Unknown-%02X:%02X:%02X(#%d) ",
+			       rsn_info.mcast->oui[0], rsn_info.mcast->oui[1],
+			       rsn_info.mcast->oui[2], rsn_info.mcast->type);
+		}
+	}
+
+	/* Check for unicast suite(s) */
+	if (rsn_info.ucast) {
+		unicast_count = ltoh16_ua(&rsn_info.ucast->count);
+		printf("\tunicast ciphers(%d): ", unicast_count);
+		for (i = 0; i < unicast_count; i++) {
+			suite = &rsn_info.ucast->list[i];
+			if (!wlu_bcmp(suite->oui, std_oui, 3)) {
+				switch (suite->type) {
+				case WPA_CIPHER_NONE:
+					printf("NONE ");
+					break;
+				case WPA_CIPHER_WEP_40:
+					printf("WEP64 ");
+					break;
+				case WPA_CIPHER_WEP_104:
+					printf("WEP128 ");
+					break;
+				case WPA_CIPHER_TKIP:
+					printf("TKIP ");
+					break;
+				case WPA_CIPHER_AES_OCB:
+					printf("AES-OCB ");
+					break;
+				case WPA_CIPHER_AES_CCM:
+					printf("AES-CCMP ");
+					break;
+				default:
+					printf("WPA-Unknown-%s(#%d) ", rsn ? "RSN" : "WPA",
+					       suite->type);
+					break;
+				}
+			}
+#ifdef  BCMCCX
+			else if (!wlu_bcmp(suite->oui, CISCO_AIRONET_OUI, 3)) {
+				switch (suite->type + CISCO_BASE) {
+				case WPA_CIPHER_CKIP:
+					printf("CKIP ");
+					break;
+				case WPA_CIPHER_CKIP_MMH:
+					printf("CKIP+CMIC ");
+					break;
+				case WPA_CIPHER_WEP_MMH:
+					printf("CMIC ");
+					break;
+				default:
+					printf("Cisco-Unknown(#%d) ", suite->type);
+					break;
+				}
+			}
+#endif /* BCMCCX */
+			else {
+				printf("Unknown-%02X:%02X:%02X(#%d) ",
+					suite->oui[0], suite->oui[1], suite->oui[2],
+					suite->type);
+			}
+		}
+		printf("\n");
+	}
+	/* Authentication Key Management */
+	if (rsn_info.akm) {
+		akm_count = ltoh16_ua(&rsn_info.akm->count);
+		printf("\tAKM Suites(%d): ", akm_count);
+		for (i = 0; i < akm_count; i++) {
+			suite = &rsn_info.akm->list[i];
+			if (!wlu_bcmp(suite->oui, std_oui, 3)) {
+				switch (suite->type) {
+				case RSN_AKM_NONE:
+					printf("None ");
+					break;
+				case RSN_AKM_UNSPECIFIED:
+					printf("WPA ");
+					break;
+				case RSN_AKM_PSK:
+					printf("WPA-PSK ");
+					break;
+				case RSN_AKM_FBT_1X:
+					printf("FT-802.1x ");
+					break;
+				case RSN_AKM_FBT_PSK:
+					printf("FT-PSK ");
+					break;
+				default:
+					printf("Unknown-%s(#%d)  ",
+					       rsn ? "RSN" : "WPA", suite->type);
+					break;
+				}
+			}
+#ifdef BCMCCX
+			else if (!wlu_bcmp(suite->oui, CISCO_AIRONET_OUI, 3)) {
+				switch (suite->type + CISCO_BASE) {
+				case WPA_AUTH_CCKM:
+					printf("CCKM ");
+					break;
+				default:
+					printf("Cisco-Unknown(#%d)  ", suite->type);
+					break;
+				}
+			}
+#endif /* BCMCCX */
+			else {
+				printf("Unknown-%02X:%02X:%02X(#%d)  ",
+					suite->oui[0], suite->oui[1], suite->oui[2],
+					suite->type);
+			}
+		}
+		printf("\n");
+	}
+
+	/* Capabilities */
+	if (rsn_info.capabilities) {
+		capabilities = ltoh16_ua(rsn_info.capabilities);
+		printf("\tCapabilities(0x%04x): ", capabilities);
+		if (rsn)
+			printf("%sPre-Auth, ", (capabilities & RSN_CAP_PREAUTH) ? "" : "No ");
+
+		printf("%sPairwise, ", (capabilities & RSN_CAP_NOPAIRWISE) ? "No " : "");
+
+		cntrs = wl_rsn_ie_decode_cntrs((capabilities & RSN_CAP_PTK_REPLAY_CNTR_MASK) >>
+		                               RSN_CAP_PTK_REPLAY_CNTR_SHIFT);
+
+		printf("%d PTK Replay Ctr%s", cntrs, (cntrs > 1)?"s":"");
+
+		if (rsn) {
+			cntrs = wl_rsn_ie_decode_cntrs(
+				(capabilities & RSN_CAP_GTK_REPLAY_CNTR_MASK) >>
+				RSN_CAP_GTK_REPLAY_CNTR_SHIFT);
+
+			printf("%d GTK Replay Ctr%s\n", cntrs, (cntrs > 1)?"s":"");
+		} else {
+			printf("\n");
+		}
+	} else {
+		printf("\tNo %s Capabilities advertised\n", rsn ? "RSN" : "WPA");
+	}
+
+}
+
+/* Validates and parses the RSN or WPA IE contents into a rsn_parse_info_t structure
+ * Returns 0 on success, or 1 if the information in the buffer is not consistant with
+ * an RSN IE or WPA IE.
+ * The buf pointer passed in should be pointing at the version field in either an RSN IE
+ * or WPA IE.
+ */
+static int
+wl_rsn_ie_parse_info(uint8* rsn_buf, uint len, rsn_parse_info_t *rsn)
+{
+	uint16 count;
+
+	memset(rsn, 0, sizeof(rsn_parse_info_t));
+
+	/* version */
+	if (len < sizeof(uint16))
+		return 1;
+
+	rsn->version = ltoh16_ua(rsn_buf);
+	len -= sizeof(uint16);
+	rsn_buf += sizeof(uint16);
+
+	/* Multicast Suite */
+	if (len < sizeof(wpa_suite_mcast_t))
+		return 0;
+
+	rsn->mcast = (wpa_suite_mcast_t*)rsn_buf;
+	len -= sizeof(wpa_suite_mcast_t);
+	rsn_buf += sizeof(wpa_suite_mcast_t);
+
+	/* Unicast Suite */
+	if (len < sizeof(uint16))
+		return 0;
+
+	count = ltoh16_ua(rsn_buf);
+
+	if (len < (sizeof(uint16) + count * sizeof(wpa_suite_t)))
+		return 1;
+
+	rsn->ucast = (wpa_suite_ucast_t*)rsn_buf;
+	len -= (sizeof(uint16) + count * sizeof(wpa_suite_t));
+	rsn_buf += (sizeof(uint16) + count * sizeof(wpa_suite_t));
+
+	/* AKM Suite */
+	if (len < sizeof(uint16))
+		return 0;
+
+	count = ltoh16_ua(rsn_buf);
+
+	if (len < (sizeof(uint16) + count * sizeof(wpa_suite_t)))
+		return 1;
+
+	rsn->akm = (wpa_suite_auth_key_mgmt_t*)rsn_buf;
+	len -= (sizeof(uint16) + count * sizeof(wpa_suite_t));
+	rsn_buf += (sizeof(uint16) + count * sizeof(wpa_suite_t));
+
+	/* Capabilites */
+	if (len < sizeof(uint16))
+		return 0;
+
+	rsn->capabilities = rsn_buf;
+
+	return 0;
+}
+
+static uint
+wl_rsn_ie_decode_cntrs(uint cntr_field)
+{
+	uint cntrs;
+
+	switch (cntr_field) {
+	case RSN_CAP_1_REPLAY_CNTR:
+		cntrs = 1;
+		break;
+	case RSN_CAP_2_REPLAY_CNTRS:
+		cntrs = 2;
+		break;
+	case RSN_CAP_4_REPLAY_CNTRS:
+		cntrs = 4;
+		break;
+	case RSN_CAP_16_REPLAY_CNTRS:
+		cntrs = 16;
+		break;
+	default:
+		cntrs = 0;
+		break;
+	}
+
+	return cntrs;
+}
+
+
+void
+wl_dump_raw_ie(bcm_tlv_t *ie, uint len)
+{
+	uint dump_len;
+
+	if (len == 0) {
+		return;
+	} else if (len == 1) {
+		printf("IE header truncated: ID: 0x%02X\n", ie->id);
+		return;
+	} else if (len < (uint)(ie->len + TLV_HDR_LEN)) {
+		printf("IE data truncated: ID: 0x%02X Len: %d\n", ie->id, ie->len);
+		dump_len = len - TLV_HDR_LEN;
+	} else {
+		printf("ID: 0x%02X Len: %d\n", ie->id, ie->len);
+		dump_len = ie->len;
+	}
+
+	/* choose how to format the data based on data len */
+	if (dump_len > 16)
+		printf("Data:\n");
+	else if (dump_len > 0)
+		printf("Data: ");
+
+	if (dump_len > 0)
+		wl_hexdump(ie->data, dump_len);
+
+	if (dump_len < ie->len)
+		printf("<missing %d bytes>\n", ie->len - dump_len);
+
+	return;
+}
+
+
+/* Pretty print the BSS list */
+static void
+dump_networks(char *network_buf)
+{
+	wl_scan_results_t *list = (wl_scan_results_t*)network_buf;
+	wl_bss_info_t *bi;
+	uint i;
+
+	if (list->count == 0)
+		return;
+	else if (list->version != WL_BSS_INFO_VERSION &&
+	         list->version != LEGACY2_WL_BSS_INFO_VERSION &&
+	         list->version != LEGACY_WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+			"but this program supports only version %d.\n",
+			list->version, WL_BSS_INFO_VERSION);
+		return;
+	}
+
+	bi = list->bss_info;
+	for (i = 0; i < list->count; i++, bi = (wl_bss_info_t*)((int8*)bi + dtoh32(bi->length))) {
+		dump_bss_info(bi);
+	}
+}
+
+static void
+bcm_wps_version(uint8 *wps_ie)
+{
+	uint16 wps_len;
+	uint16 wps_off, wps_suboff;
+	uint16 wps_key;
+	uint8 wps_field_len;
+
+	wps_len = (uint16)*(wps_ie+TLV_LEN_OFF); /* Get the length of the WPS OUI header */
+	wps_off = WPS_OUI_FIXED_HEADER_OFF; /* Skip the fixed headers */
+	wps_field_len = 1;
+
+	/* Parsing the OUI header looking for version number */
+	while ((wps_len >= wps_off + 2) && (wps_field_len))
+	{
+		wps_key = (((uint8)wps_ie[wps_off]*256) + (uint8)wps_ie[wps_off+1]);
+		if (wps_key == WPS_ID_VENDOR_EXT) {
+			/* Key found */
+			wps_suboff = wps_off + WPS_OUI_HEADER_SIZE;
+
+			/* Looking for the Vendor extension code 0x00 0x37 0x2A
+			 * and the Version 2 sudId 0x00
+			 * if found then the next byte is the len of field which is always 1
+			 * for version field the byte after is the version number
+			 */
+			if (!wlu_bcmp(&wps_ie[wps_suboff],  WFA_VENDOR_EXT_ID, WPS_OUI_LEN)&&
+				(wps_ie[wps_suboff+WPS_WFA_SUBID_V2_OFF] == WPS_WFA_SUBID_VERSION2))
+			{
+				printf("V%d.%d ", (wps_ie[wps_suboff+WPS_WFA_V2_OFF]>>4),
+				(wps_ie[wps_suboff+WPS_WFA_V2_OFF] & 0x0f));
+				return;
+			}
+		}
+		/* Jump to next field */
+		wps_field_len = wps_ie[wps_off+WPS_OUI_HEADER_LEN+1];
+		wps_off += WPS_OUI_HEADER_SIZE + wps_field_len;
+	}
+
+	/* If nothing found from the parser then this is the WPS version 1.0 */
+	printf("V1.0 ");
+}
+
+static void
+bcm_is_wps_configured(uint8 *wps_ie)
+{
+	/* Before calling this function the test of WPS_OUI type 4 should be already done
+	 * If the contents match the WPS_OUI_SC_STATE
+	 */
+	uint16 wps_key;
+	wps_key = (wps_ie[WPS_SCSTATE_OFF]*256) + wps_ie[WPS_SCSTATE_OFF+1];
+	if ((wps_ie[TLV_LEN_OFF] > (WPS_SCSTATE_OFF+5))&&
+		(wps_key == WPS_ID_SC_STATE))
+	{
+		switch (wps_ie[WPS_SCSTATE_OFF+WPS_OUI_HEADER_SIZE])
+		{
+			case WPS_SCSTATE_UNCONFIGURED:
+				printf("Unconfigured\n");
+				break;
+			case WPS_SCSTATE_CONFIGURED:
+				printf("Configured\n");
+				break;
+			default:
+				printf("Unknown State\n");
+		}
+	}
+}
+
+/* Looking for WPS OUI in the propriatary_ie */
+static bool
+bcm_is_wps_ie(uint8 *ie, uint8 **tlvs, uint32 *tlvs_len)
+{
+	bool retval = FALSE;
+	/* If the contents match the WPS_OUI and type=4 */
+	if ((ie[TLV_LEN_OFF] > (WPS_OUI_LEN+1)) &&
+		!wlu_bcmp(&ie[TLV_BODY_OFF], WPS_OUI "\x04", WPS_OUI_LEN + 1)) {
+		retval = TRUE;
+	}
+
+	/* point to the next ie */
+	ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
+	/* calculate the length of the rest of the buffer */
+	*tlvs_len -= (int)(ie - *tlvs);
+	/* update the pointer to the start of the buffer */
+	*tlvs = ie;
+
+	return retval;
+}
+
+static void
+wl_dump_wps(uint8* cp, uint len)
+{
+	uint8 *parse = cp;
+	uint32 parse_len = len;
+	uint8 *proprietary_ie;
+
+	while ((proprietary_ie = wlu_parse_tlvs(parse, parse_len, DOT11_MNG_WPA_ID))) {
+		if (bcm_is_wps_ie(proprietary_ie, &parse, &parse_len)) {
+			/* Print WPS status */
+			printf("WPS: ");
+			/* Print the version get from vendor extension field */
+			bcm_wps_version(proprietary_ie);
+			/* Print the WPS configure or Unconfigure option */
+			bcm_is_wps_configured(proprietary_ie);
+			break;
+		}
+	}
+}
+
+void
+dump_bss_info(wl_bss_info_t *bi)
+{
+	char ssidbuf[SSID_FMT_BUF_LEN];
+	char chspec_str[CHANSPEC_STR_LEN];
+	wl_bss_info_107_t *old_bi;
+	int mcs_idx = 0;
+	uint16 capability;
+
+	/* Convert version 107 to 109 */
+	if (dtoh32(bi->version) == LEGACY_WL_BSS_INFO_VERSION) {
+		old_bi = (wl_bss_info_107_t *)bi;
+		bi->chanspec = CH20MHZ_CHSPEC(old_bi->channel);
+		bi->ie_length = old_bi->ie_length;
+		bi->ie_offset = sizeof(wl_bss_info_107_t);
+	} else {
+		/* do endian swap and format conversion for chanspec if we have
+		 * not created it from legacy bi above
+		 */
+		bi->chanspec = wl_chspec_from_driver(bi->chanspec);
+	}
+
+	wl_format_ssid(ssidbuf, bi->SSID, bi->SSID_len);
+
+	printf("SSID: \"%s\"\n", ssidbuf);
+
+	printf("Mode: %s\t", capmode2str(dtoh16(bi->capability)));
+	printf("RSSI: %d dBm\t", (int16)(dtoh16(bi->RSSI)));
+
+	/*
+	 * SNR has valid value in only 109 version.
+	 * So print SNR for 109 version only.
+	 */
+	if (dtoh32(bi->version) == WL_BSS_INFO_VERSION) {
+		printf("SNR: %d dB\t", (int16)(dtoh16(bi->SNR)));
+	}
+
+	printf("noise: %d dBm\t", bi->phy_noise);
+	if (bi->flags) {
+		uint16 flags = dtoh16(bi->flags);
+		printf("Flags: ");
+		if (flags & WL_BSS_FLAGS_FROM_BEACON)
+			printf("FromBcn ");
+		if (flags & WL_BSS_FLAGS_FROM_CACHE)
+			printf("Cached ");
+		if (flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)
+			printf("RSSI on-channel ");
+		printf("\t");
+	}
+	printf("Channel: %s\n", wf_chspec_ntoa(bi->chanspec, chspec_str));
+
+	printf("BSSID: %s\t", wl_ether_etoa(&bi->BSSID));
+
+	printf("Capability: ");
+	capability = dtoh16(bi->capability);
+	if (capability & DOT11_CAP_ESS)
+		printf("ESS ");
+	if (capability & DOT11_CAP_IBSS)
+		printf("IBSS ");
+	if (capability & DOT11_CAP_POLLABLE)
+		printf("Pollable ");
+	if (capability & DOT11_CAP_POLL_RQ)
+		printf("PollReq ");
+	if (capability & DOT11_CAP_PRIVACY)
+		printf("WEP ");
+	if (capability & DOT11_CAP_SHORT)
+		printf("ShortPre ");
+	if (capability & DOT11_CAP_PBCC)
+		printf("PBCC ");
+	if (capability & DOT11_CAP_AGILITY)
+		printf("Agility ");
+	if (capability & DOT11_CAP_SHORTSLOT)
+		printf("ShortSlot ");
+	if (capability & DOT11_CAP_RRM)
+		printf("RRM ");
+	if (capability & DOT11_CAP_CCK_OFDM)
+		printf("CCK-OFDM ");
+	printf("\n");
+
+	printf("Supported Rates: ");
+	dump_rateset(bi->rateset.rates, dtoh32(bi->rateset.count));
+	printf("\n");
+	if (dtoh32(bi->ie_length))
+		wl_dump_wpa_rsn_ies((uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset)),
+		                    dtoh32(bi->ie_length));
+
+	if (dtoh32(bi->version) != LEGACY_WL_BSS_INFO_VERSION && bi->n_cap) {
+		if (bi->vht_cap)
+			printf("VHT Capable:\n");
+		else
+			printf("HT Capable:\n");
+		printf("\tChanspec: %sGHz channel %d %dMHz (0x%x)\n",
+			CHSPEC_IS2G(bi->chanspec)?"2.4":"5", CHSPEC_CHANNEL(bi->chanspec),
+		       (CHSPEC_IS80(bi->chanspec) ?
+		        80 : (CHSPEC_IS40(bi->chanspec) ?
+		              40 : (CHSPEC_IS20(bi->chanspec) ? 20 : 10))),
+			bi->chanspec);
+		printf("\tPrimary channel: %d\n", bi->ctl_ch);
+		printf("\tHT Capabilities: ");
+		if (dtoh32(bi->nbss_cap) & HT_CAP_40MHZ)
+			printf("40Mhz ");
+		if (dtoh32(bi->nbss_cap) & HT_CAP_SHORT_GI_20)
+			printf("SGI20 ");
+		if (dtoh32(bi->nbss_cap) & HT_CAP_SHORT_GI_40)
+			printf("SGI40 ");
+		printf("\n\tSupported MCS : [ ");
+		for (mcs_idx = 0; mcs_idx < (MCSSET_LEN * 8); mcs_idx++)
+			if (isset(bi->basic_mcs, mcs_idx))
+				printf("%d ", mcs_idx);
+		printf("]\n");
+
+		if (bi->vht_cap) {
+			int i;
+			uint mcs;
+			printf("\tVHT Capabilities: \n");
+			printf("\tSupported VHT (tx) Rates:\n");
+			for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
+				mcs = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_txmcsmap));
+				if (mcs != VHT_CAP_MCS_MAP_NONE)
+					printf("\t\tNSS: %d MCS: %s\n", i,
+						(mcs == VHT_CAP_MCS_MAP_0_9 ? "0-9" :
+						(mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8" : "0-7")));
+			}
+			printf("\tSupported VHT (rx) Rates:\n");
+			for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
+				mcs = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
+				if (mcs != VHT_CAP_MCS_MAP_NONE)
+					printf("\t\tNSS: %d MCS: %s\n", i,
+						(mcs == VHT_CAP_MCS_MAP_0_9 ? "0-9" :
+						(mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8" : "0-7")));
+			}
+		}
+		bi->chanspec = wl_chspec_to_driver(bi->chanspec);
+	}
+
+	if (dtoh32(bi->ie_length))
+	{
+		wl_dump_wps((uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset)),
+			dtoh32(bi->ie_length));
+	}
+
+	if (dtoh16(bi->flags) & WL_BSS_FLAGS_HS20) {
+		printf("Hotspot 2.0 capable\n");
+	}
+
+	printf("\n");
+}
+
+static int
+_wl_dump_lq(void *wl)
+{
+	int ret = BCME_OK, noise = 0;
+	wl_lq_t *plq = NULL;
+	void *ptr = NULL;
+
+	memset(buf, 0, sizeof(wl_lq_t));
+
+	/* Display stats when disabled */
+	if ((ret = wlu_get(wl, WLC_GET_PHY_NOISE, &noise, sizeof(int))) < 0) {
+		printf("wlc_get noise failed with retcode:%d\n", ret);
+		return ret;
+	}
+
+	if ((ret = wlu_var_getbuf_sm (wl, "monitor_lq_status", NULL, 0, &ptr)) < 0) {
+		printf("wlc_get lq_status failed with retcode:%d\n", ret);
+		return ret;
+	}
+
+	plq = (wl_lq_t *)ptr;
+
+	if (!plq->isvalid) {
+		printf("Stats collection currently disabled"
+	               "['wl monitor_lq 1' to enable statistics collection]\n");
+		return ret;
+	}
+
+	noise = dtoh32(noise);
+	plq->rssi[LQ_IDX_MIN] = dtoh32(plq->rssi[LQ_IDX_MIN]);
+	plq->rssi[LQ_IDX_MAX] = dtoh32(plq->rssi[LQ_IDX_MAX]);
+	plq->rssi[LQ_IDX_AVG] = dtoh32(plq->rssi[LQ_IDX_AVG]);
+
+	printf("rss: %d, %d, %d\nsnr: %d, %d, %d\n",
+		plq->rssi[LQ_IDX_MIN],
+		plq->rssi[LQ_IDX_AVG],
+		plq->rssi[LQ_IDX_MAX],
+		plq->rssi[LQ_IDX_MIN]-noise,
+		plq->rssi[LQ_IDX_AVG]-noise,
+		plq->rssi[LQ_IDX_MAX]-noise);
+
+	return ret;
+} /* _wl_dump_lq */
+
+static int
+wl_dump_lq(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv)
+		ret = _wl_dump_lq(wl);
+
+	return ret;
+} /* wl_dump_lq */
+
+static int
+wl_monitor_lq(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	char *endptr = NULL;
+	char **startptr = argv;
+
+	if (!*++startptr) { /* Get */
+		ret = wl_varint(wl, cmd, argv);
+	}
+	else {
+		int val = *startptr[0];
+		val = strtol(*startptr, &endptr, 0);
+
+		if (*endptr != '\0') {
+			return BCME_USAGE_ERROR;
+		}
+
+		val = htod32(val);
+
+		if (val == LQ_STOP_MONITOR) {
+			if ((ret = _wl_dump_lq(wl)))
+				return ret;
+		}
+
+		ret = wl_varint(wl, cmd, argv); /* Standard set call after getting stats */
+	}
+
+	return ret;
+} /* wl_monitor_lq */
+
+static int
+wl_bcnlenhist(void *wl, cmd_t *cmd, char **argv)
+{
+	wlc_bcn_len_hist_t *bcnlenhist = NULL;
+	uint32 *bcns_len = NULL;
+	char* dump_buf = NULL;
+	uint32 counter = 0;
+	int	index = 0;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	dump_buf = malloc(WLC_IOCTL_SMLEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WLC_IOCTL_SMLEN);
+		return -1;
+	}
+	memset(dump_buf, 0, WLC_IOCTL_SMLEN);
+
+	if (argv[1])
+		err = wlu_iovar_getbuf(wl, "bcnlenhist", argv[1], 1, dump_buf, WLC_IOCTL_SMLEN);
+	else
+		err = wlu_iovar_getbuf(wl, "bcnlenhist", NULL, 0, dump_buf, WLC_IOCTL_SMLEN);
+
+	if (BCME_OK == err) {
+		bcnlenhist = (wlc_bcn_len_hist_t *)dump_buf;
+
+		index = bcnlenhist->cur_index;
+		counter = bcnlenhist->ringbuff_len;
+		bcns_len = bcnlenhist->bcnlen_ring;
+
+		index--;
+		printf("LAST %d BEACON LENGTH's:  ", counter);
+		for (; counter--; index--) {
+			if (index < 0)
+				index = bcnlenhist->ringbuff_len - 1;
+			printf("%d  ", bcns_len[index]);
+		}
+
+		printf("\nMAX BCNLEN: %d\n", bcnlenhist->max_bcnlen);
+
+		if (bcnlenhist->min_bcnlen == (int)0x7fffffff)
+			printf("MIN BCNLEN: 0\n\n");
+		else
+			printf("MIN BCNLEN: %d\n\n", bcnlenhist->min_bcnlen);
+	}
+
+	free(dump_buf);
+
+	return err;
+}
+
+static int
+wl_dump_networks(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char *dump_buf, *dump_buf_orig;
+	uint32 status = 0;
+	bool iscan = FALSE;
+
+	dump_buf_orig = dump_buf = malloc(WL_DUMP_BUF_LEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WL_DUMP_BUF_LEN);
+		return BCME_NOMEM;
+	}
+
+	iscan = (cmd->get != WLC_SCAN_RESULTS);
+	if (iscan) {
+		int buflen = 1920;	/* usually fits about 10 BSS infos */
+
+		if (*(++argv)) {
+			char *endptr = NULL;
+			buflen = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		ret = wl_get_iscan(wl, dump_buf, buflen);
+	} else
+		ret = wl_get_scan(wl, WLC_SCAN_RESULTS, dump_buf, WL_DUMP_BUF_LEN);
+
+	if (ret == 0) {
+		if (iscan) {
+			status = dtoh32(((wl_iscan_results_t *)dump_buf)->status);
+			dump_buf += OFFSETOF(wl_iscan_results_t, results);
+		}
+		dump_networks(dump_buf);
+		if (iscan) {
+			switch (status) {
+			case WL_SCAN_RESULTS_PARTIAL:
+				printf("iscanresults incomplete\n");
+				break;
+			case WL_SCAN_RESULTS_SUCCESS:
+				printf("iscanresults complete\n");
+				break;
+			case WL_SCAN_RESULTS_PENDING:
+				printf("iscanresults pending\n");
+				break;
+			case WL_SCAN_RESULTS_ABORTED:
+				printf("iscanresults aborted\n");
+				break;
+			default:
+				printf("iscanresults returned unknown status %d\n", status);
+				break;
+			}
+		}
+	}
+
+exit:
+	free(dump_buf_orig);
+	return ret;
+}
+
+static int
+wl_dump_chanlist(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 chan_buf[WL_NUMCHANNELS + 1];
+	wl_uint32_list_t *list;
+	int ret;
+	uint i;
+
+	UNUSED_PARAMETER(argv);
+
+	list = (wl_uint32_list_t *)(void *)chan_buf;
+	list->count = htod32(WL_NUMCHANNELS);
+	ret = wlu_get(wl, cmd->get, chan_buf, sizeof(chan_buf));
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < dtoh32(list->count); i++)
+		printf("%d ", dtoh32(list->element[i]));
+	printf("\n");
+	return ret;
+}
+
+static int
+wl_cur_mcsset(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(buf, 0, WLC_IOCTL_SMLEN);
+	ret = wlu_iovar_get(wl, "cur_mcsset", &buf[0], MCSSET_LEN);
+	if (ret < 0)
+		return ret;
+
+	wl_print_mcsset(buf);
+
+	return ret;
+}
+
+/* Dump chanspecs based on the driver's current configuration of band, band-width & locale. */
+static int
+wl_dump_chanspecs_defset(void *wl, cmd_t *cmd, char **argv)
+{
+	const char* fn_name = "wl_dump_chanspecs_defset";
+	wl_uint32_list_t *list;
+	int ret, buflen;
+	chanspec_t c = 0;
+	uint i;
+	int err;
+	char chspec_str[CHANSPEC_STR_LEN];
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+
+	strcpy(buf, "chanspecs_defset");
+	buflen = strlen(buf) + 1;
+
+	/* toss the command name */
+	argv++;
+
+	/* Validate arguments if any */
+	if (*argv) {
+		fprintf(stderr,
+		    "%s: This IOVAR doesn't take any arguments.\n", fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	/* Add list */
+	list = (wl_uint32_list_t *)(buf + buflen);
+	list->count = htod32(WL_NUMCHANSPECS);
+	buflen += sizeof(uint32)*(WL_NUMCHANSPECS + 1);
+
+	ret = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen);
+	if (ret < 0)
+		return ret;
+
+	list = (wl_uint32_list_t *)buf;
+	for (i = 0; i < dtoh32(list->count); i++) {
+		c = (chanspec_t)dtoh32(list->element[i]);
+		wf_chspec_ntoa(c, chspec_str);
+		printf("%s (0x%04x)\n", chspec_str, c);
+	}
+	printf("\n");
+	return ret;
+
+	exit:
+		return err;
+}
+
+static int
+wl_dump_chanspecs(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_dump_chanspecs";
+	wl_uint32_list_t *list;
+	chanspec_t c = 0, *chanspec;
+	int ret, buflen;
+	uint i;
+	int err, opt_err;
+	bool band_set = FALSE, bw_set = FALSE;
+	char abbrev[WLC_CNTRY_BUF_SZ] = ""; /* default.. current locale */
+	char chspec_str[CHANSPEC_STR_LEN];
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+
+	/* multiple commands are using this API to dump a channel list:
+	 * chanspecs
+	 * roam_channels_in_cache
+	 * roam_channels_in_hotlist
+	 */
+	strcpy(buf, cmd->name);
+	buflen = strlen(buf) + 1;
+
+	/* toss the command name */
+	argv++;
+
+	/* Validate arguments if any */
+	if (*argv) {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'b') {
+				if (!to.good_int) {
+					fprintf(stderr,
+					        "%s: could not parse \"%s\" as an int for band\n",
+					        fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 5) && (to.val != 2)) {
+					fprintf(stderr,
+					        "%s: invalid band %d\n",
+					        fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 5)
+					c |= WL_CHANSPEC_BAND_5G;
+				else
+					c |= WL_CHANSPEC_BAND_2G;
+				band_set = TRUE;
+			}
+			if (to.opt == 'w') {
+				if (!to.good_int) {
+					fprintf(stderr,
+					        "%s: could not parse \"%s\" as an int for"
+					        " bandwidth\n",
+					        fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 20) && (to.val != 40) && (to.val != 80)) {
+					fprintf(stderr,
+					        "%s: invalid bandwidth %d\n",
+					        fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 20)
+					c |= WL_CHANSPEC_BW_20;
+				else if (to.val == 40)
+					c |= WL_CHANSPEC_BW_40;
+				else {
+					if (ioctl_version == 1) {
+						fprintf(stderr,
+						        "%s: bandwidth 80 MHz is not supported by "
+						        "this version driver.\n",
+						        fn_name);
+						err = BCME_USAGE_ERROR;
+						goto exit;
+
+					}
+					c |= WL_CHANSPEC_BW_80;
+				}
+
+				bw_set = TRUE;
+			}
+			if (to.opt == 'c') {
+				if (!to.valstr) {
+					fprintf(stderr,
+					        "%s: please provide country abbrev \n", fn_name);
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				strncpy(abbrev, to.valstr, WLC_CNTRY_BUF_SZ - 1);
+				abbrev[WLC_CNTRY_BUF_SZ - 1] = '\0';
+			}
+		}
+		if (!bw_set || !band_set) {
+			if (!band_set)
+				fprintf(stderr, "%s: you need to set a band, '-b <5|2>'\n",
+				        fn_name);
+			if (!bw_set)
+				fprintf(stderr,
+				        "%s: you need to set a bandwidth, '-w <20|40|80>'\n",
+				        fn_name);
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	}
+
+	/* convert chanspec to legacy if needed */
+	if (c != 0) {
+		c = wl_chspec_to_driver(c);
+		if (c == INVCHANSPEC) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	}
+
+	/* Add chanspec argument */
+	chanspec = (chanspec_t *) (buf + buflen);
+	*chanspec = c;
+	buflen += (sizeof(chanspec_t));
+
+	/* Add country abbrev */
+	strncpy(buf + buflen, abbrev, WLC_CNTRY_BUF_SZ);
+	buflen += WLC_CNTRY_BUF_SZ;
+
+	/* Add list */
+	list = (wl_uint32_list_t *)(buf + buflen);
+	list->count = htod32(WL_NUMCHANSPECS);
+	buflen += sizeof(uint32)*(WL_NUMCHANSPECS + 1);
+
+	ret = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen);
+	if (ret < 0)
+		return ret;
+
+	list = (wl_uint32_list_t *)buf;
+	for (i = 0; i < dtoh32(list->count); i++) {
+		c = wl_chspec32_from_driver(list->element[i]);
+		wf_chspec_ntoa(c, chspec_str);
+		printf("%s (0x%04x)\n", chspec_str, c);
+	}
+	printf("\n");
+	return ret;
+
+exit:
+	return err;
+}
+
+static int
+wl_channels_in_country(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_channels_in_country_t *cic;
+	int ret;
+	uint i, len;
+
+	cic = (wl_channels_in_country_t *)buf;
+	cic->buflen = WLC_IOCTL_MAXLEN;
+	cic->count = 0;
+
+	/* country abbrev must follow */
+	if (!*++argv) {
+		fprintf(stderr, "missing country abbrev\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	len = strlen(*argv);
+	if ((len > 3) || (len < 2)) {
+		fprintf(stderr, "invalid country abbrev: %s\n", *argv);
+		return BCME_BADARG;
+	}
+
+	strcpy(cic->country_abbrev, *argv);
+
+	/* band must follow */
+	if (!*++argv) {
+		fprintf(stderr, "missing band\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!stricmp(*argv, "a"))
+		cic->band = WLC_BAND_5G;
+	else if (!stricmp(*argv, "b"))
+		cic->band = WLC_BAND_2G;
+	else {
+		fprintf(stderr, "unsupported band: %s\n", *argv);
+		return BCME_UNSUPPORTED;
+	}
+
+	cic->buflen = htod32(cic->buflen);
+	cic->band = htod32(cic->band);
+	cic->count = htod32(cic->count);
+	ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < dtoh32(cic->count); i++)
+		printf("%d ", dtoh32(cic->channel[i]));
+	printf("\n");
+
+	return ret;
+}
+
+int
+wl_get_scan(void *wl, int opc, char *scan_buf, uint buf_len)
+{
+	wl_scan_results_t *list = (wl_scan_results_t*)scan_buf;
+	int ret;
+
+	list->buflen = htod32(buf_len);
+	ret = wlu_get(wl, opc, scan_buf, buf_len);
+	if (ret < 0)
+		return ret;
+	ret = 0;
+
+	list->buflen = dtoh32(list->buflen);
+	list->version = dtoh32(list->version);
+	list->count = dtoh32(list->count);
+	if (list->buflen == 0) {
+		list->version = 0;
+		list->count = 0;
+	} else if (list->version != WL_BSS_INFO_VERSION &&
+	           list->version != LEGACY2_WL_BSS_INFO_VERSION &&
+	           list->version != LEGACY_WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+			"but this program supports only version %d.\n",
+			list->version, WL_BSS_INFO_VERSION);
+		list->buflen = 0;
+		list->count = 0;
+	}
+
+	return ret;
+}
+
+static int
+wl_get_iscan(void *wl, char *scan_buf, uint buf_len)
+{
+	wl_iscan_results_t list;
+	wl_scan_results_t *results;
+	int ret;
+
+	memset(&list, '\0', sizeof(list));
+	list.results.buflen = htod32(buf_len);
+	ret = wlu_iovar_getbuf(wl, "iscanresults", &list, WL_ISCAN_RESULTS_FIXED_SIZE,
+	                      scan_buf, WLC_IOCTL_MAXLEN);
+
+	if (ret < 0)
+		return ret;
+
+	ret = 0;
+
+	results = &((wl_iscan_results_t*)scan_buf)->results;
+	results->buflen = dtoh32(results->buflen);
+	results->version = dtoh32(results->version);
+	results->count = dtoh32(results->count);
+	if (results->buflen == 0) {
+		printf("wl_get_iscan buflen 0\n");
+		results->version = 0;
+		results->count = 0;
+	} else if (results->version != WL_BSS_INFO_VERSION &&
+	           results->version != LEGACY2_WL_BSS_INFO_VERSION &&
+	           results->version != LEGACY_WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+			"but this program supports only version %d.\n",
+			results->version, WL_BSS_INFO_VERSION);
+		results->buflen = 0;
+		results->count = 0;
+	}
+
+	return ret;
+}
+
+static int
+wl_spect(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, spect;
+	char *endptr = NULL;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &spect, sizeof(spect))) < 0) {
+			return ret;
+		}
+
+		spect = dtoh32(spect);
+		switch (spect) {
+		case SPECT_MNGMT_OFF:
+			printf("Off\n");
+			break;
+
+		case SPECT_MNGMT_LOOSE_11H:
+			printf("Loose interpretation of 11h spec - may join non 11h AP.\n");
+			break;
+
+		case SPECT_MNGMT_STRICT_11H:
+			printf("Strict interpretation of 11h spec - may not join non 11h AP.\n");
+			break;
+
+		case SPECT_MNGMT_STRICT_11D:
+			printf("802.11d mode\n");
+			break;
+
+		case SPECT_MNGMT_LOOSE_11H_D:
+			printf("Loose interpretation of 11h+d spec - may join non-11h APs\n");
+			break;
+
+		default:
+			printf("invalid value 0x%x\n", spect);
+			return BCME_BADARG;
+		}
+		return (0);
+	} else {
+		spect = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		if (spect < SPECT_MNGMT_OFF || spect > SPECT_MNGMT_LOOSE_11H_D)
+			return BCME_BADARG;
+
+		spect = htod32(spect);
+		return wlu_set(wl, cmd->set, &spect, sizeof(spect));
+	}
+}
+
+static int
+wl_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ether_addr bssid;
+	wlc_ssid_t ssid;
+	char ssidbuf[SSID_FMT_BUF_LEN];
+	wl_bss_info_t *bi;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_get(wl, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN)) == 0) {
+		/* The adapter is associated. */
+		*(uint32*)buf = htod32(WLC_IOCTL_MAXLEN);
+		if ((ret = wlu_get(wl, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+
+		bi = (wl_bss_info_t*)(buf + 4);
+		if (dtoh32(bi->version) == WL_BSS_INFO_VERSION ||
+		    dtoh32(bi->version) == LEGACY2_WL_BSS_INFO_VERSION ||
+		    dtoh32(bi->version) == LEGACY_WL_BSS_INFO_VERSION)
+			dump_bss_info(bi);
+		else
+			fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+				"but this program supports only version %d.\n",
+				bi->version, WL_BSS_INFO_VERSION);
+	} else {
+		printf("Not associated. Last associated with ");
+
+		if ((ret = wlu_get(wl, WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t))) < 0) {
+			printf("\n");
+			return ret;
+		}
+
+		wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
+		printf("SSID: \"%s\"\n", ssidbuf);
+	}
+
+	return 0;
+}
+
+static int
+wl_deauth_rc(void *wl, cmd_t *cmd, char **argv)
+{
+	scb_val_t scb_val;
+	int ret;
+
+	if (!*++argv) {
+		fprintf(stderr, "STA MAC not specified, deauth all\n");
+		ret = wlu_set(wl, WLC_SCB_DEAUTHENTICATE, (void *)&ether_bcast,
+			ETHER_ADDR_LEN);
+		return ret;
+
+	} else if (!wl_ether_atoe(*argv, &scb_val.ea)) {
+		fprintf(stderr, "Malformed STA MAC parameter\n");
+		ret = BCME_USAGE_ERROR;
+
+	} else if (!*++argv) {
+		/* No reason code furnished, so driver will use its default */
+		ret = wlu_set(wl, WLC_SCB_DEAUTHENTICATE, &scb_val.ea,
+			ETHER_ADDR_LEN);
+
+	} else {
+		scb_val.val = htod32((uint32)strtoul(*argv, NULL, 0));
+		ret = wlu_set(wl, cmd->set, &scb_val, sizeof(scb_val));
+	}
+	return ret;
+}
+
+static int
+wl_wpa_auth(void *wl, cmd_t *cmd, char **argv)
+{
+	int bsscfg_idx = 0;
+	int consumed;
+	int wpa_auth = 0;
+	int ret = 0;
+	int i;
+	static struct {
+		int val;
+		const char *name;
+	} auth_mode[] =
+		  /* Keep the numeric values in the staticly initialized
+		   * help string consistent.  Unfortunately, there isn't
+		   * an automatic way for that.
+		   */
+		{{WPA_AUTH_NONE,	"WPA-NONE"},
+		 {WPA_AUTH_UNSPECIFIED,	"WPA-802.1x"},
+		 {WPA_AUTH_PSK,		"WPA-PSK"},
+#ifdef	BCMCCX
+		 {WPA_AUTH_CCKM,	"CCKM(WPA)"},
+		 {WPA2_AUTH_CCKM,	"CCKM(WPA2)"},
+#endif	/* BCMCCX */
+		 {WPA2_AUTH_UNSPECIFIED, "WPA2-802.1x"},
+		 {WPA2_AUTH_PSK,	"WPA2-PSK"},
+#ifdef BCMWAPI_WAI
+		{WAPI_AUTH_UNSPECIFIED, "WAPI-AS"},
+		{WAPI_AUTH_PSK,        "WAPI-PSK"},
+#endif /* BCMWAPI_WAI */
+		 {WPA2_AUTH_FT,		"FT"},
+		 {WPA_AUTH_DISABLED,	"disabled"}};
+
+	/* skip the command name */
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, cmd->name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+
+	argv += consumed;
+
+	if (!*argv) {
+		/* no arg, so this is a GET. */
+
+		if (!consumed)
+			ret = wlu_iovar_getint(wl, "wpa_auth", &wpa_auth);
+		else
+			ret = wl_bssiovar_getint(wl, "wpa_auth", bsscfg_idx, &wpa_auth);
+
+		if (ret < 0)
+			return ret;
+
+		/* Show all AKM suites enabled */
+		printf("0x%x", wpa_auth);
+
+		if (wpa_auth == WPA_AUTH_DISABLED)
+			printf(" Disabled");
+
+		for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++) {
+			if (wpa_auth & auth_mode[i].val)
+				printf(" %s", auth_mode[i].name);
+		}
+
+		printf("\n");
+		return ret;
+
+
+	} else {
+		/* there's an arg, so this is a SET. */
+		ret = 1;
+
+		/* Validate the user input range */
+		if (isdigit((int)*argv[0])) {
+			unsigned int range = 0;
+
+			/* param is a number; look for value in the list */
+			wpa_auth = strtoul(*argv, NULL, 0);
+
+			/* Validate the user input range */
+
+			for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++)
+				range |= auth_mode[i].val;
+
+			range = (~range) & 0xFFFF;
+
+			if (range & wpa_auth) {
+				ret = 1;
+				goto usage;
+			} else {
+				ret = 0;
+			}
+
+		} else {
+
+			int arg_count = 0;
+			char** p_argv;
+			int j = 0;
+			unsigned int range = 0;
+
+			wpa_auth = 0;
+			p_argv = argv;
+
+			for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++)
+				range |= auth_mode[i].val;
+
+			range = (~range) & (0xFFFF);
+
+			while (*p_argv) {
+				arg_count++;
+				p_argv++;
+				}
+
+			p_argv = argv;
+
+			for (j = 0; j < arg_count; j++) {
+				bool found = FALSE;
+
+				argv = p_argv + j;
+
+				/* treat param as string to be matched in list */
+				for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++) {
+					if (!stricmp(auth_mode[i].name, *argv)) {
+
+						found = TRUE;
+						wpa_auth |= auth_mode[i].val;
+						ret = 0;
+
+						/* traverse the list */
+						argv++;
+						if (!*argv)
+							break;
+					}
+				}
+
+				if ((found == FALSE) || (range & wpa_auth))
+					goto usage;
+			}
+
+		}
+		if (ret)
+			fprintf(stderr, "%s is not a valid WPA auth mode\n", *argv);
+		else {
+			if (!consumed)
+				ret = wlu_iovar_setint(wl, "wpa_auth", wpa_auth);
+			else
+				ret = wl_bssiovar_setint(wl, "wpa_auth", bsscfg_idx, wpa_auth);
+		}
+	}
+
+	return ret;
+
+usage:
+	fprintf(stderr, "Inavlid user argument.\n");
+	fprintf(stderr, "Values may be a bitvector or list of names from the set.\n");
+
+	for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++) {
+		fprintf(stderr, "\n0x%04x  %s", auth_mode[i].val, auth_mode[i].name);
+	}
+
+	printf("\n");
+	return ret;
+}
+
+static int
+wl_set_pmk(void *wl, cmd_t *cmd, char **argv)
+{
+	wsec_pmk_t psk;
+	size_t key_len;
+
+	if (!*++argv) {
+		return BCME_USAGE_ERROR;
+	}
+	key_len = strlen(*argv);
+	if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
+		fprintf(stderr, "passphrase must be between %d and %d characters long\n",
+		       WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN);
+		return BCME_BADARG;
+	}
+	psk.key_len = htod16((ushort) key_len);
+	psk.flags = htod16(WSEC_PASSPHRASE);
+	memcpy(psk.key, *argv, key_len);
+	return wlu_set(wl, cmd->set, &psk, sizeof(psk));
+}
+
+static int
+wl_wsec(void *wl, cmd_t *cmd, char **argv)
+{
+	int wsec;
+	int bsscfg_idx = 0;
+	int consumed;
+	char *endptr = NULL;
+	int error;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "wsec", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	if (!*argv) {
+		/* This is a GET */
+		if (consumed == 0) {
+			error = wlu_get(wl, WLC_GET_WSEC, &wsec, sizeof(uint32));
+			wsec = dtoh32(wsec);
+		}
+		else
+			error = wl_bssiovar_getint(wl, "wsec", bsscfg_idx, &wsec);
+
+		if (!error)
+			wl_printint(wsec);
+	} else {
+		/* This is a SET */
+		if (!stricmp(*argv, "off"))
+			wsec = 0;
+		else {
+			wsec = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		if (consumed == 0) {
+			wsec = htod32(wsec);
+			error = wlu_set(wl, WLC_SET_WSEC, &wsec, sizeof(uint32));
+		}
+		else
+			error = wl_bssiovar_setint(wl, "wsec", bsscfg_idx, wsec);
+	}
+
+	return error;
+}
+
+static int
+parse_wep(char **argv, wl_wsec_key_t *key, bool options)
+{
+	char hex[] = "XX";
+	unsigned char *data = key->data;
+	char *keystr = *argv;
+
+	switch (strlen(keystr)) {
+	case 5:
+	case 13:
+	case 16:
+		key->len = strlen(keystr);
+		memcpy(data, keystr, key->len + 1);
+		break;
+	case 12:
+	case 28:
+	case 34:
+	case 66:
+		/* strip leading 0x */
+		if (!strnicmp(keystr, "0x", 2))
+			keystr += 2;
+		else
+			return -1;
+		/* fall through */
+	case 10:
+	case 26:
+	case 32:
+	case 64:
+		key->len = strlen(keystr) / 2;
+		while (*keystr) {
+			strncpy(hex, keystr, 2);
+			*data++ = (char) strtoul(hex, NULL, 16);
+			keystr += 2;
+		}
+		break;
+	default:
+		return -1;
+	}
+
+	switch (key->len) {
+	case 5:
+		key->algo = CRYPTO_ALGO_WEP1;
+		break;
+	case 13:
+		key->algo = CRYPTO_ALGO_WEP128;
+		break;
+	case 16:
+		/* default to AES-CCM */
+		key->algo = CRYPTO_ALGO_AES_CCM;
+		break;
+	case 32:
+		key->algo = CRYPTO_ALGO_TKIP;
+		break;
+	default:
+		return -1;
+	}
+
+	/* Set as primary key by default */
+	key->flags |= WL_PRIMARY_KEY;
+
+	if (options) {
+		/* Get options */
+		while (*++argv) {
+			if (!strnicmp("ccm", *argv, 3) && key->len == 16)
+				key->algo = CRYPTO_ALGO_AES_CCM;
+#ifdef BCMWAPI_WPI
+			else if (!strnicmp("wapi", *argv, 4) && key->len == 32)
+				key->algo = CRYPTO_ALGO_SMS4;
+#endif /* BCMWAPI_WPI */
+			else if (!strnicmp("ocb", *argv, 3) && key->len == 16)
+				key->algo = CRYPTO_ALGO_AES_OCB_MPDU;
+			else if (!strnicmp("notx", *argv, 4))
+				key->flags &= ~WL_PRIMARY_KEY;
+			else if (!wl_ether_atoe(*argv, &key->ea))
+				memset(&key->ea, 0, ETHER_ADDR_LEN);
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_primary_key(void *wl, cmd_t *cmd, char **argv)
+{
+	int i, val, ret = 0;
+
+	if (!*++argv) {
+		i = 0;
+		do {
+			val = htod32(i);
+			if ((ret = wlu_get(wl, cmd->get, &val, sizeof(val))) < 0) {
+				return ret;
+			}
+			if (dtoh32(val)) {
+				printf("Key %d is primary\n", i);
+				return 0;
+			}
+		} while (++i < DOT11_MAX_DEFAULT_KEYS);
+		printf("No primary key set\n");
+
+	} else {
+		val = htod32(atoi(*argv));
+		ret = wlu_set(wl, cmd->set, &val, sizeof(val));
+	}
+	return ret;
+}
+
+static int
+wl_addwep(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wsec_key_t key;
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	memset(&key, 0, sizeof(key));
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "addwep", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	/* GET operation not allowed */
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	key.index = atoi(*argv++);
+
+	if (!*argv) {
+		fprintf(stderr, "No key specified\n");
+		return BCME_USAGE_ERROR;
+	}
+	if (parse_wep(argv, &key, TRUE))
+		return BCME_BADARG;
+
+	key.index = htod32(key.index);
+	key.len = htod32(key.len);
+	key.algo = htod32(key.algo);
+	key.flags = htod32(key.flags);
+
+	if (consumed == 0) {
+		error = wlu_set(wl, cmd->set, &key, sizeof(key));
+	} else {
+		error = wlu_bssiovar_setbuf(wl, "wsec_key", bsscfg_idx,
+			&key, sizeof(key), buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return error;
+}
+
+static int
+wl_rmwep(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wsec_key_t key;
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	memset(&key, 0, sizeof(key));
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "rmwep", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	/* GET operation not allowed */
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	key.index = htod32(atoi(*argv++));
+
+	if (*argv) {
+		if (!(wl_ether_atoe(*argv, &key.ea)))
+			return BCME_USAGE_ERROR;
+	}
+
+	if (consumed == 0) {
+		error = wlu_set(wl, cmd->set, &key, sizeof(key));
+	} else {
+		error = wlu_var_setbuf(wl, "wsec_key", &key, sizeof(key));
+	}
+
+	return error;
+}
+
+static struct {
+	uint value;
+	const char *string;
+} wsec_test[] = {
+	{WSEC_GEN_MIC_ERROR, 	"mic_error"},
+	{WSEC_GEN_REPLAY, 	"replay"},
+	{WSEC_GEN_ICV_ERROR, "icv_error"},
+	{WSEC_GEN_MFP_ACT_ERROR, "act_error"},
+	{WSEC_GEN_MFP_DISASSOC_ERROR, "disassoc_error"},
+	{WSEC_GEN_MFP_DEAUTH_ERROR, "deauth_error"},
+	{0,		NULL}
+};
+
+
+static int
+wl_wsec_test(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wsec_key_t *key;
+	int i, len;
+	char *endptr = NULL, *wsec_buf = NULL;
+	uint32 val, last_val;
+	int err = 0;
+
+	if (!*++argv) {
+		err = BCME_USAGE_ERROR;
+		goto usage;
+	}
+
+	val = strtol(*argv, &endptr, 0);
+	if (endptr == *argv) {
+		/* the value string was not parsed by strtol */
+		for (i = 0; wsec_test[i].value; i++)
+			if (stricmp(wsec_test[i].string, *argv) == 0) {
+				val = wsec_test[i].value;
+				break;
+			}
+		if (wsec_test[i].value == 0) {
+			err = BCME_BADARG;
+			goto usage;
+		}
+	}
+	++argv;
+
+	switch (val) {
+	case WSEC_GEN_REPLAY:
+	case WSEC_GEN_MIC_ERROR:
+	case WSEC_GEN_ICV_ERROR:
+	case WSEC_GEN_MFP_ACT_ERROR:
+	case WSEC_GEN_MFP_DISASSOC_ERROR:
+	case WSEC_GEN_MFP_DEAUTH_ERROR:
+		if (!*argv) {
+			fprintf(stderr, "insufficient arguments\n");
+			return BCME_USAGE_ERROR;
+		}
+		len = sizeof(wl_wsec_key_t) + 4;
+		wsec_buf = malloc(len);
+		if (wsec_buf == NULL) {
+			fprintf(stderr, "Error allocating memory failed for wsec_buf");
+			return BCME_NOMEM;
+		}
+		*(uint32 *)wsec_buf = htod32(val);
+		key = (wl_wsec_key_t *)&wsec_buf[4];
+		memset(key, 0, sizeof(wl_wsec_key_t));
+		/* If it doesn't look like an ether addr, suppose it's a key index */
+		if (!(wl_ether_atoe(*argv, &key->ea))) {
+			memset(&key->ea, 0, ETHER_ADDR_LEN);
+			key->index = htod32(atoi(*argv));
+		}
+		break;
+	default:
+		goto usage;
+	}
+
+	err = wlu_set(wl, cmd->set, wsec_buf, len);
+	free(wsec_buf);
+	goto exit;
+
+usage:
+	fprintf(stderr, "wsec test_type may be a number or name from the following set:");
+	last_val = 0xffffffff;
+	for (i = 0; (val = wsec_test[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, wsec_test[i].string);
+		else
+			fprintf(stderr, ", %s", wsec_test[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+
+exit:
+	return err;
+}
+
+static int
+wl_keys(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i, j;
+	union {
+		int index;
+		wl_wsec_key_t key;
+	} u;
+	int wep_is_on = 0;
+	const char *addr;
+	int ret = BCME_OK;
+
+	UNUSED_PARAMETER(argv);
+
+	if (wlu_iovar_getint(wl, "wsec", &wep_is_on) < 0)
+		fprintf(stderr, "Could not query wsec status.\n");
+
+	for (i = 0; i < 256; i++) {
+		memset(&u, 0, sizeof(u));
+		u.index = htod32(i);
+		ret = wlu_get(wl, cmd->get, &u, sizeof(u));
+		if (ret == BCME_IOCTL_ERROR) {
+			int bcmerr;
+			if (wlu_iovar_getint(wl, "bcmerror", &bcmerr) >= 0 &&
+				(bcmerr == BCME_BADKEYIDX)) {
+				ret = BCME_OK;
+			}
+		}
+
+		if (ret != BCME_OK)
+			break;
+
+		/* ignore empty keys */
+		if (dtoh32(u.key.algo) == CRYPTO_ALGO_OFF || (u.key.len == 0))
+			continue;
+
+		if (ETHER_ISNULLADDR(&u.key.ea))
+			addr = "(default)";
+		else
+			addr = wl_ether_etoa(&u.key.ea);
+
+		printf("%3d: %-17s Key %d: %s ", i, addr, dtoh32(u.key.index),
+		       bcm_crypto_algo_name(dtoh32(u.key.algo)));
+
+		if (wep_is_on && dtoh32(u.key.flags) & WL_PRIMARY_KEY)
+			printf("*");
+		printf("\t");
+
+		if (dtoh32(u.key.len) == 0)
+			printf("No key present");
+		else {
+			if (dtoh32(u.key.flags) & WL_SOFT_KEY)
+				printf("soft ");
+			printf("len %d, data 0x", dtoh32(u.key.len));
+			for (j = 0; j < dtoh32(u.key.len); j++)
+				printf("%02X", u.key.data[j]);
+
+			for (j = 0; j < dtoh32(u.key.len); j++)
+				if (!isprint(u.key.data[j]))
+					break;
+			if (j == dtoh32(u.key.len))
+				printf(" (%.*s)", (int)dtoh32(u.key.len), u.key.data);
+
+		}
+
+		printf("\n");
+	}
+
+	return ret;
+}
+
+static int
+wl_tsc(void *wl, cmd_t *cmd, char **argv)
+{
+	union {
+		int32 index;
+		uint8 tsc[DOT11_WPA_KEY_RSC_LEN];
+	} u;
+	uint32 hi, lo;
+	int idx, ret;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	idx = atoi(*argv);
+	if (idx < 0) {
+		fprintf(stderr, "Key index %d out of range. Should be positive.\n", idx);
+		return BCME_BADARG;
+	}
+	u.index = htod32(idx);
+	if ((ret = wlu_get(wl, cmd->get, &u, sizeof(u))) < 0)
+		return ret;
+	lo = u.tsc[0] | (u.tsc[1] << 8) | (u.tsc[2] << 16) | (u.tsc[3] << 24);
+	hi = u.tsc[4] | (u.tsc[5] << 8) | (u.tsc[6] << 16) | (u.tsc[7] << 24);
+
+	printf("Key %d TSC: 0x%04x:%08x\n", idx, hi, lo);
+	return 0;
+}
+
+
+static void
+wl_txppr_print(ppr_t *ppr, int cck, uint flags)
+{
+
+	switch (ppr_get_ch_bw(ppr)) {
+	case WL_TX_BW_20:
+		printf("\n20MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20);
+		break;
+	case WL_TX_BW_40:
+		printf("\n20 in 40MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20IN40);
+		printf("\n40MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_40);
+		break;
+	case WL_TX_BW_80:
+		printf("\n20 in 80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20IN80);
+		printf("\n40 in 80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_40IN80);
+		printf("\n80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_80);
+		break;
+	default:
+		break;
+	}
+	/* MCS32 value is obsoleted */
+	/* printf("MCS32        %2d\n", ppr->mcs32); */
+	printf("\n");
+}
+
+
+/* get a power value from the opaque ppr structure */
+static int8 wl_ppr_get_pwr(ppr_t* pprptr, reg_rate_index_t rate_idx, wl_tx_bw_t bw)
+{
+	clm_rate_group_id_t group_id = ppr_table[rate_idx].id;
+	int8 power = WL_RATE_DISABLED;
+	switch (ppr_group_table[group_id].rate_type) {
+		case PPR_RATE_DSSS:
+			{
+				ppr_dsss_rateset_t rateset;
+				ppr_get_dsss(pprptr, bw, ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		case PPR_RATE_OFDM:
+			{
+				ppr_ofdm_rateset_t rateset;
+				ppr_get_ofdm(pprptr, bw, ppr_group_table[group_id].mode,
+					ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		case PPR_RATE_HT:
+			{
+				ppr_ht_mcs_rateset_t rateset;
+				ppr_get_ht_mcs(pprptr, bw, ppr_group_table[group_id].nss,
+					ppr_group_table[group_id].mode,
+					ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		case PPR_RATE_VHT:
+			{
+				ppr_vht_mcs_rateset_t rateset;
+				ppr_get_vht_mcs(pprptr, bw, ppr_group_table[group_id].nss,
+					ppr_group_table[group_id].mode,
+					ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		default:
+			break;
+	}
+
+	return power;
+}
+
+
+#define PRINT_PPR_RATE_LOOP(idx, len, rates)		  \
+			for (idx = 0; idx < len; idx++) { \
+				if (rates[idx] == WL_RATE_DISABLED) \
+					printf("  -"); \
+				else \
+					printf(" %2d", rates[idx]); \
+			}
+
+/* print power offset for for a given bandwidth */
+static void
+wl_txppr_print_bw(ppr_t *ppr, int cck, uint flags, wl_tx_bw_t bw)
+{
+	uint i, j, rlen;
+	uint n = WL_NUM_2x2_ELEMENTS;
+	uint offset = 0;
+	int8 *ptr, *vhtptr;
+	const char *str = "";
+	bool siso = ((flags & WL_TX_POWER_F_MIMO) == 0);
+	bool vht = ((flags & WL_TX_POWER_F_VHT) != 0);
+	ppr_ofdm_rateset_t ofdm_rate;
+	ppr_vht_mcs_rateset_t vhtrate;
+
+	if (!siso) {
+		offset = n = WL_NUM_3x3_ELEMENTS;
+	}
+
+	if (cck) {
+		ppr_dsss_rateset_t rate;
+		ppr_get_dsss(ppr, bw, WL_TX_CHAINS_1, &rate);
+		printf("CCK         ");
+		PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_DSSS, rate.pwr);
+		if (!siso) {
+			ppr_get_dsss(ppr, bw, WL_TX_CHAINS_2, &rate);
+			printf("\nCCK CDD 1x2 ");
+			PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_DSSS, rate.pwr);
+			ppr_get_dsss(ppr, bw, WL_TX_CHAINS_3, &rate);
+			printf("\nCCK CDD 1x3 ");
+			PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_DSSS, rate.pwr);
+		}
+	}
+	ppr_get_ofdm(ppr, bw, WL_TX_MODE_NONE, WL_TX_CHAINS_1, &ofdm_rate);
+	printf("\nOFDM        ");
+	PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_OFDM, ofdm_rate.pwr);
+	ppr_get_ofdm(ppr, bw, WL_TX_MODE_CDD, WL_TX_CHAINS_2, &ofdm_rate);
+	printf("\nOFDM-CDD    ");
+	PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_OFDM, ofdm_rate.pwr);
+	printf("\n");
+	for (i = 0; i < n; i++) {
+		wl_tx_nss_t nss;
+		wl_tx_mode_t mode;
+		wl_tx_chains_t chains;
+		switch (i + offset) {
+			case 0:
+				str = "MCS-SISO   ";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_1;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 1:
+				str = "MCS-CDD    ";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_CDD;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 2:
+				str = "MCS STBC   ";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_STBC;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 3:
+				str = "MCS 8~15   ";
+				nss = WL_TX_NSS_2;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 4:
+			case 5:
+				ptr = NULL;
+				vhtptr = NULL;
+				break;
+			case 6:
+				str = "1 Nsts 1 Tx";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_1;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 7:
+				str = "1 Nsts 2 Tx";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_CDD;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 8:
+				str = "1 Nsts 3 Tx";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_CDD;
+				chains = WL_TX_CHAINS_3;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 9:
+				str = "2 Nsts 2 Tx";
+				nss = WL_TX_NSS_2;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 10:
+				str = "2 Nsts 3 Tx";
+				nss = WL_TX_NSS_2;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_3;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 11:
+				str = "3 Nsts 3 Tx";
+				nss = WL_TX_NSS_3;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_3;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			default:
+				ptr = NULL;
+				vhtptr = NULL;
+				break;
+		}
+		if (ptr == NULL)
+			continue;
+		ppr_get_vht_mcs(ppr, bw, nss, mode, chains, &vhtrate);
+		printf("%s ", str);
+		if (vht && vhtptr)
+			rlen = WL_RATESET_SZ_VHT_MCS;
+		else
+			rlen = WL_RATESET_SZ_HT_MCS;
+		PRINT_PPR_RATE_LOOP(j, rlen, ptr);
+		printf("\n");
+	}
+}
+
+static int
+wl_get_current_txppr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint flags;
+	chanspec_t chanspec;
+	char chanspec_str[CHANSPEC_STR_LEN];
+	uint pprsize = ppr_ser_size_by_bw(ppr_get_max_bw());
+	wl_txppr_t *wl_txppr;
+	ppr_t *pprptr = NULL;
+
+	wl_txppr = (wl_txppr_t *)malloc(sizeof(*wl_txppr) + pprsize);
+
+	if (wl_txppr == NULL) {
+		fprintf(stderr, "Error allocating memory failed for curppr");
+		return BCME_NOMEM;
+	}
+
+	memset(wl_txppr, 0, sizeof(*wl_txppr));
+	wl_txppr->buflen = pprsize;
+	if ((err = ppr_init_ser_mem_by_bw(wl_txppr->pprbuf, ppr_get_max_bw(), pprsize))
+		!= BCME_OK) {
+		free(wl_txppr);
+		return err;
+	}
+
+	if (WLC_IOCTL_MAXLEN < sizeof(wl_txppr_t) + pprsize) {
+		free(wl_txppr);
+		return BCME_ERROR;
+	}
+
+	argv++;
+	if (*argv)
+		fprintf(stderr, "Ignoring arguments for %s\n", cmd->name);
+
+	wl_txppr->ver = WL_TXPPR_VERSION;
+	wl_txppr->len = WL_TXPPR_LENGTH;
+	if ((err = wlu_iovar_getbuf(wl, "curppr", wl_txppr, sizeof(*wl_txppr) + pprsize,
+		buf, WLC_IOCTL_MAXLEN)) < 0) {
+		free(wl_txppr);
+		return err;
+	}
+
+	/* the input buffer is no longer needed, output results are in buf */
+	free(wl_txppr);
+	wl_txppr = (wl_txppr_t *)buf;
+
+	/* parse */
+	wl_txppr->flags = dtoh32(wl_txppr->flags);
+	wl_txppr->chanspec = wl_chspec_from_driver(wl_txppr->chanspec);
+	wl_txppr->local_chanspec = wl_chspec_from_driver(wl_txppr->local_chanspec);
+
+	chanspec = wl_txppr->chanspec;
+	flags = (wl_txppr->flags & WL_TX_POWER_F_VHT) |
+	       (wl_txppr->flags & WL_TX_POWER_F_HT) |
+	       (wl_txppr->flags & WL_TX_POWER_F_MIMO) |
+	       (wl_txppr->flags & WL_TX_POWER_F_SISO);
+
+	/* dump */
+	printf("Current channel:\t %s\n",
+	       wf_chspec_ntoa(wl_txppr->chanspec, chanspec_str));
+	printf("BSS channel:\t\t %s\n",
+	       wf_chspec_ntoa(wl_txppr->local_chanspec, chanspec_str));
+	printf("Power/Rate Dump (in 1/4dB): Channel %d\n", CHSPEC_CHANNEL(chanspec));
+	if ((err = ppr_deserialize_create(NULL, wl_txppr->pprbuf, pprsize, &pprptr)) == BCME_OK) {
+		wl_txppr_print(pprptr, CHSPEC_IS2G(chanspec), flags);
+		ppr_delete(NULL, pprptr);
+	}
+	return err;
+}
+
+/* This version number must be incremented for every
+ * modification to the curpower output format. Minor changes
+ * warrant a decimal point increment. Major (potential
+ * script-breaking) changes should be met with a major increment.
+ */
+#define CURPOWER_OUTPUT_FORMAT_VERSION "5.1"
+
+#define RATE_STR_LEN 64
+
+static int
+wl_get_current_power(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int mimo;
+	int i;
+	chanspec_t chanspec;
+	char chanspec_str[CHANSPEC_STR_LEN];
+	bool verbose = FALSE;
+	bool brief = FALSE;
+	int16 power_target;
+	char rate_str[RATE_STR_LEN];
+	int clk;
+	uint8 *ppr_ser;
+	size_t pprsize = ppr_ser_size_by_bw(ppr_get_max_bw());
+	tx_pwr_rpt_t *ppr_wl = NULL;
+
+	/* firmware will crash if clk = 0 while using curpower */
+	if ((err = wlu_get(wl, WLC_GET_CLK, &clk, sizeof(int))) < 0)
+		return err;
+
+	if (!clk) {
+		fprintf(stderr, "Error: clock not active, do wl up (if not done already) "
+				"and force mpc 0 to active clock\n");
+		return BCME_ERROR;
+	}
+	/* Allocate memory for curpower report structure with 2 ppr data block */
+	ppr_wl = (tx_pwr_rpt_t *)malloc(sizeof(tx_pwr_rpt_t) + pprsize*2);
+
+	if (ppr_wl == NULL) {
+		fprintf(stderr, "Allocating mem failed for curpower\n");
+		return BCME_NOMEM;
+	}
+	ppr_ser  = ppr_wl->pprdata;
+
+	memset(ppr_wl, 0, sizeof(tx_pwr_rpt_t) + pprsize*2);
+	ppr_wl->board_limit_len  = pprsize;
+	ppr_wl->target_len       = pprsize;
+	ppr_wl->version          = TX_POWER_T_VERSION;
+	/* init allocated mem for serialisation */
+	ppr_init_ser_mem_by_bw(ppr_ser, ppr_get_max_bw(), ppr_wl->board_limit_len);
+	ppr_ser += ppr_wl->board_limit_len;
+	ppr_init_ser_mem_by_bw(ppr_ser, ppr_get_max_bw(), ppr_wl->target_len);
+
+
+	if (argv[1] && (!strcmp(argv[1], "--verbose") || !strcmp(argv[1], "-v"))) {
+		verbose = TRUE;
+		argv++;
+	}
+	if (argv[1] && (!strcmp(argv[1], "--brief") || !strcmp(argv[1], "-b"))) {
+		brief = TRUE;
+		argv++;
+	}
+	argv++;
+	if (*argv)
+		fprintf(stderr, "Ignoring arguments for %s\n", cmd->name);
+
+	if ((err = wlu_get(wl, cmd->get, ppr_wl, sizeof(tx_pwr_rpt_t) + pprsize*2)) < 0) {
+		fprintf(stderr, "Error: Curpower failed. ");
+		fprintf(stderr, "Bring up interface and disable mpc if necessary (wl mpc 0)\n");
+		free(ppr_wl);
+		return err;
+	}
+
+	/* parse */
+	if (ppr_wl->version != TX_POWER_T_VERSION) {
+		printf("error: version mismatch - driver %d, wl executable was expecting %d\n",
+			ppr_wl->version, TX_POWER_T_VERSION);
+		err = BCME_ERROR;
+	} else {
+		ppr_t* ppr_board = NULL;
+		ppr_t* ppr_target = NULL;
+		ppr_wl->flags = dtoh32(ppr_wl->flags);
+		ppr_wl->chanspec = wl_chspec_from_driver(ppr_wl->chanspec);
+		ppr_wl->local_chanspec = wl_chspec_from_driver(ppr_wl->local_chanspec);
+
+		chanspec = ppr_wl->chanspec;
+		mimo = (ppr_wl->flags & WL_TX_POWER_F_HT) |
+		       (ppr_wl->flags & WL_TX_POWER_F_MIMO) |
+		       (ppr_wl->flags & WL_TX_POWER_F_SISO);
+		if ((err = ppr_deserialize_create(NULL, ppr_wl->pprdata, ppr_wl->board_limit_len,
+			&ppr_board)) != BCME_OK) {
+			goto exit;
+		}
+
+		if ((err = ppr_deserialize_create(NULL, ppr_ser, ppr_wl->target_len, &ppr_target))
+			!= BCME_OK) {
+			goto exit;
+		}
+
+		/* dump */
+		if (verbose)
+			printf("%-23s%s\n", "Output Format Version:",
+				CURPOWER_OUTPUT_FORMAT_VERSION);
+
+		printf("%-23s%s, %s\n", "Power Control:",
+		       (ppr_wl->flags & WL_TX_POWER_F_ENABLED) ? "On" : "Off",
+		       (ppr_wl->flags & WL_TX_POWER_F_HW) ? "HW" : "SW");
+		printf("%-23s%s\n", "Current Channel:",
+		       wf_chspec_ntoa(ppr_wl->chanspec, chanspec_str));
+		printf("%-23s%s\n", "BSS Channel:",
+		       wf_chspec_ntoa(ppr_wl->local_chanspec, chanspec_str));
+		printf("%-23s%d.%d dBm\n", "BSS Local Max:",
+		       DIV_QUO(ppr_wl->local_max, 4), DIV_REM(ppr_wl->local_max, 4));
+		printf("%-23s%d.%d dB\n", "BSS Local Constraint:",
+		       DIV_QUO(ppr_wl->local_constraint, 4), DIV_REM(ppr_wl->local_constraint, 4));
+		printf("%-23s%s\n", "Channel Width:",
+			((ppr_wl->channel_bandwidth == WL_BW_20MHZ) ? "20MHz" :
+			((ppr_wl->channel_bandwidth == WL_BW_40MHZ) ? "40MHz" : "80MHz")));
+		printf("%-23s%d.%d dBm\n", "User Target:",
+		       DIV_QUO(ppr_wl->user_target, 4), DIV_REM(ppr_wl->user_target, 4));
+		printf("%-23s%d.%d dB\n", "SROM Antgain 2G:",
+		       DIV_QUO(ppr_wl->antgain[0], 4), DIV_REM(ppr_wl->antgain[0], 4));
+		printf("%-23s%d.%d dB\n", "SROM Antgain 5G:",
+		       DIV_QUO(ppr_wl->antgain[1], 4), DIV_REM(ppr_wl->antgain[1], 4));
+		printf("%-23s", "SAR:");
+		if (ppr_wl->sar != WLC_TXPWR_MAX)
+			printf("%d.%d dB\n", DIV_QUO(ppr_wl->sar, 4), DIV_REM(ppr_wl->sar, 4));
+		else
+			printf("-\n");
+		printf("%-23s", "Open loop:");
+		if (ppr_wl->flags & WL_TX_POWER_F_OPENLOOP)
+			printf("On\n");
+		else
+			printf("Off\n");
+		printf("%-23s", "Current rate:");
+		wl_rate_print(rate_str, ppr_wl->last_tx_ratespec);
+		printf("[%s] %s\n", get_reg_rate_string_from_ratespec(ppr_wl->last_tx_ratespec),
+			rate_str);
+		printf("\n");
+
+		printf("Regulatory Limits:\n");
+		if (brief)
+		{
+			wl_txpwr_regulatory_array_row_print(ppr_wl->clm_limits,
+				ppr_wl->clm_limits_subchan1, ppr_wl->clm_limits_subchan2,
+				ppr_wl->channel_bandwidth,
+				get_reg_rate_index_from_ratespec(ppr_wl->last_tx_ratespec));
+		}
+		else
+		{
+			wl_txpwr_regulatory_array_print(ppr_wl->clm_limits,
+				ppr_wl->clm_limits_subchan1,
+				ppr_wl->clm_limits_subchan2, ppr_wl->channel_bandwidth, verbose);
+		}
+		printf("\n");
+
+		printf("%-23s%d\n", "Core Index:", ppr_wl->display_core);
+		printf("Board Limits:\n");
+		if (brief)
+		{
+			wl_txpwr_array_row_print(ppr_target, ppr_wl->channel_bandwidth,
+				get_reg_rate_index_from_ratespec(ppr_wl->last_tx_ratespec));
+		}
+		else
+		{
+			wl_txpwr_array_print(ppr_board, ppr_wl->channel_bandwidth, verbose,
+				CHSPEC_IS5G(chanspec));
+			printf("\n");
+		}
+
+		printf("Power Targets:\n");
+		if (brief)
+		{
+			wl_txpwr_array_row_print(ppr_target, ppr_wl->channel_bandwidth,
+				get_reg_rate_index_from_ratespec(ppr_wl->last_tx_ratespec));
+		}
+		else
+		{
+			wl_txpwr_array_print(ppr_target, ppr_wl->channel_bandwidth, verbose,
+				CHSPEC_IS5G(chanspec));
+		}
+		printf("\n");
+
+		/* print the different power estimate combinations */
+		if (mimo) {
+			printf("Maximum Power Target among all rates:\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++)
+				printf("%2d.%02d  ",
+				       DIV_QUO(ppr_wl->tx_power_max[i], 4),
+				       DIV_REM(ppr_wl->tx_power_max[i], 4));
+			printf("\n");
+
+			printf("Last est. power                     :\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++)
+				printf("%2d.%02d  ",
+				       DIV_QUO(ppr_wl->est_Pout[i], 4),
+				       DIV_REM(ppr_wl->est_Pout[i], 4));
+			printf("\n");
+
+			printf("Power Target for the current rate   :\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++)
+			{
+				if (ppr_wl->target_offsets[i] != WL_RATE_DISABLED)
+				{
+					power_target = ppr_wl->tx_power_max[i] -
+						ppr_wl->target_offsets[i];
+					/*      for ACPHY, clip the power_target if it
+					        is larger than the SAR limit for the
+					        current path. For non-ACPHY or
+					        WLC_SARLIMIT disabled, this threshold is
+					        set to be MAX pwr, ie. 127
+					*/
+					if (power_target > ppr_wl->SARLIMIT[i])
+						power_target = ppr_wl->SARLIMIT[i];
+					printf("%2d.%02d  ",
+						DIV_QUO(power_target, 4),
+						DIV_REM(power_target, 4));
+				}
+				else
+				{
+					printf("-    ");
+				}
+			}
+			printf("\n");
+
+			printf("Last adjusted est. power            :\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++)
+				printf("%2d.%02d  ",
+				       DIV_QUO(ppr_wl->est_Pout[i], 4),
+				       DIV_REM(ppr_wl->est_Pout[i], 4));
+			printf("\n");
+		} else {
+			printf("Last est. power:\t%2d.%02d dBm\n",
+			       DIV_QUO(ppr_wl->est_Pout[0], 4),
+			       DIV_REM(ppr_wl->est_Pout[0], 4));
+		}
+
+		if (!mimo && CHSPEC_IS2G(chanspec)) {
+			printf("Last CCK est. power:\t%2d.%02d dBm\n",
+			       DIV_QUO(ppr_wl->est_Pout_cck, 4),
+			       DIV_REM(ppr_wl->est_Pout_cck, 4));
+		}
+exit:
+		if (ppr_board != NULL) {
+			ppr_delete(NULL, ppr_board);
+		}
+		if (ppr_target != NULL) {
+			ppr_delete(NULL, ppr_target);
+		}
+	}
+	free(ppr_wl);
+	return err;
+}
+
+static int wl_get_txpwr_target_max(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	txpwr_target_max_t target_pwr;
+	int i;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_iovar_get(wl, cmd->name, (void *)&target_pwr,  sizeof(target_pwr))) < 0) {
+		fprintf(stderr, "Error: txpwr_target failed. Make sure interface is up.\n");
+		return err;
+	}
+
+	if (target_pwr.version != TXPWR_TARGET_VERSION) {
+		fprintf(stderr, "Error: version [%d] mismatch Driver version:%d\n",
+			TXPWR_TARGET_VERSION, target_pwr.version);
+		return err;
+	}
+
+	printf("Maximum Tx Power Target (chanspec:0x%x):\t", target_pwr.chanspec);
+	for (i = 0; i < target_pwr.rf_cores; i++)
+		printf("%2d.%02d  ",
+		       DIV_QUO(target_pwr.txpwr[i], 4),
+		       DIV_REM(target_pwr.txpwr[i], 4));
+	printf("\n");
+
+	return err;
+}
+
+/*	print a single row of the power data.
+	convert data from dB to qdB;
+	decide if the pwr data is 20 or 40MHz data;
+	print "-" in the other channels
+ */
+static void
+wl_txpwr_print_row(const char *label, uint8 chains, int8 pwr20,
+	int8 pwr20in40, int8 pwr40, int8 pwr80, int8 pwr20in80, int8 pwr40in80,
+	int8 unsupported_rate, int8 channel_bandwidth, bool verbose)
+{
+	/* homebrew conversion to qdB, pseudo-floating point representation. */
+	int pwr20_q = DIV_QUO(pwr20, 4);
+	int pwr20_r = DIV_REM(pwr20, 4);
+
+	int pwr20in40_q = DIV_QUO(pwr20in40, 4);
+	int pwr20in40_r = DIV_REM(pwr20in40, 4);
+
+	int pwr40_q = DIV_QUO(pwr40, 4);
+	int pwr40_r = DIV_REM(pwr40, 4);
+
+	int pwr80_q = DIV_QUO(pwr80, 4);
+	int pwr80_r = DIV_REM(pwr80, 4);
+
+	int pwr20in80_q = DIV_QUO(pwr20in80, 4);
+	int pwr20in80_r = DIV_REM(pwr20in80, 4);
+
+	int pwr40in80_q = DIV_QUO(pwr40in80, 4);
+	int pwr40in80_r = DIV_REM(pwr40in80, 4);
+
+
+	char rate20[]     = "-    ";
+	char rate20in40[] = "-    ";
+	char rate40[]     = "-    ";
+	char rate80[]     = "-    ";
+	char rate20in80[] = "-    ";
+	char rate40in80[] = "-    ";
+	char pad[] = "  ";
+
+	if (pwr20 != unsupported_rate)
+		sprintf(rate20, "%2d.%-2d", pwr20_q, pwr20_r);
+	if (pwr20in40 != unsupported_rate)
+		sprintf(rate20in40, "%2d.%-2d", pwr20in40_q, pwr20in40_r);
+	if (pwr40 != unsupported_rate)
+		sprintf(rate40, "%2d.%-2d", pwr40_q, pwr40_r);
+	if (pwr80 != unsupported_rate)
+		sprintf(rate80, "%2d.%-2d", pwr80_q, pwr80_r);
+	if (pwr20in80 != unsupported_rate)
+		sprintf(rate20in80, "%2d.%-2d", pwr20in80_q, pwr20in80_r);
+	if (pwr40in80 != unsupported_rate)
+		sprintf(rate40in80, "%2d.%-2d", pwr40in80_q, pwr40in80_r);
+
+	printf("%-23s%d     ", label, chains);
+	if (!verbose) {
+		switch (channel_bandwidth) {
+		case WL_BW_20MHZ:
+			printf("%s\n", rate20);
+			break;
+		case WL_BW_40MHZ:
+			printf("%s%s%s\n", rate20in40, pad, rate40);
+			break;
+		case WL_BW_80MHZ:
+			printf("%s%s%s%s%s\n", rate20in80, pad, rate40in80, pad, rate80);
+			break;
+		}
+	} else {
+		printf("%s%s%s%s%s%s%s%s%s%s%s\n", rate20, pad, rate20in40, pad,
+			rate40, pad, rate20in80, pad, rate40in80, pad, rate80);
+	}
+
+}
+
+static void
+wl_txpwr_array_row_print(ppr_t *pprptr, int8 channel_bandwidth,	reg_rate_index_t rate_index)
+{
+	const char *label;
+	int8 pwr20     = WL_RATE_DISABLED;
+	int8 pwr20in40 = WL_RATE_DISABLED;
+	int8 pwr40     = WL_RATE_DISABLED;
+	int8 pwr80     = WL_RATE_DISABLED;
+	int8 pwr20in80 = WL_RATE_DISABLED;
+	int8 pwr40in80 = WL_RATE_DISABLED;
+
+	if (rate_index == NO_RATE)
+	{
+		printf("(NO_RATE)               -     -      -      -      -      -      -\n");
+	}
+	else
+	{
+		clm_rate_group_id_t group_id = ppr_table[rate_index].id;
+		label = ppr_table[rate_index].label;
+
+		switch (channel_bandwidth) {
+		case WL_BW_20MHZ:
+			pwr20     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20);
+			break;
+
+		case WL_BW_40MHZ:
+			pwr20in40 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20IN40);
+			pwr40     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_40);
+			break;
+
+		case WL_BW_80MHZ:
+			pwr80     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_80);
+			pwr20in80 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20IN80);
+			pwr40in80 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_40IN80);
+			break;
+		}
+
+		wl_txpwr_print_row(label, ppr_group_table[group_id].chain,
+			pwr20, pwr20in40, pwr40, pwr80, pwr20in80, pwr40in80,
+			WL_RATE_DISABLED, channel_bandwidth, TRUE);
+	}
+}
+
+static void
+wl_txpwr_print_header(int8 channel_bandwidth, bool verbose)
+{
+	printf("Rate                  Chains ");
+	if (!verbose)
+	{
+		switch (channel_bandwidth) {
+		case WL_BW_20MHZ:
+			printf("20MHz\n");
+			break;
+		case WL_BW_40MHZ:
+			printf("20in40 40MHz\n");
+			break;
+		case WL_BW_80MHZ:
+			printf("20in80 40in80 80MHz\n");
+			break;
+		}
+	} else {
+		printf("20MHz  20in40 40MHz  20in80 40in80 80MHz\n");
+	}
+}
+
+static void
+wl_txpwr_array_print(ppr_t* pprptr, int8 bw, bool verbose, bool is5G)
+{
+	clm_rate_group_id_t i;
+	reg_rate_index_t rate_index = DSSS1;
+	wl_txpwr_print_header(bw, verbose);
+	for (i = RATE_GROUP_ID_DSSS; i < RATE_GROUP_ID_COUNT; i++) {
+		wl_txpwr_ppr_print(pprptr, verbose, ppr_group_table[i].rate_type, i, bw,
+			&rate_index, is5G);
+		/* VHT rates are printed in two parts: MCS + VHT8,9 */
+		if (ppr_group_table[i].rate_type == PPR_RATE_VHT)
+			i++;
+	}
+}
+
+/* print power value for each group of rates, if not in verbose mode and rates
+ * are uniform, one power value is printed out for the whole group
+ */
+static void
+wl_txpwr_ppr_print(ppr_t* pprptr, int vb, ppr_rate_type_t type,
+	clm_rate_group_id_t gid, int8 bw, reg_rate_index_t *rate_index, bool is5G)
+{
+	uint i;
+	const char *label;
+	int  buniform  = FALSE;
+	int8 pwr20     = WL_RATE_DISABLED;
+	int8 pwr20in40 = WL_RATE_DISABLED;
+	int8 pwr40     = WL_RATE_DISABLED;
+	int8 pwr80     = WL_RATE_DISABLED;
+	int8 pwr20in80 = WL_RATE_DISABLED;
+	int8 pwr40in80 = WL_RATE_DISABLED;
+	uint len       = 0;
+	if (pprptr == NULL) {
+		fprintf(stderr, "illegal ppr data!\n");
+		return;
+	}
+
+	switch (type) {
+	case PPR_RATE_DSSS:
+		{
+			int tx_pwr_min = WL_RATE_DISABLED;
+			if (is5G) {
+				tx_pwr_min = ppr_get_min(pprptr, WL_RATE_DISABLED);
+			}
+			len = sizeof(ppr_dsss_rateset_t);
+			if (bw == WL_BW_20MHZ) {
+				ppr_dsss_rateset_t rate;
+				ppr_get_dsss(pprptr, WL_TX_BW_20, ppr_group_table[gid].chain,
+					&rate);
+				if (is5G) {
+					uint idx;
+					for (idx = 0; idx < sizeof(rate); idx++) {
+						if (rate.pwr[idx] == tx_pwr_min)
+							rate.pwr[idx] = WL_RATE_DISABLED;
+					}
+				}
+				buniform = wl_array_check_val(rate.pwr,
+					sizeof(rate), rate.pwr[0]) && !vb;
+				if (buniform) {
+					pwr20 = rate.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20 = rate.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_40MHZ) {
+				ppr_dsss_rateset_t rate20in40;
+				ppr_dsss_rateset_t rate40;
+
+				ppr_get_dsss(pprptr, WL_TX_BW_20IN40, ppr_group_table[gid].chain,
+					&rate20in40);
+				ppr_get_dsss(pprptr, WL_TX_BW_40, ppr_group_table[gid].chain,
+					&rate40);
+				if (is5G) {
+					uint idx;
+					for (idx = 0; idx < sizeof(ppr_dsss_rateset_t); idx++) {
+						if (rate20in40.pwr[idx] == tx_pwr_min)
+							rate20in40.pwr[idx] = WL_RATE_DISABLED;
+						if (rate40.pwr[idx] == tx_pwr_min)
+							rate40.pwr[idx] = WL_RATE_DISABLED;
+					}
+				}
+				buniform = wl_array_check_val(rate40.pwr,
+					sizeof(ppr_dsss_rateset_t), rate40.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in40.pwr,
+					sizeof(ppr_dsss_rateset_t), rate20in40.pwr[0]);
+				if (buniform) {
+					pwr20in40 = rate20in40.pwr[0];
+					pwr40     = rate40.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20in40 = rate20in40.pwr[i];
+						pwr40     = rate40.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_80MHZ) {
+				ppr_dsss_rateset_t rate20in80;
+				ppr_dsss_rateset_t rate40in80;
+				ppr_dsss_rateset_t rate80;
+				ppr_get_dsss(pprptr, WL_TX_BW_20IN80, ppr_group_table[gid].chain,
+					&rate20in80);
+				ppr_get_dsss(pprptr, WL_TX_BW_40IN80, ppr_group_table[gid].chain,
+					&rate40in80);
+				ppr_get_dsss(pprptr, WL_TX_BW_80, ppr_group_table[gid].chain,
+					&rate80);
+				if (is5G) {
+					uint idx;
+					for (idx = 0; idx < sizeof(ppr_dsss_rateset_t); idx++) {
+						if (rate20in80.pwr[idx] == tx_pwr_min)
+							rate20in80.pwr[idx] = WL_RATE_DISABLED;
+						if (rate40in80.pwr[idx] == tx_pwr_min)
+							rate40in80.pwr[idx] = WL_RATE_DISABLED;
+						if (rate80.pwr[idx] == tx_pwr_min)
+							rate80.pwr[idx] = WL_RATE_DISABLED;
+					}
+				}
+				buniform = wl_array_check_val(rate80.pwr,
+					sizeof(ppr_dsss_rateset_t), rate80.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in80.pwr,
+					sizeof(ppr_dsss_rateset_t), rate20in80.pwr[0]) &&
+					wl_array_check_val(rate40in80.pwr,
+					sizeof(ppr_dsss_rateset_t), rate40in80.pwr[0]);
+				if (buniform) {
+					pwr20in80 = rate20in80.pwr[0];
+					pwr40in80 = rate40in80.pwr[0];
+					pwr80     = rate80.pwr[0];
+					label     = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20in80 = rate20in80.pwr[i];
+						pwr40in80 = rate40in80.pwr[i];
+						pwr80     = rate80.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			}
+			*rate_index += len;
+		}
+		break;
+	case PPR_RATE_OFDM:
+		{
+			len = sizeof(ppr_ofdm_rateset_t);
+			if (bw == WL_BW_20MHZ) {
+				ppr_ofdm_rateset_t rate;
+				ppr_get_ofdm(pprptr, WL_TX_BW_20, ppr_group_table[gid].mode,
+					ppr_group_table[gid].chain, &rate);
+				buniform = wl_array_check_val(rate.pwr,
+					sizeof(rate), rate.pwr[0]) && !vb;
+				if (buniform) {
+					pwr20 = rate.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20 = rate.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_40MHZ) {
+				ppr_ofdm_rateset_t rate20in40;
+				ppr_ofdm_rateset_t rate40;
+
+				ppr_get_ofdm(pprptr, WL_TX_BW_20IN40, ppr_group_table[gid].mode,
+					ppr_group_table[gid].chain, &rate20in40);
+				ppr_get_ofdm(pprptr, WL_TX_BW_40, ppr_group_table[gid].mode,
+					ppr_group_table[gid].chain, &rate40);
+				buniform = wl_array_check_val(rate40.pwr,
+					sizeof(ppr_ofdm_rateset_t), rate40.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in40.pwr,
+					sizeof(ppr_ofdm_rateset_t), rate20in40.pwr[0]);
+				if (buniform) {
+					pwr20in40 = rate20in40.pwr[0];
+					pwr40     = rate40.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20in40 = rate20in40.pwr[i];
+						pwr40     = rate40.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_80MHZ) {
+				ppr_ofdm_rateset_t rate20in80;
+				ppr_ofdm_rateset_t rate40in80;
+				ppr_ofdm_rateset_t rate80;
+				ppr_get_ofdm(pprptr, WL_TX_BW_20IN80, ppr_group_table[gid].mode,
+					ppr_group_table[gid].chain, &rate20in80);
+				ppr_get_ofdm(pprptr, WL_TX_BW_40IN80, ppr_group_table[gid].mode,
+					ppr_group_table[gid].chain, &rate40in80);
+				ppr_get_ofdm(pprptr, WL_TX_BW_80, ppr_group_table[gid].mode,
+					ppr_group_table[gid].chain, &rate80);
+				buniform = wl_array_check_val(rate80.pwr,
+					sizeof(ppr_ofdm_rateset_t), rate80.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in80.pwr,
+					sizeof(ppr_ofdm_rateset_t), rate20in80.pwr[0]) &&
+					wl_array_check_val(rate40in80.pwr,
+					sizeof(ppr_ofdm_rateset_t), rate40in80.pwr[0]);
+				if (buniform) {
+					pwr20in80 = rate20in80.pwr[0];
+					pwr40in80 = rate40in80.pwr[0];
+					pwr80     = rate80.pwr[0];
+					label     = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20in80 = rate20in80.pwr[i];
+						pwr40in80 = rate40in80.pwr[i];
+						pwr80     = rate80.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			}
+			*rate_index += len;
+		}
+		break;
+	case PPR_RATE_HT:
+		{
+			len = sizeof(ppr_ht_mcs_rateset_t);
+			if (bw == WL_BW_20MHZ) {
+				ppr_ht_mcs_rateset_t rate;
+				ppr_get_ht_mcs(pprptr, WL_TX_BW_20, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate);
+				buniform = wl_array_check_val(rate.pwr,
+					sizeof(rate), rate.pwr[0]) && !vb;
+				if (buniform) {
+					pwr20 = rate.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20 = rate.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_40MHZ) {
+				ppr_ht_mcs_rateset_t rate20in40;
+				ppr_ht_mcs_rateset_t rate40;
+
+				ppr_get_ht_mcs(pprptr, WL_TX_BW_20IN40, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate20in40);
+				ppr_get_ht_mcs(pprptr, WL_TX_BW_40, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate40);
+				buniform = wl_array_check_val(rate40.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate40.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in40.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate20in40.pwr[0]);
+				if (buniform) {
+					pwr20in40 = rate20in40.pwr[0];
+					pwr40     = rate40.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20in40 = rate20in40.pwr[i];
+						pwr40     = rate40.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_80MHZ) {
+				ppr_ht_mcs_rateset_t rate20in80;
+				ppr_ht_mcs_rateset_t rate40in80;
+				ppr_ht_mcs_rateset_t rate80;
+				ppr_get_ht_mcs(pprptr, WL_TX_BW_20IN80, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate20in80);
+				ppr_get_ht_mcs(pprptr, WL_TX_BW_40IN80, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate40in80);
+				ppr_get_ht_mcs(pprptr, WL_TX_BW_80, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate80);
+				buniform = wl_array_check_val(rate80.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate80.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in80.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate20in80.pwr[0]) &&
+					wl_array_check_val(rate40in80.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate40in80.pwr[0]);
+				if (buniform) {
+					pwr20in80 = rate20in80.pwr[0];
+					pwr40in80 = rate40in80.pwr[0];
+					pwr80     = rate80.pwr[0];
+					label     = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < len; i++) {
+						pwr20in80 = rate20in80.pwr[i];
+						pwr40in80 = rate40in80.pwr[i];
+						pwr80     = rate80.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			}
+			*rate_index += len;
+		}
+		break;
+	case PPR_RATE_VHT:
+		{
+			uint bvhtuniform = FALSE;
+			uint lenht = sizeof(ppr_ht_mcs_rateset_t);
+			len = sizeof(ppr_vht_mcs_rateset_t);
+			/* VHT RATES are printed as two parts: MCS0-7 and VTH8-9 */
+			if (bw == WL_BW_20MHZ) {
+				ppr_vht_mcs_rateset_t rate;
+				ppr_get_vht_mcs(pprptr, WL_TX_BW_20, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate);
+				buniform = wl_array_check_val(rate.pwr, lenht, rate.pwr[0])&& !vb;
+				bvhtuniform = wl_array_check_val(&rate.pwr[lenht], len-lenht,
+					rate.pwr[lenht]) && !vb;
+				if (buniform) {
+					pwr20 = rate.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < lenht; i++) {
+						pwr20 = rate.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+				if (bvhtuniform) {
+					pwr20 = rate.pwr[lenht];
+					/* print VHT8-9 label */
+					label = get_clm_rate_group_label(gid+1);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+				} else {
+					for (i = lenht; i < len; i++) {
+						pwr20 = rate.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_40MHZ) {
+				ppr_vht_mcs_rateset_t rate20in40;
+				ppr_vht_mcs_rateset_t rate40;
+
+				ppr_get_vht_mcs(pprptr, WL_TX_BW_20IN40, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate20in40);
+				ppr_get_vht_mcs(pprptr, WL_TX_BW_40, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate40);
+
+				buniform = wl_array_check_val(rate40.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate40.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in40.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate20in40.pwr[0]);
+				bvhtuniform = wl_array_check_val(&rate40.pwr[lenht], len-lenht,
+					rate40.pwr[lenht]) && !vb &&
+					wl_array_check_val(&rate20in40.pwr[lenht], len-lenht,
+					rate20in40.pwr[lenht]);
+				if (buniform) {
+					pwr20in40 = rate20in40.pwr[0];
+					pwr40     = rate40.pwr[0];
+					label = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < lenht; i++) {
+						pwr20in40 = rate20in40.pwr[i];
+						pwr40     = rate40.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+				if (bvhtuniform) {
+					pwr20in40 = rate20in40.pwr[lenht];
+					pwr40     = rate40.pwr[lenht];
+					/* print VHT8-9 label */
+					label = get_clm_rate_group_label(gid+1);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+				} else {
+					for (i = lenht; i < len; i++) {
+						pwr20in40 = rate20in40.pwr[i];
+						pwr40     = rate40.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			} else if (bw == WL_BW_80MHZ) {
+				ppr_vht_mcs_rateset_t rate20in80;
+				ppr_vht_mcs_rateset_t rate40in80;
+				ppr_vht_mcs_rateset_t rate80;
+				ppr_get_vht_mcs(pprptr, WL_TX_BW_20IN80, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate20in80);
+				ppr_get_vht_mcs(pprptr, WL_TX_BW_40IN80, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate40in80);
+				ppr_get_vht_mcs(pprptr, WL_TX_BW_80, ppr_group_table[gid].nss,
+					ppr_group_table[gid].mode, ppr_group_table[gid].chain,
+					&rate80);
+				buniform = wl_array_check_val(rate80.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate80.pwr[0]) && !vb &&
+					wl_array_check_val(rate20in80.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate20in80.pwr[0]) &&
+					wl_array_check_val(rate40in80.pwr,
+					sizeof(ppr_ht_mcs_rateset_t), rate40in80.pwr[0]);
+				bvhtuniform = wl_array_check_val(&rate80.pwr[lenht], len-lenht,
+					rate80.pwr[lenht]) && !vb &&
+					wl_array_check_val(&rate20in80.pwr[lenht], len-lenht,
+					rate20in80.pwr[lenht]) &&
+					wl_array_check_val(&rate40in80.pwr[lenht], len-lenht,
+					rate40in80.pwr[lenht]);
+
+				if (buniform) {
+					pwr20in80 = rate20in80.pwr[0];
+					pwr40in80 = rate40in80.pwr[0];
+					pwr80     = rate80.pwr[0];
+					label     = get_clm_rate_group_label(gid);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+
+				} else {
+					for (i = 0; i < lenht; i++) {
+						pwr20in80 = rate20in80.pwr[i];
+						pwr40in80 = rate40in80.pwr[i];
+						pwr80     = rate80.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+				if (bvhtuniform) {
+					pwr20in80 = rate20in80.pwr[lenht];
+					pwr40in80 = rate40in80.pwr[lenht];
+					pwr80     = rate80.pwr[lenht];
+					/* print VHT8-9 label */
+					label = get_clm_rate_group_label(gid+1);
+					wl_txpwr_print_row(label, ppr_group_table[gid].chain,
+						pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+						pwr40in80, WL_RATE_DISABLED, bw, vb);
+				} else {
+					for (i = lenht; i < len; i++) {
+						pwr20in80 = rate20in80.pwr[i];
+						pwr40in80 = rate40in80.pwr[i];
+						pwr80     = rate80.pwr[i];
+						label = ppr_table[*rate_index+i].label;
+						wl_txpwr_print_row(label,
+							ppr_group_table[gid].chain,
+							pwr20, pwr20in40, pwr40, pwr80, pwr20in80,
+							pwr40in80, WL_RATE_DISABLED,
+							bw, vb);
+					}
+				}
+			}
+			*rate_index += len;
+		}
+		break;
+	}
+}
+
+/* helper function to check if the array are uniformly same as the input value */
+static int wl_array_check_val(int8 *pwr, uint count, int8 val)
+{
+	uint i;
+	for (i = 0; i < count; i++) {
+		if (pwr[i] != val)
+			return FALSE;
+	}
+	return TRUE;
+}
+
+static void
+wl_txpwr_regulatory_array_row_print(int8 *powers, int8 *powers_subchan1,
+	int8 *powers_subchan2, int8 channel_bandwidth,  reg_rate_index_t rate_index)
+{
+	const int RATE_UNSUPPORTED = -128; /* CLM uses -128 as the unsupported rate */
+	const char* label;
+	uint8 chains;
+	int pwr20 = RATE_UNSUPPORTED;
+	int pwr20in40 = RATE_UNSUPPORTED;
+	int pwr40 = RATE_UNSUPPORTED;
+	int pwr80 = RATE_UNSUPPORTED;
+	int pwr20in80 = RATE_UNSUPPORTED;
+	int pwr40in80 = RATE_UNSUPPORTED;
+
+	wl_txpwr_print_header(channel_bandwidth, TRUE);
+
+	if (rate_index == NO_RATE)
+	{
+		printf("(NO_RATE)               -     -      -      -      -      -      -\n");
+	}
+	else
+	{
+		label = ppr_table[rate_index].label;
+		chains = ppr_group_table[ppr_table[rate_index].id].chain;
+
+		switch (channel_bandwidth) {
+		case WL_BW_20MHZ:
+			pwr20 = powers[ppr_table[rate_index].rate];
+			break;
+		case WL_BW_40MHZ:
+			pwr40 = powers[ppr_table[rate_index].rate];
+			pwr20in40 = powers_subchan1[ppr_table[rate_index].rate];
+			break;
+		case WL_BW_80MHZ:
+			pwr80 = powers[ppr_table[rate_index].rate];
+			pwr40in80 = powers_subchan1[ppr_table[rate_index].rate];
+			pwr20in80 = powers_subchan2[ppr_table[rate_index].rate];
+			break;
+		}
+		wl_txpwr_print_row(label, chains, pwr20, pwr20in40,
+			pwr40, pwr80, pwr20in80, pwr40in80, RATE_UNSUPPORTED,
+			channel_bandwidth, TRUE);
+	}
+}
+
+/* Essentially the same as wl_txpwr_array_print, but the
+ * format of the regulatory data is now diffreent enough that we need a separate function.
+ * The data format should be unified, and this code removed.
+ */
+static void
+wl_txpwr_regulatory_array_print(int8 *powers, int8 *powers_subchan1,
+	int8 *powers_subchan2, int8 channel_bandwidth, bool verbose)
+{
+	int i, j;
+	const int RATE_UNSUPPORTED = -128; /* CLM uses -128 as the unsupported rate */
+	const char* label;
+
+	/* This code assumes that all of the rates in a group will be contiguous */
+	wl_txpwr_print_header(channel_bandwidth, verbose);
+	for (i = 0; i < RATE_GROUP_ID_COUNT; i++) {
+		int first_rate = 0;
+		int num_rates = 0;
+		uint8 chains;
+		bool compress_rate = FALSE;
+		int pwr20 = RATE_UNSUPPORTED;
+		int pwr20in40 = RATE_UNSUPPORTED;
+		int pwr40 = RATE_UNSUPPORTED;
+		int pwr80 = RATE_UNSUPPORTED;
+		int pwr20in80 = RATE_UNSUPPORTED;
+		int pwr40in80 = RATE_UNSUPPORTED;
+
+		/* find the first rate index in this group. */
+		while ((int)ppr_table[first_rate].id != i)
+			first_rate++;
+		/* how many rates in that group? */
+		while ((first_rate + num_rates < WL_NUMRATES) &&
+			((int)ppr_table[first_rate + num_rates].id == i))
+			num_rates++;
+
+		/* are the regulatory power settings the same? */
+		switch (channel_bandwidth) {
+		case WL_BW_20MHZ:
+			compress_rate = !verbose &&
+				wl_array_uniform((uint8*)&powers[ppr_table[first_rate].rate], 0,
+				num_rates);
+			break;
+		case WL_BW_40MHZ:
+			compress_rate = !verbose &&
+				wl_array_uniform((uint8*)&powers[ppr_table[first_rate].rate], 0,
+				num_rates) &&
+				wl_array_uniform((uint8*)&powers_subchan1[ppr_table
+				[first_rate].rate], 0, num_rates);
+			break;
+		case WL_BW_80MHZ:
+			compress_rate = !verbose &&
+				wl_array_uniform((uint8*)&powers[ppr_table[first_rate].rate], 0,
+				num_rates) &&
+				wl_array_uniform((uint8*)&powers_subchan1[ppr_table
+				[first_rate].rate], 0, num_rates) &&
+				wl_array_uniform((uint8*)&powers_subchan2[ppr_table
+				[first_rate].rate], 0, num_rates);
+			break;
+		}
+
+		if (compress_rate)
+			j = num_rates - 1;
+		else
+			j = 0;
+
+		for (; j < num_rates; j++) {
+			if (compress_rate)
+				label = get_clm_rate_group_label(i);
+			else
+				label = ppr_table[first_rate + j].label;
+
+			chains = ppr_group_table[ppr_table[first_rate + j].id].chain;
+
+			switch (channel_bandwidth) {
+			case WL_BW_20MHZ:
+				pwr20 = powers[ppr_table[first_rate + j].rate];
+				break;
+			case WL_BW_40MHZ:
+				pwr40 = powers[ppr_table[first_rate + j].rate];
+				pwr20in40 = powers_subchan1[ppr_table[first_rate + j].rate];
+				break;
+			case WL_BW_80MHZ:
+				pwr80 = powers[ppr_table[first_rate + j].rate];
+				pwr40in80 = powers_subchan1[ppr_table[first_rate + j].rate];
+				pwr20in80 = powers_subchan2[ppr_table[first_rate + j].rate];
+				break;
+			}
+			wl_txpwr_print_row(label, chains, pwr20, pwr20in40,
+				pwr40, pwr80, pwr20in80, pwr40in80, RATE_UNSUPPORTED,
+				channel_bandwidth, verbose);
+		}
+	}
+}
+/* return TRUE if all the values in the array are uniformly the same */
+static int
+wl_array_uniform(uint8 *pwr, int start, int count)
+{
+	int i, rate;
+
+	for (i = 1, rate = start + 1; i < count; i++, rate++)
+		if (pwr[rate] != pwr[rate - 1])
+			return FALSE;
+
+	return TRUE;
+}
+
+static int
+wl_get_instant_power(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	tx_inst_power_t *power;
+	uint band_list[3];
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	strcpy(buf, "txinstpwr");
+	if ((ret = wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN)) < 0) {
+		return ret;
+	}
+
+	power = (tx_inst_power_t *)buf;
+	/* Make the most of the info returned in band_list!
+	 * b/g and a
+	 * b/g-uni
+	 * a-uni
+	 * NOTE: NO a and b/g case ...
+	 */
+	if ((ret = wlu_get(wl, WLC_GET_BANDLIST, band_list, sizeof(band_list))) < 0)
+		return (ret);
+	band_list[0] = dtoh32(band_list[0]);
+	band_list[1] = dtoh32(band_list[1]);
+	band_list[2] = dtoh32(band_list[2]);
+
+	/* If B/G is present it's always the lower index */
+	if (band_list[1] == WLC_BAND_2G) {
+			printf("Last B phy CCK est. power:\t%2d.%d dBm\n",
+			       DIV_QUO(power->txpwr_est_Pout[0], 4),
+			       DIV_REM(power->txpwr_est_Pout[0], 4));
+			printf("Last B phy OFDM est. power:\t%2d.%d dBm\n",
+			       DIV_QUO(power->txpwr_est_Pout_gofdm, 4),
+			       DIV_REM(power->txpwr_est_Pout_gofdm, 4));
+
+			printf("\n");
+	}
+
+	/* A band */
+	if (band_list[1] == WLC_BAND_5G || (band_list[0] > 1 && band_list[2] == WLC_BAND_5G)) {
+		printf("Last A phy est. power:\t\t%2d.%d dBm\n",
+		       DIV_QUO(power->txpwr_est_Pout[1], 4),
+		       DIV_REM(power->txpwr_est_Pout[1], 4));
+	}
+
+	return ret;
+}
+
+static int
+wl_evm(void *wl, cmd_t *cmd, char **argv)
+{
+	int val[3];
+
+	/* Get channel */
+	if (!*++argv) {
+		fprintf(stderr, "Need to specify at least one parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!stricmp(*argv, "off"))
+		val[0] = 0;
+	else
+		val[0] = atoi(*argv);
+
+	/* set optional parameters to default */
+	val[1] = 4;	/* rate in 500Kb units */
+	val[2] = 0;	/* This is ignored */
+
+	/* Get optional rate and convert to 500Kb units */
+	if (*++argv)
+		val[1] = rate_string2int(*argv);
+
+	val[0] = htod32(val[0]);
+	val[1] = htod32(val[1]);
+	val[2] = htod32(val[2]);
+	return wlu_set(wl, cmd->set, val, sizeof(val));
+}
+
+#define WL_JOIN_PARAMS_MAX WL_JOIN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(chanspec_t)
+
+/* when prescanned option is specified */
+static int
+wl_join_prescanned(void *wl, wl_join_params_t *join_params, uint *join_params_size)
+{
+	/* load with prescanned channels and bssids */
+	int ret, err = 0;
+	char *destbuf;
+	wl_scan_results_t *scanres = NULL;
+	wl_bss_info_t *bi;
+	uint i, cnt, bssid_cnt, bi_len;
+
+	if ((destbuf = malloc(WL_DUMP_BUF_LEN)) == NULL) {
+		fprintf(stderr, "Failed to allocate %d-byte buffer for scanresults\n",
+			WL_DUMP_BUF_LEN);
+		err = BCME_NOMEM;
+		goto pexit;
+	}
+
+	if ((ret = wl_get_scan(wl, WLC_SCAN_RESULTS, destbuf, WL_DUMP_BUF_LEN)) != 0) {
+		fprintf(stderr, "failed to fetch scan results, err %d\n", ret);
+		err = ret;
+		goto pexit;
+	}
+
+	scanres = (wl_scan_results_t *)destbuf;
+	if (scanres->version != WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "scan parsing failed (expect version %d, got %d)\n",
+			WL_BSS_INFO_VERSION, scanres->version);
+		err = -1;
+		goto pexit;
+	}
+
+	/* find matching ssids to fill the channel list */
+	for (cnt = i = 0, bi = scanres->bss_info; i < scanres->count;
+		 i++, bi = (wl_bss_info_t*)((int8*)bi + bi_len)) {
+		bi_len = dtoh32(bi->length);
+		if ((bi->SSID_len != join_params->ssid.SSID_len) ||
+			memcmp(bi->SSID, join_params->ssid.SSID,
+			join_params->ssid.SSID_len)) {
+			continue;
+		} else {
+			dump_bss_info(bi);
+			printf("--------------------------------\n");
+		}
+
+		memcpy(&join_params->params.chanspec_list[cnt],
+			&bi->chanspec, sizeof(chanspec_t));
+		cnt++;
+	}
+	bssid_cnt = (uint16)cnt;
+
+	/* append the corresponding bssids */
+	destbuf = (char*)&join_params->params.chanspec_list[cnt];
+	*join_params_size = destbuf - (char*)join_params;
+	*join_params_size += (cnt * sizeof(struct ether_addr));
+
+	if (*join_params_size > WL_JOIN_PARAMS_MAX) {
+		fprintf(stderr, "Can't fit bssids for all %d APs found\n", cnt);
+		err = -1;
+		goto pexit;
+	}
+
+	for (cnt = i = 0, bi = scanres->bss_info;
+		 (i < scanres->count) && (cnt < bssid_cnt);
+		 i++, bi = (wl_bss_info_t*)((int8*)bi + bi_len)) {
+		bi_len = dtoh32(bi->length);
+		if ((bi->SSID_len != join_params->ssid.SSID_len) ||
+			memcmp(bi->SSID, join_params->ssid.SSID,
+			join_params->ssid.SSID_len)) {
+			continue;
+		}
+
+		memcpy(destbuf, &bi->BSSID, sizeof(struct ether_addr));
+		destbuf += sizeof(struct ether_addr);
+		cnt++;
+	}
+
+	if (cnt != bssid_cnt) {
+		fprintf(stderr, "Mismatched channel and bssid counts!\n");
+		err = -1;
+		goto pexit;
+	}
+
+	if (cnt == 0) {
+		printf("No matches found, issuing normal join.\n");
+	} else {
+		printf("Passing %d channel/bssid pairs.\n", cnt);
+	}
+	join_params->params.bssid_cnt = htod16(bssid_cnt);
+
+pexit:
+	if (scanres)
+		free((char*)scanres);
+	else
+		free(destbuf);
+	return err;
+}
+
+/* wl join <ssid> [key <0-3>:xxxxx]
+ *                [imode bss|ibss]
+ *                [amode open|shared|openshared|wpa|wpapsk|wpa2|wpa2psk|wpanone|ftpsk]
+ *                [options]
+ * Options:
+ * -b MAC, --bssid=MAC, where MAC is in xx:xx:xx:xx:xx:xx format
+ * -c CL, --chanspecs=CL, where CL is a comma or space separated list of chanspecs
+ * -p, -passive: uses  join iovar instead of SET_SSID ioctl to force passive assoc scan
+ */
+
+static int
+wl_join(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK, idx = 0;
+	wl_join_params_t *join_params;
+	uint join_params_size;
+	wl_wsec_key_t key;
+	int wsec = 0, auth = 0, infra = 1;
+	int wpa_auth = WPA_AUTH_DISABLED;
+	char* cmd_name;
+	bool prescanned = FALSE;
+	int passive = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	cmd_name = *argv++;
+
+	/* allocate the max storage */
+	join_params_size = WL_JOIN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(chanspec_t);
+	if ((join_params = malloc(join_params_size)) == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for assoc params\n", join_params_size);
+		return BCME_NOMEM;
+	}
+	memset(join_params, 0, join_params_size);
+	memcpy(&join_params->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+	/* verify that SSID was specified and is a valid length */
+	if (!*argv || (strlen(*argv) > DOT11_MAX_SSID_LEN)) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	join_params->ssid.SSID_len = strlen(*argv);
+	memcpy(join_params->ssid.SSID, *argv, join_params->ssid.SSID_len);
+	/* default to plain old ioctl */
+	join_params_size = sizeof(wlc_ssid_t);
+	/* get current wsec */
+	if (wlu_iovar_getint(wl, "wsec", &wsec) < 0)
+		wsec = 0;
+
+	while (*++argv) {
+		if (!stricmp(*argv, "wepkey") || !stricmp(*argv, "wep") || !stricmp(*argv, "key")) {
+			/* specified wep key */
+			memset(&key, 0, sizeof(key));
+			if (!*++argv) {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			/* WEP index specified */
+			if (*(argv[0]+1) == ':') {
+				idx = *argv[0] - 0x30;
+				if (idx < 0 || idx > 3) {
+					fprintf(stderr, "Invalid key index %d specified\n", idx);
+					ret = BCME_BADARG;
+					goto exit;
+				}
+				argv[0] += 2; /* colon + digit */
+			}
+			key.index = idx;
+
+			if (parse_wep(argv, &key, FALSE)) {
+				ret = BCME_BADARG;
+				goto exit;
+			}
+
+			key.index = htod32(key.index);
+			key.len = htod32(key.len);
+			key.algo = htod32(key.algo);
+			key.flags = htod32(key.flags);
+
+			if ((ret = wlu_set(wl, WLC_SET_KEY, &key, sizeof(wl_wsec_key_t))) < 0) {
+				goto exit;
+			}
+			wsec |= WEP_ENABLED;
+		}
+		/* specified infrastructure mode */
+		else if (!stricmp(*argv, "imode") ||
+		         !stricmp(*argv, "infra") ||
+		         !stricmp(*argv, "mode")) {
+			if (!*++argv) {
+				fprintf(stderr, "%s %s: expected argument after \"infra\" keyword "
+				        "but command line ended.\n", wlu_av0, cmd_name);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			} else if (!stricmp(*argv, "ibss") ||
+			           !stricmp(*argv, "adhoc") ||
+			           !stricmp(*argv, "ad-hoc")) {
+				infra = 0;
+			} else if (!stricmp(*argv, "bss") ||
+			           !stricmp(*argv, "managed") ||
+			           !strnicmp(*argv, "infra", 5)) {
+				infra = 1;
+			} else {
+				fprintf(stderr, "%s %s: unrecongnized parameter \"%s\" after "
+				        "\"infra\" keyword\n", wlu_av0, cmd_name, *argv);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		/* specified authentication mode */
+		else if (!stricmp(*argv, "amode") || !strnicmp(*argv, "auth", 4)) {
+			if (!*++argv) {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			if (!stricmp(*argv, "open"))
+				auth = WL_AUTH_OPEN_SYSTEM;
+			else if (!stricmp(*argv, "shared"))
+				auth = WL_AUTH_SHARED_KEY;
+			else if (!stricmp(*argv, "openshared"))
+				auth = WL_AUTH_OPEN_SHARED;
+#ifdef	BCMCCX
+			else if (!stricmp(*argv, "cckm"))
+				wpa_auth = WPA_AUTH_CCKM;
+			else if (!stricmp(*argv, "cckmwpa2"))
+				wpa_auth = WPA2_AUTH_CCKM;
+#endif	/* BCMCCX */
+			else if (!stricmp(*argv, "wpanone"))
+				wpa_auth = WPA_AUTH_NONE;
+			else if (!stricmp(*argv, "wpa"))
+				wpa_auth = WPA_AUTH_UNSPECIFIED;
+			else if (!stricmp(*argv, "wpapsk"))
+				 wpa_auth = WPA_AUTH_PSK;
+			else if (!stricmp(*argv, "wpa2"))
+				wpa_auth = WPA2_AUTH_UNSPECIFIED;
+			else if (!stricmp(*argv, "wpa2psk"))
+				wpa_auth = WPA2_AUTH_PSK;
+#ifdef BCMWAPI_WAI
+			else if (!stricmp(*argv, "wapi"))
+				wpa_auth = WAPI_AUTH_UNSPECIFIED;
+			else if (!stricmp(*argv, "wapipsk"))
+				wpa_auth = WAPI_AUTH_PSK;
+#endif /* BCMWAPI_WAI */
+			else if (!stricmp(*argv, "ftpsk"))
+				wpa_auth = WPA2_AUTH_PSK | WPA2_AUTH_FT;
+			else {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!stricmp(*argv, "-passive") || !stricmp(*argv, "-p")) {
+			/* Use extended join iovar to assoc_scan passively */
+			passive = 1;
+		}
+		/* optional assoc params */
+		else if ((ret = wl_parse_assoc_params(argv, &join_params->params, &prescanned)) ==
+			BCME_OK) {
+			join_params_size = WL_JOIN_PARAMS_FIXED_SIZE +
+				dtoh32(join_params->params.chanspec_num) * sizeof(chanspec_t);
+			break;
+		}
+		else {
+			fprintf(stderr, "%s %s: unable to parse parameter \"%s\"\n",
+				wlu_av0, cmd_name, *argv);
+			goto exit;
+		}
+	}
+
+	/* set infrastructure mode */
+	infra = htod32(infra);
+	if ((ret = wlu_set(wl, WLC_SET_INFRA, &infra, sizeof(int))) < 0)
+		goto exit;
+
+	/* set authentication mode */
+	auth = htod32(auth);
+	if ((ret = wlu_set(wl, WLC_SET_AUTH, &auth, sizeof(int))) < 0)
+		goto exit;
+
+	/* set wsec mode */
+	if ((ret = wlu_iovar_setint(wl, "wsec", wsec)) < 0)
+		goto exit;
+
+	/* set WPA_auth mode */
+	wpa_auth = htod32(wpa_auth);
+	if ((ret = wlu_set(wl, WLC_SET_WPA_AUTH, &wpa_auth, sizeof(wpa_auth))) < 0)
+		goto exit;
+
+	if (passive) {
+		wl_extjoin_params_t *extjoin_params;
+		int extjoin_size;
+		int i;
+		printf("Using passive assoc scan\n");
+		extjoin_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
+			join_params->params.chanspec_num * sizeof(chanspec_t);
+		if ((extjoin_params = malloc(extjoin_size)) == NULL) {
+			fprintf(stderr, "Error allocating %d bytes for extjoin \n", extjoin_size);
+			ret = BCME_NOMEM;
+			goto exit;
+		}
+
+		/* Copy assoc params from legacy struct into extended struct */
+		memset(extjoin_params, 0, extjoin_size);
+		memcpy(&extjoin_params->ssid.SSID, &join_params->ssid.SSID, DOT11_MAX_SSID_LEN);
+		extjoin_params->ssid.SSID_len = htod32(join_params->ssid.SSID_len);
+
+		memcpy(&extjoin_params->assoc.bssid, &join_params->params.bssid, ETHER_ADDR_LEN);
+		extjoin_params->assoc.chanspec_num = join_params->params.chanspec_num;
+		for (i = 0; i < join_params->params.chanspec_num; i++) {
+			extjoin_params->assoc.chanspec_list[i] =
+				join_params->params.chanspec_list[i];
+		}
+
+		extjoin_params->scan.scan_type = WL_SCANFLAGS_PASSIVE;
+		extjoin_params->scan.nprobes = -1;
+		extjoin_params->scan.active_time = -1;
+		extjoin_params->scan.passive_time = -1;
+		extjoin_params->scan.home_time = -1;
+
+
+		ret = wlu_var_setbuf(wl, "join", extjoin_params, extjoin_size);
+		free(extjoin_params);
+	} else {
+		/* join parameters starts with the ssid */
+		join_params->ssid.SSID_len = htod32(join_params->ssid.SSID_len);
+
+		if (prescanned) {
+			if ((ret = wl_join_prescanned(wl, join_params, &join_params_size)) < 0)
+				goto exit;
+		}
+
+		/* set ssid with extend assoc params (if any) */
+		join_params->ssid.SSID_len = htod32(join_params->ssid.SSID_len);
+		ret = wlu_set(wl, WLC_SET_SSID, join_params, join_params_size);
+	}
+
+exit:
+	free(join_params);
+		return ret;
+}
+
+/* Set or Get the "bssid" iovar, with an optional config index argument:
+ *	wl bssid [-C N]|[--cfg=N] bssid
+ *
+ * Option:
+ *	-C N
+ *	--cfg=N
+ *	--config=N
+ *	--configuration=N
+ *		specify the config index N
+ * If cfg index not given on a set, the WLC_SET_BSSID ioctl will be used
+ */
+static int
+wl_bssid(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr ea;
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "bssid", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	if (*argv == NULL) {
+		if (consumed == 0) {
+			/* no config index, use WLC_GET_BSSID on the interface */
+			error = wlu_get(wl, WLC_GET_BSSID, &ea, ETHER_ADDR_LEN);
+		} else {
+			/* use "bssid" iovar since a config option was given */
+			error = wlu_bssiovar_get(wl, "bssid", bsscfg_idx, &ea, ETHER_ADDR_LEN);
+		}
+		if (error < 0)
+			return error;
+		printf("%s\n", wl_ether_etoa(&ea));
+
+	} else {
+
+		if (!wl_ether_atoe(*argv, &ea))
+			return BCME_USAGE_ERROR;
+
+		if (consumed == 0) {
+			/* no config index given, use WLC_SET_BSSID */
+			error = wlu_set(wl, WLC_SET_BSSID, &ea, ETHER_ADDR_LEN);
+		} else {
+			/* use "bssid" iovar since a config option was given */
+			error = wl_bssiovar_set(wl, "bssid", bsscfg_idx, &ea, ETHER_ADDR_LEN);
+		}
+	}
+	return error;
+}
+
+/* Set or Get the "ssid" iovar, with an optional config index argument:
+ *	wl ssid [-C N]|[--cfg=N] ssid
+ *
+ * Option:
+ *	-C N
+ *	--cfg=N
+ *	--config=N
+ *	--configuration=N
+ *		specify the config index N
+ * If cfg index not given on a set, the WLC_SET_SSID ioctl will be used
+ */
+static int
+wl_ssid(void *wl, cmd_t *cmd, char **argv)
+{
+	char ssidbuf[SSID_FMT_BUF_LEN];
+	wlc_ssid_t ssid = { 0, {0} };
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "ssid", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	if (*argv == NULL) {
+		if (consumed == 0) {
+			/* no config index, use WLC_GET_SSID on the interface */
+			if (cmd->get == WLC_GET_SSID)
+				error = wlu_get(wl, WLC_GET_SSID, &ssid, sizeof(ssid));
+			else
+				error = wlu_iovar_get(wl, cmd->name, &ssid, sizeof(ssid));
+		} else {
+			if (cmd->get == WLC_GET_SSID) {
+				/* use "ssid" iovar since a config option was given */
+				error = wlu_bssiovar_get(wl, "ssid", bsscfg_idx, &ssid,
+				                        sizeof(ssid));
+			} else {
+				error = wlu_bssiovar_get(wl, cmd->name, bsscfg_idx, &ssid,
+				                        sizeof(ssid));
+			}
+		}
+		if (error < 0)
+			return error;
+
+		ssid.SSID_len = dtoh32(ssid.SSID_len);
+		wl_format_ssid(ssidbuf, ssid.SSID, ssid.SSID_len);
+		printf("Current %s: \"%s\"\n",
+		       (cmd->get == WLC_GET_SSID)? "SSID": cmd->name,
+		       ssidbuf);
+	} else {
+		if (strlen(argv[0]) > DOT11_MAX_SSID_LEN) {
+			fprintf(stderr, "SSID arg \"%s\" must be 32 chars or less\n", argv[0]);
+			return BCME_BADARG;
+		}
+		ssid.SSID_len = strlen(argv[0]);
+		memcpy(ssid.SSID, argv[0], ssid.SSID_len);
+
+		wl_format_ssid(ssidbuf, ssid.SSID, ssid.SSID_len);
+		printf("Setting %s: \"%s\"\n", (cmd->set == WLC_SET_SSID)? "SSID": cmd->name,
+		       ssidbuf);
+
+		ssid.SSID_len = htod32(ssid.SSID_len);
+		if (consumed == 0) {
+			/* no config index given, use WLC_SET_SSID */
+			if (cmd->set == WLC_SET_SSID) {
+				error = wlu_set(wl, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t));
+			} else {
+				error = wlu_iovar_set(wl, cmd->name, &ssid, sizeof(wlc_ssid_t));
+			}
+		} else {
+			if (cmd->set == WLC_SET_SSID) {
+				/* use "ssid" iovar since a config option was given */
+				error = wl_bssiovar_set(wl, "ssid", bsscfg_idx, &ssid,
+				                        sizeof(wlc_ssid_t));
+			} else
+				error = wl_bssiovar_set(wl, cmd->name, bsscfg_idx, &ssid,
+				                        sizeof(wlc_ssid_t));
+		}
+	}
+	return error;
+}
+
+static const char*
+wl_smfs_map_type(uint8 type)
+{
+	static const struct {uint8 type; char name[32];} type_names[] = {
+		{SMFS_TYPE_AUTH, "Authentication_Request"},
+		{SMFS_TYPE_ASSOC, "Association_Request"},
+		{SMFS_TYPE_REASSOC, "Reassociation_Request"},
+		{SMFS_TYPE_DISASSOC_TX, "Disassociation_Request_TX"},
+		{SMFS_TYPE_DISASSOC_RX, "Disassociation_Request_RX"},
+		{SMFS_TYPE_DEAUTH_TX, "Deauthentication_Request_TX"},
+		{SMFS_TYPE_DEAUTH_RX, "Deauthentication_Request_RX"}
+	};
+
+	const char *tname = "UNKNOWN";
+	uint i;
+
+	for (i = 0; i < ARRAYSIZE(type_names); i++) {
+		if (type_names[i].type == type)
+		    tname = type_names[i].name;
+	}
+	return tname;
+}
+
+static int
+wl_disp_smfs(char *inbuf)
+{
+	static const char *codename[] = {"Status_code", "Reason_code"};
+	wl_smf_stats_t *smf_stats;
+	wl_smfs_elem_t *elemt = NULL;
+	const char *namebuf;
+	uint32 version;
+	int count;
+
+	smf_stats = (wl_smf_stats_t *) inbuf;
+	namebuf = wl_smfs_map_type(smf_stats->type);
+
+	version = dtoh32(smf_stats->version);
+	if (version != SMFS_VERSION) {
+		fprintf(stderr, "Sorry, your driver has smfs_version %d "
+			"but this program supports only version %d.\n",
+			version, SMFS_VERSION);
+		return -1;
+	}
+
+	printf("Frame type: %s\n", namebuf);
+	printf("\tIgnored Count: %d\n", dtoh32(smf_stats->ignored_cnt));
+	printf("\tMalformed Count: %d\n", dtoh32(smf_stats->malformed_cnt));
+
+	count = dtoh32(smf_stats->count_total);
+
+	if (count) {
+		namebuf = codename[dtoh32(smf_stats->codetype)];
+		printf("\tSuccessful/Failed Count:\n");
+		elemt = &smf_stats->elem[0];
+	}
+
+	while (count) {
+		printf("\t\t%s %d Count: %d\n",  namebuf, dtoh16(elemt->code),
+		  dtoh32(elemt->count));
+		elemt ++;
+		count --;
+	}
+
+	return 0;
+
+}
+
+/*
+ * Check for the smfstats parameters. One of defined parameters can be passed in.
+ */
+static int
+wl_smfs_option(char **argv, int* idx, int *consumed, int* clear)
+{
+	int err = 0;
+	char *p;
+	char const * smfs_opt[] = {"auth", "assoc", "reassoc", "disassoc_tx",
+							   "disassoc_rx", "deauth_tx", "deauth_rx"};
+	char const * clear_opt = "clear";
+	int i;
+	char const * cur_opt;
+
+	if (*argv == NULL) {
+		goto exit;
+	}
+
+	p = *argv++;
+
+	for (i = 0; i < SMFS_TYPE_MAX; i++) {
+		cur_opt = smfs_opt[i];
+		if (!strcmp(p, cur_opt)) {
+			*idx = i;
+			*consumed += 1;
+			goto exit;
+		}
+	}
+
+	if (!strcmp(p, clear_opt))
+		*clear = 1;
+
+exit:
+	return err;
+}
+
+/* Get or Clear (set)  the "smfstats" iovar, with an optional config index argument:
+ *	wl smfstats [-C N]|[--cfg=N] 0
+ *
+ * Option:
+ *	-C N
+ *	--cfg=N
+ *	--config=N
+ *	--configuration=N
+ *		specify the config index N
+ * If cfg index not given on a set, the WLC_SET_SMF_STATS ioctl will be used
+ */
+static int
+wl_smfstats(void *wl, cmd_t *cmd, char **argv)
+{
+	int bsscfg_idx = 0;
+	int cfg_consumed = 0, smfs_consumed = 0;
+	int err;
+	int i, val;
+	int smf_index = 0;
+	int smfs_clear = 0;
+
+	BCM_REFERENCE(cmd);
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((err = wl_cfg_option(argv, "smfstats", &bsscfg_idx, &cfg_consumed)) != 0)
+		return err;
+
+	argv += cfg_consumed;
+
+	if ((err = wl_smfs_option(argv, &smf_index, &smfs_consumed, &smfs_clear)) != 0)
+		return err;
+
+	if (!smfs_clear) {
+		if (cfg_consumed == 0) {
+			if (smfs_consumed) {
+				err = wlu_iovar_getbuf(wl, "smfstats", &smf_index, sizeof(int),
+				   buf, WLC_IOCTL_SMLEN);
+				if (!err)
+					err = wl_disp_smfs(buf);
+			}
+			else {
+				for (i = 0; i < SMFS_TYPE_MAX; i++) {
+					smf_index = i;
+					err = wlu_iovar_getbuf(wl, "smfstats", &smf_index,
+					   sizeof(int), buf, WLC_IOCTL_SMLEN);
+					if (!err)
+						err = wl_disp_smfs(buf);
+				}
+			}
+		} else {
+			/* use "stats" iovar since a config option was given */
+			if (smfs_consumed) {
+				err = wl_bssiovar_getbuf(wl, "smfstats", bsscfg_idx, &smf_index,
+				  sizeof(int), buf, WLC_IOCTL_SMLEN);
+				if (!err)
+					err = wl_disp_smfs(buf);
+			}
+			else {
+				for (i = 0; i < SMFS_TYPE_MAX; i++) {
+					smf_index = i;
+					err = wl_bssiovar_getbuf(wl, "smfstats", bsscfg_idx,
+						&smf_index, sizeof(int), buf, WLC_IOCTL_SMLEN);
+					if (!err)
+						err = wl_disp_smfs(buf);
+				}
+			}
+		}
+		if (err < 0)
+			return err;
+	} else {
+		val = 0;
+
+		if (cfg_consumed == 0)
+			err = wlu_iovar_setint(wl, "smfstats", val);
+		else
+			err = wl_bssiovar_setint(wl, "smfstats", bsscfg_idx, val);
+
+	}
+	return err;
+}
+
+#ifdef BCMCCX
+static int
+wl_leap(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_leap_list_t leap_list, *get_list;
+	wl_leap_info_t *list_item;
+	size_t len;
+	int ret, i;
+
+	if (!*++argv) {
+		/* no parameter means this is a `get'. */
+		len = sizeof(wl_leap_list_t) + 42 * sizeof(wl_leap_info_t);
+		get_list = (wl_leap_list_t *)malloc(len);
+		if (!get_list) {
+			fprintf(stderr, "memory alloc failure\n");
+			return BCME_NOMEM;
+		}
+		get_list->buflen = htod32(len);
+		if ((ret = wlu_get(wl, cmd->get, get_list, len)) < 0) {
+			free(get_list);
+			return ret;
+		}
+		get_list->buflen = dtoh32(get_list->buflen);
+		get_list->version = dtoh32(get_list->version);
+		get_list->count = dtoh32(get_list->count);
+		printf("buflen %d version %d count %d\n",
+		       get_list->buflen, get_list->version, get_list->count);
+
+		for (i = 0, list_item = get_list->leap_info;
+		     i < (int) get_list->count;
+		     i++, list_item++) {
+
+			char user[sizeof(leap_list.leap_info[0].user)+1];
+			char pw[sizeof(leap_list.leap_info[0].password)+1];
+			char dom[sizeof(leap_list.leap_info[0].domain)+1];
+			char ssidbuf[SSID_FMT_BUF_LEN];
+
+			list_item->ssid.SSID_len = dtoh32(list_item->ssid.SSID_len);
+			wl_format_ssid(ssidbuf, list_item->ssid.SSID,
+				list_item->ssid.SSID_len);
+			memcpy(user, list_item->user, list_item->user_len);
+			user[list_item->user_len] = '\0';
+			memcpy(pw, list_item->password, list_item->password_len);
+			pw[list_item->password_len] = '\0';
+			memcpy(dom, list_item->domain, list_item->domain_len);
+			dom[list_item->domain_len] = '\0';
+
+			printf(" % 2d: ssid \"%s\", user \"%s\", password \"%s\", domain \"%s\"\n",
+			       i, ssidbuf, user, pw, dom);
+
+
+		}
+		free(get_list);
+		return 0;
+	}
+	len = strlen(*argv);
+	/* ssid has to be a leagal size */
+	if (len > DOT11_MAX_SSID_LEN)
+		return BCME_BADARG;
+
+	memset(&leap_list, 0, sizeof(leap_list));
+	leap_list.buflen = htod32(sizeof(leap_list));
+	leap_list.count = htod32(1);
+
+	leap_list.leap_info[0].ssid.SSID_len = htod32(len);
+	memcpy(leap_list.leap_info[0].ssid.SSID, *argv, len);
+
+	/* user name must follow */
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	len = strlen(*argv);
+	if (len > sizeof(leap_list.leap_info[0].user))
+		return BCME_BADARG;
+	leap_list.leap_info[0].user_len = len;
+	memcpy(leap_list.leap_info[0].user, *argv, len);
+
+	/* password must follow */
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	len = strlen(*argv);
+	if (len > sizeof(leap_list.leap_info[0].password))
+		return BCME_BADARG;
+	leap_list.leap_info[0].password_len = len;
+	memcpy(leap_list.leap_info[0].password, *argv, len);
+
+	/* If there's more, it's a domain name */
+	if (*++argv) {
+		len = strlen(*argv);
+		if (len > sizeof(leap_list.leap_info[0].domain))
+			return BCME_BADARG;
+		leap_list.leap_info[0].domain_len = len;
+		memcpy(leap_list.leap_info[0].domain, *argv, len);
+	}
+
+	return wlu_set(wl, cmd->set, &leap_list, sizeof(leap_list));
+}
+#endif /* BCMCCX */
+
+static int
+wl_tssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+
+	UNUSED_PARAMETER(argv);
+
+	if (cmd->get < 0)
+		return -1;
+	if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+		return ret;
+
+	val = dtoh32(val);
+	printf("CCK %d OFDM %d\n", (val & 0xff), (val >> 8) & 0xff);
+	return 0;
+}
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a uint16.
+ */
+
+#define QDBM_OFFSET 153 /* QDBM_OFFSET */
+#define QDBM_TABLE_LEN 40 /* QDBM_TABLE_LEN */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493 /* QDBM_TABLE_LOW_BOUND */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938 /* QDBM_TABLE_HIGH_BOUND */
+
+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm:        +0	+1	+2	+3	+4	+5	+6	+7	*/
+/* 153: */      6683,	7079,	7499,	7943,	8414,	8913,	9441,	10000,
+/* 161: */      10593,	11220,	11885,	12589,	13335,	14125,	14962,	15849,
+/* 169: */      16788,	17783,	18836,	19953,	21135,	22387,	23714,	25119,
+/* 177: */      26607,	28184,	29854,	31623,	33497,	35481,	37584,	39811,
+/* 185: */      42170,	44668,	47315,	50119,	53088,	56234,	59566,	63096
+};
+
+static uint16
+wl_qdbm_to_mw(uint8 qdbm)
+{
+	uint factor = 1;
+	int idx = qdbm - QDBM_OFFSET;
+
+	if (idx >= QDBM_TABLE_LEN) {
+		/* clamp to max uint16 mW value */
+		return 0xFFFF;
+	}
+
+	/* scale the qdBm index up to the range of the table 0-40
+	 * where an offset of 40 qdBm equals a factor of 10 mW.
+	 */
+	while (idx < 0) {
+		idx += 40;
+		factor *= 10;
+	}
+
+	/* return the mW value scaled down to the correct factor of 10,
+	 * adding in factor/2 to get proper rounding.
+	 */
+	return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
+}
+
+static uint8
+wl_mw_to_qdbm(uint16 mw)
+{
+	uint8 qdbm;
+	int offset;
+	uint mw_uint = mw;
+	uint boundary;
+
+	/* handle boundary case */
+	if (mw_uint <= 1)
+		return 0;
+
+	offset = QDBM_OFFSET;
+
+	/* move mw into the range of the table */
+	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+		mw_uint *= 10;
+		offset -= 40;
+	}
+
+	for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
+		boundary = nqdBm_to_mW_map[qdbm] +
+			(nqdBm_to_mW_map[qdbm+1] - nqdBm_to_mW_map[qdbm])/2;
+		if (mw_uint < boundary) break;
+	}
+
+	qdbm += (uint8)offset;
+
+	return (qdbm);
+}
+
+#define UNIT_MW		1 /* UNIT_MW */
+#define UNIT_QDBM	2 /* UNIT_QDBM */
+#define UNIT_DBM	3 /* UNIT_DBM */
+static int
+wl_txpwr1(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, val, new_val = 0, unit;
+	const char *name = "qtxpower";
+	bool override = FALSE;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_iovar_getint(wl, name, &val)) < 0)
+			return ret;
+
+		override = ((val & WL_TXPWR_OVERRIDE) != 0);
+		val &= ~WL_TXPWR_OVERRIDE;
+		printf("TxPower is %d qdbm, %d.%d dbm, %d mW  Override is %s\n",
+		       val, DIV_QUO(val, 4), DIV_REM(val, 4),
+		       wl_qdbm_to_mw((uint8)(MIN(val, 0xff))),
+		       override ? "On" : "Off");
+		return 0;
+	} else {
+		/* for set */
+		unit = UNIT_DBM;	/* default units */
+
+		/* override can be used in combo with any unit */
+		if (!strcmp(*argv, "-o")) {
+			override = TRUE;
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+		}
+
+		if (!strcmp(*argv, "-d")) {
+			unit = UNIT_DBM;
+			argv++;
+		}
+		else if (!strcmp(*argv, "-q")) {
+			unit = UNIT_QDBM;
+			argv++;
+		}
+		else if (!strcmp(*argv, "-m")) {
+			unit = UNIT_MW;
+			argv++;
+		}
+
+		/* override can be used in combo with any unit */
+		if (!strcmp(*argv, "-o")) {
+			override = TRUE;
+			argv++;
+		}
+
+		if (!*argv)
+			return BCME_USAGE_ERROR;
+
+		val = atoi(*argv);
+
+		if (val == -1) {
+			val = 127;		/* Max val of 127 qdbm */
+			unit = UNIT_QDBM;
+		}
+
+		if (val <= 0) {
+			return BCME_BADARG;
+		}
+
+		switch (unit) {
+		case UNIT_MW:
+			new_val = wl_mw_to_qdbm((uint16)MIN(val, 0xffff));
+			break;
+		case UNIT_DBM:
+			new_val = val * 4;
+			break;
+		case UNIT_QDBM:
+			new_val = val;
+			break;
+		}
+
+		if (override)
+			new_val |= WL_TXPWR_OVERRIDE;
+
+		return wlu_iovar_setint(wl, name, new_val);
+	}
+}
+
+static int
+wl_txpwr(void *wl, cmd_t *cmd, char **argv)
+{
+	int error;
+	uint32 val;
+	char *endptr = NULL;
+	uint32 override;
+	const char *name = "qtxpower";
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		if ((error = wlu_iovar_getint(wl, name, (int *)&val)) < 0)
+			return error;
+
+		/* Report power in mw with WL_TXPWR_OVERRIDE
+		 * bit indicating the status
+		 */
+		override = ((val & WL_TXPWR_OVERRIDE) != 0);
+		val &= ~WL_TXPWR_OVERRIDE;
+		printf("%d.%d dBm = %d mw.  %s\n", DIV_QUO(val, 4), DIV_REM(val, 4),
+			wl_qdbm_to_mw((uint8)(MIN(val, 0xff))), (override ? "(Override ON)" : ""));
+		return 0;
+	} else {
+		if (!strcmp(*argv, "-u")) {
+			override = 0;
+			argv++;
+		} else
+			override = WL_TXPWR_OVERRIDE;
+
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			return BCME_USAGE_ERROR;
+		}
+
+		val = wl_mw_to_qdbm((uint16)MIN(val, 0xffff));
+
+		/* wl command input power will override current power set if told so */
+		val |= override;
+
+		return wlu_iovar_setint(wl, name, val);
+	}
+}
+
+static int
+wl_get_txpwr_limit(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint8 val_qdbm;
+	uint16 val_mw;
+	tx_power_legacy_t power;
+
+	UNUSED_PARAMETER(argv);
+
+	ret = wlu_get(wl, cmd->get, &power, sizeof(power));
+	if (ret < 0)
+		return ret;
+
+	val_qdbm = MIN(power.txpwr_band_max[0], power.txpwr_local_max);
+	val_mw = wl_qdbm_to_mw((uint8)(MIN(val_qdbm, 0xff)));
+
+	printf("%d mW (%d.%d dBm)\n", val_mw, DIV_QUO(val_qdbm, 4), DIV_REM(val_qdbm, 4));
+
+	return ret;
+}
+
+static int
+wl_atten(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	atten_t atten;
+	char *endptr;
+
+	memset(&atten, 0, sizeof(atten_t));
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+
+		if ((ret = wlu_get(wl, cmd->get, &atten, sizeof(atten_t))) < 0)
+			return ret;
+
+		printf("tx %s bb/radio/ctl1 %d/%d/%d\n",
+		       (dtoh16(atten.auto_ctrl) ? "auto" : ""),
+			dtoh16(atten.bb), dtoh16(atten.radio), dtoh16(atten.txctl1));
+
+		return 0;
+	} else {
+		if (cmd->set < 0)
+			return -1;
+
+		if (!stricmp(*argv, "auto")) {
+			atten.auto_ctrl = WL_ATTEN_PCL_ON;
+			atten.auto_ctrl = htod16(atten.auto_ctrl);
+		}
+		else if (!stricmp(*argv, "manual")) {
+			atten.auto_ctrl = WL_ATTEN_PCL_OFF;
+			atten.auto_ctrl = htod16(atten.auto_ctrl);
+		}
+		else {
+			atten.auto_ctrl = WL_ATTEN_APP_INPUT_PCL_OFF;
+			atten.auto_ctrl = htod16(atten.auto_ctrl);
+
+			atten.bb = (uint16)strtoul(*argv, &endptr, 0);
+			atten.bb = htod16(atten.bb);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+
+			atten.radio = (uint16)strtoul(*argv, &endptr, 0);
+			atten.radio = htod16(atten.radio);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+
+			atten.txctl1 = (uint16)strtoul(*argv, &endptr, 0);
+			atten.txctl1 = htod16(atten.txctl1);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+		}
+
+		return wlu_set(wl, cmd->set, &atten, sizeof(atten_t));
+	}
+}
+
+static int
+wl_maclist(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct maclist *maclist = (struct maclist *) buf;
+	struct ether_addr *ea;
+	uint i, max = (WLC_IOCTL_MAXLEN - sizeof(int)) / ETHER_ADDR_LEN;
+	uint len;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		maclist->count = htod32(max);
+		if ((ret = wlu_get(wl, cmd->get, maclist, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+		maclist->count = dtoh32(maclist->count);
+		for (i = 0, ea = maclist->ea; i < maclist->count && i < max; i++, ea++)
+			printf("%s %s\n", cmd->name, wl_ether_etoa(ea));
+		return 0;
+	} else {
+		if (cmd->set < 0)
+			return -1;
+		/* Clear list */
+		maclist->count = htod32(0);
+		if (!stricmp(*argv, "none") || !stricmp(*argv, "clear"))
+			return wlu_set(wl, cmd->set, maclist, sizeof(int));
+		/* Get old list */
+		maclist->count = htod32(max);
+		if ((ret = wlu_get(wl, cmd->get, maclist, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+		/* Append to old list */
+		maclist->count = dtoh32(maclist->count);
+		ea = &maclist->ea[maclist->count];
+		while (*argv && maclist->count < max) {
+			if (!wl_ether_atoe(*argv, ea)) {
+				printf("Problem parsing MAC address \"%s\".\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			maclist->count++;
+			ea++;
+			argv++;
+		}
+		/* Set new list */
+		len = sizeof(maclist->count) + maclist->count * sizeof(maclist->ea);
+		maclist->count = htod32(maclist->count);
+		return wlu_set(wl, cmd->set, maclist, len);
+	}
+}
+
+static int
+wl_maclist_1(void *wl, cmd_t *cmd, char **argv)
+{
+	struct maclist *maclist;
+	struct ether_addr *ea;
+	uint i;
+	int ret;
+
+	strcpy(buf, argv[0]);
+
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	maclist = (struct maclist *)buf;
+
+	for (i = 0, ea = maclist->ea; i < dtoh32(maclist->count); i++, ea++)
+		printf("%s %s\n", cmd->name, wl_ether_etoa(ea));
+	return 0;
+}
+
+static int
+wl_out(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	return wlu_set(wl, WLC_OUT, NULL, 0);
+}
+
+static int
+wl_band(void *wl, cmd_t *cmd, char **argv)
+{
+	uint band;
+	int error;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if (*argv == NULL) {	/* get current band */
+		if ((error = wlu_get(wl, WLC_GET_BAND, &band, sizeof(uint))) < 0)
+			return (error);
+		band = dtoh32(band);
+
+		if (band == WLC_BAND_AUTO)
+			printf("auto\n");
+		else if (band == WLC_BAND_5G)
+			printf("a\n");
+		else if (band == WLC_BAND_2G)
+			printf("b\n");
+		else {
+			printf("unrecognized band value %d\n", band);
+			error = BCME_ERROR;
+		}
+	} else {		/* set the band */
+		if (!stricmp(*argv, "auto"))
+			band = WLC_BAND_AUTO;
+		else if (!stricmp(*argv, "a"))
+			band = WLC_BAND_5G;
+		else if (!stricmp(*argv, "b"))
+			band = WLC_BAND_2G;
+		else {
+			printf("unsupported band: %s\n", *argv);
+			return BCME_UNSUPPORTED;
+		}
+
+		band = htod32(band);
+		error = wlu_set(wl, WLC_SET_BAND, &band, sizeof(uint));
+
+	}
+	return (error);
+}
+
+static int
+wl_bandlist(void *wl, cmd_t *cmd, char **argv)
+{
+	uint list[3];
+	int error;
+	uint i;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if ((error = wlu_get(wl, WLC_GET_BANDLIST, list, sizeof(list))) < 0)
+		return (error);
+	list[0] = dtoh32(list[0]);
+	list[1] = dtoh32(list[1]);
+	list[2] = dtoh32(list[2]);
+
+	/* list[0] is count, followed by 'count' bands */
+
+	if (list[0] > 2)
+		list[0] = 2;
+
+	for (i = 1; i <= list[0]; i++)
+		if (list[i] == WLC_BAND_5G)
+			printf("a ");
+		else if (list[i] == WLC_BAND_2G)
+			printf("b ");
+		else
+			printf("? ");
+	printf("\n");
+
+	return (0);
+}
+
+static int
+wl_phylist(void *wl, cmd_t *cmd, char **argv)
+{
+	char phylist_buf[128];
+	int error;
+	char *cp;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if ((error = wlu_get(wl, WLC_GET_PHYLIST, phylist_buf, sizeof(phylist_buf))) < 0)
+		return (error);
+
+	cp = phylist_buf;
+
+	for (; *cp; cp++)
+		printf("%c ", *cp);
+	printf("\n");
+
+	return (0);
+}
+
+#define UPGRADE_BUFSIZE	512 /* upgrade buffer size */
+
+static int
+wl_upgrade(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#else
+	FILE *fp;
+	int ret = 0;
+	struct {
+		uint32 offset;
+		char buf[UPGRADE_BUFSIZE];
+	} block;
+	uint32 offset;
+	uint len;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	if (!(fp = fopen(*argv, "rb"))) {
+		fprintf(stderr, "%s: No such file or directory\n", *argv);
+		return BCME_BADARG;
+	}
+
+	printf("Programming %s...", *argv);
+	fflush(stdout);
+	offset = 0;
+	block.offset = htod32(offset);
+	while ((len = fread(block.buf, 1, sizeof(block.buf), fp))) {
+		if ((ret = wlu_set(wl, cmd->set, &block, 4 + len)) < 0)
+			break;
+		offset += len;
+		block.offset = htod32(offset);
+		printf(".");
+		fflush(stdout);
+	}
+
+	if (ferror(fp)) {
+		ret = ferror(fp);
+		printf("\nerror reading %s\n", *argv);
+	} else {
+		long status = WLC_UPGRADE_PENDING;
+		int retries;
+
+		printf("\nCommitting image to flash...\n");
+		while (status == WLC_UPGRADE_PENDING) {
+			retries = 10;
+retry:
+			if ((ret = wlu_get(wl, WLC_UPGRADE_STATUS,
+				&status, sizeof(status))) < 0) {
+				/* the first attempt to get status will
+				 * likely fail due to dev reset
+				 */
+				if (retries--)
+					goto retry;
+				break;
+			}
+			status = dtoh32(status);
+		}
+		if (status == WLC_UPGRADE_SUCCESS)
+			printf("\nDone\n\nSuccessfully downloaded %d bytes\n", block.offset);
+		else
+			fprintf(stderr, "\n*** UPGRADE FAILED! *** (status %ld)\n", status);
+	}
+
+	fclose(fp);
+	return ret;
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+}
+
+#include <bcmnvram.h>
+
+static int
+wl_otpraw(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[392];
+	uint32 offset;
+	uint32 bits;
+	uint32 len;
+	bool get = TRUE;
+	void *ptr = NULL;
+	char *endptr;
+	uint32 i;
+
+	if (argv[1]) {
+		offset = htod32(strtoul(argv[1], &endptr, 0));
+		memcpy(var, (char *)&offset, sizeof(offset));
+		len = sizeof(offset);
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	if (argv[2]) {
+		bits = htod32(strtoul(argv[2], &endptr, 0));
+		if (bits > 3072)
+		{
+			printf("bit size (%d) too long or negative!!\n", bits);
+			return BCME_BADARG;
+		}
+	}
+	else
+		bits = 1;
+
+	memcpy(&var[len], (char *)&bits, sizeof(bits));
+	len += sizeof(bits);
+
+	if (argv[3]) {
+		unsigned char data[768];
+		uint32  patlen;
+		char *inptr = argv[3];
+
+		get = FALSE;
+
+		if (*inptr == '0' && toupper((int)(*(inptr + 1))) == 'X')
+			inptr += 2;
+
+		patlen = strlen(inptr);
+		if (patlen > 768 || (patlen * 4) < bits)
+		{
+			printf("data length (%d) too long or small!!\n", patlen);
+			return BCME_USAGE_ERROR;
+		}
+
+		for (i = 1; i <= patlen; i++)
+		{
+			int n = (int)((unsigned char)*inptr++);
+			if (!isxdigit(n)) {
+				fprintf(stderr, "invalid hex digit %c\n", n);
+				return BCME_USAGE_ERROR;
+			}
+			data[patlen - i] = (unsigned char)(isdigit(n) ? (n - '0')
+				        : ((islower(n) ? (toupper(n)) : n) - 'A' + 10));
+		}
+
+		for (i = 0; i < patlen; i += 2)
+		{
+			unsigned char v;
+			v = data[i];
+			if (i + 1 < patlen)
+				v += (data[i+1] * 16);
+			memcpy(&var[len], (char *)&v, sizeof(v));
+			len += sizeof(v);
+		}
+
+		printf("OTP RAM Write:");
+		for (i = 0; i < bits; i += 8)
+		{
+			unsigned char v;
+			v = var[2*sizeof(uint32) + (i/8)];
+
+			if ((i % 64) == 0)
+				printf("\nbit %4d:", offset + i);
+			printf(" 0x%x", v);
+		}
+		printf("\n");
+
+	}
+
+	if (get) {
+		int ret;
+		unsigned char v, *cptr;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0) {
+			printf("Error reading from OTP data\n");
+			return ret;
+		}
+
+		cptr = (unsigned char *)ptr;
+
+		printf("OTP RAM Read:");
+		for (i = 0; i < bits; i += 8)
+		{
+			v = *cptr++;
+
+			if ((i % 64) == 0)
+				printf("\nbit %4d:", offset + i);
+			printf(" 0x%02x", v);
+		}
+		printf("\n");
+		return 0;
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+}
+
+static int
+wl_otpw(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#else
+	FILE *fp;
+	int ret = 0;
+	struct nvram_header *nvr;
+	char *p, otpw_buf[1024 - 128];
+	const char *msg;
+	int len;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	if (!(fp = fopen(*argv, "rb"))) {
+		fprintf(stderr, "%s: No such file or directory\n", *argv);
+		return BCME_BADARG;
+	}
+
+	len = fread(otpw_buf, 1, sizeof(otpw_buf) - 1, fp);
+	if ((ret = ferror(fp))) {
+		printf("\nerror %d reading %s\n", ret, *argv);
+		ret = BCME_ERROR;
+		goto out;
+	}
+	if (!feof(fp)) {
+		printf("\nFile %s too large\n", *argv);
+		ret = BCME_ERROR;
+		goto out;
+	}
+
+	/* Got the bits, do they look like the output of nvserial? */
+	nvr = (struct nvram_header *)otpw_buf;
+	if (nvr->magic == NVRAM_MAGIC) {
+		if (cmd->set == WLC_OTPW) {
+			printf("File %s looks like an nvserial file, use nvotpw\n", *argv);
+			fflush(stdout);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		len  = nvr->len - sizeof(struct nvram_header);
+		if (len <= 0) {
+			printf("Invalid length (%d)\n", len);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		if (len & 1) {
+			otpw_buf[len++] = '\0';
+		}
+		p = (char *)(nvr + 1);
+		msg = "nvserial";
+	} else {
+		if (cmd->set == WLC_NVOTPW) {
+			printf("File %s is not an nvserial file\n", *argv);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		if (len & 1) {
+			printf("File %s has an odd length (%d)\n", *argv, len);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		p = otpw_buf;
+		msg = "raw";
+	}
+
+	printf("Writing %d bytes from %s file %s to otp ...\n", len, msg, *argv);
+	fflush(stdout);
+
+	if ((ret = wlu_set(wl, cmd->set, p, len)) < 0) {
+		printf("\nError %d writing %s to otp\n", ret, *argv);
+	}
+
+out:
+	fclose(fp);
+	return ret;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+wl_get_pktcnt(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	get_pktcnt_t pktcnt;
+
+	UNUSED_PARAMETER(argv);
+
+	memset(&pktcnt, 0, sizeof(pktcnt));
+	if ((ret = wlu_get(wl, cmd->get, &pktcnt, sizeof(pktcnt))) < 0)
+		return ret;
+
+	printf("Receive: good packet %d, bad packet %d, othercast good packet %d\n",
+		dtoh32(pktcnt.rx_good_pkt), dtoh32(pktcnt.rx_bad_pkt),
+		dtoh32(pktcnt.rx_ocast_good_pkt));
+	printf("Transmit: good packet %d, bad packet %d\n",
+		dtoh32(pktcnt.tx_good_pkt), dtoh32(pktcnt.tx_bad_pkt));
+
+	return ret;
+}
+
+static int
+wl_interfere(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr = NULL;
+	int mode;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &mode, sizeof(mode))) < 0)
+			return ret;
+		mode = dtoh32(mode);
+		switch (mode & 0x7f) {
+		case INTERFERE_NONE:
+			printf("All interference mitigation is disabled. (mode 0)\n");
+			break;
+		case NON_WLAN:
+			printf("Non-wireless LAN Interference mitigation is enabled. (mode 1)\n");
+			break;
+		case WLAN_MANUAL:
+			printf("Wireless LAN Interference mitigation is enabled. (mode 2)\n");
+			break;
+		case WLAN_AUTO:
+			printf("Auto Wireless LAN Interference mitigation is enabled and ");
+			if (mode & AUTO_ACTIVE)
+				printf("active. (mode 3)\n");
+			else
+				printf("not active. (mode 3)\n");
+
+			break;
+		case WLAN_AUTO_W_NOISE:
+			printf("Auto Wireless LAN Interference mitigation is enabled and ");
+			if (mode & AUTO_ACTIVE)
+				printf("active, ");
+			else
+				printf("not active, ");
+
+			printf("and noise reduction is enabled. (mode 4)\n");
+			break;
+		}
+		return 0;
+	} else {
+		mode = INTERFERE_NONE;
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		switch (val) {
+			case 0:
+				mode = INTERFERE_NONE;
+				break;
+			case 1:
+				mode = NON_WLAN;
+				break;
+			case 2:
+				mode = WLAN_MANUAL;
+				break;
+			case 3:
+				mode = WLAN_AUTO;
+				break;
+			case 4:
+				mode = WLAN_AUTO_W_NOISE;
+				break;
+			default:
+				return BCME_BADARG;
+		}
+
+		mode = htod32(mode);
+		return wlu_set(wl, cmd->set, &mode, sizeof(mode));
+	}
+}
+
+static int
+wl_interfere_override(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr;
+	int mode;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &mode, sizeof(mode))) < 0) {
+			return ret;
+		}
+		mode = dtoh32(mode);
+		switch (mode) {
+		case INTERFERE_NONE:
+			printf("Interference override NONE, "
+			"all mitigation disabled. (mode 0)\n");
+			break;
+		case NON_WLAN:
+			printf("Interference override enabled. "
+				" Non-wireless LAN Interference mitigation is enabled. (mode 1)\n");
+			break;
+		case WLAN_MANUAL:
+			printf("Interference override enabled.  "
+			" Wireless LAN Interference mitigation is enabled. (mode 2)\n");
+			break;
+		case WLAN_AUTO:
+			printf("Interference override enabled. "
+				" Interference mitigation is enabled and ");
+			if (mode & AUTO_ACTIVE)
+				printf("active. (mode 3)\n");
+			else
+				printf("not active. (mode 3)\n");
+
+			break;
+		case WLAN_AUTO_W_NOISE:
+			printf("Interference override enabled. "
+				" Interference mitigation is enabled and ");
+			if (mode & AUTO_ACTIVE)
+				printf("active, ");
+			else
+				printf("not active, ");
+
+			printf("and noise reduction is enabled. (mode 4)\n");
+			break;
+		case INTERFERE_OVRRIDE_OFF:
+			printf("Interference override disabled. \n");
+			break;
+		}
+		return 0;
+	} else {
+		mode = INTERFERE_NONE;
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		switch (val) {
+			case 0:
+				mode = INTERFERE_NONE;
+				break;
+			case 1:
+				mode = NON_WLAN;
+				break;
+			case 2:
+				mode = WLAN_MANUAL;
+				break;
+			case 3:
+				mode = WLAN_AUTO;
+				break;
+			case 4:
+				mode = WLAN_AUTO_W_NOISE;
+				break;
+			case INTERFERE_OVRRIDE_OFF:
+				mode = INTERFERE_OVRRIDE_OFF;
+				break;
+			default:
+				return BCME_BADARG;
+		}
+
+		mode = htod32(mode);
+		return wlu_set(wl, cmd->set, &mode, sizeof(mode));
+	}
+}
+
+static cntry_name_t *
+wlc_cntry_name_to_country(char *long_name)
+{
+	cntry_name_t *cntry;
+	for (cntry = cntry_names; cntry->name &&
+		stricmp(long_name, cntry->name); cntry++);
+	return (!cntry->name ? NULL : cntry);
+}
+
+static cntry_name_t *
+wlc_cntry_abbrev_to_country(const char *abbrev)
+{
+	cntry_name_t *cntry;
+	if (!*abbrev || strlen(abbrev) > 3 || strlen(abbrev) < 2)
+		return (NULL);
+	for (cntry = cntry_names; cntry->name &&
+		strnicmp(abbrev, cntry->abbrev, strlen(abbrev)); cntry++);
+	return (!cntry->name ? NULL : cntry);
+}
+
+static int
+wl_parse_country_spec(const char *spec, char *ccode, int *regrev)
+{
+	char *revstr;
+	char *endptr = NULL;
+	int ccode_len;
+	int rev = -1;
+
+	revstr = strchr(spec, '/');
+
+	if (revstr) {
+		rev = strtol(revstr + 1, &endptr, 10);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			fprintf(stderr,
+				"Could not parse \"%s\" as a regulatory revision "
+				"in the country string \"%s\"\n",
+				revstr + 1, spec);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if (revstr)
+		ccode_len = (int)(uintptr)(revstr - spec);
+	else
+		ccode_len = (int)strlen(spec);
+
+	if (ccode_len > 3) {
+		fprintf(stderr,
+			"Could not parse a 2-3 char country code "
+			"in the country string \"%s\"\n",
+			spec);
+		return BCME_USAGE_ERROR;
+	}
+
+	memcpy(ccode, spec, ccode_len);
+	ccode[ccode_len] = '\0';
+	*regrev = rev;
+
+	return 0;
+}
+
+int
+wl_country(void *wl, cmd_t *cmd, char **argv)
+{
+	cntry_name_t *cntry;
+	wl_country_t cspec = {{0}, 0, {0}};
+	int argc = 0;
+	int err;
+	int bcmerr = 1;
+
+	/* skip the command name */
+	argv++;
+
+	/* find the arg count */
+	while (argv[argc])
+		argc++;
+
+	/* check arg list count */
+	if (argc > 2) {
+		fprintf(stderr, "Too many arguments (%d) for command %s\n", argc, cmd->name);
+		return BCME_USAGE_ERROR;
+	}
+
+	buf[0] = 0;
+	if (argc == 0) {
+		const char* name = "<unknown>";
+
+		/* first try the country iovar */
+		err = wlu_iovar_get(wl, "country", &cspec, sizeof(cspec));
+
+		if (!err) {
+			cntry = wlc_cntry_abbrev_to_country(cspec.country_abbrev);
+			if (cntry)
+				name = cntry->name;
+			cspec.rev = dtoh32(cspec.rev);
+
+			printf("%s (%s/%d) %s\n",
+			       cspec.country_abbrev, cspec.ccode, cspec.rev, name);
+
+			return 0;
+		}
+
+		/* if there was an error other than BCME_UNSUPPORTED, fail now */
+		wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+		if (bcmerr != BCME_UNSUPPORTED)
+			return err;
+
+		/* if the "country" iovar is unsupported, try the WLC_SET_COUNTRY ioctl */
+		if ((err = wlu_get(wl, cmd->get, &buf[0], WLC_IOCTL_SMLEN)) < 0)
+			return err;
+		if (strlen(buf) == 0) {
+			printf("No country set\n");
+			return 0;
+
+		}
+		cntry = wlc_cntry_abbrev_to_country(buf);
+		if (cntry != NULL)
+			name = cntry->name;
+
+		printf("%s () %s\n", buf, name);
+		return 0;
+	}
+
+	if (!stricmp(*argv, "list")) {
+		uint i;
+		const char* abbrev;
+		wl_country_list_t *cl = (wl_country_list_t *)buf;
+
+		cl->buflen = WLC_IOCTL_MAXLEN;
+		cl->count = 0;
+
+		/* band may follow */
+		if (*++argv) {
+			cl->band_set = TRUE;
+			if (!stricmp(*argv, "a"))
+				cl->band = WLC_BAND_5G;
+			else if (!stricmp(*argv, "b") || !stricmp(*argv, "g"))
+				cl->band = WLC_BAND_2G;
+			else {
+				printf("unsupported band: %s\n", *argv);
+				return BCME_UNSUPPORTED;
+			}
+		} else {
+			cl->band_set = FALSE;
+		}
+
+		cl->buflen = htod32(cl->buflen);
+		cl->band_set = htod32(cl->band_set);
+		cl->band = htod32(cl->band);
+		cl->count = htod32(cl->count);
+		err = wlu_get(wl, WLC_GET_COUNTRY_LIST, buf, WLC_IOCTL_MAXLEN);
+		if (err < 0)
+			return err;
+
+		printf("Supported countries: country code and long name\n");
+		for (i = 0; i < dtoh32(cl->count); i++) {
+			abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ];
+			cntry = wlc_cntry_abbrev_to_country(abbrev);
+			printf("%s\t%s\n", abbrev, cntry ? cntry->name : "");
+		}
+		return 0;
+	}
+
+	memset(&cspec, 0, sizeof(cspec));
+	cspec.rev = -1;
+
+	if (argc == 1) {
+		/* check for the first arg being a country name, e.g. "United States",
+		 * or country spec, "US/1", or just a country code, "US"
+		 */
+		if ((cntry = wlc_cntry_name_to_country(argv[0])) != NULL) {
+			/* arg matched a country name */
+			memcpy(cspec.country_abbrev, cntry->abbrev, WLC_CNTRY_BUF_SZ);
+			err = 0;
+		} else {
+			/* parse a country spec, e.g. "US/1", or a country code.
+			 * cspec.rev will be -1 if not specified.
+			 */
+			err = wl_parse_country_spec(argv[0], cspec.country_abbrev, &cspec.rev);
+		}
+
+		if (err) {
+			fprintf(stderr,
+				"Argument \"%s\" could not be parsed as a country name, "
+				"country code, or country code and regulatory revision.\n",
+				argv[0]);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* if the arg was a country spec, then fill out ccdoe and rev,
+		 * and leave country_abbrev defaulted to the ccode
+		 */
+		if (cspec.rev != -1)
+			memcpy(cspec.ccode, cspec.country_abbrev, WLC_CNTRY_BUF_SZ);
+	} else {
+		/* for two args, the first needs to be a country code or country spec */
+		err = wl_parse_country_spec(argv[0], cspec.ccode, &cspec.rev);
+		if (err) {
+			fprintf(stderr,
+				"Argument 1 \"%s\" could not be parsed as a country code, or "
+				"country code and regulatory revision.\n",
+				argv[0]);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* the second arg needs to be a country name or country code */
+		if ((cntry = wlc_cntry_name_to_country(argv[1])) != NULL) {
+			/* arg matched a country name */
+			memcpy(cspec.country_abbrev, cntry->abbrev, WLC_CNTRY_BUF_SZ);
+		} else {
+			int rev;
+			err = wl_parse_country_spec(argv[1], cspec.country_abbrev, &rev);
+			if (rev != -1) {
+				fprintf(stderr,
+					"Argument \"%s\" had a revision. Arg 2 must be "
+					"a country name or country code without a revision\n",
+					argv[1]);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		if (err) {
+			fprintf(stderr,
+				"Argument 2 \"%s\" could not be parsed as "
+				"a country name or country code\n",
+				argv[1]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* first try the country iovar */
+	if (cspec.rev == -1 && cspec.ccode[0] == '\0')
+		err = wlu_iovar_set(wl, "country", &cspec, WLC_CNTRY_BUF_SZ);
+	else {
+		cspec.rev = htod32(cspec.rev);
+		err = wlu_iovar_set(wl, "country", &cspec, sizeof(cspec));
+	}
+
+	if (err == 0)
+		return 0;
+
+	/* if there was an error other than BCME_UNSUPPORTED, fail now */
+	wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+	if (bcmerr != BCME_UNSUPPORTED)
+		return err;
+
+	/* if the "country" iovar is unsupported, try the WLC_SET_COUNTRY ioctl if possible */
+
+	if (cspec.rev != -1 || cspec.ccode[0] != '\0') {
+		fprintf(stderr,
+			"Driver does not support full country spec interface, "
+			"only a country name or code may be sepcified\n");
+		return err;
+	}
+
+	/* use the legacy ioctl */
+	err = wlu_set(wl, WLC_SET_COUNTRY, cspec.country_abbrev, WLC_CNTRY_BUF_SZ);
+
+	return err;
+}
+
+int
+wl_country_ie_override(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc = 0;
+	int error, i;
+
+	/* skip the command name */
+	argv++;
+
+	/* find the arg count */
+	while (argv[argc])
+		argc++;
+
+	if (argc == 0) {
+		void *ptr;
+		bcm_tlv_t *ie;
+
+		if ((error = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return (error);
+
+		ie = (bcm_tlv_t *)ptr;
+
+		printf("ie tag:0x%x ie len:0x%x ie data:", ie->id, ie->len);
+
+		for (i = 0; i < ie->len; i++)
+			printf("0x%x ", ie->data[i]);
+
+		printf("\n");
+
+		return error;
+
+	} else {
+		/* Set */
+		char *endptr = NULL;
+		uchar *valsp;
+		int8 ie_len, pad = 0;
+
+		/* retrieve the ie len in advance to check for padding */
+		ie_len = (int8)strtol(*(argv + 1), NULL, 0);
+		if (ie_len & 1) {
+			fprintf(stderr, "country ie len is odd(%d), padding by 1 octet\n", ie_len);
+			pad = 1;
+		}
+
+		valsp = (uchar*)malloc(argc + pad);
+		if (valsp == NULL) {
+			fprintf(stderr, "Error allocating %d bytes country ie\n", argc);
+			return BCME_NOMEM;
+		}
+		memset(valsp, 0, argc + pad);
+
+		for (i = 0; i < argc; i++, argv++) {
+
+			valsp[i] = (uchar)strtol(*argv, &endptr, 0);
+
+			/* make sure all the value string was parsed by strtol */
+			if (*endptr != '\0') {
+				free(valsp);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/* update ie len if padded */
+		if (pad) {
+			valsp[1] += 1;
+			valsp[ie_len + TLV_HDR_LEN] = 0;
+		}
+
+		error = wlu_var_setbuf(wl, cmd->name, valsp, argc + pad);
+
+		free(valsp);
+
+		return error;
+	}
+}
+
+#define ACI_SPIN	"spin"
+#define ACI_ENTER	"enter"
+#define ACI_EXIT	"exit"
+#define ACI_GLITCH	"glitch"
+
+#define NPHY_ACI_ADCPWR_ENTER "adcpwr_enter"
+#define NPHY_ACI_ADCPWR_EXIT "adcpwr_exit"
+#define NPHY_ACI_REPEAT_CTR "repeat"
+#define NPHY_ACI_NUM_SAMPLES "samples"
+#define NPHY_ACI_UNDETECT "undetect_sz"
+#define NPHY_ACI_LOPWR "loaci"
+#define NPHY_ACI_MDPWR "mdaci"
+#define NPHY_ACI_HIPWR "hiaci"
+#define NPHY_ACI_NOISE_NOASSOC_GLITCH_TH_UP "nphy_noise_noassoc_glitch_th_up"
+#define NPHY_ACI_NOISE_NOASSOC_GLITCH_TH_DN "nphy_noise_noassoc_glitch_th_dn"
+#define NPHY_ACI_NOISE_ASSOC_GLITCH_TH_UP "nphy_noise_assoc_glitch_th_up"
+#define NPHY_ACI_NOISE_ASSOC_GLITCH_TH_DN "nphy_noise_assoc_glitch_th_dn"
+#define NPHY_ACI_NOISE_ASSOC_ACI_GLITCH_TH_UP "nphy_noise_assoc_aci_glitch_th_up"
+#define NPHY_ACI_NOISE_ASSOC_ACI_GLITCH_TH_DN "nphy_noise_assoc_aci_glitch_th_dn"
+#define NPHY_ACI_NOISE_NOASSOC_ENTER_TH "nphy_noise_noassoc_enter_th"
+#define NPHY_ACI_NOISE_ASSOC_ENTER_TH "nphy_noise_assoc_enter_th"
+#define NPHY_ACI_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH \
+"nphy_noise_assoc_rx_glitch_badplcp_enter_th"
+#define NPHY_ACI_NOISE_ASSOC_CRSIDX_INCR "nphy_noise_assoc_crsidx_incr"
+#define NPHY_ACI_NOISE_NOASSOC_CRSIDX_INCR "nphy_noise_noassoc_crsidx_incr"
+#define NPHY_ACI_NOISE_CRSIDX_DECR "nphy_noise_crsidx_decr"
+
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+static int
+wl_do_samplecollect_lcn40(void *wl, wl_samplecollect_args_t *collect, uint8 *buff, FILE *fp)
+{
+	uint32 cnt;
+	int ret = 0;
+	uint32 *data;
+	int16 IData, QData;
+	uint16 wordlength = 14;
+	uint16 mask = ((0x1 << wordlength) - 1);
+	uint16 wrap = (0x1 << (wordlength - 1));
+	uint16 maxd = (0x1 << wordlength);
+
+	ret = wlu_iovar_getbuf(wl, "sample_collect", collect, sizeof(wl_samplecollect_args_t),
+		buff, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	data = (uint32*)buff;
+	for (cnt = 0; cnt < collect->nsamps; cnt++) {
+
+		IData = data[cnt] & mask;
+		QData = ((data[cnt] >> 16) & mask);
+
+		if (IData >= wrap) {
+			IData = IData - maxd;
+		}
+		if (QData >= wrap) {
+			QData = QData - maxd;
+		}
+		fprintf(fp, "%d %d\n", IData, QData);
+	}
+	return cnt;
+}
+static int
+wl_do_samplecollect_n(void *wl, wl_samplecollect_args_t *collect, uint8 *buff, FILE *fp)
+{
+	uint16 nbytes;
+	int ret = 0;
+
+	ret = wlu_iovar_getbuf(wl, "sample_collect", collect, sizeof(wl_samplecollect_args_t),
+		buff, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	/* bytes 1:0 indicate capture length */
+	while ((nbytes = ltoh16_ua(buff))) {
+		nbytes += 2;
+		ret = fwrite(buff, 1, nbytes, fp);
+		if (ret != nbytes) {
+			fprintf(stderr, "Error writing %d bytes to file, rc %d!\n",
+				nbytes, ret);
+			ret = -1;
+			break;
+		} else {
+			fprintf(stderr, "Wrote %d bytes\n", nbytes);
+		}
+		buff += nbytes;
+	}
+	return (ret);
+}
+#endif /* defined(BWL_FILESYSTEM_SUPPORT) */
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+static int
+wl_do_samplecollect(void *wl, wl_samplecollect_args_t *collect, int sampledata_version,
+	uint32 *buff, FILE *fp)
+{
+	uint16 nbytes, tag;
+	uint32 flag, *header, sync;
+	uint8 *ptr;
+	int err;
+	wl_sampledata_t *sample_collect;
+	wl_sampledata_t sample_data, *psample;
+
+	err = wlu_iovar_getbuf(wl, "sample_collect", collect, sizeof(wl_samplecollect_args_t),
+		buff, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if (err)
+		return err;
+
+	sample_collect = (wl_sampledata_t *)buff;
+	header = (uint32 *)&sample_collect[1];
+	tag = ltoh16_ua(&sample_collect->tag);
+	if (tag != WL_SAMPLEDATA_HEADER_TYPE) {
+		fprintf(stderr, "Expect SampleData Header type %d, receive type %d\n",
+			WL_SAMPLEDATA_HEADER_TYPE, tag);
+		return -1;
+	}
+
+	nbytes = ltoh16_ua(&sample_collect->length);
+	flag = ltoh32_ua(&sample_collect->flag);
+	sync = ltoh32_ua(&header[0]);
+	if (sync != 0xACDC2009) {
+		fprintf(stderr, "Header sync word mismatch (0x%08x)\n", sync);
+		return -1;
+	}
+
+	err = fwrite((uint8 *)header, 1, nbytes, fp);
+	if (err != (int)nbytes)
+		  fprintf(stderr, "Failed write file-header to file %d\n", err);
+
+	memset(&sample_data, 0, sizeof(wl_sampledata_t));
+	sample_data.version = sampledata_version;
+	sample_data.size = htol16(sizeof(wl_sampledata_t));
+	flag = 0;
+	/* new format, used in htphy */
+	do {
+		sample_data.tag = htol16(WL_SAMPLEDATA_TYPE);
+		sample_data.length = htol16(WLC_SAMPLECOLLECT_MAXLEN);
+		/* mask seq# */
+	        sample_data.flag = htol32((flag & 0xff));
+
+		err = wlu_iovar_getbuf(wl, "sample_data", &sample_data, sizeof(wl_sampledata_t),
+			buff, WLC_SAMPLECOLLECT_MAXLEN);
+		if (err) {
+			fprintf(stderr, "Error reading back sample collected data\n");
+			err = -1;
+			break;
+		}
+
+		ptr = (uint8 *)buff + sizeof(wl_sampledata_t);
+		psample = (wl_sampledata_t *)buff;
+		tag = ltoh16_ua(&psample->tag);
+		nbytes = ltoh16_ua(&psample->length);
+		flag = ltoh32_ua(&psample->flag);
+		if (tag != WL_SAMPLEDATA_TYPE) {
+			fprintf(stderr, "Expect SampleData type %d, receive type %d\n",
+				WL_SAMPLEDATA_TYPE, tag);
+			err = -1;
+			break;
+		}
+		if (nbytes == 0) {
+			fprintf(stderr, "Done retrieving sample data\n");
+			err = -1;
+			break;
+		}
+
+		err = fwrite(ptr, 1, nbytes, fp);
+		if (err != (int)nbytes) {
+			fprintf(stderr, "Error writing %d bytes to file, rc %d!\n",
+				(int)nbytes, err);
+			err = -1;
+			break;
+		} else {
+			printf("Wrote %d bytes\n", err);
+			err = 0;
+		}
+	} while (flag & WL_SAMPLEDATA_MORE_DATA);
+	return err;
+}
+#endif /* defined(BWL_FILESYSTEM_SUPPORT) */
+
+static int
+wl_sample_collect(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#else
+	int ret = -1;
+	uint8 *buff = NULL;
+	wl_samplecollect_args_t collect;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint32 phyrev;
+	const char *fname = "sample_collect.dat";
+	FILE *fp = NULL;
+
+	/* Default setting for sampledata_version */
+	int sampledata_version = htol16(WL_SAMPLEDATA_T_VERSION);
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return ret;
+
+	phytype = dtoh32(revinfo.phytype);
+	phyrev = dtoh32(revinfo.phyrev);
+
+	/* Assign some default params first */
+	/* 60us is roughly the max we can store (for NPHY with NREV < 7). */
+	collect.coll_us = 60;
+	collect.cores = -1;
+	collect.bitStart = -1;
+	/* extended settings */
+	collect.trigger = TRIGGER_NOW;
+	collect.mode = 1;
+	collect.post_dur = 10;
+	collect.pre_dur = 10;
+	collect.gpio_sel = 0;
+	collect.downsamp = FALSE;
+	collect.be_deaf = FALSE;
+	collect.timeout = 1000;
+	collect.agc = FALSE;
+	collect.filter = FALSE;
+	collect.trigger_state = 0;
+	collect.module_sel1 = 2;
+	collect.module_sel2 = 6;
+	collect.nsamps = 2048;
+	collect.version = WL_SAMPLECOLLECT_T_VERSION;
+	collect.length = sizeof(wl_samplecollect_args_t);
+
+	/* Skip the command name */
+	argv++;
+	ret = -1;
+	while (*argv) {
+		char *s = *argv;
+
+		if (argv[1] == NULL) {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		if (!strcmp(s, "-f")) {
+			fname = argv[1];
+		} else if (!strcmp(s, "-u"))
+			collect.coll_us = atoi(argv[1]);
+		else if (!strcmp(s, "-c"))
+			collect.cores = atoi(argv[1]);
+		/* extended settings */
+		else if (!strcmp(s, "-t")) {
+			/* event trigger */
+			if (!strcmp(argv[1], "crs"))
+				collect.trigger = TRIGGER_CRS;
+			else if (!strcmp(argv[1], "crs_deassert"))
+				collect.trigger = TRIGGER_CRSDEASSERT;
+			else if (!strcmp(argv[1], "good_fcs"))
+				collect.trigger = TRIGGER_GOODFCS;
+			else if (!strcmp(argv[1], "bad_fcs"))
+				collect.trigger = TRIGGER_BADFCS;
+			else if (!strcmp(argv[1], "bad_plcp"))
+				collect.trigger = TRIGGER_BADPLCP;
+			else if (!strcmp(argv[1], "crs_glitch"))
+				collect.trigger = TRIGGER_CRSGLITCH;
+		}
+		else if (!strcmp(s, "-m")) {
+			if (!strcmp(argv[1], "gpio")) {
+				if (phytype == WLC_PHY_TYPE_HT) {
+					collect.mode = 4;
+				} else {
+					/* MIMOPHY */
+					collect.mode = 0xff;
+				}
+			} else {
+			collect.mode = atoi(argv[1]);
+			}
+		}
+		else if (!strcmp(s, "-k"))
+			collect.gpioCapMask = atoi(argv[1]);
+		else if (!strcmp(s, "-s"))
+			collect.bitStart = atoi(argv[1]);
+		else if (!strcmp(s, "-b"))
+			collect.pre_dur = atoi(argv[1]);
+		else if (!strcmp(s, "-a"))
+			collect.post_dur = atoi(argv[1]);
+		else if (!strcmp(s, "-g"))
+			collect.gpio_sel = atoi(argv[1]);
+		else if (!strcmp(s, "-d"))
+			collect.downsamp = atoi(argv[1]);
+		else if (!strcmp(s, "-e"))
+			collect.be_deaf = atoi(argv[1]);
+		else if (!strcmp(s, "-i"))
+			collect.timeout = atoi(argv[1]);
+		else if (!strcmp(s, "--agc")) {
+			/* perform software agc for sample collect */
+			collect.agc = atoi(argv[1]);
+		}
+		else if (!strcmp(s, "--filter")) {
+			/* Set HPC for LPF to lowest possible value (0x1) */
+			collect.filter = atoi(argv[1]);
+		}
+		else if (!strcmp(s, "-v"))
+			 sampledata_version = atoi(argv[1]);
+		else if (!strcmp(s, "-s"))
+			collect.trigger_state = atoi(argv[1]);
+		else if (!strcmp(s, "-x"))
+			collect.module_sel1 = atoi(argv[1]);
+		else if (!strcmp(s, "-y"))
+			collect.module_sel2 = atoi(argv[1]);
+		else if (!strcmp(s, "-n"))
+			collect.nsamps = atoi(argv[1]);
+		else {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		argv += 2;
+	}
+
+	buff = malloc(WLC_SAMPLECOLLECT_MAXLEN);
+	if (buff == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n",
+			WLC_SAMPLECOLLECT_MAXLEN);
+		return BCME_NOMEM;
+	}
+	memset(buff, 0, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if ((fp = fopen(fname, "wb")) == NULL) {
+		fprintf(stderr, "Problem opening file %s\n", fname);
+		ret = BCME_BADARG;
+		goto exit;
+	}
+
+	if ((phytype == WLC_PHY_TYPE_HT) || (phytype == WLC_PHY_TYPE_AC)) {
+		ret = wl_do_samplecollect(wl, &collect, sampledata_version, (uint32 *)buff, fp);
+	}
+	else if (phytype == WLC_PHY_TYPE_N) {
+		if (phyrev < 7) {
+		ret = wl_do_samplecollect_n(wl, &collect, buff, fp);
+		} else {
+			ret = wl_do_samplecollect(wl, &collect, sampledata_version,
+				(uint32 *)buff, fp);
+		}
+	} else if (phytype == WLC_PHY_TYPE_LCN40) {
+		if (collect.nsamps > (WLC_SAMPLECOLLECT_MAXLEN >> 2)) {
+			fprintf(stderr, "Max number of samples supported = %d\n",
+				WLC_SAMPLECOLLECT_MAXLEN >> 2);
+			ret = -1;
+			goto exit;
+		}
+		ret = wl_do_samplecollect_lcn40(wl, &collect, buff, fp);
+	}
+exit:
+	if (buff) free(buff);
+	if (fp) fclose(fp);
+	return ret;
+#endif /* !BWL_FILESYSTEM_SUPPORT */
+}
+
+/* WLOTA_EN START */
+#define WL_OTA_STRING_MAX_LEN		100
+#define WL_OTA_CMDSTREAM_MAX_LEN	200
+
+/* test_setup cmd argument ordering */
+enum {
+	WL_OTA_SYNC_TIMEOUT = 1,	/* Timeout in seconds */
+	WL_OTA_SYNCFAIL_ACTION,		/* Fail actio -1/0/1 */
+	WL_OTA_SYNC_MAC,		/* Mac address for sync */
+	WL_OTA_TX_MAC,			/* Mac address for tx test */
+	WL_OTA_RX_MAC,			/* Mac address for rx test */
+	WL_OTA_LOOP_TEST		/* Put test into loop mode */
+};
+
+/* ota_tx / ota_rx format ordering */
+enum {
+	WL_OTA_CUR_TEST,		/* ota_tx or ota_rx */
+	WL_OTA_CHAN,			/* cur channel */
+	WL_OTA_BW,			/* cur bandwidth */
+	WL_OTA_CONTROL_BAND,		/* cur control band */
+	WL_OTA_RATE,			/* cur rate */
+	WL_OTA_STF_MODE,		/* cur stf mode */
+	WL_OTA_TXANT,			/* tx ant to be used */
+	WL_OTA_RXANT,			/* rx ant to be used */
+	WL_OTA_TX_IFS,			/* ifs */
+	WL_OTA_TX_PKT_LEN,		/* pkt length */
+	WL_OTA_TX_NUM_PKT,		/* num of packets */
+	WL_OTA_PWR_CTRL_ON,		/* power control on/off */
+	WL_OTA_PWR_SWEEP		/* start:delta:stop */
+};
+/* Various error chcking options */
+enum {
+	WL_OTA_SYNCFAILACTION,
+	WL_OTA_CTRLBANDVALID,
+	WL_OTA_TXANTVALID,
+	WL_OTA_RXANTVALID,
+	WL_OTA_PWRCTRLVALID
+};
+/* Display init test seq */
+static void
+wl_ota_display_test_init_info(wl_ota_test_status_t *init_info)
+{
+	printf("Test Init Summary\n");
+	printf("----------------------------------------------------------\n");
+	printf("Toatl Number of test req %d\n\n", init_info->test_cnt);
+	printf("Sync timeout %d synch fail action: %d \n", init_info->sync_timeout,
+		init_info->sync_fail_action);
+	printf("Sync Mac address : \t");
+	printf("%s\n", wl_ether_etoa(&(init_info->sync_mac)));
+	printf("Tx Mac address : \t");
+	printf("%s\n", wl_ether_etoa(&(init_info->tx_mac)));
+	printf("Rx Mac address : \t");
+	printf("%s\n", wl_ether_etoa(&(init_info->rx_mac)));
+	printf("Test in Loop mode : %d \n", init_info->loop_test);
+	printf("\n\n\n");
+}
+static void
+wl_ota_display_rt_info(uint8 rate)
+{
+#ifndef D11AC_IOTYPES
+	if (rate & NRATE_MCS_INUSE) {
+		printf("m");
+		printf("%d ", rate & NRATE_RATE_MASK);
+	} else if (rate == 11) {
+		printf("5.5 ");
+	} else {
+		printf("%d ", (rate & NRATE_RATE_MASK) / 2);
+	}
+#else
+	printf("format changed : fix it %x \n", rate);
+#endif
+}
+/* display nth tesr arg details */
+static void
+wl_ota_display_test_option(wl_ota_test_args_t *test_arg, int16 cnt)
+{
+	uint8 i;
+	printf("Test cnt %d  \n", cnt);
+	printf("-----------------------------------------------------------\n");
+	printf("Curr Test : %s\n", ((test_arg->cur_test == 0) ? "TX" : "RX"));
+	printf("Wait for sync enabled %d \n", test_arg->wait_for_sync);
+	printf("Channel : %d", test_arg->chan);
+	printf("\t Bandwidth : %s ", ((test_arg->bw == WL_OTA_TEST_BW_20MHZ) ? "20" :
+		((test_arg->bw == WL_OTA_TEST_BW_40MHZ) ? "40" : "20 in 40")));
+	printf("\t Control Band : %c \n",  test_arg->control_band);
+	printf("Rates : ");
+	for (i = 0; i < test_arg->rt_info.rate_cnt; i++)
+		wl_ota_display_rt_info(test_arg->rt_info.rate_val_mbps[i]);
+	printf("\nStf mode :  %d \n", test_arg->stf_mode);
+	printf("Txant: %d   rxant: %d \n", test_arg->txant, test_arg->rxant);
+	printf("Pkt eng Options :  ifs %d  len: %d num: %d \n", test_arg->pkteng.delay,
+		test_arg->pkteng.length, test_arg->pkteng.nframes);
+	printf("Tx power sweep options :\nPower control %d \nstart pwr: %d  "
+		"delta: %d end pwr : %d \n", test_arg->pwr_info.pwr_ctrl_on,
+		test_arg->pwr_info.start_pwr, test_arg->pwr_info.delta_pwr,
+		test_arg->pwr_info.end_pwr);
+}
+/* do minimum string validations possible */
+/* Make stricter conditions in future */
+static int
+wl_ota_validate_string(uint8 arg, void* value)
+{
+	int ret = 0;
+	switch (arg) {
+		case WL_OTA_TXANTVALID:
+		case WL_OTA_RXANTVALID:
+			if (*(uint8*)value > 3)
+				ret = -1;
+			break;
+		case WL_OTA_CTRLBANDVALID:
+			if ((strncmp((char *)value, "l", 1)) && (strncmp((char *)value, "u", 1)))
+				ret = -1;
+			break;
+		case WL_OTA_PWRCTRLVALID:
+		case WL_OTA_SYNCFAILACTION:
+			if ((*(int8 *)value < -1) || (*(int8 *)value > 1))
+				ret = -1;
+			break;
+		default:
+			break;
+	}
+	return ret;
+}
+
+
+/* convert power info string to integer */
+/* start:delta:end */
+static int
+wl_ota_pwrinfo_parse(const char *tok_bkp, wl_ota_test_args_t *test_arg)
+{
+	char *endptr = NULL;
+	int ret = 0;
+
+	/* convert string to int */
+	/* Read start pwr */
+	test_arg->pwr_info.start_pwr = (int8)strtol(tok_bkp, &endptr, 10);
+	if (*endptr == ':') {
+		endptr++;
+		tok_bkp = endptr;
+	} else {
+		return -1;
+	}
+	/* read delta pwr */
+	test_arg->pwr_info.delta_pwr = (int8)strtol(tok_bkp, &endptr, 10);
+	if (*endptr == ':') {
+		endptr++;
+		tok_bkp = endptr;
+	} else {
+		return -1;
+	}
+	/* read end pwr */
+	test_arg->pwr_info.end_pwr = (int8)strtol(tok_bkp, &endptr, 10);
+
+	if ((*endptr != '\0') && (*endptr != '\n') && (*endptr != ' '))
+		ret = -1;
+
+	return ret;
+}
+
+/* parsing the test init seq line */
+static int
+wl_ota_parse_test_init(wl_ota_test_vector_t * init_info, char * tok, uint16 cnt)
+{
+	int ret = 0;
+	char * endptr = NULL;
+
+	switch (cnt) {
+		case WL_OTA_SYNC_TIMEOUT:
+			init_info->sync_timeout = (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_SYNCFAIL_ACTION:
+			init_info->sync_fail_action = (int8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0') {
+				ret = -1;
+				break;
+			} else {
+				ret = wl_ota_validate_string(WL_OTA_SYNCFAILACTION,
+					&(init_info->sync_fail_action));
+			}
+			break;
+		case WL_OTA_SYNC_MAC:
+			if (!wl_ether_atoe(tok, &(init_info->sync_mac)))
+				ret = -1;
+			break;
+		case WL_OTA_TX_MAC:
+			if (!wl_ether_atoe(tok, &(init_info->tx_mac)))
+				ret = -1;
+			break;
+		case WL_OTA_RX_MAC:
+			if (!wl_ether_atoe(tok, &(init_info->rx_mac)))
+				ret = -1;
+			break;
+		case WL_OTA_LOOP_TEST:
+			init_info->loop_test = (int8)strtol(tok, &endptr, 10);
+
+			if ((*endptr != '\0') && (*endptr != '\n') && (*endptr != ' '))
+				ret = -1;
+			break;
+		default:
+			break;
+	}
+	return ret;
+}
+/* parse test arguments */
+static int
+wl_ota_test_parse_test_option(wl_ota_test_args_t *test_arg, char * tok, uint16 cnt,
+	char rt_string[])
+{
+	char * endptr = NULL;
+	uint16 tok_len = 0;
+	int ret = 0;
+
+	if (test_arg->cur_test == WL_OTA_TEST_RX) {
+		switch (cnt) {
+			case WL_OTA_PWR_CTRL_ON:
+			case WL_OTA_PWR_SWEEP:
+				return 0;
+				break;
+			default:
+				break;
+		}
+	}
+	switch (cnt) {
+		case WL_OTA_CUR_TEST:
+			if (strncmp(tok, "ota_tx", 6) == 0)
+				test_arg->cur_test = WL_OTA_TEST_TX;
+			else if (strncmp(tok, "ota_rx", 6) == 0)
+				test_arg->cur_test = WL_OTA_TEST_RX;
+			else
+				ret = -1;
+			break;
+		case WL_OTA_CHAN:
+			test_arg->chan = (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_BW:
+			if (strncmp(tok, "20/40", 5) == 0) {
+				test_arg->bw = WL_OTA_TEST_BW_20_IN_40MHZ;
+			} else if (strncmp(tok, "20", 2) == 0) {
+				test_arg->bw = WL_OTA_TEST_BW_20MHZ;
+			} else if (strncmp(tok, "40", 2) == 0) {
+				test_arg->bw = WL_OTA_TEST_BW_40MHZ;
+			} else {
+				ret = -1;
+			}
+			break;
+		case WL_OTA_CONTROL_BAND:
+			test_arg->control_band = *tok;
+			ret = wl_ota_validate_string(WL_OTA_CTRLBANDVALID, tok);
+			break;
+		case WL_OTA_RATE:
+			tok_len = strlen(tok);
+			if (tok_len > WL_OTA_STRING_MAX_LEN) {
+				ret = -1;
+				goto fail;
+			}
+			strncpy(rt_string, tok, tok_len);
+			break;
+		case WL_OTA_STF_MODE:
+#ifndef D11AC_IOTYPES
+			if (strncmp(tok, "siso", 4) == 0)
+				test_arg->stf_mode = NRATE_STF_SISO;
+			else if (strncmp(tok, "cdd", 3) == 0)
+				test_arg->stf_mode = NRATE_STF_CDD;
+			else if (strncmp(tok, "stbc", 4) == 0)
+				test_arg->stf_mode = NRATE_STF_STBC;
+			else if (strncmp(tok, "sdm", 3) == 0)
+				test_arg->stf_mode = NRATE_STF_SDM;
+			else
+				ret = -1;
+#endif
+			break;
+		case WL_OTA_TXANT:
+			test_arg->txant =  (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0') {
+				ret = -1;
+				goto fail;
+			}
+			ret = wl_ota_validate_string(WL_OTA_TXANTVALID, &test_arg->txant);
+			break;
+		case WL_OTA_RXANT:
+			test_arg->rxant = (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0') {
+				ret = -1;
+				goto fail;
+			}
+			ret = wl_ota_validate_string(WL_OTA_RXANTVALID, &test_arg->rxant);
+			break;
+		case WL_OTA_TX_IFS:
+			test_arg->pkteng.delay =  (uint16)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_TX_PKT_LEN:
+			test_arg->pkteng.length = (uint16)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_TX_NUM_PKT:
+			test_arg->pkteng.nframes = (uint16)strtol(tok, &endptr, 10);
+			if ((*endptr != '\0') && (*endptr != '\n') && (*endptr != ' '))
+				ret = -1;
+			break;
+		case WL_OTA_PWR_CTRL_ON:
+			test_arg->pwr_info.pwr_ctrl_on = (int8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0') {
+				ret = -1;
+				goto fail;
+			}
+			ret = wl_ota_validate_string(WL_OTA_PWRCTRLVALID,
+				&test_arg->pwr_info.pwr_ctrl_on);
+			break;
+		case WL_OTA_PWR_SWEEP:
+			ret = wl_ota_pwrinfo_parse(tok, test_arg);
+		default:
+			break;
+	}
+
+fail:
+	return ret;
+}
+static int
+wl_ota_test_parse_rate_string(wl_ota_test_args_t *test_arg, char rt_string[100])
+{
+
+	uint8 cnt = 0;
+	char * tok = NULL;
+	char rate_st[5] = "\0";
+	uint8 int_val = 0;
+	uint16 tok_len = 0;
+	int ret = 0;
+	tok = strtok(rt_string, ",");
+
+	/* convert rate strings to int array */
+	while (tok != NULL) {
+		strncpy(rate_st, " ", 4);
+		/* skip rate parsing if its rx test case */
+		if (test_arg->cur_test == WL_OTA_TEST_RX) {
+			test_arg->rt_info.rate_val_mbps[cnt] = 0;
+			cnt = 1;
+			break;
+		}
+
+		/* Support a max of 30 rates */
+		if (cnt >= WL_OTA_TEST_MAX_NUM_RATE) {
+			ret = -1;
+			break;
+		}
+		tok_len = strlen(tok);
+		if (tok_len > 5) {
+			ret = -1;
+			break;
+		}
+		strncpy(rate_st, tok, tok_len);
+		if (strncmp(rate_st, "5.5", 3) == 0) {
+			int_val = 11;
+		} else {
+			if (rate_st[0] == 'm') {
+				rate_st[0] = ' ';
+				int_val = atoi(rate_st);
+#ifndef D11AC_IOTYPES
+				int_val |= NRATE_MCS_INUSE;
+#endif
+			} else {
+				int_val = 2 * atoi(rate_st);
+			}
+		}
+		test_arg->rt_info.rate_val_mbps[cnt] = int_val;
+		tok = strtok(NULL, ",");
+		cnt++;
+	}
+	test_arg->rt_info.rate_cnt = cnt;
+	return ret;
+}
+static int
+wl_ota_test_parse_arg(char line[], wl_ota_test_vector_t *ota_test_vctr, uint16 *test_cnt,
+	uint8 *ota_sync_found)
+{
+	char * tok = NULL;
+	char rt_string[WL_OTA_STRING_MAX_LEN] = "\0";
+	uint16 cnt = 0;
+	int ret = 0;
+	tok = strtok(line, " ");
+
+	/* Initialize the power arguments */
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.pwr_ctrl_on = -1;
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.start_pwr = -1;
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.delta_pwr = -1;
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.end_pwr = -1;
+
+	if (!strncmp(tok, "test_setup", 10))  {
+		/* Parse test setup details */
+		cnt = 0;
+		while (tok != NULL) {
+			if ((ret = wl_ota_parse_test_init(ota_test_vctr, tok, cnt)) != 0)
+				return ret;
+			tok = strtok(NULL, " ");
+			cnt++;
+		}
+	} else if (!(strncmp(tok, "ota_tx", 6)) || (!strncmp(tok, "ota_rx", 6))) {
+		/* parse tx /rx test argumenst */
+		cnt = 0;
+		while (tok != NULL) {
+			if ((ret = wl_ota_test_parse_test_option
+				(&(ota_test_vctr->test_arg[*test_cnt]),
+				tok, cnt, rt_string)) != 0) {
+				goto fail;
+			}
+			tok = strtok(NULL, " ");
+			cnt++;
+		}
+
+		/* split rate string into integer array */
+		if ((ret = wl_ota_test_parse_rate_string(&(ota_test_vctr->test_arg[*test_cnt]),
+			rt_string)) != 0) {
+			goto fail;
+		}
+
+		/* Add sync option if specified by user */
+		ota_test_vctr->test_arg[*test_cnt].wait_for_sync  = (*ota_sync_found);
+
+		/* Reset ota_sync_found for next test arg */
+		*ota_sync_found = 0;
+
+		/* Increment test cnt */
+		*test_cnt = *test_cnt + 1;
+	} else if (strncmp(tok, "ota_sync", 8) == 0) {
+		/* detect if a sync packet is required */
+		*ota_sync_found = 1;
+		ret = 0;
+	}
+fail:
+	return (ret);
+}
+static int
+wl_load_cmd_stream(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	char test_arg[WL_OTA_CMDSTREAM_MAX_LEN] = "\0";
+	uint16 test_cnt = 0;
+	uint8 * ptr1 = NULL;
+	uint8 i, num_loop = 0;
+	uint8 ota_sync_found = 0;
+
+	wl_seq_cmd_pkt_t *next_cmd;
+	wl_ota_test_vector_t *ota_test_vctr = NULL;
+
+	argv++;
+
+	if (*argv == NULL) {
+		return ret;
+	} else if (!strncmp(argv[0], "start", 5)) {
+		ret = wl_seq_start(wl, cmd, argv);
+	} else if (!strncmp(argv[0], "stop", 4)) {
+		ret = 0;
+		/* test info pointer */
+		ota_test_vctr = (wl_ota_test_vector_t *)malloc(sizeof(wl_ota_test_vector_t));
+
+		if (ota_test_vctr == NULL) {
+			fprintf(stderr, "Failed to allocate  %d bytes of memory \n",
+				(uint16)sizeof(wl_ota_test_vector_t));
+			return BCME_NOMEM;
+		}
+
+		/* Assign a new pointer so that byte wise operation is possible */
+		ptr1 = (uint8 *)ota_test_vctr;
+
+		/* Passing test structure to dongle happens in steps */
+		/* For OTA implementations its split up into chunks of 1200 bytes */
+		num_loop = sizeof(wl_ota_test_vector_t) / WL_OTA_ARG_PARSE_BLK_SIZE;
+
+		if (!cmd_batching_mode) {
+			printf("calling ota_stream stop when it's already out of batching mode\n");
+			ret = BCME_ERROR;
+			goto fail;
+		}
+		cmd_batching_mode = FALSE;
+		next_cmd = cmd_list.head;
+		if (next_cmd == NULL) {
+			printf("no command batched\n");
+			ret = 0;
+			goto fail;
+		}
+		test_cnt = 0;
+		while (next_cmd != NULL) {
+			/* Max number of test options is ARRAYSIZE(ota_test_vctr->test_arg) */
+			if (test_cnt == ARRAYSIZE(ota_test_vctr->test_arg))
+				break;
+
+			if ((ret = wl_ota_test_parse_arg(next_cmd->data, ota_test_vctr, &test_cnt,
+				&ota_sync_found)) != 0) {
+				printf("Error Parsing the test command \n");
+				ret = BCME_BADARG;
+				goto fail;
+			}
+			next_cmd = next_cmd->next;
+		}
+		ota_test_vctr->test_cnt = test_cnt;
+		/* Full size of wl_ota_test_vector_t can not be parse through wl */
+		/* max size whihc can be passed from host to dongle is limited by eth size */
+		for (i = 0; i <= num_loop; i++) {
+			/* pass on the test info to wl->test_info structure */
+			if ((ret = wlu_var_setbuf(wl, "ota_loadtest", ptr1 + i *
+				WL_OTA_ARG_PARSE_BLK_SIZE, WL_OTA_ARG_PARSE_BLK_SIZE)) < 0) {
+				fprintf(stderr, "host to dongle download failed to pass  %d"
+					"bytes in stage %d \n",
+					WL_OTA_ARG_PARSE_BLK_SIZE, i);
+			}
+		}
+fail:
+		clean_up_cmd_list();
+		free(ota_test_vctr);
+	} else {
+		while (*argv) {
+			strncat(test_arg, *argv, strlen(*argv));
+			strncat(test_arg, " ", 1);
+			argv++;
+		}
+		return add_one_batched_cmd(WLC_SET_VAR, test_arg, strlen(test_arg));
+
+	}
+	return ret;
+}
+
+static int
+wl_ota_loadtest(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	FILE *fp;
+	const char *fname = "ota_test.txt";
+	char line[WL_OTA_CMDSTREAM_MAX_LEN] = "\0";
+	char line_bkp[WL_OTA_CMDSTREAM_MAX_LEN] = "\0";
+	uint16 test_cnt = 0;
+	uint8 * ptr1 = NULL;
+	uint8 i, num_loop = 0;
+	uint8 ota_sync_found = 0;
+	wl_ota_test_vector_t *ota_test_vctr = NULL;
+
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd);
+
+	/* Read the file name */
+	if (argv[1]) {
+		fname = argv[1];
+	}
+
+	/* test info pointer */
+	ota_test_vctr = (wl_ota_test_vector_t *)malloc(sizeof(wl_ota_test_vector_t));
+
+	if (ota_test_vctr == NULL) {
+		fprintf(stderr, "Failed to allocate  %d bytes of memory \n",
+			(uint16)sizeof(wl_ota_test_vector_t));
+		return BCME_NOMEM;
+	}
+
+	/* Assign a new pointer so that byte wide operation is possible */
+	ptr1 = (uint8 *)ota_test_vctr;
+
+	/* find number of iterations required to parse full block form host to dongle */
+	num_loop = sizeof(wl_ota_test_vector_t) / WL_OTA_ARG_PARSE_BLK_SIZE;
+
+
+	/* open the flow file */
+	if ((fp = fopen(fname, "r")) == NULL) {
+		fprintf(stderr, "Problem opening file %s\n", fname);
+		free(ota_test_vctr);
+		return BCME_BADARG;
+	}
+
+	test_cnt = 0;
+	while (1) {
+		fgets(line, WL_OTA_CMDSTREAM_MAX_LEN - 1, fp);
+
+		if (feof(fp)) {
+			break;
+		}
+
+		/* Max number of test options is ARRAYSIZE(ota_test_vctr->test_arg) */
+		if (test_cnt == ARRAYSIZE(ota_test_vctr->test_arg))
+			break;
+
+		strncpy(line_bkp, line, WL_OTA_CMDSTREAM_MAX_LEN - 1);
+
+		if ((ret = wl_ota_test_parse_arg(line_bkp, ota_test_vctr,
+			&test_cnt, &ota_sync_found)) != 0) {
+			printf("Flow File Error: \nError Parsing string : %s \n", line);
+			ret = BCME_BADARG;
+			goto fail;
+		}
+	}
+	if (ota_sync_found) {
+		ret = -1;
+		printf("Flow File Error : \nFile can not end with ota_sync\n");
+		goto fail;
+	}
+	ota_test_vctr->test_cnt = test_cnt;
+
+	/* Full size of wl_ota_test_vector_t can not be parse through wl */
+	/* max size whihc can be passed from host to dongle is limited by eth size */
+	for (i = 0; i <= num_loop; i++) {
+		/* pass on the test info to wl->test_info structure */
+		if ((ret = wlu_var_setbuf(wl, cmd->name, ptr1 + i * WL_OTA_ARG_PARSE_BLK_SIZE,
+			WL_OTA_ARG_PARSE_BLK_SIZE)) < 0) {
+			fprintf(stderr, "host to dongle download failed to pass  %d"
+				"bytes in stage %d \n",
+				WL_OTA_ARG_PARSE_BLK_SIZE, i);
+			break;
+		}
+	}
+fail:
+	/* close the fp */
+	if (fp)
+		fclose(fp);
+
+	free(ota_test_vctr);
+	return ret;
+}
+static void
+wl_otatest_display_skip_test_reason(int8 skip_test_reason)
+{
+	switch (skip_test_reason) {
+		case 0 :
+			printf("Test successfully finished\n");
+			break;
+		case WL_OTA_SKIP_TEST_CAL_FAIL:
+			printf("Phy cal Failure \n");
+			break;
+		case WL_OTA_SKIP_TEST_SYNCH_FAIL:
+			printf("Sync Packet failure \n");
+			break;
+		case WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL:
+			printf("File download Failure \n");
+			break;
+		case WL_OTA_SKIP_TEST_NO_TEST_FOUND:
+			printf("No test found in the flow file \n");
+			break;
+		case WL_OTA_SKIP_TEST_WL_NOT_UP:
+			printf("WL Not UP \n");
+			break;
+		case WL_OTA_SKIP_TEST_UNKNOWN_CALL:
+			printf("Erroneous scheduling of test. Not intended \n");
+			break;
+		default:
+			printf("Unknown test state \n");
+			break;
+	}
+}
+static int
+wl_otatest_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	int16 cnt = 0;
+	wl_ota_test_status_t *test_status = NULL;
+	wl_ota_test_vector_t *ota_test_vctr = NULL;
+
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd);
+
+	test_status = (wl_ota_test_status_t *)buf;
+	if (argv[1]) {
+
+		cnt = atoi(argv[1]);
+		if ((cnt < 1) || ((uint16)cnt > ARRAYSIZE(ota_test_vctr->test_arg))) {
+			printf("Error, Out of range \n");
+			return BCME_RANGE;
+		}
+		/* read nth test arg details */
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, &cnt, sizeof(uint16),
+			buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+		if (cnt > (test_status->test_cnt)) {
+			printf("Error : Number of test seq downloaded %d  \n",
+				test_status->test_cnt);
+			return BCME_RANGE;
+		}
+
+		/* Display Test init info */
+		wl_ota_display_test_init_info(test_status);
+
+		/* Dsiplay test arg info */
+		wl_ota_display_test_option(&(test_status->test_arg), cnt);
+	} else {
+		/* read back current state */
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, NULL, 0,
+			buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+		cnt = test_status->cur_test_cnt;
+
+		switch (test_status->test_stage) {
+			case WL_OTA_TEST_IDLE:		/* Idle state */
+				printf("Init state \n");
+				break;
+			case WL_OTA_TEST_ACTIVE:	/* Active test state */
+				/* Read back details for current test arg */
+				cnt++;
+				ret = wlu_iovar_getbuf(wl, cmd->name, &cnt, sizeof(uint16),
+					buf, WLC_IOCTL_MAXLEN);
+				if (test_status->sync_status == WL_OTA_SYNC_ACTIVE)
+					printf("Waiting for sync \n");
+				else
+					wl_ota_display_test_option(&(test_status->test_arg), cnt);
+				break;
+			case WL_OTA_TEST_SUCCESS:	/* Test Finished */
+				printf("Test completed \n");
+				break;
+			case WL_OTA_TEST_FAIL:		/* Test Failed to complete */
+				wl_otatest_display_skip_test_reason(test_status->skip_test_reason);
+				break;
+			default:
+				printf("Invalid test Phase \n");
+				break;
+		}
+	}
+	return ret;
+}
+/* To stop the ota test suite */
+static int
+wl_ota_teststop(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(argv);
+	return (wlu_iovar_setint(wl, cmd->name, 1));
+}
+/* WLOTA_EN END */
+
+static int
+wl_ampdu_activate_test(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_activate_test";
+	struct agg {
+		bool val1;
+		bool val2;
+	} x;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	x.val1 = atoi(param);
+	if ((param = *++argv)) {
+		x.val2 = atoi(param);
+		printf("%d %d\n", x.val1, x.val2);
+		err = wlu_var_setbuf(wl, cmdname, &x, sizeof(x));
+	}
+	return err;
+}
+
+static int
+wl_ampdu_tid(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_tid";
+	struct ampdu_tid_control atc, *reply;
+	uint8 tid;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	atc.tid = tid;
+
+	if ((param = *++argv)) {
+		atc.enable = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &atc, sizeof(atc));
+	} else {
+		if ((err = wlu_var_getbuf_sm(wl, cmdname, &atc, sizeof(atc), &ptr) < 0))
+			return err;
+		reply = (struct ampdu_tid_control *)ptr;
+		printf("AMPDU for tid %d: %d\n", tid, reply->enable);
+	}
+	return err;
+}
+
+static int
+wl_ampdu_retry_limit_tid(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_retry_limit_tid";
+	struct ampdu_retry_tid retry_limit, *reply;
+	uint8 tid;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	retry_limit.tid = tid;
+
+	if ((param = *++argv)) {
+		retry_limit.retry = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &retry_limit, sizeof(retry_limit));
+	} else {
+		if ((err = wlu_var_getbuf(wl, cmdname, &retry_limit,
+			sizeof(retry_limit), &ptr)) < 0)
+			return err;
+		reply = (struct ampdu_retry_tid *)ptr;
+		printf("AMPDU retry limit for tid %d: %d\n", tid, reply->retry);
+	}
+	return err;
+}
+
+static int
+wl_ampdu_rr_retry_limit_tid(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_rr_retry_limit_tid";
+	struct ampdu_retry_tid retry_limit, *reply;
+	uint8 tid;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	retry_limit.tid = tid;
+
+	if ((param = *++argv)) {
+		retry_limit.retry = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &retry_limit, sizeof(retry_limit));
+	} else {
+		if ((err = wlu_var_getbuf(wl, cmdname, &retry_limit,
+			sizeof(retry_limit), &ptr)) < 0)
+			return err;
+		reply = (struct ampdu_retry_tid *)ptr;
+		printf("AMPDU regular rate retry limit for tid %d: %d\n", tid, reply->retry);
+	}
+	return err;
+}
+
+
+static int
+wl_ampdu_send_addba(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_send_addba";
+	struct ampdu_ea_tid aet;
+	uint8 tid;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	aet.tid = tid;
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing address\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &aet.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	return wlu_var_setbuf(wl, cmdname, &aet, sizeof(aet));
+}
+
+static int
+wl_ampdu_send_delba(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_send_delba";
+	struct ampdu_ea_tid aet;
+	uint8 tid;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	aet.tid = tid;
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing address\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &aet.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	return wlu_var_setbuf(wl, cmdname, &aet, sizeof(aet));
+}
+
+static int
+wl_dpt_deny(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "dpt_deny";
+	dpt_iovar_t info;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	info.pad = 0;
+
+	if (!strcmp("add", *argv))
+		info.mode = DPT_DENY_LIST_ADD;
+	else if (!strcmp("remove", *argv))
+		info.mode = DPT_DENY_LIST_REMOVE;
+	else {
+		printf("error: invalid mode string\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing mode value\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &info.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	return wlu_var_setbuf(wl, cmdname, &info, sizeof(info));
+}
+
+static int
+wl_dpt_endpoint(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "dpt_endpoint";
+	dpt_iovar_t info;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	info.pad = 0;
+
+	if (!strcmp("create", *argv))
+		info.mode = DPT_MANUAL_EP_CREATE;
+	else if (!strcmp("modify", *argv))
+		info.mode = DPT_MANUAL_EP_MODIFY;
+	else if (!strcmp("delete", *argv))
+		info.mode = DPT_MANUAL_EP_DELETE;
+	else {
+		printf("error: invalid mode string\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing ea\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &info.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	return wlu_var_setbuf(wl, cmdname, &info, sizeof(info));
+}
+
+#ifdef WLTDLS
+static int
+wl_tdls_endpoint(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname_tdls = "tdls_endpoint";
+	tdls_iovar_t info;
+	chanspec_t chanspec;
+
+	if (strcmp(cmd->name, cmdname_tdls)) {
+		printf("error: invalid command name.\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	memset(&info, 0, sizeof(tdls_iovar_t));
+
+	if (!strcmp("create", *argv))
+		info.mode = TDLS_MANUAL_EP_CREATE;
+	else if (!strcmp("modify", *argv))
+		info.mode = TDLS_MANUAL_EP_MODIFY;
+	else if (!strcmp("delete", *argv))
+		info.mode = TDLS_MANUAL_EP_DELETE;
+	else if (!strcmp("PM", *argv))
+		info.mode = TDLS_MANUAL_EP_PM;
+	else if (!strcmp("wake", *argv))
+		info.mode = TDLS_MANUAL_EP_WAKE;
+	else if (!strcmp("disc", *argv))
+		info.mode = TDLS_MANUAL_EP_DISCOVERY;
+	else if (!strcmp("cw", *argv)) {
+		info.mode = TDLS_MANUAL_EP_CHSW;
+	}
+	else if (!strcmp("wfd_disc", *argv))
+		info.mode = TDLS_MANUAL_EP_WFD_TPQ;
+	else {
+		printf("error: invalid mode string\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing ea\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &info.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if (info.mode == TDLS_MANUAL_EP_CHSW) {
+		argv++;
+		if (!*argv) {
+			printf("error: missing target channel number\n");
+			return BCME_USAGE_ERROR;
+		}
+		if (atoi(*argv) != 0) {
+			chanspec = wf_chspec_aton(*argv);
+			if (chanspec == 0) {
+				printf("error: bad chanspec \"%s\".\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			chanspec = wl_chspec_to_driver(chanspec);
+			if (chanspec == INVCHANSPEC) {
+				return BCME_USAGE_ERROR;
+			}
+			info.chanspec = chanspec;
+		}
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+}
+
+static int
+wl_pattern_atoh(char *, char *);
+
+#define WFD_DEV			0
+#define WFD_DEV_LEN		6
+#define WFD_IP				8
+#define WFD_IP_LEN		5
+#define WFD_ALT_MAC		10
+#define WFD_ALT_MAC_LEN	6
+
+static int
+wl_tdls_wfd_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname_tdls = "tdls_wfd_ie";
+	tdls_wfd_ie_iovar_t info;
+	tdls_wfd_ie_iovar_t* buf_info = (tdls_wfd_ie_iovar_t*) buf;
+	int ret;
+	uint8* ptr;
+	uint8 element, subelement;
+	uint16 offset;
+	uint8 buffer[TDLS_WFD_IE_SIZE - (WFA_OUI_LEN + 3)];
+	uint16 length, element_length, current_length;
+	bcm_tlv_t * ie;
+	unsigned long value;
+	struct ether_addr ea;
+	struct ipv4_addr ipa_set;
+
+	if (strcmp(cmd->name, cmdname_tdls)) {
+		printf("error: invalid command name.\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	if (!strcmp(*argv, "clr")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else if (!strcmp(*argv, "get")) {
+		memset(buf_info, 0, sizeof(*buf_info));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			buf_info->mode = TDLS_WFD_IE_TX;
+		else if (wl_ether_atoe(*argv, &buf_info->ea))
+			buf_info->mode = TDLS_WFD_IE_RX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, buf_info,
+			sizeof(*buf_info), buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return ret;
+		}
+
+		/* empty */
+		if (!buf_info->length)
+			return ret;
+
+		if (!*++argv)
+			wl_hexdump((uchar *)buf_info->data, buf_info->length);
+		else {
+			if (!strcmp("ip", *argv)) {
+				element = WFD_IP;
+				element_length = WFD_IP_LEN;
+			} else if (!strcmp("port", *argv)) {
+				element = WFD_DEV;
+				element_length = WFD_DEV_LEN;
+			} else {
+				printf("error: unknown element\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Reassemble the WFD IE (without header) */
+
+			ptr = buf_info->data;
+			length = buf_info->length;
+			offset = 0;
+			current_length = 0;
+
+			while (length - offset > WFA_OUI_LEN + 3) {
+				if ((ie = bcm_parse_tlvs(ptr + offset,
+					length - offset, DOT11_MNG_VS_ID)) != NULL) {
+					if (ie->len > WFA_OUI_LEN + 1) {
+						if ((!memcmp(ie->data, WFA_OUI, WFA_OUI_LEN)) &&
+						    (*(ie->data + WFA_OUI_LEN) ==
+						    WFA_OUI_TYPE_WFD)) {
+							/* WFD */
+							memcpy(buffer + current_length,
+								ie->data + WFA_OUI_LEN + 1,
+								ie->len - WFA_OUI_LEN - 1);
+							current_length += ie->len - WFA_OUI_LEN - 1;
+						}
+					}
+					offset = (uint16)((uint8*)ie - ptr + ie->len + 2);
+				}
+				else
+					break;
+			}
+
+			/* Find the elements */
+
+			ptr = buffer;
+			length = current_length;
+
+			while (length > 3) {
+				current_length = (ptr[1] << 8) + ptr[2];
+				if ((ptr[0] == element) && (current_length == element_length) &&
+				(current_length <= length - 3)) {
+
+					switch (element) {
+						case WFD_IP:
+	/* we do not care about the IP version i.e. ptr[3] */
+	printf("%u.%u.%u.%u\n", ptr[4], ptr[5], ptr[6], ptr[7]);
+						break;
+
+						case WFD_DEV:
+	/* just get the RTSP TCP valid port */
+	printf("%u\n", (ptr[5] << 8) + ptr[6]);
+						break;
+					}
+					break;
+
+				} else {
+					if (current_length + 3 < length) {
+						length -= current_length + 3;
+						ptr += current_length + 3;
+					} else
+						break;
+				}
+			}
+		}
+
+		return ret;
+
+	} else if (!strcmp(*argv, "set")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		argv++;
+		if (!*argv) {
+			printf("error: missing IE string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (strlen((char*)*argv) - 2 > sizeof(info.data) * 2) {
+			printf("error: IE string too long; max is %u bytes\n",
+			    (unsigned int)sizeof(info.data));
+			return BCME_BADARG;
+		}
+
+		ret = wl_pattern_atoh(*argv, (char*)info.data);
+
+		if (ret <= 0) {
+			printf("error: could not parse IE string address %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		info.length = ret;
+
+		if (*++argv) {
+		/* IP specified */
+
+			/* watchdog */
+			if (info.length != 32) {
+				printf(
+				"if one or several set fields are used, "
+				"the following the IE string must be\n"
+				"exactly 32 bytes and must have the following order:\n"
+				"\t6-byte header (0xDD1E506F9A0A)\n"
+				"\t9-byte subelement 0 (WFD device information)\n"
+				"\t9-byte subelement 1 (BSSID)\n"
+				"\t8-byte subelement 8 (IP address)\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!wl_atoip(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+			memcpy(&info.data[28], (uint8*) &ipa_set, sizeof(ipa_set));
+
+			if (*++argv) {
+			/* port specified */
+
+				value = strtoul(*argv, NULL, 0);
+				info.data[11] = (uint8) (0xFF & (value >> 8));
+				info.data[12] = (uint8) (0xFF & value);
+
+				if (*++argv) {
+					/* WFD type (Source or Primary Sink) specified */
+
+					element = (uint8) (0x01 & strtoul(*argv, NULL, 0));
+					if (element)
+						info.data[10] |= 0x01;
+					else
+						info.data[10] &= ~0x01;
+
+					if (*++argv) {
+					/* BSSID specified */
+
+						if (!wl_ether_atoe(*argv, &ea))
+							return BCME_USAGE_ERROR;
+
+						memcpy(&info.data[18], (uint8*) &ea, sizeof(ea));
+					}
+				}
+			}
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else if (!strcmp(*argv, "clr2")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_PROBE_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else if (!strcmp(*argv, "get2")) {
+		memset(buf_info, 0, sizeof(*buf_info));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			buf_info->mode = TDLS_WFD_PROBE_IE_TX;
+		else if (wl_ether_atoe(*argv, &buf_info->ea))
+			buf_info->mode = TDLS_WFD_PROBE_IE_RX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, buf_info,
+			sizeof(*buf_info), buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return ret;
+		}
+
+		/* empty */
+		if (!buf_info->length)
+			return ret;
+
+		if (!*++argv)
+			wl_hexdump((uchar *)buf_info->data, buf_info->length);
+
+		else {
+			if (!strcmp("alt_mac", *argv)) {
+				element = WFD_ALT_MAC;
+				element_length = WFD_ALT_MAC_LEN;
+			} else if (!strcmp("port", *argv)) {
+				element = WFD_DEV;
+				element_length = WFD_DEV_LEN;
+				subelement = 1;
+			} else if (!strcmp("PC_bit", *argv)) {
+				element = WFD_DEV;
+				element_length = WFD_DEV_LEN;
+				subelement = 0;
+			} else {
+				printf("error: unknown element\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Reassemble the WFD IE (without header) */
+
+			ptr = buf_info->data;
+			length = buf_info->length;
+			offset = 0;
+			current_length = 0;
+
+			while (length - offset > WFA_OUI_LEN + 3) {
+				if ((ie = bcm_parse_tlvs(ptr + offset,
+					length - offset, DOT11_MNG_VS_ID)) != NULL) {
+					if (ie->len > WFA_OUI_LEN + 1) {
+						if ((!memcmp(ie->data, WFA_OUI, WFA_OUI_LEN)) &&
+							(*(ie->data + WFA_OUI_LEN) ==
+							WFA_OUI_TYPE_WFD)) {
+							/* WFD */
+							memcpy(buffer + current_length,
+								ie->data + WFA_OUI_LEN + 1,
+								ie->len - WFA_OUI_LEN - 1);
+							current_length += ie->len - WFA_OUI_LEN - 1;
+						}
+					}
+					offset = (uint16)((uint8*)ie - ptr + ie->len + 2);
+				}
+				else
+					break;
+			}
+
+			/* Find the elements */
+
+			ptr = buffer;
+			length = current_length;
+
+			while (length > 3) {
+				current_length = (ptr[1] << 8) + ptr[2];
+				if ((ptr[0] == element) && (current_length == element_length) &&
+					(current_length <= length - 3)) {
+
+					switch (element) {
+	case WFD_ALT_MAC:
+		printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
+			ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8]);
+		break;
+	case WFD_DEV:
+			if (subelement)
+				/* just get the RTSP TCP valid port */
+				printf("%u\n", (ptr[5] << 8) + ptr[6]);
+			else
+				/* just get the Preferred Connection bit */
+				printf("%u\n", ptr[4] >> 7);
+		break;
+					}
+					break;
+
+				} else {
+					if (current_length + 3 < length) {
+						length -= current_length + 3;
+						ptr += current_length + 3;
+					} else
+						break;
+				}
+			}
+		}
+
+		return ret;
+
+	} else if (!strcmp(*argv, "set2")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_PROBE_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		argv++;
+		if (!*argv) {
+			printf("error: missing IE string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (strlen((char*)*argv) - 2 > sizeof(info.data) * 2) {
+			printf("error: IE string too long; max is %u bytes\n",
+				(unsigned int)sizeof(info.data));
+			return BCME_USAGE_ERROR;
+		}
+
+		ret = wl_pattern_atoh(*argv, (char*)info.data);
+
+		if (ret <= 0) {
+			printf("error: could not parse IE string address %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		info.length = ret;
+
+		if (*++argv) {
+		/* alt MAC specified */
+
+			/* watchdog */
+			if (info.length != 24) {
+				printf(
+				"if one or several set2 fields are used, "
+				"the following the IE string must be\n"
+				"exactly 24 bytes and must have the following order:\n"
+				"\t6-byte header (0xDD16506F9A0A)\n"
+				"\t9-byte subelement 0  (WFD device information)\n"
+				"\t9-byte subelement 10 (alternate MAC address)\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!wl_ether_atoe(*argv, &ea))
+				return BCME_USAGE_ERROR;
+			memcpy(&info.data[18], (uint8*) &ea, sizeof(ea));
+
+			if (*++argv) {
+			/* port specified */
+
+				value = strtoul(*argv, NULL, 0);
+				info.data[11] = (uint8) (0xFF & (value >> 8));
+				info.data[12] = (uint8) (0xFF & value);
+
+				if (*++argv) {
+					/* WFD type (Source or Primary Sink) specified */
+
+					element = (uint8) (0x01 & strtoul(*argv, NULL, 0));
+					if (element)
+						info.data[10] |= 0x01;
+					else
+						info.data[10] &= ~0x01;
+				}
+			}
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else {
+		printf("error: unknown operation\n");
+		return BCME_USAGE_ERROR;
+	}
+}
+#endif /* WLTDLS */
+
+static int
+wl_actframe(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_action_frame_t * action_frame;
+	wl_af_params_t * af_params;
+	struct ether_addr ea;
+	int argc;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || !argv[2]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if ((af_params = (wl_af_params_t *) malloc(WL_WIFI_AF_PARAMS_SIZE)) == NULL) {
+		printf("wl_actframe: unable to allocate frame \n");
+		return BCME_NOMEM;
+	}
+	af_params->channel = 0;
+	af_params->dwell_time = -1;
+	action_frame = &af_params->action_frame;
+
+	/* Add the packet Id */
+	action_frame->packetId = (uint32)(uintptr)action_frame;
+
+	/* convert the ea string into an ea struct */
+	if (!wl_ether_atoe(argv[1], &ea)) {
+		free(af_params);
+		printf(" ERROR: no valid ether addr provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	memcpy(&action_frame->da, (char*)&ea, ETHER_ADDR_LEN);
+	/* set default BSSID */
+	memcpy(&af_params->BSSID, (char*)&ea, ETHER_ADDR_LEN);
+
+	/* add the length */
+	if (argv[2]) {
+		action_frame->len  = htod16(strlen(argv[2])) / 2;
+	}
+
+	/* add the channel */
+	if (argc > 3 && argv[3]) {
+		af_params->channel = htod32(atoi(argv[3]));
+	}
+
+	/* add the dwell_time */
+	if (argc > 4 && argv[4]) {
+		af_params->dwell_time = htod32(atoi(argv[4]));
+	}
+
+	/* add the BSSID */
+	if (argc > 5 && argv[5]) {
+		if (!wl_ether_atoe(argv[5], &ea)) {
+			free(af_params);
+			printf(" ERROR: no valid ether addr provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		memcpy(&af_params->BSSID, (char*)&ea, ETHER_ADDR_LEN);
+	}
+
+	if ((err = get_ie_data ((uchar *)argv[2],
+		&action_frame->data[0],
+		action_frame->len))) {
+		free(af_params);
+		fprintf(stderr, "Error parsing data arg\n");
+		return err;
+	}
+	err = wlu_var_setbuf(wl, "actframe", af_params, WL_WIFI_AF_PARAMS_SIZE);
+
+	free(af_params);
+
+	return (err);
+
+}
+
+static int
+wl_dpt_pmk(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "dpt_pmk";
+	wsec_pmk_t psk;
+	size_t key_len;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	key_len = strlen(*argv);
+	if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
+		fprintf(stderr, "passphrase must be between %d and %d characters long\n",
+		       WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN);
+		return BCME_BADARG;
+	}
+	psk.key_len = htod16((ushort) key_len);
+	psk.flags = htod16(WSEC_PASSPHRASE);
+	memcpy(psk.key, *argv, key_len);
+
+	return wlu_var_setbuf(wl, cmdname, &psk, sizeof(wsec_pmk_t));
+}
+
+static int
+wl_dpt_fname(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "dpt_fname";
+	int err;
+	dpt_fname_t fname, *reply;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv)) {
+		fname.len = strlen(param);
+		if (fname.len >= (DPT_FNAME_LEN - 1)) {
+			fprintf(stderr, "Name must be less than 32 characters\n");
+			return BCME_BADARG;
+		}
+		memcpy(fname.name, param, fname.len);
+		fname.name[fname.len] = '\0';
+		err = wlu_var_setbuf(wl, cmdname, &fname, sizeof(fname));
+	} else {
+		if ((err = wlu_var_getbuf(wl, cmdname, &fname, sizeof(fname), &ptr) < 0))
+			return err;
+		reply = (dpt_fname_t *)ptr;
+		printf("%s\n", reply->name);
+	}
+	return err;
+}
+
+static int
+wl_dpt_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint32 i;
+	dpt_list_t *list;
+
+	if (*++argv)
+		return BCME_USAGE_ERROR;
+
+	strcpy(buf, cmd->name);
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	list = (dpt_list_t *) buf;
+
+	printf("List of DPT connections:\n");
+	for (i = 0; i < list->num; i++) {
+		printf("%s: status 0x%x rx %d tx %d rssi %d\n",
+			list->status[i].name,
+			list->status[i].status,
+			list->status[i].sta.rx_ucast_pkts,
+			list->status[i].sta.tx_pkts,
+			list->status[i].rssi);
+	}
+	return err;
+}
+
+#ifdef WLBTAMP
+#define MATCH_OP(op, opstr)	(strlen(op) == strlen(opstr) && strncmp(op, opstr, strlen(op)) == 0)
+
+static int
+wl_HCI_cmd(void *wl, cmd_t *cmd, char **argv)
+{
+	union {
+		char buf[HCI_CMD_PREAMBLE_SIZE + HCI_CMD_DATA_SIZE];
+		uint32 alignme;
+	} cbuf;
+	amp_hci_cmd_t *cpkt = (amp_hci_cmd_t *)&cbuf.buf[0];
+	char *op;
+	uint8 plen;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	/* recognize and encode operations */
+	op = *argv++;
+	if (MATCH_OP(op, "Read_Link_Quality")) {
+		cpkt->opcode = HCI_Read_Link_Quality;
+	} else if (MATCH_OP(op, "Read_Local_AMP_Info")) {
+		cpkt->opcode = HCI_Read_Local_AMP_Info;
+	} else if (MATCH_OP(op, "Read_Local_AMP_ASSOC")) {
+		cpkt->opcode = HCI_Read_Local_AMP_ASSOC;
+	} else if (MATCH_OP(op, "Write_Remote_AMP_ASSOC")) {
+		cpkt->opcode = HCI_Write_Remote_AMP_ASSOC;
+	} else if (MATCH_OP(op, "Create_Physical_Link")) {
+		cpkt->opcode = HCI_Create_Physical_Link;
+	} else if (MATCH_OP(op, "Accept_Physical_Link_Request")) {
+		cpkt->opcode = HCI_Accept_Physical_Link_Request;
+	} else if (MATCH_OP(op, "Disconnect_Physical_Link")) {
+		cpkt->opcode = HCI_Disconnect_Physical_Link;
+	} else if (MATCH_OP(op, "Create_Logical_Link")) {
+		cpkt->opcode = HCI_Create_Logical_Link;
+	} else if (MATCH_OP(op, "Accept_Logical_Link")) {
+		cpkt->opcode = HCI_Accept_Logical_Link;
+	} else if (MATCH_OP(op, "Disconnect_Logical_Link")) {
+		cpkt->opcode = HCI_Disconnect_Logical_Link;
+	} else if (MATCH_OP(op, "Logical_Link_Cancel")) {
+		cpkt->opcode = HCI_Logical_Link_Cancel;
+	} else if (MATCH_OP(op, "Short_Range_Mode")) {
+		cpkt->opcode = HCI_Short_Range_Mode;
+	} else if (MATCH_OP(op, "Read_Connection_Accept_Timeout")) {
+		cpkt->opcode = HCI_Read_Connection_Accept_Timeout;
+	} else if (MATCH_OP(op, "Write_Connection_Accept_Timeout")) {
+		cpkt->opcode = HCI_Write_Connection_Accept_Timeout;
+	} else if (MATCH_OP(op, "Read_Link_Supervision_Timeout")) {
+		cpkt->opcode = HCI_Read_Link_Supervision_Timeout;
+	} else if (MATCH_OP(op, "Write_Link_Supervision_Timeout")) {
+		cpkt->opcode = HCI_Write_Link_Supervision_Timeout;
+	} else if (MATCH_OP(op, "Reset")) {
+		cpkt->opcode = HCI_Reset;
+	} else if (MATCH_OP(op, "Enhanced_Flush")) {
+		cpkt->opcode = HCI_Enhanced_Flush;
+	} else if (MATCH_OP(op, "Read_Best_Effort_Flush_Timeout")) {
+		cpkt->opcode = HCI_Read_Best_Effort_Flush_Timeout;
+	} else if (MATCH_OP(op, "Write_Best_Effort_Flush_Timeout")) {
+		cpkt->opcode = HCI_Write_Best_Effort_Flush_Timeout;
+	} else if (MATCH_OP(op, "Read_Logical_Link_Accept_Timeout")) {
+		cpkt->opcode = HCI_Read_Logical_Link_Accept_Timeout;
+	} else if (MATCH_OP(op, "Write_Logical_Link_Accept_Timeout")) {
+		cpkt->opcode = HCI_Write_Logical_Link_Accept_Timeout;
+	} else if (MATCH_OP(op, "Read_Buffer_Size")) {
+		cpkt->opcode = HCI_Read_Buffer_Size;
+	} else if (MATCH_OP(op, "Read_Data_Block_Size")) {
+		cpkt->opcode = HCI_Read_Data_Block_Size;
+	} else if (MATCH_OP(op, "Set_Event_Mask_Page_2")) {
+		cpkt->opcode = HCI_Set_Event_Mask_Page_2;
+	} else if (MATCH_OP(op, "Flow_Spec_Modify")) {
+		cpkt->opcode = HCI_Flow_Spec_Modify;
+	} else if (MATCH_OP(op, "Read_Local_Version_Info")) {
+		cpkt->opcode = HCI_Read_Local_Version_Info;
+	} else if (MATCH_OP(op, "Read_Local_Supported_Commands")) {
+		cpkt->opcode = HCI_Read_Local_Supported_Commands;
+	} else if (MATCH_OP(op, "Read_Failed_Contact_Counter")) {
+		cpkt->opcode = HCI_Read_Failed_Contact_Counter;
+	} else if (MATCH_OP(op, "Reset_Failed_Contact_Counter")) {
+		cpkt->opcode = HCI_Reset_Failed_Contact_Counter;
+	} else {
+		printf("unsupported HCI command: %s\n", op);
+		return BCME_UNSUPPORTED;
+	}
+
+	plen = 0;
+	while (*argv && (plen < HCI_CMD_DATA_SIZE)) {
+		cpkt->parms[plen++] = (uint8)strtol(*argv++, NULL, 0);
+	}
+	cpkt->plen = plen;
+
+	return wlu_var_setbuf(wl, cmd->name, cpkt, HCI_CMD_PREAMBLE_SIZE + plen);
+}
+
+static int
+wl_HCI_ACL_data(void *wl, cmd_t *cmd, char **argv)
+{
+	amp_hci_ACL_data_t *dpkt;
+	uint16 dlen;
+	int ret;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	dpkt = (amp_hci_ACL_data_t *) malloc(HCI_ACL_DATA_PREAMBLE_SIZE + 2048);
+	if (!dpkt)
+		return BCME_NOMEM;
+
+	/* get logical link handle */
+	dpkt->handle = (HCI_ACL_DATA_BC_FLAGS | HCI_ACL_DATA_PB_FLAGS);
+	dpkt->handle |= (uint16)strtol(*argv++, NULL, 0);
+
+	/* get data */
+	dlen = 0;
+	while (*argv && (dlen < 2048)) {
+		dpkt->data[dlen++] = (uint8)strtol(*argv++, NULL, 0);
+	}
+	dpkt->dlen = dlen;
+
+	ret = wlu_var_setbuf(wl, cmd->name, dpkt, HCI_ACL_DATA_PREAMBLE_SIZE + dlen);
+
+	free(dpkt);
+	return ret;
+}
+
+static int
+wl_get_btamp_log(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, i, j;
+	char *val_name;
+	uint8 *state;
+	uint8 idx = 0;
+	void *ptr = buf;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* command name */
+	val_name = *argv++;
+
+	if (!*argv) {
+		if ((err = wlu_var_getbuf_sm (wl, cmd->name, NULL, 0, &ptr)))
+			return err;
+		state = (uint8 *)ptr;
+		idx = *state++;
+
+		for (i = 0; i < BTA_STATE_LOG_SZ; i++, idx--) {
+			j = (idx & (BTA_STATE_LOG_SZ - 1));
+			switch (state[j]) {
+				case HCIReset:
+					printf("%2d: HCI Reset\n", state[j]);
+					break;
+				case HCIReadLocalAMPInfo:
+					printf("%2d: HCI Read Local AMPInfo\n", state[j]);
+					break;
+				case HCIReadLocalAMPASSOC:
+					printf("%2d: HCI Read Local AMPASSOC\n", state[j]);
+					break;
+				case HCIWriteRemoteAMPASSOC:
+					printf("%2d: HCI Write Remote AMPASSOC\n", state[j]);
+					break;
+				case HCICreatePhysicalLink:
+					printf("%2d: HCI Create Physical Link\n", state[j]);
+					break;
+				case HCIAcceptPhysicalLinkRequest:
+					printf("%2d: HCI Accept Physical Link Request\n", state[j]);
+					break;
+				case HCIDisconnectPhysicalLink:
+					printf("%2d: HCI Disconnect Physical Link\n", state[j]);
+					break;
+				case HCICreateLogicalLink:
+					printf("%2d: HCI Create Logical Link\n", state[j]);
+					break;
+				case HCIAcceptLogicalLink:
+					printf("%2d: HCI Accept Logical Link\n", state[j]);
+					break;
+				case HCIDisconnectLogicalLink:
+					printf("%2d: HCI Disconnect Logical Link\n", state[j]);
+					break;
+				case HCILogicalLinkCancel:
+					printf("%2d: HCI Logical Link Cancel\n", state[j]);
+					break;
+				case HCIAmpStateChange:
+					printf("%2d: HCI Amp State Change\n", state[j]);
+					break;
+				default:
+					break;
+			}
+		}
+		return 0;
+	} else
+		err = wlu_iovar_setint(wl, val_name, (int)idx);
+
+	return err;
+}
+#endif /* WLBTAMP */
+
+/*
+ *  RADAR detection parameter control
+ */
+static int
+wl_radar_args(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_radar_args_t ra;
+
+	/* Skip the command name */
+	argv++;
+
+	if (*argv == NULL) {
+		/* Get */
+
+		if ((ret = wlu_iovar_get(wl, cmd->name, &ra, sizeof(ra))) < 0)
+			return ret;
+
+		if (ra.version != WL_RADAR_ARGS_VERSION) {
+			printf("\tIncorrect version of RADAR_ARGS struct: expected %d; got %d\n",
+			       WL_RADAR_ARGS_VERSION, ra.version);
+			return -1;
+		}
+		printf("version %d npulses %d ncontig %d min_pw %d max_pw %d thresh0 0x%x "
+		       "thresh1 0x%x\n",
+		       ra.version, ra.npulses, ra.ncontig, ra.min_pw,
+		       ra.max_pw, ra.thresh0, ra.thresh1);
+		printf("blank 0x%x fmdemodcfg 0x%x npulses_lp %d min_pw_lp %d "
+		       "max_pw_lp %d\n",
+		       ra.blank, ra.fmdemodcfg, ra.npulses_lp, ra.min_pw_lp,
+		       ra.max_pw_lp);
+		printf("min_fm_lp %d max_span_lp %d min_deltat %d max_deltat %d\n",
+		       ra.min_fm_lp, ra.max_span_lp, ra.min_deltat, ra.max_deltat);
+
+		printf("autocorr 0x%x st_level_time 0x%x  t2_min %d fra_pulse_err %d\n",
+		       ra.autocorr, ra.st_level_time, ra.t2_min, ra.fra_pulse_err);
+		printf("npulses_fra %d npulses_stg2 %d npulses_stg3 %d percal_mask 0x%x quant %d\n",
+			ra.npulses_fra, ra.npulses_stg2, ra.npulses_stg3, ra.percal_mask,
+			ra.quant);
+		printf("min_burst_intv_lp %d max_burst_intv_lp %d nskip_rst_lp %d max_pw_tol %d "
+				"feature_mask 0x%x\n",
+				ra.min_burst_intv_lp, ra.max_burst_intv_lp, ra.nskip_rst_lp,
+				ra.max_pw_tol, ra.feature_mask);
+		/* this part prints only param values */
+		printf("%d %d %d %d %d 0x%x "
+		       "0x%x",
+		       ra.version, ra.npulses, ra.ncontig, ra.min_pw,
+		       ra.max_pw, ra.thresh0, ra.thresh1);
+		printf(" 0x%x 0x%x %d %d "
+		       "%d",
+		       ra.blank, ra.fmdemodcfg, ra.npulses_lp, ra.min_pw_lp,
+		       ra.max_pw_lp);
+		printf(" %d %d %d %d",
+		       ra.min_fm_lp, ra.max_span_lp, ra.min_deltat, ra.max_deltat);
+
+		printf(" 0x%x 0x%x %d %d",
+		       ra.autocorr, ra.st_level_time, ra.t2_min, ra.fra_pulse_err);
+		printf(" %d %d %d 0x%x %d",
+			ra.npulses_fra, ra.npulses_stg2, ra.npulses_stg3, ra.percal_mask,
+			ra.quant);
+		printf(" %d %d %d %d "
+				"0x%x\n",
+				ra.min_burst_intv_lp, ra.max_burst_intv_lp, ra.nskip_rst_lp,
+				ra.max_pw_tol, ra.feature_mask);
+
+
+	} else {
+		/* Set */
+		char *endptr = NULL;
+		int val_count = 30;
+		long vals[30];
+		long *pval;
+		int i;
+
+		for (i = 0; i < val_count; i++, argv++) {
+			/* verify that there is another arg */
+			if (*argv == NULL)
+				return BCME_USAGE_ERROR;
+
+			vals[i] = strtol(*argv, &endptr, 0);
+
+			/* make sure all the value string was parsed by strtol */
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+		pval = vals;
+
+		ra.version       = *pval++;
+		ra.npulses       = *pval++;
+		ra.ncontig       = *pval++;
+		ra.min_pw        = *pval++;
+		ra.max_pw        = *pval++;
+		ra.thresh0       = (uint16)*pval++;
+		ra.thresh1       = (uint16)*pval++;
+		ra.blank         = (uint16)*pval++;
+		ra.fmdemodcfg    = (uint16)*pval++;
+		ra.npulses_lp    = *pval++;
+		ra.min_pw_lp     = *pval++;
+		ra.max_pw_lp     = *pval++;
+		ra.min_fm_lp     = *pval++;
+		ra.max_span_lp   = *pval++;
+		ra.min_deltat    = *pval++;
+		ra.max_deltat    = *pval++;
+		ra.autocorr      = (uint16)*pval++;
+		ra.st_level_time = (uint16)*pval++;
+		ra.t2_min        = (uint16)*pval++;
+		ra.fra_pulse_err = (uint32)*pval++;
+		ra.npulses_fra   = (int)*pval++;
+		ra.npulses_stg2  = (int)*pval++;
+		ra.npulses_stg3  = (int)*pval++;
+		ra.percal_mask   = (int)*pval++;
+		ra.quant         = (int)*pval++;
+		ra.min_burst_intv_lp = (uint32)*pval++;
+		ra.max_burst_intv_lp = (uint32)*pval++;
+		ra.nskip_rst_lp  = (int)*pval++;
+		ra.max_pw_tol    = (int)*pval++;
+		ra.feature_mask  = (uint16)*pval++;
+
+		return wlu_var_setbuf(wl, cmd->name, &ra, sizeof(wl_radar_args_t));
+	}
+	return ret;
+}
+
+static int
+wl_radar_thrs(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	wl_radar_thr_t radar_thrs;
+
+	if (*++argv) {
+		/* Set */
+		char *endptr;
+		int val_count = 12;
+		uint16 vals[12];
+		uint16 *pval;
+		int i;
+
+		for (i = 0; i < val_count; i++, argv++) {
+			/* verify that there is another arg */
+			if (*argv == NULL)
+				return BCME_USAGE_ERROR;
+
+			vals[i] = (uint16)strtol(*argv, &endptr, 0);
+
+			/* make sure all the value string was parsed by strtol */
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+		radar_thrs.version = WL_RADAR_THR_VERSION;
+
+		/* Order thresh0_20_lo, thresh1_20_lo, thresh0_40_lo, thresh1_40_lo
+		 * thresh0_20_hi, thresh1_20_hi, thresh0_40_hi, thresh1_40_hi
+		 */
+		pval = vals;
+		radar_thrs.thresh0_20_lo = (uint16)*pval++;
+		radar_thrs.thresh1_20_lo = (uint16)*pval++;
+		radar_thrs.thresh0_40_lo = (uint16)*pval++;
+		radar_thrs.thresh1_40_lo = (uint16)*pval++;
+		radar_thrs.thresh0_80_lo = (uint16)*pval++;
+		radar_thrs.thresh1_80_lo = (uint16)*pval++;
+		radar_thrs.thresh0_20_hi = (uint16)*pval++;
+		radar_thrs.thresh1_20_hi = (uint16)*pval++;
+		radar_thrs.thresh0_40_hi = (uint16)*pval++;
+		radar_thrs.thresh1_40_hi = (uint16)*pval++;
+		radar_thrs.thresh0_80_hi = (uint16)*pval++;
+		radar_thrs.thresh1_80_hi = (uint16)*pval++;
+
+		return wlu_var_setbuf(wl, cmd->name, &radar_thrs, sizeof(wl_radar_thr_t));
+	}
+	return ret;
+}
+
+static int
+wl_dfs_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_dfs_status_t *dfs_status_ptr;
+	char chanspec_str[CHANSPEC_STR_LEN];
+
+	const char *dfs_cacstate_str[WL_DFS_CACSTATES] = {
+		"IDLE",
+		"PRE-ISM Channel Availability Check(CAC)",
+		"In-Service Monitoring(ISM)",
+		"Channel Switching Announcement(CSA)",
+		"POST-ISM Channel Availability Check",
+		"PRE-ISM Ouf Of Channels(OOC)",
+		"POST-ISM Out Of Channels(OOC)"
+	};
+
+	void *ptr;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return ret;
+
+	dfs_status_ptr = (wl_dfs_status_t *)ptr;
+
+	dfs_status_ptr->state = dtoh32(dfs_status_ptr->state);
+	dfs_status_ptr->duration = dtoh32(dfs_status_ptr->duration);
+	dfs_status_ptr->chanspec_cleared = wl_chspec_from_driver(dfs_status_ptr->chanspec_cleared);
+
+	if (dfs_status_ptr->state >= WL_DFS_CACSTATES) {
+		printf("Unknown dfs state %d.\n", dfs_status_ptr->state);
+		return -1;
+	}
+
+	printf("state %s time elapsed %dms radar channel cleared by dfs ",
+		dfs_cacstate_str[dfs_status_ptr->state], dfs_status_ptr->duration);
+
+	if (dfs_status_ptr->chanspec_cleared) {
+		printf("channel %s (0x%04X)\n",
+		       wf_chspec_ntoa(dfs_status_ptr->chanspec_cleared, chanspec_str),
+		       dfs_status_ptr->chanspec_cleared);
+	}
+	else {
+		printf("none\n");
+	}
+
+	return ret;
+}
+
+static int
+wl_wds_wpa_role_old(void *wl, cmd_t *cmd, char **argv)
+{
+	uint remote[2];
+	uint *sup = remote;
+	int ret = 0;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_get(wl, WLC_WDS_GET_REMOTE_HWADDR, remote, sizeof(remote))) < 0) {
+		printf("Unable to get remote endpoint's hwaddr\n");
+		return ret;
+	}
+	if ((ret = wlu_get(wl, cmd->get, remote, sizeof(remote))) < 0) {
+		printf("Unable to get local endpoint's WPA role\n");
+		return ret;
+	}
+	printf("Local endpoing's WPA role: %s\n", dtoh32(*sup) ? "supplicant" : "authenticator");
+	return 0;
+}
+
+
+/*
+ * wlu_reg2args is a generic function that is used for setting/getting
+ * WL_IOVAR variables that require address for read, and
+ * address + data for write.
+ */
+static int
+wlu_reg2args(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	uint32 int_val;
+	bool get = TRUE;
+	uint32 len;
+	void *ptr = NULL;
+	char *endptr;
+	int ret = 0;
+
+	if (argv[1]) {
+		len = sizeof(int_val);
+		int_val = htod32(strtoul(argv[1], &endptr, 0));
+		memcpy(var, (char *)&int_val, sizeof(int_val));
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	if (argv[2]) {
+		get = FALSE;
+		int_val = htod32(strtoul(argv[2], &endptr, 0));
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+	if (get) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0)
+			return ret;
+
+		printf("0x%x\n", dtoh32(*(int *)ptr));
+	}
+	else
+		ret = wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+/*
+ * wlu_reg3args is a generic function that is used for setting/getting
+ * WL_IOVAR variables that require address + offset for read, and
+ * address + offset + data for write.
+ */
+static int
+wlu_reg3args(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	uint32 int_val;
+	bool get = TRUE;
+	uint32 len, i;
+	void *ptr = NULL;
+	char *endptr;
+	uint numargs;
+	int ret = 0;
+
+	len = 0;
+
+	if (!argv[1] || !argv[2]) {
+		printf("Wrong syntax => dev offset [val]\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argv[3]) {
+		numargs = 3;
+		get = FALSE;
+	} else
+		numargs = 2;
+
+	for (i = 1; i <= numargs; i++) {
+		int_val = htod32(strtoul(argv[i], &endptr, 0));
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+
+	if (get) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0)
+			return ret;
+
+		printf("0x%x\n", dtoh32(*(int *)ptr));
+	}
+	else
+		ret = wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+
+static int
+wl_tpc_lm(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint16 val;
+	int8 aplm, stalm;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_iovar_getint(wl, cmd->name, (int *)(uintptr)&val)) < 0)
+		return ret;
+
+	stalm = val & 0xff;
+	aplm = (val >> 8) & 0xff;
+
+	printf("TPC: APs link margin:%d\t STAs link margin:%d\n", aplm, stalm);
+
+	return 0;
+}
+
+
+static int
+wl_wds_wpa_role(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	char *mac;
+	char *sup;
+	int len;
+	int ret;
+	if (strlen("wds_wpa_role") + 1 + ETHER_ADDR_LEN + 1 > sizeof(var))
+		return -1;
+	/* build var required by WLC_GET|SET_VAR */
+	len = sprintf(var, "%s", "wds_wpa_role") + 1;
+	mac = var + len;
+	if ((ret = wlu_get(wl, WLC_WDS_GET_REMOTE_HWADDR, mac, ETHER_ADDR_LEN)) < 0) {
+		printf("Unable to get remote endpoint's hwaddr\n");
+		return ret;
+	}
+	len += ETHER_ADDR_LEN + 1;
+	if (argv[1]) {
+		sup = mac + ETHER_ADDR_LEN;
+		switch ((uchar)(*sup = atoi(argv[1]))) {
+		case WL_WDS_WPA_ROLE_AUTH:
+		case WL_WDS_WPA_ROLE_SUP:
+		case WL_WDS_WPA_ROLE_AUTO:
+			if ((ret = wlu_set(wl, cmd->set, var, len)) < 0)
+				printf("Unable to set local endpoint's WPA role\n");
+			break;
+		default:
+			printf("Invalid WPA role %s. %u:authenticator, %u:supplicant, %u:auto\n",
+				argv[1], WL_WDS_WPA_ROLE_AUTH,
+				WL_WDS_WPA_ROLE_SUP, WL_WDS_WPA_ROLE_AUTO);
+			break;
+		}
+	}
+	else if ((ret = wlu_get(wl, cmd->get, var, len)) < 0) {
+		printf("Unable to get local endpoint's WPA role\n");
+		return ret;
+	}
+	else {
+		sup = var;
+		printf("Local endpoint's WPA role: %s\n", *sup ? "supplicant" : "authenticator");
+	}
+	return ret;
+}
+
+static int
+wl_measure_req(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	struct ether_addr ea;
+
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!stricmp(*argv, "tpc"))
+		val = WLC_MEASURE_TPC;
+	else if (!stricmp(*argv, "basic"))
+		val = WLC_MEASURE_CHANNEL_BASIC;
+	else if (!stricmp(*argv, "cca"))
+		val = WLC_MEASURE_CHANNEL_CCA;
+	else if (!stricmp(*argv, "rpi"))
+		val = WLC_MEASURE_CHANNEL_RPI;
+	else {
+		printf("error: unknown measurement type %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+	argv++;
+
+	if (!*argv) {
+		printf("error: missing target address\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	val = htod32(val);
+	memcpy(&buf[0], &val, sizeof(uint32));
+	memcpy(&buf[4], ea.octet, ETHER_ADDR_LEN);
+
+	return wlu_set(wl, cmd->set, buf, sizeof(uint32) + ETHER_ADDR_LEN);
+}
+
+static int
+wl_send_quiet(void *wl, cmd_t *cmd, char **argv)
+{
+	dot11_quiet_t quiet;
+
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	/* Order is count, duration, offset */
+	quiet.count = atoi(*argv);
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	quiet.duration = atoi(*argv);
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	quiet.offset = atoi(*argv);
+	quiet.period = 0;
+
+	quiet.duration = htod16(quiet.duration);
+	quiet.offset = htod16(quiet.offset);
+	return (wlu_set(wl, cmd->set, &quiet, sizeof(quiet)));
+}
+
+static int
+wl_send_csa(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_chan_switch_t csa_arg;
+
+	/* Order is mode, count channel */
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	csa_arg.mode = atoi(*argv) ? 1 : 0;
+	if (!*++argv) {
+		printf("error: missing count\n");
+		return BCME_USAGE_ERROR;
+	}
+	csa_arg.count = atoi(*argv);
+	if (!*++argv) {
+		printf("error: missing channel\n");
+		return BCME_USAGE_ERROR;
+	}
+	csa_arg.reg = 0;
+
+	if ((csa_arg.chspec = wf_chspec_aton(*argv))) {
+		csa_arg.chspec = wl_chspec_to_driver(csa_arg.chspec);
+		if (csa_arg.chspec == INVCHANSPEC) {
+			return BCME_USAGE_ERROR;
+		}
+		/* csa action frame type */
+		if (*++argv) {
+			if (strcmp(*argv, "u") == 0)
+				csa_arg.frame_type = CSA_UNICAST_ACTION_FRAME;
+			else {
+				printf("error: invalid frame type: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+		} else
+			csa_arg.frame_type = CSA_BROADCAST_ACTION_FRAME;
+
+		err = wlu_var_setbuf(wl, cmd->name, &csa_arg, sizeof(csa_arg));
+	} else {
+		printf("Error: bad parameters \"%s\"\n", *argv);
+		return BCME_BADARG;
+	}
+
+	return err;
+}
+
+static int
+wl_var_setint(void *wl, cmd_t *cmd, char **argv)
+{
+	int32 val;
+	char *varname;
+	char *endptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("set: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (!*argv) {
+		printf("set: missing value argument for set of \"%s\"\n", varname);
+		return BCME_USAGE_ERROR;
+	}
+
+	val = strtol(*argv, &endptr, 0);
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n",
+			*argv, varname);
+		return BCME_USAGE_ERROR;
+	}
+
+	return wlu_iovar_setint(wl, varname, val);
+}
+
+static int
+wl_var_get(void *wl, cmd_t *cmd, char **argv)
+{
+	char *varname;
+	char *p;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("get: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (*argv) {
+		printf("get: error, extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, varname);
+	p = buf;
+	while (*p != '\0') {
+		*p = tolower((int)*p);
+		p++;
+	}
+	return (wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN));
+}
+
+static int
+wl_var_getinthex(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 val;
+
+	if ((err = wl_var_get(wl, cmd, argv)))
+		return (err);
+
+	val = dtoh32(*(int32*)buf);
+
+	printf("0x%08x\n", val);
+
+	return 0;
+}
+static int
+wl_var_getint(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 val;
+	char *varname;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("get: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if ((err = wlu_iovar_getint(wl, varname, &val)))
+		return (err);
+
+	if (val < 10)
+		printf("%d\n", val);
+	else
+		printf("%d (0x%x)\n", val, val);
+
+	return (0);
+}
+
+static int
+wl_var_getandprintstr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+
+	if ((err = wl_var_get(wl, cmd, argv)))
+		return (err);
+
+	printf("%s\n", buf);
+	return (0);
+}
+
+/* Variation: Like getandprint, but allow an int arg to be passed */
+static int
+wl_var_setintandprintstr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 val;
+	char *varname;
+	char *endptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("set: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (!*argv) {
+		val = 0;
+	} else {
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n",
+			       *argv, varname);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	val = htod32(val);
+	err = wlu_iovar_getbuf(wl, varname, &val, sizeof(int), buf, WLC_IOCTL_MAXLEN);
+
+	if (err)
+		return (err);
+
+	printf("%s\n", buf);
+	return (0);
+}
+
+void
+wl_printlasterror(void *wl)
+{
+	char error_str[128];
+
+	if (wlu_iovar_get(wl, "bcmerrorstr", error_str, sizeof(error_str)) != 0) {
+		fprintf(stderr, "%s: \nError getting the last error\n", wlu_av0);
+	} else {
+		fprintf(stderr, "%s: %s\n", wlu_av0, error_str);
+	}
+}
+
+/* just issue a wl_var_setint() or a wl_var_getint() if there is a 2nd arg */
+int
+wl_varint(void *wl, cmd_t *cmd, char *argv[])
+{
+	if (argv[1])
+		return (wl_var_setint(wl, cmd, argv));
+	else
+		return (wl_var_getint(wl, cmd, argv));
+}
+
+int
+wlu_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN);
+}
+
+/* get buffer for smaller sizes upto 256 bytes */
+int
+wlu_var_getbuf_sm(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_SMLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_SMLEN);
+}
+
+/* Get buffer for medium sizes upto 1500 bytes */
+int
+wlu_var_getbuf_med(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MEDLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MEDLEN);
+}
+
+
+int
+wlu_var_setbuf(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	len += param_len;
+
+	return wlu_set(wl, WLC_SET_VAR, &buf[0], len);
+}
+
+int
+wlu_var_setbuf_sm(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_SMLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	len += param_len;
+
+	return wlu_set(wl, WLC_SET_VAR, &buf[0], WLC_IOCTL_SMLEN);
+}
+
+int
+wlu_var_setbuf_med(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MEDLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	len += param_len;
+
+	return wlu_set(wl, WLC_SET_VAR, &buf[0], WLC_IOCTL_MEDLEN);
+}
+
+static int
+wl_var_void(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(argv);
+
+	if (cmd->set < 0)
+		return -1;
+
+	return wlu_var_setbuf(wl, cmd->name, NULL, 0);
+}
+
+/*
+ * format a "prefix" indexed iovar buffer
+ */
+static int
+wl_prefixiovar_mkbuf(const char *iovar, const char *prefix, int prefix_index, void *param,
+	int paramlen, void *bufptr, int buflen, int *perr)
+{
+	int8* p;
+	uint prefixlen;
+	uint namelen;
+	uint iolen;
+
+	prefixlen = strlen(prefix);	/* length of iovar prefix "bsscfg:ssid %d wlc:counter %d" */
+	namelen = strlen(iovar) + 1;	/* length of iovar name + null */
+	iolen = prefixlen + namelen + sizeof(int) + paramlen;
+
+	/* check for overflow */
+	if (buflen < 0 || iolen > (uint)buflen) {
+		*perr = BCME_BUFTOOSHORT;
+		return 0;
+	}
+
+	p = (int8*)bufptr;
+
+	/* copy prefix, no null */
+	memcpy(p, prefix, prefixlen);
+	p += prefixlen;
+
+	/* copy iovar name including null */
+	memcpy(p, iovar, namelen);
+	p += namelen;
+
+	/* send index as first param */
+	prefix_index = htod32(prefix_index);
+	memcpy(p, &prefix_index, sizeof(int32));
+	p += sizeof(int32);
+
+	/* parameter buffer follows */
+	if (paramlen)
+		memcpy(p, param, paramlen);
+
+	*perr = 0;
+	return iolen;
+}
+
+static int
+wl_bssiovar_mkbuf(const char *iovar, int bssidx, void *param,
+	int paramlen, void *bufptr, int buflen, int *perr)
+{
+	const char *prefix = "bsscfg:";
+	return wl_prefixiovar_mkbuf(iovar, prefix, bssidx,  param, paramlen, bufptr, buflen, perr);
+}
+/*
+ * set named & bss indexed driver iovar providing both parameter and i/o buffers
+ */
+int
+wlu_bssiovar_setbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+	int iolen;
+
+	iolen = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_set(wl, WLC_SET_VAR, bufptr, iolen);
+}
+
+/*
+ * get named & bss indexed driver iovar providing both parameter and i/o buffers
+ */
+static int
+wl_bssiovar_getbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+
+	wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_get(wl, WLC_GET_VAR, bufptr, buflen);
+}
+
+/*
+ * get named & bss indexed driver variable to buffer value
+ */
+int
+wlu_bssiovar_get(void *wl, const char *iovar, int bssidx, void *outbuf, int len)
+{
+	char smbuf[WLC_IOCTL_SMLEN];
+	int err;
+
+	/* use the return buffer if it is bigger than what we have on the stack */
+	if (len > (int)sizeof(smbuf)) {
+		err = wl_bssiovar_getbuf(wl, iovar, bssidx, NULL, 0, outbuf, len);
+	} else {
+		memset(smbuf, 0, sizeof(smbuf));
+		err = wl_bssiovar_getbuf(wl, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
+		if (err == 0)
+			memcpy(outbuf, smbuf, len);
+	}
+
+	return err;
+}
+
+/*
+ * set named & bss indexed driver variable to buffer value
+ */
+static int
+wl_bssiovar_set(void *wl, const char *iovar, int bssidx, void *param, int paramlen)
+{
+	char smbuf[WLC_IOCTL_SMLEN];
+
+	memset(smbuf, 0, sizeof(smbuf));
+
+	return wlu_bssiovar_setbuf(wl, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+/*
+ * get named & bsscfg indexed driver variable as an int value
+ */
+static int
+wl_bssiovar_getint(void *wl, const char *iovar, int bssidx, int *pval)
+{
+	int ret;
+
+	ret = wlu_bssiovar_get(wl, iovar, bssidx, pval, sizeof(int));
+	if (ret == 0)
+	{
+		*pval = dtoh32(*pval);
+	}
+	return ret;
+}
+
+/*
+ * set named & bsscfg indexed driver variable to int value
+ */
+static int
+wl_bssiovar_setint(void *wl, const char *iovar, int bssidx, int val)
+{
+	val = htod32(val);
+	return wl_bssiovar_set(wl, iovar, bssidx, &val, sizeof(int));
+}
+
+static int
+wl_nvdump(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	const char *iovar = "nvram_dump";
+	void *p = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the "nvdump/nvram_dump" command name */
+	argv++;
+
+	if (*argv) {
+		printf("nvdump error: extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf(wl, iovar, NULL, 0, &p)) < 0) {
+		if ((err = wlu_get(wl, WLC_NVRAM_DUMP, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+		    return err;
+		p = (void *)buf;
+	}
+	printf("%s\n", (char *)p);
+
+	return err;
+}
+
+/** Queries the driver for the value of a caller supplied nvram variable */
+static int
+wl_nvget(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	char *varname;
+	const char *iovar = "nvram_get";
+	void *p;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the "nvget/nvram_get" command name */
+	argv++;
+
+	if (!*argv) {
+		printf("nvget: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (*argv) {
+		printf("nvget error: extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf(wl, iovar, varname, strlen(varname) + 1, &p)) < 0) {
+
+		strcpy(buf, varname);
+		if ((err = wlu_get(wl, WLC_NVRAM_GET, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+		    return err;
+	}
+
+	printf("%s\n", buf);
+
+	return err;
+}
+
+static int
+wl_nvset(void *wl, cmd_t *cmd, char **argv)
+{
+	char *varname;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the "nvset" command name if present */
+	if (!strcmp("nvset", *argv))
+		argv++;
+
+	if (!*argv) {
+		printf("nvset: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (*argv) {
+		fprintf(stderr,
+		"nvset error: extra arg \"%s\"; format is name=value (no spaces around '=')\n",
+			*argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!strchr(varname, '=')) {
+		fprintf(stderr,
+		"nvset error: no '=' in \"%s\", format is name=value (no spaces around '=')\n",
+			*argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, varname);
+
+	return (wlu_set(wl, WLC_NVRAM_SET, &buf[0], strlen(buf) + 1));
+}
+
+static int
+wl_chan_info(void *wl, cmd_t *cmd, char **argv)
+{
+	uint bitmap;
+	uint channel;
+	uint32 chanspec_arg;
+	int buflen, err, first, last, minutes;
+	char *param;
+	bool all;
+
+	if (!*++argv) {
+		first = 0;
+		last = MAXCHANNEL;
+		all = TRUE;
+	} else {
+		last = first = atoi(*argv);
+		if (last <= 0) {
+			printf(" Usage: %s [channel | All ]\n", cmd->name);
+			return BCME_USAGE_ERROR;
+		}
+		all = FALSE;
+	}
+
+	for (; first <= last; first++) {
+		channel = first;
+		chanspec_arg = CH20MHZ_CHSPEC(channel);
+
+		strcpy(buf, "per_chan_info");
+		buflen = strlen(buf) + 1;
+		param = (char *)(buf + buflen);
+		/* there should be no problem if converting to a legacy chanspec
+		 * since chanspec_arg is created as 20MHz
+		 */
+		chanspec_arg = wl_chspec32_to_driver(chanspec_arg);
+		memcpy(param, (char*)&chanspec_arg, sizeof(chanspec_arg));
+
+		if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return err;
+
+		bitmap = dtoh32(*(uint *)buf);
+		minutes = (bitmap >> 24) & 0xff;
+
+		if (!(bitmap & WL_CHAN_VALID_HW)) {
+			if (!all)
+				printf("Invalid Channel\n");
+			continue;
+		}
+
+		if (!(bitmap & WL_CHAN_VALID_SW)) {
+			if (!all)
+				printf("Not supported in current locale\n");
+			continue;
+		}
+
+		printf("Channel %d\t", channel);
+
+		if (bitmap & WL_CHAN_BAND_5G)
+			printf("A Band");
+		else
+			printf("B Band");
+
+		if (bitmap & WL_CHAN_RADAR) {
+			printf(", RADAR Sensitive");
+		}
+		if (bitmap & WL_CHAN_RESTRICTED) {
+			printf(", Restricted");
+		}
+		if (bitmap & WL_CHAN_PASSIVE) {
+			printf(", Passive");
+		}
+		if (bitmap & WL_CHAN_INACTIVE) {
+			printf(", Temporarily Out of Service for %d minutes", minutes);
+		}
+		printf("\n");
+	}
+
+	return (0);
+}
+
+static int
+wl_test_tssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char* endptr = NULL;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	val = htod32(strtol(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &val, sizeof(val),
+	                      buf, WLC_IOCTL_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	val = dtoh32(*(int*)buf);
+
+	wl_printint(val);
+
+	return ret;
+}
+
+static int
+wl_test_tssi_offs(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char* endptr = NULL;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	val = htod32(strtol(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &val, sizeof(val),
+	                      buf, WLC_IOCTL_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	val = dtoh32(*(int*)buf);
+
+	wl_printint(val);
+
+	return ret;
+}
+
+static int
+wl_test_idletssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char* endptr = NULL;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	val = htod32(strtol(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer\n", *argv);
+		return -1;
+	}
+
+	if ((ret = wlu_iovar_getbuf(wl, cmd->name, &val, sizeof(val),
+		buf, WLC_IOCTL_MAXLEN)) >= 0) {
+		val = dtoh32(*(int*)buf);
+		wl_printint(val);
+	}
+
+	return ret;
+}
+
+static int
+wl_sta_info(void *wl, cmd_t *cmd, char **argv)
+{
+	sta_info_t *sta;
+	struct ether_addr ea;
+	char *param;
+	int buflen, err;
+	int i;
+
+	/* convert the ea string into an ea struct */
+	if (!*++argv || !wl_ether_atoe(*argv, &ea)) {
+		printf(" ERROR: no valid ether addr provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, "sta_info");
+	buflen = strlen(buf) + 1;
+	param = (char *)(buf + buflen);
+	memcpy(param, (char*)&ea, ETHER_ADDR_LEN);
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MEDLEN)) < 0)
+		return err;
+
+	/* display the sta info */
+	sta = (sta_info_t *)buf;
+	sta->ver = dtoh16(sta->ver);
+
+	/* Report unrecognized version */
+	if (sta->ver > WL_STA_VER) {
+		printf(" ERROR: unknown driver station info version %d\n", sta->ver);
+		return BCME_ERROR;
+	}
+
+	sta->len = dtoh16(sta->len);
+	sta->cap = dtoh16(sta->cap);
+	sta->aid = dtoh16(sta->aid);
+	sta->flags = dtoh32(sta->flags);
+	sta->idle = dtoh32(sta->idle);
+	sta->rateset.count = dtoh32(sta->rateset.count);
+	sta->in = dtoh32(sta->in);
+	sta->listen_interval_inms = dtoh32(sta->listen_interval_inms);
+	sta->ht_capabilities = dtoh16(sta->ht_capabilities);
+	sta->vht_flags = dtoh16(sta->vht_flags);
+
+	printf(" STA %s:\n", *argv);
+	printf("\t aid:%d ", WL_STA_AID(sta->aid));
+	printf("\n\t rateset ");
+	dump_rateset(sta->rateset.rates, sta->rateset.count);
+	printf("\n\t idle %d seconds\n", sta->idle);
+	printf("\t in network %d seconds\n", sta->in);
+	printf("\t state:%s%s%s\n",
+	       (sta->flags & WL_STA_AUTHE) ? " AUTHENTICATED" : "",
+	       (sta->flags & WL_STA_ASSOC) ? " ASSOCIATED" : "",
+	       (sta->flags & WL_STA_AUTHO) ? " AUTHORIZED" : "");
+
+	printf("\t flags 0x%x:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+	       sta->flags,
+	       (sta->flags & WL_STA_BRCM) ? " BRCM" : "",
+	       (sta->flags & WL_STA_WME) ? " WME" : "",
+	       (sta->flags & WL_STA_PS) ? " PS" : "",
+	       (sta->flags & WL_STA_NONERP) ? " No-ERP" : "",
+	       (sta->flags & WL_STA_APSD_BE) ? " APSD_BE" : "",
+	       (sta->flags & WL_STA_APSD_BK) ? " APSD_BK" : "",
+	       (sta->flags & WL_STA_APSD_VI) ? " APSD_VI" : "",
+	       (sta->flags & WL_STA_APSD_VO) ? " APSD_VO" : "",
+	       (sta->flags & WL_STA_N_CAP) ? " N_CAP" : "",
+	       (sta->flags & WL_STA_VHT_CAP) ? " VHT_CAP" : "",
+	       (sta->flags & WL_STA_AMPDU_CAP) ? " AMPDU" : "",
+	       (sta->flags & WL_STA_AMSDU_CAP) ? " AMSDU" : "",
+	       (sta->flags & WL_STA_MIMO_PS) ? " MIMO-PS" : "",
+	       (sta->flags & WL_STA_MIMO_RTS) ? " MIMO-PS-RTS" : "",
+	       (sta->flags & WL_STA_RIFS_CAP) ? " RIFS" : "");
+
+	printf("\t HT caps 0x%x:%s%s%s%s%s%s%s%s%s\n",
+		sta->ht_capabilities,
+	       (sta->ht_capabilities & WL_STA_CAP_LDPC_CODING) ? " LDPC" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_40MHZ) ? " 40MHz" : " ",
+	       (sta->ht_capabilities & WL_STA_CAP_GF) ? " GF" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_SHORT_GI_20) ? " SGI20" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_SHORT_GI_40) ? " SGI40" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_TX_STBC) ? " STBC-Tx" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_RX_STBC_MASK) ? " STBC-Rx" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_DELAYED_BA) ? " D-BlockAck" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_40MHZ_INTOLERANT) ? " 40-Intl" : "");
+
+	if (sta->flags & WL_STA_VHT_CAP) {
+		printf("\t VHT caps 0x%x:%s%s%s%s%s%s%s%s%s%s%s\n",
+			sta->vht_flags,
+			(sta->vht_flags & WL_STA_VHT_LDPCCAP) ? " LDPC" : "",
+			(sta->vht_flags & WL_STA_SGI80) ? " SGI80" : "",
+			(sta->vht_flags & WL_STA_SGI160) ? " SGI160" : "",
+			(sta->vht_flags & WL_STA_VHT_TX_STBCCAP) ? " STBC-Tx" : "",
+			(sta->vht_flags & WL_STA_VHT_RX_STBCCAP) ? " STBC-Rx" : "",
+			(sta->vht_flags & WL_STA_SU_BEAMFORMER) ? " SU-BFR" : "",
+			(sta->vht_flags & WL_STA_SU_BEAMFORMEE) ? " SU-BFE" : "",
+			(sta->vht_flags & WL_STA_MU_BEAMFORMER) ? " MU-BFR" : "",
+			(sta->vht_flags & WL_STA_MU_BEAMFORMEE) ? " MU-BFE" : "",
+			(sta->vht_flags & WL_STA_VHT_TXOP_PS) ? " TXOPPS" : "",
+			(sta->vht_flags & WL_STA_HTC_VHT_CAP) ? " VHT-HTC" : "");
+	}
+
+	/* Driver didn't return extended station info */
+	if (sta->len < sizeof(sta_info_t))
+		return 0;
+
+	if (sta->flags & WL_STA_SCBSTATS)
+	{
+		printf("\t tx data pkts: %d\n", dtoh32(sta->tx_tot_pkts));
+		printf("\t tx data bytes: %llu\n", dtoh64(sta->tx_tot_bytes));
+		printf("\t tx ucast pkts: %d\n", dtoh32(sta->tx_pkts));
+		printf("\t tx ucast bytes: %llu\n", dtoh64(sta->tx_ucast_bytes));
+		printf("\t tx mcast/bcast pkts: %d\n", dtoh32(sta->tx_mcast_pkts));
+		printf("\t tx mcast/bcast bytes: %llu\n", dtoh64(sta->tx_mcast_bytes));
+		printf("\t tx failures: %d\n", dtoh32(sta->tx_failures));
+		printf("\t rx data pkts: %d\n", dtoh32(sta->rx_tot_pkts));
+		printf("\t rx data bytes: %llu\n", dtoh64(sta->rx_tot_bytes));
+		printf("\t rx ucast pkts: %d\n", dtoh32(sta->rx_ucast_pkts));
+		printf("\t rx ucast bytes: %llu\n", dtoh64(sta->rx_ucast_bytes));
+		printf("\t rx mcast/bcast pkts: %d\n", dtoh32(sta->rx_mcast_pkts));
+		printf("\t rx mcast/bcast bytes: %llu\n", dtoh64(sta->rx_mcast_bytes));
+		printf("\t rate of last tx pkt: %d kbps\n", dtoh32(sta->tx_rate));
+		printf("\t rate of last rx pkt: %d kbps\n", dtoh32(sta->rx_rate));
+		printf("\t rx decrypt succeeds: %d\n", dtoh32(sta->rx_decrypt_succeeds));
+		printf("\t rx decrypt failures: %d\n", dtoh32(sta->rx_decrypt_failures));
+		printf("\t tx data pkts retried: %d\n", dtoh32(sta->tx_pkts_retried));
+		printf("\t tx data pkts retry exhausted: %d\n",
+			dtoh32(sta->tx_pkts_retry_exhausted));
+		for (i = WL_ANT_IDX_1; i < WL_RSSI_ANT_MAX; i++) {
+			if (i == WL_ANT_IDX_1)
+				printf("\t per antenna rssi of last rx data frame:");
+			printf(" %d", dtoh32(sta->rx_lastpkt_rssi[i]));
+			if (i == WL_RSSI_ANT_MAX-1)
+				printf("\n");
+		}
+		for (i = WL_ANT_IDX_1; i < WL_RSSI_ANT_MAX; i++) {
+			if (i == WL_ANT_IDX_1)
+				printf("\t per antenna average rssi of rx data frames:");
+			printf(" %d", dtoh32(sta->rssi[i]));
+			if (i == WL_RSSI_ANT_MAX-1)
+				printf("\n");
+		}
+		for (i = WL_ANT_IDX_1; i < WL_RSSI_ANT_MAX; i++) {
+			if (i == WL_ANT_IDX_1)
+				printf("\t per antenna noise floor:");
+			printf(" %d", dtoh32(sta->nf[i]));
+			if (i == WL_RSSI_ANT_MAX-1)
+				printf("\n");
+		}
+	}
+
+	return (0);
+}
+
+static int
+wl_revinfo(void *wl, cmd_t *cmd, char **argv)
+{
+	char b[8];
+	int err;
+	wlc_rev_info_t revinfo;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(&revinfo, 0, sizeof(revinfo));
+
+	if ((err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return err;
+
+	printf("vendorid 0x%x\n", dtoh32(revinfo.vendorid));
+	printf("deviceid 0x%x\n", dtoh32(revinfo.deviceid));
+	printf("radiorev 0x%x\n", dtoh32(revinfo.radiorev));
+	printf("chipnum 0x%x\n", dtoh32(revinfo.chipnum));
+	printf("chiprev 0x%x\n", dtoh32(revinfo.chiprev));
+	printf("chippackage 0x%x\n", dtoh32(revinfo.chippkg));
+	printf("corerev 0x%x\n", dtoh32(revinfo.corerev));
+	printf("boardid 0x%x\n", dtoh32(revinfo.boardid));
+	printf("boardvendor 0x%x\n", dtoh32(revinfo.boardvendor));
+	printf("boardrev %s\n", bcm_brev_str(dtoh32(revinfo.boardrev), b));
+	printf("driverrev 0x%x\n", dtoh32(revinfo.driverrev));
+	printf("ucoderev 0x%x\n", dtoh32(revinfo.ucoderev));
+	printf("bus 0x%x\n", dtoh32(revinfo.bus));
+	printf("phytype 0x%x\n", dtoh32(revinfo.phytype));
+	printf("phyrev 0x%x\n", dtoh32(revinfo.phyrev));
+	printf("anarev 0x%x\n", dtoh32(revinfo.anarev));
+	printf("nvramrev %d\n", dtoh32(revinfo.nvramrev));
+
+	return 0;
+}
+
+static int
+wl_rm_request(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_rm_request";
+	wl_rm_req_t *rm_ptr;
+	wl_rm_req_t rm;
+	wl_rm_req_elt_t req;
+	int buflen = 0;
+	int err, opt_err;
+	int type;
+	bool in_measure = FALSE;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	memset(&rm, 0, WL_RM_REQ_FIXED_LEN);
+	memset(&req, 0, sizeof(wl_rm_req_elt_t));
+
+	strcpy(buf, "rm_req");
+	buflen = strlen(buf) + 1;
+
+	rm_ptr = (wl_rm_req_t*)(buf + buflen);
+	buflen += WL_RM_REQ_FIXED_LEN;
+
+	/* toss the command name */
+	argv++;
+
+	miniopt_init(&to, fn_name, "p", FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == 't') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for the token\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+
+			if (!in_measure)
+				rm.token = to.val;
+			else
+				req.token = to.val;
+		}
+		if (to.opt == 'c') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for channel\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+
+			req.chanspec = CH20MHZ_CHSPEC(to.val);
+		}
+		if (to.opt == 'd') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for duration\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			req.dur = to.val;
+		}
+
+		if (to.opt == 'p') {
+			req.flags = WL_RM_FLAG_PARALLEL;
+		}
+
+		if (to.positional) {
+			if (!strcmp(to.valstr, "basic")) {
+				type = WL_RM_TYPE_BASIC;
+			} else if (!strcmp(to.valstr, "cca")) {
+				type = WL_RM_TYPE_CCA;
+			} else if (!strcmp(to.valstr, "rpi")) {
+				type = WL_RM_TYPE_RPI;
+			} else {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as a measurement type\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			/* complete the previous measurement */
+			if (in_measure) {
+				req.chanspec = wl_chspec_to_driver(req.chanspec);
+				req.token = htod32(req.token);
+				req.tsf_h = htod32(req.tsf_h);
+				req.tsf_l = htod32(req.tsf_l);
+				req.dur = htod32(req.dur);
+				memcpy(buf + buflen, &req, sizeof(wl_rm_req_elt_t));
+				buflen += sizeof(wl_rm_req_elt_t);
+				rm.count++;
+				req.chanspec = wl_chspec_from_driver(req.chanspec);
+				req.token = dtoh32(req.token);
+				req.tsf_h = dtoh32(req.tsf_h);
+				req.tsf_l = dtoh32(req.tsf_l);
+				req.dur = dtoh32(req.dur);
+				/* measure to measure default param update */
+				req.token++;	/* each measure gets a new token */
+				req.flags = 0;	/* measure flags are cleared between measures */
+			}
+			in_measure = TRUE;
+			req.type = (int8)type;
+		}
+	}
+
+	/* complete the last measurement */
+	if (in_measure) {
+		req.chanspec = wl_chspec_to_driver(req.chanspec);
+		req.token = htod32(req.token);
+		req.tsf_h = htod32(req.tsf_h);
+		req.tsf_l = htod32(req.tsf_l);
+		req.dur = htod32(req.dur);
+		memcpy(buf + buflen, &req, sizeof(wl_rm_req_elt_t));
+		buflen += sizeof(wl_rm_req_elt_t);
+		rm.count++;
+	}
+
+	if (rm.count == 0) {
+		fprintf(stderr, "%s: no measurement requests specified\n",
+			fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	rm.token = htod32(rm.token);
+	rm.count = htod32(rm.count);
+	memcpy(rm_ptr, &rm, WL_RM_REQ_FIXED_LEN);
+
+	err = wlu_set(wl, WLC_SET_VAR, &buf[0], buflen);
+
+exit:
+	return err;
+}
+
+static int
+wl_rm_report(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_rm_rep_t *rep_set;
+	wl_rm_rep_elt_t rep;
+	char extra[128];
+	char* p;
+	const char* name;
+	uint8* data;
+	int err, bin;
+	uint32 val;
+	uint16 channel;
+	bool aband;
+	int len;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	strcpy(buf, "rm_rep");
+
+	if ((err = wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	rep_set = (wl_rm_rep_t *)buf;
+	rep_set->token = dtoh32(rep_set->token);
+	rep_set->len = dtoh32(rep_set->len);
+
+	printf("Measurement Report: token %d, length %d\n", rep_set->token, rep_set->len);
+
+	len = rep_set->len;
+	data = (uint8*)rep_set->rep;
+	for (; len > 0; (len -= rep.len), (data += rep.len)) {
+		if (len >= WL_RM_REP_ELT_FIXED_LEN)
+			memcpy(&rep, data, WL_RM_REP_ELT_FIXED_LEN);
+		else
+			break;
+
+		rep.chanspec = wl_chspec_from_driver(rep.chanspec);
+		rep.token = dtoh32(rep.token);
+		rep.tsf_h = dtoh32(rep.tsf_h);
+		rep.tsf_l = dtoh32(rep.tsf_l);
+		rep.dur = dtoh32(rep.dur);
+		rep.len = dtoh32(rep.len);
+
+		data += WL_RM_REP_ELT_FIXED_LEN;
+		len -= WL_RM_REP_ELT_FIXED_LEN;
+
+		if (rep.type == WL_RM_TYPE_BASIC)
+			name = "Basic";
+		else if (rep.type == WL_RM_TYPE_CCA)
+			name = "CCA";
+		else if (rep.type == WL_RM_TYPE_RPI)
+			name = "RPI";
+		else
+			name = NULL;
+
+		if (name)
+			printf("\nReport   : %s\n", name);
+		else
+			printf("\nReport   : %d <unknown>\n", rep.type);
+
+		p = extra;
+		if (rep.flags & WL_RM_FLAG_PARALLEL) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Parallel");
+		}
+		if (rep.flags & WL_RM_FLAG_LATE) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Late");
+		}
+		if (rep.flags & WL_RM_FLAG_INCAPABLE) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Incapable");
+		}
+		if (rep.flags & WL_RM_FLAG_REFUSED) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Refused");
+		}
+
+		if (p != extra) {
+			printf("flags    : 0x%02x (%s)\n", rep.flags, extra);
+		} else {
+			printf("flags    : 0x%02x\n", rep.flags);
+		}
+		printf("token    : %4d\n", rep.token);
+
+		if (rep.flags & (WL_RM_FLAG_LATE |
+			WL_RM_FLAG_INCAPABLE |
+			WL_RM_FLAG_REFUSED)) {
+			continue;
+		}
+
+		channel = CHSPEC_CHANNEL(rep.chanspec);
+		aband = CHSPEC_IS5G(rep.chanspec);
+
+		printf("channel  : %4d %s\n", channel,
+		       aband ? "(a)":"(b)");
+		printf("start tsf: 0x%x:%08x\n", rep.tsf_h, rep.tsf_l);
+		printf("duration : %4d TU\n", rep.dur);
+
+		if (len < (int)rep.len) {
+			printf("Error: partial report element, %d report bytes "
+			       "remain, element claims %d\n",
+			       len, rep.len);
+			break;
+		}
+
+		if (rep.type == WL_RM_TYPE_BASIC) {
+			if (rep.len >= 4) {
+				memcpy(&val, data, sizeof(uint32));
+				val = dtoh32(val);
+				printf("Basic bits: 0x%08x\n", val);
+			}
+		} else if (rep.type == WL_RM_TYPE_CCA) {
+			if (rep.len >= 4) {
+				memcpy(&val, data, sizeof(uint32));
+				val = dtoh32(val);
+				printf("Carrier Fraction: %d / 255\n", val);
+			}
+		} else if (rep.type == WL_RM_TYPE_RPI) {
+			if (rep.len >= sizeof(wl_rm_rpi_rep_t)) {
+				wl_rm_rpi_rep_t rpi_rep;
+				int8 min = -128;
+				int8 max;
+
+				memcpy(&rpi_rep, data, sizeof(wl_rm_rpi_rep_t));
+
+				for (bin = 0; bin < 8; bin++) {
+					max = rpi_rep.rpi_max[bin];
+					if (bin == 0)
+						printf("       Power <= %3d: ",
+						       max);
+					else if (bin < 7)
+						printf(" %3d < Power <= %3d: ",
+						       min, max);
+					else
+						printf(" %3d < Power       : ",
+						       min);
+					min = max;
+					printf("%3d\n", rpi_rep.rpi[bin]);
+				}
+			}
+		}
+	}
+
+	return err;
+}
+
+static int
+wl_join_pref(void *wl, cmd_t *cmd, char **argv)
+{
+	char* data;
+	int err;
+	int len;
+	int remaining_bytes;
+	int i;
+	bcm_tlv_t *ie;
+
+	UNUSED_PARAMETER(cmd);
+
+	strcpy(buf, "join_pref");
+
+	/* set */
+	if (argv[1]) {
+		len = strlen(buf);
+		data = argv[1];
+		for (i = len + 1, len += 1 + strlen(data) / 2;
+		    (i < len) && (i < (int)WLC_IOCTL_MAXLEN); i ++) {
+			char hex[] = "XX";
+			hex[0] = *data++;
+			hex[1] = *data++;
+			buf[i] = (uint8)strtoul(hex, NULL, 16);
+		}
+		err = wlu_set(wl, WLC_SET_VAR, buf, i);
+	}
+	/* get */
+	else if (!(err = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_MAXLEN))) {
+		len = dtoh32(*(int *)buf);
+		data = buf + sizeof(int);
+		for (i = 0; i < len; i ++)
+			printf("%02x", (uint8)(data[i]));
+		printf("\n");
+		/* pretty print the join pref elements */
+		remaining_bytes = len;
+		ie = (bcm_tlv_t*)data;
+		if (!bcm_valid_tlv(ie, remaining_bytes))
+		    ie = NULL;
+		while (ie) {
+			wl_join_pref_print_ie(ie);
+			ie = bcm_next_tlv(ie, &remaining_bytes);
+		}
+	}
+	return err;
+}
+
+static void
+wl_join_pref_print_ie(bcm_tlv_t *ie)
+{
+	int i;
+	uint8 band;
+	uint8 count;
+	int suite_len;
+	uint8 *suite;
+	int data_bytes;
+
+
+	switch (ie->id) {
+	case WL_JOIN_PREF_RSSI:
+		printf("Pref RSSI\n");
+		if (ie->len > 2)
+			printf("\t<%d extra bytes in pref data>\n", ie->len);
+		break;
+	case WL_JOIN_PREF_BAND:
+		printf("Pref BAND: ");
+		if (ie->len < 2) {
+			printf("len = %d <band pref data truncated>\n", ie->len);
+			break;
+		}
+
+		band = ie->data[1];
+		if (band == WLC_BAND_AUTO)
+			printf("0x%x AUTO (no preference)\n", band);
+		else if (band == WLC_BAND_5G)
+			printf("0x%x 5 GHz\n", band);
+		else if (band == WLC_BAND_2G)
+			printf("0x%x 2.4 GHz\n", band);
+		else if (band == WLJP_BAND_ASSOC_PREF)
+			printf("0x%x Use ASSOC_PREFER value\n", band);
+		else
+			printf("0x%x\n", band);
+
+		if (ie->len > 2)
+			printf("\t<%d extra bytes in pref data>\n", ie->len - 1);
+
+		break;
+	case WL_JOIN_PREF_WPA:
+		printf("Pref WPA: ");
+		if (ie->len < 2) {
+			printf("len = %d <WPA pref data truncated>\n", ie->len);
+			break;
+		}
+		count = ie->data[1];
+		printf("%d ACP Specs\n", count);
+
+		data_bytes = ie->len - 2;
+		suite_len = 4; /* WPA Suite Selector length, OUI + type */
+		suite = ie->data + 2;
+
+		for (i = 0; i < (int)count; i++) {
+			if (data_bytes < 3 * suite_len)
+				break;
+			printf("\t");
+			/* AKM Suite */
+			wl_join_pref_print_akm(suite);
+			printf(",");
+
+			suite = suite + suite_len;
+			/* Unicast Cipher Suite */
+			printf("U:");
+			wl_join_pref_print_cipher_suite(suite);
+			printf(",");
+
+			suite = suite + suite_len;
+			/* Multicast Cipher Suite */
+			printf("M:");
+			if (!memcmp(suite, WL_WPA_ACP_MCS_ANY, suite_len))
+				printf("Any");
+			else
+				wl_join_pref_print_cipher_suite(suite);
+			printf("\n");
+
+			suite = suite + suite_len;
+			data_bytes -= 3 * suite_len;
+		}
+
+		if (i != count)
+			printf("\t<expected %d more specs, %d bytes>\n",
+			count - i, suite_len * (count - i));
+		if (data_bytes > 0)
+			printf("\t<%d extra bytes>\n", data_bytes);
+		break;
+	case WL_JOIN_PREF_RSSI_DELTA:
+		printf("RSSI Delta for Pref BAND: ");
+		if (ie->len < 2) {
+			printf("len = %d <rssi delta pref data truncated>\n", ie->len);
+			break;
+		}
+
+		band = ie->data[1];
+		if (band == WLC_BAND_AUTO)
+			printf("0x%x AUTO (no preference)\n", band);
+		else if (band == WLC_BAND_5G)
+			printf("0x%x 5 GHz\n", band);
+		else if (band == WLC_BAND_2G)
+			printf("0x%x 2.4 GHz\n", band);
+		else
+			printf("0x%x\n", band);
+
+		printf("RSSI boost %ddb\n", ie->data[0]);
+
+		break;
+	default:
+		printf("Pref 0x%x: len = %d\n", ie->id, ie->len);
+		for (i = 0; i < ie->len; i++)
+			printf("%02x", ie->data[i]);
+		printf("\n");
+		break;
+
+	}
+
+}
+
+static void
+wl_join_pref_print_akm(uint8* suite)
+{
+	uint8 type = suite[3];
+	const char *oui_name;
+
+	if (!memcmp(suite, WPA_OUI, 3))
+		oui_name = "WPA";
+	else if (!memcmp(suite, WPA2_OUI, 3))
+		oui_name = "WPA2";
+	else
+		oui_name = NULL;
+
+	if (oui_name) {
+		if (type == RSN_AKM_NONE)
+			printf("%s-NONE", oui_name);
+		else if (type == RSN_AKM_UNSPECIFIED)
+			printf("%s", oui_name);
+		else if (type == RSN_AKM_UNSPECIFIED)
+			printf("%s-PSK", oui_name);
+		else
+			printf("%s/0x%x", oui_name, type);
+	} else {
+		printf("0x%02x%02x%02x/0x%02x", suite[0], suite[1], suite[2], suite[3]);
+	}
+}
+
+static void
+wl_join_pref_print_cipher_suite(uint8* suite)
+{
+	uint8 type = suite[3];
+	const char *oui_name;
+
+	if (!memcmp(suite, WPA_OUI, 3))
+		oui_name = "WPA";
+	else if (!memcmp(suite, WPA2_OUI, 3))
+		oui_name = "WPA2";
+	else
+		oui_name = NULL;
+
+	if (oui_name) {
+		if (type == WPA_CIPHER_NONE)
+			printf("%s/NONE", oui_name);
+		else if (type == WPA_CIPHER_WEP_40)
+			printf("%s/WEP40", oui_name);
+		else if (type == WPA_CIPHER_TKIP)
+			printf("%s/TKIP", oui_name);
+		else if (type == WPA_CIPHER_AES_CCM)
+			printf("%s/AES", oui_name);
+		else if (type == WPA_CIPHER_WEP_104)
+			printf("%s/WEP104", oui_name);
+		else
+			printf("%s/0x%x", oui_name, type);
+	} else {
+		printf("0x%02x%02x%02x/0x%02x", suite[0], suite[1], suite[2], suite[3]);
+	}
+}
+
+static int
+wl_assoc_pref(void *wl, cmd_t *cmd, char **argv)
+{
+	uint assoc_pref;
+	int err;
+
+	/* set */
+	if (argv[1]) {
+		if (!strcmp(argv[1], "auto") || !strcmp(argv[1], "0"))
+			assoc_pref = WLC_BAND_AUTO;
+		else if (!strcmp(argv[1], "a") || !strcmp(argv[1], "1"))
+			assoc_pref = WLC_BAND_5G;
+		else if (!strcmp(argv[1], "b") || !strcmp(argv[1], "g") || !strcmp(argv[1], "2"))
+			assoc_pref = WLC_BAND_2G;
+		else
+			return BCME_USAGE_ERROR;
+		assoc_pref = htod32(assoc_pref);
+		err = wlu_set(wl, cmd->set, &assoc_pref, sizeof(assoc_pref));
+	}
+	/* get */
+	else if (!(err = wlu_get(wl, cmd->get, &assoc_pref, sizeof(assoc_pref)))) {
+		assoc_pref = dtoh32(assoc_pref);
+		switch (assoc_pref) {
+		case WLC_BAND_AUTO:
+			printf("auto\n");
+			break;
+		case WLC_BAND_5G:
+			printf("a\n");
+			break;
+		case WLC_BAND_2G:
+			printf("b/g\n");
+			break;
+		}
+	}
+	return err;
+}
+
+static const char ac_names[AC_COUNT][6] = {"AC_BE", "AC_BK", "AC_VI", "AC_VO"};
+
+/*
+ * Get or set WME per-AC transmit parameters
+ */
+static int
+wme_tx_params(void *wl, cmd_t *cmd, char **argv)
+{
+	char *val_p, *ac_str, *param;
+	int buflen;
+	int aci;
+	wme_tx_params_t cur_params[AC_COUNT], new_params[AC_COUNT];
+	int err;
+	int val;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	buflen = WLC_IOCTL_MAXLEN;
+
+	/*
+	 * Get current acparams, using buf as an input buffer.
+	 * Return data is array of 4 ACs of wme params.
+	 */
+
+	strcpy(buf, "wme_tx_params");
+	if ((err = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen)) < 0) {
+		return err;
+	}
+	memcpy(&cur_params, buf, WL_WME_TX_PARAMS_IO_BYTES);
+
+	if ((ac_str = *argv++) == NULL) {
+		printf("WME TX params: \n");
+		for (aci = 0; aci < AC_COUNT; aci++) {
+			printf("%s: short %d. sfb %d. long %d. lfb %d. max %d\n", ac_names[aci],
+				cur_params[aci].short_retry,
+				cur_params[aci].short_fallback,
+				cur_params[aci].long_retry,
+				cur_params[aci].long_fallback,
+				cur_params[aci].max_rate);
+		}
+	} else {
+		int chk_lim;
+		if (strcmp(ac_str, "be") == 0) {
+			aci = AC_BE;
+		} else if (strcmp(ac_str, "bk") == 0) {
+			aci = AC_BK;
+		} else if (strcmp(ac_str, "vi") == 0) {
+			aci = AC_VI;
+		} else if (strcmp(ac_str, "vo") == 0) {
+			aci = AC_VO;
+		} else {
+			printf("Unknown access class: %s\n", ac_str);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* Preload new values with current values */
+		memcpy(&new_params, &cur_params, sizeof(new_params));
+		while ((param = *argv++) != NULL) {
+			if ((val_p = *argv++) == NULL) {
+				printf("Need value following %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+			chk_lim = 15;
+			val = (int)strtoul(val_p, NULL, 0);
+			/* All values must fit in uint8 */
+			if (!strcmp(param, "short")) {
+				new_params[aci].short_retry = (uint8)val;
+			} else if (!strcmp(param, "sfb")) {
+				new_params[aci].short_fallback = (uint8)val;
+			} else if (!strcmp(param, "long")) {
+				new_params[aci].long_retry = (uint8)val;
+			} else if (!strcmp(param, "lfb")) {
+				new_params[aci].long_fallback = (uint8)val;
+			} else if ((!strcmp(param, "max_rate")) || (!strcmp(param, "max")) ||
+				(!strcmp(param, "rate"))) {
+				chk_lim = 255;
+				new_params[aci].max_rate = (uint8)val;
+			} else {
+				printf("Unknown parameter: %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+			if (val > chk_lim) {
+				printf("Value for %s must be < %d\n", param, chk_lim + 1);
+				return BCME_USAGE_ERROR;
+			}
+		}
+		strcpy(buf, "wme_tx_params");
+		memcpy(buf + strlen(buf) + 1, new_params, WL_WME_TX_PARAMS_IO_BYTES);
+		err = wlu_set(wl, WLC_SET_VAR, &buf[0], buflen);
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME Access Class (AC) parameters
+ *	wl wme_ac ap|sta [be|bk|vi|vo [ecwmax|ecwmin|txop|aifsn|acm <value>] ...]
+ * Without args past ap|sta, print current values
+ */
+static int
+wl_wme_ac_req(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *iovar_name;
+	int err;
+	edcf_acparam_t acparam_cur[AC_COUNT], acparam_new[AC_COUNT], *acp;
+	char *ac_str, *param, *val;
+	bool acm;
+	int aci, aifsn, ecwmin, ecwmax, txop;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if ((param = *argv++) == NULL)
+		return BCME_USAGE_ERROR;
+
+	if (!strcmp(param, "ap"))
+		iovar_name = "wme_ac_ap";
+	else if (!strcmp(param, "sta"))
+		iovar_name = "wme_ac_sta";
+	else
+		return BCME_USAGE_ERROR;
+
+	/*
+	 * Get current acparams into an array of 4 ACs of wme params.
+	 */
+	err = wlu_iovar_get(wl, iovar_name, &acparam_cur, sizeof(acparam_cur));
+	if (err < 0)
+		return err;
+
+	if ((ac_str = *argv++) == NULL) {
+		printf("AC Parameters\n");
+
+		for (aci = 0; aci < AC_COUNT; aci++) {
+			acp = &acparam_cur[aci];
+			acp->TXOP = dtoh16(acp->TXOP);
+			if (((acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT) != aci)
+				printf("Warning: AC params out of order\n");
+			acm = (acp->ACI & EDCF_ACM_MASK) ? 1 : 0;
+			aifsn = acp->ACI & EDCF_AIFSN_MASK;
+			ecwmin = acp->ECW & EDCF_ECWMIN_MASK;
+			ecwmax = (acp->ECW & EDCF_ECWMAX_MASK) >> EDCF_ECWMAX_SHIFT;
+			txop = acp->TXOP;
+			printf("%s: raw: ACI 0x%x ECW 0x%x TXOP 0x%x\n",
+			       ac_names[aci],
+			       acp->ACI, acp->ECW, acp->TXOP);
+			printf("       dec: aci %d acm %d aifsn %d "
+			       "ecwmin %d ecwmax %d txop 0x%x\n",
+			       aci, acm, aifsn, ecwmin, ecwmax, txop);
+			/* CWmin = 2^(ECWmin) - 1 */
+			/* CWmax = 2^(ECWmax) - 1 */
+			/* TXOP = number of 32 us units */
+			printf("       eff: CWmin %d CWmax %d TXop %dusec\n",
+			       EDCF_ECW2CW(ecwmin), EDCF_ECW2CW(ecwmax), EDCF_TXOP2USEC(txop));
+		}
+
+		err = 0;
+	} else {
+		if (strcmp(ac_str, "be") == 0)
+			aci = AC_BE;
+		else if (strcmp(ac_str, "bk") == 0)
+			aci = AC_BK;
+		else if (strcmp(ac_str, "vi") == 0)
+			aci = AC_VI;
+		else if (strcmp(ac_str, "vo") == 0)
+			aci = AC_VO;
+		else
+			return BCME_USAGE_ERROR;
+
+		/* Preload new values with current values */
+		memcpy(&acparam_new, &acparam_cur, sizeof(acparam_new));
+
+		acp = &acparam_new[aci];
+
+		while ((param = *argv++) != NULL) {
+			if ((val = *argv++) == NULL)
+				return BCME_USAGE_ERROR;
+
+			if (!strcmp(param, "acm")) {
+				if (!stricmp(val, "on") || !stricmp(val, "1"))
+					acp->ACI |= EDCF_ACM_MASK;
+				else if (!stricmp(val, "off") || !stricmp(val, "0"))
+					acp->ACI &= ~EDCF_ACM_MASK;
+				else {
+					fprintf(stderr, "acm value must be 1|0\n");
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "aifsn")) {
+				aifsn = (int)strtol(val, NULL, 0);
+				if (aifsn >= EDCF_AIFSN_MIN && aifsn <= EDCF_AIFSN_MAX)
+					acp->ACI =
+					        (acp->ACI & ~EDCF_AIFSN_MASK) |
+					        (aifsn & EDCF_AIFSN_MASK);
+				else {
+					fprintf(stderr, "aifsn %d out of range (%d-%d)\n",
+					        aifsn, EDCF_AIFSN_MIN, EDCF_AIFSN_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "ecwmax")) {
+				ecwmax = (int)strtol(val, NULL, 0);
+				if (ecwmax >= EDCF_ECW_MIN && ecwmax <= EDCF_ECW_MAX)
+					acp->ECW =
+					        ((ecwmax << EDCF_ECWMAX_SHIFT) & EDCF_ECWMAX_MASK) |
+					        (acp->ECW & EDCF_ECWMIN_MASK);
+				else {
+					fprintf(stderr, "ecwmax %d out of range (%d-%d)\n",
+					        ecwmax, EDCF_ECW_MIN, EDCF_ECW_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "ecwmin")) {
+				ecwmin = (int)strtol(val, NULL, 0);
+				if (ecwmin >= EDCF_ECW_MIN && ecwmin <= EDCF_ECW_MAX)
+					acp->ECW =
+					        ((acp->ECW & EDCF_ECWMAX_MASK) |
+					         (ecwmin & EDCF_ECWMIN_MASK));
+				else {
+					fprintf(stderr, "ecwmin %d out of range (%d-%d)\n",
+					        ecwmin, EDCF_ECW_MIN, EDCF_ECW_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "txop")) {
+				txop = (int)strtol(val, NULL, 0);
+				if (txop >= EDCF_TXOP_MIN && txop <= EDCF_TXOP_MAX)
+					acp->TXOP = htod16(txop);
+				else {
+					fprintf(stderr, "txop %d out of range (%d-%d)\n",
+					        txop, EDCF_TXOP_MIN, EDCF_TXOP_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "unexpected param %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/*
+		 * Now set the new acparams
+		 * NOTE: only one of the four ACs can be set at a time.
+		 */
+		err = wlu_iovar_set(wl, iovar_name, acp, sizeof(edcf_acparam_t));
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME APSD control parameters
+ *	wl wme_apsd_sta <max_sp_len> <be> <bk> <vi> <vo>
+ *	  <max_sp_len> is 0 (all), 2, 4, or 6
+ *        <be>, <bk>, <vi>, <vo> are each 0 or 1 for APSD enable
+ *  with no args, print current values
+ */
+static int
+wl_wme_apsd_sta(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int buflen;
+	char *param;
+	int ap_mode;
+	int qosinfo;
+	int msp, max_sp_len, be, bk, vi, vo;
+
+	if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))) < 0)
+		return err;
+
+	if (ap_mode) {
+		printf("%s: STA only\n", cmd->name);
+		return -1;
+	}
+
+	/* Display current params if no args, else set params */
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "wme_qosinfo");
+	buflen = WLC_IOCTL_MAXLEN;
+
+	param = *++argv;
+
+	if (param == NULL) {
+		if ((err = wlu_get(wl, cmd->get, &buf[0], buflen)) < 0)
+			return err;
+
+		memcpy(&qosinfo, buf, sizeof(qosinfo));
+		qosinfo = dtoh32(qosinfo);
+
+		msp = (qosinfo & WME_QI_STA_MAXSPLEN_MASK) >> WME_QI_STA_MAXSPLEN_SHIFT;
+		be = (qosinfo & WME_QI_STA_APSD_BE_MASK) >> WME_QI_STA_APSD_BE_SHIFT;
+		bk = (qosinfo & WME_QI_STA_APSD_BK_MASK) >> WME_QI_STA_APSD_BK_SHIFT;
+		vi = (qosinfo & WME_QI_STA_APSD_VI_MASK) >> WME_QI_STA_APSD_VI_SHIFT;
+		vo = (qosinfo & WME_QI_STA_APSD_VO_MASK) >> WME_QI_STA_APSD_VO_SHIFT;
+
+		max_sp_len = msp * 2;
+
+		printf("Max SP Length = %d, APSD: BE=%d BK=%d VI=%d VO=%d\n",
+		       max_sp_len, be, bk, vi, vo);
+	} else {
+		max_sp_len = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		be = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		bk = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vi = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vo = (int)strtol(param, 0, 0);
+
+		if (((be | bk | vi | vo) & ~1) | (max_sp_len & ~6)) {
+			printf("%s: Invalid parameter\n", cmd->name);
+			return BCME_BADARG;
+		}
+
+		msp = max_sp_len / 2;
+
+		qosinfo = (msp << WME_QI_STA_MAXSPLEN_SHIFT) & WME_QI_STA_MAXSPLEN_MASK;
+		qosinfo |= (be << WME_QI_STA_APSD_BE_SHIFT) & WME_QI_STA_APSD_BE_MASK;
+		qosinfo |= (bk << WME_QI_STA_APSD_BK_SHIFT) & WME_QI_STA_APSD_BK_MASK;
+		qosinfo |= (vi << WME_QI_STA_APSD_VI_SHIFT) & WME_QI_STA_APSD_VI_MASK;
+		qosinfo |= (vo << WME_QI_STA_APSD_VO_SHIFT) & WME_QI_STA_APSD_VO_MASK;
+
+		qosinfo = htod32(qosinfo);
+		memcpy(&buf[strlen(buf) + 1], &qosinfo, sizeof(qosinfo));
+
+		err = wlu_set(wl, cmd->set, &buf[0], buflen);
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME discard policy
+ *	wl wme_dp <be> <bk> <vi> <vo>
+ *        <be>, <bk>, <vi>, <vo> are each 0/1 for discard newest/oldest first
+ *  with no args, print current values
+ */
+static int
+wl_wme_dp(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int buflen;
+	char *param;
+	int dp;
+	int be, bk, vi, vo;
+
+	/* Display current params if no args, else set params */
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "wme_dp");
+	buflen = WLC_IOCTL_MAXLEN;
+
+	param = *++argv;
+
+	if (param == NULL) {
+		if ((err = wlu_get(wl, cmd->get, &buf[0], buflen)) < 0)
+			return err;
+
+		memcpy(&dp, buf, sizeof(dp));
+		dp = dtoh32(dp);
+
+		be = (dp >> AC_BE) & 1;
+		bk = (dp >> AC_BK) & 1;
+		vi = (dp >> AC_VI) & 1;
+		vo = (dp >> AC_VO) & 1;
+
+		printf("Discard oldest first: BE=%d BK=%d VI=%d VO=%d\n", be, bk, vi, vo);
+	} else {
+		be = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		bk = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vi = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vo = (int)strtol(param, 0, 0);
+
+		if ((be | bk | vi | vo) & ~1) {
+			printf("%s: Invalid parameter\n", cmd->name);
+			return BCME_BADARG;
+		}
+
+		dp = (be << AC_BE) | (bk << AC_BK) | (vi << AC_VI) | (vo << AC_VO);
+
+		dp = htod32(dp);
+		memcpy(&buf[strlen(buf) + 1], &dp, sizeof(dp));
+
+		err = wlu_set(wl, cmd->set, &buf[0], buflen);
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME lifetime parameter
+ *	"wl lifetime be|bk|vi|vo [<value>]"},
+ *  with no args, print current values
+ */
+static int
+wl_lifetime(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint8 ac;
+	char *param, *val;
+	const char *cmdname = "lifetime";
+	wl_lifetime_t lifetime, *reply;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	if (strcmp(param, "be") == 0)
+		ac = AC_BE;
+	else if (strcmp(param, "bk") == 0)
+		ac = AC_BK;
+	else if (strcmp(param, "vi") == 0)
+		ac = AC_VI;
+	else if (strcmp(param, "vo") == 0)
+		ac = AC_VO;
+	else {
+		fprintf(stderr, "unexpected param %s\n", param);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((val = *++argv) == NULL) {
+		lifetime.ac = htod32(ac);
+		if ((err = wlu_var_getbuf(wl, cmdname, &lifetime, sizeof(lifetime),
+		                         &ptr)) < 0)
+			return err;
+		reply = (wl_lifetime_t *) ptr;
+		reply->ac = dtoh32(reply->ac);
+		reply->lifetime = dtoh32(reply->lifetime);
+		printf("Lifetime for access class '%s' is %dms\n", param, reply->lifetime);
+	}
+	else {
+		lifetime.ac = htod32(ac);
+		lifetime.lifetime = htod32((uint)strtol(val, 0, 0));
+		err = wlu_var_setbuf(wl, cmdname, &lifetime, sizeof(lifetime));
+	}
+
+	return err;
+}
+
+#define VNDR_IE_OK_FLAGS \
+	(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG | VNDR_IE_ASSOCRSP_FLAG | \
+	 VNDR_IE_AUTHRSP_FLAG | VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG | \
+	 VNDR_IE_IWAPID_FLAG)
+
+static int
+wl_add_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+
+	return (wl_vndr_ie(wl, "add", VNDR_IE_OK_FLAGS, argv));
+}
+
+static int
+wl_del_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+
+	return (wl_vndr_ie(wl, "del", VNDR_IE_OK_FLAGS, argv));
+}
+
+int
+wl_mk_ie_setbuf(const char *command, uint32 pktflag_ok, char **argv,
+	vndr_ie_setbuf_t **buf, int *buf_len)
+{
+	vndr_ie_setbuf_t *ie_setbuf;
+	uint32 pktflag;
+	int ielen, datalen, buflen, iecount;
+	int err = 0;
+
+	if (!argv[1] || !argv[2] || !argv[3]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	pktflag = (uint)strtol(argv[1], 0, 0);
+
+	if (pktflag & ~pktflag_ok) {
+		fprintf(stderr, "Invalid packet flag 0x%x (%d)\n", pktflag, pktflag);
+		return BCME_BADARG;
+	}
+
+	ielen = atoi(argv[2]);
+	if (ielen > VNDR_IE_MAX_LEN) {
+		fprintf(stderr, "IE length is %d, should be <= %d\n", ielen, VNDR_IE_MAX_LEN);
+		return BCME_BADARG;
+	}
+	else if (ielen < VNDR_IE_MIN_LEN) {
+		fprintf(stderr, "IE length is %d, should be >= %d\n", ielen, VNDR_IE_MIN_LEN);
+		return BCME_BADARG;
+	}
+
+	if (strlen(argv[3]) != OUI_STR_SIZE) {
+		fprintf(stderr, "Invalid OUI length %d\n", (int)strlen(argv[3]));
+		return BCME_BADARG;
+	}
+
+	datalen = ielen - VNDR_IE_MIN_LEN;
+	if (datalen > 0) {
+		if (!argv[4]) {
+			fprintf(stderr, "Data bytes should be specified for IE of length %d\n",
+			        ielen);
+			return BCME_USAGE_ERROR;
+		}
+		else {
+			/* Ensure each data byte is 2 characters long */
+			if ((int)strlen (argv[4]) < (datalen * 2)) {
+				fprintf(stderr, "Please specify all the data bytes for this IE\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	if (datalen == 0 && (argv[4] != NULL))
+		fprintf(stderr, "Ignoring data bytes for IE of length %d", ielen);
+
+	buflen = sizeof(vndr_ie_setbuf_t) + datalen - 1;
+
+	ie_setbuf = (vndr_ie_setbuf_t *) malloc(buflen);
+
+	if (ie_setbuf == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+
+	/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+	strncpy(ie_setbuf->cmd, command, VNDR_IE_CMD_LEN - 1);
+	ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+
+	/* Buffer contains only 1 IE */
+	iecount = htod32(1);
+	memcpy((void *)&ie_setbuf->vndr_ie_buffer.iecount, &iecount, sizeof(int));
+
+	/*
+	 * The packet flag bit field indicates the packets that will
+	 * contain this IE
+	 */
+	pktflag = htod32(pktflag);
+	memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag,
+	       &pktflag, sizeof(uint32));
+
+	/* Now, add the IE to the buffer */
+	ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
+	ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
+
+	if ((err = get_oui_bytes ((uchar *)argv[3],
+		&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0]))) {
+		free(ie_setbuf);
+		fprintf(stderr, "Error parsing OUI arg\n");
+		return BCME_BADARG;
+	}
+
+	if (datalen > 0) {
+		if ((err = get_ie_data ((uchar *)argv[4],
+			&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0],
+			datalen))) {
+			free(ie_setbuf);
+			fprintf(stderr, "Error parsing data arg\n");
+			return BCME_BADARG;
+		}
+	}
+
+	/* Copy-out */
+	if (buf) {
+		*buf = ie_setbuf;
+		ie_setbuf = NULL;
+	}
+	if (buf_len)
+		*buf_len = buflen;
+
+	/* Clean-up */
+	if (ie_setbuf)
+		free(ie_setbuf);
+
+	return (err);
+}
+
+static int
+wl_vndr_ie(void *wl, const char *command, uint32 pktflag_ok, char **argv)
+{
+	vndr_ie_setbuf_t *ie_setbuf;
+	int buflen;
+	int err = 0;
+	int ret;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv + 1, argv[0], &bsscfg_idx, &consumed)) != 0)
+		return ret;
+	if (consumed)
+		argv = argv + consumed;
+	else
+		bsscfg_idx = -1;
+
+	if ((err = wl_mk_ie_setbuf(command, pktflag_ok, argv, &ie_setbuf, &buflen)) != 0)
+		return err;
+
+	if (bsscfg_idx == -1)
+		err = wlu_var_setbuf(wl, "ie", ie_setbuf, buflen);
+	else
+		err = wlu_bssiovar_setbuf(wl, "ie", bsscfg_idx,
+			ie_setbuf, buflen, buf, WLC_IOCTL_MAXLEN);
+
+	free(ie_setbuf);
+
+	return (err);
+}
+
+int
+wl_list_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	void *ptr;
+	ie_getbuf_t param;
+
+	BCM_REFERENCE(argv);
+
+	param.pktflag = (uint32) -1;
+	param.id = (uint8) DOT11_MNG_PROPR_ID;
+	err = wlu_var_getbuf(wl, cmd->name, &param, sizeof(param), &ptr);
+	if (err == 0) {
+		wl_dump_ie_buf((vndr_ie_buf_t *)ptr);
+	} else {
+		fprintf(stderr, "Error %d getting IOVar\n", err);
+	}
+
+	return err;
+}
+
+static int
+_wl_list_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	const char *old = cmd->name;
+
+	cmd->name = "ie";
+	err = wl_list_ie(wl, cmd, argv);
+	cmd->name = old;
+
+	return err;
+}
+
+static void
+wl_dump_ie_buf(vndr_ie_buf_t *ie_getbuf)
+{
+	uchar *iebuf;
+	uchar *data;
+	int tot_ie, pktflag, iecount, count, datalen, col;
+	vndr_ie_info_t *ie_info;
+	vndr_ie_t *ie;
+
+	memcpy(&tot_ie, (void *)&ie_getbuf->iecount, sizeof(int));
+	tot_ie = dtoh32(tot_ie);
+	printf("Total IEs %d\n", tot_ie);
+
+	iebuf = (uchar *)&ie_getbuf->vndr_ie_list[0];
+
+	for (iecount = 0; iecount < tot_ie; iecount++) {
+		ie_info = (vndr_ie_info_t *) iebuf;
+		memcpy(&pktflag, (void *)&ie_info->pktflag, sizeof(uint32));
+		pktflag = dtoh32(pktflag);
+		iebuf += sizeof(uint32);
+
+		printf("\n");
+
+		ie = &ie_info->vndr_ie_data;
+		printf("IE index = %d\n", iecount);
+		printf("-----------------\n");
+		printf("Pkt Flg = 0x%x\n", pktflag);
+		printf("Length  = %d\n", ie->len);
+		printf("OUI     = %02x:%02x:%02x\n",
+			ie->oui[0], ie->oui[1], ie->oui[2]);
+		printf("Data:\n");
+
+		data = &ie->data[0];
+		datalen = ie->len - VNDR_IE_MIN_LEN;
+		for (count = 0; (count < datalen);) {
+			for (col = 0; (col < MAX_DATA_COLS) &&
+				(count < datalen); col++, count++) {
+				printf("%02x ", *data++);
+			}
+			printf("\n");
+		}
+
+		iebuf += ie->len + VNDR_IE_HDR_LEN;
+	}
+}
+
+static int
+wl_rand(void *wl, cmd_t *cmd, char **argv)
+{
+	char *randbuf;
+	uint16 randnum;
+	int err;
+	void *ptr;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	randbuf = (char *)ptr;
+	memcpy(&randnum, randbuf, sizeof(uint16));
+	printf("%d\n", randnum);
+
+	return (0);
+}
+
+#define	PRVAL(name)	pbuf += sprintf(pbuf, "%s %u ", #name, dtoh32(cnt->name))
+#define	PRVALSIX(name)	pbuf += sprintf(pbuf, "%s %u ", #name, dtoh32(cnt_six->name))
+#define	PRNL()		pbuf += sprintf(pbuf, "\n")
+
+#define WL_CNT_VERSION_SIX 6
+static int
+wl_counters(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	wl_cnt_t *cnt;
+	wl_cnt_ver_six_t *cnt_six;
+	int err;
+	uint i;
+	char *pbuf = buf;
+	void *ptr;
+	uint16 ver;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+
+	ver = *(uint16*)statsbuf;
+
+	if ((ver > WL_CNT_T_VERSION) && (ver != WL_CNT_T_VERSION_7001)) {
+		printf("\tIncorrect version of counters struct: expected %d; got %d\n",
+		       WL_CNT_T_VERSION, ver);
+		return -1;
+	}
+	else if (ver == WL_CNT_VERSION_SIX) {
+		printf("\tUse version 6 counters struct\n");
+	}
+	else {
+		if ((ver != WL_CNT_T_VERSION) && (ver != WL_CNT_T_VERSION_7001)) {
+			printf("\tIncorrect version of counters struct: expected %d; got %d\n",
+			       WL_CNT_T_VERSION, ver);
+			printf("\tDisplayed values may be incorrect\n");
+		}
+	}
+
+	cnt_six = (wl_cnt_ver_six_t*)malloc(sizeof(wl_cnt_ver_six_t));
+	if (cnt_six == NULL) {
+		printf("\tCan not allocate %d bytes for counters six struct\n",
+		       (int)sizeof(wl_cnt_ver_six_t));
+		return BCME_NOMEM;
+	} else
+		memcpy(cnt_six, statsbuf, sizeof(wl_cnt_ver_six_t));
+
+	cnt = (wl_cnt_t*)malloc(sizeof(wl_cnt_t));
+	if (cnt == NULL) {
+		if (cnt_six) free(cnt_six);
+		printf("\tCan not allocate %d bytes for counters struct\n",
+		       (int)sizeof(wl_cnt_t));
+		return BCME_NOMEM;
+	} else
+		memcpy(cnt, statsbuf, sizeof(wl_cnt_t));
+
+	/* summary stat counter line */
+	PRVAL(txframe); PRVAL(txbyte); PRVAL(txretrans); PRVAL(txerror);
+	PRVAL(rxframe); PRVAL(rxbyte); PRVAL(rxerror); PRNL();
+
+	PRVAL(txprshort); PRVAL(txdmawar); PRVAL(txnobuf); PRVAL(txnoassoc);
+	PRVAL(txchit); PRVAL(txcmiss); PRNL();
+
+	PRVAL(reset); PRVAL(txserr); PRVAL(txphyerr); PRVAL(txphycrs);
+	PRVAL(txfail); PRVAL(tbtt); PRNL();
+
+	pbuf += sprintf(pbuf, "d11_txfrag %u d11_txmulti %u d11_txretry %u d11_txretrie %u\n",
+		dtoh32(cnt->txfrag), dtoh32(cnt->txmulti), dtoh32(cnt->txretry),
+		dtoh32(cnt->txretrie));
+
+	pbuf += sprintf(pbuf, "d11_txrts %u d11_txnocts %u d11_txnoack %u d11_txfrmsnt %u\n",
+		dtoh32(cnt->txrts), dtoh32(cnt->txnocts), dtoh32(cnt->txnoack),
+		dtoh32(cnt->txfrmsnt));
+
+	PRVAL(rxcrc); PRVAL(rxnobuf); PRVAL(rxnondata); PRVAL(rxbadds);
+	PRVAL(rxbadcm); PRVAL(rxdup); PRVAL(rxfragerr); PRNL();
+
+	PRVAL(rxrunt); PRVAL(rxgiant); PRVAL(rxnoscb); PRVAL(rxbadproto);
+	PRVAL(rxbadsrcmac); PRNL();
+
+	pbuf += sprintf(pbuf, "d11_rxfrag %u d11_rxmulti %u d11_rxundec %u\n",
+		dtoh32(cnt->rxfrag), dtoh32(cnt->rxmulti), dtoh32(cnt->rxundec));
+
+	PRVAL(rxctl); PRVAL(rxbadda); PRVAL(rxfilter); PRNL();
+
+	pbuf += sprintf(pbuf, "rxuflo: ");
+	for (i = 0; i < NFIFO; i++)
+		pbuf += sprintf(pbuf, "%u ", dtoh32(cnt->rxuflo[i]));
+	pbuf += sprintf(pbuf, "\n");
+	PRVAL(txallfrm); PRVAL(txrtsfrm); PRVAL(txctsfrm); PRVAL(txackfrm); PRNL();
+	PRVAL(txdnlfrm); PRVAL(txbcnfrm); PRVAL(txtplunfl); PRVAL(txphyerr); PRNL();
+	pbuf += sprintf(pbuf, "txfunfl: ");
+	for (i = 0; i < NFIFO; i++)
+		pbuf += sprintf(pbuf, "%u ", dtoh32(cnt->txfunfl[i]));
+	pbuf += sprintf(pbuf, "\n");
+
+	/* WPA2 counters */
+	PRNL();
+	if ((cnt->version == WL_CNT_VERSION_SIX) && (cnt->version != WL_CNT_T_VERSION)) {
+		PRVALSIX(tkipmicfaill); PRVALSIX(tkipicverr); PRVALSIX(tkipcntrmsr); PRNL();
+		PRVALSIX(tkipreplay); PRVALSIX(ccmpfmterr); PRVALSIX(ccmpreplay); PRNL();
+		PRVALSIX(ccmpundec); PRVALSIX(fourwayfail); PRVALSIX(wepundec); PRNL();
+		PRVALSIX(wepicverr); PRVALSIX(decsuccess); PRVALSIX(rxundec); PRNL();
+	} else {
+		PRVAL(tkipmicfaill); PRVAL(tkipicverr); PRVAL(tkipcntrmsr); PRNL();
+		PRVAL(tkipreplay); PRVAL(ccmpfmterr); PRVAL(ccmpreplay); PRNL();
+		PRVAL(ccmpundec); PRVAL(fourwayfail); PRVAL(wepundec); PRNL();
+		PRVAL(wepicverr); PRVAL(decsuccess); PRVAL(rxundec); PRNL();
+	}
+	PRNL();
+	PRVAL(rxfrmtoolong); PRVAL(rxfrmtooshrt);
+	PRVAL(rxinvmachdr); PRVAL(rxbadfcs); PRNL();
+	PRVAL(rxbadplcp); PRVAL(rxcrsglitch);
+	PRVAL(rxstrt); PRVAL(rxdfrmucastmbss); PRNL();
+	PRVAL(rxmfrmucastmbss); PRVAL(rxcfrmucast);
+	PRVAL(rxrtsucast); PRVAL(rxctsucast); PRNL();
+	PRVAL(rxackucast); PRVAL(rxdfrmocast);
+	PRVAL(rxmfrmocast); PRVAL(rxcfrmocast); PRNL();
+	PRVAL(rxrtsocast); PRVAL(rxctsocast);
+	PRVAL(rxdfrmmcast); PRVAL(rxmfrmmcast); PRNL();
+	PRVAL(rxcfrmmcast); PRVAL(rxbeaconmbss);
+	PRVAL(rxdfrmucastobss); PRVAL(rxbeaconobss); PRNL();
+	PRVAL(rxrsptmout); PRVAL(bcntxcancl);
+	PRVAL(rxf0ovfl); PRVAL(rxf1ovfl); PRNL();
+	PRVAL(rxf2ovfl); PRVAL(txsfovfl); PRVAL(pmqovfl);
+	if (cnt->version == WL_CNT_T_VERSION_7001)
+		PRVAL(rxbcnlossmbss);
+	PRNL();
+	PRVAL(rxcgprqfrm); PRVAL(rxcgprsqovfl);
+	PRVAL(txcgprsfail); PRVAL(txcgprssuc); PRNL();
+	PRVAL(prs_timeout); PRVAL(rxnack); PRVAL(frmscons);
+	PRVAL(txnack); PRVAL(txglitch_nack); PRNL();
+	PRVAL(txburst); PRVAL(txphyerror); PRNL();
+
+	if ((cnt->version == WL_CNT_VERSION_SIX) && (cnt->version != WL_CNT_T_VERSION)) {
+		PRVALSIX(txchanrej); PRNL();
+		/* per-rate receive counters */
+		PRVALSIX(rx1mbps); PRVALSIX(rx2mbps); PRVALSIX(rx5mbps5); PRNL();
+		PRVALSIX(rx6mbps); PRVALSIX(rx9mbps); PRVALSIX(rx11mbps); PRNL();
+		PRVALSIX(rx12mbps); PRVALSIX(rx18mbps); PRVALSIX(rx24mbps); PRNL();
+		PRVALSIX(rx36mbps); PRVALSIX(rx48mbps); PRVALSIX(rx54mbps); PRNL();
+
+		PRVALSIX(pktengrxducast); PRVALSIX(pktengrxdmcast); PRNL();
+
+		PRVALSIX(txmpdu_sgi); PRVALSIX(rxmpdu_sgi); PRVALSIX(txmpdu_stbc);
+		PRVALSIX(rxmpdu_stbc); PRNL();
+	} else {
+		PRVAL(txchanrej); PRNL();
+		if (cnt->version >= 4) {
+			/* per-rate receive counters */
+			PRVAL(rx1mbps); PRVAL(rx2mbps); PRVAL(rx5mbps5); PRNL();
+			PRVAL(rx6mbps); PRVAL(rx9mbps); PRVAL(rx11mbps); PRNL();
+			PRVAL(rx12mbps); PRVAL(rx18mbps); PRVAL(rx24mbps); PRNL();
+			PRVAL(rx36mbps); PRVAL(rx48mbps); PRVAL(rx54mbps); PRNL();
+		}
+
+		if (cnt->version >= 5) {
+			PRVAL(pktengrxducast); PRVAL(pktengrxdmcast); PRNL();
+		}
+
+		if (cnt->version >= 6) {
+			PRVAL(txmpdu_sgi); PRVAL(rxmpdu_sgi); PRVAL(txmpdu_stbc);
+			PRVAL(rxmpdu_stbc); PRNL();
+		}
+	}
+
+	pbuf += sprintf(pbuf, "\n");
+	fputs(buf, stdout);
+
+	if (cnt)
+		free(cnt);
+
+	if (cnt_six)
+		free(cnt_six);
+
+	return (0);
+}
+
+static int
+wl_delta_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	wl_delta_stats_t *cnt;
+	int err;
+	char *pbuf = buf;
+	void *ptr;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+
+	cnt = (wl_delta_stats_t*)malloc(sizeof(wl_delta_stats_t));
+	if (cnt == NULL) {
+		printf("\tCan not allocate %d bytes for wl delta stats struct\n",
+		       (int)sizeof(wl_delta_stats_t));
+		return BCME_NOMEM;
+	}
+	memcpy(cnt, statsbuf, sizeof(wl_delta_stats_t));
+	cnt->version = dtoh16(cnt->version);
+	cnt->length = dtoh16(cnt->length);
+
+	if (cnt->version != WL_DELTA_STATS_T_VERSION) {
+		printf("\tIncorrect version of delta stats struct: expected %d; got %d\n",
+			WL_DELTA_STATS_T_VERSION, cnt->version);
+		free(cnt);
+		return -1;
+	}
+
+	PRVAL(txframe); PRVAL(txbyte); PRVAL(txretrans); PRVAL(txfail); PRNL();
+
+	PRVAL(rxframe); PRVAL(rxbyte); PRNL();
+
+	PRVAL(rx1mbps); PRVAL(rx2mbps); PRVAL(rx5mbps5); PRVAL(rx6mbps); PRNL();
+	PRVAL(rx9mbps); PRVAL(rx11mbps); PRVAL(rx12mbps); PRVAL(rx18mbps); PRNL();
+	PRVAL(rx24mbps); PRVAL(rx36mbps); PRVAL(rx48mbps); PRVAL(rx54mbps); PRNL();
+	pbuf += sprintf(pbuf, "\n");
+
+	PRVAL(rxbadplcp); PRVAL(rxcrsglitch); PRVAL(bphy_rxcrsglitch); PRVAL(bphy_badplcp);
+	pbuf += sprintf(pbuf, "\n");
+
+	fputs(buf, stdout);
+
+	if (cnt != NULL)
+		free(cnt);
+
+	return (0);
+}
+
+static int
+wl_wme_counters(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	wl_wme_cnt_t cnt;
+	int err;
+	void *ptr;
+	char *pbuf = buf;
+	uint ac;
+	int ap_mode = 0;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_sm (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+	memcpy(&cnt, statsbuf, sizeof(cnt));
+	cnt.version = dtoh16(cnt.version);
+	cnt.length = dtoh16(cnt.length);
+
+	if (cnt.version != WL_WME_CNT_VERSION) {
+		printf("\tIncorrect version of counters struct: expected %d; got %d\n",
+			WL_WME_CNT_VERSION, cnt.version);
+		return -1;
+	}
+
+	if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))) < 0) {
+		return err;
+	}
+	ap_mode = dtoh32(ap_mode);
+
+	/* summary stat counter line */
+	for (ac = AC_BE; ac < AC_COUNT; ac++) {
+		pbuf += sprintf(pbuf, "\n%s: tx frames: %u bytes: %u failed frames: %u "
+		                "failed bytes: %u\n",
+		                ac_names[ac], dtoh32(cnt.tx[ac].packets), dtoh32(cnt.tx[ac].bytes),
+		                dtoh32(cnt.tx_failed[ac].packets), dtoh32(cnt.tx_failed[ac].bytes));
+		pbuf += sprintf(pbuf, "       rx frames: %u bytes: %u failed frames: %u "
+		                "failed bytes: %u\n", dtoh32(cnt.rx[ac].packets),
+		                dtoh32(cnt.rx[ac].bytes), dtoh32(cnt.rx_failed[ac].packets),
+		                dtoh32(cnt.rx_failed[ac].bytes));
+
+		if (ap_mode)
+			pbuf += sprintf(pbuf, "       foward frames: %u bytes: %u \n",
+			                dtoh32(cnt.forward[ac].packets),
+			                dtoh32(cnt.forward[ac].bytes));
+
+		pbuf += sprintf(pbuf, "       tx frames time expired: %u \n",
+		                dtoh32(cnt.tx_expired[ac].packets));
+	}
+	pbuf += sprintf(pbuf, "\n");
+	fputs(buf, stdout);
+	return (0);
+}
+
+static int
+wl_devpath(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	void *ptr;
+	char *pbuf = buf;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_sm (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	pbuf += strlen(buf);
+	sprintf(pbuf, "\n");
+	fputs(buf, stdout);
+	return (0);
+}
+
+static int
+wl_diag(void *wl, cmd_t *cmd, char **argv)
+{
+	uint testindex;
+	int buflen, err;
+	char *param;
+	uint32 testresult;
+
+	if (!*++argv) {
+		printf(" Usage: %s testindex[1-4]\n", cmd->name);
+		return BCME_USAGE_ERROR;
+	}
+
+	testindex = atoi(*argv);
+
+	strcpy(buf, "diag");
+	buflen = strlen(buf) + 1;
+	param = (char *)(buf + buflen);
+	testindex = htod32(testindex);
+	memcpy(param, (char*)&testindex, sizeof(testindex));
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	testresult = *(uint32 *)buf;
+	testindex = dtoh32(testindex);
+	testresult = dtoh32(testresult);
+	if (testresult != 0) {
+		printf("\ndiag test %d failed(error code %d)\n", testindex, testresult);
+	} else
+		printf("\ndiag test %d passed\n", testindex);
+
+	return (0);
+}
+
+static int
+wl_phy_rssiant(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 antindex;
+	int buflen, err;
+	char *param;
+	int16 antrssi;
+
+	if (!*++argv) {
+		printf(" Usage: %s antenna_index[0-3]\n", cmd->name);
+		return BCME_USAGE_ERROR;
+	}
+
+	antindex = htod32(atoi(*argv));
+
+	strcpy(buf, "nphy_rssiant");
+	buflen = strlen(buf) + 1;
+	param = (char *)(buf + buflen);
+	memcpy(param, (char*)&antindex, sizeof(antindex));
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	antindex = dtoh32(antindex);
+	antrssi = dtoh16(*(int16 *)buf);
+	printf("\nnphy_rssiant ant%d = %d\n", antindex, antrssi);
+
+	return (0);
+}
+
+static int
+get_oui_bytes(uchar *oui_str, uchar *oui)
+{
+	int idx;
+	uchar val;
+	uchar *src, *dest;
+	char hexstr[3];
+
+	src = oui_str;
+	dest = oui;
+
+	for (idx = 0; idx < MAX_OUI_SIZE; idx++) {
+		hexstr[0] = src[0];
+		hexstr[1] = src[1];
+		hexstr[2] = '\0';
+
+		val = (uchar) strtoul(hexstr, NULL, 16);
+
+		*dest++ = val;
+		src += 2;
+
+		if ((idx < (MAX_OUI_SIZE - 1)) && (*src++ != ':'))
+			return -1;
+	}
+
+	return 0;
+}
+
+static int
+get_ie_data(uchar *data_str, uchar *ie_data, int len)
+{
+	uchar *src, *dest;
+	uchar val;
+	int idx;
+	char hexstr[3];
+
+	src = data_str;
+	dest = ie_data;
+
+	for (idx = 0; idx < len; idx++) {
+		hexstr[0] = src[0];
+		hexstr[1] = src[1];
+		hexstr[2] = '\0';
+
+		val = (uchar) strtoul(hexstr, NULL, 16);
+
+		*dest++ = val;
+		src += 2;
+	}
+
+	return 0;
+}
+
+static int
+hexstrtobitvec(const char *cp, uchar *bitvec, int veclen)
+{
+	uchar value = 0;
+	int nibble;		/* index of current hex-format nibble to process */
+	int even;		/* 1 if even number of nibbles, 0 if odd number */
+	int i = 0;
+
+	if (cp[0] == '0' && cp[1] == 'x')
+		cp += 2;
+
+	memset(bitvec, '\0', veclen);
+	nibble = strlen(cp);
+	if (!nibble)
+		return -1;
+	even = ((nibble % 2) == 0);
+
+	/* convert from right to left (lsb is rightmost byte) */
+	--nibble;
+	while (nibble >= 0 && i < veclen && (isxdigit((int)cp[nibble]) &&
+		(value = isdigit((int)cp[nibble]) ? cp[nibble]-'0' :
+		(islower((int)cp[nibble]) ? toupper((int)cp[nibble]) : cp[nibble])-'A'+10) < 16)) {
+		if (even == ((nibble+1) % 2)) {
+			bitvec[i] += value*16;
+			++i;
+		} else
+			bitvec[i] = value;
+		--nibble;
+	}
+
+	return ((nibble == -1 && i <= veclen) ? 0 : -1);
+}
+
+static int
+wl_eventbitvec(void *wl, cmd_t *cmd, char **argv)
+{
+	char *vbuf;
+	int err;
+	uchar bitvec[WL_EVENTING_MASK_LEN];
+	bool skipzeros;
+	int i;
+
+	err = 0;
+	skipzeros = TRUE;
+
+	/* set */
+	if (argv[1]) {
+		memset(bitvec, '\0', sizeof(bitvec));
+		if (!(err = hexstrtobitvec(argv[1], bitvec, sizeof(bitvec))))
+			err = wlu_var_setbuf(wl, cmd->name, bitvec, sizeof(bitvec));
+		else
+			return BCME_BADARG;
+	}
+	/* get */
+	else {
+		void *ptr;
+
+		memset(buf, '\0', WLC_IOCTL_MAXLEN);
+		if (!(err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr))) {
+			vbuf = (char *)ptr;
+			printf("0x");
+			for (i = (sizeof(bitvec) - 1); i >= 0; i--) {
+				if (vbuf[i] || (i == 0))
+					skipzeros = FALSE;
+				if (skipzeros)
+					continue;
+				printf("%02x", vbuf[i] & 0xff);
+			}
+			printf("\n");
+		}
+	}
+
+	return (err);
+}
+
+static int
+wl_auto_channel_sel(void *wl, cmd_t *cmd, char **argv)
+{
+	/*
+	* The following condition(s) must be met when Auto Channel Selection
+	* is enabled.
+	*  - the I/F is up (change radio channel requires it is up?)
+	*  - the AP must not be associated (setting SSID to empty should
+	*    make sure it for us)
+	*/
+	int chosen = 0;
+	wl_uint32_list_t request;
+	int ret = 0;
+
+	if (!*++argv) {
+		ret = wlu_get(wl, cmd->get, &chosen, sizeof(chosen));
+		chosen = wl_chspec32_from_driver(chosen);
+		if (ret >= 0 && chosen != 0) {
+			wf_chspec_ntoa((chanspec_t)chosen, buf);
+			printf("%s (0x%x)\n", buf, chosen);
+			return 0;
+		}
+		else {
+			if (chosen == 0)
+				printf("invalid chanspec (0x%x)\n", chosen);
+		}
+	} else {
+		if (atoi(*argv) == 1) {
+			request.count = htod32(0);
+			ret = wlu_set(wl, cmd->set, &request, sizeof(request));
+		} else if (atoi(*argv) == 2) {
+			ret = wlu_get(wl, cmd->get, &chosen, sizeof(chosen));
+			if (ret >= 0 && chosen != 0)
+				ret = wlu_iovar_setint(wl, "chanspec", (int)chosen);
+		} else {
+			ret = BCME_BADARG;
+		}
+	}
+	return ret;
+}
+
+static int
+wl_varstr(void *wl, cmd_t *cmd, char **argv)
+{
+	int error;
+	char *str;
+
+	if (!*++argv) {
+		void *ptr;
+
+		if ((error = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return (error);
+
+		str = (char *)ptr;
+		printf("%s\n", str);
+		return (0);
+	} else {
+		str = *argv;
+		/* str length include NULL */
+		return wlu_var_setbuf(wl, cmd->name, str, (strlen(str)+1));
+	}
+}
+
+/* Return TRUE if it's one of the wc cmds. If WC_TOOL is not defined,
+ * it'll return TRUE by default so all the commands are allowed.
+ */
+bool wc_cmd_check(const char *cmd_name)
+{
+	uint j;
+	if (wc_cmds == NULL)
+		return TRUE;
+
+	for (j = 0; j < ARRAYSIZE(wc_cmds); j++)
+		if (strcmp(wc_cmds[j], cmd_name) == 0)
+			return TRUE;
+	return FALSE;
+}
+
+#define NUM_TSLIST_ARG 3		/* minimum number of arguments required for TSLIST */
+#define NUM_TSLIST_PER_EA_ARG 3	/* minimum number of arguments required for TSLIST */
+#define MIN_NUM_DELTS_ARG 4		/* minimum number of arguments required for DELTS */
+#define MIN_NUM_DELTS_EA_ARG 5	/* minimum number of arguments required for DELTS */
+#define MIN_NUM_ADDTS_ARG 20	/* minimum number of arguments required for ADDTS */
+#define PERIODIC_TRAFFIC 1		/* Periodic traffic type */
+#define VO_TID (0 << 1)			/* voice TID */
+#define VI_TID (1 << 1)			/* signal TID */
+#define UPLINK_DIRECTION (0 << 5)	/* uplink direction traffic stream */
+#define DOWNLINK_DIRECTION (1 << 5)	/* downlink direction traffic stream */
+#define BI_DIRECTION (3 << 5)	/* bi direction traffic stream */
+#define EDCA_ACCESS (1 << 7)	/* EDCA access policy */
+#define UAPSD_PSB (1 << 2)		/* U-APSD power saving behavior */
+#define VO_USER_PRIO (6 << 3)	/* voice user priority */
+#define VI_USER_PRIO (4 << 3)	/* signal user priority */
+#define TID_SHIFT 1				/* TID Shift */
+#define UP_SHIFT 3				/* UP Shift */
+
+static void
+wl_cac_format_tspec_htod(tspec_arg_t *tspec_arg)
+{
+	tspec_arg->version = htod16(tspec_arg->version);
+	tspec_arg->length = htod16(tspec_arg->length);
+	tspec_arg->flag = htod32(tspec_arg->flag);
+	tspec_arg->nom_msdu_size = htod16(tspec_arg->nom_msdu_size);
+	tspec_arg->max_msdu_size = htod16(tspec_arg->max_msdu_size);
+	tspec_arg->min_srv_interval = htod32(tspec_arg->min_srv_interval);
+	tspec_arg->max_srv_interval = htod32(tspec_arg->max_srv_interval);
+	tspec_arg->inactivity_interval = htod32(tspec_arg->inactivity_interval);
+	tspec_arg->suspension_interval = htod32(tspec_arg->suspension_interval);
+	tspec_arg->srv_start_time = htod32(tspec_arg->srv_start_time);
+	tspec_arg->min_data_rate = htod32(tspec_arg->min_data_rate);
+	tspec_arg->mean_data_rate = htod32(tspec_arg->mean_data_rate);
+	tspec_arg->peak_data_rate = htod32(tspec_arg->peak_data_rate);
+	tspec_arg->max_burst_size = htod32(tspec_arg->max_burst_size);
+	tspec_arg->delay_bound = htod32(tspec_arg->delay_bound);
+	tspec_arg->min_phy_rate = htod32(tspec_arg->min_phy_rate);
+	tspec_arg->surplus_bw = htod16(tspec_arg->surplus_bw);
+	tspec_arg->medium_time = htod16(tspec_arg->medium_time);
+}
+
+static void
+wl_cac_format_tspec_dtoh(tspec_arg_t *tspec_arg)
+{
+	tspec_arg->version = dtoh16(tspec_arg->version);
+	tspec_arg->length = dtoh16(tspec_arg->length);
+	tspec_arg->flag = dtoh32(tspec_arg->flag);
+	tspec_arg->nom_msdu_size = dtoh16(tspec_arg->nom_msdu_size);
+	tspec_arg->max_msdu_size = dtoh16(tspec_arg->max_msdu_size);
+	tspec_arg->min_srv_interval = dtoh32(tspec_arg->min_srv_interval);
+	tspec_arg->max_srv_interval = dtoh32(tspec_arg->max_srv_interval);
+	tspec_arg->inactivity_interval = dtoh32(tspec_arg->inactivity_interval);
+	tspec_arg->suspension_interval = dtoh32(tspec_arg->suspension_interval);
+	tspec_arg->srv_start_time = dtoh32(tspec_arg->srv_start_time);
+	tspec_arg->min_data_rate = dtoh32(tspec_arg->min_data_rate);
+	tspec_arg->mean_data_rate = dtoh32(tspec_arg->mean_data_rate);
+	tspec_arg->peak_data_rate = dtoh32(tspec_arg->peak_data_rate);
+	tspec_arg->max_burst_size = dtoh32(tspec_arg->max_burst_size);
+	tspec_arg->delay_bound = dtoh32(tspec_arg->delay_bound);
+	tspec_arg->min_phy_rate = dtoh32(tspec_arg->min_phy_rate);
+	tspec_arg->surplus_bw = dtoh16(tspec_arg->surplus_bw);
+	tspec_arg->medium_time = dtoh16(tspec_arg->medium_time);
+
+}
+
+static void wl_cac_addts_usage(void)
+{
+	fprintf(stderr, "Too few arguments\n");
+	fprintf(stderr, "wl cac_addts ver dtoken tid dir psb up a b c d e ...\n");
+	fprintf(stderr, "\twhere ver is the structure version\n");
+	fprintf(stderr, "\twhere dtoken is the dialog token [range 1-255]\n");
+	fprintf(stderr, "\twhere tid is the tspec identifier [range 0-7]\n");
+	fprintf(stderr, "\twhere dir is direction [uplink | downlink | bi-directional]\n");
+	fprintf(stderr, "\twhere psb is power save mode [legacy|U-APSD]\n");
+	fprintf(stderr, "\twhere up is user priority [range 0-7]\n");
+	fprintf(stderr, "\twhere a is the nominal MSDU size\n");
+	fprintf(stderr, "\twhere b is bool for fixed size msdu [ 0 and 1]\n");
+	fprintf(stderr, "\twhere c is the maximum MSDU size\n");
+	fprintf(stderr, "\twhere d is the minimum service interval\n");
+	fprintf(stderr, "\twhere e is the maximum service interval\n");
+	fprintf(stderr, "\twhere f is the inactivity interval\n");
+	fprintf(stderr, "\twhere g is the suspension interval\n");
+	fprintf(stderr, "\twhere h is the minimum data rate\n");
+	fprintf(stderr, "\twhere i is the mean data rate\n");
+	fprintf(stderr, "\twhere j is the peak data rate\n");
+	fprintf(stderr, "\twhere k is the max burst size\n");
+	fprintf(stderr, "\twhere l is the delay bound\n");
+	fprintf(stderr, "\twhere m is the surplus bandwidth [fixed point notation]\n");
+	fprintf(stderr, "\twhere n is the minimum PHY rate\n");
+}
+
+static void wl_cac_delts_usage(void)
+{
+	fprintf(stderr, "Too few arguments\n");
+	fprintf(stderr, "wl cac_delts ver a b c \n");
+	fprintf(stderr, "\twhere ver is the tspec version\n");
+	fprintf(stderr, "\twhere a is byte[0] of tsinfo (bits 0-7)\n");
+	fprintf(stderr, "\twhere b is byte[1] of tsinfo (bits 8-15)\n");
+	fprintf(stderr, "\twhere c is byte[2] of tsinfo (bits 16-23)\n");
+}
+
+static int
+wl_cac(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	int ap_mode = 0;
+	int apsta_mode = 0;
+	int cmd_type = 0;
+	tspec_arg_t tspec_arg;
+	char *endptr = NULL;
+	uint buflen;
+	char *arg1, *user_argv;
+	uint8 direction = BI_DIRECTION;
+	uint8 user_tid, user_prio, user_psb;
+	uint fixed;
+
+
+	if ((err = wlu_iovar_get(wl, "apsta", &apsta_mode, sizeof(apsta_mode))))
+		return err;
+
+	if (!apsta_mode) {
+		if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+			return err;
+		else {
+			if (dtoh32(ap_mode)) {
+				fprintf(stderr,
+					"This command can ONLY be executed on a STA or APSTA\n");
+				return err;
+			}
+		}
+	}
+
+	if (!strcmp(*argv, "cac_addts"))
+		cmd_type = 1;
+	else if (!strcmp(*argv, "cac_delts"))
+		cmd_type = 2;
+	else {
+		fprintf(stderr, "unknown command\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* eat command name */
+	if (!*++argv) {
+		(cmd_type == 1) ? wl_cac_addts_usage():wl_cac_delts_usage();
+		return BCME_BADARG;
+	}
+
+	buflen = sizeof(tspec_arg_t);
+	memset((uint8 *)&tspec_arg, 0, buflen);
+
+	/* get direction option */
+	arg1 = *argv;
+
+	/* Unidirectional DL/UL */
+	if (!strcmp(arg1, "UDL") || (!strcmp(arg1, "UUL")))
+		direction = DOWNLINK_DIRECTION;
+
+	if (cmd_type == 1) {
+			uint argc = 0;
+
+			/* arg count */
+			while (argv[argc])
+				argc++;
+
+			/* required argments */
+			if (argc < MIN_NUM_ADDTS_ARG) {
+				wl_cac_addts_usage();
+				return BCME_USAGE_ERROR;
+			}
+
+			tspec_arg.length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
+			tspec_arg.version = (uint16)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.dialog_token = (uint8)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			user_tid = (uint8)strtol(*argv++, &endptr, 0);
+			user_tid <<= TID_SHIFT;
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			/* store the pointer for parsing */
+			user_argv = *argv++;
+
+			if (!strcmp(user_argv, "uplink"))
+				direction = UPLINK_DIRECTION;
+			else if (!strcmp(user_argv, "downlink"))
+				direction = DOWNLINK_DIRECTION;
+			else if (!strcmp(user_argv, "bi-directional"))
+				direction = BI_DIRECTION;
+			else
+				return BCME_USAGE_ERROR;
+
+			/* store the pointer for parsing */
+			user_argv = *argv++;
+
+			if (!strcmp(user_argv, "legacy"))
+				user_psb = 0;
+			else if (!strcmp(user_argv, "U-APSD"))
+				user_psb = UAPSD_PSB;
+			else
+				return BCME_USAGE_ERROR;
+
+			user_prio = (uint8)strtol(*argv++, &endptr, 0);
+			user_prio <<= UP_SHIFT;
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.tsinfo.octets[0] = (uint8)(user_tid |
+				direction | EDCA_ACCESS);
+
+			tspec_arg.tsinfo.octets[1] = (uint8)(user_prio | user_psb);
+			tspec_arg.tsinfo.octets[2] = 0x00;
+
+			tspec_arg.nom_msdu_size = (uint16)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			fixed = (uint)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			if (fixed == 1)
+				tspec_arg.nom_msdu_size |= 0x8000;
+
+			tspec_arg.max_msdu_size = (uint16)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.min_srv_interval = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.max_srv_interval = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.inactivity_interval = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.suspension_interval = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.min_data_rate = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.mean_data_rate = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.peak_data_rate = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.max_burst_size = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.delay_bound = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.surplus_bw = (uint16)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.min_phy_rate = strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+			printf("Setting min_phy_rate to 0x%x\n", tspec_arg.min_phy_rate);
+	} else {
+			uint argc = 0;
+
+			/* arg count */
+			while (argv[argc])
+				argc++;
+
+			/* required argments */
+			if (argc < MIN_NUM_DELTS_ARG) {
+				wl_cac_delts_usage();
+				return BCME_USAGE_ERROR;
+			}
+
+			tspec_arg.length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
+			tspec_arg.version = (uint16)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.tsinfo.octets[0] = (uint8)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.tsinfo.octets[1] = (uint8)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			tspec_arg.tsinfo.octets[2] = (uint8)strtol(*argv++, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+	}
+
+	wl_cac_format_tspec_htod(&tspec_arg);
+	err = wlu_var_setbuf(wl, cmd->name, &tspec_arg, buflen);
+
+	return err;
+}
+
+/* get a list of traffic stream (TSINFO) in driver */
+static int
+wl_tslist(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int i;
+	int ap_mode, err = -1;
+	int apsta_mode = 0;
+	struct tslist *tslist;
+
+	UNUSED_PARAMETER(argv);
+
+
+	if ((err = wlu_iovar_get(wl, "apsta", &apsta_mode, sizeof(apsta_mode))))
+		return err;
+
+	if (!apsta_mode) {
+		if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+			return err;
+		else {
+			if (dtoh32(ap_mode)) {
+				fprintf(stderr,
+					"This command can ONLY be executed on a STA or APSTA\n");
+				return err;
+			}
+		}
+	}
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return err;
+
+	tslist = (struct tslist *)ptr;
+	tslist->count = dtoh32(tslist->count);
+	for (i = 0; i < tslist->count; i++)
+		printf("tsinfo 0x%02X 0x%02X 0x%02X  TID %d  User Prio %d  Direction %d\n",
+		       tslist->tsinfo[i].octets[0],
+		       tslist->tsinfo[i].octets[1],
+		       tslist->tsinfo[i].octets[2],
+		       WLC_CAC_GET_TID(tslist->tsinfo[i]),
+		       WLC_CAC_GET_USER_PRIO(tslist->tsinfo[i]),
+		       WLC_CAC_GET_DIR(tslist->tsinfo[i]));
+
+	return 0;
+}
+
+/* get specific TSPEC in driver */
+static int
+wl_tspec(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int ap_mode, err = -1;
+	tspec_arg_t *ts, tspec_arg;
+	char *temp = NULL;
+	uint argc = 0;
+
+	if ((wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+		return err;
+	ap_mode = dtoh32(ap_mode);
+
+	if (ap_mode) {
+		fprintf(stderr, "This command can only be executed on the STA\n");
+		return err;
+	}
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	while (argv[argc])
+		argc++;
+
+	/* required argments */
+	if (argc < NUM_TSLIST_ARG) {
+		fprintf(stderr, "Too few arguments\n");
+		fprintf(stderr, "wl cac_tspec 0xaa 0xbb 0xcc \n");
+		fprintf(stderr, "\twhere 0xaa is byte[0] of tsinfo (bits 0-7)\n");
+		fprintf(stderr, "\twhere 0xbb is byte[1] of tsinfo (bits 8-15)\n");
+		fprintf(stderr, "\twhere 0xcc is byte[2] of tsinfo (bits 16-23)\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset((uint8 *)&tspec_arg, 0, sizeof(tspec_arg_t));
+
+	tspec_arg.tsinfo.octets[0] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	tspec_arg.tsinfo.octets[1] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	tspec_arg.tsinfo.octets[2] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+	if ((err = wlu_var_getbuf(wl, cmd->name, &tspec_arg, sizeof(tspec_arg_t), &ptr)) < 0)
+		return err;
+
+	ts = (tspec_arg_t *)ptr;
+	wl_cac_format_tspec_dtoh(ts);
+	wl_print_tspec(ts);
+
+	return 0;
+}
+
+/* get/set max bandwidth for each access category in ap */
+static int
+wme_maxbw_params(void *wl, cmd_t *cmd, char **argv)
+{
+	wme_max_bandwidth_t cur_params, new_params;
+	char *val_p, *ac_str, *param;
+	int buflen;
+	int aci;
+	int err;
+	int val;
+	int ap_mode = 0;
+
+	argv++;
+
+	if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))) < 0)
+		return err;
+
+	if (!ap_mode) {
+		printf("%s: AP only\n", cmd->name);
+		return -1;
+	}
+
+	buflen = WLC_IOCTL_MAXLEN;
+
+	/* get the current max bandwidth, using buf as an input buffer. */
+	strcpy(buf, "wme_maxbw_params");
+	if ((err = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen)) < 0) {
+		return err;
+	}
+
+	/* cache the current values */
+	memcpy(&cur_params, buf, sizeof(wme_max_bandwidth_t));
+
+	if ((ac_str = *argv) == NULL) {
+		printf("WME bandwidth limit: \n");
+		for (aci = 0; aci < AC_COUNT; aci++) {
+			printf("%s: bandwidth limit %d\n", ac_names[aci],
+				cur_params.ac[aci]);
+		}
+	} else {
+		/* preload new values with current values */
+		memcpy(&new_params, &cur_params, sizeof(new_params));
+		while ((param = *argv++) != NULL) {
+			if ((val_p = *argv++) == NULL) {
+				printf("Need value following %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+
+			val = (int)strtoul(val_p, NULL, 0);
+
+			if (!strcmp(param, "be")) {
+				new_params.ac[AC_BE] = (uint32)val;
+			} else if (!strcmp(param, "bk")) {
+				new_params.ac[AC_BK] = (uint32)val;
+			} else if (!strcmp(param, "vi")) {
+				new_params.ac[AC_VI] = (uint32)val;
+			} else if (!strcmp(param, "vo")) {
+				new_params.ac[AC_VO] = (uint32)val;
+			} else {
+				printf("Unknown access category: %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		strcpy(buf, "wme_maxbw_params");
+		memcpy(buf + strlen(buf) + 1, &new_params, sizeof(wme_max_bandwidth_t));
+		err = wlu_set(wl, WLC_SET_VAR, &buf[0], buflen);
+
+	}
+
+	return err;
+}
+
+/* get the tspec list for the given station */
+static int
+wl_tslist_ea(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int i;
+	int ap_mode, err = -1;
+	struct tslist *tslist;
+	scb_val_t scb_val;
+
+
+	if (!*++argv) {
+		printf("MAC address must be specified\n");
+		return BCME_USAGE_ERROR;
+	} else if (!wl_ether_atoe(*argv, &scb_val.ea)) {
+		printf("Malformed MAC address parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+	if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+		return err;
+
+	ap_mode = dtoh32(ap_mode);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, &scb_val.ea, ETHER_ADDR_LEN, &ptr)) < 0)
+		return err;
+
+	tslist = (struct tslist *)ptr;
+
+	for (i = 0; i < tslist->count; i++)
+		printf("tsinfo 0x%02X 0x%02X 0x%02X  TID %d  User Prio %d  Direction %d\n",
+		       tslist->tsinfo[i].octets[0],
+		       tslist->tsinfo[i].octets[1],
+		       tslist->tsinfo[i].octets[2],
+		       WLC_CAC_GET_TID(tslist->tsinfo[i]),
+		       WLC_CAC_GET_USER_PRIO(tslist->tsinfo[i]),
+		       WLC_CAC_GET_DIR(tslist->tsinfo[i]));
+
+	return 0;
+
+}
+
+/* get specific TSPEC for a STA */
+static int
+wl_tspec_ea(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err = -1;
+	tspec_per_sta_arg_t tsea;
+	tspec_arg_t *ts;
+	char *temp;
+	uint argc = 0;
+
+	/* eat command name */
+	argv++;
+
+	while (argv[argc])
+		argc++;
+
+	/* required argments */
+	if (argc < (NUM_TSLIST_PER_EA_ARG + 1)) {
+		fprintf(stderr, "Too few arguments\n");
+		fprintf(stderr, "wl cac_tspec 0xaa 0xbb 0xcc xx:xx:xx:xx:xx:xx\n");
+		fprintf(stderr, "\twhere 0xaa is byte[0] of tsinfo (bits 0-7)\n");
+		fprintf(stderr, "\twhere 0xbb is byte[1] of tsinfo (bits 8-15)\n");
+		fprintf(stderr, "\twhere 0xcc is byte[2] of tsinfo (bits 16-23)\n");
+		fprintf(stderr, "\twhere xx:xx:xx:xx:xx:xx is mac address )\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset((uint8 *)&tsea, 0, sizeof(tspec_per_sta_arg_t));
+
+	ts = &tsea.ts;
+
+	ts->tsinfo.octets[0] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[1] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[2] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	/* add the ether address after tsinfo */
+	if (!*argv) {
+		printf("MAC address must be specified\n");
+		return BCME_USAGE_ERROR;
+	} else if (!wl_ether_atoe(*argv, &tsea.ea)) {
+		printf("Malformed MAC address parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, &tsea, sizeof(tspec_per_sta_arg_t), &ptr)) < 0)
+		return err;
+
+	ts = (tspec_arg_t *)ptr;
+	wl_cac_format_tspec_dtoh(ts);
+	wl_print_tspec(ts);
+	return 0;
+
+}
+
+static const uint8 wlu_wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE,
+             AC_BE };
+static const uint8 wlu_prio2fifo[NUMPRIO] = {
+	0,	/* 0	BE	AC_BE	Best Effort */
+	1,	/* 1	BK	AC_BK	Background */
+	2,	/* 2	--	AC_BK	Background */
+	3,	/* 3	EE	AC_BE	Best Effort */
+	4,	/* 4	CL	AC_VI	Video */
+	5,	/* 5	VI	AC_VI	Video */
+	6,	/* 6	VO	AC_VO	Voice */
+	7	/* 7	NC	AC_VO	Voice */
+};
+#define WME_PRIO2AC(prio)	wlu_wme_fifo2ac[wlu_prio2fifo[(prio)]]
+
+static void
+wl_print_tspec(tspec_arg_t *ts)
+{
+	const char *str;
+	if (ts->version != TSPEC_ARG_VERSION) {
+		printf("\tIncorrect version of TSPEC struct: expected %d; got %d\n",
+		       TSPEC_ARG_VERSION, ts->version);
+		return;
+	}
+
+	if (ts->length < (sizeof(tspec_arg_t) - (2 * sizeof(uint16)))) {
+		printf("\tTSPEC arg length too short: expected %d; got %d\n",
+		       (int)(sizeof(tspec_arg_t) - (2 * sizeof(uint16))), ts->length);
+		return;
+	}
+
+	switch (ts->flag & TSPEC_STATUS_MASK) {
+		case TSPEC_PENDING:
+			str = "PENDING";
+			break;
+		case TSPEC_ACCEPTED:
+			str = "ACCEPTED";
+			break;
+		case TSPEC_REJECTED:
+			str = "REJECTED";
+			break;
+		default:
+			str = "UNKNOWN";
+			break;
+	}
+
+	printf("version %d\n", ts->version);
+	printf("length %d\n", ts->length);
+
+	printf("TID %d %s\n", WLC_CAC_GET_TID(ts->tsinfo), str);
+	printf("tsinfo 0x%02x 0x%02x 0x%02x\n", ts->tsinfo.octets[0],
+	       ts->tsinfo.octets[1], ts->tsinfo.octets[2]);
+
+	/* breakout bitfields for apsd */
+	if (WLC_CAC_GET_PSB(ts->tsinfo)) {
+		int ac = WME_PRIO2AC(WLC_CAC_GET_USER_PRIO(ts->tsinfo));
+		switch (WLC_CAC_GET_DIR(ts->tsinfo)) {
+			case (TS_INFO_UPLINK >> TS_INFO_DIRECTION_SHIFT):
+				printf("AC[%d] : Trigger enabled\n", ac);
+				break;
+
+			case (TS_INFO_DOWNLINK >> TS_INFO_DIRECTION_SHIFT):
+				printf("AC[%d] : Delivery enabled\n", ac);
+				break;
+
+			case (TS_INFO_BIDIRECTIONAL >>
+				TS_INFO_DIRECTION_SHIFT):
+				printf("AC[%d] : Trig & Delv enabled\n", ac);
+				break;
+		}
+	} else {
+		int ac;
+		ac = WME_PRIO2AC(WLC_CAC_GET_USER_PRIO(ts->tsinfo));
+		printf("AC [%d] : Legacy Power save\n", ac);
+	}
+
+
+	printf("nom_msdu_size %d %s\n", (ts->nom_msdu_size & 0x7fff),
+	       ((ts->nom_msdu_size & 0x8000) ? "fixed size" : ""));
+	printf("max_msdu_size %d\n", ts->max_msdu_size);
+	printf("min_srv_interval %d\n", ts->min_srv_interval);
+	printf("max_srv_interval %d\n", ts->max_srv_interval);
+	printf("inactivity_interval %d\n", ts->inactivity_interval);
+	printf("suspension_interval %d\n", ts->suspension_interval);
+	printf("srv_start_time %d\n", ts->srv_start_time);
+	printf("min_data_rate %d\n", ts->min_data_rate);
+	printf("mean_data_rate %d\n", ts->mean_data_rate);
+	printf("peak_data_rate %d\n", ts->peak_data_rate);
+	printf("max_burst_size %d\n", ts->max_burst_size);
+	printf("delay_bound %d\n", ts->delay_bound);
+	printf("min_phy_rate %d\n", ts->min_phy_rate);
+	printf("surplus_bw %d\n", ts->surplus_bw);
+	printf("medium_time %d\n", ts->medium_time);
+}
+
+
+/* send delts for a specific ea */
+/* TODO : Club this with wl_tspec_ea */
+static int
+wl_cac_delts_ea(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err = -1;
+	char *endptr = NULL;
+	tspec_per_sta_arg_t tsea;
+	tspec_arg_t *ts;
+	uint argc = 0;
+
+	/* eat command name */
+	argv++;
+
+	while (argv[argc])
+		argc++;
+
+	/* required argments */
+	if (argc < (NUM_TSLIST_PER_EA_ARG + 1)) {
+		fprintf(stderr, "Too few arguments\n");
+		fprintf(stderr, "wl cac_delts_ea ver 0xaa 0xbb 0xcc xx:xx:xx:xx:xx:xx\n");
+		fprintf(stderr, "\twhere ver is the tspec version\n");
+		fprintf(stderr, "\twhere 0xaa is byte[0] of tsinfo (bits 0-7)\n");
+		fprintf(stderr, "\twhere 0xbb is byte[1] of tsinfo (bits 8-15)\n");
+		fprintf(stderr, "\twhere 0xcc is byte[2] of tsinfo (bits 16-23)\n");
+		fprintf(stderr, "\twhere xx:xx:xx:xx:xx:xx is mac address )\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset((uint8 *)&tsea, 0, sizeof(tspec_per_sta_arg_t));
+
+	ts = &tsea.ts;
+
+	ts->length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
+	ts->version = (uint16)strtol(*argv++, &endptr, 0);
+
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[0] = (uint8)strtol(*argv++, &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[1] = (uint8)strtol(*argv++, &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[2] = (uint8)strtol(*argv++, &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+
+	/* add the ether address after tsinfo */
+	if (!*argv) {
+		printf("MAC address must be specified\n");
+		return BCME_USAGE_ERROR;
+	} else if (!wl_ether_atoe(*argv, &tsea.ea)) {
+		printf("Malformed MAC address parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	wl_cac_format_tspec_htod(ts);
+	if ((err = wlu_var_getbuf(wl, cmd->name, &tsea, sizeof(tspec_per_sta_arg_t), &ptr)) < 0)
+		return err;
+
+	return 0;
+
+}
+
+static int
+wl_antsel(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *ant_sel = "fixed";
+	char *val_name;
+	wlc_antselcfg_t val = {{0}, 0};
+	int err, argc, i;
+	char *endptr = NULL;
+	uint32 txchain_bitmap = 0;
+	uint16 antsel_mask = 0;
+
+	/* toss the command name */
+	val_name = *argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+	    if ((err = wlu_iovar_get(wl, "txchain", &txchain_bitmap, sizeof(txchain_bitmap))) < 0)
+				return err;
+
+		/* iterate over max 4 chains */
+		for (i = 0; i < 4; i ++) {
+			if (!(txchain_bitmap & (1<<i)))
+				antsel_mask |=  (0xF << i * 4);
+		}
+
+		if ((err = wlu_iovar_get(wl, val_name, &val, sizeof(wlc_antselcfg_t))) < 0)
+			return err;
+
+		printf("C3C2C1C0: ");
+		for (i = ANT_SELCFG_TX_UNICAST; i < ANT_SELCFG_MAX; i++) {
+			if (val.ant_config[i] & ANT_SELCFG_AUTO)
+				ant_sel = "auto";
+			printf("0x%04X %s ",
+			antsel_mask | (val.ant_config[i] & ANT_SELCFG_MASK), ant_sel);
+		}
+		printf("\n");
+	} else {
+		/* arg count */
+		for (argc = 0; argv[argc]; argc++);
+
+		if ((argc >= 2 && argc <= 3) || argc > ANT_SELCFG_MAX) {
+			printf("invalid %d args\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		val.ant_config[ANT_SELCFG_TX_UNICAST] = (uint8)strtol(*argv++, &endptr, 0);
+		printf("UTX 0x%02x\n", val.ant_config[ANT_SELCFG_TX_UNICAST]);
+		if (*endptr != '\0') {
+			printf("Invaild UTX parameter: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		if (argc == 1) {
+			val.ant_config[ANT_SELCFG_RX_UNICAST] =
+				val.ant_config[ANT_SELCFG_TX_UNICAST];
+			val.ant_config[ANT_SELCFG_TX_DEF] = val.ant_config[ANT_SELCFG_TX_UNICAST];
+			val.ant_config[ANT_SELCFG_RX_DEF] = val.ant_config[ANT_SELCFG_TX_UNICAST];
+		} else {
+			val.ant_config[ANT_SELCFG_RX_UNICAST] = (uint8)strtol(*argv++, &endptr, 0);
+			printf("URX 0x%02x\n", val.ant_config[ANT_SELCFG_RX_UNICAST]);
+			if (*endptr != '\0') {
+				printf("Invaild URX parameter: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			val.ant_config[ANT_SELCFG_TX_DEF] = (uint8)strtol(*argv++, &endptr, 0);
+			printf("DTX 0x%02x\n", val.ant_config[ANT_SELCFG_TX_DEF]);
+			if (*endptr != '\0') {
+				printf("Invaild DTX parameter: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			val.ant_config[ANT_SELCFG_RX_DEF] = (uint8)strtol(*argv++, &endptr, 0);
+			printf("DRX 0x%02x\n", val.ant_config[ANT_SELCFG_RX_DEF]);
+			if (*endptr != '\0') {
+				printf("Invaild DRX parameter: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+		}
+		err = wlu_iovar_set(wl, val_name, &val, sizeof(wlc_antselcfg_t));
+	}
+	return err;
+}
+
+static int
+wl_txcore_pwr_offset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txchain_pwr_offsets_t offsets;
+	char *endptr;
+	int i;
+	long val;
+	int err;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		err = wlu_iovar_get(wl, cmd->name, &offsets, sizeof(wl_txchain_pwr_offsets_t));
+
+		if (err < 0)
+			return err;
+
+		printf("txcore offsets qdBm: %d %d %d %d\n",
+		       offsets.offset[0], offsets.offset[1],
+		       offsets.offset[2], offsets.offset[3]);
+
+		return 0;
+	}
+
+	memset(&offsets, 0, sizeof(wl_txchain_pwr_offsets_t));
+
+	for (i = 0; i < WL_NUM_TXCHAIN_MAX; i++, argv++) {
+		if (!*argv)
+			break;
+
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		if (val > 0)
+			return BCME_BADARG;
+
+		offsets.offset[i] = (int8)val;
+	}
+
+	err = wlu_iovar_set(wl, cmd->name, &offsets, sizeof(wl_txchain_pwr_offsets_t));
+
+	return err;
+}
+
+static int
+wl_txcore(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_txcore";
+	int err = 0, opt_err, val;
+	uint8 streams = 0;
+	bool streams_set = FALSE;
+	uint8 core = 0;
+	bool core_set = FALSE;
+	uint8 cck_mask = 0;
+	bool cck_set = FALSE;
+	uint8 ofdm_mask = 0;
+	bool ofdm_set = FALSE;
+	uint8 mcs_mask[4] = {0, 0, 0, 0}; /* pre-initialize # of streams {core:4 | stream:4} */
+	bool mcs_set = FALSE;
+	uint8 idx;
+	uint32 coremask[2] = {0, 0};
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_get(wl, cmd->name, &coremask, sizeof(uint32)*2)) < 0)
+			return err;
+
+		printf("txcore enabled bitmap (Nsts {4..1}) 0x%02x 0x%02x 0x%02x 0x%02x\n",
+			(coremask[0] >> 24) & 0xff, (coremask[0] >> 16) & 0xff,
+			(coremask[0] >> 8) & 0xff, coremask[0] & 0xff);
+		printf("txcore mask OFDM 0x%02x  CCK 0x%02x\n",
+			(coremask[1] >> 8) & 0xff, coremask[1] & 0xff);
+		return 0;
+	}
+
+	val = atoi(*argv);
+	if (val == -1)
+		goto next;
+
+	miniopt_init(&to, fn_name, "w", FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == 's') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for streams\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			streams_set = TRUE;
+			streams = (to.val & 0x0f);
+			if (streams > 4)
+				fprintf(stderr, "%s: Nsts > %d\n", fn_name, to.val);
+		}
+		if (to.opt == 'c') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for stf core\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			core_set = TRUE;
+			core = (to.val & 0x0f) << 4;
+			if (core == 0) {
+				fprintf(stderr, "%s: %1d-stream core cannot be zero\n",
+					fn_name, streams);
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+		if (to.opt == 'o') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for streams\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			ofdm_set = TRUE;
+			ofdm_mask = (to.val & 0x0f);
+			if (ofdm_mask == 0) {
+				fprintf(stderr, "%s: OFDM core cannot be zero\n", fn_name);
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+		if (to.opt == 'k') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for streams\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			cck_set = TRUE;
+			cck_mask = (to.val & 0x0f);
+			if (cck_mask == 0) {
+				fprintf(stderr, "%s: CCK core cannot be zero\n", fn_name);
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+
+		if (streams_set && core_set) {
+			streams_set = core_set = FALSE;
+			mcs_set = TRUE;
+			idx = streams - 1;
+			mcs_mask[idx] = (uint8)(core|streams);
+		}
+	}
+
+	if (streams_set != core_set) {
+		fprintf(stderr, "%s: require to set both -s x -c y\n", fn_name);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	if (mcs_set) {
+		coremask[0] |= mcs_mask[0] << 0;
+		coremask[0] |= mcs_mask[1] << 8;
+		coremask[0] |= mcs_mask[2] << 16;
+		coremask[0] |= mcs_mask[3] << 24;
+	}
+	if (cck_set)
+		coremask[1] |= cck_mask;
+	if (ofdm_set)
+		coremask[1] |= ofdm_mask << 8;
+next:
+	err = wlu_var_setbuf(wl, cmd->name, coremask, sizeof(uint32)*2);
+exit:
+	return err;
+}
+
+#ifdef PLC
+static int
+wl_plc(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	char *endptr;
+	const char *cmdname = "plc";
+	wl_plc_params_t plc, *reply;
+	int err;
+	void *ptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&plc, 0, sizeof(plc));
+
+	if ((param = *++argv) == NULL) {
+		plc.cmd = PLC_CMD_FAILOVER;
+		/* Get plc failover status */
+		err = wlu_var_getbuf_sm(wl, cmdname, &plc, sizeof(plc), &ptr);
+		reply = (wl_plc_params_t *)ptr;
+		if (err >= 0)
+			printf("%d\n", reply->plc_failover);
+		return err;
+	}
+
+	if ((strcmp(param, "1") == 0) || (strcmp(param, "0") == 0)) {
+		plc.cmd = PLC_CMD_FAILOVER;
+		plc.plc_failover = strtoul(param, &endptr, 0);
+		/* Set plc failover status */
+		err = wlu_var_setbuf(wl, cmdname, &plc, sizeof(plc));
+		return err;
+	} else if (strcmp(param, "node_list") == 0) {
+		wl_plc_nodelist_t *list = (wl_plc_nodelist_t *)buf;
+		uint32 i, max = (WLC_IOCTL_MAXLEN - sizeof(int)) / sizeof(wl_plc_nodelist_t);
+
+		/* Get the list of known nodes */
+		plc.cmd = PLC_CMD_NODE_LIST;
+		memset(buf, 0, WLC_IOCTL_MAXLEN);
+		err = wlu_iovar_getbuf(wl, cmdname, &plc, sizeof(plc), buf, WLC_IOCTL_MAXLEN);
+		if (err < 0)
+			return err;
+
+		for (i = 0; i < dtoh32(list->count) && i < max; i++) {
+			printf("%s    %-9s   %-d\n", wl_ether_etoa(&list->node[i].ea),
+			       list->node[i].node_type == NODE_TYPE_WIFI_ONLY ? "wifi-only" :
+			       list->node[i].node_type == NODE_TYPE_PLC_ONLY ? "plc-only" :
+			       list->node[i].node_type == NODE_TYPE_WIFI_PLC ? "wifi-plc" :
+			       "unknown", list->node[i].cost);
+		}
+		return err;
+	} else if (strcmp(param, "mac_affinity") == 0)
+		plc.cmd = PLC_CMD_MAC_COST;
+	else if (strcmp(param, "link_affinity") == 0)
+		plc.cmd = PLC_CMD_LINK_COST;
+	else
+		return BCME_USAGE_ERROR;
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(param, &plc.node_ea))
+		return BCME_USAGE_ERROR;
+
+	if ((param = *++argv) == NULL) {
+		/* Get plc link/mac path affinity */
+		err = wlu_var_getbuf_sm(wl, cmdname, &plc, sizeof(plc), &ptr);
+		reply = (wl_plc_params_t *)ptr;
+		if (err >= 0)
+			printf("%d\n", reply->cost);
+		return err;
+	}
+
+	/* Set plc link/mac path affinity */
+	plc.cost = strtoul(param, &endptr, 0);
+	err = wlu_var_setbuf(wl, cmdname, &plc, sizeof(plc));
+
+	return err;
+}
+#endif /* PLC */
+
+static int
+wl_txfifo_sz(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "txfifo_sz";
+	wl_txfifo_sz_t ts, *reply;
+	uint fifo;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	fifo = atoi(param);
+	if (fifo > NFIFO)
+		return BCME_USAGE_ERROR;
+	ts.fifo = fifo;
+	ts.magic = WL_TXFIFO_SZ_MAGIC;
+
+	if ((param = *++argv)) {
+		ts.size = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &ts, sizeof(ts));
+	} else {
+		if ((err = wlu_var_getbuf_sm(wl, cmdname, &ts, sizeof(ts), &ptr) < 0))
+			return err;
+		reply = (wl_txfifo_sz_t *)ptr;
+		printf("fifo %d size %d\n", fifo, reply->size);
+	}
+	return err;
+}
+#ifdef WLPFN
+static int
+wl_pfn_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_pfn_param_t pfn_param;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Setup default values */
+	pfn_param.version = PFN_VERSION;
+	/* Sorting based on list order, no back ground scan, no autoswitch,
+	  * no immediate event report, no adaptvie scan, but immediate scan
+	  */
+	pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT | ENABLE << IMMEDIATE_SCAN_BIT);
+	/* Scan frequency of 30 sec */
+	pfn_param.scan_freq = 30;
+	/* slow adapt scan is off by default */
+	pfn_param.slow_freq = 0;
+	/* RSSI margin of 30 dBm */
+	pfn_param.rssi_margin = 30;
+	/* Network timeout 60 sec */
+	pfn_param.lost_network_timeout = 60;
+	/* best n = 2 by default */
+	pfn_param.bestn = DEFAULT_BESTN;
+	/* mscan m=0 by default, so not record best networks by default */
+	pfn_param.mscan = DEFAULT_MSCAN;
+	/*  default repeat = 10 */
+	pfn_param.repeat = DEFAULT_REPEAT;
+	/* by default, maximum scan interval = 2^2*scan_freq when adaptive scan is turned on */
+	pfn_param.exp = DEFAULT_EXP;
+
+	while (*++argv) {
+		if (!stricmp(*argv, "scanfrq")) {
+			if (*++argv)
+				pfn_param.scan_freq = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing scanfrq option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "netimeout")) {
+			if (*++argv)
+				pfn_param.lost_network_timeout = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing netimeout option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "rssi_delta")) {
+			if (*++argv)
+				pfn_param.rssi_margin = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing rssi_delta option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "sort")) {
+			if (*++argv) {
+				pfn_param.flags &= ~SORT_CRITERIA_MASK;
+				if (!stricmp(*argv, "listorder"))
+					pfn_param.flags |= (PFN_LIST_ORDER << SORT_CRITERIA_BIT);
+				else if (!stricmp(*argv, "rssi"))
+					pfn_param.flags |= (PFN_RSSI << SORT_CRITERIA_BIT);
+				else {
+					fprintf(stderr, "Invalid sort option %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "Missing sort option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "immediateevent")) {
+			if (*++argv) {
+				if (!stricmp(*argv, "1")) {
+					pfn_param.flags |= IMMEDIATE_EVENT_MASK;
+				} else if (!stricmp(*argv, "0")) {
+					pfn_param.flags &= ~IMMEDIATE_EVENT_MASK;
+				} else {
+					fprintf(stderr, "Invalid immediateevent option\n");
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "Missing immediateevent option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "bkgscan")) {
+			if (*++argv) {
+				pfn_param.flags &= ~ENABLE_BKGRD_SCAN_MASK;
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << ENABLE_BKGRD_SCAN_BIT);
+				else
+					pfn_param.flags |= (DISABLE << ENABLE_BKGRD_SCAN_BIT);
+			} else {
+				fprintf(stderr, "Missing bkgscan option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "immediate")) {
+			pfn_param.flags &= ~IMMEDIATE_SCAN_MASK;
+			if (*++argv) {
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << IMMEDIATE_SCAN_BIT);
+				else
+					pfn_param.flags |= (DISABLE << IMMEDIATE_SCAN_BIT);
+			} else {
+				fprintf(stderr, "Missing immediate option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "bdscan")) {
+			if (*++argv) {
+				pfn_param.flags &= ~ENABLE_BD_SCAN_MASK;
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
+				else
+					pfn_param.flags |= (DISABLE << ENABLE_BD_SCAN_BIT);
+			} else {
+				fprintf(stderr, "Missing bdscan option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "separate")) {
+			if (*++argv) {
+				pfn_param.flags &= ~REPORT_SEPERATELY_MASK;
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << REPORT_SEPERATELY_BIT);
+				else
+					pfn_param.flags |= (DISABLE << REPORT_SEPERATELY_BIT);
+			} else {
+				fprintf(stderr, "Missing seperate option\n");
+				return -1;
+			}
+		} else if (!stricmp(*argv, "adapt")) {
+			if (*++argv) {
+				pfn_param.flags &= ~ENABLE_ADAPTSCAN_MASK;
+				if (!stricmp(*argv, "off")) {
+					pfn_param.flags |= (OFF_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else if (!stricmp(*argv, "smart")) {
+					pfn_param.flags |= (SMART_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else if (!stricmp(*argv, "strict")) {
+					pfn_param.flags |= (STRICT_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else if (!stricmp(*argv, "slow")) {
+					pfn_param.flags |= (SLOW_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else {
+					fprintf(stderr, "Invalid adaptive scan option %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "Missing adaptive scan option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "bestn")) {
+			pfn_param.bestn = atoi(*++argv);
+		} else if (!stricmp(*argv, "mscan")) {
+			pfn_param.mscan = atoi(*++argv);
+		} else if (!stricmp(*argv, "repeat")) {
+			pfn_param.repeat = atoi(*++argv);
+			if (pfn_param.repeat < 1 || pfn_param.repeat > 20) {
+				fprintf(stderr, "repeat %d out of range (1-20)\n",
+					pfn_param.repeat);
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "exp")) {
+			pfn_param.exp = atoi(*++argv);
+			if (pfn_param.exp < 1 || pfn_param.exp > 5) {
+				fprintf(stderr, "exp %d out of range (1-5)\n",
+					pfn_param.exp);
+				return BCME_BADARG;
+			}
+		} else if (!stricmp(*argv, "slowfrq")) {
+			if (*++argv)
+				pfn_param.slow_freq = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing slowfrq option\n");
+				return BCME_USAGE_ERROR;
+			}
+		}  else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if ((((pfn_param.flags & ENABLE_ADAPTSCAN_MASK) ==
+	    (SLOW_ADAPT << ENABLE_ADAPTSCAN_BIT)) &&
+	    !pfn_param.slow_freq) ||
+	    (((pfn_param.flags & ENABLE_ADAPTSCAN_MASK) !=
+	    (SLOW_ADAPT << ENABLE_ADAPTSCAN_BIT)) &&
+	    pfn_param.slow_freq)) {
+		fprintf(stderr, "SLOW_ADAPT flag and slowfrq value not match\n");
+		return BCME_BADARG;
+	}
+	pfn_param.version = htod32(pfn_param.version);
+	pfn_param.scan_freq = htod32(pfn_param.scan_freq);
+	pfn_param.lost_network_timeout = htod32(pfn_param.lost_network_timeout);
+	pfn_param.flags = htod16(pfn_param.flags);
+	pfn_param.rssi_margin = htod16(pfn_param.rssi_margin);
+	pfn_param.slow_freq = htod32(pfn_param.slow_freq);
+
+	if ((err = wlu_iovar_set(wl, "pfn_set", &pfn_param, sizeof(wl_pfn_param_t))))
+		return (err);
+
+	return (0);
+}
+
+static bool
+validate_hex(char hexchar)
+{
+	if ((hexchar >= '0' && hexchar <= '9') ||
+		(hexchar >= 'a' || hexchar <= 'z') ||
+		(hexchar >= 'A' || hexchar <= 'Z'))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static uint8
+char2hex(char hexchar)
+{
+	if (hexchar >= '0' && hexchar <= '9')
+		return (hexchar - '0');
+	else if (hexchar >= 'a' && hexchar <= 'z')
+		return (hexchar - 'a' + 10);
+	else if (hexchar >= 'A' && hexchar <= 'Z')
+		return (hexchar - 'A' + 10);
+	else
+	{
+		fprintf(stderr, "non-hex\n");
+		return 0xff;
+	}
+}
+
+#define MAXNUM_SSID_PER_ADD	16
+
+static int
+wl_pfn_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int         err;
+	wl_pfn_t    *p_pfn_element = NULL;
+	int         i, pfn_element_len, cnt;
+	wl_pfn_t    *pssidnet = NULL;
+	int32       hidden;
+
+	UNUSED_PARAMETER(cmd);
+
+	pfn_element_len = MAXNUM_SSID_PER_ADD * sizeof(wl_pfn_t);
+	p_pfn_element = (wl_pfn_t *)malloc(pfn_element_len);
+	if (p_pfn_element == NULL) {
+		fprintf(stderr, "Failed to allocate buffer for %d bytes\n", pfn_element_len);
+		return BCME_NOMEM;
+	}
+	memset(p_pfn_element, '\0', pfn_element_len);
+
+	pssidnet = p_pfn_element;
+	for (i = 0; i < MAXNUM_SSID_PER_ADD; i++) {
+		/* Default setting, open, no WPA, no WEP and bss */
+		pssidnet->auth = DOT11_OPEN_SYSTEM;
+		pssidnet->wpa_auth = WPA_AUTH_DISABLED;
+		pssidnet->wsec = 0;
+		pssidnet->infra = 1;
+		pssidnet->flags = 0;
+		pssidnet++;
+	}
+	cnt = -1;
+	pssidnet = p_pfn_element;
+	while (*++argv) {
+		if (!stricmp(*argv, "ssid")) {
+			if (*++argv) {
+				if (++cnt >= MAXNUM_SSID_PER_ADD) {
+					fprintf(stderr, "exceed max 16 SSID per pfn_add\n");
+					err = BCME_BADARG;
+					goto error;
+				}
+				if (cnt > 0) {
+					pssidnet->flags = htod32(pssidnet->flags);
+					pssidnet++;
+				}
+				strncpy((char *)pssidnet->ssid.SSID, *argv,
+				        sizeof(pssidnet->ssid.SSID));
+				pssidnet->ssid.SSID_len =
+				   strlen((char *)pssidnet->ssid.SSID);
+				if (pssidnet->ssid.SSID_len > 32) {
+					fprintf(stderr, "SSID too long: %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+				pssidnet->ssid.SSID_len = htod32(pssidnet->ssid.SSID_len);
+			} else {
+				fprintf(stderr, "no value for ssid\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		}
+		else if (!stricmp(*argv, "hidden")) {
+			if (pssidnet->ssid.SSID_len == 0) {
+				fprintf(stderr, "Wrong! Start with SSID\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+			if (*++argv) {
+				hidden = **argv - '0';
+				if (hidden != ENABLE && hidden != DISABLE) {
+					fprintf(stderr, "invalid hidden setting, use 0/1\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->flags |= hidden << WL_PFN_HIDDEN_BIT;
+			} else {
+				fprintf(stderr, "no value for hidden\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		}  else if (!stricmp(*argv, "imode")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "bss")) {
+					pssidnet->infra = 1;
+				} else if (!stricmp(*argv, "ibss")) {
+					pssidnet->infra = 0;
+				} else {
+					fprintf(stderr, "Invalid imode arg %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->infra = htod32(pssidnet->infra);
+			} else {
+				fprintf(stderr, "Missing option for imode\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "amode")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "open"))
+					pssidnet->auth = DOT11_OPEN_SYSTEM;
+				else if (!stricmp(*argv, "shared"))
+					pssidnet->auth = DOT11_SHARED_KEY;
+				else {
+					fprintf(stderr, "Invalid imode arg %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->auth = htod32(pssidnet->auth);
+			} else {
+				fprintf(stderr, "Missing option for amode\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "wpa_auth")) {
+			if (*++argv) {
+				uint32 wpa_auth;
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+
+				/* figure requested auth, allow "any" */
+				if (!stricmp(*argv, "wpapsk"))
+					pssidnet->wpa_auth = WPA_AUTH_PSK;
+				else if (!stricmp(*argv, "wpa2psk"))
+					pssidnet->wpa_auth = WPA2_AUTH_PSK;
+				else if (!stricmp(*argv, "wpadisabled"))
+					pssidnet->wpa_auth = WPA_AUTH_DISABLED;
+				else if (!stricmp(*argv, "any"))
+					pssidnet->wpa_auth = WPA_AUTH_PFN_ANY;
+				else if ((wpa_auth = strtoul(*argv, 0, 0)))
+					pssidnet->wpa_auth = wpa_auth;
+				else {
+					fprintf(stderr, "Invalid wpa_auth option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->wpa_auth = htod32(pssidnet->wpa_auth);
+			} else {
+				fprintf(stderr, "Missing option for wpa_auth\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "wsec")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "WEP")) {
+					pssidnet->wsec = WEP_ENABLED;
+				} else if (!stricmp(*argv, "TKIP"))
+					pssidnet->wsec = TKIP_ENABLED;
+				else if (!stricmp(*argv, "AES"))
+					pssidnet->wsec = AES_ENABLED;
+				else if (!stricmp(*argv, "TKIPAES"))
+					pssidnet->wsec = TKIP_ENABLED | AES_ENABLED;
+				else {
+					fprintf(stderr, "Invalid wsec option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->wsec = htod32(pssidnet->wsec);
+			} else {
+				fprintf(stderr, "Missing option for wsec\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "suppress")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "found")) {
+					pssidnet->flags |= WL_PFN_SUPPRESSFOUND_MASK;
+				} else if (!stricmp(*argv, "lost")) {
+					pssidnet->flags |= WL_PFN_SUPPRESSLOST_MASK;
+				} else if (!stricmp(*argv, "neither")) {
+					pssidnet->flags &=
+					 ~(WL_PFN_SUPPRESSLOST_MASK | WL_PFN_SUPPRESSFOUND_MASK);
+				} else {
+					fprintf(stderr, "Invalid suppress option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for suppress\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "rssi")) {
+			if (*++argv) {
+				int rssi = atoi(*argv);
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (rssi >= -128 && rssi <= 0) {
+					pssidnet->flags |= (rssi << WL_PFN_RSSI_SHIFT)
+						& WL_PFN_RSSI_MASK;
+				} else {
+					fprintf(stderr, "Invalid rssi option %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for rssi\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		}	else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			err = BCME_USAGE_ERROR;
+			goto error;
+		}
+	}
+	pssidnet->flags = htod32(pssidnet->flags);
+
+	pfn_element_len = (cnt + 1) * sizeof(wl_pfn_t);
+	if ((err = wlu_iovar_set(wl, "pfn_add", p_pfn_element,
+	     pfn_element_len))) {
+		fprintf(stderr, "pfn_add fail\n");
+		goto error;
+	}
+	free(p_pfn_element);
+	return (0);
+
+error:
+	free(p_pfn_element);
+	return err;
+}
+
+#define MAXNUM_BSSID_PER_ADD	150
+
+static int
+wl_pfn_add_bssid(void *wl, cmd_t *cmd, char **argv)
+{
+	int                 err;
+	uint8               *ptr;
+	int                 i, bssidlistlen, cnt;
+	wl_pfn_bssid_t      *bssidlist;
+	wl_pfn_bssid_t      *pbssid = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*(argv + 1)) {
+		fprintf(stderr, "Invalid command\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	bssidlistlen = MAXNUM_BSSID_PER_ADD * sizeof(wl_pfn_bssid_t);
+	bssidlist = (wl_pfn_bssid_t *)malloc(bssidlistlen);
+	if (bssidlist == NULL) {
+		fprintf(stderr, "Failed to allocate buffer for %d bytes\n", bssidlistlen);
+		return BCME_NOMEM;
+	}
+	memset(bssidlist, '\0', bssidlistlen);
+
+	cnt = 0;
+	while (*++argv) {
+		if (!stricmp(*argv, "bssid")) {
+			if (*++argv) {
+				if (cnt >= MAXNUM_BSSID_PER_ADD) {
+					fprintf(stderr, "exceed max 150 BSSID per pfn_add_bssid\n");
+					err = BCME_BADARG;
+					goto error;
+				}
+				if (!cnt)
+					pbssid = bssidlist;
+				else {
+					pbssid->flags = htod16(pbssid->flags);
+					pbssid++;
+				}
+
+				ptr = (uint8 *)*argv;
+				for (i = 0; i < ETHER_ADDR_LEN; i++)
+				{
+					if (!validate_hex(*ptr) || !validate_hex(*(ptr + 1)))
+					{
+						fprintf(stderr, "non-hex in BSSID\n");
+						err = BCME_BADARG;
+						goto error;
+					}
+					pbssid->macaddr.octet[i] =
+					      char2hex(*ptr) << 4 | char2hex(*(ptr+1));
+					ptr += 3;
+				}
+				cnt++;
+			} else {
+				fprintf(stderr, "Missing option for bssid\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "suppress")) {
+			if (!pbssid || ETHER_ISNULLADDR(pbssid->macaddr.octet)) {
+				fprintf(stderr, "Wrong! Start with BSSID\n");
+				err = BCME_BADARG;
+				goto error;
+			}
+			if (*++argv) {
+				if (!stricmp(*argv, "found")) {
+					pbssid->flags |= WL_PFN_SUPPRESSFOUND_MASK;
+				} else if (!stricmp(*argv, "lost")) {
+					pbssid->flags |= WL_PFN_SUPPRESSLOST_MASK;
+				} else if (!stricmp(*argv, "neither")) {
+					pbssid->flags &=
+					 ~(WL_PFN_SUPPRESSFOUND_MASK | WL_PFN_SUPPRESSLOST_MASK);
+				} else {
+					fprintf(stderr, "Invalid suppress option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for suppress\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "rssi")) {
+			if (*++argv) {
+				int rssi = atoi(*argv);
+				if (!pbssid || ETHER_ISNULLADDR(pbssid->macaddr.octet)) {
+					fprintf(stderr, "Wrong! Start with BSSID\n");
+					err = BCME_BADARG;
+					goto error;
+				}
+				if (rssi >= -128 && rssi <= 0) {
+					pbssid->flags |= (rssi << WL_PFN_RSSI_SHIFT)
+						& WL_PFN_RSSI_MASK;
+				} else {
+					fprintf(stderr, "Invalid rssi option %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for rssi\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			err = BCME_USAGE_ERROR;
+			goto error;
+		}
+	}
+	pbssid->flags = htod16(pbssid->flags);
+
+	bssidlistlen = cnt * sizeof(wl_pfn_bssid_t);
+	if ((err = wlu_iovar_set(wl, "pfn_add_bssid", bssidlist,
+	     bssidlistlen))) {
+		fprintf(stderr, "pfn_add_bssid fail\n");
+		goto error;
+	}
+	free(bssidlist);
+	return 0;
+
+error:
+	free(bssidlist);
+	return err;
+}
+
+static int
+wl_pfn_cfg(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pfn_cfg_t pfncfg_param;
+	int          nchan = 0;
+	int          err;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&pfncfg_param, '\0', sizeof(wl_pfn_cfg_t));
+
+	/* Setup default values */
+	pfncfg_param.reporttype = WL_PFN_REPORT_ALLNET;
+	pfncfg_param.channel_num = 0;
+
+	while (*++argv) {
+		if (!stricmp(*argv, "report")) {
+			if (*++argv) {
+				if (!stricmp(*argv, "all")) {
+					pfncfg_param.reporttype = WL_PFN_REPORT_ALLNET;
+				} else if (!stricmp(*argv, "ssidonly")) {
+					pfncfg_param.reporttype = WL_PFN_REPORT_SSIDNET;
+				} else if (!stricmp(*argv, "bssidonly")) {
+					pfncfg_param.reporttype = WL_PFN_REPORT_BSSIDNET;
+				} else {
+					fprintf(stderr, "Invalid report option %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "no value for report\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "channel")) {
+			if (*++argv) {
+				nchan = wl_parse_channel_list(*argv, pfncfg_param.channel_list,
+				                              WL_NUMCHANNELS);
+				if (nchan < 0) {
+					fprintf(stderr, "error parsing channel\n");
+					return BCME_BADARG;
+				}
+			} else {
+				fprintf(stderr, "Missing option for channel\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "prohibited")) {
+			if (*++argv) {
+				pfncfg_param.flags &= ~WL_PFN_CFG_FLAGS_PROHIBITED;
+				if (atoi(*argv))
+					pfncfg_param.flags |= WL_PFN_CFG_FLAGS_PROHIBITED;
+			} else {
+				fprintf(stderr, "Missing prohibited option value\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	pfncfg_param.reporttype = htod32(pfncfg_param.reporttype);
+	pfncfg_param.channel_num = htod32(nchan);
+	pfncfg_param.flags = htod32(pfncfg_param.flags);
+
+	if ((err = wlu_iovar_set(wl, "pfn_cfg", &pfncfg_param,
+	     sizeof(wl_pfn_cfg_t)))) {
+		fprintf(stderr, "pfn_cfg fail\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_pfn(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		val = atoi(*argv);
+		err = wlu_iovar_setint(wl, "pfn", (val ? 1 : 0));
+	} else {
+		err = wlu_iovar_getint(wl, "pfn", &val);
+		if (!err)
+			wl_printint(val);
+	}
+
+	return err;
+}
+#define WL_PFN_BESTNET_LEN	1024
+
+static int
+wl_pfnbest(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err;
+	wl_pfn_scanresults_t *bestnet;
+	wl_pfn_net_info_t *netinfo;
+	uint32 i, j;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+	bestnet = (wl_pfn_scanresults_t *)malloc(WL_PFN_BESTNET_LEN);
+	if (bestnet == NULL) {
+		fprintf(stderr, "Failed to allocate buffer of %d bytes\n", WL_PFN_BESTNET_LEN);
+		return BCME_NOMEM;
+	}
+
+	bzero(bestnet, WL_PFN_BESTNET_LEN);
+	while (bestnet->status != PFN_COMPLETE) {
+		if ((err = wlu_iovar_get(wl, "pfnbest", (void *)bestnet, WL_PFN_BESTNET_LEN))) {
+			fprintf(stderr, "pfnbest fail\n");
+			free(bestnet);
+			return err;
+		}
+		if (bestnet->count >
+		    (WL_PFN_BESTNET_LEN / sizeof(wl_pfn_net_info_t)))
+		{
+			fprintf(stderr, "invalid data\n");
+			free(bestnet);
+			return -1;
+		}
+
+		printf("ver %d, status %d, count %d\n",
+		 bestnet->version, bestnet->status, bestnet->count);
+		netinfo = bestnet->netinfo;
+		for (i = 0; i < bestnet->count; i++) {
+			for (j = 0; j < netinfo->pfnsubnet.SSID_len; j++)
+				printf("%c", netinfo->pfnsubnet.SSID[j]);
+			printf("\n");
+			printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+			        netinfo->pfnsubnet.BSSID.octet[0],
+			        netinfo->pfnsubnet.BSSID.octet[1],
+			        netinfo->pfnsubnet.BSSID.octet[2],
+			        netinfo->pfnsubnet.BSSID.octet[3],
+			        netinfo->pfnsubnet.BSSID.octet[4],
+			        netinfo->pfnsubnet.BSSID.octet[5]);
+			printf("channel: %d, RSSI: %d, timestamp: %d\n",
+			 netinfo->pfnsubnet.channel, netinfo->RSSI, netinfo->timestamp);
+			netinfo++;
+		}
+	}
+
+	free(bestnet);
+	return 0;
+}
+
+static int
+wl_pfnlbest(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err;
+	wl_pfn_lscanresults_t *bestnet;
+	wl_pfn_lnet_info_t *netinfo;
+	uint32 i, j;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		return -1;
+	}
+	bestnet = (wl_pfn_lscanresults_t *)malloc(WL_PFN_BESTNET_LEN);
+	if (bestnet == NULL) {
+		fprintf(stderr, "Failed to allocate buffer of %d bytes\n", WL_PFN_BESTNET_LEN);
+		return -1;
+	}
+	bzero(bestnet, WL_PFN_BESTNET_LEN);
+	while (bestnet->status == PFN_INCOMPLETE) {
+		if ((err = wlu_iovar_get(wl, "pfnlbest", (void *)bestnet, WL_PFN_BESTNET_LEN))) {
+			fprintf(stderr, "pfnbest fail\n");
+			return err;
+		}
+		printf("ver %d, status %d, count %d\n",
+		 bestnet->version, bestnet->status, bestnet->count);
+		netinfo = bestnet->netinfo;
+		for (i = 0; i < bestnet->count; i++) {
+			for (j = 0; j < netinfo->pfnsubnet.SSID_len; j++)
+				printf("%c", netinfo->pfnsubnet.SSID[j]);
+			printf("\n");
+			printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+			        netinfo->pfnsubnet.BSSID.octet[0],
+			        netinfo->pfnsubnet.BSSID.octet[1],
+			        netinfo->pfnsubnet.BSSID.octet[2],
+			        netinfo->pfnsubnet.BSSID.octet[3],
+			        netinfo->pfnsubnet.BSSID.octet[4],
+			        netinfo->pfnsubnet.BSSID.octet[5]);
+			printf("channel: %d, flags: %d, RSSI: %d, timestamp: %d\n",
+			 netinfo->pfnsubnet.channel, netinfo->flags,
+			 netinfo->RSSI, netinfo->timestamp);
+			printf("RTT0: %d, RTT1: %d\n", netinfo->rtt0, netinfo->rtt1);
+			netinfo++;
+		}
+	}
+
+	free(bestnet);
+	return 0;
+}
+
+static int
+wl_pfn_suspend(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err, val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		val = atoi(*argv);
+		err = wlu_iovar_setint(wl, "pfn_suspend", (val ? 1 : 0));
+	} else {
+		err = wlu_iovar_getint(wl, "pfn_suspend", &val);
+		if (!err)
+			wl_printint(val);
+	}
+
+	return err;
+}
+
+static int
+wl_pfn_mem(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err, val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv && !stricmp(*argv, "bestn")) {
+		if (*++argv)
+			val = atoi(*argv);
+		else {
+			fprintf(stderr, "Missing bestn value\n");
+			return -1;
+		}
+	} else {
+		fprintf(stderr, "Missing bestn option\n");
+		return -1;
+	}
+
+	err = wlu_iovar_setint(wl, "pfnmem", val);
+	if (err) {
+		fprintf(stderr, "pfnmem set wrong!\n");
+		return err;
+	}
+
+	err = wlu_iovar_getint(wl, "pfnmem", &val);
+	if (!err)
+		wl_printint(val);
+	else
+		fprintf(stderr, "pfnmem get wrong!\n");
+	return err;
+}
+
+static void
+wl_pfn_printnet(wl_pfn_scanresults_t *ptr, int event_type)
+{
+	wl_pfn_net_info_t *netinfo = ptr->netinfo;
+	uint32 i, j;
+
+	if (WLC_E_PFN_NET_FOUND == event_type) {
+		printf("WLC_E_PFN_NET_FOUND:\n");
+	} else if (WLC_E_PFN_NET_LOST == event_type) {
+		printf("WLC_E_PFN_NET_LOST:\n");
+	} else if (WLC_E_PFN_BSSID_NET_FOUND == event_type) {
+		printf("WLC_E_PFN_BSSID_NET_FOUND:\n");
+	} else if (WLC_E_PFN_BSSID_NET_LOST == event_type) {
+		printf("WLC_E_PFN_BSSID_NET_LOST:\n");
+	} else {
+		return;
+	}
+	printf("ver %d, status %d, count %d\n",
+	        ptr->version, ptr->status, ptr->count);
+	for (i = 0; i < ptr->count; i++) {
+		printf("%d. ", i + 1);
+		for (j = 0; j < netinfo->pfnsubnet.SSID_len; j++)
+			printf("%c", netinfo->pfnsubnet.SSID[j]);
+		printf("\n");
+		printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		        netinfo->pfnsubnet.BSSID.octet[0],
+		        netinfo->pfnsubnet.BSSID.octet[1],
+		        netinfo->pfnsubnet.BSSID.octet[2],
+		        netinfo->pfnsubnet.BSSID.octet[3],
+		        netinfo->pfnsubnet.BSSID.octet[4],
+		        netinfo->pfnsubnet.BSSID.octet[5]);
+		printf("channel %d, RSSI %d, timestamp %d\n",
+		      netinfo->pfnsubnet.channel, netinfo->RSSI, netinfo->timestamp);
+
+		netinfo++;
+	}
+}
+
+static int
+wl_pfn_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	int                 fd, err;
+	struct sockaddr_ll	sll;
+	struct ifreq        ifr;
+	char                ifnames[IFNAMSIZ] = {"eth1"};
+	bcm_event_t         * event;
+	char                data[512];
+	int                 event_type;
+	struct ether_addr   *addr;
+	char                eabuf[ETHER_ADDR_STR_LEN];
+	wl_pfn_scanresults_t *ptr;
+	wl_pfn_net_info_t   *info;
+	uint32              i, j;
+	uint32              foundcnt, lostcnt;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* Override default ifname explicitly or implicitly */
+	if (*++argv) {
+		if (strlen(*argv) >= IFNAMSIZ) {
+			printf("Interface name %s too long\n", *argv);
+			return -1;
+		}
+		strncpy(ifnames, *argv, IFNAMSIZ);
+	} else if (wl) {
+		strncpy(ifnames, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, IFNAMSIZ);
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		return -1;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		return -1;
+	}
+
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		return -1;
+	}
+
+	while (1) {
+		recv(fd, data, sizeof(data), 0);
+		event = (bcm_event_t *)data;
+		addr = (struct ether_addr *)&(event->event.addr);
+
+		event_type = ntoh32(event->event.event_type);
+
+		if (addr != NULL) {
+			sprintf(eabuf, "%02x:%02x:%02x:%02x:%02x:%02x",
+				(uchar)addr->octet[0]&0xff,
+				(uchar)addr->octet[1]&0xff,
+				(uchar)addr->octet[2]&0xff,
+				(uchar)addr->octet[3]&0xff,
+				(uchar)addr->octet[4]&0xff,
+				(uchar)addr->octet[5]&0xff);
+		}
+
+		if (ntoh32(event->event.datalen)) {
+			if (WLC_E_PFN_SCAN_COMPLETE == event_type) {
+				ptr = (wl_pfn_scanresults_t *)(data + sizeof(bcm_event_t));
+				info = ptr->netinfo;
+				foundcnt = ptr->count & 0xffff;
+				lostcnt = ptr->count >> 16;
+				printf("ver %d, status %d, found %d, lost %d\n",
+				        ptr->version, ptr->status, foundcnt, lostcnt);
+				if (foundcnt)
+					printf("Network found:\n");
+				for (i = 0; i < foundcnt; i++) {
+					printf("%d. ", i + 1);
+					for (j = 0; j < info->pfnsubnet.SSID_len; j++)
+						printf("%c", info->pfnsubnet.SSID[j]);
+					printf("\n");
+					printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+					        info->pfnsubnet.BSSID.octet[0],
+					        info->pfnsubnet.BSSID.octet[1],
+					        info->pfnsubnet.BSSID.octet[2],
+					        info->pfnsubnet.BSSID.octet[3],
+					        info->pfnsubnet.BSSID.octet[4],
+					        info->pfnsubnet.BSSID.octet[5]);
+					printf("channel %d, RSSI %d, timestamp %d\n",
+					 info->pfnsubnet.channel, info->RSSI, info->timestamp);
+					info++;
+				}
+				if (lostcnt)
+					printf("Network lost:\n");
+				for (i = 0; i < lostcnt; i++) {
+					printf("%d. ", i + 1);
+					for (j = 0; j < info->pfnsubnet.SSID_len; j++)
+						printf("%c", info->pfnsubnet.SSID[j]);
+					printf("\n");
+					printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+					        info->pfnsubnet.BSSID.octet[0],
+					        info->pfnsubnet.BSSID.octet[1],
+					        info->pfnsubnet.BSSID.octet[2],
+					        info->pfnsubnet.BSSID.octet[3],
+					        info->pfnsubnet.BSSID.octet[4],
+					        info->pfnsubnet.BSSID.octet[5]);
+					printf("channel %d, RSSI %d, timestamp %d\n",
+					 info->pfnsubnet.channel, info->RSSI, info->timestamp);
+					info++;
+				}
+			} else if ((WLC_E_PFN_NET_FOUND == event_type) ||
+			           (WLC_E_PFN_NET_LOST == event_type) ||
+			           (WLC_E_PFN_BSSID_NET_FOUND == event_type) ||
+			           (WLC_E_PFN_BSSID_NET_LOST == event_type)) {
+				wl_pfn_printnet(
+				   (wl_pfn_scanresults_t *)(data + sizeof(bcm_event_t)),
+				                            event_type);
+			}
+
+			if (WLC_E_LINK == event_type || WLC_E_NDIS_LINK == event_type) {
+				if (ntoh16(event->event.flags) & WLC_EVENT_MSG_LINK)
+					printf("MACEVENT Link up :%s\n", eabuf);
+				else
+					printf("MACEVENT Link down :%s\n", eabuf);
+			}
+		} else {
+			if (WLC_E_PFN_SCAN_NONE == event_type) {
+				printf("Got WLC_E_PFN_SCAN_NONE\n");
+			}
+			if (WLC_E_PFN_SCAN_ALLGONE == event_type) {
+				printf("Got WLC_E_PFN_SCAN_ALLGONE\n");
+			}
+			if (WLC_E_PFN_BEST_BATCHING == event_type) {
+				printf("Got WLC_E_PFN_BEST_BATCHING\n");
+			}
+		}
+	}
+	return (0);
+}
+
+#define ESCAN_EVENTS_BUFFER_SIZE 2048
+
+static int
+wl_escan_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	int					fd, err, i, octets;
+	struct sockaddr_ll	sll;
+	struct ifreq		ifr;
+	char				ifnames[IFNAMSIZ] = {"eth1"};
+	uint8               print_flag = 4;
+	bcm_event_t			* event;
+	uint32              status;
+	char*				data;
+	int					event_type;
+	uint8	event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+
+	wl_escan_result_t* escan_data;
+
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		if (strlen(*argv) >= IFNAMSIZ) {
+			printf("Interface name %s too long\n", *argv);
+			return -1;
+		}
+		strncpy(ifnames, *argv, (IFNAMSIZ - 1));
+		if (*++argv)
+			print_flag = atoi(*argv);
+	} else if (wl) {
+		strncpy(ifnames, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+	event_inds_mask[WLC_E_ESCAN_RESULT / 8] |= 1 << (WLC_E_ESCAN_RESULT % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		return (err);
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		return -1;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		return -1;
+	}
+
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		return -1;
+	}
+
+	data = (char*)malloc(ESCAN_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			ESCAN_EVENTS_BUFFER_SIZE);
+		return BCME_NOMEM;
+	}
+
+	while (1) {
+		octets = recv(fd, data, ESCAN_EVENTS_BUFFER_SIZE, 0);
+		event = (bcm_event_t *)data;
+
+		event_type = ntoh32(event->event.event_type);
+
+		if ((event_type == WLC_E_ESCAN_RESULT) && (octets > 0)) {
+			escan_data = (wl_escan_result_t*)&data[sizeof(bcm_event_t)];
+			status = ntoh32(event->event.status);
+
+			if (print_flag & 1)
+				printf("WLC_E_ESCAN_RESULT, (sync_id,status) = (%d,%d)\n",
+				escan_data->sync_id, status);
+
+			if (print_flag & 2)
+				for (i = 0; i < escan_data->bss_count; i++)
+					dump_bss_info(&escan_data->bss_info[i]);
+
+			if (print_flag & 4) {
+				if (status == WLC_E_STATUS_PARTIAL) {
+					printf("sync_id: %d, WLC_E_STATUS_PARTIAL\n",
+					escan_data->sync_id);
+					for (i = 0; i < escan_data->bss_count; i++)
+						dump_bss_info(&escan_data->bss_info[i]);
+				}
+				if (status == WLC_E_STATUS_SUCCESS)
+					printf("sync_id: %d, WLC_E_STATUS_SUCCESS => SCAN_DONE\n",
+					escan_data->sync_id);
+				if ((status != WLC_E_STATUS_SUCCESS) &&
+					(status != WLC_E_STATUS_PARTIAL))
+					printf("sync_id: %d, status:%d, misc. error/abort\n",
+					escan_data->sync_id, status);
+			}
+
+			if (print_flag & 8) {
+				int    remainder = escan_data->bss_info[0].ie_length;
+				int    processed = sizeof(wl_escan_result_t);
+				uint8* iebuf = &((uint8*)escan_data)[sizeof(wl_escan_result_t)];
+
+				if (status != WLC_E_STATUS_PARTIAL)
+					continue;
+
+				printf("MOREINFO: (sync_id,buflen,ielen) = (%d,%d,%d)\n",
+					escan_data->sync_id,
+					escan_data->buflen,
+					escan_data->bss_info[0].ie_length);
+
+				/* do a tlv sanity check */
+				while (remainder > 0) {
+					processed += 1 + 1 + iebuf[1];
+					remainder -= 1 + 1 + iebuf[1];
+					iebuf     += 1 + 1 + iebuf[1];
+				}
+				if (processed >= ESCAN_EVENTS_BUFFER_SIZE)
+					break;
+
+				if (remainder != 0) {
+					printf("ERROR: IE tlv sanity check failed for "
+						"(ssid,sync_id,buflen,ielen,remainder) = "
+						"(%s,%d,%d,%d,%d)\n",
+						escan_data->bss_info[0].SSID,
+						escan_data->sync_id, escan_data->buflen,
+						escan_data->bss_info[0].ie_length,
+						remainder);
+					iebuf = &((uint8*)escan_data)[sizeof(wl_escan_result_t)];
+					if ((escan_data->buflen - sizeof(wl_escan_result_t)) > 0) {
+						for (i = 0;
+						i < (int)(escan_data->buflen -
+							sizeof(wl_escan_result_t));
+						i++) {
+							printf("%02x ", iebuf[i]);
+						}
+						printf("\n");
+					}
+				}
+			}
+		}
+	}
+
+	/* if we ever reach here */
+	free(data);
+
+	return (0);
+}
+
+struct escan_bss {
+	struct escan_bss *next;
+	wl_bss_info_t bss[1];
+};
+#define ESCAN_BSS_FIXED_SIZE 4
+
+static int
+wl_escanresults(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)) +
+	    (WL_NUMCHANNELS * sizeof(uint16));
+	wl_escan_params_t *params;
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth1"};
+	bcm_event_t *event;
+	uint32 status;
+	char *data;
+	int event_type;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+	wl_escan_result_t *escan_data;
+	struct escan_bss *escan_bss_head = NULL;
+	struct escan_bss *escan_bss_tail = NULL;
+	struct escan_bss *result;
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_escan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, &params->params, &params_size);
+	if (err)
+		goto exit2;
+
+	memset(&ifr, 0, sizeof(ifr));
+	if (wl)
+		strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	else
+		strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+
+	/* Read the event mask from driver and unmask the event WLC_E_ESCAN_RESULT */
+	if ((err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		goto exit2;
+	event_inds_mask[WLC_E_ESCAN_RESULT / 8] |= 1 << (WLC_E_ESCAN_RESULT % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		goto exit2;
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit2;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		goto exit2;
+	}
+
+	/* bind the socket first before starting escan so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit2;
+	}
+
+	params->version = htod32(ESCAN_REQ_VERSION);
+	params->action = htod16(WL_SCAN_ACTION_START);
+
+	srand((unsigned)time(NULL));
+	params->sync_id = htod16(rand() & 0xffff);
+
+	params_size += OFFSETOF(wl_escan_params_t, params);
+	err = wlu_iovar_setbuf(wl, "escan", params, params_size, buf, WLC_IOCTL_MAXLEN);
+
+	data = (char*)malloc(ESCAN_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			ESCAN_EVENTS_BUFFER_SIZE);
+		err = BCME_NOMEM;
+		goto exit2;
+	}
+
+	/* receive scan result */
+	while (1) {
+		octets = recv(fd, data, ESCAN_EVENTS_BUFFER_SIZE, 0);
+		event = (bcm_event_t *)data;
+		event_type = ntoh32(event->event.event_type);
+
+		if ((event_type == WLC_E_ESCAN_RESULT) && (octets > 0)) {
+			escan_data = (wl_escan_result_t*)&data[sizeof(bcm_event_t)];
+			status = ntoh32(event->event.status);
+
+			if (status == WLC_E_STATUS_PARTIAL) {
+				wl_bss_info_t *bi = &escan_data->bss_info[0];
+				wl_bss_info_t *bss;
+
+				/* check if we've received info of same BSSID */
+				for (result = escan_bss_head; result; result = result->next) {
+					bss = result->bss;
+
+					if (!wlu_bcmp(bi->BSSID.octet, bss->BSSID.octet,
+						ETHER_ADDR_LEN) &&
+						CHSPEC_BAND(bi->chanspec) ==
+						CHSPEC_BAND(bss->chanspec) &&
+						bi->SSID_len == bss->SSID_len &&
+						!wlu_bcmp(bi->SSID, bss->SSID, bi->SSID_len))
+						break;
+				}
+
+				if (!result) {
+					/* New BSS. Allocate memory and save it */
+					struct escan_bss *ebss = malloc(ESCAN_BSS_FIXED_SIZE
+						+ bi->length);
+
+					if (!ebss) {
+						perror("can't allocate memory for bss");
+						goto exit1;
+					}
+
+					ebss->next = NULL;
+					memcpy(&ebss->bss, bi, bi->length);
+					if (escan_bss_tail) {
+						escan_bss_tail->next = ebss;
+					}
+					else {
+						escan_bss_head = ebss;
+					}
+					escan_bss_tail = ebss;
+				}
+				else if (bi->RSSI != WLC_RSSI_INVALID) {
+					/* We've got this BSS. Update rssi if necessary */
+					if (((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
+						(bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) &&
+					    ((bss->RSSI == WLC_RSSI_INVALID) ||
+						(bss->RSSI < bi->RSSI))) {
+						/* preserve max RSSI if the measurements are
+						 * both on-channel or both off-channel
+						 */
+						bss->RSSI = bi->RSSI;
+						bss->SNR = bi->SNR;
+						bss->phy_noise = bi->phy_noise;
+					} else if ((bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
+						(bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
+						/* preserve the on-channel rssi measurement
+						 * if the new measurement is off channel
+						*/
+						bss->RSSI = bi->RSSI;
+						bss->SNR = bi->SNR;
+						bss->phy_noise = bi->phy_noise;
+						bss->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
+					}
+				}
+			}
+			else if (status == WLC_E_STATUS_SUCCESS) {
+				/* Escan finished. Let's go dump the results. */
+				break;
+			}
+			else {
+				printf("sync_id: %d, status:%d, misc. error/abort\n",
+					escan_data->sync_id, status);
+				goto exit1;
+			}
+		}
+	}
+
+	/* print scan results */
+	for (result = escan_bss_head; result; result = result->next) {
+		dump_bss_info(result->bss);
+	}
+
+exit1:
+	/* free scan results */
+	result = escan_bss_head;
+	while (result) {
+		struct escan_bss *tmp = result->next;
+		free(result);
+		result = tmp;
+	}
+
+	free(data);
+	close(fd);
+exit2:
+	free(params);
+
+	/* Read the event mask from driver and mask the event WLC_E_ESCAN_RESULT */
+	if (!(err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		event_inds_mask[WLC_E_ESCAN_RESULT / 8] &= (~(1 << (WLC_E_ESCAN_RESULT % 8)));
+		err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN);
+	}
+
+	return err;
+}
+
+static int
+wl_event_filter(void *wl, cmd_t *cmd, char **argv)
+{
+	int     err;
+	uint8   event_inds_mask[WL_EVENTING_MASK_LEN];  /* event bit mask */
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+
+	/* Register for following event for pfn */
+	event_inds_mask[WLC_E_LINK / 8] |= 1 << (WLC_E_LINK % 8);
+	event_inds_mask[WLC_E_PFN_NET_FOUND / 8] |= 1 << (WLC_E_PFN_NET_FOUND % 8);
+	event_inds_mask[WLC_E_PFN_NET_LOST / 8] |= 1 << (WLC_E_PFN_NET_LOST % 8);
+	event_inds_mask[WLC_E_PFN_SCAN_NONE/ 8] |= 1 << (WLC_E_PFN_SCAN_NONE % 8);
+	event_inds_mask[WLC_E_PFN_SCAN_ALLGONE/ 8] |= 1 << (WLC_E_PFN_SCAN_ALLGONE % 8);
+
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		return (err);
+
+	return (0);
+}
+#endif /* WLPFN */
+
+#ifdef WLP2PO
+#define UPNP_QUERY_VERSION	"0x10"
+#define	BCM_SVC_RPOTYPE_ALL	0
+#define	BCM_SVC_RPOTYPE_BONJOUR	1
+#define	BCM_SVC_RPOTYPE_UPNP	2
+#define	BCM_SVC_RPOTYPE_WSD	3
+#define	BCM_SVC_RPOTYPE_VENDOR	255
+
+static int
+wl_p2po_listen(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, params_size;
+	wl_p2po_listen_t	params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || !argv[2]) {
+		params.period = 0;
+		params.interval = 0;
+	}
+	else {
+		params.period = atoi(argv[1]);
+		params.interval = atoi(argv[2]);
+	}
+	params_size = sizeof(wl_p2po_listen_t);
+
+	err = wlu_iovar_set(wl, "p2po_listen", &params, params_size);
+
+	return err;
+}
+
+static int
+hexstr2hex(char *str)
+{
+	int i, len;
+	char hexstr[3];
+	char *src;
+
+	src = str;
+	len = strlen(str)/2;
+
+	for (i = 0; i < len; i++) {
+		hexstr[0] = src[0];
+		hexstr[1] = src[1];
+		hexstr[2] = '\0';
+		str[i] = strtoul(hexstr, NULL, 16);
+		src += 2;
+	}
+
+	return i;
+}
+
+static int
+wl_p2po_addsvc(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int protocol, query_len, response_len, params_size;
+	char *query, *response;
+	wl_p2po_qr_t *params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || !argv[2] || !argv[3]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	protocol = atoi(argv[1]);
+	if (protocol == BCM_SVC_RPOTYPE_BONJOUR) {
+		query = argv[2];
+		response = argv[3];
+		query_len = hexstr2hex(query);
+		response_len = hexstr2hex(response);
+	} else if (protocol == BCM_SVC_RPOTYPE_UPNP) {
+		if (memcmp(argv[2], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0 ||
+			memcmp(argv[3], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0) {
+			fprintf(stderr, "UPnP query/response string must start with 0x10");
+			return BCME_USAGE_ERROR;
+		}
+		query = argv[2] + strlen(UPNP_QUERY_VERSION) - 1;
+		response = argv[3] + strlen(UPNP_QUERY_VERSION) - 1;
+		query[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+		response[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+
+		query_len = strlen(query);
+		response_len = strlen(response);
+	}
+	else {
+		fprintf(stderr, "<protocol> should be <1|2>\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	params_size = sizeof(wl_p2po_qr_t) + query_len + response_len - 1;
+	params = (wl_p2po_qr_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+
+	params->protocol = protocol;
+	params->query_len = query_len;
+	params->response_len = response_len;
+	memcpy(params->qrbuf, query, query_len);
+	memcpy(params->qrbuf+query_len, response, response_len);
+
+	err = wlu_iovar_setbuf(wl, "p2po_addsvc", params, params_size, buf, WLC_IOCTL_MAXLEN);
+
+	free(params);
+
+	return err;
+}
+
+static int
+wl_p2po_delsvc(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int protocol, query_len, params_size;
+	char *query;
+	wl_p2po_qr_t *params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || (*argv[1] != '0' && !argv[2])) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (*argv[1] == '0') {
+		protocol = 0;
+		query_len = 0;
+	}
+	else {
+		protocol = atoi(argv[1]);
+		if (protocol == BCM_SVC_RPOTYPE_BONJOUR) {
+			query = argv[2];
+			query_len = hexstr2hex(query);
+		} else if (protocol == BCM_SVC_RPOTYPE_UPNP) {
+			if (memcmp(argv[2], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0) {
+				fprintf(stderr, "UPnP query string must start with 0x10");
+				return BCME_USAGE_ERROR;
+			}
+			query = argv[2] + strlen(UPNP_QUERY_VERSION) - 1;
+			query[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+
+			query_len = strlen(query);
+		}
+		else {
+			fprintf(stderr, "<protocol> should be <1|2>\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	params_size = sizeof(wl_p2po_qr_t) + (query_len ? query_len - 1 : 0);
+	params = (wl_p2po_qr_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+
+	params->protocol = protocol;
+	params->query_len = query_len;
+	if (query_len)
+		memcpy(params->qrbuf, query, query_len);
+
+	err = wlu_iovar_set(wl, "p2po_delsvc", params, params_size);
+
+	free(params);
+
+	return err;
+}
+
+static int
+wl_p2po_sd_reqresp(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int transaction_id, protocol, query_len, params_size;
+	char *query;
+	wl_p2po_qr_t *params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || !argv[2]) {
+			fprintf(stderr, "Too few arguments\n");
+			return BCME_USAGE_ERROR;
+	}
+
+	transaction_id = atoi(argv[1]);
+	if (transaction_id < 0 || transaction_id > 255) {
+		fprintf(stderr, "<transaction id> should be between 0 and 255\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	protocol = atoi(argv[2]);
+	if (!argv[3]) {
+		/* find everything for protocol */
+		query_len = 0;
+	} else if (protocol == BCM_SVC_RPOTYPE_BONJOUR) {
+		query = argv[3];
+		query_len = hexstr2hex(query);
+	} else if (protocol == BCM_SVC_RPOTYPE_UPNP) {
+		if (memcmp(argv[3], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0) {
+			fprintf(stderr, "UPnP query string must start with 0x10");
+			return BCME_USAGE_ERROR;
+		}
+		query = argv[3] + strlen(UPNP_QUERY_VERSION) - 1;
+		query[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+
+		query_len = strlen(query);
+	} else {
+		fprintf(stderr, "<protocol> should be <0|1|2>\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	params_size = sizeof(wl_p2po_qr_t) + (query_len ? query_len - 1 : 0);
+	params = (wl_p2po_qr_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+
+	params->transaction_id = transaction_id;
+	params->protocol = protocol;
+	params->query_len = query_len;
+	if (query_len)
+		memcpy(params->qrbuf, query, query_len);
+
+	err = wlu_iovar_set(wl, "p2po_sd_req_resp", params, params_size);
+
+	free(params);
+
+	return err;
+}
+
+static int
+wl_p2po_listen_channel(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		val = atoi(*argv);
+		return wlu_iovar_setint(wl, "p2po_listen_channel", val);
+	}
+
+	fprintf(stderr, "No channel is specified\n");
+	return BCME_USAGE_ERROR;
+}
+
+static int
+wl_p2po_stop(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		val = atoi(*argv);
+		return wlu_iovar_setint(wl, "p2po_stop", val);
+	}
+
+	fprintf(stderr, "Please specify - 0:stop, 1:pause\n");
+	return BCME_USAGE_ERROR;
+}
+
+#define P2PO_EVENTS_BUFFER_SIZE	2048
+
+static int
+wl_p2po_results(void *wl, cmd_t *cmd, char **argv)
+{
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth1"};
+	char *data;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(&ifr, 0, sizeof(ifr));
+	if (wl)
+		strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	else
+		strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+	event_inds_mask[WLC_E_SERVICE_FOUND / 8] |= 1 << (WLC_E_SERVICE_FOUND % 8);
+	event_inds_mask[WLC_E_GAS_FRAGMENT_RX / 8] |= 1 << (WLC_E_GAS_FRAGMENT_RX % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		goto exit2;
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit2;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		goto exit1;
+	}
+
+	/* bind the socket first before starting so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit1;
+	}
+
+	data = (char*)malloc(P2PO_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			P2PO_EVENTS_BUFFER_SIZE);
+		err = BCME_NOMEM;
+		goto exit1;
+	}
+
+	/* receive result */
+	while (1) {
+		bcm_event_t *bcm_event;
+		int event_type;
+
+		octets = recv(fd, data, P2PO_EVENTS_BUFFER_SIZE, 0);
+		bcm_event = (bcm_event_t *)data;
+		event_type = ntoh32(bcm_event->event.event_type);
+
+		if (octets >= (int)sizeof(bcm_event_t)) {
+			if (event_type == WLC_E_SERVICE_FOUND) {
+				uint32 status = ntoh32(bcm_event->event.status);
+				wl_event_sd_t *sd_data =
+					(wl_event_sd_t *)&data[sizeof(bcm_event_t)];
+
+				sd_data->channel = dtoh16(sd_data->channel);
+
+				printf("WLC_E_SERVICE_FOUND: %s\n",
+					status == WLC_E_STATUS_PARTIAL ? "WLC_E_STATUS_PARTIAL" :
+					status == WLC_E_STATUS_SUCCESS ? "WLC_E_STATUS_SUCCESS" :
+					status == WLC_E_STATUS_FAIL ? "WLC_E_STATUS_FAIL" :
+					"unknown");
+				printf("   channel         = %d\n", sd_data->channel);
+				printf("   peer            = %s\n",
+					wl_ether_etoa(&bcm_event->event.addr));
+				if (status == WLC_E_STATUS_SUCCESS) {
+					wl_sd_tlv_t *tlv;
+					int i;
+
+					tlv = sd_data->tlv;
+					for (i = 0; i < sd_data->count; i++) {
+						printf("   [TLV %d]\n", i);
+						tlv->length = dtoh16(tlv->length);
+						printf("   protocol type   = %s\n",
+							tlv->protocol == 0 ? "ALL" :
+							tlv->protocol == BCM_SVC_RPOTYPE_BONJOUR ?
+								"BONJOUR" :
+							tlv->protocol == BCM_SVC_RPOTYPE_UPNP ?
+								"UPnP" :
+							tlv->protocol == BCM_SVC_RPOTYPE_WSD ?
+								"WS-Discovery" :
+							tlv->protocol == BCM_SVC_RPOTYPE_VENDOR ?
+								"Vendor specific" : "Unknown");
+						printf("   transaction id  = %u\n",
+							tlv->transaction_id);
+						printf("   status code     = %u\n",
+							tlv->status_code);
+						printf("   length          = %u\n", tlv->length);
+						wl_hexdump(tlv->data, tlv->length);
+
+						tlv = (wl_sd_tlv_t *)((void *)tlv + tlv->length +
+							OFFSETOF(wl_sd_tlv_t, data));
+					}
+				}
+				else {
+					/* fragments */
+				}
+			}
+		}
+	}
+
+	free(data);
+exit1:
+	close(fd);
+exit2:
+	return err;
+}
+#endif /* WLP2PO */
+
+#ifdef WLANQPO
+
+#define ANQPO_EVENTS_BUFFER_SIZE	2048
+
+static int
+wl_anqpo_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_set_t *set;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_set_t, query_data) +
+		(ANQPO_MAX_QUERY_SIZE * sizeof(uint8));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	set = (wl_anqpo_set_t *)buffer;
+	/* parameters not configured by default */
+	set->max_retransmit = -1;
+	set->response_timeout = -1;
+	set->max_comeback_delay = -1;
+	set->max_retries = -1;
+
+	while (*++argv) {
+		if (!stricmp(*argv, "max_retransmit")) {
+			if (*++argv)
+				set->max_retransmit = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing max retransmit\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "response_timeout")) {
+			if (*++argv)
+				set->response_timeout = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing response timeout\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "max_comeback_delay")) {
+			if (*++argv)
+				set->max_comeback_delay = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing max comeback delay\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "max_retries")) {
+			if (*++argv)
+				set->max_retries = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing retries\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "query")) {
+			if (*++argv) {
+				if ((set->query_len = hexstr2hex(*argv)) == 0) {
+					fprintf(stderr, "Invalid ANQP query\n");
+					err = BCME_USAGE_ERROR;
+					goto done;
+				}
+				if (set->query_len > ANQPO_MAX_QUERY_SIZE) {
+					fprintf(stderr, "ANQP query size %d exceeds %d\n",
+						set->query_len, ANQPO_MAX_QUERY_SIZE);
+					err = BCME_USAGE_ERROR;
+					goto done;
+				}
+				memcpy(set->query_data, *argv, set->query_len);
+			}
+			else {
+				fprintf(stderr, "Missing ANQP query\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			err = BCME_USAGE_ERROR;
+			goto done;
+		}
+
+	}
+
+	length = OFFSETOF(wl_anqpo_set_t, query_data) + set->query_len;
+	set->max_retransmit = htod16(set->max_retransmit);
+	set->response_timeout = htod16(set->response_timeout);
+	set->max_comeback_delay = htod16(set->max_comeback_delay);
+	set->max_retries = htod16(set->max_retries);
+	set->query_len = htod16(set->query_len);
+
+	err = wlu_iovar_set(wl, cmd->name, set, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+static int
+wl_anqpo_stop_query(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	return wlu_iovar_set(wl, cmd->name, 0, 0);
+}
+
+static int
+wl_anqpo_start_query(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_peer_list_t *list;
+	wl_anqpo_peer_t *peer;
+	int c;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_peer_list_t, peer) +
+		(ANQPO_MAX_PEER_LIST * sizeof(wl_anqpo_peer_t));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	list = (wl_anqpo_peer_list_t *)buffer;
+	peer = &list->peer[0];
+
+	c = 1;
+	while (argv[c] && argv[c + 1]) {
+		if ((peer->channel = htod16(atoi(argv[c]))) == 0) {
+			fprintf(stderr, "Invalid channel\n");
+			err = BCME_USAGE_ERROR;
+			goto done;
+		}
+		if (!wl_ether_atoe(argv[c + 1], &peer->addr)) {
+			fprintf(stderr, "Invalid address\n");
+			err = BCME_USAGE_ERROR;
+			goto done;
+		}
+		list->count++;
+		c += 2;
+		peer++;
+	}
+
+	length = OFFSETOF(wl_anqpo_peer_list_t, peer) +
+		(list->count * sizeof(wl_anqpo_peer_t));
+	list->count = htod16(list->count);
+
+	err = wlu_iovar_set(wl, cmd->name, list, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+static int
+wl_anqpo_ignore_ssid_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_ignore_ssid_list_t *list;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid) +
+		(ANQPO_MAX_IGNORE_SSID * (sizeof(wl_anqpo_ignore_ssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid)));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	list = (wl_anqpo_ignore_ssid_list_t *)buffer;
+
+	/* get */
+	if (!argv[1]) {
+		int i;
+
+		if ((err = wlu_iovar_get(wl, cmd->name, list, malloc_size)) < 0)
+			goto done;
+		list->count = dtoh16(list->count);
+		for (i = 0; i < list->count; i++) {
+			char ssidbuf[SSID_FMT_BUF_LEN];
+
+			wl_format_ssid(ssidbuf, list->ssid[i].SSID, list->ssid[i].SSID_len);
+			printf("%s\n", ssidbuf);
+		}
+		goto done;
+	}
+
+	/* set */
+	argv++;
+	if (!stricmp(*argv, "clear")) {
+		list->is_clear = TRUE;
+	}
+	else if (!stricmp(*argv, "set")) {
+		list->is_clear = TRUE;
+		while (*++argv) {
+			int len = strlen(*argv);
+			if (list->count > ANQPO_MAX_IGNORE_SSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (len > 32) {
+				fprintf(stderr, "SSID too long\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->ssid[list->count].SSID_len = len;
+			memcpy(list->ssid[list->count].SSID, *argv, len);
+			list->count++;
+		}
+	}
+	else if (!stricmp(*argv, "append")) {
+		while (*++argv) {
+			int len = strlen(*argv);
+			if (list->count > ANQPO_MAX_IGNORE_SSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (len > 32) {
+				fprintf(stderr, "SSID too long\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->ssid[list->count].SSID_len = len;
+			memcpy(list->ssid[list->count].SSID, *argv, len);
+			list->count++;
+		}
+	}
+	else {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	length = OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid) +
+		(list->count * (sizeof(wl_anqpo_ignore_ssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid)));
+	list->count = htod16(list->count);
+
+	err = wlu_iovar_set(wl, cmd->name, list, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+static int
+wl_anqpo_ignore_bssid_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_ignore_bssid_list_t *list;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid) +
+		(ANQPO_MAX_IGNORE_BSSID * (sizeof(wl_anqpo_ignore_bssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid)));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	list = (wl_anqpo_ignore_bssid_list_t *)buffer;
+
+	/* get */
+	if (!argv[1]) {
+		int i;
+
+		if ((err = wlu_iovar_get(wl, cmd->name, list, malloc_size)) < 0)
+			goto done;
+		list->count = dtoh16(list->count);
+		for (i = 0; i < list->count; i++) {
+			printf("%s\n", wl_ether_etoa(&list->bssid[i]));
+		}
+		goto done;
+	}
+
+	/* set */
+	argv++;
+	if (!stricmp(*argv, "clear")) {
+		list->is_clear = TRUE;
+	}
+	else if (!stricmp(*argv, "set")) {
+		list->is_clear = TRUE;
+		while (*++argv) {
+			if (list->count > ANQPO_MAX_IGNORE_BSSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (!wl_ether_atoe(*argv, &list->bssid[list->count])) {
+				fprintf(stderr, "Invalid BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->count++;
+		}
+	}
+	else if (!stricmp(*argv, "append")) {
+		while (*++argv) {
+			if (list->count > ANQPO_MAX_IGNORE_BSSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (!wl_ether_atoe(*argv, &list->bssid[list->count])) {
+				fprintf(stderr, "Invalid BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->count++;
+		}
+	}
+	else {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	length = OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid) +
+		(list->count * (sizeof(wl_anqpo_ignore_bssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid)));
+	list->count = htod16(list->count);
+
+	err = wlu_iovar_set(wl, cmd->name, list, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+static int
+wl_anqpo_results(void *wl, cmd_t *cmd, char **argv)
+{
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth1"};
+	char *data;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(&ifr, 0, sizeof(ifr));
+	if (wl)
+		strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	else
+		strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+	event_inds_mask[WLC_E_GAS_FRAGMENT_RX / 8] |= 1 << (WLC_E_GAS_FRAGMENT_RX % 8);
+	event_inds_mask[WLC_E_GAS_COMPLETE / 8] |= 1 << (WLC_E_GAS_COMPLETE % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		goto exit2;
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit2;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		goto exit1;
+	}
+
+	/* bind the socket first before starting so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit1;
+	}
+
+	data = (char*)malloc(ANQPO_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			ANQPO_EVENTS_BUFFER_SIZE);
+		err = BCME_NOMEM;
+		goto exit1;
+	}
+
+	/* receive result */
+	while (1) {
+		bcm_event_t *bcm_event;
+		int event_type;
+
+		octets = recv(fd, data, ANQPO_EVENTS_BUFFER_SIZE, 0);
+		bcm_event = (bcm_event_t *)data;
+		event_type = ntoh32(bcm_event->event.event_type);
+
+		if (octets >= (int)sizeof(bcm_event_t)) {
+			uint32 status = ntoh32(bcm_event->event.status);
+
+			if (event_type == WLC_E_GAS_FRAGMENT_RX) {
+				wl_event_gas_t *gas_data =
+					(wl_event_gas_t *)&data[sizeof(bcm_event_t)];
+
+				gas_data->channel = dtoh16(gas_data->channel);
+				gas_data->status_code = dtoh16(gas_data->status_code);
+				gas_data->data_len = dtoh16(gas_data->data_len);
+
+				printf("WLC_E_GAS_FRAGMENT_RX: %s\n",
+					status == WLC_E_STATUS_PARTIAL ? "WLC_E_STATUS_PARTIAL" :
+					status == WLC_E_STATUS_SUCCESS ? "WLC_E_STATUS_SUCCESS" :
+					status == WLC_E_STATUS_FAIL ? "WLC_E_STATUS_FAIL" :
+					"unknown");
+				printf("   channel         = %d\n", gas_data->channel);
+				printf("   peer            = %s\n",
+					wl_ether_etoa(&bcm_event->event.addr));
+				printf("   dialog token    = 0x%02x (%d)\n",
+					gas_data->dialog_token, gas_data->dialog_token);
+				printf("   fragment id     = 0x%02x\n", gas_data->fragment_id);
+				printf("   GAS status      = %s\n",
+					gas_data->status_code == DOT11_SC_SUCCESS ? "SUCCESS" :
+					gas_data->status_code == DOT11_SC_FAILURE ? "UNSPECIFIED" :
+					gas_data->status_code == DOT11_SC_ADV_PROTO_NOT_SUPPORTED ?
+						"ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED" :
+					gas_data->status_code == DOT11_SC_NO_OUTSTAND_REQ ?
+						"NO_OUTSTANDING_REQUEST" :
+					gas_data->status_code == DOT11_SC_RSP_NOT_RX_FROM_SERVER ?
+						"RESPONSE_NOT_RECEIVED_FROM_SERVER" :
+					gas_data->status_code == DOT11_SC_TIMEOUT ?
+						"TIMEOUT" :
+					gas_data->status_code == DOT11_SC_QUERY_RSP_TOO_LARGE ?
+						"QUERY_RESPONSE_TOO_LARGE" :
+					gas_data->status_code == DOT11_SC_SERVER_UNREACHABLE ?
+						"SERVER_UNREACHABLE" :
+					gas_data->status_code == DOT11_SC_TRANSMIT_FAILURE ?
+						"TRANSMISSION_FAILURE" : "unknown");
+				printf("   GAS data length = %d\n", gas_data->data_len);
+				if (gas_data->data_len) {
+					wl_hexdump(gas_data->data, gas_data->data_len);
+				}
+			}
+			else if (event_type == WLC_E_GAS_COMPLETE) {
+				printf("WLC_E_GAS_COMPLETE: %s\n",
+					status == WLC_E_STATUS_SUCCESS ? "WLC_E_STATUS_SUCCESS" :
+					"unknown");
+			}
+		}
+	}
+
+	free(data);
+exit1:
+	close(fd);
+exit2:
+	return err;
+}
+#endif /* WLANQPO */
+
+static int
+wl_hs20_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	int ret;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+	int length;
+	int malloc_size;
+	tlv_t *tlv;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1]) {
+		fprintf(stderr, "Too few arguments\n");
+		return -1;
+	}
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv + 1, argv[0], &bsscfg_idx, &consumed)) != 0)
+		return ret;
+	if (consumed)
+		argv = argv + consumed;
+
+	length = atoi(argv[1]);
+
+	if (length < 0 || length > 255) {
+		fprintf(stderr, "Invalid length\n");
+		return -1;
+	}
+	else if (length > 0) {
+		if (!argv[2]) {
+			fprintf(stderr,
+				"Data bytes should be specified for non-zero length\n");
+			return -1;
+		}
+		else {
+			/* Ensure each data byte is 2 characters long */
+			if ((int)strlen(argv[2]) != (length * 2)) {
+				fprintf(stderr, "Please specify all the data bytes for this IE\n");
+				return -1;
+			}
+		}
+	}
+
+	malloc_size = OFFSETOF(tlv_t, data) + length;
+	tlv = malloc(malloc_size);
+	if (tlv == 0) {
+		fprintf(stderr, "Error allocating %d bytes for IE params\n", malloc_size);
+		return -1;
+	}
+	tlv->id = DOT11_MNG_VS_ID;
+	tlv->len = length;
+
+	if (length > 0) {
+		if ((err = get_ie_data((uchar *)argv[2], tlv->data, length))) {
+			fprintf(stderr, "Error parsing data arg\n");
+			free(tlv);
+			return err;
+		}
+	}
+
+	if (bsscfg_idx == -1)
+		err = wlu_var_setbuf(wl, "hs20_ie", tlv, malloc_size);
+	else
+		err = wlu_bssiovar_setbuf(wl, "hs20_ie", bsscfg_idx,
+			tlv, malloc_size, buf, WLC_IOCTL_MAXLEN);
+
+	free(tlv);
+	return (err);
+}
+
+static dbg_msg_t toe_cmpnt[] = {
+	{TOE_TX_CSUM_OL,	"tx_csum_ol"},
+	{TOE_RX_CSUM_OL,	"rx_csum_ol"},
+	{0,			NULL}
+};
+
+static dbg_msg_t arpoe_cmpnt[] = {
+	{ARP_OL_AGENT,		"agent"},
+	{ARP_OL_SNOOP,		"snoop"},
+	{ARP_OL_HOST_AUTO_REPLY, "host_auto_reply"},
+	{ARP_OL_PEER_AUTO_REPLY, "peer_auto_reply"},
+	{0,			NULL}
+};
+
+/*
+ *  Tcpip Offload Component-wise get/set control.
+ */
+static int
+wl_offload_cmpnt(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val, last_val = 0, cmpnt_add = 0, cmpnt_del = 0;
+	char *endptr;
+	dbg_msg_t *dbg_msg = NULL;
+	void *ptr = NULL;
+	int cmpnt;
+
+	if (strcmp(cmd->name, "toe_ol") == 0)
+		dbg_msg = toe_cmpnt;
+	else if (strcmp(cmd->name, "arp_ol") == 0)
+		dbg_msg = arpoe_cmpnt;
+	else {
+		printf("Not a valid command\n");
+		return BCME_BADARG;
+	}
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return (ret);
+	cmpnt = dtoh32(*(int *)ptr);
+
+	if (!*++argv) {
+		printf("0x%x ", cmpnt);
+		for (i = 0; (val = dbg_msg[i].value); i++) {
+			if ((cmpnt & val) && (val != last_val))
+				printf(" %s", dbg_msg[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			cmpnt_del = ~0;	/* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		/* not a plain integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = dbg_msg[i].value); i++)
+				if (stricmp(dbg_msg[i].string, s) == 0)
+					break;
+			if (!val)
+				goto usage;
+		}
+		if (**argv == '-')
+			cmpnt_del |= val;
+		else
+			cmpnt_add |= val;
+		++argv;
+	}
+
+	cmpnt &= ~cmpnt_del;
+	cmpnt |= cmpnt_add;
+
+	cmpnt = htod32(cmpnt);
+	return (wlu_var_setbuf(wl, cmd->name, &cmpnt, sizeof(int)));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+
+	for (i = 0; (val = dbg_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string);
+		else
+			fprintf(stderr, ", %s", dbg_msg[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+
+	return 0;
+}
+
+#if defined(WLNDOE) || defined(WLOFFLD)
+/*
+ * If a host IP address is given, add it to the host-cache,
+ * e.g. "wl nd_hostip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump all the addresses.
+ */
+static int
+wl_hostipv6(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			 memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			 ipa_get++) {
+			/* Print ipv6 Addr */
+			for (i = 0; i < 8; i++) {
+				printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+			}
+			printf("\r\n");
+
+			ip_addr += 8;
+		}
+	} else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, IPV6_ADDR_LEN);
+	}
+	return ret;
+}
+#endif /* defined(WLOFFLD) || defined(WLNDOE) */
+
+#ifdef WLNDOE
+static int
+wl_ndstatus(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	struct nd_ol_stats_t *nd_stats;
+
+	if (!*++argv) {
+	/* Get */
+	void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		nd_stats = (struct nd_ol_stats_t *)ptr;
+
+		printf("host_ip_entries %d\r\n", nd_stats->host_ip_entries);
+		printf("host_ip_overflow %d\r\n", nd_stats->host_ip_overflow);
+		printf("peer_request %d\r\n", nd_stats->peer_request);
+		printf("peer_request_drop %d\r\n", nd_stats->peer_request_drop);
+		printf("peer_reply_drop %d\r\n", nd_stats->peer_reply_drop);
+		printf("peer_service %d\r\n", nd_stats->peer_service);
+	} else {
+		printf("Cannot set nd stats\n");
+	}
+
+	return 0;
+}
+
+/*
+ * If a solicit IP address is given, add it
+ * e.g. "wl nd_solicitip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump all the addresses.
+ */
+static int
+wl_solicitipv6(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			 memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			 ipa_get++) {
+			/* Print ipv6 Addr */
+			for (i = 0; i < 8; i++) {
+				printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+			}
+			printf("\r\n");
+
+			ip_addr += 8;
+		}
+	} else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, IPV6_ADDR_LEN);
+	}
+	return ret;
+}
+
+/*
+ * If a remote IP address is given, add it
+ * e.g. "wl nd_remoteip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump the addresses.
+ */
+static int
+wl_remoteipv6(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			 memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			 ipa_get++) {
+			/* Print ipv6 Addr */
+			for (i = 0; i < 8; i++) {
+				printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+			}
+			printf("\r\n");
+
+			ip_addr += 8;
+		}
+	} else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, IPV6_ADDR_LEN);
+	}
+	return ret;
+}
+#endif /* WLNDOE */
+/*
+ * If a host IP address is given, add it to the host-cache, e.g. "wl arp_hostip 192.168.1.1".
+ * If no address is given, dump all the addresses.
+ */
+static int
+wl_hostip(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ipv4_addr ipa_set, *ipa_get, null_ipa;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		memset(null_ipa.addr, 0, IPV4_ADDR_LEN);
+
+		for (ipa_get = (struct ipv4_addr *)ptr;
+		     memcmp(null_ipa.addr, ipa_get->addr, IPV4_ADDR_LEN) != 0;
+		     ipa_get++)
+			printf("%s\n", wl_iptoa(ipa_get));
+
+		printf("Total %d host addresses\n", (int)(ipa_get - (struct ipv4_addr *)ptr));
+	} else {
+		/* Add */
+		if (!wl_atoip(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, sizeof(IPV4_ADDR_LEN));
+	}
+
+	return ret;
+}
+/*
+ * If a host IP address is given, add it to the host-cache,
+ * e.g. "wl nd_hostip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump all the addresses.
+ */
+static int
+wl_nshostip(void *wl, cmd_t *cmd, char **argv)
+{
+
+	int ret = 0, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			ipa_get++) {
+				/* Print ipv6 Addr */
+				for (i = 0; i < 8; i++)
+					printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+				}
+			printf("\r\n");
+			ip_addr += 8;
+		}
+	else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return -1;
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name,
+		&ipa_set, IPV6_ADDR_LEN);
+		}
+	return ret;
+}
+
+#ifdef WLOFFLD
+static int
+wl_ol_notify_bcn_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	void *ptr = NULL;
+
+#define	VNDR_IE_ID		(221)
+#define OLMSG_BCN_MAX_IE	(222)
+
+	struct beacon_ie_notify_cmd {
+		uint32		id;
+		uint32		enable;
+		struct ipv4_addr vndriemask;
+	} beacon_notification_cmd;
+
+	memset(&beacon_notification_cmd, 0, sizeof(beacon_notification_cmd));
+
+	++argv; /* skip the command iteself */
+
+	if (!*argv) {
+		/* Get Everything */
+		beacon_notification_cmd.id = -1; /* -1 indicates NONE */
+		ret = wlu_var_getbuf(wl, cmd->name, &beacon_notification_cmd,
+			sizeof(beacon_notification_cmd), &ptr);
+	} else {
+		if (stricmp(*argv, "enable") == 0) { /* Enable Global flag */
+			beacon_notification_cmd.id = -1; /* -1 indicates NONE */
+			beacon_notification_cmd.enable = 1;
+			return wlu_var_setbuf(wl, cmd->name, &beacon_notification_cmd,
+				sizeof(beacon_notification_cmd));
+		} else if (stricmp(*argv, "disable") == 0) { /* Disable Global flag */
+			beacon_notification_cmd.id = -1; /* -1 indicates NONE */
+			beacon_notification_cmd.enable = 0;
+			return wlu_var_setbuf(wl, cmd->name, &beacon_notification_cmd,
+				sizeof(beacon_notification_cmd));
+		} else { /* Get/Set Enable/Disable some ID */
+
+		    beacon_notification_cmd.id = (uint8) atoi(*argv);
+
+		    if (beacon_notification_cmd.id == VNDR_IE_ID) {
+			/* Get VNDR OUI */
+			++argv;
+			if (*argv) { /* Get a specific Vendor IE */
+				if (!wl_atoip(*argv, &beacon_notification_cmd.vndriemask)) {
+					return -1;
+				}
+				++argv;
+				/* Get enable/disable flag */
+				if (*argv) { /* Set a specific Vendor ie */
+					if (stricmp(*argv, "enable") == 0)
+						beacon_notification_cmd.enable = 1;
+					else if (stricmp(*argv, "disable") == 0)
+						beacon_notification_cmd.enable = 0;
+					else
+						return -1;
+
+					return wlu_var_setbuf(wl, cmd->name,
+						&beacon_notification_cmd,
+						sizeof(beacon_notification_cmd));
+				} else {
+					ret = wlu_var_getbuf(wl, cmd->name,
+						&beacon_notification_cmd,
+						sizeof(beacon_notification_cmd),
+						&ptr);
+				}
+			} else { /* Get ALL Vendor IE */
+				ret = wlu_var_getbuf(wl, cmd->name,
+					&beacon_notification_cmd,
+					sizeof(beacon_notification_cmd),
+					&ptr);
+			}
+		    } else {
+			if (beacon_notification_cmd.id > OLMSG_BCN_MAX_IE) {
+				return -1;
+			}
+			/* Get enable/disable flag */
+			++argv;
+			if(*argv) { /* Set IE ID */
+				if (stricmp(*argv, "enable") == 0)
+					beacon_notification_cmd.enable = 1;
+				else if (stricmp(*argv, "disable") == 0)
+					beacon_notification_cmd.enable = 0;
+				else
+					return -1;
+				return wlu_var_setbuf(wl, cmd->name,
+					&beacon_notification_cmd,
+					sizeof(beacon_notification_cmd));
+			} else { /* Get IE ID */
+				ret = wlu_var_getbuf(wl, cmd->name,
+					&beacon_notification_cmd,
+					sizeof(beacon_notification_cmd),
+					&ptr);
+			}
+		    }
+		}
+	}
+	if ((ret >= 0) && (ptr != NULL)) {
+		printf("%s\n", (char *)ptr); /* Print Everything */
+	}
+	return ret;
+}
+#endif /* WLOFFLD */
+
+static int
+wl_mcast_ackmac(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	int i, err;
+	wl_rmc_entry_t ackmac_params;
+	wl_rmc_entry_table_t tablelist;
+	void *ptr = NULL;
+	wl_rmc_entry_table_t *reply = NULL;
+	wl_rmc_gbl_table_t *gtbl = NULL;
+	miniopt_t to;
+	struct ether_addr* ea = NULL;
+	bool index_set = FALSE; bool mac_set = FALSE;
+
+	/* muticast mac address - ipv4 & ipv6 resp. */
+	uint8 mc_mac[6]		 = {0x1, 0x0, 0x5e, 0x7f, 0xff, 0xff};
+	uint8 mc_mac_ipv6[6] = {0x33, 0x33, 0x0, 0x0, 0x0, 0x0};
+
+	/* index will tell us what to do */
+
+	if (!*++argv) {
+		/* Get and display all entries in the table */
+		if ((ret = wlu_var_getbuf(wl, cmd->name,
+		             NULL,
+		             0,
+		             &ptr)) < 0) {
+			return ret;
+		}
+		reply = (wl_rmc_entry_table_t *)ptr;
+		printf("\n Local: Active Mask 0x%02x  Transmitter mask 0x%02x ",
+			reply->index, reply->opcode);
+
+		printf("\n Enable\t Multi-cast Group ");
+		printf("\n %d \t\t Ack All \t", (reply->index &  WL_RMC_ACK_MCAST_ALL)?1:0);
+
+		for (i = 0; i < WL_RMC_MAX_TABLE_ENTRY; i++) {
+			printf("\n %d \t %s",
+				(reply->index & (WL_RMC_ACK_MCAST0 << i))?1:0,
+				wl_ether_etoa(&reply->entry[i].addr));
+		}
+
+		gtbl = (wl_rmc_gbl_table_t *)((char*)ptr+sizeof(wl_rmc_entry_table_t));
+
+		printf("\n Global Table: Active Mask 0x%02x ", gtbl->activeMask);
+		printf("\n Multi-cast \t\t Transmitter \t");
+		printf("\n Ack All Entry \t\t %s",
+		        wl_ether_etoa(&gtbl->ackAll.tr_info[0].addr));
+
+		for (i = 0; i <  WL_RMC_MAX_TABLE_ENTRY; i++) {
+			printf("\n %s \t", wl_ether_etoa(&gtbl->mc_entry[i].mcaddr));
+
+			printf("%s \t",
+			       wl_ether_etoa(&gtbl->mc_entry[i].tr_info[0].addr));
+
+		}
+		printf("\n");
+		return 0;
+	}
+
+	miniopt_init(&to, cmd->name, NULL, FALSE);
+
+	while ((err = miniopt(&to, argv)) != -1) {
+		if (err == 1) {
+			return BCME_USAGE_ERROR;
+		}
+		argv += to.consumed;
+		/* Index for muticast address in RMC table */
+		if (to.opt == 'i') {
+			if (!to.good_int || (to.val >=  WL_RMC_MAX_TABLE_ENTRY && to.val)) {
+				fprintf(stderr, "%s: Invalid mode value\n", cmd->name);
+				err = -1;
+				goto exit;
+			}
+			tablelist.index = to.val;
+			index_set = TRUE;
+		}
+
+		/* Add multicast address with index "i" to RMC table */
+		if (to.opt == 't') {
+			if (!wl_ether_atoe(to.valstr, &ackmac_params.addr)) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as a MAC address\n",
+					cmd->name, to.valstr);
+				err = -1;
+				goto exit;
+			}
+			mac_set = TRUE;
+		}
+	}
+
+	if (index_set) {
+		if (!mac_set) {
+			/* if table index is -1 & no mac entry, it is for ACKALL */
+			if (tablelist.index == 255) {
+				/* enable all  multi-cast */
+				tablelist.index = 0;
+				tablelist.opcode = RELMCAST_ENTRY_OP_ACK_ALL;
+				tablelist.entry[tablelist.index].flag = RELMCAST_ENTRY_OP_ACK_ALL;
+			}
+			/* if index is not -1 and no mac entry,
+			   it is for removing entry at the index
+			*/
+			else if (tablelist.index < WL_RMC_MAX_TABLE_ENTRY) {
+				/* remove multi-cast entry by setting flag to deleted  */
+				tablelist.opcode = RELMCAST_ENTRY_OP_DELETE;
+				tablelist.entry[tablelist.index].flag = RELMCAST_ENTRY_OP_DELETE;
+			}
+			else {
+				printf("%s Invalid index  %d\n", cmd->name, tablelist.index);
+				return BCME_USAGE_ERROR;
+			}
+
+			return wlu_var_setbuf(wl, cmd->name,
+			           &tablelist,
+			           sizeof(wl_rmc_entry_table_t)+sizeof(wl_rmc_gbl_table_t));
+		} else {
+			/* mac is also set */
+			memcpy(&tablelist.entry[tablelist.index].addr, &ackmac_params.addr,
+				sizeof(struct ether_addr));
+
+			/* insert to list */
+			ea = &tablelist.entry[tablelist.index].addr;
+			tablelist.entry[tablelist.index].flag = RELMCAST_ENTRY_OP_ENABLE;
+
+			/* for ipv4, initial three bytes in mc address are standard &
+			    2 bytes for ipv6
+			 */
+			if ((!memcmp(ea, mc_mac, 3) && !(ea->octet[3] & 0x80)) ||
+			     !memcmp(ea, mc_mac_ipv6, 2)) {
+
+				fprintf(stderr,
+					    "\nAdding multi-cast mac %s\n", wl_ether_etoa(ea));
+
+				return wlu_var_setbuf(wl, cmd->name,
+				         &tablelist,
+				         sizeof(wl_rmc_entry_table_t)+sizeof(wl_rmc_gbl_table_t));
+
+			} else {
+
+				fprintf(stderr, "multicast mac started with"
+					"01:00:5e:0... or 33:33:...\n");
+				ret = BCME_BADARG;
+
+			}
+		}
+	}
+exit:
+	return ret;
+}
+
+static int
+wl_mcast_ackreq(void *wl, cmd_t *cmd, char **argv)
+{
+	const char* fn_name = "wl_mcast_ackreq";
+	int err, i = 0;
+	uint argc;
+	char *endptr = NULL;
+	void *ptr = NULL;
+	uint8 *reply_mode = NULL;
+	uint8 params_mode, old_mode;
+	wl_relmcast_status_t status;
+
+	memset(&params_mode, 0, sizeof(uint8));
+	/* toss the command name */
+	argv++;
+
+	if ((err = wlu_var_getbuf_sm(wl, cmd->name, &params_mode,
+		sizeof(uint8), &ptr))  != BCME_OK) {
+		fprintf(stderr, "Error getting variable %s\n", argv[0]);
+		return err;
+	}
+
+	reply_mode = (uint8 *)ptr;
+	old_mode = *reply_mode;
+
+	if (!*argv) {
+		fprintf(stderr, "%s mode %d \n", fn_name, *reply_mode);
+		return err;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: mode disable, enable  or initiator enabled */
+	if (argc < 1)
+		return -1;
+
+	/* get the new ackreq mode */
+	params_mode = strtol(argv[0], &endptr, 0);
+
+	if ((*endptr != '\0') || (params_mode > WL_RMC_MODE_INITIATOR))
+		return -1;
+
+	if (argc > 1) {
+		fprintf(stderr,
+			"%s: could not parse extra argument %s:\n",
+			fn_name, argv[1]);
+
+		err = -1;
+		goto exit;
+	}
+
+	if ((err = wlu_var_setbuf(wl, cmd->name, &params_mode, sizeof(uint8))) != BCME_OK) {
+		goto out_of_here;
+	}
+
+	if (params_mode == WL_RMC_MODE_INITIATOR ||
+	   ((params_mode == WL_RMC_MODE_RECEIVER) &&
+	   (old_mode == WL_RMC_MODE_INITIATOR))) {
+
+		for (i = 0; i <= 10; i++) {
+			/* check status of the RCV bit to make sure ack are receive */
+			if ((err = wlu_iovar_get(wl, "rmc_status",
+			                    (void *) &status,
+			                    (sizeof(wl_relmcast_status_t)))) < 0) {
+				return (err);
+			}
+
+			if (status.err != (uint16)BCME_NOTREADY) {
+				if (status.err == (uint16)BCME_RXFAIL) {
+					fprintf(stderr, "%s: error in setting mode: no ack receive"
+					        "%d tx code %d \n",
+					         fn_name,  params_mode, status.err);
+
+					err = -1;
+				} else {
+					err = 0;
+				}
+				goto out_of_here;
+			}
+
+			/* Allow ample time (by staying in loop) to get ACK
+			   for previous TX frame
+			*/
+			{
+				volatile uint16 busycnt = -1;
+				while (--busycnt)
+					;
+				busycnt = -1;
+			}
+		} /* for loop */
+	}
+out_of_here:
+	if ((err < 0) || (i > 10))
+		fprintf(stderr, "%s: Error setting %d err %d \n", fn_name, params_mode, err);
+	else
+		fprintf(stderr, "%s: setting %d err %d \n", fn_name, params_mode, err);
+exit:
+	return 0;
+}
+
+
+static int
+wl_mcast_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, i;
+	wl_relmcast_status_t status;
+
+	if (!*++argv) {
+		/* Get */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &status,
+			(sizeof(wl_relmcast_status_t)))) < 0)
+			return (err);
+
+		if (status.ver != WL_RMC_VER) {
+			printf("Wrong Version %d %d\n", WL_RMC_VER, status.ver);
+		} else if (status.num == 0) {
+			printf("No clients associated\n");
+		} else {
+			for (i = 0; i < status.num; i++)
+			{
+				printf("%s\t%d\t%c%c%c\n", wl_ether_etoa(&status.clients[i].addr),
+					status.clients[i].rssi,
+					((status.clients[i].flag & WL_RMC_FLAG_ACTIVEACKER) ?
+					'A' : ' '),
+					((status.clients[i].flag & WL_RMC_FLAG_INBLACKLIST) ?
+					'B' : ' '),
+					((status.clients[i].flag & WL_RMC_FLAG_RELMCAST) ?
+					'R' : ' '));
+			}
+
+			printf("Notification Frame TimePeriod: %d ms\n", status.actf_time);
+		}
+	} else {
+		printf("Cannot set reliable multicast status\n");
+	}
+
+	return 0;
+}
+
+static int
+wl_mcast_actf_time(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("Action Frame tx time period: %dms\n", val);
+
+	} else {
+
+		val = (uint16)strtol(*argv, NULL, 10); /* 10 is for base 10 (decimal) */
+
+		if (val >= WL_RMC_ACTF_TIME_MIN &&
+			val <= WL_RMC_ACTF_TIME_MAX) {
+
+			error = wlu_iovar_setint(wl, name, val);
+
+		} else {
+
+			printf("\"Out of range\": valid range %dms - %dms\n",
+			                               WL_RMC_ACTF_TIME_MIN,
+			                               WL_RMC_ACTF_TIME_MAX);
+		}
+	}
+	return error;
+}
+
+static int
+wl_mcast_ar_timeout(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("Active Receiver time out: %dms\n", val);
+
+	} else {
+		val = (uint16)strtol(*argv, NULL, 10);
+		if (val >= WL_RMC_ARTMO_MIN &&
+			val <= WL_RMC_ARTMO_MAX)
+			error = wlu_iovar_setint(wl, name, val);
+		else
+			printf("\"Out of range\": valid range %dms - %dms\n",
+			WL_RMC_ARTMO_MIN,
+			WL_RMC_ARTMO_MAX);
+	}
+	return error;
+}
+
+static int
+wl_mcast_rssi_thresh(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("rmc rssi: %d\n", val);
+
+	} else {
+		val = (int8)strtol(*argv, NULL, 10);
+		error = wlu_iovar_setint(wl, name, val);
+	}
+
+	return error;
+}
+
+static int
+wl_mcast_stats(void *wl, cmd_t *cmd, char **argv)
+{
+#define	PRCNT(name)	pbuf += sprintf(pbuf, "%s %u ", #name, dtoh16(cnts_v.name))
+#define	PRCNT32(name)	pbuf += sprintf(pbuf, "%s %u ", #name, dtoh32(cnts_v.name))
+	wl_rmc_cnts_t *cnts = NULL;
+	wl_rmc_cnts_t cnts_v;
+	int err = BCME_OK;
+	uint8 argval, argc;
+	char *pbuf = buf;
+	char *endptr = NULL;
+	void *ptr = NULL;
+
+	if (!*++argv) {
+		/* no arg - get and display all values */
+
+		if ((err = wlu_var_getbuf (wl, cmd->name, &cnts_v, sizeof(wl_rmc_cnts_t),  &ptr)))
+			return (err);
+
+		cnts = (wl_rmc_cnts_t*)ptr;
+
+		memcpy((wl_rmc_cnts_t*)&cnts_v, cnts, sizeof(wl_rmc_cnts_t));
+		cnts_v.version = dtoh16(cnts->version);
+		cnts_v.length = dtoh16(cnts->length);
+
+		if (cnts_v.version != WL_RMC_CNT_VERSION) {
+			printf("\tIncorrect version of counters struct: expected %d; got %d\n",
+			        WL_RMC_CNT_VERSION, cnts->version);
+
+			return -1;
+		}
+
+		PRCNT(dupcnt); PRCNT(ackreq_err); PRCNT(af_tx_err); PRNL();
+		PRCNT(null_tx_err); PRCNT(af_unicast_tx_err); PRCNT(mc_no_amt_slot); PRNL();
+		PRCNT(mc_no_glb_slot); PRCNT(mc_not_mirrored); PRCNT(mc_existing_tr); PRNL();
+		PRCNT(mc_exist_in_amt); PRCNT(mc_not_exist_in_gbl); PRCNT(mc_utilized); PRNL();
+		PRCNT(mc_taken_other_tr); PRCNT32(rmc_rx_frames_mac); PRCNT32(rmc_tx_frames_mac);
+		PRNL(); PRCNT32(mc_ar_role_selected); PRCNT32(mc_ar_role_deleted);
+		PRCNT32(mc_noacktimer_expired); PRNL(); PRCNT32(mc_null_ar_cnt); PRNL();
+		fputs(buf, stdout);
+
+	} else {
+
+			/* arg count */
+			for (argc = 0; argv[argc]; argc++)
+				;
+			argval = strtol(argv[0], &endptr, 0);
+			if (argval == 255) {
+			/* arg is -1, clear all the values */
+				fprintf(stderr, "clearing rmc counters\n");
+				err = wlu_var_setbuf(wl, cmd->name, &cnts_v, sizeof(wl_rmc_cnts_t));
+
+			} else {
+				fprintf(stderr, "Invalid arg, only -1"
+					"is allowed to clear counters\n");
+				err = BCME_BADARG;
+			}
+	}
+	return err;
+}
+
+static int
+wl_mcast_rssi_delta(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("rmc rssi delta: %d\n", val);
+
+	} else {
+		val = (uint16)strtol(*argv, NULL, 10);
+		if (val >= 0) /* rssi delta value should be a whole number */
+			error = wlu_iovar_setint(wl, name, val);
+		else
+			printf("\"Out of range\": rmc rssi delta should be >=0\n");
+	}
+	return error;
+}
+
+static int
+wl_mcast_vsie(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	void *ptr = NULL;
+	wl_rmc_vsie_t *reply = NULL;
+	wl_rmc_vsie_t vsie;
+	char *parse = NULL;
+	char tmp[4];
+	int idx, cnt;
+
+	if (!*++argv) {
+
+		/* Get and display all entries in the table */
+		if ((ret = wlu_var_getbuf(wl, cmd->name,
+		             NULL,
+		             0,
+		             &ptr)) < 0) {
+			return ret;
+		}
+
+		reply = (wl_rmc_vsie_t*)ptr;
+
+		printf("0x%x%x%x 0x%x", reply->oui[0], reply->oui[1],
+			reply->oui[2], reply->payload);
+
+	} else {
+
+		parse = *argv++;
+
+		/* remove "0x" from the input string which is in hex */
+		if (strlen(parse)/2 > DOT11_OUI_LEN) {
+			if (!strncmp("0x", parse, strlen("0x")) ||
+			    !strncmp("0X", parse, strlen("0X"))) {
+				parse += strlen("0x");
+			}
+		}
+
+		/* if OUI string is not 6 characters, simply reject */
+		if (strlen(parse) != DOT11_OUI_LEN * 2)
+			return BCME_ERROR;
+
+		/* parse oui string */
+		for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
+			for (cnt = 0; cnt < 2; cnt++) {
+				tmp[cnt] = *parse++;
+			}
+			tmp[cnt] = '\0';
+			vsie.oui[idx] = (uint8)(strtoul(tmp, NULL, 16));
+		}
+
+		/* second argument is missing!! */
+		if (!*argv) {
+			return BCME_ERROR;
+		}
+
+		vsie.payload = (uint16)(strtoul(*argv, NULL, 16));
+		ret = wlu_var_setbuf(wl, cmd->name, &vsie, sizeof(vsie));
+	}
+
+	return ret;
+}
+
+static int
+wl_arp_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct arp_ol_stats_t *arpstats;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+		arpstats = (struct arp_ol_stats_t *)ptr;
+		printf("host_ip_entries = %d\n", dtoh32(arpstats->host_ip_entries));
+		printf("host_ip_overflow = %d\n", dtoh32(arpstats->host_ip_overflow));
+		printf("arp_table_entries = %d\n", dtoh32(arpstats->arp_table_entries));
+		printf("arp_table_overflow = %d\n", dtoh32(arpstats->arp_table_overflow));
+		printf("host_request = %d\n", dtoh32(arpstats->host_request));
+		printf("host_reply = %d\n", dtoh32(arpstats->host_reply));
+		printf("host_service = %d\n", dtoh32(arpstats->host_service));
+		printf("peer_request = %d\n", dtoh32(arpstats->peer_request));
+		printf("peer_request_drop = %d\n", dtoh32(arpstats->peer_request_drop));
+		printf("peer_reply = %d\n", dtoh32(arpstats->peer_reply));
+		printf("peer_reply_drop = %d\n", dtoh32(arpstats->peer_reply_drop));
+		printf("peer_service = %d\n", dtoh32(arpstats->peer_service));
+		printf("host_ip_entries = %d\n", dtoh32(arpstats->host_ip_entries));
+	} else
+		printf("Cannot set arp stats, use 'wl arp_stats_clear' to clear the counters\n");
+
+	return 0;
+}
+
+static int
+wl_toe_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct toe_ol_stats_t *toestats;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+		toestats = (struct toe_ol_stats_t *)ptr;
+		printf("tx_summed = %d\n", dtoh32(toestats->tx_summed));
+		printf("tx_iph_fill = %d\n", dtoh32(toestats->tx_iph_fill));
+		printf("tx_tcp_fill = %d\n", dtoh32(toestats->tx_tcp_fill));
+		printf("tx_udp_fill = %d\n", dtoh32(toestats->tx_udp_fill));
+		printf("tx_icmp_fill = %d\n", dtoh32(toestats->tx_icmp_fill));
+		printf("rx_iph_good = %d\n", dtoh32(toestats->rx_iph_good));
+		printf("rx_iph_bad = %d\n", dtoh32(toestats->rx_iph_bad));
+		printf("rx_tcp_good = %d\n", dtoh32(toestats->rx_tcp_good));
+		printf("rx_tcp_bad = %d\n", dtoh32(toestats->rx_tcp_bad));
+		printf("rx_udp_good = %d\n", dtoh32(toestats->rx_udp_good));
+		printf("rx_udp_bad = %d\n", dtoh32(toestats->rx_udp_bad));
+		printf("rx_icmp_good = %d\n", dtoh32(toestats->rx_icmp_good));
+		printf("rx_icmp_bad = %d\n", dtoh32(toestats->rx_icmp_bad));
+		printf("tx_tcp_errinj = %d\n", dtoh32(toestats->tx_tcp_errinj));
+		printf("tx_udp_errinj = %d\n", dtoh32(toestats->tx_udp_errinj));
+		printf("tx_icmp_errinj = %d\n", dtoh32(toestats->tx_icmp_errinj));
+		printf("rx_tcp_errinj = %d\n", dtoh32(toestats->rx_tcp_errinj));
+		printf("rx_udp_errinj = %d\n", dtoh32(toestats->rx_udp_errinj));
+		printf("rx_icmp_errinj = %d\n", dtoh32(toestats->rx_icmp_errinj));
+	} else
+		printf("Cannot set toe stats, use 'wl toe_stats_clear' to clear the counters\n");
+
+	return 0;
+}
+
+static void
+wl_rate_histo_print(wl_mac_ratehisto_res_t *rate_histo_res)
+{
+	uint i, nss;
+
+	printf("Rates\n");
+	for (i = 0; i < (DOT11_RATE_MAX + 1); i++) {
+		if (rate_histo_res->rate[i]) {
+			if (DIV_REM(i, 2))
+				printf("%.2d\t%d.%d Mbit/s\n",
+					rate_histo_res->rate[i], DIV_QUO(i, 2), DIV_REM(i, 2)/10);
+			else
+				printf("%.2d\t%d Mbit/s\n",
+					rate_histo_res->rate[i], DIV_QUO(i, 2));
+		}
+	}
+
+	printf("MCS indexes:\n");
+	for (i = 0; i < (WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX); i++) {
+		if (rate_histo_res->mcs[i]) {
+			printf("%d\tMCS %d\n", rate_histo_res->mcs[i], i);
+		}
+	}
+
+	printf("VHT indexes:\n");
+	for (nss = 0; nss < WL_TX_CHAINS_MAX; nss++) {
+		for (i = 0; i < WL_RATESET_SZ_VHT_MCS; i++) {
+			if (rate_histo_res->vht[i][nss]) {
+				printf("%d\tVHT %d Nss %d\n", rate_histo_res->vht[i][nss], i,
+					nss + 1);
+			}
+		}
+	}
+
+	return;
+}
+
+static int
+wl_rate_histo(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err;
+	wl_mac_ratehisto_res_t *rate_histo_res;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+
+	rate_histo_res = (wl_mac_ratehisto_res_t *)ptr;
+
+	wl_rate_histo_print(rate_histo_res);
+
+	return 0;
+}
+
+static int
+wl_mac_rate_histo(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr ea;
+	int buflen, err;
+	wl_mac_ratehisto_cmd_t *rate_histo_cmd;
+	wl_mac_ratehisto_res_t *rate_histo_res;
+
+	if (!*++argv || !wl_ether_atoe(*argv, &ea))
+		return BCME_USAGE_ERROR;
+
+	strcpy(buf, "mac_rate_histo");
+	buflen = strlen(buf) + 1;
+	rate_histo_cmd = (wl_mac_ratehisto_cmd_t *)(buf + buflen);
+	memcpy((char*)&rate_histo_cmd->ea, (char*)&ea, ETHER_ADDR_LEN);
+
+	if (*++argv)
+	{
+		/* The access category is obtained and checked for validity */
+		rate_histo_cmd->ac_cat = (uint8)strtol(*argv, NULL, 0);
+		if (!(rate_histo_cmd->ac_cat == 0x10 || rate_histo_cmd->ac_cat == 0x4)) {
+			printf("Only Access Category 0x10 and 0x4 is supported\n");
+			return BCME_BADARG;
+		}
+
+		if (*++argv) {
+			/* The number of pkts to avg is obtained and checked for valid range */
+			rate_histo_cmd->num_pkts = (uint8)strtol(*argv, NULL, 10);
+		} else {
+			/* Set default value as maximum of all access categories
+			 * so that it is set to the max value below
+			 */
+			rate_histo_cmd->num_pkts = 64;
+		}
+
+		if (rate_histo_cmd->ac_cat == 0x10 && rate_histo_cmd->num_pkts > 64) {
+			rate_histo_cmd->num_pkts = 64;
+		} else if (rate_histo_cmd->ac_cat == 0x4 && rate_histo_cmd->num_pkts > 32) {
+			rate_histo_cmd->num_pkts = 32;
+		}
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	rate_histo_res = (wl_mac_ratehisto_res_t *)buf;
+
+	wl_rate_histo_print(rate_histo_res);
+
+	printf("First TSF Timestamp: %08x%08x\n", rate_histo_res->tsf_timer[0][1],
+		rate_histo_res->tsf_timer[0][0]);
+	printf("Last TSF Timestamp : %08x%08x\n", rate_histo_res->tsf_timer[1][1],
+		rate_histo_res->tsf_timer[1][0]);
+
+	return 0;
+}
+
+static int
+wl_pkteng_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkteng_stats_t *stats;
+	void *ptr = NULL;
+	int err;
+	uint16 *pktstats;
+	int i, j;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+
+	stats = ptr;
+	printf("Lost frame count %d\n", dtoh32(stats->lostfrmcnt));
+	printf("RSSI %d\n", dtoh32(stats->rssi));
+	printf("Signal to noise ratio %d\n", dtoh32(stats->snr));
+	printf("rx1mbps %d rx2mbps %d rx5mbps5 %d\n"
+		"rx6mbps %d rx9mbps %d, rx11mbps %d\n"
+		"rx12mbps %d rx18mbps %d rx24mbps %d\n"
+		"rx36mbps %d rx48mbps %d rx54mbps %d\n",
+		stats->rxpktcnt[3], stats->rxpktcnt[1], stats->rxpktcnt[2],
+		stats->rxpktcnt[7], stats->rxpktcnt[11], stats->rxpktcnt[0],
+		stats->rxpktcnt[6], stats->rxpktcnt[10], stats->rxpktcnt[5],
+		stats->rxpktcnt[9], stats->rxpktcnt[4], stats->rxpktcnt[8]);
+	pktstats = &stats->rxpktcnt[NUM_80211b_RATES+NUM_80211ag_RATES];
+	for (i = 0; i < NUM_80211n_RATES/4; i++) {
+		for (j = 0; j < 4; j++) {
+			printf("rxmcs%d %d ", j+4*i, pktstats[j+4*i]);
+		}
+		printf("\n");
+	}
+	printf("rxmcsother %d\n", stats->rxpktcnt[NUM_80211_RATES]);
+	return 0;
+}
+
+
+#define LPPHY_PAPD_EPS_TBL_SIZE 64
+static int
+wl_phy_papdepstbl(void *wl, cmd_t *cmd, char **argv)
+{
+	int32 eps_real, eps_imag;
+	int i;
+	uint32 eps_tbl[LPPHY_PAPD_EPS_TBL_SIZE];
+	int err;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_iovar_get(wl, cmd->name, &eps_tbl, sizeof(eps_tbl))) < 0)
+		return err;
+
+	for (i = 0; i < LPPHY_PAPD_EPS_TBL_SIZE; i++) {
+		if ((eps_real = (int32)(eps_tbl[i] >> 12)) > 0x7ff)
+				eps_real -= 0x1000; /* Sign extend */
+		if ((eps_imag = (int32)(eps_tbl[i] & 0xfff)) > 0x7ff)
+				eps_imag -= 0x1000; /* Sign extend */
+		printf("%d %d\n", eps_real, eps_imag);
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_txiqcc(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err;
+	int32 iqccValues[4];
+	int32 value;
+	char *endptr;
+	int32 a, b, a1, b1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return err;
+
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_N) {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, iqccValues, 2*sizeof(int32))) < 0)
+				return err;
+			a = (int16)iqccValues[0];
+			b = (int16)iqccValues[1];
+			/* sign extend a, b from 10 bit signed value to 32 bit signed value */
+			a = ((a << 22) >> 22);
+			b = ((b << 22) >> 22);
+			printf("%d  %d\n", a, b);
+		}
+		else
+		{
+			for (i = 0; i < 2; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if (value > 511 || value < -512) {
+					return BCME_BADARG;
+				}
+				iqccValues[i] = value;
+			}
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, iqccValues, 2*sizeof(int32))) < 0)
+			return err;
+		}
+	} else {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, iqccValues, 4*sizeof(int32))) < 0)
+				return err;
+			a = (int16)iqccValues[0];
+			b = (int16)iqccValues[1];
+			a1 = (int16)iqccValues[2];
+			b1 = (int16)iqccValues[3];
+			/* sign extend a, b from 10 bit signed value to 32 bit signed value */
+			a = ((a << 22) >> 22);
+			b = ((b << 22) >> 22);
+			a1 = ((a1 << 22) >> 22);
+			b1 = ((b1 << 22) >> 22);
+			printf("%d  %d  %d  %d\n", a, b, a1, b1);
+		}
+		else
+		{
+			for (i = 0; i < 4; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if (value > 511 || value < -512) {
+					return BCME_BADARG;
+				}
+				iqccValues[i] = value;
+			}
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, iqccValues, 4*sizeof(int32))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_txlocc(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err;
+	int8 loccValues[12];
+	int32 value;
+	char *endptr;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return err;
+
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_N) {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, loccValues,
+				sizeof(loccValues))) < 0)
+				return err;
+
+			/* sign extend the loccValues */
+			loccValues[2] = (loccValues[2] << 3) >> 3;
+			loccValues[3] = (loccValues[3] << 3) >> 3;
+			loccValues[4] = (loccValues[4] << 3) >> 3;
+			loccValues[5] = (loccValues[5] << 3) >> 3;
+
+			printf("%d  %d  %d  %d  %d  %d\n", loccValues[0],
+				loccValues[1], loccValues[2], loccValues[3],
+				loccValues[4], loccValues[5]);
+		}
+		else
+		{
+			for (i = 0; i < 6; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if ((i >= 2) && (value > 15 || value < -15)) {
+					return BCME_BADARG;
+				}
+				loccValues[i] = (int8)value;
+			}
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, loccValues, 6*sizeof(int8))) < 0)
+				return err;
+		}
+	} else {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, loccValues,
+				sizeof(loccValues))) < 0)
+				return err;
+
+			/* sign extend the loccValues */
+			loccValues[2] = (loccValues[2] << 3) >> 3;
+			loccValues[3] = (loccValues[3] << 3) >> 3;
+			loccValues[4] = (loccValues[4] << 3) >> 3;
+			loccValues[5] = (loccValues[5] << 3) >> 3;
+			loccValues[8] = (loccValues[8] << 3) >> 3;
+			loccValues[9] = (loccValues[9] << 3) >> 3;
+			loccValues[10] = (loccValues[10] << 3) >> 3;
+			loccValues[11] = (loccValues[11] << 3) >> 3;
+
+			printf("%d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d\n", loccValues[0],
+				loccValues[1], loccValues[2], loccValues[3], loccValues[4],
+				loccValues[5], loccValues[6], loccValues[7], loccValues[8],
+				loccValues[9], loccValues[10], loccValues[11]);
+		}
+		else
+		{
+			for (i = 0; i < 12; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if (((i < 2) && (value > 63 || value < -64)) ||
+					((i >= 2) && (value > 15 || value < -15))) {
+					return BCME_BADARG;
+				}
+				loccValues[i] = (int8)value;
+			}
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, loccValues, 12*sizeof(int8))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_rssi_cal_freq_grp_2g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	uint8 nvramValues[14];
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+
+	if (!*++argv) {
+		/* Reading the NVRAM variable */
+		if ((err = wlu_iovar_get(wl, cmd->name, nvramValues, sizeof(nvramValues))) < 0)
+			return err;
+
+		N = 14; /* 14 corresponds to number of channels in 2g */
+
+		for (i = 0; i < N-2; i++) {
+			printf("0x%x%x,", nvramValues[i], nvramValues[i+1]);
+			i++;
+		}
+		printf("0x%x%x\n", nvramValues[i], nvramValues[i+1]);
+	} else {
+		/* Writing to NVRAM variable */
+
+		char *splt;
+		int8 tmp;
+		splt = strtok(*argv, ",");
+
+		/* N = 14 corresponds to number of channels in 2g */
+		/* N = N /2 to package 2 channel's nibbles into 1 byte */
+		N = 7;
+
+		i = 0;
+		while (splt != NULL) {
+			/* Splitting the input based on charecter ','
+			 * Further each byte is divided into 2 nibbles
+			 * and saved into 2 elements of array.
+			 */
+			tmp = strtol(splt, &endptr, 0);
+			nvramValues[i] = (tmp >> 4) & 0xf;
+			i++;
+			nvramValues[i] = tmp & 0xf;
+			splt = strtok(NULL, ",");
+			i++;
+		}
+		if (i != 14) {
+			printf("Insufficient arguments \n");
+			return BCME_BADARG;
+		}
+		if ((err = wlu_var_setbuf(wl, cmd->name, nvramValues, N*2*sizeof(int8))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rssi_gain_delta_2g_sub(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[28];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		N = 18; /* 9 entries per core, 4350 - 18 MAX entries; 4345 9 MAX entries */
+		for (i = 0; i < N; i++) {
+			if (i%9 == 0 && i > 0) {
+				printf("\n");
+				if (deltaValues[i] == -1) break;
+			}
+
+				printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		int index = 0;
+		while (argv[argc])
+			argc++;
+
+		/* ACPHY : 8/9 entries for a core; core 0 delta's can be
+		 * given with or with out core_num as first element
+		 */
+		N = argc;
+
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			if (argc == 9) {
+				/* If number of arguments is 9, then core
+				 * number has been provided.
+				 * And 8 elements related to 2
+				 * (BWs - 20 n 40) and 4 gain settings
+				 * (elna_on, elna_off, rout_1, rout_2) are
+				 * provided. So, 2 * 4 = 8 + 1 core_num = 9
+				 */
+				deltaValues[i] = (int8)value;
+			} else {
+				/* If the number of elements is not eq to 9,
+				 * then, core number was not provided.
+				 * So, if only 8 elements are provided, only
+				 * core 0's info is given. So, for i = 0,
+				 * deltaValues element is 0 (core_num). If 16
+				 * elements are provided, then core 0 and 1's info is
+				 * provided. So, i =0 element has core_num = 0,
+				 * then, next 8 elements are core 0's
+				 * deltas. For i = 8, core 1's core_num = 1
+				 * is inserted into deltaValues array.
+				 * Similarly for third core data.
+				 */
+				if (i == 0) {
+					deltaValues[index] = 0;
+					index++;
+				} else if (i == 8) {
+					deltaValues[index] = 1;
+					index++;
+				} else if (i == 16) {
+					deltaValues[index] = 2;
+					index++;
+				}
+				deltaValues[index] = (int8)value;
+				index++;
+			}
+		}
+		/* If argc == 8, then only 1 core's info was given,
+		 * so, setbuf() is called once.
+		 * If argc == 16 then core 0 and 1's info was given.
+		 * So, setbuf() is called twice.
+		 * If argc == 24 then core 0, 1 and 2's info was given.
+		 * So, setbuf() is called thrice.
+		 */
+		if ((err = wlu_var_setbuf(wl, cmd->name,
+		     deltaValues, 9*sizeof(int8))) < 0)
+			return err;
+		if (argc >= 16) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			      deltaValues + 9, 9*sizeof(int8))) < 0)
+				return err;
+		}
+		if (argc == 24) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			     deltaValues + 18, 9*sizeof(int8))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rssi_gain_delta_2g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[18];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = 15; /* ACPHY: 3 cores max x 5 entries */
+		for (i = 0; i < N; i++) {
+			if ((phytype == WLC_PHY_TYPE_AC) && (i%5 == 0)) {
+				if (i > 0) printf("\n");
+				if (deltaValues[i] == -1) break;
+			}
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		int index = 0;
+		while (argv[argc])
+			argc++;
+		if (phytype == WLC_PHY_TYPE_AC) {
+			/* N = 5;  ACPHY : 5 entries for a core */
+			N = argc;
+		}
+
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			if (argc == 5) {
+				/* If number of arguments is 5, then core number has been provided.
+				 * And 8 elements related to 2 (BWs - 20 n 40) and 2 gain settings
+				 * (elna_on, elna_off) are provided. So, 2 * 2 = 4 + 1 core_num = 5
+				 */
+				deltaValues[i] = (int8)value;
+			} else {
+				/* If the number of elements is not eq to 5,
+				 * then, core number was not provided.
+				 * So, if only 4 elements are provided, only
+				 * core 0's info is given. So, for i = 0,
+				 * deltaValues element is 0 (core_num). If 8
+				 * elements are provided, then core 0 and 1's info is
+				 * provided. So, i =0 element has core_num = 0,
+				 * then, next 4 elements are core 0's
+				 * deltas. For i = 4, core 1's core_num = 1
+				 * is inserted into deltaValues array.
+				 * Similarly for third core data.
+				 */
+				if (i == 0) {
+					deltaValues[index] = 0;
+					index++;
+				} else if (i == 4) {
+					deltaValues[index] = 1;
+					index++;
+				} else if (i == 8) {
+					deltaValues[index] = 2;
+					index++;
+				}
+				deltaValues[index] = (int8)value;
+				index++;
+			}
+
+		}
+		/* If argc == 4, then only 1 core's info was given,
+		 * so, setbuf() is called once.
+		 * If argc == 8 then core 0 and 1's info was given.
+		 * So, setbuf() is called twice.
+		 * If argc == 12 then core 0, 1 and 2's info was given.
+		 * So, setbuf() is called thrice.
+		 */
+		if ((err = wlu_var_setbuf(wl, cmd->name,
+		     deltaValues, 5*sizeof(int8))) < 0)
+			return err;
+		if (argc >= 8) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			     deltaValues + 5, 5*sizeof(int8))) < 0)
+				return err;
+		}
+		if (argc == 12) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			     deltaValues + 10, 5*sizeof(int8))) < 0)
+				return err;
+		}
+
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rssi_gain_delta_5g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[28];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0, n_per_core, n_per_core_p1;
+
+	char *varname = "rssi_cal_rev";
+	const char *iovar = "nvram_get";
+	void *p;
+
+	err = wlu_var_getbuf(wl, iovar, varname, strlen(varname) + 1, &p);
+	if (err == 0) {
+		/* This means, NVRAM variable found. */
+		/* Calls new function for accommodating ROuts */
+		value = strtol(buf, &endptr, 0);
+	}
+
+	if ((err < 0) || ((err == 0) && (value == 0))) {
+		/* This means, NVRAM variable not found or Variable is 0 */
+		/* Calls old function */
+		n_per_core = 6;
+	} else {
+		n_per_core = 12;
+	}
+
+	n_per_core_p1 = n_per_core  + 1;
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = n_per_core_p1 * 3; /* ACPHY: 3 cores max x 7 entries */
+		for (i = 0; i < N; i++) {
+			if ((phytype == WLC_PHY_TYPE_AC) && (i%n_per_core_p1 == 0)) {
+				if (i > 0) printf("\n");
+				if (deltaValues[i] == -1) break;
+			}
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		int index = 0;
+		while (argv[argc])
+			argc++;
+
+		if (phytype == WLC_PHY_TYPE_AC) {
+			/* N = 7; ACPHY : 7 entries for a core */
+			N = argc;
+		}
+
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			if (argc == n_per_core_p1) {
+				/* For Old implementation, ie, no Routs, n_per_core_p1 == 5
+				 * for New implementation, ie, no Routs, n_per_core_p1 == 9
+				 * If number of arguments is "n_per_core_p1",
+				 * then core number has been provided.
+				 */
+				deltaValues[i] = (int8)value;
+			} else  {
+				/* If the number of elements is not eq to
+				 *"n_per_core", then, core number was not provided.
+				 * So, if only "n_per_core" elements are provided,
+				 * only core 0's info is given. So, for i = 0,
+				 * deltaValues element is 0 (core_num). If "n_per_core * 2"
+				 * elements are provided, then core 0 and 1's info is
+				 * provided. So, i =0 element has core_num = 0, then,
+				 * next "n_per_core" elements are core 0's
+				 * deltas. For i = "n_per_core", core 1's
+				 * core_num = 1 is inserted into deltaValues array.
+				 * Similarly for third core data.
+				 */
+
+				if (i == (n_per_core * 0)) {
+					deltaValues[index] = 0;
+					index++;
+				}
+				if (i == (n_per_core * 1)) {
+					deltaValues[index] = 1;
+					index++;
+				}
+				if (i == (n_per_core * 2)) {
+					deltaValues[index] = 2;
+					index++;
+				}
+
+				deltaValues[index] = (int8)value;
+				index++;
+			}
+
+		}
+		/* If argc == "n_per_core", then only 1 core's infoxs
+		 * was given, so, setbuf() is called once.
+		 * If argc == "n_per_core * 2" then core 0 and 1's info
+		 * was given. So, setbuf() is called twice.
+		 * If argc == "n_per_core * 3" then core 0, 1 and 2's
+		 * info was given. So, setbuf() is called thrice.
+		 */
+		if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues,
+		      n_per_core_p1*sizeof(int8))) < 0)
+			return err;
+		if (argc >= (n_per_core * 2)) {
+			if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues +
+			     (n_per_core_p1 * 1), n_per_core_p1*sizeof(int8))) < 0)
+				return err;
+		}
+		if (argc == (n_per_core * 3)) {
+			if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues +
+			     (n_per_core_p1 * 2), n_per_core_p1*sizeof(int8))) < 0)
+				return err;
+		}
+
+	}
+	return 0;
+}
+
+static int
+wl_phy_rxgainerr_2g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[18];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = 2; /* ACPHY: 3 cores 1 entry per core */
+		for (i = 0; i < N; i++) {
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		while (argv[argc])
+			argc++;
+		if (argc != 2) {
+			printf("IOVAR works only for 2 cores scenario. \n");
+			return err;
+		}
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = 2; /* ACPHY : 5 entries for a core */
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			deltaValues[i] = (int8)value;
+		}
+		if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues, N*sizeof(int8))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rxgainerr_5g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[28];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = 2; /* ACPHY: 3 cores 1 entry per core */
+		for (i = 0; i < N; i++) {
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		while (argv[argc])
+			argc++;
+		if (argc != 2) {
+			printf("IOVAR works only for 2 cores scenario. \n");
+			return err;
+		}
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = 2; /* ACPHY : 7 entries for a core */
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			deltaValues[i] = (int8)value;
+		}
+		if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int
+wl_phytable(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 tableInfo[4];
+	int32 value;
+	char *endptr;
+	void *ptr = NULL;
+	int32 tableId, tableOffset, tableWidth, tableElement;
+
+	if (*++argv != NULL)
+		tableId = strtol(*argv, &endptr, 0);
+	else
+		return BCME_USAGE_ERROR;
+
+	if (*++argv != NULL)
+		tableOffset = strtol(*argv, &endptr, 0);
+	else
+		return BCME_USAGE_ERROR;
+
+	if (*++argv != NULL)
+		tableWidth = strtol(*argv, &endptr, 0);
+	else
+		return BCME_USAGE_ERROR;
+
+	if ((tableId < 0) || (tableOffset < 0))
+		return BCME_BADARG;
+
+	if ((tableWidth != 8) && (tableWidth != 16) && (tableWidth != 32))
+		return BCME_BADARG;
+
+	if (!*++argv) {
+		tableInfo[0] = tableId;
+		tableInfo[1] = tableOffset;
+		tableInfo[2] = tableWidth;
+
+		if ((err = wlu_var_getbuf(wl, cmd->name, tableInfo, 4*sizeof(int32), &ptr)) < 0)
+			return err;
+
+		tableElement = ((int32*)ptr)[0];
+
+		printf("0x%x(%d)\n", tableElement, tableElement);
+	}
+	else
+	{
+		value = strtol(*argv++, &endptr, 0);
+		tableElement = value;
+
+		tableInfo[0] = tableId;
+		tableInfo[1] = tableOffset;
+		tableInfo[2] = tableWidth;
+		tableInfo[3] = tableElement;
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, tableInfo, 4*sizeof(int32))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_txpwrindex(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i;
+	int ret;
+	uint32 txpwridx[4] = { 0 };
+	int8 idx[4] = { 0 };
+	uint argc;
+	char *endptr;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	for (i = 0; i < 4; i++) {
+		if (argc > i) {
+			txpwridx[i] = strtol(argv[1 + i], &endptr, 0);
+			if (*endptr != '\0') {
+				printf("error\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	if (argc == 0) {
+		if ((ret = wlu_iovar_getint(wl, cmd->name, (int*)&txpwridx[0])) < 0) {
+			return (ret);
+		}
+		txpwridx[0] = dtoh32(txpwridx[0]);
+		idx[0] = (int8)(txpwridx[0] & 0xff);
+		idx[1] = (int8)((txpwridx[0] >> 8) & 0xff);
+		idx[2] = (int8)((txpwridx[0] >> 16) & 0xff);
+		idx[3] = (int8)((txpwridx[0] >> 24) & 0xff);
+		printf("txpwrindex for core{0...3}: %d %d %d %d\n", idx[0], idx[1],
+		       idx[2], idx[3]);
+	} else {
+
+		wlc_rev_info_t revinfo;
+		uint32 phytype;
+
+		memset(&revinfo, 0, sizeof(revinfo));
+		if ((ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+			return ret;
+
+		phytype = dtoh32(revinfo.phytype);
+
+		if (phytype == WLC_PHY_TYPE_HT) {
+			if (argc != 3) {
+				printf("HTPHY must specify 3 core txpwrindex\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (phytype == WLC_PHY_TYPE_N) {
+			if (argc != 2) {
+				printf("NPHY must specify 2 core txpwrindex\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		ret = wlu_iovar_setbuf(wl, cmd->name, txpwridx, 4*sizeof(uint32),
+			buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return ret;
+}
+
+static int
+wl_phy_force_vsdb_chans(void *wl, cmd_t *cmd, char **argv)
+{
+	uint16 *chans = NULL;
+	int ret = 0;
+	void	*ptr;
+
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd);
+
+
+	if (argv[1] == NULL) {
+		if ((ret = wlu_var_getbuf(wl, "force_vsdb_chans", NULL, 0, &ptr) < 0)) {
+				printf("wl_phy_maxpower: fail to get maxpower\n");
+				return ret;
+		}
+		chans = (uint16*)ptr;
+		printf("Chans : %x %x \n", chans[0], chans[1]);
+	} else if (argv[1] && argv[2]) {
+		/* Allocate memory */
+		chans = (uint16*)malloc(2 * sizeof(uint16));
+		if (chans == NULL) {
+			printf("unable to allocate Memory \n");
+			return BCME_NOMEM;
+		}
+		chans[0]  = wf_chspec_aton(argv[1]);
+		chans[1]  = wf_chspec_aton(argv[2]);
+		if (((chans[0] & 0xff) == 0) || ((chans[1] & 0xff) == 0)) {
+			chans[0] = 0;
+			chans[1] = 0;
+		}
+		ret = wlu_iovar_setbuf(wl, cmd->name, chans, 2 * sizeof(uint16),
+			buf, WLC_IOCTL_MAXLEN);
+		if (chans)
+			free(chans);
+	} else {
+		ret = BCME_USAGE_ERROR;
+	}
+
+	return ret;
+}
+
+#ifdef SR_DEBUG
+/* Displays PMU related info on screen */
+static int
+wl_dump_pmu(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	pmu_reg_t *pmu_var;
+	int err;
+	uint i;
+	uint32 pmu_chip_ctl_reg;
+	uint32 pmu_chip_reg_reg;
+	uint32 pmu_chip_pll_reg;
+	uint32 pmu_chip_res_reg;
+	UNUSED_PARAMETER(argv);
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+	pmu_var = (pmu_reg_t *)ptr;
+	printf("PMU Control          : 0x%08x\n", pmu_var->pmu_control);
+	printf("PMU Capabilities     : 0x%08x\n", pmu_var->pmu_capabilities);
+	printf("PMU Status           : 0x%08x\n", pmu_var->pmu_status);
+	printf("Resource State       : 0x%08x\n", pmu_var->res_state);
+	printf("Resurce Pending      : 0x%08x\n", pmu_var->res_pending);
+	printf("PMU Timer            : 0x%08x\n", pmu_var->pmu_timer1);
+	printf("Minimum Resource Mask: 0x%08x\n", pmu_var->min_res_mask);
+	printf("Maximum Resource Mask: 0x%08x\n", pmu_var->max_res_mask);
+	/* Displays values of the 5 PMU Chip Control Registers */
+	pmu_chip_ctl_reg = (pmu_var->pmu_capabilities & 0xf8000000);
+	pmu_chip_ctl_reg = pmu_chip_ctl_reg >> 27;
+	for (i = 0; i < pmu_chip_ctl_reg; i++) {
+		printf("PMU ChipControl[%d]   : 0x%08x\n", i, pmu_var->pmu_chipcontrol1[i]);
+	}
+	/* Displays values of the 6 PMU Reg Control Registers */
+	pmu_chip_reg_reg = (pmu_var->pmu_capabilities & 0x07c00000);
+	pmu_chip_reg_reg = pmu_chip_reg_reg >> 22;
+	for (i = 0; i < pmu_chip_reg_reg; i++) {
+		printf("PMU RegControl[%d]    : 0x%08x\n", i, pmu_var->pmu_regcontrol[i]);
+	}
+	/* Displays values of the 6 PMU Pll Control Registers */
+	pmu_chip_pll_reg = (pmu_var->pmu_capabilities & 0x003e0000);
+	pmu_chip_pll_reg = pmu_chip_pll_reg >> 17;
+	for (i = 0; i < pmu_chip_pll_reg; i++) {
+		printf("PMU PllControl[%d]    : 0x%08x\n", i, pmu_var->pmu_pllcontrol[i]);
+	}
+	/* Displays values of the 31 PMU Resource Up/Down Timer */
+	pmu_chip_res_reg = (pmu_var->pmu_capabilities & 0x00001f00);
+	pmu_chip_res_reg = pmu_chip_res_reg >> 8;
+	for (i = 0; i < pmu_chip_res_reg; i++) {
+		printf("PMU Resource Up/Down Timer[%d]    : 0x%08x\n", i,
+		pmu_var->pmu_rsrc_up_down_timer[i]);
+	}
+	/* Displays values of the 31 PMU Resource Dependancy Mask */
+	pmu_chip_res_reg = (pmu_var->pmu_capabilities & 0x00001f00);
+	pmu_chip_res_reg = pmu_chip_res_reg >> 8;
+	for (i = 0; i < pmu_chip_res_reg; i++) {
+		printf("PMU Resource Dependancy Mask[%d]    : 0x%08x\n", i,
+		pmu_var->rsrc_dep_mask[i]);
+	}
+	return 0;
+}
+
+static int
+wl_pmu_keep_on(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	void *ptr;
+	uint32 val;
+	pmu_min_res_t *pmu_min_res_var;
+
+	if (argv[1] == NULL) {
+		if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+			return (err);
+
+		pmu_min_res_var = (pmu_min_res_t *)ptr;
+		if (pmu_min_res_var->pmu_flag == 1) {
+			printf("Minimum Resource Mask:0x%x\n",
+					pmu_min_res_var->pmu_min_res_val);
+		} else {
+			printf("The PMU is kept on upto resource# %d\n",
+				pmu_min_res_var->pmu_min_res_val);
+		}
+	}
+	else {
+		val = atoi(argv[1]);
+		wlu_iovar_setbuf(wl, cmd->name, &val, sizeof(uint32), buf, WLC_IOCTL_MAXLEN);
+	}
+	return 0;
+}
+#endif /* SR_DEBUG */
+
+static int
+wl_sarlimit(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i;
+	int ret;
+	sar_limit_t sar;
+	uint argc;
+	char *endptr;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc != 0 && argc != sizeof(sar_limit_t)) {
+		printf("Error: Input %d SAR values, need total %d SAR values\n",
+		       argc, (int)sizeof(sar_limit_t));
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argc == 0) {
+		if ((ret = wlu_iovar_get(wl, cmd->name, &sar, sizeof(sar_limit_t))) < 0) {
+			return (ret);
+		}
+		printf("\t2G:    %4d %4d %4d %4d\n",
+		       sar.band2g[0], sar.band2g[1], sar.band2g[2], sar.band2g[3]);
+		for (i = 0; i < WLC_SUBBAND_MAX; i++) {
+			printf("\t5G[%1d]  %4d %4d %4d %4d\n", i,
+			       sar.band5g[i][0], sar.band5g[i][1],
+			       sar.band5g[i][2], sar.band5g[i][3]);
+		}
+	} else {
+		uint8 *ptr = (uint8 *)&sar;
+		memset(ptr, WLC_TXPWR_MAX, sizeof(sar_limit_t));
+		for (i = 0; i < argc; i++) {
+			ptr[i] = (uint8)(strtol(argv[1 + i], &endptr, 0));
+			if (*endptr != '\0') {
+				printf("error\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+		printf("\t2G:    %4d %4d %4d %4d\n",
+		       sar.band2g[0], sar.band2g[1], sar.band2g[2], sar.band2g[3]);
+		for (i = 0; i < WLC_SUBBAND_MAX; i++) {
+			printf("\t5G[%1d]  %4d %4d %4d %4d\n", i,
+			       sar.band5g[i][0], sar.band5g[i][1],
+			       sar.band5g[i][2], sar.band5g[i][3]);
+		}
+		ret = wlu_iovar_set(wl, cmd->name, &sar, sizeof(sar_limit_t));
+	}
+
+	return ret;
+}
+
+static int
+wl_bmon_bssid(void *wl, cmd_t *cmd, char **argv)
+{
+	uint argc;
+	uint8 params[ETHER_ADDR_LEN + 1];
+
+	argv ++;
+
+	/* arg count */
+	argc = ARGCNT(argv);
+	if (argc < 2)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], (struct ether_addr *)&params[0]))
+		return BCME_USAGE_ERROR;
+
+	params[ETHER_ADDR_LEN] = (uint8)strtoul(argv[1], NULL, 0);
+
+	return wlu_iovar_set(wl, cmd->name, params, sizeof(params));
+}
+
+static int
+wl_phy_pavars(void *wl, cmd_t *cmd, char **argv)
+{
+	const pavars_t *pav = pavars;
+	uint16	inpa[WL_PHY_PAVARS_LEN];
+	char	*cpar = NULL, *p = NULL;
+	char	*par;
+	char	delimit[2] = " \0";
+	int	err = 0;
+	unsigned int val, val2[16];
+	void	*ptr = NULL;
+	int paparambwver = 0;
+
+	const char *iovar = "nvram_dump";
+	void *p1 = NULL;
+
+	if ((err = wlu_var_getbuf(wl, iovar, NULL, 0, &p1)) < 0) {
+		if ((err = wlu_get(wl, WLC_NVRAM_DUMP, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+		    return err;
+		p1 = (void *)buf;
+	}
+
+	if ((p1 = strstr(p1, "paparambwver"))) {
+		char *q = NULL;
+
+		p1 = (void*)((char*)p1 + 13);
+		paparambwver = strtoul(p1, &q, 10);
+	}
+
+	if (paparambwver == 1)
+		pav = pavars_bwver_1;
+	else if (paparambwver == 2)
+		pav = pavars_bwver_2;
+	else
+		pav = pavars;
+
+	if (*++argv) {	/* set */
+		while (pav->phy_type != PHY_TYPE_NULL) {
+			bool found = FALSE;
+			int i = 0;
+
+			inpa[i++] = pav->phy_type;
+			inpa[i++] = pav->bandrange;
+			inpa[i++] = pav->chain;
+
+			par = malloc(strlen(pav->vars)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			strcpy(par, pav->vars);
+
+			cpar = strtok (par, delimit);	/* current param */
+
+			if (pav->phy_type == PHY_TYPE_AC) {
+				int pnum = 0, n;
+
+				if (pav->bandrange == WL_CHAN_FREQ_RANGE_2G)
+					pnum = 3;
+				else if (pav->bandrange == WL_CHAN_FREQ_RANGE_5G_4BAND)
+					pnum = 12;
+
+				/* Find the parameter in the input argument list */
+				if ((p = find_pattern2(argv, cpar, val2, pnum))) {
+					found = TRUE;
+					for (n = 0; n < pnum; n ++)
+						inpa[i + n] = (uint16)val2[n];
+				}
+			} else {
+				do {
+					val = 0;
+
+					/* Find the parameter in the input argument list */
+					if ((p = find_pattern(argv, cpar, &val))) {
+						found = TRUE;
+						inpa[i] = (uint16)val;
+					} else
+						inpa[i] = 0;
+					i++;
+				} while ((cpar = strtok (NULL, delimit)));
+			}
+			free(par);
+
+			if (found) {
+				if ((err = wlu_var_setbuf(wl, cmd->name, inpa,
+					WL_PHY_PAVARS_LEN * sizeof(uint16))) < 0) {
+					printf("wl_phy_pavars: fail to set\n");
+					return err;
+				}
+			}
+			pav++;
+		}
+	} else {	/* get */
+		while (pav->phy_type != PHY_TYPE_NULL) {
+			int i = 0;
+			uint16	*outpa;
+
+			inpa[i++] = pav->phy_type;
+			inpa[i++] = pav->bandrange;
+			inpa[i++] = pav->chain;
+
+			par = malloc(strlen(pav->vars)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			strcpy(par, pav->vars);
+
+			if ((err = wlu_var_getbuf_sm(wl, cmd->name, inpa,
+				WL_PHY_PAVARS_LEN * sizeof(uint16), &ptr)) < 0) {
+				printf("phy %x band %x chain %d err %d\n", pav->phy_type,
+					pav->chain, pav->bandrange, err);
+				free(par);
+				break;
+			}
+
+			outpa = (uint16*)ptr;
+			if (outpa[0] == PHY_TYPE_NULL) {
+				pav++;
+				free(par);
+				continue;
+			}
+
+			cpar = strtok(par, delimit);	/* current param */
+
+			if (pav->phy_type == PHY_TYPE_AC) {
+				int pnum = 0, n;
+
+				if (pav->bandrange == WL_CHAN_FREQ_RANGE_2G)
+					pnum = 3;
+				else if (pav->bandrange == WL_CHAN_FREQ_RANGE_5G_4BAND)
+					pnum = 12;
+
+				printf("%s=", cpar);
+				for (n = 0; n < pnum; n ++) {
+					if (n != 0)
+						printf(",");
+					printf("0x%x", outpa[i + n]);
+				}
+				printf("\n");
+			} else {
+				do {
+					printf("%s=0x%x\n", cpar, outpa[i++]);
+				} while ((cpar = strtok (NULL, delimit)));
+			}
+			pav++;
+			free(par);
+		}
+	}
+
+	return err;
+}
+
+static int
+wl_phy_povars(void *wl, cmd_t *cmd, char **argv)
+{
+	const povars_t *pov = povars;
+	wl_po_t	inpo;
+	char	*cpar = NULL, *p = NULL;
+	char	*par;	/* holds longest povars->vars */
+	char	delimit[2] = " \0";
+	int	err = 0;
+	uint val;
+	void	*ptr = NULL;
+
+	if (*++argv) {	/* set */
+		while (pov->phy_type != PHY_TYPE_NULL) {
+			bool found = FALSE;
+			int i = 0;
+
+			inpo.phy_type = pov->phy_type;
+			inpo.band = pov->bandrange;
+
+			par = malloc(strlen(pov->vars)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			strcpy(par, pov->vars);
+
+			/* Take care of cck and ofdm before walking through povars->vars */
+			if (pov->bandrange == WL_CHAN_FREQ_RANGE_2G) {
+				p = find_pattern(argv, "cck2gpo", &val);
+				if (p)	found = TRUE;
+				inpo.cckpo = p ? (uint16)val : 0;
+
+				p = find_pattern(argv, "ofdm2gpo", &val);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GL) {
+				p = find_pattern(argv, "ofdm5glpo", &val);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GM) {
+				p = find_pattern(argv, "ofdm5gpo", &val);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GH) {
+				p = find_pattern(argv, "ofdm5ghpo", &val);
+			}
+			inpo.ofdmpo = p ? (uint32)val : 0;
+			if (p)	found = TRUE;
+
+			cpar = strtok (par, delimit);	/* current param */
+			do {
+				val = 0;
+
+				/* Find the parameter in the input argument list */
+				p = find_pattern(argv, cpar, &val);
+				if (p)	found = TRUE;
+				inpo.mcspo[i] = p ? (uint16)val : 0;
+				i++;
+			} while ((cpar = strtok (NULL, delimit)));
+
+			if (found) {
+				if ((err = wlu_var_setbuf(wl, cmd->name, &inpo,
+					sizeof(wl_po_t))) < 0) {
+					printf("wl_phy_povars: fail to set\n");
+					free(par);
+					return err;
+				}
+			}
+			pov++;
+			free(par);
+		}
+	} else {	/* get */
+		while (pov->phy_type != PHY_TYPE_NULL) {
+			int i = 0;
+			wl_po_t	*outpo;
+
+			inpo.phy_type = pov->phy_type;
+			inpo.band = pov->bandrange;
+
+			par = malloc(strlen(pov->vars)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			strcpy(par, pov->vars);
+
+			if ((err = wlu_var_getbuf(wl, cmd->name, &inpo, sizeof(povars_t),
+				&ptr)) < 0) {
+				printf("phy %x band %x err %d\n", pov->phy_type,
+					pov->bandrange, err);
+				free(par);
+				break;
+			}
+
+			outpo = (wl_po_t*)ptr;
+			if (outpo->phy_type == PHY_TYPE_NULL) {
+				pov++;
+				free(par);
+				continue;
+			}
+
+			/* Take care of cck and ofdm before walking through povars->vars */
+			if (outpo->band == WL_CHAN_FREQ_RANGE_2G) {
+				printf("cck2gpo=0x%x\n", outpo->cckpo);
+				printf("ofdm2gpo=0x%x\n", outpo->ofdmpo);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GL) {
+				printf("ofdm5glpo=0x%x\n", outpo->ofdmpo);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GM) {
+				printf("ofdm5gpo=0x%x\n", outpo->ofdmpo);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GH) {
+				printf("ofdm5ghpo=0x%x\n", outpo->ofdmpo);
+			}
+
+			cpar = strtok(par, delimit);	/* current param */
+			do {
+				printf("%s=0x%x\n", cpar, outpo->mcspo[i++]);
+			} while ((cpar = strtok (NULL, delimit)));
+
+			pov++;
+			free(par);
+		}
+	}
+
+	return err;
+}
+
+static int
+wl_phy_rpcalvars(void *wl, cmd_t *cmd, char **argv)
+{
+	int    err = 0, k;
+	unsigned int val;
+	wl_rpcal_t rpcal[WL_NUM_RPCALVARS], *rpcal_out;
+	void *ptr = NULL;
+
+	if (*++argv) {	/* set */
+		bool found = FALSE;
+
+		/* initialization */
+		memset(&(rpcal[0]), 0, sizeof(wl_rpcal_t)*WL_NUM_RPCALVARS);
+
+		if (find_pattern(argv, "rpcal2g", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_2G].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_2G].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb0", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND0].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND0].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb1", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND1].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND1].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb2", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND2].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND2].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb3", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND3].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND3].update = 1;
+		}
+
+		if (found) {
+			err = wlu_var_setbuf(wl, cmd->name, &(rpcal[0]),
+			                     sizeof(wl_rpcal_t)*WL_NUM_RPCALVARS);
+			if (err < 0) {
+				printf("wl_phy_rpcalvars: fail to set\n");
+				return err;
+			}
+		} else {
+			printf("wl_phy_rpcalvars: fail to found matching rpcalvar name\n");
+			return err;
+		}
+
+	} else {	/* get */
+
+		err = wlu_var_getbuf(wl, cmd->name, &(rpcal[0]),
+		                     sizeof(wl_rpcal_t)*WL_NUM_RPCALVARS, &ptr);
+
+		if (err < 0) {
+			printf("wl_phy_rpcalvars: fail to get\n");
+			return err;
+		} else {
+			rpcal_out = (wl_rpcal_t*) ptr;
+		}
+
+		for (k = 0; k < WL_NUM_RPCALVARS; k++) {
+
+			switch (k) {
+			case WL_CHAN_FREQ_RANGE_2G:
+				printf("rpcal2g=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND0:
+				printf("rpcal5gb0=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND1:
+				printf("rpcal5gb1=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND2:
+				printf("rpcal5gb2=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND3:
+				printf("rpcal5gb3=0x%x\n", rpcal_out[k].value);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_fem(void *wl, cmd_t *cmd, char **argv)
+{
+	srom_fem_t	fem;
+	srom_fem_t	*rfem;
+	void		*ptr;
+	bool	found = FALSE;
+	int	err = 0;
+	uint	val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {	/* write fem */
+
+		/* fem2g */
+		memset(&fem, 0, sizeof(srom_fem_t));
+
+		if (find_pattern(argv, "tssipos2g", &val)) {
+			found = TRUE;
+			fem.tssipos = val;
+		}
+
+		if (find_pattern(argv, "extpagain2g", &val)) {
+			found = TRUE;
+			fem.extpagain = val;
+		}
+
+		if (find_pattern(argv, "pdetrange2g", &val)) {
+			found = TRUE;
+			fem.pdetrange = val;
+		}
+
+		if (find_pattern(argv, "triso2g", &val)) {
+			found = TRUE;
+			fem.triso = val;
+		}
+
+		if (find_pattern(argv, "antswctl2g", &val)) {
+			found = TRUE;
+			fem.antswctrllut = val;
+		}
+
+		if (found) {
+			if ((err = wlu_var_setbuf(wl, "fem2g", &fem, sizeof(srom_fem_t)) < 0))
+				printf("wl_phy_fem: fail to set fem2g\n");
+			else
+				printf("fem2g set\n");
+		}
+
+		found = FALSE;
+		/* fem5g */
+		memset(&fem, 0, sizeof(srom_fem_t));
+
+		if (find_pattern(argv, "tssipos5g", &val)) {
+			found = TRUE;
+			fem.tssipos = val;
+		}
+
+		if (find_pattern(argv, "extpagain5g", &val)) {
+			found = TRUE;
+			fem.extpagain = val;
+		}
+
+		if (find_pattern(argv, "pdetrange5g", &val)) {
+			found = TRUE;
+			fem.pdetrange = val;
+		}
+
+		if (find_pattern(argv, "triso5g", &val)) {
+			found = TRUE;
+			fem.triso = val;
+		}
+
+		if (find_pattern(argv, "antswctl5g", &val)) {
+			found = TRUE;
+			fem.antswctrllut = val;
+		}
+
+		if (found) {
+			if ((err = wlu_var_setbuf(wl, "fem5g", &fem, sizeof(srom_fem_t)) < 0))
+				printf("wl_phy_fem: fail to set fem5g\n");
+			else
+				printf("fem5g set\n");
+		}
+	} else {
+		if ((err = wlu_var_getbuf(wl, "fem2g", NULL, 0, (void**)&ptr) < 0)) {
+			printf("wl_phy_fem: fail to get fem2g\n");
+		} else {
+			rfem = (srom_fem_t*)ptr; /* skip the "fem2g" */
+			printf("tssipos2g=0x%x extpagain2g=0x%x pdetrange2g=0x%x"
+			       " triso2g=0x%x antswctl2g=0x%x\n",
+			       rfem->tssipos, rfem->extpagain, rfem->pdetrange,
+			       rfem->triso, rfem->antswctrllut);
+	       }
+
+		if ((err = wlu_var_getbuf(wl, "fem5g", NULL, 0, (void**)&ptr) < 0)) {
+			printf("wl_phy_fem: fail to get fem5g\n");
+		} else {
+			rfem = (srom_fem_t*)ptr; /* skip the "fem2g" */
+			printf("tssipos5g=0x%x extpagain5g=0x%x pdetrange5g=0x%x"
+			       " triso5g=0x%x antswctl5g=0x%x\n",
+			       rfem->tssipos, rfem->extpagain, rfem->pdetrange,
+			       rfem->triso, rfem->antswctrllut);
+		}
+	}
+
+	return err;
+}
+
+static int
+wl_phy_maxpower(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err = 0;
+	uint	val;
+	uint8	maxp[8];
+	void	*ptr;
+	uint8	*rmaxp;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {	/* write maxpower */
+
+		if (find_pattern(argv, "maxp2ga0", &val))
+			maxp[0] = val;
+		else
+			printf("Missing maxp2ga0\n");
+
+		if (find_pattern(argv, "maxp2ga1", &val))
+			maxp[1] = val;
+		else
+			printf("Missing maxp2ga1\n");
+
+		if (find_pattern(argv, "maxp5ga0", &val))
+			maxp[2] = val;
+		else
+			printf("Missing maxp5ga0\n");
+
+		if (find_pattern(argv, "maxp5ga1", &val))
+			maxp[3] = val;
+		else
+			printf("Missing maxp5ga1\n");
+
+		if (find_pattern(argv, "maxp5gla0", &val))
+			maxp[4] = val;
+		else
+			printf("Missing maxp5gla0\n");
+
+		if (find_pattern(argv, "maxp5gla1", &val))
+			maxp[5] = val;
+		else
+			printf("Missing maxp5gla1\n");
+
+		if (find_pattern(argv, "maxp5gha0", &val))
+			maxp[6] = val;
+		else
+			printf("Missing maxp5gha0\n");
+
+		if (find_pattern(argv, "maxp5gha1", &val))
+			maxp[7] = val;
+		else
+			printf("Missing maxp5gha1\n");
+
+		if ((err = wlu_var_setbuf(wl, "maxpower", &maxp, 8 * sizeof(uint8)) < 0)) {
+			printf("wl_phy_maxpower: fail to set\n");
+		}
+	} else {
+		if ((err = wlu_var_getbuf(wl, "maxpower", NULL, 0, &ptr) < 0)) {
+			printf("wl_phy_maxpower: fail to get maxpower\n");
+			return err;
+		}
+		rmaxp = (uint8*)ptr;
+		printf("maxp2ga0=%x\n", rmaxp[0]);
+		printf("maxp2ga1=%x\n", rmaxp[1]);
+		printf("maxp5ga0=%x\n", rmaxp[2]);
+		printf("maxp5ga1=%x\n", rmaxp[3]);
+		printf("maxp5gla0=%x\n", rmaxp[4]);
+		printf("maxp5gla1=%x\n", rmaxp[5]);
+		printf("maxp5gha0=%x\n", rmaxp[6]);
+		printf("maxp5gha1=%x\n", rmaxp[7]);
+	}
+
+	return err;
+}
+
+static int
+wl_antgain(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err = 0;
+	uint	val;
+	uint8	ag[2];
+	uint8	*rag;
+	void	*ptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {	/* write maxpower */
+		if (find_pattern(argv, "ag0", &val))
+			ag[0] = val & 0xff;
+		else {
+			printf("Missing ag0\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (find_pattern(argv, "ag1", &val))
+			ag[1] = val & 0xff;
+		else {
+			printf("Missing ag1\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((err = wlu_var_setbuf(wl, "antgain", &ag, 2 * sizeof(uint8)) < 0)) {
+			printf("wl_antgain: fail to set\n");
+		}
+	} else {
+		if ((err = wlu_var_getbuf(wl, "antgain", NULL, 0, &ptr) < 0)) {
+			printf("wl_antgain: fail to get antgain\n");
+			return err;
+		}
+		rag = (uint8*)ptr;
+		printf("ag0=%x\n", rag[0]);
+		printf("ag1=%x\n", rag[1]);
+	}
+
+	return err;
+}
+
+static int
+wl_pkteng(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkteng_t pkteng;
+
+	memset(&pkteng, 0, sizeof(pkteng));
+	if (strcmp(cmd->name, "pkteng_stop") == 0) {
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+		if (strcmp(*argv, "tx") == 0)
+			pkteng.flags = WL_PKTENG_PER_TX_STOP;
+		else if (strcmp(*argv, "rx") == 0)
+			pkteng.flags = WL_PKTENG_PER_RX_STOP;
+		else
+			return BCME_USAGE_ERROR;
+	}
+	else if (strcmp(cmd->name, "pkteng_start") == 0) {
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+		if (!wl_ether_atoe(*argv, (struct ether_addr *)&pkteng.dest))
+			return BCME_USAGE_ERROR;
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+		if ((strcmp(*argv, "tx") == 0) || (strcmp(*argv, "txwithack") == 0))  {
+			if (strcmp(*argv, "tx") == 0)
+				pkteng.flags = WL_PKTENG_PER_TX_START;
+			else
+				pkteng.flags = WL_PKTENG_PER_TX_WITH_ACK_START;
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			if (strcmp(*argv, "async") == 0)
+				pkteng.flags &= ~WL_PKTENG_SYNCHRONOUS;
+			else if (strcmp(*argv, "sync") == 0)
+				pkteng.flags |= WL_PKTENG_SYNCHRONOUS;
+			else
+				/* neither optional parameter [async|sync] */
+				--argv;
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			pkteng.delay = strtoul(*argv, NULL, 0);
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			pkteng.length = strtoul(*argv, NULL, 0);
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			pkteng.nframes = strtoul(*argv, NULL, 0);
+			if (*++argv)
+				if (!wl_ether_atoe(*argv, (struct ether_addr *)&pkteng.src))
+					return BCME_USAGE_ERROR;
+		}
+		else if ((strcmp(*argv, "rx") == 0) || (strcmp(*argv, "rxwithack") == 0)) {
+			if ((strcmp(*argv, "rx") == 0))
+				pkteng.flags = WL_PKTENG_PER_RX_START;
+			else
+				pkteng.flags = WL_PKTENG_PER_RX_WITH_ACK_START;
+
+			if (*++argv) {
+				if (strcmp(*argv, "async") == 0)
+					pkteng.flags &= ~WL_PKTENG_SYNCHRONOUS;
+				else if (strcmp(*argv, "sync") == 0) {
+					pkteng.flags |= WL_PKTENG_SYNCHRONOUS;
+					/* sync mode requires number of frames and timeout */
+					if (!*++argv)
+						return BCME_USAGE_ERROR;
+					pkteng.nframes = strtoul(*argv, NULL, 0);
+					if (!*++argv)
+						return BCME_USAGE_ERROR;
+					pkteng.delay = strtoul(*argv, NULL, 0);
+				}
+			}
+		}
+		else
+			return BCME_USAGE_ERROR;
+	}
+	else {
+		printf("Invalid command name %s\n", cmd->name);
+		return 0;
+	}
+
+	pkteng.flags = htod32(pkteng.flags);
+	pkteng.delay = htod32(pkteng.delay);
+	pkteng.nframes = htod32(pkteng.nframes);
+	pkteng.length = htod32(pkteng.length);
+
+	return (wlu_var_setbuf(wl, "pkteng", &pkteng, sizeof(pkteng)));
+}
+
+static int
+wl_rxiq(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_rxiqest";
+	int err, argc, opt_err;
+	uint32 rxiq;
+	uint8 resolution = 0;
+	uint8 lpf_hpc = 1;
+	uint8 dig_lpf = 1;
+	uint8 gain_correct = 0;
+	uint8 extra_gain_3dBsteps = 0;
+	uint8 force_gain_type = 0;
+	uint8 antenna = 3;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	/* DEFAULT:
+	 * gain_correct = 0 (disable gain correction),
+	 * lpf_hpc = 1 (sets lpf hpc to lowest value),
+	 * dig_lpf = 1; (sets to ltrn_lpf mode)
+	 * resolution = 0 (coarse),
+	 * samples = 1024 (2^10) and antenna = 3
+	 * force_gain_type = 0 (init gain mode)
+	 */
+	rxiq = (extra_gain_3dBsteps << 28) | (gain_correct << 24) | (dig_lpf << 22)
+	        | (lpf_hpc << 20) | (resolution << 16) | (10 << 8) | (force_gain_type << 4)
+	        | antenna;
+
+	if (argc != 0) {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'g') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int"
+						" for gain-correction (0, 1, 2, 3, 4, 7, 8)\n",
+						fn_name, to.valstr);
+
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) || (to.val > 8)) {
+					fprintf(stderr, "%s: invalid gain-correction select %d"
+						" (0,1,2,3,4,7,8)\n", fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				gain_correct = to.val & 0xf;
+				rxiq = ((gain_correct << 24) | (rxiq & 0xf0ffffff));
+			}
+			if (to.opt == 'f') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int"
+						" for lpf-hpc override select (0, 1)\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) || (to.val > 1)) {
+					fprintf(stderr, "%s: invalid lpf-hpc override select %d"
+						" (0,1)\n", fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				lpf_hpc = to.val & 0xf;
+				rxiq = ((lpf_hpc << 20) | (rxiq & 0xff0fffff));
+			}
+			if (to.opt == 'w') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int"
+						" for dig-lpf override select (0, 1 or 2)\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) || (to.val > 2)) {
+					fprintf(stderr, "%s: invalid dig-lpf override select %d"
+						" (0,1,2)\n", fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				dig_lpf = to.val & 0x3;
+				rxiq = ((dig_lpf << 22) | (rxiq & 0xff3fffff));
+			}
+			if (to.opt == 'r') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int"
+						" for resolution (0, 1)\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) || (to.val > 1)) {
+					fprintf(stderr, "%s: invalid resolution select %d"
+						" (0,1)\n", fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				resolution = to.val & 0xf;
+				rxiq = ((resolution << 16) | (rxiq & 0xfff0ffff));
+			}
+			if (to.opt == 's') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" the sample count\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val < 0 || to.val > 16) {
+					fprintf(stderr, "%s: sample count too large %d"
+						"(10 <= x <= 16)\n", fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				rxiq = (((to.val & 0xff) << 8) | (rxiq & 0xffff00ff));
+			}
+			if (to.opt == 'a') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int"
+						" for antenna (0, 1, 3)\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) || (to.val > 3)) {
+					fprintf(stderr, "%s: invalid antenna select %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				rxiq = ((rxiq & 0xffffff00) | (to.val & 0xff));
+			}
+			if (to.opt == 'e') {
+				if (!to.good_int) {
+					fprintf(stderr,
+					        "%s: could not parse \"%s\" as an int"
+					        " for extra INITgain\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) || (to.val > 24) || (to.val % 3 != 0)) {
+					fprintf(stderr,
+					        "%s: Valid extra INITgain = {0, 3, .., 21, 24}\n",
+					        fn_name);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				rxiq = ((((to.val/3) & 0xf) << 28) | (rxiq & 0x0fffffff));
+			}
+			if (to.opt == 'i') {
+				if (!to.good_int) {
+					fprintf(stderr,
+					        "%s: could not parse \"%s\" as an int"
+					        " for init or clipLO mode\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 0) && (to.val != 1) &&
+				    (to.val != 2) && (to.val != 3) && (to.val != 4)) {
+					fprintf(stderr,
+					"%s: Valid options - 0(default gain), 1(fixed high gain)"
+					"or 4(fixed low gain). \n",
+						fn_name);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				rxiq = ((rxiq & 0xffffff0f) | ((to.val << 4) & 0xf0));
+			}
+		}
+	}
+
+	if ((err = wlu_iovar_setint(wl, cmd->name, (int)rxiq)) < 0)
+		return err;
+	if ((err = wlu_iovar_getint(wl, cmd->name, (int*)&rxiq)) < 0)
+		return err;
+
+	if (resolution == 1) {
+		/* fine resolution power reporting (0.25dB resolution) */
+		uint8 core;
+		int16 tmp;
+		if (rxiq >> 20) {
+			/* Three chains: */
+			for (core = 0; core < 3; core ++) {
+				tmp = (rxiq >> (10*core)) & 0x3ff;
+				tmp = ((int16)(tmp << 6)) >> 6; /* sign extension */
+				if (tmp < 0) {
+					tmp = -1*tmp;
+					printf("-%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				} else {
+					printf("%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				}
+			}
+			printf("\n");
+		} else if (rxiq >> 10) {
+			/* 2 chains */
+			for (core = 0; core < 2; core ++) {
+				tmp = (rxiq >> (10*core)) & 0x3ff;
+				tmp = ((int16)(tmp << 6)) >> 6; /* sign extension */
+				if (tmp < 0) {
+					tmp = -1*tmp;
+					printf("-%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				} else {
+					printf("%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				}
+			}
+			printf("\n");
+		} else {
+			/* 1 chain */
+			tmp = rxiq & 0x3ff;
+			tmp = ((int16)(tmp << 6)) >> 6; /* sign extension */
+			if (tmp < 0) {
+				tmp = -1*tmp;
+				printf("-%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+			} else {
+				printf("%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+			}
+			printf("\n");
+		}
+	} else {
+		if (rxiq >> 16)
+			printf("%ddBm %ddBm %ddBm\n", (int8)(rxiq & 0xff),
+			       (int8)((rxiq >> 8) & 0xff), (int8)((rxiq >> 16) & 0xff));
+		else if (rxiq >> 8)
+			printf("%ddBm %ddBm\n", (int8)(rxiq & 0xff), (int8)((rxiq >> 8) & 0xff));
+		else
+			printf("%ddBm\n", (int8)(rxiq & 0xff));
+	}
+exit:
+	return err;
+}
+
+/* Convert user's input in hex pattern to byte-size mask */
+static int
+wl_pattern_atoh(char *src, char *dst)
+{
+	int i;
+	if (strncmp(src, "0x", 2) != 0 &&
+	    strncmp(src, "0X", 2) != 0) {
+		printf("Data invalid format. Needs to start with 0x\n");
+		return -1;
+	}
+	src = src + 2; /* Skip past 0x */
+	if (strlen(src) % 2 != 0) {
+		printf("Data invalid format. Needs to be of even length\n");
+		return -1;
+	}
+	for (i = 0; *src != '\0'; i++) {
+		char num[3];
+		strncpy(num, src, 2);
+		num[2] = '\0';
+		dst[i] = (uint8)strtoul(num, NULL, 16);
+		src += 2;
+	}
+	return i;
+}
+
+static int
+wl_wowl_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int flags_prev = 0;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if ((err = wlu_iovar_getint(wl, "wowl_status", &flags_prev)))
+		return err;
+
+	printf("Status of last wakeup:\n");
+	printf("\tflags:0x%x\n", flags_prev);
+
+	if (flags_prev & WL_WOWL_BCN)
+		printf("\t\tWake-on-Loss-of-Beacons enabled\n");
+
+	if (flags_prev & WL_WOWL_MAGIC)
+		printf("\t\tWake-on-Magic frame enabled\n");
+	if (flags_prev & WL_WOWL_NET)
+		printf("\t\tWake-on-Net pattern enabled\n");
+	if (flags_prev & WL_WOWL_DIS)
+		printf("\t\tWake-on-Deauth enabled\n");
+
+	if (flags_prev & WL_WOWL_RETR)
+		printf("\t\tRetrograde TSF enabled\n");
+	if (flags_prev & WL_WOWL_TST)
+		printf("\t\tTest-mode enabled\n");
+
+	printf("\n");
+
+	return 0;
+}
+
+static int
+wl_wowl_wakeind(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wowl_wakeind_t wake = {0, 0};
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if (*argv) {
+		if (strcmp(*argv, "clear"))
+			return BCME_USAGE_ERROR;
+		err = wlu_iovar_set(wl, "wowl_wakeind", *argv, strlen(*argv));
+		return err;
+	}
+
+	if ((err = wlu_iovar_get(wl, "wowl_wakeind", &wake, sizeof(wl_wowl_wakeind_t))) < 0)
+		return err;
+
+	if (wake.pci_wakeind)
+		printf("PCI Indication set\n");
+	if (wake.ucode_wakeind != 0) {
+		printf("MAC Indication set\n");
+
+		if ((wake.ucode_wakeind & WL_WOWL_MAGIC) == WL_WOWL_MAGIC)
+			printf("\tMAGIC packet received\n");
+		if ((wake.ucode_wakeind & WL_WOWL_NET) == WL_WOWL_NET)
+			printf("\tPacket received with Netpattern\n");
+		if ((wake.ucode_wakeind & WL_WOWL_DIS) == WL_WOWL_DIS)
+			printf("\tDisassociation/Deauth received\n");
+		if ((wake.ucode_wakeind & WL_WOWL_RETR) == WL_WOWL_RETR)
+			printf("\tRetrograde TSF detected\n");
+		if ((wake.ucode_wakeind & WL_WOWL_BCN) == WL_WOWL_BCN)
+			printf("\tBeacons Lost\n");
+		if ((wake.ucode_wakeind & WL_WOWL_TST) == WL_WOWL_TST)
+			printf("\tTest Mode\n");
+		if ((wake.ucode_wakeind & WL_WOWL_M1) == WL_WOWL_M1)
+			printf("\tPTK Refresh received.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_EAPID) == WL_WOWL_EAPID)
+			printf("\tEAP-Identity request received\n");
+		if ((wake.ucode_wakeind & WL_WOWL_GTK_FAILURE) == WL_WOWL_GTK_FAILURE)
+			printf("\tWake on GTK failure.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_EXTMAGPAT) == WL_WOWL_EXTMAGPAT)
+			printf("\tExtended Magic Packet received.\n");
+
+		if ((wake.ucode_wakeind & WL_WOWL_KEYROT) == WL_WOWL_KEYROT)
+			printf("\tKey Rotation Packet received.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_SCANOL) == WL_WOWL_SCANOL)
+			printf("\tWake on Scan offload.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_MDNS_CONFLICT) == WL_WOWL_MDNS_CONFLICT)
+			printf("\tWake on MDNS Conflict.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_MDNS_SERVICE) == WL_WOWL_MDNS_SERVICE)
+			printf("\tWake on MDNS Service.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_TCPKEEP_DATA) == WL_WOWL_TCPKEEP_DATA)
+			printf("\tWake on TCP Keepalive Data.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_TCPKEEP_TIME) == WL_WOWL_TCPKEEP_TIME)
+			printf("\tWake on TCP Keepalive Timeout.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_FW_HALT) == WL_WOWL_FW_HALT)
+			printf("\tWake on Firmware died in wowl mode.\n");
+
+
+		if ((wake.ucode_wakeind & (WL_WOWL_NET | WL_WOWL_MAGIC | WL_WOWL_EXTMAGPAT))) {
+			if ((wake.ucode_wakeind & WL_WOWL_BCAST) == WL_WOWL_BCAST)
+				printf("\t\tBroadcast/Mcast frame received\n");
+			else
+				printf("\t\tUnicast frame received\n");
+		}
+	}
+
+	if (!wake.pci_wakeind && wake.ucode_wakeind == 0)
+		printf("No wakeup indication set\n");
+
+	return 0;
+}
+/* Used by NINTENDO2 */
+static int
+wl_wowl_wake_reason(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_wr_t wr;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		err = wlu_iovar_get(wl, "wakeup_reason", &wr, sizeof(wl_wr_t));
+		if (err)
+			return err;
+
+		if (wr.reason && wr.reason < REASON_LAST) {
+			printf("ID: %d\t", wr.id);
+
+			if (wr.reason == LCD_ON)
+			printf("Reason: LCD_ON\n");
+			else if (wr.reason == LCD_OFF)
+			printf("Reason: LCD_OFF\n");
+			else if (wr.reason == DRC1_WAKE)
+			printf("Reason: DRC1_WAKE\n");
+			else if (wr.reason == DRC2_WAKE)
+			printf("Reason: DRC2_WAKE\n");
+		}
+		else
+			printf("Unknown wakeup Reason\n");
+	}
+		return err;
+}
+
+/* Send a wakeup frame to sta in WAKE mode */
+static int
+wl_wowl_pkt(void *wl, cmd_t *cmd, char **argv)
+{
+	char *arg = buf;
+	const char *str;
+	char *dst;
+	uint tot = 0;
+	uint16 type, pkt_len;
+	int dst_ea = 0; /* 0 == manual, 1 == bcast, 2 == ucast */
+	char *ea[ETHER_ADDR_LEN];
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	UNUSED_PARAMETER(cmd);
+
+	str = "wowl_pkt";
+	strncpy(arg, str, strlen(str));
+	arg[strlen(str)] = '\0';
+	dst = arg + strlen(str) + 1;
+	tot += strlen(str) + 1;
+
+	pkt_len = (uint16)htod32(strtoul(*argv, NULL, 0));
+
+	*((uint16*)dst) = pkt_len;
+
+	dst += sizeof(pkt_len);
+	tot += sizeof(pkt_len);
+
+	if (!*++argv) {
+		printf("Dest of the packet needs to be provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Dest of the frame */
+	if (!strcmp(*argv, "bcast")) {
+		dst_ea = 1;
+		if (!wl_ether_atoe("ff:ff:ff:ff:ff:ff", (struct ether_addr *)dst))
+			return BCME_USAGE_ERROR;
+	} else if (!strcmp(*argv, "ucast")) {
+		dst_ea = 2;
+		if (!*++argv) {
+			printf("EA of ucast dest of the packet needs to be provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		if (!wl_ether_atoe(*argv, (struct ether_addr *)dst))
+			return BCME_USAGE_ERROR;
+		/* Store it */
+		memcpy(ea, dst, ETHER_ADDR_LEN);
+	} else if (!wl_ether_atoe(*argv, (struct ether_addr *)dst))
+		return BCME_USAGE_ERROR;
+
+	dst += ETHER_ADDR_LEN;
+	tot += ETHER_ADDR_LEN;
+
+	if (!*++argv) {
+		printf("type - magic/net needs to be provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (strncmp(*argv, "magic", strlen("magic")) == 0)
+		type = WL_WOWL_MAGIC;
+	else if (strncmp(*argv, "net", strlen("net")) == 0)
+		type = WL_WOWL_NET;
+	else if (strncmp(*argv, "eapid", strlen("eapid")) == 0)
+		type = WL_WOWL_EAPID;
+	else
+		return BCME_USAGE_ERROR;
+
+	*((uint16*)dst) = type;
+	dst += sizeof(type);
+	tot += sizeof(type);
+
+	if (type == WL_WOWL_MAGIC) {
+		if (pkt_len < MAGIC_PKT_MINLEN)
+			return BCME_BADARG;
+
+		if (dst_ea == 2)
+			memcpy(dst, ea, ETHER_ADDR_LEN);
+		else {
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+
+			if (!wl_ether_atoe(*argv, (struct ether_addr *)dst))
+				return BCME_USAGE_ERROR;
+		}
+		tot += ETHER_ADDR_LEN;
+	} else if (type == WL_WOWL_NET) {
+		wl_wowl_pattern_t *wl_pattern;
+		wl_pattern = (wl_wowl_pattern_t *)dst;
+
+		if (!*++argv) {
+			printf("Starting offset not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		wl_pattern->offset = (uint)htod32(strtoul(*argv, NULL, 0));
+
+		wl_pattern->masksize = 0;
+
+		wl_pattern->patternoffset = (uint)htod32(sizeof(wl_wowl_pattern_t));
+
+		dst += sizeof(wl_wowl_pattern_t);
+
+		if (!*++argv) {
+			printf("pattern not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		wl_pattern->patternsize =
+		        (uint)htod32(wl_pattern_atoh((char *)(uintptr)*argv, dst));
+		dst += wl_pattern->patternsize;
+		tot += sizeof(wl_wowl_pattern_t) + wl_pattern->patternsize;
+
+		wl_pattern->reasonsize = 0;
+		if (*++argv) {
+			wl_pattern->reasonsize =
+				(uint)htod32(wl_pattern_atoh((char *)(uintptr)*argv, dst));
+			tot += wl_pattern->reasonsize;
+		}
+	} else {	/* eapid */
+		if (!*++argv) {
+			printf("EAPOL identity string not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		*dst++ = strlen(*argv);
+		strncpy(dst, *argv, strlen(*argv));
+		tot += 1 + strlen(*argv);
+	}
+	return (wlu_set(wl, WLC_SET_VAR, arg, tot));
+}
+
+static int
+wl_wowl_pattern(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint i, j;
+	uint8 *ptr;
+	wl_wowl_pattern_t *wl_pattern;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		char *arg = buf;
+		const char *str;
+		char *dst;
+		uint tot = 0;
+
+		if (strcmp(*argv, "add") != 0 && strcmp(*argv, "del") != 0 &&
+		    strcmp(*argv, "clr") != 0) {
+			return BCME_USAGE_ERROR;
+		}
+
+		str = "wowl_pattern";
+		strncpy(arg, str, strlen(str));
+		arg[strlen(str)] = '\0';
+		dst = arg + strlen(str) + 1;
+		tot += strlen(str) + 1;
+
+		str = *argv;
+		strncpy(dst, str, strlen(str));
+		tot += strlen(str) + 1;
+
+		if (strcmp(str, "clr") != 0) {
+			wl_pattern = (wl_wowl_pattern_t *)(dst + strlen(str) + 1);
+			dst = (char*)wl_pattern + sizeof(wl_wowl_pattern_t);
+			if (!*++argv) {
+				printf("Starting offset not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+			wl_pattern->offset = htod32(strtoul(*argv, NULL, 0));
+			if (!*++argv) {
+				printf("Mask not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Parse the mask */
+			str = *argv;
+			wl_pattern->masksize = htod32(wl_pattern_atoh((char *)(uintptr)str, dst));
+			if (wl_pattern->masksize == (uint)-1)
+				return BCME_USAGE_ERROR;
+
+			dst += wl_pattern->masksize;
+			wl_pattern->patternoffset = htod32((sizeof(wl_wowl_pattern_t) +
+			                                    wl_pattern->masksize));
+
+			if (!*++argv) {
+				printf("Pattern value not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Parse the value */
+			str = *argv;
+			wl_pattern->patternsize =
+			        htod32(wl_pattern_atoh((char *)(uintptr)str, dst));
+			if (wl_pattern->patternsize == (uint)-1)
+				return BCME_USAGE_ERROR;
+			tot += sizeof(wl_wowl_pattern_t) + wl_pattern->patternsize +
+			        wl_pattern->masksize;
+		}
+
+		return (wlu_set(wl, WLC_SET_VAR, arg, tot));
+	} else {
+		wl_wowl_pattern_list_t *list;
+		if ((err = wlu_iovar_get(wl, "wowl_pattern", buf, WLC_IOCTL_MAXLEN)) < 0)
+			return err;
+		list = (wl_wowl_pattern_list_t *)buf;
+		printf("#of patterns :%d\n", list->count);
+		ptr = (uint8 *)list->pattern;
+		for (i = 0; i < list->count; i++) {
+			uint8 *pattern;
+
+			wl_pattern = (wl_wowl_pattern_t *)ptr;
+			printf("Pattern %d:\n", i+1);
+			printf("ID         :0x%x\n"
+				"Offset     :%d\n"
+				"Masksize   :%d\n"
+				"Mask       :0x",
+				(uint32)wl_pattern->id, wl_pattern->offset, wl_pattern->masksize);
+			pattern = ((uint8 *)wl_pattern + sizeof(wl_wowl_pattern_t));
+			for (j = 0; j < wl_pattern->masksize; j++)
+				printf("%02x", pattern[j]);
+			printf("\n"
+			       "PatternSize:%d\n"
+			       "Pattern    :0x", wl_pattern->patternsize);
+			/* Go to end to find pattern */
+			pattern = ((uint8*)wl_pattern + wl_pattern->patternoffset);
+			for (j = 0; j < wl_pattern->patternsize; j++)
+				printf("%02x", pattern[j]);
+			printf("\n\n");
+			ptr += (wl_pattern->masksize + wl_pattern->patternsize +
+			        sizeof(wl_wowl_pattern_t));
+		}
+	}
+
+	return err;
+}
+
+
+static int
+wl_wowl_extended_magic(void *wl, cmd_t *cmd, char **argv)
+{
+	char *arg = buf;
+	const char *str;
+	char *dst;
+	uint tot;
+	int ret;
+
+	str = "wowl_ext_magic";
+	strncpy(arg, str, strlen(str));
+	arg[strlen(str)] = '\0';
+
+	if (*++argv) {
+		dst = arg + strlen(str) + 1;
+		tot = strlen(str) + 1;
+		ret = wl_pattern_atoh(*argv, dst);
+		if (ret == -1)
+			return BCME_USAGE_ERROR;
+		if (ret != 6) {
+			printf("Extended magic pattern must be 6-byte length\n");
+			return BCME_USAGE_ERROR;
+		}
+		tot += 6;
+
+		ret = wlu_set(wl, cmd->set, arg, tot);
+		return ret;
+	}
+
+
+	if ((ret = wlu_get(wl, cmd->get, arg, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	printf("0x");
+	for (ret = 0; ret < 6; ret++)
+		printf("%02x", (uint8)arg[ret]);
+	printf("\n");
+
+	return 0;
+
+}
+
+
+static int
+wl_rifs(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int val, rifs;
+	char *val_name;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* command name */
+	val_name = *argv++;
+
+	if (!*argv) {
+		if ((err = wlu_iovar_getint(wl, val_name, (int*)&rifs)) < 0)
+			return err;
+
+		printf("%s\n", ((rifs & 0xff) ? "On" : "Off"));
+		return 0;
+	}
+
+	val = rifs = (atoi(*argv) ? 1 : 0);
+	if (rifs != 0 && rifs != 1)
+		return BCME_USAGE_ERROR;
+
+	if ((err = wlu_set(wl, WLC_SET_FAKEFRAG, &val, sizeof(int))) < 0) {
+		printf("Set frameburst error %d\n", err);
+		return err;
+	}
+	if ((err = wlu_iovar_setint(wl, val_name, (int)rifs)) < 0)
+		printf("Set rifs error %d\n", err);
+
+	return err;
+}
+
+static int
+wl_rifs_advert(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int rifs_advert;
+	char *val_name;
+
+	BCM_REFERENCE(cmd);
+
+	/* command name */
+	val_name = *argv++;
+
+	if (!*argv) {
+		if ((err = wlu_iovar_getint(wl, val_name, (int*)&rifs_advert)) < 0)
+			return err;
+
+		printf("%s\n", ((rifs_advert & 0xff) ? "On" : "Off"));
+		return 0;
+	}
+
+	if (strcmp(*argv, "-1") && strcmp(*argv, "0"))
+		return BCME_USAGE_ERROR;
+
+	rifs_advert = atoi(*argv);
+
+	if ((err = wlu_iovar_setint(wl, val_name, (int)rifs_advert)) < 0)
+		printf("Set rifs mode advertisement error %d\n", err);
+
+	return err;
+}
+
+/* this is the batched command packet size. now for remoteWL, we set it to 512 bytes */
+#define MEMBLOCK (512 - 32) /* allow 32 bytes for overhead (header, alignment, etc) */
+
+int wl_seq_batch_in_client(bool enable)
+{
+	batch_in_client = enable;
+	return 0;
+}
+
+
+int
+wl_seq_start(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if (!batch_in_client) {
+		return wlu_iovar_setbuf(wl, "seq_start", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+	}
+	else {
+		if (cmd_batching_mode) {
+			printf("calling seq_start() when it's already in batching mode\n");
+			clean_up_cmd_list();
+			cmd_batching_mode = FALSE;
+			return BCME_USAGE_ERROR;
+		}
+		else {
+			cmd_batching_mode = TRUE;
+			cmd_pkt_list_num = 0;
+
+			cmd_list.head = NULL;
+			cmd_list.tail = NULL;
+		}
+	}
+
+	return 0;
+}
+
+int
+wl_seq_stop(void *wl, cmd_t *cmd, char **argv)
+{
+	char *bufp;
+	int ret = 0;
+	int seq_list_len;
+	int len;
+	wl_seq_cmd_pkt_t *next_cmd;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if (!batch_in_client) {
+		return wlu_iovar_setbuf(wl, "seq_stop", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+	}
+	else {
+		if (!cmd_batching_mode) {
+			printf("calling seq_stop when it's already out of batching mode\n");
+			return BCME_USAGE_ERROR;
+		}
+		cmd_batching_mode = FALSE;
+
+		next_cmd = cmd_list.head;
+
+		/* dump batched commands to the DUT */
+
+		if (next_cmd == NULL) {
+			printf("no command batched\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		ret = wlu_iovar_setbuf(wl, "seq_start", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+		if (ret) {
+			printf("failed to send seq_start\n");
+			goto fail;
+		}
+
+		while (next_cmd != NULL) {
+			bufp = buf;
+			memset(bufp, 0, WLC_IOCTL_MAXLEN);
+
+			strcpy(bufp, "seq_list");
+			bufp += (strlen("seq_list") + 1);
+			bufp = ALIGN_ADDR(bufp, WL_SEQ_CMD_ALIGN_BYTES);
+			seq_list_len = bufp - buf;
+
+			while ((seq_list_len < MEMBLOCK) && (next_cmd != NULL)) {
+				len = ROUNDUP(next_cmd->cmd_header.len, WL_SEQ_CMD_ALIGN_BYTES);
+				len += (seq_list_len + sizeof(wl_seq_cmd_ioctl_t));
+
+				if (len < MEMBLOCK) {
+					memcpy(bufp, &(next_cmd->cmd_header),
+						sizeof(wl_seq_cmd_ioctl_t));
+					bufp += sizeof(wl_seq_cmd_ioctl_t);
+					memcpy(bufp, next_cmd->data, next_cmd->cmd_header.len);
+					bufp += next_cmd->cmd_header.len;
+					bufp = ALIGN_ADDR(bufp, WL_SEQ_CMD_ALIGN_BYTES);
+					seq_list_len = len;
+
+					next_cmd = next_cmd->next;
+				}
+				else
+					break;
+			}
+
+			ret = wl_set(wl, WLC_SET_VAR, &buf[0], seq_list_len);
+
+			if (ret) {
+				printf("failed to send seq_list\n");
+				goto fail;
+			}
+		}
+
+		ret = wlu_iovar_setbuf(wl, "seq_stop", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+		if (ret) {
+			printf("failed to send seq_stop\n");
+		}
+
+	fail:
+		clean_up_cmd_list();
+		return ret;
+	}
+}
+
+static int
+wl_obss_scan_params_range_chk(wl_obss_scan_arg_t *obss_scan_arg)
+{
+	if (obss_scan_arg->passive_dwell < 0)
+		obss_scan_arg->passive_dwell = WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT;
+	else if (obss_scan_arg->passive_dwell < WLC_OBSS_SCAN_PASSIVE_DWELL_MIN ||
+		obss_scan_arg->passive_dwell > WLC_OBSS_SCAN_PASSIVE_DWELL_MAX) {
+		printf("passive dwell not in range %d\n", obss_scan_arg->passive_dwell);
+		return -1;
+	}
+
+	if (obss_scan_arg->active_dwell < 0)
+		obss_scan_arg->active_dwell = WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT;
+	else if (obss_scan_arg->active_dwell < WLC_OBSS_SCAN_ACTIVE_DWELL_MIN ||
+		obss_scan_arg->active_dwell > WLC_OBSS_SCAN_ACTIVE_DWELL_MAX) {
+		printf("active dwell not in range %d\n", obss_scan_arg->active_dwell);
+		return -1;
+	}
+
+	if (obss_scan_arg->bss_widthscan_interval < 0)
+		obss_scan_arg->bss_widthscan_interval =
+			WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT;
+	else if (obss_scan_arg->bss_widthscan_interval < WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN ||
+		obss_scan_arg->bss_widthscan_interval > WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX) {
+		printf("Width Trigger Scan Interval not in range %d\n",
+		       obss_scan_arg->bss_widthscan_interval);
+		return -1;
+	}
+
+	if (obss_scan_arg->chanwidth_transition_delay < 0)
+		obss_scan_arg->chanwidth_transition_delay =
+			WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT;
+	else if ((obss_scan_arg->chanwidth_transition_delay <
+		WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN) ||
+		(obss_scan_arg->chanwidth_transition_delay >
+		WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX)) {
+		printf("Width Channel Transition Delay Factor not in range %d\n",
+		       obss_scan_arg->chanwidth_transition_delay);
+		return -1;
+	}
+
+	if (obss_scan_arg->passive_total < 0)
+		obss_scan_arg->passive_total = WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT;
+	else if (obss_scan_arg->passive_total < WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN ||
+		obss_scan_arg->passive_total > WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX) {
+		printf("Passive Total per Channel not in range %d\n", obss_scan_arg->passive_total);
+		return -1;
+	}
+
+	if (obss_scan_arg->active_total < 0)
+		obss_scan_arg->active_total = WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT;
+	if (obss_scan_arg->active_total < WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN ||
+		obss_scan_arg->active_total > WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX) {
+		printf("Active Total per Channel not in range %d\n", obss_scan_arg->active_total);
+		return -1;
+	}
+
+	if (obss_scan_arg->activity_threshold < 0)
+		obss_scan_arg->activity_threshold = WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT;
+	else if (obss_scan_arg->activity_threshold < WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN ||
+		obss_scan_arg->activity_threshold > WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX) {
+		printf("Activity Threshold not in range %d\n", obss_scan_arg->activity_threshold);
+		return -1;
+	}
+	return 0;
+}
+
+/* Send a periodic keep-alive packet at the specificed interval. */
+static int
+wl_keep_alive(void *wl, cmd_t *cmd, char **argv)
+{
+	const char 				*str;
+	wl_keep_alive_pkt_t	keep_alive_pkt;
+	wl_keep_alive_pkt_t	*keep_alive_pktp;
+	int						buf_len;
+	int						str_len;
+	int						i;
+	int 						rc;
+	void						*ptr = NULL;
+
+
+	if (*++argv == NULL) {
+	   /*
+	   ** Get current keep-alive status.
+	   */
+		if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return rc;
+
+		keep_alive_pktp = (wl_keep_alive_pkt_t *) ptr;
+
+		printf("Period (msec) :%d\n"
+		       "Length        :%d\n"
+		       "Packet        :0x",
+		       dtoh32(keep_alive_pktp->period_msec),
+		       dtoh16(keep_alive_pktp->len_bytes));
+
+		for (i = 0; i < keep_alive_pktp->len_bytes; i++)
+			printf("%02x", keep_alive_pktp->data[i]);
+
+		printf("\n");
+	}
+	else {
+		/*
+		** Set keep-alive attributes.
+		*/
+
+		str = "keep_alive";
+		str_len = strlen(str);
+		strncpy(buf, str, str_len);
+		buf[ str_len ] = '\0';
+
+		keep_alive_pktp = (wl_keep_alive_pkt_t *) (buf + str_len + 1);
+		keep_alive_pkt.period_msec = htod32(strtoul(*argv, NULL, 0));
+		buf_len = str_len + 1;
+
+
+		if (keep_alive_pkt.period_msec == 0) {
+			keep_alive_pkt.len_bytes = 0;
+
+			buf_len += sizeof(wl_keep_alive_pkt_t);
+		}
+		else {
+			if (NULL != *++argv) {
+				keep_alive_pkt.len_bytes =
+				htod16(wl_pattern_atoh(*argv, (char *) keep_alive_pktp->data));
+				buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes);
+			}
+			else {
+				keep_alive_pkt.len_bytes = 0;
+				buf_len += WL_KEEP_ALIVE_FIXED_LEN;
+			}
+		}
+
+		/* Keep-alive attributes are set in local	variable (keep_alive_pkt), and
+		 * then memcpy'ed into buffer (keep_alive_pktp) since there is no
+		 * guarantee that the buffer is properly aligned.
+		 */
+		memcpy((char *)keep_alive_pktp, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN);
+
+
+		rc = wlu_set(wl,
+		            WLC_SET_VAR,
+		            buf,
+		            buf_len);
+
+	}
+
+	return (rc);
+}
+
+/* mkeep-alive : Send a periodic keep-alive packet or null-data at the specificed interval. */
+/* wowl_keepalive : Send a periodic keep alive packet the specificed interval in wowl mode. */
+static int
+wl_mkeep_alive(void *wl, cmd_t *cmd, char **argv)
+{
+	const char 				*str;
+	wl_mkeep_alive_pkt_t	mkeep_alive_pkt;
+	wl_mkeep_alive_pkt_t	*mkeep_alive_pktp;
+	int						buf_len;
+	int						str_len;
+	int						len_bytes;
+	int						i;
+	int 					rc;
+	void					*ptr = NULL;
+
+	memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t));
+
+	str = *argv;  /* mkeep_alive or wowl_keepalive */
+	if (*++argv == NULL) {
+		return BCME_USAGE_ERROR;
+	}
+	else {
+		/* read the packet index */
+		int mkeep_alive_id = htod32(strtoul(*argv, NULL, 0));
+
+		if (*++argv == NULL) {
+			/*
+			** Get current keep-alive status.
+			*/
+			if ((rc = wlu_var_getbuf(wl, cmd->name, &mkeep_alive_id,
+				sizeof(int), &ptr)) < 0)
+				return rc;
+
+			mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) ptr;
+
+			printf("Id            :%d\n"
+				   "Period (msec) :%d\n"
+				   "Length        :%d\n"
+				   "Packet        :0x",
+				   mkeep_alive_pktp->keep_alive_id,
+				   dtoh32(mkeep_alive_pktp->period_msec),
+				   dtoh16(mkeep_alive_pktp->len_bytes));
+
+			for (i = 0; i < mkeep_alive_pktp->len_bytes; i++)
+				printf("%02x", mkeep_alive_pktp->data[i]);
+
+			printf("\n");
+			return rc;
+		}
+
+		str_len = strlen(str);
+		strncpy(buf, str, str_len);
+		buf[ str_len ] = '\0';
+		mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1);
+		mkeep_alive_pkt.period_msec = htod32(strtoul(*argv, NULL, 0));
+		buf_len = str_len + 1;
+		mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
+		mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
+		mkeep_alive_pkt.keep_alive_id = mkeep_alive_id;
+
+		len_bytes = 0;
+
+		buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
+		if (mkeep_alive_pkt.period_msec != 0) {
+			if (NULL != *++argv) {
+				len_bytes = wl_pattern_atoh(*argv, (char *) mkeep_alive_pktp->data);
+				buf_len += len_bytes;
+			}
+		}
+		mkeep_alive_pkt.len_bytes = htod16(len_bytes);
+
+		/* Keep-alive attributes are set in local	variable (mkeep_alive_pkt), and
+		 * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no
+		 * guarantee that the buffer is properly aligned.
+		 */
+		memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN);
+
+		rc = wlu_set(wl,
+		            WLC_SET_VAR,
+		            buf,
+		            buf_len);
+
+	}
+
+	return (rc);
+}
+
+
+/* Enable/disable installed packet filter. */
+static int
+wl_pkt_filter_enable(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkt_filter_enable_t	enable_parm;
+	int							rc;
+
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse packet filter id. */
+	enable_parm.id = htod32(strtoul(*argv, NULL, 0));
+
+	if (*++argv == NULL) {
+		printf("Enable/disable value not provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse enable/disable value. */
+	enable_parm.enable = htod32(strtoul(*argv, NULL, 0));
+
+
+	/* Enable/disable the specified filter. */
+	rc = wlu_var_setbuf(wl,
+	                   cmd->name,
+	                   &enable_parm,
+	                   sizeof(wl_pkt_filter_enable_t));
+
+	return (rc);
+}
+
+
+/* Install a new packet filter. */
+static int
+wl_pkt_filter_add(void *wl, cmd_t *cmd, char **argv)
+{
+	const char          *str;
+	wl_pkt_filter_t     pkt_filter;
+	wl_pkt_filter_t     *pkt_filterp;
+	int                 buf_len;
+	int                 str_len;
+	int                 rc;
+	uint32              mask_size;
+	uint32              pattern_size;
+
+	UNUSED_PARAMETER(cmd);
+
+	str = "pkt_filter_add";
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[ str_len ] = '\0';
+	buf_len = str_len + 1;
+
+	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+
+	/* Parse packet filter id. */
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	pkt_filter.id = htod32(strtoul(*argv, NULL, 0));
+
+	/* Parse filter polarity. */
+	if (*++argv == NULL) {
+		printf("Polarity not provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	pkt_filter.negate_match = htod32(strtoul(*argv, NULL, 0));
+
+	/* Parse filter type. */
+	if (*++argv == NULL) {
+		printf("Filter type not provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	pkt_filter.type = htod32(strtoul(*argv, NULL, 0));
+	if ((pkt_filter.type != WL_PKT_FILTER_TYPE_PATTERN_MATCH) &&
+		(pkt_filter.type != WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT)) {
+		printf("Invalid filter type %d\n", pkt_filter.type);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Handle basic pattern filter */
+	if (pkt_filter.type == WL_PKT_FILTER_TYPE_PATTERN_MATCH) {
+		wl_pkt_filter_pattern_t *pfilter = &pkt_filterp->u.pattern;
+
+		/* Parse pattern filter offset. */
+		if (*++argv == NULL) {
+			printf("Offset not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		pkt_filter.u.pattern.offset = htod32(strtoul(*argv, NULL, 0));
+
+		/* Parse pattern filter mask. */
+		if (*++argv == NULL) {
+			printf("Bitmask not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc = wl_pattern_atoh(*argv, (char *)pfilter->mask_and_pattern);
+		if (rc <= 0) {
+			printf("Invalid mask provided: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		mask_size = htod32(rc);
+
+		/* Parse pattern filter pattern. */
+		if (*++argv == NULL) {
+			printf("Pattern not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc = wl_pattern_atoh(*argv, (char *)&pfilter->mask_and_pattern[rc]);
+		if (rc <= 0) {
+		printf("Invalid pattern provided: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		pattern_size = htod32(rc);
+
+		if (mask_size != pattern_size) {
+			printf("Mask and pattern not the same size\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		pkt_filter.u.pattern.size_bytes = mask_size;
+		buf_len += WL_PKT_FILTER_FIXED_LEN;
+		buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * rc);
+
+		/* The fields that were put in a local for alignment purposes now
+		 * get copied to the right place in the ioctl buffer.
+		 */
+		memcpy((char *)pkt_filterp, &pkt_filter,
+		       WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+	}
+
+	/* Handle pattern filter with timeout event */
+	if (pkt_filter.type == WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT) {
+		wl_pkt_filter_pattern_timeout_t *pfilter = &pkt_filterp->u.pattern_timeout;
+
+		/* Parse pattern filter offset. */
+		if (*++argv == NULL) {
+			printf("Offset not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		pkt_filter.u.pattern.offset = htod32(strtoul(*argv, NULL, 0));
+
+		/* Parse pattern filter mask. */
+		if (*++argv == NULL) {
+			printf("Bitmask not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc = wl_pattern_atoh(*argv, (char *)pfilter->mask_and_pattern);
+		if (rc <= 0) {
+			printf("Invalid mask provided: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		mask_size = htod32(rc);
+
+		/* Parse pattern filter pattern. */
+		if (*++argv == NULL) {
+			printf("Pattern not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc = wl_pattern_atoh(*argv, (char *)&pfilter->mask_and_pattern[rc]);
+		if (rc <= 0) {
+			printf("Rejecting: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		pattern_size = htod32(rc);
+
+		if (mask_size != pattern_size) {
+			printf("Mask and pattern not the same size\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (*++argv == NULL) {
+			printf("timeout not specified\n");
+			return BCME_USAGE_ERROR;
+		}
+		pkt_filter.u.pattern_timeout.timeout = htod32(strtoul(*argv, NULL, 0));
+		pkt_filter.u.pattern.size_bytes = mask_size;
+		buf_len += WL_PKT_FILTER_FIXED_LEN;
+		buf_len += (WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN + 2 * rc);
+
+		/* The fields that were put in a local for alignment purposes now
+		 * get copied to the right place in the ioctl buffer.
+		 */
+		memcpy((char *)pkt_filterp, &pkt_filter,
+				WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN);
+	}
+
+	rc = wlu_set(wl, WLC_SET_VAR, buf, buf_len);
+
+	return (rc);
+}
+
+static void
+wl_pkt_filter_list_mask_pat(uint8 *bytes, uint size, char *indent)
+{
+	uint j;
+
+	printf("%sMask        :0x", indent);
+
+	for (j = 0; j < size; j++)
+		printf("%02x", bytes[j]);
+
+	printf("\n%sPattern     :0x", indent);
+
+	for (; j < 2 * size; j++)
+		printf("%02x", bytes[j]);
+
+	printf("\n\n");
+}
+
+/* List installed packet filters. */
+static int
+wl_pkt_filter_list(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkt_filter_list_t	*list;
+	wl_pkt_filter_t		*filterp;
+	void						*ptr = NULL;
+	unsigned int			i;
+	int 						rc;
+	unsigned int			filter_len;
+	uint32					enable;
+
+
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse filter list to retrieve (enabled/disabled). */
+	enable = htod32(strtoul(*argv, NULL, 0));
+	/*
+	** Get list of installed packet filters.
+	*/
+	if ((rc = wlu_var_getbuf(wl, cmd->name, &enable, sizeof(enable), &ptr)) < 0)
+		return rc;
+
+	list = (wl_pkt_filter_list_t *) ptr;
+
+	printf("Num filters: %d\n\n", list->num);
+
+	filterp = list->filter;
+	for (i = 0; i < list->num; i++)
+	{
+		uint type = dtoh32(filterp->type);
+
+		if (type == WL_PKT_FILTER_TYPE_PATTERN_MATCH) {
+			printf("Id          :%d\n"
+			       "Negate      :%d\n"
+			       "Type        :%d\n"
+			       "Offset      :%d\n"
+			       "Pattern len :%d\n",
+			       dtoh32(filterp->id),
+			       dtoh32(filterp->negate_match),
+			       dtoh32(filterp->type),
+			       dtoh32(filterp->u.pattern.offset),
+			       dtoh32(filterp->u.pattern.size_bytes));
+
+			wl_pkt_filter_list_mask_pat(filterp->u.pattern.mask_and_pattern,
+			                            dtoh32(filterp->u.pattern.size_bytes), "");
+			filter_len = WL_PKT_FILTER_PATTERN_FIXED_LEN +
+			        2 * dtoh32(filterp->u.pattern.size_bytes);
+		} else if (type == WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT) {
+			printf("Id          :%d\n"
+				"Negate      :%d\n"
+				"Type        :%d\n"
+				"Offset      :%d\n"
+				"Pattern len :%d\n"
+				"Timeout     :%d seconds\n",
+				dtoh32(filterp->id),
+				dtoh32(filterp->negate_match),
+				dtoh32(filterp->type),
+				dtoh32(filterp->u.pattern_timeout.offset),
+				dtoh32(filterp->u.pattern_timeout.size_bytes),
+				dtoh32(filterp->u.pattern_timeout.timeout));
+
+			wl_pkt_filter_list_mask_pat(filterp->u.pattern_timeout.mask_and_pattern,
+							dtoh32(filterp->u.pattern_timeout.size_bytes), "");
+			filter_len = WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN +
+					2 * dtoh32(filterp->u.pattern_timeout.size_bytes);
+		}
+
+		filter_len += WL_PKT_FILTER_FIXED_LEN;
+		filterp = (wl_pkt_filter_t *) ((uint8 *)filterp + filter_len);
+		filterp = ALIGN_ADDR(filterp, sizeof(uint32));
+
+	}
+
+	return (rc);
+}
+
+
+/* Get packet filter debug statistics. */
+static int
+wl_pkt_filter_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkt_filter_stats_t	*stats;
+	uint32						id;
+	int 							rc;
+	void							*ptr = NULL;
+
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse filter id to retrieve. */
+	id = htod32(strtoul(*argv, NULL, 0));
+
+
+	/* Get debug stats. */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, &id, sizeof(id), &ptr)) < 0)
+		return rc;
+
+	stats = (wl_pkt_filter_stats_t *) ptr;
+
+	printf("Packets matched for filter '%d': %d\n"
+			 "Total packets discarded        : %d\n"
+			 "Total packet forwarded         : %d\n",
+			 id,
+			 dtoh32(stats->num_pkts_matched),
+			 dtoh32(stats->num_pkts_discarded),
+			 dtoh32(stats->num_pkts_forwarded));
+
+	return (rc);
+}
+
+#ifdef TRAFFIC_MGMT
+/* Get/set traffic management configuration. */
+static int
+wl_trf_mgmt_config(void *wl, cmd_t *cmd, char **argv)
+{
+	uint		    argc = 0;
+	uint32		    i;
+	trf_mgmt_config_t   *ptrf_mgmt_config;
+	uint8		    buf[sizeof(trf_mgmt_config_t)];
+	int		    buf_len;
+	char		    *endptr = NULL;
+	int		    rc = -1;
+	void		    *ptr = NULL;
+
+	if (!*++argv) {
+	   /*
+	    * Get current traffic management configuration.
+	    */
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)ptr;
+
+	    printf("Enabled                   : %d\n",
+	        dtoh32(ptrf_mgmt_config->trf_mgmt_enabled));
+	    printf("Host IP Address           : %s\n",
+	        wl_iptoa((void *)&ptrf_mgmt_config->host_ip_addr));
+	    printf("Host IP Subnet Mask       : %s\n",
+	        wl_iptoa((void *)&ptrf_mgmt_config->host_subnet_mask));
+	    printf("Downlink Bandwidth        : %d\n",
+	        dtoh32(ptrf_mgmt_config->downlink_bandwidth));
+	    printf("Uplink Bandwidth          : %d\n",
+	        dtoh32(ptrf_mgmt_config->uplink_bandwidth));
+	    printf("\n");
+
+	    printf("Minimum Tx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[0]));
+	    printf("Minimum Tx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[1]));
+	    printf("Minimum Tx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[2]));
+	    printf("\n");
+
+	    printf("Minimum Rx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_rx_bandwidth[0]));
+	    printf("Minimum Rx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_rx_bandwidth[1]));
+	    printf("Minimum Rx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_rx_bandwidth[2]));
+	    printf("\n");
+
+	    printf("Flags                     : 0x%04X\n",
+	        dtoh32(ptrf_mgmt_config->flags));
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required	arguments */
+	    if ((argc != 1) && (argc != 5) && (argc != 6)) {
+		fprintf(stderr,	"Too few/many arguments	(require 1 or 5 or 6 , got %d)\n", argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)buf;
+	    buf_len	     = sizeof(trf_mgmt_config_t);
+	    memset((uint8 *)buf, 0, buf_len);
+
+	    ptrf_mgmt_config->trf_mgmt_enabled = htod32((int32)strtol(*argv++, &endptr,	0));
+	    if (*endptr	!= '\0') {
+		return BCME_USAGE_ERROR;
+	    }
+
+	    if (argc > 1) {
+		if (ptrf_mgmt_config->trf_mgmt_enabled)	{
+		    if (!wl_atoip(*argv++, (void *)&ptrf_mgmt_config->host_ip_addr)) {
+			return BCME_USAGE_ERROR;
+		    }
+		    if (!wl_atoip(*argv++, (void *)&ptrf_mgmt_config->host_subnet_mask)) {
+			return BCME_USAGE_ERROR;
+		    }
+		    ptrf_mgmt_config->downlink_bandwidth =
+		        htod32((int32)strtol(*argv++, &endptr, 0));
+		    ptrf_mgmt_config->uplink_bandwidth =
+		        htod32((int32)strtol(*argv++, &endptr, 0));
+
+		    /*
+		     * Zero-fill min bandwidth based. This will	cause the driver to use
+		     * defult settings
+		     */
+		    for	(i = 0;	i < TRF_MGMT_MAX_PRIORITIES; i++) {
+			ptrf_mgmt_config->min_tx_bandwidth[i] =	0;
+			ptrf_mgmt_config->min_rx_bandwidth[i] =	0;
+		    }
+
+		    if (argc ==	6) {
+			ptrf_mgmt_config->flags	= htod32((int32)strtol(*argv++,	&endptr, 0));
+		    }
+		} else {
+		    return BCME_BADARG;
+		}
+	    }
+
+	    rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_config, buf_len);
+	}
+	return rc;
+}
+#endif  /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Sets a traffic management filter. */
+static int
+wl_trf_mgmt_filters_add(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *param;
+	char                    *endptr = NULL;
+	int                     rc = -1;
+
+	(void)param;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc != 4) {
+	    fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 4, argc);
+	    return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	ptrf_mgmt_filter->priority = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+/* Sets a traffic management filter L2/L3/L4 */
+static int
+wl_trf_mgmt_filters_addex(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *param;
+	char                    *endptr = NULL;
+	int                     rc = -1;
+
+	(void)param;
+	(void)cmd;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc < 3) {
+		fprintf(stderr, "Too few arguments (require > 3  got %d)\n", argc);
+		return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->flags = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	if (ptrf_mgmt_filter->flags & TRF_FILTER_MAC_ADDR) {
+
+		if (argc != 3) {
+			fprintf(stderr, "Too many arguments (require 3 got %d)\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		if (!wl_ether_atoe(*argv++, &ptrf_mgmt_filter->dst_ether_addr))
+			return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->priority = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+	} else {
+		/* required arguments */
+		if (argc != 5) {
+			fprintf(stderr, "Too few/many arguments (require 5 got %d)\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+			    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+			    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->priority = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+			    return BCME_USAGE_ERROR;
+	}
+
+	rc = wlu_var_setbuf(wl, "trf_mgmt_filters_add", ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+#endif  /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Removes a traffic management filter. */
+static int
+wl_trf_mgmt_filters_remove(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *endptr = NULL;
+	char                    *param;
+	int                     rc = -1;
+
+	(void)param;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc != 3) {
+	    fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 3, argc);
+	    return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+	ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+	ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+	rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+
+/* Removes a traffic management filter for L2/L3/L4 */
+static int
+wl_trf_mgmt_filters_removeex(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *endptr = NULL;
+	char                    *param;
+	int                     rc = -1;
+
+	(void)param;
+	(void)cmd;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc < 2) {
+	    fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 2, argc);
+	    return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->flags = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0') {
+		return BCME_USAGE_ERROR;
+	}
+	if (ptrf_mgmt_filter->flags & TRF_FILTER_MAC_ADDR) {
+
+		if (argc != 2) {
+			fprintf(stderr, "Too many arguments (require 2 got %d)\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		if (!wl_ether_atoe(*argv++, &ptrf_mgmt_filter->dst_ether_addr)) {
+			return BCME_USAGE_ERROR;
+		}
+
+	} else {
+		if (argc < 4) {
+			fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 4, argc);
+			return BCME_USAGE_ERROR;
+		}
+		ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+		if (*endptr != '\0')
+		    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+		if (*endptr != '\0')
+		    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+		if (*endptr != '\0')
+		    return BCME_USAGE_ERROR;
+	}
+
+	rc = wlu_var_setbuf(wl, "trf_mgmt_filters_remove", ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+#endif  /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* lists the current traffic management filters. */
+static int
+wl_trf_mgmt_filters_list(void *wl, cmd_t *cmd, char **argv)
+{
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint                    i;
+	int                     rc = -1;
+	void                    *ptr = NULL;
+
+	UNUSED_PARAMETER(argv);
+
+	/*
+	 * Get current traffic management filters.
+	 */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+	    return rc;
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)ptr;
+
+	printf("Number of filters : %d\n", dtoh32(ptrf_mgmt_filter_list->num_filters));
+
+	for (i = 0; i < ptrf_mgmt_filter_list->num_filters; i++) {
+	    ptrf_mgmt_filter = &ptrf_mgmt_filter_list->filter[i];
+
+		if (ptrf_mgmt_filter->flags & TRF_FILTER_MAC_ADDR) {
+			printf("\n");
+			printf("Filter #%d\n", i);
+			printf("Flags    : 0x%02x\n", dtoh32(ptrf_mgmt_filter->flags));
+			printf("Dst EtherAddr    : %s\n",
+				wl_ether_etoa(&ptrf_mgmt_filter->dst_ether_addr));
+			printf("Priority : %d\n", dtoh32(ptrf_mgmt_filter->priority));
+		} else {
+			printf("\n");
+			printf("Filter #%d\n", i);
+			printf("Dst Port : %d\n", dtoh32(ptrf_mgmt_filter->dst_port));
+			printf("Src Port : %d\n", dtoh32(ptrf_mgmt_filter->src_port));
+			printf("Protocol : %d\n", dtoh32(ptrf_mgmt_filter->prot));
+			printf("Flags    : 0x%02x\n", dtoh32(ptrf_mgmt_filter->flags));
+			printf("Priority : %d\n", dtoh32(ptrf_mgmt_filter->priority));
+		}
+	}
+
+	return rc;
+}
+#endif  /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Clears the traffic management filters. */
+static int
+wl_trf_mgmt_filters_clear(void *wl, cmd_t *cmd, char **argv)
+{
+	int rc = -1;
+
+	UNUSED_PARAMETER(argv);
+
+	rc = wlu_var_setbuf(wl, cmd->name, NULL, 0);
+
+	return rc;
+}
+#endif  /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/*
+ * Get/set traffic management bandwidth configuration. We support the ability to get/set just the
+ * bandwidth parameters in the global trf_mgmt_config_t structure.
+ */
+static int
+wl_trf_mgmt_bandwidth(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                argc = 0;
+	trf_mgmt_config_t   *ptrf_mgmt_config;
+	uint8               buf[sizeof(trf_mgmt_config_t)];
+	int                 buf_len;
+	char                *endptr = NULL;
+	int                 i, total_bandwidth;
+	int                 rc = -1;
+	void                *ptr = NULL;
+
+	if (!*++argv) {
+	   /*
+	    * Get current traffic management bandwidth settings.
+	    */
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)ptr;
+
+	    printf("Downlink Bandwidth        : %d\n",
+	        dtoh32(ptrf_mgmt_config->downlink_bandwidth));
+	    printf("Uplink Bandwidth          : %d\n",
+	        dtoh32(ptrf_mgmt_config->uplink_bandwidth));
+	    printf("\n");
+
+	    printf("Minimum Tx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[0]));
+	    printf("Minimum Tx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[1]));
+	    printf("Minimum Tx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[2]));
+	    printf("\n");
+
+	    printf("Minimum Rx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[0]));
+	    printf("Minimum Rx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[1]));
+	    printf("Minimum Rx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[2]));
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc < 5) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 5, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)buf;
+	    buf_len          = sizeof(trf_mgmt_config_t);
+
+	    memcpy(buf, ptr, buf_len);
+
+	    ptrf_mgmt_config->downlink_bandwidth = htod32((int32)strtol(*argv++, &endptr, 0));
+	    if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	    ptrf_mgmt_config->uplink_bandwidth = htod32((int32)strtol(*argv++, &endptr, 0));
+	    if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	    for (i = 0, total_bandwidth = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		ptrf_mgmt_config->min_tx_bandwidth[i] =
+		    htod32((int32)strtol(*argv++, &endptr, 0));
+
+		if (*endptr != '\0')
+		   return BCME_USAGE_ERROR;
+		total_bandwidth += ptrf_mgmt_config->min_tx_bandwidth[i];
+	    }
+
+	    if (total_bandwidth != 100) {
+		fprintf(stderr,
+		    "Sum of gauranteed bandwidth levels must equal 100 (got %d)\n",
+		    total_bandwidth);
+		return BCME_BADARG;
+	    }
+
+	    if (argc > 5) {
+		for (i = 0, total_bandwidth = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		    ptrf_mgmt_config->min_rx_bandwidth[i] =
+		        htod32((int32)strtol(*argv++, &endptr, 0));
+
+		    if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+		    total_bandwidth += ptrf_mgmt_config->min_rx_bandwidth[i];
+		}
+
+		if (total_bandwidth != 100) {
+		    fprintf(stderr,
+		        "Sum of gauranteed rx bandwidth levels must equal 100 (got %d)\n",
+		        total_bandwidth);
+		    return BCME_BADARG;
+		}
+	    } else {
+		for (i = 0, total_bandwidth = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		    ptrf_mgmt_config->min_rx_bandwidth[i] = ptrf_mgmt_config->min_tx_bandwidth[i];
+		}
+	    }
+
+	    rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_config, buf_len);
+	}
+
+	return rc;
+}
+#endif /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/*
+ * Get/set traffic management operational flags. We use this to change flags that
+ * can't be set by GUI. This allows us to configure certain options that we may want to
+ * enable/disable in the shipping product.
+ */
+static int
+wl_trf_mgmt_flags(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                argc = 0;
+	uint32              flags;
+	char                *endptr = NULL;
+	int                 rc = -1;
+	void                *ptr = NULL;
+
+	if (!*++argv) {
+	   /*
+	    * Get current traffic management bandwidth settings.
+	    */
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    flags = *(uint32 *)ptr;
+
+	    printf("Flags : 0x%04X\n", flags);
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc != 1) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 1, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    flags = htod32((int32)strtol(*argv++, &endptr, 0));
+	    if (*endptr != '\0') {
+		return BCME_USAGE_ERROR;
+	    }
+	    rc = wlu_var_setbuf(wl, cmd->name, &flags, sizeof(uint32));
+	}
+
+	return rc;
+}
+#endif /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Print traffic management statistics. */
+static void
+wl_trf_mgmt_print_stats(void *ptr, uint index)
+{
+	trf_mgmt_stats_array_t  *ptrf_mgmt_statistics_array;
+	trf_mgmt_stats_t        *ptrf_mgmt_statistics;
+
+	ptrf_mgmt_statistics_array = (trf_mgmt_stats_array_t *)ptr;
+
+	ptrf_mgmt_statistics = &ptrf_mgmt_statistics_array->tx_queue_stats[index];
+
+	printf("Statistics for Tx Queue[%d]\n", index);
+	printf("\n");
+	printf("Num. packets processed : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_packets));
+	printf("Num. bytes processed   : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_bytes));
+	printf("Num. packets discarded : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_discarded_packets));
+
+	ptrf_mgmt_statistics = &ptrf_mgmt_statistics_array->rx_queue_stats[index];
+
+	printf("\n");
+	printf("Statistics for Rx Queue[%d]\n", index);
+	printf("\n");
+	printf("Num. packets processed : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_packets));
+	printf("Num. bytes processed   : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_bytes));
+	printf("Num. packets discarded : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_discarded_packets));
+
+	printf("\n");
+}
+#endif /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Get traffic management statistics. */
+static int
+wl_trf_mgmt_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	uint    argc = 0;
+	uint    i;
+	int     rc = -1;
+	char    *endptr = NULL;
+	void    *ptr = NULL;
+
+	/*
+	 * Get current traffic management statistics.
+	 */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+	    return rc;
+
+	if (!*++argv) {
+	    /*
+	     * Print all of the current traffic management statistics.
+	     */
+	    for (i = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		wl_trf_mgmt_print_stats(ptr, i);
+	    }
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc != 1) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 1, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    i = htod16((int16)strtol(*argv, &endptr, 0));
+	    if (i >= TRF_MGMT_MAX_PRIORITIES) {
+		fprintf(stderr, "Index must be < %d)\n", TRF_MGMT_MAX_PRIORITIES);
+		return BCME_BADARG;
+	    }
+
+	    /* Print the current traffic management statistics for the specified queue index. */
+	    wl_trf_mgmt_print_stats(ptr, i);
+	}
+
+
+	return rc;
+}
+#endif /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Clears the traffic management statistics. */
+static int
+wl_trf_mgmt_stats_clear(void *wl, cmd_t *cmd, char **argv)
+{
+	int rc = -1;
+
+	UNUSED_PARAMETER(argv);
+
+	rc = wlu_var_setbuf(wl, cmd->name, NULL, 0);
+
+	return rc;
+}
+#endif /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Print traffic management shaping info. */
+static void
+wl_trf_mgmt_print_global_shaping_info(void *ptr)
+{
+	trf_mgmt_shaping_info_array_t   *ptrf_mgmt_shaping_info_array;
+	trf_mgmt_global_info_t          *ptrf_mgmt_global_info;
+
+	ptrf_mgmt_shaping_info_array = (trf_mgmt_shaping_info_array_t *)ptr;
+
+	ptrf_mgmt_global_info = &ptrf_mgmt_shaping_info_array->tx_global_shaping_info;
+
+	printf("Global shaping info. for Tx Queues\n");
+	printf("\n");
+	printf("Maximum bytes/second                      : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_second);
+	printf("Maximum bytes/sampling period             : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_sampling_period);
+	printf("Total bytes consumed per second           : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_second);
+	printf("Total bytes consumed per sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_sampling_period);
+	printf("Unused bytes for current sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_unused_bytes_per_sampling_period);
+
+	printf("\n");
+
+	ptrf_mgmt_global_info = &ptrf_mgmt_shaping_info_array->rx_global_shaping_info;
+
+	printf("Global shaping info. for Rx Queues\n");
+	printf("\n");
+	printf("Maximum bytes/second                      : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_second);
+	printf("Maximum bytes/sampling period             : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_sampling_period);
+	printf("Total bytes consumed per second           : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_second);
+	printf("Total bytes consumed per sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_sampling_period);
+	printf("Unused bytes for current sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_unused_bytes_per_sampling_period);
+
+	printf("\n");
+}
+#endif /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+static void
+wl_trf_mgmt_print_shaping_info(void *ptr, uint index)
+{
+	trf_mgmt_shaping_info_array_t   *ptrf_mgmt_shaping_info_array;
+	trf_mgmt_shaping_info_t         *ptrf_mgmt_shaping_info;
+
+	ptrf_mgmt_shaping_info_array = (trf_mgmt_shaping_info_array_t *)ptr;
+
+	ptrf_mgmt_shaping_info = &ptrf_mgmt_shaping_info_array->tx_queue_shaping_info[index];
+
+	printf("Shaping info. for Tx Queue[%d]\n", index);
+	printf("\n");
+	printf("Gauranteed bandwidth percentage  : %d%%\n",
+	    dtoh32(ptrf_mgmt_shaping_info->gauranteed_bandwidth_percentage));
+	printf("Guaranteed bytes/second          : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_second));
+	printf("Guaranteed bytes/sampling period : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_sampling_period));
+	printf("Num. bytes produced per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_produced_per_second));
+	printf("Num. bytes consumed per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_consumed_per_second));
+	printf("Num. packets pending             : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_packets));
+	printf("Num. bytes pending               : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_bytes));
+
+	ptrf_mgmt_shaping_info = &ptrf_mgmt_shaping_info_array->rx_queue_shaping_info[index];
+
+	printf("\n");
+	printf("Shaping info. for Rx Queue[%d]\n", index);
+	printf("\n");
+	printf("Gauranteed bandwidth percentage  : %d%%\n",
+	    dtoh32(ptrf_mgmt_shaping_info->gauranteed_bandwidth_percentage));
+	printf("Guaranteed bytes/second          : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_second));
+	printf("Guaranteed bytes/sampling period : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_sampling_period));
+	printf("Num. bytes produced per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_produced_per_second));
+	printf("Num. bytes consumed per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_consumed_per_second));
+	printf("Num. packets pending             : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_packets));
+	printf("Num. bytes pending               : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_bytes));
+
+	printf("\n");
+}
+#endif /* TRAFFIC_MGMT */
+
+#ifdef TRAFFIC_MGMT
+/* Get traffic management shaping info. */
+static int
+wl_trf_mgmt_shaping_info(void *wl, cmd_t *cmd, char **argv)
+{
+	uint    argc = 0;
+	uint    i;
+	int     rc = -1;
+	char    *endptr = NULL;
+	void    *ptr = NULL;
+
+	/*
+	 * Get current traffic management shaping info.
+	 */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+	    return rc;
+
+	if (!*++argv) {
+	    /*
+	     * Print all of the current traffic management shaping info.
+	     */
+	    wl_trf_mgmt_print_global_shaping_info(ptr);
+
+	    for (i = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		wl_trf_mgmt_print_shaping_info(ptr, i);
+	    }
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc != 1) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 1, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    i = htod16((int16)strtol(*argv, &endptr, 0));
+	    if (i >= TRF_MGMT_MAX_PRIORITIES) {
+		fprintf(stderr, "Index must be < %d)\n", TRF_MGMT_MAX_PRIORITIES);
+		return BCME_BADARG;
+	    }
+
+	    /* Print the current traffic management shaping info for the specified queue index. */
+	    wl_trf_mgmt_print_global_shaping_info(ptr);
+	    wl_trf_mgmt_print_shaping_info(ptr, i);
+	}
+
+
+	return rc;
+}
+#endif  /* TRAFFIC_MGMT */
+
+static int
+wl_obss_scan(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_obss_scan_arg_t obss_scan_arg;
+	char *endptr = NULL;
+	uint buflen;
+	uint argc = 0;
+
+	if (!*++argv) {
+		void *ptr = NULL;
+		wl_obss_scan_arg_t *obss_scan_param;
+
+		err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr);
+		if (err < 0)
+		        return err;
+
+		obss_scan_param = (wl_obss_scan_arg_t *)ptr;
+		printf("%d %d %d %d %d %d %d\n",
+		       dtoh16(obss_scan_param->passive_dwell),
+		       dtoh16(obss_scan_param->active_dwell),
+		       dtoh16(obss_scan_param->bss_widthscan_interval),
+		       dtoh16(obss_scan_param->passive_total),
+		       dtoh16(obss_scan_param->active_total),
+		       dtoh16(obss_scan_param->chanwidth_transition_delay),
+		       dtoh16(obss_scan_param->activity_threshold));
+		return 0;
+	}
+
+	/* arg count */
+	while (argv[argc])
+		argc++;
+
+	buflen = WL_OBSS_SCAN_PARAM_LEN;
+	memset((uint8 *)&obss_scan_arg, 0, buflen);
+
+	/* required argments */
+	if (argc < WL_MIN_NUM_OBSS_SCAN_ARG) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n",
+			WL_MIN_NUM_OBSS_SCAN_ARG, argc);
+		return BCME_USAGE_ERROR;
+	}
+
+	obss_scan_arg.passive_dwell = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.active_dwell = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.bss_widthscan_interval = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.passive_total = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.active_total = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.chanwidth_transition_delay = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.activity_threshold = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	if (wl_obss_scan_params_range_chk(&obss_scan_arg))
+		return BCME_RANGE;
+
+	err = wlu_var_setbuf(wl, cmd->name, &obss_scan_arg, buflen);
+
+	return err;
+}
+
+#ifdef RWL_WIFI
+/* Function added to support RWL_WIFI Transport
+* Used to find the remote server with proper mac address given by
+* the user,this cmd is specific to RWL_WIFIi protocol
+*/
+static int wl_wifiserver(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	if ((ret = wlu_iovar_set(wl, cmd->name, *argv, strlen(*argv))) < 0) {
+		printf("Error finding the remote server  %s\n", argv[0]);
+		return ret;
+	}
+	return ret;
+}
+#endif
+static int
+wl_obss_coex_action(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	char var[256];
+	wl_action_obss_coex_req_t *req = (wl_action_obss_coex_req_t *)var;
+	int val;
+	int num = 0;
+	uint8 options = 0;
+
+	argv++;
+	memset(&var, 0, sizeof(wl_action_obss_coex_req_t));
+	while (*argv) {
+		if (!strncmp(*argv, "-i", 2) && ((options & 0x1) != 0x1)) {
+			argv++;
+			if (!*argv)
+				return BCME_USAGE_ERROR;
+			val = atoi(*argv);
+			if ((val != 0) && (val != 1))
+				return BCME_BADARG;
+			req->info |= val ? WL_COEX_40MHZ_INTOLERANT : 0;
+			options |= 0x1;
+		}
+		else if (!strncmp(*argv, "-w", 2) && ((options & 0x2) != 0x2)) {
+			argv++;
+			if (!*argv)
+				return BCME_USAGE_ERROR;
+			val = atoi(*argv);
+			if ((val != 0) && (val != 1))
+				return BCME_BADARG;
+			req->info |= val ? WL_COEX_WIDTH20 : 0;
+			options |= 0x2;
+		}
+		else if (!strncmp(*argv, "-c", 2) && ((options & 0x4) != 0x4)) {
+			argv++;
+			while (*argv) {
+				if (isdigit((unsigned char)(**argv))) {
+					val = htod32(strtoul(*argv, NULL, 0));
+					if ((val == 0) || (val > 14)) {
+						printf("Invalid channel %d\n", val);
+						return BCME_BADARG;
+					}
+					req->ch_list[num] = (uint8)val;
+					num++;
+					argv++;
+					if (num > 14) {
+						printf("Too many channels (max 14)\n");
+						return BCME_BADARG;
+					}
+				} else
+					break;
+			}
+			if (!num) {
+				printf("With option '-c' specified, a channel list is required\n");
+				return BCME_BADARG;
+			}
+			req->num = num;
+			options |= 0x4;
+			continue;
+		}
+		else
+			return BCME_USAGE_ERROR;
+		argv++;
+	}
+	if (!options)
+		return BCME_BADARG;
+	err = wlu_var_setbuf(wl, cmd->name, &var, (sizeof(wl_action_obss_coex_req_t) +
+		(req->num ? (req->num - 1) * sizeof(uint8) : 0)));
+	return err;
+}
+
+static int
+wl_srchmem(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	struct args {
+		int reg;
+		uint32 ssidlen;
+		uint8 ssid[DOT11_MAX_SSID_LEN];
+	} x;
+	char *endptr;
+	uint argc;
+	char *iovar;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&x, 0, sizeof(x));
+
+	/* save command name */
+	iovar = argv[0];
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: reg offset */
+	if (argc < 1)
+		return BCME_USAGE_ERROR;
+
+	x.reg = strtol(argv[0], &endptr, 0);
+	if (*endptr != '\0' || x.reg > 15)
+		return BCME_USAGE_ERROR;
+
+	if (argc > 2)
+		return BCME_USAGE_ERROR;
+
+	if (argc == 2) {
+		uint32 len;
+
+		len = strlen(argv[1]);
+		if (len > sizeof(x.ssid)) {
+			printf("ssid too long\n");
+			return BCME_BADARG;
+		}
+		memcpy(x.ssid, argv[1], len);
+		x.ssidlen = len;
+	}
+
+	/* issue the get or set ioctl */
+	if (argc == 1) {
+		x.reg = htod32(x.reg);
+
+		ret = wlu_iovar_getbuf(wl, iovar, &x, sizeof(x), buf, WLC_IOCTL_SMLEN);
+		if (ret < 0) {
+			printf("get returned error 0x%x\n", ret);
+			return (ret);
+		}
+
+		wl_hexdump((uchar *)buf, sizeof(x.ssidlen) + sizeof(x.ssid));
+	} else {
+		x.reg = htod32(x.reg);
+		x.ssidlen = htod32(x.ssidlen);
+
+		ret = wlu_iovar_set(wl, iovar, &x, sizeof(x));
+		if (ret < 0) {
+			printf("set returned error 0x%x\n", ret);
+			return (ret);
+		}
+	}
+
+	return (ret);
+}
+
+cntry_name_t cntry_names[] = {
+
+{"AFGHANISTAN",		"AF"},
+{"ALBANIA",		"AL"},
+{"ALGERIA",		"DZ"},
+{"AMERICAN SAMOA",	"AS"},
+{"ANDORRA",		"AD"},
+{"ANGOLA",		"AO"},
+{"ANGUILLA",		"AI"},
+{"ANTARCTICA",		"AQ"},
+{"ANTIGUA AND BARBUDA",	"AG"},
+{"ARGENTINA",		"AR"},
+{"ARMENIA",		"AM"},
+{"ARUBA",		"AW"},
+{"ASCENSION ISLAND",	"AC"},
+{"AUSTRALIA",		"AU"},
+{"AUSTRIA",		"AT"},
+{"AZERBAIJAN",		"AZ"},
+{"BAHAMAS",		"BS"},
+{"BAHRAIN",		"BH"},
+{"BANGLADESH",		"BD"},
+{"BARBADOS",		"BB"},
+{"BELARUS",		"BY"},
+{"BELGIUM",		"BE"},
+{"BELIZE",		"BZ"},
+{"BENIN",		"BJ"},
+{"BERMUDA",		"BM"},
+{"BHUTAN",		"BT"},
+{"BOLIVIA",		"BO"},
+{"BOSNIA AND HERZEGOVINA",		"BA"},
+{"BOTSWANA",		"BW"},
+{"BOUVET ISLAND",	"BV"},
+{"BRAZIL",		"BR"},
+{"BRITISH INDIAN OCEAN TERRITORY",		"IO"},
+{"BRUNEI DARUSSALAM",	"BN"},
+{"BULGARIA",		"BG"},
+{"BURKINA FASO",	"BF"},
+{"BURUNDI",		"BI"},
+{"CAMBODIA",		"KH"},
+{"CAMEROON",		"CM"},
+{"CANADA",		"CA"},
+{"CAPE VERDE",		"CV"},
+{"CAYMAN ISLANDS",	"KY"},
+{"CENTRAL AFRICAN REPUBLIC",		"CF"},
+{"CHAD",		"TD"},
+{"CHILE",		"CL"},
+{"CHINA",		"CN"},
+{"CHRISTMAS ISLAND",	"CX"},
+{"CLIPPERTON ISLAND",	"CP"},
+{"COCOS (KEELING) ISLANDS",		"CC"},
+{"COLOMBIA",		"CO"},
+{"COMOROS",		"KM"},
+{"CONGO",		"CG"},
+{"CONGO, THE DEMOCRATIC REPUBLIC OF THE",		"CD"},
+{"COOK ISLANDS",	"CK"},
+{"COSTA RICA",		"CR"},
+{"COTE D'IVOIRE",	"CI"},
+{"CROATIA",		"HR"},
+{"CUBA",		"CU"},
+{"CYPRUS",		"CY"},
+{"CZECH REPUBLIC",	"CZ"},
+{"DENMARK",		"DK"},
+{"DJIBOUTI",		"DJ"},
+{"DOMINICA",		"DM"},
+{"DOMINICAN REPUBLIC",	"DO"},
+{"ECUADOR",		"EC"},
+{"EGYPT",		"EG"},
+{"EL SALVADOR",		"SV"},
+{"EQUATORIAL GUINEA",	"GQ"},
+{"ERITREA",		"ER"},
+{"ESTONIA",		"EE"},
+{"ETHIOPIA",		"ET"},
+{"FALKLAND ISLANDS (MALVINAS)",		"FK"},
+{"FAROE ISLANDS",	"FO"},
+{"FIJI",		"FJ"},
+{"FINLAND",		"FI"},
+{"FRANCE",		"FR"},
+{"FRENCH GUIANA",	"GF"},
+{"FRENCH POLYNESIA",	"PF"},
+{"FRENCH SOUTHERN TERRITORIES",		"TF"},
+{"GABON",		"GA"},
+{"GAMBIA",		"GM"},
+{"GEORGIA",		"GE"},
+{"GERMANY",		"DE"},
+{"GHANA",		"GH"},
+{"GIBRALTAR",		"GI"},
+{"GREECE",		"GR"},
+{"GREENLAND",		"GL"},
+{"GRENADA",		"GD"},
+{"GUADELOUPE",		"GP"},
+{"GUAM",		"GU"},
+{"GUATEMALA",		"GT"},
+{"GUERNSEY",		"GG"},
+{"GUINEA",		"GN"},
+{"GUINEA-BISSAU",	"GW"},
+{"GUYANA",		"GY"},
+{"HAITI",		"HT"},
+{"HEARD ISLAND AND MCDONALD ISLANDS",		"HM"},
+{"HOLY SEE (VATICAN CITY STATE)",		"VA"},
+{"HONDURAS",		"HN"},
+{"HONG KONG",		"HK"},
+{"HUNGARY",		"HU"},
+{"ICELAND",		"IS"},
+{"INDIA",		"IN"},
+{"INDONESIA",		"ID"},
+{"IRAN, ISLAMIC REPUBLIC OF",		"IR"},
+{"IRAQ",		"IQ"},
+{"IRELAND",		"IE"},
+{"ISRAEL",		"IL"},
+{"ITALY",		"IT"},
+{"JAMAICA",		"JM"},
+{"JAPAN",		"JP"},
+{"JERSEY",		"JE"},
+{"JORDAN",		"JO"},
+{"KAZAKHSTAN",		"KZ"},
+{"KENYA",		"KE"},
+{"KIRIBATI",		"KI"},
+{"KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF",		"KP"},
+{"KOREA, REPUBLIC OF",	"KR"},
+{"KUWAIT",		"KW"},
+{"KYRGYZSTAN",		"KG"},
+{"LAO PEOPLE'S DEMOCRATIC REPUBLIC",		"LA"},
+{"LATVIA",		"LV"},
+{"LEBANON",		"LB"},
+{"LESOTHO",		"LS"},
+{"LIBERIA",		"LR"},
+{"LIBYAN ARAB JAMAHIRIYA",		"LY"},
+{"LIECHTENSTEIN",	"LI"},
+{"LITHUANIA",		"LT"},
+{"LUXEMBOURG",		"LU"},
+{"MACAO",		"MO"},
+{"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF",		"MK"},
+{"MADAGASCAR",		"MG"},
+{"MALAWI",		"MW"},
+{"MALAYSIA",		"MY"},
+{"MALDIVES",		"MV"},
+{"MALI",		"ML"},
+{"MALTA",		"MT"},
+{"MAN, ISLE OF",	"IM"},
+{"MARSHALL ISLANDS",	"MH"},
+{"MARTINIQUE",		"MQ"},
+{"MAURITANIA",		"MR"},
+{"MAURITIUS",		"MU"},
+{"MAYOTTE",		"YT"},
+{"MEXICO",		"MX"},
+{"MICRONESIA, FEDERATED STATES OF",		"FM"},
+{"MOLDOVA, REPUBLIC OF",		"MD"},
+{"MONACO",		"MC"},
+{"MONGOLIA",		"MN"},
+{"MONTENEGRO",		"ME"},
+{"MONTSERRAT",		"MS"},
+{"MOROCCO",		"MA"},
+{"MOZAMBIQUE",		"MZ"},
+{"MYANMAR",		"MM"},
+{"NAMIBIA",		"NA"},
+{"NAURU",		"NR"},
+{"NEPAL",		"NP"},
+{"NETHERLANDS",		"NL"},
+{"NETHERLANDS ANTILLES",		"AN"},
+{"NEW CALEDONIA",	"NC"},
+{"NEW ZEALAND",		"NZ"},
+{"NICARAGUA",		"NI"},
+{"NIGER",		"NE"},
+{"NIGERIA",		"NG"},
+{"NIUE",		"NU"},
+{"NORFOLK ISLAND",		"NF"},
+{"NORTHERN MARIANA ISLANDS",		"MP"},
+{"NORWAY",		"NO"},
+{"OMAN",		"OM"},
+{"PAKISTAN",		"PK"},
+{"PALAU",		"PW"},
+{"PALESTINIAN TERRITORY, OCCUPIED",		"PS"},
+{"PANAMA",		"PA"},
+{"PAPUA NEW GUINEA",	"PG"},
+{"PARAGUAY",		"PY"},
+{"PERU",		"PE"},
+{"PHILIPPINES",		"PH"},
+{"PITCAIRN",		"PN"},
+{"POLAND",		"PL"},
+{"PORTUGAL",		"PT"},
+{"PUERTO RICO",		"PR"},
+{"QATAR",		"QA"},
+{"Q1",		"Q1"},
+{"REUNION",		"RE"},
+{"ROMANIA",		"RO"},
+{"RUSSIAN FEDERATION",	"RU"},
+{"RWANDA",		"RW"},
+{"SAINT HELENA",	"SH"},
+{"SAINT KITTS AND NEVIS",		"KN"},
+{"SAINT LUCIA",		"LC"},
+{"SAINT PIERRE AND MIQUELON",		"PM"},
+{"SAINT VINCENT AND THE GRENADINES",		"VC"},
+{"SAMOA",		"WS"},
+{"SAN MARINO",		"SM"},
+{"SAO TOME AND PRINCIPE",		"ST"},
+{"SAUDI ARABIA",	"SA"},
+{"SENEGAL",		"SN"},
+{"SERBIA",		"RS"},
+{"SEYCHELLES",		"SC"},
+{"SIERRA LEONE",	"SL"},
+{"SINGAPORE",		"SG"},
+{"SLOVAKIA",		"SK"},
+{"SLOVENIA",		"SI"},
+{"SOLOMON ISLANDS",	"SB"},
+{"SOMALIA",		"SO"},
+{"SOUTH AFRICA",	"ZA"},
+{"SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS",		"GS"},
+{"SPAIN",		"ES"},
+{"SRI LANKA",		"LK"},
+{"SUDAN",		"SD"},
+{"SURINAME",		"SR"},
+{"SVALBARD AND JAN MAYEN",		"SJ"},
+{"SWAZILAND",		"SZ"},
+{"SWEDEN",		"SE"},
+{"SWITZERLAND",		"CH"},
+{"SYRIAN ARAB REPUBLIC",		"SY"},
+{"TAIWAN, PROVINCE OF CHINA",		"TW"},
+{"TAJIKISTAN",		"TJ"},
+{"TANZANIA, UNITED REPUBLIC OF",		"TZ"},
+{"THAILAND",		"TH"},
+{"TIMOR-LESTE (EAST TIMOR)",		"TL"},
+{"TOGO",		"TG"},
+{"TOKELAU",		"TK"},
+{"TONGA",		"TO"},
+{"TRINIDAD AND TOBAGO",	"TT"},
+{"TRISTAN DA CUNHA",	"TA"},
+{"TUNISIA",		"TN"},
+{"TURKEY",		"TR"},
+{"TURKMENISTAN",	"TM"},
+{"TURKS AND CAICOS ISLANDS",		"TC"},
+{"TUVALU",		"TV"},
+{"UGANDA",		"UG"},
+{"UKRAINE",		"UA"},
+{"UNITED ARAB EMIRATES",		"AE"},
+{"UNITED KINGDOM",	"GB"},
+{"UNITED STATES",	"US"},
+{"UNITED STATES MINOR OUTLYING ISLANDS",		"UM"},
+{"URUGUAY",		"UY"},
+{"UZBEKISTAN",		"UZ"},
+{"VANUATU",		"VU"},
+{"VENEZUELA",		"VE"},
+{"VIET NAM",		"VN"},
+{"VIRGIN ISLANDS, BRITISH",		"VG"},
+{"VIRGIN ISLANDS, U.S.",		"VI"},
+{"WALLIS AND FUTUNA",	"WF"},
+{"WESTERN SAHARA",	"EH"},
+{"YEMEN",		"YE"},
+{"YUGOSLAVIA",		"YU"},
+{"ZAMBIA",		"ZM"},
+{"ZIMBABWE",		"ZW"},
+{"RADAR CHANNELS",	"RDR"},
+{"ALL CHANNELS",	"ALL"},
+{NULL,			NULL}
+};
+
+static void
+wl_print_mcsset(char *mcsset)
+{
+	int i;
+
+	printf("MCS SET : [ ");
+	for (i = 0; i < (MCSSET_LEN * 8); i++)
+		if (isset(mcsset, i))
+			printf("%d ", i);
+	printf("]\n");
+}
+
+static void
+wl_print_vhtmcsset(uint16 *mcsset)
+{
+	int i, j;
+
+	for (i = 0; i < VHT_CAP_MCS_MAP_NSS_MAX; i++) {
+		if (mcsset[i]) {
+			if (i == 0)
+				printf("VHT SET : ");
+			else
+				printf("        : ");
+			for (j = 0; j <= 9; j++)
+				if (isbitset(mcsset[i], j))
+					printf("%dx%d ", j, i + 1);
+			printf("\n");
+		} else {
+			break;
+		}
+	}
+}
+
+static int
+wl_txmcsset(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+
+	if ((err = wl_var_get(wl, cmd, argv)) < 0)
+		return err;
+	wl_print_mcsset(buf);
+
+	return err;
+}
+
+static int
+wl_rxmcsset(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+
+	if ((err = wl_var_get(wl, cmd, argv)) < 0)
+		return err;
+
+	wl_print_mcsset(buf);
+
+	return err;
+}
+
+static int
+wl_mimo_stf(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	int32 int_val;
+	bool get = TRUE;
+	uint32 len = 0;
+	void *ptr = NULL;
+	char *endptr;
+	int i = 0, j = 0;
+	int ret = 0;
+
+	while (argv[i])
+		i++;
+
+	if (i > 4)
+		return BCME_USAGE_ERROR;
+
+	/* toss the command name */
+	argv++;
+	j = 1;
+
+	if (i == 1) {
+		int_val = -1;
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+	else {
+		if (isdigit((unsigned char)(**argv))) {
+			get = FALSE;
+			int_val = htod32(strtoul(*argv, &endptr, 0));
+			if ((int_val != 0) && (int_val != 1)) {
+				fprintf(stderr, "wl mimo_ss_stf: bad stf mode.\n");
+				return BCME_BADARG;
+			}
+			memcpy(var, (char *)&int_val, sizeof(int_val));
+			len += sizeof(int_val);
+			argv++;
+			j++;
+		}
+
+		 if (j == i) {
+			int_val = -1;
+			memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+			len += sizeof(int_val);
+		}
+		else if (!strncmp(*argv, "-b", 2)) {
+			argv++;
+			j++;
+			if (j == i)
+				return BCME_BADARG;
+
+			if (!strcmp(*argv, "a"))
+				int_val = 1;
+			else if (!strcmp(*argv, "b"))
+				int_val = 0;
+			else {
+				fprintf(stderr,
+					"wl mimo_ss_stf: wrong -b option, \"-b a\" or \"-b b\"\n");
+				return BCME_USAGE_ERROR;
+			}
+			j++;
+			if (j < i)
+				return BCME_BADARG;
+			memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+			len += sizeof(int_val);
+		}
+	}
+
+	if (get) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0)
+			return ret;
+
+		printf("0x%x\n", dtoh32(*(int *)ptr));
+	}
+	else
+		ret = wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+#ifdef WLEXTLOG
+static int
+wl_extlog(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	char *endptr;
+	int err;
+	int from_last;
+	int i, j;
+	char *log_p = NULL;
+	wlc_extlog_req_t r_args;
+	wlc_extlog_results_t *results;
+	void *ptr = NULL;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 3)
+		return BCME_USAGE_ERROR;
+
+	if (argc == 1)
+		from_last = 0;
+	else {
+		from_last = htod32(strtoul(argv[1], &endptr, 0));
+		if ((from_last != 0) && (from_last != 1))
+			return BCME_BADARG;
+	}
+
+	r_args.from_last = from_last;
+	if (argc == 3)
+		r_args.num = htod32(strtoul(argv[2], &endptr, 0));
+	else
+		r_args.num = 32;
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, &r_args, sizeof(wlc_extlog_req_t), &ptr)) < 0)
+			return err;
+
+	results = (wlc_extlog_results_t *)buf;
+
+	printf("get external log records: %d\n", results->num);
+	if (!results->num)
+		return 0;
+
+	if (results->version != EXTLOG_CUR_VER) {
+		printf("version mismatch: version = 0x%x, expected 0x%0x\n",
+			results->version, EXTLOG_CUR_VER);
+		return 0;
+	}
+
+	log_p = (char *)&results->logs[0];
+
+	printf("Seq:\tTime(ms) Log\n");
+	for (i = 0; i < (int)results->num; i++) {
+		printf("%d:\t%d\t ", ((log_record_t*)log_p)->seq_num,
+			((log_record_t*)log_p)->time);
+		for (j = 0; j < FMTSTR_MAX_ID; j++)
+			if (((log_record_t*)log_p)->id == extlog_fmt_str[j].id)
+				break;
+		if (j == FMTSTR_MAX_ID) {
+			printf("fmt string not found for id %d\n", ((log_record_t*)log_p)->id);
+			log_p += results->record_len;
+			continue;
+		}
+
+		switch (extlog_fmt_str[j].arg_type) {
+			case LOG_ARGTYPE_NULL:
+				printf("%s", extlog_fmt_str[j].fmt_str);
+				break;
+
+			case LOG_ARGTYPE_STR:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->str);
+				break;
+
+			case LOG_ARGTYPE_INT:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->arg);
+				break;
+
+			case LOG_ARGTYPE_INT_STR:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->arg,
+					((log_record_t*)log_p)->str);
+				break;
+
+			case LOG_ARGTYPE_STR_INT:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->str,
+					((log_record_t*)log_p)->arg);
+				break;
+			}
+		log_p += results->record_len;
+	}
+
+	return 0;
+
+}
+
+static int
+wl_extlog_cfg(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	char *endptr;
+	wlc_extlog_cfg_t *r_cfg;
+	wlc_extlog_cfg_t w_cfg;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc == 1) {
+		err = wl_var_get(wl, cmd, argv);
+		if (err < 0)
+			return err;
+		r_cfg = (wlc_extlog_cfg_t *)buf;
+		printf("max_number=%d, module=%x, level=%d, flag=%d, version=0x%04x\n",
+			r_cfg->max_number, r_cfg->module, r_cfg->level,
+			r_cfg->flag, r_cfg->version);
+	}
+	else if (argc == 4) {
+		w_cfg.module = htod16((uint16)(strtoul(argv[1], &endptr, 0)));
+		w_cfg.level = (uint8)strtoul(argv[2], &endptr, 0);
+		w_cfg.flag = (uint8)strtoul(argv[3], &endptr, 0);
+		err = wlu_var_setbuf(wl, cmd->name, &w_cfg, sizeof(wlc_extlog_cfg_t));
+	}
+	else {
+		fprintf(stderr, "illegal command!\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	return err;
+}
+#endif /* WLEXTLOG */
+
+static int
+wl_assertlog(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err;
+	int i;
+	char *log_p = NULL;
+	assertlog_results_t *results;
+	void *ptr = NULL;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 1)
+		return BCME_USAGE_ERROR;
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+
+	results = (assertlog_results_t *)buf;
+
+	printf("get external assert logs: %d\n", results->num);
+	if (!results->num)
+		return 0;
+
+	if (results->version != ASSERTLOG_CUR_VER) {
+		printf("Version mismatch: version = 0x%x, expected 0x%x\n",
+			results->version, ASSERTLOG_CUR_VER);
+		return 0;
+	}
+
+	log_p = (char *)&results->logs[0];
+
+	printf("id: \ttime(ms) \tstring\n");
+	for (i = 0; i < (int)results->num; i++) {
+		printf("%d: \t%d \t%s", i, ((assert_record_t *)log_p)->time,
+			((assert_record_t *)log_p)->str);
+		log_p += results->record_len;
+	}
+
+	return 0;
+}
+
+extern cca_congest_channel_req_t *
+cca_per_chan_summary(cca_congest_channel_req_t *input,
+	cca_congest_channel_req_t *avg, bool percent);
+
+extern int
+cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer);
+
+static const char *
+cca_level(int score, int med, int hi)
+{
+	if (score < med)
+		return ("Low");
+	if (score >= med && score < hi)
+		return ("Medium");
+	if (score >= hi)
+		return ("High");
+	return NULL;
+}
+
+static const char *cca_errors[] = {
+	"No error",
+	"Preferred band",
+	"Dwell Duration too low",
+	"Channel prefs",
+	"Interference too high",
+	"Only 1 channel inoput"
+};
+
+static int
+wl_cca_get_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	cca_congest_channel_req_t *results;
+	cca_congest_channel_req_t req;
+	cca_congest_t *chptr;
+	cca_congest_channel_req_t *avg[MAX_CCA_CHANNELS]; /* Max num of channels */
+	void *ptr = NULL;
+	char *param, *val_p;
+	int base, limit, i, channel, err = 0;
+	int ibss_per, obss_per, inter_per, val;
+	const char *ibss_lvl = NULL;
+	const char *obss_lvl = NULL;
+	const char *inter_lvl = NULL;
+	int tmp_channel;
+	chanspec_t new_chanspec, cur_chanspec;
+	bool do_average = TRUE;
+	bool do_individ = FALSE;
+	bool do_analyze = TRUE;
+	bool curband = FALSE;
+	int avg_chan_idx = 0;
+	uint32 flags;
+
+
+	req.num_secs = 10;
+	tmp_channel = 0xff;
+
+	argv++;
+
+	/* Parse args */
+	while ((param = *argv++) != NULL) {
+		if (stricmp(param, "-n") == 0) {
+			do_analyze = FALSE;
+			continue;
+		}
+		if (stricmp(param, "-i") == 0) {
+			do_individ = TRUE;
+			continue;
+		}
+		if (stricmp(param, "-curband") == 0) {
+			curband = TRUE;
+			continue;
+		}
+
+		if ((val_p = *argv++) == NULL) {
+			printf("Need value following %s\n", param);
+			return BCME_USAGE_ERROR;
+		}
+		if (stricmp(param, "-c") == 0) {
+			tmp_channel = (int)strtoul(val_p, NULL, 0);
+		}
+
+		if (stricmp(param, "-cs") == 0) {
+			if ((new_chanspec = wf_chspec_aton(val_p)))
+				tmp_channel = wf_chspec_ctlchan(new_chanspec);
+		}
+
+		if (stricmp(param, "-s") == 0) {
+			req.num_secs = (int)strtoul(val_p, NULL, 0);
+			if (req.num_secs == 0 || req.num_secs > MAX_CCA_SECS) {
+				printf("%d: Num of seconds must be <= %d\n",
+					req.num_secs, MAX_CCA_SECS);
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+	if (!do_average && !do_individ) {
+		printf("Must pick at least one of averages or individual secs\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (tmp_channel == 0) {
+		/* do all channels */
+		base = 1; limit = 255;
+	} else {
+		/* Use current channel as default if none specified */
+		if (tmp_channel == 0xff) {
+			if ((err = wlu_iovar_getint(wl, "chanspec", (int*)&val)) < 0) {
+				printf("CCA: Can't get currrent chanspec\n");
+				return err;
+			}
+			cur_chanspec = wl_chspec32_from_driver(val);
+			tmp_channel = wf_chspec_ctlchan(cur_chanspec);
+			printf("Using channel %d\n", tmp_channel);
+		}
+		base = limit = tmp_channel;
+	}
+
+
+	for (channel = base; channel <= limit; channel++) {
+
+		/* Get stats for each channel */
+		req.chanspec = CH20MHZ_CHSPEC(channel);
+		req.chanspec = wl_chspec_to_driver(req.chanspec);
+		if ((err = wlu_var_getbuf(wl, cmd->name, &req, sizeof(req), &ptr)) < 0)
+			return err;
+
+		results = (cca_congest_channel_req_t *)ptr;
+		results->chanspec = wl_chspec_from_driver(results->chanspec);
+		if (results->chanspec == 0 || results->num_secs == 0)
+			continue;
+
+		if (results->num_secs > MAX_CCA_SECS) {
+			printf("Bogus num of seconds returned %d\n", results->num_secs);
+			return -1;
+		}
+
+		/* Summarize and save summary for this channel */
+		if (do_average) {
+			avg[avg_chan_idx] = (cca_congest_channel_req_t *)
+				malloc(sizeof(cca_congest_channel_req_t));
+			if (avg[avg_chan_idx] == NULL) {
+				printf("unable to allocate memory\n");
+				return BCME_NOMEM;
+			}
+			cca_per_chan_summary(results, avg[avg_chan_idx], 1);
+			if (avg[avg_chan_idx]->num_secs)
+				avg_chan_idx++;
+		}
+
+		/* printf stats for each second of each channel */
+		if (do_individ) {
+			if (channel == base)
+				printf("chan dur      ibss           obss"
+					"           interf       time\n");
+			for (i = 0; i < results->num_secs; i++) {
+				chptr = &results->secs[i];
+				if (chptr->duration) {
+					/* Percentages */
+					ibss_per = chptr->congest_ibss * 100 /chptr->duration;
+					obss_per = chptr->congest_obss * 100 /chptr->duration;
+					inter_per = chptr->interference * 100 /chptr->duration;
+					/* Levels */
+					ibss_lvl = cca_level(ibss_per, IBSS_MED, IBSS_HI);
+					obss_lvl = cca_level(obss_per, OBSS_MED, OBSS_HI);
+					inter_lvl = cca_level(inter_per, INTERFER_MED, INTERFER_HI);
+
+				printf("%-3u %4d %4u %2d%% %-6s %4u %2d%% %-6s %4u %2d%% %-6s %d\n",
+					CHSPEC_CHANNEL(results->chanspec),
+					chptr->duration,
+					chptr->congest_ibss, ibss_per, ibss_lvl,
+					chptr->congest_obss, obss_per, obss_lvl,
+					chptr->interference, inter_per, inter_lvl,
+					chptr->timestamp);
+				}
+			}
+		}
+	}
+
+	/* Print summary stats of each channel */
+	if (do_average) {
+		int j;
+		printf("Summaries:\n");
+		printf("chan dur      ibss           obss             interf     num seconds\n");
+		for (j = 0; j < avg_chan_idx; j++) {
+			/* Percentages */
+			ibss_per = avg[j]->secs[0].congest_ibss;
+			obss_per = avg[j]->secs[0].congest_obss;
+			inter_per = avg[j]->secs[0].interference;
+			/* Levels */
+			ibss_lvl = cca_level(ibss_per, IBSS_MED, IBSS_HI);
+			obss_lvl = cca_level(obss_per, OBSS_MED, OBSS_HI);
+			inter_lvl = cca_level(inter_per, INTERFER_MED, INTERFER_HI);
+
+			if (avg[j]->num_secs) {
+				printf("%-3u %4d %4s %2d%% %-6s %4s %2d%% %-6s %4s %2d%% %-6s %d\n",
+					CHSPEC_CHANNEL(avg[j]->chanspec),
+					avg[j]->secs[0].duration,
+					"", avg[j]->secs[0].congest_ibss, ibss_lvl,
+					"", avg[j]->secs[0].congest_obss, obss_lvl,
+					"", avg[j]->secs[0].interference, inter_lvl,
+					avg[j]->num_secs);
+			}
+		}
+	}
+
+	if (!do_analyze)
+		return err;
+
+	if ((err = wlu_iovar_getint(wl, "chanspec", (int *)&val)) < 0) {
+		printf("CCA: Can't get currrent chanspec\n");
+		return err;
+	}
+	cur_chanspec = wl_chspec32_from_driver(val);
+	flags = 0;
+	if (curband) {
+		if (CHSPEC_IS5G(cur_chanspec))
+			flags |= CCA_FLAG_5G_ONLY;
+		if (CHSPEC_IS2G(cur_chanspec))
+			flags |= CCA_FLAG_2G_ONLY;
+	}
+
+	if ((err = cca_analyze(avg,  avg_chan_idx, flags, &new_chanspec)) != 0) {
+		printf("Cannot find a good channel due to: %s\n", cca_errors[err]);
+		return BCME_ERROR;
+	}
+	printf("Recommended channel: %d\n", wf_chspec_ctlchan(new_chanspec));
+
+	return 0;
+}
+
+static int
+wl_itfr_get_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	interference_source_rep_t *iftr_stats = NULL;
+	const char *iftr_source[] = {"none", "wireless phone", "wireless video camera",
+		"microwave oven", "wireless baby monitor", "bluetooth device",
+		"wireless video camera or baby monitor", "bluetooth or baby monitor",
+		"video camera or phone", "unidentified"}; /* sync with interference_source_t */
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, (void*)&iftr_stats)) < 0)
+		return err;
+
+	if (iftr_stats->flags & ITFR_NOISY_ENVIRONMENT)
+		printf("Feature is stopped due to noisy environment\n");
+	else
+		printf("Interference %s detected. last interference at timestamp %d: "
+			"source is %s on %s channel\n",
+			(iftr_stats->flags & ITFR_INTERFERENCED) ? "is" : "is not",
+			iftr_stats->timestamp, iftr_source[iftr_stats->source],
+			(iftr_stats->flags & ITFR_HOME_CHANNEL) ? "home" : "non-home");
+
+	return err;
+}
+
+static int
+wl_chanim_acs_record(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err = 0, i;
+	wl_acs_record_t *result;
+
+	/* need to add to this str if new acs trigger type is added */
+	const char *trig_str[] = {"None", "IOCTL", "CHANIM", "TIMER", "BTA"};
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return err;
+
+	result = (wl_acs_record_t *) ptr;
+
+	if (!result->count) {
+		printf("There is no ACS recorded\n");
+		return err;
+	}
+
+	printf("current timestamp: %u (ms)\n", result->timestamp);
+
+	printf("Timestamp(ms)  ACS Trigger  Selected Channel  Glitch Count  CCA Count\n");
+	for (i = 0; i < result->count; i++) {
+		uint8 idx = CHANIM_ACS_RECORD - result->count + i;
+		chanim_acs_record_t * record = &result->acs_record[idx];
+
+		record->selected_chspc = wl_chspec_from_driver(record->selected_chspc);
+
+		printf("%10u \t%s \t%10d \t%12d \t%8d\n", record->timestamp,
+		   trig_str[record->trigger], wf_chspec_ctlchan(record->selected_chspc),
+		   record->glitch_cnt, record->ccastats);
+	}
+	return err;
+}
+
+static int
+wl_chanim_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_chanim_stats_t *list;
+	wl_chanim_stats_t param;
+	chanim_stats_t *stats;
+	void *ptr;
+	int j;
+
+	UNUSED_PARAMETER(argv);
+
+	param.buflen = htod32(sizeof(wl_chanim_stats_t));
+	param.count = htod32(WL_CHANIM_COUNT_ONE);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, &param, sizeof(wl_chanim_stats_t), &ptr)) < 0) {
+		printf("failed to get chanim results");
+		return err;
+	}
+
+	list = (wl_chanim_stats_t*)ptr;
+
+	list->buflen = dtoh32(list->buflen);
+	list->version = dtoh32(list->version);
+	list->count = dtoh32(list->count);
+
+	printf("version: %d \n", list->version);
+
+	if (list->buflen == 0) {
+		list->version = 0;
+		list->count = 0;
+	} else if (list->version != WL_CHANIM_STATS_VERSION) {
+		printf("Sorry, your driver has wl_chanim_stats version %d "
+			"but this program supports only version %d.\n",
+				list->version, WL_CHANIM_STATS_VERSION);
+		list->buflen = 0;
+		list->count = 0;
+	}
+
+	stats = list->stats;
+	stats->glitchcnt = htod32(stats->glitchcnt);
+	stats->badplcp = htod32(stats->badplcp);
+	stats->chanspec = htod16(stats->chanspec);
+	stats->timestamp = htod32(stats->timestamp);
+
+	printf("chanspec tx   inbss   obss   nocat   nopkt   doze     txop     "
+		   "goodtx  badtx   glitch   badplcp  knoise  idle  timestamp\n");
+	printf("0x%4x\t", stats->chanspec);
+	for (j = 0; j < CCASTATS_MAX; j++)
+		printf("%d\t", stats->ccastats[j]);
+	printf("%d\t%d\t%d\t%d\t%d", dtoh32(stats->glitchcnt), dtoh32(stats->badplcp),
+		stats->bgnoise, stats->chan_idle, dtoh32(stats->timestamp));
+	printf("\n");
+
+	return (err);
+}
+
+static int
+wl_txdelay_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	txdelay_params_t param;
+	int argc;
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current txdelay params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &param,
+			(sizeof(txdelay_params_t)))) < 0)
+			return (err);
+
+		printf("Txdelay params: ratio[%d] cnt[%d] period[%d] tune[%d]\n",
+			param.ratio, param.cnt,	param.period, param.tune);
+	}
+	else {
+		char *endptr;
+		/* Validate num of entries */
+		for (argc = 0; argv[argc]; argc++);
+		if (argc != 4)
+			return BCME_USAGE_ERROR;
+
+		argc = 0;
+		param.ratio = strtol(argv[argc], &endptr, 0);
+		argc++;
+		param.cnt = strtol(argv[argc], &endptr, 0);
+		argc++;
+		param.period = strtol(argv[argc], &endptr, 0);
+		argc++;
+		param.tune = strtol(argv[argc], &endptr, 0);
+
+		/* Set txdelay params */
+		err = wlu_iovar_set(wl, cmd->name, (void *) &param,
+			(sizeof(txdelay_params_t)));
+	}
+	return (err);
+}
+
+static int
+wl_intfer_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_intfer_params_t param;
+	int		argc;
+	char 	*endptr = NULL;
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current txdelay params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &param,
+			(sizeof(wl_intfer_params_t)))) < 0)
+			goto error;
+
+		if (param.version != INTFER_VERSION) {
+			printf("Interference params structure version (%d) is not the "
+				"version (%d) supported by this tool",
+				INTFER_VERSION, param.version);
+			err = BCME_USAGE_ERROR;
+		}
+		else
+			printf("Intference params: period[%x] cnt[%x] txfail_thresh[%x]"
+				" tcptxfail_thresh[%x]\n", param.period, param.cnt,
+				param.txfail_thresh, param.tcptxfail_thresh);
+	}
+	else {
+		/* Validate num of entries */
+		err = BCME_USAGE_ERROR;
+
+		for (argc = 0; argv[argc]; argc++);
+		if (argc != 4)
+			goto error;
+
+		param.period = (uint8)strtol(argv[0], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		param.cnt = (uint8)strtol(argv[1], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		param.txfail_thresh = (uint8)strtol(argv[2], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		param.tcptxfail_thresh = (uint8)strtol(argv[3], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		/* Set intfer params */
+		param.version = INTFER_VERSION;
+		err = wlu_iovar_set(wl, cmd->name, (void *) &param,
+			(sizeof(wl_intfer_params_t)));
+	}
+error:
+	return (err);
+}
+
+#ifdef WLP2P
+static int
+wl_p2p_state(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_disc_st_t st;
+	int count;
+	char *endptr;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count < 1)
+		return BCME_USAGE_ERROR;
+
+	st.state = (uint8) strtol(argv[0], &endptr, 0);
+	if (st.state == WL_P2P_DISC_ST_LISTEN) {
+		if (count != 3)
+			return BCME_USAGE_ERROR;
+		if ((st.chspec = wf_chspec_aton(argv[1])) == 0) {
+			fprintf(stderr, "error parsing chanspec arg \"%s\"\n", argv[1]);
+			return BCME_BADARG;
+		}
+		st.chspec = wl_chspec_to_driver(st.chspec);
+		if (st.chspec == INVCHANSPEC) {
+			return BCME_USAGE_ERROR;
+		}
+		st.dwell = (uint16) strtol(argv[2], &endptr, 0);
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &st, sizeof(st));
+}
+
+static int
+wl_p2p_scan(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_scan_t *params = NULL;
+	int params_size = 0;
+	int malloc_size = 0;
+	int sparams_size = 0;
+	int err = 0;
+
+	if (*(argv + 1) != NULL) {
+		malloc_size = sizeof(wl_p2p_scan_t);
+		switch (toupper(**(argv + 1))) {
+		case 'S':
+			malloc_size += WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+			break;
+		case 'E':
+			malloc_size += OFFSETOF(wl_escan_params_t, params) +
+			        WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+			break;
+		}
+	}
+	if (malloc_size == 0) {
+		fprintf(stderr, "wrong syntax, need 'S' or 'E'\n");
+		return BCME_BADARG;
+	}
+
+	malloc_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_p2p_scan_t *)malloc(malloc_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", malloc_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, malloc_size);
+
+	switch (toupper(**(argv + 1))) {
+	case 'S': {
+		wl_scan_params_t *sparams = (wl_scan_params_t *)(params+1);
+		sparams_size = malloc_size - sizeof(wl_p2p_scan_t);
+
+		params->type = 'S';
+
+		if ((err = wl_scan_prep(wl, cmd, argv + 1, sparams, &sparams_size)) == 0)
+			params_size = sizeof(wl_p2p_scan_t) + sparams_size;
+		break;
+	}
+
+	case 'E': {
+		wl_escan_params_t *eparams = (wl_escan_params_t *)(params+1);
+		sparams_size = malloc_size - sizeof(wl_p2p_scan_t) - sizeof(wl_escan_params_t);
+
+		params->type = 'E';
+
+		eparams->version = htod32(ESCAN_REQ_VERSION);
+		eparams->action = htod16(WL_SCAN_ACTION_START);
+
+		srand((unsigned)time(NULL));
+		eparams->sync_id = htod16(rand() & 0xffff);
+
+		if ((err = wl_scan_prep(wl, cmd, argv + 1, &eparams->params, &sparams_size)) == 0)
+			params_size = sizeof(wl_p2p_scan_t) + sizeof(wl_escan_params_t) +
+				sparams_size;
+		break;
+	}
+	}
+
+	if (!err)
+		err = wlu_iovar_setbuf(wl, cmd->name, params, params_size, buf, WLC_IOCTL_MAXLEN);
+
+	free(params);
+	return err;
+}
+
+static int
+wl_p2p_ifadd(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_if_t ifreq;
+	int count;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count < 2)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &ifreq.addr))
+		return BCME_USAGE_ERROR;
+
+	if (stricmp(argv[1], "go") == 0)
+		ifreq.type = WL_P2P_IF_GO;
+	else if (stricmp(argv[1], "client") == 0)
+		ifreq.type = WL_P2P_IF_CLIENT;
+	else if (stricmp(argv[1], "dyngo") == 0)
+		ifreq.type = WL_P2P_IF_DYNBCN_GO;
+	else
+		return BCME_USAGE_ERROR;
+
+	if (ifreq.type == WL_P2P_IF_GO || ifreq.type == WL_P2P_IF_DYNBCN_GO) {
+		if (count > 2) {
+			if ((ifreq.chspec = wf_chspec_aton(argv[2])) == 0) {
+				fprintf(stderr, "error parsing chanspec arg \"%s\"\n", argv[2]);
+				return BCME_BADARG;
+			}
+			ifreq.chspec = wl_chspec_to_driver(ifreq.chspec);
+			if (ifreq.chspec == INVCHANSPEC) {
+				return BCME_BADARG;
+			}
+		}
+		else
+			ifreq.chspec = 0;
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &ifreq, sizeof(ifreq));
+}
+
+static int
+wl_p2p_ifdel(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr addr;
+	int count;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count != 1)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &addr))
+		return BCME_USAGE_ERROR;
+
+	return wlu_var_setbuf(wl, cmd->name, &addr, sizeof(addr));
+}
+
+static int
+wl_p2p_ifupd(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_if_t ifreq;
+	int count;
+	int ret;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, cmd->name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+	argv += consumed;
+	if (consumed == 0)
+		bsscfg_idx = -1;
+
+	count = ARGCNT(argv);
+	if (count < 2)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &ifreq.addr))
+		return BCME_USAGE_ERROR;
+
+	if (stricmp(argv[1], "go") == 0)
+		ifreq.type = WL_P2P_IF_GO;
+	else if (stricmp(argv[1], "client") == 0)
+		ifreq.type = WL_P2P_IF_CLIENT;
+	else
+		return BCME_USAGE_ERROR;
+
+	ifreq.chspec = 0;
+
+	if (bsscfg_idx == -1)
+		return wlu_var_setbuf(wl, cmd->name, &ifreq, sizeof(ifreq));
+	return wlu_bssiovar_setbuf(wl, cmd->name, bsscfg_idx,
+	                          &ifreq, sizeof(ifreq),
+	                          buf, WLC_IOCTL_MAXLEN);
+}
+
+static int
+wl_p2p_if(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr addr;
+	int count;
+	wl_p2p_ifq_t *ptr;
+	int err;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count != 1)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &addr))
+		return BCME_USAGE_ERROR;
+
+	err = wlu_var_getbuf(wl, cmd->name, &addr, sizeof(addr), (void*)&ptr);
+	if (err >= 0)
+		printf("%u %s\n", dtoh32(ptr->bsscfgidx), (ptr->ifname));
+
+	return err;
+}
+
+static int
+wl_p2p_ops(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_ops_t ops;
+	int count;
+	char *endptr;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count < 1) {
+		wl_p2p_ops_t *ops;
+		int err;
+
+		err = wlu_var_getbuf(wl, cmd->name, NULL, 0, (void *)&ops);
+		if (err != BCME_OK) {
+			fprintf(stderr, "%s: error %d\n", cmd->name, err);
+			return err;
+		}
+
+		printf("ops: %u ctw: %u\n", ops->ops, ops->ctw);
+
+		return BCME_OK;
+	}
+
+	ops.ops = (uint8) strtol(argv[0], &endptr, 0);
+	if (ops.ops != 0) {
+		if (count != 2)
+			return BCME_USAGE_ERROR;
+		ops.ctw = (uint8) strtol(argv[1], &endptr, 0);
+	}
+	else
+		ops.ctw = 0;
+
+	return wlu_var_setbuf(wl, cmd->name, &ops, sizeof(ops));
+}
+
+static int
+wl_p2p_noa(void *wl, cmd_t *cmd, char **argv)
+{
+	int count;
+	wl_p2p_sched_t *noa;
+	int len;
+	int i;
+	char *endptr;
+
+	argv ++;
+
+	strcpy(buf, cmd->name);
+
+	count = ARGCNT(argv);
+	if (count < 2) {
+		int err = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_MAXLEN);
+		wl_p2p_sched_t *sched;
+		int i;
+
+		if (err != BCME_OK) {
+			fprintf(stderr, "%s: error %d\n", cmd->name, err);
+			return err;
+		}
+
+		sched = (wl_p2p_sched_t *)buf;
+		for (i = 0; i < 16; i ++) {
+			if (sched->desc[i].count == 0)
+				break;
+			printf("start: %u interval: %u duration: %u count: %u\n",
+			       sched->desc[i].start, sched->desc[i].interval,
+			       sched->desc[i].duration, sched->desc[i].count);
+		}
+
+		return BCME_OK;
+	}
+
+	len = strlen(buf);
+
+	noa = (wl_p2p_sched_t *)&buf[len + 1];
+	len += 1;
+
+	noa->type = (uint8)strtol(argv[0], &endptr, 0);
+	len += sizeof(noa->type);
+	noa->action = (uint8)strtol(argv[1], &endptr, 0);
+	len += sizeof(noa->action);
+
+	argv += 2;
+	count -= 2;
+
+	/* action == -1 is to cancel the current schedule */
+	if (noa->action == WL_P2P_SCHED_ACTION_RESET) {
+		/* the fixed portion of wl_p2p_sched_t with action == WL_P2P_SCHED_ACTION_RESET
+		 * is required to cancel the curret schedule.
+		 */
+		len += (char *)&noa->desc[0] - ((char *)buf + len);
+	}
+	/* Take care of any special cases only and let all other cases fall through
+	 * as normal 'start/interval/duration/count' descriptions.
+	 * All cases start with 'type' 'action' 'option'.
+	 * Any count value greater than 255 is to repeat unlimited.
+	 */
+	else {
+		switch (noa->type) {
+		case WL_P2P_SCHED_TYPE_ABS:
+		case WL_P2P_SCHED_TYPE_REQ_ABS:
+			if (count < 1)
+				return BCME_USAGE_ERROR;
+			noa->option = (uint8)strtol(argv[0], &endptr, 0);
+			len += sizeof(noa->option);
+			argv += 1;
+			count -= 1;
+			break;
+		}
+
+		/* add any paddings before desc field */
+		len += (char *)&noa->desc[0] - ((char *)buf + len);
+
+		switch (noa->type) {
+		case WL_P2P_SCHED_TYPE_ABS:
+			switch (noa->option) {
+			case WL_P2P_SCHED_OPTION_BCNPCT:
+				if (count == 1) {
+					noa->desc[0].duration = htod32(strtol(argv[0], &endptr, 0));
+					noa->desc[0].start = 100 - noa->desc[0].duration;
+				}
+				else if (count == 2) {
+					noa->desc[0].start = htod32(strtol(argv[0], &endptr, 0));
+					noa->desc[0].duration = htod32(strtol(argv[1], &endptr, 0));
+				}
+				else {
+					fprintf(stderr, "Usage: wl p2p_noa 0 %d 1 "
+					        "<start-pct> <duration-pct>\n",
+					        noa->action);
+					return BCME_USAGE_ERROR;
+				}
+				len += sizeof(wl_p2p_sched_desc_t);
+				break;
+
+			default:
+				if (count < 4 || (count % 4) != 0) {
+					fprintf(stderr, "Usage: wl p2p_noa 0 %d 0 "
+					        "<start> <interval> <duration> <count> ...\n",
+					        noa->action);
+					return BCME_USAGE_ERROR;
+				}
+				goto normal;
+			}
+			break;
+
+		default:
+			if (count != 4) {
+				fprintf(stderr, "Usage: wl p2p_noa 1 %d "
+				        "<start> <interval> <duration> <count> ...\n",
+				        noa->action);
+				return BCME_USAGE_ERROR;
+			}
+			/* fall through... */
+		normal:
+			for (i = 0; i < count; i += 4) {
+				noa->desc[i / 4].start = htod32(strtoul(argv[i], &endptr, 0));
+				noa->desc[i / 4].interval = htod32(strtol(argv[i + 1], &endptr, 0));
+				noa->desc[i / 4].duration = htod32(strtol(argv[i + 2], &endptr, 0));
+				noa->desc[i / 4].count = htod32(strtol(argv[i + 3], &endptr, 0));
+				len += sizeof(wl_p2p_sched_desc_t);
+			}
+			break;
+		}
+	}
+
+	return wlu_set(wl, WLC_SET_VAR, buf, len);
+}
+#endif /* WLP2P */
+
+static int
+wl_rpmt(void *wl, cmd_t *cmd, char **argv)
+{
+	int count;
+	int len;
+	char *endptr;
+	uint32 val;
+
+	argv ++;
+
+	count = ARGCNT(argv);
+	if (count != 2) {
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, cmd->name);
+	len = strlen(buf) + 1;
+
+	val = htod32(strtoul(argv[0], &endptr, 0));
+	memcpy(&buf[len], &val, sizeof(uint32));
+	len += sizeof(uint32);
+	val = htod32(strtoul(argv[1], &endptr, 0));
+	memcpy(&buf[len], &val, sizeof(uint32));
+	len += sizeof(uint32);
+
+	return wlu_set(wl, WLC_SET_VAR, buf, len);
+}
+
+static int
+wl_ledbh(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_led_info_t led;
+	void	*ptr = NULL;
+
+	memset(&led, 0, sizeof(wl_led_info_t));
+	if (*++argv == NULL) {
+		printf("Usage: ledbh [led#] [behavior#]\n");
+		return BCME_USAGE_ERROR;
+	}
+	led.index = (int)strtoul(*argv, NULL, 10);
+
+	if (led.index > 3) {
+		printf("only 4 led supported\n");
+		return BCME_BADARG;
+	}
+
+	if (*++argv) {	/* set */
+		/* Read the original back so we don't toggle the activehi */
+		if ((err = wlu_var_getbuf(wl, cmd->name, (void*)&led,
+			sizeof(wl_led_info_t), &ptr)) < 0) {
+			printf("wl_ledbh: fail to get. code %x\n", err);
+		}
+		led.behavior = (int)strtoul(*argv, NULL, 10);
+		led.activehi = ((wl_led_info_t*)ptr)->activehi;
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, (void*)&led,
+			sizeof(wl_led_info_t))) < 0) {
+			printf("wl_ledbh: fail to set\n");
+		}
+	} else {	/* get */
+		wl_led_info_t *ledo;
+
+		if ((err = wlu_var_getbuf(wl, cmd->name, (void*)&led,
+			sizeof(wl_led_info_t), &ptr)) < 0) {
+			printf("wl_ledbh: fail to get\n");
+		}
+		ledo = (wl_led_info_t*)ptr;
+
+		printf("led %d behavior %d\n", ledo->index, ledo->behavior);
+	}
+
+	return err;
+}
+
+static int
+wl_led_blink_sync(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	int in_arg[2];
+	void *ptr = NULL;
+	char *endptr;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 3 || argc < 2)
+		return BCME_USAGE_ERROR;
+
+	in_arg[0] = htod32((uint32)(strtoul(argv[1], &endptr, 0)));
+
+	if (in_arg[0] > 3) {
+		printf("only 4 led supported\n");
+		return BCME_BADARG;
+	}
+
+	if (argc == 2) {
+		err = wlu_var_getbuf(wl, cmd->name, (void*)in_arg, sizeof(int), &ptr);
+		if (err < 0)
+			return err;
+		printf("led%d, blink_sync is %s\n", in_arg[0],
+			(dtoh32(*(int*)ptr) != 0) ? "TRUE" : "FALSE");
+	}
+	else if (argc == 3) {
+		in_arg[1] = htod32((uint32)(strtoul(argv[2], &endptr, 0)));
+		err = wlu_var_setbuf(wl, cmd->name, in_arg, sizeof(in_arg));
+	}
+	else {
+		fprintf(stderr, "illegal command!\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	return err;
+}
+
+/* RM Enable Capabilities */
+static dbg_msg_t rrm_msgs[] = {
+	{DOT11_RRM_CAP_LINK,	"Link_Measurement"},				/* bit0 */
+	{DOT11_RRM_CAP_NEIGHBOR_REPORT,	"Neighbor_Report"},			/* bit1 */
+	{DOT11_RRM_CAP_PARALLEL,	"Parallel_Measurement"},		/* bit2 */
+	{DOT11_RRM_CAP_REPEATED,	"Repeated_Measurement"},		/* bit3 */
+	{DOT11_RRM_CAP_BCN_PASSIVE,	"Beacon_Passive"},			/* bit4 */
+	{DOT11_RRM_CAP_BCN_ACTIVE,	"Beacon_Active"},			/* bit5 */
+	{DOT11_RRM_CAP_BCN_TABLE,	"Beacon_Table"},			/* bit6 */
+	{DOT11_RRM_CAP_BCN_REP_COND,	"Beacon_measurement_Reporting_Condition"}, /* bit7 */
+	{DOT11_RRM_CAP_FM,	"Frame_Measurement"},				/* bit8 */
+	{DOT11_RRM_CAP_CLM,	"Channel_load_Measurement"},			/* bit9 */
+	{DOT11_RRM_CAP_NHM,	"Noise_Histogram_measurement"},			/* bit10 */
+	{DOT11_RRM_CAP_SM,	"Statistics_Measurement"},			/* bit11 */
+	{DOT11_RRM_CAP_LCIM,	"LCI_Measurement"},				/* bit12 */
+	{DOT11_RRM_CAP_LCIA,	"LCI_Azimuth"},					/* bit13 */
+	{DOT11_RRM_CAP_TSCM,	"Tx_Stream_Category_Measurement"},		/* bit14 */
+	{DOT11_RRM_CAP_TTSCM,	"Triggered_Tx_stream_Category_Measurement"},	/* bit15 */
+	{DOT11_RRM_CAP_AP_CHANREP,	"AP_Channel_Report"},			/* bit16 */
+	{DOT11_RRM_CAP_RMMIB,	"RM_MIB"},					/* bit17 */
+	/* bit 18-26, unused */
+	{DOT11_RRM_CAP_MPTI,	"Measurement_Pilot_Transmission_Information"},	/* bit27 */
+	{DOT11_RRM_CAP_NBRTSFO,	"Neighbor_Report_TSF_Offset"},			/* bit28 */
+	{DOT11_RRM_CAP_RCPI,	"RCPI_Measurement"},				/* bit29 */
+	{DOT11_RRM_CAP_RSNI,	"RSNI_Measurement"},				/* bit30 */
+	{DOT11_RRM_CAP_BSSAAD,	"BSS_Average_Access_Delay"},			/* bit31 */
+	{DOT11_RRM_CAP_BSSAAC,	"BSS_Available_Admission_Capacity"},		/* bit32 */
+	{DOT11_RRM_CAP_AI,	"Antenna_Information"},				/* bit33 */
+	{0,		NULL}
+};
+
+static bool rrm_input_validation(uint val, uint hval, dbg_msg_t *dbg_msg)
+{
+	int i;
+	uint32 flag = 0;
+
+	if ((val == 0) && (hval == 0))
+		return TRUE;
+
+	for (i = 0; dbg_msg[i].value <= DOT11_RRM_CAP_BSSAAD; i++)
+		flag |= 1 << dbg_msg[i].value;
+	flag = ~flag;
+	if (val & flag)
+		return FALSE;
+
+	flag = 0;
+	if (hval != 0) {
+		for (; dbg_msg[i].value; i++) {
+			flag |= 1 << (dbg_msg[i].value - DOT11_RRM_CAP_BSSAAC);
+		}
+		flag = ~flag;
+		if (hval & flag)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int
+wl_rrm(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, i;
+	uint hval = 0, val = 0, len, found, rmcap_del = 0, rmcap2_del = 0;
+	uint rmcap_add = 0, rmcap2_add = 0;
+	char *endptr = NULL;
+	dbg_msg_t *dbg_msg = rrm_msgs;
+	void *ptr = NULL;
+	dot11_rrm_cap_ie_t rrm_cap, *reply;
+	uint high = 0, low = 0, bit = 0, hbit = 0;
+	const char *cmdname = "rrm";
+
+	UNUSED_PARAMETER(cmd);
+
+	err = wlu_var_getbuf_sm(wl, cmdname, &rrm_cap, sizeof(rrm_cap), &ptr);
+	if (err < 0)
+		return err;
+	reply = (dot11_rrm_cap_ie_t *)ptr;
+
+	high = reply->cap[4];
+	low = reply->cap[0] | (reply->cap[1] << 8) | (reply->cap[2] << 16) | (reply->cap[3] << 24);
+	if (!*++argv) {
+		if (high != 0)
+			printf("0x%x%08x", high, low);
+		else
+			printf("0x%x ", low);
+		for (i = 0; ((bit = dbg_msg[i].value) <= DOT11_RRM_CAP_BSSAAD); i++) {
+			if (low & (1 << bit))
+				printf(" %s", dbg_msg[i].string);
+		}
+		for (; (hbit = dbg_msg[i].value); i++) {
+			if (high & (1 << hbit))
+				printf(" %s", dbg_msg[i].string);
+		}
+		printf("\n");
+
+		return err;
+	}
+	while (*argv) {
+		char *s = *argv;
+		char t[32];
+
+		found = 0;
+		if (*s == '+' || *s == '-')
+			s++;
+		else {
+			/* used for clearing previous value */
+			rmcap_del = ~0;
+			rmcap2_del = ~0;
+		}
+		val = strtoul(s, &endptr, 0);
+		/* Input is decimal number or hex with prefix 0x and > 32 bits */
+		if (val == 0xFFFFFFFF) {
+			if (!(*s == '0' && *(s+1) == 'x')) {
+				fprintf(stderr,
+				"Msg bits >32 take only numerical input in hex\n");
+				val = 0;
+			} else {
+				/* Input number with prefix 0x */
+				char c[32] = "0x";
+				len = strlen(s);
+				hval = strtoul(strncpy(t, s, len-8), &endptr, 0);
+				*endptr = 0;
+				s = s + strlen(t);
+				s = strcat(c, s);
+				val = strtoul(s, &endptr, 0);
+				/* Input number > 64bit */
+				if (hval == 0xFFFFFFFF) {
+					fprintf(stderr, "Invalid entry for RM Capabilities\n");
+					hval = 0;
+					val = 0;
+				}
+			}
+		}
+		/* validet the input number */
+		if (!rrm_input_validation(val, hval, dbg_msg))
+			goto usage;
+		/* Input is a string */
+		if (*endptr != '\0') {
+			for (i = 0; ((bit = dbg_msg[i].value) <= DOT11_RRM_CAP_BSSAAD); i++) {
+				if (stricmp(dbg_msg[i].string, s) == 0) {
+					found = 1;
+					break;
+				}
+			}
+			if (!found) {
+				for (; (hbit = dbg_msg[i].value); i++) {
+					if (stricmp(dbg_msg[i].string, s) == 0)
+						break;
+				}
+				if (hbit)
+					hval = 1 << (hbit - DOT11_RRM_CAP_BSSAAC);
+				else
+					hval = 0;
+			} else {
+				val = 1 << bit;
+			}
+			if (!val && !hval)
+			      goto usage;
+		}
+		if (**argv == '-') {
+			rmcap_del |= val;
+			if (!found)
+				rmcap2_del |= hval;
+		}
+		else {
+			rmcap_add |= val;
+			if (!found)
+				rmcap2_add |= hval;
+		}
+		++argv;
+	}
+
+	low &= ~rmcap_del;
+	high &= ~rmcap2_del;
+	low |= rmcap_add;
+	high |= rmcap2_add;
+
+	rrm_cap.cap[4] = high;
+	rrm_cap.cap[0] = low & 0x000000ff;
+	rrm_cap.cap[1] = (low & 0x0000ff00) >> 8;
+	rrm_cap.cap[2] = (low & 0x00ff0000) >> 16;
+	rrm_cap.cap[3] = (low & 0xff000000) >> 24;
+
+	err = wlu_var_setbuf(wl, cmdname, &rrm_cap, sizeof(dot11_rrm_cap_ie_t));
+	return err;
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+	for (i = 0; (bit = dbg_msg[i].value) <= DOT11_RRM_CAP_BSSAAD; i++) {
+		fprintf(stderr, "\n0x%04x %s", (1 << bit), dbg_msg[i].string);
+	}
+	for (; (hbit = dbg_msg[i].value); i++) {
+		hbit -= DOT11_RRM_CAP_BSSAAC;
+		fprintf(stderr, "\n0x%x00000000 %s", (1 << hbit), dbg_msg[i].string);
+	}
+	fprintf(stderr, "\n");
+	return BCME_OK;
+}
+
+static int
+wl_rrm_stat_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_stat_req";
+	statreq_t sreq_buf;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&sreq_buf, 0, sizeof(statreq_t));
+
+	if (argv[1]) {
+		/* da */
+		if (!wl_ether_atoe(argv[1], &sreq_buf.da)) {
+			printf("wl_rrm_stat_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* random interval */
+	if (argv[2]) {
+		sreq_buf.random_int = htod32(strtoul(argv[2], NULL, 0));
+	}
+	/* duration */
+	if (argv[3]) {
+		sreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+	/* peer address */
+	if (argv[4]) {
+		if (!wl_ether_atoe(argv[4], &sreq_buf.peer)) {
+			printf("wl_rrm_stat_req parsing peer failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* group id */
+	if (argv[5]) {
+		sreq_buf.group_id =
+			htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* repetitions */
+	if (argv[6]) {
+		sreq_buf.reps = htod32(strtoul(argv[6], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &sreq_buf, sizeof(sreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_frame_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_frame_req";
+	framereq_t freq_buf;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&freq_buf, 0, sizeof(framereq_t));
+	if (argv[1]) {
+		/* Regulatory class */
+		freq_buf.reg = htod32(strtoul(argv[1], NULL, 0));
+	}
+
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &freq_buf.da)) {
+			printf("wl_rrm_frame_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		freq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+	/* random interval */
+	if (argv[4]) {
+		freq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+	/* channel */
+	if (argv[5]) {
+		freq_buf.chan = htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* transmit address */
+	if (argv[6]) {
+		if (!wl_ether_atoe(argv[6], &freq_buf.ta)) {
+			printf("wl_rrm_frame_req parsing ta failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* repetitions */
+	if (argv[7]) {
+		freq_buf.reps = htod32(strtoul(argv[7], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &freq_buf, sizeof(freq_buf));
+	return err;
+}
+
+static int
+wl_rrm_chload_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_chload_req";
+	rrmreq_t chreq_buf;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&chreq_buf, 0, sizeof(rrmreq_t));
+
+	if (argv[1]) {
+		/* Regulatory class */
+		chreq_buf.reg = htod32(strtoul(argv[1], NULL, 0));
+	}
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &chreq_buf.da)) {
+			printf("wl_rrm_chload_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		chreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+	/* random interval */
+	if (argv[4]) {
+		chreq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+	/* channel */
+	if (argv[5]) {
+		chreq_buf.chan = htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* repetitions */
+	if (argv[6]) {
+		chreq_buf.reps = htod32(strtoul(argv[6], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &chreq_buf, sizeof(chreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_noise_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_noise_req";
+	rrmreq_t nreq_buf;
+
+	UNUSED_PARAMETER(cmd);
+	printf("wl_rrm_noise_req\n");
+
+	memset(&nreq_buf, 0, sizeof(rrmreq_t));
+	if (argv[1]) {
+		/* Regulatory class */
+		nreq_buf.reg = htod32(strtoul(argv[1], NULL, 0));
+	}
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &nreq_buf.da)) {
+			printf("wl_rrm_noise_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		nreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+
+	}
+	/* random interval */
+	if (argv[4]) {
+		nreq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+	/* channel */
+	if (argv[5]) {
+		nreq_buf.chan = htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* repetitions */
+	if (argv[6]) {
+		nreq_buf.reps = htod32(strtoul(argv[6], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &nreq_buf, sizeof(nreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_bcn_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	uint8 mode = 0;
+	const char *cmdname = "rrm_bcn_req";
+	bcnreq_t bcnreq_buf;
+	wlc_ssid_t ssid;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&bcnreq_buf, 0, sizeof(bcnreq_t));
+
+	if (argv[1]) {
+		/* bcn mode: ACTIVE/PASSIVE/SCAN_CACHE */
+		mode = htod32(strtoul(argv[1], NULL, 0));
+		if (mode > 2) {
+			printf("wl_rrm_bcn_req parsing bcn mode failed\n");
+			return BCME_BADARG;
+		}
+		bcnreq_buf.bcn_mode = mode;
+	}
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &bcnreq_buf.da)) {
+			printf("wl_rrm_bcn_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		bcnreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+
+	/* random interval */
+	if (argv[4]) {
+		bcnreq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+
+	/* channel */
+	if (argv[5]) {
+		bcnreq_buf.channel = htod32(strtoul(argv[5], NULL, 0));
+	}
+	printf("wl_rrm_bcn_req:bcn mode: %d, duration: %d, "
+			"chan: %d\n", mode,
+			bcnreq_buf.dur, bcnreq_buf.channel);
+
+	/* SSID */
+	if (argv[6]) {
+		uint32 len;
+
+		len = strlen(argv[6]);
+		if (len > DOT11_MAX_SSID_LEN) {
+			printf("ssid too long\n");
+			return BCME_BADARG;
+		}
+		memset(&ssid, 0, sizeof(wlc_ssid_t));
+		memcpy(ssid.SSID, argv[6], len);
+		ssid.SSID_len = len;
+		memcpy(&bcnreq_buf.ssid, &ssid, sizeof(wlc_ssid_t));
+	}
+
+	/* repetitions */
+	if (argv[7]) {
+		bcnreq_buf.reps = htod32(strtoul(argv[7], NULL, 0));
+	}
+
+	err = wlu_iovar_set(wl, cmdname, &bcnreq_buf, sizeof(bcnreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_lm_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_lm_req";
+
+	struct ether_addr da;
+	UNUSED_PARAMETER(cmd);
+
+	if (argv[1]) {
+		if (!wl_ether_atoe(argv[1], &da)) {
+			printf("wl_rrm_lm_req parsing arg1 failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	err = wlu_iovar_set(wl, cmdname, &da, sizeof(da));
+	return err;
+}
+
+static int
+wl_rrm_nbr_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wlc_ssid_t ssid;
+
+	UNUSED_PARAMETER(cmd);
+
+	strcpy(buf, "rrm_nbr_req");
+	buflen = strlen("rrm_nbr_req") + 1;
+
+	if (*++argv) {
+		uint32 len;
+
+		len = strlen(*argv);
+		if (len > DOT11_MAX_SSID_LEN) {
+			printf("ssid too long\n");
+			return BCME_BADARG;
+		}
+		memset(&ssid, 0, sizeof(wlc_ssid_t));
+		memcpy(ssid.SSID, *argv, len);
+		ssid.SSID_len = len;
+		memcpy(&buf[buflen], &ssid, sizeof(wlc_ssid_t));
+		buflen += sizeof(wlc_ssid_t);
+	}
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+/* For mapping customer's user space command, two calls of the same iovar. */
+static int
+wl_rrm_nbr_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0, buflen, i;
+	uint16 list_cnt;
+	nbr_element_t *nbr_elt;
+	uint8 *ptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "rrm_nbr_list");
+	buflen = strlen("rrm_nbr_list") + 1;
+
+	if (*++argv != NULL)
+		return BCME_USAGE_ERROR;
+
+	if ((err = wlu_get(wl, WLC_GET_VAR, buf, buflen)) < 0)
+		return err;
+
+	list_cnt = *(uint16 *)buf;
+
+	if (list_cnt == 0)
+		return err;
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "rrm_nbr_list");
+	buflen = strlen("rrm_nbr_list") + 1;
+
+	memcpy(&buf[buflen], &list_cnt, sizeof(uint16));
+
+	printf("RRM Neighbor Report List:\n");
+
+	if ((err = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	ptr = (uint8 *)buf;
+
+	for (i = 0; i < list_cnt; i++) {
+		nbr_elt = (nbr_element_t *)ptr;
+		printf("AP %2d: ", i + 1);
+		printf("bssid %02x:%02x:%02x:%02x:%02x:%02x ", nbr_elt->bssid.octet[0],
+			nbr_elt->bssid.octet[1], nbr_elt->bssid.octet[2], nbr_elt->bssid.octet[3],
+			nbr_elt->bssid.octet[4], nbr_elt->bssid.octet[5]);
+
+		printf("bssid_info %08x ", load32_ua(&nbr_elt->bssid_info));
+		printf("reg %2d channel %3d phytype %d\n", nbr_elt->reg,
+			nbr_elt->channel, nbr_elt->phytype);
+
+		ptr += TLV_HDR_LEN + DOT11_NEIGHBOR_REP_IE_FIXED_LEN;
+	}
+
+	return err;
+}
+
+static int
+wl_rrm_nbr_del_nbr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_nbr_del_nbr";
+	struct ether_addr ea;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv == NULL) {
+		printf("no bssid specified\n");
+		return BCME_USAGE_ERROR;
+	} else {
+		if (!wl_ether_atoe(*argv, &ea)) {
+			printf("Incorrect bssid format\n");
+			return BCME_ERROR;
+		}
+		err = wlu_iovar_set(wl, cmdname, &ea, sizeof(ea));
+	}
+
+	return err;
+}
+
+static int
+wl_rrm_nbr_add_nbr(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	const char *cmdname = "rrm_nbr_add_nbr";
+	nbr_element_t nbr_elt;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&nbr_elt, 0, sizeof(nbr_element_t));
+
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc != 6)
+		return BCME_USAGE_ERROR;
+
+	/* bssid */
+	if (!wl_ether_atoe(argv[1], &nbr_elt.bssid)) {
+		printf("wl_rrm_nbr_add_nbr parsing bssid failed\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* bssid info */
+	nbr_elt.bssid_info = htod32(strtoul(argv[2], NULL, 0));
+
+	/* Regulatory class */
+	nbr_elt.reg = htod32(strtoul(argv[3], NULL, 0));
+
+	/* channel */
+	nbr_elt.channel = htod32(strtoul(argv[4], NULL, 0));
+
+	/* phytype */
+	nbr_elt.phytype = htod32(strtoul(argv[5], NULL, 0));
+
+	nbr_elt.id = DOT11_MNG_NEIGHBOR_REP_ID;
+	nbr_elt.len = DOT11_NEIGHBOR_REP_IE_FIXED_LEN;
+
+	err = wlu_iovar_set(wl, cmdname, &nbr_elt, TLV_HDR_LEN + DOT11_NEIGHBOR_REP_IE_FIXED_LEN);
+	return err;
+}
+
+static dbg_msg_t wl_wnm_msgs[] = {
+	{WL_WNM_BSSTRANS,	"BSS-Transition"},
+	{WL_WNM_PROXYARP,	"Proxy-ARP"},
+	{WL_WNM_MAXIDLE,	"BSS-Max-Idle-Period"},
+	{WL_WNM_TIMBC,		"TIM-Broadcast"},
+	{WL_WNM_TFS,		"Traffic-Filtering"},
+	{WL_WNM_SLEEP,		"WNM-Sleep-Mode"},
+	{WL_WNM_DMS,		"Directed-Multicast"},
+	{WL_WNM_FMS,		"Flexible-Multicast"},
+	{WL_WNM_NOTIF,		"Notification"},
+	{0, ""}
+};
+
+static int
+wl_wnm(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val;
+	int wnmmask;
+	char *s;
+
+	ret = wlu_iovar_getint(wl, cmd->name, &wnmmask);
+	if (ret < 0)
+		return ret;
+
+	if (!*++argv) {
+		printf("0x%x:", wnmmask);
+		for (i = 0; wl_wnm_msgs[i].value; i++)
+			if (wnmmask & wl_wnm_msgs[i].value)
+				printf("  %s", wl_wnm_msgs[i].string);
+		printf("\n");
+		return 0;
+	}
+
+	s = *argv;
+	if (*s == '+' || *s == '-')
+		s++;
+
+	if (!*s)
+		goto usage;
+
+	val = strtoul(s, &s, 0);
+	if (*s)
+		goto usage;
+
+	if (**argv == '+')
+		wnmmask |= val;
+	else if (**argv == '-')
+		wnmmask &= ~val;
+	else
+		wnmmask = val;
+
+	return wlu_iovar_setint(wl, cmd->name, wnmmask);
+
+usage:
+	fprintf(stderr, "WNM mask is a bitfield from the following set. "
+		"Use + or - prefix to combine with current value:\n");
+
+	for (i = 0; wl_wnm_msgs[i].value; i++)
+		fprintf(stderr, " 0x%04x %s\n", wl_wnm_msgs[i].value, wl_wnm_msgs[i].string);
+
+	return 0;
+}
+
+static int
+wl_wnm_bsstq(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wlc_ssid_t ssid;
+
+	UNUSED_PARAMETER(cmd);
+
+	strcpy(buf, "wnm_bsstrans_query");
+	buflen = strlen("wnm_bsstrans_query") + 1;
+
+	if (*++argv) {
+		uint32 len;
+
+		len = strlen(*argv);
+		if (len > DOT11_MAX_SSID_LEN) {
+			printf("ssid too long\n");
+			return (-1);
+		}
+		memset(&ssid, 0, sizeof(wlc_ssid_t));
+		memcpy(ssid.SSID, *argv, len);
+		ssid.SSID_len = len;
+		memcpy(&buf[buflen], &ssid, sizeof(wlc_ssid_t));
+		buflen += sizeof(wlc_ssid_t);
+	}
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+#define TCLAS_ARG_CHECK(argv, str) \
+	do { \
+		if (*++(argv) == NULL) { \
+			printf("TCLAS Frame Classifier: %s not provided\n", (str)); \
+			return BCME_ERROR; \
+		} \
+	} while (0)
+
+static int
+wl_tclas_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1, buflen;
+	dot11_tclas_fc_t *fc;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	/* Check the user priority value */
+	TCLAS_ARG_CHECK(argv, "user priority");
+	buf[buflen++] = (uint8)strtoul(*argv, NULL, 0);
+
+	/* unaligned! */
+	fc = (dot11_tclas_fc_t *) (buf + buflen);
+	memset((void *)fc, 0, sizeof(dot11_tclas_fc_t));
+
+	/* Parse frame classifier type and mask */
+	TCLAS_ARG_CHECK(argv, "type");
+	fc->hdr.type = (uint8)strtoul(*argv, NULL, 0);
+
+	TCLAS_ARG_CHECK(argv, "mask");
+	fc->hdr.mask = (uint8)strtoul(*argv, NULL, 0);
+	if (fc->hdr.type ==  DOT11_TCLAS_FC_0_ETH) {
+		dot11_tclas_fc_0_eth_t *fc_eth = (dot11_tclas_fc_0_eth_t *)fc;
+
+		TCLAS_ARG_CHECK(argv, "src mac");
+		if (strlen(*argv) > 1) {
+			if (!wl_ether_atoe(*argv, (struct ether_addr *)fc_eth->sa)) {
+				printf(" ERROR: no valid src ether addr provided\n");
+				return BCME_ERROR;
+			}
+		}
+		else
+			memset(fc_eth->sa, 0, ETHER_ADDR_LEN);
+
+		TCLAS_ARG_CHECK(argv, "dst mac");
+		if (strlen(*argv) > 1) {
+			if (!wl_ether_atoe(*argv, (struct ether_addr *)fc_eth->da)) {
+				printf(" ERROR: no valid dst ether addr provided\n");
+				return BCME_ERROR;
+			}
+		}
+		else
+			memset(fc_eth->da, 0, ETHER_ADDR_LEN);
+
+		TCLAS_ARG_CHECK(argv, "ether type");
+		fc_eth->eth_type = hton16((uint16)strtoul(*argv, NULL, 0));
+
+		buflen += DOT11_TCLAS_FC_0_ETH_LEN;
+
+		err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+	}
+	else if (fc->hdr.type == DOT11_TCLAS_FC_1_IP ||
+		fc->hdr.type == DOT11_TCLAS_FC_4_IP_HIGHER) {
+		uint8 version;
+
+		TCLAS_ARG_CHECK(argv, "ip version");
+		version = (uint8)strtoul(*argv, NULL, 0);
+		if (version == IP_VER_6) {
+			dot11_tclas_fc_4_ipv6_t *fc_ipv6 = (dot11_tclas_fc_4_ipv6_t *)fc;
+			uint32 fl;
+
+			fc_ipv6->version = version;
+
+			TCLAS_ARG_CHECK(argv, "ipv6 source ip");
+			if (!wl_atoipv6(*argv, (struct ipv6_addr *)&fc_ipv6->saddr)) {
+				printf("incorrect ipv6 source ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv6 dest ip");
+			if (!wl_atoipv6(*argv, (struct ipv6_addr *)&fc_ipv6->daddr)) {
+				printf("incorrect ipv6 dest ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv6 source port");
+			fc_ipv6->src_port = hton16((uint16)strtoul(*argv, NULL, 0));
+
+			TCLAS_ARG_CHECK(argv, "ipv6 dest port");
+			fc_ipv6->dst_port = hton16((uint16)strtoul(*argv, NULL, 0));
+
+			TCLAS_ARG_CHECK(argv, "ipv6 dscp");
+			fc_ipv6->dscp = (uint8)strtoul(*argv, NULL, 0);
+
+			TCLAS_ARG_CHECK(argv, "ipv6 next header");
+			fc_ipv6->nexthdr = (uint8)strtoul(*argv, NULL, 0);
+
+			TCLAS_ARG_CHECK(argv, "ipv6 flow label");
+			fl = (uint32) strtoul(*argv, NULL, 0);
+			fc_ipv6->flow_lbl[2] = (fl >> 16) & 0xFF;
+			fc_ipv6->flow_lbl[1] = (fl >> 8) & 0xFF;
+			fc_ipv6->flow_lbl[0] = (fl >> 0) & 0xFF;
+
+			buflen += DOT11_TCLAS_FC_4_IPV6_LEN;
+
+			err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+		} else
+		if (version == IP_VER_4) {
+			dot11_tclas_fc_1_ipv4_t *fc_ipv4 = (dot11_tclas_fc_1_ipv4_t *)fc;
+
+			fc_ipv4->version = version;
+
+			TCLAS_ARG_CHECK(argv, "ipv4 source ip");
+			if (!wl_atoip(*argv, (struct ipv4_addr *)&fc_ipv4->src_ip)) {
+				printf("incorrect source ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv4 dest ip");
+			if (!wl_atoip(*argv, (struct ipv4_addr *)&fc_ipv4->dst_ip)) {
+				printf("incorrect dest ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv4 source port");
+			fc_ipv4->src_port = (uint16)strtoul(*argv, NULL, 0);
+			fc_ipv4->src_port = hton16(fc_ipv4->src_port);
+
+			TCLAS_ARG_CHECK(argv, "ipv4 dest port");
+			fc_ipv4->dst_port = (uint16)strtoul(*argv, NULL, 0);
+			fc_ipv4->dst_port = hton16(fc_ipv4->dst_port);
+
+			TCLAS_ARG_CHECK(argv, "ipv4 dscp");
+			fc_ipv4->dscp = (uint8)strtoul(*argv, NULL, 0);
+
+			TCLAS_ARG_CHECK(argv, "ipv4 protocol");
+			fc_ipv4->protocol = (uint8)strtoul(*argv, NULL, 0);
+
+			buflen += DOT11_TCLAS_FC_1_IPV4_LEN;
+
+			err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+		} else
+			return BCME_ERROR;
+	} else {
+		printf("Unsupported frame classifier type 0x%2x\n", fc->hdr.type);
+		return BCME_ERROR;
+	}
+
+	return err;
+}
+
+static int
+wl_tclas_del(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen, totlen;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+	totlen = buflen + 2;
+
+	/* Set initial length */
+	buf[buflen] = 0;	/* first value present for init index */
+	buf[buflen + 1] = 0;	/* second value present for delete count */
+
+	/* Check idx and add if present */
+	if (*++argv == NULL)
+		goto set;
+	buf[buflen] = 1;
+	buf[buflen + 1] = (uint8)strtoul(*argv, NULL, 0);
+
+	/* Check len and add if present */
+	if (*++argv == NULL)
+		goto set;
+	buf[buflen] = 2;
+	buf[buflen + 2] = (uint8)strtoul(*argv, NULL, 0);
+
+	if (*++argv) {
+		printf("Too much args provided\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, totlen);
+
+	return err;
+}
+
+
+static void
+wl_tclas_dump(wl_tclas_t *tclas)
+{
+	dot11_tclas_fc_hdr_t *fc = &tclas->fc.hdr;
+	dot11_tclas_fc_0_eth_t *eth = &tclas->fc.t0_eth;
+	dot11_tclas_fc_1_ipv4_t *ipv4 = &tclas->fc.t1_ipv4;
+	dot11_tclas_fc_4_ipv6_t *ipv6 = &tclas->fc.t4_ipv6;
+
+#define TCDMP(x) ((fc->mask & (x))?'+':'-')
+
+	printf("up %d  type %d  mask 0x%x  ", tclas->user_priority, fc->type, fc->mask);
+
+	/* Check frame classifier parameter type */
+	if (fc->type == DOT11_TCLAS_FC_0_ETH) {
+		printf("(Eth: ");
+		printf("%cSA %s  ", TCDMP(1), wl_ether_etoa((struct ether_addr*)eth->sa));
+		printf("%cDA %s  ", TCDMP(2), wl_ether_etoa((struct ether_addr*)eth->da));
+		printf("%ctype 0x%04x", TCDMP(4), ntoh16(eth->eth_type));
+		printf(")\n");
+	} else if (fc->type == DOT11_TCLAS_FC_1_IP ||
+		(fc->type == DOT11_TCLAS_FC_4_IP_HIGHER && ipv4->version == IP_VER_4)) {
+		/* Check parameter type 1/4 IPv4 version */
+		printf("(IPv4: ");
+		printf("%cver %d  ", TCDMP(1), ipv4->version);
+		printf("%csip %s  ", TCDMP(2), wl_iptoa((struct ipv4_addr *)&ipv4->src_ip));
+		printf("%cdip %s  ", TCDMP(4), wl_iptoa((struct ipv4_addr *)&ipv4->dst_ip));
+		printf("%csp %d  ", TCDMP(8), ntoh16(ipv4->src_port));
+		printf("%cdp %d  ", TCDMP(16), ntoh16(ipv4->dst_port));
+		printf("%cdscp 0x%x  ", TCDMP(32), ipv4->dscp);
+		printf("%cprot %d", TCDMP(64), ipv4->protocol);
+		printf(")\n");
+	} else if (fc->type == DOT11_TCLAS_FC_4_IP_HIGHER && ipv6->version == IP_VER_6) {
+		/* Check parameter type 4 IPv6 version */
+		printf("(IPv6: ");
+		printf("%cver %d  ", TCDMP(1), ipv6->version);
+		printf("%csip %s  ", TCDMP(2), wl_ipv6toa(ipv6->saddr));
+		printf("%cdip %s  ", TCDMP(4), wl_ipv6toa(ipv6->daddr));
+		printf("%csp %d  ", TCDMP(8), ntoh16(ipv6->src_port));
+		printf("%cdp %d  ", TCDMP(16), ntoh16(ipv6->dst_port));
+		printf("%cdscp 0x%x  ", TCDMP(32), ipv6->dscp);
+		printf("%cprot %d", TCDMP(64), ipv6->nexthdr);
+		printf("%cfl %d", TCDMP(64),
+			ipv6->flow_lbl[2]<<16 | ipv6->flow_lbl[1]<<8 | ipv6->flow_lbl[0]);
+		printf(")\n");
+	} else {
+		printf("(type unsupported)\n");
+	}
+}
+
+static int
+wl_tclas_list_parse(wl_tclas_list_t *list)
+{
+	uint32 i;
+	uint8 *ptr = (uint8 *)&list->tclas[0];
+	int retlen = 0;
+
+	for (i = 0; i < list->num; i++) {
+		wl_tclas_t *tclas = (wl_tclas_t *)ptr;
+
+		printf("tclas idx %d: ", i);
+
+		wl_tclas_dump(tclas);
+
+		retlen += WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+
+		/* Move to the next tclas frame classifier parameter */
+		ptr += WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+	}
+
+	return retlen;
+}
+
+static int
+wl_tclas_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_tclas_list_t *tclas_list = NULL;
+	void *ptr = NULL;
+
+	if (*++argv) {
+		printf("Too much args provided\n");
+		return BCME_ERROR;
+	}
+
+	err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr);
+	if (err == BCME_OK) {
+		tclas_list = (wl_tclas_list_t *)ptr;
+		if (tclas_list->num == 0)
+			printf("No tclas frame classifier parameter entry\n");
+		else
+			wl_tclas_list_parse(tclas_list);
+	}
+
+	return err;
+}
+
+#ifdef WLWNM
+static int
+wl_wnm_tfsreq_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = -1, buflen;
+	wl_tfs_req_t tfs_req;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	strcpy(buf, "wnm_tfsreq_add");
+	buflen = strlen("wnm_tfsreq_add") + 1;
+
+	if (argc != 5 || *++(argv) == NULL) {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	tfs_req.tfs_id = (uint8)strtoul(*argv++, NULL, 0);
+
+	if (*argv != NULL)
+		tfs_req.tfs_actcode = (uint8)strtoul(*argv++, NULL, 0);
+	else {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	if (*argv != NULL)
+		tfs_req.tfs_subelem_id = (uint8)strtoul(*argv++, NULL, 0);
+	else {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	if (*argv != NULL)
+		tfs_req.send = strtoul(*argv, NULL, 0) == 0 ? FALSE : TRUE;
+	else {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	if (tfs_req.tfs_id == 0 ||
+		tfs_req.tfs_actcode > 3 ||
+		tfs_req.tfs_subelem_id > 1) {
+		printf("Input args not in range\n");
+		return BCME_ERROR;
+	}
+
+	buf[buflen++] = tfs_req.tfs_id;
+	buf[buflen++] = tfs_req.tfs_actcode;
+	buf[buflen++] = tfs_req.tfs_subelem_id;
+	buf[buflen++] = tfs_req.send;
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_dms_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_dms_set_t *dms_set;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+	dms_set = (wl_dms_set_t *) (buf + buflen);
+	dms_set->user_id = 0;
+	dms_set->tclas_proc = 0;
+	buflen += sizeof(wl_dms_set_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <send> argument\n");
+		return BCME_ERROR;
+	}
+	dms_set->send = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	dms_set->user_id = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	dms_set->tclas_proc = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv)) {
+		printf("extra argument\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_dms_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_dms_status_t *dms_list = (wl_dms_status_t *)buf;
+	uint8 *p = (uint8 *)dms_list->desc;
+
+	strcpy(buf, argv[0]);
+
+	ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+	if (ret < 0)
+		return ret;
+
+	dms_list->cnt = dtoh32(dms_list->cnt);
+
+	while (dms_list->cnt--) {
+
+		wl_dms_desc_t *desc = (wl_dms_desc_t *)p;
+
+		printf("DMS desc UserID %d:\n", desc->user_id);
+		printf("\tstatus:%d   token:%d   DMS ID:%d   TCLAS proc:%d\n",
+			desc->status, desc->token, desc->dms_id, desc->tclas_proc);
+
+		p += WL_DMS_DESC_FIXED_SIZE;
+
+		if (desc->mac_len) {
+			printf("\tRegistered STA:\n");
+
+			while (desc->mac_len) {
+				printf("\t\t- %s\n", wl_ether_etoa((struct ether_addr*)p));
+				p += ETHER_ADDR_LEN;
+				desc->mac_len -= ETHER_ADDR_LEN;
+			}
+		}
+
+		printf("\tTCLAS:\n");
+		while (desc->tclas_len) {
+			wl_tclas_t *tclas = (wl_tclas_t *)p;
+
+			printf("\t\t- ");
+			wl_tclas_dump(tclas);
+
+			p += WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+			desc->tclas_len -= WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_wnm_dms_term(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_dms_term_t *dms_term;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	dms_term = (wl_dms_term_t *) (buf + buflen);
+	dms_term->user_id = 0;
+	buflen += sizeof(wl_dms_term_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <del> argument\n");
+		return BCME_ERROR;
+	}
+	dms_term->del = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	dms_term->user_id = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv)) {
+		printf("extra argument\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_service_term(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_service_term_t *term;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	term = (wl_service_term_t *) (buf + buflen);
+	term->u.dms.user_id = 0;
+	buflen += sizeof(wl_service_term_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <service> argument\n");
+		return BCME_ERROR;
+	}
+	term->service = (uint8) strtoul(*argv, NULL, 0);
+
+	/* Need per service processing from here? */
+	if (*++(argv) == NULL) {
+		printf("Missing <del> argument\n");
+		return BCME_ERROR;
+	}
+	term->u.dms.del = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	term->u.dms.user_id = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv)) {
+		printf("extra argument\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_timbc_offset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_timbc_offset_t *timbc_offset;
+	char *p = buf;
+	int size;
+	UNUSED_PARAMETER(cmd);
+
+	size = sprintf(p, "%s", *argv++) + 1;
+
+	if (*argv == NULL) {
+		/* retrieve bss idle period if argument count incorrect */
+		int err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+		if (err < 0)
+			return err;
+
+		timbc_offset = (wl_timbc_offset_t *)buf;
+		printf("TIMBC offset: %d, tsf_present: %d, fix_interval: %d, rate_override: %d\n",
+			timbc_offset->offset, timbc_offset->tsf_present, timbc_offset->fix_intv,
+			timbc_offset->rate_override);
+
+		return BCME_OK;
+
+	} else {
+		if (!isdigit((int)*argv[0]))
+			return BCME_ERROR;
+
+		timbc_offset = (wl_timbc_offset_t *)(p + size);
+
+		timbc_offset->offset = (int16)strtoul(*argv++, NULL, 0);
+		timbc_offset->tsf_present = TRUE;
+		timbc_offset->fix_intv = 0;
+		timbc_offset->rate_override = 0;
+
+		if (*argv != NULL) {
+			timbc_offset->tsf_present = (bool)strtoul(*argv++, NULL, 0);
+			if (*argv != NULL) {
+				timbc_offset->fix_intv = (uint16)strtoul(*argv++, NULL, 0);
+				if (*argv != NULL) {
+					timbc_offset->rate_override =
+						(uint16)strtoul(*argv++, NULL, 0);
+				}
+			}
+		}
+
+		return wlu_set(wl, WLC_SET_VAR, buf, size + sizeof(wl_timbc_offset_t));
+	}
+}
+
+static int
+wl_wnm_timbc_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_timbc_set_t *req;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	req = (wl_timbc_set_t *) (buf + buflen);
+	req->flags = 0;
+	req->rate_min = 0;
+	req->rate_max = 0;
+	buflen += sizeof(wl_timbc_set_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <interval> argument\n");
+		return BCME_ERROR;
+	}
+	req->interval = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	req->flags = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	req->rate_min = htod16(rate_string2int(*argv));
+
+	if (*++(argv) == NULL)
+		goto set;
+	req->rate_max = htod16(rate_string2int(*argv));
+
+	if (*++(argv)) {
+		printf("Too many arguments\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_timbc_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_timbc_status_t *status = (wl_timbc_status_t *)buf;
+	char hrate[16], lrate[16];
+
+	strcpy(buf, argv[0]);
+
+	ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+	if (ret < 0)
+		return ret;
+
+	printf("TIM BC current status: %d  status_ap: %d\n"
+		"  interval: %d   offset: %d\n"
+		"  high rate: %s   low rate: %s\n",
+		status->status_sta,
+		status->status_ap,
+		status->interval, status->offset,
+		rate_int2string(hrate, status->rate_high),
+		rate_int2string(lrate, status->rate_low));
+
+	return BCME_OK;
+}
+
+static int
+wl_wnm_maxidle(void *wl, cmd_t *cmd, char **argv)
+{
+	struct {
+		int period;
+		int protect;
+	} params = { 0, 0 };
+	char *endptr;
+
+	if (*++argv == NULL) {
+		/* retrieve bss idle period if argument count incorrect */
+		int err = wlu_iovar_getint(wl, cmd->name, &params.period);
+		if (err < 0)
+			return err;
+
+		printf("BSS Max Idle Period: %d\n", dtoh32(params.period));
+		return BCME_OK;
+
+	} else {
+		/* parse the idle period */
+		params.period = strtoul(*argv++, &endptr, 0);
+		htod32(params.period);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		/* parse the optional keep-alive protect flag */
+		if (*argv) {
+			params.protect = strtoul(*argv, &endptr, 0);
+			htod32(params.protect);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &params, sizeof(params));
+	}
+}
+
+static int
+wl_wnm_bsstrans_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_bsstrans_req_t bsstrans_req;
+	int buflen = sprintf(buf, "%s", *argv) + 1;
+	int tmp;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* req mode parsing */
+	if (*++argv == NULL) {
+		fprintf(stderr, "%s: error: reqmode missing\n", __FUNCTION__);
+		return BCME_ERROR;
+	}
+	bsstrans_req.reqmode = strtoul(*argv, NULL, 0);
+
+	/* tbtt parsing */
+	if (*++argv == NULL) {
+		fprintf(stderr, "%s: error: tbtt missing\n", __FUNCTION__);
+		return BCME_ERROR;
+	}
+	tmp = strtoul(*argv, NULL, 0);
+	if (tmp > 65535 || tmp < 0) {
+		fprintf(stderr, "%s: error: tbtt out of range(%d)\n", __FUNCTION__, tmp);
+		return BCME_ERROR;
+	}
+	else
+		bsstrans_req.tbtt = tmp;
+
+	/* dur parsing */
+	if (*++argv == NULL) {
+		fprintf(stderr, "%s: error: dur missing\n", __FUNCTION__);
+		return BCME_ERROR;
+	}
+	tmp = strtoul(*argv, NULL, 0);
+	if (tmp > 65535 || tmp < 0) {
+		fprintf(stderr, "%s: error: dur out of range(%d)\n", __FUNCTION__, tmp);
+		return BCME_ERROR;
+	}
+	else
+		bsstrans_req.dur = tmp;
+
+	/* unicast/broadcast parsing */
+	if (*++argv != NULL)
+		bsstrans_req.unicast = strtoul(*argv, NULL, 0);
+	else
+		bsstrans_req.unicast = 1;
+
+	memcpy(&buf[buflen], &bsstrans_req, sizeof(bsstrans_req));
+	buflen += sizeof(bsstrans_req);
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+/*
+ * Get or Set wnm keepalive configuration
+ */
+static int
+wl_wnm_keepalives_max_idle(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, argc;
+	keepalives_max_idle_t keepalive;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &keepalive,
+			(sizeof(keepalive)))) < 0)
+			return (err);
+
+		printf("Keepalives_max_idle parameters -\n");
+		printf("num_of_keepalives_per_bss_max_idle\t\t= %d\nmkeep_alive_index\t= %d"
+			"\nmax_interval\t= %d\n", keepalive.keepalive_count,
+			keepalive.mkeepalive_index, keepalive.max_interval);
+	} else {
+		char *endptr;
+		/* Validate num of entries */
+		for (argc = 0; argv[argc]; argc++);
+		if (argc < 2 || argc > 3)
+			return BCME_ERROR;
+
+		keepalive.keepalive_count = strtol(argv[0], &endptr, 0);
+		keepalive.mkeepalive_index = strtol(argv[1], &endptr, 0);
+		if (argc == 3)
+			keepalive.max_interval = strtol(argv[2], &endptr, 0);
+		else
+			keepalive.max_interval = 0;
+
+		/* Set params */
+		err = wlu_iovar_set(wl, cmd->name, (void *) &keepalive,
+			(sizeof(keepalives_max_idle_t)));
+	}
+
+	return err;
+}
+
+#endif /* WLWNM */
+
+static int
+wl_tsf(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "tsf";
+	struct tsf {
+		uint32 low;
+		uint32 high;
+	} tsf_buf;
+	char *endptr;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* toss the command name */
+	argv++;
+
+	if (*argv == NULL) {
+		/* get */
+		err = wlu_iovar_get(wl, cmdname, &tsf_buf, sizeof(tsf_buf));
+		if (err)
+			return err;
+		printf("0x%08X 0x%08X\n", htod32(tsf_buf.high), htod32(tsf_buf.low));
+	} else {
+		/* set */
+		if (argv[1] == NULL)
+			return BCME_USAGE_ERROR;
+
+		tsf_buf.high = (uint32)strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "%s: %s: error parsing \"%s\" as an integer\n",
+			        wlu_av0, cmdname, *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		argv++;
+		tsf_buf.low = (uint32)strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "%s: %s: error parsing \"%s\" as an integer\n",
+			        wlu_av0, cmdname, *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		tsf_buf.low = dtoh32(tsf_buf.low);
+		tsf_buf.high = dtoh32(tsf_buf.high);
+
+		err = wlu_iovar_set(wl, cmdname, &tsf_buf, sizeof(tsf_buf));
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+static int
+wl_mfp_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	int flag = 0;
+	const char *cmdname = "mfp";
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)buf = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, buf, 256);
+
+	return (err);
+
+}
+
+static int
+wl_mfp_sha256(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	int flag = 0;
+	const char *cmdname = "mfp_sha256";
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)buf = flag;
+		err = wlu_iovar_set(wl, cmdname, buf, 256);
+	} else {
+		/* get */
+		err = wlu_iovar_getint(wl, cmdname, &flag);
+		if (err == BCME_OK)
+			printf("%d\n", flag);
+	}
+
+	return (err);
+
+}
+
+static int
+wl_mfp_sa_query(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_sa_query_t * query;
+	int argc;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if ((query = (wl_sa_query_t *) malloc(sizeof(wl_sa_query_t))) == NULL) {
+		printf("unable to allocate frame \n");
+		return BCME_NOMEM;
+	}
+	memset(query, 0, sizeof(wl_sa_query_t));
+
+	/* add the flag */
+	if (argc > 1 && argv[1]) {
+		query->flag = htod32(atoi(argv[1]));
+	}
+
+	/* add the action */
+	if (argc > 2 && argv[2]) {
+		query->action = htod32(atoi(argv[2]));
+	}
+
+	/* add the id */
+	if (argc > 3 && argv[3]) {
+		query->id = htod32(atoi(argv[3]));
+	}
+
+	err = wlu_var_setbuf(wl, "mfp_sa_query", query, sizeof(wl_sa_query_t));
+
+	free(query);
+
+	return (err);
+
+}
+
+static int
+wl_mfp_disassoc(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_disassoc";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(flag)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+static int
+wl_mfp_deauth(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_deauth";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(flag)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+static int
+wl_mfp_assoc(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_assoc";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(int)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+static int
+wl_mfp_auth(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_auth";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(int)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+
+static int
+wl_mfp_reassoc(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_reassoc";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(int)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+
+#ifdef EVENT_LOG_COMPILE
+static int wl_event_log_set_init(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_set_init";
+	wl_el_set_params_t pars;
+	int argc;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc != 3) {
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&pars, sizeof(wl_el_set_params_t), 0);
+	pars.set = atoi(argv[1]);
+	pars.size = htod32(atoi(argv[2]));
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+
+	return err;
+}
+
+static int wl_event_log_set_expand(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_set_expand";
+	wl_el_set_params_t pars;
+	int argc;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc != 3) {
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&pars, sizeof(wl_el_set_params_t), 0);
+	pars.set = atoi(argv[1]);
+	pars.size = htod32(atoi(argv[2]));
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+
+	return err;
+}
+
+static int wl_event_log_set_shrink(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_set_shrink";
+	wl_el_set_params_t pars;
+	int argc;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc != 2) {
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&pars, sizeof(wl_el_set_params_t), 0);
+	pars.set = atoi(argv[1]);
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+
+	return err;
+}
+
+static int wl_event_log_tag_control(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_tag_control";
+	wl_el_tag_params_t pars;
+	int argc;
+	int err;
+	int flags = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc < 4) {
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+
+	memset(&pars, sizeof(wl_el_tag_params_t), 0);
+	pars.tag = htod16(atoi(*argv++));
+	pars.set = atoi(*argv++);
+
+	while (*argv) {
+		if (!strcmp(*argv, "LOG")) {
+			flags |= EVENT_LOG_TAG_FLAG_LOG;
+		} else if (!strcmp(*argv, "PRINT")) {
+			flags |= EVENT_LOG_TAG_FLAG_PRINT;
+		} else if (!strcmp(*argv, "NONE")) {
+			flags |= EVENT_LOG_TAG_FLAG_NONE;
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+		argv++;
+	}
+
+	pars.flags = flags;
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+
+	return err;
+}
+#endif /* EVENT_LOG_COMPILE */
+
+
+static int
+wl_spatial_policy(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err, i, *reply;
+	int mode[SPATIAL_MODE_MAX_IDX] = {-1, -1, -1, -1, -1};
+
+	/* Order is 2G, 5G-LOW, 5G-MID, 5G-HIGH, 5G-UPPER
+	 * if only one argument given, than all band or sub-band take the
+	 * same value
+	 */
+	if (!*++argv) {
+		bool all_same = TRUE;
+		if ((err = wlu_var_getbuf(wl, cmd->name, &mode, sizeof(mode), &ptr)) < 0)
+			return err;
+		reply = (int *)ptr;
+		for (i = 1; i < SPATIAL_MODE_MAX_IDX; i++) {
+			 /* check if return values for each band/sub-band is same or not */
+			 if (reply[i-1] != reply[i])
+				 all_same = FALSE;
+		}
+		if (all_same)
+			printf("%2d\n", reply[0]);
+		else {
+			printf("2.4GHz       : %2d\n", reply[SPATIAL_MODE_2G_IDX]);
+			printf("5GHz (lower) : %2d\n", reply[SPATIAL_MODE_5G_LOW_IDX]);
+			printf("5GHz (middle): %2d\n", reply[SPATIAL_MODE_5G_MID_IDX]);
+			printf("5GHz (high)  : %2d\n", reply[SPATIAL_MODE_5G_HIGH_IDX]);
+			printf("5GHz (upper) : %2d\n", reply[SPATIAL_MODE_5G_UPPER_IDX]);
+		}
+		return 0;
+	}
+	mode[0] = atoi(*argv);
+	if (!*++argv) {
+		for (i = 1; i < SPATIAL_MODE_MAX_IDX; i++)
+			mode[i] = mode[0];
+	} else {
+		for (i = 1; i < SPATIAL_MODE_MAX_IDX; i++) {
+			mode[i] = atoi(*argv);
+			if (!*++argv && i < (SPATIAL_MODE_MAX_IDX - 1)) {
+				printf("error: missing arguments\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+	err = wlu_var_setbuf(wl, cmd->name, &mode, sizeof(mode));
+	return err;
+}
+
+static int
+wl_ratetbl_ppr(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err, i, *reply;
+	int val[12];
+
+	/* Order is 2G, 5G-LOW, 5G-MID, 5G-HIGH, 5G-UPPER
+	 * if only one argument given, than all band or sub-band take the
+	 * same value
+	 */
+	memset(&val, 0, sizeof(val));
+	if (!*++argv) {
+		if ((err = wlu_var_getbuf(wl, cmd->name, &val, sizeof(val), &ptr)) < 0)
+			return err;
+		reply = (int *)ptr;
+		for (i = 0; i < 12; i++)
+			printf("%s: %2d\n", (reply[i] & 0x80) ? "OFDM" : "CCK ", (reply[i] & 0x7f));
+		return 0;
+	}
+	val[0] = atoi(*argv++);
+	val[1] = atoi(*argv++);
+	err = wlu_var_setbuf(wl, cmd->name, &val, sizeof(val));
+	return err;
+}
+
+static int
+wlu_mempool(void *wl, cmd_t *cmd, char **argv)
+{
+	void               *ptr;
+	int                ret;
+	int                i;
+	wl_mempool_stats_t *stats;
+	bcm_mp_stats_t     *mp_stats;
+
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return ret;
+
+	stats = (wl_mempool_stats_t *) ptr;
+	mp_stats = stats->s;
+
+	printf("%-8s %8s %8s %8s %8s %8s\n", "Name", "SZ", "Max", "Curr", "HiWater", "Failed");
+	for (i = 0; i < stats->num; i++) {
+		printf("%-8s %8d %8d %8d %8d %8d\n", mp_stats->name, (int) mp_stats->objsz,
+		       mp_stats->nobj, mp_stats->num_alloc, mp_stats->high_water,
+		       mp_stats->failed_alloc);
+
+		mp_stats++;
+	}
+
+	return (0);
+}
+
+static int
+wl_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err;
+	uchar *data;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+	int iecount;
+	ie_setbuf_t *ie_setbuf;
+	ie_getbuf_t param;
+	uchar datalen, type, count, col;
+
+	/* parse a bsscfg_idx option if present */
+	if ((err = wl_cfg_option(argv + 1, argv[0], &bsscfg_idx, &consumed)) != 0)
+		return err;
+	if (consumed)
+		argv = argv + consumed;
+	else
+		bsscfg_idx = -1;
+
+	if (!*++argv) {
+		fprintf(stderr, "missing parameter type\n");
+		return BCME_USAGE_ERROR;
+	}
+	/* get IE type */
+	type = (uchar)atoi(argv[0]);
+
+	if (!*++argv) {
+		param.id = type;
+		ptr = buf;
+		if (bsscfg_idx == -1)
+			err = wlu_var_getbuf(wl, cmd->name, &param, sizeof(param), &ptr);
+		else
+			err = wl_bssiovar_getbuf(wl, cmd->name, bsscfg_idx, &param, sizeof(param),
+			buf, WLC_IOCTL_MAXLEN);
+		if (err == 0) {
+			data = (uchar *)ptr;
+			datalen = data[1]+2;
+			printf("%s len %d\n", cmd->name, datalen);
+			printf("%s Data:\n", cmd->name);
+			for (count = 0; (count < datalen);) {
+				for (col = 0; (col < MAX_DATA_COLS) &&
+					(count < datalen); col++, count++) {
+					printf("%02x", *data++);
+				}
+				printf("\n");
+			}
+		}
+		else {
+			fprintf(stderr, "Error %d getting IOVar\n", err);
+		}
+		return err;
+	}
+
+	/* get IE length */
+	datalen = (uchar)atoi(argv[0]);
+
+	if (datalen > 0) {
+		if (!argv[1]) {
+			fprintf(stderr, "Data bytes should be specified for IE of length %d\n",
+				datalen);
+			return BCME_USAGE_ERROR;
+		}
+		else {
+			/* Ensure each data byte is 2 characters long */
+			if ((int)strlen (argv[1]) < (datalen * 2)) {
+				fprintf(stderr, "Please specify all the data bytes for this IE\n");
+				return BCME_BADARG;
+			}
+		}
+	}
+
+	if ((datalen == 0) && (argv[1] != NULL))
+		fprintf(stderr, "Ignoring data bytes for IE of length %d\n", datalen);
+
+	count = sizeof(ie_setbuf_t) + datalen - 1;
+	data = malloc(count);
+	if (data == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+
+	ie_setbuf = (ie_setbuf_t *) data;
+	/* Copy the ie SET command ("add") to the buffer */
+	strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
+	ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+	/* Buffer contains only 1 IE */
+	iecount = htod32(1);
+	memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
+
+	/* Now, add the IE to the buffer */
+	ie_setbuf->ie_buffer.ie_list[0].ie_data.id = type;
+	ie_setbuf->ie_buffer.ie_list[0].ie_data.len = datalen;
+
+	if (datalen > 0) {
+		if ((err = get_ie_data ((uchar *)argv[1],
+		          (uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0],
+		          datalen))) {
+			free(data);
+			fprintf(stderr, "Error parsing data arg\n");
+			return err;
+		}
+	}
+
+	if (bsscfg_idx == -1)
+		err = wlu_var_setbuf(wl, cmd->name, data, count);
+	else
+		err = wlu_bssiovar_setbuf(wl, cmd->name, bsscfg_idx,
+			data, count, buf, WLC_IOCTL_MAXLEN);
+
+	free(data);
+	return (err);
+}
+
+static int
+wl_wnm_url(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err;
+	uchar *data;
+	uchar datalen, count;
+	wnm_url_t *url;
+
+	if (!*++argv) {
+		err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr);
+		if (err == 0) {
+			data = (uchar *)ptr;
+			datalen = data[0];
+			data ++;
+			*(data + datalen) = '\0';
+			printf("%s URL len %d\n", cmd->name, datalen);
+			printf("%s URL: %s\n", cmd->name, data);
+		}
+		else {
+			fprintf(stderr, "Error %d getting IOVar\n", err);
+		}
+		return err;
+	}
+
+	/* get URL length */
+	datalen = (uchar)atoi(argv[0]);
+
+	if (datalen > 0) {
+		if (!argv[1]) {
+			fprintf(stderr, "URL string should be specified for URL length %d\n",
+				datalen);
+			return BCME_BADARG;
+		}
+		else {
+			if ((int)strlen (argv[1]) != datalen) {
+				fprintf(stderr, "length is not matching to string\n");
+				return BCME_BADARG;
+			}
+		}
+	}
+
+	if ((datalen == 0) && (argv[1] != NULL))
+		fprintf(stderr, "Ignoring data bytes for length %d\n", datalen);
+
+	count = sizeof(wnm_url_t) + datalen - 1;
+	data = malloc(count);
+	if (data == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+
+	url = (wnm_url_t *) data;
+	url->len = datalen;
+	if (datalen > 0) {
+		memcpy(url->data, argv[1], datalen);
+	}
+
+	err = wlu_var_setbuf(wl, cmd->name, data, count);
+
+	free(data);
+	return (err);
+}
+
+/* Restore the ignored warnings status */
+
+
+static int
+wl_sleep_ret_ext(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc, i;
+	uint32 val;
+	char *endptr = NULL;
+	wl_pm2_sleep_ret_ext_t sleep_ret_ext;
+	wl_pm2_sleep_ret_ext_t* sleep_ret_ext_ptr;
+
+	/* Skip the command name */
+	UNUSED_PARAMETER(cmd);
+	argv++;
+
+	/* If no arguments are given, print the existing settings */
+	argc = ARGCNT(argv);
+	if (argc == 0) {
+		char *logic_str;
+
+		/* Get and print the values */
+		if ((ret = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, (void*) &sleep_ret_ext_ptr)))
+			return ret;
+
+		if (sleep_ret_ext_ptr->logic == WL_DFRTS_LOGIC_OFF)
+			logic_str = "DISABLED";
+		else if (sleep_ret_ext_ptr->logic == WL_DFRTS_LOGIC_OR)
+			logic_str = "OR";
+		else if (sleep_ret_ext_ptr->logic == WL_DFRTS_LOGIC_AND)
+			logic_str = "AND";
+		else
+			logic_str = "ERROR";
+
+		printf("logic: %d (%s)\n",
+		       sleep_ret_ext_ptr->logic, logic_str);
+		if (sleep_ret_ext_ptr->logic != WL_DFRTS_LOGIC_OFF) {
+			printf("low_ms: %d\n", sleep_ret_ext_ptr->low_ms);
+			printf("high_ms: %d\n", sleep_ret_ext_ptr->high_ms);
+			printf("rx_pkts_threshold: %d\n",
+				sleep_ret_ext_ptr->rx_pkts_threshold);
+			printf("tx_pkts_threshold: %d\n",
+			       sleep_ret_ext_ptr->tx_pkts_threshold);
+			printf("txrx_pkts_threshold: %d\n",
+			       sleep_ret_ext_ptr->txrx_pkts_threshold);
+			printf("rx_bytes_threshold: %d\n",
+			       sleep_ret_ext_ptr->rx_bytes_threshold);
+			printf("tx_bytes_threshold: %d\n",
+			       sleep_ret_ext_ptr->tx_bytes_threshold);
+			printf("txrx_bytes_threshold: %d\n",
+			       sleep_ret_ext_ptr->txrx_bytes_threshold);
+		}
+		return 0;
+	}
+
+	memset(&sleep_ret_ext, 0, sizeof(wl_pm2_sleep_ret_ext_t));
+	i = 0;
+
+	/* Get the first 'logic' argument. */
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	if (val != WL_DFRTS_LOGIC_OFF && val != WL_DFRTS_LOGIC_OR &&
+		val != WL_DFRTS_LOGIC_AND) {
+		printf("Invalid logic value %u\n", val);
+		goto usage;
+	}
+	sleep_ret_ext.logic = val;
+	++i;
+
+	/* If logic is 0 (disable) then no more arguments are needed */
+	if (sleep_ret_ext.logic == 0)
+		goto set;
+
+	if (argc < 9)
+		goto usage;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.low_ms = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.high_ms = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.rx_pkts_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.tx_pkts_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.txrx_pkts_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.rx_bytes_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.tx_bytes_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.txrx_bytes_threshold = val;
+	++i;
+
+	if (i != argc)
+		goto usage;
+
+set:
+	return wlu_var_setbuf(wl, cmd->name, &sleep_ret_ext,
+		sizeof(wl_pm2_sleep_ret_ext_t));
+
+usage:
+	printf("Usage: %s [logic] [<low_ms> <high_ms>"
+		" <rxP> <txP> <txrxP> <rxB> <txB> <txrxB>\n", wlu_av0);
+	printf("Parameters:\n");
+	printf("logic   : 0=disable, 1=OR, 2=AND all non-zero switching thresholds.\n");
+	printf("low_ms  : Low pm2_sleep_ret value.\n");
+	printf("high_ms : High pm2_sleep_ret value.\n");
+	printf("rxP     : Switching threshold in # of rx packets.\n");
+	printf("          eg. Switch from the low to high FRTS value if rxP or\n");
+	printf("          more packets are received in a PM2 radio wake period.\n");
+	printf("          0 means ignore this threshold.\n");
+	printf("txP     : Switching threshold in # of tx packets.\n");
+	printf("txrxP   : Switching threshold in # of combined tx+rx packets.\n");
+	printf("rxB     : Switching threshold in # of rx bytes.\n");
+	printf("txB     : Switching threshold in # of tx bytes.\n");
+	printf("txrxB   : Switching threshold in # of combined tx+rx bytes.\n");
+	return -1;
+}
+
+static int wl_stamon_sta_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	wlc_stamon_sta_config_t stamon_cfg;
+
+	memset(&stamon_cfg, 0, sizeof(wlc_stamon_sta_config_t));
+	if (!*++argv) {
+		err = wlu_iovar_get(wl, cmd->name, &stamon_cfg,
+			sizeof(wlc_stamon_sta_config_t));
+		if (!err)
+			printf("%s \n", wl_ether_etoa(&stamon_cfg.ea));
+	} else {
+		if (!stricmp(*argv, "add"))
+			stamon_cfg.cmd = STAMON_CFG_CMD_ADD;
+		else if (!stricmp(*argv, "del"))
+			stamon_cfg.cmd = STAMON_CFG_CMD_DEL;
+		else {
+			printf("error: unknown operation option%s\n", *argv);
+			err =  -1;
+		}
+
+		if (!err) {
+			argv++;
+			if (!*argv || !wl_ether_atoe(*argv, &stamon_cfg.ea)) {
+				printf(" ERROR: no valid ether addr provided\n");
+				err = -1;
+			} else {
+				err = wlu_iovar_set(wl, cmd->name,
+					&stamon_cfg, sizeof(wlc_stamon_sta_config_t));
+			}
+		}
+	}
+
+	return err;
+}
+
+static monitor_promisc_level_msg_t wl_monpromisc_level_msgs[] = {
+	{WL_MONPROMISC_PROMISC,	"promisc"},
+	{WL_MONPROMISC_CTRL, "ctrl"},
+	{WL_MONPROMISC_FCS, "fcs"},
+	{0,		NULL}
+};
+
+static int
+wl_monitor_promisc_level(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val = 0, last_val = 0;
+	uint promiscbitmap = 0, promiscbitmap_add = 0, promiscbitmap_del = 0;
+	char *endptr;
+	const char *cmdname = "monitor_promisc_level";
+
+	UNUSED_PARAMETER(cmd);
+	if ((ret = wlu_iovar_getint(wl, cmdname, (int *)&promiscbitmap) < 0)) {
+		return ret;
+	}
+	promiscbitmap = dtoh32(promiscbitmap);
+	if (!*++argv) {
+		printf("0x%x ", promiscbitmap);
+		for (i = 0; (val = wl_monpromisc_level_msgs[i].value); i++) {
+			if ((promiscbitmap & val) && (val != last_val))
+				printf(" %s", wl_monpromisc_level_msgs[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			promiscbitmap_del = ~0; /* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		if (val == 0xFFFFFFFF) {
+			fprintf(stderr,
+				"Bits >32 are not supported on this driver version\n");
+			val = 1;
+		}
+		/* not an integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = wl_monpromisc_level_msgs[i].value); i++)
+				if (stricmp(wl_monpromisc_level_msgs[i].string, s) == 0)
+					break;
+				if (!val)
+					goto usage;
+		}
+		if (**argv == '-')
+			promiscbitmap_del |= val;
+		else
+			promiscbitmap_add |= val;
+		++argv;
+	}
+	promiscbitmap &= ~promiscbitmap_del;
+	promiscbitmap |= promiscbitmap_add;
+	promiscbitmap = htod32(promiscbitmap);
+	return (wlu_iovar_setint(wl, cmdname, (int)promiscbitmap));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+	for (i = 0; (val = wl_monpromisc_level_msgs[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, wl_monpromisc_level_msgs[i].string);
+		else
+			fprintf(stderr, ", %s", wl_monpromisc_level_msgs[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+	return 0;
+}
+
+#if defined(DWDS)
+static int
+wl_dwds_config(void *wl, cmd_t *cmd, char **argv)
+{
+	wlc_dwds_config_t dwds;
+	int err;
+
+	memset(&dwds, 0, sizeof(wlc_dwds_config_t));
+
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return -1;
+	}
+
+	if (!stricmp(*argv, "enable"))
+		dwds.enable = 1;
+	else if (!stricmp(*argv, "disable"))
+		dwds.enable = 0;
+	else {
+		printf("error: unknown mode option %s\n", *argv);
+		return -1;
+	}
+	argv++;
+	/* look for sta/dwds */
+	if (!stricmp(*argv, "sta"))
+		dwds.mode = 1;
+	else if (!stricmp(*argv, "ap"))
+		dwds.mode = 0;
+	else {
+		printf("error: unknown mode option %s\n", *argv);
+		return -1;
+	}
+
+	argv++;
+	/* convert the ea string into an ea struct */
+	if (!*argv || !wl_ether_atoe(*argv, &dwds.ea)) {
+		printf(" ERROR: no valid ether addr provided\n");
+		return -1;
+	}
+
+	if ((err = wlu_iovar_set(wl, cmd->name, &dwds, sizeof(wlc_dwds_config_t))) < 0)
+		return err;
+
+	return (0);
+
+}
+#endif /* DWDS */
+
+static int
+wl_bss_peer_info(void *wl, cmd_t *cmd, char **argv)
+{
+	bss_peer_list_info_t *info;
+	bss_peer_info_t *peer_info;
+	bss_peer_info_param_t param;
+	int err, i;
+	void *ptr;
+
+	memset(&param, 0, sizeof(bss_peer_info_param_t));
+	param.version = htod16(BSS_PEER_INFO_PARAM_CUR_VER);
+
+	if (*++argv) {
+		if (!wl_ether_atoe(*argv, &param.ea)) {
+			printf(" ERROR: no valid ether addr provided\n");
+			return -1;
+		}
+	}
+
+	if ((err = wlu_var_getbuf_med(wl, cmd->name, &param, sizeof(bss_peer_info_param_t),
+		&ptr)) < 0)
+		return err;
+
+	info = (bss_peer_list_info_t*)ptr;
+
+	if ((dtoh16(info->version) != BSS_PEER_LIST_INFO_CUR_VER) ||
+		(dtoh16(info->bss_peer_info_len) != sizeof(bss_peer_info_t))) {
+		printf("BSS peer info version/structure size mismatch driver %d firmware %d \r\n",
+			BSS_PEER_LIST_INFO_CUR_VER, dtoh16(info->version));
+		return -1;
+	}
+
+	if (WLC_IOCTL_MEDLEN < (BSS_PEER_LIST_INFO_FIXED_LEN +
+		(dtoh32(info->count) * sizeof(bss_peer_info_t)))) {
+		printf("ERROR : peer list received exceed the buffer size\r\n");
+	}
+
+	for (i = 0; i < (int)dtoh32(info->count); i++) {
+		peer_info = &info->peer_info[i];
+		peer_info->rateset.count = dtoh32(peer_info->rateset.count);
+		printf("PEER%d: MAC: %s: RSSI %d TxRate %d kbps RxRate %d kbps age : %ds\r\n",
+			i, wl_ether_etoa(&peer_info->ea), peer_info->rssi,
+			dtoh32(peer_info->tx_rate), dtoh32(peer_info->rx_rate),
+			dtoh32(peer_info->age));
+			printf("\t rateset ");
+			dump_rateset(peer_info->rateset.rates, peer_info->rateset.count);
+			printf("\r\n");
+	}
+
+	return 0;
+}
+
+static int
+wl_aibss_txfail_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = USAGE_ERROR;
+	aibss_txfail_config_t txfail_config;
+
+	if (!*++argv) {
+		/* Get */
+		memset(&txfail_config, 0, sizeof(txfail_config));
+		/* get current rateset */
+		if ((ret = wlu_iovar_get(wl, cmd->name, &txfail_config,
+		        sizeof(txfail_config))) < 0)
+		        goto error;
+
+		printf("AIBSS TXFAIL config beacon timeout duration: %d \r\n"
+		                "Max consecutive Tx failure before TXFAIL event:%d \r\n",
+		                txfail_config.bcn_timeout, txfail_config.max_tx_retry);
+	}
+	else {
+		char *p = argv[0];
+		char *endptr = NULL;
+
+		/* Extract the content */
+		if (!p || *p == '\0')
+		        goto error;
+
+		txfail_config.bcn_timeout = strtoul(p, &endptr, 0);
+
+		p = endptr;
+		/* check and skip , */
+		if (*p == '\0' || *++p == '\0')
+		        goto error;
+
+		txfail_config.max_tx_retry = strtoul(p, &endptr, 0);
+
+
+		if (*endptr != '\0')
+		        goto error;
+		txfail_config.version = AIBSS_TXFAIL_CONFIG_VER_0;
+		txfail_config.len = sizeof(txfail_config);
+		ret = wlu_iovar_set(wl, cmd->name, (void *) &txfail_config,
+		        sizeof(txfail_config));
+	}
+
+error:
+	return ret;
+}
+
+static int
+wl_bssload_static(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_bssload_static_t bssload;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* get */
+	if (!argv[1]) {
+		if ((err = wlu_iovar_get(wl, cmd->name, &bssload, sizeof(bssload))) < 0)
+			return err;
+		if (bssload.is_static) {
+			printf("station count: %d\n", dtoh16(bssload.sta_count));
+			printf("channel utilization: %d\n", bssload.chan_util);
+			printf("avail admission capacity: %d\n", dtoh16(bssload.aac));
+		}
+	}
+	else {
+		/* set */
+		argv++;
+		memset(&bssload, 0, sizeof(bssload));
+		if (!stricmp(*argv, "off")) {
+			bssload.is_static = FALSE;
+		}
+		else {
+			bssload.sta_count = htod16(strtoul(*argv, NULL, 0));
+
+			if (*++argv == NULL) {
+				printf("wl_bssload_static: "
+					"channel utilization not provided\n");
+				return -1;
+			}
+			bssload.chan_util = strtoul(*argv, NULL, 0);
+
+			if (*++argv == NULL) {
+				printf("wl_bssload_static: "
+					"avail admission capacity not provided\n");
+				return -1;
+			}
+			bssload.aac = htod16(strtoul(*argv, NULL, 0));
+
+			bssload.is_static = TRUE;
+		}
+
+		err = wlu_iovar_set(wl, cmd->name, &bssload, sizeof(bssload));
+	}
+
+	return err;
+}
+
+#ifdef TBTT_OFFSET_STAT
+static int
+wl_tbtt_offset_stat(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	tbtt_offset_stat_t *tbtt_offset_stat = NULL;
+
+	UNUSED_PARAMETER(argv);
+
+	/* Get only */
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, (void **)(&tbtt_offset_stat))) < 0)
+		return (ret);
+
+	printf("avg: %d\nmin: %d\nmax: %d\n",
+	       dtoh32(tbtt_offset_stat->tbtt_offset_avg),
+	       dtoh32(tbtt_offset_stat->tbtt_offset_min),
+	       dtoh32(tbtt_offset_stat->tbtt_offset_max));
+
+	return 0;
+}
+#endif /* TBTT_OFFSET_STAT */
+
+#ifdef WIN32
+#pragma warning(pop)
+#endif
diff --git a/src/wl/exe/wlu.h b/src/wl/exe/wlu.h
new file mode 100644
index 0000000..5fde76d
--- /dev/null
+++ b/src/wl/exe/wlu.h
@@ -0,0 +1,115 @@
+/*
+ * Common code for wl command line utility
+ *
+ * Copyright 2002, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied or
+ * duplicated in any form, in whole or in part, without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * $Id: wlu.h 432727 2013-10-29 12:39:22Z $
+ */
+
+#ifndef _wlu_h_
+#define _wlu_h_
+
+#include "wlu_cmd.h"
+
+extern const char *wlu_av0;
+extern int g_wlc_idx;
+
+/* parse common option */
+extern int wl_option(char ***pargv, char **pifname, int *phelp);
+extern void wl_cmd_init(void);
+extern void wlu_init(void);
+
+/* print usage */
+extern void wl_cmd_usage(FILE *fid, cmd_t *cmd);
+extern void wl_usage(FILE *fid, cmd_t *port_cmds);
+extern void wl_cmds_usage(FILE *fid, cmd_t *port_cmds);
+
+/* print helpers */
+extern void wl_printlasterror(void *wl);
+extern void wl_printint(int val);
+
+/* pretty print an SSID */
+extern int wl_format_ssid(char* buf, uint8* ssid, int ssid_len);
+
+/* pretty hex print a contiguous buffer */
+extern void wl_hexdump(uchar *buf, uint nbytes);
+
+/* check driver version */
+extern int wl_check(void *wl);
+
+/* wl functions used by the ndis wl. */
+extern void dump_rateset(uint8 *rates, uint count);
+extern uint freq2channel(uint freq);
+extern int wl_ether_atoe(const char *a, struct ether_addr *n);
+extern char *wl_ether_etoa(const struct ether_addr *n);
+struct ipv4_addr;	/* forward declaration */
+extern int wl_atoip(const char *a, struct ipv4_addr *n);
+extern char *wl_iptoa(const struct ipv4_addr *n);
+extern cmd_func_t wl_int;
+extern cmd_func_t wl_varint;
+extern void wl_dump_raw_ie(bcm_tlv_t *ie, uint len);
+extern int wl_mk_ie_setbuf(const char *command, uint32 pktflag_ok, char **argv,
+	vndr_ie_setbuf_t **buf, int *buf_len);
+extern cmd_func_t wl_list_ie;
+
+extern void wl_printlasterror(void *wl);
+extern bool wc_cmd_check(const char *cmd);
+
+
+/* functions for downloading firmware to a device via serial or other transport */
+
+#ifdef BCMDLL
+#ifdef LOCAL
+extern FILE *dll_fd;
+#else
+extern void * dll_fd_out;
+extern void * dll_fd_in;
+#endif
+#undef printf
+#undef fprintf
+#define printf printf_to_fprintf	/* printf to stdout */
+#define fprintf fprintf_to_fprintf	/* fprintf to stderr */
+extern void fprintf_to_fprintf(FILE * stderror, const char *fmt, ...);
+extern void printf_to_fprintf(const char *fmt, ...);
+extern void raw_puts(const char *buf, void *dll_fd_out);
+#define	fputs(buf, stdout) raw_puts(buf, dll_fd_out)
+#endif /* BCMDLL */
+
+#define RAM_SIZE_4325  0x60000
+#define RAM_SIZE_4329  0x48000
+#define RAM_SIZE_43291 0x60000
+#define RAM_SIZE_4330_a1  0x3c000
+#define RAM_SIZE_4330_b0  0x48000
+
+/* useful macros */
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a)  (sizeof(a)/sizeof(a[0]))
+#endif /* ARRAYSIZE */
+
+/* buffer length needed for wl_format_ssid
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL
+ */
+#define SSID_FMT_BUF_LEN (4*32+1)	/* Length for SSID format string */
+
+#define USAGE_ERROR  -1		/* Error code for Usage */
+#define CMD_DEPRECATED -4 /* Commands that are functionally deprecated or don't provide
+			   * a useful value to a specific OS port of wl
+			   */
+
+/* integer output format */
+#define INT_FMT_DEC	0	/* signed integer */
+#define INT_FMT_UINT	1	/* unsigned integer */
+#define INT_FMT_HEX	2	/* hexdecimal */
+
+/* command line argument usage */
+#define CMD_ERR	-1	/* Error for command */
+#define CMD_OPT	0	/* a command line option */
+#define CMD_WL	1	/* the start of a wl command */
+
+#endif /* _wlu_h_ */
diff --git a/src/wl/exe/wlu_client_shared.c b/src/wl/exe/wlu_client_shared.c
new file mode 100644
index 0000000..1ad7950
--- /dev/null
+++ b/src/wl/exe/wlu_client_shared.c
@@ -0,0 +1,1220 @@
+/*
+ * Common code for remotewl client
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_client_shared.c 430139 2013-10-17 11:15:17Z $
+ */
+#ifdef WIN32
+#define NEED_IR_TYPES
+
+#include <winsock2.h>
+#include <windows.h>
+#include <ntddndis.h>
+#include <epictrl.h>
+#include <irelay.h>
+#include <winioctl.h>
+#include <nuiouser.h>
+#else /* LINUX */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <net/if.h>
+#include <unistd.h>
+#endif /* WIN32 */
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <proto/ethernet.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#include <signal.h>
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
+#include <rwl_wifi.h>
+#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
+#include "wlu.h"
+#include "wlu_remote.h"
+#include "wlu_pipe.h"
+#include "wlu_client_shared.h"
+
+char* remote_vista_cmds[] = {"join", "sup_wpa", "wsec", "set_pmk", "legacylink", "list",
+	"disassoc", "xlist", NULL};
+int vista_cmd_index;
+#define SHELL_CMD_LEN (256)
+
+#ifdef RWL_SOCKET
+extern int validate_server_address();
+static int rwl_socket_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf);
+#endif
+static int rwl_dongle_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf, int cmd);
+#ifdef RWL_WIFI
+static int rwl_wifi_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf);
+#endif
+/* We don't want the server to allocate bigger buffers for some of the commands
+ * like scanresults. Server can still allocate 8K memory and send the response
+ * in fragments. This is used in case of Get commands only.
+ */
+#define SERVER_RESPONSE_MAX_BUF_LEN 8192
+
+extern unsigned short g_rwl_servport;
+extern char *g_rwl_servIP;
+int g_child_pid;
+#ifdef RWL_WIFI
+/* dword align allocation */
+static union {
+	char bufdata[WLC_IOCTL_MAXLEN];
+	uint32 alignme;
+} bufstruct_wlu;
+static char *g_rwl_aligned_buf = (char*) &bufstruct_wlu.bufdata;
+
+extern char *g_rwl_buf_mac;
+#endif
+#ifdef RWL_SOCKET
+/* Make initial connection from client to server through sockets */
+static int
+rwl_connect_socket_server(void)
+{
+	int SockDes = -1;
+	struct sockaddr_in servAddr;
+	memset(&servAddr, 0, sizeof(servAddr));
+	if ((SockDes = (*(int *)rwl_open_pipe(remote_type, "\0", 0, 0))) == FAIL)
+		return FAIL;
+	if (!validate_server_address())
+		return FAIL;
+	DPRINT_DBG(OUTPUT, "ServerIP:%s,ServerPort:%d\n", g_rwl_servIP, g_rwl_servport);
+	servAddr.sin_family = AF_INET;
+	servAddr.sin_port = hton16(g_rwl_servport);
+	servAddr.sin_addr.s_addr = inet_addr(g_rwl_servIP);
+
+	if (rwl_sockconnect(SockDes, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
+		rwl_close_pipe(remote_type, (void*) &SockDes);
+		return FAIL;
+	}
+	return SockDes;
+}
+
+/* This routine is used for both Get and Set Ioctls for the socket */
+static int
+rwl_information_socket(void *wl, int cmd, void* input_buf, unsigned long *input_len,
+	unsigned long *tx_len, uint flags)
+{
+	int error, Sockfd;
+	rem_ioctl_t *rem_ptr = NULL;
+
+	if ((Sockfd = rwl_connect_socket_server()) < 0) {
+		DPRINT_ERR(ERR, "Error in getting the Socket Descriptor\n");
+		return FAIL;
+	}
+	wl = (void *)(&Sockfd);
+
+	if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
+		*tx_len, flags, 0) < 0) {
+		DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+
+	if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+		DPRINT_ERR(ERR, "query_info_fe: Reading CDC header 	failed\n");
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+	rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+
+	if (rem_ptr->msg.len > *input_len) {
+		DPRINT_ERR(ERR, "query_info_fe: needed size(%d) > "
+		           "actual size(%ld)\n", rem_ptr->msg.len, *input_len);
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+
+	if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) {
+		DPRINT_ERR(ERR, "query_info_fe: No results!\n");
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+
+	if (rem_ptr->msg.flags & REMOTE_REPLY)
+		error = rem_ptr->msg.cmd;
+	else
+		error = 0;
+
+	rwl_close_pipe(remote_type, wl);
+
+	return error;
+}
+#endif /* RWL_SOCKET */
+/*
+ * Receives the fragmented response from serial server.
+ * Called from rwl_queryinformation_fe front end function for dongle case only when
+ * the client expects data in chunks more than DATA_FRAME_LEN * (960) bytes.
+ */
+static int
+rwl_serial_fragmented_response_fe(void *wl, rem_ioctl_t *rem_ptr, void* input_buf,
+unsigned long *bytes_to_read)
+{
+	int error;
+	uint32 total_numread;
+	uchar *local_buf, *local_result;
+	uint frames_to_read, frame_count;
+
+	DPRINT_DBG(OUTPUT, "rem_ptr->msg.len=%d \t rem_ptr->data_len=%d\n",
+		rem_ptr->msg.len, rem_ptr->data_len);
+
+	/* Calculate the number of frames for the response */
+	if (rem_ptr->data_len == 0) {
+		DPRINT_ERR(ERR, "data_len is:%d\n", rem_ptr->data_len);
+		return (FAIL);
+	}
+	frames_to_read = (*bytes_to_read)/rem_ptr->data_len;
+	if ((*bytes_to_read) % rem_ptr->data_len > 0)
+		frames_to_read += 1;
+
+	DPRINT_DBG(OUTPUT, "No of frames=%d\n", frames_to_read);
+
+	if ((local_result = (uchar*)malloc(rem_ptr->msg.len)) == NULL) {
+		DPRINT_ERR(ERR, "Malloc failed for serial fragmented frame"
+		"local result \n");
+		return FAIL;
+	}
+
+	/* Response will come in DATA_FRAME_LEN + REMOTE_SIZE (960+16) bytes
+	 * packet with CDC header and then followed by response.
+	 */
+	total_numread = 0;
+	frame_count = 0;
+	while (total_numread != *bytes_to_read) {
+		local_buf = (uchar*)malloc(rem_ptr->data_len);
+		if (local_buf == NULL) {
+			free(local_result);
+			return FAIL;
+		}
+
+		DPRINT_DBG(OUTPUT, "Total bytes=%d\n", total_numread);
+		DPRINT_DBG(OUTPUT, "Frame (Reverse):%d\n", frames_to_read);
+
+		if (remote_CDC_rx(wl, rem_ptr, local_buf, rem_ptr->data_len, 0) == -1) {
+			free(local_buf);
+			free(local_result);
+			return FAIL;
+		}
+
+		/* Concatenate the response to loc_res. */
+		memcpy(&local_result[frame_count*DATA_FRAME_LEN], local_buf,
+			rem_ptr->data_len);
+
+		total_numread += rem_ptr->data_len;
+		frame_count++;
+		frames_to_read--;
+
+		DPRINT_DBG(OUTPUT, "Total bytes=%d\n", total_numread);
+
+		if (frames_to_read == 0) {
+			/* When all the frames are received copy the data to original buf */
+			memcpy(input_buf, local_result, total_numread);
+			if (rem_ptr->msg.flags & REMOTE_REPLY) {
+				error = rem_ptr->msg.cmd;
+			}
+		}
+
+		if (total_numread != *bytes_to_read) {
+			/* Receive the next header */
+			if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+				DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed");
+			}
+		}
+		free(local_buf);
+	}
+	free(local_result);
+	return error;
+}
+
+/* This routine is common to both set and Get Ioctls for the dongle case */
+static int
+rwl_information_dongle(void *wl, int cmd, void* input_buf, unsigned long *input_len,
+	uint tx_len, uint flags)
+{
+	int error;
+	rem_ioctl_t *rem_ptr = NULL;
+
+	if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
+		tx_len, flags, 0) < 0) {
+		DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
+		return FAIL;
+	}
+
+	/* Get the header */
+	if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+		DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
+		return BCME_SERIAL_PORT_ERR;
+	}
+
+	/* Make sure there is enough room */
+	if (rem_ptr->msg.len > *input_len) {
+		DPRINT_DBG(OUTPUT, "query_info_fe: needed size(%d) > actual"
+			"size(%ld)\n", rem_ptr->msg.len, *input_len);
+		return FAIL;
+	}
+
+	/*  We can grab short frames all at once.  Longer frames (> 960 bytes)
+	 *  come in fragments.
+	*/
+	if (rem_ptr->data_len < DATA_FRAME_LEN) {
+		if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) {
+			DPRINT_ERR(ERR, "query_info_fe: No results!\n");
+			return FAIL;
+		}
+		if (rem_ptr->msg.flags & REMOTE_REPLY)
+			error = rem_ptr->msg.cmd;
+		else
+			error = 0;
+	} else {
+		/* rwl_serial_fragmented_response_fe returns either valid number or FAIL.
+		  * In any case return the same value to caller
+		*/
+		error = rwl_serial_fragmented_response_fe(wl, rem_ptr, input_buf, input_len);
+	}
+	return error;
+}
+/* Handler to signal the reader thread that ctrl-C is pressed */
+volatile sig_atomic_t g_sig_ctrlc = 1;
+void ctrlc_handler(int num)
+{
+	UNUSED_PARAMETER(num);
+	g_sig_ctrlc = 0;
+}
+
+/* Issue shell commands independent of transport type and return result */
+static int
+rwl_shell_information_fe(void *wl, int cmd, uchar* input_buf, unsigned long *input_len)
+{
+	int error, remote_cmd;
+	uchar* resp_buf = NULL;
+	rem_ioctl_t *rem_ptr = NULL;
+
+#ifdef RWL_WIFI
+	char *cbuf, retry;
+	dot11_action_wifi_vendor_specific_t *list;
+#endif
+
+#ifdef RWL_SOCKET
+	int Sockfd;
+#endif
+
+	remote_cmd = REMOTE_SHELL_CMD;
+
+#ifdef RWLASD
+	if (cmd == ASD_CMD)
+		remote_cmd = REMOTE_ASD_CMD;
+#endif
+	if (cmd == VISTA_CMD)
+		remote_cmd = REMOTE_VISTA_CMD;
+
+	switch (remote_type) {
+		case REMOTE_SOCKET:
+#ifdef RWL_SOCKET
+			if ((Sockfd = rwl_connect_socket_server()) < 0) {
+				DPRINT_ERR(ERR, " Error in getting the SocDes\n");
+				return BCME_ERROR;
+			}
+
+			wl = (void *)(&Sockfd);
+			if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
+				remote_cmd, 0) < 0) {
+				DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
+				rwl_close_pipe(remote_type, wl);
+				return BCME_ERROR;
+			}
+			/* For backward compatibility for ASD, async and kill commands do the
+			 * old way
+			 */
+			if (remote_cmd == REMOTE_SHELL_CMD && !strstr((char*)input_buf, "%") &&
+				!strstr((char*)input_buf, "kill"))
+				error = rwl_socket_shellresp(wl, rem_ptr, input_buf);
+			else {
+				if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+					DPRINT_ERR(ERR, "shell_info_fe: Receiving CDC"
+						"header failed\n");
+					rwl_close_pipe(remote_type, wl);
+					return FAIL;
+				}
+
+				if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+					DPRINT_ERR(ERR, "Mem alloc fails\n");
+					rwl_close_pipe(remote_type, wl);
+					return FAIL;
+				}
+
+				if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+					rem_ptr->msg.len, 0) == FAIL) {
+					DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
+					rwl_close_pipe(remote_type, wl);
+					free(resp_buf);
+					return FAIL;
+				}
+
+				/* print the shell result */
+				resp_buf[rem_ptr->msg.len] = '\0';
+				/* The return value of the shell command
+				 * will be stored in rem_ptr->msg.cmd
+				 * Return that value to the client process
+				 */
+				if (rem_ptr->msg.flags & REMOTE_REPLY)
+					error = rem_ptr->msg.cmd;
+				fputs((char*)resp_buf, stdout);
+			}
+			rwl_close_pipe(remote_type, wl);
+#endif /* RWL_SOCKET */
+			break;
+		case REMOTE_DONGLE:
+		case REMOTE_SERIAL:
+			if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
+			                  remote_cmd, 0) < 0) {
+				DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
+				return FAIL;
+			}
+
+			/* For backward compatibility for ASD, async and kill commands do the
+			 * old way
+			 */
+			if (remote_cmd != REMOTE_ASD_CMD && !strstr((char*)input_buf, "%") &&
+				!strstr((char*)input_buf, "kill"))
+				error = rwl_dongle_shellresp(wl, rem_ptr, input_buf, cmd);
+			else {
+				if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+					DPRINT_ERR(ERR, "shell_info_fe:"
+					"Receiving CDC header failed\n");
+					return BCME_SERIAL_PORT_ERR;
+				}
+			rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+			/* In case of shell or ASD commands the response
+			 * size is not known in advance
+			 * Hence based on response from the server memory is allocated
+			 */
+			if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+				DPRINT_ERR(ERR, "Mem alloc fails for shell response buffer\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->data_len < DATA_FRAME_LEN) {
+				/* Response comes in one shot not in fragments */
+				if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+					rem_ptr->msg.len, 0) == FAIL) {
+					DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
+					free(resp_buf);
+					return FAIL;
+				}
+			} else {
+				error = rwl_serial_fragmented_response_fe(wl, rem_ptr,
+					resp_buf, (unsigned long *)&(rem_ptr->msg.len));
+			}
+			/* print the shell result */
+			resp_buf[rem_ptr->msg.len] = '\0';
+			/* The return value of the shell command will be stored in rem_ptr->msg.cmd
+			 * Return that value to the client process
+			 */
+				if (rem_ptr->msg.flags & REMOTE_REPLY)
+					error = rem_ptr->msg.cmd;
+			fputs((char*)resp_buf, stdout);
+			}
+			break;
+
+		case REMOTE_WIFI:
+#ifdef RWL_WIFI
+			/* Unlike dongle or UART case the response for wi-fi comes in single frame.
+			 * (CDC header + data). Hence the single read is called for header and data.
+			 * If any error in reading then we sleep for some time before retrying.
+			 */
+			if ((list = (dot11_action_wifi_vendor_specific_t *)
+				malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+				return FAIL;
+			}
+			if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
+				free(list);
+				return FAIL;
+			}
+
+			if ((cbuf = (char*) malloc(*input_len)) == NULL) {
+				DPRINT_ERR(ERR, "Malloc failed for shell response\n");
+				free(rem_ptr);
+				free(list);
+				return FAIL;
+			}
+
+			/* copy of the original buf is required for retry */
+			memcpy(cbuf, (char*)input_buf, *input_len);
+			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+
+				rwl_wifi_purge_actionframes(wl);
+				if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
+				remote_cmd, 0) < 0) {
+						DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
+							"Send command failed\n");
+						rwl_sleep(RWL_WIFI_RETRY_DELAY);
+						free(rem_ptr);
+						free(list);
+						return FAIL;
+				}
+				/* For backward compatibility for ASD,
+				 * async and kill commands do the
+				 * old way
+				 */
+				if (remote_cmd == REMOTE_SHELL_CMD &&
+					!strstr((char*)input_buf, "%") &&
+					!strstr((char*)input_buf, "kill")) {
+					error = rwl_wifi_shellresp(wl, rem_ptr, input_buf);
+						if (rem_ptr->msg.len == 0)
+						break;
+					}
+				else if (remote_cmd == REMOTE_VISTA_CMD) {
+					if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0,
+					NULL, RWL_WIFI_SHELL_CMD)) < 0) {
+						DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
+						"error in reading shell response\n");
+						continue;
+					}
+					if (rem_ptr->msg.flags & REMOTE_REPLY) {
+						 error = rem_ptr->msg.cmd;
+						 break;
+					} else {
+						rwl_sleep(RWL_WIFI_RETRY_DELAY);
+						continue;
+					}
+				}
+				else {
+					/* ASD commands may take long time to give back
+					* the response (eg: file transfer)
+					*/
+					if (remote_cmd == REMOTE_ASD_CMD) {
+						for (;;) {
+						/* copy back the buffer to input buffer */
+						memcpy((char*)input_buf, cbuf, *input_len);
+
+							if ((error = remote_CDC_DATA_wifi_rx_frag(
+								wl, rem_ptr, 0, NULL,
+								RWL_WIFI_SHELL_CMD)) < 0) {
+								DPRINT_DBG(OUTPUT,
+								"rwl_shell_information_fe(wifi):"
+								"err in reading shell response\n");
+								continue;
+							}
+							if (rem_ptr->msg.flags & REMOTE_REPLY) {
+								error = rem_ptr->msg.cmd;
+								retry = RWL_WIFI_RETRY;
+								break;
+							} else {
+								rwl_sleep(RWL_WIFI_RETRY_DELAY);
+								continue;
+							}
+						}
+					}
+				}
+
+			}
+			free(rem_ptr);
+			free(list);
+			if (cbuf != NULL)
+				free(cbuf);
+#endif /* RWL_WIFI */
+			break;
+
+		default:
+			break;
+	} /* End of switch (remote_type) */
+
+	if (resp_buf)
+		free(resp_buf);
+
+	return error;
+}
+
+/* Prepare to issue shell command */
+int
+rwl_shell_cmd_proc(void *wl, char **argv, int cmd)
+{
+	uchar *buff;
+	unsigned long len = SHELL_CMD_LEN;
+	int err;
+
+	if ((buff = malloc(SHELL_CMD_LEN)) == NULL) {
+		DPRINT_ERR(ERR, "\n Mem alloc fails for shell cmd buffer\n");
+		return FAIL;
+	}
+
+	memset(buff, 0, sizeof(SHELL_CMD_LEN));
+	while (*argv) {
+		strcat((char*)buff, *argv);
+		argv++;
+		if (*argv)
+			strcat((char*)buff, " "); /* leave space between args */
+	}
+
+	err = rwl_shell_information_fe(wl, cmd, buff, &len);
+	free(buff);
+	return err;
+}
+
+/* transport independent entry point for GET ioctls */
+int
+rwl_queryinformation_fe(void *wl, int cmd, void* input_buf,
+	unsigned long *input_len, int debug, int rem_ioctl_select) {
+	int error = 0;
+	uint tx_len;
+#if defined(RWL_SERIAL) || RWL_WIFI
+	rem_ioctl_t *rem_ptr = NULL;
+#endif
+
+#ifdef RWL_WIFI
+	int retry;
+	char *cinput_buf;
+#endif
+
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type) {
+		case REMOTE_SOCKET:
+#ifdef RWL_SOCKET
+		/* We don't want the server to allocate bigger buffers
+		 * for some of the commands
+		 * like scanresults. Server can still allocate 8K memory
+		 * and send the response
+		 */
+		if (*input_len > SERVER_RESPONSE_MAX_BUF_LEN)
+			*input_len = SERVER_RESPONSE_MAX_BUF_LEN;
+		error = rwl_information_socket(wl, cmd, input_buf, input_len,
+			input_len, rem_ioctl_select);
+#endif /* RWL_SOCKET */
+		break;
+
+#ifdef RWL_SERIAL
+		/* System serial transport is not supported in Linux. Only XP */
+		case REMOTE_SERIAL:
+			tx_len = MIN(*input_len, 1024);
+			/* Time estimate assumes 115K baud */
+			if (*input_len > (1024 *10))
+				/* Multiply by 2. The buffer has to go there and back */
+				DPRINT_DBG(OUTPUT, "Wait time: %lu seconds\n",
+				((*input_len)+ tx_len) / (115200/8));
+
+			if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
+			tx_len, rem_ioctl_select, debug) < 0) {
+				DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
+				return FAIL;
+			}
+
+			if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
+				DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.flags != REMOTE_REPLY) {
+				DPRINT_ERR(ERR, "query_info_fe: response format error.\n");
+				return FAIL;
+			}
+			if (rem_ptr->msg.len > *input_len) {
+				DPRINT_ERR(ERR, "query_info_fe: needed size(%d) greater than "
+				"actual size(%lu)\n", rem_ptr->msg.len, *input_len);
+				return FAIL;
+			}
+
+			if (error != 0)
+				DPRINT_ERR(ERR, "query_info_fe: remote cdc header return "
+					   "error code %d\n", error);
+			if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, debug) == -1) {
+				DPRINT_ERR(ERR, "query_info_fe: No results!\n");
+				return FAIL;
+			}
+			if (rem_ptr->msg.flags & REMOTE_REPLY)
+				error = rem_ptr->msg.cmd;
+			break;
+
+#endif /* RWL_SERIAL */
+		case REMOTE_DONGLE:
+			/* We don't want the server to allocate bigger buffers
+			 * for some of the commands
+			 * like scanresults. Server can still allocate 8K
+			 *memory and send the response
+			 * in fragments.
+			 */
+			if (*input_len > SERVER_RESPONSE_MAX_BUF_LEN)
+				*input_len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 256 bytes as
+			 *UART input buffer
+			 * is 512 bytes
+			 */
+			tx_len = MIN(*input_len, 256);
+			error = rwl_information_dongle(wl, cmd, input_buf, input_len,
+				tx_len, rem_ioctl_select);
+
+			break;
+
+		case REMOTE_WIFI:
+#ifdef RWL_WIFI
+			/* We don't want the server to allocate bigger buffers
+			 * for some of the commands
+			 * like scanresults. Server can still allocate 8K memory
+			 * and send the response
+			 * in fragments.
+			 */
+			if (*input_len > SERVER_RESPONSE_MAX_BUF_LEN)
+				*input_len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 960 bytes
+			 * as wifi max frame size if 960
+			 * and actual data for any command will not exceed 960 bytes
+			*/
+			tx_len = MIN(*input_len, RWL_WIFI_FRAG_DATA_SIZE);
+
+			if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
+				return FAIL;
+			}
+			if ((cinput_buf = (char*)malloc(tx_len)) == NULL) {
+				DPRINT_ERR(ERR, "Malloc failed for query information fe"
+				"character buf \n");
+				free(rem_ptr);
+				return FAIL;
+			}
+
+			memcpy(cinput_buf, (char*)input_buf, tx_len); /* Keep a copy of input_buf */
+
+			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+
+				rwl_wifi_purge_actionframes(wl);
+
+				if (retry > 3)
+					DPRINT_INFO(OUTPUT, "ir_queryinformation_fe : retry %d"
+					"cmd %d\n", retry, cmd);
+
+				/* copy back the buffer to input buffer */
+				memcpy((char*)input_buf, cinput_buf, tx_len);
+
+				/* Issue the command */
+				if ((error = remote_CDC_wifi_tx(wl, cmd, input_buf,
+					*input_len, tx_len, rem_ioctl_select)) < 0) {
+					DPRINT_DBG(OUTPUT, "query_info_fe: Send command failed\n");
+						rwl_sleep(RWL_WIFI_RETRY_DELAY);
+						continue;
+				}
+
+				if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr,
+					*input_len, input_buf, RWL_WIFI_WL_CMD) < 0)) {
+					DPRINT_DBG(OUTPUT, "ir_queryinformation_fe :"
+					"Error in reading the frag bytes\n");
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+					continue;
+				}
+
+				if (rem_ptr->msg.flags & REMOTE_REPLY) {
+					error = rem_ptr->msg.cmd;
+					break;
+				} else {
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+				}
+			}
+
+			free(rem_ptr);
+			if (cinput_buf)
+				free(cinput_buf);
+			break;
+#endif /* RWL_WIFI */
+		default:
+			DPRINT_ERR(ERR, "rwl_queryinformation_fe: Unknown"
+				"remote_type %d\n", remote_type);
+		break;
+	}
+	return error;
+}
+
+/*
+* This is the front end query function for Set Ioctls. This is used by clients
+for executing Set Ioctls.
+*/
+int
+rwl_setinformation_fe(void *wl, int cmd, void* buf,
+	unsigned long *len, int debug, int rem_ioctl_select) {
+	int error = 0;
+	uint tx_len;
+#if defined(RWL_SERIAL) || RWL_WIFI
+	rem_ioctl_t *rem_ptr = NULL;
+#endif
+
+#ifdef RWL_WIFI
+	dot11_action_wifi_vendor_specific_t *list = NULL;
+	char *cbuf, retry;
+#endif
+
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type) {
+		case REMOTE_SOCKET:
+#ifdef RWL_SOCKET
+			error = rwl_information_socket(wl, cmd, buf, len, len, rem_ioctl_select);
+#endif
+			break;
+#ifdef RWL_SERIAL
+		case REMOTE_SERIAL:
+			if (*len > (1024 *10))
+				DPRINT_DBG(OUTPUT, "Wait time: %lu seconds\n", (*len)/(115200/8));
+
+			if (remote_CDC_tx(wl, cmd, buf, *len, *len, rem_ioctl_select, debug) < 0) {
+				DPRINT_ERR(ERR, "set_info_fe: Send command failed\n");
+				return FAIL;
+			}
+
+			if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
+				DPRINT_ERR(ERR, "set_info_fe: Reading CDC header failed\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.flags != REMOTE_REPLY)	{
+				DPRINT_ERR(ERR, "set_info_fe: response format error.\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.len > *len) {
+				DPRINT_ERR(ERR, "set_info_fe: needed size (%d) greater than "
+					   "actual size (%lu)\n", rem_ptr->msg.len, *len);
+				return FAIL;
+			}
+
+			if (error != 0) {
+				DPRINT_ERR(ERR, "set_info_fe: remote cdc header return "
+					   "error code (%d)\n", error);
+			}
+			if (remote_CDC_rx(wl, rem_ptr, buf, rem_ptr->msg.len, debug) == -1) {
+				DPRINT_ERR(ERR, "set_info_fe: fetching results failed\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.flags & REMOTE_REPLY)
+				error = rem_ptr->msg.cmd;
+			break;
+#endif /* RWL_SERIAL */
+		case REMOTE_DONGLE:
+			if (*len > SERVER_RESPONSE_MAX_BUF_LEN)
+				*len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 256 bytes as
+			 *UART input buffer
+			 * is 512 bytes
+			 */
+			tx_len = MIN(*len, 512);
+			error = rwl_information_dongle(wl, cmd, buf, len, tx_len, rem_ioctl_select);
+			break;
+
+		case REMOTE_WIFI:
+#ifdef RWL_WIFI
+			if (*len > SERVER_RESPONSE_MAX_BUF_LEN)
+				*len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 960 bytes
+			 * as wifi max frame size if 960
+			 * and actual data for any command will not exceed 960 bytes
+			*/
+			tx_len = MIN(*len, RWL_WIFI_FRAG_DATA_SIZE);
+
+			if ((cbuf = (char*) malloc(tx_len)) == NULL) {
+				DPRINT_ERR(ERR, "Malloc failed for set_info_fe character buf\n");
+				return FAIL;
+			}
+			if ((list = (dot11_action_wifi_vendor_specific_t *)
+					malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+				free(cbuf);
+				return FAIL;
+			}
+
+			if ((rem_ptr = (rem_ioctl_t *)malloc(sizeof(rem_ioctl_t))) == NULL) {
+				free(list);
+				free(cbuf);
+				return FAIL;
+			}
+
+			memcpy(cbuf, (char*)buf, tx_len);
+
+			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+
+				rwl_wifi_purge_actionframes(wl);
+				/* copy back the buffer to input buffer */
+				memcpy((char*)buf, (char*)cbuf, tx_len);
+
+				if (retry > 3)
+					DPRINT_INFO(OUTPUT, "retry %d cmd %d\n", retry, cmd);
+
+				if ((error = remote_CDC_wifi_tx(wl, cmd, buf, *len,
+				                                tx_len, rem_ioctl_select) < 0)) {
+					DPRINT_ERR(ERR, "ir_setinformation_fe: Send"
+					"command failed\n");
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+					continue;
+				}
+
+				if ((char*)buf != NULL) {
+					/* In case cmd is findserver, response is not
+					 * required from the server
+					 */
+					if (!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD)) {
+						break;
+					}
+				}
+
+				/* Read the CDC header and data of for the sent cmd
+				 * resposne
+				 */
+				if ((error = remote_CDC_DATA_wifi_rx((void*)wl, list) < 0)) {
+					DPRINT_ERR(ERR, "ir_setinformation_fe: failed to read"
+						"the response\n");
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+					continue;
+				}
+
+				memcpy((char*)rem_ptr,
+				(char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET],
+				REMOTE_SIZE);
+				rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+
+				memcpy((char*)buf, (char*)&list->data[REMOTE_SIZE],
+				rem_ptr->msg.len);
+
+				if (rem_ptr->msg.flags & REMOTE_REPLY) {
+					error = rem_ptr->msg.cmd;
+					break;
+				} else {
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+				}
+			}
+				free(rem_ptr);
+				free(list);
+			if (cbuf != NULL)
+				free(cbuf);
+			break;
+#endif /* RWL_WIFI */
+		default:
+			DPRINT_ERR(ERR, "rwl_setinformation_fe: Unknown remote_type:%d\n",
+			remote_type);
+		break;
+	}
+
+	return error;
+}
+
+#ifdef RWL_WIFI
+int
+rwl_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len, error;
+
+	memset((char*)g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(g_rwl_aligned_buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&g_rwl_aligned_buf[len], param, param_len);
+
+	*bufptr = g_rwl_aligned_buf;
+	/*   When user wants to execute local CMD being in remote wifi mode,
+	*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+	*/
+	rwl_wifi_swap_remote_type(remote_type);
+
+	error = wl_get(wl, WLC_GET_VAR, &g_rwl_aligned_buf[0], WLC_IOCTL_MAXLEN);
+	/* revert back to the old remote type */
+	rwl_wifi_swap_remote_type(remote_type);
+	return error;
+}
+
+int
+rwl_var_setbuf(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len, error;
+
+	memset(g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(g_rwl_aligned_buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&g_rwl_aligned_buf[len], param, param_len);
+
+	len += param_len;
+	/*   When user wants to execute local CMD being in remote wifi mode,
+	*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+	*/
+	rwl_wifi_swap_remote_type(remote_type);
+	error = wl_set(wl, WLC_SET_VAR, &g_rwl_aligned_buf[0], len);
+	/* revert back to the old type */
+	rwl_wifi_swap_remote_type(remote_type);
+	return error;
+}
+
+/* This function will send the buffer to the dongle driver */
+int
+rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len)
+{
+	int len, error;
+
+	memset(g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(g_rwl_aligned_buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy((void*)&g_rwl_aligned_buf[len+ OFFSETOF(wl_action_frame_t, data)],
+		param,
+		param_len);
+
+	/* Set the PacketID (not used by remote WL */
+	memset((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, packetId)], 0, 4);
+
+	/* Set the dest addr */
+	memcpy((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, da)],
+	(void*)g_rwl_buf_mac,
+	ETHER_ADDR_LEN);
+
+	/* set the length */
+	memcpy((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, len)],
+	(void*) &param_len,
+	2);
+
+	len  += param_len + ETHER_ADDR_LEN + 2 + 4;
+
+	/*   When user wants to execute local CMD being in remote wifi mode,
+	*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+	*/
+	rwl_wifi_swap_remote_type(remote_type);
+
+	error = wl_set(wl, WLC_SET_VAR, &g_rwl_aligned_buf[0], len);
+	/* revert back to the old type */
+	rwl_wifi_swap_remote_type(remote_type);
+	return error;
+}
+#endif /* RWL_WIFI */
+/*
+ * Function for printing the usage if user type invalid command line
+ * options(e.g wl --serial or --dongle or --socket or --wifi)
+ */
+void
+rwl_usage(int remote_type)
+{
+	switch (remote_type) {
+	case REMOTE_SERIAL:
+			fprintf(stderr, " Usage: wl/dhd [--linuxdut/linux] [--debug]");
+			fprintf(stderr, " [--serial port no]");
+			fprintf(stderr, "[--ReadTimeout n] [--interactive] [--clientbatch] \n");
+			fprintf(stderr, "\t--linuxdut/linux removes the WLC_OID_BASE");
+			fprintf(stderr, "when sending the IOCTL command \n");
+			fprintf(stderr, "\t--debug prints out tx packets sending down ");
+			fprintf(stderr, " the serial line, and other debug info \n");
+			fprintf(stderr, "\t--serial enables the remoteWL serial port number\n");
+			fprintf(stderr, "\t--interactive enables using WL in interactive mode\n");
+			fprintf(stderr, "\t--clientbatch enables command batchinng on the client,");
+			fprintf(stderr, " the default is batching on driver\n");
+		break;
+	case REMOTE_DONGLE:
+			fprintf(stderr, " Usage: wl/dhd --dongle <Device Name>  <command>\n");
+			fprintf(stderr, "\t<Device Name> COM1/COM2 (WinXP) or /dev/ttyS0"
+			" or /dev/ttyS1 (Linux)\n");
+			fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
+			fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
+			fprintf(stderr, "\t\t shell command usage: sh <command>\n");
+		break;
+	case REMOTE_SOCKET:
+			fprintf(stderr, " Usage: "
+				"wl/dhd --socket <IP ADDRESS> [<PORT>] <command>\n");
+			fprintf(stderr, "\t<IPADDRESS> IP address of server machine\n");
+			fprintf(stderr, "\t<PORT> Port no of server\n");
+			fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
+			fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
+			fprintf(stderr, "\t\t shell command usage: sh <command>\n");
+			fprintf(stderr, "\t If <PORT> is omitted, use default port number 8000\n");
+		break;
+	case REMOTE_WIFI:
+			fprintf(stderr, " Usage: wl/dhd --wifi <MAC Address> <command>\n");
+			fprintf(stderr, "\t<MAC Address> MAC Address\n");
+			fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
+			fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
+			fprintf(stderr, "\t\t shell command usage: sh <command>\n");
+		break;
+	default:
+		break;
+	}
+}
+#ifdef RWL_SOCKET
+/* Note in case of error ( returned value == FAIL) it is assumed that wl is closed by caller,
+ * no treatment in this function
+ */
+static int
+rwl_socket_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf)
+{
+	uchar* resp_buf = NULL;
+	int pid, msg_len, error;
+	g_sig_ctrlc = 1;
+	g_child_pid = pid = rwl_shell_createproc(wl);
+	if (pid == 0) {
+		while (g_sig_ctrlc);
+		remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0);
+		exit(0);
+	}
+
+	do {
+		if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+		DPRINT_ERR(ERR, "rwl_socket_shellresp: Receiving CDC"
+			"header failed\n");
+		return FAIL;
+		}
+		msg_len = rem_ptr->msg.len;
+		if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+			DPRINT_ERR(ERR, "rwl_socket_shellresp: Mem alloc fails\n");
+			return FAIL;
+		}
+		if (msg_len > 0) {
+			if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+				rem_ptr->msg.len, 0) == FAIL) {
+				DPRINT_ERR(ERR, "rwl_socket_shellresp: No results!\n");
+				free(resp_buf);
+				return FAIL;
+			}
+		}
+		/* print the shell result */
+		resp_buf[rem_ptr->msg.len] = '\0';
+		/* The return value of the shell command
+		 * will be stored in rem_ptr->msg.cmd
+		 * Return that value to the client process
+		 */
+		if (rem_ptr->msg.flags & REMOTE_REPLY)
+			error = rem_ptr->msg.cmd;
+		write(1, resp_buf, msg_len);
+	} while (msg_len);
+	rwl_shell_killproc(pid);
+	return error;
+}
+#endif /* RWL_SOCKET */
+/* For wifi shell responses read data until server stops sending */
+#ifdef RWL_WIFI
+static int
+rwl_wifi_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf)
+{
+	int pid, msg_len, error;
+	g_sig_ctrlc = 1;
+	g_child_pid = pid = rwl_shell_createproc(wl);
+	if (pid == 0)
+	{
+		while (g_sig_ctrlc);
+		remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0);
+		exit(0);
+	}
+
+	do {
+		if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0,
+		NULL, RWL_WIFI_SHELL_CMD)) < 0) {
+			DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
+			"error in reading shell response\n");
+			continue;
+		}
+		msg_len = rem_ptr->msg.len;
+		error = rem_ptr->msg.cmd;
+	} while (msg_len);
+
+	rwl_shell_killproc(pid);
+	return error;
+}
+#endif /* RWL_WIFI */
+
+/* For dongle or system serial shell responses read data until server stops sending */
+static int
+rwl_dongle_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf, int cmd)
+{
+	int pid, msg_len, error;
+	uchar *resp_buf;
+
+	g_sig_ctrlc = 1;
+	g_child_pid = pid = rwl_shell_createproc(wl);
+	if (pid == 0) {
+		while (g_sig_ctrlc);
+		remote_CDC_tx(wl, cmd, input_buf, 0, 0, CTRLC_FLAG, 0);
+		exit(0);
+	}
+
+	do {
+		if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+			DPRINT_ERR(ERR, "shell_info_fe: Receiving CDC header failed\n");
+			return BCME_SERIAL_PORT_ERR;
+		}
+		/* In case of shell or ASD commands the response size is not known in advance
+		* Hence based on response from the server memory is allocated
+		*/
+		msg_len = rem_ptr->msg.len;
+		if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+			DPRINT_ERR(ERR, "Mem alloc fails for shell response buffer\n");
+			return FAIL;
+		}
+		/* Response comes in one shot not in fragments */
+		if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+			rem_ptr->msg.len, 0) == FAIL) {
+			DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
+			free(resp_buf);
+			return FAIL;
+		}
+		/* print the shell result */
+		resp_buf[rem_ptr->msg.len] = '\0';
+		/* The return value of the shell command will be stored in rem_ptr->msg.cmd
+		 * Return that value to the client process
+		 */
+		if (rem_ptr->msg.flags & REMOTE_REPLY)
+			error = rem_ptr->msg.cmd;
+		write(1, resp_buf, msg_len);
+	} while (msg_len);
+	rwl_shell_killproc(pid);
+	return error;
+}
+
+int rwl_detect(void *wl, bool debug, int* os_type_ptr)
+{
+	int error, buf = UNKNOWN_OS;
+	unsigned long len = sizeof(buf);
+
+	error = rwl_queryinformation_fe(wl,
+		NEGOTIATE_GET_OS, &buf, &len, debug, REMOTE_NEGOTIATE_CMD);
+	if (!error) {
+		if (buf > UNKNOWN_OS && buf < INVALID_OS) {
+			*os_type_ptr = buf;
+			if (debug)
+				fprintf(stderr, "Autodetect: %d\n", *os_type_ptr);
+			return 0;
+		}
+	}
+
+	fprintf(stderr, "Autodetect failed, rwl server is either "
+			"too old or unreachable. Use --nodetect to disable autodetect.\n");
+	return FAIL;
+}
+
+int rwl_check_port_number(char *s, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if (!isdigit(s[i]))
+			return FAIL;
+	}
+	return SUCCESS;
+}
diff --git a/src/wl/exe/wlu_client_shared.h b/src/wl/exe/wlu_client_shared.h
new file mode 100644
index 0000000..ed8452d
--- /dev/null
+++ b/src/wl/exe/wlu_client_shared.h
@@ -0,0 +1,37 @@
+/*
+ * OS independent client specific declarations
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_client_shared.h 331785 2012-05-07 21:05:20Z $
+ */
+#ifndef _wlu_client_shared_h
+#define _wlu_client_shared_h
+
+/* Newly added wrappers from wlu_client_shared.c */
+extern int
+rwl_shell_cmd_proc(void *wl, char **argv, int cmd);
+extern int
+rwl_queryinformation_fe(void *wl, int cmd, void* input_buf, unsigned long *input_len,
+int debug, int rem_ioctl_select);
+extern int
+rwl_setinformation_fe(void *wl, int cmd, void* buf, unsigned long *len, int debug,
+int rem_ioctl_select);
+extern void
+rwl_usage(int remote_type);
+extern int
+rwl_detect(void *wl, bool debug, int* os_type_ptr);
+
+extern int rwl_shell_createproc(void *wl);
+extern void rwl_shell_killproc(int pid);
+/* declaring these as extern to be used in wlu_ndis.c and wlu_linux.c */
+extern volatile sig_atomic_t g_sig_ctrlc;
+extern void ctrlc_handler(int num);
+
+#endif /* _wlu_client_share_h */
diff --git a/src/wl/exe/wlu_cmd.c b/src/wl/exe/wlu_cmd.c
new file mode 100644
index 0000000..f63d41d
--- /dev/null
+++ b/src/wl/exe/wlu_cmd.c
@@ -0,0 +1,21 @@
+/*
+ * $Id: wlu_cmd.c 428479 2013-10-08 23:08:49Z $
+ * $Copyright: (c) 2006, Broadcom Corp.
+ * All Rights Reserved.$
+ *
+ * File:        wlu_cmd.c
+ * Purpose:     Command and IO variable information commands
+ * Requires:
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <wlioctl.h>
+
+#include "wlu.h"
diff --git a/src/wl/exe/wlu_cmd.h b/src/wl/exe/wlu_cmd.h
new file mode 100644
index 0000000..c98ced1
--- /dev/null
+++ b/src/wl/exe/wlu_cmd.h
@@ -0,0 +1,141 @@
+/*
+ * Command structure for wl command line utility
+ *
+ * Copyright 2002, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied or
+ * duplicated in any form, in whole or in part, without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * $Id: wlu_cmd.h 428479 2013-10-08 23:08:49Z $
+ */
+
+#ifndef _wlu_cmd_h_
+#define _wlu_cmd_h_
+
+typedef struct cmd cmd_t;
+typedef int (cmd_func_t)(void *wl, cmd_t *cmd, char **argv);
+
+/* generic command line argument handler */
+struct cmd {
+	const char *name;
+	cmd_func_t *func;
+	int get;
+	int set;
+	const char *help;
+};
+
+/* list of command line arguments */
+extern cmd_t wl_cmds[];
+extern cmd_t wl_varcmd;
+
+/* per-port ioctl handlers */
+extern int wl_get(void *wl, int cmd, void *buf, int len);
+extern int wl_set(void *wl, int cmd, void *buf, int len);
+
+/*
+ * Flags for command categories.  A command may belong to
+ * multiple categories.  These are used in bitmaps, so be careful
+ * to keep the macro value (2 ^ n) and the array indexes (n)
+ * consistent.
+ */
+
+#define CMD_PHY               0x1
+#define CMD_CHAN              0x2
+#define CMD_RATE              0x4
+#define CMD_POWER             0x8
+#define CMD_MAC               0x10
+#define CMD_MGMT              0x20
+#define CMD_SEC               0x40
+#define CMD_WME               0x80
+#define CMD_MON               0x100
+#define CMD_AP                0x200
+#define CMD_STA               0x400
+#define CMD_BOARD             0x800
+#define CMD_ADMIN             0x1000
+#define CMD_DEV               0x2000
+#define CMD_DEP               0x4000
+#define CMD_UNCAT             0x8000
+
+#define CMD_ALL               0xffff
+
+/* Initializer for category string array */
+
+#define CMD_CATEGORY_STRINGS_INIT { \
+	"phy",   \
+	"chan",  \
+	"rate",  \
+	"power", \
+	"mac",   \
+	"mgmt",  \
+	"sec",   \
+	"wme",   \
+	"mon",   \
+	"ap",    \
+	"sta",   \
+	"board", \
+	"admin", \
+	"dev",   \
+	"dep",   \
+	"uncat", \
+	"" }
+
+extern const char *wl_cmd_category_strings[];
+extern const int wl_cmd_category_count;
+
+/* Initializer for category description strings array */
+#define CMD_CATEGORY_DESC_INIT { \
+	"PHY and radio; speed, band, etc", \
+	"Channel; subclass of phy",  \
+	"Rate; subclass of phy, a/b/g",  \
+	"Power; subclass of phy", \
+	"MAC; Media access",   \
+	"Management, association, IE, etc",  \
+	"Security; subclass of mgmt",   \
+	"WME; media extensions",   \
+	"Monitoring device (counters, etc)",   \
+	"AP subclass of mgmt", \
+	"STA subclass of mgmt", \
+	"Board, hardware", \
+	"Administration; software, UI, diags", \
+	"Device; low level control", \
+	"Deprecated", \
+	"Uncategorized so far", \
+	"" }
+
+extern const char *wl_cmd_category_desc[];
+
+/*
+ *
+ * IO variable information
+ *
+ */
+
+/* Supplemental IO variable info structure */
+typedef const struct wlu_iov_info_s {
+	const char *name;
+	uint32 cat;  /* Category flags; same as command categories */
+	uint32 flags; /* See below */
+	int dflt;  /* Only for integers; see flags */
+	const char *desc;  /* Description */
+} wlu_iov_info_t;
+
+/* Flags for wlu_iov_info_t */
+#define WLU_IOVI_READ_ONLY         0x1   /* Known to be read only */
+#define WLU_IOVI_WRITE_ONLY        0x2   /* Known to be write only */
+#define WLU_IOVI_BCM_INTERNAL      0x4   /* Known to be BCM internal */
+#define WLU_IOVI_DEFAULT_VALID     0x8   /* Default value in structure is valid */
+
+extern wlu_iov_info_t wlu_iov_info[];
+extern int wlu_iov_info_count;
+
+#define WLU_IOV_BLOCK_LEN	10
+
+#define WLU_MOD_NAME_MAX	64 /* Max num modules */
+#define WLU_MOD_NAME_BYTES	16 /* Size of modules name */
+
+extern int wl_get_scan(void *wl, int opc, char *scan_buf, uint buf_len);
+
+#endif /* _wlu_cmd_h_ */
diff --git a/src/wl/exe/wlu_common.c b/src/wl/exe/wlu_common.c
new file mode 100644
index 0000000..4207287
--- /dev/null
+++ b/src/wl/exe/wlu_common.c
@@ -0,0 +1,385 @@
+/*
+ * Common code for wl routines
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_common.c 433133 2013-10-30 19:23:45Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "wlu_common.h"
+#include "wlu.h"
+#include <bcmendian.h>
+
+extern int wl_get(void *wl, int cmd, void *buf, int len);
+extern int wl_set(void *wl, int cmd, void *buf, int len);
+
+wl_cmd_list_t cmd_list;
+int cmd_pkt_list_num;
+bool cmd_batching_mode;
+
+const char *wlu_av0;
+
+/* global wlc index indentifier for RSDB -W/--wlc option */
+int g_wlc_idx = -1;
+
+
+
+/*
+ * format an iovar buffer
+ * iovar name is converted to lower case
+ */
+static uint
+wl_iovar_mkbuf(const char *name, char *data, uint datalen, char *iovar_buf, uint buflen, int *perr)
+{
+	uint iovar_len;
+	char *p;
+
+	iovar_len = strlen(name) + 1;
+
+	/* check for overflow */
+	if ((iovar_len + datalen) > buflen) {
+		*perr = BCME_BUFTOOSHORT;
+		return 0;
+	}
+
+	/* copy data to the buffer past the end of the iovar name string */
+	if (datalen > 0)
+		memmove(&iovar_buf[iovar_len], data, datalen);
+
+	/* copy the name to the beginning of the buffer */
+	strcpy(iovar_buf, name);
+
+	/* wl command line automatically converts iovar names to lower case for
+	 * ease of use
+	 */
+	p = iovar_buf;
+	while (*p != '\0') {
+		*p = tolower((int)*p);
+		p++;
+	}
+
+	*perr = 0;
+	return (iovar_len + datalen);
+}
+
+void
+init_cmd_batchingmode(void)
+{
+	cmd_pkt_list_num = 0;
+	cmd_batching_mode = FALSE;
+}
+
+void
+clean_up_cmd_list(void)
+{
+	wl_seq_cmd_pkt_t *this_cmd, *next_cmd;
+
+	this_cmd = cmd_list.head;
+	while (this_cmd != NULL) {
+		next_cmd = this_cmd->next;
+		if (this_cmd->data != NULL) {
+			free(this_cmd->data);
+		}
+		free(this_cmd);
+		this_cmd = next_cmd;
+	}
+	cmd_list.head = NULL;
+	cmd_list.tail = NULL;
+	cmd_pkt_list_num = 0;
+}
+
+int
+add_one_batched_cmd(int cmd, void *cmdbuf, int len)
+{
+	wl_seq_cmd_pkt_t *new_cmd;
+
+	new_cmd = malloc(sizeof(wl_seq_cmd_pkt_t));
+
+	if (new_cmd == NULL) {
+		printf("malloc(%d) failed, free %d batched commands and exit batching mode\n",
+			(int)sizeof(wl_seq_cmd_pkt_t), cmd_pkt_list_num);
+		goto free_and_exit;
+	} else {
+			printf("batching %dth command %d\n", cmd_pkt_list_num+1, cmd);
+
+	}
+
+	new_cmd->cmd_header.cmd = cmd;
+	new_cmd->cmd_header.len = len;
+	new_cmd->next  = NULL;
+
+	new_cmd->data = malloc(len);
+
+	if (new_cmd->data == NULL) {
+		printf("malloc(%d) failed, free %d batched commands and exit batching mode\n",
+			len, cmd_pkt_list_num);
+		free(new_cmd);
+		goto free_and_exit;
+	}
+
+	memcpy(new_cmd->data, cmdbuf, len);
+
+	if (cmd_list.tail != NULL)
+		cmd_list.tail->next = new_cmd;
+	else
+		cmd_list.head = new_cmd;
+
+	cmd_list.tail = new_cmd;
+
+	cmd_pkt_list_num ++;
+	return 0;
+
+free_and_exit:
+
+	clean_up_cmd_list();
+
+	if (cmd_batching_mode) {
+		cmd_batching_mode = FALSE;
+	}
+	else {
+		printf("calling add_one_batched_cmd() at non-command-batching mode, weird\n");
+	}
+
+	return -1;
+}
+
+int
+wlu_get_req_buflen(int cmd, void *cmdbuf, int len)
+{
+	int modified_len = len;
+	char *cmdstr = (char *)cmdbuf;
+
+	if (len == WLC_IOCTL_MAXLEN) {
+		if ((strcmp(cmdstr, "dump") == 0) ||
+			(cmd == WLC_SCAN_RESULTS))
+			modified_len = WLC_IOCTL_MAXLEN;
+		else
+			modified_len = WLC_IOCTL_MEDLEN;
+	}
+	return modified_len;
+}
+/* Wrapper function that converts -W option in to "wlc:" prefix
+ * (1) It converts an existing iovar to the following format
+ * wlc:<iovar_name>\0<wlc_idx><param>
+ * (2) It converts an existing ioctl to the following format
+ * wlc:ioc\0<wlc_idx><ioct_cmd_id><param>
+ * NOTE: (2) requires new iovar named "ioc" in driver
+*/
+static int
+wlu_wlc_wrapper(void *wl, bool get, int* cmd, void *cmdbuf, int len, void **outbuf, int *outlen)
+{
+	void *param = cmdbuf;
+	int paramlen = len;
+	int wlc_idx = g_wlc_idx;
+	char *name = NULL;
+	BCM_REFERENCE(wl);
+	/* Wrap only if we find a valid WLC index and iovar name */
+	if (wlc_idx >= 0) {
+		int cmdlen = 0;
+		int prefix_len = 0;
+		char *lbuf = NULL;
+		char *buf = NULL;
+		bool ioctl_wrap = FALSE;
+		if ((*cmd == WLC_GET_VAR) || (*cmd == WLC_SET_VAR)) {
+			/* incoming command is an iovar */
+			/* pull out name\0param */
+			name = cmdbuf;
+			cmdlen = strlen(name);
+			param = ((char*)cmdbuf) + cmdlen + 1;
+			paramlen = len - cmdlen - 1;
+		} else {
+			/* we are an ioctl, invoke the common "ioc" iovar and wrap the cmd */
+			name = "ioc";
+			cmdlen = strlen(name);
+			/* additional 4 bytes for storing IOCTL_CMD_ID */
+			prefix_len = sizeof(int);
+			ioctl_wrap = TRUE;
+		}
+		prefix_len += strlen("wlc:") + 1 +  cmdlen + sizeof(int);
+		/* now create wlc:<name>\0<wlc_idx><param> */
+		buf = lbuf = malloc(prefix_len + paramlen);
+		if (buf == NULL) {
+			printf("%s:malloc(%d) failed\n", __FUNCTION__, prefix_len + paramlen);
+			return BCME_NOMEM;
+		}
+		memcpy(buf, "wlc:", 4); buf += 4;
+		strcpy(buf, name); buf += (cmdlen+1);
+		wlc_idx = htod32(wlc_idx);
+		memcpy(buf, &wlc_idx, sizeof(int32)); buf += sizeof(int32);
+		if (ioctl_wrap) {
+			/* For IOCTL wlc:ioc\0<wlc_idx><ioctl_id><param> */
+			int32 ioctl_cmd = htod32(*cmd);
+			memcpy(buf, &ioctl_cmd, sizeof(int32)); buf += sizeof(int32);
+		}
+		memcpy(buf, param, paramlen);
+		*cmd = (get) ? WLC_GET_VAR : WLC_SET_VAR;
+		param = lbuf;
+		paramlen += prefix_len;
+	}
+	*outlen = paramlen;
+	*outbuf = param;
+	return BCME_OK;
+}
+/* now IOCTL GET commands shall call wlu_get() instead of wl_get() so that the commands
+ * can be batched when needed
+ */
+int
+wlu_get(void *wl, int cmd, void *cmdbuf, int len)
+{
+	void *outbuf = NULL;
+	int outlen;
+	int err = 0;
+	if (cmd_batching_mode) {
+		if (!WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd)) {
+			printf("IOCTL GET command %d is not supported in batching mode\n", cmd);
+			return BCME_UNSUPPORTED;
+		}
+	}
+
+	err = wlu_wlc_wrapper(wl, TRUE, &cmd, cmdbuf, len, &outbuf, &outlen);
+	if (err != BCME_OK) return err;
+	err = wl_get(wl, cmd, outbuf, outlen);
+
+	if (outbuf != cmdbuf) {
+		memcpy(cmdbuf, outbuf, len);
+		free(outbuf);
+	}
+	return err;
+}
+
+/* now IOCTL SET commands shall call wlu_set() instead of wl_set() so that the commands
+ * can be batched when needed
+ */
+int
+wlu_set(void *wl, int cmd, void *cmdbuf, int len)
+{
+	int err = 0;
+	void *outbuf = NULL;
+	int outlen;
+
+	err = wlu_wlc_wrapper(wl, FALSE, &cmd, cmdbuf, len, &outbuf, &outlen);
+	if (err != BCME_OK) return err;
+
+	if (cmd_batching_mode) {
+		err = add_one_batched_cmd(cmd, outbuf, outlen);
+	}
+	else {
+		err = wl_set(wl, cmd, outbuf, outlen);
+	}
+	if (outbuf != cmdbuf) {
+		memcpy(cmdbuf, outbuf, len);
+		free(outbuf);
+	}
+	return err;
+
+}
+
+/*
+ * get named iovar providing both parameter and i/o buffers
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_getbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+
+	wl_iovar_mkbuf(iovar, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_get(wl, WLC_GET_VAR, bufptr, buflen);
+}
+
+/*
+ * set named iovar providing both parameter and i/o buffers
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_setbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+	int iolen;
+
+	iolen = wl_iovar_mkbuf(iovar, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_set(wl, WLC_SET_VAR, bufptr, iolen);
+}
+
+/*
+ * get named iovar without parameters into a given buffer
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_get(void *wl, const char *iovar, void *outbuf, int len)
+{
+	char smbuf[WLC_IOCTL_SMLEN];
+	int err;
+
+	/* use the return buffer if it is bigger than what we have on the stack */
+	if (len > (int)sizeof(smbuf)) {
+		err = wlu_iovar_getbuf(wl, iovar, NULL, 0, outbuf, len);
+	} else {
+		memset(smbuf, 0, sizeof(smbuf));
+		err = wlu_iovar_getbuf(wl, iovar, NULL, 0, smbuf, sizeof(smbuf));
+		if (err == 0)
+			memcpy(outbuf, smbuf, len);
+	}
+
+	return err;
+}
+
+/*
+ * set named iovar given the parameter buffer
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_set(void *wl, const char *iovar, void *param, int paramlen)
+{
+	char smbuf[WLC_IOCTL_SMLEN*2];
+
+	memset(smbuf, 0, sizeof(smbuf));
+
+	return wlu_iovar_setbuf(wl, iovar, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+/*
+ * get named iovar as an integer value
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_getint(void *wl, const char *iovar, int *pval)
+{
+	int ret;
+
+	ret = wlu_iovar_get(wl, iovar, pval, sizeof(int));
+	if (ret >= 0)
+	{
+		*pval = dtoh32(*pval);
+	}
+	return ret;
+}
+
+/*
+ * set named iovar given an integer parameter
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_setint(void *wl, const char *iovar, int val)
+{
+	val = htod32(val);
+	return wlu_iovar_set(wl, iovar, &val, sizeof(int));
+}
diff --git a/src/wl/exe/wlu_common.h b/src/wl/exe/wlu_common.h
new file mode 100644
index 0000000..2153c3d
--- /dev/null
+++ b/src/wl/exe/wlu_common.h
@@ -0,0 +1,72 @@
+/*
+ * Common code for wl routines
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_common.h 402715 2013-05-16 18:50:09Z $
+ */
+#include <wlioctl.h>
+#include <bcmutils.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+
+/* IOCTL swapping mode for Big Endian host with Little Endian dongle.  Default to off */
+/* The below macros handle endian mis-matches between wl utility and wl driver. */
+static bool g_swap = FALSE;
+#define htod64(i) (g_swap?bcmswap64(i):(uint64)(i))
+#define htod32(i) (g_swap?bcmswap32(i):(uint32)(i))
+#define htod16(i) (g_swap?bcmswap16(i):(uint16)(i))
+#define dtoh64(i) (g_swap?bcmswap64(i):(uint64)(i))
+#define dtoh32(i) (g_swap?bcmswap32(i):(uint32)(i))
+#define dtoh16(i) (g_swap?bcmswap16(i):(uint16)(i))
+#define htodchanspec(i) (g_swap?htod16(i):i)
+#define dtohchanspec(i) (g_swap?dtoh16(i):i)
+#define htodenum(i) (g_swap?((sizeof(i) == 4) ? htod32(i) : ((sizeof(i) == 2) ? htod16(i) : i)):i)
+#define dtohenum(i) (g_swap?((sizeof(i) == 4) ? dtoh32(i) : ((sizeof(i) == 2) ? htod16(i) : i)):i)
+
+/* command batching data structure */
+typedef struct wl_seq_cmd_pkt {
+	struct wl_seq_cmd_pkt	*next;
+	wl_seq_cmd_ioctl_t cmd_header;
+	char * data;			/* user buffer */
+} wl_seq_cmd_pkt_t;
+
+typedef struct wl_cmd_list {
+	wl_seq_cmd_pkt_t	*head;
+	wl_seq_cmd_pkt_t	*tail;
+} wl_cmd_list_t;
+
+extern wl_cmd_list_t cmd_list;
+extern int cmd_pkt_list_num;
+extern bool cmd_batching_mode;
+
+extern int wlu_iovar_getbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen);
+extern int wlu_iovar_setbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen);
+extern int wlu_var_setbuf(void *wl, const char *iovar, void *param, int param_len);
+extern int wlu_iovar_getint(void *wl, const char *iovar, int *pval);
+extern void init_cmd_batchingmode(void);
+extern void clean_up_cmd_list(void);
+extern int wl_check(void *wl);
+
+extern int add_one_batched_cmd(int cmd, void *cmdbuf, int len);
+extern int wlu_get_req_buflen(int cmd, void *cmdbuf, int len);
+extern int wlu_get(void *wl, int cmd, void *cmdbuf, int len);
+extern int wlu_set(void *wl, int cmd, void *cmdbuf, int len);
+extern int wlu_iovar_get(void *wl, const char *iovar, void *outbuf, int len);
+extern int wlu_iovar_set(void *wl, const char *iovar, void *param, int paramlen);
+extern int wlu_iovar_getint(void *wl, const char *iovar, int *pval);
+extern int wlu_iovar_setint(void *wl, const char *iovar, int val);
diff --git a/src/wl/exe/wlu_iov.c b/src/wl/exe/wlu_iov.c
new file mode 100644
index 0000000..6f5633a
--- /dev/null
+++ b/src/wl/exe/wlu_iov.c
@@ -0,0 +1,22 @@
+/*
+ * Automatically generated IOVariable merge information
+ * $Copyright: (c) 2006, Broadcom Corp.
+ * All Rights Reserved.$
+ * $Id: wlu_iov.c 341355 2012-06-27 13:08:42Z $
+ *
+ * Contains user IO variable information
+ * Note that variable type information comes from the driver
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <wlioctl.h>
+
+#include "wlu.h"
diff --git a/src/wl/exe/wlu_linux.c b/src/wl/exe/wlu_linux.c
new file mode 100644
index 0000000..5bd7523
--- /dev/null
+++ b/src/wl/exe/wlu_linux.c
@@ -0,0 +1,1020 @@
+/*
+ * Linux port of wl command line utility
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_linux.c 454792 2014-02-11 20:40:19Z $
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#ifndef TARGETENV_android
+#include <error.h>
+#endif /* TARGETENV_android */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <proto/ethernet.h>
+#include <proto/bcmip.h>
+
+#ifndef TARGETENV_android
+#include <linux/types.h>
+#endif /* TARGETENV_android */
+
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+#include <signal.h>
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <bcmutils.h>
+#include <sys/wait.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include "wlu.h"
+#include <bcmcdc.h>
+#include "wlu_remote.h"
+#include "wlu_client_shared.h"
+#include "wlu_pipe.h"
+#ifdef NL80211
+#include "wlu_nl80211.h"
+#endif /* NL80211 */
+#include <miniopt.h>
+
+#define DEV_TYPE_LEN					3 /* length for devtype 'wl'/'et' */
+#define INTERACTIVE_NUM_ARGS			15
+#define INTERACTIVE_MAX_INPUT_LENGTH	512
+#define NO_ERROR						0
+#define RWL_WIFI_JOIN_DELAY				5
+
+/* Function prototypes */
+static cmd_t *wl_find_cmd(char* name);
+static int do_interactive(struct ifreq *ifr);
+static int wl_do_cmd(struct ifreq *ifr, char **argv);
+int process_args(struct ifreq* ifr, char **argv);
+extern int g_child_pid;
+/* RemoteWL declarations */
+int remote_type = NO_REMOTE;
+int rwl_os_type = LINUX_OS;
+static bool rwl_dut_autodetect = TRUE;
+static bool debug = FALSE;
+extern char *g_rwl_buf_mac;
+extern char* g_rwl_device_name_serial;
+unsigned short g_rwl_servport;
+char *g_rwl_servIP = NULL;
+unsigned short defined_debug = DEBUG_ERR | DEBUG_INFO;
+static uint interactive_flag = 0;
+extern char *remote_vista_cmds[];
+extern char g_rem_ifname[IFNAMSIZ];
+extern int rwl_check_port_number(char *s, int len);
+
+#ifdef NL80211
+static void
+syserr(char *s)
+{
+	UNUSED_PARAMETER(s);
+}
+
+static int wl_driver_nl80211(void *wl, wl_ioctl_t *ioc)
+{
+	struct wl_netlink_info wl_nli;
+	struct ifreq *ifr = (struct ifreq *)wl;
+	int ret = 0;
+
+	wl_nli.ifidx = if_nametoindex(ifr->ifr_name);
+	if (!wl_nli.ifidx) {
+		fprintf(stderr, "invalid device %s\n", ifr->ifr_name);
+		return BCME_IOCTL_ERROR;
+	}
+
+	if (wlnl_sock_connect(&wl_nli) < 0) {
+		fprintf(stderr, "%s: ", wlu_av0);
+		perror("socket");
+		exit(errno);
+	}
+
+	ret = wlnl_do_testmode(&wl_nli, ioc);
+	wlnl_sock_disconnect(&wl_nli);
+	return ret;
+}
+#else
+static void
+syserr(char *s)
+{
+	fprintf(stderr, "%s: ", wlu_av0);
+	perror(s);
+	exit(errno);
+}
+
+static int wl_driver_nl80211(void *wl, wl_ioctl_t *ioc)
+{
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(ioc);
+	return BCME_IOCTL_ERROR;
+}
+#endif /* NL80211 */
+
+static int wl_driver_ioctl(void *wl, wl_ioctl_t *ioc)
+{
+	struct ifreq *ifr = (struct ifreq *) wl;
+	int ret;
+	int s;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* do it */
+	ifr->ifr_data = (caddr_t)ioc;
+	ret = ioctl(s, SIOCDEVPRIVATE, ifr);
+
+	/* cleanup */
+	close(s);
+	return ret;
+}
+
+static int (*g_driver_io)(void *wl, wl_ioctl_t *ioc) = wl_driver_ioctl;
+
+int
+wl_ioctl(void *wl, int cmd, void *buf, int len, bool set)
+{
+	wl_ioctl_t ioc;
+	int ret;
+
+	/* do it */
+	ioc.cmd = cmd;
+	ioc.buf = buf;
+	ioc.len = len;
+	ioc.set = set;
+
+	ret = g_driver_io(wl, &ioc);
+	if (ret < 0) {
+		if (g_driver_io == wl_driver_ioctl) {
+			/* try using nl80211 testmode interface */
+			ret = wl_driver_nl80211(wl, &ioc);
+			if (ret >= 0) {
+				g_driver_io = wl_driver_nl80211;
+				goto exit;
+			}
+		}
+		if (cmd != WLC_GET_MAGIC)
+			ret = BCME_IOCTL_ERROR;
+	}
+
+exit:
+	return ret;
+}
+
+static int
+wl_get_dev_type(char *name, void *buf, int len)
+{
+	int s;
+	int ret;
+	struct ifreq ifr;
+	struct ethtool_drvinfo info;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* get device type */
+	memset(&info, 0, sizeof(info));
+	info.cmd = ETHTOOL_GDRVINFO;
+	ifr.ifr_data = (caddr_t)&info;
+	strncpy(ifr.ifr_name, name, IFNAMSIZ);
+	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
+
+		/* print a good diagnostic if not superuser */
+		if (errno == EPERM)
+			syserr("wl_get_dev_type");
+
+		*(char *)buf = '\0';
+	} else {
+		strncpy(buf, info.driver, len);
+	}
+
+	close(s);
+	return ret;
+}
+
+static int
+wl_find(struct ifreq *ifr)
+{
+	char proc_net_dev[] = "/proc/net/dev";
+	FILE *fp;
+	char buf[1000], *c, *name;
+	char dev_type[DEV_TYPE_LEN];
+	int status;
+
+	ifr->ifr_name[0] = '\0';
+
+	if (!(fp = fopen(proc_net_dev, "r")))
+		return BCME_ERROR;
+
+	/* eat first two lines */
+	if (!fgets(buf, sizeof(buf), fp) ||
+	    !fgets(buf, sizeof(buf), fp)) {
+		fclose(fp);
+		return BCME_ERROR;
+	}
+
+	while (fgets(buf, sizeof(buf), fp)) {
+		c = buf;
+		while (isspace(*c))
+			c++;
+		if (!(name = strsep(&c, ":")))
+			continue;
+		strncpy(ifr->ifr_name, name, IFNAMSIZ-1);
+		ifr->ifr_name[IFNAMSIZ-1] = 0;
+		if (wl_get_dev_type(name, dev_type, DEV_TYPE_LEN) >= 0 &&
+			(!strncmp(dev_type, "wl", 2) ||
+			!strncmp(dev_type, "brc", 3)))
+			if (wl_check((void *) ifr) == 0)
+				break;
+		ifr->ifr_name[0] = '\0';
+	}
+	if (ifr->ifr_name[0] == '\0')
+		status = BCME_ERROR;
+	else
+		status = BCME_OK;
+
+	fclose(fp);
+	return status;
+}
+
+
+static int
+ioctl_queryinformation_fe(void *wl, int cmd, void* input_buf, unsigned long *input_len)
+{
+	int error = NO_ERROR;
+
+	if (remote_type == NO_REMOTE) {
+		error = wl_ioctl(wl, cmd, input_buf, *input_len, FALSE);
+	} else {
+		error = rwl_queryinformation_fe(wl, cmd, input_buf,
+		              input_len, 0, REMOTE_GET_IOCTL);
+
+	}
+	return error;
+}
+
+static int
+ioctl_setinformation_fe(void *wl, int cmd, void* buf, unsigned long *input_len)
+{
+	int error = 0;
+
+	if (remote_type == NO_REMOTE) {
+		error = wl_ioctl(wl,  cmd, buf, *input_len, TRUE);
+	} else {
+		error = rwl_setinformation_fe(wl, cmd, buf,
+			input_len, 0, REMOTE_SET_IOCTL);
+	}
+
+	return error;
+}
+
+int
+wl_get(void *wl, int cmd, void *buf, int len)
+{
+	int error = 0;
+	unsigned long input_len = len;
+
+	if ((rwl_os_type == WIN32_OS || rwl_os_type == WINVISTA_OS) && remote_type != NO_REMOTE)
+		cmd += WL_OID_BASE;
+	error = (int)ioctl_queryinformation_fe(wl, cmd, buf, &input_len);
+
+	if (error == BCME_SERIAL_PORT_ERR)
+		return BCME_SERIAL_PORT_ERR;
+	else if (error == BCME_NODEVICE)
+		return BCME_NODEVICE;
+	else if (error != 0)
+		return BCME_IOCTL_ERROR;
+
+	return 0;
+}
+
+int
+wl_set(void *wl, int cmd, void *buf, int len)
+{
+	int error = 0;
+	unsigned long input_len = len;
+
+	if ((rwl_os_type == WIN32_OS || rwl_os_type == WINVISTA_OS) && remote_type != NO_REMOTE)
+		cmd += WL_OID_BASE;
+	error = (int)ioctl_setinformation_fe(wl, cmd, buf, &input_len);
+
+	if (error == BCME_SERIAL_PORT_ERR)
+		return BCME_SERIAL_PORT_ERR;
+	else if (error == BCME_NODEVICE)
+		return BCME_NODEVICE;
+	else if (error != 0)
+		return BCME_IOCTL_ERROR;
+
+	return 0;
+}
+
+#if defined(WLMSO)
+int wl_os_type_get_rwl()
+{
+	return rwl_os_type;
+}
+
+void wl_os_type_set_rwl(int os_type)
+{
+	rwl_os_type = os_type;
+}
+
+int wl_ir_init_rwl(void **irh)
+{
+	switch (rwl_get_remote_type()) {
+	case NO_REMOTE:
+	case REMOTE_WIFI: {
+		struct ifreq *ifr;
+		ifr = malloc(sizeof(struct ifreq));
+		if (ifr) {
+			memset(ifr, 0, sizeof(ifr));
+			wl_find(ifr);
+		}
+		*irh = ifr;
+	}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+void wl_close_rwl(int remote_type, void *irh)
+{
+	switch (remote_type) {
+	case NO_REMOTE:
+	case REMOTE_WIFI:
+		free(irh);
+		break;
+	default:
+		break;
+	}
+}
+
+#define LINUX_NUM_ARGS  16
+
+static int
+buf_to_args(char *tmp, char *new_args[])
+{
+	char line[INTERACTIVE_MAX_INPUT_LENGTH];
+	char *token;
+	int argc = 0;
+
+	if (strlen(tmp) >= INTERACTIVE_MAX_INPUT_LENGTH) {
+		printf("wl:error: Input string too long; must be < %d bytes\n",
+		       INTERACTIVE_MAX_INPUT_LENGTH);
+		return 0;
+	}
+
+	strcpy(line, tmp);
+	while  (argc < (LINUX_NUM_ARGS - 1) &&
+		(token = strtok(argc ? NULL : line, " \t")) != NULL) {
+		new_args[argc] = malloc(strlen(token)+1);
+		strncpy(new_args[argc], token, strlen(token)+1);
+		argc++;
+	}
+	new_args[argc] = NULL;
+	if (argc == (LINUX_NUM_ARGS - 1) && (token = strtok(NULL, " \t")) != NULL) {
+		printf("wl:error: too many args; argc must be < %d\n",
+		       (LINUX_NUM_ARGS - 1));
+		argc = LINUX_NUM_ARGS;
+	}
+	return argc;
+}
+
+int
+wl_lib(char *input_str)
+{
+	struct ifreq ifr;
+	char *ifname = NULL;
+	int err = 0;
+	int help = 0;
+	int status = CMD_WL;
+	void* serialHandle = NULL;
+	char *tmp_argv[LINUX_NUM_ARGS];
+	char **argv = tmp_argv;
+	int argc;
+
+	/* buf_to_args return 0 if no args or string too long
+	 * or return NDIS_NUM_ARGS if too many args
+	 */
+	if (((argc = buf_to_args(input_str, argv)) == 0) || (argc == LINUX_NUM_ARGS)) {
+		printf("wl:error: can't convert input string\n");
+		return (-1);
+	}
+#else
+/* Main client function */
+int
+main(int argc, char **argv)
+{
+	struct ifreq ifr;
+	char *ifname = NULL;
+	int err = 0;
+	int help = 0;
+	int status = CMD_WL;
+#if defined(RWL_DONGLE) || RWL_SERIAL
+	void* serialHandle = NULL;
+#endif
+
+#endif /* WLMSO */
+	wlu_av0 = argv[0];
+
+	wlu_init();
+	memset(&ifr, 0, sizeof(ifr));
+	(void)*argv++;
+
+	if ((status = wl_option(&argv, &ifname, &help)) == CMD_OPT) {
+		if (ifname)
+			strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+		/* Bug fix: If -h is used as an option, the above function call
+		 * will notice it and raise the flag but it won't be processed
+		 * in this function so we undo the argv increment so that the -h
+		 * can be spotted by the next call of wl_option. This will ensure
+		 * that wl -h [cmd] will function as desired.
+		 */
+		else if (help)
+			(void)*argv--;
+	}
+
+	/* Linux client looking for a indongle reflector */
+	if (*argv && strncmp (*argv, "--indongle", strlen(*argv)) == 0) {
+		rwl_dut_autodetect = FALSE;
+		(void)*argv++;
+	}
+	/* Linux client looking for a WinVista server */
+	if (*argv && strncmp (*argv, "--vista", strlen(*argv)) == 0) {
+		rwl_os_type = WINVISTA_OS;
+		rwl_dut_autodetect = FALSE;
+		(void)*argv++;
+	}
+
+	/* Provide option for disabling remote DUT autodetect */
+	if (*argv && strncmp(*argv, "--nodetect", strlen(*argv)) == 0) {
+		rwl_dut_autodetect = FALSE;
+		argv++;
+	}
+
+	if (*argv && strncmp (*argv, "--debug", strlen(*argv)) == 0) {
+		debug = TRUE;
+		argv++;
+	}
+
+	/* RWL socket transport Usage: --socket ipaddr/hostname [port num] */
+	if (*argv && strncmp (*argv, "--socket", strlen(*argv)) == 0) {
+		(void)*argv++;
+
+		remote_type = REMOTE_SOCKET;
+
+		if (!(*argv)) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		/* IP address validation is done in client_shared file */
+		g_rwl_servIP = *argv;
+		(void)*argv++;
+
+		/* Port number validation is done in client_shared file */
+		g_rwl_servport = DEFAULT_SERVER_PORT;
+		if ((*argv) && (rwl_check_port_number(*argv, strlen(*argv)) == SUCCESS)) {
+			g_rwl_servport = atoi(*argv);
+			(void)*argv++;
+		}
+	}
+
+	/* RWL from system serial port on client to uart serial port on server */
+	/* Usage: --serial /dev/ttyS0 */
+	if (*argv && strncmp (*argv, "--serial", strlen(*argv)) == 0) {
+		(void)*argv++;
+		remote_type = REMOTE_SERIAL;
+	}
+
+	/* RWL from system serial port on client to uart dongle port on server */
+	/* Usage: --dongle /dev/ttyS0 */
+	if (*argv && strncmp (*argv, "--dongle", strlen(*argv)) == 0) {
+		(void)*argv++;
+		remote_type = REMOTE_DONGLE;
+	}
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)
+	if (remote_type == REMOTE_SERIAL || remote_type == REMOTE_DONGLE) {
+		if (!(*argv)) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		g_rwl_device_name_serial = *argv;
+		(void)*argv++;
+		if ((serialHandle = rwl_open_pipe(remote_type, g_rwl_device_name_serial, 0, 0))
+			 == NULL) {
+			DPRINT_ERR(ERR, "serial device open error\r\n");
+			return -1;
+		}
+		ifr = (*(struct ifreq *)serialHandle);
+	}
+#endif /*  RWL_SERIAL */
+
+	/* RWL over wifi.  Usage: --wifi mac_address */
+	if (*argv && strncmp (*argv, "--wifi", strlen(*argv)) == 0) {
+		(void)*argv++;
+		/* use default interface */
+		if (!*ifr.ifr_name)
+			wl_find(&ifr);
+
+		/* validate the interface */
+		if (!*ifr.ifr_name || (err = wl_check((void *)&ifr)) < 0) {
+			fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
+			exit(1);
+		}
+
+		remote_type = REMOTE_WIFI;
+
+		if (argc < 4) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		/* copy server mac address to local buffer for later use by findserver cmd */
+		if (!wl_ether_atoe(*argv, (struct ether_addr *)g_rwl_buf_mac)) {
+			fprintf(stderr,
+			"could not parse as an ethternet MAC address\n");
+			return FAIL;
+		}
+		(void)*argv++;
+	}
+
+	if ((*argv) && (strlen(*argv) > 2) &&
+		(strncmp(*argv, "--interactive", strlen(*argv)) == 0)) {
+		interactive_flag = 1;
+	}
+
+	/* Process for local wl */
+	if (remote_type == NO_REMOTE) {
+		if (interactive_flag == 1)
+			(void)*argv--;
+		err = process_args(&ifr, argv);
+		return err;
+	} else {
+		/* Autodetect remote DUT */
+		if (rwl_dut_autodetect == TRUE)
+			rwl_detect((void*)&ifr, debug, &rwl_os_type);
+	}
+
+	/* RWL client needs to initialize ioctl_version */
+	if (wl_check((void *)&ifr) != 0) {
+		fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
+			exit(1);
+	}
+
+	if (interactive_flag == 1) {
+		err = do_interactive(&ifr);
+		return err;
+	}
+
+	if ((*argv) && (interactive_flag == 0)) {
+		err = process_args(&ifr, argv);
+		if ((err == BCME_SERIAL_PORT_ERR) && (remote_type == REMOTE_DONGLE)) {
+			DPRINT_ERR(ERR, "\n Retry again\n");
+			err = process_args((struct ifreq*)&ifr, argv);
+		}
+		return err;
+	}
+	rwl_usage(remote_type);
+#if defined(RWL_DONGLE) || RWL_SERIAL
+	if (remote_type == REMOTE_DONGLE || remote_type == REMOTE_SERIAL)
+		rwl_close_pipe(remote_type, (void*)&ifr);
+#endif /* RWL_DONGLE || RWL_SERIAL */
+	return err;
+}
+
+/*
+ * Function called for  'local' execution and for 'remote' non-interactive session
+ * (shell cmd, wl cmd)
+ */
+int
+process_args(struct ifreq* ifr, char **argv)
+{
+	char *ifname = NULL;
+	int help = 0;
+	int status = 0;
+	int vista_cmd_index;
+	int err = 0;
+	cmd_t *cmd = NULL;
+#ifdef RWL_WIFI
+	int retry;
+#endif
+
+	while (*argv) {
+		if ((strcmp (*argv, "sh") == 0) && (remote_type != NO_REMOTE)) {
+			(void)*argv++; /* Get the shell command */
+			if (*argv) {
+				/* Register handler in case of shell command only */
+				err = rwl_shell_cmd_proc((void*)ifr, argv, SHELL_CMD);
+			} else {
+				DPRINT_ERR(ERR, "Enter the shell "
+				           "command, e.g. ls(Linux) or dir(Win CE)\n");
+				err = -1;
+			}
+			return err;
+		}
+
+#ifdef RWLASD
+		if ((strcmp (*argv, "asd") == 0) && (remote_type != NO_REMOTE)) {
+			(void)*argv++; /* Get the asd command */
+			if (*argv) {
+				err = rwl_shell_cmd_proc((void*)ifr, argv, ASD_CMD);
+			} else {
+				DPRINT_ERR(ERR, "Enter the ASD command, e.g. ca_get_version\n");
+				err = -1;
+			}
+			return err;
+		}
+#endif
+		if (rwl_os_type == WINVISTA_OS) {
+			for (vista_cmd_index = 0; remote_vista_cmds[vista_cmd_index] &&
+				strcmp(remote_vista_cmds[vista_cmd_index], *argv);
+				vista_cmd_index++);
+			if (remote_vista_cmds[vista_cmd_index] != NULL) {
+				err = rwl_shell_cmd_proc((void *)ifr, argv, VISTA_CMD);
+				if ((remote_type == REMOTE_WIFI) && ((!strcmp(*argv, "join")))) {
+#ifdef RWL_WIFI
+					DPRINT_INFO(OUTPUT,
+						"\nChannel will be synchronized by Findserver\n\n");
+					sleep(RWL_WIFI_JOIN_DELAY);
+					for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+						if ((rwl_find_remote_wifi_server(ifr,
+							&g_rwl_buf_mac[0]) == 0)) {
+						break;
+					}
+				}
+#endif /* RWL_WIFI */
+			}
+			return err;
+			}
+		}
+
+		if ((status = wl_option(&argv, &ifname, &help)) == CMD_OPT) {
+			if (help)
+				break;
+			if (ifname) {
+				if (remote_type == NO_REMOTE) {
+					strncpy((*ifr).ifr_name, ifname, IFNAMSIZ);
+				}
+				else {
+					strncpy(g_rem_ifname, ifname, IFNAMSIZ);
+				}
+			}
+			continue;
+		}
+		/* parse error */
+		else if (status == CMD_ERR)
+			break;
+
+		if (remote_type == NO_REMOTE) {
+			/* use default interface */
+			if (!*(*ifr).ifr_name)
+				wl_find(ifr);
+
+			/* validate the interface */
+			if (!*(*ifr).ifr_name || (err = wl_check((void *)ifr)) < 0) {
+				fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
+				exit(1);
+			}
+
+			if ((strcmp (*argv, "--interactive") == 0) || (interactive_flag == 1)) {
+				err = do_interactive(ifr);
+				return err;
+			}
+		 }
+		/* search for command */
+		cmd = wl_find_cmd(*argv);
+		/* if not found, use default set_var and get_var commands */
+		if (!cmd) {
+			cmd = &wl_varcmd;
+		}
+#ifdef RWL_WIFI
+		if (!strcmp(cmd->name, "findserver")) {
+			remote_wifi_ser_init_cmds((void *) ifr);
+		}
+#endif /* RWL_WIFI */
+
+		/* RWL over Wifi supports 'lchannel' command which lets client
+		 * (ie *this* machine) change channels since normal 'channel' command
+		 * applies to the server (ie target machine)
+		 */
+		if (remote_type == REMOTE_WIFI)	{
+#ifdef RWL_WIFI
+			if (!strcmp(argv[0], "lchannel")) {
+				strcpy(argv[0], "channel");
+				rwl_wifi_swap_remote_type(remote_type);
+				err = (*cmd->func)((void *) ifr, cmd, argv);
+				rwl_wifi_swap_remote_type(remote_type);
+			} else {
+				err = (*cmd->func)((void *) ifr, cmd, argv);
+			}
+			/* After join cmd's gets exeuted on the server side , client needs to know
+			* the channel on which the server is associated with AP , after delay of
+			* few seconds client will intiate the scan on diffrent channels by calling
+			* rwl_find_remote_wifi_server fucntion
+			*/
+			if ((!strcmp(cmd->name, "join") || ((!strcmp(cmd->name, "ssid") &&
+				(*(++argv) != NULL))))) {
+				DPRINT_INFO(OUTPUT, "\n Findserver is called to synchronize the"
+				"channel\n\n");
+				sleep(RWL_WIFI_JOIN_DELAY);
+				for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+					if ((rwl_find_remote_wifi_server(ifr,
+					&g_rwl_buf_mac[0]) == 0)) {
+						break;
+					}
+				}
+			}
+#endif /* RWL_WIFI */
+		} else {
+			/* do command */
+			err = (*cmd->func)((void *) ifr, cmd, argv);
+		}
+		break;
+	} /* while loop end */
+
+/* provide for help on a particular command */
+	if (help && *argv) {
+		cmd = wl_find_cmd(*argv);
+		if (cmd) {
+			wl_cmd_usage(stdout, cmd);
+		} else {
+			DPRINT_ERR(ERR, "%s: Unrecognized command \"%s\", type -h for help\n",
+			                                                          wlu_av0, *argv);
+		}
+	} else if (!cmd)
+		wl_usage(stdout, NULL);
+	else if (err == BCME_USAGE_ERROR)
+		wl_cmd_usage(stderr, cmd);
+	else if (err == BCME_IOCTL_ERROR)
+		wl_printlasterror((void *) ifr);
+	else if (err == BCME_NODEVICE)
+		DPRINT_ERR(ERR, "%s : wl driver adapter not found\n", g_rem_ifname);
+
+	return err;
+}
+
+/* Function called for 'local' interactive session and for 'remote' interactive session */
+static int
+do_interactive(struct ifreq *ifr)
+{
+	int err = 0;
+
+#ifdef RWL_WIFI
+	int retry;
+#endif
+
+	while (1) {
+		char *fgsret;
+		char line[INTERACTIVE_MAX_INPUT_LENGTH];
+		fprintf(stdout, "> ");
+		fgsret = fgets(line, sizeof(line), stdin);
+
+		/* end of file */
+		if (fgsret == NULL)
+			break;
+		if (line[0] == '\n')
+			continue;
+
+		if (strlen (line) > 0) {
+			/* skip past first arg if it's "wl" and parse up arguments */
+			char *argv[INTERACTIVE_NUM_ARGS];
+			int argc;
+			char *token;
+			argc = 0;
+
+			while (argc < (INTERACTIVE_NUM_ARGS - 1) &&
+			       (token = strtok(argc ? NULL : line, " \t\n")) != NULL) {
+
+				/* Specifically make sure empty arguments (like SSID) are empty */
+				if (token[0] == '"' && token[1] == '"') {
+				    token[0] = '\0';
+				}
+
+				argv[argc++] = token;
+			}
+			argv[argc] = NULL;
+			if (argc == (INTERACTIVE_NUM_ARGS - 1) &&
+			    (token = strtok(NULL, " \t")) != NULL) {
+				printf("wl:error: too many args; argc must be < %d\n",
+				       (INTERACTIVE_NUM_ARGS - 1));
+				continue;
+			}
+#ifdef RWL_WIFI
+		if (!strcmp(argv[0], "findserver")) {
+			remote_wifi_ser_init_cmds((void *) ifr);
+		}
+#endif /* RWL_WIFI */
+
+			if (strcmp(argv[0], "q") == 0 || strcmp(argv[0], "exit") == 0) {
+				break;
+			}
+
+			if ((strcmp(argv[0], "sh") == 0) && (remote_type != NO_REMOTE))  {
+				if (argv[1]) {
+					process_args(ifr, argv);
+				} else {
+					DPRINT_ERR(ERR, "Give shell command");
+					continue;
+				}
+			} else { /* end shell */
+				/* check for lchannel support,applicable only for wifi transport.
+				* when lchannel is called remote type is swapped by calling swap_
+				* remote_type.This is done to change, the remote type to local,
+				* so that local machine's channel can be executed and
+				* returned to the user.
+				* To get back the original remote type, swap is recalled.
+				*/
+				if (remote_type == REMOTE_WIFI) {
+#ifdef RWL_WIFI
+					if (!strcmp(argv[0], "lchannel")) {
+						strcpy(argv[0], "channel");
+						rwl_wifi_swap_remote_type(remote_type);
+						err = wl_do_cmd(ifr, argv);
+						rwl_wifi_swap_remote_type(remote_type);
+					} else {
+						err = wl_do_cmd(ifr, argv);
+					}
+				/* After join cmd's gets exeuted on the server side, client
+				 * needs to know the channel on which the server is associated
+				 * with AP , after delay of few seconds client will intiate the
+				 * scan on diffrent channels by calling
+				 * rwl_find_remote_wifi_server function
+				 */
+					if ((!strcmp(argv[0], "join")) ||
+						(!strcmp(argv[0], "ssid"))) {
+						DPRINT_INFO(OUTPUT, "\n Findserver is called"
+						"after the join issued to remote \n \n");
+						sleep(RWL_WIFI_JOIN_DELAY);
+						for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+							if ((rwl_find_remote_wifi_server(ifr,
+							&g_rwl_buf_mac[0]) == 0)) {
+								break;
+							}
+						}
+					}
+#endif /* RWL_WIFI */
+				} else {
+					err = wl_do_cmd(ifr, argv);
+				}
+			} /* end of wl */
+		} /* end of strlen (line) > 0 */
+	} /* while (1) */
+
+	return err;
+}
+
+/*
+ * find command in argv and execute it
+ * Won't handle changing ifname yet, expects that to happen with the --interactive
+ * Return an error if unable to find/execute command
+ */
+static int
+wl_do_cmd(struct ifreq *ifr, char **argv)
+{
+	cmd_t *cmd = NULL;
+	int err = 0;
+	int help = 0;
+	char *ifname = NULL;
+	int status = CMD_WL;
+
+	/* skip over 'wl' if it's there */
+	if (*argv && strcmp (*argv, "wl") == 0) {
+		argv++;
+	}
+
+	/* handle help or interface name changes */
+	if (*argv && (status = wl_option (&argv, &ifname, &help)) == CMD_OPT) {
+		if (ifname) {
+			fprintf(stderr,
+			        "Interface name change not allowed within --interactive\n");
+		}
+	}
+
+	/* in case wl_option eats all the args */
+	if (!*argv) {
+		return err;
+	}
+
+	if (status != CMD_ERR) {
+		/* search for command */
+		cmd = wl_find_cmd(*argv);
+
+		/* defaults to using the set_var and get_var commands */
+		if (!cmd) {
+			cmd = &wl_varcmd;
+		}
+		/* do command */
+		err = (*cmd->func)((void *)ifr, cmd, argv);
+	}
+	/* provide for help on a particular command */
+	if (help && *argv) {
+	  cmd = wl_find_cmd(*argv);
+	 if (cmd) {
+		wl_cmd_usage(stdout, cmd);
+	} else {
+			DPRINT_ERR(ERR, "%s: Unrecognized command \"%s\", type -h for help\n",
+			       wlu_av0, *argv);
+	       }
+	} else if (!cmd)
+		wl_usage(stdout, NULL);
+	else if (err == BCME_USAGE_ERROR)
+		wl_cmd_usage(stderr, cmd);
+	else if (err == BCME_IOCTL_ERROR)
+		wl_printlasterror((void *)ifr);
+	else if (err == BCME_NODEVICE)
+		DPRINT_ERR(ERR, "%s : wl driver adapter not found\n", g_rem_ifname);
+
+	return err;
+}
+
+/* Search the wl_cmds table for a matching command name.
+ * Return the matching command or NULL if no match found.
+ */
+static cmd_t *
+wl_find_cmd(char* name)
+{
+	cmd_t *cmd = NULL;
+
+	/* search the wl_cmds for a matching name */
+	for (cmd = wl_cmds; cmd->name && strcmp(cmd->name, name); cmd++);
+
+	if (cmd->name == NULL)
+		cmd = NULL;
+
+	return cmd;
+}
+
+void def_handler(int signum)
+{
+	UNUSED_PARAMETER(signum);
+	kill(g_child_pid, SIGINT);
+	kill(getpid(), SIGINT);
+	exit(0);
+}
+/* Create a child that waits for Ctrl-C at the client side
+ */
+int rwl_shell_createproc(void *wl)
+{
+	UNUSED_PARAMETER(wl);
+	signal(SIGINT, ctrlc_handler);
+	signal(SIGTERM, def_handler);
+	signal(SIGABRT, def_handler);
+	return fork();
+}
+
+/* In case if the server shell command exits normally
+ * then kill the thread that was waiting for Ctr-C to happen
+ * at the client side
+ */
+void rwl_shell_killproc(int pid)
+{
+	kill(pid, SIGKILL);
+	signal(SIGINT, SIG_DFL);
+	wait(NULL);
+}
+#ifdef RWL_SOCKET
+/* to validate hostname/ip given by the client */
+int validate_server_address()
+{
+	struct hostent *he;
+	struct ipv4_addr temp;
+	if (!wl_atoip(g_rwl_servIP, &temp)) {
+	/* Wrong IP address format check for hostname */
+		if ((he = gethostbyname(g_rwl_servIP)) != NULL) {
+			if (!wl_atoip(*he->h_addr_list, &temp)) {
+				g_rwl_servIP =
+				inet_ntoa(*(struct in_addr *)*he->h_addr_list);
+				if (g_rwl_servIP == NULL) {
+					DPRINT_ERR(ERR, "Error at inet_ntoa \n");
+					return FAIL;
+				}
+			} else {
+				DPRINT_ERR(ERR, "Error in IP address \n");
+				return FAIL;
+			}
+		} else {
+			DPRINT_ERR(ERR, "Enter correct IP address/hostname format\n");
+			return FAIL;
+		}
+	}
+	return SUCCESS;
+}
+#endif /* RWL_SOCKET */
diff --git a/src/wl/exe/wlu_pipe.c b/src/wl/exe/wlu_pipe.c
new file mode 100644
index 0000000..a8d5580
--- /dev/null
+++ b/src/wl/exe/wlu_pipe.c
@@ -0,0 +1,1068 @@
+/*
+ * Common Functionality for pipe
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_pipe.c 363727 2012-10-19 02:21:29Z $
+ */
+#ifdef WIN32
+#define NEED_IR_TYPES
+
+#include <windows.h>
+#include <epictrl.h>
+#include <irelay.h>
+#endif /* WIN32 */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <wlioctl.h>
+#include <net/if.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef TARGETOS_symbian
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#else
+#include <malloc.h>
+#endif /* TARGETOS_symbian */
+#include <typedefs.h>
+#include <wlioctl.h>
+
+#include <proto/ethernet.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
+#include <rwl_wifi.h>
+#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
+#include "wlu.h"
+#include "wlu_remote.h"
+
+static rem_ioctl_t rem_cdc;
+char  *g_rwl_device_name_serial = "";
+bool g_rwl_swap = FALSE;
+char g_rem_ifname[IFNAMSIZ] = "\0";
+int need_speedy_response; /* Indicate findserver is checking channels */
+
+	/* Linux 100 usec */
+#define SYNC_TIME 100
+
+#define UART_FIFO_LEN 			64
+#define END_OF_PACK_SEP_LEN 	2
+#define INIT_CMD_SLEEP 			500
+#define dtoh32(i) i
+
+/* dword align allocation */
+union {
+	uchar bufdata[ETHER_ADDR_LEN];
+	uint32 alignme;
+} bufmac_wlu;
+char *g_rwl_buf_mac = (char*) &bufmac_wlu.bufdata;
+
+#ifdef RWL_WIFI
+/* dword align allocation */
+union {
+	uchar shelldata[WL_MAX_BUF_LEN];
+	uint32 alignme;
+} shell_wlu;
+char *g_rwl_buf_shell = (char*) &shell_wlu.shelldata;
+int rwl_find_remote_wifi_server(void *wl, char *id);
+int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);
+
+/*
+ * This function runs a set of commands before running the wi-fi server
+ * This is avoids packet drops and improves performance.
+ * We run the following wl commands
+ * up, mpc 0, wsec 0, slow_timer 999999, fast_timer 999999, glacial_timer 999999
+ * legacylink 1, monitor 1.
+ */
+void remote_wifi_ser_init_cmds(void *wl)
+{
+	int err;
+	char bigbuf[RWL_WIFI_BUF_LEN];
+	uint len = 0, count;
+	/* The array stores command, length and then data format */
+	remote_wifi_cmds_t wifi_cmds[] = {
+						{WLC_UP,  NULL, 0x0},
+						{WLC_SET_VAR,  "mpc", 0},
+						{WLC_SET_WSEC,  NULL, 0x0},
+						{WLC_SET_VAR, "slow_timer", 999999},
+						{WLC_SET_VAR, "fast_timer", 999999},
+						{WLC_SET_VAR, "glacial_timer", 999999},
+						{WLC_SET_MONITOR, NULL, 0x1},
+						{WLC_SET_PM, NULL, 0x0}
+	};
+
+	for (count = 0; count < ARRAYSIZE(wifi_cmds); count++) {
+
+		if (wifi_cmds[count].data == NULL)
+			len = sizeof(int);
+		else
+			len = strlen(wifi_cmds[count].data) + 1 + sizeof(int);
+
+		/* If the command length exceeds the buffer length continue
+		 * executing the next command
+		 */
+		if (len > sizeof(bigbuf)) {
+			DPRINT_ERR(ERR, "Err: command len exceeds buf len. Check"
+				"initialization cmds\n");
+			continue;
+		}
+
+		if (wifi_cmds[count].data != NULL) {
+			strcpy(bigbuf, wifi_cmds[count].data);
+			memcpy(&bigbuf[strlen(wifi_cmds[count].data)+1],
+			(char*)&wifi_cmds[count].value, sizeof(int));
+		} else {
+			memcpy(&bigbuf[0], (char*)&wifi_cmds[count].value, sizeof(int));
+		}
+#ifdef WIN32
+		/* Add OID base for NDIS commands */
+
+		err = (int)ir_setinformation(wl, wifi_cmds[count].cmd + WL_OID_BASE,
+		bigbuf, &len);
+#endif
+
+		if (wifi_cmds[count].cmd == WLC_UP)
+			/* NULL needs to be passed to the driver if WL UP command needs to
+			 * be executed Otherwise driver hangs
+			 */
+			err = wl_ioctl(wl, wifi_cmds[count].cmd,
+				NULL, 0, TRUE);
+		else
+			err = wl_ioctl(wl, wifi_cmds[count].cmd,
+			(void*)&bigbuf, len, TRUE);
+		rwl_sleep(INIT_CMD_SLEEP);
+	}
+	BCM_REFERENCE(err);
+}
+
+/* When user wants to execute local CMD being in remote wifi mode, this fucntion is used
+ * to change the remote types.
+ * This fucntion is called to swap the remote type to execute the cmd using the local
+ *  driver interface.
+ * This is required for to call proper front end fucntions to achive the local set/get ioctl.
+ */
+void
+rwl_wifi_swap_remote_type(int flag)
+{
+	static int remote_flag;
+	if (flag == REMOTE_WIFI) {
+		remote_type = NO_REMOTE;
+		remote_flag = flag;
+	} else if (remote_flag == REMOTE_WIFI) {
+		remote_type = remote_flag;
+		remote_flag = flag;
+	}
+	return;
+}
+
+void
+rwl_wifi_free_list(dot11_action_wifi_vendor_specific_t *list[])
+{
+	int i;
+	for (i = 0; i < RWL_DEFAULT_WIFI_FRAG_COUNT; i++) {
+		if (list[i])
+			free(list[i]);
+	}
+}
+
+/*
+ *  Configures local channel  for finding server.
+ *  Server call this fucntion for getting its current channel,
+ *  client uses this fucntion for setting its channel to new channel.
+ */
+static int
+rwl_wifi_config_channel(void *wl, int cmd, int *channel)
+{
+	int error;
+	channel_info_t ci;
+	error = -1;
+	/* Get functionality is used only by server */
+	if (cmd == WLC_GET_CHANNEL) {
+		memset((char*)&ci, 0, sizeof(ci));
+		if ((error = wl_get(wl, cmd, &ci, sizeof(channel_info_t))) < 0)
+			return error;
+		ci.hw_channel = dtoh32(ci.hw_channel);
+		ci.scan_channel = dtoh32(ci.scan_channel);
+		ci.target_channel = dtoh32(ci.target_channel);
+		if (ci.scan_channel) {
+			printf("Scan in progress.\n");
+		}
+		*channel = ci.hw_channel;
+	}
+
+	if (cmd == WLC_SET_CHANNEL) {
+		/* Set functionality is used by the client */
+		ci.target_channel = *channel;
+		/*   When user wants to execute local CMD being in remote wifi mode,
+		*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+		*/
+		rwl_wifi_swap_remote_type(remote_type);
+		error = wl_set(wl, cmd, &ci.target_channel, sizeof(int));
+		/* rever it back to same old remote type */
+		rwl_wifi_swap_remote_type(remote_type);
+	}
+	return error;
+}
+/*
+allocate the memory for action frame and update with wifi tranport header.
+*/
+dot11_action_wifi_vendor_specific_t *
+rwl_wifi_allocate_actionframe()
+{
+	dot11_action_wifi_vendor_specific_t *action_frame;
+
+	if ((action_frame = (dot11_action_wifi_vendor_specific_t *)
+	malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+		DPRINT_ERR(ERR, "rwl_wifi_allocate_actionframe: unable to allocate frame \n");
+		return action_frame;
+	}
+	action_frame->category 	= RWL_ACTION_WIFI_CATEGORY;
+	action_frame->OUI[0] 	= RWL_WIFI_OUI_BYTE0;
+	action_frame->OUI[1] 	= RWL_WIFI_OUI_BYTE1;
+	action_frame->OUI[2] 	= RWL_WIFI_OUI_BYTE2;
+	action_frame->type   	= RWL_WIFI_DEFAULT_TYPE;
+	action_frame->subtype   = RWL_WIFI_DEFAULT_SUBTYPE;
+
+	return action_frame;
+}
+/*
+ * Send the valid action frame (CDC+DATA) through the REF driver interface.
+ * if the CMD is "findserver" then "findmypeer" frames are sent on the diffrent
+ * channels to reconnect
+ * to with server. Other wl cmd takes the normal path.
+ * parameter 3 , i.e. buf contains the cmd line arguments  and buf_len is the actual
+ * length of the buf. data_len is the length of the actual data to be sent to remote server.
+ */
+int
+remote_CDC_wifi_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags)
+{
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+	int error, read_try;
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send;
+
+	/* prepare CDC header */
+	rem_ptr->msg.cmd = cmd;
+	rem_ptr->msg.len = buf_len;
+	rem_ptr->msg.flags = flags;
+	rem_ptr->data_len = data_len;
+	if (strlen(g_rem_ifname) != 0)
+		strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ);
+	rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
+
+	if ((data_len > buf_len)) {
+		DPRINT_ERR(ERR, "remote_CDC_wifi_tx: data_len (%d) > buf_len (%d)\n",
+		data_len, buf_len);
+		return (FAIL);
+	}
+	/* client will not send data greater than RWL_WIFI_FRAG_DATA_SIZE to server,
+	 * this condition should not be hit on client side, when sending the cmd
+	 * to remote server
+	 */
+	if (data_len > RWL_WIFI_FRAG_DATA_SIZE)
+		DPRINT_DBG(OUTPUT, "data size exceeds data_len %d\n", rem_ptr->msg.len);
+
+	if ((buf != NULL) && (strlen((char*)buf) >= (sizeof(RWL_WIFI_FIND_SER_CMD)-1)) &&
+		(!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD))) {
+		/* This is special case for wifi, when user wants to findserver,
+		* client has to execute it locally.Find the channel on the on
+		* which DUT is operating and sync up with specified MAC address,
+		* retry if fails to find the server
+		*/
+		for (read_try = 0; read_try < RWL_WIFI_RETRY; read_try++) {
+			if (((error = rwl_find_remote_wifi_server(wl,
+			&g_rwl_buf_mac[0])) == 0)) {
+				break;
+			}
+		}
+		return error;
+	}
+
+	if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_ERR(ERR, "remote_CDC_wifi_tx: Failed to allocate memory\n");
+		return (FAIL);
+	}
+	/* only data length needs to be sent to remote server using this function
+	* This function is only meant for client to send data to server
+	* Copy the CDC header and data to action frame data feild
+	* Now we have encapsulated the CDC header and data completely to in the
+	* action frame.
+	*/
+	memcpy((void*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
+		(char*)rem_ptr, REMOTE_SIZE);
+	if (buf != NULL) {
+	  memcpy((void*)&rem_wifi_send->data[REMOTE_SIZE], buf, data_len);
+	}
+
+	/* Send the action frame to remote server using the  rwl_var_setbuf fucntion,
+	 * which will use the local driver interface to send this frame on the air
+	 */
+	if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
+	RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+		DPRINT_ERR(ERR, "Unable to read the action frame %d error\n", error);
+	}
+	free(rem_wifi_send);
+	return error;
+}
+
+/*
+ * Read the valid action frame through the REF/DUT driver interface.
+ * Retry for no of times, wait for action frame for the specified time.
+ */
+int
+remote_CDC_DATA_wifi_rx(void *wl, dot11_action_wifi_vendor_specific_t * rec_frame)
+{
+	int error, read_try;
+	void *ptr = NULL;
+
+
+	/* retry is to ensure to read late arrival action frame */
+	for (read_try = 0; read_try < RWL_WIFI_RX_RETRY; read_try++) {
+		/* read the action frame queued in the local driver wifi queue */
+		if ((error = rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,
+		 RWL_WIFI_ACTION_FRAME_SIZE, &ptr)) < 0) {
+			DPRINT_ERR(ERR, "remote_CDC_DATA_wifi_rx: Error in reading the frame %d\n",
+			error);
+			return error;
+		}
+		/* copy the read action frame to the user frame and cjheck for the action category.
+		 *  If the action category matches with RWL_ACTION_WIFI_CATEGORY ,
+		 *  then its the valid frame, otherwise ignore it.
+		 */
+		memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);
+
+		if (rec_frame->category == RWL_ACTION_WIFI_CATEGORY) {
+			break;
+		} else {
+			/* If we are executing findserver then sleep less */
+			if (!need_speedy_response)
+				rwl_sleep(RWL_WIFI_RX_DELAY);
+			else
+				rwl_sleep(RWL_CHANNEL_RX_SCAN_DELAY);
+		}
+	}
+	/* If failed to get the valid frame , indicate the error  */
+	if (!(rec_frame->category == RWL_ACTION_WIFI_CATEGORY)) {
+		return (FAIL);
+	}
+	return error;
+}
+/*
+ * read data that has reached client in fragments. If the functtion is
+ * called from rwl_shell_information_fe then the flag will be set to 1.
+ * For shell response this function will output the response on the standard interface.
+ * Response will be coming in out of order , this fucntion will make it inorder.
+ * Duplicate action frames are ignored.
+ */
+int
+remote_CDC_DATA_wifi_rx_frag(void *wl, rem_ioctl_t *rem_ptr, uint input_len,
+void *input, bool shell)
+{
+	int error, totalfrag, seq_num, num_frags, remainingbytes;
+	dot11_action_wifi_vendor_specific_t *rec_frame;
+	uchar *input_buf = (uchar*)input;
+	/* An array of pointers to each recieved frag */
+	dot11_action_wifi_vendor_specific_t *master_list[RWL_DEFAULT_WIFI_FRAG_COUNT];
+
+	UNUSED_PARAMETER(input_len);
+	remainingbytes = 0;
+
+	memset(master_list, 0, sizeof(master_list));
+	/* in case of shell cmd's receive size is unknown */
+	if (shell) {
+		input_buf = (uchar*)g_rwl_buf_shell;
+		memset(input_buf, 0, WL_MAX_BUF_LEN);
+	}
+
+	/* We don't yet know how many fragments we will need to read since the
+	   length is contained in the first frgment of the message itself. Set
+	   totalfrag to an arbitry large number and we will readjust it after we
+	   successfully recieve the first frag.
+	*/
+	totalfrag = RWL_DEFAULT_WIFI_FRAG_COUNT;
+
+	for (num_frags = 0; num_frags <= totalfrag; num_frags++) {
+		if ((rec_frame = rwl_wifi_allocate_actionframe()) == NULL) {
+			DPRINT_DBG(OUTPUT, "malloc failure\n");
+			rwl_wifi_free_list(master_list);
+			return (FAIL);
+		}
+		if ((error = remote_CDC_DATA_wifi_rx((void*)wl, rec_frame)) < 0) {
+			free(rec_frame);
+			rwl_wifi_free_list(master_list);
+			return FAIL;
+		}
+
+		if (rec_frame->subtype >= RWL_DEFAULT_WIFI_FRAG_COUNT) {
+			DPRINT_DBG(OUTPUT, " Read bogus subtype %d\n", rec_frame->subtype);
+			free(rec_frame);
+			continue;
+		}
+		/* Keep only originals and discard any dup frags */
+		if (!master_list[rec_frame->subtype]) {
+			master_list[rec_frame->subtype] = rec_frame;
+		} else {
+			num_frags--;
+			free(rec_frame);
+		}
+
+		/* Look for first frag so we can accurately calculate totalfrag */
+		if (rec_frame->subtype == RWL_WIFI_DEFAULT_SUBTYPE) {
+			memcpy((char*)rem_ptr,
+			(char*)&master_list[rec_frame->subtype]->
+			data[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE);
+			rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+			totalfrag = rem_ptr->msg.len / RWL_WIFI_FRAG_DATA_SIZE;
+			remainingbytes = rem_ptr->msg.len % RWL_WIFI_FRAG_DATA_SIZE;
+		}
+	}
+
+	/* All frags are now read and there are no dups. Check for missing frags */
+	for (seq_num = 0; seq_num < totalfrag; seq_num++) {
+		if (!master_list[seq_num]) {
+			DPRINT_DBG(OUTPUT, "Missing frag number %d\n", seq_num);
+			rwl_wifi_free_list(master_list);
+			return (FAIL);
+		}
+	}
+	/*
+	case 1: response in one frame i.e if (totalfrag==0)
+	case 2: response in multiple frame ( multiple of RWL_WIFI_FRAG_DATA_SIZE)
+	case 3: response in multiple frame and not in multiple of RWL_WIFI_FRAG_DATA_SIZE
+	*/
+
+	/* case 1: Check for the response in single frame */
+	if (totalfrag == 0)
+		memcpy((char*)&input_buf[0],
+		(char*)&master_list[0]->data[REMOTE_SIZE], rem_ptr->msg.len);
+	else /* case 2: Copy fragments into contiguous frame */
+		memcpy((char*)&input_buf[0],
+		(char*)&master_list[0]->data[REMOTE_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
+
+	/*
+	* If all the frames are recieved , copy them to a contigues buffer
+	*/
+	for (seq_num = 1; seq_num < totalfrag; seq_num++) {
+		memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],
+		(char*)&master_list[seq_num]->data, RWL_WIFI_FRAG_DATA_SIZE);
+	}
+
+	/* case 3 : if response is in fragments and valid data in the last frame is less
+	 * than RWL_WIFI_FRAG_DATA_SIZE
+	 */
+	if (remainingbytes && (totalfrag > 0))
+		memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],
+		(char*)&master_list[seq_num]->data, remainingbytes);
+
+	if (shell) {
+		write(1, (char*)input_buf, strlen((char*)input_buf));
+	}
+
+	rwl_wifi_free_list(master_list);
+	return error;
+}
+/*
+ * read out all the action frame which are queued in the driver even
+ * before issuing any wl cmd. This is essential because due to late arrival of frame it can
+ * get queued after the read expires.
+ */
+void
+rwl_wifi_purge_actionframes(void *wl)
+{
+	dot11_action_wifi_vendor_specific_t *rec_frame;
+	void *ptr = NULL;
+
+	if ((rec_frame = (dot11_action_wifi_vendor_specific_t *)
+	malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+		DPRINT_DBG(OUTPUT, "Purge Error in reading the frame \n");
+		return;
+	}
+
+	for (;;) {
+		if (rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,
+		RWL_WIFI_ACTION_FRAME_SIZE, &ptr) < 0) {
+			DPRINT_DBG(OUTPUT, "rwl_wifi_purge_actionframes:"
+			"Purge Error in reading the frame \n");
+			break;
+		}
+		memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);
+
+		if ((rec_frame->category != RWL_ACTION_WIFI_CATEGORY))
+			break;
+	}
+
+	free(rec_frame);
+
+	return;
+}
+/*
+ * check for the channel of remote and respond if it matches with its current
+ * channel. Once the server gets the handshake cmd, it will check the channel
+ * number of the remote with its channel and if it matches , then it send out the
+ * ack to the remote client. This fucntion is used only by the server.
+ */
+void
+rwl_wifi_find_server_response(void *wl, dot11_action_wifi_vendor_specific_t *rec_frame)
+{
+	int error, send, server_channel;
+
+	if (rec_frame->type == RWL_WIFI_FIND_MY_PEER) {
+
+		rec_frame->type = RWL_WIFI_FOUND_PEER;
+		/* read channel on of the SERVER */
+		rwl_wifi_config_channel(wl, WLC_GET_CHANNEL, &server_channel);
+		/* overlapping channel not supported,
+		so server will only respond to client on the channel of the client
+		*/
+		if (rec_frame->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] == server_channel) {
+			/* send the response by updating server channel in the frame */
+			rec_frame->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] = server_channel;
+			/* change the TYPE feild for giving the ACK */
+			for (send = 0; send < RWL_WIFI_SEND; send++) {
+				if ((error = rwl_var_send_vs_actionframe(wl,
+					RWL_WIFI_ACTION_CMD,
+					rec_frame,
+					RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+					DPRINT_ERR(ERR, "rwl_wifi_find_server_response: Failed"
+					"to Send the Frame %d\n", error);
+					break;
+				}
+				rwl_sleep(RWL_WIFI_SEND_DELAY);
+			}
+		}
+	}
+	return;
+}
+/*
+ * This function is used by client only. Sends the finmypeer sync frame to remote
+ * server on diffrent channels and  waits for the response.
+ */
+int
+rwl_find_remote_wifi_server(void *wl, char *id)
+{
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send, *rem_wifi_recv;
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+	/* This list is generated considering valid channel and if this
+	 * may requires updation or deletion. This needs to be identified.
+	 * we have assumed that server band is not known and considered all band channels.
+	 */
+	int wifichannel[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+	11, 36, 40, 44, 48, 149, 153, 157, 161, 165};
+	int i, error, schannel, channel_count;
+	struct ether_addr * curr_macaddr;
+	int ret;
+	need_speedy_response = TRUE;
+
+	if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate \n");
+		return FAIL;
+	}
+	if ((rem_wifi_recv = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate\n");
+		free(rem_wifi_send);
+		return FAIL;
+	}
+
+	channel_count = sizeof(wifichannel) / sizeof(int);
+
+	/* make dummy read to make sure we don't read the already queued
+	 * actionframes against the cmd we issue
+	 */
+	rwl_wifi_purge_actionframes(wl);
+
+	/* update the client sync specifier */
+	rem_wifi_send->type = RWL_WIFI_FIND_MY_PEER;
+	/* update the CDC flag to indicate it is handshake frame */
+	rem_ptr->msg.cmd = 0;
+	/* cmd =0 ,this will be ignored when server receive frame
+	 * with REMOTE_FINDSERVER_IOCTL flag
+	 */
+	rem_ptr->msg.len = RWL_WIFI_FRAG_DATA_SIZE;
+	rem_ptr->msg.flags = REMOTE_FINDSERVER_IOCTL;
+	rem_ptr->data_len = RWL_WIFI_FRAG_DATA_SIZE;
+	rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
+
+	memcpy((char*)&rem_wifi_send->data, (char*)rem_ptr, REMOTE_SIZE);
+	/* copy server mac to which ref driver needs to send unicast action frame */
+	memcpy((char*)&rem_wifi_send->data[RWL_REF_MAC_ADDRESS_OFFSET], &id[0], ETHER_ADDR_LEN);
+
+	if ((ret = rwl_var_getbuf(wl, "cur_etheraddr", NULL, 0, (void**) &curr_macaddr)) < 0) {
+		DPRINT_ERR(ERR, "Error getting current Mac addr \n");
+		return FAIL;
+	}
+
+	memcpy((char*)&rem_wifi_send->data[RWL_DUT_MAC_ADDRESS_OFFSET], (char*)curr_macaddr->octet,
+		ETHER_ADDR_LEN);
+	/* Start with the channel in the list and keep changing till the server
+	 * responds or channels list ends
+	 */
+	for (i = 0; i < channel_count; i++) {
+		DPRINT_INFO(OUTPUT, "Scanning Channel: %d ...\n", wifichannel[i]);
+		if ((error = rwl_wifi_config_channel(wl, WLC_SET_CHANNEL,
+		&wifichannel[i])) < 0) {
+			DPRINT_ERR(ERR, " Failed to set the specified channel %d\n",
+			wifichannel[i]);
+			break;
+		}
+		/* send channel detail of client to server */
+		rem_wifi_send->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] = wifichannel[i];
+
+		if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
+		RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+			DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
+			break;
+		}
+		/* read the server response on the same channel */
+		if ((error = remote_CDC_DATA_wifi_rx(wl, rem_wifi_recv)) < 0) {
+			rwl_sleep(RWL_CHANNEL_SCAN_WAIT);
+			continue;
+		}
+		/* Verify for the Type RWL_WIFI_FOUND_PEER */
+		if (rem_wifi_recv->type == RWL_WIFI_FOUND_PEER) {
+			if (rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] ==
+				rem_wifi_recv->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET]) {
+
+				DPRINT_INFO(OUTPUT, "Server is on channel # %d\n",
+				rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET]);
+
+				schannel = rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET];
+				/* Set the back to the channel on which REF was originally */
+				if ((error = rwl_wifi_config_channel(wl,
+				WLC_SET_CHANNEL, &schannel) < 0)) {
+					DPRINT_ERR(ERR, "Failed to set the specified"
+					"channel %d\n", schannel);
+				} else {
+					DPRINT_ERR(ERR, "REF now moved to the"
+					"channel of server # %d\n", schannel);
+				}
+				need_speedy_response = FALSE;
+				/* we are done here, end the loop */
+				break;
+			} else {
+				DPRINT_INFO(OUTPUT, "Server is operating on diffrent channel."
+				"continue scanning\n");
+			}
+		}
+		/* before chaning the channel of client and sending sync frame
+		 * wait for while and send
+		 */
+		rwl_sleep(RWL_CHANNEL_SCAN_WAIT);
+	}
+	need_speedy_response = FALSE;
+
+	free(rem_wifi_send);
+	free(rem_wifi_recv);
+	return error;
+}
+#endif /* RWL_WIFI */
+#ifdef RWL_DONGLE
+static int
+remote_CDC_tx_dongle(void *wl, rem_ioctl_t *rem_ptr, uchar *buf)
+{
+	unsigned long numwritten;
+	char end_of_packet[END_OF_PACK_SEP_LEN] = "\n\n";
+	uchar loc_buf[UART_FIFO_LEN];
+	uint len = END_OF_PACK_SEP_LEN;
+	uint noframes, frame_count, rem_bytes;
+	uint n_bytes;
+	uint data_len;
+
+	/* Converting the CDC header with keyword 'rwl ' in ascii format
+	 * as dongle UART understands only ascii format.
+	 * In dongle UART driver CDC structure is made from the ascii data
+	 * it received.
+	 */
+	sprintf((char*)loc_buf, "rwl %d %d %d %d ", rem_ptr->msg.cmd, rem_ptr->msg.len,
+		rem_ptr->msg.flags, rem_ptr->data_len);
+	n_bytes = strlen((char*)loc_buf);
+
+	data_len = ltoh32(rem_ptr->data_len);
+	DPRINT_DBG(OUTPUT, "rwl %x %d %d %d ", ltoh32(rem_ptr->msg.cmd), ltoh32(rem_ptr->msg.len),
+		ltoh32(rem_ptr->msg.flags), data_len);
+	DPRINT_DBG(OUTPUT, "CDC Header:No of bytes to be sent=%d\n", n_bytes);
+	DPRINT_DBG(OUTPUT, "Data:No of bytes to be sent=%d\n", data_len);
+
+	/* Send the CDC Header */
+	if (rwl_write_serial_port(wl, (char*)loc_buf, n_bytes, &numwritten) < 0) {
+		DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
+		DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != n_bytes %d\n",
+			numwritten, n_bytes);
+		return (FAIL);
+	}
+
+	/* Dongle UART FIFO len is 64 bytes and flow control is absent.
+	 * While transmitting large chunk of data the data was getting lost
+	 * at UART driver so for large chunk of data 64 bytes are sent at a time
+	 * folowed by delay and then next set of 64 bytes and so on.
+	 * For data which is less than 64 bytes it is sent in one shot
+	 */
+
+	noframes = rem_ptr->data_len/UART_FIFO_LEN;
+	if (noframes == 0) {
+		/* Send the data now */
+		if (rwl_write_serial_port(wl, (char*)buf, rem_ptr->data_len, &numwritten) < 0) {
+			DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
+			DPRINT_ERR(ERR, "Data_Tx: Header: numwritten %ld != len %d\n",
+			numwritten, rem_ptr->data_len);
+			return (FAIL);
+		}
+
+	} else {
+		if (rem_ptr->data_len % UART_FIFO_LEN == 0) {
+			rem_bytes = UART_FIFO_LEN;
+		} else {
+			rem_bytes = rem_ptr->data_len % UART_FIFO_LEN;
+			noframes += 1;
+		}
+
+		for (frame_count = 0; frame_count < noframes; frame_count++) {
+			if (frame_count != noframes-1) {
+				memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
+				UART_FIFO_LEN);
+				/* Send the data now */
+				if (rwl_write_serial_port(wl, (char*)loc_buf, UART_FIFO_LEN,
+				&numwritten) == -1) {
+					DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
+					return (-1);
+				}
+
+			} else {
+				memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
+				rem_bytes);
+
+				if (rwl_write_serial_port(wl, (char*)loc_buf, rem_bytes,
+				&numwritten) == -1) {
+					DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
+					return (-1);
+				}
+
+			}
+			rwl_sleep(SYNC_TIME);
+		}
+	}
+
+	/* Send end of packet now */
+	if (rwl_write_serial_port(wl, end_of_packet, len, &numwritten) == -1) {
+		DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
+		DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != len %d\n",
+			numwritten, len);
+		return (FAIL);
+	}
+
+	DPRINT_DBG(OUTPUT, "Packet sent!\n");
+
+	/* Return size of actual buffer to satisfy accounting going on above this level */
+	return (ltoh32(rem_ptr->msg.len));
+}
+#endif /* RWL_DONGLE */
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)|| defined(RWL_SOCKET)
+void *
+rwl_open_pipe(int remote_type, char *port, int ReadTotalTimeout, int debug)
+{
+	return rwl_open_transport(remote_type, port, ReadTotalTimeout, debug);
+}
+
+int
+rwl_close_pipe(int remote_type, void* handle)
+{
+	return rwl_close_transport(remote_type, handle);
+}
+#endif
+
+int
+remote_CDC_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags, int debug)
+{
+#ifdef RWL_SERIAL
+	unsigned long numwritten = 0;
+#endif
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+#ifdef RWL_WIFI
+	int error;
+	uint totalframes, tx_count;
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send;
+#endif
+	UNUSED_PARAMETER(debug);
+	UNUSED_PARAMETER(buf);
+	UNUSED_PARAMETER(wl);
+
+	memset(rem_ptr, 0, sizeof(rem_ioctl_t));
+	rem_ptr->msg.cmd = cmd;
+	rem_ptr->msg.len = buf_len;
+	rem_ptr->msg.flags = flags;
+	rem_ptr->data_len = data_len;
+	if (strlen(g_rem_ifname) != 0)
+		strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ);
+	rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
+	if (data_len > buf_len) {
+		DPRINT_ERR(ERR, "remote_CDC_tx: data_len (%d) > buf_len (%d)\n", data_len, buf_len);
+		return (FAIL);
+	}
+#ifdef RWL_SERIAL
+	if (remote_type == REMOTE_SERIAL) {
+		int ret;
+		/* Send CDC header first */
+		if ((ret = rwl_write_serial_port(wl, (char *)rem_ptr,
+			REMOTE_SIZE, &numwritten)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+		numwritten = ret;
+
+		/* Send data second */
+		if ((ret = rwl_write_serial_port(wl, (char*)buf,
+			data_len, &numwritten)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+		numwritten = ret;
+
+		return (buf_len);
+	}
+#endif /* RWL_SERIAL */
+#ifdef RWL_DONGLE
+	if (remote_type == REMOTE_DONGLE) {
+		return (remote_CDC_tx_dongle(wl, rem_ptr, buf));
+	}
+#endif /* RWL_DONGLE */
+#ifdef RWL_SOCKET
+	if (remote_type == REMOTE_SOCKET) {
+		int ret;
+
+		/* Send CDC header first */
+		if ((ret = rwl_send_to_streamsocket(*(int*)wl, (char *)rem_ptr,
+			REMOTE_SIZE, 0)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+
+		/* Send data second */
+		if ((ret = rwl_send_to_streamsocket(*(int*)wl, (const char*)buf,
+			data_len, 0)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+
+		return (buf_len);
+	}
+#endif /* RWL_SOCKET */
+
+#ifdef RWL_WIFI
+	/*
+	 * wifi action frame is formed based on the CDC header and data.
+	 * If the data is bigger than RWL_WIFI_FRAG_DATA_SIZE size, number of fragments are
+	 * calculated and sent
+	 * similar number of action frames with subtype incremented with sequence.
+	 * Frames are sent with delay to avoid the outof order at receving end
+	 */
+	if (remote_type == REMOTE_WIFI) {
+		if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
+			DPRINT_ERR(ERR, "remote_CDC_tx: Failed to get allocated buffer\n");
+			return (FAIL);
+		}
+
+		if (buf_len > RWL_WIFI_FRAG_DATA_SIZE) {
+			/* response needs to be sent in fragments */
+			totalframes = buf_len / RWL_WIFI_FRAG_DATA_SIZE;
+			memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
+			(char*)rem_ptr,	REMOTE_SIZE);
+			memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE], &buf[0],
+			RWL_WIFI_FRAG_DATA_SIZE);
+			/* update type feild to inform receiver it's frammeted response frame
+			*/
+			rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+			rem_wifi_send->subtype = RWL_WIFI_DEFAULT_SUBTYPE;
+
+			if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
+				rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+				DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
+				free(rem_wifi_send);
+				return error;
+			}
+			/* Send remaining bytes in fragments */
+			for (tx_count = 1; tx_count < totalframes; tx_count++) {
+				rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+				rem_wifi_send->subtype = tx_count;
+				/* First frame onwards , buf contains only data */
+				memcpy((char*)&rem_wifi_send->data,
+				&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
+				if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
+					rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+					free(rem_wifi_send);
+					return error;
+				}
+				rwl_sleep(RWL_WIFI_SEND_DELAY);
+			}
+
+			/* Check for remaing bytes to send */
+			if ((totalframes*RWL_WIFI_FRAG_DATA_SIZE) != buf_len) {
+				rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+				rem_wifi_send->subtype = tx_count;
+				memcpy((char*)&rem_wifi_send->data,
+				&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE],
+				(buf_len - (tx_count*RWL_WIFI_FRAG_DATA_SIZE)));
+				if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
+					rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+					free(rem_wifi_send);
+					return error;
+				}
+			}
+		} else {
+			/* response fits to single frame */
+			memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
+			(char*)rem_ptr,	REMOTE_SIZE);
+			/* when data_len is 0 , buf will be NULL */
+			if (buf != NULL) {
+				memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE],
+				&buf[0], data_len);
+			}
+			error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
+			RWL_WIFI_ACTION_FRAME_SIZE);
+			free(rem_wifi_send);
+			return error;
+		}
+	}
+#endif /* RWL_WIFI */
+	return (0);
+}
+
+
+rem_ioctl_t *
+remote_CDC_rx_hdr(void *remote, int debug)
+{
+#ifdef RWL_SOCKET
+	int ret;
+#endif /* RWL_SOCKET */
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE) || defined(RWL_SOCKET)
+	uint numread = 0;
+#endif
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+	memset(rem_ptr, 0, sizeof(rem_ioctl_t));
+
+	UNUSED_PARAMETER(remote);
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type)	{
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)
+		case REMOTE_SERIAL:
+		case REMOTE_DONGLE:
+			if (rwl_read_serial_port(remote, (char *)rem_ptr, sizeof(rem_ioctl_t),
+				&numread) < 0) {
+				DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Header Read failed \n");
+				return (NULL);
+			}
+			break;
+#endif /* RWL_SERIAL |  RWL_DONGLE */
+
+
+#ifdef RWL_SOCKET
+		case REMOTE_SOCKET:
+			ret = rwl_receive_from_streamsocket(*(int*)remote, (char *)rem_ptr,
+				sizeof(rem_ioctl_t), 0);
+			numread = ret;
+			if (ret == -1) {
+				DPRINT_ERR(ERR, "remote_CDC_rx_hdr: numread:%d", numread);
+				return (NULL);
+			}
+		if (numread == 0) {
+		      DPRINT_DBG(OUTPUT, "\n remote_CDC_rx_hdr:No data to receive\n");
+			return NULL;
+			}
+			break;
+#endif
+		default:
+			DPRINT_ERR(ERR, "\n Unknown Transport Type\n");
+			break;
+	}
+
+	return (rem_ptr);
+}
+
+/* Return a CDC type buffer */
+int
+remote_CDC_rx(void *wl, rem_ioctl_t *rem_ptr, uchar *readbuf, uint buflen, int debug)
+{
+	uint numread = 0;
+
+#ifdef RWL_SOCKET
+	int ret;
+#endif
+
+#ifdef RWL_WIFI
+	UNUSED_PARAMETER(numread);
+#endif /* RWL_WIFI */
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(readbuf);
+	UNUSED_PARAMETER(buflen);
+	UNUSED_PARAMETER(debug);
+	UNUSED_PARAMETER(numread);
+
+	if (rem_ptr->data_len > rem_ptr->msg.len) {
+		DPRINT_ERR(ERR, "remote_CDC_rx: remote data len (%d) > msg len (%d)\n",
+			rem_ptr->data_len, rem_ptr->msg.len);
+		return (FAIL);
+	}
+
+
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+	if ((remote_type == REMOTE_DONGLE) || (remote_type == REMOTE_SERIAL)) {
+		if (rwl_read_serial_port(wl, (char*)readbuf, rem_ptr->data_len,
+			&numread) < 0) {
+			DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Data Receivefailed \n");
+			return (FAIL);
+		}
+	}
+#endif /* RWL_DONGLE || RWL_SERIAL */
+
+#ifdef RWL_SOCKET
+	if (remote_type == REMOTE_SOCKET) {
+		if (((ret = rwl_receive_from_streamsocket(*(int*)wl, (char*)readbuf,
+		rem_ptr->data_len, 0)) == -1)) {
+				DPRINT_ERR(ERR, "remote_CDC_rx:Data Receive failed\n");
+				return (FAIL);
+		}
+	}
+#endif /* RWL_SOCKET */
+	return (SUCCESS);
+}
+#ifdef RWL_SOCKET
+int
+rwl_sockconnect(int SockDes, struct sockaddr *servAddr, int size)
+{
+	DPRINT_DBG(OUTPUT, "sockconnet SockDes=%d\n", SockDes);
+	if (rwl_connectsocket(SockDes, servAddr, size) < 0) {
+			DPRINT_ERR(ERR, "\n Server is not running\n");
+			return FAIL;
+	}
+	return SUCCESS;
+}
+#endif /* RWL_SOCKET */
+void
+rwl_swap_header(rem_ioctl_t *rem_ptr, bool host_to_network)
+{
+	rem_ptr->msg.cmd = host_to_network?(htol32(rem_ptr->msg.cmd)):(ltoh32(rem_ptr->msg.cmd));
+	rem_ptr->msg.len = host_to_network?(htol32(rem_ptr->msg.len)):(ltoh32(rem_ptr->msg.len));
+	rem_ptr->msg.flags = host_to_network?(htol32(rem_ptr->msg.flags)):
+		(ltoh32(rem_ptr->msg.flags));
+	rem_ptr->msg.status = host_to_network?(htol32(rem_ptr->msg.status)):
+		(ltoh32(rem_ptr->msg.status));
+	rem_ptr->data_len = host_to_network?(htol32(rem_ptr->data_len)):(ltoh32(rem_ptr->data_len));
+}
diff --git a/src/wl/exe/wlu_pipe.h b/src/wl/exe/wlu_pipe.h
new file mode 100644
index 0000000..752b84c
--- /dev/null
+++ b/src/wl/exe/wlu_pipe.h
@@ -0,0 +1,48 @@
+/*
+ * OS independent declarations
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_pipe.h 287128 2011-09-30 04:27:53Z $
+ */
+#ifndef _wlu_pipe_h
+#define _wlu_pipe_h
+
+/* Function prototypes defined in wlu_pipe.c */
+
+/* Macros to access globals */
+extern char *g_rwl_device_name_serial;
+#define rwl_get_serial_port_name()		(g_rwl_device_name_serial)
+#define rwl_set_serial_port_name(name) 	(g_rwl_device_name_serial = name)
+extern char *g_rwl_buf_mac;
+#define rwl_get_wifi_mac()				(g_rwl_buf_mac)
+
+extern int remote_CDC_tx(void *wl, uint cmd, uchar *buf, uint buf_len,
+uint data_len, uint flags, int debug);
+extern rem_ioctl_t *remote_CDC_rx_hdr(void *remote, int debug);
+extern int remote_CDC_rx(void *wl, rem_ioctl_t *rem_ptr, uchar *readbuf, uint buflen, int debug);
+
+extern void* rwl_open_pipe(int remote_type, char *port, int ReadTotalTimeout, int debug);
+extern int rwl_close_pipe(int remote_type, void* hndle);
+
+#ifdef RWL_SOCKET
+extern int rwl_sockconnect(int SockDes, struct sockaddr *servAddr, int size);
+#endif /* RWL_SOCKET */
+
+extern int remote_CDC_DATA_wifi_rx_frag(void *wl, rem_ioctl_t *rem_ptr, uint input_len,
+void *input, bool shell);
+extern int remote_CDC_DATA_wifi_rx(void *wl, struct dot11_action_wifi_vendor_specific *rec_frame);
+extern int
+remote_CDC_wifi_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags);
+extern void rwl_wifi_server_response(void *wl, struct dot11_action_wifi_vendor_specific *rec_frame);
+extern int rwl_find_remote_wifi_server(void *wl, char *id);
+extern void rwl_wifi_purge_actionframes(void *wl);
+extern void rwl_wifi_swap_remote_type(int flag);
+extern void remote_wifi_ser_init_cmds(void *wl);
+#endif /* _wlu_pipe_h */
diff --git a/src/wl/exe/wlu_pipe_linux.c b/src/wl/exe/wlu_pipe_linux.c
new file mode 100644
index 0000000..26a6659
--- /dev/null
+++ b/src/wl/exe/wlu_pipe_linux.c
@@ -0,0 +1,569 @@
+/*
+ * linux version of remote Wl transport mechanisms (pipes).
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_pipe_linux.c 386901 2013-02-22 08:46:40Z $
+ */
+
+/*  Revision History: Linux version of remote Wl transport mechanisms (pipes).
+ *
+ * Date        Author         Description
+ *
+ * 27-Dec-2007 Suganthi        Version 0.0
+ *
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <proto/802.11.h>
+#include <bcmendian.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#include <wlioctl.h>
+#include <typedefs.h>
+#include "wlu_remote.h"
+#include <miniopt.h>
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+#define READ_DELAY 			500000
+#define BAUD_RATE_115200	115200
+#define VMIN_VAL			16
+#define VTIME_VAL			50
+#define LINUX_SYNC_DELAY	200
+extern char  *g_rwl_device_name_serial;
+#endif
+
+#define MICRO_SEC_CONVERTER_VAL		1000
+int g_irh;
+int g_shellsync_pid;
+
+#ifdef RWL_SOCKET
+#define MAX_INTERFACE_NAME	32
+
+static int
+rwl_opensocket(int AddrFamily, int Type, int Protocol)
+{
+	int SockDes;
+
+	if ((SockDes = socket(AddrFamily, Type, Protocol)) == -1) {
+		perror("rwl_opensocket Fails:");
+		DPRINT_ERR(ERR, "\nerrno:%d\n", errno);
+		return FAIL;
+	}
+	return SockDes;
+}
+
+static int
+rwl_set_socket_option(int SocketDes, int Level, int OptName, int Val)
+{
+	if (setsockopt(SocketDes, Level, OptName, &Val, sizeof(int)) == -1) {
+		perror("Error at SetTCPSocketOpt()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/* Function to connect with the server waiting in the same port */
+int
+rwl_connectsocket(int SocketDes, struct sockaddr* SerAddr, int SizeOfAddr)
+{
+	if (connect(SocketDes, SerAddr, SizeOfAddr) == -1) {
+		perror("Failed to connect() to server");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Function for associating a local address with a socket.
+ */
+int
+rwl_bindsocket(int SocketDes, struct sockaddr * MyAddr, int SizeOfAddr)
+{
+	if (bind(SocketDes, MyAddr, SizeOfAddr) == -1) {
+		perror("Error at rwl_bindSocket()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Function for making the socket to listen for incoming connection.
+ */
+int
+rwl_listensocket(int SocketDes, int BackLog)
+{
+	if (listen(SocketDes, BackLog) == -1) {
+		perror("Error at rwl_listensocket()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Function for permitting an incoming connection attempt on a socket
+ * Function  called by server
+ */
+int
+rwl_acceptconnection(int SocketDes, struct sockaddr* ClientAddr, int *SizeOfAddr)
+{
+	int NewSockDes;
+
+	if ((NewSockDes = accept(SocketDes, ClientAddr, (socklen_t*)SizeOfAddr)) == -1) {
+		perror("Error at rwl_acceptConnection()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return NewSockDes;
+}
+
+static int
+rwl_closesocket(int SocketDes)
+{
+	if (close(SocketDes) == -1) {
+		perror("Error at rwl_closeSocket()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/* Transmit the response in the opened TCP stream socket */
+int
+rwl_send_to_streamsocket(int SocketDes, const char* SendBuff, int data_size, int Flag)
+{
+	int total_numwritten = 0,  numwritten = 0;
+	while (total_numwritten < data_size) {
+		if ((numwritten = send(SocketDes, SendBuff,
+			data_size - total_numwritten, Flag)) == -1) {
+			perror("Failed to send()");
+			DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+			return (FAIL);
+		}
+
+		/* Sent successfully at first attempt no more retries */
+		if (numwritten == data_size) {
+			total_numwritten = numwritten;
+			break;
+		}
+
+		/* If socket is busy we may hit this condition */
+		if (numwritten != data_size - total_numwritten) {
+			DPRINT_DBG(OUTPUT, "wanted to send %d bytes sent only %d bytes\n",
+				data_size - total_numwritten, numwritten);
+		}
+
+		/* Now send the remaining buffer */
+		total_numwritten += numwritten;
+		SendBuff += numwritten;
+	}
+
+	return total_numwritten;
+}
+
+/* Receive the response from the opened TCP stream socket */
+int
+rwl_receive_from_streamsocket(int SocketDes, char* RecvBuff, int data_size, int Flag)
+{
+	int numread;
+	int total_numread = 0;
+
+	while (total_numread < data_size) {
+		if ((numread = recv(SocketDes, RecvBuff, data_size - total_numread, Flag)) == -1) {
+			perror("Failed to Receive()");
+			DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+			return FAIL;
+		}
+
+		if (numread != data_size - total_numread) {
+			DPRINT_DBG(OUTPUT, "asked %d bytes got %d bytes\n",
+				data_size - total_numread, numread);
+		}
+
+		if (numread == 0)
+			break;
+
+		total_numread += numread;
+		RecvBuff += numread;
+	}
+
+	return numread;
+}
+
+
+int
+rwl_init_server_socket_setup(int argc, char** argv, uint remote_type)
+{
+	char netif[MAX_INTERFACE_NAME];
+	unsigned short servPort;
+	struct sockaddr_in ServerAddress;
+	int err, SockDes, val;
+
+	/* Default option */
+	servPort = DEFAULT_SERVER_PORT;
+
+	strcpy(netif, "eth0");
+
+	/* User option can override default arguments */
+	if (argc == 3) {
+		argv++;
+
+		if (isalpha(**argv) == FALSE) {
+			DPRINT_ERR(ERR, "USAGE ERROR:Incorrect network interface\n");
+			return FAIL;
+		}
+		strcpy(netif, *argv);
+		argv++;
+
+		if (isdigit(**argv) == FALSE) {
+			DPRINT_ERR(ERR, "USAGE ERROR:Incorrect port\n");
+			return FAIL;
+		}
+		servPort = atoi(*argv);
+	}
+
+	if (argc == 2) {
+		argv++;
+
+		if (isalpha(**argv) == FALSE) {
+			if (isdigit(**argv) == FALSE) {
+				DPRINT_ERR(ERR, "USAGE ERROR\n");
+				return FAIL;
+			}
+			else
+				servPort = atoi(*argv);
+		}
+		else
+			strcpy(netif, *argv);
+	}
+
+	DPRINT_INFO(OUTPUT, "INFO: Network Interface:%s, Port:%d\n",
+		netif, servPort);
+
+	if ((SockDes = (*(int *)rwl_open_transport(remote_type, NULL, 0, 0))) == FAIL)
+	   return FAIL;
+
+	val = 1;
+	if ((rwl_set_socket_option(SockDes, SOL_SOCKET, SO_REUSEADDR, val)) == FAIL)
+		return FAIL;
+
+	memset(&ServerAddress, 0, sizeof(ServerAddress));
+
+	rwl_GetifAddr(netif, &ServerAddress);
+	ServerAddress.sin_family = AF_INET; /* host byte order */
+	ServerAddress.sin_port = hton16(servPort); /* short, network byte order */
+
+	if (((err = rwl_bindsocket(SockDes, (struct sockaddr *)&ServerAddress,
+	sizeof(ServerAddress))) == FAIL))
+		return err;
+	if ((err = rwl_listensocket(SockDes, BACKLOG)) == FAIL)
+		return err;
+
+	DPRINT_DBG(OUTPUT, "Waiting for client to connect...\n");
+
+	return SockDes;
+}
+
+int rwl_GetifAddr(char *ifname, struct sockaddr_in *sa)
+{
+	struct ifreq ifr;
+	int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+
+	if (fd < 0)
+	{
+	   DPRINT_ERR(ERR, "socket open error\n");
+	   return FAIL;
+	}
+
+	strcpy(ifr.ifr_name, ifname);
+	ifr.ifr_addr.sa_family = AF_INET;
+	if (ioctl(fd, SIOCGIFADDR, &ifr) == 0)
+	{
+		 memcpy(sa, (struct sockaddr_in *)&ifr.ifr_addr, sizeof(struct sockaddr_in));
+	         close(fd);
+		 return SUCCESS;
+	}
+	close(fd);
+	return FAIL;
+}
+#endif /* RWL_SOCKET */
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)
+static int
+rwl_open_serial(int remote_type, char *port)
+{
+	struct termios tio;
+	int fCom;
+	int speed;
+	long BAUD, DATABITS, STOPBITS, PARITYON;
+	speed_t baud_rate;
+
+	DPRINT_DBG(OUTPUT, "\n rwl_open_serial:%s\n", port);
+	if (remote_type == REMOTE_DONGLE)
+		fCom = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
+	else
+		fCom = open(port, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC);
+	if (fCom < 0) {
+		DPRINT_ERR(ERR, "open COM failed with error %d.\n", errno);
+		return fCom;
+	} else {
+		/* To make the read as a blocking operation */
+		fcntl(fCom, F_SETFL, 0);
+	}
+
+	bzero(&tio, sizeof(tio));
+	/* Get the current option for the port... */
+	tcgetattr(fCom, &tio);
+	/* Set the baud rate */
+	cfsetispeed(&tio, B115200);
+	cfsetospeed(&tio, B115200);
+	if (remote_type == REMOTE_DONGLE) {
+		if (tcsetattr(fCom, TCSANOW, &tio) < 0) {
+			perror("tcsetattr:setspeed");
+			return FAIL;
+		}
+
+		baud_rate = cfgetospeed(&tio);
+		if (baud_rate == B115200)
+			speed = BAUD_RATE_115200;
+		DPRINT_DBG(OUTPUT, "Baud_rate set is:%d\n", speed);
+
+		BAUD = B115200;
+		DATABITS = CS8;
+		STOPBITS = 1;
+		PARITYON = 0;
+
+		tio.c_cflag = BAUD |  DATABITS | STOPBITS | PARITYON | CLOCAL | CREAD;
+		tio.c_iflag = IGNPAR;
+		tio.c_oflag = 0;
+		tio.c_lflag = 0;
+		tio.c_cc[VMIN] = VMIN_VAL;
+		tio.c_cc[VTIME] = VTIME_VAL;
+
+		tcflush(fCom, TCIOFLUSH);
+		if (tcsetattr(fCom, TCSANOW, &tio) < 0) {
+			perror("tcsetattr:");
+			return FAIL;
+		}
+
+		if (tcgetattr(fCom, &tio) < 0) {
+			perror("tcgetattr:");
+			return FAIL;
+		}
+
+		DPRINT_DBG(OUTPUT, "tcgetattr:VMIN is:%d\n", tio.c_cc[VMIN]);
+		DPRINT_DBG(OUTPUT, "tcgetattr:VTIME is:%d\n", tio.c_cc[VTIME]);
+		tcflush(fCom, TCIOFLUSH);
+	}
+	else {
+		UNUSED_PARAMETER(PARITYON);
+		UNUSED_PARAMETER(STOPBITS);
+		UNUSED_PARAMETER(DATABITS);
+		UNUSED_PARAMETER(BAUD);
+		UNUSED_PARAMETER(baud_rate);
+		UNUSED_PARAMETER(speed);
+
+		/* Enable the receiver and set local mode  */
+		tio.c_cflag |= (CLOCAL | CREAD);
+
+		tio.c_cflag &= ~PARENB;
+		tio.c_cflag &= ~CSTOPB;
+		tio.c_cflag &= ~CSIZE;
+		tio.c_cflag |= CS8;
+		tio.c_cc[VTIME] = 255;
+		tio.c_cc[VMIN] = 1;
+
+		tio.c_iflag = 0;
+		tio.c_iflag  |= IGNBRK;
+
+		tio.c_oflag  &= ~OPOST;
+		tio.c_oflag  &= ~OLCUC;
+		tio.c_oflag  &= ~ONLCR;
+		tio.c_oflag  &= ~OCRNL;
+		tio.c_oflag  &= ~ONOCR;
+		tio.c_oflag  &= ~ONLRET;
+		tio.c_oflag  &= ~OFILL;
+
+		tio.c_lflag &= ~ICANON;
+		tio.c_lflag &= ~ISIG;
+		tio.c_lflag &= ~XCASE;
+		tio.c_lflag &= ~ECHO;
+		tio.c_lflag &= ~FLUSHO;
+		tio.c_lflag &= ~IEXTEN;
+		tio.c_lflag |= NOFLSH;
+		/* Set the new tio for the port... */
+		tcsetattr(fCom, TCSANOW, &tio);
+		tcflush(fCom, TCIOFLUSH);
+	}
+	return (fCom);
+}
+int
+rwl_write_serial_port(void* hndle, char* write_buf, unsigned long size, unsigned long *numwritten)
+{
+	int ret;
+
+	ret = write((*(int *)hndle), (const void*)write_buf, size);
+	*numwritten = ret;
+	if (ret == -1) {
+		perror("WriteToPort Failed");
+		DPRINT_ERR(ERR, "Errno:%d\n", errno);
+		return FAIL;
+	}
+	if (*numwritten != size) {
+		DPRINT_ERR(ERR, "rwl_write_serial_port failed numwritten %ld != len %ld\n",
+		*numwritten, size);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+int
+rwl_read_serial_port(void* hndle, char* read_buf, uint data_size, uint *numread)
+{
+	int ret;
+	uint total_numread = 0;
+	while (total_numread < data_size) {
+		ret = read(*(int *)hndle, read_buf, data_size - total_numread);
+		*numread = ret;
+		if (ret == -1) {
+
+			perror("ReadFromPort Failed");
+			DPRINT_ERR(ERR, "Errno:%d\n", errno);
+			return FAIL;
+		}
+		if (*numread != data_size - total_numread) {
+			DPRINT_DBG(OUTPUT, "asked for %d bytes got %d bytes\n",
+			data_size - total_numread, *numread);
+		}
+		if (*numread == 0)
+			break;
+
+		total_numread += *numread;
+		read_buf += *numread;
+	}
+	return SUCCESS;
+}
+
+void
+rwl_sync_delay(uint noframes)
+{
+	if (noframes > 1) {
+		rwl_sleep(LINUX_SYNC_DELAY);
+	}
+}
+
+#endif /* RWL_DONGLE ||RWL_SERIAL */
+
+#if defined(RWL_DONGLE) || defined(RWL_SOCKET) || defined(RWL_SERIAL)
+void*
+rwl_open_transport(int remote_type, char *port, int ReadTotalTimeout, int debug)
+{
+	void* hndle;
+
+	UNUSED_PARAMETER(port);
+	UNUSED_PARAMETER(ReadTotalTimeout);
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type) {
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+	case REMOTE_SERIAL:
+#ifdef RWL_SERIAL
+			g_rwl_device_name_serial = port;
+#endif
+	case REMOTE_DONGLE:
+			if ((g_irh = rwl_open_serial(remote_type, g_rwl_device_name_serial))
+				 == FAIL) {
+			/* Initial port opening settings failed in reboot.
+			 * So retry opening the serial port
+			 */
+				if ((g_irh = rwl_open_serial(remote_type, g_rwl_device_name_serial))
+					 == FAIL) {
+					DPRINT_ERR(ERR, "Can't open serial port\n");
+					return NULL;
+				}
+			}
+			break;
+#endif /* RWL_DONGLE || RWL_SERIAL */
+
+#ifdef RWL_SOCKET
+		case REMOTE_SOCKET:
+			if ((g_irh = rwl_opensocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == FAIL) {
+				DPRINT_ERR(ERR, "\nCan't open socket \n");
+				return NULL;
+			}
+
+			break;
+#endif /* RWL_SOCKET */
+
+		default:
+		DPRINT_ERR(ERR, "rwl_open_transport: Unknown remote_type %d\n", remote_type);
+		return NULL;
+		break;
+	} /* end - switch case */
+
+	hndle = (void*) &g_irh;
+	return hndle;
+}
+
+int
+rwl_close_transport(int remote_type, void* Des)
+{
+	switch (remote_type) {
+#ifdef RWL_SOCKET
+		case REMOTE_SOCKET:
+			if (rwl_closesocket(*(int *)Des) == FAIL)
+				return FAIL;
+		break;
+#endif /* RWL_SOCKET */
+
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+	case REMOTE_DONGLE:
+	case REMOTE_SERIAL:
+			if (close(*(int *)Des) == -1)
+				return FAIL;
+		break;
+#endif /* RWL_DONGLE || RWL_SERIAL */
+
+		default:
+			DPRINT_ERR(ERR, "close_pipe: Unknown remote_type %d\n", remote_type);
+		break;
+	}
+	return SUCCESS;
+}
+#endif /* #if defined (RWL_DONGLE) || defined (RWL_SOCKET) */
+
+void
+rwl_sleep(int delay)
+{
+	usleep(delay * MICRO_SEC_CONVERTER_VAL);
+}
+
+#if defined(WLMSO)
+int
+rwl_init_socket(void)
+{
+	return 0;
+}
+#endif
diff --git a/src/wl/exe/wlu_rates_matrix.c b/src/wl/exe/wlu_rates_matrix.c
new file mode 100644
index 0000000..a44f5d1
--- /dev/null
+++ b/src/wl/exe/wlu_rates_matrix.c
@@ -0,0 +1,740 @@
+/*
+ * This module does provides various mappings to or from the CLM rate indexes.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ */
+/*FILE-CSTYLED*/
+
+#include <stdio.h>
+#include <typedefs.h>
+
+#include "wlu_rates_matrix.h"
+
+#define CLM_NO_RATE_STRING "NO_RATE"
+#define EXP_MODE_UNKNOWN   "Unknown expansion mode"
+#define AUTO_RATESPEC 0x0
+#define MHZ_TO_HALF_MHZ 2
+
+typedef enum exp_mode {
+	EXP_MODE_ID_DEF = 0,
+	EXP_MODE_ID_STBC,
+	EXP_MODE_ID_TXBF,
+	EXP_MODE_ID_MAX
+} exp_mode_t;
+
+static reg_rate_index_t get_legacy_reg_rate_index(int rate_hmhz, int tx_expansion, exp_mode_t mode);
+static reg_rate_index_t get_ht_reg_rate_index(int mcs, int tx_expansion, exp_mode_t mode);
+static reg_rate_index_t get_vht_reg_rate_index(int mcs, int nss, int tx_expansion, exp_mode_t mode);
+static int get_legacy_rate_identifier(int rate_hmhz);
+static int get_legacy_mode_identifier(int tx_expansion, exp_mode_t mode);
+static int get_vht_rate_identifier(int vht_mcs_index);
+static int get_vht_ss1_mode_identifier(int tx_expansion, exp_mode_t mode);
+static int get_vht_ss2_mode_identifier(int tx_expansion, exp_mode_t mode);
+static int get_vht_ss3_mode_identifier(int tx_expansion, exp_mode_t mode);
+static const char *get_mode_name(exp_mode_t mode);
+
+enum {
+	LEGACY_RATE_ID_NO_RATE = -1,
+	LEGACY_RATE_ID_1MHZ = 0,
+	LEGACY_RATE_ID_2MHZ,
+	LEGACY_RATE_ID_5_5MHZ,
+	LEGACY_RATE_ID_11MHZ,
+	LEGACY_RATE_ID_6MHZ,
+	LEGACY_RATE_ID_9MHZ,
+	LEGACY_RATE_ID_12MHZ,
+	LEGACY_RATE_ID_18MHZ,
+	LEGACY_RATE_ID_24MHZ,
+	LEGACY_RATE_ID_36MHZ,
+	LEGACY_RATE_ID_48MHZ,
+	LEGACY_RATE_ID_54MHZ,
+	LEGACY_RATE_ID_MAX
+};
+
+enum {
+	LEGACY_MODE_ID_NONE = 0,
+	LEGACY_MODE_ID_TXEXP1,
+	LEGACY_MODE_ID_TXEXP2,
+	LEGACY_MODE_ID_TXBF1,
+	LEGACY_MODE_ID_TXBF2,
+	LEGACY_MODE_ID_MAX
+};
+
+enum {
+	VHT_RATE_INDEX_0 = 0,
+	VHT_RATE_INDEX_1,
+	VHT_RATE_INDEX_2,
+	VHT_RATE_INDEX_3,
+	VHT_RATE_INDEX_4,
+	VHT_RATE_INDEX_5,
+	VHT_RATE_INDEX_6,
+	VHT_RATE_INDEX_7,
+	VHT_RATE_INDEX_8,
+	VHT_RATE_INDEX_9,
+	VHT_RATE_INDEX_MAX
+};
+
+enum {
+	VHT_SS1_MODE_ID_NONE = 0,
+	VHT_SS1_MODE_ID_CDD1,
+	VHT_SS1_MODE_ID_STBC,
+	VHT_SS1_MODE_ID_CDD2,
+	VHT_SS1_MODE_ID_STBC_SPEXP1,
+	VHT_SS1_MODE_ID_TXBF1,
+	VHT_SS1_MODE_ID_TXBF2,
+	VHT_SS1_MODE_ID_MAX
+};
+
+enum {
+	VHT_SS2_MODE_ID_NONE = 0,
+	VHT_SS2_MODE_ID_SPEXP1,
+	VHT_SS2_MODE_ID_TXBF0,
+	VHT_SS2_MODE_ID_TXBF1,
+	VHT_SS2_MODE_ID_MAX
+};
+
+enum {
+	VHT_SS3_MODE_ID_NONE = 0,
+	VHT_SS3_MODE_ID_TXBF0,
+	VHT_SS3_MODE_ID_MAX
+};
+
+const char *clm_rate_group_labels[] = {
+	"DSSS",
+	"OFDM",
+	"MCS0_7",
+	"VHT8_9SS1",
+	"DSSS_MULTI1",
+	"OFDM_CDD1",
+	"MCS0_7_CDD1",
+	"VHT8_9SS1_CDD1",
+	"MCS0_7_STBC",
+	"VHT8_9SS1_STBC",
+	"MCS8_15",
+	"VHT8_9SS2",
+	"DSSS_MULTI2",
+	"OFDM_CDD2",
+	"MCS0_7_CDD2",
+	"VHT8_9SS1_CDD2",
+	"MCS0_7_STBC_SPEXP1",
+	"VHT8_9SS1_STBC_SPEXP1",
+	"MCS8_15_SPEXP1",
+	"VHT8_9SS2_SPEXP1",
+	"MCS16_23",
+	"VHT8_9SS3",
+	"OFDM_TXBF1",
+	"MCS0_7_TXBF1",
+	"VHT8_9SS1_TXBF1",
+	"MCS8_15_TXBF0",
+	"OFDM_TXBF2",
+	"MCS0_7_TXBF2",
+	"VHT8_9SS1_TXBF2",
+	"MCS8_15_TXBF1",
+	"VHT8_9SS2_TXBF1",
+	"MCS16_23_TXBF0",
+};
+
+
+const char *clm_rate_labels[] = {
+	"DSSS1",
+	"DSSS2",
+	"DSSS5",
+	"DSSS11",
+	"OFDM6",
+	"OFDM9",
+	"OFDM12",
+	"OFDM18",
+	"OFDM24",
+	"OFDM36",
+	"OFDM48",
+	"OFDM54",
+	"MCS0",
+	"MCS1",
+	"MCS2",
+	"MCS3",
+	"MCS4",
+	"MCS5",
+	"MCS6",
+	"MCS7",
+	"VHT8SS1",
+	"VHT9SS1",
+	"DSSS1_MULTI1",
+	"DSSS2_MULTI1",
+	"DSSS5_MULTI1",
+	"DSSS11_MULTI1",
+	"OFDM6_CDD1",
+	"OFDM9_CDD1",
+	"OFDM12_CDD1",
+	"OFDM18_CDD1",
+	"OFDM24_CDD1",
+	"OFDM36_CDD1",
+	"OFDM48_CDD1",
+	"OFDM54_CDD1",
+	"MCS0_CDD1",
+	"MCS1_CDD1",
+	"MCS2_CDD1",
+	"MCS3_CDD1",
+	"MCS4_CDD1",
+	"MCS5_CDD1",
+	"MCS6_CDD1",
+	"MCS7_CDD1",
+	"VHT8SS1_CDD1",
+	"VHT9SS1_CDD1",
+	"MCS0_STBC",
+	"MCS1_STBC",
+	"MCS2_STBC",
+	"MCS3_STBC",
+	"MCS4_STBC",
+	"MCS5_STBC",
+	"MCS6_STBC",
+	"MCS7_STBC",
+	"VHT8SS1_STBC",
+	"VHT9SS1_STBC",
+	"MCS8",
+	"MCS9",
+	"MCS10",
+	"MCS11",
+	"MCS12",
+	"MCS13",
+	"MCS14",
+	"MCS15",
+	"VHT8SS2",
+	"VHT9SS2",
+	"DSSS1_MULTI2",
+	"DSSS2_MULTI2",
+	"DSSS5_MULTI2",
+	"DSSS11_MULTI2",
+	"OFDM6_CDD2",
+	"OFDM9_CDD2",
+	"OFDM12_CDD2",
+	"OFDM18_CDD2",
+	"OFDM24_CDD2",
+	"OFDM36_CDD2",
+	"OFDM48_CDD2",
+	"OFDM54_CDD2",
+	"MCS0_CDD2",
+	"MCS1_CDD2",
+	"MCS2_CDD2",
+	"MCS3_CDD2",
+	"MCS4_CDD2",
+	"MCS5_CDD2",
+	"MCS6_CDD2",
+	"MCS7_CDD2",
+	"VHT8SS1_CDD2",
+	"VHT9SS1_CDD2",
+	"MCS0_STBC_SPEXP1",
+	"MCS1_STBC_SPEXP1",
+	"MCS2_STBC_SPEXP1",
+	"MCS3_STBC_SPEXP1",
+	"MCS4_STBC_SPEXP1",
+	"MCS5_STBC_SPEXP1",
+	"MCS6_STBC_SPEXP1",
+	"MCS7_STBC_SPEXP1",
+	"VHT8SS1_STBC_SPEXP1",
+	"VHT9SS1_STBC_SPEXP1",
+	"MCS8_SPEXP1",
+	"MCS9_SPEXP1",
+	"MCS10_SPEXP1",
+	"MCS11_SPEXP1",
+	"MCS12_SPEXP1",
+	"MCS13_SPEXP1",
+	"MCS14_SPEXP1",
+	"MCS15_SPEXP1",
+	"VHT8SS2_SPEXP1",
+	"VHT9SS2_SPEXP1",
+	"MCS16",
+	"MCS17",
+	"MCS18",
+	"MCS19",
+	"MCS20",
+	"MCS21",
+	"MCS22",
+	"MCS23",
+	"VHT8SS3",
+	"VHT9SS3",
+	"OFDM6_TXBF1",
+	"OFDM9_TXBF1",
+	"OFDM12_TXBF1",
+	"OFDM18_TXBF1",
+	"OFDM24_TXBF1",
+	"OFDM36_TXBF1",
+	"OFDM48_TXBF1",
+	"OFDM54_TXBF1",
+	"MCS0_TXBF1",
+	"MCS1_TXBF1",
+	"MCS2_TXBF1",
+	"MCS3_TXBF1",
+	"MCS4_TXBF1",
+	"MCS5_TXBF1",
+	"MCS6_TXBF1",
+	"MCS7_TXBF1",
+	"VHT8SS1_TXBF1",
+	"VHT9SS1_TXBF1",
+	"MCS8_TXBF0",
+	"MCS9_TXBF0",
+	"MCS10_TXBF0",
+	"MCS11_TXBF0",
+	"MCS12_TXBF0",
+	"MCS13_TXBF0",
+	"MCS14_TXBF0",
+	"MCS15_TXBF0",
+	"OFDM6_TXBF2",
+	"OFDM9_TXBF2",
+	"OFDM12_TXBF2",
+	"OFDM18_TXBF2",
+	"OFDM24_TXBF2",
+	"OFDM36_TXBF2",
+	"OFDM48_TXBF2",
+	"OFDM54_TXBF2",
+	"MCS0_TXBF2",
+	"MCS1_TXBF2",
+	"MCS2_TXBF2",
+	"MCS3_TXBF2",
+	"MCS4_TXBF2",
+	"MCS5_TXBF2",
+	"MCS6_TXBF2",
+	"MCS7_TXBF2",
+	"VHT8SS1_TXBF2",
+	"VHT9SS1_TXBF2",
+	"MCS8_TXBF1",
+	"MCS9_TXBF1",
+	"MCS10_TXBF1",
+	"MCS11_TXBF1",
+	"MCS12_TXBF1",
+	"MCS13_TXBF1",
+	"MCS14_TXBF1",
+	"MCS15_TXBF1",
+	"VHT8SS2_TXBF1",
+	"VHT9SS2_TXBF1",
+	"MCS16_TXBF0",
+	"MCS17_TXBF0",
+	"MCS18_TXBF0",
+	"MCS19_TXBF0",
+	"MCS20_TXBF0",
+	"MCS21_TXBF0",
+	"MCS22_TXBF0",
+	"MCS23_TXBF0",
+};
+
+int legacy_reg_rate_map[LEGACY_RATE_ID_MAX][LEGACY_MODE_ID_MAX] = {
+	{DSSS1,  DSSS1_MULTI1,  DSSS1_MULTI2, NO_RATE,       NO_RATE},
+	{DSSS2,  DSSS2_MULTI1,  DSSS2_MULTI2, NO_RATE,       NO_RATE},
+	{DSSS5,  DSSS5_MULTI1,  DSSS5_MULTI2, NO_RATE,       NO_RATE},
+	{DSSS11, DSSS11_MULTI1, DSSS11_MULTI2,NO_RATE,       NO_RATE},
+	{OFDM6,  OFDM6_CDD1,    OFDM6_CDD2,   OFDM6_TXBF1,   OFDM6_TXBF2},
+	{OFDM9,  OFDM9_CDD1,    OFDM9_CDD2,   OFDM9_TXBF1,   OFDM9_TXBF2},
+	{OFDM12, OFDM12_CDD1,   OFDM12_CDD2,  OFDM12_TXBF1,  OFDM12_TXBF2},
+	{OFDM18, OFDM18_CDD1,   OFDM18_CDD2,  OFDM18_TXBF1,  OFDM18_TXBF2},
+	{OFDM24, OFDM24_CDD1,   OFDM24_CDD2,  OFDM24_TXBF1,  OFDM24_TXBF2},
+	{OFDM36, OFDM36_CDD1,   OFDM36_CDD2,  OFDM36_TXBF1,  OFDM36_TXBF2},
+	{OFDM48, OFDM48_CDD1,   OFDM48_CDD2,  OFDM48_TXBF1,  OFDM48_TXBF2},
+	{OFDM54, OFDM54_CDD1,   OFDM54_CDD2,  OFDM54_TXBF1,  OFDM54_TXBF2}
+};
+
+int vht_ss1_reg_rate_map[VHT_RATE_INDEX_MAX][VHT_SS1_MODE_ID_MAX] = {
+	{MCS0,    MCS0_CDD1,    MCS0_STBC,    MCS0_CDD2,    MCS0_STBC_SPEXP1,  MCS0_TXBF1,  MCS0_TXBF2},
+	{MCS1,    MCS1_CDD1,    MCS1_STBC,    MCS1_CDD2,    MCS1_STBC_SPEXP1,  MCS1_TXBF1,  MCS1_TXBF2},
+	{MCS2,    MCS2_CDD1,    MCS2_STBC,    MCS2_CDD2,    MCS2_STBC_SPEXP1,  MCS2_TXBF1,  MCS2_TXBF2},
+	{MCS3,    MCS3_CDD1,    MCS3_STBC,    MCS3_CDD2,    MCS3_STBC_SPEXP1,  MCS3_TXBF1,  MCS3_TXBF2},
+	{MCS4,    MCS4_CDD1,    MCS4_STBC,    MCS4_CDD2,    MCS4_STBC_SPEXP1,  MCS4_TXBF1,  MCS4_TXBF2},
+	{MCS5,    MCS5_CDD1,    MCS5_STBC,    MCS5_CDD2,    MCS5_STBC_SPEXP1,  MCS5_TXBF1,  MCS5_TXBF2},
+	{MCS6,    MCS6_CDD1,    MCS6_STBC,    MCS6_CDD2,    MCS6_STBC_SPEXP1,  MCS6_TXBF1,  MCS6_TXBF2},
+	{MCS7,    MCS7_CDD1,    MCS7_STBC,    MCS7_CDD2,    MCS7_STBC_SPEXP1,  MCS7_TXBF1,  MCS7_TXBF2},
+	{VHT8SS1, VHT8SS1_CDD1, VHT8SS1_STBC, VHT8SS1_CDD2, VHT8SS1_STBC_SPEXP1,VHT8SS1_TXBF1, VHT8SS1_TXBF2},
+	{VHT9SS1, VHT9SS1_CDD1, VHT9SS1_STBC, VHT9SS1_CDD2, VHT9SS1_STBC_SPEXP1,VHT9SS1_TXBF1, VHT9SS1_TXBF2}
+};
+
+int vht_ss2_reg_rate_map[VHT_RATE_INDEX_MAX][VHT_SS2_MODE_ID_MAX] = {
+	{MCS8,    MCS8_SPEXP1,   MCS8_TXBF0,     MCS8_TXBF1},
+	{MCS9,    MCS9_SPEXP1,   MCS9_TXBF0,     MCS9_TXBF1},
+	{MCS10,   MCS10_SPEXP1,  MCS10_TXBF0,    MCS10_TXBF1},
+	{MCS11,   MCS11_SPEXP1,  MCS11_TXBF0,    MCS11_TXBF1},
+	{MCS12,   MCS12_SPEXP1,  MCS12_TXBF0,    MCS12_TXBF1},
+	{MCS13,   MCS13_SPEXP1,  MCS13_TXBF0,    MCS13_TXBF1},
+	{MCS14,   MCS14_SPEXP1,  MCS14_TXBF0,    MCS14_TXBF1},
+	{MCS15,   MCS15_SPEXP1,  MCS15_TXBF0,    MCS15_TXBF1},
+	{VHT8SS2, VHT8SS2_SPEXP1,NO_RATE,        VHT8SS2_TXBF1},
+	{VHT9SS2, VHT9SS2_SPEXP1,NO_RATE,        VHT8SS2_TXBF1}
+};
+
+int vht_ss3_reg_rate_map[VHT_RATE_INDEX_MAX][VHT_SS3_MODE_ID_MAX] = {
+	{MCS16,      MCS16_TXBF0},
+	{MCS17,      MCS17_TXBF0},
+	{MCS18,      MCS18_TXBF0},
+	{MCS19,      MCS19_TXBF0},
+	{MCS20,      MCS20_TXBF0},
+	{MCS21,      MCS21_TXBF0},
+	{MCS22,      MCS22_TXBF0},
+	{MCS23,      MCS23_TXBF0},
+	{VHT8SS3,    NO_RATE},
+	{VHT9SS3,    NO_RATE}
+};
+
+const char *exp_mode_name[EXP_MODE_ID_MAX] = {
+	"CDD",
+	"STBC",
+	"TXBF"
+};
+
+const char *
+get_clm_rate_group_label(int rategroup)
+{
+	return clm_rate_group_labels[rategroup];
+}
+
+const char *
+get_reg_rate_string_from_ratespec(int ratespec)
+{
+	reg_rate_index_t index = get_reg_rate_index_from_ratespec(ratespec);
+
+	if (index >= 0)
+	{
+		return clm_rate_labels[index];
+	}
+	return CLM_NO_RATE_STRING;
+}
+
+reg_rate_index_t
+get_reg_rate_index_from_ratespec(int ratespec)
+{
+	uint encode, rate, txexp;
+	bool stbc,txbf;
+	int rate_index = NO_RATE;
+	exp_mode_t expmode = EXP_MODE_ID_DEF;
+
+	/* If auto is set, we don't get a ratespec that can be decoded */
+	if (ratespec == AUTO_RATESPEC)
+		return rate_index;
+
+	encode = (ratespec & WL_RSPEC_ENCODING_MASK);
+	rate   = (ratespec & WL_RSPEC_RATE_MASK);
+	txexp  = (ratespec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
+	stbc   = (ratespec & WL_RSPEC_STBC) != 0;
+	txbf   = (ratespec & WL_RSPEC_TXBF) != 0;
+
+	if (stbc && txbf) {
+		return rate_index;
+	} else if (txbf) {
+		expmode = EXP_MODE_ID_TXBF;
+	} else if (stbc) {
+		expmode = EXP_MODE_ID_STBC;
+	}
+
+	if (encode == WL_RSPEC_ENCODE_RATE) {
+		rate_index = get_legacy_reg_rate_index(rate, txexp, expmode);
+	} else if (encode == WL_RSPEC_ENCODE_HT) {
+		rate_index = get_ht_reg_rate_index(rate, txexp, expmode);
+	} else if (encode == WL_RSPEC_ENCODE_VHT) {
+		uint mcs = (ratespec & WL_RSPEC_VHT_MCS_MASK);
+		uint nss = (ratespec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+		rate_index = get_vht_reg_rate_index(mcs, nss, txexp, expmode);
+	}
+
+	return rate_index;
+}
+
+reg_rate_index_t
+get_legacy_reg_rate_index(int rate_hmhz, int tx_expansion, exp_mode_t expmode)
+{
+	reg_rate_index_t index = NO_RATE;
+	int rate_id;
+	rate_id = get_legacy_rate_identifier(rate_hmhz);
+	if (rate_id == LEGACY_RATE_ID_NO_RATE || (expmode == EXP_MODE_ID_TXBF && rate_id < LEGACY_RATE_ID_6MHZ))
+	{
+		fprintf(stderr, "ERROR: Bad legacy rate spec: %d\n", rate_hmhz);
+	}
+	else
+	{
+		index = legacy_reg_rate_map[rate_id][get_legacy_mode_identifier(tx_expansion, expmode)];
+	}
+	return index;
+}
+
+static int get_legacy_rate_identifier(int rate_hmhz)
+{
+	int rate_lut[LEGACY_RATE_ID_MAX];
+	int rate_index = LEGACY_RATE_ID_NO_RATE;
+	int i;
+
+	rate_lut[LEGACY_RATE_ID_1MHZ]   = 1 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_2MHZ]   = 2 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_5_5MHZ] = 11; /* 5.5 * MHZ_TO_HALF_MHZ */
+	rate_lut[LEGACY_RATE_ID_11MHZ]  = 11 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_6MHZ]   = 6 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_9MHZ]   = 9 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_12MHZ]  = 12 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_18MHZ]  = 18 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_24MHZ]  = 24 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_36MHZ]  = 36 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_48MHZ]  = 48 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_54MHZ]  = 54 * MHZ_TO_HALF_MHZ;
+
+	for (i = 0; i < LEGACY_RATE_ID_MAX; i++)
+	{
+		if (rate_lut[i] == rate_hmhz)
+		{
+			rate_index = i;
+			break;
+		}
+	}
+
+	return rate_index;
+}
+
+static int get_legacy_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		mode_identifier = LEGACY_MODE_ID_NONE;
+	}
+	else if (tx_expansion == 1)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = LEGACY_MODE_ID_TXEXP1;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = LEGACY_MODE_ID_TXBF1;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad legacy tx_expansion spec: %d expansion mode %s\n",
+				 tx_expansion, get_mode_name(expmode));
+			break;
+		}
+	}
+	else if (tx_expansion == 2)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = LEGACY_MODE_ID_TXEXP2;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = LEGACY_MODE_ID_TXBF2;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad legacy tx_expansion spec: %d expansion mode %s\n",
+				 tx_expansion, get_mode_name(expmode));
+			break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad legacy tx_expansion spec: %d expansion mode %s\n", tx_expansion,
+				get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+reg_rate_index_t
+get_ht_reg_rate_index(int mcs, int tx_expansion, exp_mode_t expmode)
+{
+	reg_rate_index_t rate_index = NO_RATE;
+	int vht_mcs, nss;
+
+	if (mcs > 23)
+	{
+		fprintf(stderr, "ERROR: Bad ht mcs spec: %d\n", mcs);
+	}
+	else
+	{
+		vht_mcs = mcs % 8;
+		nss = (mcs / 8) + 1;
+
+		rate_index = get_vht_reg_rate_index(vht_mcs, nss, tx_expansion, expmode);
+	}
+
+	return rate_index;
+}
+
+reg_rate_index_t
+get_vht_reg_rate_index(int mcs, int nss, int tx_expansion, exp_mode_t expmode)
+{
+	reg_rate_index_t rate_index = NO_RATE;
+	int rate_id = get_vht_rate_identifier(mcs);
+
+	if (nss == 1)
+	{
+		rate_index = vht_ss1_reg_rate_map[rate_id][get_vht_ss1_mode_identifier(tx_expansion, expmode)];
+	}
+	else if (nss == 2)
+	{
+		rate_index = vht_ss2_reg_rate_map[rate_id][get_vht_ss2_mode_identifier(tx_expansion, expmode)];
+	}
+	else if (nss == 3)
+	{
+		rate_index = vht_ss3_reg_rate_map[rate_id][get_vht_ss3_mode_identifier(tx_expansion, expmode)];
+	}
+
+	return rate_index;
+}
+
+static int get_vht_rate_identifier(int vht_mcs_index)
+{
+	int rate_index = 0;
+
+	if (vht_mcs_index >= VHT_RATE_INDEX_0 && vht_mcs_index < VHT_RATE_INDEX_MAX)
+	{
+		rate_index = vht_mcs_index;
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht mcs spec: %d\n", vht_mcs_index);
+	}
+	return rate_index;
+}
+
+static int get_vht_ss1_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		switch (expmode)
+		{
+			case EXP_MODE_ID_DEF:
+				mode_identifier = VHT_SS1_MODE_ID_NONE;
+				break;
+			case EXP_MODE_ID_STBC:
+				mode_identifier = VHT_SS1_MODE_ID_STBC;
+				break;
+			default:
+				fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode %s\n", tx_expansion,
+						get_mode_name(expmode));
+				break;
+		}
+	}
+	else if (tx_expansion == 1)
+	{
+		switch (expmode)
+		{
+			case EXP_MODE_ID_DEF:
+				mode_identifier = VHT_SS1_MODE_ID_CDD1;
+				break;
+			case EXP_MODE_ID_STBC:
+				mode_identifier = VHT_SS1_MODE_ID_STBC_SPEXP1;
+				break;
+			case EXP_MODE_ID_TXBF:
+				mode_identifier = VHT_SS1_MODE_ID_TXBF1;
+				break;
+			default:
+				fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode %s\n", tx_expansion,
+						get_mode_name(expmode));
+				break;
+		}
+	}
+	else if (tx_expansion == 2)
+	{
+		switch (expmode)
+		{
+			case EXP_MODE_ID_DEF:
+				mode_identifier = VHT_SS1_MODE_ID_CDD2;
+				break;
+			case EXP_MODE_ID_TXBF:
+				mode_identifier = VHT_SS1_MODE_ID_TXBF2;
+				break;
+			default:
+				fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode %s\n", tx_expansion,
+						get_mode_name(expmode));
+				break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode: %s\n", tx_expansion,
+				 get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+static int get_vht_ss2_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS2_MODE_ID_NONE;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS2_MODE_ID_TXBF0;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss2 mode: %d, expansion mode %s\n", tx_expansion,
+				get_mode_name(expmode));
+			break;
+		}
+	}
+	else if (tx_expansion == 1)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS2_MODE_ID_SPEXP1;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS2_MODE_ID_TXBF1;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss2 mode: %d, expansion mode %s\n", tx_expansion,
+				  get_mode_name(expmode));
+			break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht ss2 mode: %d expansion mode: %s\n", tx_expansion,
+			   get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+static int get_vht_ss3_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS3_MODE_ID_NONE;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS3_MODE_ID_TXBF0;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss3 mode: %d, expansion mode: %s\n", tx_expansion
+					, get_mode_name(expmode));
+			break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht ss3 mode: %d, expansion: %s\n", tx_expansion,
+			   get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+static const char *get_mode_name(exp_mode_t mode)
+{
+	if (mode >= EXP_MODE_ID_MAX)
+		return EXP_MODE_UNKNOWN;
+
+	return exp_mode_name[mode];
+}
diff --git a/src/wl/exe/wlu_rates_matrix.h b/src/wl/exe/wlu_rates_matrix.h
new file mode 100644
index 0000000..d9fe645
--- /dev/null
+++ b/src/wl/exe/wlu_rates_matrix.h
@@ -0,0 +1,401 @@
+/*
+ * This module does provides various mappings to or from the CLM rate indexes.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ */
+/*FILE-CSTYLED*/
+
+#ifndef _WLU_RATES_MATRIX_H_
+#define _WLU_RATES_MATRIX_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <bcmwifi_rates.h>
+#include <wlioctl.h>
+#include <typedefs.h>
+#include <epivers.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmwifi_channels.h>
+#include <wlc_ppr.h>
+
+#include <inttypes.h>
+#include <miniopt.h>
+
+#define WL_UNSUPPORTED_IDX 0xFFF
+
+typedef enum clm_rate_group_id {
+	RATE_GROUP_ID_DSSS = 0,
+	RATE_GROUP_ID_OFDM,
+	RATE_GROUP_ID_MCS0_7,
+	RATE_GROUP_ID_VHT8_9SS1,
+	RATE_GROUP_ID_DSSS_MULTI1,
+	RATE_GROUP_ID_OFDM_CDD1,
+	RATE_GROUP_ID_MCS0_7_CDD1,
+	RATE_GROUP_ID_VHT8_9SS1_CDD1,
+	RATE_GROUP_ID_MCS0_7_STBC,
+	RATE_GROUP_ID_VHT8_9SS1_STBC,
+	RATE_GROUP_ID_MCS8_15,
+	RATE_GROUP_ID_VHT8_9SS2,
+	RATE_GROUP_ID_DSSS_MULTI2,
+	RATE_GROUP_ID_OFDM_CDD2,
+	RATE_GROUP_ID_MCS0_7_CDD2,
+	RATE_GROUP_ID_VHT8_9SS1_CDD2,
+	RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,
+	RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1,
+	RATE_GROUP_ID_MCS8_15_SPEXP1,
+	RATE_GROUP_ID_VHT8_9SS2_SPEXP1,
+	RATE_GROUP_ID_MCS16_23,
+	RATE_GROUP_ID_VHT8_9SS3,
+	RATE_GROUP_ID_OFDM_TXBF1,
+	RATE_GROUP_ID_MCS0_7_TXBF1,
+	RATE_GROUP_ID_VHT8_9SS1_TXBF1,
+	RATE_GROUP_ID_MCS8_15_TXBF0,
+	RATE_GROUP_ID_OFDM_TXBF2,
+	RATE_GROUP_ID_MCS0_7_TXBF2,
+	RATE_GROUP_ID_VHT8_9SS1_TXBF2,
+	RATE_GROUP_ID_MCS8_15_TXBF1,
+	RATE_GROUP_ID_VHT8_9SS2_TXBF1,
+	RATE_GROUP_ID_MCS16_23_TXBF0,
+	RATE_GROUP_ID_COUNT
+} clm_rate_group_id_t;
+
+
+typedef struct {
+    char label[23];
+    uint8 chains;
+    clm_rate_group_id_t id;
+    clm_rates_t rate;
+    uint bw20ssl;
+    uint bw20n;
+    uint bw20ht;
+    uint bw40ssl;
+    uint bw40n;
+    uint bw40ht;
+    uint bw20in40ssl;
+    uint bw20in40n;
+    uint bw20in40ht;
+    uint bw80ssl;
+    uint bw80n;
+    uint bw80ht;
+    uint bw20in80ssl;
+    uint bw20in80n;
+    uint bw20in80ht;
+    uint bw40in80ssl;
+    uint bw40in80n;
+    uint bw40in80ht;
+} clm_rate_matrix_t;
+
+typedef enum reg_rate_index {
+	NO_RATE = -1,
+	DSSS1, DSSS2, DSSS5, DSSS11,
+	OFDM6, OFDM9, OFDM12, OFDM18,
+	OFDM24, OFDM36, OFDM48, OFDM54,
+	MCS0, MCS1, MCS2, MCS3,
+	MCS4, MCS5, MCS6, MCS7,
+	VHT8SS1, VHT9SS1,
+	DSSS1_MULTI1, DSSS2_MULTI1, DSSS5_MULTI1, DSSS11_MULTI1,
+	OFDM6_CDD1, OFDM9_CDD1, OFDM12_CDD1, OFDM18_CDD1,
+	OFDM24_CDD1, OFDM36_CDD1, OFDM48_CDD1, OFDM54_CDD1,
+	MCS0_CDD1, MCS1_CDD1, MCS2_CDD1, MCS3_CDD1,
+	MCS4_CDD1, MCS5_CDD1, MCS6_CDD1, MCS7_CDD1,
+	VHT8SS1_CDD1, VHT9SS1_CDD1,
+	MCS0_STBC, MCS1_STBC, MCS2_STBC, MCS3_STBC,
+	MCS4_STBC, MCS5_STBC, MCS6_STBC, MCS7_STBC,
+	VHT8SS1_STBC, VHT9SS1_STBC,
+	MCS8, MCS9, MCS10, MCS11,
+	MCS12, MCS13, MCS14, MCS15,
+	VHT8SS2, VHT9SS2,
+	DSSS1_MULTI2, DSSS2_MULTI2, DSSS5_MULTI2, DSSS11_MULTI2,
+	OFDM6_CDD2, OFDM9_CDD2, OFDM12_CDD2, OFDM18_CDD2,
+	OFDM24_CDD2, OFDM36_CDD2, OFDM48_CDD2, OFDM54_CDD2,
+	MCS0_CDD2, MCS1_CDD2, MCS2_CDD2, MCS3_CDD2,
+	MCS4_CDD2, MCS5_CDD2, MCS6_CDD2, MCS7_CDD2,
+	VHT8SS1_CDD2, VHT9SS1_CDD2,
+	MCS0_STBC_SPEXP1, MCS1_STBC_SPEXP1, MCS2_STBC_SPEXP1, MCS3_STBC_SPEXP1,
+	MCS4_STBC_SPEXP1, MCS5_STBC_SPEXP1, MCS6_STBC_SPEXP1, MCS7_STBC_SPEXP1,
+	VHT8SS1_STBC_SPEXP1, VHT9SS1_STBC_SPEXP1,
+	MCS8_SPEXP1, MCS9_SPEXP1, MCS10_SPEXP1, MCS11_SPEXP1,
+	MCS12_SPEXP1, MCS13_SPEXP1, MCS14_SPEXP1, MCS15_SPEXP1,
+	VHT8SS2_SPEXP1, VHT9SS2_SPEXP1,
+	MCS16, MCS17, MCS18, MCS19,
+	MCS20, MCS21, MCS22, MCS23,
+	VHT8SS3, VHT9SS3,
+	OFDM6_TXBF1, OFDM9_TXBF1, OFDM12_TXBF1, OFDM18_TXBF1,
+	OFDM24_TXBF1, OFDM36_TXBF1, OFDM48_TXBF1, OFDM54_TXBF1,
+	MCS0_TXBF1, MCS1_TXBF1, MCS2_TXBF1, MCS3_TXBF1,
+	MCS4_TXBF1, MCS5_TXBF1, MCS6_TXBF1, MCS7_TXBF1,
+	VHT8SS1_TXBF1, VHT9SS1_TXBF1,
+	MCS8_TXBF0, MCS9_TXBF0, MCS10_TXBF0, MCS11_TXBF0,
+	MCS12_TXBF0, MCS13_TXBF0, MCS14_TXBF0, MCS15_TXBF0,
+	OFDM6_TXBF2, OFDM9_TXBF2, OFDM12_TXBF2, OFDM18_TXBF2,
+	OFDM24_TXBF2, OFDM36_TXBF2, OFDM48_TXBF2, OFDM54_TXBF2,
+	MCS0_TXBF2, MCS1_TXBF2, MCS2_TXBF2, MCS3_TXBF2,
+	MCS4_TXBF2, MCS5_TXBF2, MCS6_TXBF2, MCS7_TXBF2,
+	VHT8SS1_TXBF2, VHT9SS1_TXBF2,
+	MCS8_TXBF1, MCS9_TXBF1, MCS10_TXBF1, MCS11_TXBF1,
+	MCS12_TXBF1, MCS13_TXBF1, MCS14_TXBF1, MCS15_TXBF1,
+	VHT8SS2_TXBF1, VHT9SS2_TXBF1,
+	MCS16_TXBF0, MCS17_TXBF0, MCS18_TXBF0, MCS19_TXBF0,
+	MCS20_TXBF0, MCS21_TXBF0, MCS22_TXBF0, MCS23_TXBF0,
+} reg_rate_index_t;
+
+typedef enum ppr_rate_type {
+	PPR_RATE_DSSS,
+	PPR_RATE_OFDM,
+	PPR_RATE_HT,
+	PPR_RATE_VHT,
+} ppr_rate_type_t;
+
+typedef struct ppr_tbl {
+	char label[23];
+	clm_rate_group_id_t id;
+	clm_rates_t         rate;
+} ppr_tbl_t;
+
+typedef struct ppr_group {
+	clm_rate_group_id_t	id;
+	wl_tx_chains_t		chain;
+	wl_tx_mode_t		mode;
+	wl_tx_nss_t		nss;
+	ppr_rate_type_t		rate_type;
+	reg_rate_index_t	first_rate;
+} ppr_group_t;
+
+static const ppr_group_t ppr_group_table[] = {
+	/*group id				chains			mode			nss		rate type		offset-first*/
+	{RATE_GROUP_ID_DSSS,			WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_DSSS,		DSSS1},
+	{RATE_GROUP_ID_OFDM,			WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6},
+	{RATE_GROUP_ID_MCS0_7,			WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0},
+	{RATE_GROUP_ID_VHT8_9SS1,		WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0},
+	{RATE_GROUP_ID_DSSS_MULTI1,		WL_TX_CHAINS_2,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_DSSS,		DSSS1_MULTI1},
+	{RATE_GROUP_ID_OFDM_CDD1,		WL_TX_CHAINS_2,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_CDD1},
+	{RATE_GROUP_ID_MCS0_7_CDD1,		WL_TX_CHAINS_2,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD1},
+	{RATE_GROUP_ID_VHT8_9SS1_CDD1,		WL_TX_CHAINS_2,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD1},
+	{RATE_GROUP_ID_MCS0_7_STBC,		WL_TX_CHAINS_2,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC},
+	{RATE_GROUP_ID_VHT8_9SS1_STBC,		WL_TX_CHAINS_2,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC},
+	{RATE_GROUP_ID_MCS8_15,			WL_TX_CHAINS_2,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8},
+	{RATE_GROUP_ID_VHT8_9SS2,		WL_TX_CHAINS_2,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8},
+	{RATE_GROUP_ID_DSSS_MULTI2,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_DSSS,		DSSS1_MULTI2},
+	{RATE_GROUP_ID_OFDM_CDD2,		WL_TX_CHAINS_3,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_CDD2},
+	{RATE_GROUP_ID_MCS0_7_CDD2,		WL_TX_CHAINS_3,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD2},
+	{RATE_GROUP_ID_VHT8_9SS1_CDD2,		WL_TX_CHAINS_3,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD2},
+	{RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP1},
+	{RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP1},
+	{RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP1},
+	{RATE_GROUP_ID_VHT8_9SS2_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP1},
+	{RATE_GROUP_ID_MCS16_23,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16},
+	{RATE_GROUP_ID_VHT8_9SS3,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16},
+	{RATE_GROUP_ID_OFDM_TXBF1,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_TXBF1},
+	{RATE_GROUP_ID_MCS0_7_TXBF1,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF1},
+	{RATE_GROUP_ID_VHT8_9SS1_TXBF1,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF1},
+	{RATE_GROUP_ID_MCS8_15_TXBF0,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_HT,		MCS8_TXBF0},
+	{RATE_GROUP_ID_OFDM_TXBF2,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_TXBF2},
+	{RATE_GROUP_ID_MCS0_7_TXBF2,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF2},
+	{RATE_GROUP_ID_VHT8_9SS1_TXBF2,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF2},
+	{RATE_GROUP_ID_MCS8_15_TXBF1,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF1},
+	{RATE_GROUP_ID_VHT8_9SS2_TXBF1,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF1},
+	{RATE_GROUP_ID_MCS16_23_TXBF0,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_3,	PPR_RATE_HT,		MCS16_TXBF0},
+};
+
+static const ppr_tbl_t ppr_table[] = {
+	/* Label			Rate Group ID				CLM index*/
+	{"DSSS1",			RATE_GROUP_ID_DSSS,			WL_RATE_1X1_DSSS_1},
+	{"DSSS2",			RATE_GROUP_ID_DSSS,			WL_RATE_1X1_DSSS_2},
+	{"DSSS5",			RATE_GROUP_ID_DSSS,			WL_RATE_1X1_DSSS_5_5},
+	{"DSSS11",			RATE_GROUP_ID_DSSS,			WL_RATE_1X1_DSSS_11},
+	{"OFDM6",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_6},
+	{"OFDM9",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_9},
+	{"OFDM12",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_12},
+	{"OFDM18",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_18},
+	{"OFDM24",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_24},
+	{"OFDM36",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_36},
+	{"OFDM48",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_48},
+	{"OFDM54",			RATE_GROUP_ID_OFDM,			WL_RATE_1X1_OFDM_54},
+	{"MCS0",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS0},
+	{"MCS1",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS1},
+	{"MCS2",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS2},
+	{"MCS3",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS3},
+	{"MCS4",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS4},
+	{"MCS5",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS5},
+	{"MCS6",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS6},
+	{"MCS7",			RATE_GROUP_ID_MCS0_7,			WL_RATE_1X1_MCS7},
+	{"VHT8SS1",			RATE_GROUP_ID_VHT8_9SS1,		WL_RATE_1X1_VHT8SS1},
+	{"VHT9SS1",			RATE_GROUP_ID_VHT8_9SS1,		WL_RATE_1X1_VHT9SS1},
+	{"DSSS1_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1,		WL_RATE_1X2_DSSS_1},
+	{"DSSS2_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1,		WL_RATE_1X2_DSSS_2},
+	{"DSSS5_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1,		WL_RATE_1X2_DSSS_5_5},
+	{"DSSS11_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1,		WL_RATE_1X2_DSSS_11},
+	{"OFDM6_CDD1",			RATE_GROUP_ID_OFDM_CDD1,	        WL_RATE_1X2_CDD_OFDM_6},
+	{"OFDM9_CDD1",			RATE_GROUP_ID_OFDM_CDD1,	        WL_RATE_1X2_CDD_OFDM_9},
+	{"OFDM12_CDD1",			RATE_GROUP_ID_OFDM_CDD1,		WL_RATE_1X2_CDD_OFDM_12,},
+	{"OFDM18_CDD1",			RATE_GROUP_ID_OFDM_CDD1,		WL_RATE_1X2_CDD_OFDM_18,},
+	{"OFDM24_CDD1",			RATE_GROUP_ID_OFDM_CDD1,		WL_RATE_1X2_CDD_OFDM_24,},
+	{"OFDM36_CDD1",			RATE_GROUP_ID_OFDM_CDD1,		WL_RATE_1X2_CDD_OFDM_36,},
+	{"OFDM48_CDD1",			RATE_GROUP_ID_OFDM_CDD1,		WL_RATE_1X2_CDD_OFDM_48,},
+	{"OFDM54_CDD1",			RATE_GROUP_ID_OFDM_CDD1,		WL_RATE_1X2_CDD_OFDM_54,},
+	{"MCS0_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS0},
+	{"MCS1_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS1},
+	{"MCS2_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS2},
+	{"MCS3_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS3},
+	{"MCS4_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS4},
+	{"MCS5_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS5},
+	{"MCS6_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS6},
+	{"MCS7_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1,		WL_RATE_1X2_CDD_MCS7},
+	{"VHT8SS1_CDD1",		RATE_GROUP_ID_VHT8_9SS1_CDD1,		WL_RATE_1X2_VHT8SS1},
+	{"VHT9SS1_CDD1",		RATE_GROUP_ID_VHT8_9SS1_CDD1,		WL_RATE_1X2_VHT9SS1},
+	{"MCS0_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS0},
+	{"MCS1_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS1},
+	{"MCS2_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS2},
+	{"MCS3_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS3},
+	{"MCS4_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS4},
+	{"MCS5_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS5},
+	{"MCS6_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS6},
+	{"MCS7_STBC",			RATE_GROUP_ID_MCS0_7_STBC,		WL_RATE_2X2_STBC_MCS7},
+	{"VHT8SS1_STBC",		RATE_GROUP_ID_VHT8_9SS1_STBC,		WL_RATE_2X2_STBC_VHT8SS1},
+	{"VHT9SS1_STBC",		RATE_GROUP_ID_VHT8_9SS1_STBC,		WL_RATE_2X2_STBC_VHT9SS1},
+	{"MCS8",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS8},
+	{"MCS9",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS9},
+	{"MCS10",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS10},
+	{"MCS11",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS11},
+	{"MCS12",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS12},
+	{"MCS13",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS13},
+	{"MCS14",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS14},
+	{"MCS15",			RATE_GROUP_ID_MCS8_15,			WL_RATE_2X2_SDM_MCS15},
+	{"VHT8SS2",			RATE_GROUP_ID_VHT8_9SS2,		WL_RATE_2X2_VHT8SS2},
+	{"VHT9SS2",			RATE_GROUP_ID_VHT8_9SS2,		WL_RATE_2X2_VHT9SS2},
+	{"DSSS1_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2,		WL_RATE_1X3_DSSS_1},
+	{"DSSS2_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2,		WL_RATE_1X3_DSSS_2},
+	{"DSSS5_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2,		WL_RATE_1X3_DSSS_5_5},
+	{"DSSS11_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2,		WL_RATE_1X3_DSSS_11},
+	{"OFDM6_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_6},
+	{"OFDM9_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_9},
+	{"OFDM12_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_12},
+	{"OFDM18_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_18},
+	{"OFDM24_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_24},
+	{"OFDM36_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_36},
+	{"OFDM48_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_48},
+	{"OFDM54_CDD2",			RATE_GROUP_ID_OFDM_CDD2,		WL_RATE_1X3_CDD_OFDM_54},
+	{"MCS0_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS0},
+	{"MCS1_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS1},
+	{"MCS2_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS2},
+	{"MCS3_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS3},
+	{"MCS4_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS4},
+	{"MCS5_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS5},
+	{"MCS6_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS6},
+	{"MCS7_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2,		WL_RATE_1X3_CDD_MCS7},
+	{"VHT8SS1_CDD2",		RATE_GROUP_ID_VHT8_9SS1_CDD2,		WL_RATE_1X3_VHT8SS1},
+	{"VHT9SS1_CDD2",		RATE_GROUP_ID_VHT8_9SS1_CDD2,		WL_RATE_1X3_VHT9SS1},
+	{"MCS0_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS0},
+	{"MCS1_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS1},
+	{"MCS2_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS2},
+	{"MCS3_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS3},
+	{"MCS4_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS4},
+	{"MCS5_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS5},
+	{"MCS6_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS6},
+	{"MCS7_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_RATE_2X3_STBC_MCS7},
+	{"VHT8SS1_STBC_SPEXP1",		RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1,	WL_RATE_2X3_STBC_VHT8SS1},
+	{"VHT9SS1_STBC_SPEXP1",		RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1,	WL_RATE_2X3_STBC_VHT9SS1},
+	{"MCS8_SPEXP1",			RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS8},
+	{"MCS9_SPEXP1",			RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS9},
+	{"MCS10_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS10},
+	{"MCS11_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS11},
+	{"MCS12_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS12},
+	{"MCS13_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS13},
+	{"MCS14_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS14},
+	{"MCS15_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_RATE_2X3_SDM_MCS15},
+	{"VHT8SS2_SPEXP1",		RATE_GROUP_ID_VHT8_9SS2_SPEXP1,		WL_RATE_2X3_VHT8SS2},
+	{"VHT9SS2_SPEXP1",		RATE_GROUP_ID_VHT8_9SS2_SPEXP1,		WL_RATE_2X3_VHT9SS2},
+	{"MCS16",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS16},
+	{"MCS17",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS17},
+	{"MCS18",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS18},
+	{"MCS19",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS19},
+	{"MCS20",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS20},
+	{"MCS21",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS21},
+	{"MCS22",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS22},
+	{"MCS23",			RATE_GROUP_ID_MCS16_23,			WL_RATE_3X3_SDM_MCS23},
+	{"VHT8SS3",			RATE_GROUP_ID_VHT8_9SS3,		WL_RATE_3X3_VHT8SS3},
+	{"VHT9SS3",			RATE_GROUP_ID_VHT8_9SS3,		WL_RATE_3X3_VHT9SS3},
+	{"OFDM6_TXBF1",			RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_6},
+	{"OFDM9_TXBF1",			RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_9},
+	{"OFDM12_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_12},
+	{"OFDM18_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_18},
+	{"OFDM24_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_24},
+	{"OFDM36_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_36},
+	{"OFDM48_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_48},
+	{"OFDM54_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1,		WL_RATE_1X2_TXBF_OFDM_54},
+	{"MCS0_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS0},
+	{"MCS1_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS1},
+	{"MCS2_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS1},
+	{"MCS3_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS3},
+	{"MCS4_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS4},
+	{"MCS5_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS5},
+	{"MCS6_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS6},
+	{"MCS7_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1,		WL_RATE_1X2_TXBF_MCS7},
+	{"VHT8SS1_TXBF1",		RATE_GROUP_ID_VHT8_9SS1_TXBF1,		WL_RATE_1X2_TXBF_VHT8SS1},
+	{"VHT9SS1_TXBF1",		RATE_GROUP_ID_VHT8_9SS1_TXBF1,		WL_RATE_1X2_TXBF_VHT9SS1},
+	{"MCS8_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS8},
+	{"MCS9_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS9},
+	{"MCS10_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS10},
+	{"MCS11_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS11},
+	{"MCS12_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS12},
+	{"MCS13_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS13},
+	{"MCS14_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS14},
+	{"MCS15_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0,		WL_RATE_2X2_TXBF_SDM_MCS15},
+	{"OFDM6_TXBF2",			RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_6},
+	{"OFDM9_TXBF2",			RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_9},
+	{"OFDM12_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_12},
+	{"OFDM18_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_18},
+	{"OFDM24_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_24},
+	{"OFDM36_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_36},
+	{"OFDM48_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_48},
+	{"OFDM54_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2,		WL_RATE_1X3_TXBF_OFDM_54},
+	{"MCS0_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS0},
+	{"MCS1_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS1},
+	{"MCS2_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS2},
+	{"MCS3_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS3},
+	{"MCS4_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS4},
+	{"MCS5_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS5},
+	{"MCS6_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS6},
+	{"MCS7_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2,		WL_RATE_1X3_TXBF_MCS7},
+	{"VHT8SS1_TXBF2",		RATE_GROUP_ID_VHT8_9SS1_TXBF2,		WL_RATE_1X3_TXBF_VHT8SS1},
+	{"VHT9SS1_TXBF2",		RATE_GROUP_ID_VHT8_9SS1_TXBF2,		WL_RATE_1X3_TXBF_VHT9SS1},
+	{"MCS8_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS8},
+	{"MCS9_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS9},
+	{"MCS10_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS10},
+	{"MCS11_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS11},
+	{"MCS12_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS12},
+	{"MCS13_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS13},
+	{"MCS14_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS14},
+	{"MCS15_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1,		WL_RATE_2X3_TXBF_SDM_MCS15},
+	{"VHT8SS2_TXBF1",		RATE_GROUP_ID_VHT8_9SS2_TXBF1,		WL_RATE_2X3_TXBF_VHT8SS2},
+	{"VHT9SS2_TXBF1",		RATE_GROUP_ID_VHT8_9SS2_TXBF1,		WL_RATE_2X3_TXBF_VHT9SS2},
+	{"MCS16_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS16},
+	{"MCS17_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS17},
+	{"MCS18_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS18},
+	{"MCS19_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS19},
+	{"MCS20_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS20},
+	{"MCS21_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS21},
+	{"MCS22_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS22},
+	{"MCS23_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0,		WL_RATE_3X3_TXBF_SDM_MCS23},
+};
+
+#define MHZ_TO_HALF_MHZ 2
+
+const char *get_clm_rate_group_label(int rategroup);
+const char *get_reg_rate_string_from_ratespec(int ratespec);
+reg_rate_index_t get_reg_rate_index_from_ratespec(int ratespec);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _WLU_RATES_MATRIX_H_ */
diff --git a/src/wl/exe/wlu_remote.h b/src/wl/exe/wlu_remote.h
new file mode 100644
index 0000000..cfeb88a
--- /dev/null
+++ b/src/wl/exe/wlu_remote.h
@@ -0,0 +1,230 @@
+/*
+ * OS independent remote wl declarations
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_remote.h 425230 2013-09-23 10:53:48Z $
+ */
+#ifndef _wlu_remote_h
+#define _wlu_remote_h
+#include <wlioctl.h>
+/* Remote wl declararions */
+#define NO_REMOTE       0
+#define REMOTE_SERIAL 	1
+#define REMOTE_SOCKET 	2
+#define REMOTE_WIFI     3
+#define REMOTE_DONGLE   4
+#define SHELL_CMD       -1 /* Invalid cmd id for shell */
+#define ASD_CMD       	-2 /* Cmd id for ASD command */
+#define SERVER_RESPONSE_MAX_BUF_LEN 8192
+#define SHELL_RESP_SIZE 1024
+#define CTRLC_PACKET 0xDEADBEAF
+#define CTRLC_FLAG -4
+#define VISTA_CMD	-3 /* cmd id for remote vista */
+
+/* For cross OS support */
+/* For autonegotiation to work, these defines should be
+ * the same for client and server.
+ */
+#define UNKNOWN_OS	0
+#define LINUX_OS  	1
+#define WIN32_OS  	2
+#define MAC_OSX		3
+#define BACKLOG 	4
+#define WINVISTA_OS	5
+#define INDONGLE	6
+#define INVALID_OS	7	/* Should be last */
+
+/* Used in cdc_ioctl_t.flags field */
+#define REMOTE_SET_IOCTL			1
+#define REMOTE_GET_IOCTL			2
+#define REMOTE_REPLY				4
+#define REMOTE_SHELL_CMD			8
+#define REMOTE_FINDSERVER_IOCTL		16 /* Find remote server */
+#define REMOTE_ASD_CMD				32 /* ASD integration */
+#define RDHD_SET_IOCTL			64
+#define RDHD_GET_IOCTL			128
+#define REMOTE_VISTA_CMD			256 /* for remote vista specific commands */
+#define REMOTE_NEGOTIATE_CMD			512 /* for RWL negotiation */
+#define NEGOTIATE_GET_OS			0   /* detect remote OS */
+#define RWL_WIFI_DEFAULT_TYPE 		0x00
+#define RWL_WIFI_DEFAULT_SUBTYPE 	0x00
+#define RWL_ACTION_FRAME_DATA_SIZE 	1024	/* fixed size for the wifi frame data */
+#define RWL_WIFI_CDC_HEADER_OFFSET 	0
+#define RWL_WIFI_FRAG_DATA_SIZE 	960 /* max size of the frag data */
+#define RWL_DEFAULT_WIFI_FRAG_COUNT 127 /* maximum fragment count */
+#define RWL_WIFI_RETRY				5	/* CMD retry count for wifi */
+#define RWL_WIFI_RX_RETRY			20  /* WIFI response rerty count */
+#define RWL_WIFI_SEND				5   /* WIFI frame sent count */
+#define RWL_WIFI_RETRY_DELAY   		1000 /* wifi specific retry delay  */
+#define RWL_WIFI_SEND_DELAY			100  /* delay between two frames */
+#define RWL_WIFI_RX_DELAY			250  /*  wait between send and receive */
+#define RWL_WIFI_RX_SHELL_DELAY		1000 /* delay added for shell cmd response read */
+#define RWL_CHANNEL_RX_SCAN_DELAY	10  /* Delay between findserver rx calls */
+#define RWL_CHANNEL_SCAN_WAIT		250 /* Sleep time in between the channel scans */
+#define RWL_WIFI_BUF_LEN			64
+#define RWL_WIFI_SHELL_CMD			1
+#define RWL_WIFI_WL_CMD            	0
+#define RWL_WIFI_FIND_SER_CMD 		"findserver"
+#define RWL_WIFI_ACTION_CMD   		"wifiaction"
+#define RWL_WIFI_GET_ACTION_CMD         "rwlwifivsaction"
+#define RWL_DONGLE_SET_CMD			"dongleset"
+#define DATA_FRAME_LEN				960
+/* wl & shell cmd work fine for 960 (512+256+128+64) */
+
+
+/*
+ * Information about the action frame data fields in the
+ * dot11_action_wifi_vendor_specific
+ * cdc struct (1 to 16. This does not include status flag. Since this
+ * is not directly visible to the driver code we cant use sizeof struct
+ * cdc_ioctl_t. Hence Ref MAC address offset starts from byte 17.
+ * REF MAC ADDR (6 bytes (MAC Address len) from byte 17 to 22)
+ * DUT MAC ADDR (6 bytes after the REF MAC Address byte 23 to 28)
+ * unused (byte 29 to 49)
+ * REF/Client Channel offset (50)
+ * DUT/Server channel offset (51)
+ * ---------------------------------------------------------------------------------------
+ * cdc struct|REF MAC ADDR|DUT_MAC_ADDR|un used|REF Channel|DUT channel|Action frame Data|
+ * 1---------17-----------23-------------------50----------51----------52----------------1040
+ * REF MAC addr after CDC struct without status flag (status flag not used by wifi)
+ */
+#define RWL_ACTION_WIFI_CATEGORY	127  /* Vendor Specific category value for wifi */
+#define RWL_REF_MAC_ADDRESS_OFFSET	17
+#define RWL_DUT_MAC_ADDRESS_OFFSET	23
+#define RWL_WIFI_CLIENT_CHANNEL_OFFSET	50
+#define RWL_WIFI_SERVER_CHANNEL_OFFSET	51
+
+#define SUCCESS 					1
+#define FAIL   						-1
+#define NO_PACKET        			-2
+#define SERIAL_PORT_ERR  			-3
+
+#define DEFAULT_SERVER_PORT   		8000
+
+#define WL_MAX_BUF_LEN 				(127 * 1024)
+#define MAX_VISTA_ARGC				10
+#define HOST_TO_NETWORK				TRUE
+#define NETWORK_TO_HOST				FALSE
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ				16
+#endif
+
+/* We don't want the server to allocate bigger buffers for some of the commands
+ * like scanresults. Server can still allocate 8K memory and send the response
+ * in fragments. This is used in case of Get commands only.
+ */
+#define SERVER_RESPONSE_MAX_BUF_LEN 8192
+/* Used to set the cmds for wifi specific init */
+typedef struct remote_wifi_cmds {
+	uint32	cmd;		/* common ioctl definition */
+	char	*data;		/* max size of the data length */
+	int		value;
+} remote_wifi_cmds_t;
+
+/* Added for debug utility support */
+#define ERR		stderr
+#define OUTPUT	stdout
+
+#define DEBUG_DEFAULT	0x0001
+#define DEBUG_ERR		0x0001
+#define DEBUG_INFO		0x0002
+#define DEBUG_DBG		0x0004
+
+/* #ifdef TARGETOS_symbian */
+#define DPRINT_ERR	if (defined_debug & DEBUG_ERR) \
+			    fprintf
+#define DPRINT_INFO	if (defined_debug & DEBUG_INFO) \
+			    fprintf
+#define DPRINT_DBG	if (defined_debug & DEBUG_DBG) \
+			    fprintf
+extern unsigned short defined_debug;
+#ifdef WIN32
+/* Function defined in wlu.c for client and wlu_server_ce.c for server */
+extern int wl_atoip(const char *a, struct ipv4_addr *n);
+#endif
+/* Function defined to do host to network and network to host conversions */
+void rwl_swap_header(rem_ioctl_t *rem_ptr, bool host_to_network);
+
+/* Macros to access remote type */
+extern int remote_type;
+#define rwl_get_remote_type()		(remote_type)
+#define rwl_set_remote_type(type)	(remote_type = type)
+
+/* Macros to access server IP and port globals */
+extern char *g_rwl_servIP;
+#define rwl_get_server_ip()			(g_rwl_servIP)
+#define rwl_set_server_ip(ip) 		(g_rwl_servIP = ip)
+extern unsigned short g_rwl_servport;
+#define rwl_get_server_port()		(g_rwl_servport)
+#define rwl_set_server_port(port) 	(g_rwl_servport = port)
+
+extern int rwl_read_serial_port(void* hndle, char* read_buf, uint data_size, uint *numread);
+extern int rwl_write_serial_port(void* hndle, char* write_buf, unsigned long size,
+unsigned long *numwritten);
+extern void rwl_sleep(int delay);
+extern void* rwl_open_transport(int remote_type, char *port, int ReadTotalTimeout, int debug);
+extern int rwl_close_transport(int remote_type, void * handle);
+extern int rwl_poll_serial_buffer(void *hndle);
+extern int rwl_serial_handle_timeout(void);
+extern void rwl_sync_delay(uint noframes);
+
+#ifdef RWL_SOCKET
+extern int rwl_connectsocket(int SocketDes, struct sockaddr* SerAddr, int SizeOfAddr);
+extern  int rwl_acceptconnection(int SocketDes, struct sockaddr *ClientAddr, int *SizeOfAddr);
+extern int rwl_send_to_streamsocket(int SocketDes, const char* SendBuff, int data_size, int Flag);
+extern int rwl_receive_from_streamsocket(int SocketDes, char* RecvBuff, int data_size, int Flag);
+extern int rwl_init_server_socket_setup(int argc, char** argv, uint remote_type);
+extern int rwl_GetifAddr(char *ifname, struct sockaddr_in* sa);
+#endif /* RWL_SOCKET */
+
+extern int set_interface(void *wl, char *intf_name);
+
+/* Win32 specific function wlu_pipe_win32.c */
+extern int rwl_init_ws2_32dll(void);
+extern int rwl_terminate_ws2_32dll(void);
+
+/* Function definitions for wlu_client_shared.c and wlu_server_shared.c */
+extern int rwl_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr);
+extern int rwl_var_setbuf(void *wl, const char *iovar, void *param, int param_len);
+extern int rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len);
+
+/* Function definitions for wlu_ndis.c/wlu_linux.c  and wlu_server_ce.c/wlu_server_linux.c  */
+extern int wl_get(void *wl, int cmd, void *buf, int len);
+extern int wl_set(void *wl, int cmd, void *buf, int len);
+#ifdef RWLASD
+typedef unsigned char BYTE;
+extern void wfa_dut_init(BYTE **tBuf, BYTE **rBuf, BYTE **paBuf, BYTE **cBuf, struct timeval **);
+extern int remote_asd_exec(unsigned char* command, int* cmd_len);
+void wfa_dut_deinit(void);
+#endif
+extern int get_ctrlc_header(void *wl);
+extern int remote_tx_response(void *wl, void *buf_ptr, int cmd);
+extern rem_ioctl_t *g_rem_ptr;
+extern int g_rwl_hndle;
+/* Variable to indiate if the server child has completed execution */
+extern volatile sig_atomic_t g_sig_chld;
+
+/*
+ * Separate paths are defined for android and linux machines
+ * / filesystem on android is read only memory
+ */
+#ifndef WIN32
+#ifdef TARGETENV_android
+#define SH_PATH "/data/busybox/sh"
+#define SHELL_RESP_PATH  "/data/local/RWL/" /* Default path for storing files for shell response */
+#define	TEMPLATE         "/data/local/RWL/SyncXXXXXX"
+#else
+#define SHELL_RESP_PATH  "/tmp/RWL/" /* Default path for storing files for shell response */
+#define	TEMPLATE         "/tmp/RWL/SyncXXXXXX"
+#define SH_PATH "/bin/sh"
+#endif
+#endif /* !WIN32 */
+#endif /* _wlu_remote_h */
diff --git a/src/wl/exe/wlu_server_linux.c b/src/wl/exe/wlu_server_linux.c
new file mode 100644
index 0000000..b958e5f
--- /dev/null
+++ b/src/wl/exe/wlu_server_linux.c
@@ -0,0 +1,371 @@
+/*
+ * Wl server for linux
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_server_linux.c 420848 2013-08-29 08:58:47Z $
+ */
+
+/* Revision History:Linux port of Remote wl server
+ *
+ * Date        Author         Description
+ *
+ * 27-Dec-2007 Suganthi        Version 0.1
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#ifndef TARGETENV_android
+#include <linux/types.h>
+#endif
+
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <dhdioctl.h>
+#include <proto/ethernet.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#include "wlu_remote.h"
+
+
+#define DEV_TYPE_LEN    3 /* length for devtype 'wl'/'et' */
+#define BUF_LENGTH		1000
+
+#define dtoh32(i) i
+
+
+const char *rwl_server_name;
+void *g_wl_handle;
+unsigned short defined_debug = DEBUG_ERR | DEBUG_INFO;
+extern int remote_server_exec(int argc, char **argv, void *ifr);
+
+/* Global to have the PID of the current sync command
+ * This is required in case the sync command fails to respond,
+ * the alarm handler shall kill the PID upon a timeout
+ */
+int g_shellsync_pid;
+unsigned char g_return_stat = 0;
+
+static void
+syserr(char *s)
+{
+	fprintf(stderr, "%s: ", rwl_server_name);
+	perror(s);
+	exit(errno);
+}
+/* The handler for DHD commands */
+int
+dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set)
+{
+	struct ifreq *ifr = (struct ifreq *) dhd;
+	dhd_ioctl_t ioc;
+	int ret = 0;
+	int s;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* do it */
+	ioc.cmd = cmd;
+	ioc.buf = buf;
+	ioc.len = len;
+	ioc.set = set;
+	ioc.driver = DHD_IOCTL_MAGIC;
+	ifr->ifr_data = (caddr_t) &ioc;
+	if ((ret = ioctl(s, SIOCDEVPRIVATE, ifr)) < 0) {
+		if (cmd != DHD_GET_MAGIC) {
+			ret = BCME_IOCTL_ERROR;
+		}
+	}
+	/* cleanup */
+	close(s);
+	return ret;
+}
+
+int
+wl_ioctl(void *wl, int cmd, void *buf, int len, bool set)
+{
+	struct ifreq *ifr = (struct ifreq *) wl;
+	wl_ioctl_t ioc;
+	int ret = 0;
+	int s;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* do it */
+	ioc.cmd = cmd;
+	ioc.buf = buf;
+	ioc.len = len;
+	ioc.set = set;
+	ifr->ifr_data = (caddr_t) &ioc;
+	if ((ret = ioctl(s, SIOCDEVPRIVATE, ifr)) < 0) {
+		if (cmd != WLC_GET_MAGIC) {
+			ret = BCME_IOCTL_ERROR;
+		}
+	}
+	/* cleanup */
+	close(s);
+	return ret;
+}
+
+/* Functions copied from wlu.c to check for the driver adapter in the server machine */
+int
+wl_check(void *wl)
+{
+	int ret;
+	int val;
+
+	if ((ret = wl_ioctl(wl, WLC_GET_MAGIC, &val, sizeof(int), FALSE)) < 0)
+		return ret;
+	if (val != WLC_IOCTL_MAGIC)
+		return -1;
+	if ((ret = wl_ioctl(wl, WLC_GET_VERSION, &val, sizeof(int), FALSE)) < 0)
+		return ret;
+	val = dtoh32(val);
+
+	if (val > WLC_IOCTL_VERSION) {
+		fprintf(stderr, "Version mismatch, please upgrade\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int
+wl_get_dev_type(char *name, void *buf, int len)
+{
+	int s;
+	int ret;
+	struct ifreq ifr;
+	struct ethtool_drvinfo info;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* get device type */
+	memset(&info, 0, sizeof(info));
+	info.cmd = ETHTOOL_GDRVINFO;
+	ifr.ifr_data = (caddr_t)&info;
+	strncpy(ifr.ifr_name, name, IFNAMSIZ);
+	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
+	/* print a good diagnostic if not superuser */
+		if (errno == EPERM)
+			syserr("wl_get_dev_type");
+		*(char *)buf = '\0';
+	} else {
+		strncpy(buf, info.driver, len);
+	}
+	close(s);
+	return ret;
+}
+
+static void
+wl_find_adapter(struct ifreq *ifr)
+{
+	char proc_net_dev[] = "/proc/net/dev";
+	FILE *fp;
+	char buf[BUF_LENGTH], *c, *name;
+	char dev_type[DEV_TYPE_LEN];
+
+	ifr->ifr_name[0] = '\0';
+
+	if (!(fp = fopen(proc_net_dev, "r")))
+		return;
+
+	/* eat first two lines */
+	if (!fgets(buf, sizeof(buf), fp) ||
+	    !fgets(buf, sizeof(buf), fp)) {
+		fclose(fp);
+		return;
+	}
+
+	while (fgets(buf, sizeof(buf), fp)) {
+		c = buf;
+		while (isspace(*c))
+			c++;
+		if (!(name = strsep(&c, ":")))
+			continue;
+		strncpy(ifr->ifr_name, name, IFNAMSIZ-1);
+		ifr->ifr_name[IFNAMSIZ-1] = 0;
+		if (wl_get_dev_type(name, dev_type, DEV_TYPE_LEN) >= 0 &&
+			!strncmp(dev_type, "wl", 2))
+		if (wl_check((void *) ifr) == 0)
+				break;
+		ifr->ifr_name[0] = '\0';
+	}
+
+	fclose(fp);
+}
+
+int
+wl_get(void *wl, int cmd, void *buf, int len)
+{
+	int error;
+
+	error = wl_ioctl(wl, cmd, buf, len, FALSE);
+
+	return error;
+}
+
+int
+wl_set(void *wl, int cmd, void *buf, int len)
+{
+	int error;
+
+	error = wl_ioctl(wl,  cmd, buf, len, TRUE);
+
+	return error;
+}
+
+extern int set_ctrlc;
+void handle_ctrlc(int unused)
+{
+	UNUSED_PARAMETER(unused);
+	set_ctrlc = 1;
+	return;
+}
+
+volatile sig_atomic_t g_sig_chld = 1;
+void rwl_chld_handler(int num)
+{
+	int child_status;
+
+	UNUSED_PARAMETER(num);
+	/* g_return_stat is being set with the return status of sh commands */
+	waitpid(g_shellsync_pid, &child_status, WNOHANG);
+	if (WIFEXITED(child_status))
+		g_return_stat = WEXITSTATUS(child_status);
+	else if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG)
+		g_return_stat = 0;
+	else
+		g_return_stat = 1;
+	g_sig_chld = 0;
+}
+
+/* Alarm handler called after SHELL_TIMEOUT value
+ * This handler kills the non-responsive shell process
+ * with the PID value g_shellsync_pid
+ */
+static void
+sigalrm_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+
+	if (g_shellsync_pid) {
+		kill(g_shellsync_pid, SIGINT);
+	}
+#ifdef RWL_SOCKET
+	g_sig_chld = 0;
+#endif
+}
+
+static void
+def_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+	kill(g_shellsync_pid, SIGKILL);
+	exit(0);
+}
+
+static void
+pipe_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+	kill(g_shellsync_pid, SIGKILL);
+}
+
+int
+main(int argc, char **argv)
+{
+	int err = 0;
+	struct ifreq *ifr;
+
+	rwl_server_name = argv[0];
+
+	if ((ifr = calloc(1, sizeof(*ifr))) == NULL)
+	{
+		DPRINT_ERR(ERR, "wl_server: Unable to allocate memory for handle\n");
+		exit(1);
+	}
+
+	/* use default interface */
+	if (!ifr->ifr_name[0])
+		wl_find_adapter(ifr);
+	/* validate the interface */
+	if (!ifr->ifr_name[0] || wl_check((void *)ifr)) {
+		DPRINT_INFO(OUTPUT, "wl_server: wl driver adapter not found\n");
+	}
+	g_wl_handle = ifr;
+
+	/* Register signal handlers */
+	signal(SIGCHLD, rwl_chld_handler);
+	signal(SIGALRM, sigalrm_handler);
+	signal(SIGTERM, def_handler);
+	signal(SIGPIPE, pipe_handler);
+	signal(SIGABRT, def_handler);
+#ifdef RWL_DONGLE
+	signal(SIGINT, handle_ctrlc);
+#endif
+	/* Main server process for all transport types */
+	err = remote_server_exec(argc, argv, ifr);
+	free(ifr);
+	return err;
+}
+
+/*
+ * Funtion to store old interface.
+ */
+void
+store_old_interface(void *wl, char *old_intf_name)
+{
+	strcpy(old_intf_name, ((struct ifreq *)wl)->ifr_name);
+}
+
+/*
+ * Function to set interface.
+ */
+int
+set_interface(void *wl, char *intf_name)
+{
+	struct ifreq *ifr = (struct ifreq *)wl;
+
+	if (strlen(intf_name) != 0) {
+		strncpy(ifr->ifr_name, intf_name, strlen(intf_name) + 1);
+		return BCME_OK;
+	}
+	else {
+		DPRINT_DBG(OUTPUT, "Default Interface will be used ... \n");
+		return BCME_ERROR;
+	}
+}
diff --git a/src/wl/exe/wlu_server_shared.c b/src/wl/exe/wlu_server_shared.c
new file mode 100644
index 0000000..f9cd905
--- /dev/null
+++ b/src/wl/exe/wlu_server_shared.c
@@ -0,0 +1,1040 @@
+/*
+ * File Name: wlu_server_shared.c
+ * Common server specific functions for linux and win32
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_server_shared.c 428561 2013-10-09 09:32:29Z $
+ */
+
+/*
+ * Description: Main Server specific wrappers
+ * This module implements all the server specific functions
+ * for Win32 and Linux
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef TARGETOS_symbian
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+#else
+#include <malloc.h>
+#endif /* TARGETOS_symbian */
+#include <assert.h>
+
+#include <errno.h>
+#ifndef WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+#if  !defined(TARGETOS_symbian)
+#include <arpa/inet.h>
+#include <net/if.h>
+#endif
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#endif /* WIN32 */
+
+#ifdef WIN32
+#include <windows.h>
+#include <winioctl.h>
+#include <ntddndis.h>
+#include <typedefs.h>
+#include <epictrl.h>
+#include <irelay.h>
+#include <proto/ethernet.h>
+#include <nuiouser.h>
+#include <bcmendian.h>
+#include <oidencap.h>
+#include <bcmutils.h>
+#include <proto/802.11.h>
+#endif /* WIN32 */
+
+#include <bcmcdc.h>
+#include <wlioctl.h>
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
+#include <rwl_wifi.h>
+#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
+#include "wlu.h"
+#include "wlu_remote.h"
+#include "wlu_pipe.h"
+#include "wlu_server_shared.h"
+#ifdef RWLASD
+extern int g_serv_sock_desc;
+#endif
+int g_rwl_hndle;
+int set_ctrlc = 0;
+
+#ifdef RWL_DONGLE
+static rem_ioctl_t loc_cdc;
+static const char* cmdname = "remote";
+static const char* dongleset = "dongleset";
+#endif
+
+extern void store_old_interface(void *wl, char *old_intf_name);
+extern int wl_check(void *wl);
+
+extern void handle_ctrlc(int unused);
+/* Function: rwl_transport_setup
+ * This will do the initialization for
+ * for all the transports
+ */
+static int
+rwl_transport_setup(int argc, char** argv)
+{
+	int transport_descriptor = -1;
+
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(argv);
+
+#ifdef RWL_SOCKET
+	/* This function will parse the socket command line arguments
+	 * & open the socket in listen mode
+	 */
+	remote_type = REMOTE_SOCKET;
+	transport_descriptor = rwl_init_server_socket_setup(argc, argv, remote_type);
+
+	if (transport_descriptor < 0) {
+		DPRINT_ERR(ERR, "wl_socket_server:Transport setup failed \n");
+	}
+#endif /* RWL_SOCKET */
+#if defined(RWL_DONGLE) || defined(RWL_WIFI) || defined(RWL_SERIAL)
+	g_rem_pkt_ptr = &g_rem_pkt;
+	transport_descriptor = 0;
+
+#ifdef RWL_WIFI
+	remote_type = REMOTE_WIFI;
+#endif
+
+#ifdef RWL_DONGLE
+	remote_type = REMOTE_DONGLE;
+#endif /* RWL_DONGLE */
+#ifdef RWL_SERIAL
+	remote_type = REMOTE_SERIAL;
+	if (argc < 2) {
+		DPRINT_ERR(ERR, "Port name is required from the command line\n");
+	} else {
+		(void)*argv++;
+		DPRINT_DBG(OUTPUT, "Port name is %s\n", *argv);
+		transport_descriptor = *(int*) rwl_open_transport(remote_type, *argv, 0, 0);
+	}
+#endif  /* RWL_SERIAL */
+#endif /* RWL_DONGLE ||RWL_SERIAL ||RWL_WIFI */
+#ifdef RWLASD
+	g_serv_sock_desc = transport_descriptor;
+#endif
+	return transport_descriptor;
+
+}
+
+/* Function: remote_rx_header
+ * This function will receive the CDC header from client
+ * for socket transport
+ * It will receive the command or ioctl from dongle driver for
+ * dongle UART serial transport and wifi transport.
+ * Arguments: wl - handle to driver
+ *          : Des - Socket Descriptor to pass in AcceptConnection
+ *          : g_rwl_hndle - Return socket handle that is used for transmission
+ *          :           and reception of data in case of socket
+ *                        In case of serial, it is just a return value
+ */
+static int
+remote_rx_header(void *wl, int trans_Des)
+{
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(trans_Des);
+
+#ifdef RWL_SOCKET
+	{
+		struct sockaddr_in ClientAddress;
+		int SizeOfCliAdd = sizeof(ClientAddress);
+
+		/* Get the socket handle g_rwl_hndle for transmission & reception */
+		if ((g_rwl_hndle = rwl_acceptconnection(trans_Des,
+		                                        (struct sockaddr *)&ClientAddress,
+		                                        &SizeOfCliAdd)) == BCME_ERROR) {
+			return BCME_ERROR;
+		}
+
+		/* Get CDC header in order to determine buffer requirements */
+		if ((g_rem_ptr = remote_CDC_rx_hdr((void *)&g_rwl_hndle, 0)) == NULL) {
+			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
+			return BCME_ERROR;
+		}
+	}
+#endif /* RWL_SOCKET */
+
+#ifdef RWL_DONGLE
+	{
+		void *pkt_ptr = NULL;
+		int error;
+
+		/* wl driver is polled after every 200 ms (POLLING_TIME) */
+		rwl_sleep(POLLING_TIME);
+
+		if ((error = rwl_var_getbuf(wl, cmdname, NULL, 0, &pkt_ptr)) < 0) {
+			DPRINT_ERR(ERR, "No packet in wl driver\r\n");
+			return BCME_ERROR;
+		}
+
+		DPRINT_DBG(OUTPUT, "Polling the wl driver, error status=%d\n", error);
+
+		if ((*(int *)pkt_ptr) == 0) {
+			DPRINT_DBG(ERR, "packet not received\n");
+			return BCME_ERROR;
+		}
+
+		DPRINT_DBG(OUTPUT, "packet received\n");
+
+		/* Extract CDC header in order to determine buffer requirements */
+		memcpy(g_rem_pkt_ptr, pkt_ptr, sizeof(rem_packet_t));
+		g_rem_ptr = &g_rem_pkt_ptr->rem_cdc;
+	}
+#endif /* RWL_DONGLE */
+
+#ifdef RWL_SERIAL
+	{
+		if (g_rwl_hndle == -1) {
+			DPRINT_ERR(ERR, "failed to open com port.\r\n");
+			return BCME_ERROR;
+		}
+
+		if ((g_rem_ptr = remote_CDC_rx_hdr((void *)&g_rwl_hndle, 1)) == NULL) {
+			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
+			return BCME_ERROR;
+		}
+	}
+#endif  /* RWL_SERIAL */
+
+#ifdef RWL_WIFI
+	{
+		/* Poll the driver for the valid action frame and update the CDC + data  */
+		dot11_action_wifi_vendor_specific_t *list;
+
+		if ((list = rwl_wifi_allocate_actionframe()) == NULL) {
+			DPRINT_DBG(OUTPUT, "remote_rx_header: Failed to allocate frame \n");
+			return BCME_ERROR;
+		}
+
+		if (remote_CDC_DATA_wifi_rx((void *)wl, list) < 0) {
+			free(list);
+			return BCME_ERROR;
+		}
+
+		/* copy the valid length of the data to the g_rem_pkt_ptr */
+		memcpy(g_rem_pkt_ptr, &list->data[0], sizeof(rem_packet_t));
+		g_rem_ptr = &g_rem_pkt_ptr->rem_cdc;
+		free(list);
+	}
+#endif /* RWL_WIFI */
+
+	rwl_swap_header(g_rem_ptr, NETWORK_TO_HOST);
+
+	DPRINT_INFO(OUTPUT, "%d %d %d %d\r\n", g_rem_ptr->msg.cmd,
+	g_rem_ptr->msg.len, g_rem_ptr->msg.flags, g_rem_ptr->data_len);
+
+	return SUCCESS;
+
+}
+
+/* Function: remote_rx_data
+ * This function will receive the data from client
+ * for different transports
+ * In case of socket the data comes from a open TCP socket
+ * However in case of dongle UART or wi-fi the data is accessed
+ * from the driver buffers.
+ */
+int
+remote_rx_data(void* buf_ptr)
+{
+#if defined(RWL_SOCKET) || defined(RWL_SERIAL)
+
+	if ((remote_CDC_rx((void *)&g_rwl_hndle, g_rem_ptr, buf_ptr,
+	                             g_rem_ptr->msg.len, 0)) == BCME_ERROR) {
+		DPRINT_ERR(ERR, "Reading CDC %d data bytes failed\n", g_rem_ptr->msg.len);
+		return BCME_ERROR;
+	}
+#elif defined(RWL_DONGLE) || defined(RWL_WIFI)
+	if (g_rem_ptr->data_len != 0) {
+		int length = g_rem_ptr->data_len;
+		if (g_rem_ptr->data_len > g_rem_ptr->msg.len) {
+			length = g_rem_ptr->msg.len;
+		}
+		memcpy(buf_ptr, g_rem_pkt_ptr->message, length);
+	}
+	else
+		buf_ptr = NULL;
+#else
+	UNUSED_PARAMETER(buf_ptr);
+#endif /* RWL_SOCKET || RWL_SERIAL */
+	return SUCCESS;
+}
+
+#ifdef RWL_DONGLE
+/*
+ * Function to send the serial response to wl driver
+ * The function calculates the no of frames based on the DATA_FRAME_LEN
+ * adds cdc header to every frame, copies the header and fragmented frame
+ * into rem_buf_ptr and sends the packet down to wl driver
+ */
+
+static int
+rwl_serial_fragmented_tx(void* wl, rem_ioctl_t *rem_ptr, uchar *buf_ptr, int error)
+{
+	rem_ioctl_t *loc_ptr = &loc_cdc;
+	uchar* rem_buf_ptr;
+	uint noframes = 1;    /* Default noframes = 1 */
+	uint count;
+	uint frame_count;
+	uint rem_bytes;
+
+	loc_ptr->msg.cmd = error;
+	loc_ptr->msg.flags = REMOTE_REPLY;
+	loc_ptr->msg.len = rem_ptr->msg.len;
+	loc_ptr->data_len = rem_ptr->data_len;
+
+	/* Fragment the result if it is more than DATA_FRAME_LEN (960) */
+	if (loc_ptr->msg.len > DATA_FRAME_LEN) {
+		/* Calculate no of frames */
+		noframes = (loc_ptr->msg.len)/DATA_FRAME_LEN;
+		if ((loc_ptr->msg.len) % DATA_FRAME_LEN > 0) {
+			noframes += 1;
+			rem_bytes = (loc_ptr->msg.len) % DATA_FRAME_LEN;
+		} else {
+			rem_bytes = DATA_FRAME_LEN;
+		}
+	} else {
+		rem_bytes = loc_ptr->msg.len;
+	}
+	DPRINT_INFO(OUTPUT, "No of frames = %d, rem_bytes:%d\n", noframes, rem_bytes);
+	count = 0;
+	frame_count = noframes;
+	rem_buf_ptr = (uchar*)malloc(DONGLE_TX_FRAME_SIZE + REMOTE_SIZE);
+
+	while (count < noframes) {
+		memset(rem_buf_ptr, 0, DONGLE_TX_FRAME_SIZE + REMOTE_SIZE);
+		/* Send reply to client */
+		rem_ptr->msg.cmd = loc_ptr->msg.cmd;
+		rem_ptr->msg.flags = loc_ptr->msg.flags;
+		rem_ptr->msg.len = loc_ptr->msg.len;
+
+		if (frame_count == 1)
+			rem_ptr->data_len = rem_bytes;
+		else
+			rem_ptr->data_len = DATA_FRAME_LEN;
+
+		DPRINT_DBG(OUTPUT, "GET--rem_ptr->data_len=%d\n", rem_ptr->data_len);
+
+		/* Copy CDC Header */
+		memcpy(rem_buf_ptr, (uchar*)rem_ptr, REMOTE_SIZE);
+
+		/* Copy Data now */
+		memcpy(&rem_buf_ptr[REMOTE_SIZE], &buf_ptr[count*DATA_FRAME_LEN],
+		                                              rem_ptr->data_len);
+		count++;
+		frame_count--;
+
+		DPRINT_INFO(OUTPUT, "FRAME %d\n", count);
+		DPRINT_INFO(OUTPUT, "%d %d  %d  %d\n", rem_ptr->msg.cmd, rem_ptr->msg.len,
+			rem_ptr->msg.flags, rem_ptr->data_len);
+
+		rwl_sync_delay(noframes);
+
+		if ((error = rwl_var_setbuf(wl, cmdname, rem_buf_ptr,
+		            DONGLE_TX_FRAME_SIZE+REMOTE_SIZE)) < 0) {
+			DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", error);
+			if (rem_buf_ptr)
+				free(rem_buf_ptr);
+			return BCME_ERROR;
+		}
+		else
+			DPRINT_INFO(OUTPUT, "Packet sent to wl driver,error=%d\n", error);
+	}
+
+	if (rem_buf_ptr)
+		free(rem_buf_ptr);
+
+	return error;
+}
+
+/* This function transmits the response to the dongle driver in the case
+ * of serial dongle transport.
+ * In the case of big response, it calls the rwl_serial_fragmented_response
+ * function to fragment the response and sends down to the driver.
+ */
+
+static int
+remote_CDC_dongle_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags)
+{
+	int error;
+	rem_ioctl_t resp_rem_cdc;
+
+	if (flags & REMOTE_SET_IOCTL) {
+		uchar* rem_buf_ptr;
+		/* for set commands message length and data length should be set to zero
+		 * unlike Get Ioctl which will have valid data and message length
+		 */
+		resp_rem_cdc.msg.len = 0;
+		resp_rem_cdc.data_len = 0;
+		resp_rem_cdc.msg.cmd = cmd;
+		resp_rem_cdc.msg.flags = REMOTE_REPLY;
+
+		DPRINT_INFO(OUTPUT, "Set:Resp packet:%d %d %d %d\n", resp_rem_cdc.msg.cmd,
+		resp_rem_cdc.msg.len, resp_rem_cdc.msg.flags, resp_rem_cdc.data_len);
+
+		if ((rem_buf_ptr = (uchar*)malloc(DONGLE_TX_FRAME_SIZE + REMOTE_SIZE)) == NULL) {
+			DPRINT_ERR(ERR, "malloc failed for remote_CDC_dongle_tx\n");
+			return BCME_ERROR;
+		}
+
+		/* Send reply to client here */
+		memcpy(rem_buf_ptr, (char*)(&resp_rem_cdc), REMOTE_SIZE);
+		if ((error = rwl_var_setbuf((void*)wl, cmdname, rem_buf_ptr,
+		                 DONGLE_TX_FRAME_SIZE + REMOTE_SIZE)) < 0) {
+			DPRINT_ERR(ERR, "unable to send SET results to driver=%d\n", error);
+		} else
+			DPRINT_INFO(OUTPUT, "Packet sent to wl driver, error=%d\n", error);
+
+		if (rem_buf_ptr)
+			free(rem_buf_ptr);
+
+	} else { /* GET_IOCTL */
+		resp_rem_cdc.msg.cmd = cmd;
+		resp_rem_cdc.msg.len = buf_len;
+		resp_rem_cdc.msg.flags = flags;
+		resp_rem_cdc.data_len = data_len;
+		if ((error = rwl_serial_fragmented_tx(wl, &resp_rem_cdc, buf, cmd)) < 0)
+			DPRINT_ERR(ERR, "wl_server_serial: Return error code failed\n");
+	}
+	return error;
+}
+#endif /* RWL_DONGLE */
+
+/* This function gets the command send by the client from the dongle driver */
+int
+rwl_var_getbuf(void* wl, const char* iovar, void* param, int param_len, void** buf_ptr)
+{
+	int len;
+
+	memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy((char*)rwl_buf, iovar);
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&rwl_buf[len], param, param_len);
+
+	*buf_ptr = rwl_buf;
+
+	return wl_get(wl, WLC_GET_VAR, &rwl_buf[0], WLC_IOCTL_MAXLEN);
+}
+
+/* This function will send the buffer to the dongle driver */
+int
+rwl_var_setbuf(void* wl, const char* iovar, void* param, int param_len)
+{
+	int len;
+
+	memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy((char*)rwl_buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&rwl_buf[len], param, param_len);
+
+	len  += param_len;
+
+	DPRINT_DBG(OUTPUT, "setbuf:%s, len:%d\n", rwl_buf, len);
+
+	return wl_set(wl, WLC_SET_VAR, &rwl_buf[0], len);
+}
+
+/* This function will send the buffer to the dongle driver */
+int
+rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len)
+{
+	int len;
+
+	memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy((char*) rwl_buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy((void*)&rwl_buf[len+ OFFSETOF(wl_action_frame_t, data)], param, param_len);
+
+	/* Set the PacketID (not used by remote WL */
+	memset((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, packetId)], 0, 4);
+
+	/* Set the dest addr */
+	memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, da)],
+	(void*)&rwlea,
+	ETHER_ADDR_LEN);
+
+	/*  set the length */
+	memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, len)], (void*) &param_len, 2);
+
+	len  += param_len + ETHER_ADDR_LEN + 2 + 4;
+
+	DPRINT_DBG(OUTPUT, "setbuf:%s, len:%d\n", rwl_buf, len);
+
+	return wl_set(wl, WLC_SET_VAR, &rwl_buf[0], len);
+}
+/*
+ * This function is used for transmitting the response over different
+ * transports.
+ * In case of socket the data is directly sent to the client which is waiting on a open socket.
+ * In case of socket the data is sent in one big chunk unlike other transports
+ *
+ * In case of serial the data is sent to the driver using remote_CDC_dongle_tx function
+ * which in turn may fragment the data and send it in chunks to the client.
+ *
+ * In case of wi-fi the data is sent to the driver using the remote_CDC_tx. However
+ * in this case the data is converted into 802.11 Action frames and sent using wi-fi driver.
+ * Arguments: wl - Driver handle
+ *            hndle - Socket handle for socket transport.
+ */
+int
+remote_tx_response(void *wl, void* buf_ptr, int cmd)
+{
+	int error = -1;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(buf_ptr);
+	UNUSED_PARAMETER(cmd);
+
+#if defined(RWL_SOCKET) || defined(RWL_SERIAL)
+	if ((error = remote_CDC_tx((void*)&g_rwl_hndle, cmd, buf_ptr, g_rem_ptr->msg.len,
+	                                  g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
+		DPRINT_ERR(ERR, "wl_server: Return results failed\n");
+#endif /* RWL_SOCKET || RWL_SERIAL */
+
+#ifdef RWL_DONGLE
+	if ((error = remote_CDC_dongle_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
+	                          g_rem_ptr->data_len, g_rem_ptr->msg.flags)) < 0)
+		DPRINT_ERR(ERR, "wl_server: Return results failed\n");
+#endif /* RWL_DONGLE */
+
+#ifdef RWL_WIFI
+	/* Purge all the queued cmd's , this to ensure late response time out at */
+	/* client side and client might issue the next cmd if server is slow */
+	rwl_wifi_purge_actionframes(wl);
+	if ((g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) ||
+		(g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)||
+		(g_rem_ptr->msg.flags & REMOTE_ASD_CMD) ||
+		(g_rem_ptr->msg.flags & REMOTE_VISTA_CMD)) {
+		if ((error = remote_CDC_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
+			g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
+			DPRINT_ERR(ERR, "Wifi_server: Return results failed\n");
+	} else {
+		if ((error = remote_CDC_tx(wl, cmd, buf_ptr, 0, 0, REMOTE_REPLY, 0)) < 0)
+			DPRINT_ERR(ERR, "Failed due to bad flag %d\n", g_rem_ptr->msg.flags);
+	}
+#endif /* RWL_WIFI */
+	return error;
+}
+
+/* Close the Socket handle */
+void close_sock_handle(int hndle)
+{
+#ifdef RWL_SOCKET
+	rwl_close_pipe(remote_type, (void*)&hndle);
+#else
+	UNUSED_PARAMETER(hndle);
+#endif
+}
+
+
+/*
+ * Send the response to the remote if the channel of the server matches with the
+ * server channel.
+ */
+void remote_wifi_response(void* wl)
+{
+#ifdef RWL_WIFI
+	dot11_action_wifi_vendor_specific_t *list;
+
+	if ((list = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_DBG(OUTPUT, "remote_wifi_response: Failed to allocate frame \n");
+		return;
+	}
+
+	/* it's sync frame and received from client */
+	memcpy((char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET],
+	&g_rem_pkt_ptr[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE);
+	memcpy((char*)&list->data[REMOTE_SIZE], g_rem_pkt_ptr->message,
+	RWL_WIFI_FRAG_DATA_SIZE);
+	list->type = RWL_WIFI_FIND_MY_PEER;
+	/* Store the client mac addr */
+	memcpy((void*)&rwlea, (void*)&list->data[RWL_DUT_MAC_ADDRESS_OFFSET], ETHER_ADDR_LEN);
+	/* send the response to client if server is on the same channel */
+	rwl_wifi_find_server_response(wl, list);
+
+	free(list);
+#else
+	UNUSED_PARAMETER(wl);
+#endif /* RWL_WIFI */
+	return;
+}
+
+/* Function to check IN-dongle mode firmware */
+int
+rwl_iovar_check(void *wl)
+{
+	void *ptr;
+#ifdef RWL_WIFI
+	dot11_action_wifi_vendor_specific_t rec_frame;
+
+	/* Check for indongle mode firmware */
+	return rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, &rec_frame,
+	RWL_WIFI_ACTION_FRAME_SIZE, &ptr);
+#endif
+	UNUSED_PARAMETER(ptr);
+	UNUSED_PARAMETER(wl);
+#ifdef RWL_DONGLE
+	return rwl_var_getbuf(wl, "remote", NULL, 0, &ptr);
+#else
+	return 0;
+#endif
+}
+
+
+#ifndef TARGETOS_symbian
+/* Function to get a ctrl-c packet */
+int
+get_ctrlc_header(void *wl)
+{
+#if defined(RWL_SOCKET) || defined(RWL_SERIAL)
+	fd_set fdset;
+	struct timeval tv;
+	UNUSED_PARAMETER(wl);
+	FD_ZERO(&fdset);
+	FD_SET((unsigned)g_rwl_hndle, &fdset);
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+	if ((select(g_rwl_hndle+1, &fdset, NULL, NULL, &tv)) > 0) {
+		if (FD_ISSET(g_rwl_hndle, &fdset)) {
+			remote_CDC_rx_hdr((void *)&g_rwl_hndle, 0);
+			return BCME_OK;
+		}
+	}
+	return BCME_ERROR;
+
+#else
+	return remote_rx_header(wl, 0);
+#endif /* if defined(RWL_SOCKET) || defined(RWL_SERIAL) */
+}
+#endif /* TARGETOS_symbian */
+
+/* Main server module common for all transports
+ * This module will do the initial transport setups.
+ * Then it receives the command from client in CDC format
+ * and transmits the response back to the client.
+ * In the case of socket, it receives the command from the client
+ * and sends the response directly to the client via TCP socket.
+ *
+ * In the case of serial & wifi , it receives the command from the driver
+ * and sends the response to the driver.
+ */
+int
+remote_server_exec(int argc, char **argv, void *wl)
+{
+	int err;
+	int transport_descriptor;
+	char *async_cmd_flag = NULL;
+	int skip;
+	int download_flag = 0;
+	FILE *fp = NULL;
+	char *fn = "dwnldfile.bin";
+	char old_intf_name[IFNAMSIZ];
+#ifdef WIN32
+	char shell_fname[MAX_SHELL_FILE_LENGTH];
+	DWORD dwlen;
+#endif
+#ifdef RWL_DONGLE
+	int uart_enable = 1;
+	/* To set dongle flag when dongle server starts */
+	if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
+		sizeof(int))) < 0) {
+			DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
+	}
+#endif
+	if (rwl_iovar_check (wl) < 0) {
+		DPRINT_ERR(ERR, "wl_server: RWL_WIFI/RWL_DONGLE not defined ");
+		DPRINT_ERR(ERR, "Or In-Dongle mode enabled\n");
+		exit(0);
+	}
+	/* Initialise for all the transports - socket, serial, and wifi
+	 * In Socket transport, main socket handler will be returned.
+	 */
+	if ((transport_descriptor = rwl_transport_setup(argc, argv)) < 0)
+		return BCME_ERROR;
+
+#ifdef RWL_WIFI
+	remote_wifi_ser_init_cmds(wl);
+#endif
+	/* Create a directory /tmp/RWL for the shell response files */
+	if (rwl_create_dir() < 0)
+		return BCME_ERROR;
+
+
+#ifdef RWLASD
+	/* DUT initialization function */
+	wfa_dut_init(&trafficBuf, &respBuf, &parmsVal, &xcCmdBuf, &toutvalp);
+#endif
+
+	/* Copy old interface name to restore it */
+	store_old_interface(wl, old_intf_name);
+
+	while (1) {
+		uchar *buf_ptr = NULL;
+		char *errstr = NULL;
+#ifdef VISTA_SERVER
+		int index;
+		char *vista_buf[MAX_VISTA_ARGC];
+#endif
+#ifdef RWL_SERIAL
+		g_rwl_hndle = transport_descriptor;
+#else
+		g_rwl_hndle = -1;
+#endif
+#ifdef RWL_DONGLE
+		if (set_ctrlc) {
+			uart_enable = 0;
+			if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
+				sizeof(int))) < 0) {
+				DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
+			}
+			set_ctrlc = 0;
+			exit(0);
+		}
+#endif /* RWL_DONGLE */
+
+		/* Receive the CDC header */
+		if ((remote_rx_header(wl, transport_descriptor)) == BCME_ERROR) {
+			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
+			continue;
+		}
+
+		DPRINT_INFO(OUTPUT, "REC : cmd %d\t msg len %d  msg flag %d\t msg status %d\n",
+		            g_rem_ptr->msg.cmd, g_rem_ptr->msg.len,
+		            g_rem_ptr->msg.flags, g_rem_ptr->msg.status);
+
+#ifdef RWL_WIFI
+		/* send the response to remote if it is findserver cmd, this is specific to wifi */
+		if (g_rem_ptr->msg.flags & REMOTE_FINDSERVER_IOCTL) {
+			remote_wifi_response(wl);
+			continue;
+		}
+#endif /* RWL_WIFI */
+
+		/*
+		 * Allocate buffer only if there is a response message expected.
+		 * Some commands such as up/down do not output anything.
+		 */
+		if (g_rem_ptr->msg.len) {
+			if ((buf_ptr = malloc(g_rem_ptr->msg.len)) == NULL) {
+				DPRINT_ERR(ERR, "malloc of %d bytes failed\n", g_rem_ptr->msg.len);
+				continue;
+			}
+		}
+
+		/* Receive the data */
+		if ((err = remote_rx_data(buf_ptr)) == BCME_ERROR) {
+			if (buf_ptr)
+				free(buf_ptr);
+			continue;
+		}
+
+		/* Process RWL negotiate commands */
+		if (g_rem_ptr->msg.flags & REMOTE_NEGOTIATE_CMD) {
+			if (g_rem_ptr->msg.cmd == NEGOTIATE_GET_OS) {
+				if (g_rem_ptr->msg.len >= sizeof(int)) {
+					*(int*)buf_ptr = LINUX_OS;
+					g_rem_ptr->msg.len = sizeof(int);
+
+					DPRINT_INFO(OUTPUT, "RESP : os type %d\n", *(int*)buf_ptr);
+					if (remote_tx_response(wl, buf_ptr, 0) < 0)
+						DPRINT_ERR(ERR, "\nReturn results failed\n");
+				}
+			}
+#ifdef RWL_SOCKET
+			close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+			if (buf_ptr)
+				free(buf_ptr);
+			continue;
+		}
+
+		/* Process command */
+		if (g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) {
+			/* Get the response length first and get the response buffer in case of
+			 * synchronous shell commands and the buf_ptr will have the response file
+			 * name. In case of asynchronous shell commands, buf_ptr
+			 * will be get updated by the remote_shell_execute function.
+			 */
+			need_speedy_response = 1;
+#ifndef WIN32
+			if (buf_ptr) {
+				async_cmd_flag = strstr((char*)buf_ptr, "%");
+			}
+			if ((err = remote_shell_execute((char*)buf_ptr, wl)) > 0) {
+				if (async_cmd_flag)
+					g_rem_ptr->msg.len = err;
+			}
+			/* Sync shell command: No need to send response from here */
+			else {
+#ifdef RWL_SOCKET
+				/* Transmitted to client. Then close the handle &
+				 * get the new handle for next transmission & reception.
+				 */
+				close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+				continue;
+			}
+#else
+			if ((err = remote_shell_execute((char*)buf_ptr, wl)) != SUCCESS) {
+				DPRINT_ERR(ERR, "Error in executing shell command\n");
+				if (buf_ptr)
+					free(buf_ptr);
+#ifdef RWL_SOCKET
+				/* Transmitted to client. Then close the handle &
+				 * get the new handle for next transmission & reception.
+				 */
+				close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+				continue;
+			}
+			/* Get the response from the temporary file */
+			if ((err = remote_shell_get_resp(shell_fname, wl)) != SUCCESS) {
+				DPRINT_ERR(ERR, "Error in executing shell command\n");
+			}
+			if (buf_ptr)
+				free(buf_ptr);
+#ifdef RWL_SOCKET
+			/* Transmitted to client. Then close the handle &
+			 * get the new handle for next transmission & reception.
+			 */
+			close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+			continue;
+#endif	/* WIN32 */
+		} /* REMOTE_SHELL_CMD */
+
+#ifdef RWLASD
+		if (g_rem_ptr->msg.flags & REMOTE_ASD_CMD) {
+			if ((err = remote_asd_exec(buf_ptr, (int *)&g_rem_ptr->msg.len)) < 0) {
+				DPRINT_ERR(ERR, "Error in executing asd command\n");
+			}
+		} /* REMOTE_ASD_CMD */
+#endif
+
+/*
+ * added to take care of OID base problem for cross OS RWL cleint server
+ * In case of LX Server and WIN32 client OID base need to be removed
+ * In case of WIN32 server and LX client OID base need to be added
+ */
+		if (!(g_rem_ptr->msg.flags & REMOTE_ASD_CMD)) {
+		if (g_rem_ptr->msg.cmd > MAX_IOVAR)
+			g_rem_ptr->msg.cmd -= WL_OID_BASE;
+#if defined(WIN32)
+		if (g_rem_ptr->msg.cmd < MAX_IOVAR)
+			g_rem_ptr->msg.cmd += WL_OID_BASE;
+#endif
+		}
+#ifdef VISTA_SERVER
+		if (g_rem_ptr->msg.flags & REMOTE_VISTA_CMD) {
+			vista_buf[0] = strtok(buf_ptr, " \t\n");
+			for (index = 1; (vista_buf[index] = strtok(NULL, " \t\n")) != NULL;
+				index++);
+			if ((err = remote_vista_exec(wl, vista_buf)) < 0) {
+				DPRINT_ERR(ERR, "Error in executing vista command\n");
+			}
+			memcpy(buf_ptr, vista_buf[0], strlen(vista_buf[0]));
+			g_rem_ptr->msg.len = strlen(vista_buf[0]);
+		} /* REMOTE_VISTA_CMD */
+#endif /* VISTA_SERVER */
+
+#ifndef RWL_DONGLE
+		if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
+			g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
+			if (strlen(g_rem_ptr->intf_name) != 0) {
+				struct ifreq ifr;
+				/* validate the interface */
+				memset(&ifr, 0, sizeof(ifr));
+				if (g_rem_ptr->intf_name)
+					strncpy(ifr.ifr_name, g_rem_ptr->intf_name, IFNAMSIZ);
+
+				if (wl_check((void *)&ifr)) {
+					DPRINT_ERR(ERR, "%s: wl driver adapter not found\n",
+						g_rem_ptr->intf_name);
+					/* Signal end of command output */
+					g_rem_ptr->msg.len = 0;
+					remote_tx_response(wl, NULL, BCME_NODEVICE);
+					if (buf_ptr)
+						free(buf_ptr);
+#ifdef RWL_SOCKET
+					close_sock_handle(g_rwl_hndle);
+#endif
+					continue;
+				}
+
+				if (set_interface(wl, g_rem_ptr->intf_name) == BCME_OK)
+					DPRINT_DBG(OUTPUT, "\n %s Interface will be used \n",
+						(char *)wl);
+			}
+		}
+#endif /* ifndef RWL_DONGLE */
+		if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL ||
+			g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
+#ifdef WIN32
+#if defined(RWL_DONGLE) || defined(RWL_WIFI)
+			/* For commands with msg length as zero initialize the buffer to null */
+			if (g_rem_ptr->msg.len == 0)
+				buf_ptr = NULL;
+#endif
+#else
+			if (g_rem_ptr->msg.len == 0)
+				buf_ptr = NULL;
+#endif /* WIN32 */
+
+			if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
+				if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
+				    !strncmp((const char *)buf_ptr,
+					     "init", g_rem_ptr->msg.len)) {
+					DPRINT_INFO(OUTPUT, "REC : init command\n");
+					err = 0;
+				} else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
+				   !strncmp((const char *)buf_ptr,
+					    "download", g_rem_ptr->msg.len)) {
+					DPRINT_INFO(OUTPUT, "REC : download command\n");
+					download_flag =  download_flag? 0: 1;
+					if (download_flag) {
+						DPRINT_INFO(OUTPUT, "download started\n");
+						if (!(fp = fopen(fn, "wb"))) {
+							DPRINT_ERR(ERR, "Failed to open file\n");
+							err = -2;
+						}
+					} else {
+						DPRINT_INFO(OUTPUT, "download completed\n");
+						if (fp != NULL)
+							fclose(fp);
+					}
+					err = 0;
+				} else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
+				   !strncmp((const char *)buf_ptr,
+					    "membytes", g_rem_ptr->msg.len)) {
+					DPRINT_INFO(OUTPUT, "REC : membytes command\n");
+					skip = strlen("membytes ") + 8;
+					if (fp != NULL)
+						fwrite(buf_ptr + skip, 1,
+						       g_rem_ptr->msg.len - skip, fp);
+					else
+						DPRINT_ERR(ERR, "Download file has been closed.\n");
+					err = 0;
+				} else {
+					err = wl_ioctl(wl, g_rem_ptr->msg.cmd,
+					       (void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
+					DPRINT_INFO(OUTPUT, "SEND : cmd %d\t msg len %d\n",
+					    g_rem_ptr->msg.cmd, g_rem_ptr->msg.len);
+					DPRINT_INFO(OUTPUT, "error code: %d\n", err);
+				}
+			}
+			if (err == BCME_IOCTL_ERROR) {
+				if (rwl_var_getbuf(wl, "bcmerrorstr", NULL, 0, (void**)&errstr)) {
+					DPRINT_ERR(ERR, "Error in executing wl_ioctl\r\n");
+				} else {
+					DPRINT_ERR(ERR, "%s\n", errstr);
+				}
+				DPRINT_ERR(ERR, "Setting Default Interface1 \n");
+				set_interface(wl, old_intf_name);
+			}
+
+			if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
+				err = dhd_ioctl(wl, g_rem_ptr->msg.cmd,
+				(void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
+			}
+			g_rem_ptr->msg.flags = REMOTE_SET_IOCTL;
+
+		} /* RDHD/REMOTE_SET_IOCTL */
+
+		if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
+			g_rem_ptr->msg.flags & RDHD_GET_IOCTL) {
+			if (g_rem_ptr->msg.cmd == WLC_GET_VAR && buf_ptr &&
+				strncmp((const char *)buf_ptr, "exit", g_rem_ptr->msg.len) == 0) {
+					/* exit command from remote client terminates server */
+					free(buf_ptr);
+					break;
+			}
+			if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)
+				err = wl_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
+					g_rem_ptr->msg.len, FALSE);
+			if (err == BCME_IOCTL_ERROR) {
+				if (rwl_var_getbuf(wl, "bcmerrorstr", NULL, 0, (void**)&errstr)) {
+					DPRINT_ERR(ERR,
+						"REMOTE_GET_IOCTL::Error in executing wl_ioctl\n");
+				} else {
+					DPRINT_ERR(ERR, "%s\n", errstr);
+				}
+				DPRINT_ERR(ERR, "Setting Default Interface \n");
+				set_interface(wl, old_intf_name);
+			}
+
+			if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL)
+				err = dhd_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
+					g_rem_ptr->msg.len, FALSE);
+			g_rem_ptr->msg.flags = REMOTE_GET_IOCTL;
+		} /* REMOTE_GET_IOCTL */
+		DPRINT_INFO(OUTPUT, "RESP : cmd %d\t msg len %d\n",
+		g_rem_ptr->msg.cmd, g_rem_ptr->msg.len);
+		/* setting back default interface  */
+		set_interface(wl, old_intf_name);
+		/* Transmit the response results */
+		if (remote_tx_response(wl, buf_ptr, err) < 0) {
+			DPRINT_ERR(ERR, "\nReturn results failed\n");
+		}
+
+#ifdef RWL_SOCKET
+		if (g_rem_ptr->msg.flags != REMOTE_SHELL_CMD)
+		/* Transmitted to client. Then close the handle & get the new handle
+		 * for next transmission & reception. In case of shell commands this
+		 * should be closed in respective shellproc files.
+		 */
+		close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+
+		if (buf_ptr) {
+			free(buf_ptr);
+		}
+	} /* end of while */
+#if defined(RWL_SOCKET)
+	/* Close the main handle for socket */
+	close_sock_handle(transport_descriptor);
+#elif defined(RWL_SERIAL)
+	/* Close the main handle for serial pipe  */
+	rwl_close_pipe(remote_type, (void*)&transport_descriptor);
+#endif
+
+#ifdef RWLASD
+	wfa_dut_deinit();
+#endif
+
+	return err;
+}
diff --git a/src/wl/exe/wlu_server_shared.h b/src/wl/exe/wlu_server_shared.h
new file mode 100644
index 0000000..a63b5c1
--- /dev/null
+++ b/src/wl/exe/wlu_server_shared.h
@@ -0,0 +1,67 @@
+/*
+ * wl server declarations
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: wlu_server_shared.h 287128 2011-09-30 04:27:53Z $
+ */
+
+#ifndef _wlu_server_shared_h
+#define _wlu_server_shared_h
+
+	extern int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);
+
+	extern int dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set);
+
+#ifdef RWLASD
+/* streams' buffers */
+BYTE *xcCmdBuf = NULL, *parmsVal = NULL;
+BYTE *trafficBuf = NULL, *respBuf = NULL;
+struct timeval *toutvalp = NULL;
+#endif
+
+#define POLLING_TIME      			200
+#define DONGLE_TX_FRAME_SIZE   		1024
+#define MESSAGE_LENGTH				1024
+#define MAX_SHELL_FILE_LENGTH       50
+#define MAX_IOVAR				10000
+int remote_type = NO_REMOTE;
+rem_ioctl_t *g_rem_ptr;
+
+extern int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);
+
+/* Function prototypes from shellpoc_linux.c/shell_ce.c */
+extern int rwl_create_dir(void);
+extern int remote_shell_execute(char *buf_ptr, void *wl);
+extern int remote_shell_get_resp(char* shell_fname, void *wl);
+extern void rwl_wifi_find_server_response(void *wl, dot11_action_wifi_vendor_specific_t *rec_frame);
+extern dot11_action_wifi_vendor_specific_t *rwl_wifi_allocate_actionframe(void);
+
+/* Common code for serial and wifi */
+#if defined(RWL_DONGLE) || defined(RWL_WIFI) || defined(RWL_SERIAL)
+typedef struct rem_packet {
+	rem_ioctl_t rem_cdc;
+	uchar message[MESSAGE_LENGTH];
+} rem_packet_t;
+#define REMOTE_PACKET_SIZE sizeof(rem_packet_t)
+
+rem_packet_t *g_rem_pkt_ptr;
+rem_packet_t g_rem_pkt;
+#endif
+
+static struct ether_addr rwlea;
+
+static union {
+	uchar bufdata[WLC_IOCTL_MAXLEN];
+	uint32 alignme;
+} bufstruct_wlu;
+static uchar* rwl_buf = (uchar*) &bufstruct_wlu.bufdata;
+extern int need_speedy_response;
+
+#endif /* _wlu_server_shared_h_ */
diff --git a/src/wl/phymods/cmn/hal/include/phy_dbg_api.h b/src/wl/phymods/cmn/hal/include/phy_dbg_api.h
new file mode 100644
index 0000000..ced8146
--- /dev/null
+++ b/src/wl/phymods/cmn/hal/include/phy_dbg_api.h
@@ -0,0 +1,35 @@
+/*
+ * Debug module public interface (to MAC driver).
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id$
+ */
+
+#ifndef _phy_dbg_api_h_
+#define _phy_dbg_api_h_
+
+/* Debug message levels */
+#define PHYHAL_ERROR		0x0001
+#define PHYHAL_TRACE		0x0002
+#define PHYHAL_INFORM		0x0004
+#define PHYHAL_TMP		0x0008
+#define PHYHAL_TXPWR		0x0010
+#define PHYHAL_CAL		0x0020
+#define PHYHAL_ACI		0x0040
+#define PHYHAL_RADAR		0x0080
+#define PHYHAL_THERMAL		0x0100
+#define PHYHAL_PAPD		0x0200
+#define PHYHAL_FCBS		0x0400
+#define PHYHAL_WD		0x0800
+#define PHYHAL_RXIQ		0x1000
+
+#define PHYHAL_TIMESTAMP	0x8000
+
+#endif /* _phy_dbg_api_h_ */
diff --git a/src/wl/ppr/include/wlc_ppr.h b/src/wl/ppr/include/wlc_ppr.h
new file mode 100644
index 0000000..0329a75
--- /dev/null
+++ b/src/wl/ppr/include/wlc_ppr.h
@@ -0,0 +1,360 @@
+/*
+ * PHY module Power-per-rate API. Provides interface functions and definitions for opaque
+ * ppr structure for use containing regulatory and board limits and tx power targets.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: $
+ */
+
+#ifndef _wlc_ppr_h_
+#define _wlc_ppr_h_
+
+#include <bcmwifi_rates.h>
+#include <bcmutils.h>
+#ifdef BCMDRIVER
+#include <osl.h>
+#else
+#define osl_t void
+#endif
+
+/* Helper macro */
+#define PPR_CHSPEC_BW(x) (CHSPEC_IS80(x) ? WL_TX_BW_80 : \
+	(CHSPEC_IS40(x) ? WL_TX_BW_40 : WL_TX_BW_20))
+
+#ifndef BCMPHYCORENUM
+#define PPR_MAX_TX_CHAINS 3
+#else
+#if (BCMPHYCORENUM < 1) || (BCMPHYCORENUM > 3)
+#error Invalid number of PHY cores
+#endif /* BCMPHYCORENUM < 1 || BCMPHYCORENUM > 3 */
+#define PPR_MAX_TX_CHAINS (BCMPHYCORENUM)
+#endif /* !defined(BCMPHYCORENUM) */
+
+/* Opaque PPR data - it keeps its structure to itself */
+typedef struct ppr ppr_t;
+
+
+/* Power values for DSSS 1, 2, 5.5, 11 */
+typedef struct ppr_dsss_rateset { int8 pwr[WL_RATESET_SZ_DSSS]; } ppr_dsss_rateset_t;
+
+/* Power values for OFDM 6, 9, 12... 54 */
+typedef struct ppr_ofdm_rateset { int8 pwr[WL_RATESET_SZ_OFDM]; } ppr_ofdm_rateset_t;
+
+/* Power values one set of 8 HT MCS values (0-7, 8-15, etc) */
+typedef struct ppr_ht_mcs_rateset { int8 pwr[WL_RATESET_SZ_HT_MCS]; } ppr_ht_mcs_rateset_t;
+
+/* Power values one set of 10 VHT MCS values (0-9) */
+typedef struct ppr_vht_mcs_rateset { int8 pwr[WL_RATESET_SZ_VHT_MCS]; } ppr_vht_mcs_rateset_t;
+
+
+/* API Routines */
+
+/* Initialization routine for opaque PPR struct */
+void ppr_init(ppr_t* pprptr, wl_tx_bw_t bw);
+
+/* Reinitialization routine for opaque PPR struct */
+void ppr_clear(ppr_t* pprptr);
+
+
+/* Size routine for user alloc/dealloc */
+uint32 ppr_size(wl_tx_bw_t bw);
+
+/* Size routine for user serialization alloc */
+uint32 ppr_ser_size(const ppr_t* pprptr);
+
+/* Size routine for user serialization alloc for a given bw */
+uint32 ppr_ser_size_by_bw(wl_tx_bw_t bw);
+
+/* Init allocated memory with a ppr serialization head
+ * This function must be called if serialization side has different
+ * compilation conditions (e.g PPR_MAX_TX_CHAINS, WL_BEAMFORMING etc.)
+ */
+int ppr_init_ser_mem_by_bw(uint8* pbuf, wl_tx_bw_t bw, uint32 len);
+
+/* Init allocated memory with a ppr serialization head for the given ppr pointer
+ * This function must be called if serialization side has different
+ * compilation conditions (e.g PPR_MAX_TX_CHAINS, WL_BEAMFORMING etc.)
+ */
+int ppr_init_ser_mem(uint8* pbuf, ppr_t * ppr, uint32 len);
+
+/* Constructor routine for opaque PPR struct */
+ppr_t* ppr_create(osl_t *osh, wl_tx_bw_t bw);
+
+/* Destructor routine for opaque PPR struct */
+void ppr_delete(osl_t *osh, ppr_t* pprptr);
+
+/* Type routine for inferring opaque structure size */
+wl_tx_bw_t ppr_get_ch_bw(const ppr_t* pprptr);
+
+/* Type routine to get ppr supported maximum bw */
+wl_tx_bw_t ppr_get_max_bw(void);
+
+/* Get the DSSS values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	ppr_dsss_rateset_t* dsss);
+
+/* Get the OFDM values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	ppr_ofdm_rateset_t* ofdm);
+
+/* Get the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_get_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, ppr_ht_mcs_rateset_t* mcs);
+
+/* Get the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_get_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+ wl_tx_chains_t tx_chains, ppr_vht_mcs_rateset_t* mcs);
+
+/* Get the minimum power for a VHT MCS rate specified by Nss, with the given bw and tx chains.
+ * Disabled rates are ignored
+ */
+int ppr_get_vht_mcs_min(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+ wl_tx_chains_t tx_chains, int8* mcs_min);
+
+
+/* Routines to set target powers per rate for a whole rate set */
+
+/* Set the DSSS values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	const ppr_dsss_rateset_t* dsss);
+
+/* Set the OFDM values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const ppr_ofdm_rateset_t* ofdm);
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_ht_mcs_rateset_t* mcs);
+
+/* Set the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_vht_mcs_rateset_t* mcs);
+
+
+/* Routines to set a whole rate set to a single target value */
+
+/* Set the DSSS values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains, const int8 power);
+
+/* Set the OFDM values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const int8 power);
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power);
+
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power);
+
+
+/* Helper routines to operate on the entire ppr set */
+
+/* Ensure no rate limit is greater than the specified maximum */
+uint ppr_apply_max(ppr_t* pprptr, int8 max);
+
+/* Make disabled rates explicit. If one rate in a group is disabled, disable the whole group */
+int ppr_force_disabled(ppr_t* pprptr, int8 threshold);
+
+/*
+ * Reduce total transmitted power to level of constraint.
+ * For two chain rates, the per-antenna power must be halved.
+ * For three chain rates, it must be a third of the constraint.
+ */
+uint ppr_apply_constraint_total_tx(ppr_t* pprptr, int8 constraint);
+
+/* Ensure no rate limit is lower than the specified minimum */
+uint ppr_apply_min(ppr_t* pprptr, int8 min);
+
+
+/* Ensure no rate limit in this ppr set is greater than the corresponding limit in ppr_cap */
+uint ppr_apply_vector_ceiling(ppr_t* pprptr, const ppr_t* ppr_cap);
+
+/* Ensure no rate limit in this ppr set is lower than the corresponding limit in ppr_min */
+uint ppr_apply_vector_floor(ppr_t* pprptr, const ppr_t* ppr_min);
+
+
+/* Get the maximum power in the ppr set */
+int8 ppr_get_max(ppr_t* pprptr);
+
+/*
+ * Get the minimum power in the ppr set excluding disallowed
+ * rates and powers set to the minimum for the phy
+ */
+int8 ppr_get_min(ppr_t* pprptr, int8 floor);
+
+
+/* Get the maximum power for a given bandwidth in the ppr set */
+int8 ppr_get_max_for_bw(ppr_t* pprptr, wl_tx_bw_t bw);
+
+/* Get the minimum power for a given bandwidth  in the ppr set */
+int8 ppr_get_min_for_bw(ppr_t* pprptr, wl_tx_bw_t bw);
+
+
+typedef void (*ppr_mapfn_t)(void *context, uint8 *a, uint8 *b);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_dsss(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_ofdm(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_ht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_vht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_all(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2);
+
+/* Get the first index that is larger than a given power level */
+int16 ppr_get_idx(ppr_t* pprptr, int8 pwr);
+
+/* Set PPR struct to a certain power level */
+void ppr_set_cmn_val(ppr_t* pprptr, int8 val);
+
+/* Make an identical copy of a ppr structure (for ppr_bw==all case) */
+void ppr_copy_struct(ppr_t* pprptr_s, ppr_t* pprptr_d);
+
+/* Subtract each power from a common value and re-store */
+void ppr_cmn_val_minus(ppr_t* pprptr, int8 val);
+
+/* Compare two ppr variables p1 and p2, save the min. value of each
+ * contents to variable p1
+ */
+void ppr_compare_min(ppr_t* p1, ppr_t* p2);
+
+/* compare two ppr variables p1 and p2, save the max. value of each
+ * contents to variable p1
+ */
+void ppr_compare_max(ppr_t* p1, ppr_t* p2);
+
+/* Serialize the contents of the opaque ppr struct.
+ * Writes number of bytes copied, zero on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int ppr_serialize(const ppr_t* pprptr, uint8* buf, uint buflen, uint* bytes_copied);
+
+/* Deserialize the contents of a buffer into an existing opaque ppr struct.
+ * The ppr struct *must* be of the same type as the one that was serialized.
+ * Returns error code, BCME_OK if successful.
+ */
+int ppr_deserialize(ppr_t* pprptr, const uint8* buf, uint buflen);
+
+/* Deserialize the contents of a buffer into a new opaque ppr struct.
+ * Creates an opaque structure referenced by *pptrptr, NULL on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int ppr_deserialize_create(osl_t *osh, const uint8* buf, uint buflen, ppr_t** pprptr);
+
+/* Subtract a common value from each power and re-store */
+void ppr_minus_cmn_val(ppr_t* pprptr, int8 val);
+
+/* Add a common value to the given bw struct components */
+void ppr_plus_cmn_val(ppr_t* pprptr, int8 val);
+
+/* Multiply a percentage */
+void ppr_multiply_percentage(ppr_t* pprptr, uint8 val);
+
+
+#ifdef WLTXPWR_CACHE
+
+/**
+ * Usage of the WLTXPWR_CACHE API:
+ * 1. Reserve one or more entries in the cache for a specific chanspec:
+ * 		wlc_phy_txpwr_setup_entry(chanspec1);
+ * 		wlc_phy_txpwr_setup_entry(chanspec2);
+ * 2. Use any of the getter/setter functions. Note that they may return an error on a chanspec
+ *    that was not reserved. For setter functions, for pointer type arguments (e.g. ppr_t), the
+ *    cache maintains a reference to the caller provided object rather than copying it.
+ * 3. Use wlc_phy_txpwr_cache_clear() or wlc_phy_txpwr_cache_invalidate() to get rid of cache
+ *    entries. Note that this clears, amongst others, ppr_t structs.
+ *
+ * For non-BMAC builds, only the cache is allowed to delete the ppr_t object, and the driver code is
+ * not allowed to reuse it for another channel as it can when the cache is not being used.
+ *
+ * For BMAC builds, the cache has to be made to release the stf offsets object to avoid some nasty
+ * race conditions.
+ *
+ * Mike thinks when this is reimplemented for trunk he would consider having a reference count
+ * associated with each object to make this cleaner.
+ *
+ * Note that the functions start with wlc_phy_* despite not residing in the PHY code. This is
+ * probably for historical reasons.
+ */
+
+enum txpwr_cache_info_type {
+	TXPWR_CACHE_STF_OFFSETS,	/* PPR offsets for stf */
+	TXPWR_CACHE_POWER_OFFSETS,	/* PPR offsets for phy */
+	TXPWR_CACHE_NUM_TYPES,	/* How many types of pwr info */
+};
+
+#define TXPWR_STF_PWR_MIN_INVALID 0x80
+#define TXPWR_STF_TARGET_PWR_MIN_INVALID 0x40
+#define TXPWR_STF_TARGET_PWR_NOT_CACHED 0x20
+
+extern ppr_t* wlc_phy_get_cached_pwr(chanspec_t chanspec, uint pwr_type);
+
+extern int wlc_phy_set_cached_pwr(osl_t *osh, chanspec_t chanspec, uint pwr_type, ppr_t* pwrptr);
+
+extern uint8 wlc_phy_get_cached_pwr_max(chanspec_t chanspec, uint core);
+
+extern int wlc_phy_set_cached_pwr_max(chanspec_t chanspec, uint core, uint8 max_pwr);
+
+extern uint8 wlc_phy_get_cached_pwr_min(chanspec_t chanspec, uint core);
+
+extern int wlc_phy_set_cached_pwr_min(chanspec_t chanspec, uint core, uint8 min_pwr);
+
+extern int wlc_phy_get_cached_stf_target_pwr_min(chanspec_t chanspec);
+
+extern int wlc_phy_set_cached_stf_target_pwr_min(chanspec_t chanspec, int min_pwr);
+
+extern int8 wlc_phy_get_cached_txchain_offsets(chanspec_t chanspec, uint core);
+
+extern int wlc_phy_set_cached_txchain_offsets(chanspec_t chanspec, uint core, int8 offset);
+
+extern bool wlc_phy_txpwr_cache_is_cached(chanspec_t chanspec);
+
+extern bool wlc_phy_is_pwr_cached(uint pwr_type, ppr_t* pwrptr);
+
+extern void wlc_phy_uncache_pwr(uint pwr_type, ppr_t* pwrptr);
+
+extern chanspec_t wlc_phy_txpwr_cache_find_other_cached_chanspec(chanspec_t chanspec);
+
+extern void wlc_phy_txpwr_cache_clear(osl_t *osh, chanspec_t chanspec);
+
+extern void wlc_phy_txpwr_cache_invalidate(void);
+
+extern void wlc_phy_txpwr_cache_close(osl_t *osh);
+
+extern int wlc_phy_txpwr_setup_entry(chanspec_t chanspec);
+
+extern bool wlc_phy_get_stf_ppr_cached(chanspec_t chanspec);
+
+extern void wlc_phy_set_stf_ppr_cached(chanspec_t chanspec, bool bcached);
+
+extern int wlc_phy_get_cached_stf_pwr_min_dbm(void);
+
+extern void wlc_phy_set_cached_stf_pwr_min_dbm(int min_pwr);
+
+extern void wlc_phy_set_cached_stf_max_offset(chanspec_t chanspec, uint8 max_offset);
+
+extern uint8 wlc_phy_get_cached_stf_max_offset(chanspec_t chanspec);
+#endif /* WLTXPWR_CACHE */
+#endif	/* _wlc_ppr_h_ */
diff --git a/src/wl/ppr/src/wlc_ppr.c b/src/wl/ppr/src/wlc_ppr.c
new file mode 100644
index 0000000..448821a
--- /dev/null
+++ b/src/wl/ppr/src/wlc_ppr.c
@@ -0,0 +1,2456 @@
+/*
+ *  PHY module Power-per-rate API. Provides interface functions and definitions for
+ * ppr structure for use containing regulatory and board limits and tx power targets.
+ *
+ * Copyright (C) 2016, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: $
+ */
+
+
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <bcmwifi_channels.h>
+#include <wlc_ppr.h>
+
+#ifndef BCMDRIVER
+
+#ifndef WL_BEAMFORMING
+#define WL_BEAMFORMING /* enable TxBF definitions for utility code */
+#endif
+
+#ifndef bcopy
+#include <string.h>
+#include <stdlib.h>
+#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
+#endif
+
+#ifndef ASSERT
+#define ASSERT(exp)	do {} while (0)
+#endif
+#endif /* BCMDRIVER */
+
+/* ppr local TXBF_ENAB() macro because wlc->pub struct is not accessible */
+#ifdef WL_BEAMFORMING
+#if defined(WLTXBF_DISABLED)
+#define PPR_TXBF_ENAB()	(0)
+#else
+#define PPR_TXBF_ENAB()	(1)
+#endif
+#else
+#define PPR_TXBF_ENAB()	(0)
+#endif /* WL_BEAMFORMING */
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define PPR_SERIALIZATION_VER 1
+
+/* ppr deserialization header */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_deser_header {
+	uint8  version;
+	uint8  bw;
+	uint16 per_band_size;
+	uint32 flags;
+} BWL_POST_PACKED_STRUCT ppr_deser_header_t;
+
+
+typedef BWL_PRE_PACKED_STRUCT struct ppr_ser_mem_flag {
+	uint32 magic_word;
+	uint32 flag;
+} BWL_POST_PACKED_STRUCT ppr_ser_mem_flag_t;
+
+
+#define WLC_TXPWR_DB_FACTOR 4 /* conversion for phy txpwr cacluations that use .25 dB units */
+
+
+/* QDB() macro takes a dB value and converts to a quarter dB value */
+#ifdef QDB
+#undef QDB
+#endif
+#define QDB(n) ((n) * WLC_TXPWR_DB_FACTOR)
+
+
+/* Flag bits in serialization/deserialization */
+#define PPR_MAX_TX_CHAIN_MASK	0x00000003 /* mask of Tx chains */
+#define PPR_BEAMFORMING			0x00000004 /* bit indicates BF is on */
+#define PPR_SER_MEM_WORD		0xBEEFC0FF /* magic word indicates serialization start */
+
+
+/* size of serialization header */
+#define SER_HDR_LEN    sizeof(ppr_deser_header_t)
+
+
+/* Per band tx powers */
+typedef BWL_PRE_PACKED_STRUCT struct pprpb {
+	/* start of 20MHz tx power limits */
+	int8 p_1x1dsss[WL_RATESET_SZ_DSSS];			/* Legacy CCK/DSSS */
+	int8 p_1x1ofdm[WL_RATESET_SZ_OFDM]; 		/* 20 MHz Legacy OFDM transmission */
+	int8 p_1x1vhtss1[WL_RATESET_SZ_VHT_MCS];	/* 8HT/10VHT pwrs starting at 1x1mcs0 */
+#if (PPR_MAX_TX_CHAINS > 1)
+	int8 p_1x2dsss[WL_RATESET_SZ_DSSS];			/* Legacy CCK/DSSS */
+	int8 p_1x2cdd_ofdm[WL_RATESET_SZ_OFDM];		/* 20 MHz Legacy OFDM CDD transmission */
+	int8 p_1x2cdd_vhtss1[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 1x2cdd_mcs0 */
+	int8 p_2x2stbc_vhtss1[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 2x2stbc_mcs0 */
+	int8 p_2x2vhtss2[WL_RATESET_SZ_VHT_MCS];	/* 8HT/10VHT pwrs starting at 2x2sdm_mcs8 */
+#if (PPR_MAX_TX_CHAINS > 2)
+	int8 p_1x3dsss[WL_RATESET_SZ_DSSS];			/* Legacy CCK/DSSS */
+	int8 p_1x3cdd_ofdm[WL_RATESET_SZ_OFDM];		/* 20 MHz Legacy OFDM CDD transmission */
+	int8 p_1x3cdd_vhtss1[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 1x3cdd_mcs0 */
+	int8 p_2x3stbc_vhtss1[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 2x3stbc_mcs0 */
+	int8 p_2x3vhtss2[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 2x3sdm_mcs8 spexp1 */
+	int8 p_3x3vhtss3[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 3x3sdm_mcs16 */
+#endif
+
+#ifdef WL_BEAMFORMING
+	int8 p_1x2txbf_ofdm[WL_RATESET_SZ_OFDM];	/* 20 MHz Legacy OFDM TXBF transmission */
+	int8 p_1x2txbf_vhtss1[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 1x2txbf_mcs0 */
+	int8 p_2x2txbf_vhtss2[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 2x2txbf_mcs8 */
+#if (PPR_MAX_TX_CHAINS > 2)
+	int8 p_1x3txbf_ofdm[WL_RATESET_SZ_OFDM];	/* 20 MHz Legacy OFDM TXBF transmission */
+	int8 p_1x3txbf_vhtss1[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 1x3txbf_mcs0 */
+	int8 p_2x3txbf_vhtss2[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 2x3txbf_mcs8 */
+	int8 p_3x3txbf_vhtss3[WL_RATESET_SZ_VHT_MCS]; /* 8HT/10VHT pwrs starting at 3x3txbf_mcs16 */
+#endif
+#endif /* WL_BEAMFORMING */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+} BWL_POST_PACKED_STRUCT pprpbw_t;
+
+
+#define PPR_CHAIN1_FIRST OFFSETOF(pprpbw_t, p_1x1dsss)
+#define PPR_CHAIN1_END   (OFFSETOF(pprpbw_t, p_1x1vhtss1) + sizeof(((pprpbw_t *)0)->p_1x1vhtss1))
+#define PPR_CHAIN1_SIZE  PPR_CHAIN1_END
+#if (PPR_MAX_TX_CHAINS > 1)
+#define PPR_CHAIN2_FIRST OFFSETOF(pprpbw_t, p_1x2dsss)
+#define PPR_CHAIN2_FIRST_MCS OFFSETOF(pprpbw_t, p_1x2cdd_vhtss1)
+#define PPR_CHAIN2_END   (OFFSETOF(pprpbw_t, p_2x2vhtss2) + sizeof(((pprpbw_t *)0)->p_2x2vhtss2))
+#define PPR_CHAIN2_SIZE  (PPR_CHAIN2_END - PPR_CHAIN2_FIRST)
+#define PPR_CHAIN2_MCS_SIZE  (PPR_CHAIN2_END - PPR_CHAIN2_FIRST_MCS)
+#if (PPR_MAX_TX_CHAINS > 2)
+#define PPR_CHAIN3_FIRST OFFSETOF(pprpbw_t, p_1x3dsss)
+#define PPR_CHAIN3_FIRST_MCS OFFSETOF(pprpbw_t, p_1x3cdd_vhtss1)
+#define PPR_CHAIN3_END   (OFFSETOF(pprpbw_t, p_3x3vhtss3) + sizeof(((pprpbw_t *)0)->p_3x3vhtss3))
+#define PPR_CHAIN3_SIZE  (PPR_CHAIN3_END - PPR_CHAIN3_FIRST)
+#define PPR_CHAIN3_MCS_SIZE  (PPR_CHAIN3_END - PPR_CHAIN3_FIRST_MCS)
+#endif
+
+#ifdef WL_BEAMFORMING
+#define PPR_BF_CHAIN2_FIRST OFFSETOF(pprpbw_t, p_1x2txbf_ofdm)
+#define PPR_BF_CHAIN2_FIRST_MCS OFFSETOF(pprpbw_t, p_1x2txbf_vhtss1)
+#define PPR_BF_CHAIN2_END   (OFFSETOF(pprpbw_t, p_2x2txbf_vhtss2) + \
+	sizeof(((pprpbw_t *)0)->p_2x2txbf_vhtss2))
+#define PPR_BF_CHAIN2_SIZE  (PPR_BF_CHAIN2_END - PPR_BF_CHAIN2_FIRST)
+#define PPR_BF_CHAIN2_MCS_SIZE  (PPR_BF_CHAIN2_END - PPR_BF_CHAIN2_FIRST_MCS)
+#if (PPR_MAX_TX_CHAINS > 2)
+#define PPR_BF_CHAIN3_FIRST OFFSETOF(pprpbw_t, p_1x3txbf_ofdm)
+#define PPR_BF_CHAIN3_FIRST_MCS OFFSETOF(pprpbw_t, p_1x3txbf_vhtss1)
+#define PPR_BF_CHAIN3_END   (OFFSETOF(pprpbw_t, p_3x3txbf_vhtss3) + \
+	sizeof(((pprpbw_t *)0)->p_3x3txbf_vhtss3))
+#define PPR_BF_CHAIN3_SIZE  (PPR_BF_CHAIN3_END - PPR_BF_CHAIN3_FIRST)
+#define PPR_BF_CHAIN3_MCS_SIZE  (PPR_BF_CHAIN3_END - PPR_BF_CHAIN3_FIRST_MCS)
+#endif
+
+#endif /* WL_BEAMFORMING */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+
+
+#define PPR_BW_MAX WL_TX_BW_80 /* Maximum supported bandwidth */
+
+/* Structure to contain ppr values for a 20MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_20 {
+	/* 20MHz tx power limits */
+	pprpbw_t b20;
+} BWL_POST_PACKED_STRUCT ppr_bw_20_t;
+
+
+/* Structure to contain ppr values for a 40MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_40 {
+	/* 40MHz tx power limits */
+	pprpbw_t b40;
+	/* 20in40MHz tx power limits */
+	pprpbw_t b20in40;
+} BWL_POST_PACKED_STRUCT ppr_bw_40_t;
+
+
+/* Structure to contain ppr values for an 80MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_80 {
+	/* 80MHz tx power limits */
+	pprpbw_t b80;
+	/* 20in80MHz tx power limits */
+	pprpbw_t b20in80;
+	/* 40in80MHz tx power limits */
+	pprpbw_t b40in80;
+} BWL_POST_PACKED_STRUCT ppr_bw_80_t;
+
+
+/*
+ * This is the initial implementation of the structure we're hiding. It is sized to contain only
+ * the set of powers it requires, so the union is not necessarily the size of the largest member.
+ */
+
+BWL_PRE_PACKED_STRUCT struct ppr {
+	wl_tx_bw_t ch_bw;
+
+	BWL_PRE_PACKED_STRUCT union {
+		ppr_bw_20_t ch20;
+		ppr_bw_40_t ch40;
+		ppr_bw_80_t ch80;
+	} ppr_bw;
+} BWL_POST_PACKED_STRUCT;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+
+/* Returns a flag of ppr conditions (chains, txbf etc.) */
+static uint32 ppr_get_flag(void)
+{
+	uint32 flag = 0;
+	flag  |= PPR_MAX_TX_CHAINS & PPR_MAX_TX_CHAIN_MASK;
+#if PPR_MAX_TX_CHAINS > 1
+	if (PPR_TXBF_ENAB()) {
+		flag  |= PPR_BEAMFORMING;
+	}
+#endif
+	return flag;
+}
+
+static uint16 ppr_ser_size_per_band(uint32 flags)
+{
+	uint16 ret = PPR_CHAIN1_SIZE; /* at least 1 chain rates should be there */
+	uint8 chain   = flags & PPR_MAX_TX_CHAIN_MASK;
+	bool bf      = (flags & PPR_BEAMFORMING) != 0;
+	BCM_REFERENCE(chain);
+	BCM_REFERENCE(bf);
+#if (PPR_MAX_TX_CHAINS > 1)
+	if (chain > 1) {
+		ret += PPR_CHAIN2_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (chain > 2) {
+		ret += PPR_CHAIN3_SIZE;
+	}
+#endif
+
+#ifdef WL_BEAMFORMING
+	if (PPR_TXBF_ENAB() && bf) {
+		ret += PPR_BF_CHAIN2_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (PPR_TXBF_ENAB() && bf && chain > 2) {
+		ret += PPR_BF_CHAIN3_SIZE;
+	}
+#endif
+#endif /* WL_BEAMFORMING */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	return ret;
+}
+
+/* Return the required serialization size based on the flag field. */
+static uint ppr_ser_size_by_flag(uint32 flag, wl_tx_bw_t bw)
+{
+	uint ret = ppr_ser_size_per_band(flag);
+	switch (bw) {
+	case WL_TX_BW_20:
+		break;
+	case WL_TX_BW_40:
+		ret *= sizeof(ppr_bw_40_t)/sizeof(pprpbw_t);
+		break;
+	case WL_TX_BW_80:
+		ret *= sizeof(ppr_bw_80_t)/sizeof(pprpbw_t);
+		break;
+	default:
+		ASSERT(0);
+	}
+	return ret;
+}
+
+#define COPY_PPR_TOBUF(x, y) do { bcopy(&pprbuf[x], *buf, y); \
+	*buf += y; ret += y; } while (0);
+
+
+/* Serialize ppr data of a bandwidth into the given buffer */
+static uint ppr_serialize_block(const uint8* pprbuf, uint8** buf, uint32 serflag)
+{
+	uint ret = 0;
+#if (PPR_MAX_TX_CHAINS > 1)
+	uint chain   = serflag & PPR_MAX_TX_CHAIN_MASK; /* chain number in serialized block */
+	bool bf      = (serflag & PPR_BEAMFORMING) != 0;
+#endif
+
+	COPY_PPR_TOBUF(PPR_CHAIN1_FIRST, PPR_CHAIN1_SIZE);
+#if (PPR_MAX_TX_CHAINS > 1)
+	BCM_REFERENCE(bf);
+	if (chain > 1) {
+		COPY_PPR_TOBUF(PPR_CHAIN2_FIRST, PPR_CHAIN2_SIZE);
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (chain > 2) {
+		COPY_PPR_TOBUF(PPR_CHAIN3_FIRST, PPR_CHAIN3_SIZE);
+	}
+#endif
+#ifdef WL_BEAMFORMING
+	if (PPR_TXBF_ENAB() && bf) {
+		COPY_PPR_TOBUF(PPR_BF_CHAIN2_FIRST, PPR_BF_CHAIN2_SIZE);
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (PPR_TXBF_ENAB() && bf && chain > 2) {
+		COPY_PPR_TOBUF(PPR_BF_CHAIN3_FIRST, PPR_BF_CHAIN3_SIZE);
+	}
+#endif
+#endif /* WL_BEAMFORMING */
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+	return ret;
+}
+
+
+/* Serialize ppr data of each bandwidth into the given buffer, returns bytes copied */
+static uint ppr_serialize_data(const ppr_t *pprptr, uint8* buf, uint32 serflag)
+{
+	uint ret = sizeof(ppr_deser_header_t);
+	ppr_deser_header_t* header = (ppr_deser_header_t*)buf;
+	ASSERT(pprptr && buf);
+	header->version = PPR_SERIALIZATION_VER;
+	header->bw      = (uint8)pprptr->ch_bw;
+	header->flags   = HTON32(ppr_get_flag());
+	header->per_band_size	= HTON16(ppr_ser_size_per_band(serflag));
+
+	buf += sizeof(*header);
+	switch (header->bw) {
+	case WL_TX_BW_20:
+		{
+			const uint8* pprbuf = (const uint8*)&pprptr->ppr_bw.ch20.b20;
+			ret += ppr_serialize_block(pprbuf, &buf, serflag);
+		}
+		break;
+	case WL_TX_BW_40:
+		{
+			const uint8* pprbuf = (const uint8*)&pprptr->ppr_bw.ch40.b40;
+			ret += ppr_serialize_block(pprbuf, &buf, serflag);
+			pprbuf = (const uint8*)&pprptr->ppr_bw.ch40.b20in40;
+			ret += ppr_serialize_block(pprbuf, &buf, serflag);
+		}
+		break;
+	case WL_TX_BW_80:
+		{
+			const uint8* pprbuf = (const uint8*)&pprptr->ppr_bw.ch80.b80;
+			ret += ppr_serialize_block(pprbuf, &buf, serflag);
+			pprbuf = (const uint8*)&pprptr->ppr_bw.ch80.b20in80;
+			ret += ppr_serialize_block(pprbuf, &buf, serflag);
+			pprbuf = (const uint8*)&pprptr->ppr_bw.ch80.b40in80;
+			ret += ppr_serialize_block(pprbuf, &buf, serflag);
+		}
+		break;
+	default:
+		ASSERT(0);
+	}
+	return ret;
+}
+
+
+/* Copy serialized ppr data of a bandwidth */
+static void ppr_copy_serdata(uint8* pobuf, const uint8** inbuf, uint32 flag, uint16 per_band_size)
+{
+	uint chain   = flag & PPR_MAX_TX_CHAIN_MASK;
+	bool bf      = (flag & PPR_BEAMFORMING) != 0;
+	uint16 len   = PPR_CHAIN1_SIZE;
+	BCM_REFERENCE(chain);
+	BCM_REFERENCE(bf);
+	bcopy(*inbuf, pobuf, PPR_CHAIN1_SIZE);
+	*inbuf += PPR_CHAIN1_SIZE;
+#if (PPR_MAX_TX_CHAINS > 1)
+	if (chain > 1) {
+		bcopy(*inbuf, &pobuf[PPR_CHAIN2_FIRST], PPR_CHAIN2_SIZE);
+		*inbuf += PPR_CHAIN2_SIZE;
+		len += PPR_CHAIN2_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (chain > 2) {
+		bcopy(*inbuf, &pobuf[PPR_CHAIN3_FIRST], PPR_CHAIN3_SIZE);
+		*inbuf += PPR_CHAIN3_SIZE;
+		len += PPR_CHAIN3_SIZE;
+	}
+#endif
+
+#ifdef WL_BEAMFORMING
+	if (PPR_TXBF_ENAB() && bf) {
+		bcopy(*inbuf, &pobuf[PPR_BF_CHAIN2_FIRST], PPR_BF_CHAIN2_SIZE);
+		*inbuf += PPR_BF_CHAIN2_SIZE;
+		len += PPR_BF_CHAIN2_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (PPR_TXBF_ENAB() && bf && chain > 2) {
+		bcopy(*inbuf, &pobuf[PPR_BF_CHAIN3_FIRST], PPR_BF_CHAIN3_SIZE);
+		*inbuf += PPR_BF_CHAIN3_SIZE;
+		len += PPR_BF_CHAIN3_SIZE;
+	}
+#endif
+#endif  /* WL_BEAMFORMING */
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+	if (len < per_band_size) {
+		 *inbuf += (per_band_size - len);
+	}
+}
+
+
+/* Deserialize data into a ppr_t structure */
+static void
+ppr_deser_cpy(ppr_t* pptr, const uint8* inbuf, uint32 flag, wl_tx_bw_t bw, uint16 per_band_size)
+{
+	pptr->ch_bw = bw;
+	switch (bw) {
+	case WL_TX_BW_20:
+		{
+			uint8* pobuf = (uint8*)&pptr->ppr_bw.ch20;
+			ppr_copy_serdata(pobuf, &inbuf, flag, per_band_size);
+		}
+		break;
+	case WL_TX_BW_40:
+		{
+			uint8* pobuf = (uint8*)&pptr->ppr_bw.ch40.b40;
+			ppr_copy_serdata(pobuf, &inbuf, flag, per_band_size);
+			pobuf = (uint8*)&pptr->ppr_bw.ch40.b20in40;
+			ppr_copy_serdata(pobuf, &inbuf, flag, per_band_size);
+		}
+		break;
+	case WL_TX_BW_80:
+		{
+			uint8* pobuf = (uint8*)&pptr->ppr_bw.ch80.b80;
+			ppr_copy_serdata(pobuf, &inbuf, flag, per_band_size);
+			pobuf = (uint8*)&pptr->ppr_bw.ch80.b20in80;
+			ppr_copy_serdata(pobuf, &inbuf, flag, per_band_size);
+			pobuf = (uint8*)&pptr->ppr_bw.ch80.b40in80;
+			ppr_copy_serdata(pobuf, &inbuf, flag, per_band_size);
+		}
+		break;
+	default:
+		ASSERT(0);
+	}
+}
+
+
+/* Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_20(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	if (bw == WL_TX_BW_20)
+		pwrs = &p->ppr_bw.ch20.b20;
+	/* else */
+	/*   ASSERT(0); */
+	return pwrs;
+}
+
+
+/* Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_40(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	switch (bw) {
+	case WL_TX_BW_40:
+		pwrs = &p->ppr_bw.ch40.b40;
+	break;
+	case WL_TX_BW_20:
+
+	case WL_TX_BW_20IN40:
+		pwrs = &p->ppr_bw.ch40.b20in40;
+	break;
+	default:
+		/* ASSERT(0); */
+	break;
+	}
+	return pwrs;
+}
+
+
+/* Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_80(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	switch (bw) {
+	case WL_TX_BW_80:
+		pwrs = &p->ppr_bw.ch80.b80;
+	break;
+	case WL_TX_BW_20:
+	case WL_TX_BW_20IN40:
+	case WL_TX_BW_20IN80:
+		pwrs = &p->ppr_bw.ch80.b20in80;
+	break;
+	case WL_TX_BW_40:
+	case WL_TX_BW_40IN80:
+		pwrs = &p->ppr_bw.ch80.b40in80;
+	break;
+	default:
+		/* ASSERT(0); */
+	break;
+	}
+	return pwrs;
+}
+
+
+typedef pprpbw_t* (*wlc_ppr_get_bw_pwrs_fn_t)(ppr_t* p, wl_tx_bw_t bw);
+
+typedef struct {
+	wl_tx_bw_t ch_bw;		/* Bandwidth of the channel for which powers are stored */
+	/* Function to retrieve the powers for the requested bandwidth */
+	wlc_ppr_get_bw_pwrs_fn_t fn;
+} wlc_ppr_get_bw_pwrs_pair_t;
+
+
+static const wlc_ppr_get_bw_pwrs_pair_t ppr_get_bw_pwrs_fn[] = {
+	{WL_TX_BW_20, ppr_get_bw_powers_20},
+	{WL_TX_BW_40, ppr_get_bw_powers_40},
+	{WL_TX_BW_80, ppr_get_bw_powers_80}
+};
+
+
+/* Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers(ppr_t* p, wl_tx_bw_t bw)
+{
+	uint32 i;
+
+	if (p == NULL) {
+		return NULL;
+	}
+
+	for (i = 0; i < (int)ARRAYSIZE(ppr_get_bw_pwrs_fn); i++) {
+		if (ppr_get_bw_pwrs_fn[i].ch_bw == p->ch_bw)
+			return ppr_get_bw_pwrs_fn[i].fn(p, bw);
+	}
+
+	ASSERT(0);
+	return NULL;
+}
+
+
+/*
+ * Rate group power finder functions: ppr_get_xxx_group()
+ * To preserve the opacity of the PPR struct, even inside the API we try to limit knowledge of
+ * its details. Almost all API functions work on the powers for individual rate groups, rather than
+ * directly accessing the struct. Once the section of the structure corresponding to the bandwidth
+ * has been identified using ppr_get_bw_powers(), the ppr_get_xxx_group() functions use knowledge
+ * of the number of spatial streams, the number of tx chains, and the expansion mode to return a
+ * pointer to the required group of power values.
+ */
+
+/* Get a pointer to the power values for the given dsss rate group for a given channel bandwidth */
+static int8* ppr_get_dsss_group(pprpbw_t* bw_pwrs, wl_tx_chains_t tx_chains)
+{
+	int8* group_pwrs = NULL;
+
+	switch (tx_chains) {
+#if (PPR_MAX_TX_CHAINS > 1)
+#if (PPR_MAX_TX_CHAINS > 2)
+	case WL_TX_CHAINS_3:
+		group_pwrs = bw_pwrs->p_1x3dsss;
+		break;
+#endif
+	case WL_TX_CHAINS_2:
+		group_pwrs = bw_pwrs->p_1x2dsss;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	case WL_TX_CHAINS_1:
+		group_pwrs = bw_pwrs->p_1x1dsss;
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+	return group_pwrs;
+}
+
+
+/* Get a pointer to the power values for the given ofdm rate group for a given channel bandwidth */
+static int8* ppr_get_ofdm_group(pprpbw_t* bw_pwrs, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains)
+{
+	int8* group_pwrs = NULL;
+	BCM_REFERENCE(mode);
+	switch (tx_chains) {
+#if (PPR_MAX_TX_CHAINS > 1)
+#if (PPR_MAX_TX_CHAINS > 2)
+	case WL_TX_CHAINS_3:
+#ifdef WL_BEAMFORMING
+		if (mode == WL_TX_MODE_TXBF)
+			group_pwrs = bw_pwrs->p_1x3txbf_ofdm;
+		else
+#endif
+			group_pwrs = bw_pwrs->p_1x3cdd_ofdm;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+	case WL_TX_CHAINS_2:
+#ifdef WL_BEAMFORMING
+		if (mode == WL_TX_MODE_TXBF)
+			group_pwrs = bw_pwrs->p_1x2txbf_ofdm;
+		else
+#endif
+			group_pwrs = bw_pwrs->p_1x2cdd_ofdm;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	case WL_TX_CHAINS_1:
+		group_pwrs = bw_pwrs->p_1x1ofdm;
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+	return group_pwrs;
+}
+
+
+/*
+ * Tables to provide access to HT/VHT rate group powers. This avoids an ugly nested switch with
+ * messy conditional compilation.
+ *
+ * Access to a given table entry is via table[chains - Nss][mode], except for the Nss3 table, which
+ * only has one row, so it can be indexed directly by table[mode].
+ *
+ * Separate tables are provided for each of Nss1, Nss2 and Nss3 because they are all different
+ * sizes. A combined table would be very sparse, and this arrangement also simplifies the
+ * conditional compilation.
+ *
+ * Each row represents a given number of chains, so there's no need for a zero row. Because
+ * chains >= Nss is always true, there is no one-chain row for Nss2 and there are no one- or
+ * two-chain rows for Nss3. With the tables correctly sized, we can index the rows
+ * using [chains - Nss].
+ *
+ * Then, inside each row, we index by mode:
+ * WL_TX_MODE_NONE, WL_TX_MODE_STBC, WL_TX_MODE_CDD, WL_TX_MODE_TXBF.
+ */
+
+#define OFFSNONE (-1)
+
+static const int mcs_groups_nss1[PPR_MAX_TX_CHAINS][WL_NUM_TX_MODES] = {
+	/* WL_TX_MODE_NONE
+	   WL_TX_MODE_STBC
+	   WL_TX_MODE_CDD
+	   WL_TX_MODE_TXBF
+	*/
+	/* 1 chain */
+	{OFFSETOF(pprpbw_t, p_1x1vhtss1),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 1)
+	/* 2 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x2cdd_vhtss1),
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x3cdd_vhtss1),
+	OFFSNONE}
+#endif
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+};
+
+#ifdef WL_BEAMFORMING
+/* mcs group with TXBF data */
+static const int mcs_groups_nss1_txbf[PPR_MAX_TX_CHAINS][WL_NUM_TX_MODES] = {
+	/* WL_TX_MODE_NONE
+	   WL_TX_MODE_STBC
+	   WL_TX_MODE_CDD
+	   WL_TX_MODE_TXBF
+	*/
+	/* 1 chain */
+	{OFFSETOF(pprpbw_t, p_1x1vhtss1),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 1)
+	/* 2 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x2cdd_vhtss1),
+	OFFSETOF(pprpbw_t, p_1x2txbf_vhtss1)},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x3cdd_vhtss1),
+	OFFSETOF(pprpbw_t, p_1x3txbf_vhtss1)}
+#endif
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+};
+#endif /* WL_BEAMFORMING */
+
+#if (PPR_MAX_TX_CHAINS > 1)
+static const int mcs_groups_nss2[PPR_MAX_TX_CHAINS - 1][WL_NUM_TX_MODES] = {
+	/* 2 chain */
+	{OFFSETOF(pprpbw_t, p_2x2vhtss2),
+	OFFSETOF(pprpbw_t, p_2x2stbc_vhtss1),
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSETOF(pprpbw_t, p_2x3vhtss2),
+	OFFSETOF(pprpbw_t, p_2x3stbc_vhtss1),
+	OFFSNONE,
+	OFFSNONE}
+#endif
+};
+
+#ifdef WL_BEAMFORMING
+/* mcs group with TXBF data */
+static const int mcs_groups_nss2_txbf[PPR_MAX_TX_CHAINS - 1][WL_NUM_TX_MODES] = {
+	/* 2 chain */
+	{OFFSETOF(pprpbw_t, p_2x2vhtss2),
+	OFFSETOF(pprpbw_t, p_2x2stbc_vhtss1),
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_2x2txbf_vhtss2)},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSETOF(pprpbw_t, p_2x3vhtss2),
+	OFFSETOF(pprpbw_t, p_2x3stbc_vhtss1),
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_2x3txbf_vhtss2)}
+#endif
+};
+#endif /* WL_BEAMFORMING */
+
+#if (PPR_MAX_TX_CHAINS > 2)
+static const int mcs_groups_nss3[WL_NUM_TX_MODES] = {
+/* 3 chains only */
+	OFFSETOF(pprpbw_t, p_3x3vhtss3),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE,
+};
+
+#ifdef WL_BEAMFORMING
+/* mcs group with TXBF data */
+static const int mcs_groups_nss3_txbf[WL_NUM_TX_MODES] = {
+/* 3 chains only */
+	OFFSETOF(pprpbw_t, p_3x3vhtss3),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_3x3txbf_vhtss3)
+};
+#endif /* WL_BEAMFORMING */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+
+/* Get a pointer to the power values for the given rate group for a given channel bandwidth */
+static int8* ppr_get_mcs_group(pprpbw_t* bw_pwrs, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains)
+{
+	int8* group_pwrs = NULL;
+	int offset;
+
+	switch (Nss) {
+#if (PPR_MAX_TX_CHAINS > 1)
+#if (PPR_MAX_TX_CHAINS > 2)
+	case WL_TX_NSS_3:
+		if (tx_chains == WL_TX_CHAINS_3) {
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				offset = mcs_groups_nss3_txbf[mode];
+			} else
+#endif /* WL_BEAMFORMING */
+			{
+				offset = mcs_groups_nss3[mode];
+			}
+			if (offset != OFFSNONE) {
+				group_pwrs = (int8*)bw_pwrs + offset;
+			}
+		}
+		else
+			ASSERT(0);
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+	case WL_TX_NSS_2:
+		if ((tx_chains >= WL_TX_CHAINS_2) && (tx_chains <= PPR_MAX_TX_CHAINS)) {
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				offset = mcs_groups_nss2_txbf[tx_chains - Nss][mode];
+			} else
+#endif /* WL_BEAMFORMING */
+			{
+				offset = mcs_groups_nss2[tx_chains - Nss][mode];
+			}
+			if (offset != OFFSNONE) {
+				group_pwrs = (int8*)bw_pwrs + offset;
+			}
+		}
+		else
+			ASSERT(0);
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	case WL_TX_NSS_1:
+		if (tx_chains <= PPR_MAX_TX_CHAINS) {
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				offset = mcs_groups_nss1_txbf[tx_chains - Nss][mode];
+			} else
+#endif /* WL_BEAMFORMING */
+			{
+				offset = mcs_groups_nss1[tx_chains - Nss][mode];
+			}
+			if (offset != OFFSNONE) {
+				group_pwrs = (int8*)bw_pwrs + offset;
+			}
+		}
+		else
+			ASSERT(0);
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+	return group_pwrs;
+}
+
+/* Size routine for user alloc/dealloc */
+static uint32 ppr_pwrs_size(wl_tx_bw_t bw)
+{
+	uint32 size;
+
+	switch (bw) {
+	case WL_TX_BW_20:
+		size = sizeof(ppr_bw_20_t);
+	break;
+	case WL_TX_BW_40:
+		size = sizeof(ppr_bw_40_t);
+	break;
+	case WL_TX_BW_80:
+		size = sizeof(ppr_bw_80_t);
+	break;
+	default:
+		ASSERT(0);
+		size = 0;
+	break;
+	}
+	return size;
+}
+
+
+/* Initialization routine */
+void ppr_init(ppr_t* pprptr, wl_tx_bw_t bw)
+{
+	memset(pprptr, (int8)WL_RATE_DISABLED, ppr_size(bw));
+	pprptr->ch_bw = bw;
+}
+
+
+/* Reinitialization routine for opaque PPR struct */
+void ppr_clear(ppr_t* pprptr)
+{
+	memset((uchar*)&pprptr->ppr_bw, (int8)WL_RATE_DISABLED, ppr_pwrs_size(pprptr->ch_bw));
+}
+
+
+/* Size routine for user alloc/dealloc */
+uint32 ppr_size(wl_tx_bw_t bw)
+{
+	return ppr_pwrs_size(bw) + sizeof(wl_tx_bw_t);
+}
+
+
+/* Size routine for user serialization alloc */
+uint32 ppr_ser_size(const ppr_t* pprptr)
+{
+	return ppr_pwrs_size(pprptr->ch_bw) + SER_HDR_LEN;	/* struct size plus headers */
+}
+
+
+/* Size routine for user serialization alloc */
+uint32 ppr_ser_size_by_bw(wl_tx_bw_t bw)
+{
+	return ppr_pwrs_size(bw) + SER_HDR_LEN;	/* struct size plus headers */
+}
+
+
+/* Constructor routine for opaque PPR struct */
+ppr_t* ppr_create(osl_t *osh, wl_tx_bw_t bw)
+{
+	ppr_t* pprptr;
+
+	ASSERT((bw == WL_TX_BW_20) || (bw == WL_TX_BW_40) || (bw == WL_TX_BW_80));
+#ifndef BCMDRIVER
+	BCM_REFERENCE(osh);
+	if ((pprptr = (ppr_t*)malloc((uint)ppr_size(bw))) != NULL) {
+#else
+	if ((pprptr = (ppr_t*)MALLOC(osh, (uint)ppr_size(bw))) != NULL) {
+#endif
+		ppr_init(pprptr, bw);
+	}
+	return pprptr;
+}
+
+
+/* Init flags in the memory block for serialization, the serializer will check
+ * the flag to decide which ppr to be copied
+ */
+int ppr_init_ser_mem_by_bw(uint8* pbuf, wl_tx_bw_t bw, uint32 len)
+{
+	ppr_ser_mem_flag_t *pmflag;
+
+	if (pbuf == NULL || ppr_ser_size_by_bw(bw) > len)
+		return BCME_BADARG;
+
+	pmflag = (ppr_ser_mem_flag_t *)pbuf;
+	pmflag->magic_word = HTON32(PPR_SER_MEM_WORD);
+	pmflag->flag   = HTON32(ppr_get_flag());
+
+	/* init the memory */
+	memset(pbuf + sizeof(*pmflag), (uint8)WL_RATE_DISABLED, len-sizeof(*pmflag));
+	return BCME_OK;
+}
+
+
+int ppr_init_ser_mem(uint8* pbuf, ppr_t * ppr, uint32 len)
+{
+	return ppr_init_ser_mem_by_bw(pbuf, ppr->ch_bw, len);
+}
+
+
+/* Destructor routine for opaque PPR struct */
+void ppr_delete(osl_t *osh, ppr_t* pprptr)
+{
+	ASSERT((pprptr->ch_bw == WL_TX_BW_20) || (pprptr->ch_bw == WL_TX_BW_40) ||
+		(pprptr->ch_bw == WL_TX_BW_80));
+#ifndef BCMDRIVER
+	BCM_REFERENCE(osh);
+	free(pprptr);
+#else
+	MFREE(osh, pprptr, (uint)ppr_size(pprptr->ch_bw));
+#endif
+}
+
+
+/* Type routine for inferring opaque structure size */
+wl_tx_bw_t ppr_get_ch_bw(const ppr_t* pprptr)
+{
+	return pprptr->ch_bw;
+}
+
+
+/* Type routine to get ppr supported maximum bw */
+wl_tx_bw_t ppr_get_max_bw(void)
+{
+	return PPR_BW_MAX;
+}
+
+
+/* Get the dsss values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	ppr_dsss_rateset_t* dsss)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_dsss_group(bw_pwrs, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, dsss->pwr, sizeof(*dsss));
+			cnt = sizeof(*dsss);
+		}
+	}
+	if (cnt == 0) {
+		memset(dsss->pwr, (int8)WL_RATE_DISABLED, sizeof(*dsss));
+	}
+	return cnt;
+}
+
+
+/* Get the ofdm values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	ppr_ofdm_rateset_t* ofdm)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_ofdm_group(bw_pwrs, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, ofdm->pwr, sizeof(*ofdm));
+			cnt = sizeof(*ofdm);
+		}
+	}
+	if (cnt == 0) {
+		memset(ofdm->pwr, (int8)WL_RATE_DISABLED, sizeof(*ofdm));
+	}
+	return cnt;
+}
+
+
+/* Get the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_get_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, ppr_ht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, mcs->pwr, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	if (cnt == 0) {
+		memset(mcs->pwr, (int8)WL_RATE_DISABLED, sizeof(*mcs));
+	}
+
+	return cnt;
+}
+
+
+/* Get the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_get_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, ppr_vht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, mcs->pwr, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	if (cnt == 0) {
+		memset(mcs->pwr, (int8)WL_RATE_DISABLED, sizeof(*mcs));
+	}
+	return cnt;
+}
+
+
+#define TXPPR_TXPWR_MAX 0x7f             /* WLC_TXPWR_MAX */
+
+/* Get the minimum power for a VHT MCS rate specified by Nss, with the given bw and tx chains.
+ * Disabled rates are ignored
+ */
+int ppr_get_vht_mcs_min(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+ wl_tx_chains_t tx_chains, int8* mcs_min)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int result = BCME_ERROR;
+	uint i = 0;
+
+	*mcs_min = TXPPR_TXPWR_MAX;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			for (i = 0; i < sizeof(ppr_vht_mcs_rateset_t); i++) {
+				/* ignore disabled rates! */
+				if (powers[i] != WL_RATE_DISABLED)
+					*mcs_min = MIN(*mcs_min, powers[i]);
+			}
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/* Routines to set target powers per rate in a group */
+
+/* Set the dsss values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	const ppr_dsss_rateset_t* dsss)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_dsss_group(bw_pwrs, tx_chains);
+		if (powers != NULL) {
+			bcopy(dsss->pwr, powers, sizeof(*dsss));
+			cnt = sizeof(*dsss);
+		}
+	}
+	return cnt;
+}
+
+
+/* Set the ofdm values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const ppr_ofdm_rateset_t* ofdm)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_ofdm_group(bw_pwrs, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(ofdm->pwr, powers, sizeof(*ofdm));
+			cnt = sizeof(*ofdm);
+		}
+	}
+	return cnt;
+}
+
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_ht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(mcs->pwr, powers, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	return cnt;
+}
+
+
+/* Set the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_vht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(mcs->pwr, powers, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	return cnt;
+}
+
+
+/* Routines to set rate groups to a single target value */
+
+/* Set the dsss values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains, const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_dsss_group(bw_pwrs, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_dsss_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	return cnt;
+}
+
+
+/* Set the ofdm values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_ofdm_group(bw_pwrs, mode, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_ofdm_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	return cnt;
+}
+
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_ht_mcs_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	return cnt;
+}
+
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_vht_mcs_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	return cnt;
+}
+
+
+/* Helper routines to operate on the entire ppr set */
+
+/* Ensure no rate limit is greater than the cap */
+uint ppr_apply_max(ppr_t* pprptr, int8 maxval)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		*rptr = MIN(*rptr, maxval);
+	}
+	return i;
+}
+
+
+/*
+ * Check for any power in the rate group at or below the threshold. If any is
+ * found, set the entire group to WL_RATE_DISABLED. An exception is made for
+ * VHT 8 and 9 which will not cause the entire group to be disabled if they
+ * are disabled or below the threshold.
+ */
+static void ppr_force_disabled_group(int8* powers, int8 threshold, uint len)
+{
+	uint i;
+
+	for (i = 0; (i < len) && (i < WL_RATESET_SZ_HT_MCS); i++) {
+		/* if we find a below-threshold rate in the set... */
+		if (powers[i] <= threshold) {
+			/* disable the entire rate set and return */
+			for (i = 0; i < len; i++) {
+				powers[i] = WL_RATE_DISABLED;
+			}
+			return;
+		}
+	}
+	/* VHT 8 and 9 can be disabled separately */
+	for (; i < len; i++) {
+		if (powers[i] <= threshold) {
+			powers[i] = WL_RATE_DISABLED;
+		}
+	}
+}
+
+
+/*
+ * Make low power rates (below the threshold) explicitly disabled.
+ * If one rate in a group is disabled, disable the whole group.
+ */
+int ppr_force_disabled(ppr_t* pprptr, int8 threshold)
+{
+	wl_tx_bw_t bw;
+
+	for (bw = WL_TX_BW_20; bw <= WL_TX_BW_80; bw++) {
+		pprpbw_t* bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+
+		if (bw_pwrs != NULL) {
+			int8* powers;
+#if (PPR_MAX_TX_CHAINS > 1)
+			int8* mcs_powers;
+#endif
+			powers = (int8*)ppr_get_dsss_group(bw_pwrs, WL_TX_CHAINS_1);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_DSSS);
+
+			powers = (int8*)ppr_get_ofdm_group(bw_pwrs,
+				WL_TX_MODE_NONE, WL_TX_CHAINS_1);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+			powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_NONE,
+				WL_TX_CHAINS_1);
+			ASSERT(powers);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_VHT_MCS);
+
+#if (PPR_MAX_TX_CHAINS > 1)
+			powers = (int8*)ppr_get_dsss_group(bw_pwrs, WL_TX_CHAINS_2);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_DSSS);
+
+			powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_CDD, WL_TX_CHAINS_2);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_2);
+			ASSERT(mcs_powers);
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN2_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS) {
+				ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_VHT_MCS);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_TXBF,
+					WL_TX_CHAINS_2);
+				ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_2);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN2_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS) {
+					ppr_force_disabled_group(powers, threshold,
+						WL_RATESET_SZ_VHT_MCS);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+
+#if (PPR_MAX_TX_CHAINS > 2)
+			powers = (int8*)ppr_get_dsss_group(bw_pwrs, WL_TX_CHAINS_3);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_DSSS);
+
+			powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_CDD, WL_TX_CHAINS_3);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_3);
+			ASSERT(mcs_powers);
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN3_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS) {
+				ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_VHT_MCS);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_TXBF,
+					WL_TX_CHAINS_3);
+				ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_3);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN3_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS) {
+					ppr_force_disabled_group(powers, threshold,
+						WL_RATESET_SZ_VHT_MCS);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+#endif /* (PPR_MAX_TX_CHAINS > 2) */
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+		}
+	}
+	return BCME_OK;
+}
+
+
+#if (PPR_MAX_TX_CHAINS > 1)
+#define APPLY_CONSTRAINT(x, y, max) do {		\
+		ret += (y - x);							\
+		for (i = x; i < y; i++)					\
+			pprbuf[i] = MIN(pprbuf[i], max);	\
+	} while (0);
+
+
+/* Apply appropriate single-, two- and three-chain constraints across the appropriate ppr block */
+static uint ppr_apply_constraint_to_block(int8* pprbuf, int8 constraint)
+{
+	uint ret = 0;
+	uint i = 0;
+	int8 constraint_2chain = constraint - QDB(3);
+#if (PPR_MAX_TX_CHAINS > 2)
+	int8 constraint_3chain = constraint - (QDB(4) + 3); /* - 4.75dBm */
+#endif
+
+	APPLY_CONSTRAINT(PPR_CHAIN1_FIRST, PPR_CHAIN1_END, constraint);
+	APPLY_CONSTRAINT(PPR_CHAIN2_FIRST, PPR_CHAIN2_END, constraint_2chain);
+#if (PPR_MAX_TX_CHAINS > 2)
+	APPLY_CONSTRAINT(PPR_CHAIN3_FIRST, PPR_CHAIN3_END, constraint_3chain);
+#endif
+#ifdef WL_BEAMFORMING
+	APPLY_CONSTRAINT(PPR_BF_CHAIN2_FIRST, PPR_BF_CHAIN2_END, constraint_2chain);
+#if (PPR_MAX_TX_CHAINS > 2)
+	APPLY_CONSTRAINT(PPR_BF_CHAIN3_FIRST, PPR_BF_CHAIN3_END, constraint_3chain);
+#endif
+#endif /* WL_BEAMFORMING */
+	return ret;
+}
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+
+
+/*
+ * Reduce total transmitted power to level of constraint.
+ * For two chain rates, the per-antenna power must be halved.
+ * For three chain rates, it must be a third of the constraint.
+ */
+uint ppr_apply_constraint_total_tx(ppr_t* pprptr, int8 constraint)
+{
+	uint ret = 0;
+
+#if (PPR_MAX_TX_CHAINS > 1)
+	int8* pprbuf;
+	ASSERT(pprptr);
+
+	switch (pprptr->ch_bw) {
+	case WL_TX_BW_20:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch20.b20;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+	case WL_TX_BW_40:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch40.b40;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch40.b20in40;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+	case WL_TX_BW_80:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch80.b80;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch80.b20in80;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch80.b40in80;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+	default:
+		ASSERT(0);
+	}
+
+#else
+	ASSERT(pprptr);
+	ret = ppr_apply_max(pprptr, constraint);
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	return ret;
+}
+
+
+/* Ensure no rate limit is lower than the specified minimum */
+uint ppr_apply_min(ppr_t* pprptr, int8 minval)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		*rptr = MAX(*rptr, minval);
+	}
+	return i;
+}
+
+
+/* Ensure no rate limit in this ppr set is greater than the corresponding limit in ppr_cap */
+uint ppr_apply_vector_ceiling(ppr_t* pprptr, const ppr_t* ppr_cap)
+{
+	uint i = 0;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	const int8* capptr = (const int8*)&ppr_cap->ppr_bw;
+
+	if (pprptr->ch_bw == ppr_cap->ch_bw) {
+		for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++, capptr++) {
+			*rptr = MIN(*rptr, *capptr);
+		}
+	}
+	return i;
+}
+
+
+/* Ensure no rate limit in this ppr set is lower than the corresponding limit in ppr_min */
+uint ppr_apply_vector_floor(ppr_t* pprptr, const ppr_t* ppr_min)
+{
+	uint i = 0;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	const int8* minptr = (const int8*)&ppr_min->ppr_bw;
+
+	if (pprptr->ch_bw == ppr_min->ch_bw) {
+		for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++, minptr++) {
+			*rptr = MAX((uint8)*rptr, (uint8)*minptr);
+		}
+	}
+	return i;
+}
+
+
+/* Get the maximum power in the ppr set */
+int8 ppr_get_max(ppr_t* pprptr)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	int8 maxval = *rptr++;
+
+	for (i = 1; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		maxval = MAX(maxval, *rptr);
+	}
+	return maxval;
+}
+
+
+/*
+ * Get the minimum power in the ppr set, excluding disallowed
+ * rates and (possibly) powers set to the minimum for the phy
+ */
+int8 ppr_get_min(ppr_t* pprptr, int8 floor)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	int8 minval = WL_RATE_DISABLED;
+
+	for (i = 0; (i < ppr_pwrs_size(pprptr->ch_bw)) && ((minval == WL_RATE_DISABLED) ||
+		(minval == floor)); i++, rptr++) {
+		minval = *rptr;
+	}
+	for (; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		if ((*rptr != WL_RATE_DISABLED) && (*rptr != floor))
+			minval = MIN(minval, *rptr);
+	}
+	return minval;
+}
+
+
+/* Get the maximum power for a given bandwidth in the ppr set */
+int8 ppr_get_max_for_bw(ppr_t* pprptr, wl_tx_bw_t bw)
+{
+	uint i;
+	const pprpbw_t* bw_pwrs;
+	const int8* rptr;
+	int8 maxval;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		rptr = (const int8*)bw_pwrs;
+		maxval = *rptr++;
+
+		for (i = 1; i < sizeof(*bw_pwrs); i++, rptr++) {
+			maxval = MAX(maxval, *rptr);
+		}
+	} else {
+		maxval = WL_RATE_DISABLED;
+	}
+	return maxval;
+}
+
+
+/* Get the minimum power for a given bandwidth  in the ppr set */
+int8 ppr_get_min_for_bw(ppr_t* pprptr, wl_tx_bw_t bw)
+{
+	uint i;
+	const pprpbw_t* bw_pwrs;
+	const int8* rptr;
+	int8 minval;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		rptr = (const int8*)bw_pwrs;
+		minval = *rptr++;
+
+		for (i = 1; i < sizeof(*bw_pwrs); i++, rptr++) {
+			minval = MIN(minval, *rptr);
+		}
+	} else
+		minval = WL_RATE_DISABLED;
+	return minval;
+}
+
+
+/* Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_dsss(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2,
+	wl_tx_bw_t bw, wl_tx_chains_t tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	ASSERT(pprptr1);
+	ASSERT(pprptr2);
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_dsss_group(bw_pwrs1, tx_chains);
+		powers2 = (int8*)ppr_get_dsss_group(bw_pwrs2, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_DSSS; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+
+/* Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_ofdm(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2,
+	wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_ofdm_group(bw_pwrs1, mode, tx_chains);
+		powers2 = (int8*)ppr_get_ofdm_group(bw_pwrs2, mode, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_OFDM; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+
+/* Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_ht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_mcs_group(bw_pwrs1, Nss, mode, tx_chains);
+		powers2 = (int8*)ppr_get_mcs_group(bw_pwrs2, Nss, mode, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_HT_MCS; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+
+/* Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_vht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t
+	tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_mcs_group(bw_pwrs1, Nss, mode, tx_chains);
+		powers2 = (int8*)ppr_get_mcs_group(bw_pwrs2, Nss, mode, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_VHT_MCS; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+
+/* Map the given function with its context value over the two power vectors */
+
+void
+ppr_map_vec_all(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2)
+{
+	uint i;
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* rptr1 = (int8*)&pprptr1->ppr_bw;
+	int8* rptr2 = (int8*)&pprptr2->ppr_bw;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, WL_TX_BW_20);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, WL_TX_BW_20);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		rptr1 = (int8*)bw_pwrs1;
+		rptr2 = (int8*)bw_pwrs2;
+		for (i = 0; i < sizeof(pprpbw_t); i++, rptr1++, rptr2++) {
+			(fn)(context, (uint8*)rptr1, (uint8*)rptr2);
+		}
+	}
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, WL_TX_BW_40);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, WL_TX_BW_40);
+
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		rptr1 = (int8*)bw_pwrs1;
+		rptr2 = (int8*)bw_pwrs2;
+		for (i = 0; i < sizeof(pprpbw_t); i++, rptr1++, rptr2++) {
+			(fn)(context, (uint8*)rptr1, (uint8*)rptr2);
+		}
+
+		bw_pwrs1 = ppr_get_bw_powers(pprptr1, WL_TX_BW_20IN40);
+		bw_pwrs2 = ppr_get_bw_powers(pprptr2, WL_TX_BW_20IN40);
+		if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+			rptr1 = (int8*)bw_pwrs1;
+			rptr2 = (int8*)bw_pwrs2;
+			for (i = 0; i < sizeof(pprpbw_t); i++, rptr1++, rptr2++) {
+				(fn)(context, (uint8*)rptr1, (uint8*)rptr2);
+			}
+		}
+	}
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, WL_TX_BW_80);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, WL_TX_BW_80);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		rptr1 = (int8*)bw_pwrs1;
+		rptr2 = (int8*)bw_pwrs2;
+		for (i = 0; i < sizeof(pprpbw_t); i++, rptr1++, rptr2++) {
+			(fn)(context, (uint8*)rptr1, (uint8*)rptr2);
+		}
+
+		bw_pwrs1 = ppr_get_bw_powers(pprptr1, WL_TX_BW_20IN80);
+		bw_pwrs2 = ppr_get_bw_powers(pprptr2, WL_TX_BW_20IN80);
+		if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+			rptr1 = (int8*)bw_pwrs1;
+			rptr2 = (int8*)bw_pwrs2;
+			for (i = 0; i < sizeof(pprpbw_t); i++, rptr1++, rptr2++) {
+				(fn)(context, (uint8*)rptr1, (uint8*)rptr2);
+			}
+		}
+
+		bw_pwrs1 = ppr_get_bw_powers(pprptr1, WL_TX_BW_40IN80);
+		bw_pwrs2 = ppr_get_bw_powers(pprptr2, WL_TX_BW_40IN80);
+		if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+			rptr1 = (int8*)bw_pwrs1;
+			rptr2 = (int8*)bw_pwrs2;
+			for (i = 0; i < sizeof(pprpbw_t); i++, rptr1++, rptr2++) {
+				(fn)(context, (uint8*)rptr1, (uint8*)rptr2);
+			}
+		}
+	}
+}
+
+
+/* Set PPR struct to a certain power level */
+void
+ppr_set_cmn_val(ppr_t* pprptr, int8 val)
+{
+	memset((uchar*)&pprptr->ppr_bw, val, ppr_pwrs_size(pprptr->ch_bw));
+}
+
+
+/* Make an identical copy of a ppr structure (for ppr_bw==all case) */
+void
+ppr_copy_struct(ppr_t* pprptr_s, ppr_t* pprptr_d)
+{
+	int8* rptr_s = (int8*)&pprptr_s->ppr_bw;
+	int8* rptr_d = (int8*)&pprptr_d->ppr_bw;
+	/* ASSERT(ppr_pwrs_size(pprptr_d->ch_bw) >= ppr_pwrs_size(pprptr_s->ch_bw)); */
+
+	if (pprptr_s->ch_bw == pprptr_d->ch_bw)
+		bcopy(rptr_s, rptr_d, ppr_pwrs_size(pprptr_s->ch_bw));
+	else {
+		const pprpbw_t* src_bw_pwrs;
+		pprpbw_t* dest_bw_pwrs;
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_40);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_40);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20IN40);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20IN40);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_80);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_80);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20IN80);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20IN80);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_40IN80);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_40IN80);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+	}
+}
+
+
+/* Subtract each power from a common value and re-store */
+void
+ppr_cmn_val_minus(ppr_t* pprptr, int8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr = val - *rptr;
+	}
+
+}
+
+
+/* Subtract a common value from each power and re-store */
+void
+ppr_minus_cmn_val(ppr_t* pprptr, int8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr = (*rptr > val) ? (*rptr - val) : 0;
+	}
+
+}
+
+
+/* Add a common value to each power and re-store */
+void
+ppr_plus_cmn_val(ppr_t* pprptr, int8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr += val;
+	}
+
+}
+
+
+/* Multiply by a percentage */
+void
+ppr_multiply_percentage(ppr_t* pprptr, uint8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->ch_bw); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr = (*rptr * val) / 100;
+	}
+
+}
+
+
+/* Compare two ppr variables p1 and p2, save the min value of each
+ * contents to variable p1
+ */
+void
+ppr_compare_min(ppr_t* p1, ppr_t* p2)
+{
+	uint i;
+	int8* rptr1 = NULL;
+	int8* rptr2 = NULL;
+	uint32 pprsize = 0;
+
+	if (p1->ch_bw == p2->ch_bw) {
+		rptr1 = (int8*)&p1->ppr_bw;
+		rptr2 = (int8*)&p2->ppr_bw;
+		pprsize = ppr_pwrs_size(p1->ch_bw);
+	}
+
+	for (i = 0; i < pprsize; i++, rptr1++, rptr2++) {
+		*rptr1 = MIN(*rptr1, *rptr2);
+	}
+}
+
+
+/* Compare two ppr variables p1 and p2, save the max. value of each
+ * contents to variable p1
+ */
+void
+ppr_compare_max(ppr_t* p1, ppr_t* p2)
+{
+	uint i;
+	int8* rptr1 = NULL;
+	int8* rptr2 = NULL;
+	uint32 pprsize = 0;
+
+	if (p1->ch_bw == p2->ch_bw) {
+		rptr1 = (int8*)&p1->ppr_bw;
+		rptr2 = (int8*)&p2->ppr_bw;
+		pprsize = ppr_pwrs_size(p1->ch_bw);
+	}
+
+	for (i = 0; i < pprsize; i++, rptr1++, rptr2++) {
+		*rptr1 = MAX(*rptr1, *rptr2);
+	}
+}
+
+
+/* Serialize the contents of the opaque ppr struct.
+ * Writes number of bytes copied, zero on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int
+ppr_serialize(const ppr_t* pprptr, uint8* buf, uint buflen, uint* bytes_copied)
+{
+	int err = BCME_OK;
+	if (buflen <= sizeof(ppr_ser_mem_flag_t)) {
+		err = BCME_BUFTOOSHORT;
+	} else {
+		ppr_ser_mem_flag_t *smem_flag = (ppr_ser_mem_flag_t *)buf;
+		uint32 flag = NTOH32(smem_flag->flag);
+
+		/* check if memory contains a valid flag, if not, use current
+		 * condition (num of chains, txbf etc.) to serialize data.
+		 */
+		if (NTOH32(smem_flag->magic_word) != PPR_SER_MEM_WORD) {
+			flag = ppr_get_flag();
+		}
+
+		if (buflen >= ppr_ser_size_by_flag(flag, pprptr->ch_bw)) {
+			*bytes_copied = ppr_serialize_data(pprptr, buf, flag);
+		} else {
+			err = BCME_BUFTOOSHORT;
+		}
+	}
+	return err;
+}
+
+
+/* Deserialize the contents of a buffer into an opaque ppr struct.
+ * Creates an opaque structure referenced by *pptrptr, NULL on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int
+ppr_deserialize_create(osl_t *osh, const uint8* buf, uint buflen, ppr_t** pprptr)
+{
+	const uint8* bptr = buf;
+	int err = BCME_OK;
+	ppr_t* lpprptr = NULL;
+
+	if ((buflen > SER_HDR_LEN) && (bptr != NULL) && (*bptr == PPR_SERIALIZATION_VER)) {
+		const ppr_deser_header_t * ser_head = (const ppr_deser_header_t *)bptr;
+		wl_tx_bw_t ch_bw = ser_head->bw;
+		/* struct size plus header */
+		uint32 ser_size = ppr_pwrs_size(ch_bw) + SER_HDR_LEN;
+
+		if ((lpprptr = ppr_create(osh, ch_bw)) != NULL) {
+			uint32 flags = NTOH32(ser_head->flags);
+			uint16 per_band_size = NTOH16(ser_head->per_band_size);
+			/* set the data with default value before deserialize */
+			ppr_set_cmn_val(lpprptr, WL_RATE_DISABLED);
+
+			ppr_deser_cpy(lpprptr, bptr + sizeof(*ser_head), flags, ch_bw,
+				per_band_size);
+		} else if (buflen < ser_size) {
+			err = BCME_BUFTOOSHORT;
+		} else {
+			err = BCME_NOMEM;
+		}
+	} else if (buflen <= SER_HDR_LEN) {
+		err = BCME_BUFTOOSHORT;
+	} else if (bptr == NULL) {
+		err = BCME_BADARG;
+	} else {
+		err = BCME_VERSION;
+	}
+	*pprptr = lpprptr;
+	return err;
+}
+
+
+/* Deserialize the contents of a buffer into an opaque ppr struct.
+ * Creates an opaque structure referenced by *pptrptr, NULL on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int
+ppr_deserialize(ppr_t* pprptr, const uint8* buf, uint buflen)
+{
+	const uint8* bptr = buf;
+	int err = BCME_OK;
+	ASSERT(pprptr);
+	if ((buflen > SER_HDR_LEN) && (bptr != NULL) && (*bptr == PPR_SERIALIZATION_VER)) {
+		const ppr_deser_header_t * ser_head = (const ppr_deser_header_t *)bptr;
+		wl_tx_bw_t ch_bw = ser_head->bw;
+
+		if (ch_bw == pprptr->ch_bw) {
+			uint32 flags = NTOH32(ser_head->flags);
+			uint16 per_band_size = NTOH16(ser_head->per_band_size);
+			ppr_set_cmn_val(pprptr, WL_RATE_DISABLED);
+			ppr_deser_cpy(pprptr, bptr + sizeof(*ser_head), flags, ch_bw,
+				per_band_size);
+		} else {
+			err = BCME_BADARG;
+		}
+	} else if (buflen <= SER_HDR_LEN) {
+		err = BCME_BUFTOOSHORT;
+	} else if (bptr == NULL) {
+		err = BCME_BADARG;
+	} else {
+		err = BCME_VERSION;
+	}
+	return err;
+}
+
+
+#ifdef WLTXPWR_CACHE
+
+#define MAX_TXPWR_CACHE_ENTRIES 2
+#define TXPWR_ALL_INVALID	 0xff
+#define TXPWR_CACHE_TXPWR_MAX 0x7f             /* WLC_TXPWR_MAX; */
+
+/* transmit power cache */
+typedef struct tx_pwr_cache_entry {
+	chanspec_t chanspec;
+	ppr_t* cache_pwrs[TXPWR_CACHE_NUM_TYPES];
+	uint8 tx_pwr_max[PPR_MAX_TX_CHAINS];
+	uint8 tx_pwr_min[PPR_MAX_TX_CHAINS];
+	int8 txchain_offsets[PPR_MAX_TX_CHAINS];
+	uint8 data_invalid_flags;
+	int stf_tx_target_pwr_min;
+} tx_pwr_cache_entry_t;
+
+#ifdef TXPWR_CACHE_IN_ROM
+uint8 txpwr_cache[MAX_TXPWR_CACHE_ENTRIES*16] = {0};
+#endif
+
+static tx_pwr_cache_entry_t tx_pwr_cache[MAX_TXPWR_CACHE_ENTRIES] = {{0}, {0}};
+
+static int stf_tx_pwr_min = TXPWR_CACHE_TXPWR_MAX;
+
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_entry(chanspec_t chanspec);
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_diff_entry(chanspec_t chanspec);
+static void wlc_phy_txpwr_cache_clear_entry(osl_t *osh, tx_pwr_cache_entry_t* entryptr);
+
+
+/* Find a cache entry for the specified chanspec. */
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_entry(chanspec_t chanspec)
+{
+	uint i;
+	tx_pwr_cache_entry_t* entryptr = NULL;
+
+	for (i = 0; i < (MAX_TXPWR_CACHE_ENTRIES) && (entryptr == NULL); i++) {
+		if (tx_pwr_cache[i].chanspec == chanspec) {
+			entryptr = &tx_pwr_cache[i];
+		}
+	}
+	return entryptr;
+}
+
+
+/* Find a cache entry that's NOT for the specified chanspec. */
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_diff_entry(chanspec_t chanspec)
+{
+	uint i;
+	tx_pwr_cache_entry_t* entryptr = NULL;
+
+	for (i = 0; i < (MAX_TXPWR_CACHE_ENTRIES) && (entryptr == NULL); i++) {
+		if (tx_pwr_cache[i].chanspec != chanspec) {
+			entryptr = &tx_pwr_cache[i];
+		}
+	}
+	return entryptr;
+}
+
+
+/* Clear a specific cache entry. Delete any ppr_t structs and clear the pointers. */
+static void wlc_phy_txpwr_cache_clear_entry(osl_t *osh, tx_pwr_cache_entry_t* entryptr)
+{
+	uint i;
+
+	entryptr->chanspec = 0;
+
+	ASSERT(entryptr != NULL);
+	for (i = 0; i < TXPWR_CACHE_NUM_TYPES; i++) {
+		if (entryptr->cache_pwrs[i] != NULL) {
+			ppr_delete(osh, entryptr->cache_pwrs[i]);
+			entryptr->cache_pwrs[i] = NULL;
+		}
+	}
+	/*
+	 * Don't bother with max, min and txchain_offsets, as they need to be
+	 * initialised when the entry is setup for a new chanspec
+	 */
+}
+
+
+/*
+ * Get a ppr_t struct of a given type from the cache for the specified chanspec.
+ * Don't return the pointer if the cached data is invalid.
+ */
+ppr_t* wlc_phy_get_cached_pwr(chanspec_t chanspec, uint pwr_type)
+{
+	ppr_t* pwrptr = NULL;
+
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if ((entryptr != NULL) &&
+			((entryptr->data_invalid_flags & (0x01 << pwr_type)) == 0))
+			pwrptr = entryptr->cache_pwrs[pwr_type];
+	}
+
+	return pwrptr;
+}
+
+
+/* Add a ppr_t struct of a given type to the cache for the specified chanspec. */
+int wlc_phy_set_cached_pwr(osl_t *osh, chanspec_t chanspec, uint pwr_type, ppr_t* pwrptr)
+{
+	int result = BCME_NOTFOUND;
+
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if (entryptr != NULL) {
+			if ((entryptr->cache_pwrs[pwr_type] != NULL) &&
+				(entryptr->cache_pwrs[pwr_type] != pwrptr)) {
+				ppr_delete(osh, entryptr->cache_pwrs[pwr_type]);
+			}
+			entryptr->cache_pwrs[pwr_type] = pwrptr;
+			entryptr->data_invalid_flags &= ~(0x01 << pwr_type); /* now valid */
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+/* Indicate if we have cached a particular ppr_t struct for any chanspec. */
+bool wlc_phy_is_pwr_cached(uint pwr_type, ppr_t* pwrptr)
+{
+	bool result = FALSE;
+	uint i;
+
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		for (i = 0; (i < MAX_TXPWR_CACHE_ENTRIES) && (result == FALSE); i++) {
+			if (tx_pwr_cache[i].cache_pwrs[pwr_type] == pwrptr) {
+				result = TRUE;
+			}
+		}
+	}
+	return result;
+}
+
+/* Get the minimum target power for all cores for the chanspec. */
+int wlc_phy_get_cached_stf_target_pwr_min(chanspec_t chanspec)
+{
+	int min_pwr = TXPWR_CACHE_TXPWR_MAX;
+
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+	if ((entryptr != NULL) &&
+		((entryptr->data_invalid_flags & (TXPWR_STF_TARGET_PWR_MIN_INVALID)) == 0))
+		min_pwr = entryptr->stf_tx_target_pwr_min;
+
+	return min_pwr;
+}
+
+
+/* set the minimum target power for all cores for the chanspec. */
+int wlc_phy_set_cached_stf_target_pwr_min(chanspec_t chanspec, int min_pwr)
+{
+	int result = BCME_NOTFOUND;
+
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+	if (entryptr != NULL) {
+		entryptr->stf_tx_target_pwr_min = min_pwr;
+		entryptr->data_invalid_flags &= ~TXPWR_STF_TARGET_PWR_MIN_INVALID; /* now valid */
+		result = BCME_OK;
+	}
+	return result;
+}
+
+
+/* Get the maximum power for the specified core and chanspec. */
+uint8 wlc_phy_get_cached_pwr_max(chanspec_t chanspec, uint core)
+{
+	uint8 max_pwr = WL_RATE_DISABLED;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if (entryptr != NULL)
+			max_pwr = entryptr->tx_pwr_max[core];
+	}
+
+	return max_pwr;
+}
+
+
+/* Set the maximum power for the specified core and chanspec. */
+int wlc_phy_set_cached_pwr_max(chanspec_t chanspec, uint core, uint8 max_pwr)
+{
+	int result = BCME_NOTFOUND;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if (entryptr != NULL) {
+			entryptr->tx_pwr_max[core] = max_pwr;
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/* Get the minimum power for the specified core and chanspec. */
+uint8 wlc_phy_get_cached_pwr_min(chanspec_t chanspec, uint core)
+{
+	uint8 min_pwr = WL_RATE_DISABLED;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if (entryptr != NULL)
+			min_pwr = entryptr->tx_pwr_min[core];
+	}
+
+	return min_pwr;
+}
+
+
+/* Set the minimum power for the specified core and chanspec. */
+int wlc_phy_set_cached_pwr_min(chanspec_t chanspec, uint core, uint8 min_pwr)
+{
+	int result = BCME_NOTFOUND;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if (entryptr != NULL) {
+			entryptr->tx_pwr_min[core] = min_pwr;
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/* Get the txchain offsets for the specified chanspec. */
+int8 wlc_phy_get_cached_txchain_offsets(chanspec_t chanspec, uint core)
+{
+	uint8 offset = WL_RATE_DISABLED;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if (entryptr != NULL)
+			offset = entryptr->txchain_offsets[core];
+	}
+
+	return offset;
+}
+
+
+/* Set the txchain offsets for the specified chanspec. */
+int wlc_phy_set_cached_txchain_offsets(chanspec_t chanspec, uint core, int8 offset)
+{
+	int result = BCME_NOTFOUND;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+
+		if (entryptr != NULL) {
+			entryptr->txchain_offsets[core] = offset;
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/* Indicate if we have a cache entry for the specified chanspec. */
+bool wlc_phy_txpwr_cache_is_cached(chanspec_t chanspec)
+{
+	bool result = FALSE;
+
+	if (wlc_phy_txpwr_cache_get_entry(chanspec)) {
+		result = TRUE;
+	}
+	return result;
+}
+
+
+/* Find a cache entry that's NOT for the specified chanspec. Return the chanspec. */
+chanspec_t wlc_phy_txpwr_cache_find_other_cached_chanspec(chanspec_t chanspec)
+{
+	chanspec_t chan = 0;
+
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_diff_entry(chanspec);
+	if (entryptr != NULL) {
+		chan = entryptr->chanspec;
+	}
+	return chan;
+}
+
+
+/* Find a specific cache entry and clear it. */
+void wlc_phy_txpwr_cache_clear(osl_t *osh, chanspec_t chanspec)
+{
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+	if (entryptr != NULL) {
+		wlc_phy_txpwr_cache_clear_entry(osh, entryptr);
+	}
+}
+
+
+/* Invalidate all cached data. */
+void wlc_phy_txpwr_cache_invalidate(void)
+{
+	uint j;
+
+	for (j = 0; j < MAX_TXPWR_CACHE_ENTRIES; j++) {
+		tx_pwr_cache_entry_t* entryptr = &tx_pwr_cache[j];
+		if (entryptr->chanspec != 0) {
+			uint i;
+			entryptr->data_invalid_flags = TXPWR_ALL_INVALID;
+			for (i = 0; i < PPR_MAX_TX_CHAINS; i++) {
+				entryptr->tx_pwr_min[i] = TXPWR_CACHE_TXPWR_MAX;
+				entryptr->tx_pwr_max[i] = WL_RATE_DISABLED;
+				entryptr->txchain_offsets[i] = WL_RATE_DISABLED;
+			}
+			entryptr->stf_tx_target_pwr_min = TXPWR_CACHE_TXPWR_MAX;
+		}
+	}
+}
+
+/* Clear all cache entries. */
+void wlc_phy_txpwr_cache_close(osl_t *osh)
+{
+	uint i;
+
+	for (i = 0; i < MAX_TXPWR_CACHE_ENTRIES; i++) {
+		tx_pwr_cache_entry_t* entryptr = &tx_pwr_cache[i];
+		if (entryptr->chanspec != 0) {
+			wlc_phy_txpwr_cache_clear_entry(osh, entryptr);
+		}
+	}
+}
+
+
+/* Find an empty cache entry and initialise it. */
+int wlc_phy_txpwr_setup_entry(chanspec_t chanspec)
+{
+	int result = BCME_NOTFOUND;
+	/* find an empty entry */
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(0);
+	if (entryptr != NULL) {
+		uint i;
+
+		entryptr->chanspec = chanspec;
+		for (i = 0; i < PPR_MAX_TX_CHAINS; i++) {
+			entryptr->tx_pwr_min[i] = TXPWR_CACHE_TXPWR_MAX; /* WLC_TXPWR_MAX; */
+			entryptr->tx_pwr_max[i] = WL_RATE_DISABLED;
+			entryptr->txchain_offsets[i] = WL_RATE_DISABLED;
+		}
+		entryptr->stf_tx_target_pwr_min = TXPWR_CACHE_TXPWR_MAX;
+		entryptr->data_invalid_flags |= TXPWR_STF_TARGET_PWR_NOT_CACHED;
+		result = BCME_OK;
+	}
+	return result;
+}
+
+/* Drop any reference to a particular ppr_t struct from the cache. */
+void wlc_phy_uncache_pwr(uint pwr_type, ppr_t* pwrptr)
+{
+	bool result = FALSE;
+	uint i;
+
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		for (i = 0; (i < MAX_TXPWR_CACHE_ENTRIES) && (result == FALSE); i++) {
+			if (tx_pwr_cache[i].cache_pwrs[pwr_type] == pwrptr) {
+				tx_pwr_cache[i].cache_pwrs[pwr_type] = NULL;
+			}
+		}
+	}
+}
+
+bool wlc_phy_get_stf_ppr_cached(chanspec_t chanspec)
+{
+	bool ret = FALSE;
+	tx_pwr_cache_entry_t *entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+	if (entryptr != NULL)
+		ret = !(entryptr->data_invalid_flags & TXPWR_STF_TARGET_PWR_NOT_CACHED);
+	return ret;
+}
+
+void wlc_phy_set_stf_ppr_cached(chanspec_t chanspec, bool bcached)
+{
+	tx_pwr_cache_entry_t *entryptr = wlc_phy_txpwr_cache_get_entry(chanspec);
+	if (entryptr != NULL) {
+		if (bcached)
+			entryptr->data_invalid_flags &= ~TXPWR_STF_TARGET_PWR_NOT_CACHED;
+		else
+			entryptr->data_invalid_flags |= TXPWR_STF_TARGET_PWR_NOT_CACHED;
+	}
+}
+
+/* Get the cached minimum Tx power */
+int wlc_phy_get_cached_stf_pwr_min_dbm(void)
+{
+	return stf_tx_pwr_min;
+}
+
+/* set the cached minimum Tx power */
+void wlc_phy_set_cached_stf_pwr_min_dbm(int min_pwr)
+{
+	stf_tx_pwr_min = min_pwr;
+}
+
+#endif /* WLTXPWR_CACHE */