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, ¶m);
+ /* Recv thread priority decreased */
+ param.sched_priority = 10;
+ pthread_attr_setschedparam(&attr, ¶m);
+ /* 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(>gStartSyncTime, >gFinishSyncTime);
+
+ 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, ¶ms->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, ¶m, sizeof(param), &ptr)) < 0)
+ return err;
+
+ printf("0x%x\n", *((uint32 *)ptr));
+ } else {
+ err = wlu_var_setbuf(wl, cmd->name, ¶m, 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(¶ms->bssid, ðer_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, ¶ms->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(¶ms->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, ¶ms_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, ¶ms_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, ¶ms->params, ¶ms_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, ¶ms->params, ¶ms_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, ¶ms->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, ¶ms->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 *)¶ms->ssid[0].SSID, params->ssid[0].SSID_len,
+ (char *)¶ms->ssid[1].SSID, params->ssid[1].SSID_len,
+ (char *)¶ms->ssid[2].SSID, params->ssid[2].SSID_len,
+ (char *)¶ms->ssid[3].SSID, params->ssid[3].SSID_len,
+ (char *)¶ms->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 *)ðer_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, ðer_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, ¶m, 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, ¶ms->params, ¶ms_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", ¶ms, 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(>bl->ackAll.tr_info[0].addr));
+
+ for (i = 0; i < WL_RMC_MAX_TABLE_ENTRY; i++) {
+ printf("\n %s \t", wl_ether_etoa(>bl->mc_entry[i].mcaddr));
+
+ printf("%s \t",
+ wl_ether_etoa(>bl->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(¶ms_mode, 0, sizeof(uint8));
+ /* toss the command name */
+ argv++;
+
+ if ((err = wlu_var_getbuf_sm(wl, cmd->name, ¶ms_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, ¶ms_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 *)¶ms[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, ¶m, 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 *) ¶m,
+ (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 *) ¶m,
+ (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 *) ¶m,
+ (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 *) ¶m,
+ (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, ¶ms.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, ¶ms, 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, ¶m, sizeof(param), &ptr);
+ else
+ err = wl_bssiovar_getbuf(wl, cmd->name, bsscfg_idx, ¶m, 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(¶m, 0, sizeof(bss_peer_info_param_t));
+ param.version = htod16(BSS_PEER_INFO_PARAM_CUR_VER);
+
+ if (*++argv) {
+ if (!wl_ether_atoe(*argv, ¶m.ea)) {
+ printf(" ERROR: no valid ether addr provided\n");
+ return -1;
+ }
+ }
+
+ if ((err = wlu_var_getbuf_med(wl, cmd->name, ¶m, 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*) ¶m_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*) ¶m_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 */