From bd8827d169a39215f8965676c5f0e7e58d114dcc Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 13 Jan 2020 10:09:32 +0800 Subject: [PATCH] mwifiex: 8997: add W16.68.10.p16 release sdk The sdk release is from NXP offial web: https://www.nxp.com/products/wireless/wi-fi-plus-bluetooth/ 88w8997-wi-fi-dual-band-with-bluetooth-5-for-a-v-streaming-and-digital-tv:88W8997?tab=Design_Tools_Tab The release file is: PCIE-WLAN-UART-BT-8997-U16-X86-W16.68.10.p16-16.26.10.p16-C4X16640_V4-MGPL The sdk version is: W16.68.10.p16 Signed-off-by: Fugang Duan --- mwifiex_8997/Makefile | 580 + mwifiex_8997/README | 2225 ++ mwifiex_8997/README_MLAN | 3649 +++ mwifiex_8997/README_OPENWRT | 356 + mwifiex_8997/README_RBC | 103 + mwifiex_8997/README_UAP | 2664 +++ mwifiex_8997/README_WIFIDIRECT | 448 + mwifiex_8997/gpl-2.0.txt | 339 + mwifiex_8997/mapp/mlan2040coex/Makefile | 48 + mwifiex_8997/mapp/mlan2040coex/mlan2040coex.c | 1322 ++ mwifiex_8997/mapp/mlan2040coex/mlan2040coex.h | 233 + mwifiex_8997/mapp/mlan2040coex/mlan2040misc.c | 280 + mwifiex_8997/mapp/mlan2040coex/mlan2040misc.h | 443 + mwifiex_8997/mapp/mlanconfig/Makefile | 48 + .../mapp/mlanconfig/config/11n_2040coex.conf | 21 + .../mapp/mlanconfig/config/arpfilter.conf | 29 + .../mapp/mlanconfig/config/auto_tx.conf | 54 + .../mapp/mlanconfig/config/bg_scan.conf | 157 + .../mlanconfig/config/bg_scan_wifidirect.conf | 88 + .../mapp/mlanconfig/config/cal_data.conf | 42 + .../mapp/mlanconfig/config/crypto_test.conf | 58 + .../mapp/mlanconfig/config/cwmode.conf | 51 + .../config/ed_mac_ctrl_V3_8997.conf | 23 + .../mapp/mlanconfig/config/host_tdls.conf | 22 + .../mapp/mlanconfig/config/init_cfg.conf | 11 + mwifiex_8997/mapp/mlanconfig/config/mef.conf | 167 + .../mapp/mlanconfig/config/mef_mdns.conf | 204 + .../mlanconfig/config/mef_ws_discovery.conf | 204 + mwifiex_8997/mapp/mlanconfig/config/mem.conf | 17 + .../mapp/mlanconfig/config/mgmt_frame.conf | 30 + .../mapp/mlanconfig/config/mgmtfilter.conf | 15 + .../mapp/mlanconfig/config/or_data.conf | 7 + .../mapp/mlanconfig/config/pad_cfg.conf | 11 + .../mapp/mlanconfig/config/requesttpc.conf | 15 + .../mapp/mlanconfig/config/robust_btc.conf | 212 + .../mapp/mlanconfig/config/small_debug.conf | 62 + mwifiex_8997/mapp/mlanconfig/config/smc.conf | 124 + .../mapp/mlanconfig/config/subevent.conf | 103 + mwifiex_8997/mapp/mlanconfig/config/tdls.conf | 118 + .../mapp/mlanconfig/config/tspecs.conf | 100 + .../mapp/mlanconfig/config/turbo_mode.conf | 9 + .../mapp/mlanconfig/config/tx_ctrl.conf | 58 + .../mlanconfig/config/txpwrlimit_cfg.conf | 759 + .../mapp/mlanconfig/config/txrate_cfg.conf | 171 + mwifiex_8997/mapp/mlanconfig/mlanconfig.c | 4827 ++++ mwifiex_8997/mapp/mlanconfig/mlanconfig.h | 791 + mwifiex_8997/mapp/mlanconfig/mlanhostcmd.c | 951 + mwifiex_8997/mapp/mlanconfig/mlanhostcmd.h | 372 + mwifiex_8997/mapp/mlanconfig/mlanmisc.c | 1030 + mwifiex_8997/mapp/mlanconfig/mlanmisc.h | 681 + mwifiex_8997/mapp/mlanevent/Makefile | 51 + mwifiex_8997/mapp/mlanevent/mlanevent.c | 2775 +++ mwifiex_8997/mapp/mlanevent/mlanevent.h | 1354 ++ mwifiex_8997/mapp/mlanutl/Makefile | 54 + mwifiex_8997/mapp/mlanutl/mlanhostcmd.c | 922 + mwifiex_8997/mapp/mlanutl/mlanhostcmd.h | 119 + mwifiex_8997/mapp/mlanutl/mlanoffload.c | 2519 +++ mwifiex_8997/mapp/mlanutl/mlanoffload.h | 441 + mwifiex_8997/mapp/mlanutl/mlanregclass.c | 539 + mwifiex_8997/mapp/mlanutl/mlanregclass.h | 99 + mwifiex_8997/mapp/mlanutl/mlanroamagent.c | 3669 +++ mwifiex_8997/mapp/mlanutl/mlanroamagent.h | 314 + mwifiex_8997/mapp/mlanutl/mlanscanagent.c | 840 + mwifiex_8997/mapp/mlanutl/mlanscanagent.h | 149 + mwifiex_8997/mapp/mlanutl/mlanutl.c | 18720 ++++++++++++++++ mwifiex_8997/mapp/mlanutl/mlanutl.h | 2967 +++ mwifiex_8997/mapp/mlanutl/timestamp.c | 413 + mwifiex_8997/mapp/mlanutl/timestamp.h | 54 + mwifiex_8997/mapp/uaputl/Makefile | 53 + .../mapp/uaputl/config/80211d_domain.conf | 45 + .../mapp/uaputl/config/embedded_dhcp.conf | 9 + .../config/sample_cal_data_bg_8688.conf | 42 + .../mapp/uaputl/config/tdls_ext_cap.conf | 6 + mwifiex_8997/mapp/uaputl/config/uapcoex.conf | 22 + mwifiex_8997/mapp/uaputl/config/uaputl.conf | 149 + .../mapp/uaputl/config/uaputl_wifidirect.conf | 80 + mwifiex_8997/mapp/uaputl/uapcmd.c | 7424 ++++++ mwifiex_8997/mapp/uaputl/uapcmd.h | 79 + mwifiex_8997/mapp/uaputl/uaphostcmd.c | 335 + mwifiex_8997/mapp/uaputl/uaputl.c | 14266 ++++++++++++ mwifiex_8997/mapp/uaputl/uaputl.h | 2602 +++ mwifiex_8997/mapp/wifidirectutl/Makefile | 56 + .../mapp/wifidirectutl/config/wifidirect.conf | 415 + .../wifidirectutl/config/wifidisplay.conf | 93 + .../mapp/wifidirectutl/wifi_display.c | 1332 ++ .../mapp/wifidirectutl/wifi_display.h | 256 + .../mapp/wifidirectutl/wifidirectutl.c | 8223 +++++++ .../mapp/wifidirectutl/wifidirectutl.h | 1418 ++ mwifiex_8997/mlan/mlan.h | 35 + mwifiex_8997/mlan/mlan_11ac.c | 1332 ++ mwifiex_8997/mlan/mlan_11ac.h | 55 + mwifiex_8997/mlan/mlan_11d.c | 1639 ++ mwifiex_8997/mlan/mlan_11h.c | 4270 ++++ mwifiex_8997/mlan/mlan_11h.h | 195 + mwifiex_8997/mlan/mlan_11n.c | 3248 +++ mwifiex_8997/mlan/mlan_11n.h | 422 + mwifiex_8997/mlan/mlan_11n_aggr.c | 595 + mwifiex_8997/mlan/mlan_11n_aggr.h | 37 + mwifiex_8997/mlan/mlan_11n_rxreorder.c | 1664 ++ mwifiex_8997/mlan/mlan_11n_rxreorder.h | 104 + mwifiex_8997/mlan/mlan_cfp.c | 3119 +++ mwifiex_8997/mlan/mlan_cmdevt.c | 6842 ++++++ mwifiex_8997/mlan/mlan_decl.h | 1511 ++ mwifiex_8997/mlan/mlan_fw.h | 6820 ++++++ mwifiex_8997/mlan/mlan_ieee.h | 2023 ++ mwifiex_8997/mlan/mlan_init.c | 1549 ++ mwifiex_8997/mlan/mlan_init.h | 90 + mwifiex_8997/mlan/mlan_ioctl.h | 4679 ++++ mwifiex_8997/mlan/mlan_join.c | 2411 ++ mwifiex_8997/mlan/mlan_join.h | 40 + mwifiex_8997/mlan/mlan_main.h | 3577 +++ mwifiex_8997/mlan/mlan_meas.c | 463 + mwifiex_8997/mlan/mlan_meas.h | 55 + mwifiex_8997/mlan/mlan_misc.c | 5338 +++++ mwifiex_8997/mlan/mlan_module.c | 55 + mwifiex_8997/mlan/mlan_pcie.c | 2578 +++ mwifiex_8997/mlan/mlan_pcie.h | 215 + mwifiex_8997/mlan/mlan_scan.c | 6316 ++++++ mwifiex_8997/mlan/mlan_shim.c | 1450 ++ mwifiex_8997/mlan/mlan_sta_cmd.c | 3646 +++ mwifiex_8997/mlan/mlan_sta_cmdresp.c | 2908 +++ mwifiex_8997/mlan/mlan_sta_event.c | 1401 ++ mwifiex_8997/mlan/mlan_sta_ioctl.c | 5809 +++++ mwifiex_8997/mlan/mlan_sta_rx.c | 687 + mwifiex_8997/mlan/mlan_sta_tx.c | 324 + mwifiex_8997/mlan/mlan_txrx.c | 394 + mwifiex_8997/mlan/mlan_uap.h | 89 + mwifiex_8997/mlan/mlan_uap_cmdevent.c | 5148 +++++ mwifiex_8997/mlan/mlan_uap_ioctl.c | 2110 ++ mwifiex_8997/mlan/mlan_uap_txrx.c | 770 + mwifiex_8997/mlan/mlan_util.h | 537 + mwifiex_8997/mlan/mlan_wmm.c | 3751 ++++ mwifiex_8997/mlan/mlan_wmm.h | 244 + mwifiex_8997/mlinux/mlan.h | 35 + mwifiex_8997/mlinux/mlan_decl.h | 1511 ++ mwifiex_8997/mlinux/mlan_ieee.h | 2023 ++ mwifiex_8997/mlinux/mlan_ioctl.h | 4679 ++++ mwifiex_8997/mlinux/moal_cfg80211.c | 4114 ++++ mwifiex_8997/mlinux/moal_cfg80211.h | 476 + mwifiex_8997/mlinux/moal_cfgvendor.c | 1285 ++ mwifiex_8997/mlinux/moal_cfgvendor.h | 229 + mwifiex_8997/mlinux/moal_debug.c | 1222 + mwifiex_8997/mlinux/moal_eth_ioctl.c | 15226 +++++++++++++ mwifiex_8997/mlinux/moal_eth_ioctl.h | 505 + mwifiex_8997/mlinux/moal_ioctl.c | 6781 ++++++ mwifiex_8997/mlinux/moal_main.c | 8698 +++++++ mwifiex_8997/mlinux/moal_main.h | 2893 +++ mwifiex_8997/mlinux/moal_pcie.c | 1379 ++ mwifiex_8997/mlinux/moal_pcie.h | 119 + mwifiex_8997/mlinux/moal_priv.c | 6647 ++++++ mwifiex_8997/mlinux/moal_priv.h | 723 + mwifiex_8997/mlinux/moal_proc.c | 713 + mwifiex_8997/mlinux/moal_shim.c | 3476 +++ mwifiex_8997/mlinux/moal_shim.h | 134 + mwifiex_8997/mlinux/moal_sta_cfg80211.c | 8492 +++++++ mwifiex_8997/mlinux/moal_sta_cfg80211.h | 42 + mwifiex_8997/mlinux/moal_uap.c | 3877 ++++ mwifiex_8997/mlinux/moal_uap.h | 508 + mwifiex_8997/mlinux/moal_uap_cfg80211.c | 3325 +++ mwifiex_8997/mlinux/moal_uap_cfg80211.h | 29 + mwifiex_8997/mlinux/moal_uap_priv.c | 190 + mwifiex_8997/mlinux/moal_uap_priv.h | 209 + mwifiex_8997/mlinux/moal_uap_wext.c | 1879 ++ mwifiex_8997/mlinux/moal_wext.c | 3157 +++ mwifiex_8997/mlinux/moal_wext.h | 51 + mwifiex_8997/script/pcie/load | 15 + mwifiex_8997/script/pcie/unload | 17 + .../script/wifidirect/start_auto_go.sh | 30 + .../script/wifidirect/start_find_phase.sh | 25 + .../script/wifidirect/start_listen_state.sh | 18 + .../script/wifidirect/stop_auto_go.sh | 8 + .../wifidirect/stop_wifidirect_client.sh | 6 + mwifiex_8997/script/wifidirect/update_mac.sh | 16 + .../script/wifidisplay/start_auto_go.sh | 36 + .../script/wifidisplay/start_find_phase.sh | 30 + mwifiex_8997/script/wifidisplay/update_mac.sh | 16 + 176 files changed, 272625 insertions(+) create mode 100755 mwifiex_8997/Makefile create mode 100755 mwifiex_8997/README create mode 100755 mwifiex_8997/README_MLAN create mode 100755 mwifiex_8997/README_OPENWRT create mode 100755 mwifiex_8997/README_RBC create mode 100755 mwifiex_8997/README_UAP create mode 100755 mwifiex_8997/README_WIFIDIRECT create mode 100755 mwifiex_8997/gpl-2.0.txt create mode 100755 mwifiex_8997/mapp/mlan2040coex/Makefile create mode 100755 mwifiex_8997/mapp/mlan2040coex/mlan2040coex.c create mode 100755 mwifiex_8997/mapp/mlan2040coex/mlan2040coex.h create mode 100755 mwifiex_8997/mapp/mlan2040coex/mlan2040misc.c create mode 100755 mwifiex_8997/mapp/mlan2040coex/mlan2040misc.h create mode 100755 mwifiex_8997/mapp/mlanconfig/Makefile create mode 100755 mwifiex_8997/mapp/mlanconfig/config/11n_2040coex.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/arpfilter.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/auto_tx.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/bg_scan.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/bg_scan_wifidirect.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/cal_data.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/crypto_test.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/cwmode.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/ed_mac_ctrl_V3_8997.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/host_tdls.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/init_cfg.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/mef.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/mef_mdns.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/mef_ws_discovery.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/mem.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/mgmt_frame.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/mgmtfilter.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/or_data.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/pad_cfg.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/requesttpc.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/robust_btc.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/small_debug.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/smc.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/subevent.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/tdls.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/tspecs.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/turbo_mode.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/tx_ctrl.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/txpwrlimit_cfg.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/config/txrate_cfg.conf create mode 100755 mwifiex_8997/mapp/mlanconfig/mlanconfig.c create mode 100755 mwifiex_8997/mapp/mlanconfig/mlanconfig.h create mode 100755 mwifiex_8997/mapp/mlanconfig/mlanhostcmd.c create mode 100755 mwifiex_8997/mapp/mlanconfig/mlanhostcmd.h create mode 100755 mwifiex_8997/mapp/mlanconfig/mlanmisc.c create mode 100755 mwifiex_8997/mapp/mlanconfig/mlanmisc.h create mode 100755 mwifiex_8997/mapp/mlanevent/Makefile create mode 100755 mwifiex_8997/mapp/mlanevent/mlanevent.c create mode 100755 mwifiex_8997/mapp/mlanevent/mlanevent.h create mode 100755 mwifiex_8997/mapp/mlanutl/Makefile create mode 100755 mwifiex_8997/mapp/mlanutl/mlanhostcmd.c create mode 100755 mwifiex_8997/mapp/mlanutl/mlanhostcmd.h create mode 100755 mwifiex_8997/mapp/mlanutl/mlanoffload.c create mode 100755 mwifiex_8997/mapp/mlanutl/mlanoffload.h create mode 100755 mwifiex_8997/mapp/mlanutl/mlanregclass.c create mode 100755 mwifiex_8997/mapp/mlanutl/mlanregclass.h create mode 100755 mwifiex_8997/mapp/mlanutl/mlanroamagent.c create mode 100755 mwifiex_8997/mapp/mlanutl/mlanroamagent.h create mode 100755 mwifiex_8997/mapp/mlanutl/mlanscanagent.c create mode 100755 mwifiex_8997/mapp/mlanutl/mlanscanagent.h create mode 100755 mwifiex_8997/mapp/mlanutl/mlanutl.c create mode 100755 mwifiex_8997/mapp/mlanutl/mlanutl.h create mode 100755 mwifiex_8997/mapp/mlanutl/timestamp.c create mode 100755 mwifiex_8997/mapp/mlanutl/timestamp.h create mode 100755 mwifiex_8997/mapp/uaputl/Makefile create mode 100755 mwifiex_8997/mapp/uaputl/config/80211d_domain.conf create mode 100755 mwifiex_8997/mapp/uaputl/config/embedded_dhcp.conf create mode 100755 mwifiex_8997/mapp/uaputl/config/sample_cal_data_bg_8688.conf create mode 100755 mwifiex_8997/mapp/uaputl/config/tdls_ext_cap.conf create mode 100755 mwifiex_8997/mapp/uaputl/config/uapcoex.conf create mode 100755 mwifiex_8997/mapp/uaputl/config/uaputl.conf create mode 100755 mwifiex_8997/mapp/uaputl/config/uaputl_wifidirect.conf create mode 100755 mwifiex_8997/mapp/uaputl/uapcmd.c create mode 100755 mwifiex_8997/mapp/uaputl/uapcmd.h create mode 100755 mwifiex_8997/mapp/uaputl/uaphostcmd.c create mode 100755 mwifiex_8997/mapp/uaputl/uaputl.c create mode 100755 mwifiex_8997/mapp/uaputl/uaputl.h create mode 100755 mwifiex_8997/mapp/wifidirectutl/Makefile create mode 100755 mwifiex_8997/mapp/wifidirectutl/config/wifidirect.conf create mode 100755 mwifiex_8997/mapp/wifidirectutl/config/wifidisplay.conf create mode 100755 mwifiex_8997/mapp/wifidirectutl/wifi_display.c create mode 100755 mwifiex_8997/mapp/wifidirectutl/wifi_display.h create mode 100755 mwifiex_8997/mapp/wifidirectutl/wifidirectutl.c create mode 100755 mwifiex_8997/mapp/wifidirectutl/wifidirectutl.h create mode 100755 mwifiex_8997/mlan/mlan.h create mode 100755 mwifiex_8997/mlan/mlan_11ac.c create mode 100755 mwifiex_8997/mlan/mlan_11ac.h create mode 100755 mwifiex_8997/mlan/mlan_11d.c create mode 100755 mwifiex_8997/mlan/mlan_11h.c create mode 100755 mwifiex_8997/mlan/mlan_11h.h create mode 100755 mwifiex_8997/mlan/mlan_11n.c create mode 100755 mwifiex_8997/mlan/mlan_11n.h create mode 100755 mwifiex_8997/mlan/mlan_11n_aggr.c create mode 100755 mwifiex_8997/mlan/mlan_11n_aggr.h create mode 100755 mwifiex_8997/mlan/mlan_11n_rxreorder.c create mode 100755 mwifiex_8997/mlan/mlan_11n_rxreorder.h create mode 100755 mwifiex_8997/mlan/mlan_cfp.c create mode 100755 mwifiex_8997/mlan/mlan_cmdevt.c create mode 100755 mwifiex_8997/mlan/mlan_decl.h create mode 100755 mwifiex_8997/mlan/mlan_fw.h create mode 100755 mwifiex_8997/mlan/mlan_ieee.h create mode 100755 mwifiex_8997/mlan/mlan_init.c create mode 100755 mwifiex_8997/mlan/mlan_init.h create mode 100755 mwifiex_8997/mlan/mlan_ioctl.h create mode 100755 mwifiex_8997/mlan/mlan_join.c create mode 100755 mwifiex_8997/mlan/mlan_join.h create mode 100755 mwifiex_8997/mlan/mlan_main.h create mode 100755 mwifiex_8997/mlan/mlan_meas.c create mode 100755 mwifiex_8997/mlan/mlan_meas.h create mode 100755 mwifiex_8997/mlan/mlan_misc.c create mode 100755 mwifiex_8997/mlan/mlan_module.c create mode 100755 mwifiex_8997/mlan/mlan_pcie.c create mode 100755 mwifiex_8997/mlan/mlan_pcie.h create mode 100755 mwifiex_8997/mlan/mlan_scan.c create mode 100755 mwifiex_8997/mlan/mlan_shim.c create mode 100755 mwifiex_8997/mlan/mlan_sta_cmd.c create mode 100755 mwifiex_8997/mlan/mlan_sta_cmdresp.c create mode 100755 mwifiex_8997/mlan/mlan_sta_event.c create mode 100755 mwifiex_8997/mlan/mlan_sta_ioctl.c create mode 100755 mwifiex_8997/mlan/mlan_sta_rx.c create mode 100755 mwifiex_8997/mlan/mlan_sta_tx.c create mode 100755 mwifiex_8997/mlan/mlan_txrx.c create mode 100755 mwifiex_8997/mlan/mlan_uap.h create mode 100755 mwifiex_8997/mlan/mlan_uap_cmdevent.c create mode 100755 mwifiex_8997/mlan/mlan_uap_ioctl.c create mode 100755 mwifiex_8997/mlan/mlan_uap_txrx.c create mode 100755 mwifiex_8997/mlan/mlan_util.h create mode 100755 mwifiex_8997/mlan/mlan_wmm.c create mode 100755 mwifiex_8997/mlan/mlan_wmm.h create mode 100755 mwifiex_8997/mlinux/mlan.h create mode 100755 mwifiex_8997/mlinux/mlan_decl.h create mode 100755 mwifiex_8997/mlinux/mlan_ieee.h create mode 100755 mwifiex_8997/mlinux/mlan_ioctl.h create mode 100755 mwifiex_8997/mlinux/moal_cfg80211.c create mode 100755 mwifiex_8997/mlinux/moal_cfg80211.h create mode 100755 mwifiex_8997/mlinux/moal_cfgvendor.c create mode 100755 mwifiex_8997/mlinux/moal_cfgvendor.h create mode 100755 mwifiex_8997/mlinux/moal_debug.c create mode 100755 mwifiex_8997/mlinux/moal_eth_ioctl.c create mode 100755 mwifiex_8997/mlinux/moal_eth_ioctl.h create mode 100755 mwifiex_8997/mlinux/moal_ioctl.c create mode 100755 mwifiex_8997/mlinux/moal_main.c create mode 100755 mwifiex_8997/mlinux/moal_main.h create mode 100755 mwifiex_8997/mlinux/moal_pcie.c create mode 100755 mwifiex_8997/mlinux/moal_pcie.h create mode 100755 mwifiex_8997/mlinux/moal_priv.c create mode 100755 mwifiex_8997/mlinux/moal_priv.h create mode 100755 mwifiex_8997/mlinux/moal_proc.c create mode 100755 mwifiex_8997/mlinux/moal_shim.c create mode 100755 mwifiex_8997/mlinux/moal_shim.h create mode 100755 mwifiex_8997/mlinux/moal_sta_cfg80211.c create mode 100755 mwifiex_8997/mlinux/moal_sta_cfg80211.h create mode 100755 mwifiex_8997/mlinux/moal_uap.c create mode 100755 mwifiex_8997/mlinux/moal_uap.h create mode 100755 mwifiex_8997/mlinux/moal_uap_cfg80211.c create mode 100755 mwifiex_8997/mlinux/moal_uap_cfg80211.h create mode 100755 mwifiex_8997/mlinux/moal_uap_priv.c create mode 100755 mwifiex_8997/mlinux/moal_uap_priv.h create mode 100755 mwifiex_8997/mlinux/moal_uap_wext.c create mode 100755 mwifiex_8997/mlinux/moal_wext.c create mode 100755 mwifiex_8997/mlinux/moal_wext.h create mode 100755 mwifiex_8997/script/pcie/load create mode 100755 mwifiex_8997/script/pcie/unload create mode 100755 mwifiex_8997/script/wifidirect/start_auto_go.sh create mode 100755 mwifiex_8997/script/wifidirect/start_find_phase.sh create mode 100755 mwifiex_8997/script/wifidirect/start_listen_state.sh create mode 100755 mwifiex_8997/script/wifidirect/stop_auto_go.sh create mode 100755 mwifiex_8997/script/wifidirect/stop_wifidirect_client.sh create mode 100755 mwifiex_8997/script/wifidirect/update_mac.sh create mode 100755 mwifiex_8997/script/wifidisplay/start_auto_go.sh create mode 100755 mwifiex_8997/script/wifidisplay/start_find_phase.sh create mode 100755 mwifiex_8997/script/wifidisplay/update_mac.sh diff --git a/mwifiex_8997/Makefile b/mwifiex_8997/Makefile new file mode 100755 index 0000000..2f2771e --- /dev/null +++ b/mwifiex_8997/Makefile @@ -0,0 +1,580 @@ +# File: Makefile +# +# Copyright (C) 2008-2019, Marvell International Ltd. +# +# This software file (the "File") is distributed by Marvell International +# Ltd. under the terms of the GNU General Public License Version 2, June 1991 +# (the "License"). You may use, redistribute and/or modify this File in +# accordance with the terms and conditions of the License, a copy of which +# is available by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the +# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. +# +# A copy of the GPL is available in file gpl-2.0.txt accompanying in this +# deliverables. +# +# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE +# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE +# ARE EXPRESSLY DISCLAIMED. The License provides additional details about +# this warranty disclaimer. + +COMPATDIR=/lib/modules/$(KERNELVERSION_X86)/build/compat-wireless-3.2-rc1-1/include +CC= $(CROSS_COMPILE)gcc -I$(COMPATDIR) +LD= $(CROSS_COMPILE)ld +BACKUP= /root/backup +YMD= `date +%Y%m%d%H%M` + +ifneq ($(COMPAT_VERSION_CODE),) +DRV_DIR ?= $(shell pwd) +export DRV_DIR +COMPAT_VERSION=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$1}') +COMPAT_PATCHLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$2}') +COMPAT_SUBLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$3}') +DECL_HEADER_FILE=$(DRV_DIR)/mlinux/moal_main.h +$(shell sed -i 's/COMPAT_VERSION_CODE KERNEL_VERSION.*/COMPAT_VERSION_CODE KERNEL_VERSION(\ + $(COMPAT_VERSION), $(COMPAT_PATCHLEVEL), $(COMPAT_SUBLEVEL))/g' $(DECL_HEADER_FILE)) +endif + +############################################################################# +# Configuration Options +############################################################################# + +# Debug Option +# DEBUG LEVEL n/1/2: +# n: NO DEBUG +# 1: Only PRINTM(MMSG,...), PRINTM(MFATAL,...), ... +# 2: All PRINTM() +CONFIG_DEBUG=1 + +# Proc debug file +CONFIG_PROC_DEBUG=y + +# Enable STA mode support +CONFIG_STA_SUPPORT=y + +# Enable uAP mode support +CONFIG_UAP_SUPPORT=y + +# Enable WIFIDIRECT support +CONFIG_WIFI_DIRECT_SUPPORT=y + +# Enable WIFIDISPLAY support +CONFIG_WIFI_DISPLAY_SUPPORT=y + +# Re-association in driver +CONFIG_REASSOCIATION=y + + +# Manufacturing firmware support +CONFIG_MFG_CMD_SUPPORT=y + +# OpenWrt support +CONFIG_OPENWRT_SUPPORT=n + +# Big-endian platform +CONFIG_BIG_ENDIAN=n + + + + +ifeq ($(CONFIG_DRV_EMBEDDED_SUPPLICANT), y) +CONFIG_EMBEDDED_SUPP_AUTH=y +else +ifeq ($(CONFIG_DRV_EMBEDDED_AUTHENTICATOR), y) +CONFIG_EMBEDDED_SUPP_AUTH=y +endif +endif + + + + +# DFS testing support +CONFIG_DFS_TESTING_SUPPORT=y + +# Multi-channel support +CONFIG_MULTI_CHAN_SUPPORT=y + + +CONFIG_ANDROID_KERNEL=n + + +#32bit app over 64bit kernel support +CONFIG_USERSPACE_32BIT_OVER_KERNEL_64BIT=n + + +############################################################################# +# Select Platform Tools +############################################################################# + +MODEXT = ko +ccflags-y += -I$(M)/mlan +ccflags-y += -DLINUX + + + + +KERNELVERSION_X86 := $(shell uname -r) +KERNELDIR ?= /lib/modules/$(KERNELVERSION_X86)/build +LD += -S + +BINDIR = ../bin_pcie8997 +APPDIR= $(shell if test -d "mapp"; then echo mapp; fi) + +############################################################################# +# Compiler Flags +############################################################################# + + ccflags-y += -I$(KERNELDIR)/include + + ccflags-y += -DFPNUM='"68"' + +ifeq ($(CONFIG_DEBUG),1) + ccflags-y += -DDEBUG_LEVEL1 +endif + +ifeq ($(CONFIG_DEBUG),2) + ccflags-y += -DDEBUG_LEVEL1 + ccflags-y += -DDEBUG_LEVEL2 + DBG= -dbg +endif + +ifeq ($(CONFIG_PROC_DEBUG),y) + ccflags-y += -DPROC_DEBUG + export CONFIG_PROC_DEBUG +endif + +ifeq ($(CONFIG_64BIT), y) + ccflags-y += -DMLAN_64BIT +endif + +ifeq ($(CONFIG_STA_SUPPORT),y) + ccflags-y += -DSTA_SUPPORT +ifeq ($(CONFIG_REASSOCIATION),y) + ccflags-y += -DREASSOCIATION +endif +else +CONFIG_WIFI_DIRECT_SUPPORT=n +CONFIG_WIFI_DISPLAY_SUPPORT=n +CONFIG_STA_WEXT=n +CONFIG_STA_CFG80211=n +endif + +ifeq ($(CONFIG_UAP_SUPPORT),y) + ccflags-y += -DUAP_SUPPORT +else +CONFIG_WIFI_DIRECT_SUPPORT=n +CONFIG_WIFI_DISPLAY_SUPPORT=n +CONFIG_UAP_WEXT=n +CONFIG_UAP_CFG80211=n +endif + +ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y) + ccflags-y += -DWIFI_DIRECT_SUPPORT +endif +ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y) + ccflags-y += -DWIFI_DISPLAY_SUPPORT +endif + +ifeq ($(CONFIG_MFG_CMD_SUPPORT),y) + ccflags-y += -DMFG_CMD_SUPPORT +endif + +ifeq ($(CONFIG_BIG_ENDIAN),y) + ccflags-y += -DBIG_ENDIAN_SUPPORT +endif + +ifeq ($(CONFIG_USERSPACE_32BIT_OVER_KERNEL_64BIT),y) + ccflags-y += -DUSERSPACE_32BIT_OVER_KERNEL_64BIT +endif + + + +ifeq ($(CONFIG_MULTI_CHAN_SUPPORT),y) + ccflags-y += -DMULTI_CHAN_SUPPORT +endif + +ifeq ($(CONFIG_DFS_TESTING_SUPPORT),y) + ccflags-y += -DDFS_TESTING_SUPPORT +endif + + +ifeq ($(CONFIG_ANDROID_KERNEL), y) + ccflags-y += -DANDROID_KERNEL +endif + +ifeq ($(CONFIG_OPENWRT_SUPPORT), y) + ccflags-y += -DOPENWRT +endif + + +ifeq ($(CONFIG_T50), y) + ccflags-y += -DT50 + ccflags-y += -DT40 + ccflags-y += -DT3T +endif + +# add -Wno-packed-bitfield-compat when GCC version greater than 4.4 +GCC_VERSION := $(shell echo `gcc -dumpversion | cut -f1-2 -d.` \>= 4.4 | sed -e 's/\./*100+/g' | bc ) +ifeq ($(GCC_VERSION),1) + ccflags-y += -Wno-packed-bitfield-compat +endif + +############################################################################# +# Make Targets +############################################################################# + +ifneq ($(KERNELRELEASE),) + +ifeq ($(CONFIG_WIRELESS_EXT),y) +ifeq ($(CONFIG_WEXT_PRIV),y) + # Enable WEXT for STA + CONFIG_STA_WEXT=y + # Enable WEXT for uAP + CONFIG_UAP_WEXT=y +else +# Disable WEXT for STA + CONFIG_STA_WEXT=n +# Disable WEXT for uAP + CONFIG_UAP_WEXT=n +endif +endif + +# Enable CFG80211 for STA +ifeq ($(CONFIG_CFG80211),y) + CONFIG_STA_CFG80211=y +else +ifeq ($(CONFIG_CFG80211),m) + CONFIG_STA_CFG80211=y +else + CONFIG_STA_CFG80211=n +endif +endif + +# OpenWrt +ifeq ($(CONFIG_OPENWRT_SUPPORT), y) +ifeq ($(CPTCFG_CFG80211),y) + CONFIG_STA_CFG80211=y +else +ifeq ($(CPTCFG_CFG80211),m) + CONFIG_STA_CFG80211=y +else + CONFIG_STA_CFG80211=n +endif +endif +endif + +# Enable CFG80211 for uAP +ifeq ($(CONFIG_CFG80211),y) + CONFIG_UAP_CFG80211=y +else +ifeq ($(CONFIG_CFG80211),m) + CONFIG_UAP_CFG80211=y +else + CONFIG_UAP_CFG80211=n +endif +endif + +# OpenWrt +ifeq ($(CONFIG_OPENWRT_SUPPORT), y) +ifeq ($(CPTCFG_CFG80211),y) + CONFIG_UAP_CFG80211=y +else +ifeq ($(CPTCFG_CFG80211),m) + CONFIG_UAP_CFG80211=y +else + CONFIG_UAP_CFG80211=n +endif +endif +endif + +ifneq ($(CONFIG_STA_SUPPORT),y) + CONFIG_WIFI_DIRECT_SUPPORT=n + CONFIG_WIFI_DISPLAY_SUPPORT=n + CONFIG_STA_WEXT=n + CONFIG_STA_CFG80211=n +endif + +ifneq ($(CONFIG_UAP_SUPPORT),y) + CONFIG_WIFI_DIRECT_SUPPORT=n + CONFIG_WIFI_DISPLAY_SUPPORT=n + CONFIG_UAP_WEXT=n + CONFIG_UAP_CFG80211=n +endif + +ifeq ($(CONFIG_STA_SUPPORT),y) +ifeq ($(CONFIG_STA_WEXT),y) + ccflags-y += -DSTA_WEXT +endif +ifeq ($(CONFIG_STA_CFG80211),y) + ccflags-y += -DSTA_CFG80211 +endif +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) +ifeq ($(CONFIG_UAP_WEXT),y) + ccflags-y += -DUAP_WEXT +endif +ifeq ($(CONFIG_UAP_CFG80211),y) + ccflags-y += -DUAP_CFG80211 +endif +endif + +print: +ifeq ($(CONFIG_STA_SUPPORT),y) +ifeq ($(CONFIG_STA_WEXT),n) +ifeq ($(CONFIG_STA_CFG80211),n) + @echo "Can not build STA without WEXT or CFG80211" + exit 2 +endif +endif +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) +ifeq ($(CONFIG_UAP_WEXT),n) +ifeq ($(CONFIG_UAP_CFG80211),n) + @echo "Can not build UAP without WEXT or CFG80211" + exit 2 +endif +endif +endif + + + + + +MOALOBJS = mlinux/moal_main.o \ + mlinux/moal_ioctl.o \ + mlinux/moal_shim.o \ + mlinux/moal_eth_ioctl.o + +MLANOBJS = mlan/mlan_shim.o mlan/mlan_init.o \ + mlan/mlan_txrx.o \ + mlan/mlan_cmdevt.o mlan/mlan_misc.o \ + mlan/mlan_cfp.o \ + mlan/mlan_module.o + +MLANOBJS += mlan/mlan_wmm.o +MLANOBJS += mlan/mlan_pcie.o +MLANOBJS += mlan/mlan_11n_aggr.o +MLANOBJS += mlan/mlan_11n_rxreorder.o +MLANOBJS += mlan/mlan_11n.o +MLANOBJS += mlan/mlan_11ac.o +MLANOBJS += mlan/mlan_11d.o +MLANOBJS += mlan/mlan_11h.o +ifeq ($(CONFIG_STA_SUPPORT),y) +MLANOBJS += mlan/mlan_meas.o +MLANOBJS += mlan/mlan_scan.o \ + mlan/mlan_sta_ioctl.o \ + mlan/mlan_sta_rx.o \ + mlan/mlan_sta_tx.o \ + mlan/mlan_sta_event.o \ + mlan/mlan_sta_cmd.o \ + mlan/mlan_sta_cmdresp.o \ + mlan/mlan_join.o +ifeq ($(CONFIG_STA_WEXT),y) +MOALOBJS += mlinux/moal_priv.o \ + mlinux/moal_wext.o +endif +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) +MLANOBJS += mlan/mlan_uap_ioctl.o +MLANOBJS += mlan/mlan_uap_cmdevent.o +MLANOBJS += mlan/mlan_uap_txrx.o +MOALOBJS += mlinux/moal_uap.o +ifeq ($(CONFIG_UAP_WEXT),y) +MOALOBJS += mlinux/moal_uap_priv.o +MOALOBJS += mlinux/moal_uap_wext.o +endif +endif +ifeq ($(CONFIG_STA_CFG80211),y) +MOALOBJS += mlinux/moal_cfg80211.o +MOALOBJS += mlinux/moal_cfgvendor.o +MOALOBJS += mlinux/moal_sta_cfg80211.o +endif +ifeq ($(CONFIG_UAP_CFG80211),y) +MOALOBJS += mlinux/moal_cfg80211.o +MOALOBJS += mlinux/moal_cfgvendor.o +MOALOBJS += mlinux/moal_uap_cfg80211.o +endif + +ifdef CONFIG_PROC_FS +MOALOBJS += mlinux/moal_proc.o +ifeq ($(CONFIG_PROC_DEBUG),y) +MOALOBJS += mlinux/moal_debug.o +endif +endif + + + + + + + + +ifeq ($(CONFIG_CONCURRENT_DRIVER),y) +obj-m := mlan_pcie.o +mlan_pcie-objs := $(MLANOBJS) +else +obj-m := mlan.o +mlan-objs := $(MLANOBJS) +endif +MOALOBJS += mlinux/moal_pcie.o +obj-m += pcie8xxx.o +pcie8xxx-objs := $(MOALOBJS) + +# Otherwise we were called directly from the command line; invoke the kernel build system. +else + +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +endif + +############################################################### + +export CC LD ccflags-y KERNELDIR + +ifeq ($(CONFIG_STA_SUPPORT),y) +ifeq ($(CONFIG_UAP_SUPPORT),y) +.PHONY: mapp/mlanconfig mapp/mlan2040coex mapp/mlanevent mapp/uaputl mapp/mlanutl clean distclean +else +.PHONY: mapp/mlanconfig mapp/mlanevent mapp/mlan2040coex mapp/mlanutl clean distclean +endif +else +ifeq ($(CONFIG_UAP_SUPPORT),y) +.PHONY: mapp/mlanevent mapp/uaputl clean distclean +endif +endif + @echo "Finished Making Marvell Wlan Linux Driver" + +ifeq ($(CONFIG_STA_SUPPORT),y) +mapp/mlanconfig: + $(MAKE) -C $@ +mapp/mlanutl: + $(MAKE) -C $@ +mapp/mlan2040coex: + $(MAKE) -C $@ +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) +mapp/uaputl: + $(MAKE) -C $@ +endif +ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y) +mapp/wifidirectutl: + $(MAKE) -C $@ +endif +mapp/mlanevent: + $(MAKE) -C $@ + +echo: + +build: echo default + + @if [ ! -d $(BINDIR) ]; then \ + mkdir $(BINDIR); \ + fi + +ifeq ($(CONFIG_CONCURRENT_DRIVER),y) + cp -f mlan_pcie.$(MODEXT) $(BINDIR)/mlan_pcie$(DBG).$(MODEXT) +else + cp -f mlan.$(MODEXT) $(BINDIR)/mlan$(DBG).$(MODEXT) +endif + cp -f pcie8xxx.$(MODEXT) $(BINDIR)/pcie8997$(DBG).$(MODEXT) + cp -rpf script/pcie/* $(BINDIR)/ + +ifeq ($(CONFIG_STA_SUPPORT),y) + cp -f README $(BINDIR) + cp -f README_MLAN $(BINDIR) + cp -f README_RBC $(BINDIR) +ifeq ($(CONFIG_OPENWRT_SUPPORT),y) + cp -f README_OPENWRT $(BINDIR) +endif +ifneq ($(APPDIR),) + $(MAKE) -C mapp/mlanconfig $@ INSTALLDIR=$(BINDIR) + $(MAKE) -C mapp/mlanutl $@ INSTALLDIR=$(BINDIR) + $(MAKE) -C mapp/mlan2040coex $@ INSTALLDIR=$(BINDIR) +endif +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) + cp -f README_UAP $(BINDIR) +ifneq ($(APPDIR),) + $(MAKE) -C mapp/uaputl $@ INSTALLDIR=$(BINDIR) +endif +endif +ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y) + cp -f README_WIFIDIRECT $(BINDIR) + cp -rpf script/wifidirect $(BINDIR) +ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y) + cp -rpf script/wifidisplay $(BINDIR) +endif +ifneq ($(APPDIR),) + $(MAKE) -C mapp/wifidirectutl $@ INSTALLDIR=$(BINDIR) +endif +endif +ifneq ($(APPDIR),) + $(MAKE) -C mapp/mlanevent $@ INSTALLDIR=$(BINDIR) +endif + +clean: + -find . -name "*.o" -exec rm {} \; + -find . -name "*.ko" -exec rm {} \; + -find . -name ".*.cmd" -exec rm {} \; + -find . -name "*.mod.c" -exec rm {} \; + -find . -name "Module.symvers" -exec rm {} \; + -find . -name "Module.markers" -exec rm {} \; + -find . -name "modules.order" -exec rm {} \; + -find . -name ".*.dwo" -exec rm {} \; + -find . -name "*dwo" -exec rm {} \; + -rm -rf .tmp_versions +ifneq ($(APPDIR),) +ifeq ($(CONFIG_STA_SUPPORT),y) + $(MAKE) -C mapp/mlanconfig $@ + $(MAKE) -C mapp/mlanutl $@ + $(MAKE) -C mapp/mlan2040coex $@ +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) + $(MAKE) -C mapp/uaputl $@ +endif +ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y) + $(MAKE) -C mapp/wifidirectutl $@ +endif + $(MAKE) -C mapp/mlanevent $@ +endif + +install: default + + cp -f mlan.$(MODEXT) $(INSTALLDIR)/mlan$(DBG).$(MODEXT) + cp -f pcie8xxx.$(MODEXT) $(INSTALLDIR)/pcie8997$(DBG).$(MODEXT) + echo $(INSTALLDIR) + echo "pcie8997 Driver Installed" + +distclean: + -find . -name "*.o" -exec rm {} \; + -find . -name "*.orig" -exec rm {} \; + -find . -name "*.swp" -exec rm {} \; + -find . -name "*.*~" -exec rm {} \; + -find . -name "*~" -exec rm {} \; + -find . -name "*.d" -exec rm {} \; + -find . -name "*.a" -exec rm {} \; + -find . -name "tags" -exec rm {} \; + -find . -name ".*" -exec rm -rf 2> /dev/null \; + -find . -name "*.ko" -exec rm {} \; + -find . -name ".*.cmd" -exec rm {} \; + -find . -name "*.mod.c" -exec rm {} \; + -find . -name ".*.dwo" -exec rm {} \; + -find . -name "*dwo" -exec rm {} \; + -rm -rf .tmp_versions +ifneq ($(APPDIR),) +ifeq ($(CONFIG_STA_SUPPORT),y) + $(MAKE) -C mapp/mlanconfig $@ + $(MAKE) -C mapp/mlanutl $@ + $(MAKE) -C mapp/mlan2040coex $@ +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) + $(MAKE) -C mapp/uaputl $@ +endif +ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y) + $(MAKE) -C mapp/wifidirectutl $@ +endif + $(MAKE) -C mapp/mlanevent $@ +endif + +# End of file diff --git a/mwifiex_8997/README b/mwifiex_8997/README new file mode 100755 index 0000000..bc32676 --- /dev/null +++ b/mwifiex_8997/README @@ -0,0 +1,2225 @@ +=============================================================================== + U S E R M A N U A L + + Copyright (C) 2008-2019, Marvell International Ltd. + All Rights Reserved + +1) FOR DRIVER BUILD + + Goto source code directory wlan_src/. + make [clean] build + The driver and utility binaries can be found in ../bin_xxxx directory. + The driver code supports Linux kernel up to 5.0.9. + +2) FOR DRIVER INSTALL + + a) Copy firmware image pcie8897_uapsta.bin | ... to /lib/firmware/mrvl/ directory, + create the directory if it doesn't exist. + b) Install WLAN driver + There are drv_mode, max_sta_bss, max_uap_bss etc. module parameters. + The bit settings of drv_mode are, + Bit 0 : STA + Bit 1 : uAP + Bit 2 : WIFIDIRECT + Bit 4 : NAN + + max_sta_bss: Maximum number of STA BSS (default 1, max 1) + sta_name: Name of the STA interface (default: "mlan") + max_uap_bss: Maximum number of uAP BSS (default 1, max 2) + uap_name: Name of the uAP interface (default: "uap") + uap_max_sta: Maximum number of STA for UAP/GO (default 0, max 10) + max_wfd_bss: Maximum number of WIFIDIRECT BSS (default 1, max 1) + wfd_name: Name of the WIFIDIRECT interface (default: "wfd") + max_vir_bss: Number of Virtual interfaces (default 0) + nan_name: Name of the NAN interface (default: "nan") + max_nan_bss: Number of NAN interfaces (default 1) + For example, to install PCIE8897 driver, + insmod mlan.ko + insmod pcie8897.ko [drv_mode=3] [fw_name=mrvl/pcie8897_uapsta.bin] + To load driver in STA only mode, + insmod mlan.ko + insmod pcie8897.ko drv_mode=1 [fw_name=mrvl/pcie8897_uapsta.bin] + To load driver in uAP only mode, + insmod mlan.ko + insmod pcie8897.ko drv_mode=2 [fw_name=mrvl/pcie8897_uapsta.bin] + + To switch mode between STA only, uAP only and uAPSTA in run time, + echo drv_mode=1 > /proc/mwlan/config // STA mode + echo drv_mode=2 > /proc/mwlan/config // uAP mode + echo drv_mode=3 > /proc/mwlan/config // uAPSTA mode + c) Uninstall WLAN driver, + ifconfig mlanX down + ifconfig uapX down + rmmod pcie8xxx + rmmod mlan + + Use mfg_mode = 1: + To load driver with MFG firmware file, when insmod WLAN driver and specify MFG firmware name if needed. + This option loads default normal FW on HW reset (reset button is pressed on the board). + + Use mfg_mode = 2: + To load driver with MFG firmware file, when insmod WLAN driver and specify MFG firmware name if needed. + This option reloads previously specifed MFG firmware only on HW reset. + + There are some other parameters for debugging purpose etc. Use modinfo to check details. + drvdbg= + dev_cap_mask= + mac_addr=xx:xx:xx:xx:xx:xx + auto_ds=0|1|2 + ps_mode=0|1|2 + p2p_enh=0|1 + max_tx_buf=2048|4096|8192 + cfg_11d=0|1|2 + dts_enable=0|1 + hw_test=0|1 + fw_serial=0|1 + req_fw_nowait=0|1 + init_cfg= + e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf + cal_data_cfg= + e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf + txpwrlimit_cfg= + e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf + init_hostcmd_cfg= + e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf + cfg80211_wext= + Bit 0: STA WEXT + Bit 1: uAP WEXT + Bit 2: STA CFG80211 + Bit 3: uAP CFG80211 + cfg80211_drcs=1|0 + reg_alpha2= + wq_sched_prio: Priority for work queue + wq_sched_policy: Scheduling policy for work queue + (0: SCHED_NORMAL, 1: SCHED_FIFO, 2: SCHED_RR, 3: SCHED_BATCH, 5: SCHED_IDLE) + Please note that, both wq_sched_prio and wq_sched_policy should be provided + as module parameters. If wq_sched_policy is (0, 3 or 5), then wq_sched_prio + must be 0. wq_sched_prio should be 1 to 99 otherwise. + rx_work=0|1|2 + indrstcfg=<2-byte IR configuration> + gpio pin (high byte): GPIO pin no to be used as trigger for out band reset + (0xFF: default pin configuration) + ir_mode (low byte) : independent reset mode + (0: disable, 1: enable out band, 2: enable in band) + For example, to enable out band reset via gpio_pin 14 + indrstcfg=0x0e01 + To enable out band reset via default gpio_pin + indrstcfg=0xff01 + To enable in band reset and disable out band reset + indrstcfg=0x02 + + Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used + for module parameters. + insmod sd8xxx.ko " ..." + +3) FOR DRIVER PROC & DEBUG + + The following info are provided in /proc/net/mwlan/mlanX/info, + on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/info. + + driver_name = "wlan" + driver_version = + interface_name = "mlanX" + bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown" + media_state = "Disconnected" | "Connected" + mac_address = <6-byte adapter MAC address> + multicase_count = + essid = + bssid = + channel = + region_code = + multicast_address[n] = + num_tx_bytes = + num_rx_bytes = + num_tx_pkts = + num_rx_pkts = + num_tx_pkts_dropped = + num_rx_pkts_dropped = + num_tx_pkts_err = + num_rx_pkts_err = + carrier "on" | "off" + tx queue "stopped" | "started" + + The following debug info are provided in /proc/net/mwlan/mlanX/debug, + on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/debug. + + drvdbg = + wmm_ac_vo = + wmm_ac_vi = + wmm_ac_be = + wmm_ac_bk = + max_tx_buf_size = + tx_buf_size = + curr_tx_buf_size = + ps_mode = <0/1, CAM mode/PS mode> + ps_state = <0/1/2/3, awake state/pre-sleep state/sleep-confirm state/sleep state> + is_deep_sleep = <0/1, not deep sleep state/deep sleep state> + wakeup_dev_req = <0/1, wakeup device not required/required> + wakeup_tries = + hs_configured = <0/1, host sleep not configured/configured> + hs_activated = <0/1, extended host sleep not activated/activated> + tx_pkts_queued = + pps_uapsd_mode = <0/1, PPS/UAPSD mode disabled/enabled> + sleep_pd = + qos_cfg = + tx_lock_flag = <0/1, Tx lock flag> + port_open = <0/1, port open flag> + scan_processing = <0/1, scan processing flag> + num_tx_timeout = + num_cmd_timeout = + timeout_cmd_id = + timeout_cmd_act = + last_cmd_id = + last_cmd_act = + last_cmd_index = <0 based last command index> + last_cmd_resp_id = + last_cmd_resp_index = <0 based last command response index> + last_event = + last_event_index = <0 based last event index> + num_cmd_h2c_fail = + num_cmd_sleep_cfm_fail = + num_tx_h2c_fail = + num_evt_deauth = + num_evt_disassoc = + num_evt_link_lost = + num_cmd_deauth = + num_cmd_assoc_ok = + num_cmd_assoc_fail = + cmd_sent = <0/1, send command resources available/sending command to device> + data_sent = <0/1, send data resources available/sending data to device> + txbd_rdptr = + txbd_wrptr = + rxbd_rdptr = + rxbd_wrptr = + eventbd_rdptr = + eventbd_wrptr = + cmd_resp_received = <0/1, no cmd response to process/response received and yet to process> + event_received = <0/1, no event to process/event received and yet to process> + ioctl_pending = + tx_pending = + rx_pending = + lock_count = + malloc_count = + mbufalloc_count = + malloc_cons_count = + main_state = + + Use dmesg or cat /var/log/debug to check driver debug messages. + To log driver debug messages to file, + a) Edit /etc/syslog.conf, add one line "*.debug /var/log/debug" + on kernel 2.6.24 or later, edit /etc/rsyslog.conf instead + b) touch /var/log/debug (if the file doesn't exist) + c) service syslog restart + on kernel 2.6.24 or later, service rsyslog restart + + Update /proc/sys/kernel/printk to change message log levels. + For example, + echo 6 > /proc/sys/kernel/printk (messages with a higher priority than 6 + will be printed to the console) + echo 15 > /proc/sys/kernel/printk (all messages will be printed to console) + +4) FOR IWPRIV COMMAND + +NAME + This manual describes the usage of private commands used in Marvell MLAN + Linux Driver. + + To use parameters as hex format, a '0x' must precede it for the parameters to + be parsed properly. + +SYNOPSIS + iwpriv [sub-command] ... + + iwpriv mlanX version + iwpriv mlanX verext + iwpriv mlanX getsignal [m] [n] + iwpriv mlanX antcfg [m] [n] + iwpriv mlanX regioncode [n] + iwpriv mlanX cfpcode [m] [n] + iwpriv mlanX wwscfg [m] + iwpriv mlanX esuppmode + iwpriv mlanX passphrase + iwpriv mlanX httxcfg [] [] + iwpriv mlanX htcapinfo [] [] + iwpriv mlanX addbapara

+ iwpriv mlanX aggrpriotbl + iwpriv mlanX addbareject + iwpriv mlanX txbufcfg + iwpriv mlanX amsduaggrctrl + iwpriv mlanX httxbfcap [cap] + iwpriv mlanX httxbfcfg "[;GlobalData/tsData/interval/txPeerData/snrData]" + iwpriv mlanX deepsleep [n] [m] + iwpriv mlanX hscfg [condition [[GPIO# [gap]]]] + iwpriv mlanX hssetpara condition [GPIO# [gap]] + iwpriv mlanX deauth [n] + iwpriv mlanX radioctrl + iwpriv mlanX reassoctrl [n] + iwpriv mlanX bandcfg [l] [m] [n] + iwpriv mlanX getlog + iwpriv mlanX 11dcfg + iwpriv mlanX 11dclrtbl + iwpriv mlanX wmmcfg [n] + iwpriv mlanX txpowercfg [ [ [ ]]] + iwpriv mlanX qoscfg + iwpriv mlanX getdatarate + iwpriv mlanX txratecfg [n] + iwpriv mlanX bcninterval [n] + iwpriv mlanX sysclock [clk1] [clk2] [clk3] [clk4] + iwpriv mlanX drvdbg [n] + iwpriv mlanX mgmtframectrl + iwpriv mlanX warmreset + iwpriv mlanX regrdwr [value] + iwpriv mlanX rdeeprom + iwpriv mlanX memrdwr

[value] + iwpriv mlanX inactivityto [k] + iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext] + iwpriv mlanX sleeppd [n] + iwpriv mlanX pscfg [k] [d] [l] ... + iwpriv mlanX fwwakeupmethod [n] [g] + iwpriv mlanX associate " " + iwpriv mlanX sleepparams [ ] + iwpriv mlanX netmon [ [ [offset]]] + iwpriv mlanX authtype [n] + iwpriv mlanX powercons [n] + iwpriv mlanX htstreamcfg [n] + iwpriv mlanX ipaddr [";"] + iwpriv mlanX macctrl [n] + iwpriv mlanX dfstesting [ ] + iwpriv mlanX indrstcfg [gpio_pin] + +DESCRIPTION + Those commands are used to send additional commands to the Marvell MLAN + card via the Linux device driver. + + The mlanX parameter specifies the network device that is to be used to + perform this command on. It could be mlan0, mlan1 etc. + +version + This is used to get the current version of the driver and the firmware. + +verext + Retrieve and display an extended version string from the firmware + + Usage: + iwpriv mlanX verext [#] + + where [#] is an optional argument to retrieve a specific version string, + omission of the argument retrieves the 0 indexed string. + +getsignal + This command gets the last and average value of RSSI, SNR and NF of + Beacon and Data. + Note: This command is available only when STA is connected. + + where value of m is: + 1 -- RSSI (Receive Signal Strength Indication) + 2 -- SNR (Signal to Noise Ratio) + 3 -- NF (Noise Floor) + where value of n is: + 1 -- Beacon last + 2 -- Beacon average + 3 -- Data last + 4 -- Data average + + Examples: + iwpriv mlan0 getsignal 1 : Get the RSSI info (beacon last, beacon + average, data last and data average) + iwpriv mlan0 getsignal 3 4 : Get the NF of data average + iwpriv mlan0 getsignal 2 1 : Get the SNR of beacon last + iwpriv mlan0 getsignal : Get all of the signal info + mlan0 getsignal:-32 -33 -35 -36 67 59 63 56 -99 -92 -98 -92 + RSSI info: beacon last -32, beacon average -33, data last -35, data average -36 + SNR info: beacon last 67, beacon average 59, data last 63, data average 56 + NF info: beacon last -99, beacon average -92, data last -98, data average -92 + +antcfg + This command is used to set/get the mode of Tx/Rx path. + + where value of m is: + Bit 0 -- Tx Path A + Bit 1 -- Tx Path B + Bit 0-1 -- Tx Path A+B + + where value of n is: + Bit 0 -- Rx Path A + Bit 1 -- Rx Path B + Bit 0-1 -- Rx Path A+B + The Tx path setting (m) is used if Rx path (n) is not provided. + + Examples: + iwpriv mlan0 antcfg : Get Tx and Rx path + iwpriv mlan0 antcfg 3 : Set Tx and Rx path to A+B + iwpriv mlan0 antcfg 1 3 : Set Tx path to A and Rx path to A+B + +regioncode + This command is used to set/get the region code in the station. + Note: This command should be issued at beginning before band/channel selection + and association. + + where value is 'region code' for various regions like + USA FCC, Canada IC, Europe ETSI, Japan ... + The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode. + + Examples: + iwpriv mlan0 regioncode : Get region code + iwpriv mlan0 regioncode 0x10 : Set region code to USA (0x10) + + Note : in some case regioncode will be 0 after updated countycode or 80211d + i.e. mlanutl mlanX countrycode (CA, JP, CN, DE, ES AT, BR, RU) + or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU) + Please use cfp instead of it. + +cfpcode + This command is used to set/get the Channel-Frequency-Power table codes. + The region table can be selected through region code. + The current configuration is returned if no parameter provided. + + where the parameters are, + [m]: code of the CFP table for 2.4GHz (0: unchanged) + [n]: code of the CFP table for 5GHz (0 or not provided: unchanged) + + Examples: + iwpriv mlan0 cfpcode : Get current configuration + iwpriv mlan0 cfpcode 0x30 : Set 2.4GHz CFP table code 0x30 (EU), + keep 5GHz table unchanged + iwpriv mlan0 cfpcode 0x10 5 : Set 2.4GHz CFP table code 0x10 (USA) + and 5GHz table code 5 + +wwscfg + This command is used to set/get the WWS (World Wide Safe) mode. + + where value of m is: + 0 -- Disable WWS mode (default) + 1 -- Enable WWS mode + + Examples: + iwpriv mlan0 wwscfg : Get WWS mode + iwpriv mlan0 wwscfg 1 : Enable WWS mode + iwpriv mlan0 wwscfg 0 : Disable WWS mode + +esuppmode + This command is used to get the current RSN mode and active pairwise/group + cipher for WPA/WPA2 mode. + Note: This command is available only when STA is connected. + + These are bits settings used to indicate each RSN mode. + Bit 0 : No RSN + Bit 1-2 : RFU + Bit 3 : WPA + Bit 4 : WPA-NONE + Bit 5 : WPA2 + Bit 6 : AES + Bit 7-15 : RFU + + These are bits settings used to indicate each pairwise and group cipher. + Bit 0 : RFU + Bit 1 : RFU + Bit 2 : TKIP + Bit 3 : AES + Bit 2-7 : RFU + + Example: + iwpriv mlan0 esuppmode : Get RSN mode and pairwise/group cipher + 8 4 4 + (The current RSN mode is WPA, active pairwise cipher is TKIP and + active group cipher is TKIP.) + +passphrase + This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode. + + Where + ASCII string for ssid/passphrase/psk. + + 1) "0;" - This will get the passphrase, AKMP + for specified ssid, if none specified then it will get all. + + Example: + iwpriv mlan0 passphrase "0;ssid=marvell" + + 2) "1;; + " - Passphrase and psk cannot be provided for the same SSID. + This command takes only one SSID at a time, If ssid= is present it should contain + a passphrase or psk. If no arguments are provided then AKMP=802.1x, and passphrase + should be provided after association. + End of each parameter should be followed by a ';'(except for the last parameter) + as the delimiter. If ';' or '/' has to be used in an SSID then a '/' should be preceded + to ';' or '/' as a escape. + + Examples: + iwpriv mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd" + iwpriv mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>" + + If user wants to input the ssid as "mrvl; AP" then command has to be + iwpriv mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh" + + If user wants to input the ssid as "//;" then command has to be + iwpriv mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh" + + 3) "2;" - This will clear the passphrase + for specified ssid, if none specified then it will clear all. + + Examples: + iwpriv mlan0 passphrase "2;ssid=marvell" + iwpriv mlan0 passphrase "2" : Clear all profiles and disable embedded supplicant + +httxcfg + This command is used to configure various 11n specific configuration + for transmit (such as Short GI, Channel BW and Green field support) + + where is + This is a bitmap and should be used as following + Bit 15-8: Reserved set to 0 + Bit 7: STBC enable/disable + Bit 6: Short GI in 40 Mhz enable/disable + Bit 5: Short GI in 20 Mhz enable/disable + Bit 4: Green field enable/disable + Bit 3-2: Reserved set to 1 + Bit 1: 20/40 Mhz enable disable. + Bit 0: LDPC enable/disable + + When Bit 1 is set then firmware could transmit in 20Mhz or 40Mhz based + on rate adaptation. When this bit is reset then firmware will only + transmit in 20Mhz. + + where is + - This is the band info for settings. + 0: Settings for both 2.4G and 5G bands + 1: Settings for 2.4G band + 2: Settings for 5G band + + Examples: + iwpriv mlanX httxcfg + This will display HT Tx configuration. + If the configurations for 2.4G and 5G are different, + the first value is for 2.4G and the second value is for 5G. + Otherwise, it will display a single value for both bands. + + iwpriv mlanX httxcfg 0x62 + This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band. + + iwpriv mlanX httxcfg 0x30 1 + This will enable Short GI 20 Mhz and Green field for 2.4G band. + + The default value is 0x20 for 2.4G and 0x62 for 5G. + + Note:- If 20/40 MHz support is disabled in htcapinfo, device will not transmit + in 40 MHz even 20/40 MHz is enabled in httxcfg. + +htcapinfo + This command is used to configure some of parameters in HTCapInfo IE + (such as Short GI, Channel BW, and Green field support) + + where is + - This is a bitmap and should be used as following + Bit 29: Green field enable/disable + Bit 26: Rx STBC Support enable/disable. (As we support + single spatial stream only 1 bit is used for Rx STBC) + Bit 24: Short GI in 40 Mhz enable/disable + Bit 23: Short GI in 20 Mhz enable/disable + Bit 17: 20/40 Mhz enable disable. + Bit 8: Enable/disable 40Mhz Intolarent bit in ht capinfo. + 0 will reset this bit and 1 will set this bit in + htcapinfo attached in assoc request. + All others are reserved and should be set to 0. + + Setting of any other bits will return error. + + where is + - This is the band info for settings. + 0: Settings for both 2.4G and 5G bands + 1: Settings for 2.4G band + 2: Settings for 5G band + + Examples: + iwpriv mlanX htcapinfo + This will display HT capabilties information. + If the information for 2.4G and 5G is different, + the first value is for 2.4G and the second value is for 5G. + Otherwise, it will display a single value for both bands. + + iwpriv mlanX htcapinfo 0x1820000 + This will enable Short GI, Channel BW to 20/40 and disable Green field support for 2.4G and 5G band. + + iwpriv mlanX htcapinfo 0x800000 2 + This will enable Short GI, Channel BW to 20 only, No Rx STBC support and disable Green field support for 5G band. + + The default value is 0x4800000 for 2.4G and 0x5820000 for 5G. + + Note:- This command can be issued any time but it will only come to effect from + next association. (as HTCapInfo is sent only during Association). + +addbapara + This command can be used to update the default ADDBA parameters. + + where is + - This is the block ack timeout for ADDBA request. + 0 : Disable (recommended for throughput test) + 1 - 65535 : Block Ack Timeout in TU + + where is + - Window size for ADDBA request. (16 is recommended and default value) + + where is + - Window size for ADDBA response. (48 is recommended and 32 is default value) + (16 is recommended for IWNCOMM AP in WAPI throughput test) + + Current window size limit for Tx as well as Rx is 1023. + + where

is + - amsdu support for ADDBA request. (1 is default value) + 0: disable amsdu in ADDBA request + 1: enable amsdu in ADDBA request + + where is + - amsdu support for ADDBA response. (1 is default value) + 0: disable amsdu in ADDBA response + 1: enable amsdu in ADDBA response + + eg: + iwpriv mlanX addbapara - This command will get the current addba params + iwpriv mlanX addbapara 1000 64 8 0 0 - This will change the ADDBA timeout to (1000 * 1024) us, + txwinsize to 64 and rxwinsize to 8 and disable amdsu in ADDBA request/response. + + The default setting is 65535 16 32 1 1. + + In case the ADDBA timeout value is updated then a ADDBA is sent for all streams + to update the timeout value. + + In case txwinsize and/or rxwinsize is updated, the effect could only be seen on + next ADDBA request/response. The current streams will not be affected with this + change. + + In case of txamsdu/rxamsdu is updated, the effect could only be seen on + next ADDBA request/response. The current streams will not be affected with this + change. AMSDU in AMPDU stream will be enabled when AP support this feature + and AMSDU is enabled in aggrpriotbl. + +aggrpriotbl + This command is used set/get the priority table for AMPDU/AMSDU traffic per tid. + This command can also be used to disable AMPDU/AMSDU for a given tid. + In case of AMPDU this priority table will be used to setup block ack (to make + sure the highest priority tid always uses AMPDU as we have limited AMPDU streams) + + where ... + + - This is priority for Tid0 for AMPDU packet. A priority could be any + values between 0 - 7, 0xff to disable aggregation. + - This is priority for Tid0 for AMSDU packet. A priority could be any + values between 0 - 7, 0xff to disable aggregation. + + eg: + iwpriv mlanX aggrpriotbl - This command will get the current Priority table for AMPDU and AMSDU. + <2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255>. This is read as + <"Prio for AMPDU for Tid0" "Prio for AMSDU for Tid0" + "Prio for AMPDU for Tid1" "Prio for AMSDU for Tid1" and so on + iwpriv mlanX aggrpriotbl 2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255 - + This will set the priority table for AMPDU and AMSDU + Priority for Tid0/AMPDU = 2, Tid0/AMSDU = 2, Tid1/AMPDU = 0, Tid1/AMSDU = 0 + and so on. Aggregation for Tid6 and Tid7 are disabled. + Here higher the priority number, higher the priority (i.e. 7 + has higher priority than 6). Similarly for AMSDU. + iwpriv mlanX aggrpriotbl 0xff 2 0xff 0 0xff 1 0xff 3 0xff 4 0xff 5 0xff 0xff 0xff 0xff - This will disable + AMPDU for all the TIDs but will still keep AMSDU enabled to Tid0 to Tid5 + + The default setting is 2 255 0 255 1 255 3 255 4 255 5 255 255 255 255 255. + + A delBA should be seen in case a disable happens on a TID for which AMPDU stream + is currently setup. + + Note:- This command should only be issue in disconnected state. + +addbareject + This command is used set/get the addbareject table for all the TIDs. + This command can also be used to enable rejection of ADDBA requests for a given tid. + + where ... + + - This can be 0/1 for TidX. 1 enables rejection of ADDBA request for TidX and + 0 would accept any ADDBAs for TidX. + + eg: + iwpriv mlanX addbareject - This command will get the current table. + [0 0 0 0 0 0 0 0]. ADDBA would be accepted for all TIDs. This is the default state. + + iwpriv mlanX addbareject 0 0 1 1 0 0 0 0 - This command will accept ADDBA requests for + Tid [0,1,4,5,6,7] and reject ADDBA requests for Tid [2,3] + + iwpriv mlanX addbareject 1 1 1 1 1 1 1 1 - This will enable rejection of ADDBA requests for + all Tids. + + Note:- This command should only be issue in disconnected state. + +txbufcfg + This command can be used to get current buffer size. + + eg: + iwpriv mlanX txbufcfg - This will display the current buffer size. + + Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size. + +amsduaggrctrl + This command could be used to enable/disable a feature where firmware gives feedback to driver + regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the + current rate to decide the buffer size we could transmit. The max buffer size will still be + limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit + 4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate) + + If enabled AMSDU buffer size at various rates will be as follows + + 1. Legacy B/G rate. + No AMSDU aggregation. + + 2. BW20 HT Rate: + When TX rate goes down, + MCS 7, 6, 5, 4: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 3, 2: + a 4K aggregation size (if TX buffer size is 8K/4K) + b 2K aggregation size (if TX buffer size is 2K) + + MCS 1, 0: + a No aggregation + + When TX rate goes up, + MCS 7, 6, 5: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 4, 3: + a 4K aggregation size (if TX buffer size is 8K/4K) + b 2K aggregation size (if TX buffer size is 2K) + + MCS 2, 1, 0: + a No aggregation + + 3. BW40 HT Rate: + When TX rate goes down, + MCS 7, 6, 5, 4, 3, 2, 1: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 0: + a No aggregation + + When TX rate goes up, + MCS 7, 6, 5, 4, 3: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 2, 1, 0: + a No aggregation + + where is 0/1 (for disable/enable) + + eg: + iwpriv mlanx amsduaggrctrl 1 - Enable this feature + iwpriv mlanx amsduaggrctrl 0 - Disable this feature + iwpriv mlanx amsduaggrctrl - This will get the enable/disable flag + and the current AMSDU buffer size). The AMSDU buffer size returned is only + valid after association as before association there is no rate info. + + Note:- This command to enable/disable could be given anytime (before/after + association). This feature is enabled by default by the driver during + initialization. + +httxbfcap + This command is used to set/get the TX beamforming capabilities. + + Usage: + iwpriv mlanX httxbfcap [cap] + + where the parameters are, + cap: TX beamforming capabilities + Bit 0 : Implicit TX BF receiving capable + Bit 1 : RX staggered sounding capable + Bit 2 : TX staggered sounding capable + Bit 3 : RX NDP capable + Bit 4 : TX NDP capable + Bit 5 : Implicit TX BF capable + Bit 6-7 : Calibration + 0: - not supported + 1: - STA can respond to a calibration request using + the CSI Report, but cannot initiate calibration + 2: - reserved + 3: - STA can both initiate and respond to a calibration request + Bit 8 : Explicit CSI TX BF capable + Bit 9 : Explicit non-compressed steering capable + Bit 10 : Explicit compressed steering capable + Bit 11-12: Explicit TX BF CSI feedback + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 13-14: Explicit non-compressed BF feedback capable + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 15-16: Explicit compressed BF feedback capable + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 17-18: Minimal grouping + 0: - no grouping (STA supports groups of 1) + 1: - groups of 1, 2 + 2: - groups of 1, 4 + 3: - groups of 1, 2, 4 + Bit 19-20: CSI number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 21-22: Non-compressed steering number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 23-24: Compressed steering number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 25-26: CSI max number of rows beamformer supported + 0: - single row of CSI + 1: - 2 rows of CSI + 2: - 3 rows of CSI + 3: - 4 rows of CSI + Bit 27-28: Channel estimation capability + 0: - 1 space time stream + 1: - 2 space time streams + 2: - 3 space time streams + 3: - 4 space time streams + Bit 29-31: Reserved + + Examples: + iwpriv mlan0 httxbfcap : Get the current TX BF capabilities + iwpriv mlan0 httxbfcap 0x0000001F : Set the TX BF capabilities of the + Implicit TX BF receiving capable, + RX staggered sounding capable, + TX staggered sounding capable, + RX NDP capable and TX NDP capable + +httxbfcfg + This command is used to configure the TX beamforming options. + Note: Any new subcommand should be inserted in the second + argument and each argument of the sub command should be + separated by semicolon. For global configuration, the + arguments should be separated by space. + + Usage: + iwpriv mlanX httxbfcfg "[;GlobalData/tsData/interval/txPeerData/snrData]" + + where the parameters are, + action: TX beamforming action + 0: Control global parameters for beamforming + 1: Performs NDP Sounding for PEER + 2: TX BF interval in milliseconds + 3: Enable/Disable beamforming/sounding for a particular peer + 4: TX BF SNR Threshold for peer + .. + GlobalData: Global parameter arguments. + It contains beamforming enable, sounding enable, FB type, snr_threshold + sounding interval, Beamformig mode values seperated by space. + Syntax: + iwpriv mlanX httxbfcfg ; + + tsData: Trigger sounding for PEER specific arguments, + it contains PEER MAC and status + interval: TX BF interval in milliseconds + txPeerData: Enable/Disable beamforming/sounding for the indicated peer, + it contains PEER MAC, sounding, beamfoming options and FB type; + snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR + + Examples: + iwpriv mlan0 httxbfcfg "0" : Get current global configuration parameter + iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64" : Get the TX BF periodicity for a given peer + iwpriv mlan0 httxbfcfg "3" : Get the list of MAC addresses that have + beamforming and/or sounding enabled + iwpriv mlan0 httxbfcfg "4" : Get the list of PEER MAC, SNR tuples + programmed into the firmware. + iwpriv mlan0 httxbfcfg "0;0 0 3 10 500 5" : Disable beamforming, sounding, set FB type + to 3, snr threshold to 10, sounding interval + to 500 ms and beamforming mode to 5 + iwpriv mlan0 httxbfcfg "1;00:50:43:20:BF:64" : Perform NDP Trigger sounding to peer + 00:50:43:20:BF:64 + iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64;500" : Set TX BF periodicity for peer 00:50:43:20:BF:64 + to 500 milliseconds + iwpriv mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3" : Enable beamforming, disable sounding and set + FB type to 3 for peer 00:50:43:20:BF:43 + iwpriv mlan0 httxbfcfg "4;00:50:43:20:BF:24;43" : Set TX BF SNR threshold to peer + 00:50:43:20:BF:24 with SNR 43 + +mgmtframectrl + This command is used to get/set mask for the management frames which needs to be forwarded to application layer. + + Usage: + iwpriv mlanX mgmtframectrl [m] + + where the parameter [m] is the bit mask of management frame reception. + Following are the bit definitions. + Bit 0 : Association Request + Bit 1 : Association Response + Bit 2 : Re-Association Request + Bit 3 : Re-Association Response + Bit 4 : Probe Request + Bit 5 : Probe Response + Bit 8 : Beacon Frames + + Examples: + iwpriv mlan0 mgmtframectrl : Get the current Mgmt Frame forwarding mask + iwpriv mlan0 mgmtframectrl 0x0020 : Bit 5 is set, Forward probe response + frames to application layer + +deepsleep + This command is used to set/get auto deep sleep mode. + + Usage: + iwpriv mlanX deepsleep [n] [m] + + where the parameters are: + [n]: Enable/disable auto deep sleep mode (1/0) + [m]: Idle time in milliseconds after which firmware will put the device + in deep sleep mode. Default value is 100 ms. + + Examples: + iwpriv mlan0 deepsleep : Display auto deep sleep mode + iwpriv mlan0 deepsleep 1 : Enable auto deep sleep mode, idle time unchanged + iwpriv mlan0 deepsleep 0 : Disable auto deep sleep mode + iwpriv mlan0 deepsleep 1 500 : Enable auto deep sleep mode with idle time 500 ms + Note: + Deepsleep must be disabled before changing idle time. + +hscfg + This command is used to configure the host sleep parameters. + + Usage: + iwpriv mlanX hscfg [condition [[GPIO# [gap]]]] + + This command takes one (condition), two (condition and GPIO#) or three + (condition, GPIO# and gap) parameters for set. If no parameter provided, + get is performed. + + where Condition is: + bit 0 = 1 -- broadcast data + bit 1 = 1 -- unicast data + bit 2 = 1 -- mac event + bit 3 = 1 -- multicast data + bit 6 = 1 -- Wakeup when mgmt frame received. + bit 7 = 1 -- Reserved + bit 8 = 1 -- Disable non maskable data wakeup. + + The host sleep mode will be canceled if condition is set to -1. The default is 0x7. + + where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid + GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead). + The default is 0xff. + + where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff + for special setting (host acknowledge required) when GPIO is used to wakeup host. + The default is 200. + + The host sleep set except for cancellation will be blocked if host sleep is + already activated. + + Examples: + iwpriv mlan0 hscfg : Get current host sleep mode + iwpriv mlan0 hscfg -1 : Cancel host sleep mode + iwpriv mlan0 hscfg 3 : Broadcast and unicast data + Use GPIO and gap set previously + iwpriv mlan0 hscfg 2 3 : Unicast data + Use GPIO 3 and gap set previously + iwpriv mlan0 hscfg 2 1 0xa0 : Unicast data + Use GPIO 1 and gap 160 ms + iwpriv mlan0 hscfg 2 0xff : Unicast data + Use interface (e.g. SDIO) + Use gap set previously + iwpriv mlan0 hscfg 4 3 0xff : MAC event + Use GPIO 3 + Special host sleep mode + iwpriv mlan0 hscfg 1 0xff 0xff : Broadcast data + Use interface (e.g. SDIO) + Use gap 255ms + +hssetpara + This command is used to set host sleep parameters. + + Usage: + iwpriv mlanX hssetpara Condition [GPIO# [gap]] + + Note: + 1) The usages of parameters are the same as "hscfg" command. + 2) The parameters will be saved in the driver and be used when host suspends. + +deauth + This command is used to send a de-authentication to an arbitrary AP. + If [n] is omitted, the driver will deauth the associated AP. + If in ad-hoc mode this command is used to stop beacon transmission + from the station and go into idle state. + + When is supplied as a MAC address, the driver will deauth the + specified AP. If the AP address matches the driver's associated AP, + the driver will disconnect. Otherwise, the driver remains connected. + +radioctrl + This command is used to turn on/off the radio. + Note: The radio can be disabled only in disconnected state. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + iwpriv mlan0 radioctrl 1 : Turn the radio on + iwpriv mlan0 radioctrl : Get radio status + +reassoctrl + This command is used to turn on/off re-association in driver. + + Usage: + iwpriv mlanX reassoctrl [n] + + Where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + iwpriv mlan0 reassoctrl : Get re-association status + iwpriv mlan0 reassoctrl 1 : Turn re-association on + +bandcfg + This command is used to set/get infra/ad-hoc band. + Note: This command is only available in disconnected state. + + Usage: + iwpriv mlanX bandcfg [l] [m] [n] + + where the parameters: + [l]: Infrastructure band + bit 0: B + bit 1: G + bit 2: A + bit 3: GN + bit 4: AN + + bit 5: AC 2.4G + bit 6: AC 5G + [m]: Ad-hoc start band + bit 0: B + bit 1: G + bit 2: A + [n]: Ad-hoc start channel + Examples: + iwpriv mlan0 bandcfg : Get infra/ad-hoc band and ad-hoc + start channel configurations + iwpriv mlan0 bandcfg 1 : Set infra band to B only + iwpriv mlan0 bandcfg 3 2 6 : Set infra band to B/G, ad-hoc start band + to G and ad-hoc start channel to 6 + +getlog + This command is used to get the statistics available in the station. + +11dcfg + This command is used to control 11D. No argument is used to get. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + iwpriv mlan0 11dcfg 1 : Enable 11D + iwpriv mlan0 11dcfg : Get 11D status + +11dclrtbl + This command is used to clear the 11D channel table. + + Usage: + iwpriv mlanX 11dclrtbl + +wmmcfg + This command is used to control WMM. No argument is used to get. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + iwpriv mlan0 wmmcfg 1 : Enable WMM + iwpriv mlan0 wmmcfg : Get WMM status + +txpowercfg + This command is used to get/set the Tx power configuration. + + Where + - Data rate index + 0 1 Mbps + 1 2 Mbps + 2 5.5 Mbps + 3 11 Mbps + 4 6 Mbps + 5 9 Mbps + 6 12 Mbps + 7 18 Mbps + 8 24 Mbps + 9 36 Mbps + 10 48 Mbps + 11 54 Mbps + 12 MCS0 (BW20) + 13 MCS1 (BW20) + 14 MCS2 (BW20) + 15 MCS3 (BW20) + 16 MCS4 (BW20) + 17 MCS5 (BW20) + 18 MCS6 (BW20) + 19 MCS7 (BW20) + 20 MCS8 (BW20) + 21 MCS9 (BW20) + 22 MCS10 (BW20) + 23 MCS11 (BW20) + 24 MCS12 (BW20) + 25 MCS13 (BW20) + 26 MCS14 (BW20) + 27 MCS15 (BW20) + 140 MCS0 (BW40) + 141 MCS1 (BW40) + 142 MCS2 (BW40) + 143 MCS3 (BW40) + 144 MCS4 (BW40) + 145 MCS5 (BW40) + 146 MCS6 (BW40) + 147 MCS7 (BW40) + 148 MCS0 (BW40) + 149 MCS1 (BW40) + 150 MCS2 (BW40) + 151 MCS3 (BW40) + 152 MCS4 (BW40) + 153 MCS5 (BW40) + 154 MCS6 (BW40) + 155 MCS7 (BW40) + 0xff Default + - Minimum power level in dBm + - Maximum power level in dBm + - Power step + + Note: Firmware may adjust the setting if over limit, final value can be + verified using get command. + + Examples: + iwpriv mlan0 txpowercfg 0xff : Default power configuration + iwpriv mlan0 txpowercfg 11 12 : Set power level 12 dBm to data rate 54 Mbps + iwpriv mlan0 txpowercfg 7 11 16 1 : Set power level 11 dBm to 16 dBm with + step 1 to data rate 18 Mbps + iwpriv mlan0 txpowercfg : Get current configuration + mlan0 txpowercfg:2 3 13 18 2 1 1 13 18 2 0 0 13 18 2 + 10 11 13 15 2 8 9 13 16 2 6 7 13 17 2 4 5 13 17 2 + 17 19 13 15 2 15 16 13 16 2 13 14 13 17 2 12 12 13 17 2 + 145 147 13 14 1 143 144 13 14 1 141 142 13 14 1 140 140 13 14 1 + + 2 -> First rate index is 5.5 Mbps. + 3 -> Last rate index is 11 Mbps. + 13 -> Min Tx power value is 13 dBm. + 18 -> Max Tx power value is 18 dBm. + 2 -> Power adjustment step value is 2. + + Similarly + 17 -> First rate index is MCS5 (BW20). + 19 -> Last rate index is MCS7 (BW20). + 13 -> Min Tx power value is 13 dBm. + 15 -> Max Tx power value is 15 dBm. + 2 -> Power adjustment step value is 2. + + so on... + +qoscfg + This command sets WMM IE QOS info when an argument is given, and gets current WMM + IE QOS info when no argument is given. + + Examples: + iwpriv mlan0 qoscfg 0x0f : Set WMM IE QOS info to 0x0f + iwpriv mlan0 qoscfg : Get WMM IE QOS info + +getdatarate + This command is used to get the data rate (index) being used in last Tx + packet and last Rx packet. + +bcninterval + This command is used to set/get the beacon interval in ad-hoc mode. + The valid beacon interval is between 20 - 1000, default beacon + interval is 100. + + Where + Beacon interval in TU (Time Unit: 1024 us). + + Examples: + iwpriv mlan0 bcninterval 200 : Set ad-hoc beacon interval to 200 + iwpriv mlan0 bcninterval : Get ad-hoc beacon interval + +sysclock + This command is used to set/get system clocks in MHz. + The current system clock, configurable system clocks and all of the + supported system clocks will be returned if no parameter provided. + + Examples: + iwpriv mlan0 sysclock : Get system clocks + 80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ... + (The current system clock is 80 MHz. + The configurable system clocks of non-security, security, non-security + A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz. + The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz, + 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different + for different chips, you could use this command to get the supported system clock) + + iwpriv mlanX sysclock 80 : Set system clock in non-security mode + to 80 MHz, no change for others + iwpriv mlanX sysclock 0 0 128 : Set system clock in non-security A-MPDU + mode to 128 MHz, no changes for others + +drvdbg + This command is used to set/get the bit masks of driver debug message control. + + Usage: + iwpriv mlanX drvdbg [n] + + Where the parameter is the generic debug message control bit mask. + The following types of driver debug messages can be dynamically enabled or + disabled by setting or clearing the corresponding bits, + bit 0: MMSG PRINTM(MMSG,...) + bit 1: MFATAL PRINTM(MFATAL,...) + bit 2: MERROR PRINTM(MERROR,...) + bit 3: MDATA PRINTM(MDATA,...) + bit 4: MCMND PRINTM(MCMND,...) + bit 5: MEVENT PRINTM(MEVENT,...) + bit 6: MINTR PRINTM(MINTR,...) + bit 7: MIOCTL PRINTM(MIOCTL,...) + ... + bit 16: MDAT_D PRINTM(MDAT_D,...), DBG_HEXDUMP(MDAT_D,...) + bit 17: MCMD_D PRINTM(MCMD_D,...), DBG_HEXDUMP(MCMD_D,...) + bit 18: MEVT_D PRINTM(MEVT_D,...), DBG_HEXDUMP(MEVT_D,...) + bit 19: MFW_D PRINTM(MFW_D,...), DBG_HEXDUMP(MFW_D,...) + bit 20: MIF_D PRINTM(MIF_D,...), DBG_HEXDUMP(MIF_D,...) + ... + bit 28: MENTRY PRINTM(MENTRY,...), ENTER(), LEAVE() + bit 29: MWARN PRINTM(MWARN,...) + bit 30: MINFO PRINTM(MINFO,...) + + If CONFIG_DEBUG=2, all kinds of debug messages can be configured. + + If CONFIG_DEBUG=1, all kinds of debug messages can be configured except + for MENTRY, MWARN and MINFO. By default MMSG, MFATAL and MERROR are enabled. + + Some special debug messages, + '*' // MLAN driver ISR is called (bit 6 MINTR enabled) + '|' // PS awake event is received (bit 5 MEVENT enabled) + '_' // PS sleep event is received (bit 5 MEVENT enabled) + '+' // PS sleep confirm is sent (bit 5 MEVENT enabled) + + Examples: + iwpriv mlan0 drvdbg : Get the current driver debug masks + iwpriv mlan0 drvdbg 0 : Disable all the debug messages + iwpriv mlan0 drvdbg 7 : Enable MMSG, MFATAL and MERROR messages + iwpriv mlan0 drvdbg 0x20037 : Enable MMSG, MFATAL, MEEROR, + MCMND, MEVENT and MCMD_D messages + iwpriv mlan0 drvdbg -1 : Enable all the debug messages + +warmreset + This command is used for warm reset of the interface. + + Usage: + iwpriv mlanX warmreset + +regrdwr + This command is used to read/write the adapter register. + + Usage: + iwpriv mlanX regrdwr [value] + + where the parameters are, + : 1:MAC/SOC, 2:BBP, 3:RF, 5:CAU + : offset of register + [value]: value to be written + Note: If highest bit of a 32-bit value needs to be set, use negative input. + The calculation is -(0xffffffff - value + 1). Range from -0x80000000 to -1. + + Examples: + iwpriv mlan0 regrdwr 1 0xa060 : Read the MAC register + iwpriv mlan0 regrdwr 1 0xa060 0x12 : Write the MAC register + iwpriv mlan0 regrdwr 1 0xa794 -0x80000000 + : Write 0x80000000 to MAC register + iwpriv mlan0 regrdwr 1 0xa794 -0x00000001 + : Write 0xffffffff to MAC register + +rdeeprom + This command is used to read the EEPROM contents of the card. + + Usage: + iwpriv mlanX rdeeprom + + where the parameters are, + : multiples of 4 + : 4-20, multiples of 4 + + Example: + iwpriv mlan0 rdeeprom 0 20 : Read 20 bytes of EEPROM data from offset 0 + +memrdwr + This command is used to read/write the adapter memory. + + Usage: + iwpriv mlanX memrdwr

[value] + + where the parameters are, +
: memory address + [value]: value to be written + Note: If highest bit of a 32-bit address/value needs to be set, use negitive input. + The calculation is -(0xffffffff - address/value + 1). Range from -0x80000000 to -1. + + Examples: + iwpriv mlan0 memrdwr 0x4cf70 : Read memory address 0x4cf70 + iwpriv mlan0 memrdwr -0x80000000 + : Read memory address 0x80000000 + iwpriv mlan0 memrdwr -0x7fff6000 -0x40000000 + : Write 0xc0000000 to memory address 0x8000a000 + +inactivityto + This command is used to set/get the inactivity timeout value, which specifies + when WLAN device is put to sleep. + + Usage: + iwpriv mlanX inactivityto [k] + + where the parameter are: + : timeout unit in microseconds. + : Inactivity timeout for unicast data. + : Inactivity timeout for multicast data. + [k]: Inactivity timeout for new Rx traffic after PS notification to AP. + + Examples: + iwpriv mlan0 inactivityto : Get the timeout value + iwpriv mlan0 inactivityto 1000 2 3 : Set timeout unit to 1000 us (1 ms), + inactivity timeout for unicast data is 2 ms, + inactivity timeout for multicast data is 3 ms + +scancfg + This command is used to set/get scan configuration parameters. + + Usage: + iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext] + + where the parameters: + [t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active) + [m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any) + [p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4) + [s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms) + [a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms) + [b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms) + [ext]: Extended scan (0: Legacy scan, 1: Extended scan) + + No change if the parameter is 0 or the parameter is not provided. + + Examples: + iwpriv mlan0 scancfg : Get all the current scan configuration settings + iwpriv mlan0 scancfg 1 3 : Set scan type to active and scan mode to any, + all the other scan configurations are unchanged + iwpriv mlan0 scancfg 0 1 2 200 : Set scan mode to BSS, number of probes to 2 and + specific scan time to 200 ms, all the other scan + configurations are unchanged + +sleeppd + This command is used to configure the sleep period of the WLAN device. + + Usage: + iwpriv mlanX sleeppd [] + + Where the parameter is: + period: sleep period in milliseconds. Range 10~60. 0 for disable. + + Examples: + iwpriv mlan0 sleeppd : Get sleep period configuration + iwpriv mlan0 sleeppd 10 : Set sleep period to 10 ms + +pscfg + This command is used to set/get PS configuration parameters. + + Usage: + iwpriv mlanX pscfg [k] [d] [l] ... + + Where the parameters: + [k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds) + [d]: DTIM interval ( 0: Unchanged, + 1-5: Value, + 65534: DTIM will be ignored, listen interval will be used, + 65533: Closest DTIM to the listen interval period will be used ) + [l]: Local listen interval ( 0: Unchanged, + -1: Disable, + 1-49: Value in beacon intervals, + >= 50: Value in TUs ) + [b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable) + [p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms) + [m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode) + No change if parameters are not provided. + + Examples: + iwpriv mlan0 pscfg : Get all the current PS configuration settings + iwpriv mlan0 pscfg 3 4 : Set PS keep alive null packet interval to 3 seconds + and DTIM interval to 4, all the other configurations + are unchanged + iwpriv mlan0 pscfg 0 0 0 0 50 2 : Set delay to PS to 50 ms and PS mode to PS-Poll mode, + keep the others unchanged + +fwwakeupmethod + This command is used to set/get the firmware wakeup method. + + where value is: + [n]: + 1 -- Firmware wakeup through the interface command interrupt + -- (default setting for SDIO/PCIe/USB) + 2 -- Firmware wakeup through the GPIO pin + [g]:If firware wakeup throug GPIO pin, [g] is GPIO pin number + + Examples: + iwpriv mlan0 fwwakeupmethod : Get current firmware wakeup method + iwpriv mlan0 fwwakeupmethod 1 : Set firmware wakeup method to Interface mode + iwpriv mlan0 fwwakeupmethod 2 5 : Set firmware wakeup method to GPIO mode, GPIO_pin=5 + +getkey + This command is used to get PTK/GTK + + iwpriv mlanX getkey +associate + Request an association to a given SSID/BSSID pair. This the only accurate + way to pick a specific AP and ESS for an association. The entry must + already exist in the scan table for the association to be attempted. + + iwpriv mlanX associate "xx:xx:xx:xx:xx:xx SSID" + +sleepparams + This command is used to set the sleepclock configurations + + Usage: + iwpriv mlanX sleepparams [ ] + + where: + p1 is Sleep clock error in ppm (0-65535) + p2 is Wakeup offset in usec (0-65535) + p3 is Clock stabilization time in usec (0-65535) + p4 is Control periodic calibration (0-2) + p5 is Control the use of external sleep clock (0-2) + p6 is reserved for debug (0-65535) + + Examples: + iwpriv mlan0 sleepparams : Get current sleepclock configuration + iwpriv mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration + +netmon + This command is used to set/get sniffer mode configuration. + Note: The channel and band config is optional. If not specified, or if + any STA/uAP/STA+uAP connection is active, sniffer activity will be started + on the current config set in the FW. + 'rtap' monitor interface will be created on enabling sniffer activity and + should be made 'up' for capturing in a sniffer app. + + Usage: + iwpriv netmon [ []] + iwpriv netmon [ [] [ [offset]]] + + Where the parameters are: + : mlanX, uapX + : (1/0) enable/disable sniffer activity + : network monitor filer flag + bit 0: (1/0) enable/disable management frame + bit 1: (1/0) enable/disable control frame + bit 2: (1/0) enable/disable data frame + bit 3: (1/0) enable/disable frames destined to active connection only + bit 4: (1/0) enable/disable decrypted unicast data/mgmt frames + : 802.11 band + bit 0: B + bit 1: G + bit 2: A + bit 3: GN + bit 4: AN + bit 5: AC 2.4G + bit 6: AC 5G + : channel to monitor + [offset] : secondary channel bandwidth + 0 - Bandwidth 20Mhz + 1 - HT Bandwidth 40Mhz sec channel above + 3 - HT Bandwidth 40Mhz sec channel below + 4 - VHT Bandwidth 80Mhz + + Examples: + iwpriv mlan0 netmon : Get the current sniffer mode configuration + iwpriv mlan0 netmon 0 : Disable network monitor activity + iwpriv uap0 netmon 1 7 : Enable sniffer activity on current channel set in FW, + set filter data, control, management frame. + iwpriv mlan0 netmon 1 4 11 6 : Enable sniffer activity in absence of active connection, + set filter data frame, band B/G/GN and channel 6 + iwpriv mlan0 netmon 1 7 20 64 1 : Enable sniffer activity in absence of active connection, + set filter management, control and data frame, band A/AN, + channel 64 and secondary channel above + iwpriv uap0 netmon 1 0x0c : Enable sniffer activity, set filter data frames + destined to the active uAP connection only + + iwpriv mlan0 netmon 1 0x1d : Enable sniffer activity, set filter decrypted data and + management frames destined to the active STA connection + only + +authtype + This command is used to set/get authentication type. + + Usage: + iwpriv mlanX authtype [n] + + where + 0: 802.11 open system authentication + 1: 802.11 shared key authentication + 255: allow open system or shared key authentication (default) + + Examples: + iwpriv mlan0 authtype 0 : use open system authentication + iwpriv mlan0 authtype 1 : use shared key authentication + iwpriv mlan0 authtype 255 : allow open system or shared key authentication + iwpriv mlan0 authtype : get current setting + +powercons + This command is used to set the local transmit power constraint. + Value is in dbm unit. This command is only used for ad-hoc start. + + Usage: + iwpriv mlanX powercons [n] + + Examples: + iwpriv mlanX powercons : get the current setting + iwpriv mlanX powercons 12 : set local power constraint to 12 dbm + +htstreamcfg + This command is used to set/get HT stream configuration. + The setting only takes effect in next association. + + Usage: + iwpriv mlanX htstreamcfg [n] + + where + 0x11: HT stream 1x1 mode + 0x22: HT stream 2x2 mode + + Examples: + iwpriv mlan0 htstreamcfg : Get current setting + iwpriv mlan0 htstreamcfg 0x11 : Set HT stream 1x1 mode + iwpriv mlan0 htstreamcfg 0x22 : Set HT stream 2x2 mode + +ipaddr + This command is used to set/get IP address. + + Usage: + iwpriv mlanX ipaddr [";"] + + where + 0: Remove the IP address + bit 0: Set IP address for broadcast ARP filter, which will be auto enabled + in next host sleep configuration + bit 1: Set IP address for auto broadcast ARP response + + Examples: + iwpriv mlan0 ipaddr : Get current settings + iwpriv mlan0 ipaddr "0" : Remove IP address + iwpriv mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter + iwpriv mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter + : and auto ARP response + +macctrl + This command is used to set/get MAC control. + It's recommended to read the current setting first to avoid override issue. + + Usage: + iwpriv mlanX macctrl [n] + + where + bit 0: Rx enabled + bit 1: Tx enabled + bit 3: WEP enabled + bit 4: EthernetII enabled + bit 7: Promiscuous enabled + bit 8: All multicast enabled + bit 9: RTS/CTS enabled (0: CTS to self) + bit 11: Force 11n protection disabled + bit 12: Ad-hoc g protection disabled + ... + + Examples: + iwpriv mlan0 macctrl : Get current MAC control + iwpriv mlan0 macctrl 0x13 : Set Tx/Rx on and EthernetII on + iwpriv mlan0 macctrl 0x813 : Set Tx/Rx on and EthernetII on + : Disable force 11n protection + +dfstesting + This command is used to set/get settings for DFS testing. + + Usage: + iwpriv mlanX dfstesting [ ] + + where is user-configured Channel Availability Check in msec + 0 = disable, use default period (60000) + 1-65535 = enable with that period + where is user-configured Non-Occupancy Period in sec + 0 = disable, use default period (1800) + 1-65535 = enable with that period + where is enable/disable no channel change on radar + 0 = disable, 1 = enable (overrides below) + where is user-configured channel to change to on radar + 0 = disable, 1-255 = enable with that channel + (channel validity for region, etc. is not checked) + (only takes effect if no_chan_change = 0) + + Examples: + iwpriv mlan0 dfstesting : Get current dfstesting settings + iwpriv mlan0 dfstesting 2000 0 0 0 : user_cac=2sec, others disabled/default + iwpriv mlan0 dfstesting 0 0 1 0 : only no_chan_change enabled + iwpriv mlan0 dfstesting 0 120 0 64 : user_nop=2min, force chan 64 on radar + +indrstcfg + This command is used to set/get settings for independent reset mode + + Usage: + iwpriv mlanX indrstcfg [gpio_pin] + + where is independent reset mode + 0 = disable independent reset + 1 = enable out band and disable in band + 2 = enable in band and disable out band + where is user-configured gpio pin number to be used for oob mode + 0xFF = use FW default gpio assignment + 0-15 = gpio pin number + + Examples: + iwpriv mlan0 indrstcfg : Get current settings + iwpriv mlan0 indrstcfg 1 14 : Enable oob_mode with gpio pin 14 + iwpriv mlan0 indrstcfg 1 0xff : Enable oob_mode with default gpio pin + iwpriv mlan0 indrstcfg 0 : Disable ir_mode + iwpriv mlan0 indrstcfg 2 : Enable in band reset mode + + +=============================================================================== + U S E R M A N U A L F O R M L A N C O N F I G + +NAME +mlanconfig - configure the additional parameters available for the Marvell mdriver. + +SYNOPSIS +mlanconfig -v +mlanconfig [parameters] ... + +mlanconfig mlanX hostcmd bgscfg +mlanconfig mlanX hostcmd requesttpc +mlanconfig mlanX hostcmd crypto_test +mlanconfig mlanX hostcmd subevent_get +mlanconfig mlanX hostcmd subevent_set +mlanconfig mlanX hostcmd auto_tx_get +mlanconfig mlanX hostcmd nat_keep_alive +mlanconfig mlanX hostcmd auto_tx_unreg +mlanconfig mlanX hostcmd txrate_cfg_get +mlanconfig mlanX hostcmd txrate_cfg_set_bg +mlanconfig mlanX hostcmd txrate_cfg_set_bgn +mlanconfig mlanX hostcmd txpwrlimit_cfg_get +mlanconfig mlanX hostcmd txpwrlimit_2g_cfg_set +mlanconfig mlanX hostcmd txpwrlimit_5g_cfg_set +mlanconfig mlanX hostcmd pad_cfg_get +mlanconfig mlanX hostcmd pad_cfg_set +mlanconfig mlanX hostcmd <11n_2040coex.conf> 2040coex +mlanconfig mlanX hostcmd mode_get +mlanconfig mlanX hostcmd mode_timeshare +mlanconfig mlanX hostcmd mode_spatial +mlanconfig mlanX hostcmd generictime +mlanconfig mlanX hostcmd a2dptime +mlanconfig mlanX hostcmd inquirytim +mlanconfig mlanX hostcmd ap_generictime +mlanconfig mlanX hostcmd ap_a2dptime +mlanconfig mlanX hostcmd ap_inquirytime +mlanconfig mlanX arpfilter +mlanconfig mlanX mefcfg +mlanconfig mlanX cfgdata +mlanconfig mlanX setuserscan [ARGS] +mlanconfig mlanX getscantable [ARGS] +mlanconfig mlanX addts +mlanconfig mlanX delts +mlanconfig mlanX qconfig set msdu [Queue Id: 0-3] +mlanconfig mlanX qconfig get [Queue Id: 0-3] +mlanconfig mlanX qconfig def [Queue Id: 0-3] +mlanconfig mlanX qstats on [Queue Id: 0-3] +mlanconfig mlanX qstats off [Queue Id: 0-3] +mlanconfig mlanX qstats get [Queue Id: 0-3] +mlanconfig mlanX qstatus +mlanconfig mlanX ts_status +mlanconfig mlanX regrdwr [value] +mlanconfig mlanX memrdwr
[value] +mlanconfig mlanX customie +mlanconfig mlanX tdls_config <0/1> +mlanconfig mlanX tdls_setinfo +mlanconfig mlanX tdls_setup +mlanconfig mlanX tdls_discovery +mlanconfig mlanX tdls_teardown +mlanconfig mlanX tdls_powermode +mlanconfig mlanX tdls_channel_switch +mlanconfig mlanX tdls_stop_channel_switch +mlanconfig mlanX tdls_cs_params +mlanconfig mlanX tdls_disable_cs <0/1> +mlanconfig mlanX tdls_link_status +mlanconfig mlanX tdls_debug "wrong_bss" <0/1> +mlanconfig mlanX tdls_debug "setup_existing_link" <0/1> +mlanconfig mlanX tdls_debug "fail_setup_confirm" <0/1> +mlanconfig mlanX tdls_debug "setup_with_prohibited" <0/1> +mlanconfig mlanX tdls_debug "higher_lower_mac" <0/1> +mlanconfig mlanX tdls_debug "ignore_key_expiry" <0/1> +mlanconfig mlanX tdls_debug "allow_weak_security" <0/1> +mlanconfig mlanX tdls_debug "stop_rx" <0/1> +mlanconfig mlanX tdls_debug "cs_im_return" <0/1> +mlanconfig mlanX mgmtframetx + + +DESCRIPTION + +Those commands are used in Marvell specific application called mlanconfig. + +=========== +-v + This command is used to display the version of mlanconfig utility. + Usage: + mlanconfig -v + +hostcmd bgscfg + This command is used to configure the various parameters for PPS/UAPSD + or normal background scan. + + Usage: + mlanconfig mlanX hostcmd config/bg_scan.conf bgscfg + +hostcmd requesttpc + This command is used to request 802.11H TPC info. + + Usage: + mlanconfig mlanX hostcmd config/requesttpc.conf requesttpc + +hostcmd crypto_test + This command is used to test the encryption/decryption API of the firmware. + + Usage: + mlanconfig mlanX hostcmd config/crypto_test.conf crypto_test + +hostcmd subevent_get +hostcmd subevent_set + This command is used to get/set the configurations for event descriptor + interface command. + subsvent_get: get subscribed event parameters + subsvent_set: set subscribed event parameters + + Usage: + mlanconfig mlanX hostcmd config/subevent.conf subevent_get + mlanconfig mlanX hostcmd config/subevent.conf subevent_set + +hostcmd auto_tx_get +hostcmd nat_keep_alive +hostcmd auto_tx_unreg + This command is used to configures the Frame Auto Transmission parameters. + auto_tx_get: get auto_tx parameters + nat_keep_alive: register to firmware for sending NAT Keep Alive packet + auto_tx_unreg: unregister to firmware auto_tx + + Usage: + mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_get + mlanconfig mlanX hostcmd config/auto_tx.conf nat_keep_alive + mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_unreg + +hostcmd txrate_cfg_get +hostcmd txrate_cfg_set_bg +hostcmd txrate_cfg_set_bgn + This command is used to set/get the transmit data rate. + + Usage: + mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get + mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg + mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn + +hostcmd txpwrlimit_cfg_get +hostcmd txpwrlimit_2g_cfg_set +hostcmd txpwrlimit_5g_cfg_set + This command is used to set/get the configuration data of Tx power limitation. + Note: The configuration set should be issued when STA is disconnected. + + Usage: + mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get + mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set + mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set + +hostcmd pad_cfg_get +hostcmd pad_cfg_set + This command is used to set/get the configuration data for PAD OR. + + Usage: + mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_get + mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_set + +hostcmd 2040coex + This command is used to send the 11n 20/40 Coex command to firmware. + Firmware will send 11n 20/40 Coex management action frame to AP. + + Usage: + mlanconfig mlanX hostcmd config/11n_2040coex.conf 2040coex + +hostcmd mode_get +hostcmd mode_timeshare +hostcmd mode_spatial + This command is used to get/set Robust BT Coex. + mode_get: get the current mode + mode_timeshare: set Robust BT Coex to timeshare mode (default on 1x1 chips) + mode_spatial: set Robust BT Coex to spatial mode (only for, and default on 2x2 chips) + + Usage: + mlanconfig mlanX hostcmd config/robust_btc.conf mode_get + mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare + mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial + +hostcmd generictime +hostcmd a2dptime +hostcmd inquirytime +hostcmd ap_generictime +hostcmd ap_a2dptime +hostcmd ap_inquirytime + This command is used to configure the time slice of COEX (only works in timeshare mode) + generictime: configure the Bttime and Wlantime in Station Generic case + a2dptime: configure the Bttime and Wlantime in Station A2DP case + inquirytime: configure the Bttime and Wlantime in Station Inquiry case + ap_generictime: configure the Bttime and Wlantime in Ap Generic case + ap_a2dptime: configure the Bttime and Wlantime in Ap A2DP case + ap_inquirytime: configure the Bttime and Wlantime in Ap Inquiry case + + Usage: + mlanutl mlanX hostcmd config/robust_btc.conf generictime + mlanutl mlanX hostcmd config/robust_btc.conf a2dptime + mlanutl mlanX hostcmd config/robust_btc.conf inquirytim + mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime + mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime + mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime + +arpfilter + This command is used to configure the ARP filtering parameters. + + Usage: + mlanconfig mlanX arpfilter config/arpfilter.conf + +mefcfg + This command is used to set MEF settings. + + Usage: + mlanconfig mlanX mefcfg config/mef.conf + +cfgdata + This command is used to set/get the configuration data to/from firmware. + + Usage: + mlanconfig mlanX cfgdata <.conf file name> + This command is used to set the cfg data in the .conf file to firmware. + + mlanconfig mlanX cfgdata + This command is used to get the cfg data from firmware and display + on to the console. + + Where the value of field is: + 2 -- Cal data download and <.conf file name> is cal_data.conf + +setuserscan + Initiate a customized scan and retrieve the results + + Usage: + mlanconfig mlanX setuserscan [ARGS] + + Where [ARGS]: + ssid="[SSID]" specify a SSID filter for the scan + chan=[chan#][band][mode] where band is [a,b,g,n] and mode is + blank for active or 'p' for passive + bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan + wc="[WILDCARD SSID]" specify a UNIX pattern matching filter (using * + and ?) for SSIDs found in a broadcast probe + keep=[0 or 1] keep the previous scan results (1), discard (0) + dur=[scan time] time to scan for each channel in milliseconds + gap=[time gap] Time gap between two scans in milliseconds + probes=[#] number of probe requests to send on each chan + for each broadcast probe required and each SSID + specific probe required (1-4) + type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any) + + Any combination of the above arguments can be supplied on the command line. + If the chan token is absent, a full channel scan will be completed by driver. + If the dur or probes tokens are absent, the driver default setting will be + used. The bssid and ssid fields, if blank, will produce an unfiltered scan. + It's allowed to input multiple ssid/wc entries, the max entry number is 10. + The type field will default to 3 (Any) and the keep field will default to 0 + (Discard). + + Examples: + 1) Perform an active scan on channels 1, 6, and 11 in the 'g' band: + setuserscan chan=1g,6g,11g + + 2) Perform a passive scan on channel 11 for 20 ms: + setuserscan chan=11gp dur=20 + + 3) Perform an active scan on channels 1, 6, and 11; and a passive scan on + channel 36 in the 'a' band: + setuserscan chan=1g,6g,11g,36ap + + 4) Perform an active scan on channel 6 and 36 for specific SSID: + setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2 + + 5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep + the current scan table intact, update existing or append new scan data: + setuserscan bssid=00:50:43:20:12:82 keep=1 + + 6) Scan channel 6, for all infrastructure networks, sending two probe + requests. Keep the previous scan table intact. Update any duplicate + BSSID/SSID matches with the new scan data: + setuserscan chan=6g type=1 probes=2 keep=1 + + 7) Scan channel 1 and 6, for all networks matching the Mrvl*AP + or AP*Mrvl? patterns and for MrvlTst SSID. Generate 3 broadcast + probes for the patterns and 3 SSID specific probes for MrvlTst on + both channel 1 and channel 6. + setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst" + + 8) Scan all the channels for specified band. + setuserscan chan=0g + + 9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms + with time gap of 50ms between 2 scans + setuserscan chan=1g,6g probes=3 dur=40 gap=50 + + All entries in the scan table (not just the new scan data when keep=1) + will be displayed upon completion by use of the getscantable ioctl. + +getscantable + Display the current contents of the driver scan table + + Usage: + mlanconfig mlanX getscantable + mlanconfig mlanX getscantable [#] + mlanconfig mlanX getscantable tsf + mlanconfig mlanX getscantable help + + 1) Without argument, the entire scantable is displayed. + 2) Specifying a # will display detailed information about a specific scan + table entry. '0' displays driver cached information regarding the + current association (if any). + 3) The tsf argument will display the entire scan table with the recorded + TSF timestamp for the entry. + 4) The help argument will display the legend for the capability field. + +addts + Send an ADDTS command to the associated AP. + + Process a given conf file for a specific TSPEC data block. Send the + TSPEC along with any other IEs to the driver/firmware for transmission + in an ADDTS request to the associated AP. + + Return the execution status of the command as well as the ADDTS response + from the AP if any. + + Usage: + mlanconfig mlanX addts + +delts + Send a DELTS command to the associated AP. + + Process a given conf file for a specific TSPEC data block. Send the + TSPEC along with any other IEs to the driver/firmware for transmission + in a DELTS request to the associated AP. + + Return the execution status of the command. There is no response to a + DELTS from the AP. + + Usage: + mlanconfig mlanX delts + +qconfig + Send a WMM AC Queue configuration command to get/set/default params + + Configure or get the parameters of a WMM AC queue. The command takes + an optional Queue Id as a last parameter. Without the queue id, all + queues will be acted upon. + + Usage: + mlanconfig mlanX qconfig set msdu [Queue Id: 0-3] + mlanconfig mlanX qconfig get [Queue Id: 0-3] + mlanconfig mlanX qconfig def [Queue Id: 0-3] + +qstats + Turn on/off or retrieve and clear the queue statistics for an AC + + Turn the queue statistics collection on/off for a given AC or retrieve the + current accumulated stats and clear them from the firmware. The command + takes an optional Queue Id as a last parameter. Without the queue id, + all queues will be acted upon. + + Usage: + mlanconfig mlanX qstats on [Queue Id: 0-3] + mlanconfig mlanX qstats off [Queue Id: 0-3] + mlanconfig mlanX qstats get [Queue Id: 0-3] + +qstatus + This command retrieves the current status of the WMM queues. If WMM + is enabled then it displays the information for each AC in a table. + + Usage: + mlanconfig mlanX qstatus + +ts_status + This command queries the FW for the status of TSIDs 0 through 7 + configured via call admission control and displays the results in a + table. + + Usage: + mlanconfig mlanX ts_status + +regrdwr + This command is used to read/write the adapter register. + + Usage: + mlanconfig mlanX regrdwr [value] + + where the parameters are, + : 1:MAC/SOC, 2:BBP, 3:RF, 5:CAU + : offset of register + [value]: value to be written + + Examples: + mlanconfig mlan0 regrdwr 1 0xa060 : Read the MAC register + mlanconfig mlan0 regrdwr 1 0xa794 0x80000000 + : Write 0x80000000 to MAC register + +memrdwr + This command is used to read/write the adapter memory. + + Usage: + mlanconfig mlanX memrdwr
[value] + + where the parameters are, +
: memory address + [value]: value to be written + + Examples: + mlanconfig mlan0 memrdwr 0x80000000 : Read memory address 0x80000000 + mlanconfig mlan0 memrdwr 0x80000000 0xffffffff + : Write 0xffffffff to memory address 0x80000000 + +customie + This command is used to set or get custom IEs for management frames. + + Usage : customie [INDEX] [MASK] [IEBuffer] + empty - Get all IE settings + INDEX: 0 - Get/Set IE index 0 setting + 1 - Get/Set IE index 1 setting + 2 - Get/Set IE index 2 setting + MAX IE Index depends on device memory. + + -1 - Append/Delete IE automatically + Delete will delete the IE from the matching IE buffer + Append will append the IE to the buffer with the same mask + MASK : Management subtype mask value as per bit definitions + : Bit 0 - Association request + : Bit 1 - Association response + : Bit 2 - Reassociation request + : Bit 3 - Reassociation response + : Bit 4 - Probe request + : Bit 5 - Probe response + : Bit 8 - Beacon + MASK : MASK = 0 to clear the mask and the IE buffer + IEBuffer : IE Buffer in hex (max 256 bytes) + The Buffer should not be space separated. + + Example: + ./mlanconfig mlan0 customie + Get IE buffer, subtype mask settings for all indices. + + ./mlanconfig mlan0 customie 1 + Get IE buffer and subtype mask for the Index = 1. + + ./mlanconfig mlan0 customie 2 0 + Clear IE buffer and mask value for Index = 2. + + ./mlanconfig mlan0 customie 3 0x101 0xdd051234567890 + Set IE buffer and mask value for Index = 3. + + ./mlanconfig mlan0 customie -1 0x101 0xdd051234567890 + Append the specified IEBuffer at index with mask value of 0x101. + + ./mlanconfig mlan0 customie -1 0 0xdd051234567890 + Delete the specified IEBuffer from all the IEs. + + ./mlanconfig mlan0 customie 2 0 0xdd051234567890 + Delete the specified IEBuffer from the IEs at index 2. + +tdls_config + This command is used to enable/disable TDLS on device. + + Usage : tdls_config <0/1> + 1: Enable TDLS + 0: Disable TDLS +tdls_setinfo + This command is used for setting the capabilities of the TDLS station. + + Usage : tdls_setinfo + Set capabilities of TDLS station. +tdls_setup + This command is used to send TDLS setup request. + + Usage: tdls_setup + Send TDLS setup request. +tdls_discovery + This command is used to request TDLS discovery. + + Usage : tdls_discovery + Request TDLS discovery. +tdls_teardown + This command is used to send TDLS teardown request. + + Usage : tdls_teardown + Request teardown of TDLS link. +tdls_powermode + This command is used to send TDLS powermode request. + + Usage : tdls_powermode + Send TDLS powermode (either 0:Active, 1:PowerSave) command. +tdls_channel_switch + This command is used to send TDLS channel switch request. + + Usage : tdls_channel_switch + Send TDLS channel switch command. +tdls_stop_channel_switch + This command is used to send stop TDLS channel switch request. + + Usage : tdls_stop_channel_switch + Send stop TDLS channel switch command. +tdls_cs_params + This command is used to set TDLS channel switch params + + Usage : tdls_cs_params + Set TDLS channel switch params. +tdls_disable_cs + This command is used to disable TDLS channel switch + + Usage : tdls_disable_cs <0/1> + Disable TDLS channel switch. +tdls_link_status [peer_mac_address] + This command is used to get link information about TDLS links or + a TDLS link correponding to peer mac address. + + Usage : tdls_link_status + Send TDLS command to get current link status. +tdls_debug + This command is used for FW debug functionality and tests. + +mgmtframetx + This command is used to send mgmt frame + + Usage: + mlanconfig mlanX mgmtframetx + +=============================================================================== + U S E R M A N U A L F O R DRIVER COMMAND + +NAME +DRIVER COMMAND - This command is Marvell private command, it can enable and + configure Roaming offload and provide the interface between + between WPA_Supplicant and the Marvell mdriver +SYNOPSIS +WPA_CLI: DRIVER SETROAMOFFLOAD data1 +WPA_CLI: DRIVER SETROAMOFFLOAD 0/1/2/3/4/5 +Enable/Disable Roaming offload with different mode: +data1: + 0 - disable + 1 - enable and wakeup host based on roamOffloadAPlist + 2 - enable and ignore the roamOffloadAPlist + 3 - based on 2, and reconnect with the same BSSID when disconnect during host suspend + 4 - based on 2, and reconnect with the same SSID when disconnect during host suspend + 5 - based 0n 2, no roaming and only reconnect the specific BSSID/SSID when disconnect during host suspend + +WPA_CLI: DRIVER SETROAMOFFLAPLIST data1 [data2] ...... +WPA_CLI: DRIVER SETROAMOFFLAPLIST xx:xx:xx:xx:xx:xx +Download roaming offload AP list to Driver: + xx:xx:xx:xx:xx:xx - the BSSID of AP, one or more than one BSSIDs are allowed. + +WPA_CLI: DRIVER CFGROAMOFFLOAD [data1 = xx] [data2 = xx] [data3 = xx] [data4 = xx] ..... +WPA_CLI: DRIVER CFGROAMOFFLOAD [BSSID = xx:xx:xx:xx:xx:xx] [SSID = marvell_ap] + [RETRY_COUNT = 0xff] [MAX_RSSI = 50] [MIN_RSSI=60] [SETP_RSSI = 5] ...... + +Configure Roaming offload: +Note: all parameters are optional. +Examples: + DRIVER CFGROAMOFFLOAD BSSID = 00:50:43:21:30:ca SSID = marvell_ap RETRY_COUNT = 0xff MAX_RSSI = 50 + +=============================================================================== + U S E R M A N U A L F O R M L A N 2 0 4 0 C O E X + +NAME +mlan2040coex - This application handles the 11n 20/40 coexistence operation for + the Marvell mdriver + +SYNOPSIS +mlan2040coex [-d ] [-i ] [hvB] + -d = Device number (n) + -i = Interface name (intfname) + -h = Help + -v = Version + -B = Run the process in background +Note: If device number (n) is not present, then 0 assumed. + If intfname is not present, then mlan0 assumed. + +=============================================================================== + U S E R M A N U A L F O R MLANEVENT + +NAME +mlanevent.exe + +This tool can be used to listen for and obtain events from the driver +through the netlink layer. + +---------------- +Supported events +---------------- +STA_DEAUTH +STA_ASSOC +BSS_START +BSS_IDLE +BSS_ACTIVE + +----------------- +Details of events +----------------- + +STA_DEAUTH +---------- + For this event, the following information is shown: + + Deauthenticated STA MAC address. + + Reason for deauthentication. + +STA_ASSOC +---------- + For this event, the following information is shown: + + STA MAC address. + +BSS_START +---------- + For this event, the following information is shown: + + AP MAC address. + +BSS_IDLE +---------- + For this event, there is no associated information. + +BSS_ACTIVE +---------- + For this event, there is no associated information. + +=============================================================================== diff --git a/mwifiex_8997/README_MLAN b/mwifiex_8997/README_MLAN new file mode 100755 index 0000000..3107e5f --- /dev/null +++ b/mwifiex_8997/README_MLAN @@ -0,0 +1,3649 @@ +=============================================================================== + U S E R M A N U A L + + Copyright (C) 2008-2019, Marvell International Ltd. + All Rights Reserved + +1) FOR DRIVER BUILD + + Goto source code directory wlan_src/. + make [clean] build + The driver and utility binaries can be found in ../bin_xxxx directory. + The driver code supports Linux kernel up to 5.0.9. + +2) FOR DRIVER INSTALL + + a) Copy firmware image pcie8897_uapsta.bin | ... to /lib/firmware/mrvl/ directory, + create the directory if it doesn't exist. + b) Install WLAN driver + There are drv_mode, max_sta_bss, max_uap_bss etc. module parameters. + The bit settings of drv_mode are, + Bit 0 : STA + Bit 1 : uAP + Bit 2 : WIFIDIRECT + Bit 4 : NAN + + max_sta_bss: Maximum number of STA BSS (default 1, max 1) + sta_name: Name of the STA interface (default: "mlan") + max_uap_bss: Maximum number of uAP BSS (default 1, max 2) + uap_name: Name of the uAP interface (default: "uap") + max_wfd_bss: Maximum number of WIFIDIRECT BSS (default 1, max 1) + wfd_name: Name of the WIFIDIRECT interface (default: "wfd") + max_vir_bss: Number of Virtual interfaces (default 0) + nan_name: Name of the NAN interface (default: "nan") + max_nan_bss: Number of NAN interfaces (default 1) + For example, to install PCIE8897 driver, + insmod mlan.ko + insmod pcie8897.ko [drv_mode=3] [fw_name=mrvl/pcie8897_uapsta.bin] + To load driver in STA only mode, + insmod mlan.ko + insmod pcie8897.ko drv_mode=1 [fw_name=mrvl/pcie8897_uapsta.bin] + To load driver in uAP only mode, + insmod mlan.ko + insmod pcie8897.ko drv_mode=2 [fw_name=mrvl/pcie8897_uapsta.bin] + + To switch mode between STA only, uAP only and uAPSTA in run time, + echo drv_mode=1 > /proc/mwlan/config // STA mode + echo drv_mode=2 > /proc/mwlan/config // uAP mode + echo drv_mode=3 > /proc/mwlan/config // uAPSTA mode + c) Uninstall WLAN driver, + ifconfig mlanX down + ifconfig uapX down + rmmod pcie8xxx + rmmod mlan + + To load driver with MFG firmware file, use mfg_mode=1 when insmod WLAN driver and + specify MFG firmware name if needed. + + There are some other parameters for debugging purpose etc. Use modinfo to check details. + drvdbg= + dev_cap_mask= + mac_addr=xx:xx:xx:xx:xx:xx + auto_ds=0|1|2 + ps_mode=0|1|2 + p2p_enh=0|1 + max_tx_buf=2048|4096|8192 + cfg_11d=0|1|2 + dts_enable=0|1 + hw_test=0|1 + fw_serial=0|1 + req_fw_nowait=0|1 + init_cfg= + e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf + cal_data_cfg= + e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf + txpwrlimit_cfg= + e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf + init_hostcmd_cfg= + e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf + cfg80211_wext= + Bit 0: STA WEXT + Bit 1: uAP WEXT + Bit 2: STA CFG80211 + Bit 3: uAP CFG80211 + cfg80211_drcs=1|0 + reg_alpha2= + wq_sched_prio: Priority for work queue + wq_sched_policy: Scheduling policy for work queue + (0: SCHED_NORMAL, 1: SCHED_FIFO, 2: SCHED_RR, 3: SCHED_BATCH, 5: SCHED_IDLE) + Please note that, both wq_sched_prio and wq_sched_policy should be provided + as module parameters. If wq_sched_policy is (0, 3 or 5), then wq_sched_prio + must be 0. wq_sched_prio should be 1 to 99 otherwise. + rx_work=0|1|2 + indication_gpio=0xXY + gtk_rekey_offload=0|1|2 + napi=0|1 + Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used + for module parameters. + insmod sd8xxx.ko " ..." + +3) FOR DRIVER PROC & DEBUG + + The following info are provided in /proc/net/mwlan/mlanX|uapX|wfdX/info, + on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/info. + + driver_name = "wlan" or "uap" + driver_version = + interface_name = "mlanX", "uapX" or "wfdX" + bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown" + media_state = "Disconnected" | "Connected" + mac_address = <6-byte adapter MAC address> + multicase_count = // Only for STA + essid = // Only for STA + bssid = // Only for STA + channel = // Only for STA + region_code = // Only for STA + multicast_address[n] = // Only for STA + num_tx_bytes = + num_rx_bytes = + num_tx_pkts = + num_rx_pkts = + num_tx_pkts_dropped = + num_rx_pkts_dropped = + num_tx_pkts_err = + num_rx_pkts_err = + carrier "on" | "off" + tx queue "stopped" | "started" + tkip_mic_failures = 0 // Only for uAP + ccmp_decrypt_errors = 0 // Only for uAP + wep_undecryptable_count = 0 // Only for uAP + wep_icv_error_count = 0 // Only for uAP + decrypt_failure_count = 0 // Only for uAP + mcast_tx_count = 0 // Only for uAP + failed_count = 0 // Only for uAP + retry_count = 0 // Only for uAP + multiple_retry_count = 0 // Only for uAP + frame_duplicate_count = 0 // Only for uAP + rts_success_count = 0 // Only for uAP + rts_failure_count = 0 // Only for uAP + ack_failure_count = 0 // Only for uAP + rx_fragment_count = 0 // Only for uAP + mcast_rx_frame_count = 0 // Only for uAP + fcs_error_count = 0 // Only for uAP + tx_frame_count = 0 // Only for uAP + rsna_tkip_cm_invoked = 0 // Only for uAP + rsna_4way_hshk_failures = 0 // Only for uAP + + The following debug info are provided in /proc/net/mwlan/mlanX|uapX|wfdX/debug, + on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/debug. + + drvdbg = + wmm_ac_vo = + wmm_ac_vi = + wmm_ac_be = + wmm_ac_bk = + max_tx_buf_size = + tx_buf_size = + curr_tx_buf_size = + ps_mode = <0/1, CAM mode/PS mode> + ps_state = <0/1/2/3, awake state/pre-sleep state/sleep-confirm state/sleep state> + is_deep_sleep = <0/1, not deep sleep state/deep sleep state> // Only for STA + wakeup_dev_req = <0/1, wakeup device not required/required> + wakeup_tries = + hs_configured = <0/1, host sleep not configured/configured> + hs_activated = <0/1, extended host sleep not activated/activated> + tx_pkts_queued = + pps_uapsd_mode = <0/1, PPS/UAPSD mode disabled/enabled> // Only for STA + sleep_pd = // Only for STA + qos_cfg = // Only for STA + tx_lock_flag = <0/1, Tx lock flag> // Only for STA + port_open = <0/1, port open flag> // Only for STA + scan_processing = <0/1, scan processing flag> // Only for STA + num_bridge_pkts = // Only for uAP + num_drop_pkts = // Only for uAP + num_tx_timeout = + num_cmd_timeout = + timeout_cmd_id = + timeout_cmd_act = + last_cmd_id = + last_cmd_act = + last_cmd_index = <0 based last command index> + last_cmd_resp_id = + last_cmd_resp_index = <0 based last command response index> + last_event = + last_event_index = <0 based last event index> + num_cmd_h2c_fail = + num_cmd_sleep_cfm_fail = + num_tx_h2c_fail = + num_evt_deauth = // Only for STA + num_evt_disassoc = // Only for STA + num_evt_link_lost = // Only for STA + num_cmd_deauth = // Only for STA + num_cmd_assoc_ok = // Only for STA + num_cmd_assoc_fail = // Only for STA + cmd_sent = <0/1, send command resources available/sending command to device> + data_sent = <0/1, send data resources available/sending data to device> + txbd_rdptr = + txbd_wrptr = + rxbd_rdptr = + rxbd_wrptr = + eventbd_rdptr = + eventbd_wrptr = + cmd_resp_received = <0/1, no cmd response to process/response received and yet to process> + event_received = <0/1, no event to process/event received and yet to process> + ioctl_pending = + tx_pending = + rx_pending = + lock_count = + malloc_count = + mbufalloc_count = + malloc_cons_count = + main_state = + + Issue debug_dump command through proc. + Usage: + echo "debug_dump" > /proc/mwlan/config + + Examples: + echo "debug_dump" > /proc/mwlan/config # dump driver internal debug status. + + Use dmesg or cat /var/log/debug to check driver debug messages. + To log driver debug messages to file, + a) Edit /etc/syslog.conf, add one line "*.debug /var/log/debug" + on kernel 2.6.24 or later, edit /etc/rsyslog.conf instead + b) touch /var/log/debug (if the file doesn't exist) + c) service syslog restart + on kernel 2.6.24 or later, service rsyslog restart + + Update /proc/sys/kernel/printk to change message log levels. + For example, + echo 6 > /proc/sys/kernel/printk (messages with a higher priority than 6 + will be printed to the console) + echo 15 > /proc/sys/kernel/printk (all messages will be printed to console) + +4) FOR FW RELOAD + a) Enable parallel firmware download in driver parameter + insmod sd8xxx.ko fw_serial=0 + + b) default fw name for parallel firmware download + sd8887_wlan_a2.bin + + c) Trigger FW reload + echo "fw_reload=1" > /proc/mwlan/config trigger inband firmware reset and reload firmware + echo "fw_reload=2" > /proc/mwlan/config trigger firmware reload + echo "fw_reload=3" > /proc/mwlan/config set firmware reload flag in driver. + echo "fw_reload=4" > /proc/mwlan/config trigger pcie FLR and reload firmware. + + (Note: This feature will be supported on Robin3 and KF2. + For CAC-A2, it only work with the board which supports parallel fw download) + + + +=============================================================================== + U S E R M A N U A L F O R MLANUTL + +NAME + mlanutl - configure the additional parameters available for Marvell mdriver. + +SYNOPSIS + mlanutl -v + mlanutl [parameters] ... + + mlanutl mlanX 11dcfg + mlanutl mlanX 11dclrtbl + mlanutl mlanX addbapara [

] + mlanutl uapX addbapara [

] + mlanutl mlanX addbareject [ ... ] + mlanutl uapX addbareject [ ... ] + mlanutl mlanX addts + mlanutl mlanX aggrpriotbl [ ... ] + mlanutl uapX aggrpriotbl [ ... ] + mlanutl mlanX amsduaggrctrl + mlanutl mlanX antcfg [m] [n] + mlanutl mlanX/uapX mimoswitch [tx_antmode] [rx_antmode] + mlanutl mlanX arpfilter + mlanutl mlanX assocessid <"[essid]"> + mlanutl mlanX assocessid_bssid <"[bssid] [essid]"> + mlanutl mlanX associate " " + mlanutl mlanX authtype [n] + mlanutl mlanX autotdls [n] + mlanutl mlanX tdls_idle_time [n] + mlanutl uapX dfs_offload [n] + mlanutl mlanX bandcfg [l] [m] [n] + mlanutl mlanX bcninterval [n] + mlanutl wfdX bssrole [l] + mlanutl mlanX cfgdata [] + mlanutl mlanX cfpcode [m] [n] + mlanutl mlanX changraph [ ] + mlanutl mlanX coex_rx_winsize [m] + mlanutl mlanX countrycode [l] + + mlanutl mlanX cfpinfo + mlanutl uapX cfpinfo + + mlanutl mlanX acs [ ... ] + mlanutl uapX acs [ ... ] + + mlanutl mlanX customie [[[] ] ] + mlanutl mlanX deauth [l] + mlanutl uapX deauth [l] + mlanutl mlanX deepsleep [l] [m] + mlanutl mlanX delba [ ] + mlanutl uapX delba [ ] + mlanutl mlanX delts + mlanutl mlanX dfstesting [ ] + mlanutl mlanX dfs_repeater [n] + mlanutl mlanX drvdbg [n] + mlanutl mlanX esuppmode [l] [m] [n] + mlanutl mlanX extcapcfg [] + mlanutl mlanX fwmacaddr [mac_addr] + mlanutl mlanX getdatarate + mlanutl uapX getdatarate + mlanutl mlanX getlog + mlanutl mlanX getscantable [ARGS] + mlanutl mlanX getsignal [m] [n] + mlanutl mlanX signalextcfg [m] + mlanutl mlanX getsignalextv2 [m] + mlanutl mlanX getsignalext [m] + mlanutl mlanX dyn_bw [n] + mlanutl uapX getstalist + mlanutl uapX channel_switch + mlanutl mlanX hostcmd <11n_2040coex.conf> 2040coex + mlanutl mlanX hostcmd auto_tx_get + mlanutl mlanX hostcmd auto_tx_unreg + mlanutl mlanX hostcmd bgscfg + + mlanutl mlanX hostcmd coalesce_cfg + mlanutl mlanX hostcmd ed_mac_ctrl + mlanutl mlanX hostcmd crypto_test + mlanutl mlanX hostcmd nat_keep_alive + mlanutl mlanX hostcmd pad_cfg_get + mlanutl mlanX hostcmd pad_cfg_set + mlanutl mlanX hostcmd requesttpc + mlanutl mlanX hostcmd mode_get + mlanutl mlanX hostcmd mode_timeshare + mlanutl mlanX hostcmd mode_spatial + mlanutl mlanX hostcmd mode_none + mlanutl mlanX hostcmd gpio_cfg + mlanutl mlanX hostcmd generictime + mlanutl mlanX hostcmd a2dptime + mlanutl mlanX hostcmd inquirytim + mlanutl mlanX hostcmd ap_generictime + mlanutl mlanX hostcmd ap_a2dptime + mlanutl mlanX hostcmd ap_inquirytime + mlanutl mlanX hostcmd subevent_get + mlanutl mlanX hostcmd subevent_set + mlanutl mlanX hostcmd txpwrlimit_2g_cfg_set + mlanutl mlanX hostcmd txpwrlimit_5g_cfg_set + mlanutl mlanX hostcmd txpwrlimit_cfg_get + mlanutl mlanX hostcmd txrate_cfg_get + mlanutl mlanX hostcmd txrate_cfg_set_bg + mlanutl mlanX hostcmd txrate_cfg_set_bgn + mlanutl mlanX hostcmd generate_raw + mlanutl mlanX hostcmd fwdump + + mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] [ind_GPIO# [level]] + mlanutl mlanX hssetpara condition [GPIO# [gap]] [ind_GPIO# [level]] + mlanutl mlanX mgmtfilter + mlanutl mlanX auto_arp [n] + mlanutl mlanX htcapinfo [] [] + mlanutl mlanX htstreamcfg [n] + mlanutl mlanX httxbfcap [cap] + mlanutl mlanX httxbfcfg "[;GlobalData/tsData/interval/txPeerData/snrData]" + mlanutl mlanX httxcfg [] [] + mlanutl mlanX inactivityto [k] + mlanutl mlanX ipaddr [";"] + mlanutl mlanX linkstats + mlanutl mlanX listeninterval [l] + mlanutl mlanX macctrl [n] + mlanutl uapX macctrl [n] + mlanutl mlanX mefcfg + mlanutl mlanX memrdwr

[value] + mlanutl mlanX miracastcfg [l] [m] [n] + mlanutl mlanX mgmtframectrl [] + mlanutl uapX mgmtframectrl [] + mlanutl mlanX mgmtframetx + mlanutl mlanX netmon [ [ [offset]]] + mlanutl mlanX offchannel [ ] + mlanutl mlanX otpuserdata + mlanutl mlanX passphrase [l] + mlanutl mlanX pb_bypass [data_1, data_2, ... data_n] + mlanutl mlanX pcieregrw [value] + mlanutl mlanX pciebar0regrw [value] + mlanutl mlanX pmfcfg + mlanutl mlanX port_ctrl [n] + mlanutl mlanX powercons [n] + mlanutl mlanX pscfg [k] [d] [l] ... + mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p] + mlanutl mlanX psmode [l] + mlanutl robustcoex [Enable/Disable] [gpionum] [gpiopolarity] + mlanutl mlanX qconfig def [Queue Id: 0-3] + mlanutl mlanX qconfig get [Queue Id: 0-3] + mlanutl mlanX qconfig set msdu [Queue Id: 0-3] + mlanutl mlanX qoscfg + mlanutl mlanX qstatus + mlanutl mlanX radioctrl [n] + mlanutl mlanX rdeeprom + mlanutl mlanX reassoctrl [n] + mlanutl mlanX regioncode [n] + mlanutl mlanX regrdwr [value] + mlanutl mlanX rejectaddbareq [conditions] + mlanutl uapX rejectaddbareq [conditions] + mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [c] [ext] + mlanutl mlanX setuserscan [ARGS] + mlanutl mlanX cancelscan + mlanutl mlanX sleepparams [ ] + mlanutl mlanX sleeppd [n] + mlanutl mlanX sysclock [clk1] [clk2] [clk3] [clk4] + mlanutl mlanX tcpackenh [l] + mlanutl mlanX tdls_channel_switch + mlanutl mlanX tdls_config <0/1> + mlanutl mlanX tdls_cs_params + mlanutl mlanX tdls_debug "allow_weak_security" <0/1> + mlanutl mlanX tdls_debug "cs_im_return" <0/1> + mlanutl mlanX tdls_debug "fail_setup_confirm" <0/1> + mlanutl mlanX tdls_debug "higher_lower_mac" <0/1> + mlanutl mlanX tdls_debug "ignore_key_expiry" <0/1> + mlanutl mlanX tdls_debug "setup_existing_link" <0/1> + mlanutl mlanX tdls_debug "setup_with_prohibited" <0/1> + mlanutl mlanX tdls_debug "stop_rx" <0/1> + mlanutl mlanX tdls_debug "wrong_bss" <0/1> + mlanutl mlanX tdls_disable_cs <0/1> + mlanutl mlanX tdls_discovery + mlanutl mlanX tdls_link_status + mlanutl mlanX tdls_powermode + mlanutl mlanX tdls_setinfo + mlanutl mlanX tdls_setup + mlanutl mlanX tdls_stop_channel_switch + mlanutl mlanX tdls_teardown + mlanutl mlanX ts_status + mlanutl mlanX tsf + mlanutl mlanX txaggrctrl [m] + mlanutl mlanX txbufcfg + mlanutl mlanX txratecfg [l] [m] [n] + mlanutl uapX txratecfg [l] [m] [n] + mlanutl mlanX verext + mlanutl mlanX version + mlanutl mlanX vhtcfg [l] [m] [n] [o] + mlanutl uapX vhtcfg [l] [m] [n] [o] + mlanutl per_pkt_cfg [tx_rx_control] [type_num] [ether_type1 ether_type2 ...] [tx_rx_control] [type_num] [ether_type1 ether_type2 ...] + mlanutl dot11_txrx + mlanutl mlanX txrxhistogram [action] [tx_rx_statics] + mlanutl uapX txrxhistogram [action] [tx_rx_statics] + mlanutl mlanX wakeupreason + mlanutl uapX wakeupreason + mlanutl mlanX warmreset + mlanutl mlanX wpssession [n] + mlanutl mlanX wmmcfg [n] + mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP] + mlanutl mlanX wwscfg [m] + mlanutl mlanX mc_cfg [n] + mlanutl mlanX mc_policy [n] + mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] + mlanutl p2pX cfg_noa [h] [i] [j] [k] [l] + mlanutl p2pX cfg_opp_ps [m] [n] + mlanutl mlanX get_sensor_temp + mlanutl mlanX 11k_enable [n] + mlanutl mlanX neighbor_report + mlanutl indrstcfg [gpio_pin] + + mlanutl fwwakeupmethod + mlanutl tx_ampdu_prot_mode [mode] + + mlanutl uapX ctrldeauth + + mlanutl mlanX/uapX bootsleep <1/0> + +DESCRIPTION + Those commands are used to send additional commands to the Marvell MLAN + card via the Linux device driver. + + The mlanX parameter specifies the network device that is to be used to + perform this command on. It could be mlan0, mlan1 etc. + +11dcfg + This command is used to control 11D. No argument is used to get. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 11dcfg 1 : Enable 11D + mlanutl mlan0 11dcfg : Get 11D status + +11dclrtbl + This command is used to clear the 11D channel table. + + Usage: + mlanutl mlanX 11dclrtbl + +addbapara + This command can be used to update the default ADDBA parameters. + + where is + - This is the block ack timeout for ADDBA request. + 0 : Disable (recommended for throughput test) + 1 - 65535 : Block Ack Timeout in TU + + where is + - Window size for ADDBA request. (16 is recommended and default value) + + where is + - Window size for ADDBA response. (48 is recommended and 32 is default value) + (16 is recommended for IWNCOMM AP in WAPI throughput test) + + Current window size limit for Tx as well as Rx is 1023. + + where

is + - amsdu support for ADDBA request. (1 is default value) + 0: disable amsdu in ADDBA request + 1: enable amsdu in ADDBA request + + where is + - amsdu support for ADDBA response. (1 is default value) + 0: disable amsdu in ADDBA response + 1: enable amsdu in ADDBA response + + eg: + mlanutl mlanX addbapara - This command will get the current addba params + mlanutl mlanX addbapara 1000 64 8 0 0 - This will change the ADDBA timeout to (1000 * 1024) us, + txwinsize to 64 and rxwinsize to 8 and disable amdsu in ADDBA request/response. + + The default setting is 65535 16 32 1 1. + + In case the ADDBA timeout value is updated then a ADDBA is sent for all streams + to update the timeout value. + + In case txwinsize and/or rxwinsize is updated, the effect could only be seen on + next ADDBA request/response. The current streams will not be affected with this + change. + + In case of txamsdu/rxamsdu is updated, the effect could only be seen on + next ADDBA request/response. The current streams will not be affected with this + change. AMSDU in AMPDU stream will be enabled when AP support this feature + and AMSDU is enabled in aggrpriotbl. + +addbareject + This command is used set/get the addbareject table for all the TIDs. + This command can also be used to enable rejection of ADDBA requests for a given tid. + + where ... + + - This can be 0/1 for TidX. 1 enables rejection of ADDBA request for TidX and + 0 would accept any ADDBAs for TidX. + + eg: + mlanutl mlanX addbareject - This command will get the current table. + [0 0 0 0 0 0 0 0]. ADDBA would be accepted for all TIDs. This is the default state. + + mlanutl mlanX addbareject 0 0 1 1 0 0 0 0 - This command will accept ADDBA requests for + Tid [0,1,4,5,6,7] and reject ADDBA requests for Tid [2,3] + + mlanutl mlanX addbareject 1 1 1 1 1 1 1 1 - This will enable rejection of ADDBA requests for + all Tids. + + Note:- This command should only be issue in disconnected state. + +addts + Send an ADDTS command to the associated AP. + + Process a given conf file for a specific TSPEC data block. Send the + TSPEC along with any other IEs to the driver/firmware for transmission + in an ADDTS request to the associated AP. + + Return the execution status of the command as well as the ADDTS response + from the AP if any. + + Usage: + mlanutl mlanX addts + +aggrpriotbl + This command is used set/get the priority table for AMPDU/AMSDU traffic per tid. + This command can also be used to disable AMPDU/AMSDU for a given tid. + In case of AMPDU this priority table will be used to setup block ack (to make + sure the highest priority tid always uses AMPDU as we have limited AMPDU streams) + + where ... + + - This is priority for Tid0 for AMPDU packet. A priority could be any + values between 0 - 7, 0xff to disable aggregation. + - This is priority for Tid0 for AMSDU packet. A priority could be any + values between 0 - 7, 0xff to disable aggregation. + + eg: + mlanutl mlanX aggrpriotbl - This command will get the current Priority table for AMPDU and AMSDU. + <2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255>. This is read as + <"Prio for AMPDU for Tid0" "Prio for AMSDU for Tid0" + "Prio for AMPDU for Tid1" "Prio for AMSDU for Tid1" and so on + mlanutl mlanX aggrpriotbl 2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255 - + This will set the priority table for AMPDU and AMSDU + Priority for Tid0/AMPDU = 2, Tid0/AMSDU = 2, Tid1/AMPDU = 0, Tid1/AMSDU = 0 + and so on. Aggregation for Tid6 and Tid7 are disabled. + Here higher the priority number, higher the priority (i.e. 7 + has higher priority than 6). Similarly for AMSDU. + mlanutl mlanX aggrpriotbl 0xff 2 0xff 0 0xff 1 0xff 3 0xff 4 0xff 5 0xff 0xff 0xff 0xff - This will disable + AMPDU for all the TIDs but will still keep AMSDU enabled to Tid0 to Tid5 + + The default setting is 2 255 0 255 1 255 3 255 4 255 5 255 255 255 255 255. + + A delBA should be seen in case a disable happens on a TID for which AMPDU stream + is currently setup. + + Note:- This command should only be issue in disconnected state. + +amsduaggrctrl + This command could be used to enable/disable a feature where firmware gives feedback to driver + regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the + current rate to decide the buffer size we could transmit. The max buffer size will still be + limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit + 4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate) + + If enabled AMSDU buffer size at various rates will be as follows + + 1. Legacy B/G rate. + No AMSDU aggregation. + + 2. BW20 HT Rate: + When TX rate goes down, + MCS 7, 6, 5, 4: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 3, 2: + a 4K aggregation size (if TX buffer size is 8K/4K) + b 2K aggregation size (if TX buffer size is 2K) + + MCS 1, 0: + a No aggregation + + When TX rate goes up, + MCS 7, 6, 5: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 4, 3: + a 4K aggregation size (if TX buffer size is 8K/4K) + b 2K aggregation size (if TX buffer size is 2K) + + MCS 2, 1, 0: + a No aggregation + + 3. BW40 HT Rate: + When TX rate goes down, + MCS 7, 6, 5, 4, 3, 2, 1: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 0: + a No aggregation + + When TX rate goes up, + MCS 7, 6, 5, 4, 3: + a 8K aggregation size (if TX buffer size is 8K) + b 4K aggregation size (if TX buffer size is 4K) + c 2K aggregation size (if TX buffer size is 2K) + + MCS 2, 1, 0: + a No aggregation + + where is 0/1 (for disable/enable) + + eg: + mlanutl mlan0 amsduaggrctrl 1 - Enable this feature + mlanutl mlan0 amsduaggrctrl 0 - Disable this feature + mlanutl mlan0 amsduaggrctrl - This will get the enable/disable flag + and the current AMSDU buffer size). The AMSDU buffer size returned is only + valid after association as before association there is no rate info. + + Note:- This command to enable/disable could be given anytime (before/after + association). This feature is enabled by default by the driver during + initialization. + +antcfg + This command is used to set/get the mode of Tx/Rx path. + + For chip which support STREAM_2X2 + where value of m is: + Bit 0 -- Tx Path A or Tx/Rx Path A if [n] is not provided + Bit 1 -- Tx Path B or Tx/Rx Path B if [n] is not provided + Bit 0-1 -- Tx Path A+B or Tx/Rx Path A+B if [n] is not provided + where value of n is: + Bit 0 -- Rx Path A + Bit 1 -- Rx Path B + Bit 0-1 -- Rx Path A+B + The Tx path setting (m) is used for both Tx and Rx if Rx path (n) is not provided. + + Examples: + mlanutl mlan0 antcfg : Get Tx and Rx path + mlanutl mlan0 antcfg 3 : Set Tx and Rx path to A+B + mlanutl mlan0 antcfg 1 3 : Set Tx path to A and Rx path to A+B + +mimoswitch + This command is used to do MIMO switch for 11n and 11ac mode and is available for all interfaces. + mlanutl mlanX/uapX mimoswitch [tx_antmode] [rx_antmode] + + This command takes 2 conditions. + The supported options are: + tx_antmode: 1 - ANTENNA A + 2 - ANTENNA B + 3 - ANTENNA AB + rx_antmode: 1 - ANTENNA A + 2 - ANTENNA B + 3 - ANTENNA AB + Examples: + mlanutl mlan0/uap0 mimoswitch 1 1 : set Tx and Rx path to ANTENNA A + mlanutl mlna0/uap0 mimoswitch 2 2 : set Tx and Rx path to ANTENNA B + mlanutl mlan0/uap0 mimoswitch 3 3 : set Tx and Rx path to ANTENNA A+B + mlnautl mlan0/uap0 mimoswitch 1 3 : set Tx path to ANTENNA A and Rx path to ANTENNA A+B + +arpfilter + This command is used to configure the ARP filtering parameters. + + Usage: + mlanutl mlanX arpfilter + + Where the parameter is: + arpfilter.conf : The configuration file specifying ARP filtering parameters. + + Example: + mlanutl mlan0 arpfilter config/arpfilter.conf + +assocessid + This command is used to assoc essid with asynced mode, + and driver will auto retry if driver auto assoc enabled. + + Usage: + mlanutl mlanX assocessid <"[essid]"> + + Where + <"[essid]"> is the essid which need to be associated with asynced mode. + + Examples: + mlanutl mlan0 assocessid "Marvell Micro AP" : Associate to the ESSID "Marvell Micro AP" + +assocessid_bssid + This command is used to assoc AP by ssid/bssid pair with asynced mode, + and driver will auto retry if driver auto assoc enabled. + + Usage: + mlanutl mlanX assocessid_bssid <"[bssid] [essid]"> + + Where + <"[bssid]"> is the bssid which need to be associated with asynced mode. + <"[essid]"> is the essid which need to be associated with asynced mode. + + Examples: + mlanutl mlan0 assocessid_bssid "xx:xx:xx:xx:xx:xx Marvell Micro AP" : Associate to the AP which ssid = "Marvell Micro AP", bssid = "xx:xx:xx:xx:xx:xx" + +associate + Request an association to a given SSID/BSSID pair. This the only accurate + way to pick a specific AP and ESS for an association. The entry must + already exist in the scan table for the association to be attempted. + + mlanutl mlanX associate "xx:xx:xx:xx:xx:xx SSID" + +authtype + This command is used to set/get authentication type. + + Usage: + mlanutl mlanX authtype [n] + + where + 0: 802.11 open system authentication + 1: 802.11 shared key authentication + 255: allow open system or shared key authentication (default) + + Examples: + mlanutl mlan0 authtype 0 : use open system authentication + mlanutl mlan0 authtype 1 : use shared key authentication + mlanutl mlan0 authtype 255 : allow open system or shared key authentication + mlanutl mlan0 authtype : get current setting + +autotdls + This command is used to enable/disable auto TDLS. + + Usage: + mlanutl mlanX autotdls [n] + + where + 0: Disable auto tdls + 1: Enable auto tdls + + Examples: + mlanutl mlan0 autotdls 1 : enable auto TDLS + mlanutl mlan0 autotdls 0 : disable auto TDLS + mlanutl mlan0 autotdls : get current setting + +dyn_bw + This command is used to set/get dynamic bandwidth. + + Usage: + mlanutl mlanX dyn_bw [n] + + where + [BIT0] + 0 = TxInfo Indicated BW Disable + 1 = TxInfo Indicated BW Enable + [BIT1] + 0 = TxInfo Dynamatic BW Disable + 1 = TxInfo Dynamatic BW Enable + [BIT2] + 0 = TxInfo Force send RTS Disable + 1 = TxInfo Force send RTS Enable + [BIT3] + 0 = Mac Dynamic BW Operation Mode Disable (Static BW Operation Mode) + 1 = Mac Dynamic BW Operation Mode Enable + other bits reserved. + + If no parameter provided, get is performed. + + Examples: + mlanutl mlan0 dyn_bw 0x1 : Enable TxInfo Indicated BW + mlanutl mlan0 dyn_bw : get current setting + +tdls_idle_time + This command is used to set/get TDLS idle timeout. The valid value is between 0-0xffff. When set to 0, the tdls_idle_time will use default value(60). + + Usage: + mlanutl mlanX tdls_idle_time [n] + + where + TDLS idle timeout value + + Examples: + mlanutl mlan0 tdls_idle_time 30 : set tdls_idle_time value to 30 + mlanutl mlan0 tdls_idle_time 0 : use default tdls_idle_time value(60) + mlanutl mlan0 tdls_idle_time : get current setting + +dfs_offload + This command is used to enable/disable DFS offload. The valid value is 0/1. + Note: The parameters can be set only in disconnected state. + + Usage: + mlanutl uapX dfs_offload [n] + + where + Enable/disable + + Examples: + mlanutl uap0 dfs_offload 1 : enable DFS offload + mlanutl uap0 dfs_offload 0 : disable DFS offload + +bandcfg + This command is used to set/get infra/ad-hoc band. + Note: This command is only available in disconnected state. + + Usage: + mlanutl mlanX bandcfg [l] [m] [n] + + where the parameters: + [l]: Infrastructure band + bit 0: B + bit 1: G + bit 2: A + bit 3: GN + bit 4: AN + + bit 5: AC 2.4G + bit 6: AC 5G + [m]: Ad-hoc start band + bit 0: B + bit 1: G + bit 2: A + [n]: Ad-hoc start channel + Examples: + mlanutl mlan0 bandcfg : Get infra/ad-hoc band and ad-hoc + start channel configurations + mlanutl mlan0 bandcfg 1 : Set infra band to B only + mlanutl mlan0 bandcfg 3 2 6 : Set infra band to B/G, ad-hoc start band + to G and ad-hoc start channel to 6 + +bcninterval + This command is used to set/get the beacon interval in ad-hoc mode. + The valid beacon interval is between 20 - 1000, default beacon + interval is 100. + + Where + Beacon interval in TU (Time Unit: 1024 us). + + Examples: + mlanutl mlan0 bcninterval 200 : Set ad-hoc beacon interval to 200 + mlanutl mlan0 bcninterval : Get ad-hoc beacon interval + +bssrole + This command is used to set/get the BSS role. + + Where + [l] is + - This parameter specifies the BSS role to set. + 0 : STA + 1 : uAP + + Examples: + mlanutl wfd0 bssrole : Get the current BSS role + mlanutl wfd0 bssrole 1 : Set the current BSS role to uAP + +cfgdata + This command is used to set/get the configuration data to/from firmware. + + Usage: + mlanutl mlanX cfgdata [<.conf file name>] + + Where the parameters are: + type : + 2 -- CAL data download and <.conf file name> is cal_data.conf + .conf file name : The configuration file used to set/get the configuration data. + + Examples: + mlanutl mlan0 cfgdata 2 + : This command is used to get and display the CAL data from firmware. + +cfpcode + This command is used to set/get the Channel-Frequency-Power table codes. + The region table can be selected through region code. + The current configuration is returned if no parameter provided. + + where the parameters are, + [m]: code of the CFP table for 2.4GHz (0: unchanged) + [n]: code of the CFP table for 5GHz (0 or not provided: unchanged) + + Examples: + mlanutl mlan0 cfpcode : Get current configuration + mlanutl mlan0 cfpcode 0x30 : Set 2.4GHz CFP table code 0x30 (EU), + keep 5GHz table unchanged + mlanutl mlan0 cfpcode 0x10 5 : Set 2.4GHz CFP table code 0x10 (USA) + and 5GHz table code 5 + +changraph + Displays 2-dimensional graph, plotting channel number along x-axis and + anpi or channel-load along y-axis, depending on whether it is an anpi graph + or a channel load graph. + + Usage: + mlanutl mlanX changraph [ ] + where: + load: Only channel vs channel-load graph is displayed + anpi: Only channel vs Average Noise Power Indicator(ANPI) + graph is displayed + anpiload: Both the graphs for anpi and for the load are displayed + loops: This is used to calculate the number of times + the graph [load or anpi or both] will be printed + +coex_rx_winsize + This command is used to set/get control to coex RX window size + + where value of m is: + 0 -- Disable COEX RX winsize (default) + 1 -- Enable COEX RX winsize + + Examples: + mlanutl mlan0 coex_rx_winsize : Get COEX RX winsize + mlanutl mlan0 coex_rx_winsize 1 : Enable COEX RX winsize + +countrycode + This command is used to set and get the country code. + + Where + [l] is Country code + + Examples: + mlanutl mlan0 countrycode : Get current countrycode + mlanutl mlan0 countrycode CN : Set countrycode as China (CN) + +cfpinfo + This command is used to get region, country, environment codes, + channel and power table information from the FW. + + Examples: + mlanutl mlan0 cfpinfo : Display cfp tables + mlanutl uap0 cfpinfo + +acs + This command is used to issue acs scan, then FW will + report the best channel and channel statistics. + User could specify channels or not. If channel is not + specified, acs scan will be on all supported channels. + + Examples: + mlanutl mlan0 acs : ACS scan on all supported channels + mlanutl uap0 acs : ACS scan on all supported channels + mlanutl mlan0 acs 5 6 7 8 : ACS scan on 5 6 7 8 channels + mlanutl uap0 acs 1 2 3 : ACS scan on 1 2 3 channels + +customie + This command is used to set or get custom IEs for management frames. + + Usage: + mlanutl mlanX customie [[[] ] ] + + Where the parameter is: + empty - Get all IE settings + : 0 - Get/Set IE index 0 setting + 1 - Get/Set IE index 1 setting + 2 - Get/Set IE index 2 setting + MAX IE Index depends on device memory. + -1 - Append/Delete IE automatically + Delete will delete the IE from the matching IE buffer + Append will append the IE to the buffer with the same mask + : Management subtype mask value as per bit definitions + : Bit 0 - Association request + : Bit 1 - Association response + : Bit 2 - Reassociation request + : Bit 3 - Reassociation response + : Bit 4 - Probe request + : Bit 5 - Probe response + : Bit 8 - Beacon + : mask = 0 to clear the mask and the IE buffer + : IE Buffer in hex (max 256 bytes) + The Buffer should not be space separated. + + Examples: + mlanutl mlan0 customie + : Get IE buffer, subtype mask settings for all indices. + + mlanutl mlan0 customie 1 + : Get IE buffer and subtype mask for the Index = 1. + + mlanutl mlan0 customie 2 0 + : Clear IE buffer and mask value for Index = 2. + + mlanutl mlan0 customie 3 0x101 0xdd051234567890 + : Set IE buffer and mask value for Index = 3. + + mlanutl mlan0 customie -1 0x101 0xdd051234567890 + : Append the specified IEBuffer at index with mask value of 0x101. + + mlanutl mlan0 customie -1 0 0xdd051234567890 + : Delete the specified IEBuffer from all the IEs. + + mlanutl mlan0 customie 2 0 0xdd051234567890 + : Delete the specified IEBuffer from the IEs at index 2. + +deauth + This command is used to send a de-authentication to an arbitrary AP. + If [l] is omitted, the driver will deauth the associated AP. + If in ad-hoc mode this command is used to stop beacon transmission + from the station and go into idle state. + + When is supplied as a MAC address, the driver will deauth the + specified AP. If the AP address matches the driver's associated AP, + the driver will disconnect. Otherwise, the driver remains connected. + + When this command is executed on AP interface, it is used to send + a de-authentication to associated station. + +deepsleep + This command is used to set/get auto deep sleep mode. + + Usage: + mlanutl mlanX deepsleep [l] [m] + + where the parameters are: + [l]: Enable/disable auto deep sleep mode (1/0) + [m]: Idle time in milliseconds after which firmware will put the device + in deep sleep mode. Default value is 100 ms. + + Examples: + mlanutl mlan0 deepsleep : Display auto deep sleep mode + mlanutl mlan0 deepsleep 1 : Enable auto deep sleep mode, idle time unchanged + mlanutl mlan0 deepsleep 0 : Disable auto deep sleep mode + mlanutl mlan0 deepsleep 1 500 : Enable auto deep sleep mode with idle time 500 ms + Note: + Deepsleep must be disabled before changing idle time. + +delba + This command is used to delete either all Tx BA or all Rx BA or a specific BA stream + based on direction, TID and peer address. + + where [ ] + - This is the direction of BA stream, Tx (bit 0), Rx (bit 1). + - This is the TID (0-7, 0xff for all) of BA stream. + - This is the peer MAC addres of BA stream. + + eg: + mlanutl mlanX delba 2 - This command will delete all the Rx BA streams. + mlanutl mlanX delba 3 - This command will delete all the Tx and Rx BA streams. + mlanutl mlanX delba 1 0 - This command will delete all the Tx streams with TID 0. + mlanutl mlanX delba 2 0xff "00:11:22:33:44:55" - This command will delete all the Rx BA streams + with specified peer MAC address + mlanutl mlanX delba 1 3 "00:11:22:33:44:55" - This command will delete the Tx BA stream with + TID 3 and specified peer MAC address. + +delts + Send a DELTS command to the associated AP. + + Process a given conf file for a specific TSPEC data block. Send the + TSPEC along with any other IEs to the driver/firmware for transmission + in a DELTS request to the associated AP. + + Return the execution status of the command. There is no response to a + DELTS from the AP. + + Usage: + mlanutl mlanX delts + +dfstesting + This command is used to set/get settings for DFS testing. + + Usage: + mlanutl mlanX dfstesting [ ] + + where is user-configured Channel Availability Check in msec + 0 = disable, use default period (60000) + 1-65535 = enable with that period + where is user-configured Non-Occupancy Period in sec + 0 = disable, use default period (1800) + 1-65535 = enable with that period + where is enable/disable no channel change on radar + 0 = disable, 1 = enable (overrides below) + where is user-configured channel to change to on radar + 0 = disable, 1-255 = enable with that channel + (channel validity for region, etc. is not checked) + (only takes effect if no_chan_change = 0) + + Examples: + mlanutl mlan0 dfstesting : Get current dfstesting settings + mlanutl mlan0 dfstesting 2000 0 0 0 : user_cac=2sec, others disabled/default + mlanutl mlan0 dfstesting 0 0 1 0 : only no_chan_change enabled + mlanutl mlan0 dfstesting 0 120 0 64 : user_nop=2min, force chan 64 on radar + +dfs_repeater + This command is used to get/set DFS Repeater mode. + + Usage: + mlanutl mlan0 dfs_repeater + + where the parameter is : + null: to get current setting + 1: to enable dfs_repeater mode + 0: to disable dfs_repeater mode + + eg., + mlanutl mlan0 dfs_repeater :get current setting + mlanutl mlan0 dfs_repeater 1 :enable dfs repeater mode + mlanutl mlan0 dfs_repeater 0 :disable dfs repeater mode + +drvdbg + This command is used to set/get the bit masks of driver debug message control. + + Usage: + mlanutl mlanX drvdbg [n] + + Where the parameter is the generic debug message control bit mask. + The following types of driver debug messages can be dynamically enabled or + disabled by setting or clearing the corresponding bits, + bit 0: MMSG PRINTM(MMSG,...) + bit 1: MFATAL PRINTM(MFATAL,...) + bit 2: MERROR PRINTM(MERROR,...) + bit 3: MDATA PRINTM(MDATA,...) + bit 4: MCMND PRINTM(MCMND,...) + bit 5: MEVENT PRINTM(MEVENT,...) + bit 6: MINTR PRINTM(MINTR,...) + bit 7: MIOCTL PRINTM(MIOCTL,...) + ... + bit 16: MDAT_D PRINTM(MDAT_D,...), DBG_HEXDUMP(MDAT_D,...) + bit 17: MCMD_D PRINTM(MCMD_D,...), DBG_HEXDUMP(MCMD_D,...) + bit 18: MEVT_D PRINTM(MEVT_D,...), DBG_HEXDUMP(MEVT_D,...) + bit 19: MFW_D PRINTM(MFW_D,...), DBG_HEXDUMP(MFW_D,...) + bit 20: MIF_D PRINTM(MIF_D,...), DBG_HEXDUMP(MIF_D,...) + ... + bit 28: MENTRY PRINTM(MENTRY,...), ENTER(), LEAVE() + bit 29: MWARN PRINTM(MWARN,...) + bit 30: MINFO PRINTM(MINFO,...) + + If CONFIG_DEBUG=2, all kinds of debug messages can be configured. + + If CONFIG_DEBUG=1, all kinds of debug messages can be configured except + for MENTRY, MWARN and MINFO. By default MMSG, MFATAL and MERROR are enabled. + + Some special debug messages, + '*' // MLAN driver ISR is called (bit 6 MINTR enabled) + '|' // PS awake event is received (bit 5 MEVENT enabled) + '_' // PS sleep event is received (bit 5 MEVENT enabled) + '+' // PS sleep confirm is sent (bit 5 MEVENT enabled) + + Examples: + mlanutl mlan0 drvdbg : Get the current driver debug masks + mlanutl mlan0 drvdbg 0 : Disable all the debug messages + mlanutl mlan0 drvdbg 7 : Enable MMSG, MFATAL and MERROR messages + mlanutl mlan0 drvdbg 0x20037 : Enable MMSG, MFATAL, MEEROR, + MCMND, MEVENT and MCMD_D messages + mlanutl mlan0 drvdbg -1 : Enable all the debug messages + +esuppmode + This command is used to set/get the e-supplicant mode configurations/status. + + Note: The configurations can be set only before association. + For get, the configurations will be returned before association + and the current status will be returned after association. + + Where + [l] is + - This parameter specifies the RSN mode configuration + Bit 0 : No RSN + Bit 1-2 : RFU + Bit 3 : WPA + Bit 4 : WPA-NONE + Bit 5 : WPA2 + Bit 6-15 : RFU + [m] is + - This parameter specifies the pairwise cipher + Bit 0 : RFU + Bit 1 : RFU + Bit 2 : TKIP + Bit 3 : AES + Bit 4-7 : RFU + [n] is + - This parameter specifies the group cipher + Bit 0 : RFU + Bit 1 : RFU + Bit 2 : TKIP + Bit 3 : AES + Bit 4-7 : RFU + Note that: the RFU bits cannot be SET. + + Examples: + mlanutl mlan0 esuppmode : Get RSN mode and pairwise/group cipher + mlanutl mlan0 esuppmode 8 4 4 : Set RSN mode yo WPA, active pairwise and + group ciphers to TKIP + +extcapcfg + This command is used to set/get extended capabilities. + + Usage: + mlanutl mlanX extcapcfg [] + + where : Extended capabilities in hex (max 9 bytes) + The Buffer should not be space separated. + + Examples: + mlanutl mlan0 extcapcfg 0x0000008020 : Set TDLS support and Interworking bits. + +fwmacaddr + This command is used to set/get FW side MAC address but host side address will remain as earlier. + + Usage: + mlanutl mlanX fwmacaddr [mac_addr] + + where is desired MAC address + + Examples: + mlanutl mlan0 fwmacaddr : Get current FW MAC address + mlanutl mlan0 fwmacaddr 00:50:43:20:bc:44 : Set FW side MAC address + +getdatarate + This command is used to get the data rate being used in last Tx + packet and last Rx packet. + +getkey + This command is used to get PTK/GTK + + mlanutl mlanX getkey + +getlog + This command is used to get the statistics available in the station. + Following stats are displayed:- + dot11MulticastTransmittedFrameCount Increments when the multicast bit is set in the destination + MAC address of a successfully transmitted MSDU + + dot11FailedCount Increments when an MSDU is not transmitted successfully + + dot11RetryCount Increments when an MSDU is successfully transmitted after one + or more retransmissions + + dot11MultipleRetryCount Increments when an MSDU is successfully transmitted after more + than one retransmission + + dot11FrameDuplicateCount Increments when a frame is received that the Sequence Control + field is indicating a duplicate count + + dot11RTSSuccessCount Increments when a CTS is received in response to an RTS + + dot11RTSFailureCount Increments when a CTS is not received in response to an RTS + + dot11ACKFaliureCount Increments when an ACK is not received when expected + + dot11ReceivedFragmentCount Increments for each successfully received MPDU of type Data or Management + + dot11MulticastReceivedFrameCount Increments when a MSDU is received with the multicast bit set in the destination MAC address + + dot11FCSErrorCount Increments when an FCS error is detected in a received MPDU + + dot11TransmittedFrameCount Increments for each successfully transmitted MSDU + + dot11WeplcvErrCnt Increment when WEP decryption error for key index 0.3 + + beaconReceivedCnt Increments when received beacon + + beaconMissedCnt Increments when beacon missed + + dot11TransmittedFrameCount Increments for each successfully transmitted MSDU + + dot11QosTransmittedFragmentCount Increments when a corresponding UP's MPDU transmitted successfully + + dot11QosFailedCount Increments when a corresponding UP's MSDU not transmitted successfully + + dot11QosRetryCount Increment when a corresponding UP's MSDU transmitted successfully after one or more retransmission + + dot11QosMultipleRetryCount Increments when a corresponding UP's MSDU is successfully transmitted after more than one retransmission + + dot11QosFrameDuplicateCount Increments when a corresponding UP's frame is received that the Sequence + Control field is indicating a duplicate frame + + dot11QosRTSSuccessCount Increments when a CTS is received in response to an RTS, which is sent for a corresponding UP's Qos frame + + dot11QosRTSFailureCount Increments when a CTS is not received in response to an RTS, which is sent for a corresponding UP's + Qos frame + + dot11QosACKFailureCount Increments when an ACK is not received when expected for a corresponding UP's Qos frame + + dot11QosReceivedFragmentCount Increments when a corresponding UP's MPDU received + + dot11QosTransmittedFrameCount Increments when a corresponding UP's MSDU transmitted + + dot11QosDiscardedFrameCount Increments when a corresponding UP's MSDU not transmitted successfully + + dot11QosMPDUsReceivedCount Increments when a corresponding UP's MDPU received + + + dot11QosRetriesReceivedCount Increments when a corresponding UP's MDPU received which retry bit is set + + dot11RSNAStatsCMACICVErrors Increment when a MPDU discard by CMAC integrity check + + dot11RSNAStatsCMACReplays Increments when a MPDU discarded by the CMAC replay error + + dot11RSNAStatsRobustMgmtCCMPReplays Increments when a robust management frame discarded by CCMP replay error + + dot11RSNAStatsTKIPICVErrors Increments when a MPDU discarded by TKIP ICV error + + dot11RSNAStatsTKIPReplays Increments when a MPDU discarded by TKIP replay error + + dot11RSNAStatsCCMPDecryptErrors Increments when a MPDU discarded by CCMP decryption error + + dot11RSNAStatsCCMPReplays Increments when a MPDU discarded by CCMP replay error + + dot11TransmittedAMSDUCount Increments when a A-MSDU transmitted successfully + + dot11FailedAMSDUCount Increments when a A-MSDU not transmitted successfully + + dot11RetryAMSDUCount Increments when a A-MSDU is successfully transmitted after one or more retransmissions + + dot11MultipleRetryAMSDUCount Increments when a A-MSDU is successfully transmitted after more than one retransmissions + + dot11TransmittedOctetsInAMSDUCount Increments by the number of octets in the frame body + of an A-MSDU frame when an A-MSDU frame is successfully transmitted + + dot11AMSDUAckFailureCount Increments when an acknowledgment to an A-MSDU is not received when expected. + + dot11ReceivedAMSDUCount Increments when a A-MSDU frame received + + dot11ReceivedOctetsInAMSDUCount Increments by the number of octets in the frame body + of an A-MSDU frame when an A-MSDU frame is received + + dot11TransmittedAMPDUCount Increments when an A-MPDU is transmitted + + dot11TransmittedMPDUsInAMPDUCount Increments by the number of MPDUs in the A-MPDU when an A-MPDU is transmitted + + dot11TransmittedOctetsInAMPDUCount Increments by the number of octets in the A-MPDU frame when an A-MPDU frame is transmitted + + dot11AMPDUReceivedCount Increments when the MAC receives an A-MPDU from the PHY + + dot11MPDUInReceivedAMPDUCount Increments by the number of MPDUs received in the + A-MPDU when an A-MPDU is received + + dot11ReceivedOctetsInAMPDUCount Increments by the number of octets in the A-MPDU + frame when an A-MPDU frame is received + + dot11AMPDUDelimiterCRCErrorCount Increments when an MPDU delimiter has a CRC error when this is the first + CRC error in the received A-MPDU or when the previous delimiter has been decoded correctly + +per_pkt_cfg +-------------- + mlanutl per_pkt_cfg [tx_rx_control] [type_num] [ether_type1 ether_type2...] [tx_rx_control] [type_num] [ether_type1 ether_type2 ...] + This command is used to set tx/rx per packet Txctl and Rxinfo configuration. + + The supported options are: + tx_rx_control : + 0 - disable Tx and Rx per packet control + 1 - enable Tx per packet control + 2 - enable Rx Per packet control + 3 - enable Tx and Rx Per packet control + + type_num : Number of ether_types which support per packet control, the Max is 8. + ether_type : Array of ether_types for which need to do per-packet Tx control or get per-packet Rx info. + + Examples: + mlanutl mlan0/uap0 per_pkt_cfg : get the configuration of per-packet control + mlanutl mlan0/uap0 per_pkt_cfg 0 : disable per-packet control + mlanutl mlan0/uap0 per_pkt_cfg 3 1 0x88dc : set the Tx and Rx per-packet control configuration + +dot11_txrx + This command is used to send or receive packets. + + Usage: + mlanutl dot11_txrx + interface : mlanX or uapX + options send : + conf_file : config file name + options recv : [ verbose_mode ] + protocol : packet protocol type + verbose_mode : v -- enter verbose mode + + Example: + mlanutl mlan0 dot11_txrx send config/tx_ctrl.conf : To send packets + mlanutl mlan0 dot11_txrx recv 0x88dc : To receive packets of type 0x88dc + mlanutl mlan0 dot11_txrx recv 0x88dc v : To receive packets of type 0x88dc and + enter verbose mode + +txrxhistogram +-------------- + mlanutl mlanX/uapX txrxhistogram [action] [tx_rx_statics] + This command is used to get tx/rx statics from firmware. + + This command takes 2 conditions. + The supported options are: + action : 0 - disable Tx/Rx statics + 1 - enable Tx/Rx statics + 2 - get Tx/Rx statics + tx_rx_statics: 1 - enable/disable/get Tx statics + 2 - enable/disable/get Rx statics + 3 - enable/disable/get Tx and Rx statics + Examples: + mlanutl mlan0/uap0 txrxhistogram 1 3 : enable Tx and Rx statics + mlanutl mlna0/uap0 txrxhistogram 0 3 : disable Tx and Rx statics + mlanutl mlan0/uap0 txrxhistogram 2 2 : Get only Rx statics + mlnautl mlan0/uap0 txrxhistogram 2 1 : Get only Tx statics + mlnautl mlan0/uap0 txrxhistogram 2 3 : Get both Tx/Rx statics + +getscantable + Display the current contents of the driver scan table + + Usage: + mlanutl mlanX getscantable + mlanutl mlanX getscantable [#] + mlanutl mlanX getscantable tsf + mlanutl mlanX getscantable ch + mlanutl mlanX getscantable help + + 1) Without argument, the entire scantable is displayed in terms of channel (ch), signal strength (ss), BSS id (bssid), capability (cap), and SSID, + where each column in the capability is described as follows: + column 1 indicates the IBSS capability: A (Adhoc), I (Infra) + column 2 indicates the encryption capability: P (WEP), W (WPA), 2 (WPA2) + column 3 indicates the 11D capability: D (11D) + column 4 indicates the WMM capability: W (WMM), C (CAC) + column 5 indicates the 11K capability: K (11K) + column 6 indicates the 11R capability: R (11R) + column 7 indicates the WPS capability: S (WPS) + column 8 indicates the 11N/11AC capability: N (11N), A (11AC) + + 2) Specifying a # will display detailed information about a specific scan + table entry. '0' displays driver cached information regarding the + current association (if any). + 3) The tsf argument will display the entire scan table with the recorded + TSF timestamp for the entry. + 4) The ch argument will display the entire scan table sorted by channel + number in the ascending order. If this argument is not specified, + scan table is sorted by signal strength in the descending order. + 6) The help argument will display the legend for the capability field. + +getsignal + This command gets the last and average value of RSSI, SNR and NF of + Beacon and Data. + Note: This command is available only when STA is connected. + + where value of m is: + 1 -- RSSI (Receive Signal Strength Indication) + 2 -- SNR (Signal to Noise Ratio) + 3 -- NF (Noise Floor) + where value of n is: + 1 -- Beacon last + 2 -- Beacon average + 3 -- Data last + 4 -- Data average + + Examples: + mlanutl mlan0 getsignal 1 : Get the RSSI info (beacon last, beacon + average, data last and data average) + mlanutl mlan0 getsignal 3 4 : Get the NF of data average + mlanutl mlan0 getsignal 2 1 : Get the SNR of beacon last + mlanutl mlan0 getsignal : Get all of the signal info + mlan0 getsignal:-32 -33 -35 -36 67 59 63 56 -99 -92 -98 -92 + RSSI info: beacon last -32, beacon average -33, data last -35, data average -36 + SNR info: beacon last 67, beacon average 59, data last 63, data average 56 + NF info: beacon last -99, beacon average -92, data last -98, data average -92 + +getsignalext + This command gets the last and average value of RSSI, SNR and NF of + Beacon and Data of spectific antenna path. + Note: This command is available only when STA is connected. + Driver will enable signalext and collect signal information for one second. + + where value of m is: + 1 -- PATH A + 2 -- PATH B + 3 -- PATH A+B + + Examples: + mlanutl mlan0 getsignalext :Get All path's signal. + mlanutl maln0 getsignalext 3 :Get path A+B signal + mlanutl maln0 getsignalext 1 :Get path A signal + mlanutl mlan0 getsignalext 2 :Get path B signal + + PATH A: -46 -46 -49 -49 65 45 39 42 -111 -91 -88 -91 + + PATH A: RSSI info: beacon last -46, beacon average -46, data last -49, data average -49 + SNR info: beacon last 65, beacon average 45, data last 39, data average 42 + NF info: beacon last -111, beacon average -91, data last -88, data average -91 + +signalextcfg + This command is used to enable/disable signalext + Usage: + mlanutl mlanX signalextcfg [m] + where the value of [m] is: + 1 -- enable signalext in firmware + 0 -- disable signalext in firmware + Examples: + mlanutl mlan0 signalextcfg 1 : Enable signalext in firmware + mlanutl mlan0 signalextcfg 0 : Disable signalext in firmware + +getsignalextv2 + This command gets the last and average value of RSSI, SNR and NF of + Beacon and Data of spectific antenna path. + Note: This command is available only when STA is connected. + "mlanutl mlanX signalextcfg 1" command needs to be issued before issuing this command. + + where value of m is: + 1 -- PATH A + 2 -- PATH B + 3 -- PATH A+B + + Examples: + mlanutl mlan0 getsignalextv2 :Get All path's signal. + mlanutl maln0 getsignalextv2 3 :Get path A+B signal + mlanutl maln0 getsignalextv2 1 :Get path A signal + mlanutl mlan0 getsignalextv2 2 :Get path B signal + + PATH A: -46 -46 -49 -49 65 45 39 42 -111 -91 -88 -91 + + PATH A: RSSI info: beacon last -46, beacon average -46, data last -49, data average -49 + SNR info: beacon last 65, beacon average 45, data last 39, data average 42 + NF info: beacon last -111, beacon average -91, data last -88, data average -91 + +getstalist + This command is used to get list of associated stations to the AP. + + Example: + mlanutl uap0 getstalist + +channel_switch + This command is used to do channel switch according to spec. + + Where the paramters are: + switch mode : 0 -- no need to block traffic, 1 -- need block traffic + oper class : operating class according to IEEE std802.11 spec, when 0 is used, only CSA IE will be used + new channel : the channel will switch to + switch count: channel switch time to send ECSA ie + bandwidth : channel width switch to(optional),only for 5G channels. + Support value 1 -- 40M above, 3 -- 40M below, 4 -- 80M, 5 -- 160M + + Example: + mlanutl uap0 channel_switch 1 115 36 10 :switch to channel 36, oper class 115 + mlanutl uap0 channel_switch 1 81 6 10 :switch to channel 6, oper class 81 + mlanutl uap0 channel_switch 1 0 6 10 :switch to channel 6 + mlanutl uap0 channel_switch 1 0 36 10 1 :switch to channel 36, bandwidth 40MHz above + +hostcmd 2040coex + This command is used to send the 11n 20/40 Coex command to firmware. + Firmware will send 11n 20/40 Coex management action frame to AP. + + Usage: + mlanutl mlanX hostcmd config/11n_2040coex.conf 2040coex + +hostcmd auto_tx_get +hostcmd auto_tx_unreg + This command is used to configures the Frame Auto Transmission parameters. + auto_tx_get: get auto_tx parameters + auto_tx_unreg: unregister to firmware auto_tx + + Usage: + mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_get + mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_unreg + +hostcmd bgscfg + This command is used to configure the various parameters for PPS/UAPSD + or normal background scan. + + Usage: + mlanutl mlanX hostcmd config/bg_scan.conf bgscfg + +hostcmd coalesce_cfg + This command is used to set/clear rules to filter and buffer + broadcast/multicast packet which reduce unwanted patcket or interrupt to + host. + + Usage: + mlanutl mlanX hostcmd coalesce_cfg + +hostcmd ed_mac_ctrl + This command is used to control ED MAC. + + Usage: + mlanutl mlanX hostcmd ed_mac_ctrl + +hostcmd crypto_test + This command is used to test the encryption/decryption API of the firmware. + + Usage: + mlanutl mlanX hostcmd config/crypto_test.conf crypto_test + +hostcmd nat_keep_alive + This command is used to configures the Frame Auto Transmission parameters. + nat_keep_alive: register to firmware for sending NAT Keep Alive packet + + Usage: + mlanutl mlanX hostcmd config/auto_tx.conf nat_keep_alive + +hostcmd pad_cfg_get +hostcmd pad_cfg_set + This command is used to set/get the configuration data for PAD OR. + + Usage: + mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_get + mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_set + +hostcmd requesttpc + This command is used to request 802.11H TPC info. + + Usage: + mlanutl mlanX hostcmd config/requesttpc.conf requesttpc + +hostcmd mode_get +hostcmd mode_timeshare +hostcmd mode_spatial +hostcmd mode_none + This command is used to get/set Robust BT Coex. + mode_get: get the current mode + mode_timeshare: set Robust BT Coex to timeshare mode (default on 1x1_1Antenna chips) + mode_spatial: set Robust BT Coex to spatial mode (default on 2x2 chips) + mode_none: set Robust BT Coex to mode none (default on chips with dedicated BT Antenna. Example: 2x2_3Antenna, 1x1_2Antenna chips) + + Usage: + mlanutl mlanX hostcmd config/robust_btc.conf mode_get + mlanutl mlanX hostcmd config/robust_btc.conf mode_timeshare + mlanutl mlanX hostcmd config/robust_btc.conf mode_spatial + mlanutl mlanX hostcmd config/robust_btc.conf mode_none + +hostcmd gpio_cfg + This command is used to enable/disable GPIO cfg. + gpio_cfg: enable/disable GPIO cfg for external bt request (default is enable with High Polarity) + + Usage: + mlanutl mlanX hostcmd config/robust_btc.conf gpio_cfg + +hostcmd generictime +hostcmd a2dptime +hostcmd inquirytime +hostcmd ap_generictime +hostcmd ap_a2dptime +hostcmd ap_inquirytime + This command is used to configure the time slice of COEX (only works in timeshare mode) + generictime: configure the Bttime and Wlantime in Station Generic case + a2dptime: configure the Bttime and Wlantime in Station A2DP case + inquirytime: configure the Bttime and Wlantime in Station Inquiry case + ap_generictime: configure the Bttime and Wlantime in Ap Generic case + ap_a2dptime: configure the Bttime and Wlantime in Ap A2DP case + ap_inquirytime: configure the Bttime and Wlantime in Ap Inquiry case + + Usage: + mlanutl mlanX hostcmd config/robust_btc.conf generictime + mlanutl mlanX hostcmd config/robust_btc.conf a2dptime + mlanutl mlanX hostcmd config/robust_btc.conf inquirytim + mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime + mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime + mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime + +hostcmd subevent_get +hostcmd subevent_set + This command is used to get/set the configurations for event descriptor + interface command. + subsvent_get: get subscribed event parameters + subsvent_set: set subscribed event parameters + + Usage: + mlanutl mlanX hostcmd config/subevent.conf subevent_get + mlanutl mlanX hostcmd config/subevent.conf subevent_set + +hostcmd txpwrlimit_2g_cfg_set +hostcmd txpwrlimit_5g_cfg_set +hostcmd txpwrlimit_cfg_get + This command is used to set/get the configuration data of Tx power limitation. + Note: The configuration set should be issued when STA is disconnected. + + Usage: + mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get + mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set + mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set + +hostcmd txrate_cfg_get +hostcmd txrate_cfg_set_bg +hostcmd txrate_cfg_set_bgn + This command is used to set/get the transmit data rate. + + Usage: + mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get + mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg + mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn + +hostcmd generate_raw + This command is used to generate the raw data(hostcommand block) for + hostcommand in and write that to file + + Usage: + mlanutl mlanX hostcmd generate_raw + +hostcmd fwdump + This command is used to trigger firmware dump + + Usage: + mlanutl mlanX hostcmd fwdump + +hscfg + This command is used to configure the host sleep parameters. + + Usage: + mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]] + + This command takes one (condition), two (condition and GPIO#) or three + (condition, GPIO# and gap). If more than three parameters, it can set different or multiple features indicating by type(this is optional): + + If type=1, it will set indication gpio and its level. And the parameter format will be (condition, GPIO#,gap and type,ind_GPIO#) or + (condition, GPIO#, gap, type, ind_GPIO# and level). + + If type=2, it will set extend hscfg wakup method. And the parameter format will be (condition, GPIO#, gap, type, force_ignore, + use_ext_gap, ext_gap [gpio_wave]). gpio_wave parameter is optional and default value is 0(falling edge). Each bit of + event_force_ignore and event_use_ext_gap will be defined to one same event, and set one same event(same bit) in those two + parameters is not allowed. Set bit(s) in event_force_ignore means the event(s) will be forced ignore in firmware silently. + Set bit(s) in event_use_ext_gap mean the event(s) will use extend gap to inform host. Not set means not handle. + + If type=3, it will set hs_wakeup_interval. + + If no parameter provided, get is performed. + + The usages of parameters for "hscfg" are the same as that for "hssetpara" command. + +hssetpara + This command is used to set host sleep parameters. + + Usage: + mlanutl mlanX hssetpara condition [GPIO# [gap]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]] (optional)[type hs_wakeup_interval] + + This command takes one (condition), two (condition and GPIO#) or three + (condition, GPIO# and gap).If more than three parameters, it can set different or multiple features indicating by type and + the detailed usage is the same as hscfg above. + + where Condition is: + bit 0 = 1 -- broadcast data + bit 1 = 1 -- unicast data + bit 2 = 1 -- mac event + bit 3 = 1 -- multicast data + bit 6 = 1 -- Wakeup when mgmt frame received. + Bit 31 = 1 -- Don't wakeup when IPV6 packet received. + + The host sleep mode will be canceled if condition is set to -1. The default is 0x7. + + where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid + GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead). + The default is 0xff. + + where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff + for special setting (host acknowledge required) when GPIO is used to wakeup host. + The default is 200. + + The host sleep set except for cancellation will be blocked if host sleep is + already activated. + + where ind_GPIO# is the pin number of GPIO used to indicate wakeup source. The level on + this GPIO will indicate normal wakeup source or abnormal wakeup source. + + where level is used to set level(0/1) on ind_GPIO# pin for indication normal wakeup source. + The opposite level will indicate abnormal wakeup source. The default value is 0. + + where event_force_ignore is a bitmap,each bit represent one wakeup reason event. Set the bit means this + wakeup reason should be force ignored in firmware. Reset the bit means do not handle this reason. + + where event_use_ext_gap is a bitmap, each bit represent one wakeup reason event. Set the bit means this + wakeup reason should use ext_gap to indicate host. Reset the bit means do not handle this reason. + + where event_force_ignore and event_use_ext_gap have the same wakeup reason event definition of each bit: + bit 0 = 1 --Disconnect + bit 1 = 1 --GTK/iGTK rekey failure + bit 2 = 1 --Eapol + other bits --Reserved + They should not set both for one same wakeup reason. + + where ext_gap is the extend gap based on third parameter Gap. Only valid when use_ext_gap is used. + The total gap is (Gap + (x+1)*ext_gap). x means the bit number(start from 0) of this reason in use_ext_gap. + + where gpio_wave is used to set GPIO wave level for hscfg extend. 0 means falling edge, 1 means rising edge. + This parameter is optional and default value is 0. + + where hs_wakeup_interval is used to set host sleep wakeup interval and the type must set to 3 to indicate + this feature. And the value will round to the nearest multiple dtim*beacon_interval in fw. The unit is milliseconds. + + Examples: + mlanutl mlan0 hssetpara -1 : Cancel host sleep mode + mlanutl mlan0 hssetpara 3 : Broadcast and unicast data + Use GPIO and gap set previously + mlanutl mlan0 hssetpara 2 3 : Unicast data + Use GPIO 3 and gap set previously + mlanutl mlan0 hssetpara 2 1 0xa0 : Unicast data + Use GPIO 1 and gap 160 ms + mlanutl mlan0 hssetpara 2 0xff : Unicast data + Use interface (e.g. SDIO) + Use gap set previously + mlanutl mlan0 hssetpara 4 3 0xff : MAC event + Use GPIO 3 + Special host sleep mode + mlanutl mlan0 hssetpara 1 0xff 0xff : Broadcast data + + mlanutl mlan0 hssetpara 2 1 0xa0 1 5 1 : Unicast data + Use GPIO 1 + Gap 160 ms + type=1 to set indication GPIO feature + Use GPIO 5 to indicate wakeup source + High level on GPIO 5 means this is a normal wakeup + mlanutl mlan0 hssetpara 2 1 0xa0 1 5 : Unicast data + Use GPIO 1 + Gap 160 ms + type=1 to set indication GPIO feature + Use GPIO 5 to indicate wakeup source + Use level set previously. + + mlanutl mlan0 hssetpara 2 1 0xa0 2 0 0x1 10 1: Unicast data + Use GPIO 1 + Gap 160 ms + type=2 to set extend hscfg feature + Force_ignore not used + Disconnect will use extend gap to indicate host + Use gap 170. + Rising edge + mlanutl mlan0 hssetpara 2 1 0xa0 2 0x1 0 0 0: Unicast data + Use GPIO 1 + Gap 160 ms + type=2 to set extend hscfg feature + Falling edge + Force ignore Disconnect + Extend gap not used + Not used. + Falling edge + mlanutl mlan0 hssetpara 2 1 0xa0 3 400: Unicast data + Use GPIO 1 + Gap 160 ms + type=3 to set hs_wakeup_interval feature + hs_wakeup_interval set to 400ms + + Note: The parameters will be saved in the driver and be used when host suspends. + The ind_GPIO# and level parameters only work with specific board and firmware. + +mgmtfilter + This command is used to set management frame to wake up host when host suspend. + + Usage: + mlanutl mlanX mgmtfilter + + where + This conf file will set management frame catagory, action and frame mask. + + Examples: + mlanutl mlan0 mgmtfilter mgmtfilter.conf + +auto_arp + This command is used to enable/disable auto arp response in host sleep mode. + No argument is used to get. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 auto_arp 0 : Disable auto arp response from FW + mlanutl mlan0 auto_arp : Get auto arp configuration status + +htcapinfo + This command is used to configure some of parameters in HTCapInfo IE + (such as Short GI, Channel BW, and Green field support) + + where is + - This is a bitmap and should be used as following + Bit 29: Green field enable/disable + Bit 26: Rx STBC Support enable/disable. (As we support + single spatial stream only 1 bit is used for Rx STBC) + Bit 25: Tx STBC support enable/disable. + Bit 24: Short GI in 40 Mhz enable/disable + Bit 23: Short GI in 20 Mhz enable/disable + Bit 22: Rx LDPC enable/disable + Bit 17: 20/40 Mhz enable disable. + Bit 8: Enable/disable 40Mhz Intolarent bit in ht capinfo. + 0 will reset this bit and 1 will set this bit in + htcapinfo attached in assoc request. + All others are reserved and should be set to 0. + + Setting of any other bits will return error. + + where is + - This is the band info for settings. + 0: Settings for both 2.4G and 5G bands + 1: Settings for 2.4G band + 2: Settings for 5G band + + Example: + mlanutl mlanX htcapinfo + This will display HT capabilties information. + If the information for 2.4G and 5G is different, + the first value is for 2.4G and the second value is for 5G. + Otherwise, it will display a single value for both bands. + + mlanutl mlanX htcapinfo 0x1820000 + This will enable Short GI, Channel BW to 20/40 and disable Green field support for 2.4G and 5G band. + + mlanutl mlanX htcapinfo 0x800000 2 + This will enable Short GI, Channel BW to 20 only, No Rx STBC support and disable Green field support for 5G band. + + The default value is 0x4800000 for 2.4G and 0x5820000 for 5G. + + Note:- This command can be issued any time but it will only come to effect from + next association. (as HTCapInfo is sent only during Association). + +htstreamcfg + This command is used to set/get HT stream configuration. + The setting only takes effect in next association. + + Usage: + mlanutl mlanX htstreamcfg [n] + + where + 0x11: HT stream 1x1 mode + 0x22: HT stream 2x2 mode + + Examples: + mlanutl mlan0 htstreamcfg : Get current setting + mlanutl mlan0 htstreamcfg 0x11 : Set HT stream 1x1 mode + mlanutl mlan0 htstreamcfg 0x22 : Set HT stream 2x2 mode + +httxbfcap + This command is used to set/get the TX beamforming capabilities. + + Usage: + mlanutl mlanX httxbfcap [cap] + + where the parameters are, + cap: TX beamforming capabilities + Bit 0 : Implicit TX BF receiving capable + Bit 1 : RX staggered sounding capable + Bit 2 : TX staggered sounding capable + Bit 3 : RX NDP capable + Bit 4 : TX NDP capable + Bit 5 : Implicit TX BF capable + Bit 6-7 : Calibration + 0: - not supported + 1: - STA can respond to a calibration request using + the CSI Report, but cannot initiate calibration + 2: - reserved + 3: - STA can both initiate and respond to a calibration request + Bit 8 : Explicit CSI TX BF capable + Bit 9 : Explicit non-compressed steering capable + Bit 10 : Explicit compressed steering capable + Bit 11-12: Explicit TX BF CSI feedback + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 13-14: Explicit non-compressed BF feedback capable + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 15-16: Explicit compressed BF feedback capable + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 17-18: Minimal grouping + 0: - no grouping (STA supports groups of 1) + 1: - groups of 1, 2 + 2: - groups of 1, 4 + 3: - groups of 1, 2, 4 + Bit 19-20: CSI number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 21-22: Non-compressed steering number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 23-24: Compressed steering number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 25-26: CSI max number of rows beamformer supported + 0: - single row of CSI + 1: - 2 rows of CSI + 2: - 3 rows of CSI + 3: - 4 rows of CSI + Bit 27-28: Channel estimation capability + 0: - 1 space time stream + 1: - 2 space time streams + 2: - 3 space time streams + 3: - 4 space time streams + Bit 29-31: Reserved + + Examples: + mlanutl mlan0 httxbfcap : Get the current TX BF capabilities + mlanutl mlan0 httxbfcap 0x0000001F : Set the TX BF capabilities of the + Implicit TX BF receiving capable, + RX staggered sounding capable, + TX staggered sounding capable, + RX NDP capable and TX NDP capable + +httxbfcfg + This command is used to configure the TX beamforming options. + Note: Any new subcommand should be inserted in the second + argument and each argument of the sub command should be + separated by semicolon. For global configuration, the + arguments should be separated by space. + + Usage: + mlanutl mlanX httxbfcfg "[;GlobalData/tsData/interval/txPeerData/snrData/txSounding]" + + where the parameters are, + action: TX beamforming action + 0: Control global parameters for beamforming + 1: Performs NDP Sounding for PEER + 2: TX BF interval in milliseconds + 3: Enable/Disable beamforming/sounding for a particular peer + 4: TX BF SNR Threshold for peer + .. + 5: Get and set transmit sounding configuration + GlobalData: Global parameter arguments. + It contains beamforming enable, sounding enable, FB type, snr_threshold + sounding interval, Beamformig mode values seperated by space. + Syntax: + mlanutl mlanX httxbfcfg ; + + tsData: Trigger sounding for PEER specific arguments, + it contains PEER MAC and status + interval: TX BF interval in milliseconds + txPeerData: Enable/Disable beamforming/sounding for the indicated peer, + it contains PEER MAC, sounding, beamfoming options and FB type; + snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR + txSounding: the 1st parameter - enable/disable Tx sounding (enable: 1; disable: 0) + the 2nd parameter - sounding type (HT: 1; VHT: 2) + the 3rd parameter - sounding interval (ms, resoultion: 10 ms) + + Examples: + mlanutl mlan0 httxbfcfg "0" : Get current global configuration parameter + mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64" : Get the TX BF periodicity for a given peer + mlanutl mlan0 httxbfcfg "3" : Get the list of MAC addresses that have + beamforming and/or sounding enabled + mlanutl mlan0 httxbfcfg "4" : Get the list of PEER MAC, SNR tuples + programmed into the firmware. + mlanutl mlan0 httxbfcfg "0;0 0 3 10 500 5" : Disable beamforming, sounding, set FB type + to 3, snr threshold to 10, sounding interval + to 500 ms and beamforming mode to 5 + mlanutl mlan0 httxbfcfg "1;00:50:43:20:BF:64" : Perform NDP Trigger sounding to peer + 00:50:43:20:BF:64 + mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64;500" : Set TX BF periodicity for peer 00:50:43:20:BF:64 + to 500 milliseconds + mlanutl mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3" : Enable beamforming, disable sounding and set + FB type to 3 for peer 00:50:43:20:BF:43 + mlanutl mlan0 httxbfcfg "4;00:50:43:20:BF:24;43" : Set TX BF SNR threshold to peer + 00:50:43:20:BF:24 with SNR 43 + mlanutl mlan0 httxbfcfg "5;1 2 100" : Set TX Sounding: enable Tx Sounding, Sounding Type is VHT, and Sounding Interval is 100 ms. + +httxcfg + This command is used to configure various 11n specific configuration + for transmit (such as Short GI, Channel BW and Green field support) + + where is + This is a bitmap and should be used as following + Bit 15-10: Reserved set to 0 + Bit 9-8: Rx STBC set to 0x01 + BIT9 BIT8 Description + 0 0 No spatial streams + 0 1 One spatial streams supported + 1 0 Reserved + 1 1 Reserved + Bit 7: STBC enable/disable + Bit 6: Short GI in 40 Mhz enable/disable + Bit 5: Short GI in 20 Mhz enable/disable + Bit 4: Green field enable/disable + Bit 3-2: Reserved set to 1 + Bit 1: 20/40 Mhz enable disable. + Bit 0: LDPC enable/disable + + When Bit 1 is set then firmware could transmit in 20Mhz or 40Mhz based + on rate adaptation. When this bit is reset then firmware will only + transmit in 20Mhz. + + where is + - This is the band info for settings. + 0: Settings for both 2.4G and 5G bands + 1: Settings for 2.4G band + 2: Settings for 5G band + + Example: + mlanutl mlanX httxcfg + This will display HT Tx configuration for 2.4G and 5G band. + + mlanutl mlanX httxcfg 0x62 + This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band. + + mlanutl mlanX httxcfg 0x30 1 + This will enable Short GI 20 Mhz and Green field for 2.4G band. + + The default value is 0x20 for 2.4G and 0x62 for 5G. + + Note:- If 20/40 MHz support is disabled in htcapinfo, device will not transmit + in 40 MHz even 20/40 MHz is enabled in httxcfg. + +inactivityto + This command is used to set/get the inactivity timeout value, which specifies + when WLAN device is put to sleep. + + Usage: + mlanutl mlanX inactivityto [k] + + where the parameter are: + : timeout unit in microseconds. + : Inactivity timeout for unicast data. + : Inactivity timeout for multicast data. + [k]: Inactivity timeout for new Rx traffic after PS notification to AP. + + Examples: + mlanutl mlan0 inactivityto : Get the timeout value + mlanutl mlan0 inactivityto 1000 2 3 : Set timeout unit to 1000 us (1 ms), + inactivity timeout for unicast data is 2 ms, + inactivity timeout for multicast data is 3 ms + +ipaddr + This command is used to set/get IP address. + + Usage: + mlanutl mlanX ipaddr [";"] + + where + 0: Remove the IP address + bit 0: Set IP address for broadcast ARP filter, which will be auto enabled + in next host sleep configuration + bit 1: Set IP address for auto broadcast ARP response + + Examples: + mlanutl mlan0 ipaddr : Get current settings + mlanutl mlan0 ipaddr "0" : Remove IP address + mlanutl mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter + mlanutl mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter + : and auto ARP response + +linkstats + This command is used to get the link statistics from the firmware. + + Usage: + mlanutl mlanX linkstats + +listeninterval + This command is used to set/get listen interval in assoc request. + + Usage: + mlanutl mlanX listeninterval [l] + + where the parameter: + [l]: Value of listen interval [Default 10] + + Examples: + mlanutl mlan0 listeninterval : Display Listen interval + mlanutl mlan0 listeninterval 1 : Set Listen interval to 1. + +macctrl + This command is used to set/get MAC control. + It's recommended to read the current setting first to avoid override issue. + + Usage: + mlanutl mlanX macctrl [n] + + where + bit 0: Rx enabled + bit 1: Directed Filter enabled + bit 2: LoopBack enabled + bit 3: WEP enabled + bit 4: EthernetII enabled + bit 5: MultiCast enabled + bit 6: BroadCast enabled + bit 7: Promiscuous enabled + bit 8: All MultiCast enabled + bit 9: RTS/CTS enabled (0: CTS to self) + bit 10: Enforce Protection enabled + bit 11: Force 11N Protection enabled + bit 12: Rx 802.11 Packets enabled + bit 13: Ad-hoc g Protection enabled + bit 14: Reserved + bit 15: WEP Type + bit 16: BandWidth Indication in RTS enabled + bit 17: Dynamic BandWidth Indication Mode in RTS enabled + bit 18-31: Reserved + + Examples: + mlanutl mlan0 macctrl : Get current MAC control + mlanutl mlan0 macctrl 0x13 : Set Rx enabled and Directed Filter enabled and EthernetII enabled + mlanutl mlan0 macctrl 0x813 : Set Rx enabled and Directed Filter enabled and EthernetII enabled + Force 11N Protection enabled + +mefcfg + This command is used to set MEF settings. + + Usage: + mlanutl mlanX mefcfg + + Where the parameter is: + mef.conf : The configuration file specifying the MEF settings. + + Example: + mlanutl mlan0 mefcfg config/mef.conf + +memrdwr + This command is used to read/write the adapter memory. + + Usage: + mlanutl mlanX memrdwr

[value] + + where the parameters are, +
: memory address + [value]: value to be written + + Examples: + mlanutl mlan0 memrdwr 0x4cf70 : Read memory address 0x4cf70 + mlanutl mlan0 memrdwr 0x80000000 0xffffffff + : Write 0xffffffff to memory address 0x80000000 + +miracastcfg + This command is used to set/get the miracast configuration. + + Usage: + mlanutl mlanX miracastcfg [l] [m] [n] + + where the parameters are, + [l]: miracast mode + 0: Disable + 1: Source + 2: Sink + [m]: scan time per channel, in ms + [n]: gap during two scans, in ms + + Examples: + mlanutl mlan0 miracastcfg : Get miracast configuration + mlanutl mlan0 miracastcfg 0 : Disable miracast configuration + mlanutl mlan0 miracastcfg 1 20 40 : Set miracast mode as source, with scan time + 20ms per channel and gap during two scans 40ms + +mgmtframectrl + This command is used to set/get registered frame type to passthrough. + + Usage: + mlanutl mlanX mgmtframectrl [] + mlanutl uapX mgmtframectrl [] + + Where the parameter is: + : the bit mask of management frame reception. + : Bit 0 - Association Request + : Bit 1 - Association Response + : Bit 2 - Re-Association Request + : Bit 3 - Re-Association Response + : Bit 4 - Probe Request + : Bit 5 - Probe Response + : Bit 8 - Beacon Frames + + Examples: + mlanutl mlan0 mgmtframectrl : Get present mask + mlanutl mlan0 mgmtframectrl 0x0020 : Bit 5 is set, Forward probe response frames to application layer + +mgmtframetx + This command is used to send management frame. + + Usage: + mlanutl mlanX mgmtframetx + + Where the parameter is: + mgmt_frame.conf : The configuration file contains the management frame. + + Examples: + mlanutl mlan0 mgmtframetx config/mgmt_frame.conf + +netmon + This command is used to set/get sniffer mode configuration. + Note: The channel and band config is optional. If not specified, or if + any STA/uAP/STA+uAP connection is active, sniffer activity will be started + on the current config set in the FW. + 'rtap' monitor interface will be created on enabling sniffer activity and + should be made 'up' for capturing in a sniffer app. + + Usage: + mlanutl netmon [ []] + mlanutl mlanX netmon [ [] [ [offset]]] + + Where the parameters are: + : mlanX, uapX + : (0) disable sniffer activity + : (1) enable sniffer activity + + : network monitor fitler flag + bit 0: (1/0) enable/disable management frame + bit 1: (1/0) enable/disable control frame + bit 2: (1/0) enable/disable data frame + bit 3: (1/0) enable/disable frames destined to active connection only + bit 4: (1/0) enable/disable decrypted unicast data/mgmt frames + + : 802.11 band + bit 0: B + bit 1: G + bit 2: A + bit 3: GN + bit 4: AN + bit 5: AC 2.4G + bit 6: AC 5G + : channel to monitor + + [offset] : secondary channel bandwidth + 0 - Bandwidth 20Mhz + 1 - HT Bandwidth 40Mhz sec channel above + 3 - HT Bandwidth 40Mhz sec channel below + 4 - VHT Bandwidth 80Mhz + + Examples: + mlanutl mlan0 netmon : Get the current sniffer mode configuration + mlanutl mlan0 netmon 0 : Disable network monitor activity + mlanutl uap0 netmon 1 7 : Enable sniffer activity on current channel set in FW, + set filter data, control, management frame. + mlanutl mlan0 netmon 1 4 11 6 : Enable sniffer activity in absence of active connection, + set filter data frame, band B/G/GN and channel 6 + mlanutl mlan0 netmon 1 7 20 64 1 : Enable sniffer activity in absence of active connection + set filter management, control and data frame, band A/AN, + channel 64 and secondary channel above + mlanutl uap0 netmon 1 0x0c : Enable sniffer activity, set filter data frames + destined to the active uAP connection only + + mlanutl mlan0 netmon 1 0x1d : Enable sniffer activity, set filter decrypted data and + management frames destined to the active STA connection + only + +offchannel + This command is used to set/cancel the offchannel configuration. + Note: This command only can be used when cfg80211 is enabled during load time. + + Usage: + mlanutl mlanX offchannel [ ] + + where + + 0 : Cancel the offchannel configuration + 1 : Set the offchannel configuration + + The channel to configure + + The duration for which to configure + : channel bandwidth + 0 - Bandwidth 20Mhz + 1 - HT Bandwidth 40Mhz sec channel above + 3 - HT Bandwidth 40Mhz sec channel below + 4 - VHT Bandwidth 80Mhz + + Examples: + mlanutl mlan0 offchannel : Get current offchannel status. + mlanutl mlan0 offchannel 0 : Cancel the offchannel configuration. + mlanutl mlan0 offchannel 1 3 5 : Configure channel 3 for 5 milliseconds. + mlanutl mlan0 offchannel 1 36 5000 : Configure channel 36 for 5000 milliseconds. + mlanutl mlan0 offchannel 1 64 500 4 : Configure channel 64 in 80MHz for 500 + milliseconds. + +otpuserdata + This command is used to get the OTP user data. + + Where + is + - This parameter specifies the length of OTP user data to be read + + Examples: + mlanutl mlan0 otpuserdata 10 : Get the 10-byte OTP user data + +passphrase + This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode. + + Where + ASCII string for ssid/passphrase/psk. + + 1) "0;" - This will get the passphrase, AKMP + for specified ssid, if none specified then it will get all. + + Example: + mlanutl mlan0 passphrase "0;ssid=marvell" + + 2) "1;; + " - Passphrase and psk cannot be provided for the same SSID. + This command takes only one SSID at a time, If ssid= is present it should contain + a passphrase or psk. If no arguments are provided then AKMP=802.1x, and passphrase + should be provided after association. + End of each parameter should be followed by a ';'(except for the last parameter) + as the delimiter. If ';' or '/' has to be used in an SSID then a '/' should be preceded + to ';' or '/' as a escape. + + Examples: + mlanutl mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd" + mlanutl mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>" + + If user wants to input the ssid as "mrvl; AP" then command has to be + mlanutl mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh" + + If user wants to input the ssid as "//;" then command has to be + mlanutl mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh" + + 3) "2;" - This will clear the passphrase + for specified ssid, if none specified then it will clear all. + + Examples: + mlanutl mlan0 passphrase "2;ssid=marvell" + mlanutl mlan0 passphrase "2" : Clear all profiles and disable embedded supplicant + +pb_bypass + This command is used to get the By-passed TX packet from upper layer. + + Usage: + + mlanutl mlanX pb_bypass [data_1, data_2, ... data_n] + + where value of data_1, data_2, ... data_n isBypass TX Data + +pcieregrw + This command is used to read/write PCIE register. + + Usage: + mlanutl mlanX pcieregrw [value] + + where the parameters are, + : The offset of PCIE register + [value]: The value to write + + Examples: + mlanutl mlan0 pcieregrw 0x48 : Read PCIE register 0x48 + mlanutl mlan0 pcieregrw 0x44 8 : Write 8 to PCIE register 0x44 + +pciebar0regrw + This command is used to read/write PCIE register/memory from BAR0. + + Usage: + mlanutl mlanX pciebar0regrw [value] + + where the parameters are, + : The offset of PCIE register + [value]: The value to write + + Examples: + mlanutl mlan0 pciebar0regrw 0x48 : Read PCIE register 0x48 + mlanutl mlan0 pciebar0regrw 0x44 8 : Write 8 to PCIE register 0x44 + +pmfcfg + This command is used to set/get management frame protection parameters. + + Usage: + mlanutl mlanX pmfcfg + + where + : Management Frame Protection Capable (MFPC) + 1: Management Frame Protection Capable + 0: Management Frame Protection not Capable + : Management Frame Protection Required (MFPR) + 1: Management Frame Protection Required + 0: Management Frame Protection Optional + Default setting is PMF not capable. + m = 0, n = 1 is an invalid combination + + Examples: + mlanutl mlan0 pmfcfg : Get PMF parameters + mlanutl mlan0 pmfcfg 1 0 : Set MFPC and make MFPR optional + +port_ctrl + This command is used to Set/Get Port Control mode. No argument is used to get. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 port_ctrl 1 : Enable Port Control mode + mlanutl mlan0 port_ctrl : Get Port Control mode status + +powercons + This command is used to set the local transmit power constraint. + Value is in dbm unit. This command is only used for ad-hoc start. + + Usage: + mlanutl mlanX powercons [n] + + Examples: + mlanutl mlanX powercons : get the current setting + mlanutl mlanX powercons 12 : set local power constraint to 12 dbm + +pscfg + This command is used to set/get PS configuration parameters. + + Usage: + mlanutl mlanX pscfg [k] [d] [l] ... + + Where the parameters: + [k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds) + [d]: DTIM interval ( 0: Unchanged, + 1-5: Value, + 65534: DTIM will be ignored, listen interval will be used, + 65533: Closest DTIM to the listen interval period will be used ) + [l]: Local listen interval ( 0: Unchanged, + -1: Disable, + 1-49: Value in beacon intervals, + >= 50: Value in TUs ) + [b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable) + [p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms) + [m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode) + No change if parameters are not provided. + + Examples: + mlanutl mlan0 pscfg : Get all the current PS configuration settings + mlanutl mlan0 pscfg 3 4 : Set PS keep alive null packet interval to 3 seconds + and DTIM interval to 4, all the other configurations + are unchanged + mlanutl mlan0 pscfg 0 0 0 0 50 2 : Set delay to PS to 50 ms and PS mode to PS-Poll mode, + keep the others unchanged + +bcntimeoutcfg + This command is used to set Beacon timeout parameters. + + Usage: + mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p] + + Where the parameters: + [l]: Beacon miss timeout period Rx window (in ms) + [m]: Beacon miss timeout period (unit in beacon interval) + [o]: Beacon reacquire timeout period Rx window (unit in beacon interval) + [p]: Beacon reacquire timeout period (unit in beacon interval) + Please note that it would be better [m]+[p] not exceed 64. + Examples: + mlanutl mlan0 bcntimeoutcfg 10 30 2 30 : Set beacon timeout configure to + Beacon miss timeout period Rx window : 10 (ms) + Beacon miss timeout period : 30 (Beacon Interval) + Beacon reacquire timeout period Rx window : 2 (Beacon Interval) + Beacon reacquire timeout period : 30 (Beacon Interval) + +psmode + This command is used to set/get the IEEE PS mode configuration. + + Usage: + mlanutl mlanX psmode [l] + + where the parameter: + [l] + 0 : Disable IEEE PS mode + 1 : Enable IEEE PS mode + : Get IEEE PS mode + + Examples: + mlanutl mlan0 psmode : Get IEEE PS mode. + mlanutl mlan0 psmode 1 : Enable IEEE PS mode. + +qconfig + Send a WMM AC Queue configuration command to get/set/default params + + Configure or get the parameters of a WMM AC queue. The command takes + an optional Queue Id as a last parameter. Without the queue id, all + queues will be acted upon. + + Usage: + mlanutl mlanX qconfig def [Queue Id: 0-3] + mlanutl mlanX qconfig get [Queue Id: 0-3] + mlanutl mlanX qconfig set msdu [Queue Id: 0-3] + +qoscfg + This command sets WMM IE QOS info when an argument is given, and gets current WMM + IE QOS info when no argument is given. + + Examples: + mlanutl mlanX qoscfg 0x0f : Set WMM IE QOS info to 0x0f + mlanutl mlanX qoscfg : Get WMM IE QOS info + +qstatus + This command retrieves the current status of the WMM queues. If WMM + is enabled then it displays the information for each AC in a table. + + Usage: + mlanutl mlanX qstatus + +radioctrl + This command is used to turn on/off the radio. + Note: The radio can be disabled only in disconnected state. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 radioctrl 1 : Turn the radio on + mlanutl mlan0 radioctrl : Get radio status + +rdeeprom + This command is used to read the EEPROM contents of the card. + + Usage: + mlanutl mlanX rdeeprom + + where the parameters are, + : multiples of 4 + : 4-20, multiples of 4 + + Example: + mlanutl mlan0 rdeeprom 0 20 : Read 20 bytes of EEPROM data from offset 0 + +reassoctrl + This command is used to turn on/off re-association in driver. + + Usage: + mlanutl mlanX reassoctrl [n] + + Where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 reassoctrl : Get re-association status + mlanutl mlan0 reassoctrl 1 : Turn re-association on + +regioncode + This command is used to set/get the region code in the station. + Note: This command should be issued at beginning before band/channel selection + and association. + + where value is 'region code' for various regions like + USA FCC, Canada IC, Europe ETSI, Japan ... + The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode. + + Examples: + mlanutl mlan0 regioncode : Get region code + mlanutl mlan0 regioncode 0x10 : Set region code to USA (0x10) + Note : in some case regioncode will be 0 after updated countycode or 80211d + i.e. mlanutl mlanX countrycode (CA, JP, CN, DE, ES AT, BR, RU) + or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU) + Please use cfp instead of it. + +regrdwr + This command is used to read/write the adapter register. + + Usage: + mlanutl mlanX regrdwr [value] + + where the parameters are, + : 1:MAC/SOC, 2:BBP, 3:RF, 5:CAU, 6:PSU + : offset of register + [value]: value to be written + Note: + BBP reg (type 2) 0xXZZZ: + X: 0=BBUD, 8=BBUA. + ZZZ: offset (0-0xFFF). + RF reg (type 3) 0xXYZZ: + X = Path ID (0-1) + Y = Page Number (0-6) in selected Path + ZZ = Register offset in selected path/page + + Examples: + mlanutl mlan0 regrdwr 1 0xa060 : Read the MAC register + mlanutl mlan0 regrdwr 1 0xa794 0x80000000 + : Write 0x80000000 to MAC register + +rejectaddbareq + This command is used to set/get the conditions of rejecting addba request. + + Usage: + mlanutl mlanX rejectaddbareq [conditions] + mlanutl uapX rejectaddbareq [conditions] + + Where conditions are: + bit 0 = 1 -- reject the addba request when host sleep activated + others -- reserved + + Examples: + mlanutl mlan0 rejectaddbareq : Get the reject addba request conditions + mlanutl mlan0 rejectaddbareq 0x1 : Reject the addba request + when host sleep activated + mlanutl uap0 rejectaddbareq 0x1 : Reject the addba request + when host sleep activated + +scancfg + This command is used to set/get scan configuration parameters. + + Usage: + mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [c] [ext] + + where the parameters: + [t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active) + [m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any) + [p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4) + [s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms) + [a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms) + [b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms) + + [c]: Passive to Active Scan (0: Unchanged, 1: Enable, 2: Disable, default Enable) + [c]: Passive to Active Scan (0: Unchanged, 1: Enable, 2: Disable, default Disable) + + [ext]: Extended scan (0: Unchanged, 1: Legacy scan, 2: Extended scan, 3: Extended scan enhance) + No change if the parameter is 0 or the parameter is not provided. + + Examples: + mlanutl mlan0 scancfg : Get all the current scan configuration settings + mlanutl mlan0 scancfg 1 3 : Set scan type to active and scan mode to any, + all the other scan configurations are unchanged + mlanutl mlan0 scancfg 0 1 2 200 : Set scan mode to BSS, number of probes to 2 and + specific scan time to 200 ms, all the other scan + configurations are unchanged + mlanutl mlan0 scancfg 0 0 0 0 0 0 1 : Set Passive to Active Scan to enable, all the + other scan configurations are unchanged + mlanutl mlan0 scancfg 2 0 0 0 0 0 2 : Set scan type to passive, Passive to Active + Scan to disable, all the other scan configurations + are unchanged + +setuserscan + Initiate a customized scan and retrieve the results + + Usage: + mlanutl mlanX setuserscan [ARGS] + + Where [ARGS]: + ssid="[SSID]" specify a SSID filter for the scan + chan=[chan#][band][mode] where band is [a,b,g,n] and mode is + blank for unchange, or 'c' for active or 'p' for passive + bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan + wc="[WILDCARD SSID]" specify a UNIX pattern matching filter (using * + and ?) for SSIDs found in a broadcast probe + keep=[0 or 1] keep the previous scan results (1), discard (0) + dur=[scan time] time to scan for each channel in milliseconds + gap=[gap time] Time gap between two scans in milliseconds + probes=[#] number of probe requests to send on each chan + for each broadcast probe required and each SSID + specific probe required (1-4) + bss_type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any) + sort_by_ch Sort by channel number in ascending order. + Default mode: Sort by Signal Strength in descending order. + scan_type=[0,1] ext scan type (0-1) 0: legacy, 1: enhance scan + + Any combination of the above arguments can be supplied on the command line. + If the chan token is absent, a full channel scan will be completed by driver. + If the dur or probes tokens are absent, the driver default setting will be + used. The bssid and ssid fields, if blank, will produce an unfiltered scan. + It's allowed to input multiple ssid/wc entries, the max entry number is 10. + The type field will default to 3 (Any) and the keep field will default to 0 + (Discard). + + Examples: + 1) Perform an active scan on channels 1, 6, and 11 in the 'g' band: + setuserscan chan=1g,6g,11g + + 2) Perform a passive scan on channel 11 for 20 ms: + setuserscan chan=11gp dur=20 + + 3) Perform an active scan on channels 1, 6, and 11; and a passive scan on + channel 36 in the 'a' band: + setuserscan chan=1g,6g,11g,36ap + + 4) Perform an active scan on channel 6 and 36 for specific SSID: + setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2 + + 5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep + the current scan table intact, update existing or append new scan data: + setuserscan bssid=00:50:43:20:12:82 keep=1 + + 6) Scan channel 6, for all infrastructure networks, sending two probe + requests. Keep the previous scan table intact. Update any duplicate + BSSID/SSID matches with the new scan data: + setuserscan chan=6g bss_type=1 probes=2 keep=1 + + 7) Scan channel 1 and 6, for all networks matching the Mrvl*AP + or AP*Mrvl? patterns and for MrvlTst SSID. Generate 3 broadcast + probes for the patterns and 3 SSID specific probes for MrvlTst on + both channel 1 and channel 6. + setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst" + + 8) Scan all the channels for specified band. + setuserscan chan=0g + + 9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms + with time gap of 50ms between 2 scans + setuserscan chan=1g,6g probes=3 dur=40 gap=50 + + 10) Perform an enhance scan + setuserscan scan_type=1 + + All entries in the scan table (not just the new scan data when keep=1) + will be displayed upon completion by use of the getscantable ioctl. +cancelscan + This command is used to cancel scan + Usage: + mlanutl mlanX cancelscan +sleepparams + This command is used to set the sleepclock configurations + + Usage: + mlanutl mlanX sleepparams [ ] + + where: + p1 is Sleep clock error in ppm (0-65535) + p2 is Wakeup offset in usec (0-65535) + p3 is Clock stabilization time in usec (0-65535) + p4 is Control periodic calibration (0-2) + p5 is Control the use of external sleep clock (0-2) + p6 is reserved for debug (0-65535) + + Examples: + mlanutl mlan0 sleepparams : Get current sleepclock configuration + mlanutl mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration + +sleeppd + This command is used to configure the sleep period of the WLAN device. + + Usage: + mlanutl mlanX sleeppd [] + + Where the parameter is: + period: sleep period in milliseconds. Range 10~60. 0 for disable. + + Examples: + mlanutl mlan0 sleeppd : Get sleep period configuration + mlanutl mlan0 sleeppd 10 : Set sleep period to 10 ms + +sysclock + This command is used to set/get system clocks in MHz. + The current system clock, configurable system clocks and all of the + supported system clocks will be returned if no parameter provided. + + Examples: + mlanutl mlan0 sysclock : Get system clocks + 80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ... + (The current system clock is 80 MHz. + The configurable system clocks of non-security, security, non-security + A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz. + The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz, + 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different + for different chips, you could use this command to get the supported system clock) + + mlanutl mlanX sysclock 80 : Set system clock in non-security mode + to 80 MHz, no change for others + mlanutl mlanX sysclock 0 0 128 : Set system clock in non-security A-MPDU + mode to 128 MHz, no changes for others + +host_tdls_config + This command is used to support channel switch and uapsd for host based tdls + + Usage: + mlanutl mlanX host_tdls_config + + + Where the parameter is: + host_tdls.conf: The configuration file specifying to enable/disable uapsd/cs and related parameters. + + Examples: + mlanutl mlan0 host_tdls_config config/host_tdls.conf + : enable or disable uapsd/cs, config the channel related ie, based on the configuration file. +tdls_channel_switch + This command is used to send TDLS channel switch request. + + Usage: + mlanutl mlanX tdls_channel_switch + + Where the parameter is: + tdls.conf: The configuration file for sending TDLS channel switch command. + + Examples: + mlanutl mlan0 tdls_channel_switch config/tdls.conf + : Send TDLS channel switch command, based on the configuration file. + +tdls_config + This command is used to enable/disable TDLS on device. + + Usage: + mlanutl mlanX tdls_config <0/1> + + Where the parameter is: + 0: Enable TDLS. + 1: Disable TDLS. + + Examples: + mlanutl mlan0 tdls_config 0 : Disable TDLS + mlanutl mlan0 tdls_config 1 : Enable TDLS + +tdls_cs_params + This command is used to set TDLS channel switch params + + Usage: + mlanutl mlanX tdls_cs_params + + Where the parameter is: + tdls.conf: The configuration file specifying the TDLS channel switch params. + + Examples: + mlanutl mlan0 tdls_cs_params config/tdls.conf + : Set TDLS channel switch params, based on the configuration file. + +tdls_debug + This command is used for FW debug functionality and tests. + +tdls_disable_cs + This command is used to disable TDLS channel switch + + Usage: + mlanutl mlanX tdls_disable_cs + + Where the parameter is: + tdls.conf: The configuration file to disable TDLS channel switch. + + Examples: + mlanutl mlan0 tdls_disable_cs config/tdls.conf + : Disable TDLS channel switch, based on the configuration file. + +tdls_discovery + This command is used to request TDLS discovery. + + Usage: + mlanutl mlanX tdls_discovery + + Where the parameter is: + tdls.conf: The configuration file to request TDLS discovery. + + Examples: + mlanutl mlan0 tdls_discovery config/tdls.conf + : Request TDLS discovery based on the configuration file. + +tdls_link_status [peer_mac_address] + This command is used to get link information about TDLS links or + a TDLS link correponding to peer mac address. + + Usage: + mlanutl mlanX tdls_link_status + + Where the parameter is: + tdls.conf: The configuration file to send TDLS command to get current link status. + + Examples: + mlanutl mlan0 tdls_link_status config/tdls.conf + : Send TDLS command to get current link status based on the configuration file. + +tdls_powermode + This command is used to send TDLS powermode request. + + Usage: + mlanutl mlanX tdls_powermode + + Where the parameter is: + tdls.conf: The configuration file for sending TDLS powermode command. + + Examples: + mlanutl mlan0 tdls_powermode config/tdls.conf + : Send TDLS powermode (either 0:Active, 1:PowerSave) command, based on the configuration file. + +tdls_setinfo + This command is used for setting the capabilities of the TDLS station. + + Usage: + mlanutl mlanX tdls_setinfo + + Where the parameter is: + tdls.conf: The configuration file specifying the capabilities of the TDLS station. + + Examples: + mlanutl mlan0 tdls_setinfo config/tdls.conf + : Set capabilities of the TDLS station, based on the configuration file. + +tdls_setup + This command is used to send TDLS setup request. + + Usage: + mlanutl mlanX tdls_setup + + Where the parameter is: + tdls.conf: The configuration file for sending TDLS setup request. + + Examples: + mlanutl mlan0 tdls_setup config/tdls.conf + : Send TDLS setup request, based on the configuration file. + +tdls_stop_channel_switch + This command is used to send stop TDLS channel switch request. + + Usage: + mlanutl mlanX tdls_stop_channel_switch + + Where the parameter is: + tdls.conf: The configuration file for sending stop TDLS channel switch command. + + Examples: + mlanutl mlan0 tdls_stop_channel_switch config/tdls.conf + : Send stop TDLS channel switch command, based on the configuration file. + +tdls_teardown + This command is used to send TDLS teardown request. + + Usage: + mlanutl mlanX tdls_teardown + + Where the parameter is: + tdls.conf: The configuration file for requesting teardown of TDLS link. + + Examples: + mlanutl mlan0 tdls_teardown config/tdls.conf + : Request teardown of TDLS link, based on the configuration file. + +ts_status + This command queries the FW for the status of TSIDs 0 through 7 + configured via call admission control and displays the results in a + table. + + Usage: + mlanutl mlanX ts_status + +tsf + Get the TSF timer value for the station. Station maintains a TSF timer with + modulus 2^64 counting in increments of microseconds. + + Usage: + mlanutl mlanX tsf + +txaggrctrl + This command is used to enable/disable TX AMPDU on infra link when TDLS link is established + + Usage: + mlanutl mlanX txaggrctrl [m] + + Where: + [m]: 1 to enable TX AMPDU on infra link; 0 to disable TX AMPDU on infra link + + Examples: + mlanutl mlan0 txaggrctrl : Get current TX AMPDU status on infra link + mlanutl mlan0 txaggrctrl 0 : Disable TX AMPDU on infra link + mlanutl mlan0 txaggrctrl 1 : Enable TX AMPDU on infra link + + Note: + The set command only works when TDLS link is established. + +txbufcfg + This command can be used to get current buffer size. + + eg: + mlanutl mlanX txbufcfg - This will display the current buffer size. + + Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size. + +txratecfg + This command is used to set/get the transmit data rate. + + Note: + 1) The data rate can be set only after association. + + 2) If the reassoc is OFF driver reset the data rate to auto if the connection state is disconnected. + Please note that user has to re-issue the set data rate command if the driver is disconnected. + + 3) If the reassoc is ON driver remembers the data rate set by the user, if the driver is + disconnected user does not have to re-issue the set data rate again. + + Where + [l] is + - This parameter specifies the data rate format used in this command + 0: LG + 1: HT + 2: VHT + 0xff: Auto + + [m] is + - This parameter specifies the rate or MCS index + If is 0 (LG), + 0 1 Mbps + 1 2 Mbps + 2 5.5 Mbps + 3 11 Mbps + 4 6 Mbps + 5 9 Mbps + 6 12 Mbps + 7 18 Mbps + 8 24 Mbps + 9 36 Mbps + 10 48 Mbps + 11 54 Mbps + If is 1 (HT), + 0 MCS0 + 1 MCS1 + 2 MCS2 + 3 MCS3 + 4 MCS4 + 5 MCS5 + 6 MCS6 + 7 MCS7 + 8 MCS8 + 9 MCS9 + 10 MCS10 + 11 MCS11 + 12 MCS12 + 13 MCS13 + 14 MCS14 + 15 MCS15 + If is 2 (VHT), + 0 MCS0 + 1 MCS1 + 2 MCS2 + 3 MCS3 + 4 MCS4 + 5 MCS5 + 6 MCS6 + 7 MCS7 + 8 MCS8 + 9 MCS9 + [n] is + - This parameter specifies the NSS. It is valid only for VHT + If is 2 (VHT), + 1 NSS1 + 2 NSS2 + + Examples: + mlanutl mlan0 txratecfg : Read the current data rate setting + mlanutl mlan0 txratecfg 0 3 : Set fixed Tx rate to 11 Mbps + mlanutl mlan0 txratecfg 0 11 : Set fixed Tx rate to 54 Mbps + mlanutl mlan0 txratecfg 1 3 : Set fixed Tx rate to MCS3 + mlanutl mlan0 txratecfg 2 3 2 : Set fixed Tx rate to MCS3 for NSS2 + mlanutl mlan0 txratecfg 0xff : Disable fixed rate and uses auto rate + +verext + Retrieve and display an extended version string from the firmware + + Usage: + mlanutl mlanX verext [#] + + where [#] is an optional argument to retrieve a specific version string, + omission of the argument retrieves the 0 indexed string. + +version + This is used to get the current version of the driver and the firmware. + +vhtcfg + This command is used to set and get various 11ac specific configuration + for transmission and reception. For the SET operation, all paramaters + may be applied. For the GET operation, only the first two parameters are applied. + The 6th argument "rx_mcs_set" can be used to disbale/enable 802.11ac. + + where is + - This is the band setting for the vhtcfg + 0: Settings for both 2.4G and 5G bands (for SET operation, 11N BW only) + 1: Settings for 2.4G band (for 11N BW only) + 2: Settings for 5G band + + where is + - This parameter specifies the configuration of VHT operation for TX or/and VHT capabilities + 0: Unspecified + 1: configuration of VHT capabilities for Tx operations (STA only) + 2: configuration of VHT capabilities for association (STA only) + 3: configuration of VHT capabilities (uAP only) + Note: For the STA, the VHT capabilities configuration is applied in association, + whereas the VHT operations configuration is actually used in Tx. + + where [l] is + - This parameter specifies the bandwidth (BW) configuration + applied to the vhtcfg. + If is 1/3 (Tx operations), + 0: Tx BW follows the BW (20/40 MHz) from 11N CFG + 1: Tx BW follows the BW (80/160/80+80 MHz) from VHT Capabilities + defined in below for 5G band. + If is 2 (association), + 0: Rx BW follows the BW (20/40 MHz) from 11N CFG + 1: Rx BW follows the BW (80/160/80+80 MHz) from VHT Capabilities + defined in below for 5G band. + + where [m] is + - This parameter specifies the VHT capabilities info if is 2 (association) + or the VHT Tx operations if is 1 (Tx operations). + The VHT Tx operation should be a subset of VHT capabilities for association. + It is a bitmap and should be used as follows: + + Bit 31-30: Reserved and set to 0 + Bit 29: TX antenna pattern consistency + 1: antenna pattern does not change + 0: antenna pattern might change + Bit 28: RX antenna pattern consistency + 1: antenna pattern does not change + 0: antenna pattern might change + Bit 27-26: VHT link adaptation capable + 0: no feedback of VHT MFB from the STA + 1: unsolicted feedback of VHT MFB from the STA + 2: both response and unsolicted feedback of VHT MFB + from the STA + 3: reserved and set to 0 + Bit 25-23: Maximum A-MPDU length exponent + Bit 22: +HTC-VHT capable (1: enable. 0 disable) + Bit 21: VHT TXOP PS + Bit 20: MU beamformee capable (1: enable. 0 disable) + Bit 19: MU beamformer capable (1: enable. 0 disable) + Bit 18-16: Number of sounding dimensions (set to maximum-1 + if Bit 11 is 1. Otherwise, reserved and set to 0) + Bit 15-13: Compressed steering number of beamformer + antennas supported (set to maximum-1 if Bit 12 is 1. + Otherwise, reserved and set to 0) + Bit 12: SU beamformee capable (1: enable. 0 disable) + Bit 11: SU beamformer capable (1: enable. 0 disable) + Bit 10-8: Rx STBC + 0: no support + 1: support of 1 spatial stream + 2: support of 1-2 streams + 3: support of 1-3 spatial streams + 4: support of 1-4 spatial streams + 5-7: reserved and set to 0 + Bit 7: TX STBC (1: enable. 0 disable) + Bit 6: Short GI for 160 and 80+80 MHz (1: enable. 0 disable) + Bit 5: Short GI for 80 MHz (1: enable. 0 disable) + Bit 4: Rx LDPC (1: enable. 0 disable) + Bit 3-2: Supported channel width set. + 0: no support of either 160 or 80+80 MHz. + 1: support of 160 MHz + 2: support of both 160 and 80+80 MHz. + 3: reserved and set to 0. + Bit 1-0: Maximum MPDU length + 0: 3895 octets. + 1: 7991 octets. + 2: 11454 octets. + 3: reserved and set to 0. + + Note: for the STA, if is 1 (Tx operations), the bitmap for may be simplied as follows: + Bit 31-8: Reserved and set to 0 + Bit 7: Tx STBC (1: enable. 0 disable) + Bit 6: Reserved and set to 0 + Bit 5: Short GI for 80 Mhz (1: enable. 0 disable) + Bit 4: LDPC (1: enable. 0 disable) + Bit 3-0: Reserved and set to 0 + + where [n] is , + - This parameter specifies the TX MCS map. It may not be used for the STA if is 1 (Tx operations). + It is a bitmap and should be used as following + Bit 15-0: MCS map, which is defined as folows: + Bit 15-14: Max MCS for 8 SS + Bit 13-12: Max MCS for 7 SS + Bit 11-10: Max MCS for 6 SS + Bit 9-8: Max MCS for 5 SS + Bit 7-6: Max MCS for 4 SS + Bit 5-4: Max MCS for 3 SS + Bit 3-2: Max MCS for 2 SS + Bit 1-0: Max MCS for 1 SS + + where [o] is . + - This parameter specifies the RX MCS map. It may not be used for the STA if is 1 (Tx operations). + It is a bitmap with the same sructure as for + rx_mcs_map = 0xffff : FW will disable 802.11ac + rx_mcs_map = others : FW will enable 802.11ac + + Note: The user setting of vhtcap may be overwritten by the driver + if the setting of those fields is beyond the hardware capabilities. + + Examples: + mlanutl mlan0 vhtcfg 2 1 : Get current VHT configuration in 5GHz for the STA. + mlanutl mlan0 vhtcfg 2 2 : Get maximum VHT configuration in 5GHz for the STA. + mlanutl mlan0 vhtcfg 2 1 1 0x000001f0 + : Set the Tx operations configuration in 5GHz for the STA, + Tx BW follows the VHT Capabilities. + mlanutl mlan0 vhtcfg 2 2 0 0x000001f0 0xfff5 0xfffa + : Set the VHT capabilities configuration in 5GHz for the STA, + the Tx supports MCS 0-8 for both 1 and 2 spatial streams, + while the Rx supports MCS 0-9 for both 1 and 2 spatial streams. + mlanutl uap0 vhtcfg 2 3 0 0x000001f0 0xfffa 0xfffa + : Set the current/maximum VHT configuration in 5GHz for the uAP. + Both Tx and Rx supports MCS 0-9 for both 1 and 2 spatial streams. + mlanutl uap0 vhtcfg 2 3 0 0x000001b0 + : Set the VHT capability information in 5GHz for the uAP, and keep the Tx/Rx MCS Map same as before. + +opermodecfg + This command is used to set and get 11ac Operating Mode Notification configuration. + + where is + - This is the channel width setting for the opermodecfg + 1: 20MHz + 2: 40MHz + 3: 80MHz + 4: 160MHz or 80+80MHz + + where is + - This parameter specifies the nss that the STA can receive. + 1: NSS1 + 2: NSS2 + 3: NSS3 + 4: NSS4 + 5: NSS5 + 6: NSS6 + 7: NSS7 + 8: NSS8 + +wakeupreason + This command is used to get the host sleep wakeup reason. + + Usage: + mlanutl mlanX wakeupreason + mlanutl uapX wakeupreason + Examples: + mlanutl mlan0 wakeupreason : Get the host sleep wakeup reason + mlanutl uap0 wakeupreason : Get the host sleep wakeup reason + 0: unknown + 1: Broadcast data matched + 2: Multicast data matched + 3: Unicast data matched + 4: Maskable event matched + 5. Non-maskable event matched + 6: Non-maskable condition matched (EAPoL rekey) + 7: Magic pattern matched + 8: Control frame matched + 9: Management frame matched + Others: reserved. (0) + +warmreset + This command is used for warm reset of the interface. + + Usage: + mlanutl mlanX warmreset + +wpssession + This command is used to control wps session. No argument is used to get. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 wpssession 1 : Enable wpssession + mlanutl mlan0 wpssession : Get wpssession status + +wmmcfg + This command is used to control WMM. No argument is used to get. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 wmmcfg 1 : Enable WMM + mlanutl mlan0 wmmcfg : Get WMM status + +wmmparamcfg + This command is used to configure WMM paramameters. + + Usage: + mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP] + + The supported option are: + AC_BE: 0 + AC_BK: 1 + AC_VI: 2 + AC_V0: 3 + AIFSN: AIFSN value + ECW_MAX: ECW max + ECW_MIN: ECW min + TX_OP: TXOP Limit + empty - Get current WMM parameters + + Example: + mlanutl mlanX wmmparamcfg 0 3 10 4 0 + Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + + mlanutl mlanX wmmparamcfg 1 7 10 4 0 + Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + + mlanutl mlanX wmmparamcfg 2 2 4 3 94 + Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94 + + mlanutl mlanX wmmparamcfg 3 2 3 2 47 + Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47 + + mlanutl mlanX wmmparamcfg + Get current WMM parameters + + mlanutl mlanX wmmparamcfg 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47 + Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94 + Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47 + +wwscfg + This command is used to set/get the WWS (World Wide Safe) mode. + + where value of m is: + 0 -- Disable WWS mode (default) + 1 -- Enable WWS mode + + Examples: + mlanutl mlan0 wwscfg : Get WWS mode + mlanutl mlan0 wwscfg 1 : Enable WWS mode + mlanutl mlan0 wwscfg 0 : Disable WWS mode + +mc_cfg + This command is used to set/get the channel time. + + Usage: + mlanutl mlanX mc_cfg [n] + + where : Channel time in microseconds. + + Examples: + mlanutl mlanX mc_cfg : Get Channel time and buffer weight. + mlanutl mlanX mc_cfg 10000 : Set Channel time to 10000us. + +mc_policy + This command is used to set/get the multi-channel policy. + Note: This is a device specific command. Hence, setting on one interface is + reflected on all other interfaces. + + Usage: + mlanutl mlanX mc_policy [n] + + where : Multi-channel policy + + Examples: + mlanutl mlanX mc_policy : Get multi-channel policy setting. + mlanutl mlanX mc_policy 1 : Set multi-channel policy to 1. + mlanutl mlanX mc_policy 0 : Disable multi-channel policy + +mc_cfg_ext + This command is used to set/get the drcs parameters. + + Usage: + mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] + + where: + channel index0: + [c] : chantime(in TU) + [s] : switchtime(in TU) + [u] : undozetime(in TU) + [m] : mode :0x0 --- PM1(default) + 0x1 --- Null2Self + channel index1: + : chantime(in TU) + : switchtime(in TU) + : undozetime(in TU) + : mode :0x0 --- PM1(default) + 0x1 --- Null2Self + Note: + channel index0: the first channel + channel index1: the second channel + undozetime should be less than other channel's switchtime + If want to set two channels the same parameters, just ignore the last four parameters and + use [c] [s] [u] [m] to set. + Examples: + mlanutl mlanX mc_cfg_ext : Get the drcs parameters for two channels. + mlanutl mlanX mc_cfg_ext 15 10 5 0 : Set two channels:channeltime 15TU, switchtime 10TU, undozetime 5TU, mode PM1 + mlanutl mlanX mc_cfg_ext 15 10 5 0 25 15 9 0 : Set channel index0: channeltime 17TU, switchtime 10TU, undozetime 5TU, mode PM1; + set channel index1: channeltime 25TU, switchtime 15TU, undozetime 9TU, mode PM1. + +cfg_noa + This is used to get/set P2P NoA (Notice of Absence) parameters only for P2P GO. + + Usage: + mlanutl p2pX cfg_noa [h] [i] [j] [k] [l] + + where: + [h] : noa_enable : 1/0 Set to 1 to enable NoA, 0 to disable NoA. + [i] : index : 0 - 255 Identifies an instance of NoA timing. + [j] : count : 1 - 255 Indicates the number of absence intervals. + 255 means a continuous schedule. + [k] : duration : Indicates the maximum duration in units of microseconds + that P2P GO can remain absent following the start of + a NoA interval. + [l] : interval : Indicates the length of the NoA interval in units of + microseconds. + + Examples: + mlanutl p2pX cfg_noa : Get noa configuration. + mlanutl p2pX cfg_noa 1 1 255 50 100 : Set noa configuration. + +cfg_opp_ps + This is used to get/set P2P OPP-PS parameters only for P2P GO. + + Usage: + mlanutl p2pX cfg_opp_ps [m] [n] + + where: + [m] : ps_enable : 1/0 Set to 1 to indicate P2P GO is using opportunistic + power save. Set to 0 if opportunistic power save is disabled. + [n] : ct_window : A period of time in TU after a TBTT during which P2P GO + is present. 0 indicates that there shall be no + CTWindow (Client Traffic Window). + + Examples: + mlanutl p2pX cfg_opp_ps : Get noa configuration. + mlanutl p2pX cfg_opp_ps 1 7 : Set noa configuration. + +rxpktcoal_cfg + This is used to get/set RX packet coalescing paramters + Usage: + mlanutl mlanX rxpktcoal_cfg [m] [n] + + where: + [m]: pkt_threshold: count after which packets would be sent to host. Valid values 1-7 + [n]: delay: timeout in ms after which packets would be sent to host. Valid values 1-4 + Coalescing is disabled if both or either of packet_thershold and delay is zero + + RX packet coalescing parameters can be changed only when device is in + idle state i.e. all interfaces are disconnected. + +get_sensor_temp + This command is used to get SOC temperature + Usage: + mlanutl mlanX get_sensor_temp +11k_enable + This command is used to control 11K. No argument is used to get. + only available when disconnected. + + where value of n is: + 0 -- Disable + 1 -- Enable + + Examples: + mlanutl mlan0 11k_enable 1 : Enable 11k + mlanutl mlan0 11k_enable : Get 11k status + +neighbor_report + This command is used to get neighbor AP list. + You can open mlanevent to show the AP list result before issue this command. + + Usage: + mlanutl mlanX neighbor_report + +indrstcfg + This command is used to set/ get independent reset mode configuration + + Usage : + mlanutl indrstcfg [gpio_pin] + + interface : mlanX, uapX + ir_mode : 0 -- Disable + 1 -- Enable out band reset, disable in band + 2 -- Enable in band, disable out band + gpio_pin : 255 -- Default pin for reset + any other number for changing the gpio for reset. + + Example : + mlanutl mlan0 indrstcfg 1 255 : Set default pin on interface mlan0 as reset pin + mlanutl mlan0 indrstcfg 0 : Disable the gpio 17 as reset pin on interface mlan0 + mlanutl mlan0 indrstcfg : Get the status and the pin used for reset pin + mlanutl mlan0 indrstcfg 2 : Enable in band reset mode + + This command is used to set FW wakeup method and GPIO pin + Usage : + mlanutl fwwakeupmethod + interface : mlanX + method: + 1 -- Firmware wakeup through the interface command interrupt + -- (default setting for SDIO/PCIe/USB) + 2 -- Firmware wakeup through the GPIO pin + GPIO_pin: If firware wakeup throug GPIO pin, [g] is GPIO pin number + Example : + mlanutl mlan0 fwwakeupmethod : Get current wakeup method + mlanutl mlan0 fwwakeupmethod 1 : Set wakeup method is interface method + mlanutl mlan0 fwwakeupmethod 2 5 : Set wakeup method is GPIO method and GPIO pin is 5. + +tx_ampdu_prot_mode + This command is used to set either RTS/CTS or CTS2SELF protection mechanism + in MAC, for aggregated Tx QoS data frames. RTS/CTS is enabled by default. + + Usage: + mlanutl tx_ampdu_prot_mode [mode] + + Where the parameters are: + : mlanX, + uapX + [mode] : 0 - Set RTS/CTS mode + 1 - Set CTS2SELF mode + 2 - Disable Protection mode + + Examples: + mlanutl mlan0 tx_ampdu_prot_mode + - Get currently set protection mode for Tx AMPDU + mlanutl mlan0 tx_ampdu_prot_mode 1 + - Set protection mode for Tx AMPDU to CTS2SELF + +robustcoex + This command is used to set robust coex. + + Usage : + mlanutl robustcoex [Enable/Disable] [gpionum] [gpiopolarity] + Enable/Disable : 0 -- Disable ; 1 -- Enable + gpionum : Number of gpio + gpiopolarity : polarity of gpio + + Example : + mlanutl mlan0 robustcoex gpiocfg 1 4 1 : Enable robustcoex gpio, set gpionum to 4 and gpiopolarity to 1 + mlanutl mlan0 robustcoex gpiocfg 0 : Disable robustcoex gpio + +ctrldeauth + This command is used to set/get firmware ctrldeauth setting + Usage : + mlanutl uapX ctrldeauth + + Where value of n is : + 0 -- Firmware will use default behavior + 1 -- Firmware will not send deauth packet when uap move to another channel. + + Example : + mlanutl uap0 ctrldeauth : Get current setting + mlanutl uap0 ctrldeauth : Firmware will not send deauth packet when uap move to different channel. + +cwmode + This command is used to set Cont. Tx/Wave mode. + + Usage: + mlanutl cwmode config/cwmode.conf + interface: mlanX + cwmode.conf: This config file specifies whether to enable/disable Cont Tx/Wave mode. + User can specify parameters like Channel, datarate, BW, Channel Offset, Band. + Detailed information about parameters is mentioned in the conf file. + Example: + mlanutl mlan0 cwmode config/cwmode.conf : Enable/Disable Cont Tx/Wave mode. + mlanutl mlan0 cwmode : Get current Tx mode + +bootsleep + This command is used to set and get boot sleep configure. + + Usage : + mlanutl mlanX/uapX bootsleep + : enable boot sleep + : 0 - disable boot sleep + : 1 - enable boot sleep + + Example : + mlanutl mlan0/uap0 bootsleep 1 : Enable boot sleep + mlanutl mlan0/uap0 bootsleep : Get boot sleep configure + + +=============================================================================== diff --git a/mwifiex_8997/README_OPENWRT b/mwifiex_8997/README_OPENWRT new file mode 100755 index 0000000..90a6722 --- /dev/null +++ b/mwifiex_8997/README_OPENWRT @@ -0,0 +1,356 @@ +================================================================================= + U S E R M A N U A L F O R OpenWrt + +This section describes detailed steps to add Marvell Wireless NIC (sdio/usb/pcie) +driver to OpenWrt build system. + +Add marvell driver (sdio/usb/pcie) to OpenWrt build system. + +1. Go to the openwrt source code folder +2. make menuconfig + choose x86 platform + other general openwrt configurations please refer to: + https://wiki.openwrt.org/doc/howto/build +3. After make menuconfig + make sure that following configurations are set in .config + CONFIG_PACKAGE_hostapd=y + CONFIG_PACKAGE_hostapd-common=y + CONFIG_PACKAGE_kmod-cfg80211=y +4. Go to the openwrt source code folder and Compile openwrt BSP + make V=s [-j[number]] +5. After the first time compiling, openwrt/dl folder will be created + , related packages will be downloaded during compiling, so you need + network access as long as you need to compile openwrt BSP. +6. Go to the openwrt source code folder: openwrt/dl/ +7. Find compat-wireless-xxxx-xx-xx.tar.bz2, and uncompress the package +8. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/ +9. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Kconfig + + source "drivers/net/wireless/marvell/libertas/Kconfig" + source "drivers/net/wireless/marvell/libertas_tf/Kconfig" + source "drivers/net/wireless/marvell/mwifiex/Kconfig" + +source "drivers/net/wireless/marvell/mrvl-pcie/Kconfig" + +source "drivers/net/wireless/marvell/mrvl-sd8xxx/Kconfig" + +source "drivers/net/wireless/marvell/mrvl-usb/Kconfig" + +10. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Makefile + + obj-$(CPTCFG_LIBERTAS_THINFIRM) += libertas_tf/ + obj-$(CPTCFG_MWIFIEX) += mwifiex/ + +obj-$(CPTCFG_MRVL_PCIE) += mrvl-pcie/ + +obj-$(CPTCFG_MRVL_SD8XXX) += mrvl-sd8xxx/ + +obj-$(CPTCFG_MRVL_USB) += mrvl-usb/ + +11. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/ +12. mkdir (mrvl-pcie/mrvl-sd8xxx/mrvl-usb) +13. copy (pcie/sdio/usb)/wlan_src/* to (mrvl-pcie/mrvl-sd8xxx/mrvl-usb) +14. Go to mrvl-pcie/mrvl-sd8xxx/mrvl-usb +15. Add new Kconfig: + mrvl-pcie/Kconfig + + +config MRVL_PCIE + + tristate "Marvell Wireless Driver for PCIE 8997" + + depends on m + + depends on PCI + + depends on CFG80211 + + depends on WIRELESS_EXT + + ---help--- + + This adds support for wireless adapters based on Marvell + + pcie 8997 chipsets with PCIe interface. + + + + If you choose to build it as a module, it will be called + + pcie8xxx. + + mrvl-sd8xxx/Kconfig + + +config MRVL_SD8XXX + + tristate "Marvell sdio 802.11n/802.11ac Wireless cards" + + depends on m + + depends on MMC + + depends on CFG80211 + + depends on WIRELESS_EXT + + ---help--- + + A driver for Marvell sdio 802.11n/802.11ac Wireless cards. + + mrvl-usb/Kconfig + + +config MRVL_USB + + tristate "Marvell sdio 802.11n/802.11ac Wireless cards" + + depends on m + + depends on USB + + depends on CFG80211 + + depends on WIRELESS_EXT + + ---help--- + + A driver for Marvell sdio 802.11n/802.11ac Wireless cards. + +16. Open moal_main.h under (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlinux/ + + find #define COMPAT_VERSION_CODE KERNEL_VERSION_CODE(x, x, x) + modify (x, x, x) to the kernel version code of backports/compat-wireless package + + backported kernel version code could be found in + compat-wireless-xxxx-xx-xx/version as following + + 'BACKPORTED_KERNEL_VERSION="v4.4-rc5-1913-gc8fdf68"' + v4.4 means KERNEL_VERSION(4, 4, 0) + +17. Modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile + + # OpenWrt support + -CONFIG_OPENWRT_SUPPORT=n + +CONFIG_OPENWRT_SUPPORT=y + + ... + + ############################################################################# + # Select Platform Tools + ############################################################################# + + MODEXT = ko + -ccflags-y += -I$(M)/mlan + +ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan + ccflags-y += -DLINUX + + + ifeq ($(CONFIG_EMBEDDED_SUPP_AUTH), y) + -ccflags-y += -I$(M)/mlan/esa + -ccflags-y += -I$(M)/mlan/esa/common + +ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa + +ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa/common + endif + +18. compress compat-wireless-xxxx-xx-xx to its original .tar.bz2 format +19. Go to the openwrt source code folder: openwrt/package/kernel/mac80211/ +20. Modify openwrt/package/kernel/mac80211/Makefile. + + PKG_DRIVERS = \ + adm8211 \ + ath ath5k ath9k ath9k-common ath9k-htc ath10k \ + b43 b43legacy \ + carl9170 \ + hermes hermes-pci hermes-pcmcia hermes-plx\ + iwl-legacy iwl3945 iwl4965 iwlwifi \ + lib80211 \ + libipw ipw2100 ipw2200 \ + libertas-sdio libertas-usb libertas-spi \ + mac80211-hwsim \ + mt7601u \ + mwl8k mwifiex-pcie \ + +mrvl-pcie \ + +mrvl-sd8xxx \ + +mrvl-usb \ + p54-common p54-pci p54-spi p54-usb \ + rt2x00-lib rt2x00-pci rt2x00-usb \ + rt2400-pci rt2500-pci rt2500-usb \ + + ... + + +define KernelPackage/mrvl-pcie + + $(call KernelPackage/mac80211/Default) + + TITLE:=Marvell pcie wireless driver + + URL:=http://wireless.kernel.org/en/users/Drivers/mwifiex + + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT + + FILES:= \ + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan.ko \ + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/pcie8xxx.ko + + AUTOLOAD:=$(call AutoProbe,mrvl-pcie) + +endef + + +define KernelPackage/mrvl-pcie/description + + Kernel modules for Marvell pcie 802.11n/802.11ac PCIe Wireless cards + +endef + + +define KernelPackage/mrvl-sd8xxx + + $(call KernelPackage/mac80211/Default) + + DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT + + TITLE:=Marvell sdio Wireless Driver + + FILES:= \ + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan.ko \ + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/sd8xxx.ko + + AUTOLOAD:=$(call AutoProbe, mrvl-sd8xxx) + +endef + + +define KernelPackage/mrvl-sd8xxx/description + + Kernel modules for Marvell sdio 802.11n/802.11ac Wireless cards + +endef + + +define KernelPackage/mrvl-usb + + $(call KernelPackage/mac80211/Default) + + DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT + + TITLE:=Marvell usb Wireless Driver + + FILES:= \ + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan.ko \ + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/usb8xxx.ko + + AUTOLOAD:=$(call AutoProbe, mrvl-usb) + +endef + + +define KernelPackage/mrvl-usb/description + + Kernel modules for Marvell usb 802.11n/802.11ac Wireless cards + +endef + + ... + + config-$(call config_package,mwl8k) += MWL8K + config-$(call config_package,mwifiex-pcie) += MWIFIEX MWIFIEX_PCIE + +config-$(call config_package,mrvl-pcie) += MRVL_PCIE + +config-$(call config_package,mrvl-sd8xxx) += MRVL_SD8XXX + +config-$(call config_package,mrvl-usb) += MRVL_USB + config-$(call config_package,rtl8180) += RTL8180 + config-$(call config_package,rtl8187) += RTL8187 + + ... + + $(eval $(call KernelPackage,mwl8k)) + $(eval $(call KernelPackage,mwifiex-pcie)) + +$(eval $(call KernelPackage,mrvl-pcie)) + +$(eval $(call KernelPackage,mrvl-sd8xxx)) + +$(eval $(call KernelPackage,mrvl-usb)) + $(eval $(call KernelPackage,p54-common)) + +OpenWrt configuration +21. Go to OpenWrt srouce code folder +22. Make menuconfig + + select one of the newly added marvell driver + │-> Kernel modules + │ -> Wireless Drivers + | ->mrvl-pcie + | ->mrvl-sd8xxx + | ->mrvl-usb + +23. Other general configurations, please refer to the https://wiki.openwrt.org/doc/howto/build +24. after menucofig make soure that following configurations are seletect + + CONFIG_PACKAGE_hostapd=y + CONFIG_PACKAGE_hostapd-common=y + CONFIG_PACKAGE_kmod-cfg80211=y + + Go to openwrt folder and re-build openwrt BSP + make V=s [-j[number]] + + After openwrt BSP is successfully build, kernel modules could be found + both in the build folder and the running OS once openwrt is boot up. + kernel modules will be written to u-disk while openwrt img is burned to u-disk. + + kernel modules in openwrt build dir: + openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-x86_64/compat-wireless-2016-01-10/ + ipkg-x86_64/kmod-mrvl-(usb/sd8xxx/pcie)/lib/modules/3.18.45/ + + kernel modules in openwrt running OS: + /lib/modules/xx.xx.xx/ + +25. To support SDIO card in OpenWrt x86 platforma + Add following kernel configurations for OpenWrt + Go to OpenWrt source code foler + + make kernel_menuconfig + + Device Drivers----> + --- MMC/SD/SDIO card support + [ ] MMC debugging + [ ] MMC host clock gating + *** MMC/SD/SDIO Card Drivers *** + < > MMC block device driver + < > SDIO UART/GPS class support + < > MMC host test driver + *** MMC/SD/SDIO Host Controller Drivers *** + <*> Secure Digital Host Controller Interface support + <*> SDHCI support on PCI bus + [ ] Ricoh MMC Controller Disabler + < > SDHCI platform and OF driver helper + < > Winbond W83L51xD SD/MMC Card Interface support + < > TI Flash Media MMC/SD Interface support + < > ENE CB710 MMC/SD Interface support + < > VIA SD/MMC Card Reader Driver + < > Renesas USDHI6ROL0 SD/SDIO Host Controller support + + Compile OpenWrt using Make V=s, then write openwrt img to u-disk and boot up + +26. Bring up marvell wireless NIC on OpenWrt system + + copy pcie/sdio/usb firmware to /lib/firmware/mrvl folder + On OpenWrt running OS + scp usrname@:/path/firmware.bin /lib/firmware/mrvl + + Another way is to add firmware binary to OpenWrt source code + +27. load marvell pcie/sdio/usb driver modules + + End with Marvell Wirelss NIC card bring up on OpenWrt + +======================================================================================================= +If firmware is copied to OpenWrt via scp, following steps could be ignored. +28. Add firmware binary in OpenWrt + Copy pcie/usb/sdio firmware to folder: + openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-firmware-52442afee9907bc32a058f22bb3295d040677c26/mrvl/ +29. Go to penwrt/package/firmware/linux-firmware + Modify marvell.mk as following + + +Package/mrvl-pcie-firmware = $(call Package/firmware-default,Marvell PCIE8997 firmware) + +define Package/mrvl-pcie-firmware/install + + $(INSTALL_DIR) $(1)/lib/firmware/mrvl + + $(INSTALL_DATA) \ + + $(PKG_BUILD_DIR)/mrvl/pcieusb8997_combo_v4.bin \ + + $(1)/lib/firmware/mrvl/ + +endef + +$(eval $(call BuildPackage,mrvl-pcie-firmware)) + + +Package/mrvl-sd8xxx-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware) + +define Package/mrvl-sd8xxx-firmware/install + + $(INSTALL_DIR) $(1)/lib/firmware/mrvl + + $(INSTALL_DATA) \ + + $(PKG_BUILD_DIR)/mrvl/sdsd8997_combo_v4.bin \ + + $(1)/lib/firmware/mrvl/ + +endef + +$(eval $(call BuildPackage,mrvl-sd8xxx-firmware)) + + +Package/mrvl-usb-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware) + +define Package/mrvl-usb-firmware/install + + $(INSTALL_DIR) $(1)/lib/firmware/mrvl + + $(INSTALL_DATA) \ + + $(PKG_BUILD_DIR)/mrvl/usbusb8997_combo_v4.bin \ + + $(1)/lib/firmware/mrvl/ + +endef + +$(eval $(call BuildPackage,mrvl-usb-firmware)) + +30. re-modify openwrt/package/kernel/mac80211/Makefile + + for PCIE + + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT +mrvl-pcie-firmware + for SDIO + + DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT +mrvl-sd8xxx-firmware + for USB + + DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT +mrvl-usb-firmware +31. Go to step 25. +======================================================================================================= +To support SDIO, USB and PCIE in one OpenWrt BSP +if no need to support multi bus types in one BSP, ignore the following steps +32. Re-modify Modify openwrt/package/kernel/mac80211/Makefile. + for PCIE + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan-pcie.ko \ + for SDIO + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan-sdio.ko \ + for USB + + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan-usb.ko \ +33. Re-modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile + for PCIE + + -obj-m := mlan.o + -mlan-objs := $(MLANOBJS) + +obj-m := mlan-pcie.o + +mlan-pcie-objs := $(MLANOBJS) + + for SDIO + + -obj-m := mlan.o + -mlan-objs := $(MLANOBJS) + +obj-m := mlan-sdio.o + +mlan-sdio-objs := $(MLANOBJS) + + for USB + + -obj-m := mlan.o + -mlan-objs := $(MLANOBJS) + +obj-m := mlan-usb.o + +mlan-usb-objs := $(MLANOBJS) +34. Go to step 25. diff --git a/mwifiex_8997/README_RBC b/mwifiex_8997/README_RBC new file mode 100755 index 0000000..470ff29 --- /dev/null +++ b/mwifiex_8997/README_RBC @@ -0,0 +1,103 @@ +=============================================================================== + U S E R M A N U A L for Robust BT-WLAN coex (RBC) + + Copyright (C) 2014-2019, Marvell International Ltd. + All Rights Reserved +=============================================================================== + +############################### + +# Abbreviations and acronyms + +############################### +RBC - Robust BT-WLAN co-existence +TMD - Time Distribute +SMPS - Spatial Multiplexing Power Save + +############################### + +# Default RBC modes: + +############################### +1. For systems where BT and WLAN have seperate antennas, RBC mode is + automatically disabled in FW after detecting this from FEM cal data. e.g. + For 1x1 Dual-Ant system and 2x2 3-Ant system RBC mode is disabled. +2. For systems where BT and WLAN share an antenna, RBC mode is automatically + enabled in FW after detecting this from FEM cal data. + Default modes: + 1x1 single antenna system: TMD RBC + 2x2 2-antenna system: 1x1 SMPS RBC + + +################################# + +# 2x2 2-antenna system RBC modes + +################################# +There are three mutually exclusive RBC modes for a 2x2 system. +The default RBC mode is 1x1 SMPS RBC. The required RBC mode must be +configured before starting uAP or associating in-STA. The mode cannot be +changed dynamically when any of these connections is active. The modes are +described below: +1. 1x1 SMPS RBC mode: WLAN switches to 1x1 FEM when BT is turned on. Also, + in-STA goes to SMPS mode w.r.t. ext-AP. When BT is turned off, WLAN + switches back to 2x2 FEM setting and in-STA moves out of SMPS. + uAP starts bss with only 1-stream even BT is off because it cannot + dynamically move between 1-stream and 2-stream rates like in-STA. To start + uAP with 2-stream, RBC mode has to be disabled. +2. 1x2 SMPS RBC mode: Similar as 1x1 SMPS RBC mode. WLAN switches to 1x2 FEM + when BT is turned on. In this mode, it is expected that when BT is not + actively transmitting, WLAN can receive on both the antennas to enhance + the range. Note that 1-stream rates are used for receive and transmit. +3. 2x2 TMD RBC mode: WLAN uses 2x2 antenna setting and timeshares the antenna + with BT. + +############################### + +# RBC mode select: + +############################### + +User can use robust_btc.conf and hostcmd to select different RBC mode: + +hostcmd mode_get +hostcmd mode_timeshare +hostcmd mode_spatial + This command is used to get/set Robust BT Coex. + mode_get: get the current mode + mode_timeshare: set Robust BT Coex to timeshare mode (default on 1x1 chips) + mode_spatial: set Robust BT Coex to spatial mode (only for, and default on 2x2 chips) + + Usage: + mlanconfig mlanX hostcmd config/robust_btc.conf mode_get + mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare + mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial + +hostcmd gpio_cfg + This command is used to enable/disable GPIO cfg. + gpio_cfg: enable/disable GPIO cfg for external bt request (default is enable with High Polarity) + + Usage: + mlanconfig mlanX hostcmd config/robust_btc.conf gpio_cfg + +hostcmd generictime +hostcmd a2dptime +hostcmd inquirytime +hostcmd ap_generictime +hostcmd ap_a2dptime +hostcmd ap_inquirytime + This command is used to configure the time slice of COEX (only works in timeshare mode) + generictime: configure the Bttime and Wlantime in Station Generic case + a2dptime: configure the Bttime and Wlantime in Station A2DP case + inquirytime: configure the Bttime and Wlantime in Station Inquiry case + ap_generictime: configure the Bttime and Wlantime in Ap Generic case + ap_a2dptime: configure the Bttime and Wlantime in Ap A2DP case + ap_inquirytime: configure the Bttime and Wlantime in Ap Inquiry case + + Usage: + mlanutl mlanX hostcmd config/robust_btc.conf generictime + mlanutl mlanX hostcmd config/robust_btc.conf a2dptime + mlanutl mlanX hostcmd config/robust_btc.conf inquirytim + mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime + mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime + mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime diff --git a/mwifiex_8997/README_UAP b/mwifiex_8997/README_UAP new file mode 100755 index 0000000..4e0f01c --- /dev/null +++ b/mwifiex_8997/README_UAP @@ -0,0 +1,2664 @@ +=============================================================================== + U S E R M A N U A L + + Copyright (C) 2009-2019, Marvell International Ltd. + All Rights Reserved + +1) FOR DRIVER BUILD + + Goto source code directory wlan_src. + make [clean] build + The driver binaries can be found in ../bin_xxxx directory. + The driver code supports Linux kernel up to 5.0.9. + +2) FOR DRIVER INSTALL + + a) Copy firmware image pcie8897_uapsta.bin | ... to /lib/firmware/mrvl/ directory, + create the directory if it doesn't exist. + b) Install WLAN driver + There are drv_mode, max_sta_bss, max_uap_bss etc. module parameters. + The bit settings of drv_mode are, + Bit 0 : STA + Bit 1 : uAP + Bit 2 : WIFIDIRECT + Bit 4 : NAN + + max_uap_bss: Maximum number of uAP BSS (default 1, max 2) + uap_name: Name of the uAP interface (default: "uap") + For example, to install PCIE8897 driver, + To load driver in uAP only mode, + insmod mlan.ko + insmod pcie8897.ko drv_mode=2 [fw_name=mrvl/pcie8897_uapsta.bin] + + To switch mode between STA only, uAP only and uAPSTA in run time, + echo drv_mode=1 > /proc/mwlan/config // STA mode + echo drv_mode=2 > /proc/mwlan/config // uAP mode + echo drv_mode=3 > /proc/mwlan/config // uAPSTA mode + c) Uninstall WLAN driver, + ifconfig mlanX down + ifconfig uapX down + rmmod pcie8xxx + rmmod mlan + + To load driver with MFG firmware file, use mfg_mode=1 when insmod WLAN driver and + specify MFG firmware name if needed. + + There are some other parameters for debugging purpose etc. Use modinfo to check details. + drvdbg= + dev_cap_mask= + mac_addr=xx:xx:xx:xx:xx:xx + auto_ds=0|1|2 + ps_mode=0|1|2 + max_tx_buf=2048|4096|8192 + cfg_11d=0|1|2 + dts_enable=0|1 + hw_test=0|1 + fw_serial=0|1 + req_fw_nowait=0|1 + init_cfg= + e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf + cal_data_cfg= + e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf + txpwrlimit_cfg= + e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf + init_hostcmd_cfg= + e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf + cfg80211_wext= + Bit 0: STA WEXT + Bit 1: uAP WEXT + Bit 2: STA CFG80211 + Bit 3: uAP CFG80211 + wq_sched_prio: Priority for work queue + wq_sched_policy: Scheduling policy for work queue + (0: SCHED_NORMAL, 1: SCHED_FIFO, 2: SCHED_RR, 3: SCHED_BATCH, 5: SCHED_IDLE) + Please note that, both wq_sched_prio and wq_sched_policy should be provided + as module parameters. If wq_sched_policy is (0, 3 or 5), then wq_sched_prio + must be 0. wq_sched_prio should be 1 to 99 otherwise. + rx_work=0|1|2 + + Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used + for module parameters. + insmod sd8xxx.ko " ..." + +3) FOR DRIVER PROC & DEBUG + The following info are provided in /proc/mwlan/uapX/info. + + driver_name = "uap" + driver_version = + InterfaceName= "uapX" + State= "Disconnected" | "Connected" + MACAddress= <6-byte adapter MAC address> + MCCount= + num_tx_bytes = + num_rx_bytes = + num_tx_pkts = + num_rx_pkts = + num_tx_pkts_dropped = + num_rx_pkts_dropped = + num_tx_pkts_err = + num_rx_pkts_err = + num_tx_timeout = + carrier "on" | "off" + tx queue "stopped" | "started" + + The following debug info are provided in /proc/mwlan/uapX/debug. + + drvdbg = + bit 0: MMSG PRINTM(MMSG,...) + bit 1: MFATAL PRINTM(MFATAL,...) + bit 2: MERROR PRINTM(MERROR,...) + bit 3: MDATA PRINTM(MDATA,...) + bit 4: MCMND PRINTM(MCMND,...) + bit 5: MEVENT PRINTM(MEVENT,...) + bit 6: MINTR PRINTM(MINTR,...) + bit 7: MIOCTL PRINTM(MIOCTL,...) + ... + bit 16: MDAT_D PRINTM(MDAT_D,...), DBG_HEXDUMP(MDAT_D,...) + bit 17: MCMD_D PRINTM(MCMD_D,...), DBG_HEXDUMP(MCMD_D,...) + bit 18: MEVT_D PRINTM(MEVT_D,...), DBG_HEXDUMP(MEVT_D,...) + bit 19: MFW_D PRINTM(MFW_D,...), DBG_HEXDUMP(MFW_D,...) + bit 20: MIF_D PRINTM(MIF_D,...), DBG_HEXDUMP(MIF_D,...) + ... + bit 28: MENTRY PRINTM(MENTRY,...), ENTER(), LEAVE() + bit 29: MWARN PRINTM(MWARN,...) + bit 30: MINFO PRINTM(MINFO,...) + wmm_ac_vo = + wmm_ac_vi = + wmm_ac_be = + wmm_ac_bk = + max_tx_buf_size = + tx_buf_size = + curr_tx_buf_size = + ps_mode = <0/1, CAM mode/PS mode> + ps_state = <0/1/2/3, awake state/pre-sleep state/sleep-confirm state/sleep state> + wakeup_dev_req = <0/1, wakeup device not required/required> + wakeup_tries = + hs_configured = <0/1, host sleep not configured/configured> + hs_activated = <0/1, extended host sleep not activated/activated> + tx_pkts_queued = + num_bridge_pkts = + num_drop_pkts = + num_tx_timeout = + num_cmd_timeout = + timeout_cmd_id = + timeout_cmd_act = + last_cmd_id = + last_cmd_act = + last_cmd_index = <0 based last command index> + last_cmd_resp_id = + last_cmd_resp_index = <0 based last command response index> + last_event = + last_event_index = <0 based last event index> + num_cmd_h2c_fail = + num_cmd_sleep_cfm_fail = + num_tx_h2c_fail = + cmd_sent = <0/1, send command resources available/sending command to device> + data_sent = <0/1, send data resources available/sending data to device> + txbd_rdptr = + txbd_wrptr = + rxbd_rdptr = + rxbd_wrptr = + eventbd_rdptr = + eventbd_wrptr = + cmd_resp_received = <0/1, no cmd response to process/response received and yet to process> + event_received = <0/1, no event to process/event received and yet to process> + ioctl_pending = + tx_pending = + rx_pending = + lock_count = + malloc_count = + mbufalloc_count = + malloc_cons_count = + main_state = + + Example: + echo "drvdbg=0x7" > /proc/mwlan/uapX/debug #enable MMSG,MFATAL,MERROR messages + + Use dmesg or cat /var/log/debug to check driver debug messages. + + To log driver debug messages to file, + a) Edit /etc/rsyslog.conf, add one line "*.debug /var/log/debug" + b) touch /var/log/debug (if the file doesn't exist) + c) service rsyslog restart + +4) SOFT_RESET command + This command is used to perform a "soft reset" on the module. + The FW code will disable hardware and jump to boot code. + Host software will then need to re-download firmware if required. + + Usage: + echo "soft_reset=1" > /proc/mwlan/config + +=============================================================================== + + U S E R M A N U A L F O R UAPUTL + +NAME +uaputl.exe [options] [command parameters]] + +Options: + --help Display help + -v Display version + -i + -d + +Example: + ./uaputl.exe --help + "display help for uaputl" + + ./uaputl.exe sys_config --help + "display help for sys_config command" + +This tool can be used to set/get uAP's settings. To change AP settings, you might +need to issue "bss_stop" command to stop AP before making change and issue "bss_start" +command to restart the AP after making change. + +------------------ +Supported Commands +------------------ +version +debug_level +sys_config [CONFIG_FILE_NAME] +bss_config [CONFIG_FILE_NAME] +sys_info +sys_reset +bss_start +bss_stop +sta_list +sta_deauth +sta_deauth_ext +radioctrl [0|1] +txratecfg [l] [m] [n] +antcfg [m] [n] +pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE] +sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer] +coex_config [CONFIG_FILE_NAME] +hscfg [condition [[GPIO# [gap]]]] +hssetpara condition [[GPIO# [gap]]] +sys_cfg_wmm [qosinfo=] + [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP] +sys_cfg_ap_wmm [0] + [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP] +sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_MAP] +addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu] +aggrpriotbl ... +addbareject ... +httxbfcfg [ACT_DATA] +httxcfg [] +htstreamcfg [n] +deepsleep [MODE] [IDLE_TIME] +hostcmd txpwrlimit_cfg_get +hostcmd txpwrlimit_2g_cfg_set +hostcmd txpwrlimit_5g_cfg_set +tx_data_pause [ENABLE][TX_BUF_CNT] +vhtcfg [l] [m] [n] [o] +dfstesting [ ] +cscount [] +mgmtframectrl [MASK] + +------------------------------------------------------------------- +The following commands can be issued individually for debug purpose +------------------------------------------------------------------- +sys_cfg_ap_mac_address [AP_MAC_ADDRESS] +sys_cfg_ssid [SSID] +sys_cfg_beacon_period [BEACON_PERIOD] +sys_cfg_dtim_period [DTIM_PERIOD] +sys_cfg_channel [CHANNEL] [MODE] +sys_cfg_channel_ext [CHANNEL] [BAND] [MODE] +sys_cfg_scan_channels [CHANNEL[.BAND]] +sys_cfg_rates [RATES] +sys_cfg_rates_ext [rates RATES] [mbrate RATE] +sys_cfg_tx_power [TX_POWER] +sys_cfg_bcast_ssid_ctl [0|1|2] +sys_cfg_preamble_ctl +sys_cfg_bss_status +sys_cfg_rts_threshold [RTS_THRESHOLD] +sys_cfg_frag_threshold [FRAG_THRESHOLD] +sys_cfg_rsn_replay_prot [1|0] +sys_cfg_tx_beacon_rate [TX_BEACON_RATE] +sys_cfg_mcbc_data_rate [MCBC_DATA_RATE] +sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL] +sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER] +sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER] +sys_cfg_auth [AUTH_MODE] +sys_cfg_protocol [PROTOCOL] [AKM_SUITE] +sys_cfg_pmf [MFPC] [MFPR] +sys_cfg_wep_key [INDEX ISDEFAULT KEY] +sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER] +sys_cfg_pwk_cipher [] [PAIRWISE_CIPHER] +sys_cfg_gwk_cipher [GROUP_CIPHER] +sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER] +sys_cfg_wpa_passphrase [PASSPHRASE] +sys_cfg_max_sta_num [STA_NUM] +sys_cfg_retry_limit [RETRY_LIMIT] +sys_cfg_sticky_tim_config [ENABLE] [ ] +sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS] +sys_cfg_2040_coex [ENABLE] +sys_cfg_eapol_pwk_hsk [ ] +sys_cfg_eapol_gwk_hsk [ ] +sta_filter_table +regrdwr [value] +memaccess [value] +rdeeprom +cfg_data [*.conf] +sys_cfg_80211d [state STATE] [country COUNTRY] +uap_stats +sys_cfg_tdls_ext_cap [CONFIG_FILE] +sys_cfg_restrict_client_mode [ [MODE_CONFIG]] +skip_cac [] + +------------------- +Details of Commands +------------------- + +version +------- + "./uaputl.exe -v" + + This command prints the uAP utility version information. + +debug_level +----------- + "./uaputl.exe -d " + + The supported debug_level are: + 0 - no debug + 1 - enable MSG_DEBUG + 2 - enable all the debug + This command use to control the debug level of uaputl.exe. + + Example: + ./uaputl.exe -d 2 sys_config + Enable all the debug in uaputl.exe + +sys_config +---------- + "./uaputl.exe sys_config [CONFIG_FILE]" + This command is used to set or get the current settings of the Micro AP. + + The supported options are: + CONFIG_FILE is file contain all the Micro AP settings. + empty - Get current Micro AP settings + + Example: + ./uaputl.exe sys_config + Get current settings of the Micro AP. + + ./uaputl.exe sys_config config/uaputl.conf + Load Micro AP's settings from uaputl.conf file and set. + +bss_config +---------- + "./uaputl.exe bss_config [CONFIG_FILE]" + This command is used to set or get the current settings of the BSS. + + The supported options are: + CONFIG_FILE is file contain all the BSS settings. + empty - Get current BSS settings + + Example: + ./uaputl.exe bss_config + Get current settings of the BSS. + + ./uaputl.exe bss_config config/uaputl.conf + Load BSS settings from uaputl.conf file and set. + +sys_info +-------- + "./uaputl.exe sys_info" + + This command returns system information such as firmware version number + and HW information. + +sys_reset +--------- + "./uaputl.exe sys_reset" + + This command is used to reset the Micro AP back to its initial state. + For example, this can be used to recover from a serious error, or before + creating a new BSS. + + This command has the following effects: + 1. The WLAN hardware MAC is reset. + 2. All MIB variables are initialized to their respective default + values. + 3. The firmware internal variables are reset to their respective + default values. + 4. The firmware state machines are reset to their respective initial + states. + +bss_start +--------- + "./uaputl.exe bss_start" + + This command starts the BSS. + There is no error for redundant bss_start command. + +bss_stop +-------- + "./uaputl.exe bss_stop" + + This command stops the BSS. The command causes the firmware to: + 1. Deauthenticate all associated client stations. + 2. Turn off the radio (hence stopping beaconing). + There is no error for redundant bss_stop command. + +sta_list +-------- + "./uaputl.exe sta_list" + + This command returns the list of client stations that are currently + associated with the AP. + + The output is formatted as shown below, for each STA: + "STA information: + ========================== + MAC Address: + Power mfg status: active|power save + Rssi: " + +sta_deauth +---------- + "./uaputl.exe sta_deauth " + + This command is used to de-authentciate a client station for any reason. + +radioctrl +---------- + "./uaputl.exe radioctrl [0|1]" + + This command is used to set or get the radio settings. + The supported options are: + 1 - Turn radio on + 0 - Turn radio off + empty - Get current radio setting + +txratecfg +---------- + "./uaputl.exe txratecfg [l] [m] [n]" + + This command is used to set/get the transmit data rate. + + Where + [l] is + - This parameter specifies the data rate format used in this command + 0: LG + 1: HT + 2: VHT + 0xff: Auto + + [m] is + - This parameter specifies the rate or MCS index + If is 0 (LG), + 0 1 Mbps + 1 2 Mbps + 2 5.5 Mbps + 3 11 Mbps + 4 6 Mbps + 5 9 Mbps + 6 12 Mbps + 7 18 Mbps + 8 24 Mbps + 9 36 Mbps + 10 48 Mbps + 11 54 Mbps + If is 1 (HT), + 0 MCS0 + 1 MCS1 + 2 MCS2 + 3 MCS3 + 4 MCS4 + 5 MCS5 + 6 MCS6 + 7 MCS7 + 8 MCS8 + 9 MCS9 + 10 MCS10 + 11 MCS11 + 12 MCS12 + 13 MCS13 + 14 MCS14 + 15 MCS15 + 32 MCS32 + If is 2 (VHT), + 0 MCS0 + 1 MCS1 + 2 MCS2 + 3 MCS3 + 4 MCS4 + 5 MCS5 + 6 MCS6 + 7 MCS7 + 8 MCS8 + 9 MCS9 + [n] is + - This parameter specifies the NSS. It is valid only for VHT + If is 2 (VHT), + 1 NSS1 + 2 NSS2 + + Examples: + ./uaputl.exe txratecfg 0 3 : Set fixed Tx rate to 11 Mbps + ./uaputl.exe txratecfg 0 11 : Set fixed Tx rate to 54 Mbps + ./uaputl.exe txratecfg 1 3 : Set fixed Tx rate to MCS3 + ./uaputl.exe txratecfg 2 3 2 : Set fixed Tx rate to MCS3 for NSS2 + ./uaputl.exe txratecfg 0xff : Disable fixed rate and uses auto rate + ./uaputl.exe txratecfg : Read the current data rate setting + +antcfg +---------- + "./uaputl.exe antcfg [m] [n]" + + This command is used to set/get the transmit and receive antenna. + where value of m is: + Bit 0 -- Tx Path A + Bit 1 -- Tx Path B + Bit 0-1 -- Tx Path A+B + + where value of n is: + Bit 0 -- Rx Path A + Bit 1 -- Rx Path B + Bit 0-1 -- Rx Path A+B + The Tx path setting (m) is used if Rx path (n) is not provided. + + Examples: + ./uaputl.exe antcfg : Get Tx and Rx path + ./uaputl.exe antcfg 3 : Set Tx and Rx path to A+B + ./uaputl.exe antcfg 2 3 : Set Tx path to B and Rx path to A+B + +sys_cfg_ap_mac_address +---------------------- + "./uaputl.exe sys_cfg_ap_mac_address [AP_MAC_ADDRESS]" + + This command is used to set or get the AP MAC address. + + If no arguments are given, this command returns the current AP MAC + address. + Otherwise, this MAC address becomes the BSSID of the infrastructure + network created by the AP. + + Example: + ./uaputl.exe sys_cfg_ap_mac_address 00:50:43:20:aa:bb + Set AP MAC address to 00:50:43:20:aa:bb + + ./uaputl.exe sys_cfg_ap_mac_address + Get AP MAC address" + +sys_cfg_ssid +------------ + "./uaputl.exe sys_cfg_ssid [SSID]" + + This command is used to set or get the AP SSID. + + If no arguments are given, this command returns the current AP SSID. + While setting, the maximum length of the SSID can be 32 characters. + + Example: + ./uaputl.exe sys_cfg_ssid microap + Set AP ssid to "microap" + + ./uaputl.exe sys_cfg_ssid + Get AP ssid + +sys_cfg_beacon_period +--------------------- + "./uaputl.exe sys_cfg_beacon_period [BEACON_PERIOD]" + + This command is used to set or get the AP beacon period. + + If no arguments are given, this command returns the current AP beacon + period. + + Beacon period is represented in milliseconds. + + Example: + ./uaputl.exe sys_cfg_beacon_period 100 + Set AP beacon period to 100 TU + + ./uaputl.exe sys_cfg_beacon_period + Get AP beacon period + +sys_cfg_dtim_period +------------------- + "./uaputl.exe sys_cfg_dtim_period [DTIM_PERIOD] + + This command is used to set or get the AP DTIM period. + + If no arguments are given, this command returns the current AP DTIM + period. + + Example: + ./uaputl.exe sys_cfg_dtim_period 3 + Set AP DTIM period to 3 + + ./uaputl.exe sys_cfg_dtim_period + Get AP DTIM period + +sys_cfg_scan_channels +--------------------- + "./uaputl.exe sys_cfg_scan_channels [CHANNEL[.BAND]]" + + This command is used to set or get the AP's scan channel list. + + If no arguments are given, this command returns the scan channel list. + If BAND is 0, channel is set in 2.4 GHz band and if BAND is 1, channel is set to 5GHz. + Channels from only one of the bands should be specified. + Each CHANNEL.BAND pair must be separated by a space. BAND parameter is optional. + + Example: + ./uaputl.exe sys_cfg_scan_channels 1 11 6 + Set AP scan channel list to 1 11 6 + + ./uaputl.exe sys_cfg_scan_channels 11.0 6.0 + Set AP scan channel list to 11 6 + + ./uaputl.exe sys_cfg_scan_channels + Get AP scan channel list + + ./uaputl.exe sys_cfg_scan_channels 8.1 16.1 34 + Set AP scan channel list to 8 16 and 34 in 5GHz band. + +sys_cfg_channel +--------------- + "./uaputl.exe sys_cfg_channel [CHANNEL] [MODE]" + + This command is used to set or get the AP radio channel. + + If no arguments are given, this command returns the current AP radio + channel. + + MODE: band config mode. + Bit 0: automatic channel selection (ACS) enable/disable + Bit 1: secondary channel is above primary channel enable/disable(only allow for channel 1-7) + Bit 2: secondary channel is below primary channel enable/disable(only allow for channel 5-11) + For 'a' band channel: + Bit 1: secondary channel is above primary channel enable/disable + Bit 2: secondary channel is below primary channel enable/disable + Only following pairs of channels are valid for secondary channel setting in 5GHz band. + 36, 40 + 44, 48 + 52, 56 + 60, 64 + 100, 104 + 108, 112 + 116, 120 + 124, 128 + 132, 136 + 149, 153 + 157, 161 + + Example: + ./uaputl.exe sys_cfg_channel 6 + Set AP radio channel to 6, and no secondary channel. + + ./uaputl.exe sys_cfg_channel 11 0 + Set AP radio channel to 11 with Manual Channel Select. + + ./uaputl.exe sys_cfg_channel 0 1 + Set AP to ACS. + + ./uaputl.exe sys_cfg_channel + Get AP radio channel + + ./uaputl.exe sys_cfg_channel 6 2 + Set AP primary radio channel to 6, and secondary channel is above. + ./uaputl.exe sys_cfg_channel 6 4 + Set AP primary radio channel to 6, and secondary channel is below + ./uaputl.exe sys_cfg_channel 0 3 + Set AP to ACS mode, and secondary channel is above. + ./uaputl.exe sys_cfg_channel 0 5 + Set AP to ACS mode, and secondary channel is below. + ./uaputl.exe sys_cfg_channel 36 2 + Set AP primary radio channel to 36, and secondary channel is above. + ./uaputl.exe sys_cfg_channel 40 4 + Set AP primary radio channel to 40, and secondary channel is below. + +sys_cfg_channel_ext +--------------- + "./uaputl.exe sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]" + + This command is used to set or get the AP radio channel. + + If no arguments are given, this command returns the current AP radio + channel. + + BAND: 0 : 2.4GHz operation + 1 : 5GHz operation + MODE: band config mode. + Bit 0: automatic channel selection (ACS) enable/disable + Bit 1: secondary channel is above primary channel enable/disable(only allow for channel 1-7) + Bit 2: secondary channel is below primary channel enable/disable(only allow for channel 5-11) + For 'a' band channel: + Bit 1: secondary channel is above primary channel enable/disable + Bit 2: secondary channel is below primary channel enable/disable + Only following pairs of channels are valid for secondary channel setting in 5GHz band. + 36, 40 + 44, 48 + 52, 56 + 60, 64 + 100, 104 + 108, 112 + 116, 120 + 124, 128 + 132, 136 + 149, 153 + 157, 161 + + Example: + ./uaputl.exe sys_cfg_channel_ext 6 +Set AP radio channel to 6, and no secondary channel. + + ./uaputl.exe sys_cfg_channel_ext 11 0 0 + Set AP radio channel to 11 in 2.4GHz band with Manual Channel Select. + + ./uaputl.exe sys_cfg_channel_ext 0 0 1 + Set AP to ACS mode and 2.4GHz band. + + ./uaputl.exe sys_cfg_channel_ext 8 0 + Set AP to channel 8 and 2.4GHz band. + + ./uaputl.exe sys_cfg_channel_ext 8 1 + Set AP to channel 8 and 5GHz band. + + ./uaputl.exe sys_cfg_channel_ext 36 1 + Set AP to channel 36 and 5GHZ band. + + ./uaputl.exe sys_cfg_channel_ext + Get AP radio channel, band and mode. + + ./uaputl.exe sys_cfg_channel_ext 6 0 2 + Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is above. + ./uaputl.exe sys_cfg_channel_ext 6 0 4 + Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is below + ./uaputl.exe sys_cfg_channel_ext 0 0 3 + Set AP to ACS mode, band to 2.4GHz and secondary channel is above. + ./uaputl.exe sys_cfg_channel_ext 0 0 5 + Set AP to ACS mode, band to 2.4GHz and secondary channel is below. + ./uaputl.exe sys_cfg_channel_ext 36 1 2 + Set AP primary radio channel to 36, band to 5GHz and secondary channel is above. + ./uaputl.exe sys_cfg_channel_ext 40 1 4 + Set AP primary radio channel to 40, band to 5GHz and secondary channel is below. + +sys_cfg_rates +------------- + "./uaputl.exe sys_cfg_rates [RATES]" + + If 'Rate' provided, a 'set' is performed else a 'get' is performed + RATES is provided as a set of data rates, in unit of 500 kilobits + A rate with MSB bit is basic rate, i.e 0x82 is basic rate. + + 'set' will not allowed after bss start. + + Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 + Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c + Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc + + Each rate must be separated by a space. + + Example: + ./uaputl.exe sys_cfg_rates 0x82 0x84 0x96 0x0c 0x12 0x18 + ./uaputl.exe sys_cfg_rates + +sys_cfg_rates_ext +----------------- + "./uaputl.exe sys_cfg_rates_ext [rates RATES] [mbrate RATE]" + + If 'Rate' provided, a 'set' is performed else a 'get' is performed. + RATES is provided as a set of data rates, in unit of 500 kilobits + A rate with MSB bit is basic rate, i.e 0x82 is basic rate. + If only operational rates is provided, MCBC rate and unicast rate will be set to auto. + + Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 + Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c + Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc + Rates 2, 4, 11 and 22 (in units of 500 Kbps) must be present in either of + basic or non-basic rates. If OFDM rates are enabled then 12, 24 and 48 (in + units of 500 Kbps) must be present in either basic or non-basic rates. + + Each rate must be separated by a space. + + rates followed by RATES for setting operational rates. + mbrate followed by RATE for setting multicast and broadcast rate. + + operational rates only allow to set before bss start. + + Example: + ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48 mbrate 0x16 + Set AP operation rates to 0x82,0x04,11,0x96,12,24,48, multicast rate to 0x16 + ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48 + Set AP operation rates to 0x82,0x04,11,0x96,12,24,48. + +sys_cfg_tx_power +---------------- + "./uaputl.exe sys_cfg_tx_power [TX_POWER]" + + This command is used to set or get the AP Tx power. + + If no arguments are given, this command returns the current AP Tx power. + + Tx power level is represented in dBm. + + Example: + ./uaputl.exe sys_cfg_tx_power 13 + Set AP Tx power to 13 dBm + + ./uaputl.exe sys_cfg_tx_power + Get AP Tx power + +sys_cfg_bcast_ssid_ctl +---------------------- + "./uaputl.exe sys_cfg_bcast_ssid_ctl [0|1|2]" + + This command is used to set or get the SSID broadcast feature setting. + + The supported options are: + 0 - Disable SSID broadcast, send empty SSID (length=0) in beacon. + 1 - Enable SSID broadcast + 2 - Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length + empty - Get current SSID broadcast setting + + When broadcast SSID is enabled, the AP responds to probe requests from + client stations that contain null SSID. + + When broadcast SSID is disabled (sys_cfg_bcast_ssid_ctl = 0/2), the AP: + 1. Does not respond to probe requests that contain null SSID. + 2. when sys_cfg_bcast_ssid_ctl = 0, generates beacons that contain null SSID (length=0). + 3. when sys_cfg_bcast_ssid_ctl = 2, clear SSID (ACSII 0) in beacon and keep the original length + + Example: + ./uaputl.exe sys_cfg_bcast_ssid_ctl 0 + Disable SSID broadcast, send empty SSID (length=0) in beacon. + + ./uaputl.exe sys_cfg_bcast_ssid_ctl 1 + Enable SSID broadcast + + ./uaputl.exe sys_cfg_bcast_ssid_ctl 2 + Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length + + ./uaputl.exe sys_cfg_bcast_ssid_ctl + Get SSID broadcast setting + +sys_cfg_preamble_ctl +-------------------- + "./uaputl.exe sys_cfg_preamble_ctl" + + This command is used to get type of preamble. + + Example: + ./uaputl.exe sys_cfg_preamble_ctl + Get AP preamble setting + +sys_cfg_bss_status +-------------------- + "./uaputl.exe sys_cfg_bss_status" + + This command is used to get current BSS status. + + Example: + ./uaputl.exe sys_cfg_bss_status + Get current BSS status + +sys_cfg_rts_threshold +--------------------- + "./uaputl.exe sys_cfg_rts_threshold [RTS_THRESHOLD]" + + This command is used to set or get the RTS threshold value. + + If no arguments are given, this command returns the current RTS threshold + value. + + Example: + ./uaputl.exe sys_cfg_rts_threshold 2347 + Set AP RTS threshold to 2347 + + ./uaputl.exe sys_cfg_rts_threshold + Get AP RTS threshold + +sys_cfg_frag_threshold +---------------------- + "./uaputl.exe sys_cfg_frag_threshold [FRAG_THRESHOLD]" + + This command is used to set or get the Fragmentation threshold value. + + If no arguments are given, this command returns the current Fragmentation threshold + value. + + Example: + ./uaputl.exe sys_cfg_frag_threshold 2346 + Set AP Fragmentation threshold to 2346 + + ./uaputl.exe sys_cfg_frag_threshold + Get AP Fragmentation threshold + + Note: Please use aggrpriotbl command to disable the AMPDU/AMSDU aggregation when frag_threshold is set. + +sys_cfg_rsn_replay_prot +----------------------- + "./uaputl.exe sys_cfg_rsn_replay_prot [1|0]" + + This command is used to enable or disable RSN replay protection. + + The supported options are: + 0 - Disable RSN replay protection + 1 - Enable RSN replay protection + empty - Get current RSN replay protection setting + + Example: + ./uaputl.exe sys_cfg_rsn_replay_prot 1 + Enable RSN replay protection + + ./uaputl.exe sys_cfg_rsn_replay_prot + Get RSN replay protection setting + +sys_cfg_tx_beacon_rate +-------------------- + "./uaputl.exe sys_cfg_tx_beacon_rate [TX_BEACON_RATE]" + + This command is used to set or get the Tx beacon rate settings. + + The supported options are: + 0 - Auto rate + >0 - Set specified beacon rate + empty - Get current beacon rate + + Tx beacon rate is represented in units of 500 kbps. While setting Tx beacon + rates, only zero or rates currently configured are allowed. + + Following is the list of supported rates in units of 500 Kbps: + 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 + 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c + + Example: + ./uaputl.exe sys_cfg_tx_beacon_rate 0x04 + Set AP Tx beacon rate to 2 M + + ./uaputl.exe sys_cfg_tx_beacon_rate 4 + Set AP Tx data beacon to 2 M + + ./uaputl.exe sys_cfg_tx_beacon_rate + Get AP Tx beacon rate + +sys_cfg_mcbc_data_rate +---------------------- + "./uaputl.exe sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]" + + This command is used to set or get the MCBC data rate to use for multicast + or broadcast packet transmission. + + The supported options are: + 0 - Auto rate + >0 - Set specified MCBC data rate + empty - Get current MCBC data rate + + MCBC data rate is represented in units of 500 kbps. While setting MCBC data + rates, only zero or one of rates currently configured as basic rates are allowed. + + For example: If current basic rates is "0x82 0x84 0x8b 0x96", then the allowed + values for MCBC data rate will be "0x2 0x4 0xb 0x16". + + Example: + ./uaputl.exe sys_cfg_mcbc_data_rate 22 + Set AP MCBC data rate to 11 M + + ./uaputl.exe sys_cfg_mcbc_data_rate 0 + Set AP MCBC data rate to auto + + ./uaputl.exe sys_cfg_mcbc_data_rate + Get AP MCBC data rate + +sys_cfg_pkt_fwd_ctl +------------------- + "./uaputl.exe sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]" + + This command is used to set or get the packet forwarding control + settings. + + where PKT_FWD_CTRL is: + bit 0 -- Packet forwarding handled by Host (0) or Firmware (1) + bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1) + bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1) + bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1) + empty - Get current packet forwarding setting + + Example: + ./uaputl.exe sys_cfg_pkt_fwd_ctl 1 + Set AP packet forwarding control in firmware to allow all packets + + ./uaputl.exe sys_cfg_pkt_fwd_ctl 6 + Set AP packet forwarding control in Host, only allow Inter-BSS unicast packets forwarding. + + ./uaputl.exe sys_cfg_pkt_fwd_ctl 8 + Set AP packet forwarding control in Host, only allow Intra-BSS packets forwarding. + + ./uaputl.exe sys_cfg_pkt_fwd_ctl 0 + Set AP packet forwarding control in Host, allow Intra-BSS packets and + Inter-BSS unicast packets forwarding. + + ./uaputl.exe sys_cfg_pkt_fwd_ctl + Get AP packet forwarding control + +sys_cfg_sta_ageout_timer +------------------------ + "./uaputl.exe sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]" + + This command is used to set or get the STA ageout value. + + Value of 0 will mean that stations will never be aged out. + + Minimum value for this is 100. Maximum allowed setting should be 864000. + + If no arguments are given, this command returns the current STA ageout + value. + + Ageout timer value is represented in units of 100 ms. + + Example: + ./uaputl.exe sys_cfg_sta_ageout_timer 1800 + Set AP STA ageout time to 180000 ms + + ./uaputl.exe sys_cfg_sta_ageout_timer + Get AP STA ageout time + +sys_cfg_ps_sta_ageout_timer +--------------------------- + "./uaputl.exe sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]" + + This command is used to set or get the PS STA ageout value. + + Value of 0 will mean that stations will never be aged out. + + Minimum value for this is 100. Maximum allowed setting should be 864000. + + If no arguments are given, this command returns the current PS STA ageout + value. + + Ageout timer value is represented in units of 100 ms. + + Example: + ./uaputl.exe sys_cfg_ps_sta_ageout_timer 1800 + Set AP PS STA ageout time to 180000 ms + + ./uaputl.exe sys_cfg_ps_sta_ageout_timer + Get AP PS STA ageout time + +sys_cfg_auth +------------ + "./uaputl.exe sys_cfg_auth [AUTHMODE]" + + This command is used to set or get the AP authentication mode. + + The supported options are: + AUTHMODE : 0 - Open authentication + 1 - Shared key authentication + 255 - Auto (Open and Shared key) authentication + empty - Get current authentication mode + + Example: + ./uaputl.exe sys_cfg_auth 0 + Set AP authentication mode to Open. + + ./uaputl.exe sys_cfg_auth + Get AP authentication mode. + +sys_cfg_protocol +---------------- + "./uaputl.exe sys_cfg_protocol [PROTOCOL] [AKM_SUITE]" + + This command is used to set or get the encryption protocol. + + The supported options are: + PROTOCOL: + 1 No RSN + 2 WEP Static + 8 WPA + 32 WPA2 + 40 WPA, WPA2 Mixed Mode + empty - Get current encryption protocol + + AKM_SUITE: + bit 0 KEY_MGMT_EAP + bit 1 KEY_MGMT_PSK + bit 2 KEY_MGMT_NONE + bit 8 KEY_MGMT_PSK_SHA256 + + Example: + ./uaputl.exe sys_cfg_protocol 2 + Set AP encryption protocol to static WEP. + + ./uaputl.exe sys_cfg_protocol + Get AP encryption protocol. + + ./uaputl.exe sys_cfg_protocol 32 0x102 + Set AP encryption protocol to WPA2 and AKM SUITE to PSK and PSK SHA256 + + ./uaputl.exe sys_cfg_protocol 40 0x100 + Set AP encryption protocol to WPA+WPA2 and AKM SUITE to PSK SHA256 + +sys_cfg_pmf +----------- + "./uaputl.exe sys_cfg_pmf [MFPC] [MFPR]" + + This command is used to set or get the PMF settings. + + The supported options are: + MFPC: 0 - Mgmt frame protection not capable + 1 - Mgmt frame protection capable + + MFPR: 0 - Mgmt frame protection not required + 1 - Mgmt frame protection required + x - don't care if MFPC = 0 + + Example: + ./uaputl.exe sys_cfg_pmf 1 1 + Set AP's PMF params to Mgmt frames protection capable and required. + + ./uaputl.exe sys_cfg_pmf + Get AP's PMF params settings. + +sys_cfg_wep_key +--------------- + "./uaputl.exe sys_cfg_wep_key [INDEX ISDEFAULT Key_0] + [INDEX ISDEFAULT Key_1] + [INDEX ISDEFAULT Key_2] + [INDEX ISDEFAULT Key_3] + [INDEX]" + + This command is used to set or get the WEP key settings. + + The supported options are: + INDEX: 0 - KeyIndex is 0 + 1 - KeyIndex is 1 + 2 - KeyIndex is 2 + 3 - KeyIndex is 3 + ISDEFAULT: 0: KeyIndex is not the default + 1: KeyIndex is the default transmit key + + KEY_* : Key value. + empty - Get current WEP key settings for all the keys + INDEX - Only INDEX will get the key setting for the particular + KeyIndex. + + Example: + ./uaputl.exe sys_cfg_wep_key 0 1 55555 + Set AP's default transmit key to "55555", key index is 0. + + ./uaputl.exe sys_cfg_wep_key 0 1 12345678901234567890123456 + Set AP's default transmit key to "12345678901234567890123456", key index is 0. + + ./uaputl.exe sys_cfg_wep_key + Get AP all the WEP keys settings. + + ./uaputl.exe sys_cfg_wep_key 1 + Get WEP key setting for the KeyIndex = 1. + +sys_cfg_cipher +-------------- + "./uaputl.exe sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]" + + This command is used to set or get the key types for the pairwise and group key. + + The supported options are: + PAIRWISE_CIPHER: + 0 None + 4 TKIP + 8 AES CCMP + 12 AES CCMP + TKIP + GROUP_CIPHER: + 0 None + 4 TKIP + 8 AES CCMP + empty - Get current key types + + Valid combinations of [PAIRWISE_CIPHER GROUP_CIPHER] are: + [0 0], [4 4], [8 8], [12 4]. + + Example: + ./uaputl.exe sys_cfg_cipher 4 4 + Set AP's pairwise and group key's type to TKIP. + + ./uaputl.exe sys_cfg_cipher + Get AP's key types for the pairwise and group key. + +sys_cfg_pwk_cipher +------------------ + "./uaputl.exe sys_cfg_pwk_cipher [] [PAIRWISE_CIPHER]" + + This command is used to set or get protocol and corresponding pairwise cipher settings. + + The supported options are: + PROTOCOL: + 0 None + 8 WPA + 32 WPA2 + PAIRWISE_CIPHER: + 0 None + 4 TKIP + 8 AES CCMP + 12 AES CCMP + TKIP + WPA/TKIP cipher cannot be used when uAP operates in 802.11n mode. + If only PROTOCOL is provided, pairwise cipher for that protocol is displayed. + empty - Get protocol and corresponding pairwise cipher settings. + + Example: + ./uaputl.exe sys_cfg_pwk_cipher 8 4 + Set AP's pairwise cipher to TKIP for WPA protocol. + + ./uaputl.exe sys_cfg_pwk_cipher 32 + Get AP's pairwise cipher for WPA2 protocol. + + ./uaputl.exe sys_cfg_pwk_cipher + Get AP's protocol and corresponding pairwise cipher settings. + +sys_cfg_gwk_cipher +------------------ + "./uaputl.exe sys_cfg_gwk_cipher [GROUP_CIPHER]" + + This command is used to set or get group cipher. + + The supported options are: + GROUP_CIPHER: + 0 None + 4 TKIP + 8 AES CCMP + empty - Get group cipher settings. + + Example: + ./uaputl.exe sys_cfg_gwk_cipher 8 + Set AP's group cipher to AES CCMP. + + ./uaputl.exe sys_cfg_gwk_cipher + Get AP's group cipher settings. + +sys_cfg_group_rekey_timer +------------------------- + "./uaputl.exe sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]" + + This command is used to set or get the AP group re-key time interval, in seconds. + + The supported options are: + GROUP_REKEY_TIMER is represented in seconds. This is only applicable + if the protocol is WPA or WPA2. Value of 0 will disable group re-key. + + empty - Get current group rekey timer + + Example: + ./uaputl.exe sys_cfg_group_rekey_timer 1800 + Set AP's group re-key time interval to 1800 s + + ./uaputl.exe sys_cfg_group_rekey_timer + Get AP's group re-key time interval. + +sys_cfg_wpa_passphrase +---------------------- + "./uaputl.exe sys_cfg_wpa_passphrase [PASSPHRASE]" + + This command is used to set or get the WPA or WPA2 passphrase. + + If no arguments are given, this command returns the current WPA or WPA2 + passphrase. + While setting, the maximum length of the passphrase can be 64 characters. + + Example: + ./uaputl.exe sys_cfg_wpa_passphrase 1234567890 + Set AP's WPA or WPA2 passphrase to "1234567890" + + ./uaputl.exe sys_cfg_wpa_passphrase + Get AP's WPA or WPA2 passphrase. + +sys_cfg_max_sta_num +------------------- + "./uaputl.exe sys_cfg_max_sta_num [STA_NUM]" + + This command is used to set or get the maximum number of stations allowed to connect to uAP. + + If no arguments are given, this command returns the configured maximum number of stations + allowed to connect to uAP and maximum number of stations supported. + + Example: + ./uaputl.exe sys_cfg_max_sta_num 2 + Set AP's maximum station number to 2 + + ./uaputl.exe sys_cfg_max_sta_num + Get AP's maximum station number configured and maximum station number supported. + +sys_cfg_retry_limit +------------------- + "./uaputl.exe sys_cfg_retry_limit [RETRY_LIMIT]" + + This command is used to set or get the retry limit to use for packet transmissions. + + The maximum retry_limit allowed is 14. + + If no arguments are given, this command returns the current retry limit value. + + Example: + ./uaputl.exe sys_cfg_retry_limit 2 + Set AP's retry limit value to 2 + + ./uaputl.exe sys_cfg_retry_limit + Get AP's retry limit value + +sys_cfg_sticky_tim_config +------------------------- + "./uaputl.exe sys_cfg_sticky_tim_config [ENABLE] [ ]" + + This command is used to set or get sticky TIM configuration. + + ENABLE is used to enable or disable sticky TIM feature. + Following are the valid values of ENABLE + 0- disable SticktyTIM + 1- enable StickyTIM (Both DURATION in beacons and STICKY_BIT_MASK must be provided) + 2- enable StickyTIM (enable sticky TIM without changing previous values of + DURATION and STICKY_BIT_MASK) + + When bit 0 of STICKY_BIT_MASK is set, TIM bit is made sticky and when + cleared, normal TIM bit updates resume. + When bit 1 of STICKY_BIT_MASK is set, MoreData bit is made sticky and when + cleared, normal MoreData bit updates resume. + STICKY_BIT_MASK = 0 is NOT a valid configuration value. + + If no argument is given, this command returns current sticky TIM configuration. + + Example: + ./uaputl.exe sys_cfg_sticky_tim_config + Get sticky TIM configuration. + + ./uaputl.exe sys_cfg_sticky_tim_config 0 + Disable sticky TIM feature. + + ./uaputl.exe sys_cfg_sticky_tim_config 1 30 1 + Enable sticky TIM feature with DURATION of 30 beacons and + STICKY_BIT_MASK set to 1. + +sys_cfg_sticky_tim_sta_mac_addr +------------------------------- + "./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]" + + This command is used to set or get sticky TIM control parameter for associated station. + + CONTROL when set to 1, sticky TIM bit for that station is activated. + When set to 0, sticky TIM bit for that station is deactivated. + + If no argument is given, it returns sticky TIM configuration for all associated stations. + If only STA_MAC_ADDRESS is provided, it returns sticky TIM configartion for that station. + + Example: + ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr + Get sticky TIM configuration for all associated stations. + + ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 00:50:43:20:11:22 + Get control parameter for station 00:50:43:20:11:22. + + ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 1 00:50:43:20:11:22 + Set control parameter for station with MAC address 00:50:43:20:11:22 to 1. + + Note:TIM bit for an associated STA is made sticky only if both below mentioned + conditions are satisfied + 1.Enable = 1 or 2 in most recently received sys_cfg_sticky_tim_config command, and + 2.Control = 1 in most recently received sys_cfg_sticky_tim_sta_mac_addr + with this station MAC address. + +sys_cfg_2040_coex +------------------------------- + "./uaputl.exe sys_cfg_2040_coex [ENABLE]" + + This command is used to set or get 20/40 BSS coexistence configuration. + + ENABLE when set to 0, disables 20/40 coex. + When set to 1, enables 20/40 coex. + + If no argument is given, it returns 20/40 BSS coex configuration. + + Example: + ./uaputl.exe sys_cfg_2040_coex + Get 20/40 BSS coexistence configuration. + + ./uaputl.exe sys_cfg_2040_coex 0 + Disable 20/40 BSS coexistence. + + ./uaputl.exe sys_cfg_2040_coex 1 + Enable 20/40 BSS coexistence. + + Note:20/40 BSS coex configuration can be set only before starting BSS. + +sys_cfg_eapol_pwk_hsk +--------------------- + "./uaputl.exe sys_cfg_eapol_pwk_hsk [ ]" + + This command is used to set or get pairwise handshake update timeout and + number of retries. + + Both TIMEOUT and number of RETRIES should be provided for a 'set'. + + If no arguments are given, this command returns timeout value and number + of + retries for pairwise key. + + Example: + ./uaputl.exe sys_cfg_eapol_pwk_hsk 50 2 + Set AP's pairwise key timeout to 50ms and number of retries to 2. + + ./uaputl.exe sys_cfg_eapol_pwk_hsk + Get AP's pairwise key timeout and number of retries. + +sys_cfg_eapol_gwk_hsk +--------------------- + "./uaputl.exe sys_cfg_eapol_gwk_hsk [ ]" + + This command is used to set or get groupwise handshake update timeout and + number of retries. + + Both TIMEOUT and number of RETRIES should be provided for a 'set'. + + If no arguments are given, this command returns timeout value and number + of retries for groupwise key. + + Example: + ./uaputl.exe sys_cfg_eapol_gwk_hsk 50 2 + Set AP's groupwise key timeout to 50ms and number of retries to 2. + + ./uaputl.exe sys_cfg_eapol_gwk_hsk + Get AP's groupwise key timeout and number of retries. + +sta_filter_table +---------------- + "./uaputl.exe sta_filter_table []" + + This command is used to get or set the client station MAC address + filter table. + + The supported options are: + FILTERMODE : 0 - Disable filter table + 1 - Allow mac address specified in the allowed list + 2 - Block MAC addresses specified in the banned list + MACADDRESS_LIST is the list of MAC addresses to be acted upon. Each + MAC address must be separated with a space. Maximum of 16 MAC addresses + are supported. + + empty - Get current client station MAC address filter table. + + Example: + ./uaputl.exe sta_filter_table 0 + Disable filter table + + ./uaputl.exe sta_filter_table 1 00:50:43:20:aa:bb + Set AP's filter mode to allow, only MAC address "00:50:43:ab:bb" will be allowed. + + ./uaputl.exe sta_filter_table + Get AP's filter table settings. + +regrdwr +------- + "./uaputl.exe regrdwr [value]" + + These commands are used to read the MAC, BBP and RF registers from the card. + TYPE can take 3 values, 1 - read/write MAC register + 2 - read/write BBP register + 3 - read/write RF register + + OFFSET specifies the offset location that is to be read. + This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x"). + + value if specified, then that value will be written to that offset in the specified register. Value should be + specified in hexadecimal. + + Example: + ./uaputl.exe regrdwr 1 0xa123 + read MAC register 0xa123 + + ./uaputl.exe regrdwr 1 0xa123 0xaa + write 0xaa to MAC register 0xa123 + + ./uaputl.exe regrdwr 2 0x0123 + read BBP register 0x0123 + + ./uaputl.exe regrdwr 2 0x0123 0xaa + write 0xaa to BBP register 0x0123 + + ./uaputl.exe regrdwr 3 0x0123 + read RF register 0x0123 + + ./uaputl.exe regrdwr 3 0x0123 0xaa + write 0xaa to RF register 0x0123 + +memaccess +--------- + "./uaputl.exe memaccess [value]" + This commands is used to read/write to a memory address + + ADDR specifies the address of the location that is to be read/write + This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x"). + + value if specified, then that value will be written to that address in the specified register. + + Example: + ./uaputl.exe memaccess 0xc00153e4 + read contents of memory location 0xc00153e4 + + + ./uaputl.exe memaccess 0xc00153e4 0xaabbccdd + write value 0xaabbccdd to memory location 0xc00153e4 + +rdeeprom +-------- + "./uaputl.exe rdeeprom " + + This command is used to read bytes from offset location on + EEPROM + + offset: 0,4,8,..., multiple of 4 + bytecount: 4-20, multiple of 4 + + Example: + ./uaputl.exe rdeeprom 200 12 + read 12 bytes from offset 200 ON EEPROM + +cfg_data +-------- + "./uaputl.exe cfg_data [*.conf]" + + This command is used to set/get the configuration data to/from the firmware. + + type: 2 -- cal data + + Example: + ./uaputl.exe cfg_data 2 cal_data.conf + read cal_data from cal_data.conf and download to firmware. + ./uaputl.exe cfg_data 2 + read cal_data from firmware + +sys_cfg_80211d +-------------- + "./uaputl.exe sys_cfg_80211d [state STATE] [country COUNTRY]" + This command is used to set/get 802.11D specific parameters. + If no parameters are provided, this command returns state, country and + domain information. + + Allowed values for state are 0 for disable and 1 for enable. + COUNTRY is a two letter string input (derived from ISO 3166 code; + http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm + ) + + Countries are mapped with specific domain in file "80211d_domain.conf". In + order to set customize band setting, user can modify 80211d_domain.conf + file. + + Example: + ./uaputl.exe sys_cfg_80211d state 0 + To-disable + + ./uaputl.exe sys_cfg_80211d state 1 + To-enable + + ./uaputl.exe sys_cfg_80211d country IN + for using country as INDIA + + ./uaputl.exe sys_cfg_80211d state 1 country US + for enabling and setting country in single command. + +uap_stats +--------- + "./uaputl.exe uap_stats" + This command is used to get uAP statistics. + + Example: + ./uaputl.exe uap_stats + +pscfg +--------- + "./uaputl.exe pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE] + + This command is used to set or get the AP's power mode and power save params. + + The supported options are: + MODE : 0 - disable power mode + 2 - enable inactivity based power save mode + + PS PARAMS: + CTRL: 0 - disable protection frame Tx before PS + 1 - enable protection frame Tx before PS + INACTTO: Inactivity timeout in microseconds, default value is 200000 us + MIN_SLEEP: Minimum sleep duration in microseconds, default value 17000 us + MAX_SLEEP: Maximum sleep duration in microseconds, default value 17000 us + The value of MIN_SLEEP should be >= 5000 us. + The value of MAX_SLEEP should be <= beacon interval(when ctrl: 0). + The value of MAX_SLEEP should be <= 32000 us(when ctrl: 1). + + MIN_AWAKE: Minimum awake duration in microseconds, default value is 2000 us + MAX_AWAKE: Maximum awake duration in microseconds, default value is 2000 us + The value of MIN_AWAKE should be >= 2000 us. + MIN_AWAKE,MAX_AWAKE only valid when MODE is set to inactivity based power save mode. + + + empty - Get current power mode and power save params. + + Example: + ./uaputl.exe pscfg 0 + Disable AP's power mode. + + ./uaputl.exe pscfg 2 + Enable inactivity based power save mode. + + ./uaputl.exe pscfg 2 1 400000 20000 20000 10000 10000 + Enable inactivity based power save mode, enable protection, set inactivity timeout 400000 us + set minimum sleep duration to 20000 us, maximum sleep duration to 20000 us + and set minimum awake duration to 10000us, maximum awake duration to 10000 us + + ./uaputl.exe pscfg + Get current AP's power mode and power save params. + +hscfg +----- + ./uaputl.exe hscfg [condition [[GPIO# [gap]]]] + This command is used to configure the host sleep parameters. + + This command takes one (condition), two (condition and GPIO#) or three + (condition, GPIO# and gap) parameters for set. If no parameter provided, + get is performed. + + where Condition is: + bit 0 = 1 -- broadcast data + bit 1 = 1 -- unicast data + bit 2 = 1 -- mac event + bit 3 = 1 -- multicast data + bit 6 = 1 -- Wakeup when mgmt frame received. + + The host sleep mode will be cancelled if condition is set to 0xffff. + The default is 0x7. + + where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid + GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead). + The default is 0xff. + + where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff + for special setting (host acknowledge required) when GPIO is used to wakeup host. + The default is 200. + + Examples: + ./uaputl.exe hscfg : Get current host sleep mode + ./uaputl.exe hscfg 0xffff : Cancel host sleep mode + ./uaputl.exe hscfg 3 : Broadcast and unicast data + Use GPIO and gap set previously + ./uaputl.exe hscfg 2 3 : Unicast data + Use GPIO 3 and gap set previously + ./uaputl.exe hscfg 2 1 0xa0 : Unicast data + Use GPIO 1 and gap 160 ms + ./uaputl.exe hscfg 2 0xff : Unicast data + Use interface (e.g. SDIO) + Use gap set previously + ./uaputl.exe hscfg 4 3 0xff : MAC event + Use GPIO 3 + Special host sleep mode + ./uaputl.exe hscfg 1 0xff 0xff : Broadcast data + Use interface (e.g. SDIO) + Use gap 255ms + +hssetpara +--------- + ./uaputl.exe hssetpara condition [[GPIO# [gap]]] + This command is used to configure the host sleep parameters. + + Note: + 1) The usages of parameters are the same as "hscfg" command. + 2) The parameters will be saved in the driver and be used when host suspends. + +sta_deauth_ext +-------------- + "./uaputl.exe sta_deauth_ext " + + This command is used to de-authenticate a client station with specific reason code. + + Example: + ./uaputl.exe sta_deauth_ext 00:50:43:20:34:58 4 + deauth station 00:50:43:20:34:58 with IEEE reason code 4 (Disassociated due to inactivity) + +sys_cfg_custom_ie +----------------- + "./uaputl.exe sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]" + + This command is used to set or get custom IEs for management frames. + + The supported options are: + INDEX: 0 - IE Index is 0 + 1 - IE Index is 1 + 2 - IE Index is 2 + MAX IE Index depends on device memory. + + -1 - Append/Delete IE automatically + Delete will delete the IE from the matching IE buffer + Append will append the IE to the buffer with the same mask + MASK : Management subtype mask value as per bit definitions + : Bit 0 - Association request. + : Bit 1 - Association response. + : Bit 2 - Reassociation request. + : Bit 3 - Reassociation response. + : Bit 4 - Probe request. + : Bit 5 - Probe response. + : Bit 8 - Beacon. + MASK : MASK = 0 to clear the mask and the IE buffer + + IEBuffer: IE buffer to set in hexadecimal bytes. + The Buffer should not be space separated. + ( Maximum length = 256 bytes ) + empty - Get IE buffer, subtype mask settings for all the indices [0-3]. + INDEX - Only INDEX will get the IE buffer configured for the particular + Index. + + Example: + ./uaputl.exe sys_cfg_custom_ie + Get IE buffer, subtype mask settings for all indices. + + ./uaputl.exe sys_cfg_custom_ie 1 + Get IE buffer and subtype mask WEP key setting for the Index = 1. + + ./uaputl.exe sys_cfg_custom_ie 2 0 + Clear IE buffer and mask value for Index = 2. + + ./uaputl.exe sys_cfg_custom_ie 3 0x101 0xdd051234567890 + Set IE buffer and mask value for Index = 3. + + ./uaputl.exe sys_cfg_custom_ie -1 0x101 0xdd051234567890 + Append the specified IEBuffer at index with mask value of 0x101 + + ./uaputl.exe sys_cfg_custom_ie -1 0 0xdd051234567890 + Delete the specified IEBuffer from all the IEs. + + ./uaputl.exe sys_cfg_custom_ie 2 0 0xdd051234567890 + Delete the specified IEBuffer from the IEs at index 2. + +coex_config +----------- + "./uaputl.exe coex_config [CONFIG_FILE]" + This command is used to set or get the BT coex configuration settings. + + The supported options are: + CONFIG_FILE is file contain all the BT coex settings. + empty - Get current BT coex settings + + Example: + ./uaputl.exe coex_config + Get current BT coex settings. + + ./uaputl.exe coex_config uapcoex.conf + Load BT coex configuration settings from uapcoex.conf file and set. + +sys_cfg_wmm +----------- + "./uaputl.exe sys_cfg_wmm [qosinfo=] + [0] + [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]" + + This command can be used set/get beacon WMM parameters + + The supported option are: + qosinfo: qos information. User can set only MSB. Valid values are 0x80 and 0x00. + Lower 4 bits are managed by FW. Hence, value read for qosinfo may have + lower 4 bits non-zero. + + AC_BE: 0 + AC_BK: 1 + AC_VI: 2 + AC_V0: 3 + AIFSN: AIFSN value + ECW_MAX: ECW max + ECW_MIN: ECW min + TX_OP: TXOP Limit + empty - Get current WMM parameters + When all the parameter are 0, wmm will be disabled. + + Example: + ./uaputl.exe sys_cfg_wmm 0 3 10 4 0 + Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + + ./uaputl.exe sys_cfg_wmm 1 7 10 4 0 + Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + + ./uaputl.exe sys_cfg_wmm 2 2 4 3 94 + Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94 + + ./uaputl.exe sys_cfg_wmm 3 2 3 2 47 + Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47 + + ./uaputl.exe sys_cfg_wmm + Get current wmm parameters + + ./uaputl.exe sys_cfg_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47 + Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94 + Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47 + + ./uaputl.exe sys_cfg_wmm qosinfo=0x80 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47 + Enable wmm PS mode. + Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94 + Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47 + + ./uaputl.exe sys_cfg_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + ./uaputl.exe sys_cfg_wmm 0 + Disable wmm + +sys_cfg_ap_wmm +----------- + "./uaputl.exe sys_cfg_ap wmm [0] + [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP] + [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]" + + This command can be used set/get AP WMM parameters + + The supported option are: + AC_BE: 0 + AC_BK: 1 + AC_VI: 2 + AC_V0: 3 + AIFSN: AIFSN value + ECW_MAX: ECW max + ECW_MIN: ECW min + TX_OP: TXOP Limit + empty - Get current AP WMM parameters + When all the parameter are 0, AP wmm will be disabled. + + Example: + ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0 + Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + + ./uaputl.exe sys_cfg_ap_wmm 1 7 10 4 0 + Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + + ./uaputl.exe sys_cfg_ap_wmm 2 2 4 3 94 + Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94 + + ./uaputl.exe sys_cfg_ap_wmm 3 2 3 2 47 + Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47 + + ./uaputl.exe sys_cfg_ap_wmm + Get current AP wmm parameters + + ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47 + Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0 + Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94 + Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47 + + ./uaputl.exe sys_cfg_ap_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + ./uaputl.exe sys_cfg_ap_wmm 0 + Disable AP wmm + +addbapara +--------- + "./uaputl.exe addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu]" + This command can be used to update the default ADDBA parameters. + + The supported options are: + timeout - This is the block ack timeout for ADDBA request. + 0 : Disable (recommended for throughput test) + 1 - 65535 : Block Ack Timeout in TU + txwinsize - Buffer size for ADDBA request. (32 is default value) + rxwinsize - Buffer size for ADDBA response. (16 is default value) + txamsdu - amsdu support for ADDBA request. (1 is default value) + 0 : Disable amsdu in ADDBA request. + 1 - Enable amsdu in ADDBA request. + rxamsdu - amsdu support for ADDBA response. (1 is default value) + 0 : Disable amsdu in ADDBA response. + 1 - Enable amsdu in ADDBA response. + empty - Get current ADDBA parameters. + + Current window size limit for Tx as well as Rx is 1023. + + Example: + ./uaputl.exe addbapara + Get the current addba params + ./uaputl.exe addbaparam 1000 64 8 0 0 + This will change the ADDBA timeout to (1000 * 1024) us, txwinsize to 64 and rxwinsize to 8 + and disable AMSDU in ADDBA request/response. + + In case the ADDBA timeout value is updated then a ADDBA is sent for all streams + to update the timeout value. + + In case txwinsize and/or rxwinsize is updated, the effect could only be seen on + next ADDBA request/response. The current streams will not be affected with this + change. + + In case of txamdsdu/rxamsdu is updated, the effect could only be seen on + next ADDBA request/response. The current streams will not be affected with this + change. AMSDU in AMPDU stream will be enabled when AP support this feature + and AMSDU is enabled in aggrpriotbl. + +sys_cfg_11n +----------- + "./uaputl.exe sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_CAP]" + This command can be used set/get 802.11n parameters. + + The supported option are: + ENABLE: 0 - disable 802.11n in uap + 1 - enable 802.11n in uap + Note: If 802.11n is disabled, 802.11ac MUST be disabled at the same time + HTCAP: HT Capabilities info (default value is 0x111c) + Bit 15-13: Reserved set to 0 + Bit 12: DSS/CCK mode in 40MHz enable/disable + Bit 11-10: Reserved set to 0 + Bit 9-8: Reserved set to 0x01 + Bit 7: STBC enable/disable + Bit 6: Short GI in 40 Mhz enable/disable + Bit 5: Short GI in 20 Mhz enable/disable + Bit 4: Green field enable/disable + Bit 3-2: Reserved set to 1 + Bit 1: 20/40 Mhz enable disable. + Bit 0: LDPC enable/disable + AMPDU: A-MPDU Parameter (default value is 0x03) + Bit 7-5: Reserved set to 0 + Bit 4-2: Minimum MPDU Start spacing + Set to 0 for no restriction + Set to 1 for 1/4 us + Set to 2 for 1/2 us + Set to 3 for 1 us + Set to 4 for 2 us + Set to 5 for 4 us + Set to 6 for 8 us + Set to 7 for 16 us + Bit 1-0: Max A-MPDU length + TXBFCAP: TX Beamforming capabilities + Bit 0 : Implicit TX BF receiving capable + Bit 1 : RX staggered sounding capable + Bit 2 : TX staggered sounding capable + Bit 3 : RX NDP capable + Bit 4 : TX NDP capable + Bit 5 : Implicit TX BF capable + Bit 6-7 : Calibration + 0: - not supported + 1: - STA can respond to a calibration request using + the CSI Report, but cannot initiate calibration + 2: - reserved + 3: - STA can both initiate and respond to a calibration request + Bit 8 : Explicit CSI TX BF capable + Bit 9 : Explicit non-compressed steering capable + Bit 10 : Explicit compressed steering capable + Bit 11-12: Explicit TX BF CSI feedback + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 13-14: Explicit non-compressed BF feedback capable + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 15-16: Explicit compressed BF feedback capable + 0: - not supported + 1: - delayed feedback + 2: - immediate feedback + 3: - delayed and immediate feedback + Bit 17-18: Minimal grouping + 0: - no grouping (STA supports groups of 1) + 1: - groups of 1, 2 + 2: - groups of 1, 4 + 3: - groups of 1, 2, 4 + Bit 19-20: CSI number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 21-22: Non-compressed steering number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 23-24: Compressed steering number of beamformer antennas supported + 0: - single TX antenna sounding + 1: - 2 TX antenna sounding + 2: - 3 TX antenna sounding + 3: - 4 TX antenna sounding + Bit 25-26: CSI max number of rows beamformer supported + 0: - single row of CSI + 1: - 2 rows of CSI + 2: - 3 rows of CSI + 3: - 4 rows of CSI + Bit 27-28: Channel estimation capability + 0: - 1 space time stream + 1: - 2 space time streams + 2: - 3 space time streams + 3: - 4 space time streams + Bit 29-31: Reserved + HT_MCS_MAP: MCS rate bitmap + Bit 0-7 : MCS_SET_0 + Bit 15-8 : MCS_SET_1 + empty - Get current 802.11n parameters. + + Example: + ./uaputl.exe sys_cfg_11n 1 0x117e 3 + enable 802.11n, and set HT Capabilities info to 0x117e, and A-MPDU Parameter to 0x03 + ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF + enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU + Parameter to 0x03 and TX Beamforming capabilities to 0xFFFFFFFF + ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF 0x00100023 + enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU + Parameter to 0x03, TX Beamforming capabilities to 0xFFFFFFFF and + MCS rate bitmap to 0x00100023. + ./uaputl.exe sys_cfg_11n 0 + disable 802.11n in uap + ./uaputl.exe sys_cfg_11n + Get current 802.11n parameters + +aggrpriotbl +----------- + "./uaputl.exe aggrpriotbl ... " + This command is used set/get the priority table for AMPDU/AMSDU traffic per tid. + This command can also be used to disable AMPDU/AMSDU for a given tid. + In case of AMPDU this priority table will be used to setup block ack (to make + sure the highest priority tid always uses AMPDU as we have limited AMPDU streams) + + The supported option are: + ... + + - This is priority for Tid0 for AMPDU packet. A priority could be any + values between 0 - 7, 0xff to disable aggregation. + - This is priority for Tid0 for AMSDU packet. A priority could be any + values between 0 - 7, 0xff to disable aggregation. + + empty - Get current priority table for AMPDU/AMSDU traffic. + + Example: + ./uaputl.exe aggrpriotbl + This command will get the current Priority table for AMPDU and AMSDU. + <2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255>. This is read as + <"Prio for AMPDU for Tid0" "Prio for AMSDU for Tid0" + "Prio for AMPDU for Tid1" "Prio for AMSDU for Tid1" and so on + + ./uaputl.exe aggrpriotbl 2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255 + This will set the priority table for AMPDU and AMSDU + Priority for Tid0/AMPDU = 2, Tid0/AMSDU = 2, Tid1/AMPDU = 0, Tid1/AMSDU = 0 + and so on. Aggregation for Tid6 and Tid7 are disabled. + Here higher the priority number, higher the priority (i.e. 7 + has higher priority than 6). Similarly for AMSDU. + + ./uaputl.exe aggrpriotbl 0xff 2 0xff 0 0xff 1 0xff 3 0xff 4 0xff 5 0xff 0xff 0xff 0xff + This will disable AMPDU for all the TIDs but will still keep AMSDU enabled to Tid0 to Tid5 + + The default setting is 2 255 0 255 1 255 3 255 4 255 5 255 255 255 255 255. + + A delBA should be seen in case a disable happens on a TID for which AMPDU stream + is currently setup. + + Note:- This command should only be issued in disconnected state. + +addbareject +----------- + "./uaputl.exe addbareject ... " + This command is used set/get the addbareject table for all the TIDs. + This command can also be used to enable rejection of ADDBA requests for a given tid. + + The supported option are: + ... + - This can be 0/1 for TidX. 1 enables rejection of ADDBA request for TidX and + 0 would accept any ADDBAs for TidX. + empty - Get current addbareject table for all the TIDs. + + Example: + ./uaputl.exe addbareject + This command will get the current table. + [0 0 0 0 0 0 1 1]. ADDBA would be accepted for all TIDs except for TID [6,7]. + This is the default state. + + ./uaputl.exe addbareject 0 0 1 1 0 0 0 0 + This command will accept ADDBA requests for Tid [0,1,4,5,6,7] and reject ADDBA requests for Tid [2,3] + + ./uaputl.exe addbareject 1 1 1 1 1 1 1 1 + This will enable rejection of ADDBA requests for all Tids. + + Note:- This command should only be issued in disconnected state. + +sys_cfg_tdls_ext_cap +-------------------- + + "./uaputl.exe sys_cfg_tdls_ext_cap [CONFIG_FILE]" + + This command is used to set/get TDLS extended capability settings. + + If CONFIG_FILE is provided, a SET is performed , else a GET is performed. + + Examples: + ./uaputl.exe sys_cfg_tdls_ext_cap config/tdls_ext_cap.conf + Set TDLS extended capability parameters in the config file. + ./uaputl.exe sys_cfg_tdls_ext_cap + Get TDLS extended capability parameters. + + "./uaputl.exe skip_cac []" + + This command is used to set/get SKIP_CAC feature. If enabled then next BSS + start would skip the channel availability check (CAC). The mode will be + disabled automatically once BSS_START is performed. + + MODE : 0 - Disable skip CAC mode + 1 - Enable skip CAC mode + + eg., + ./uaputl.exe skip_cac ==> GET current configured mode + ./uaputl.exe skip_cac 1 ==> enables skip_cac mode + ./uaputl.exe skip_cac 0 ==> disable skip_cac mode + +httxbfcfg +--------- + "./uaputl.exe httxbfcfg [ACT_DATA]" + + This command is used to configure the TX beamforming options. + + The supported options are: + ACTION: 0 - Control global parameters for beamforming + 1 - Performs NDP Sounding for PEER + 2 - TX BF interval in milliseconds + 3 - Enable/Disable beamforming/sounding for the indicated peer. + 4 - TX BF SNR Threshold for peer + ACT_DATA: Specific data for the above actions + For ACTION 0 - Beamforming enable/disable, sounding enable/disable, + FB type, snr_threshold, sounding interval, Beamformig mode + For ACTION 1 - PEER MAC and status + For ACTION 2 - TX BF interval + For ACTION 3 - PEER MAC + For ACTION 4 - PEER MAC and SNR + empty - Get action specific settings + + Examples: + ./uaputl.exe httxbfcfg 0 : Get current global configuration parameter + ./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64 : Get the TX BF periodicity for a given peer + ./uaputl.exe httxbfcfg 3 : Get the list of MAC addresses that have + beamforming and/or sounding enabled + ./uaputl.exe httxbfcfg 4 : Get the list of PEER MAC, SNR tuples + programmed into the firmware. + ./uaputl.exe httxbfcfg 0 0 0 3 10 500 5 : Disable beamforming, sounding, set FB type + to 3, snr threshold to 10, sounding interval + to 500 ms and beamforming mode to 5 + ./uaputl.exe httxbfcfg 1 00:50:43:20:BF:64 : Perform NDP Trigger sounding to peer + 00:50:43:20:BF:64 + ./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64 500 : Set TX BF periodicity for peer 00:50:43:20:BF:64 + to 500 milliseconds + ./uaputl.exe httxbfcfg 3 00:50:43:20:BF:43 1 0 3 : Enable beamforming, disable sounding and set + FB type to 3 for peer 00:50:43:20:BF:43 + ./uaputl.exe httxbfcfg 4 00:50:43:20:BF:24 43 : Set TX BF SNR threshold to peer + + +httxcfg + This command is used to configure various 11n specific configuration + for transmit (such as Short GI, Channel BW and Green field support) + + where is + This is a bitmap and should be used as following + Bit 15-10: Reserved set to 0 + Bit 9-8: Rx STBC set to 0x01 + BIT9 BIT8 Description + 0 0 No spatial streams + 0 1 One spatial streams supported + 1 0 Reserved + 1 1 Reserved + Bit 7: STBC enable/disable + Bit 6: Short GI in 40 Mhz enable/disable + Bit 5: Short GI in 20 Mhz enable/disable + Bit 4: Green field enable/disable + Bit 3-2: Reserved set to 1 + Bit 1: 20/40 Mhz enable disable. + Bit 0: LDPC enable/disable + + When Bit 1 is set then firmware could transmit in 20Mhz or 40Mhz based + on rate adaptation. When this bit is reset then firmware will only + transmit in 20Mhz. + + Example: + ./uaputl.exe -i uapX httxcfg + This will display HT Tx configuration. + + ./uaputl.exe -i uapX httxcfg 0x62 + This will enable 20/40 and Short GI but will disable Green field. + + ./uaputl.exe -i uapX httxcfg 0x30 + This will enable Short GI 20 Mhz and Green field. + + Note:- If 20/40 MHz support is disabled in htcapinfo, device will not transmit + in 40 MHz even 20/40 MHz is enabled in httxcfg. + +htstreamcfg + This command is used to set/get HT stream configuration. + The setting only takes effect in next association. + + Usage: + ./uaputl.exe -i uapX htstreamcfg [n] + + where + 0x11: HT stream 1x1 mode + 0x22: HT stream 2x2 mode + + Examples: + ./uaputl.exe -i uapX htstreamcfg : Get current setting + ./uaputl.exe -i uapX htstreamcfg 0x11 : Set HT stream 1x1 mode + ./uaputl.exe -i uapX htstreamcfg 0x22 : Set HT stream 2x2 mode + +deepsleep +--------- + "./uaputl.exe deepsleep [MODE] [IDLE_TIME]" + This command is used to set/get auto deep sleep mode. + + The supported option are: + [MODE]: Enable/disable auto deep sleep mode (1/0) + [IDLE_TIME]: Idle time in milliseconds after which firmware will put the device + in deep sleep mode. Default value is 100 ms. + empty - Get current deep sleep mode. + + Example: + ./uaputl.exe deepsleep : Display auto deep sleep mode + ./uaputl.exe deepsleep 1 : Enable auto deep sleep mode, idle time unchanged + ./uaputl.exe deepsleep 0 : Disable auto deep sleep mode + ./uaputl.exe deepsleep 1 500 : Enable auto deep sleep mode with idle time 500 ms + + Note: + Deepsleep must be disabled before changing idle time. + +txpwrlimit_cfg_get +txpwrlimit_2g_cfg_set +txpwrlimit_5g_cfg_set +------------------ + This command is used to set/get the configuration data of Tx power limitation. + Note: The configuration set should be issued when no STA is connected. + + Examples: + ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get + ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set + ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set + +rxpktcoal_cfg +------------- + "./uaputl.exe rxpktcoal_cfg [PKT-THRESHOLD] [TIMEOUT]" + + This is used to get/set RX packet coalescing paramters + + The supported option are: + [PKT-THRESHOLD]: count after which packets would be sent to host. Valid values 1-7 + [TIMEOUT]: timeout in ms after which packets would be sent to host. Valid values 1-4 + Coalescing is disabled if both or either of packet_thershold and delay is zero + + RX packet coalescing parameters can be changed only when device is in + idle state i.e. all interfaces are disconnected. + + Example: + ./uaputl.exe rxpktcoal_cfg : Display RX packet coalescing settings + ./uaputl.exe rxpktcoal_cfg 5 1 : Enable RX packet coalescing: packet count 5, delay 1. + ./uaputl.exe rxpktcoal_cfg 0 0 : Disable RX packet coalescing. + +tx_data_pause +------------- + "./uaputl.exe tx_data_pause [ENABLE][TX_BUF_CNT]" + + This command is used to set/get tx data pause settings. + + The supported option are: + [ENABLE]: Enable/disable pause tx events from firmware to host. + [TX_BUF_CNT]: Max number of TX buffers allowed for all PS clients + empty - Get current tx data pause settings + + Example: + ./uaputl.exe tx_data_pause : Display tx data pause settings + ./uaputl.exe tx_data_pause 1 : Enable pause tx event, max tx buffer number unchanged. + ./uaputl.exe tx_data_pause 0 : Disable pasue tx event, max tx buffer number unchanged. + ./uaputl.exe tx_data_pause 1 15 : Enable pause tx event, with max tx buffer number 15. + +vhtcfg + This command is used to set and get various 11ac specific configuration + for transmission and reception. For the SET operation, all paramaters + may be applied. For the GET operation, only the first two parameters are applied. + The 6th argument "rx_mcs_set" can be used to disbale/enable 802.11ac. + + where is + - This is the band setting for the vhtcfg + 0: Settings for both 2.4G and 5G bands (for SET operation, 11N BW only) + 1: Settings for 2.4G band (for 11N BW only) + 2: Settings for 5G band + + where is + - This parameter specifies the configuration of VHT operation for TX or/and VHT capabilities + 3: configuration of VHT capabilities (uAP only) + Note: For the UAP, only 3 is supported for txrx. + + where [l] is + - This parameter specifies the bandwidth (BW) configuration + applied to the vhtcfg. + If is 3 (For uAP), + 0: Tx BW follows the BW (20/40 MHz) from 11N CFG + 1: Tx BW follows the BW (80/160/80+80 MHz) from VHT Capabilities + defined in below for 5G band. + + where [m] is + - This parameter specifies the VHT capabilities info if is 2 (association) + or the VHT Tx operations if is 1 (Tx operations). + The VHT Tx operation should be a subset of VHT capabilities for association. + It is a bitmap and should be used as follows: + + Bit 31-30: Reserved and set to 0 + Bit 29: TX antenna pattern consistency + 1: antenna pattern does not change + 0: antenna pattern might change + Bit 28: RX antenna pattern consistency + 1: antenna pattern does not change + 0: antenna pattern might change + Bit 27-26: VHT link adaptation capable + 0: no feedback of VHT MFB from the STA + 1: unsolicted feedback of VHT MFB from the STA + 2: both response and unsolicted feedback of VHT MFB + from the STA + 3: reserved and set to 0 + Bit 25-23: Maximum A-MPDU length exponent + Bit 22: +HTC-VHT capable (1: enable. 0 disable) + Bit 21: VHT TXOP PS + Bit 20: MU beamformee capable (1: enable. 0 disable) + Bit 19: MU beamformer capable (1: enable. 0 disable) + Bit 18-16: Number of sounding dimensions (set to maximum-1 + if Bit 11 is 1. Otherwise, reserved and set to 0) + Bit 15-13: Compressed steering number of beamformer + antennas supported (set to maximum-1 if Bit 12 is 1. + Otherwise, reserved and set to 0) + Bit 12: SU beamformee capable (1: enable. 0 disable) + Bit 11: SU beamformer capable (1: enable. 0 disable) + Bit 10-8: Rx STBC + 0: no support + 1: support of 1 spatial stream + 2: support of 1-2 streams + 3: support of 1-3 spatial streams + 4: support of 1-4 spatial streams + 5-7: reserved and set to 0 + Bit 7: TX STBC (1: enable. 0 disable) + Bit 6: Short GI for 160 and 80+80 MHz (1: enable. 0 disable) + Bit 5: Short GI for 80 MHz (1: enable. 0 disable) + Bit 4: Rx LDPC (1: enable. 0 disable) + Bit 3-2: Supported channel width set. + 0: no support of either 160 or 80+80 MHz. + 1: support of 160 MHz + 2: support of both 160 and 80+80 MHz. + 3: reserved and set to 0. + Bit 1-0: Maximum MPDU length + 0: 3895 octets. + 1: 7991 octets. + 2: 11454 octets. + 3: reserved and set to 0. + + where [n] is , + - This parameter specifies the TX MCS map. It may not be used for the STA if is 1 (Tx operations). + It is a bitmap and should be used as following + Bit 15-0: MCS map, which is defined as folows: + Bit 15-14: Max MCS for 8 SS + Bit 13-12: Max MCS for 7 SS + Bit 11-10: Max MCS for 6 SS + Bit 9-8: Max MCS for 5 SS + Bit 7-6: Max MCS for 4 SS + Bit 5-4: Max MCS for 3 SS + Bit 3-2: Max MCS for 2 SS + Bit 1-0: Max MCS for 1 SS + + where [o] is . + - This parameter specifies the RX MCS map. It may not be used for the STA if is 1 (Tx operations). + It is a bitmap with the same sructure as for + rx_mcs_map = 0xffff : FW will disable 802.11ac + rx_mcs_map = others : FW will enable 802.11ac + + Note: The user setting of vhtcap may be overwritten by the driver + if the setting of those fields is beyond the hardware capabilities. + + Examples: + ./uaputl.exe -i uapX vhtcfg 2 3 : Get current VHT configuration in 5GHz for the uAP. + ./uaputl.exe -i uapX vhtcfg 2 3 0 0x000001f0 0xfffa 0xfffa + : Set the current/maximum VHT configuration in 5GHz for the uAP. + Both Tx and Rx supports MCS 0-9 for both 1 and 2 spatial streams. + ./uaputl.exe -i uapX vhtcfg 2 3 0 0x000001b0 + : Set the VHT capability information in 5GHz for the uAP, and keep the Tx/Rx MCS Map same as before. + +dfstesting +---------- + "./uaputl.exe dfstesting [ ]" + + This command is used to set/get DFS testing settings. + + The supported option are: + : user-configured Channel Availability Check in msec + 0 = disable, use default period (60000) + 1-65535 = enable with that period + : user-configured Non-Occupancy Period in sec + 0 = disable, use default period (1800) + 1-65535 = enable with that period + : enable/disable no channel change on radar + 0 = disable, 1 = enable (overrides below) + : user-configured channel to change to on radar + 0 = disable, 1-255 = enable with that channel + (channel validity for region, etc. is not checked) + (only takes effect if no_chan_change = 0) + + Example: + ./uaputl.exe dfstesting : Get current dfstesting settings + ./uaputl.exe dfstesting 2000 0 0 0 : user_cac=2sec, others disabled/default + ./uaputl.exe dfstesting 0 0 1 0 : only no_chan_change enabled + ./uaputl.exe dfstesting 0 120 0 64 : user_nop=2min, force chan 64 on radar + +cscount +--------------- + + "./uaputl.exe cscount []" + + This command is used to configure the number of beacons AP sends with channel switch IE, before channel change due to + radar detection. If not configured, is set to 5 by default. + + The supported options are: + : user configured channel switch count + 5-20 = configure with that value + + Example: + ./uaputl.exe cscount : Get user configured channel switch count value + ./uaputl.exe cscount 10 : Set channel switch count to 10 + + +mgmtframectrl +------------- + "./uaputl.exe mgmtframectrl [MASK]" + + This command is used to set/get management frame control mask. + + where the parameter [MASK] is the bit mask of management frame reception. + Following are the bit definitions. + Bit 0 : Association Request + Bit 1 : Association Response + Bit 2 : Re-Association Request + Bit 3 : Re-Association Response + Bit 4 : Probe Request + Bit 5 : Probe Response + Bit 8 : Beacon Frames + + Example: + ./uaputl.exe mgmtframectrl 0x101 + Set management frame control mask to 0x101. + +restrict_client_mode +-------------------- + "./uaputl.exe restrict_client_mode [ [MODE_CONFIG]]" + + This command is used to set/get the mode in which the ex-Stations can connect to the uAP. + If no arguments are given, this command returns the current configuration. + By default this feature will be disabled. + [ENABLE]: + 1: Enable the feature. + 0: Disable the feature. + [MODE_CONFIG]: config mode. + Bit 0: B only Mode. + Bit 1: A only Mode. + Bit 2: G only Mode. + Bit 3: N only Mode. + Bit 4: AC only Mode. + + Example: + ./uaputl.exe restrict_client_mode 1 0x8. + Only N mode clients will be able to connect. Association will fail for other clients. + + ./uaputl.exe restrict_client_mode 0. + This feature is disabled. + + Note: + The set operation should be performed before bss is started. + User should make sure that the mode advertized by uAP in beacons + (i.e. combination of supported/extended rates IE and capability IEs) + is superset of the mode allowed for ex-STA associations using this TLV. + +uap_oper_ctrl +------------- + "./uaputl.exe uap_oper_ctrl [control] [chanopt] [bandcfg] [channel]" + + This command is used to set/get uAP operation control when in-STA disconnected with ext-AP. + If no arguments are given, this command returns the current configuration. + + The supported options are: + : 0 default, do nothing + 2 uAP stops and restart automatically + Specify which channel should be used when uap restarts automatically + 1: uap restarts on default 2.4G/channel 6 + 2: uap restart on band/channel configured by driver previously + 3: uap restart on band/channel configured by parameter bandcfg/channel + This parameter specifies the bandwidth when chanopt is 3 + 0: 20Mhz + 2: 40Mhz + 3: 80Mhz + This parameter specifies the channel will be used when chanopt is 3 + + Example: + ./uaputl.exe uap_oper_ctrl 2 1 + uap stops and restart automatically when in-STA disconnects with ext-AP, + and restart on default 2.4G/channel 6. + + ./uaputl.exe uap_oper_ctrl 2 2 + uap stops and restart automatically when in-STA disconnects with ext-AP, + and restart on band/channel configured by driver previously. + + ./uaputl.exe uap_oper_ctrl 2 3 2 36 + uap stops and restart automatically when in-STA disconnects with ext-AP, + and restart on channel 36, bandwidth 40. + + ./uaputl.exe uap_oper_ctrl 0 + when in-STA disconnects with ext-AP, uap will stay on current operation channel. + + ./uaputl.exe uap_oper_ctrl + Get current uap operation control setting. +=============================================================================== + U S E R M A N U A L F O R MLANEVENT + +NAME +mlanevent.exe + +This tool can be used to listen for and obtain events from the uAP driver +through the netlink layer. + +---------------- +Supported events +---------------- +STA_DEAUTH +STA_ASSOC +BSS_START +BSS_IDLE +BSS_ACTIVE + +----------------- +Details of events +----------------- + +STA_DEAUTH +---------- + For this event, the following information is shown: + + Deauthenticated STA MAC address. + + Reason for deauthentication. + +STA_ASSOC +--------- + For this event, the following information is shown: + + STA MAC address. + +BSS_START +--------- + For this event, the following information is shown: + + AP MAC address. + +BSS_IDLE +-------- + For this event, there is no associated information. + +BSS_ACTIVE +---------- + For this event, there is no associated information. + +=============================================================================== + U S E R M A N U A L F O R IWPRIV + +NAME + This manual describes the usage of private commands used in Marvell MLAN + Linux UAP Driver. + + To use parameters as hex format, a '0x' must precede it for the parameters to + be parsed properly. + +SYNOPSIS + iwpriv [sub-command] ... + + iwpriv uapX version + iwpriv uapX verext + iwpriv uapX start + iwpriv uapX stop + iwpriv uapX bssstart + iwpriv uapX bssstop + iwpriv uapX fwreload + iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC,][KEY,] + [CHANNEL,][PREAMBLE,][MAX_SCB,][END]" + +DESCRIPTION + Those commands are used to send additional commands to the Marvell MLAN + card via the Linux device driver. + + The uapX parameter specifies the network device that is to be used to + perform this command on. It could be uap0, uap1 etc. + +version + This is used to get the current version of the driver and the firmware. + +verext + Retrieve and display an extended version string from the firmware + + Usage: + iwpriv uapX verext [#] + + where [#] is an optional argument to retrieve a specific version string, + omission of the argument retrieves the 0 indexed string. + +start + Start the uAP driver. + + Usage: + iwpriv uapX start + +stop + Stop the uAP driver. + + Usage: + iwpriv uapX stop + +bssstart + Start the AP mode, so that uAP will start transmitting beacon. + + Usage: + iwpriv uapX bssstart + +bssstop + Stop the AP mode and disconnect all stations. uAP will stop + transmitting beacon as well. + + Usage: + iwpriv uapX bssstop + +fwreload + Reload the firmware. Here string "FW_PATH=" in the path + argument is mandatory part. + + Usage: + iwpriv uapX fwreload + +apcfg + This command is used to set the AP configurations. Here string + "ASCII_CMD=AP_CFG" is minimum requirement in the ASCII string. + Note: BSS will be stopped then restarted if BSS is already started + when the command is received. + + Usage: + iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC=sec,] + [KEY=key,][CHANNEL=channel,][MAX_SCB=max_scb,][END]" + + Where the parameters are: + SSID: Set SSID to be used in beacon and probe response + [SEC]: Security modes - open, wep128, wpa-psk or wpa2-psk + 11n will be auto disabled in wep128 and wpa-psk mode + [KEY]: Encrypted key for wep128, wpa-psk or wpa2-psk, minimum 8 chars + [CHANNEL]: Channel to be selected + [MAX_SCB]: Maximum STA number + [END]: Optional termination in ASCII string + + Examples: + iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP" + : Set AP SSID to "TEST_uAP" + iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=open" + : Set AP SSID to "TEST_uAP" and + security mode is disabled + iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=WPA2-PSK,KEY=ecbe5facdbfe234a" + : Set AP SSID to "TEST_uAP" and security mode + to WPA2-SPK and encrypted key ecbe5facdbfe234a + iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,CHANNEL=8" + : Set AP SSID to "TEST_uAP" and + set the AP channel to 8 + +=============================================================================== diff --git a/mwifiex_8997/README_WIFIDIRECT b/mwifiex_8997/README_WIFIDIRECT new file mode 100755 index 0000000..b56602a --- /dev/null +++ b/mwifiex_8997/README_WIFIDIRECT @@ -0,0 +1,448 @@ + +=============================================================================== + + S E T U P I N S T R U C T I O N S F O R *WifiDirect* + +Driver,FW release: + +1. Make sure, bg_scan.conf,uaputl.conf has SSID starting with "DIRECT-" +2. Download uAP configuration and BG scan configuration. +3. This version of wifidirectutl breaks the backward compatibility and will work +with following releases - + 8797 >= 14.xx.16.p15 + >= 14.xx.11.p138 + 8766 >= 14.xx.11.p138 + 8787 >= 14.xx.9.p89 + + However, In case one needs to run the utility in backward compatibility mode + he can do so by running following command before running the utility - + + # export WIFIDIR_USE_FIXED_IE_INDICES=1 + + To disable backward comaptibility mode run following command - + + # export WIFIDIR_USE_FIXED_IE_INDICES=0 + +WPSWIFIDIRECT release: + +1. Modify the wifidirect.conf file to specify the correct HW addresses of + devices. The DUT mac address and peer mac address needs to be correctly + entered. + +=============================================================================== + U S E R M A N U A L F O R WIFIDIRECTUTL + +NAME + wifidirectutl + +This tool can be used to configure WifiDirect parameters. + +------------------ +Supported Commands +------------------ +wifidirect_mode [MODE] +wifidirect_config [*.conf] +wifidirect_params_config [*.conf] +wifidirect_action_frame <*.conf> | [ ] +wifidirect_discovery_request <*.conf> +wifidirect_discovery_response <*.conf> + +wifidirect_cfg_discovery_period [ ] +wifidirect_cfg_intent [IntentValue] +wifidirect_cfg_capability [ ] +wifidirect_cfg_noa [ ] +wifidirect_cfg_opp_ps [] +wifidirect_cfg_invitation_list [mac_addr] +wifidirect_cfg_listen_channel [ListenChannel] +wifidirect_cfg_op_channel [OperatingChannel] +wifidirect_cfg_persistent_group_record [index] [role] + [ ] [peermac1] [peermac2] +wifidirect_cfg_persistent_group_invoke [index] | +wifidirect_cfg_presence_req_params [ ] +wifidirect_cfg_ext_listen_time [ ] +wifidirect_cfg_provisioning_params [ ] +wifidirect_cfg_wps_params [] + +wifidirect_mode [mode] +---------- + "./wifidirectutl wifidirect_mode [mode]" + + This command is used to setup various modes for wifidirect device. + The mode 2 can be used only when wifidirect is started using mode 1. + The mode 3 should not be used for uAP. + + The supported options are: + mode : 0 - stop wifidirect mode + 1 - start wifidirect mode + 2 - start wifidirect group owner mode + 3 - start wifidirect client mode + 4 - start wifidirect find phase + 5 - stop wifidirect find phase + empty - Get current wifidirect mode + + Example: + ./wifidirectutl wifidirect_mode 0 + Stop wifidirect mode. + + ./wifidirectutl wifidirect_mode 1 + Start wifidirect mode. + + ./wifidirectutl wifidirect_mode + Get current WIFIDIRECT start/stop mode. + +wifidirect_config +---------- + "./wifidirectutl wifidirect_config [*.conf]" + + This command is used to set/get the wifidirect configuration. + + Example: + ./wifidirectutl wifidirect_config wifidirect.conf + Read configuration from wifidirect.conf and apply it. + ./wifidirectutl wifidirect_config + Read existing wifidirect configuration and display it. + +wifidirect_params_config +---------- + "./wifidirectutl wifidirect_params_config [*.conf]" + + This command is used to set/get the wifidirect parameters configuration. + + Example: + ./wifidirectutl wifidirect_params_config wifidirect.conf + Read parameter configuration from wifidirect.conf and apply it. + ./wifidirectutl wifidirect_params_config + Read existing wifidirect parameters's configuration and display it. + +wifidirect_action_frame +---------- + "./wifidirectutl wifidirect_action_frame <*.conf> | " + + This command is used to send action frames as specified in config file or on command line. + + Example: + ./wifidirectutl wifidirect_action_frame wifidirect.conf + Read action_frame from wifidirect.conf and send to peer. + ./wifidirectutl wifidirect_action_frame + Read action frame parameters from command line and send to peer. + +wifidirect_discovery_request +---------- + "./wifidirectutl wifidirect_discovery_request <*.conf>" + + This command is used to send wifidirect discovery request packet. + + Example: + ./wifidirectutl wifidirect_discovery_request wifidirect.conf + Read discovery packet from wifidirect.conf and send to peer. + +wifidirect_discovery_response +---------- + "./wifidirectutl wifidirect_discovery_response <*.conf>" + + This command is used to send wifidirect discovery response packet. + + Example: + ./wifidirectutl wifidirect_discovery_response wifidirect.conf + Read discovery packet from wifidirect.conf and send to peer. + +wifidirect_cfg_discovery_period +---------- + "./wifidirectutl wifidirect_cfg_discovery_period [ ]" + + This command is used to set or get minimum and maximum discovery period. + + Example: + ./wifidirectutl wifidirect_cfg_discovery_period 10 20 + Set minimum discovery interval to 10 and maximum discovery + interval to 20. + + ./wifidirectutl wifidirect_cfg_discovery_period + Get minimum and maximum discovery interval. + +wifidirect_cfg_intent +---------- + "./wifidirectutl wifidirect_cfg_intent [IntentValue]" + + This command is used to set or get intent value. + + Example: + ./wifidirectutl wifidirect_cfg_intent 12 + Set intent value to 12. + + ./wifidirectutl wifidirect_cfg_intent + Get Group Owner Intent. + +wifidirect_cfg_capability +---------- + "./wifidirectutl wifidirect_cfg_capability [ ]" + + This command is used to set or get device capability and group capability. + + Example: + ./wifidirectutl wifidirect_cfg_capability 10 20 + Set Device capability to 10 and group capability to 20 + + ./wifidirectutl wifidirect_cfg_capability + Get Device capability and group capability. + +wifidirect_cfg_noa +---------- + "./wifidirectutl wifidirect_cfg_noa [ ]" + + This command is used to set or get NoA parameters like count_type, duration and + interval in ms when NoA is enabled. Valid value of index is [0, 1]. + + Example: + ./wifidirectutl wifidirect_cfg_noa enable 0 10 50 100 + Enable NoA and set count to 10, duration to 50ms and interval to 100 ms + for index 0. + + ./wifidirectutl wifidirect_cfg_noa disable 1 + Disable NoA at index 1. + + ./wifidirectutl wifidirect_cfg_noa + Get NoA settings. + +wifidirect_cfg_opp_ps +---------- + "./wifidirectutl wifidirect_cfg_opp_ps []" + + This command is used to set or get Opportunistic power save and CT window. + + Example: + ./wifidirectutl wifidirect_cfg_opp_ps enable 50 + Set OppPS and CTwindow value to 50. + + ./wifidirectutl wifidirect_cfg_opp_ps disable + Disable OppPS. + + ./wifidirectutl wifidirect_cfg_opp_ps + Get OppPS and CT window. + +wifidirect_cfg_invitation_list +---------- + "./wifidirectutl wifidirect_cfg_invitation_list [mac_addr]" + + This command is used to set or get invitation list of peers. + + Example: + ./wifidirectutl wifidirect_cfg_invitation_list 00:50:43:20:23:34 + Set 00:50:43:20:23:34 in invitation list of peers. + + ./wifidirectutl wifidirect_cfg_invitation_list + Get Invitation list of peers. + +wifidirect_cfg_listen_channel +---------- + "./wifidirectutl wifidirect_cfg_listen_channel [ListenChannel]" + + This command is used to set or get Listen channel. + + Example: + ./wifidirectutl wifidirect_cfg_listen_channel 11 + Set Listen channel to 11. + + ./wifidirectutl wifidirect_cfg_listen_channel + Get Listen channel. + +wifidirect_cfg_op_channel +---------- + "./wifidirectutl wifidirect_cfg_op_channel [OperatingChannel]" + + This command is used to set or get Operating channel. + + Example: + ./wifidirectutl wifidirect_cfg_op_channel 11 + Set Operating channel to 11. + + ./wifidirectutl wifidirect_cfg_op_channel + Get Operating channel. + +wifidirect_cfg_persistent_group_record +---------- + "./wifidirectutl [index] [role] + [ ] [peermac1] [peermac2]" + + This command is used to set or get the persistent group record + maintained in the device. Valid index is from 0 to 3. The role should be + 0 for client, 1 for group-owner. + + Example: + ./wifidirectutl wifidirect_cfg_persistent_group_record 0 1 + 00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890" + 00:50:43:20:c2:d0 + Set persistent group record with index 0, role as group owner, bssId and + device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address. + The passphrase get converted to PSK. + + ./wifidirectutl wifidirect_cfg_persistent_group_record 1 1 + 00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890" + 0x1234567890123456789012345678901234567890123456789012345678901234 + Set persistent group record with index 1, role as group owner, bssId and + device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address. + The passphrase get converted to PSK. + PSK is specified with "0x" prefix and 32 bytes (64 characters). + + ./wifidirectutl wifidirect_cfg_persistent_group_record 1 + Get persistent group record with index 1. + + ./wifidirectutl wifidirect_cfg_persistent_group_record + Get persistent group record for all indices. + +wifidirect_cfg_persistent_group_invoke +---------- + "./wifidirectutl wifidirect_cfg_persistent_group_invoke [index] | " + + This command is used to invoke a particular persistent group record + from the list. Valid index is from 0 to 3. + + ./wifidirectutl wifidirect_cfg_persistent_group_invoke 2 + Invoke persistent group record with index 1. + + ./wifidirectutl wifidirect_cfg_persistent_group_invoke cancel + Cancel invokation of persistent groups. + +wifidirect_cfg_presence_req_params +---------- + "./wifidirectutl wifidirect_cfg_presence_req_params [ ]" + + This command is used to set/get presence request parameters. Type should + be 1 for preferred values and 2 for acceptable values. + + ./wifidirectutl wifidirect_cfg_presence_req_params 1 50 100 + Set duration to 50ms and interval to 100ms. + + ./wifidirectutl wifidirect_cfg_presence_req_params + Get presence request parameters. + +wifidirect_cfg_ext_listen_time +---------- + "./wifidirectutl wifidirect_cfg_ext_listen_time [ ]" + + This command is used to set/get extended listen timing parameters. + + ./wifidirectutl wifidirect_cfg_ext_listen_time 1200 1300 + Set availability period to 1200ms and availability interval to 1300 ms. + + ./wifidirectutl wifidirect_cfg_ext_listen_time + Get extended listen timing parameters. + +wifidirect_cfg_provisioning_params +---------- + "./wifidirectutl wifidirect_cfg_provisioning_params [ ]" + + This command is used to set/get provisioning protocol parameters. Action should + be 1 for request parameters and 2 for response parameters. + + ./wifidirectutl wifidirect_cfg_provisioning_params 1 0x80 0x04 + Set config method to 0x86 and device password to 0x04. + + ./wifidirectutl wifidirect_cfg_provisioning_params + Get Provision protocol parameters. + +wifidirect_cfg_wps_params +---------- + "./wifidirectutl wifidirect_cfg_wps_params []" + + This command is used to set WPS action. action can be "pin" (pin entered), + "pbc"(button pressed) or "none". + + Example: + ./wifidirectutl wifidirect_cfg_wps_params pin + Indicates pin operation + + ./wifidirectutl wifidirect_cfg_wps_params none + Indicates no operation + +=============================================================================== + U S E R M A N U A L F O R WIFIDISPLAY + +wifidisplay_mode +----------- + "./wifidirectutl wifidisplay_mode []" + This command is used to enable or disable wifi-display. The possible values are either 1 or 0. + Example: + ./wifidirectutl wifidisplay_mode 1 + Indicates enable wifi_display + + ./wifidirectutl wifidisplay_mode 0 + Indicates disable wifi_display + +wifidisplay_config +----------- + "./wifidirectutl wifidisplay_config [*.conf]" + + This command is used to set/get the wifidisplay configuration. + + Example: + ./wifidirectutl wifidisplay_config wifidisplay.conf + Read configuration from wifidisplay.conf and apply it. + ./wifidirectutl wifidisplay_config + Read existing wifidisplay configuration and display it. + +wifidisplay_update_devinfo +---------- + "./wifidirectutl wifidisplay_update_devinfo [value]" + + This command is used to set the device information of wifidisplay device information subelement. + This command will overwrite the new device information with user defined value. + + Example: + ./wifidirectutl wifidisplay_update_devinfo 10 + Update device information programmed with new value 10 by overwritting existing value. + +wifidisplay_discovery_request +---------- + "./wifidirectutl wifidisplay_discovery_request [*.config]" + + This command is used to send wifi display service discovery request. + + Example: + ./wifidirectutl wifidisplay_discovery_request wifidisplay.conf + Read discovery packet from wifidisplay.conf and send to peer. + +wifidisplay_discovery_response +---------- + "./wifidirectutl wifidisplay_discovery_response <*.conf>" + + This command is used to send wifidisplay discovery response packet. + + Example: + ./wifidirectutl wifidisplay_discovery_response wifidisplay.conf + Read discovery packet from wifidisplay.conf and send to peer. + +=============================================================================== + U S E R M A N U A L F O R MLANEVENT + +NAME +mlanevent.exe + +This tool can be used to listen for and obtain events from the driver +through the netlink layer. This is only used for display/debugging purpose. + +---------------- +Supported events +---------------- +WIFIDIRECT_GENERIC_EVENT +WIFIDIRECT_SERVICE_DISCOVERY + +----------------- +Details of events +----------------- + +WIFIDIRECT_GENERIC_EVENT +----------------- + For this event, the following information is shown: + + Event length. + + Event Type indicating Negociation, Invitation, Discoverability, + Provision discovery related Request or Response. + + Event SubType indicating Client or Group owner role. + + Peer MAC address. + + Associated WIFIDIRECT IE elements. + +WIFIDIRECT_SERVICE_DISCOVERY +--------------------- + For this event, the following information is shown: + + Peer MAC address. + + Service discovery packet details. diff --git a/mwifiex_8997/gpl-2.0.txt b/mwifiex_8997/gpl-2.0.txt new file mode 100755 index 0000000..2c62266 --- /dev/null +++ b/mwifiex_8997/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + License is intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Lesser General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains + a notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the + Program (independent of having been made by running the Program). + Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and give any other recipients of the Program a copy of this License + along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this License. + However, parties who have received copies, or rights, from you under + this License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions + of the General Public License from time to time. Such new versions will + be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and conditions + either of that version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number of + this License, you may choose any version ever published by the Free Software + Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the author + to ask for permission. For software which is copyrighted by the Free + Software Foundation, write to the Free Software Foundation; we sometimes + make exceptions for this. Our decision will be guided by the two goals + of preserving the free status of all derivatives of our free software and + of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS + TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, + INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING + OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED + TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY + YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the appropriate + parts of the General Public License. Of course, the commands you use may + be called something other than `show w' and `show c'; they could even be + mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Lesser General + Public License instead of this License. diff --git a/mwifiex_8997/mapp/mlan2040coex/Makefile b/mwifiex_8997/mapp/mlan2040coex/Makefile new file mode 100755 index 0000000..12c3a67 --- /dev/null +++ b/mwifiex_8997/mapp/mlan2040coex/Makefile @@ -0,0 +1,48 @@ +# +# File : mlan2040coex/Makefile +# +# Copyright (C) 2009-2019, Marvell International Ltd. All Rights Reserved + +# Path to the top directory of the mlandriver distribution +PATH_TO_TOP = ../.. + +# Determine how we should copy things to the install directory +ABSPATH := $(filter /%, $(INSTALLDIR)) +RELPATH := $(filter-out /%, $(INSTALLDIR)) +INSTALLPATH := $(ABSPATH) +ifeq ($(strip $(INSTALLPATH)),) +INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH) +endif + +# Override CFLAGS for application sources, remove __ kernel namespace defines +CFLAGS := $(filter-out -D__%, $(ccflags-y)) +# remove KERNEL include dir +CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS)) + +# +# List of application executables to create +# +libobjs:= mlan2040coex.o mlan2040misc.o +exectarget=mlan2040coex +TARGETS := $(exectarget) + +# +# Make target rules +# + +# All rule compiles list of TARGETS using builtin program target from src rule +all : +$(exectarget): $(libobjs) + $(CC) $(CFLAGS) $(libobjs) -o $(exectarget) + +# Update any needed TARGETS and then copy to the install path +build install: $(TARGETS) + @cp -f $(exectarget) $(INSTALLPATH) + +clean: + @rm -f $(exectarget) + @rm -f *.o + +distclean: clean + @rm -f *~ core + @rm -f tags diff --git a/mwifiex_8997/mapp/mlan2040coex/mlan2040coex.c b/mwifiex_8997/mapp/mlan2040coex/mlan2040coex.c new file mode 100755 index 0000000..79d0709 --- /dev/null +++ b/mwifiex_8997/mapp/mlan2040coex/mlan2040coex.c @@ -0,0 +1,1322 @@ +/** @file mlan2040coex.c + * + * @brief 11n 20/40 MHz Coex application + * + * Copyright (C) 2009-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 06/24/2009: initial version +************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ANDROID +#include +#else +#include +#endif +#include "mlan2040coex.h" +#include "mlan2040misc.h" + +/** coex application's version number */ +#define COEX_VER "M2.0" + +/** Initial number of total private ioctl calls */ +#define IW_INIT_PRIV_NUM 128 +/** Maximum number of total private ioctl calls supported */ +#define IW_MAX_PRIV_NUM 1024 + +/******************************************************** + Local Variables +********************************************************/ + +static char *usage[] = { + "Usage: ", + " mlan2040coex [-i ] [-hvB] ", + " -h = help", + " -v = version", + " -B = run the process in background.", + " (if intfname not present then mlan0 assumed)" +}; + +t_s32 sockfd = 0; /**< socket descriptor */ +char dev_name[IFNAMSIZ + 1]; /**< device name */ + +/** Flag: is 2040coex command required */ +int coex_cmd_req_flag = FALSE; +/** Flag: is associated */ +int assoc_flag = FALSE; +/** Flag: is HT AP */ +int is_ht_ap = FALSE; +/** terminate flag */ +int terminate_flag = FALSE; + +/******************************************************** + Global Variables +********************************************************/ +/** OBSS scan parameter of associated AP */ +OBSSScanParam_t cur_obss_scan_param; + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief Prepare command buffer + * @param buffer Command buffer to be filled + * @param cmd Command id + * @param num Number of arguments + * @param args Arguments list + * @return MLAN_STATUS_SUCCESS + */ +static int +prepare_buffer(t_u8 *buffer, char *cmd, t_u32 num, char *args[]) +{ + t_u8 *pos = NULL; + unsigned int i = 0; + + memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + + /* Flag it for our use */ + pos = buffer; + strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL)); + pos += (strlen(CMD_MARVELL)); + + /* Insert command */ + strncpy((char *)pos, (char *)cmd, strlen(cmd)); + pos += (strlen(cmd)); + + /* Insert arguments */ + for (i = 0; i < num; i++) { + strncpy((char *)pos, args[i], strlen(args[i])); + pos += strlen(args[i]); + if (i < (num - 1)) { + strncpy((char *)pos, " ", strlen(" ")); + pos += 1; + } + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process OBSS scan table + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_scantable(void) +{ + char ssid[MRVDRV_MAX_SSID_LENGTH + 1] = { 0 }; + unsigned int scan_start; + int idx, i = 0, j, already_listed, ssid_len = 0, ssid_idx; + + t_u8 *pcurrent; + t_u8 *pnext; + IEEEtypes_ElementId_e *pelement_id; + t_u8 *pelement_len, ht_cap_present, intol_bit_is_set; + int ret = MLAN_STATUS_SUCCESS; + t_s32 bss_info_len = 0; + t_u32 fixed_field_length = 0; + + IEEEtypes_CapInfo_t cap_info; + t_u8 tsf[8]; + t_u16 beacon_interval; + IEEEtypes_HTCap_t *pht_cap; + + wlan_ioctl_get_scan_table_info *prsp_info; + wlan_get_scan_table_fixed fixed_fields; + + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Start preparing the buffer */ + /* Initialize buffer */ + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + memset(&cap_info, 0x00, sizeof(cap_info)); + memset(leg_ap_chan_list, 0, sizeof(leg_ap_chan_list)); + num_leg_ap_chan = 0; + + scan_start = 1; + + do { + /* buffer = CMD_MARVELL + */ + prepare_buffer(buffer, "getscantable", 0, NULL); + prsp_info = + (wlan_ioctl_get_scan_table_info *)(buffer + + strlen(CMD_MARVELL) + + strlen + ("getscantable")); + + prsp_info->scan_number = scan_start; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + if (errno == EAGAIN) { + ret = -EAGAIN; + } else { + perror("mlan2040coex"); + fprintf(stderr, + "mlan2040coex: getscantable fail\n"); + ret = MLAN_STATUS_FAILURE; + } + goto done; + } + + prsp_info = (wlan_ioctl_get_scan_table_info *)buffer; + pcurrent = 0; + pnext = prsp_info->scan_table_entry_buf; + + if (scan_start == 1) { + printf("----------------------------------------------\n"); + } + + for (idx = 0; (unsigned int)idx < prsp_info->scan_number; idx++) { + + /* + * Set pcurrent to pnext in case pad bytes are at the end + * of the last IE we processed. + */ + pcurrent = pnext; + + memcpy((t_u8 *)&fixed_field_length, + (t_u8 *)pcurrent, sizeof(fixed_field_length)); + pcurrent += sizeof(fixed_field_length); + + memcpy((t_u8 *)&bss_info_len, + (t_u8 *)pcurrent, sizeof(bss_info_len)); + pcurrent += sizeof(bss_info_len); + + memcpy((t_u8 *)&fixed_fields, + (t_u8 *)pcurrent, sizeof(fixed_fields)); + pcurrent += fixed_field_length; + + pnext = pcurrent + bss_info_len; + + if (bss_info_len >= (sizeof(tsf) + + sizeof(beacon_interval) + + sizeof(cap_info))) { + pcurrent += + (sizeof(tsf) + sizeof(beacon_interval) + + sizeof(cap_info)); + bss_info_len -= + (sizeof(tsf) + sizeof(beacon_interval) + + sizeof(cap_info)); + } + ht_cap_present = FALSE; + intol_bit_is_set = FALSE; + memset(ssid, 0, MRVDRV_MAX_SSID_LENGTH + 1); + ssid_len = 0; + while (bss_info_len >= 2) { + pelement_id = (IEEEtypes_ElementId_e *)pcurrent; + pelement_len = pcurrent + 1; + pcurrent += 2; + + switch (*pelement_id) { + case SSID: + if (*pelement_len && + *pelement_len <= + MRVDRV_MAX_SSID_LENGTH) { + memcpy(ssid, pcurrent, + *pelement_len); + ssid_len = *pelement_len; + } + break; + + case HT_CAPABILITY: + pht_cap = + (IEEEtypes_HTCap_t *) + pelement_id; + ht_cap_present = TRUE; + if (IS_INTOL_BIT_SET + (le16_to_cpu + (pht_cap->ht_cap.ht_cap_info))) { + intol_bit_is_set = TRUE; + } + break; + default: + break; + } + pcurrent += *pelement_len; + bss_info_len -= (2 + *pelement_len); + } + if (!ht_cap_present || intol_bit_is_set) { + printf("%s AP found on channel number: %-3d ", + intol_bit_is_set ? "40 MHZ intolerant" : + "Legacy", fixed_fields.channel); + if (ssid_len) { + printf("SSID: "); + /* Print out the ssid or the hex values if non-printable */ + for (ssid_idx = 0; ssid_idx < ssid_len; + ssid_idx++) { + if (isprint(ssid[ssid_idx])) { + printf("%c", + ssid[ssid_idx]); + } else { + printf("\\%02x", + ssid[ssid_idx]); + } + } + } + printf("\n"); + + /* Verify that the channel is already listed or not */ + already_listed = FALSE; + for (j = 0; j < i; j++) { + if (leg_ap_chan_list[j].chan_num == + fixed_fields.channel) { + already_listed = TRUE; + if (intol_bit_is_set) + leg_ap_chan_list[j]. + is_intol_set = + intol_bit_is_set; + break; + } + } + if (!already_listed) { + /* add the channel in list */ + leg_ap_chan_list[i].chan_num = + fixed_fields.channel; + leg_ap_chan_list[i].is_intol_set = + intol_bit_is_set; + i++; + coex_cmd_req_flag = TRUE; + num_leg_ap_chan++; + } + } + } + scan_start += prsp_info->scan_number; + + } while (prsp_info->scan_number); + +done: + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return ret; +} + +/** BSS Mode any (both infra and adhoc) */ +#define BSS_MODE_ANY 3 + +/** current scan config parameters */ +#define SCAN_CFG_PARAMS 7 + +/** Active : 1 , Passive : 2 */ +#define SCAN_TYPE_ACTIVE 1 + +/** + * @brief Issue get scan type command + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +get_scan_cfg(int *scan_param) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int ret = MLAN_STATUS_SUCCESS; + + /* Start preparing the buffer */ + /* Initialize buffer */ + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* buffer = CMD_MARVELL + */ + prepare_buffer(buffer, "scancfg", 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlan2040coex"); + fprintf(stderr, "mlan2040coex: get_scan_cfg fail\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + scan_param = (int *)(buffer); +done: + if (cmd) + free(cmd); + if (buffer) + free(buffer); + + return ret; +} + +/** + * @brief Issue OBSS scan command + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_setuserscan(void) +{ + wlan_ioctl_user_scan_cfg scan_req; + int scan_cfg[SCAN_CFG_PARAMS]; + t_u8 *buffer = NULL, *pos = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int status = 0; + + memset(&scan_req, 0x00, sizeof(scan_req)); + memset(scan_cfg, 0x00, SCAN_CFG_PARAMS); + coex_cmd_req_flag = FALSE; + + if (get_scan_cfg(scan_cfg) != MLAN_STATUS_SUCCESS) { + printf("mlan2040coex: scancfg ioctl failure"); + return -EFAULT; + } + + if (scan_cfg[0] == SCAN_TYPE_ACTIVE) + scan_req.chan_list[0].scan_time = + (t_u32)le16_to_cpu(cur_obss_scan_param. + obss_scan_active_dwell); + else + scan_req.chan_list[0].scan_time = + (t_u32)le16_to_cpu(cur_obss_scan_param. + obss_scan_passive_total); + scan_req.bss_mode = (scan_cfg[1]) ? scan_cfg[1] : BSS_MODE_ANY; + + /* Start preparing the buffer */ + /* Initialize buffer */ + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* buffer = CMD_MARVELL + */ + prepare_buffer(buffer, "setuserscan", 0, NULL); + pos = buffer + strlen(CMD_MARVELL) + strlen("setuserscan"); + + /* buffer = buffer + 'scan_req' */ + memcpy(pos, &scan_req, sizeof(wlan_ioctl_user_scan_cfg)); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlan2040coex"); + fprintf(stderr, "mlan2040coex: setuserscan fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /** process scan results */ + do { + status = process_scantable(); + } while (status == -EAGAIN); + + if (cmd) + free(cmd); + if (buffer) + free(buffer); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Display usage + * + * @return NA + */ +static t_void +display_usage(t_void) +{ + t_u32 i; + for (i = 0; i < NELEMENTS(usage); i++) + fprintf(stderr, "%s\n", usage[i]); +} + +/** + * @brief get connection status + * + * @param data Pointer to the output buffer holding connection status + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +int +get_connstatus(int *data) +{ + struct ether_addr apaddr; + struct ether_addr etherzero = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* buffer = CMD_MARVELL + */ + prepare_buffer(buffer, "getwap", 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlan2040coex"); + fprintf(stderr, "mlan2040coex: getwap fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + memset(&apaddr, 0, sizeof(struct ether_addr)); + memcpy(&apaddr, (struct ether_addr *)(buffer), + sizeof(struct ether_addr)); + + if (!memcmp(&apaddr, ðerzero, sizeof(struct ether_addr))) { + /* not associated */ + *data = FALSE; + } else { + /* associated */ + *data = TRUE; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Print connect and disconnect event related information + * + * @param buffer Pointer to received event buffer + * @param size Length of the received event + * + * @return N/A + */ +void +print_event_drv_connected(t_u8 *buffer, t_u16 size) +{ + struct ether_addr *wap; + struct ether_addr etherzero = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; + char buf[32]; + + wap = (struct ether_addr *)(buffer + strlen(CUS_EVT_AP_CONNECTED)); + + if (!memcmp(wap, ðerzero, sizeof(struct ether_addr))) { + printf("---< Disconnected from AP >---\n"); + memset(&cur_obss_scan_param, 0, sizeof(cur_obss_scan_param)); + assoc_flag = FALSE; + is_ht_ap = FALSE; + } else { + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X", + wap->ether_addr_octet[0], + wap->ether_addr_octet[1], + wap->ether_addr_octet[2], + wap->ether_addr_octet[3], + wap->ether_addr_octet[4], wap->ether_addr_octet[5]); + printf("---< Connected to AP: %s >---\n", buf); + /** set TRUE, if connected */ + assoc_flag = TRUE; + } +} + +/** + * @brief Parse and print received event information + * + * @param event Pointer to received event + * @param size Length of the received event + * @param evt_conn A pointer to a output buffer. It sets TRUE when it gets + * the event CUS_EVT_OBSS_SCAN_PARAM, otherwise FALSE + * @param if_name The interface name + * + * @return N/A + */ +void +print_event(event_header *event, t_u16 size, int *evt_conn, char *if_name) +{ + if (!strncmp + (CUS_EVT_AP_CONNECTED, (char *)event, + strlen(CUS_EVT_AP_CONNECTED))) { + if (strlen(if_name)) + printf("EVENT for interface %s\n", if_name); + print_event_drv_connected((t_u8 *)event, size); + return; + } + if (!strncmp + (CUS_EVT_OBSS_SCAN_PARAM, (char *)event, + strlen(CUS_EVT_OBSS_SCAN_PARAM))) { + if (strlen(if_name)) + printf("EVENT for interface %s\n", if_name); + printf("---< %s >---\n", CUS_EVT_OBSS_SCAN_PARAM); + memset(&cur_obss_scan_param, 0, sizeof(cur_obss_scan_param)); + memcpy(&cur_obss_scan_param, + ((t_u8 *)event + strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1), + sizeof(cur_obss_scan_param)); + /** set TRUE, since it is an HT AP */ + is_ht_ap = TRUE; + *evt_conn = TRUE; + return; + } + if (!strncmp + (CUS_EVT_BW_CHANGED, (char *)event, strlen(CUS_EVT_BW_CHANGED))) { + if (strlen(if_name)) + printf("EVENT for interface %s\n", if_name); + printf("---< %s >---\n", CUS_EVT_BW_CHANGED); + return; + } +} + +/** + * @brief This function parses for NETLINK events + * + * @param nlh Pointer to Netlink message header + * @param bytes_read Number of bytes to be read + * @param evt_conn A pointer to a output buffer. It sets TRUE when it gets + * the event CUS_EVT_OBSS_SCAN_PARAM, otherwise FALSE + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +static int +drv_nlevt_handler(struct nlmsghdr *nlh, int bytes_read, int *evt_conn) +{ + int len, plen; + t_u8 *buffer = NULL; + t_u32 event_id = 0; + event_header *event = NULL; + char if_name[IFNAMSIZ + 1]; + + /* Initialize receive buffer */ + buffer = (t_u8 *)malloc(NL_MAX_PAYLOAD); + if (!buffer) { + printf("ERR: Could not alloc buffer\n"); + return MLAN_STATUS_FAILURE; + } + memset(buffer, 0, NL_MAX_PAYLOAD); + + *evt_conn = FALSE; + while ((unsigned int)bytes_read >= NLMSG_HDRLEN) { + len = nlh->nlmsg_len; /* Length of message including header */ + plen = len - NLMSG_HDRLEN; + if (len > bytes_read || plen < 0) { + /* malformed netlink message */ + return MLAN_STATUS_FAILURE; + } + if ((unsigned int)len > NLMSG_SPACE(NL_MAX_PAYLOAD)) { + printf("ERR:Buffer overflow!\n"); + return MLAN_STATUS_FAILURE; + } + memset(buffer, 0, NL_MAX_PAYLOAD); + memcpy(buffer, NLMSG_DATA(nlh), plen); + + if (NLMSG_OK(nlh, len)) { + memcpy(&event_id, buffer, sizeof(event_id)); + + if (((event_id & 0xFF000000) == 0x80000000) || + ((event_id & 0xFF000000) == 0)) { + event = (event_header *)buffer; + } else { + memset(if_name, 0, IFNAMSIZ + 1); + memcpy(if_name, buffer, IFNAMSIZ); + event = (event_header *)(buffer + IFNAMSIZ); + } + } + + print_event(event, bytes_read, evt_conn, if_name); + len = NLMSG_ALIGN(len); + bytes_read -= len; + nlh = (struct nlmsghdr *)((char *)nlh + len); + } + return MLAN_STATUS_SUCCESS; +} + +/** Maximum event message length */ +#define MAX_MSG_LENGTH 1024 + +/** + * @brief Configure and read event data from netlink socket + * + * @param nl_sk Netlink socket handler + * @param msg Pointer to message header + * @param ptv Pointer to struct timeval + * + * @return Number of bytes read or MLAN_STATUS_FAILURE + */ +int +read_event(int nl_sk, struct msghdr *msg, struct timeval *ptv) +{ + int count = -1; + int ret = MLAN_STATUS_FAILURE; + fd_set rfds; + + /* Setup read fds and initialize event buffers */ + FD_ZERO(&rfds); + FD_SET(nl_sk, &rfds); + + /* Wait for reply */ + ret = select(nl_sk + 1, &rfds, NULL, NULL, ptv); + + if (ret == MLAN_STATUS_FAILURE) { + /* Error */ + terminate_flag++; + ptv->tv_sec = DEFAULT_SCAN_INTERVAL; + ptv->tv_usec = 0; + goto done; + } else if (!ret) { + if (assoc_flag && is_ht_ap) { + /** Issue OBSS scan */ + process_setuserscan(); + /** Invoke 2040coex command, if any legacy AP found or + * any AP has 40MHz intolarent bit set */ + if (coex_cmd_req_flag) + invoke_coex_command(); + } + if (assoc_flag && is_ht_ap) { + /* Timeout. Try again after BSS channel width triger scan + interval when the STA is connected with a HT AP */ + ptv->tv_sec = + (t_u32)le16_to_cpu(cur_obss_scan_param. + bss_chan_width_trigger_scan_int); + } else { + /* Timeout. Try again after default duration when the STA is + not connected with a HT AP */ + ptv->tv_sec = DEFAULT_SCAN_INTERVAL; + } + ptv->tv_usec = 0; + goto done; + } + + if (!FD_ISSET(nl_sk, &rfds)) { + /* Unexpected error. Try again */ + ptv->tv_sec = DEFAULT_SCAN_INTERVAL; + ptv->tv_usec = 0; + goto done; + } + /* Success */ + count = recvmsg(nl_sk, msg, 0); + +done: + return count; +} + +/** Maximum event message length */ +#define MAX_MSG_LENGTH 1024 +/** + * @brief Run the application + * + * @param nl_sk Netlink socket + * + * @return N/A + */ +void +run_app(int nl_sk) +{ + struct timeval tv; + int bytes_read, evt_conn; + struct msghdr msg; + struct sockaddr_nl dest_addr; + struct nlmsghdr *nlh; + struct iovec iov; + + /** Get connection status */ + if (get_connstatus(&assoc_flag) == MLAN_STATUS_FAILURE) + return; + + /* Initialize timeout value */ + tv.tv_sec = DEFAULT_SCAN_INTERVAL; + tv.tv_usec = 0; + + /* Initialize netlink header */ + nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(NL_MAX_PAYLOAD)); + if (!nlh) { + printf("ERR: Could not allocate space for netlink header\n"); + goto done; + } + memset(nlh, 0, NLMSG_SPACE(NL_MAX_PAYLOAD)); + /* Fill the netlink message header */ + nlh->nlmsg_len = NLMSG_SPACE(NL_MAX_PAYLOAD); + nlh->nlmsg_pid = getpid(); /* self pid */ + nlh->nlmsg_flags = 0; + + /* Initialize I/O vector */ + memset(&iov, 0, sizeof(struct iovec)); + iov.iov_base = (void *)nlh; + iov.iov_len = nlh->nlmsg_len; + + /* Set destination address */ + memset(&dest_addr, 0, sizeof(struct sockaddr_nl)); + dest_addr.nl_family = AF_NETLINK; + dest_addr.nl_pid = 0; /* Kernel */ + dest_addr.nl_groups = NL_MULTICAST_GROUP; + + /* Initialize message header */ + memset(&msg, 0, sizeof(struct msghdr)); + msg.msg_name = (void *)&dest_addr; + msg.msg_namelen = sizeof(dest_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + while (!terminate_flag) { + /* event buffer is received for all the interfaces */ + bytes_read = read_event(nl_sk, &msg, &tv); + /* handle only NETLINK events here */ + drv_nlevt_handler((struct nlmsghdr *)nlh, bytes_read, + &evt_conn); + if (assoc_flag && is_ht_ap) { + /** If the event is connected with an HT AP then issue OBSS scan immediately */ + if (evt_conn) { + /** Issue OBSS scan */ + process_setuserscan(); + /** Invoke 2040coex command, if any legacy AP found or + * any AP has 40MHz intolarent bit set */ + if (coex_cmd_req_flag) + invoke_coex_command(); + } + tv.tv_sec = + (t_u32)le16_to_cpu(cur_obss_scan_param. + bss_chan_width_trigger_scan_int); + } else { + tv.tv_sec = DEFAULT_SCAN_INTERVAL; + } + tv.tv_usec = 0; + } + +done: + if (nl_sk > 0) + close(nl_sk); + if (nlh) + free(nlh); + return; +} + +/** + * @brief Determine the netlink number + * + * @return Netlink number to use + */ +static int +get_netlink_num(int dev_index) +{ + FILE *fp = NULL; + int netlink_num = NETLINK_MARVELL; + char str[64]; + char *srch = "netlink_num"; + char filename[64]; + + if (dev_index == 0) { + strcpy(filename, "/proc/mwlan/config"); + } else if (dev_index > 0) { + sprintf(filename, "/proc/mwlan/config%d", dev_index); + } + /* Try to open /proc/mwlan/config$ */ + fp = fopen(filename, "r"); + + if (fp) { + while (fgets(str, sizeof(str), fp)) { + if (strncmp(str, srch, strlen(srch)) == 0) { + netlink_num = atoi(str + strlen(srch) + 1); + break; + } + } + fclose(fp); + } else { + return -1; + } + + printf("Netlink number = %d\n", netlink_num); + return netlink_num; +} + +/** + * @brief opens netlink socket to receive NETLINK events + * @return socket id --success, otherwise--MLAN_STATUS_FAILURE + */ +int +open_netlink(int dev_index) +{ + int sk = -1; + struct sockaddr_nl src_addr; + int netlink_num = 0; + + netlink_num = get_netlink_num(dev_index); + if (netlink_num < 0) { + printf("ERR:Could not get netlink socket. Invalid device number.\n"); + return sk; + } + + /* Open netlink socket */ + sk = socket(PF_NETLINK, SOCK_RAW, netlink_num); + if (sk < 0) { + printf("ERR:Could not open netlink socket.\n"); + return sk; + } + + /* Set source address */ + memset(&src_addr, 0, sizeof(src_addr)); + src_addr.nl_family = AF_NETLINK; + src_addr.nl_pid = getpid(); + src_addr.nl_groups = NL_MULTICAST_GROUP; + + /* Bind socket with source address */ + if (bind(sk, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) { + printf("ERR:Could not bind socket!\n"); + close(sk); + return -1; + } + return sk; +} + +/** + * @brief Terminate signal handler + * @param signal Signal to handle + * @return NA + */ +static t_void +terminate_handler(int signal) +{ + printf("Stopping application.\n"); +#if DEBUG + printf("Process ID of process killed = %d\n", getpid()); +#endif + terminate_flag = TRUE; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief Process host command + * @param hostcmd_idx Host command index + * @param chan_list A pointer to a channel list + * @param chan_num Number of channels in the channel list + * @param reg_class Regulatory class of the channels + * @param is_intol_ap_present Flag:is there any 40 MHz intolerant AP is present or not + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_host_cmd(int hostcmd_idx, t_u8 *chan_list, t_u8 chan_num, + t_u8 reg_class, t_u8 is_intol_ap_present) +{ + int ret = MLAN_STATUS_SUCCESS; + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + prepare_buffer(buffer, "hostcmd", 0, NULL); + switch (hostcmd_idx) { + case CMD_2040COEX: + prepare_coex_cmd_buff(buffer + strlen(CMD_MARVELL) + + strlen("hostcmd"), chan_list, chan_num, + reg_class, is_intol_ap_present); + break; + default: + break; + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlan2040coex"); + fprintf(stderr, "mlan2040coex: hostcmd fail\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + ret = process_host_cmd_resp("hostcmd", buffer); + +done: + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return ret; +} + +/** + * @brief Check the STA is 40 MHz intolerant or not + * @param intol Flag: TRUE when the STA is 40 MHz intolerant, otherwise FALSE + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +is_intolerant_sta(int *intol) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int htcap_info, ret = MLAN_STATUS_SUCCESS; + + *intol = FALSE; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* buffer = CMD_MARVELL + */ + prepare_buffer(buffer, "htcapinfo", 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlan2040coex"); + fprintf(stderr, "mlan2040coex: htcapinfo fail\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + htcap_info = *((int *)(buffer)); + + if (htcap_info & MBIT(8)) + *intol = TRUE; + +done: + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return ret; +} + +/** + * @brief get region code + * @param reg_code Pointer to region code + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +get_region_code(int *reg_code) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int ret = MLAN_STATUS_SUCCESS; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* buffer = CMD_MARVELL + */ + prepare_buffer(buffer, "regioncode", 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlan2040coex"); + fprintf(stderr, "mlan2040coex: regioncode fail\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + memcpy(reg_code, buffer, sizeof(int)); +done: + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return ret; +} + +/** No option */ +#define NO_OPTION -1 + +/** + * @brief Entry function for coex + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +main(int argc, char *argv[]) +{ + char ifname[IFNAMSIZ + 1] = "mlan0"; + int c, daemonize = FALSE; + t_s32 nl_sk = 0; + /**< netlink socket descriptor to receive an event */ + int dev_index = 0; /** initialise with -1 to open multiple NETLINK Sockets */ + + char temp[2]; + int arg_count = 0; + int ifname_given = FALSE; + + for (;;) { + c = getopt(argc, argv, "Bhi:vd:"); + /* check if all command-line options have been parsed */ + if (c == NO_OPTION) + break; + + switch (c) { + case 'B': + daemonize = TRUE; + break; + case 'h': + display_usage(); + return MLAN_STATUS_SUCCESS; + case 'v': + fprintf(stdout, + "Marvell 20/40coex application version %s\n", + COEX_VER); + return MLAN_STATUS_SUCCESS; + case 'i': + ifname_given = TRUE; + if (strlen(optarg) < IFNAMSIZ) + strncpy(ifname, optarg, IFNAMSIZ - 1); + else { + fprintf(stdout, "Interface name too long\n"); + display_usage(); + return MLAN_STATUS_SUCCESS; + } + arg_count += 1; + break; + case 'd': + strncpy(temp, optarg, strlen(optarg)); + if (isdigit(temp[0])) + dev_index = atoi(temp); + arg_count += 1; + break; + default: + fprintf(stdout, "Invalid argument\n"); + display_usage(); + return MLAN_STATUS_SUCCESS; + } + } + + if (!ifname_given) { + sprintf(ifname, "mlan%d", dev_index); + } + + if (optind < argc) { + fputs("Too many arguments.\n", stderr); + display_usage(); + goto done; + } + + strncpy(dev_name, ifname, IFNAMSIZ - 1); + + /* create a socket */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "mlan2040coex: Cannot open socket.\n"); + goto done; + } + + /* create netlink sockets and bind them with app side addr */ + nl_sk = open_netlink(dev_index); + + if (nl_sk < 0) { + fprintf(stderr, "mlan2040coex: Cannot open netlink socket.\n"); + goto done; + } + + signal(SIGHUP, terminate_handler); /* catch hangup signal */ + signal(SIGTERM, terminate_handler); /* catch kill signal */ + signal(SIGINT, terminate_handler); /* catch kill signal */ + signal(SIGALRM, terminate_handler); /* catch kill signal */ + + /** Make the process background-process */ + if (daemonize) { + if (daemon(0, 0)) + fprintf(stderr, "mlan2040coex: Cannot start daemon\n"); + } + + /** run the application */ + run_app(nl_sk); + +done: + if (sockfd > 0) + close(sockfd); + if (nl_sk > 0) + close(nl_sk); + + return MLAN_STATUS_SUCCESS; +} diff --git a/mwifiex_8997/mapp/mlan2040coex/mlan2040coex.h b/mwifiex_8997/mapp/mlan2040coex/mlan2040coex.h new file mode 100755 index 0000000..b0b79d4 --- /dev/null +++ b/mwifiex_8997/mapp/mlan2040coex/mlan2040coex.h @@ -0,0 +1,233 @@ +/** @file mlan2040coex.h + * + * @brief This file contains definitions for application + * + * Copyright (C) 2009-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 06/24/2009: initial version +************************************************************************/ +#ifndef _COEX_H_ +#define _COEX_H_ + +/** Marvell private command identifier */ +#define CMD_MARVELL "MRVL_CMD" + +/** IOCTL number */ +#define MLAN_ETH_PRIV (SIOCDEVPRIVATE + 14) + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#undef BIG_ENDIAN_SUPPORT +#endif + +/** 16 bits byte swap */ +#define swap_byte_16(x) \ +((t_u16)((((t_u16)(x) & 0x00ffU) << 8) | \ + (((t_u16)(x) & 0xff00U) >> 8))) + +/** 32 bits byte swap */ +#define swap_byte_32(x) \ +((t_u32)((((t_u32)(x) & 0x000000ffUL) << 24) | \ + (((t_u32)(x) & 0x0000ff00UL) << 8) | \ + (((t_u32)(x) & 0x00ff0000UL) >> 8) | \ + (((t_u32)(x) & 0xff000000UL) >> 24))) + +/** 64 bits byte swap */ +#define swap_byte_64(x) \ + ((t_u64)((t_u64)(((t_u64)(x) & 0x00000000000000ffULL) << 56) | \ + (t_u64)(((t_u64)(x) & 0x000000000000ff00ULL) << 40) | \ + (t_u64)(((t_u64)(x) & 0x0000000000ff0000ULL) << 24) | \ + (t_u64)(((t_u64)(x) & 0x00000000ff000000ULL) << 8) | \ + (t_u64)(((t_u64)(x) & 0x000000ff00000000ULL) >> 8) | \ + (t_u64)(((t_u64)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (t_u64)(((t_u64)(x) & 0x00ff000000000000ULL) >> 40) | \ + (t_u64)(((t_u64)(x) & 0xff00000000000000ULL) >> 56) )) + +/** Convert to correct endian format */ +#ifdef BIG_ENDIAN_SUPPORT +/** CPU to little-endian convert for 16-bit */ +#define cpu_to_le16(x) swap_byte_16(x) +/** CPU to little-endian convert for 32-bit */ +#define cpu_to_le32(x) swap_byte_32(x) +/** CPU to little-endian convert for 64-bit */ +#define cpu_to_le64(x) swap_byte_64(x) +/** Little-endian to CPU convert for 16-bit */ +#define le16_to_cpu(x) swap_byte_16(x) +/** Little-endian to CPU convert for 32-bit */ +#define le32_to_cpu(x) swap_byte_32(x) +/** Little-endian to CPU convert for 64-bit */ +#define le64_to_cpu(x) swap_byte_64(x) +#else +/** Do nothing */ +#define cpu_to_le16(x) (x) +/** Do nothing */ +#define cpu_to_le32(x) (x) +/** Do nothing */ +#define cpu_to_le64(x) (x) +/** Do nothing */ +#define le16_to_cpu(x) (x) +/** Do nothing */ +#define le32_to_cpu(x) (x) +/** Do nothing */ +#define le64_to_cpu(x) (x) +#endif + +#ifdef __GNUC__ +/** Structure packing begins */ +#define PACK_START +/** Structure packeing end */ +#define PACK_END __attribute__ ((packed)) +#else +/** Structure packing begins */ +#define PACK_START __packed +/** Structure packeing end */ +#define PACK_END +#endif + +/** Character, 1 byte */ +typedef signed char t_s8; +/** Unsigned character, 1 byte */ +typedef unsigned char t_u8; + +/** Short integer */ +typedef signed short t_s16; +/** Unsigned short integer */ +typedef unsigned short t_u16; + +/** Integer */ +typedef signed int t_s32; +/** Unsigned integer */ +typedef unsigned int t_u32; + +/** Long long integer */ +typedef signed long long t_s64; +/** Unsigned long long integer */ +typedef unsigned long long t_u64; + +/** Void pointer (4-bytes) */ +typedef void t_void; + +#ifdef FALSE +#undef FALSE +#endif + +#ifdef TRUE +#undef TRUE +#endif + +#ifndef MIN +/** Find minimum value */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +/** Type definition: boolean */ +typedef enum { FALSE, TRUE } boolean; + +/** Find number of elements */ +#define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) +/** Success */ +#define MLAN_STATUS_SUCCESS (0) +/** Failure */ +#define MLAN_STATUS_FAILURE (-1) + +/** Enumeration for host-command index */ +enum COMMANDS { + CMD_2040COEX = 1, +}; +/** Maximum number of channels that can be sent in a setuserscan ioctl */ +#define WLAN_IOCTL_USER_SCAN_CHAN_MAX 50 + +#ifndef ETH_ALEN +/** MAC address length */ +#define ETH_ALEN 6 +#endif + +/** Netlink protocol number */ +#define NETLINK_MARVELL (MAX_LINKS - 1) +/** Netlink maximum payload size */ +#define NL_MAX_PAYLOAD 1024 +/** Netlink multicast group number */ +#define NL_MULTICAST_GROUP RTMGRP_LINK +/** Default wait time in seconds for events */ +#define UAP_RECV_WAIT_DEFAULT 10 +#ifndef NLMSG_HDRLEN +/** NL message header length */ +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#endif + +/** Event header */ +typedef PACK_START struct _event_header { + /** Event ID */ + t_u32 event_id; + /** Event data */ + t_u8 event_data[0]; +} PACK_END event_header; + +/** Event ID length */ +#define EVENT_ID_LEN 4 + +/** Custom events definitions */ +/** AP connected event */ +#define CUS_EVT_AP_CONNECTED "EVENT=AP_CONNECTED" + +/** Custom event : BW changed */ +#define CUS_EVT_BW_CHANGED "EVENT=BW_CHANGED" +/** Custom event : OBSS scan parameter */ +#define CUS_EVT_OBSS_SCAN_PARAM "EVENT=OBSS_SCAN_PARAM" + +/** Custom events definitions end */ + +/** Structure defination of chan_intol_t*/ +typedef struct _chan_intol_t { + /** Channel numer */ + t_u8 chan_num; + /** Flag: Is any 40MHz intolerant AP found in this channel */ + t_u8 is_intol_set; +} chan_intol_t; + +/** Private command structure */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT +struct eth_priv_cmd { + /** Command buffer pointer */ + t_u64 buf; + /** buffer updated by driver */ + int used_len; + /** buffer sent by application */ + int total_len; +} __ATTRIB_PACK__; +#else +struct eth_priv_cmd { + /** Command buffer */ + t_u8 *buf; + /** Used length */ + int used_len; + /** Total length */ + int total_len; +}; +#endif + +/** Legacy APs channel list */ +chan_intol_t leg_ap_chan_list[WLAN_IOCTL_USER_SCAN_CHAN_MAX]; +/** Total number of channel present in Legacy APs channel list */ +t_u8 num_leg_ap_chan; +int get_region_code(int *reg_code); +int process_host_cmd(int cmd, t_u8 *chan_list, t_u8 chan_num, t_u8 reg_class, + t_u8 is_intol_ap_present); +int is_intolerant_sta(int *intol); + +#endif /* _COEX_H_ */ diff --git a/mwifiex_8997/mapp/mlan2040coex/mlan2040misc.c b/mwifiex_8997/mapp/mlan2040coex/mlan2040misc.c new file mode 100755 index 0000000..a818989 --- /dev/null +++ b/mwifiex_8997/mapp/mlan2040coex/mlan2040misc.c @@ -0,0 +1,280 @@ +/** @file mlan2040misc.c + * + * @brief This file contains helper functions for coex application + * + * Copyright (C) 2009-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 06/24/2009: initial version +************************************************************************/ +#include +#include +#include +#include +#include "mlan2040coex.h" +#include "mlan2040misc.h" + +/******************************************************** + Local Variables +********************************************************/ +/** Regulatory class and Channel mapping for various regions */ +static class_chan_t us_class_chan_t[] = { + {32, {1, 2, 3, 4, 5, 6, 7}, 7}, + {33, {5, 6, 7, 8, 9, 10, 11}, 7} +}; + +static class_chan_t europe_class_chan_t[] = { + {11, {1, 2, 3, 4, 5, 6, 7, 8, 9}, 9}, + {12, {5, 6, 7, 8, 9, 10, 11, 12, 13}, 9} +}; + +static class_chan_t japan_class_chan_t[] = { + {56, {1, 2, 3, 4, 5, 6, 7, 8, 9}, 9}, + {57, {5, 6, 7, 8, 9, 10, 11, 12, 13}, 9}, + {58, {14}, 1} +}; + +/** Region-code(Regulatory domain) and Class-channel table mapping */ +static region_class_chan_t region_class_chan_table[] = { + {0x10, us_class_chan_t, sizeof(us_class_chan_t) / sizeof(class_chan_t)} /* US */ + , + {0x20, us_class_chan_t, sizeof(us_class_chan_t) / sizeof(class_chan_t)} /* CANADA */ + , + {0x30, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)} /* EUROPE */ + , + {0x32, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)} /* FRANCE */ + , + {0x40, japan_class_chan_t, sizeof(japan_class_chan_t) / sizeof(class_chan_t)} /* JAPAN */ + , + {0x41, japan_class_chan_t, sizeof(japan_class_chan_t) / sizeof(class_chan_t)} /* JAPAN */ + , + {0x50, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)} /* CHINA */ +}; + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ +/** + * @brief This function prepares the channel list for a particular + * regulatory class from channel number for legacy AP + * @param cur_class_chan_table A pointer to the class_chan_t + * @param num_entry Number of entry in cur_class_chan_table table + * @param chan_list A pointer to the output channel list + * @param chan_num total number of channel in output channel list + * @param reg_domain regulatory domain + * @param reg_class regulatory class + * @param is_intol_ap_present It sets TRUE when 40MHz intolerant AP is found + * otherwise FALSE + * @return None + */ +static void +get_channels_for_specified_reg_class(class_chan_t *cur_class_chan_table, + int num_entry, t_u8 *chan_list, + t_u8 *chan_num, t_u8 reg_domain, + t_u8 reg_class, t_u8 *is_intol_ap_present) +{ + int i, j, k, idx = 0; + + *is_intol_ap_present = FALSE; + + /* For each regulatory class */ + for (i = 0; i < num_entry; i++) { + if (cur_class_chan_table[i].reg_class == reg_class) { + /* For each channel of the regulatory class */ + for (j = 0; j < cur_class_chan_table[i].total_chan; j++) { + for (k = 0; k < num_leg_ap_chan; k++) { + + if (cur_class_chan_table[i]. + channels[j] == + leg_ap_chan_list[k].chan_num) { + *(chan_list + idx) = + leg_ap_chan_list[k]. + chan_num; + idx++; + if (leg_ap_chan_list[k]. + is_intol_set) + *is_intol_ap_present = + TRUE; + } + } + } + break; + } + } + /* update the total number of channel */ + *chan_num = idx--; + return; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief Prepare 2040 coex command buffer + * @param buf A pointer to the command buffer + * @param chan_list Channel list + * @param num_of_chan Number of channel present in channel list + * @param reg_class Regulatory class + * @param is_intol_ap_present Flag: is any 40 MHz intolerant AP + * is present in these chaanel set + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +void +prepare_coex_cmd_buff(t_u8 *buf, t_u8 *chan_list, t_u8 num_of_chan, + t_u8 reg_class, t_u8 is_intol_ap_present) +{ + HostCmd_DS_GEN *hostcmd; + MrvlIETypes_2040COEX_t *coex_ie = NULL; + MrvlIETypes_2040BssIntolerantChannelReport_t *bss_intol_ie = NULL; + t_u8 *pos = NULL; + int intol; + + hostcmd = (HostCmd_DS_GEN *)(buf + sizeof(t_u32)); + hostcmd->command = cpu_to_le16(HostCmd_CMD_11N_2040COEX); + hostcmd->size = S_DS_GEN; + pos = buf + sizeof(t_u32) + S_DS_GEN; + { + coex_ie = (MrvlIETypes_2040COEX_t *)pos; + coex_ie->header.element_id = TLV_ID_2040COEX; + coex_ie->header.len = sizeof(coex_ie->coex_elem); + /* Check STA is 40 MHz intolerant or not */ + is_intolerant_sta(&intol); + if (intol) + coex_ie->coex_elem |= MBIT(1); + + if (is_intol_ap_present) + coex_ie->coex_elem |= MBIT(2); + pos += sizeof(MrvlIETypes_2040COEX_t); + hostcmd->size += sizeof(MrvlIETypes_2040COEX_t); + } + { + bss_intol_ie = + (MrvlIETypes_2040BssIntolerantChannelReport_t *)pos; + bss_intol_ie->header.element_id = + TLV_ID_2040BSS_INTOL_CHAN_REPORT; + hostcmd->size += + sizeof(MrvlIETypes_2040BssIntolerantChannelReport_t) - + sizeof(bss_intol_ie->chan_num); + bss_intol_ie->reg_class = reg_class; + memcpy(bss_intol_ie->chan_num, chan_list, num_of_chan); + bss_intol_ie->header.len = + sizeof(bss_intol_ie->reg_class) + num_of_chan; + hostcmd->size += num_of_chan; + } + hostcmd->size = cpu_to_le16(hostcmd->size); + return; +} + +/** + * @brief Invoke multiple 2040Coex commands for multiple regulatory classes + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +invoke_coex_command(void) +{ + int cur_reg_domain; + t_u8 chan_list[MAX_CHAN], is_intol_ap_present; + t_u8 num_of_chan; + int i, num_entry, ret = MLAN_STATUS_SUCCESS; + class_chan_t *cur_class_chan_table = NULL; + + /** get region code */ + ret = get_region_code(&cur_reg_domain); + if (ret != MLAN_STATUS_SUCCESS) + return ret; + /** Find region_class_chan_table for this region */ + for (i = 0; + (unsigned int)i < + (sizeof(region_class_chan_table) / sizeof(region_class_chan_t)); + i++) { + if (region_class_chan_table[i].reg_domain == cur_reg_domain) { + cur_class_chan_table = + region_class_chan_table[i].class_chan_list; + num_entry = + region_class_chan_table[i].num_class_chan_entry; + break; + } + } + if (cur_class_chan_table == NULL) { + printf("No region_class_chan table found for this region\n"); + return MLAN_STATUS_FAILURE; + } + + for (i = 0; i < num_entry; i++) { + /** Get channels for the specified regulatory class */ + get_channels_for_specified_reg_class(cur_class_chan_table, + num_entry, chan_list, + &num_of_chan, + cur_reg_domain, + cur_class_chan_table[i]. + reg_class, + &is_intol_ap_present); + + /** If any channel found for this regulatory class, then invoke the 2040coex command */ + if (num_of_chan > 0) { + ret = process_host_cmd(CMD_2040COEX, chan_list, + num_of_chan, + cur_class_chan_table[i]. + reg_class, is_intol_ap_present); + if (ret) + break; + } + } + return ret; +} + +/** + * @brief Process host_cmd response + * + * @param cmd_name The command string + * @param buf A pointer to the response buffer + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_host_cmd_resp(char *cmd_name, t_u8 *buf) +{ + t_u32 hostcmd_size = 0; + HostCmd_DS_GEN *hostcmd = NULL; + int ret = MLAN_STATUS_SUCCESS; + + buf += strlen(CMD_MARVELL) + strlen(cmd_name); + memcpy((t_u8 *)&hostcmd_size, buf, sizeof(t_u32)); + buf += sizeof(t_u32); + + hostcmd = (HostCmd_DS_GEN *)buf; + hostcmd->command = le16_to_cpu(hostcmd->command); + hostcmd->size = le16_to_cpu(hostcmd->size); + + hostcmd->command &= ~HostCmd_RET_BIT; + if (!le16_to_cpu(hostcmd->result)) { + switch (hostcmd->command) { + } + } else { + printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + ret = MLAN_STATUS_FAILURE; + } + return ret; +} diff --git a/mwifiex_8997/mapp/mlan2040coex/mlan2040misc.h b/mwifiex_8997/mapp/mlan2040coex/mlan2040misc.h new file mode 100755 index 0000000..7aaad6d --- /dev/null +++ b/mwifiex_8997/mapp/mlan2040coex/mlan2040misc.h @@ -0,0 +1,443 @@ +/** @file mlan2040misc.h + * + * @brief This file contains command definitions for application + * + * Copyright (C) 2009-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 06/24/2009: initial version +************************************************************************/ +#ifndef _COEX_MISC_H_ +#define _COEX_MISC_H_ + +/** MLAN MAC Address Length */ +#define MLAN_MAC_ADDR_LENGTH (6) +/** Size of command buffer */ +#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) + +/** Command RET code, MSB is set to 1 */ +#define HostCmd_RET_BIT 0x8000 +/** General purpose action : Get */ +#define HostCmd_ACT_GEN_GET 0x0000 +/** General purpose action : Set */ +#define HostCmd_ACT_GEN_SET 0x0001 +/** TLV Id for 2040Coex IE */ +#define TLV_ID_2040COEX 0x48 +/** TLV Id for 2040BSS intolarent channel report IE */ +#define TLV_ID_2040BSS_INTOL_CHAN_REPORT 0x49 +/** Host-command for 2040coex command */ +#define HostCmd_CMD_11N_2040COEX 0x00e9 +/** Maximum scan response buffer size */ +#define SCAN_RESP_BUF_SIZE 2000 + +/** Maximum length of SSID */ +#define MRVDRV_MAX_SSID_LENGTH 32 + +/** Length of ethernet address */ +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif +/** Maximum length of SSID list */ +#define MRVDRV_MAX_SSID_LIST_LENGTH 10 +/** Default scan interval in second*/ +#define DEFAULT_SCAN_INTERVAL 300 + +/** BIT value */ +#define MBIT(x) (((t_u32)1) << (x)) + +/** Check intolerent bit set */ +#define IS_INTOL_BIT_SET(cap_info) (cap_info & MBIT(14)) + +/** Check OBSS non-HT STAs present bit set */ +#define IS_NON_HT_STA_PRESENT(ht_info) (ht_info.field3 & MBIT(4)) + +/** IEEE Type definitions */ +typedef enum _IEEEtypes_ElementId_e { + SSID = 0, + SUPPORTED_RATES = 1, + FH_PARAM_SET = 2, + DS_PARAM_SET = 3, + CF_PARAM_SET = 4, + IBSS_PARAM_SET = 6, + HT_CAPABILITY = 45, + HT_OPERATION = 61, + BSSCO_2040 = 72, + OVERLAPBSSSCANPARAM = 74, + EXT_CAPABILITY = 127, + ERP_INFO = 42, + EXTENDED_SUPPORTED_RATES = 50, + VENDOR_SPECIFIC_221 = 221, + WMM_IE = VENDOR_SPECIFIC_221, + RSN_IE = 48, +} __attribute__ ((packed)) + IEEEtypes_ElementId_e; + +/** HT Capabilities Data */ + typedef struct _HTCap_t { + /** HT Capabilities Info field */ + t_u16 ht_cap_info; + /** A-MPDU Parameters field */ + t_u8 ampdu_param; + /** Supported MCS Set field */ + t_u8 supported_mcs_set[16]; + /** HT Extended Capabilities field */ + t_u16 ht_ext_cap; + /** Transmit Beamforming Capabilities field */ + t_u32 tx_bf_cap; + /** Antenna Selection Capability field */ + t_u8 asel; + /** Reserved set to 0 */ + t_u16 reserved; + } __attribute__ ((packed)) + HTCap_t, *pHTCap_t; + +/** HT Information Data */ + typedef struct _HTInfo_t { + /** Primary channel */ + t_u8 pri_chan; + /** Field 2 */ + t_u8 field2; + /** Field 3 */ + t_u16 field3; + /** Field 4 */ + t_u16 field4; + /** Bitmap indicating MCSs supported by all HT STAs in the BSS */ + t_u8 basic_mcs_set[16]; + /** Reserved set to 0 */ + t_u16 reserved; + } __attribute__ ((packed)) + HTInfo_t, *pHTInfo_t; + +/** 20/40 BSS Coexistence Data */ + typedef struct _BSSCo2040_t { + /** 20/40 BSS Coexistence value */ + t_u8 bss_co_2040_value; + /** Reserve field */ + t_u8 reserved[3]; + } __attribute__ ((packed)) + BSSCo2040_t, *pBSSCo2040_t; + +/** Extended Capabilities Data */ + typedef struct _ExtCap_t { + /** Extended Capabilities value */ + t_u8 ext_cap_value; + /** Reserved field */ + t_u8 reserved[3]; + } __attribute__ ((packed)) + ExtCap_t, *pExtCap_t; + +/** Overlapping BSS Scan Parameters Data */ + typedef struct _OverlapBSSScanParam_t { + /** OBSS Scan Passive Dwell */ + t_u16 obss_scan_passive_dwell; + /** OBSS Scan Active Dwell */ + t_u16 obss_scan_active_dwell; + /** BSS Channel Width Trigger Scan Interval */ + t_u16 bss_chan_width_trigger_scan_int; + /** OBSS Scan Passive Total Per Channel */ + t_u16 obss_scan_passive_total; + /** OBSS Scan Active Total Per Channel */ + t_u16 obss_scan_active_total; + /** BSS Width Channel Transition Delay Factor */ + t_u16 bss_width_chan_trans_delay; + /** OBSS Scan Activity Threshold */ + t_u16 obss_scan_active_threshold; + } __attribute__ ((packed)) + OBSSScanParam_t, *pOBSSScanParam_t; + +/** IEEEtypes_CapInfo_t structure*/ + typedef struct _IEEEtypes_CapInfo_t { + /** Capability Bit Map : ESS */ + t_u8 ess:1; + /** Capability Bit Map : IBSS */ + t_u8 ibss:1; + /** Capability Bit Map : CF pollable */ + t_u8 cf_pollable:1; + /** Capability Bit Map : CF poll request */ + t_u8 cf_poll_rqst:1; + /** Capability Bit Map : privacy */ + t_u8 privacy:1; + /** Capability Bit Map : Short preamble */ + t_u8 short_preamble:1; + /** Capability Bit Map : PBCC */ + t_u8 pbcc:1; + /** Capability Bit Map : Channel agility */ + t_u8 chan_agility:1; + /** Capability Bit Map : Spectrum management */ + t_u8 spectrum_mgmt:1; + /** Capability Bit Map : Reserved */ + t_u8 rsrvd3:1; + /** Capability Bit Map : Short slot time */ + t_u8 short_slot_time:1; + /** Capability Bit Map : APSD */ + t_u8 apsd:1; + /** Capability Bit Map : Reserved */ + t_u8 rsvrd2:1; + /** Capability Bit Map : DSS OFDM */ + t_u8 dsss_ofdm:1; + /** Capability Bit Map : Reserved */ + t_u8 rsrvd1:2; + } __attribute__ ((packed)) + IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t; + + typedef struct { + t_u8 chan_number; + /**< Channel Number to scan */ + t_u8 radio_type; + /**< Radio type: 'B/G' Band = 0, 'A' Band = 1 */ + t_u8 scan_type; + /**< Scan type: Active = 1, Passive = 2 */ + t_u8 reserved; + /**< Reserved */ + t_u32 scan_time; + /**< Scan duration in milliseconds; if 0 default used */ + } __attribute__ ((packed)) + wlan_ioctl_user_scan_chan; + + typedef struct { + char ssid[MRVDRV_MAX_SSID_LENGTH + 1]; + /**< SSID */ + t_u8 max_len; /**< Maximum length of SSID */ + } __attribute__ ((packed)) + wlan_ioctl_user_scan_ssid; + + typedef struct { + + /** Flag set to keep the previous scan table intact */ + t_u8 keep_previous_scan; /* Do not erase the existing scan results */ + + /** BSS mode to be sent in the firmware command */ + t_u8 bss_mode; + + /** Configure the number of probe requests for active chan scans */ + t_u8 num_probes; + + /** Reserved */ + t_u8 reserved; + + /** BSSID filter sent in the firmware command to limit the results */ + t_u8 specific_bssid[ETH_ALEN]; + /** SSID filter list used in the to limit the scan results */ + wlan_ioctl_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH]; + + /** Variable number (fixed maximum) of channels to scan up */ + wlan_ioctl_user_scan_chan chan_list[WLAN_IOCTL_USER_SCAN_CHAN_MAX]; + + } __attribute__ ((packed)) + wlan_ioctl_user_scan_cfg; + +/** IEEE IE header */ + typedef struct _IEEEtypes_Header_t { + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; + } __attribute__ ((packed)) + IEEEtypes_Header_t, *pIEEEtypes_Header_t; + +/** HT Capabilities IE */ + typedef struct _IEEEtypes_HTCap_t { + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** HTCap struct */ + HTCap_t ht_cap; + } __attribute__ ((packed)) + IEEEtypes_HTCap_t, *pIEEEtypes_HTCap_t; + +/** HT Information IE */ + typedef struct _IEEEtypes_HTInfo_t { + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** HTInfo struct */ + HTInfo_t ht_info; + } __attribute__ ((packed)) + IEEEtypes_HTInfo_t, *pIEEEtypes_HTInfo_t; + +/** 20/40 BSS Coexistence IE */ + typedef struct _IEEEtypes_2040BSSCo_t { + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** BSSCo2040_t struct */ + BSSCo2040_t bss_co_2040; + } __attribute__ ((packed)) + IEEEtypes_2040BSSCo_t, *pIEEEtypes_2040BSSCo_t; + +/** Extended Capabilities IE */ + typedef struct _IEEEtypes_ExtCap_t { + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** ExtCap_t struct */ + ExtCap_t ext_cap; + } __attribute__ ((packed)) + IEEEtypes_ExtCap_t, *pIEEEtypes_ExtCap_t; + +/** Overlapping BSS Scan Parameters IE */ + typedef struct _IEEEtypes_OverlapBSSScanParam_t { + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** OBSSScanParam_t struct */ + OBSSScanParam_t obss_scan_param; + } __attribute__ ((packed)) + IEEEtypes_OverlapBSSScanParam_t, *pIEEEtypes_OverlapBSSScanParam_t; + + typedef struct _wlan_get_scan_table_fixed { + /** BSSID of this network */ + t_u8 bssid[MLAN_MAC_ADDR_LENGTH]; + /** Channel this beacon/probe response was detected */ + t_u8 channel; + /** RSSI for the received packet */ + t_u8 rssi; + /** TSF value from the firmware at packet reception */ + t_u64 network_tsf; + } wlan_get_scan_table_fixed; + +/** + * Structure passed in the wlan_ioctl_get_scan_table_info for each + * BSS returned in the WLAN_GET_SCAN_RESP IOCTL + */ + typedef struct _wlan_ioctl_get_scan_table_entry { + /** + * Fixed field length included in the response. + * + * Length value is included so future fixed fields can be added to the + * response without breaking backwards compatibility. Use the length + * to find the offset for the bssInfoLength field, not a sizeof() calc. + */ + t_u32 fixed_field_length; + + /** + * Length of the BSS Information (probe resp or beacon) that + * follows starting at bssInfoBuffer + */ + t_u32 bss_info_length; + + /** + * Always present, fixed length data fields for the BSS + */ + wlan_get_scan_table_fixed fixed_fields; + + /* + * Probe response or beacon scanned for the BSS. + * + * Field layout: + * - TSF 8 octets + * - Beacon Interval 2 octets + * - Capability Info 2 octets + * + * - IEEE Infomation Elements; variable number & length per 802.11 spec + */ + /* t_u8 bss_info_buffer[1]; */ + } wlan_ioctl_get_scan_table_entry; + +/** + * Sructure to retrieve the scan table + */ + typedef struct { + /** + * - Zero based scan entry to start retrieval in command request + * - Number of scans entries returned in command response + */ + t_u32 scan_number; + /** + * Buffer marker for multiple wlan_ioctl_get_scan_table_entry structures. + * Each struct is padded to the nearest 32 bit boundary. + */ + t_u8 scan_table_entry_buf[1]; + } wlan_ioctl_get_scan_table_info; + +/* Define general hostcmd data structure */ +/** HostCmd_DS_GEN */ + typedef struct _HostCmd_DS_GEN { + /** Command */ + t_u16 command; + /** Size */ + t_u16 size; + /** Sequence number */ + t_u16 seq_num; + /** Result */ + t_u16 result; + } __attribute__ ((packed)) + HostCmd_DS_GEN; + +/** Size of HostCmd_DS_GEN */ +#define S_DS_GEN sizeof(HostCmd_DS_GEN) + +/** TLV related data structures*/ +/** MrvlIEtypesHeader_t */ + typedef struct _MrvlIEtypesHeader { + /** Header type */ + t_u16 type; + /** Header length */ + t_u16 len; + } __attribute__ ((packed)) + MrvlIEtypesHeader_t; + +/** _MrvlIETypes_2040BssIntolerantChannelReport_t */ + typedef struct _MrvlIETypes_2040BssIntolerantChannelReport_t { + /** Header */ + IEEEtypes_Header_t header; + /** regulatory class */ + t_u8 reg_class; + /** channel numbers for legacy AP */ + t_u8 chan_num[1]; + } __attribute__ ((packed)) + MrvlIETypes_2040BssIntolerantChannelReport_t; + +/** MrvlIETypes_2040COEX_t */ + typedef struct _MrvlIETypes_2040COEX_t { + /** Header */ + IEEEtypes_Header_t header; + /** 2040 coex element */ + t_u8 coex_elem; + } __attribute__ ((packed)) + MrvlIETypes_2040COEX_t; + + typedef struct _HostCmd_DS_CMD_11N_2040COEX { + /** 2040 coex element */ + MrvlIETypes_2040COEX_t coex; + /** 2040 BSS intolerant channel report*/ + MrvlIETypes_2040BssIntolerantChannelReport_t chan_intol_report; + } __attribute__ ((packed)) + HostCmd_DS_CMD_11N_2040COEX; + +/** Maximum number of channel per regulatory class */ +#define MAX_CHAN 20 + typedef struct _class_chan_t { + /** Regulatory class */ + t_u8 reg_class; + /** Channel numbers */ + t_u8 channels[MAX_CHAN]; + /** Total number of channels */ + t_u8 total_chan; + } class_chan_t; + + typedef struct _region_class_chan_t { + /** Regulatory domain */ + int reg_domain; + /** Channel numbers */ + class_chan_t *class_chan_list; + /** Number of class channel table entry */ + int num_class_chan_entry; + } region_class_chan_t; + + int process_host_cmd_resp(char *cmd_name, t_u8 *buf); + void prepare_coex_cmd_buff(t_u8 *buf, t_u8 *chan_list, t_u8 num_of_chan, + t_u8 reg_class, t_u8 is_intol_ap_present); + int invoke_coex_command(void); + +#endif /* _COEX_MISC_H_ */ diff --git a/mwifiex_8997/mapp/mlanconfig/Makefile b/mwifiex_8997/mapp/mlanconfig/Makefile new file mode 100755 index 0000000..162949b --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/Makefile @@ -0,0 +1,48 @@ +# +# File : mlanconfig/Makefile +# +# Copyright (C) 2008-2019, Marvell International Ltd. All Rights Reserved + +# Path to the top directory of the mlandriver distribution +PATH_TO_TOP = ../.. + +# Determine how we should copy things to the install directory +ABSPATH := $(filter /%, $(INSTALLDIR)) +RELPATH := $(filter-out /%, $(INSTALLDIR)) +INSTALLPATH := $(ABSPATH) +ifeq ($(strip $(INSTALLPATH)),) +INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH) +endif + +# Override CFLAGS for application sources, remove __ kernel namespace defines +CFLAGS := $(filter-out -D__%, $(ccflags-y)) +# remove KERNEL include dir +CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS)) + +# +# List of application executables to create +# +libobjs:= mlanconfig.o mlanhostcmd.o mlanmisc.o +exectarget=mlanconfig +TARGETS := $(exectarget) + +# +# Make target rules +# + +# All rule compiles list of TARGETS using builtin program target from src rule +all : +$(exectarget): $(libobjs) + $(CC) $(CFLAGS) $(libobjs) -o $(exectarget) + +# Update any needed TARGETS and then copy to the install path +build install: $(TARGETS) + @cp -rf config $(INSTALLPATH) + +clean: + @rm -f $(exectarget) + @rm -f *.o + +distclean: clean + @rm -f *~ core + @rm -f tags diff --git a/mwifiex_8997/mapp/mlanconfig/config/11n_2040coex.conf b/mwifiex_8997/mapp/mlanconfig/config/11n_2040coex.conf new file mode 100755 index 0000000..1e8cda7 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/11n_2040coex.conf @@ -0,0 +1,21 @@ +# File : 11n_2040coex.conf + +######################### 20/40 Coex command ################## +2040coex={ + CmdCode=0x00e9 # do NOT change this line + + 2040CoexTlvType:1=0x48 + 2040CoexTlvLen:1={ + 2040CoexElement:1=0x04 + } + + 2040BssIntlChanTlvType:1=0x49 + 2040BssIntlChanTlvLen:1={ + RegulatoryDomain:1=32 # USA: 32 (1-7), 33 (5-11) + ChannelNum:1=1 + ChannelNum:1=2 + # ... + } +} + +################################################################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/arpfilter.conf b/mwifiex_8997/mapp/mlanconfig/config/arpfilter.conf new file mode 100755 index 0000000..a50b089 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/arpfilter.conf @@ -0,0 +1,29 @@ +# File : arpfilter.conf + +######################### Host Sleep ARP/IP filtering command ################## +# add arp filter +# firmware supports 8 entries of ARP_FILTER. Each entry has 8 bytes. +# must not exceed 8x8+4=68 bytes + +arpfilter={ + TlvType:2=0x0115 + TlvLength:2={ + AddrType:2=3 # multicast + EthType:2=0xffff # Any + Ipv4Addr:4=0xffffffff # Any + AddrType:2=1 # broadcast + EthType:2=0x0608 # ARP: 0x0806 + Ipv4Addr:4=0x6200a8c0 # 192.168.0.98 + AddrType:2=2 # unicast + EthType:2=0xffff # Any + Ipv4Addr:4=0xffffffff # Any + } +} + +# remove arp filter +#arpfilter={ +# TlvType:2=0x0115 +# TlvLength:2={ +# } +#} +######################### Host Sleep ARP/IP filtering command ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/auto_tx.conf b/mwifiex_8997/mapp/mlanconfig/config/auto_tx.conf new file mode 100755 index 0000000..6c35540 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/auto_tx.conf @@ -0,0 +1,54 @@ +# File : auto_tx.conf + +######################### Auto-TX command ################## +auto_tx_get={ + CmdCode=0x0082 # do NOT change this line + + Action:2=0 # GET +} + +auto_tx_unreg={ + CmdCode=0x0082 # do NOT change this line + + Action:2=1 # SET +} + +nat_keep_alive={ + CmdCode=0x0082 # do NOT change this line + + Action:2=1 # SET + + AutoTxTlvType:2=0x0118 + AutoTxTlvLength:2={ # 58 = 6 + 52 (FrameLen) + Interval:2=2 # 1 - 3600 seconds + Priority:1=7 # Priority, ignored if non-WMM + Reserved:1=0 + FrameLength:2={ # 52 = 6 (DA) + 6 (SA) + 2 + 38 (Length) + DestMacAddr:6='0x00,0x40,0xf4,0xbf,0x24,0xee' + SrcMacAddr:6='0x00,0x00,0x00,0x00,0x00,0x00' + Length:2='0x00,38' # 38 = 8 (SNAP hdr) + 29 (IP) + 1 (padding) + DSAP:1=0xaa # SNAP header + SSAP:1=0xaa + Ctrl:1=0x03 + SNAP_OUI:3='0x00,0x00,0x00' + SNAP_PID:2='0x08,0x00' # IP Packet + IPv4:1=0x45 + IP_TOS:1=0x00 + IP_LEN:2='0x00,29' # IP hdr 20 + payload 9 = 29 + IP_ID:2=0xefbe + IP_Flag_FragOffset:2=0x0000 + IP_TTL:1=128 + IP_Prot:1=17 # UDP protocol + IPhdr_cksum:2=0xc5f9 # may need re-calculation if changed + IPsrcAddr:4='192,168,0,201' # 192.168.0.201 + IPdstAddr:4='192,168,0,1' # 192.168.0.1 + UDPsrcPort:2='0x11,0x94' # 4500 + UDPdstPort:2='0x11,0x94' # 4500 + UDPlength:2='0x00,9' # UDP hdr 8 + payload 1 = 9 + UDPcksum:2=0x985b # may need re-calculation if changed + UDPpayload:1=0xff + padding:1=0 # MAC Padding for 32bit alignment, set to 0 + } + } +} +######################### Auto-TX command ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/bg_scan.conf b/mwifiex_8997/mapp/mlanconfig/config/bg_scan.conf new file mode 100755 index 0000000..e174936 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/bg_scan.conf @@ -0,0 +1,157 @@ +# File : bg_scan.conf + +######################### BG Scan Configuration command ################## +########### Sample configuration for Get BG Scan Configuration ##################### +#bgscfg={ +# CmdCode=0x006b # do NOT change this line +# Action:1=0 # 0- Get, 1- Set +# ConfigType:1=0 # 0- normal BG Scan config, 1-PPS or UAPSD BG Scan config +# Enable:1=1 # 0- Disable, 1-Enable +# BssType:1=0 # 1 - Infrastructure,2 - IBSS,3 - Any +# ChannelsPerScan:1=0 # Number of Channel to scan at one scan; maximum 14 +# Reserved1:3=0 +# ScanInterval:4=0 # Interval between consecutive scan (in milliseconds) +# Reserved2:4=0 +# ReportConditions:4=0 # bit0 - SSID match + # bit1 - SNR above SNR threshold + # bit2 - RSSI above RSSI threshold + # bit31 - All channels scanned at least once +# Reserved3:2=0 +#} + +########### SET BG Scan Configuration ##################### +bgscfg={ + CmdCode=0x006b # do NOT change this line + Action:1=1 # 0- Get, 1- Set + ConfigType:1=0 # 0- normal BG Scan config, 1-PPS or UAPSD BG Scan config + Enable:1=1 # 0- Disable, 1-Enable + BssType:1=3 # 1 - Infrastructure,2 - IBSS,3 - Any + ChannelsPerScan:1=14 # Number of Channel to scan at one scan; maximum 14 + Reserved1:3=0 + ScanInterval:4=1000 # Interval between consecutive scan (in milliseconds) + Reserved2:4=0 + ReportConditions:4=1 # bit0 - SSID match + # bit1 - SNR above SNR threshold + # bit2 - RSSI above RSSI threshold + # bit31 - All channels scanned at least once + Reserved3:2=0 + + # SSID parameter set: + # + # MaxSSIDLen entries: + # + # 1. MaxSSIDLen:1=0x00 - to denote match AP name exactly, + # generate SSID specific probes + # 2. MaxSSIDLen:1=maxlen - to denote AP name will be use to base match the + # SSID and SSID's max length is 'maxlen', + # do not generate SSID specific probes + # 3. MaxSSIDLen:1=wildcard match char ('*' or '?') + # - to denote wildcard AP name will be use to match the SSID + # 4. MaxSSIDLen:1=0xff - to denote unix pattern matching + # + # SSID entries: + # + # SSID="AP_NAME" - to mention the SSID to match + + # SSID Examples: + # + # + # Match SSID name "MarvellAP" exactly, generate SSID specific probes + # + SSIDHeaderType:2=0x0112 + SSIDHeaderLen:2={ + MaxSSIDLen:1=0x00 + SSID:9="MarvellAP" + } + + # + # MarvellAP will be use to base match the SSID and SSID's max length is 12 + # +# SSIDHeaderType:2=0x0112 +# SSIDHeaderLen:2={ +# MaxSSIDLen:1=0x0c +# SSID:9="MarvellAP" +# } + + # + # Match "MarvellAP*" where '*' is a single char + # +# SSIDHeaderType:2=0x0112 +# SSIDHeaderLen:2={ +# MaxSSIDLen:1='*' +# SSID:10="MarvellAP*" +# } + + # + # Match "Mar?ell*" with unix pattern matching + # +# SSIDHeaderType:2=0x0112 +# SSIDHeaderLen:2={ +# MaxSSIDLen:1=0xff # For unix pattern matching +# SSID:8="Mar?ell*" +# } + + # Number Probe requests to be sent for broadcast and + # for each SSID specific scan required. + # + # If any SSID in the list has a non-zero modifier (wildcard match char, + # unix pattern match, maxlen), "Numprobes" of broadcast probe requests + # will be transmitted once per channel and the results matched against + # all entries. + # + # Set to 0 to use global scan probes setting + # + ProbeHeaderType:2=0x0102 + ProbeHeaderLen:2={ + NumProbes:2=2 + } + + # ChannelList contains the channels to scan + # The ChannelList should be specified in the form of + # + # RadioType, ChanNumber, ScanType, MinScanTime, ScanTime; + # + # RadioType - 0 [B/G Band], 1 [A Band] + # ScanType - 2 [Active], 3 [Passive] + # + + ChannHeaderType:2=0x0101 + ChannHeaderLen:2={ + Chan1_RadioType:1=0 + Chan1_ChanNumber:1=10 + Chan1_ScanType:1=2 + Chan1_MinScanTime:2=10 + Chan1_ScanTime:2=100 + + Chan2_RadioType:1=0 + Chan2_ChanNumber:1=6 + Chan2_ScanType:1=3 + Chan2_MinScanTime:2=10 + Chan2_ScanTime:2=100 + } + + # SNR threshold used when ReportConditions bit1 is set + SNRHeaderType:2=0x0105 + SNRHeaderLen:2={ + SNRValue:1=40 #SNR Thereshold Value + SNRFreq:1=0 + } + + # RSSI threshold used when ReportConditions bit2 is set + # + # Threshold is absolute value and match value would + # therefore be less than or equal to trigger a report + RSSIHeaderType:2=0x0104 + RSSIHeaderLen:2={ + RSSIValue:1=50 #RSSI Thereshold Value + RSSIFreq:1=0 + } + + # StartLaterValue: 0 - BGScan start immediately + # 1 - BGScan will start later after "Scan Interval" + StartLaterHeaderType:2=0x011e + StartLaterHeaderLen:2={ + StartLaterValue:2=0 + } +} +######################### BG Scan Configuration command ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/bg_scan_wifidirect.conf b/mwifiex_8997/mapp/mlanconfig/config/bg_scan_wifidirect.conf new file mode 100755 index 0000000..f480a9c --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/bg_scan_wifidirect.conf @@ -0,0 +1,88 @@ +# File : bg_scan_wifidirect.conf + +######################### BG Scan Configuration command ################## +########### SET BG Scan Configuration ##################### +bgscfg={ + CmdCode=0x006b # do NOT change this line + Action:1=1 # 0- Get, 1- Set + ConfigType:1=0 # 0- normal BG Scan config, 1-PPS or UAPSD BG Scan config + Enable:1=1 # 0- Disable, 1-Enable + BssType:1=3 # 1 - Infrastructure,2 - IBSS,3 - Any + ChannelsPerScan:1=3 # Number of Channel to scan at one scan; maximum 14 + Reserved1:3=0 + ScanInterval:4=1000 # Interval between consecutive scan (in milliseconds) + StoreCondition:4=1 # 1 - SSID match (bit 0) + # 2 - SSID match AND SNR above SNR threshold (bit 1) + ReportConditions:4=1 # 1 - SSID match (bit 0) + # 2 - SSID match AND SNR above SNR threshold (bit 1) + Reserved3:2=0 + + # SSID parameter set: + # + SSIDHeaderType:2=0x0112 + SSIDHeaderLen:2={ + MaxSSIDLen:1=0x00 + SSID:7="DIRECT-" + } + + # Number Probe requests to be sent for broadcast and + # for each SSID specific scan required. + # + # If any SSID in the list has a non-zero modifier (wildcard match char, + # unix pattern match, maxlen), "Numprobes" of broadcast probe requests + # will be transmitted once per channel and the results matched against + # all entries. + # + # Set to 0 to use global scan probes setting + # + ProbeHeaderType:2=0x0102 + ProbeHeaderLen:2={ + NumProbes:2=2 + } + + # ChannelList contains the channels to scan + # The ChannelList should be specified in the form of + # + # RadioType, ChanNumber, ScanType, MinScanTime, ScanTime; + # + # RadioType - 0 [B/G Band], 1 [A Band] + # ScanType - 2 [Active], 3 [Passive] + # + + ChannHeaderType:2=0x0101 + ChannHeaderLen:2={ + Chan1_RadioType:1=0 + Chan1_ChanNumber:1=1 + Chan1_ScanType:1=2 + Chan1_MinScanTime:2=10 + Chan1_ScanTime:2=100 + + Chan2_RadioType:1=0 + Chan2_ChanNumber:1=6 + Chan2_ScanType:1=2 + Chan2_MinScanTime:2=10 + Chan2_ScanTime:2=100 + + Chan3_RadioType:1=0 + Chan3_ChanNumber:1=11 + Chan3_ScanType:1=2 + Chan3_MinScanTime:2=10 + Chan3_ScanTime:2=100 + } + + # SNR threshold to match, when StoreCondition + # or ReportConditions been set to 2 + SNRHeaderType:2=0x0105 + SNRHeaderLen:2={ + SNRValue:1=40 #SNR Thereshold Value + SNRFreq:1=0 + } + + # StartLaterValue: 0 - BGScan start immediately + # 1 - BGScan will start later after "Scan Interval" + StartLaterHeaderType:2=0x011e + StartLaterHeaderLen:2={ + StartLaterValue:2=0 + } +} +######################### BG Scan Configuration command ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/cal_data.conf b/mwifiex_8997/mapp/mlanconfig/config/cal_data.conf new file mode 100755 index 0000000..e37f674 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/cal_data.conf @@ -0,0 +1,42 @@ +01 00 0c 00 58 02 +00 40 68 0c 00 00 00 40 00 00 00 00 00 11 00 00 +00 11 00 10 00 00 00 00 00 00 00 00 00 00 00 00 +10 12 00 10 10 86 40 89 01 03 02 00 01 02 05 00 +01 03 05 00 17 17 00 05 00 00 00 00 00 00 00 00 +00 30 1f 11 00 00 00 70 00 00 00 00 13 00 1e 01 +00 1e 5e 15 29 5e 15 13 5c 1d 0d 0b 1d 0d 0b 29 +0d 0b 29 5c 0b 29 5c 1d 00 5c 1d 0d 00 00 00 00 +00 5c c0 0e 00 00 00 cc 00 5f 00 00 07 01 04 00 +00 00 0e 0d 00 00 00 00 00 00 00 00 00 00 00 ff +00 00 00 01 00 00 00 00 00 00 00 ff 00 00 00 01 +00 00 00 00 00 00 00 ff 00 00 00 01 00 00 00 00 +00 00 00 ff 00 00 00 01 00 00 00 00 06 3c 06 3d +00 00 00 00 00 00 00 00 00 00 00 00 +00 5c dc 25 00 00 01 28 00 6f 00 00 07 01 04 00 +00 00 0e 0d 00 00 00 00 00 00 00 00 00 08 00 07 +00 00 00 09 00 00 00 00 00 08 00 07 00 00 00 09 +00 00 00 00 00 08 00 07 00 00 00 09 00 00 00 00 +00 08 00 07 00 00 00 09 00 00 00 00 06 3c 06 3d +00 00 00 00 00 00 00 00 00 00 00 00 +00 14 9f 1f 00 00 01 3c 03 00 00 00 00 f1 0a f1 +00 fb 0d fb +00 20 dd 28 00 00 01 5c 08 86 00 88 ff 06 b1 05 +24 24 3c 42 00 00 24 18 a4 24 bc bc 3d 00 a0 8f +00 14 00 2a 00 00 01 70 00 00 30 00 01 05 1b 00 +00 00 00 01 +00 74 2c 10 00 00 01 e4 00 00 00 00 09 6a 09 b0 +0b 12 00 6c 04 0a 00 6c 03 03 00 6c 03 03 00 6c +3f ff ff 00 3f ff ff 01 3f ff ff 02 3f ff ff 03 +15 00 00 04 17 00 00 05 19 00 00 06 1b 00 00 07 +1d 00 00 08 1f 00 00 09 21 00 00 0a 23 00 00 0b +25 00 00 0c 28 00 00 0d 2a 00 00 0e 2d 00 00 0f +2f 00 00 10 32 00 00 11 34 00 00 12 3f ff ff 13 +3f ff ff 14 +00 74 84 10 ff ff ff ff 01 00 00 00 09 b0 09 ba +0a 0f 00 6c 04 09 00 6c 03 03 00 6c 03 03 00 6c +3f ff ff 00 3f ff ff 01 3f ff ff 02 3f ff ff 03 +15 00 00 04 17 00 00 05 1a 00 00 06 1c 00 00 07 +1f 00 00 08 21 00 00 09 23 00 00 0a 26 00 00 0b +2a 00 00 0c 2d 00 00 0d 31 00 00 0e 34 00 00 0f +3f ff ff 10 3f ff ff 11 3f ff ff 12 3f ff ff 13 +3f ff ff 14 diff --git a/mwifiex_8997/mapp/mlanconfig/config/crypto_test.conf b/mwifiex_8997/mapp/mlanconfig/config/crypto_test.conf new file mode 100755 index 0000000..d35812f --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/crypto_test.conf @@ -0,0 +1,58 @@ +# File : crypto_test.conf + +######################### crypto_test command configuration ################## +# support algorithm:1-RC4, 2-AES, 3-AES_KEY_WRAP,4-AES-CCM + +crypto_test={ + CmdCode=0x0078 # do NOT change this line + #EncDec: 0-Decrypt, 1-Encrypt + EncDec:2=0 + #Algorithm: 1-RC4, 2-AES, 3-AES_KEY_WRAP + Algorithm:2=1 + #KeyIVLength: Length of KeyIV (bytes) + KeyIVLength:2=8 + #KeyIV: Key IV + KeyIV:32='0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11' + #KeyLength: Length of Key (bytes) + KeyLength:2=16 + #Key: Key + Key:32='0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22' + #DataType: DataType + DataType:2=0x0111 + #DataLength: Data Length + DataLength:2={ + #Data: Data + Data:8='0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33' + } +} + +#####Sample crypto_test command configuration for AES-CCM algorithm ######### + +#crypto_test={ +# CmdCode=0x0078 # do NOT change this line +# #EncDec: 0-Decrypt, 1-Encrypt +# EncDec:2=1 +# #Algorithm: 4-AES-CCM +# Algorithm:2=4 +# #KeyLength: Length of Key (bytes) +# KeyLength:2=16 +# #Key: Key +# Key:32='0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22' +# #NonceLength: Length of Nonce (bytes) +# NonceLength:2=10 +# #Nonce: Nonce +# Nonce:14='0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11' +# #AADLength: Length of AAD (bytes) +# AADLength:2=12 +# #AAD: AAD +# AAD:32='0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33' +# #DataType: DataType +# DataType:2=0x0111 +# #DataLength: Data Length +# DataLength:2={ +# #Data: Data +# Data:8='0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33' +# } +#} + +######################### End of crypto_test configuration command ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/cwmode.conf b/mwifiex_8997/mapp/mlanconfig/config/cwmode.conf new file mode 100755 index 0000000..1f245a2 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/cwmode.conf @@ -0,0 +1,51 @@ +#CW_MODE settings configuration +# +CW_MODE={ +#Mode of operation 0: Disable current Tx Mode, 1: Continuous Tx Packet, 2: Continuous Wave/Tone +Mode=1 +#Channel number +Channel=6 +#channel Info +#bit [3:0] - channel offset 0: no secondary channel, 1: secondary channel above, 2: reserved, 3: secondary channel below +#bit [4:7] - channel band 0: 2.4G, 1: 5G, 2: 4G, 3: reserved +Chaninfo=0x00 +#Tx power for Cont Tx in dbm +TxPower=12 +# Packet Length for Cont Tx +# legacy rates: upto 2312, HT/VHT rates: upto 8K +PktLength=2048 +#RateInfo for Cont Tx +RateInfo=0x0000 +#rateInfo = 0x0732 : format = VHT, Bandwidth = 80MHz, datarate/MCS index = MCS7 +#rateInfo = 0x0000 : format = legacy, Bandwidth = 20MHz, datarate/MCS index = 1Mbps +#rateInfo = 0x0521 : format = HT, Bandwidth = 40MHz, datarate/MCS index = MCS5 +#rateInfo = 0x4521 : format = HT, Bandwidth = 40MHz, datarate/MCS index = MCS5, NSS = 1 +#rateInfo = 0x8921 : format = HT, Bandwidth = 40MHz, datarate/MCS index = MCS9, NSS = 2 +#bit [1:0] - Format 0: legacy, 1: 11n (HT), 2: 11ac (VHT) +#bit 2 - STBC (Not used for Cont Tx test) +#bit 3 - Beamforming (Not used for Cont Tx test) +#bit [5:4] - Bandwidth 0: 20MHz, 2: 40MHz, 3: 80MHz +#bit [7:6] - reserved +#bit [13:8] - index : data rate or MCS +#bit [15:14]- NSS (Used for 2x2 chips). Used in FW only for 2x2 chips. +# can take following values. +#If is 0 (LG), #If is 1 (HT) #If is 2 (VHT) +# NSS = 1 NSS = 1 or 2 +# 0 1 Mbps 0 MCS0 0 MCS0 +# 1 2 Mbps 1 MCS1 1 MCS1 +# 2 5.5 Mbps 2 MCS2 2 MCS2 +# 3 11 Mbps 3 MCS3 3 MCS3 +# 5 6 Mbps 4 MCS4 4 MCS4 +# 6 9 Mbps 5 MCS5 5 MCS5 +# 7 12 Mbps 6 MCS6 6 MCS6 +# 8 18 Mbps 7 MCS7 7 MCS7 +# Used only for NSS = 2 +# 9 24 Mbps 8 MCS8 +# 10 36 Mbps 9 MCS9 +# 11 48 Mbps 10 MCS10 +# 12 54 Mbps 11 MCS11 +# 12 MCS12 +# 13 MCS13 +# 14 MCS14 +# 15 MCS15 +} diff --git a/mwifiex_8997/mapp/mlanconfig/config/ed_mac_ctrl_V3_8997.conf b/mwifiex_8997/mapp/mlanconfig/config/ed_mac_ctrl_V3_8997.conf new file mode 100755 index 0000000..6c86bd7 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/ed_mac_ctrl_V3_8997.conf @@ -0,0 +1,23 @@ +# File : ed_mac_ctrl_V3_8997.conf +# +# ed_mac_ctrl_v3 is used for 88W8997, 88W8987, 88W8977 +# ./mlanutl mlan0 hostcmd config/ed_mac_ctrl_V3_8997.conf ed_mac_ctrl_v3 +# +## Set Energy Detect Threshold for EU Adaptivity test + +ed_mac_ctrl_v3={ + CmdCode=0x0130 #Command code, DO NOT change this line + ed_ctrl_2g.enable:2=0x1 # 0 - disable EU adaptivity for 2.4GHz band + # 1 - enable EU adaptivity for 2.4GHz band + + ed_ctrl_2g.offset:2=0x0 # 0 - Default Energy Detect threshold + #offset value range: 0x80 to 0x7F + + ed_ctrl_5g.enable:2=0x1 # 0 - disable EU adaptivity for 5GHz band + # 1 - enable EU adaptivity for 5GHz band + + ed_ctrl_5g.offset:2=0x4 # 0 - Default Energy Detect threshold + #offset value range: 0x80 to 0x7F + + ed_ctrl_txq_lock:4=0xFF #DO NOT Change this line +} diff --git a/mwifiex_8997/mapp/mlanconfig/config/host_tdls.conf b/mwifiex_8997/mapp/mlanconfig/config/host_tdls.conf new file mode 100755 index 0000000..3316d79 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/host_tdls.conf @@ -0,0 +1,22 @@ +# File : host_tdls.conf + +######################### HOST TDLS commands configuration ################## +# starts with a command name with parameters embedded inside + +host_tdls_config={ + uapsd_support=1 # 1: suport uapsd, 0: uapsd not support + cs_support=1 # 1: support channel switch, 0: don't support channel switch + SupportedChannels={ + FirstChannelNo=1 + NumberofSubBandChannels=11 + # multiple instances of First Channel No, Number of SubBand Channels + } + SupportedRegulatoryClasses={ + CurrentRegulatoryClass=1 + NumofRegulatoryClasses=15 + ListOfRegulatoryClasses=1,2,3,4,12,22,23,24,25,27,28,29,30,32,33 + } + +} + +######################### HOST TDLS commands configuration ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/init_cfg.conf b/mwifiex_8997/mapp/mlanconfig/config/init_cfg.conf new file mode 100755 index 0000000..d37cc4d --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/init_cfg.conf @@ -0,0 +1,11 @@ +# File : init_cfg.conf + +# MAC address (interface: address) +mac_addr=mlan0: 00:50:43:20:12:34 +mac_addr=uap0: 00:50:43:20:12:35 +mac_addr=wfd0: 00:50:43:20:12:36 + +# Register (type, offset, value) +# type 1:MAC/SOC, 2:BBP, 3:RF, 5:CAU +wlan_reg=1,0xA794,0x55FF55FF + diff --git a/mwifiex_8997/mapp/mlanconfig/config/mef.conf b/mwifiex_8997/mapp/mlanconfig/config/mef.conf new file mode 100755 index 0000000..37d19a4 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/mef.conf @@ -0,0 +1,167 @@ +# File : mef.conf + +######################### MEF Configuration command ################## +mefcfg={ + #Criteria: bit0-broadcast, bit1-unicast, bit3-multicast + Criteria=2 # Unicast frames are received during hostsleepmode + NumEntries=1 # Number of activated MEF entries + #mef_entry_0: example filters to match TCP destination port 80 send by 192.168.0.88 pkt or magic pkt. + mef_entry_0={ + #mode: bit0--hostsleep mode, bit1--non hostsleep mode + mode=1 # HostSleep mode + #action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host + action=3 # Allow and Wake host + filter_num=3 # Number of filter + #RPN only support "&&" and "||" operator,space can not be removed between operator. + RPN=Filter_0 && Filter_1 || Filter_2 + #Byte comparison filter's type is 0x41,Decimal comparison filter's type is 0x42, + #Bit comparison filter's type is 0x43 + #Filter_0 is decimal comparison filter, it always with type=0x42 + #Decimal filter always has type, pattern, offset, numbyte 4 field + #Filter_0 will match rx pkt with TCP destination port 80 + Filter_0={ + type=0x42 # decimal comparison filter + pattern=80 # 80 is the decimal constant to be compared + offset=44 # 44 is the byte offset of the field in RX pkt to be compare + numbyte=2 # 2 is the number of bytes of the field + } + #Filter_1 is Byte comparison filter, it always with type=0x41 + #Byte filter always has type, byte, repeat, offset 4 filed + #Filter_1 will match rx pkt send by IP address 192.168.0.88 + Filter_1={ + type=0x41 # Byte comparison filter + repeat=1 # 1 copies of 'c0:a8:00:58' + byte=c0:a8:00:58 # 'c0:a8:00:58' is the byte sequence constant with each byte + # in hex format, with ':' as delimiter between two byte. + offset=34 # 34 is the byte offset of the equal length field of rx'd pkt. + } + #Filter_2 is Magic packet, it will looking for 16 contiguous copies of '00:50:43:20:01:02' from + # the rx pkt's offset 14 + Filter_2={ + type=0x41 # Byte comparison filter + repeat=16 # 16 copies of '00:50:43:20:01:02' + byte=00:50:43:20:01:02 # '00:50:43:20:01:02' is the byte sequence constant + offset=14 # 14 is the byte offset of the equal length field of rx'd pkt. + } + } +} + + +#--------------------------examples for MEF filters-------------------------------- +# example: filters to match ARP packet with protocol addr 192.168.0.104 +# mef_entry_0={ +# mode=1 # HostSleep mode +# action=3 # Allow and Wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 && Filter_1 && Filter_2 +# #Filter_0 looking for rx pkt with DA is broadcast address +# Filter_0={ +# type=0x41 +# repeat=6 +# byte=ff +# offset=0 +# } +# #Filter_1 looking for rx pkt with EtherType is 0x0806(ARP) +# Filter_1={ +# type=0x41 +# repeat=1 +# byte=08:06 +# offset=20 +# } +# #Filter_2 looking for rx pkt with ARP target protocol addr 192.168.0.104 +# Filter_2={ +# type=0x41 +# repeat=1 +# byte=c0:a8:00:68 +# offset=46 +# } +# } +#------------------------------------------------------------------------------------- +# example: filter to check if the destination MAC address is unicast pkt +# mef_entry_0={ +# mode=1 # HostSleep mode +# action=3 # Allow and Wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 +# #Filter_0 is Bit comparison filter, it always with type=0x43 +# #Byte filter always has type, byte, mask, offset 4 filed +# #"byte" is the byte sequence constant with each byte in hex format, with ':' as delimiter between two byte +# #"mask" is also with each byte in hex format, with ':' as delimiter between two byte +# #"byte" should has the same length as "mask" +# #Filter_0 will check if the destination MAC address is unicast pkt +# Filter_0={ +# type=0x43 #Bit comparison filter +# byte=00 #00 is the 1-byte sequence constant +# offset=0 #0 is the byte offset of the rx pkt +# mask=01 #1 is the 1-byte mask +# } +# } +#-------------------------------------------------------------------------------------------------- +# example: Disable MEF filters +# mefcfg={ +# #Criteria: bit0-broadcast, bit1-unicast, bit3-multicast +# Criteria=2 # Unicast frames are received during hostsleepmode +# NumEntries=0 # Number of activated MEF entries +# } +#-------------------------------------------------------------------------------------------------- +# example: Test MEF filters +# mefcfg={ +# Criteria=1 +# NumEntries=1 +# mef_entry_0={ +# mode=4 # Test Mode +# action=16 # Invoke Test +# filter_num=0 +# } +# } +#----------------------------------------------------------------------------------------------------- +# example: Test MEF filters +# mefcfg={ +# Criteria=1 +# NumEntries=1 +# mef_entry_0={ +# mode=4 +# action=0 +# filter_num=1 +# RPN=Filter_0 +# Filter_0={ +# type=0x44 # test filter +# repeat=2 # 2 copies of 'BE:EF' +# byte=BE:EF # 'BE:EF' is the byte sequence constant +# offset=18 # 18 is the byte offset of the equal length field of rx'd pkt. +# dest=00:50:43:20:5a:82 # '00:50:43:20:5a:82' is the byte sequence constant +# } +# } +# } +#---------------------------------------------------------------------------------------------------- +#example: Filter broadcast/ipv4 multicast/ipv6 multicast packets in non hostsleep mode +#mefcfg={ +# Criteria=9 # broadcast and multicast frames +# NumEntries=1 # Number of activated MEF entries +# mef_entry_0={ +# mode=2 # non HostSleep mode +# action=0 # discard and not wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 || Filter_1 || Filter_2 +# Filter_0={ # IPV4 multicast +# type=0x41 # byte comparison filter +# byte=01:00:5e # 01:00:5e is the byte constant to be compared +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# repeat=1 # +# } +# Filter_1={ # broadcast packet check +# type=0x41 # Byte comparison filter +# repeat=6 # 6 copies of 'ff', means broadcast +# byte=ff # 'ff'(0xff) is the byte sequence constant with each byte +# # in hex format, with ':' as delimiter between two byte. +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# } +# Filter_2={ # IPV6 multicast +# type=0x41 # byte comparison filter +# byte=33:33 # 33:33 is the byte constant to be compared +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# repeat=1 # +# } +# } +#} +#------------------------------------------------------------------------------------------------------ diff --git a/mwifiex_8997/mapp/mlanconfig/config/mef_mdns.conf b/mwifiex_8997/mapp/mlanconfig/config/mef_mdns.conf new file mode 100755 index 0000000..568ca6f --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/mef_mdns.conf @@ -0,0 +1,204 @@ +# File : mef_mdns.conf + +######################### MEF Configuration command ################## +mefcfg={ + #Criteria: bit0-broadcast, bit1-unicast, bit3-multicast + Criteria=8 # Multicast frames are received during hostsleepmode + NumEntries=2 # Number of activated MEF entries + #mef_entry_0: example filters to match WS-Discovery pkt for IPv4. + mef_entry_0={ + #mode: bit0--hostsleep mode, bit1--non hostsleep mode + mode=1 # HostSleep mode + #action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host + action=3 # Allow and Wake host + filter_num=4 # Number of filter + #RPN only support "&&" and "||" operator,space can not be removed between operator. + RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3 + #Filter_0 will match IPv4 protocol packet + Filter_0={ + type=0x41 + repeat=1 + byte=08:00 + offset=20 + } + #Filter_1 will match dest multicast IPv4 address 224.0.0.251 + Filter_1={ + type=0x41 + repeat=1 + byte=e0:00:00:fb + offset=38 + } + #Filter_2 will match UDP packet + Filter_2={ + type=0x42 + pattern=17 + offset=31 + numbyte=1 + } + #Filter_3 will match UDP port 5353 + Filter_3={ + type=0x42 + pattern=5353 + offset=44 + numbyte=2 + } + } + #mef_entry_1: example filters to match WS-Discovery pkt for IPv6. + mef_entry_1={ + #mode: bit0--hostsleep mode, bit1--non hostsleep mode + mode=1 # HostSleep mode + #action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host + action=3 # Allow and Wake host + filter_num=4 # Number of filter + #RPN only support "&&" and "||" operator,space can not be removed between operator. + RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3 + #Filter_0 will match IPv4 protocol packet + Filter_0={ + type=0x41 + repeat=1 + byte=86:dd + offset=20 + } + #Filter_1 will match dest multicast IPv6 address FF02::FB + Filter_1={ + type=0x41 + repeat=1 + byte=ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:fb + offset=46 + } + #Filter_2 will match UDP packet + Filter_2={ + type=0x42 + pattern=17 + offset=28 + numbyte=1 + } + #Filter_3 will match UDP port 5353 + Filter_3={ + type=0x42 + pattern=5353 + offset=64 + numbyte=2 + } + } +} + + +#--------------------------examples for MEF filters-------------------------------- +# example: filters to match ARP packet with protocol addr 192.168.0.104 +# mef_entry_0={ +# mode=1 # HostSleep mode +# action=3 # Allow and Wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 && Filter_1 && Filter_2 +# #Filter_0 looking for rx pkt with DA is broadcast address +# Filter_0={ +# type=0x41 +# repeat=6 +# byte=ff +# offset=0 +# } +# #Filter_1 looking for rx pkt with EtherType is 0x0806(ARP) +# Filter_1={ +# type=0x41 +# repeat=1 +# byte=08:06 +# offset=20 +# } +# #Filter_2 looking for rx pkt with ARP target protocol addr 192.168.0.104 +# Filter_2={ +# type=0x41 +# repeat=1 +# byte=c0:a8:00:68 +# offset=46 +# } +# } +#------------------------------------------------------------------------------------- +# example: filter to check if the destination MAC address is unicast pkt +# mef_entry_0={ +# mode=1 # HostSleep mode +# action=3 # Allow and Wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 +# #Filter_0 is Bit comparison filter, it always with type=0x43 +# #Byte filter always has type, byte, mask, offset 4 filed +# #"byte" is the byte sequence constant with each byte in hex format, with ':' as delimiter between two byte +# #"mask" is also with each byte in hex format, with ':' as delimiter between two byte +# #"byte" should has the same length as "mask" +# #Filter_0 will check if the destination MAC address is unicast pkt +# Filter_0={ +# type=0x43 #Bit comparison filter +# byte=00 #00 is the 1-byte sequence constant +# offset=0 #0 is the byte offset of the rx pkt +# mask=01 #1 is the 1-byte mask +# } +# } +#-------------------------------------------------------------------------------------------------- +# example: Disable MEF filters +# mefcfg={ +# #Criteria: bit0-broadcast, bit1-unicast, bit3-multicast +# Criteria=2 # Unicast frames are received during hostsleepmode +# NumEntries=0 # Number of activated MEF entries +# } +#-------------------------------------------------------------------------------------------------- +# example: Test MEF filters +# mefcfg={ +# Criteria=1 +# NumEntries=1 +# mef_entry_0={ +# mode=4 # Test Mode +# action=16 # Invoke Test +# filter_num=0 +# } +# } +#----------------------------------------------------------------------------------------------------- +# example: Test MEF filters +# mefcfg={ +# Criteria=1 +# NumEntries=1 +# mef_entry_0={ +# mode=4 +# action=0 +# filter_num=1 +# RPN=Filter_0 +# Filter_0={ +# type=0x44 # test filter +# repeat=2 # 2 copies of 'BE:EF' +# byte=BE:EF # 'BE:EF' is the byte sequence constant +# offset=18 # 18 is the byte offset of the equal length field of rx'd pkt. +# dest=00:50:43:20:5a:82 # '00:50:43:20:5a:82' is the byte sequence constant +# } +# } +# } +#---------------------------------------------------------------------------------------------------- +#example: Filter broadcast/ipv4 multicast/ipv6 multicast packets in non hostsleep mode +#mefcfg={ +# Criteria=9 # broadcast and multicast frames +# NumEntries=1 # Number of activated MEF entries +# mef_entry_0={ +# mode=2 # non HostSleep mode +# action=0 # discard and not wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 || Filter_1 || Filter_2 +# Filter_0={ # IPV4 multicast +# type=0x41 # byte comparison filter +# byte=01:00:5e # 01:00:5e is the byte constant to be compared +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# repeat=1 # +# } +# Filter_1={ # broadcast packet check +# type=0x41 # Byte comparison filter +# repeat=6 # 6 copies of 'ff', means broadcast +# byte=ff # 'ff'(0xff) is the byte sequence constant with each byte +# # in hex format, with ':' as delimiter between two byte. +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# } +# Filter_2={ # IPV6 multicast +# type=0x41 # byte comparison filter +# byte=33:33 # 33:33 is the byte constant to be compared +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# repeat=1 # +# } +# } +#} +#------------------------------------------------------------------------------------------------------ diff --git a/mwifiex_8997/mapp/mlanconfig/config/mef_ws_discovery.conf b/mwifiex_8997/mapp/mlanconfig/config/mef_ws_discovery.conf new file mode 100755 index 0000000..518a240 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/mef_ws_discovery.conf @@ -0,0 +1,204 @@ +# File : mef_ws_discovery.conf + +######################### MEF Configuration command ################## +mefcfg={ + #Criteria: bit0-broadcast, bit1-unicast, bit3-multicast + Criteria=8 # Multicast frames are received during hostsleepmode + NumEntries=2 # Number of activated MEF entries + #mef_entry_0: example filters to match WS-Discovery pkt for IPv4. + mef_entry_0={ + #mode: bit0--hostsleep mode, bit1--non hostsleep mode + mode=1 # HostSleep mode + #action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host + action=3 # Allow and Wake host + filter_num=4 # Number of filter + #RPN only support "&&" and "||" operator,space can not be removed between operator. + RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3 + #Filter_0 will match IPv4 protocol packet + Filter_0={ + type=0x41 + repeat=1 + byte=08:00 + offset=20 + } + #Filter_1 will match dest multicast IPv4 address 239.255.255.250 + Filter_1={ + type=0x41 + repeat=1 + byte=ef:ff:ff:fa + offset=38 + } + #Filter_2 will match UDP packet + Filter_2={ + type=0x42 + pattern=17 + offset=31 + numbyte=1 + } + #Filter_3 will match UDP port 3702 + Filter_3={ + type=0x42 + pattern=3702 + offset=44 + numbyte=2 + } + } + #mef_entry_1: example filters to match WS-Discovery pkt for IPv6. + mef_entry_1={ + #mode: bit0--hostsleep mode, bit1--non hostsleep mode + mode=1 # HostSleep mode + #action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host + action=3 # Allow and Wake host + filter_num=4 # Number of filter + #RPN only support "&&" and "||" operator,space can not be removed between operator. + RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3 + #Filter_0 will match IPv4 protocol packet + Filter_0={ + type=0x41 + repeat=1 + byte=86:dd + offset=20 + } + #Filter_1 will match dest multicast IPv6 address FF02::C + Filter_1={ + type=0x41 + repeat=1 + byte=ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:0c + offset=46 + } + #Filter_2 will match UDP packet + Filter_2={ + type=0x42 + pattern=17 + offset=28 + numbyte=1 + } + #Filter_3 will match UDP port 3702 + Filter_3={ + type=0x42 + pattern=3702 + offset=64 + numbyte=2 + } + } +} + + +#--------------------------examples for MEF filters-------------------------------- +# example: filters to match ARP packet with protocol addr 192.168.0.104 +# mef_entry_0={ +# mode=1 # HostSleep mode +# action=3 # Allow and Wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 && Filter_1 && Filter_2 +# #Filter_0 looking for rx pkt with DA is broadcast address +# Filter_0={ +# type=0x41 +# repeat=6 +# byte=ff +# offset=0 +# } +# #Filter_1 looking for rx pkt with EtherType is 0x0806(ARP) +# Filter_1={ +# type=0x41 +# repeat=1 +# byte=08:06 +# offset=20 +# } +# #Filter_2 looking for rx pkt with ARP target protocol addr 192.168.0.104 +# Filter_2={ +# type=0x41 +# repeat=1 +# byte=c0:a8:00:68 +# offset=46 +# } +# } +#------------------------------------------------------------------------------------- +# example: filter to check if the destination MAC address is unicast pkt +# mef_entry_0={ +# mode=1 # HostSleep mode +# action=3 # Allow and Wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 +# #Filter_0 is Bit comparison filter, it always with type=0x43 +# #Byte filter always has type, byte, mask, offset 4 filed +# #"byte" is the byte sequence constant with each byte in hex format, with ':' as delimiter between two byte +# #"mask" is also with each byte in hex format, with ':' as delimiter between two byte +# #"byte" should has the same length as "mask" +# #Filter_0 will check if the destination MAC address is unicast pkt +# Filter_0={ +# type=0x43 #Bit comparison filter +# byte=00 #00 is the 1-byte sequence constant +# offset=0 #0 is the byte offset of the rx pkt +# mask=01 #1 is the 1-byte mask +# } +# } +#-------------------------------------------------------------------------------------------------- +# example: Disable MEF filters +# mefcfg={ +# #Criteria: bit0-broadcast, bit1-unicast, bit3-multicast +# Criteria=2 # Unicast frames are received during hostsleepmode +# NumEntries=0 # Number of activated MEF entries +# } +#-------------------------------------------------------------------------------------------------- +# example: Test MEF filters +# mefcfg={ +# Criteria=1 +# NumEntries=1 +# mef_entry_0={ +# mode=4 # Test Mode +# action=16 # Invoke Test +# filter_num=0 +# } +# } +#----------------------------------------------------------------------------------------------------- +# example: Test MEF filters +# mefcfg={ +# Criteria=1 +# NumEntries=1 +# mef_entry_0={ +# mode=4 +# action=0 +# filter_num=1 +# RPN=Filter_0 +# Filter_0={ +# type=0x44 # test filter +# repeat=2 # 2 copies of 'BE:EF' +# byte=BE:EF # 'BE:EF' is the byte sequence constant +# offset=18 # 18 is the byte offset of the equal length field of rx'd pkt. +# dest=00:50:43:20:5a:82 # '00:50:43:20:5a:82' is the byte sequence constant +# } +# } +# } +#---------------------------------------------------------------------------------------------------- +#example: Filter broadcast/ipv4 multicast/ipv6 multicast packets in non hostsleep mode +#mefcfg={ +# Criteria=9 # broadcast and multicast frames +# NumEntries=1 # Number of activated MEF entries +# mef_entry_0={ +# mode=2 # non HostSleep mode +# action=0 # discard and not wake host +# filter_num=3 # Number of filter +# RPN=Filter_0 || Filter_1 || Filter_2 +# Filter_0={ # IPV4 multicast +# type=0x41 # byte comparison filter +# byte=01:00:5e # 01:00:5e is the byte constant to be compared +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# repeat=1 # +# } +# Filter_1={ # broadcast packet check +# type=0x41 # Byte comparison filter +# repeat=6 # 6 copies of 'ff', means broadcast +# byte=ff # 'ff'(0xff) is the byte sequence constant with each byte +# # in hex format, with ':' as delimiter between two byte. +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# } +# Filter_2={ # IPV6 multicast +# type=0x41 # byte comparison filter +# byte=33:33 # 33:33 is the byte constant to be compared +# offset=0 # 0 is the byte offset of the equal length field of rx'd pkt. +# repeat=1 # +# } +# } +#} +#------------------------------------------------------------------------------------------------------ diff --git a/mwifiex_8997/mapp/mlanconfig/config/mem.conf b/mwifiex_8997/mapp/mlanconfig/config/mem.conf new file mode 100755 index 0000000..cf649c9 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/mem.conf @@ -0,0 +1,17 @@ +#File : memory/register update +# memory/register update file +mem_set={ + CmdCode=0x0086 #do NOT change this line + Action:2=1 # 1 - SET + Rsrvd:2=0 + Addr:4=0x8000a584 # memory/register address + Value:4=0x16161669 #Value +} + +mem_get={ + CmdCode=0x0086 #do NOT change this line + Action:2=0 # 1 - SET + Rsrvd:2=0 + Addr:4=0x8000a584 # memory/register address + Result:4=0 +} diff --git a/mwifiex_8997/mapp/mlanconfig/config/mgmt_frame.conf b/mwifiex_8997/mapp/mlanconfig/config/mgmt_frame.conf new file mode 100755 index 0000000..22b19b1 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/mgmt_frame.conf @@ -0,0 +1,30 @@ +# Format of the packet data to be sent. +# Update the TxControl value for TxPD, else zero is sent. +# all packet data is written under "Data" block + +PktType=0x00 # should be zero for MGMT frames +PktSubType=0x05 + # Assoc Request 0 + # Assoc Response 1 + # Re-Assoc Request 2 + # Re-Assoc Response 3 + # Probe Request 4 + # Probe Response 5 + # Beacon 8 + # Atim 9 + # Dis-assoc 10 + # Auth 11 + # Deauth 12 + # Action Frame 13 + +FromDS=0 +ToDS=0 + +Addr1=00:50:43:27:B0:41 # Destination address +Addr2=00:50:43:21:0F:84 # Source address +Addr3=00:50:43:21:0F:84 # BSSID + +Data=0x01,0x01,0x00,0x0c,0x00,0x58,0x02,0x40 + +SeqNum=0 +FragNum=0 diff --git a/mwifiex_8997/mapp/mlanconfig/config/mgmtfilter.conf b/mwifiex_8997/mapp/mlanconfig/config/mgmtfilter.conf new file mode 100755 index 0000000..8ee0298 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/mgmtfilter.conf @@ -0,0 +1,15 @@ +##############management frame filter to wake up host ########### +##### support two entries currently ###### +mgmtfilter={ + entry_num=1 + entry_0={ + action=1 # discard and wakeup host + type=0x1 # p2p frames + frame_mask=0x7 # Go neg req & rsp & cfm frame + } +# entry_1={ +# action=0 # discard and not wakeup host +# type=0xff # management frames +# frame_mask=0x3 # assoc req & rsp frame +# } +} diff --git a/mwifiex_8997/mapp/mlanconfig/config/or_data.conf b/mwifiex_8997/mapp/mlanconfig/config/or_data.conf new file mode 100755 index 0000000..99154f5 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/or_data.conf @@ -0,0 +1,7 @@ + 07 01 03 3A 80 00 3A 00 ff ff 00 17 03 00 07 03 + 09 00 0e 10 16 02 19 25 1a 04 1c ff 32 5e 33 15 + 35 29 36 17 4b 74 4c 64 4d 3b 50 27 61 d6 62 98 + 6b ae 6f 5b 77 f2 79 ff 7f 2d + 07 01 12 16 c0 00 ff ff ff ff 00 05 03 10 32 5c + 33 1a 6b a2 7f 20 + diff --git a/mwifiex_8997/mapp/mlanconfig/config/pad_cfg.conf b/mwifiex_8997/mapp/mlanconfig/config/pad_cfg.conf new file mode 100755 index 0000000..80e2788 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/pad_cfg.conf @@ -0,0 +1,11 @@ +# File : pad_cfg.conf + +## Get CFG data for PAD OR +pad_cfg_get={ + CmdCode=0x008f # do NOT change this line + Action:2=0 # 0 - GET + Type:2=5 # 5 - optimized pad reg + CfgLen:2={ + } +} + diff --git a/mwifiex_8997/mapp/mlanconfig/config/requesttpc.conf b/mwifiex_8997/mapp/mlanconfig/config/requesttpc.conf new file mode 100755 index 0000000..690c30d --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/requesttpc.conf @@ -0,0 +1,15 @@ +# File : requesttpc.conf + +######################### requesttpc command configuration ################## + +requesttpc={ + CmdCode=0x0060 # do NOT change this line + #DestMac: Destination STA address + DestMac:6='0x02,0x04,0x0e,0x06,0x01,0x12' + #RateIndex: IEEE Rate index to send request + RateIndex:1=22 + #Timeout: Response timeout in ms + Timeout:2=10 +} + +######################### End of requesttpc command configuration ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/robust_btc.conf b/mwifiex_8997/mapp/mlanconfig/config/robust_btc.conf new file mode 100755 index 0000000..fd33a88 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/robust_btc.conf @@ -0,0 +1,212 @@ +# File : robust_btc.conf + +######################### Robust Coex command ############### +mode_get={ + CmdCode=0x00e0 # do NOT change this line + Action:2=0 # GET + RSVD:2=0 + + # Robust Coex Mode TLV + RobustCoexTlvType:2=0x0160 + RobustCoexTlvLength:2={ + Enable:1=0x00 # Read-back Coex mode(s) + Reserved:3=0 + } +} + +mode_timeshare={ + CmdCode=0x00e0 # do NOT change this line + Action:2=1 # SET + RSVD:2=0 + + # Robust Coex Mode TLV + RobustCoexTlvType:2=0x0160 + RobustCoexTlvLength:2={ + # All the modes below are mutually exclusive of each other; + Enable:1=0x01 # Bit0: Enable 2x2 or 1x1 Time Distribute(TMD) + # Robust Coex(RBC) mode, when uAP bss start, + # uAP TMD RBC scheme is enabled, + # STA TMD RBC scheme is disabled. + Reserved:3=0 + } +} + +mode_spatial={ + CmdCode=0x00e0 # do NOT change this line + Action:2=1 # SET + RSVD:2=0 + + # Robust Coex Mode TLV + RobustCoexTlvType:2=0x0160 + RobustCoexTlvLength:2={ + # All the modes below are mutually exclusive of each other; + Enable:1=0x82 # Bit1: Enable 1x1 SMPS Spatial RBC Mode, e.g. 0x02 + # Bit7: Enable uAP+STA SMPS RBC Mode, + # when uAP bss start, uAP SMPS RBC scheme enable, + # must combined with BIT1 or BIT2, e.g. 0x82, 0x84. + Reserved:3=0 + } +} + +mode_none={ + CmdCode=0x00e0 # do NOT change this line + Action:2=1 # SET + RSVD:2=0 + + # Robust Coex Mode TLV + RobustCoexTlvType:2=0x0160 + RobustCoexTlvLength:2={ + Enable:1=0 # Concurrent Coex mode. Used for chips which has + # separate antenna for BT + Reserved:3=0 + } +} + +mode_2={ + CmdCode=0x00e0 # do NOT change this line + Action:2=1 # SET + RSVD:2=0 + + # Robust Coex Mode TLV + RobustCoexTlvType:2=0x0160 + RobustCoexTlvLength:2={ + Enable:1=0x20 # Concurrent Coex mode with Tx power control and Rx De-sense. + # Used for chips which has separate antenna for BT + Reserved:3=0 + } +} + +gpio_cfg={ + CmdCode=0x00e0 # do NOT change this line + Action:2=1 # SET + RSVD:2=0 + + # Robust Coex Mode TLV + RobustCoexTlvType:2=0x021B + RobustCoexTlvLength:2={ + Enable:1=0x1 # enable GPIO cfg for external bt request + gpionum:1=4 # gpio 4 + gpiopolarity:1=1 # Polarity High + } +} + +external_coex_config={ + CmdCode=0x00e0 + Action:2=1 //0x0 get, 0x1 set + RSVD:2=0 + RobustCoexTlvType:2=0x0238 //TLV ID + RobustCoexTlvLength:2={ + Enabled:1=0x01 // 0x00 disable, 0x01 enalbe + + ExtHighInputPriority:1=0x02 // Input priority: 0x00 Input Low Priority, 0x01 Input Medium Priority, 0x02 Input High Priority + ExtLowInputPriority:1=0x02 + + ExtPriGPIONum:1=0x06; // Input Priority signal GPIO pin number + ExtPriGPIOPolarity:1=0x01; // Polarity: 0x00 Active Low, 0x01 Active High + + ExtReqGPIONum:1=0x07; // Input Request signal GPIO pin number + ExtReqGPIOPolarity:1=0x01; // Polarity: 0x00 Active Low, 0x01 Active High + + ExtGrntGPIONum:1=0x05; // Output Grant signal GPIO pin number + ExtGrntGPIOPolarity:1=0x01; // Polarity: 0x00 Active Low, 0x01 Active High + + } +} + +#In Station generic case +#BT time is set as BTTime +#Wlan time is set as Wlan Time +generictime={ + CmdCode=0x00e0 + Action:2=1 + RSVD:2=0 + RobustCoexTlvType:2=0x0390 + RobustCoexTlvLength:2={ + Enable:2=0x01 + BtTime:2=10000 #(10ms) BTTime must be less than 65535 + WlanTime:2=40000 #(40ms) WlanTime must be less than 65535 + } +} + +#In Station A2DP case +#BT time is set as BTTime +#Wlan time is set as Wlan Time +a2dptime={ + CmdCode=0x00e0 + Action:2=1 + RSVD:2=0 + RobustCoexTlvType:2=0x0391 + RobustCoexTlvLength:2={ + Enable:2=0x01 + BtTime:2=10000 #(10ms) BTTime must be less than 65535 + WlanTime:2=39500 #(39.5ms) WlanTime must be less than 65535 + } +} + +#In Station inquiry case +#BT time is set as BTTime +#Wlan time is set as Wlan Time +inquirytime={ + CmdCode=0x00e0 + Action:2=1 + RSVD:2=0 + RobustCoexTlvType:2=0x0392 + RobustCoexTlvLength:2={ + Enable:2=0x01 + BtTime:2=21215 #(21.215ms) BTTime must be less than 65535 + WlanTime:2=11000 #(11ms) WlanTime must be less than 65535 + } +} + +#In Ap generic case +#BT time is BTTimeBusy when BT has traffic +#BT time is BTTimeIdle when BT is idle +#Wlan time is WlanTimeBusy when Wlan has traffic +#Wlan time is WlanTimeIdle when Wlan is idle +ap_generictime={ + CmdCode=0x00e0 + Action:2=1 + RSVD:2=0 + RobustCoexTlvType:2=0x0393 + RobustCoexTlvLength:2={ + Enable:2=0x01 + BtTime_MAX:2=23000 #(23ms) BTTime(BT Busy) must be less than 28767 + BtTime_MIN:2=6500 #(6.5ms) BTTime(BT Idle) must be less than 28767 + WlanTime_MAX:2=18000 #(18ms) WlanTime(Wlan Busy) must be less than 32767 + WlanTime_MIN:2=5750 #(5.75ms) WlanTime(Wlan Idle) must be less than 32767 + } +} + +#In Ap A2DP case +#BT time is change from BTTimeMax to BTTimeMin +#Wlan time is change from WlanTimeMax to WlanTimeMin +ap_a2dptime={ + CmdCode=0x00e0 + Action:2=1 + RSVD:2=0 + RobustCoexTlvType:2=0x0394 + RobustCoexTlvLength:2={ + Enable:2=0x01 + BtTimebusy:2=23000 #(23ms) Maximum BTTime must be less than 32767 + BtTimeidle:2=6500 #(6.5ms) Minimum BTTime must be less than 32767 + WlanTimebusy:2=18000 #(18ms) Maximum WlanTime must be less than 32767 + WlanTimeidle:2=5750 #(5.75ms) Minimum WlanTime must be less than 32767 + } +} + +#In Ap inquiry case +#BT time is set as BTTime +#Wlan time is set as Wlan Time +ap_inquirytime={ + CmdCode=0x00e0 + Action:2=1 + RSVD:2=0 + RobustCoexTlvType:2=0x0395 + RobustCoexTlvLength:2={ + Enable:2=0x01 + BtTime:2=28750 #(28.75ms) BTTime must less than 32767 + WlanTime:2=20000 #(20ms) WlanTime must be less than 32767 + } +} + +######################### Robust Coex command ############### diff --git a/mwifiex_8997/mapp/mlanconfig/config/small_debug.conf b/mwifiex_8997/mapp/mlanconfig/config/small_debug.conf new file mode 100755 index 0000000..1457426 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/small_debug.conf @@ -0,0 +1,62 @@ +# File : small_debug.conf + +######################### DBG Config command ############### +small_debug_enable={ + CmdCode=0x008b # do NOT change this line + + Dst:1=0x06 # dbgs_cfg_t + Air_Chan:1=0x00 + RSVD:1=0 + Num_Entries:1=0x81 # one entry global enable + + # dbgs_t + En_Mask:2=0x0000 # en_mask_id + BaseId:2=0x0000 # base_id +} + +small_debug_disable={ + CmdCode=0x008b # do NOT change this line + + Dst:1=0x00 + Air_Chan:1=0x00 + RSVD:1=0 + Num_Entries:1=0x00 +} + +######################### DBG Get Trace Memory ############### +# Disable Air and Host destinations to disable dbgs_drain +# Enable only the Power save ID - Host interface is a course enable - not on specific event +trace_enable={ + CmdCode=0x008b # do NOT change this line + + Dst:1=0x00 # dbgs_cfg_t - don't drain debug + Air_Chan:1=0x00 + RSVD:1=0 + Num_Entries:1=0x02 # 2 entry + + # dbgs_t + En_Mask:2=0x5fff # en_mask_id - enable single ID=0x80 + BaseId:2=0x0020 # base_id + En_Mask:2=0x5fff # en_mask_id - enable single ID=0x80 + BaseId:2=0x0021 # base_id +} + +get_trace={ + CmdCode=0x008c # do NOT change this line + + startAddress:4=0x02 # read trace memeory - not a generic memory read + len:2=0x0000 # First read=0 - for next reads use the returned next start +} + +trace_disable={ + CmdCode=0x008b # do NOT change this line + + Dst:1=0x00 # dbgs_cfg_t - don't drain debug + Air_Chan:1=0x00 + RSVD:1=0 + Num_Entries:1=0x01 # one entry + + # dbgs_t + En_Mask:2=0x0000 # en_mask_id + BaseId:2=0x0000 # base_id +} diff --git a/mwifiex_8997/mapp/mlanconfig/config/smc.conf b/mwifiex_8997/mapp/mlanconfig/config/smc.conf new file mode 100755 index 0000000..9bead4c --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/smc.conf @@ -0,0 +1,124 @@ +# File : smc.conf + +smc_get={ + CmdCode=0x012d #do not change this + + Action:2=0 # GET +} + +smc_set={ + CmdCode=0x012d #do not change this + + Action:2=1 # SET + +# SSID + SSIDHeaderType:2=0x0000 + SSIDHeaderLen:2={ + SSID:10="Marvell_SMC_1" + } + +# Beacon Period. +# This should be smaller than than MinScanTime. + BeaconHeaderType:2=0x012c + BeaconHeaderLen:2={ + beaconPeriod:2=30 + } + +# Channel list. +# ChanNumber, MinScanTime and ScanTime are mandatory. +# MinScanTime is minimum dwelling time for ChanNumber channel. +# ScanTime is maximum dwelling time for ChanNumber channel. + ChannHeaderType:2=0x0101 + ChannHeaderLen:2={ + +# Following four line define one channel. +# Please add similar four lines with different channel number for new channel. + Chan1_RadioType:1=0 + Chan1_ChanNumber:1=1 + Chan1_ScanType:1=2 + Chan1_MinScanTime:2=40 + Chan1_ScanTime:2=200 + + Chan2_RadioType:1=0 + Chan2_ChanNumber:1=6 + Chan2_ScanType:1=3 + Chan2_MinScanTime:2=40 + Chan2_ScanTime:2=200 + + Chan3_RadioType:1=0 + Chan3_ChanNumber:1=9 + Chan3_ScanType:1=2 + Chan3_MinScanTime:2=40 + Chan3_ScanTime:2=100 + + Chan2_RadioType:1=0 + Chan2_ChanNumber:1=11 + Chan2_ScanType:1=3 + Chan2_MinScanTime:2=40 + Chan2_ScanTime:2=200 + } + +#Custom IE +#Currently max size of custom IE supported is 50 bytes. +# +# CustomHeaderType:2=0x010a +# CustomHeaderLen:2={ +# start:1=0xdd +# start:1=0x10 +# start:1=0x00 +# start:1=0x01 +# start:1=0x02 +# start:1=0x03 +# start:1=0x04 +# start:1=0x05 +# start:1=0x06 +# start:1=0x07 +# start:1=0x08 +# start:1=0x09 +# start:1=0x0a +# start:1=0x0b +# start:1=0x0c +# start:1=0x0d +# start:1=0x0e +# start:1=0x0f +# } + +#Multicast mac filtering address +#All the multicast packets from starting mac address to ending mac address would +#be captured and sent to the host. + MACHeaderType:2=0x01cc + MACHeaderLen:2={ +#Staring Multicast mac address + start:1=0x01 + start:1=0x00 + start:1=0x5e + start:1=0x00 + start:1=0x00 + start:1=0x01 + +#Ending Multicast mac address + end:1=0x01 + end:1=0x00 + end:1=0x5e + end:1=0x7f + end:1=0xff + end:1=0xff + +#FilterType +# 1 for RX AP frames +# 2 for RX STA frames +# 3 for both + Filter:2=0x3 + } + +} +smc_start={ + CmdCode=0x012d #do not change this + + Action:2=2 # START +} +smc_stop={ + CmdCode=0x012d #do not change this + + Action:2=3 # STOP +} diff --git a/mwifiex_8997/mapp/mlanconfig/config/subevent.conf b/mwifiex_8997/mapp/mlanconfig/config/subevent.conf new file mode 100755 index 0000000..ac7f333 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/subevent.conf @@ -0,0 +1,103 @@ +# File : subevent.conf + +######################### Subscribe Events command ################## +subevent_get={ + CmdCode=0x0075 # do NOT change this line + + Action:2=0 # GET + Events:2=0 +} + +subevent_set={ + CmdCode=0x0075 # do NOT change this line + + Action:2=1 # SET + Events:2=0xbc8 # bit0 - Beacon RSSI_LOW + # bit1 - Beacon SNR_LOW + # bit2 - FAILED_COUNT + # bit3 - Beacon Missed + # bit4 - Beacon RSSI_HIGH + # bit5 - Beacon SNR_HIGH + # bit6 - Data RSSI_LOW + # bit7 - Data SNR_LOW + # bit8 - Data RSSI_HIGH + # bit9 - Data SNR_HIGH + # bit10 - LINK_QUALITY + # bit11 - PRE_BCN_LOST + # bit12-15 - Reserved + + LowRssiTlvType:2=0x0104 + LowRssiTlvLength:2={ + Threshold:1=70 + ReportingFreq:1=0 + } + + LowSnrTlvType:2=0x0105 + LowSnrTlvLength:2={ + Threshold:1=56 + ReportingFreq:1=0 + } + + FailedCountTlvType:2=0x0106 + FailedCountTlvLength:2={ + Threshold:1=5 + ReportingFreq:1=0 + } + + BeaconMissTlvType:2=0x0107 + BeaconMissTlvLength:2={ + BeaconMissed:1=60 + Reserved:1=0 + } + + HighRssiTlvType:2=0x0116 + HighRssiTlvLength:2={ + Threshold:1=40 + ReportingFreq:1=0 + } + + HighSnrTlvType:2=0x0117 + HighSnrTlvLength:2={ + Threshold:1=86 + ReportingFreq:1=0 + } + + DataLowRssiTlvType:2=0x0126 + DataLowRssiTlvLength:2={ + Threshold:1=10 + ReportingFreq:1=0 + } + + DataLowSnrTlvType:2=0x0127 + DataLowSnrTlvLength:2={ + Threshold:1=66 + ReportingFreq:1=0 + } + + DataHighRssiTlvType:2=0x0128 + DataHighRssiTlvLength:2={ + Threshold:1=50 + ReportingFreq:1=0 + } + + DataHighSnrTlvType:2=0x0129 + DataHighSnrTlvLength:2={ + Threshold:1=96 + ReportingFreq:1=1 + } + LinkQualityTlvType:2=0x0124 + LinkQualityTlvType:2={ + LinkSNRThreshold:2=0x0056 + LinkSNRFrequency:2=0x0003 + MinRateVal:2=0x0014 + MinRateFreq:2=0x0003 + TxLatencyVal:4=0x00C8 + TxLatencyThreshold:4=0x0003 + } + PreBcnLostTlvType:2=0x0149 + PreBcnLostTlvLength:2={ + PreBeaconCnt:1=30 + Reserved:1=0 + } +} +######################### Subscribe Events command ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/tdls.conf b/mwifiex_8997/mapp/mlanconfig/config/tdls.conf new file mode 100755 index 0000000..d7369cf --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/tdls.conf @@ -0,0 +1,118 @@ +# File : tdls.conf + +######################### TDLS commands configuration ################## +# starts with a command name with parameters embedded inside + +tdls_setinfo={ + CapInfo=0x2421 + Rate=0x02,0x04,0x0b,0x16,0x0C,0x12,0x18,0x24,0x30,0x48,0x60,0x6c + QosInfo=0x0F # 1 byte qos capability field. Valid values 0x00 or 0x0F + # For AMPDU over direct link, this should be 0x00 + ExtendCapabilities=0x00,0x00,0x00,0x50,0x20 # Enable Peer U-APSD(Bit28), TDLS channel switch(Bit30), TDLS(Bit37) + HTCapability={ + HTCapabilityInfo=0x62 # 2 byte HT capability field. + AMPDUParam=0x3 + SupportedMCSSet=0xFF,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + HTExtCapability=0x00 + TxBfCapability=0x00 + AntennaSel=0x00 + } + HTInformation={ + PrimaryChannel=1 + Field2=0x0 + Field3=0x5 + Field4=0x0 + BasicMCSSet=0xFF,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + # 16 elements as per the structure. + } + 2040BSSCoex=0x01 # 1 byte 2040 Coex field. + VHTCapability={ + VHTCapabilityInfo=0x33C00000 # 4 byte VHT capability field. + RxMCSMap=0xFFFC + RxMaxRate=0x0000 #bit 29-31 reserved + TxMCSMap=0xFFFC + TxMaxRate=0x0000 #bit 61-63 reserved + } + VHTOper={ + ChanWidth=0x01; + ChanCF1=0x01; + ChanCF2=0x01; + BasicMCSMap=0xFF, 0XFF; #Basic MCS set map, each 2 bits stands for a Nss + } +# Uncomment the RSNInfo while testing open-secure network. + RSNInfo={ + GroupCipherSuite=0x00,0x0F,0xAC,0x07 + PairwiseCipherCount=1 + PairwiseCipherSuite=0x00,0x0F,0xAC,0x04 # CCMP + #PairwiseCipherSuite=0x00,0x0F,0xAC,0x02 # TKIP multiple Pairwise Cipher Suite if count > 1. + AKMSuiteCount=1 + AKMSuite=0x00,0x0F,0xAC,0x07 # multiple AKM Suite if count > 1. + #AKMSuite=0x00,0x0F,0xAC,0x07 # multiple AKM Suite if count > 1. + RSNCapability=0x200 # Enable PeerKey + PMKIDCount=0 + } + SupportedChannels={ + FirstChannelNo=1 + NumberofSubBandChannels=11 + # multiple instances of First Channel No, Number of SubBand Channels + } + SupportedRegulatoryClasses={ + CurrentRegulatoryClass=1 + NumofRegulatoryClasses=15 + ListOfRegulatoryClasses=1,2,3,4,12,22,23,24,25,27,28,29,30,32,33 + } + +# CountryInfo={ +# CountryString="US" # 3 byte country string +# FirstChannel=1 +# NumberofChannels=11 +# TxPower=30 +# # multiple instances of First Channel, Number of Channels, Tx Power +# } +} + +tdls_discovery={ + PeerMAC=00:50:43:27:B0:41 # MAC address of Peer +} + +tdls_setup={ + PeerMAC=00:50:43:27:B0:41 # MAC address of Peer + WaitTimems=3000 # Time in milliseconds to wait + # for setup response from peer + KeyLifetime=301 # Lifetime of security key in seconds. +} + +tdls_teardown={ + PeerMAC=00:50:43:27:B0:41 # MAC address of Peer + ReasonCode=26 # Tear down reason code +} + +tdls_channel_switch={ + PeerMAC=00:50:43:27:B0:41 # MAC address of Peer + Band=0 # Band + PrimaryChannel=6 # Primary channel no for channel switching + SecondaryChannelOffset=0 # Secondary channel offset + Periodicity=1 # Channel switch periodicity + ChannelSwitchTime=10 # Channel switch time in ms. + ChannelSwitchTimeout=14 # Channel switch timeout in ms + RegulatoryClass=12 # Target regulatory class +} + +tdls_cs_params={ + UnitTime=2 # Unit time, multiples of 10 ms + ThresholdOtherLink=10 # Threshold for other link + ThresholdDirectLink=1 # Threshold for direct link +} + + +tdls_stop_channel_switch={ + PeerMAC=00:50:43:27:B0:41 # MAC address of Peer +} + +tdls_powermode={ + PeerMAC=00:50:43:27:B0:41 # MAC address of Peer + PowerMode=1 # 0: Active, 1 : Power Save +} + + +######################### TDLS commands configuration ################## diff --git a/mwifiex_8997/mapp/mlanconfig/config/tspecs.conf b/mwifiex_8997/mapp/mlanconfig/config/tspecs.conf new file mode 100755 index 0000000..86c1ac6 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/tspecs.conf @@ -0,0 +1,100 @@ +# TSPEC contents for TID=0, UserPriority = 6 +[tspec0] +# Element ID +dd +# Length +3d +# OUI +00 50 f2 +# OUI Type +02 +# OUI SubType +02 +# Version +01 +# TSInfo +e0 34 00 +# Nominal MSDU Size +d0 80 +# Maximum MSDU Size +d0 00 +# Min Service Interval +20 4e 00 00 +# Max Service Interval +20 4e 00 00 +# Inactivity Interval +80 96 98 00 +# Suspension Interval +ff ff ff ff +# Service Start Time +00 00 00 00 +# Minimum Data Rate +00 45 01 00 +# Mean Data Rate +00 45 01 00 +# Peak Data Rate +00 45 01 00 +# Max Burst Size +00 00 00 00 +# Delay Bound +00 00 00 00 +# Min PHY Rate +00 1b b7 00 +# Surplus Bandwidth Allowance +00 30 +# Medium Time +00 00 +# Extra Data Bytes +[/tspec0] + + +# TSPEC contents for TID=1, UserPriority = 4 +[tspec1] +# Element ID +dd +# Length +3d +# OUI +00 50 f2 +# OUI Type +02 +# OUI SubType +02 +# Version +01 +# TSInfo +e3 20 00 +# Nominal MSDU Size +96 00 +# Maximum MSDU Size +dc 05 +# Min Service Interval +00 00 00 00 +# Max Service Interval +00 00 00 00 +# Inactivity Interval +00 00 00 00 +# Suspension Interval +ff ff ff ff +# Service Start Time +00 00 00 00 +# Minimum Data Rate +a0 00 00 00 +# Mean Data Rate +a0 00 00 00 +# Peak Data Rate +a0 00 00 00 +# Max Burst Size +00 00 00 00 +# Delay Bound +00 00 00 00 +# Min PHY Rate +80 8d 5b 00 +# Surplus Bandwidth Allowance +00 30 +# Medium Time +00 00 +# Extra Data Bytes +dd 04 00 50 43 ff +[/tspec1] + diff --git a/mwifiex_8997/mapp/mlanconfig/config/turbo_mode.conf b/mwifiex_8997/mapp/mlanconfig/config/turbo_mode.conf new file mode 100755 index 0000000..8a92f2f --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/turbo_mode.conf @@ -0,0 +1,9 @@ +#File : turbo_mode.conf +## WMM turbo mode config command +turbo_mode_set={ + CmdCode=0x0016 # do NOT change this line + Action:2=1 # 1 - SET + OID:2=0x27 # OID_WMM_TURBO_MODE + Size:2=128 + Value:128=5 # 1 -- Enable turbo_mode_1; 2 -- Enable turbo_mode_2; otherwise, disable turbo_mode +} diff --git a/mwifiex_8997/mapp/mlanconfig/config/tx_ctrl.conf b/mwifiex_8997/mapp/mlanconfig/config/tx_ctrl.conf new file mode 100755 index 0000000..013065b --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/tx_ctrl.conf @@ -0,0 +1,58 @@ +#protocol +Protocol=0x88dc + +# configure data rate in unit of 0.5Mbps +# 0 - auto rate determined by firmware +# Any other data rate except these data rates will +# be overwritten by default data rate. +# datarate index, unit in 0.5Mbps +# Index | 20MHz | 10MHz +# 12 | 6Mbps | 3Mbps +# 18 | 9Mbps | 4.5Mbps +# 24 | 12Mbps | 6Mbps +# 36 | 18Mbps | 9Mbps +# 48 | 24Mbps | 12Mbps +# 72 | 36Mbps | 18Mbps +# 96 | 48Mbps | 24Mbps +# 108 | 54Mbps | 27.5Mbps +Datarate=12 + +# configure Channel for the packet +# 0 - the channel set during the enable would be used +Channel=0 + +# configure Bandwith (only for 11p) +# 0: auto bandwith setting by firmware +# bit4: 1 use bit[3:0] bandwith setting +# bit[3:0]: +# 0 - 5MHz +# 1 - 10MHz +# 2 - 20MHz +# 3 - 40MHz +# 4 - 80MHz +Bandwidth=0x00 + +# configure power settings +# bit[7] host tx power control flag +# 0x0: use fw setting for tx power +# 0x1: value specified in bit[6] and bit[5:0] are valid +# bit[6] sign of the power specified in bit[5:0] +# 0x0: power specified in bit[5:0] is postive (+) +# 0x1: power specified in bit[5:0] is negative (-) +# bit[5:0] power to be used for transmission (in dBm) +Power=0x00 + +# configure Priority of the packet +# 1,2 - BK +# 0,3 - BE +# 4,5 - VI +# 6,7 - VO +Priority=0 + +# configure tx retry time +Retry_limit=0 + +# Destination MAC Address +Addr=00:50:43:22:0f:b0 + +Data=0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x8,0x9,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x8,0x9,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x8,0x9,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19 diff --git a/mwifiex_8997/mapp/mlanconfig/config/txpwrlimit_cfg.conf b/mwifiex_8997/mapp/mlanconfig/config/txpwrlimit_cfg.conf new file mode 100755 index 0000000..20c9220 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/txpwrlimit_cfg.conf @@ -0,0 +1,759 @@ +# File : txpwrlimit_cfg.conf +## Get CFG data for Tx power limitation +txpwrlimit_2g_cfg_get={ + CmdCode=0x00fb # do NOT change this line + Action:2=0 # 0 - GET + SubBand:2=0x00 # 0x00 2G subband (2.4G: channel 1-14) + # 0x10 5G subband0 (5G: channel 36,40,44,48, + # 52,56,60,64) + # 0x11 5G subband1 (5G: channel 100,104,108,112, + # 116,120,124,128, + # 132,136,140,144) + # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172) + # 0x13 5G subband3 (5G: channel 183,184,185,187,188, + # 189, 192,196; + # 5G: channel 7,8,11,12,16,34) +} + + +txpwrlimit_5g_cfg_get_sub0={ + CmdCode=0x00fb # do NOT change this line + Action:2=0 # 0 - GET + SubBand:2=0x10 # 0x00 2G subband (2.4G: channel 1-14) + # 0x10 5G subband0 (5G: channel 36,40,44,48, + # 52,56,60,64) + # 0x11 5G subband1 (5G: channel 100,104,108,112, + # 116,120,124,128, + # 132,136,140,144) + # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172) + # 0x13 5G subband3 (5G: channel 183,184,185,187,188, + # 189, 192,196; + # 5G: channel 7,8,11,12,16,34) +} + + +txpwrlimit_5g_cfg_get_sub1={ + CmdCode=0x00fb # do NOT change this line + Action:2=0 # 0 - GET + SubBand:2=0x11 # 0x00 2G subband (2.4G: channel 1-14) + # 0x10 5G subband0 (5G: channel 36,40,44,48, + # 52,56,60,64) + # 0x11 5G subband1 (5G: channel 100,104,108,112, + # 116,120,124,128, + # 132,136,140,144) + # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172) + # 0x13 5G subband3 (5G: channel 183,184,185,187,188, + # 189, 192,196; + # 5G: channel 7,8,11,12,16,34) +} + + +txpwrlimit_5g_cfg_get_sub2={ + CmdCode=0x00fb # do NOT change this line + Action:2=0 # 0 - GET + SubBand:2=0x12 # 0x00 2G subband (2.4G: channel 1-14) + # 0x10 5G subband0 (5G: channel 36,40,44,48, + # 52,56,60,64) + # 0x11 5G subband1 (5G: channel 100,104,108,112, + # 116,120,124,128, + # 132,136,140,144) + # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172) + # 0x13 5G subband3 (5G: channel 183,184,185,187,188, + # 189, 192,196; + # 5G: channel 7,8,11,12,16,34) +} + + +txpwrlimit_5g_cfg_get_sub3={ + CmdCode=0x00fb # do NOT change this line + Action:2=0 # 0 - GET + SubBand:2=0x13 # 0x00 2G subband (2.4G: channel 1-14) + # 0x10 5G subband0 (5G: channel 36,40,44,48, + # 52,56,60,64) + # 0x11 5G subband1 (5G: channel 100,104,108,112, + # 116,120,124,128, + # 132,136,140,144) + # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172) + # 0x13 5G subband3 (5G: channel 183,184,185,187,188, + # 189, 192,196; + # 5G: channel 7,8,11,12,16,34) +} + +#ifdef VHT2G_SUPPORT +## Set CFG data for Tx power limitation +## +## TLVStartFreq: Starting Frequency of the band for this channel +## 2407, 2414 or 2400 for 2.4 GHz +## TLVChanWidth: Channel Width +## 20 +## TLVChanNum : Channel Number +## TLVPwr[] : ModulationGroup +## 0: CCK (1,2,5.5,11 Mbps) +## 1: OFDM (6,9,12,18 Mbps) +## 2: OFDM (24,36 Mbps) +## 3: OFDM (48,54 Mbps) +## 4: HT20 (MCS0,1,2) +## 5: HT20 (MCS3,4) +## 6: HT20 (MCS5,6,7) +## 7: HT40 (MCS0,1,2) +## 8: HT40 (MCS3,4) +## 9: HT40 (MCS5,6,7) +## 10: HT2_20 (MCS8,9,10) +## 11: HT2_20 (MCS11,12) +## 12: HT2_20 (MCS13,14,15) +## 13: HT2_40 (MCS8,9,10) +## 14: HT2_40 (MCS11,12) +## 15: HT2_40 (MCS13,14,15) +## 16: VHT_QAM256 (MCS8) +## 17: VHT_40_QAM256 (MCS8,9) +## 18: VHT_80_PSK (MCS0,1,2) : Redundent Rates for 2G +## 19: VHT_80_QAM16 (MCS3,4) : Redundent Rates for 2G +## 20: VHT_80_QAM64 (MCS5,6,7) : Redundent Rates for 2G +## 21: VHT_80_QAM256 (MCS8,9) : Redundent Rates for 2G +## 22: VHT2_20_QAM256 (MCS8,9) +## 23: VHT2_40_QAM256 (MCS8,9) +## Power Limit in dBm +## +## + +## 2G subband0 Tx power limit CFG +txpwrlimit_2g_cfg_set={ + CmdCode=0x00fb # do NOT change this line + Action:2=1 # 1 - SET + SubBand:2=0 # do NOT use this member in set cmd + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=1 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=2 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=3 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=4 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=5 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=6 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=7 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=8 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=9 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=10 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=11 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=12 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=13 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=14 + TLVPwr:32='0,12,1,12,2,12,3,12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11,12,12,12,13,12,14,12,15,12,16,12,17,12,18,0,19,0,20,0,21,0,22,12,23,12' + } +} + +#else +## Set CFG data for Tx power limitation +## +## TLVStartFreq: Starting Frequency of the band for this channel +## 2407, 2414 or 2400 for 2.4 GHz +## 5000 +## 4000 +## TLVChanWidth: Channel Width +## 20 +## TLVChanNum : Channel Number +## TLVPwr[] : ModulationGroup +## 0: CCK (1,2,5.5,11 Mbps) +## 1: OFDM (6,9,12,18 Mbps) +## 2: OFDM (24,36 Mbps) +## 3: OFDM (48,54 Mbps) +## 4: HT20 (MCS0,1,2) +## 5: HT20 (MCS3,4) +## 6: HT20 (MCS5,6,7) +## 7: HT40 (MCS0,1,2) +## 8: HT40 (MCS3,4) +## 9: HT40 (MCS5,6,7) +## 10: HT2_20 (MCS8,9,10) +## 11: HT2_20 (MCS11,12) +## 12: HT2_20 (MCS13,14,15) +## 13: HT2_40 (MCS8,9,10) +## 14: HT2_40 (MCS11,12) +## 15: HT2_40 (MCS13,14,15) +## 16: VHT_QAM256 (MCS8) +## 17: VHT_40_QAM256 (MCS8,9) +## 18: VHT_80_PSK (MCS0,1,2) +## 19: VHT_80_QAM16 (MCS3,4) +## 20: VHT_80_QAM64 (MCS5,6,7) +## 21: VHT_80_QAM256 (MCS8,9) +## 22: VHT2_20_QAM256 (MCS8,9) +## 23: VHT2_40_QAM256 (MCS8,9) +## 24: VHT2_80_PSK (MCS0, 1, 2) +## 25: VHT2_80_QAM16 (MCS3,4) +## 26: VHT2_80_QAM64 (MCS5,6,7) +## 27: VHT2_80_QAM256 (MCS8,9) +## Power Limit in dBm +## +## Note: For KF, add VHT 20/40/80 1SS/2SS mod group. + +## 2G subband0 Tx power limit CFG +txpwrlimit_2g_cfg_set={ + CmdCode=0x00fb # do NOT change this line + Action:2=1 # 1 - SET + SubBand:2=0 # do NOT use this member in set cmd + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=1 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=2 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=3 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=4 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=5 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=6 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=7 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=8 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=9 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=10 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=11 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=12 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=13 + TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15' + } + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=2407 + TLVChanWidth:1=20 + TLVChanNum:1=14 + TLVPwr:32='0,12,1,12,2,12,3,12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11,12,12,12,13,12,14,12,15,12' + } +} +#endif + +## 5G subband1 Tx power limit CFG +txpwrlimit_5g_cfg_set_sub0={ + CmdCode=0x00fb # do NOT change this line + Action:2=1 # 1 - SET + SubBand:2=0 # do NOT use this member in set cmd + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=36 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=40 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=44 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=48 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=52 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=56 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=60 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=64 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } +} + +## 5G subband2 Tx power limit CFG +txpwrlimit_5g_cfg_set_sub1={ + CmdCode=0x00fb # do NOT change this line + Action:2=1 # 1 - SET + SubBand:2=0 # do NOT use this member in set cmd + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=100 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=104 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=108 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=112 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=116 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=120 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=124 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=128 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=132 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=136 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=140 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=144 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + +} + + +## 5G subband3 Tx power limit CFG +txpwrlimit_5g_cfg_set_sub2={ + CmdCode=0x00fb # do NOT change this line + Action:2=1 # 1 - SET + SubBand:2=0 # do NOT use this member in set cmd + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=149 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=153 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=157 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=161 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=165 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } +} + + +## 5G subband4 Tx power limit CFG +txpwrlimit_5g_cfg_set_sub3={ + CmdCode=0x00fb # do NOT change this line + Action:2=1 # 1 - SET + SubBand:2=0 # do NOT use this in set cmd + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=183 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=184 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=185 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=187 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=188 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=189 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=192 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=4000 + TLVChanWidth:1=20 + TLVChanNum:1=196 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=7 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=8 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=11 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=12 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=16 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } + + + ChanTRPC.TlvType:2=0x0189 + ChanTRPC.TlvLength:2={ + TLVStartFreq:2=5000 + TLVChanWidth:1=20 + TLVChanNum:1=34 + TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10' + } +} + diff --git a/mwifiex_8997/mapp/mlanconfig/config/txrate_cfg.conf b/mwifiex_8997/mapp/mlanconfig/config/txrate_cfg.conf new file mode 100755 index 0000000..4d2f789 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/config/txrate_cfg.conf @@ -0,0 +1,171 @@ +# File : txrate_cfg.conf + +## Tx Rate Configuration command +txrate_cfg_get={ + CmdCode=0x00d6 # do NOT change this line + Action:2=0 # 0 - GET + Index:2=0 # do NOT change this line + + TxRateScope.TlvType:2=0x0153 + TxRateScope.TlvLength:2={ + } +} + +txrate_cfg_set_bg={ + CmdCode=0x00d6 # do NOT change this line + + Action:2=1 # 1 - SET + Index:2=0 # do NOT change this line + + TxRateScope.TlvType:2=0x0153 + TxRateScope.TlvLength:2={ + ################# TXRATE SCOPE ###################### + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit Data rate + # 0 1 Mbps + # 1 2 Mbps + # 2 5.5 Mbps + # 3 11 Mbps + # 4 Reserved + HRDSSS.RateScope:2=0x0000 + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit Data rate + # 0 6 Mbps + # 1 9 Mbps + # 2 12 Mbps + # 3 18 Mbps + # 4 24 Mbps + # 5 36 Mbps + # 6 48 Mbps + # 7 54 Mbps + OFDM.RateScope:2=0x0080 + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit Data rate + # 0 MCS0 + # 1 MCS1 + # 2 MCS2 + # 3 MCS3 + # 4 MCS4 + # 5 MCS5 + # 6 MCS6 + # 7 MCS7 + # 32 MCS32 + HT.RateScopeDword0:4=0x00000000 + HT.RateScopeDword1:4=0x00000000 + HT.RateScopeDword2:4=0x00000000 + HT.RateScopeDword3:4=0x00000000 + } + + TxRateDrop.TlvType:2=0x0151 + TxRateDrop.TlvLength:2={ + RateDrop.Mode:4=0x00000001 + } +} + +txrate_cfg_set_bgn={ + CmdCode=0x00d6 # do NOT change this line + + Action:2=1 # 1 - SET + Index:2=0 # do NOT change this line + + TxRateScope.TlvType:2=0x0153 + TxRateScope.TlvLength:2={ + ################# TXRATE SCOPE ###################### + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit Data rate + # 0 1 Mbps + # 1 2 Mbps + # 2 5.5 Mbps + # 3 11 Mbps + # 4 Reserved + HRDSSS.RateScope:2=0x0000 + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit Data rate + # 0 6 Mbps + # 1 9 Mbps + # 2 12 Mbps + # 3 18 Mbps + # 4 24 Mbps + # 5 36 Mbps + # 6 48 Mbps + # 7 54 Mbps + OFDM.RateScope:2=0x0000 + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit Data rate + # 0 MCS0 + # 1 MCS1 + # 2 MCS2 + # 3 MCS3 + # 4 MCS4 + # 5 MCS5 + # 6 MCS6 + # 7 MCS7 + # 32 MCS32 + HT.RateScopeDword0:4=0x00000080 + HT.RateScopeDword1:4=0x00000000 + HT.RateScopeDword2:4=0x00000000 + HT.RateScopeDword3:4=0x00000000 + } + + TxRateDrop.TlvType:2=0x0151 + TxRateDrop.TlvLength:2={ + RateDrop.Mode:4=0x00000001 + } +} + +########supported BasicRate setting########### +basic_rate_get={ + CmdCode=0x00d6 # do NOT change this line + Action:2=0 # 0 - GET + Index:2=0 # do NOT change this line + + TlvType:2=0x21a + TlvLength:2={ + } +} + +basic_rate_set={ + CmdCode=0x00d6 # do NOT change this line + + Action:2=1 # 1 - SET + Index:2=0 # do NOT change this line + + TlvType:2=0x21a + TlvLength:2={ + BasicRateSupport:2=0x000f #defalt value + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit BasicRateSupport + # 0 DBPSK1Mbps + # 1 DQPSK2Mbps + # 2 CCK5_5Mbps + # 3 CCK11Mbps + # 4 Not used. + # 5 OFDM6Mbps + # 6 OFDM9Mbps + # 7 OFDM12Mbps + # 8 OFDM18Mbps + # 9 OFDM24Mbps + # 10 OFDM36Mbps + # 11 OFDM48Mbps + # 12 OFDM54Mbps + # 13-15 Reserved + #note: value0x0 represents no setting value + #For example: + #BasicRateSupport:2=0x3 set supported BasicRate to DBPSK1Mbps, DQPSK2Mbps + #BasicRateSupport:2=0x180 set supported BasicRate to OFDM18Mbps, OFDM12Mbps + } +} diff --git a/mwifiex_8997/mapp/mlanconfig/mlanconfig.c b/mwifiex_8997/mapp/mlanconfig/mlanconfig.c new file mode 100755 index 0000000..15421e4 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/mlanconfig.c @@ -0,0 +1,4827 @@ +/** @file mlanconfig.c + * + * @brief Program to configure addition parameters into the mlandriver + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 11/26/2008: initial version + 03/10/2009: add setuserscan, getscantable etc. commands + 08/11/2009: add addts, regclass, setra, scanagent etc. commands +************************************************************************/ + +#include "mlanconfig.h" +#include "mlanhostcmd.h" +#include "mlanmisc.h" + +/** mlanconfig version number */ +#define MLANCONFIG_VER "M2.0" + +/** Initial number of total private ioctl calls */ +#define IW_INIT_PRIV_NUM 128 +/** Maximum number of total private ioctl calls supported */ +#define IW_MAX_PRIV_NUM 1024 + +/******************************************************** + Local Variables +********************************************************/ + +/** Private ioctl commands */ +enum COMMANDS { + CMD_HOSTCMD, + CMD_MEFCFG, + CMD_ARPFILTER, + CMD_CFG_DATA, + CMD_GET_SCAN_RSP, + CMD_SET_USER_SCAN, + CMD_ADD_TS, + CMD_DEL_TS, + CMD_QCONFIG, + CMD_QSTATS, + CMD_TS_STATUS, + CMD_WMM_QSTATUS, + CMD_REGRW, + CMD_MEMRW, + CMD_STA_CUSTOM_IE, + CMD_STA_MGMT_FRAME_TX, + CMD_TDLS_CONF, + CMD_TDLS_INFO, + CMD_TDLS_DISCOVERY, + CMD_TDLS_SETUP, + CMD_TDLS_TEARDOWN, + CMD_TDLS_POWERMODE, + CMD_TDLS_LINK_STATUS, + CMD_TDLS_DEBUG, + CMD_TDLS_CHANNEL_SWITCH, + CMD_TDLS_STOP_CHAN_SWITCH, + CMD_TDLS_CS_PARAMS, + CMD_TDLS_CS_DISABLE, +}; + +static t_s8 *commands[] = { + "hostcmd", + "mefcfg", + "arpfilter", + "cfgdata", + "getscantable", + "setuserscan", + "addts", + "delts", + "qconfig", + "qstats", + "ts_status", + "qstatus", + "regrdwr", + "memrdwr", + "customie", + "mgmtframetx", + "tdls_config", + "tdls_setinfo", + "tdls_discovery", + "tdls_setup", + "tdls_teardown", + "tdls_powermode", + "tdls_link_status", + "tdls_debug", + "tdls_channel_switch", + "tdls_stop_channel_switch", + "tdls_cs_params", + "tdls_disable_cs", +}; + +static t_s8 *usage[] = { + "Usage: ", + " mlanconfig -v (version)", + " mlanconfig [...]", + " where", + " mlanX : wireless network interface", + " cmd : hostcmd", + " : mefcfg", + " : customie", + " : mgmtframetx", + " : arpfilter", + " : tdls_config", + " : tdls_setinfo", + " : tdls_discovery", + " : tdls_setup", + " : tdls_teardown", + " : tdls_powermode", + " : tdls_link_status", + " : tdls_debug", + " : tdls_channel_switch", + " : tdls_stop_channel_switch", + " : tdls_cs_params", + " : tdls_disable_cs", + " : cfgdata", + " : getscantable, setuserscan", + " : addts, delts, qconfig, qstats, ts_status, qstatus", + " : regrdwr, memrdwr", + " : additional parameter for hostcmd", + " : ", + " : additional parameters for mefcfg are:", + " : ", + " : additional parameters for customie are:", + " : ", + " : additional parameters for mgmtframetx are:", + " : ", + " : additional parameter for arpfilter", + " : ", + " : additional parameter for tdls_setinfo", + " : ", + " : additional parameter for tdls_discovery", + " : ", + " : additional parameter for tdls_setup", + " : ", + " : additional parameter for tdls_teardown", + " : ", + " : additional parameter for tdls_powermode", + " : ", + " : additional parameter for tdls_debug ", + " : additional parameter for tdls_channel_switch", + " : ", + " : additional parameter for tdls_stop_channel_switch", + " : ", + " : additional parameter for tdls_cs_params", + " : ", + " : additional parameter for cfgdata", + " : ", + " : additional parameter for addts", + " : ", + " : additional parameter for delts", + " : ", + " : additional parameter for qconfig", + " : <[set msdu [Queue Id: 0-3]]", + " : [get [Queue Id: 0-3]] [def [Queue Id: 0-3]]>", + " : additional parameter for qstats", + " : <[get [User Priority: 0-7]]>", + " : additional parameter for regrdwr", + " : [value]", + " : additional parameter for memrdwr", + " :
[value]", +}; + +t_s32 sockfd; /**< socket */ +t_s8 dev_name[IFNAMSIZ + 1]; /**< device name */ +static struct iw_priv_args *priv_args = NULL; /**< private args */ +static int we_version_compiled = 0; + /**< version compiled */ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ +/** + * @brief isdigit for String. + * + * @param x Char string + * @return MLAN_STATUS_FAILURE for non-digit. + * MLAN_STATUS_SUCCESS for digit + */ +static int +ISDIGIT(t_s8 *x) +{ + unsigned int i; + for (i = 0; i < strlen(x); i++) + if (isdigit(x[i]) == 0) + return MLAN_STATUS_FAILURE; + return MLAN_STATUS_SUCCESS; +} + +/** + * Check of decimal or hex string + * @param num string + */ +#define IS_HEX_OR_DIGIT(num) \ + (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num))) + +/** + * @brief Get private info. + * + * @param ifname A pointer to net name + * @return MLAN_STATUS_SUCCESS--success, otherwise --fail + */ +static int +get_private_info(const t_s8 *ifname) +{ + /* This function sends the SIOCGIWPRIV command, which is + * handled by the kernel and gets the total number of + * private ioctl's available in the host driver. + */ + struct iwreq iwr; + int s, ret = MLAN_STATUS_SUCCESS; + struct iw_priv_args *ppriv = NULL; + struct iw_priv_args *new_priv; + int result = 0; + size_t size = IW_INIT_PRIV_NUM; + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { + perror("socket[PF_INET,SOCK_DGRAM]"); + return MLAN_STATUS_FAILURE; + } + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, ifname, IFNAMSIZ - 1); + + do { + /* (Re)allocate the buffer */ + new_priv = realloc(ppriv, size * sizeof(ppriv[0])); + if (new_priv == NULL) { + printf("Error: Buffer allocation failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + ppriv = new_priv; + + iwr.u.data.pointer = (caddr_t) ppriv; + iwr.u.data.length = size; + iwr.u.data.flags = 0; + + if (ioctl(s, SIOCGIWPRIV, &iwr) < 0) { + result = errno; + ret = MLAN_STATUS_FAILURE; + if (result == E2BIG) { + /* We need a bigger buffer. Check if kernel gave us any hints. */ + if (iwr.u.data.length > size) { + /* Kernel provided required size */ + size = iwr.u.data.length; + } else { + /* No hint from kernel, double the buffer size */ + size *= 2; + } + } else { + /* ioctl error */ + perror("ioctl[SIOCGIWPRIV]"); + break; + } + } else { + /* Success. Return the number of private ioctls */ + priv_args = ppriv; + ret = iwr.u.data.length; + break; + } + } while (size <= IW_MAX_PRIV_NUM); + + if ((ret == MLAN_STATUS_FAILURE) && (ppriv)) + free(ppriv); + + close(s); + + return ret; +} + +/** + * @brief Get Sub command ioctl number + * + * @param i command index + * @param priv_cnt Total number of private ioctls availabe in driver + * @param ioctl_val A pointer to return ioctl number + * @param subioctl_val A pointer to return sub-ioctl number + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +static int +marvell_get_subioctl_no(t_s32 i, + t_s32 priv_cnt, int *ioctl_val, int *subioctl_val) +{ + t_s32 j; + + if (priv_args[i].cmd >= SIOCDEVPRIVATE) { + *ioctl_val = priv_args[i].cmd; + *subioctl_val = 0; + return MLAN_STATUS_SUCCESS; + } + + j = -1; + + /* Find the matching *real* ioctl */ + + while ((++j < priv_cnt) + && ((priv_args[j].name[0] != '\0') || + (priv_args[j].set_args != priv_args[i].set_args) || + (priv_args[j].get_args != priv_args[i].get_args))) { + } + + /* If not found... */ + if (j == priv_cnt) { + printf("%s: Invalid private ioctl definition for: 0x%x\n", + dev_name, priv_args[i].cmd); + return MLAN_STATUS_FAILURE; + } + + /* Save ioctl numbers */ + *ioctl_val = priv_args[j].cmd; + *subioctl_val = priv_args[i].cmd; + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Get ioctl number + * + * @param ifname A pointer to net name + * @param priv_cmd A pointer to priv command buffer + * @param ioctl_val A pointer to return ioctl number + * @param subioctl_val A pointer to return sub-ioctl number + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +static int +marvell_get_ioctl_no(const t_s8 *ifname, + const t_s8 *priv_cmd, int *ioctl_val, int *subioctl_val) +{ + t_s32 i; + t_s32 priv_cnt; + int ret = MLAN_STATUS_FAILURE; + + priv_cnt = get_private_info(ifname); + + /* Are there any private ioctls? */ + if (priv_cnt <= 0 || priv_cnt > IW_MAX_PRIV_NUM) { + /* Could skip this message ? */ + printf("%-8.8s no private ioctls.\n", ifname); + } else { + for (i = 0; i < priv_cnt; i++) { + if (priv_args[i].name[0] && + !strcmp(priv_args[i].name, priv_cmd)) { + ret = marvell_get_subioctl_no(i, priv_cnt, + ioctl_val, + subioctl_val); + break; + } + } + } + + if (priv_args) { + free(priv_args); + priv_args = NULL; + } + + return ret; +} + +/** + * @brief Retrieve the ioctl and sub-ioctl numbers for the given ioctl string + * + * @param ioctl_name Private IOCTL string name + * @param ioctl_val A pointer to return ioctl number + * @param subioctl_val A pointer to return sub-ioctl number + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +int +get_priv_ioctl(char *ioctl_name, int *ioctl_val, int *subioctl_val) +{ + int retval; + + retval = marvell_get_ioctl_no(dev_name, + ioctl_name, ioctl_val, subioctl_val); + + return retval; +} + +/** + * @brief Process host_cmd + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_host_cmd(int argc, char *argv[]) +{ + t_s8 cmdname[256]; + t_u8 *buf; + HostCmd_DS_GEN *hostcmd; + struct iwreq iwr; + int ret = MLAN_STATUS_SUCCESS; + int ioctl_val, subioctl_val; + FILE *fp = NULL; + + if (get_priv_ioctl("hostcmd", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc < 5) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./mlanconfig mlanX hostcmd \n"); + exit(1); + } + + if ((fp = fopen(argv[3], "r")) == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[3]); + exit(1); + } + + buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (buf == NULL) { + printf("Error: allocate memory for hostcmd failed\n"); + fclose(fp); + return -ENOMEM; + } + snprintf(cmdname, sizeof(cmdname), "%s", argv[4]); + ret = prepare_host_cmd_buffer(fp, cmdname, buf); + fclose(fp); + + if (ret == MLAN_STATUS_FAILURE) + goto _exit_; + + hostcmd = (HostCmd_DS_GEN *)buf; + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = (t_u8 *)hostcmd; + iwr.u.data.length = le16_to_cpu(hostcmd->size); + + iwr.u.data.flags = 0; + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, + "mlanconfig: MLANHOSTCMD is not supported by %s\n", + dev_name); + ret = MLAN_STATUS_FAILURE; + goto _exit_; + } + ret = process_host_cmd_resp(buf); + +_exit_: + if (buf) + free(buf); + + return ret; +} + +/** + * @brief get range + * + * @return MLAN_STATUS_SUCCESS--success, otherwise --fail + */ +static int +get_range(t_void) +{ + struct iw_range *range; + struct iwreq iwr; + size_t buf_len; + + buf_len = sizeof(struct iw_range) + 500; + range = malloc(buf_len); + if (range == NULL) { + printf("Error: allocate memory for iw_range failed\n"); + return -ENOMEM; + } + memset(range, 0, buf_len); + memset(&iwr, 0, sizeof(struct iwreq)); + iwr.u.data.pointer = (caddr_t) range; + iwr.u.data.length = buf_len; + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + + if ((ioctl(sockfd, SIOCGIWRANGE, &iwr)) < 0) { + printf("Get Range Results Failed\n"); + free(range); + return MLAN_STATUS_FAILURE; + } + we_version_compiled = range->we_version_compiled; + printf("Driver build with Wireless Extension %d\n", + range->we_version_compiled); + free(range); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Display usage + * + * @return NA + */ +static t_void +display_usage(t_void) +{ + t_u32 i; + for (i = 0; i < NELEMENTS(usage); i++) + fprintf(stderr, "%s\n", usage[i]); +} + +/** + * @brief Find command + * + * @param maxcmds max command number + * @param cmds A pointer to commands buffer + * @param cmd A pointer to command buffer + * @return index of command or MLAN_STATUS_FAILURE + */ +static int +findcommand(t_s32 maxcmds, t_s8 *cmds[], t_s8 *cmd) +{ + t_s32 i; + + for (i = 0; i < maxcmds; i++) { + if (!strcasecmp(cmds[i], cmd)) { + return i; + } + } + + return MLAN_STATUS_FAILURE; +} + +/** + * @brief Process arpfilter + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_arpfilter(int argc, char *argv[]) +{ + t_u8 *buf; + struct iwreq iwr; + t_u16 length = 0; + int ret = MLAN_STATUS_SUCCESS; + FILE *fp = NULL; + int ioctl_val, subioctl_val; + + if (get_priv_ioctl("arpfilter", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc < 4) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./mlanconfig mlanX arpfilter \n"); + exit(1); + } + + if ((fp = fopen(argv[3], "r")) == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[3]); + return MLAN_STATUS_FAILURE; + } + buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (buf == NULL) { + printf("Error: allocate memory for arpfilter failed\n"); + fclose(fp); + return -ENOMEM; + } + ret = prepare_arp_filter_buffer(fp, buf, &length); + fclose(fp); + + if (ret == MLAN_STATUS_FAILURE) + goto _exit_; + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = buf; + iwr.u.data.length = length; + iwr.u.data.flags = 0; + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, + "mlanconfig: arpfilter command is not supported by %s\n", + dev_name); + ret = MLAN_STATUS_FAILURE; + goto _exit_; + } + +_exit_: + if (buf) + free(buf); + + return ret; +} + +/** + * @brief Process cfgdata + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_cfg_data(int argc, char *argv[]) +{ + t_u8 *buf; + HostCmd_DS_GEN *hostcmd; + struct iwreq iwr; + int ret = MLAN_STATUS_SUCCESS; + int ioctl_val, subioctl_val; + FILE *fp = NULL; + + if (get_priv_ioctl("hostcmd", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc < 4 || argc > 5) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./mlanconfig mlanX cfgdata \n"); + exit(1); + } + + if (argc == 5) { + if ((fp = fopen(argv[4], "r")) == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[3]); + exit(1); + } + } + buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (buf == NULL) { + printf("Error: allocate memory for hostcmd failed\n"); + if (argc == 5) + fclose(fp); + return -ENOMEM; + } + ret = prepare_cfg_data_buffer(argc, argv, fp, buf); + if (argc == 5) + fclose(fp); + + if (ret == MLAN_STATUS_FAILURE) + goto _exit_; + + hostcmd = (HostCmd_DS_GEN *)buf; + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = (t_u8 *)hostcmd; + iwr.u.data.length = le16_to_cpu(hostcmd->size); + + iwr.u.data.flags = 0; + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, + "mlanconfig: MLANHOSTCMD is not supported by %s\n", + dev_name); + ret = MLAN_STATUS_FAILURE; + goto _exit_; + } + ret = process_host_cmd_resp(buf); + +_exit_: + if (buf) + free(buf); + + return ret; +} + +/** + * @brief read current command + * @param ptr A pointer to data + * @param curCmd A pointer to the buf which will hold current command + * @return NULL or the pointer to the left command buf + */ +static t_s8 * +readCurCmd(t_s8 *ptr, t_s8 *curCmd) +{ + t_s32 i = 0; +#define MAX_CMD_SIZE 64 /**< Max command size */ + + while (*ptr != ']' && i < (MAX_CMD_SIZE - 1)) + curCmd[i++] = *(++ptr); + + if (*ptr != ']') + return NULL; + + curCmd[i - 1] = '\0'; + + return ++ptr; +} + +/** + * @brief parse command and hex data + * @param fp A pointer to FILE stream + * @param dst A pointer to the dest buf + * @param cmd A pointer to command buf for search + * @return Length of hex data or MLAN_STATUS_FAILURE + */ +static int +fparse_for_cmd_and_hex(FILE * fp, t_u8 *dst, t_u8 *cmd) +{ + t_s8 *ptr; + t_u8 *dptr; + t_s8 buf[256], curCmd[64]; + t_s32 isCurCmd = 0; + + dptr = dst; + while (fgets(buf, sizeof(buf), fp)) { + ptr = buf; + + while (*ptr) { + /* skip leading spaces */ + while (*ptr && isspace(*ptr)) + ptr++; + + /* skip blank lines and lines beginning with '#' */ + if (*ptr == '\0' || *ptr == '#') + break; + + if (*ptr == '[' && *(ptr + 1) != '/') { + if (!(ptr = readCurCmd(ptr, curCmd))) + return MLAN_STATUS_FAILURE; + + if (strcasecmp(curCmd, (char *)cmd)) /* Not equal */ + isCurCmd = 0; + else + isCurCmd = 1; + } + + /* Ignore the rest if it is not correct cmd */ + if (!isCurCmd) + break; + + if (*ptr == '[' && *(ptr + 1) == '/') + return (dptr - dst); + + if (isxdigit(*ptr)) { + ptr = convert2hex(ptr, dptr++); + } else { + /* Invalid character on data line */ + ptr++; + } + } + } + + return MLAN_STATUS_FAILURE; +} + +/** + * @brief Send an ADDTS command to the associated AP + * + * Process a given conf file for a specific TSPEC data block. Send the + * TSPEC along with any other IEs to the driver/firmware for transmission + * in an ADDTS request to the associated AP. + * + * Return the execution status of the command as well as the ADDTS response + * from the AP if any. + * + * mlanconfig mlanX addts + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_addts(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_addts_req_t addtsReq; + + FILE *fp = NULL; + char filename[48]; + char config_id[20]; + + memset(&addtsReq, 0x00, sizeof(addtsReq)); + memset(filename, 0x00, sizeof(filename)); + + if (get_priv_ioctl("addts", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc != 6) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3]))); + if ((fp = fopen(filename, "r")) == NULL) { + perror("fopen"); + fprintf(stderr, "Cannot open file %s\n", argv[3]); + return -EFAULT;; + } + + snprintf(config_id, sizeof(config_id), "tspec%d", atoi(argv[4])); + + addtsReq.ieDataLen = fparse_for_cmd_and_hex(fp, + addtsReq.ieData, + (t_u8 *)config_id); + + if (addtsReq.ieDataLen > 0) { + printf("Found %d bytes in the %s section of conf file %s\n", + (int)addtsReq.ieDataLen, config_id, filename); + } else { + fprintf(stderr, "section %s not found in %s\n", + config_id, filename); + if (fp) + fclose(fp); + return -EFAULT; + } + + addtsReq.timeout_ms = atoi(argv[5]); + + printf("Cmd Input:\n"); + hexdump(config_id, addtsReq.ieData, addtsReq.ieDataLen, ' '); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.flags = subioctl_val; + iwr.u.data.pointer = (caddr_t) & addtsReq; + iwr.u.data.length = (sizeof(addtsReq) + - sizeof(addtsReq.ieData) + + addtsReq.ieDataLen); + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("mlanconfig: addts ioctl"); + if (fp) + fclose(fp); + return -EFAULT; + } + + printf("Cmd Output:\n"); + printf("ADDTS Command Result = %d\n", addtsReq.commandResult); + printf("ADDTS IEEE Status = %d\n", addtsReq.ieeeStatusCode); + hexdump(config_id, addtsReq.ieData, addtsReq.ieDataLen, ' '); + + if (fp) + fclose(fp); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Send a DELTS command to the associated AP + * + * Process a given conf file for a specific TSPEC data block. Send the + * TSPEC along with any other IEs to the driver/firmware for transmission + * in a DELTS request to the associated AP. + * + * Return the execution status of the command. There is no response to a + * DELTS from the AP. + * + * mlanconfig mlanX delts + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_delts(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_delts_req_t deltsReq; + + FILE *fp = NULL; + char filename[48]; + char config_id[20]; + + memset(&deltsReq, 0x00, sizeof(deltsReq)); + memset(filename, 0x00, sizeof(filename)); + + if (get_priv_ioctl("delts", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc != 5) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3]))); + if ((fp = fopen(filename, "r")) == NULL) { + perror("fopen"); + fprintf(stderr, "Cannot open file %s\n", argv[3]); + return -EFAULT; + } + + snprintf(config_id, sizeof(config_id), "tspec%d", atoi(argv[4])); + + deltsReq.ieDataLen = fparse_for_cmd_and_hex(fp, + deltsReq.ieData, + (t_u8 *)config_id); + + if (deltsReq.ieDataLen > 0) { + printf("Found %d bytes in the %s section of conf file %s\n", + (int)deltsReq.ieDataLen, config_id, filename); + } else { + fprintf(stderr, "section %s not found in %s\n", + config_id, filename); + if (fp) + fclose(fp); + return -EFAULT; + } + + printf("Cmd Input:\n"); + hexdump(config_id, deltsReq.ieData, deltsReq.ieDataLen, ' '); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.flags = subioctl_val; + iwr.u.data.pointer = (caddr_t) & deltsReq; + iwr.u.data.length = (sizeof(deltsReq) + - sizeof(deltsReq.ieData) + + deltsReq.ieDataLen); + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("mlanconfig: delts ioctl"); + if (fp) + fclose(fp); + return -EFAULT; + } + + printf("Cmd Output:\n"); + printf("DELTS Command Result = %d\n", deltsReq.commandResult); + if (fp) + fclose(fp); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Send a WMM AC Queue configuration command to get/set/default params + * + * Configure or get the parameters of a WMM AC queue. The command takes + * an optional Queue Id as a last parameter. Without the queue id, all + * queues will be acted upon. + * + * mlanconfig mlanX qconfig set msdu [Queue Id: 0-3] + * mlanconfig mlanX qconfig get [Queue Id: 0-3] + * mlanconfig mlanX qconfig def [Queue Id: 0-3] + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_qconfig(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_queue_config_t queue_config_cmd; + mlan_wmm_ac_e ac_idx; + mlan_wmm_ac_e ac_idx_start; + mlan_wmm_ac_e ac_idx_stop; + + const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" }; + + if (argc < 4) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + if (get_priv_ioctl("qconfig", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + memset(&queue_config_cmd, 0x00, sizeof(queue_config_cmd)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = (caddr_t) & queue_config_cmd; + iwr.u.data.length = sizeof(queue_config_cmd); + iwr.u.data.flags = subioctl_val; + + if (strcmp(argv[3], "get") == 0) { + /* 3 4 5 */ + /* qconfig get [qid] */ + if (argc == 4) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 5) { + if (atoi(argv[4]) < WMM_AC_BK || + atoi(argv[4]) > WMM_AC_VO) { + fprintf(stderr, "ERROR: Invalid Queue ID!\n"); + return -EINVAL; + } + ac_idx_start = atoi(argv[4]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_GET; + + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_config_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qconfig ioctl"); + } else { + printf("qconfig %s(%d): MSDU Lifetime GET = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry); + } + } + } else if (strcmp(argv[3], "set") == 0) { + if ((argc >= 5) && strcmp(argv[4], "msdu") == 0) { + /* 3 4 5 6 7 */ + /* qconfig set msdu [qid] */ + if (argc == 6) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 7) { + if (atoi(argv[6]) < WMM_AC_BK || + atoi(argv[6]) > WMM_AC_VO) { + fprintf(stderr, + "ERROR: Invalid Queue ID!\n"); + return -EINVAL; + } + ac_idx_start = atoi(argv[6]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, + "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_SET; + queue_config_cmd.msduLifetimeExpiry = atoi(argv[5]); + + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; + ac_idx++) { + queue_config_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qconfig ioctl"); + } else { + printf("qconfig %s(%d): MSDU Lifetime SET = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry); + } + } + } else { + /* Only MSDU Lifetime provisioning accepted for now */ + fprintf(stderr, "Invalid set parameter: s/b [msdu]\n"); + return -EINVAL; + } + } else if (strncmp(argv[3], "def", strlen("def")) == 0) { + /* 3 4 5 */ + /* qconfig def [qid] */ + if (argc == 4) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 5) { + if (atoi(argv[4]) < WMM_AC_BK || + atoi(argv[4]) > WMM_AC_VO) { + fprintf(stderr, "ERROR: Invalid Queue ID!\n"); + return -EINVAL; + } + ac_idx_start = atoi(argv[4]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_DEFAULT; + + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_config_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qconfig ioctl"); + } else { + printf("qconfig %s(%d): MSDU Lifetime DEFAULT = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry); + } + } + } else { + fprintf(stderr, + "Invalid qconfig command; s/b [set, get, default]\n"); + return -EINVAL; + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Turn on/off or retrieve and clear the queue statistics for a UP + * + * Turn the statistics collection on/off for a given UP or retrieve the + * current accumulated stats and clear them from the firmware. The command + * takes an optional Queue Id as a last parameter. Without the queue id, + * all queues will be acted upon. + * + * mlanconfig mlanX qstats get [User Priority: 0-7] + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_qstats(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_queue_stats_t queue_stats_cmd; + t_u8 up_idx; + t_u8 up_idx_start; + t_u8 up_idx_stop; + t_u16 usedTime[MAX_USER_PRIORITIES]; + t_u16 policedTime[MAX_USER_PRIORITIES]; + + const char *ac_str_tbl[] = { "BE", "BK", "BK", "BE", + "VI", "VI", "VO", "VO" + }; + + if (argc < 3) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + if (get_priv_ioctl("qstats", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + printf("\n"); + + memset(usedTime, 0x00, sizeof(usedTime)); + memset(policedTime, 0x00, sizeof(policedTime)); + memset(&queue_stats_cmd, 0x00, sizeof(queue_stats_cmd)); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = (caddr_t) & queue_stats_cmd; + iwr.u.data.length = sizeof(queue_stats_cmd); + iwr.u.data.flags = subioctl_val; + + if ((argc > 3) && strcmp(argv[3], "on") == 0) { + if (argc == 4) { + up_idx_start = 0; + up_idx_stop = 7; + } else if (argc == 5) { + if (atoi(argv[4]) < 0 || atoi(argv[4]) > 7) { + fprintf(stderr, + "ERROR: Invalid User Priority!\n"); + return -EINVAL; + } + up_idx_start = atoi(argv[4]); + up_idx_stop = up_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_stats_cmd.action = WMM_STATS_ACTION_START; + for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) { + queue_stats_cmd.userPriority = up_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qstats ioctl"); + } else { + printf("qstats UP%d, %s turned on\n", + up_idx, ac_str_tbl[up_idx]); + } + } + } else if ((argc > 3) && strcmp(argv[3], "off") == 0) { + if (argc == 4) { + up_idx_start = 0; + up_idx_stop = 7; + } else if (argc == 5) { + if (atoi(argv[4]) < 0 || atoi(argv[4]) > 7) { + fprintf(stderr, + "ERROR: Invalid User Priority!\n"); + return -EINVAL; + } + up_idx_start = atoi(argv[4]); + up_idx_stop = up_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_stats_cmd.action = WMM_STATS_ACTION_STOP; + for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) { + queue_stats_cmd.userPriority = up_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qstats ioctl"); + } else { + printf("qstats UP%d, %s turned off\n", + up_idx, ac_str_tbl[up_idx]); + } + } + } else if ((argc >= 3) && + ((argc == 3) ? 1 : (strcmp(argv[3], "get") == 0))) { + /* If the user types: "mlanconfig mlanX qstats" without get argument. + * The mlanconfig application invokes "get" option for all UPs + */ + if ((argc == 4) || (argc == 3)) { + up_idx_start = 0; + up_idx_stop = 7; + } else if (argc == 5) { + if (atoi(argv[4]) < 0 || atoi(argv[4]) > 7) { + fprintf(stderr, + "ERROR: Invalid User Priority!\n"); + return -EINVAL; + } + up_idx_start = atoi(argv[4]); + up_idx_stop = up_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + printf("%s %6s %5s %8s %8s %6s %6s %6s %6s %6s %6s\n", + "AC-UP", "Count", "Loss", "TxDly", "QDly", + "<=5", "<=10", "<=20", "<=30", "<=50", ">50"); + printf("----------------------------------" + "---------------------------------------------\n"); + queue_stats_cmd.action = WMM_STATS_ACTION_GET_CLR; + + for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) { + queue_stats_cmd.userPriority = up_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qstats ioctl"); + } else { + printf(" %s-%d %6u %5u %8u %8u %6u %6u %6u %6u %6u %6u\n", ac_str_tbl[up_idx], up_idx, queue_stats_cmd.pktCount, queue_stats_cmd.pktLoss, (unsigned int)queue_stats_cmd.avgTxDelay, (unsigned int)queue_stats_cmd.avgQueueDelay, queue_stats_cmd.delayHistogram[0], queue_stats_cmd.delayHistogram[1], queue_stats_cmd.delayHistogram[2], queue_stats_cmd.delayHistogram[3], (queue_stats_cmd.delayHistogram[4] + queue_stats_cmd.delayHistogram[5]), queue_stats_cmd.delayHistogram[6]); + + usedTime[up_idx] = queue_stats_cmd.usedTime; + policedTime[up_idx] = + queue_stats_cmd.policedTime; + } + } + + printf("----------------------------------" + "---------------------------------------------\n"); + printf("\nAC-UP UsedTime PolicedTime\n"); + printf("------------------------------------\n"); + + for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) { + printf(" %s-%d %6u %6u\n", + ac_str_tbl[up_idx], + up_idx, + (unsigned int)usedTime[up_idx], + (unsigned int)policedTime[up_idx]); + } + } else { + fprintf(stderr, "Invalid qstats command;\n"); + return -EINVAL; + } + printf("\n"); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Get the current status of the WMM Queues + * + * Command: mlanconfig mlanX qstatus + * + * Retrieve the following information for each AC if wmm is enabled: + * - WMM IE ACM Required + * - Firmware Flow Required + * - Firmware Flow Established + * - Firmware Queue Enabled + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_wmm_qstatus(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_queue_status_t qstatus; + mlan_wmm_ac_e acVal; + + if (get_priv_ioctl("qstatus", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + memset(&qstatus, 0x00, sizeof(qstatus)); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.flags = subioctl_val; + iwr.u.data.pointer = (caddr_t) & qstatus; + iwr.u.data.length = (sizeof(qstatus)); + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("mlanconfig: qstatus ioctl"); + return -EFAULT; + } + + for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) { + switch (acVal) { + case WMM_AC_BK: + printf("BK: "); + break; + case WMM_AC_BE: + printf("BE: "); + break; + case WMM_AC_VI: + printf("VI: "); + break; + case WMM_AC_VO: + printf("VO: "); + break; + default: + printf("??: "); + } + + printf("ACM[%c], FlowReq[%c], FlowCreated[%c], Enabled[%c]," + " DE[%c], TE[%c]\n", + (qstatus.acStatus[acVal].wmmAcm ? 'X' : ' '), + (qstatus.acStatus[acVal].flowRequired ? 'X' : ' '), + (qstatus.acStatus[acVal].flowCreated ? 'X' : ' '), + (qstatus.acStatus[acVal].disabled ? ' ' : 'X'), + (qstatus.acStatus[acVal].deliveryEnabled ? 'X' : ' '), + (qstatus.acStatus[acVal].triggerEnabled ? 'X' : ' ')); + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Get the current status of the WMM Traffic Streams + * + * Command: mlanconfig mlanX ts_status + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_wmm_ts_status(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_ts_status_t ts_status; + int tid; + + const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" }; + + if (get_priv_ioctl("ts_status", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + printf("\nTID Valid AC UP PSB FlowDir MediumTime\n"); + printf("---------------------------------------------------\n"); + + for (tid = 0; tid <= 7; tid++) { + memset(&ts_status, 0x00, sizeof(ts_status)); + ts_status.tid = tid; + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.flags = subioctl_val; + iwr.u.data.pointer = (caddr_t) & ts_status; + iwr.u.data.length = (sizeof(ts_status)); + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("mlanconfig: ts_status ioctl"); + return -EFAULT; + } + + printf(" %02d %3s %2s %u %c ", + ts_status.tid, + (ts_status.valid ? "Yes" : "No"), + (ts_status. + valid ? ac_str_tbl[ts_status.accessCategory] : "--"), + ts_status.userPriority, (ts_status.psb ? 'U' : 'L')); + + if ((ts_status.flowDir & 0x03) == 0) { + printf("%s", " ---- "); + } else { + printf("%2s%4s", + (ts_status.flowDir & 0x01 ? "Up" : ""), + (ts_status.flowDir & 0x02 ? "Down" : "")); + } + + printf("%12u\n", ts_status.mediumTime); + } + + printf("\n"); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Provides interface to perform read/write operations on regsiter + * + * Command: mlanconfig mlanX regrdwr [value] + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_regrdwr(int argc, char *argv[]) +{ + struct iwreq iwr; + int ioctl_val, subioctl_val; + t_u32 type, offset, value; + t_u8 buf[100]; + HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf; + int ret = MLAN_STATUS_SUCCESS; + + /* Check arguments */ + if ((argc < 5) || (argc > 6)) { + printf("Parameters for regrdwr: [value]\n"); + return -EINVAL; + } + + if (get_priv_ioctl("hostcmd", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + type = a2hex_or_atoi(argv[3]); + offset = a2hex_or_atoi(argv[4]); + if (argc > 5) + value = a2hex_or_atoi(argv[5]); + if ((ret = prepare_hostcmd_regrdwr(type, offset, + (argc > 5) ? &value : NULL, buf))) { + return ret; + } + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = buf; + iwr.u.data.length = le16_to_cpu(hostcmd->size); + iwr.u.data.flags = 0; + + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, + "mlanconfig: MLANHOSTCMD is not supported by %s\n", + dev_name); + return MLAN_STATUS_FAILURE; + } + ret = process_host_cmd_resp(buf); + + return ret; +} + +/** + * @brief Provides interface to perform read/write the adapter memory + * + * Command: mlanconfig mlanX memrdwr
[value] + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_memrdwr(int argc, char *argv[]) +{ + struct iwreq iwr; + int ioctl_val, subioctl_val; + t_u32 address, value; + t_u8 buf[100] = { 0 }; + HostCmd_DS_MEM *pmem; + HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf; + int ret = MLAN_STATUS_SUCCESS; + + pmem = (HostCmd_DS_MEM *)(buf + S_DS_GEN); + + /* Check arguments */ + if ((argc < 4) || (argc > 5)) { + printf("Parameters for memrdwr:
[value]\n"); + return -EINVAL; + } + + if (get_priv_ioctl("hostcmd", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + address = a2hex_or_atoi(argv[3]); + pmem->addr = cpu_to_le32(address); + if (argc > 4) { + pmem->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + value = a2hex_or_atoi(argv[4]); + pmem->value = cpu_to_le32(value); + } else { + pmem->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + pmem->value = 0; + } + hostcmd->command = cpu_to_le16(HostCmd_CMD_MEM_ACCESS); + hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_MEM)); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = buf; + iwr.u.data.length = le16_to_cpu(hostcmd->size); + iwr.u.data.flags = 0; + + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, + "mlanconfig: MLANHOSTCMD is not supported by %s\n", + dev_name); + return MLAN_STATUS_FAILURE; + } + ret = process_host_cmd_resp(buf); + + return ret; +} + +/** custom IE, auto mask value */ +#define CUSTOM_IE_AUTO_MASK 0xffff + +/** + * @brief Show usage information for the customie + * command + * + * $return N/A + **/ +void +print_custom_ie_usage(void) +{ + printf("\nUsage : customie [INDEX] [MASK] [IEBuffer]"); + printf("\n empty - Get all IE settings\n"); + printf("\n INDEX: 0 - Get/Set IE index 0 setting"); + printf("\n 1 - Get/Set IE index 1 setting"); + printf("\n 2 - Get/Set IE index 2 setting"); + printf("\n 3 - Get/Set IE index 3 setting"); + printf("\n . "); + printf("\n . "); + printf("\n . "); + printf("\n -1 - Append/Delete IE automatically"); + printf("\n Delete will delete the IE from the matching IE buffer"); + printf("\n Append will append the IE to the buffer with the same mask"); + printf("\n MASK : Management subtype mask value as per bit defintions"); + printf("\n : Bit 0 - Association request."); + printf("\n : Bit 1 - Association response."); + printf("\n : Bit 2 - Reassociation request."); + printf("\n : Bit 3 - Reassociation response."); + printf("\n : Bit 4 - Probe request."); + printf("\n : Bit 5 - Probe response."); + printf("\n : Bit 8 - Beacon."); + printf("\n MASK : MASK = 0 to clear the mask and the IE buffer"); + printf("\n IEBuffer : IE Buffer in hex (max 256 bytes)\n\n"); + return; +} + +/** + * @brief Converts a string to hex value + * + * @param str A pointer to the string + * @param raw A pointer to the raw data buffer + * @return Number of bytes read + **/ +int +string2raw(char *str, unsigned char *raw) +{ + int len = (strlen(str) + 1) / 2; + + do { + if (!isxdigit(*str)) { + return -1; + } + *str = toupper(*str); + *raw = CHAR2INT(*str) << 4; + ++str; + *str = toupper(*str); + if (*str == '\0') + break; + *raw |= CHAR2INT(*str); + ++raw; + } while (*++str != '\0'); + return len; +} + +/** + * @brief Creates a hostcmd request for custom IE settings + * and sends to the driver + * + * Usage: "customie [INDEX] [MASK] [IEBuffer]" + * + * Options: INDEX : 0 - Get/Delete IE index 0 setting + * 1 - Get/Delete IE index 1 setting + * 2 - Get/Delete IE index 2 setting + * 3 - Get/Delete IE index 3 setting + * . + * . + * . + * -1 - Append IE at the IE buffer with same MASK + * MASK : Management subtype mask value + * IEBuffer: IE Buffer in hex + * empty - Get all IE settings + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + **/ +static int +process_custom_ie(int argc, char *argv[]) +{ + tlvbuf_custom_ie *tlv = NULL; + tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv = NULL; + custom_ie *ie_ptr = NULL; + t_u8 *buffer = NULL; + t_u16 buf_len = 0; + t_u16 mgmt_subtype_mask = 0; + int ie_buf_len = 0, ie_len = 0, i = 0; + struct ifreq ifr; + + /* mlanconfig mlan0 customie idx flag buf */ + if (argc > 6) { + printf("ERR:Too many arguments.\n"); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + /* Error checks and initialize the command length */ + if (argc > 3) { + if (((IS_HEX_OR_DIGIT(argv[3]) == MLAN_STATUS_FAILURE) && + (atoi(argv[3]) != -1)) || (atoi(argv[3]) < -1)) { + printf("ERR:Illegal index %s\n", argv[3]); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + } + switch (argc) { + case 3: + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + break; + case 4: + if (atoi(argv[3]) < 0) { + printf("ERR:Illegal index %s. Must be either greater than or equal to 0 for Get Operation \n", argv[3]); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + break; + case 5: + if (MLAN_STATUS_FAILURE == ishexstring(argv[4]) || + A2HEXDECIMAL(argv[4]) != 0) { + printf("ERR: Mask value should be 0 to clear IEBuffers.\n"); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + if (atoi(argv[3]) == -1) { + printf("ERR: You must provide buffer for automatic deletion.\n"); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie); + break; + case 6: + /* This is to check negative numbers and special symbols */ + if (MLAN_STATUS_FAILURE == IS_HEX_OR_DIGIT(argv[4])) { + printf("ERR:Mask value must be 0 or hex digits\n"); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + /* If above check is passed and mask is not hex, then it must be 0 */ + if ((ISDIGIT(argv[4]) == MLAN_STATUS_SUCCESS) && atoi(argv[4])) { + printf("ERR:Mask value must be 0 or hex digits\n "); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + if (MLAN_STATUS_FAILURE == ishexstring(argv[5])) { + printf("ERR:Only hex digits are allowed\n"); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + ie_buf_len = strlen(argv[5]); + if (!strncasecmp("0x", argv[5], 2)) { + ie_len = (ie_buf_len - 2 + 1) / 2; + argv[5] += 2; + } else + ie_len = (ie_buf_len + 1) / 2; + if (ie_len > MAX_IE_BUFFER_LEN) { + printf("ERR:Incorrect IE length %d\n", ie_buf_len); + print_custom_ie_usage(); + return MLAN_STATUS_FAILURE; + } + mgmt_subtype_mask = (t_u16)A2HEXDECIMAL(argv[4]); + buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie) + ie_len; + break; + } + /* Initialize the command buffer */ + buffer = (t_u8 *)malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + memset(buffer, 0, buf_len); + tlv = (tlvbuf_custom_ie *)buffer; + tlv->tag = MRVL_MGMT_IE_LIST_TLV_ID; + if (argc == 3 || argc == 4) { + if (argc == 3) + tlv->length = 0; + else { + tlv->length = sizeof(t_u16); + ie_ptr = (custom_ie *)(tlv->ie_data); + ie_ptr->ie_index = (t_u16)(atoi(argv[3])); + } + } else { + /* Locate headers */ + ie_ptr = (custom_ie *)(tlv->ie_data); + /* Set TLV fields */ + tlv->length = sizeof(custom_ie) + ie_len; + ie_ptr->ie_index = atoi(argv[3]); + ie_ptr->mgmt_subtype_mask = mgmt_subtype_mask; + ie_ptr->ie_length = ie_len; + if (argc == 6) + string2raw(argv[5], ie_ptr->ie_buffer); + } + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)buffer; + /* Perform ioctl */ + if (ioctl(sockfd, CUSTOM_IE_CFG, &ifr)) { + perror("ioctl[CUSTOM_IE_CFG]"); + printf("ERR:Command sending failed!\n"); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + /* Print response */ + if (argc > 4) { + printf("custom IE setting successful\n"); + } else { + printf("Querying custom IE successful\n"); + tlv = (tlvbuf_custom_ie *)buffer; + ie_len = tlv->length; + ie_ptr = (custom_ie *)(tlv->ie_data); + while ((unsigned int)ie_len >= sizeof(custom_ie)) { + printf("Index [%d]\n", ie_ptr->ie_index); + if (ie_ptr->ie_length) + printf("Management Subtype Mask = 0x%02x\n", + (ie_ptr->mgmt_subtype_mask) == 0 ? + CUSTOM_IE_AUTO_MASK : + (ie_ptr->mgmt_subtype_mask)); + else + printf("Management Subtype Mask = 0x%02x\n", + (ie_ptr->mgmt_subtype_mask)); + hexdump("IE Buffer", (void *)ie_ptr->ie_buffer, + ie_ptr->ie_length, ' '); + ie_len -= sizeof(custom_ie) + ie_ptr->ie_length; + ie_ptr = (custom_ie *)((t_u8 *)ie_ptr + + sizeof(custom_ie) + + ie_ptr->ie_length); + } + } + max_mgmt_ie_tlv = + (tlvbuf_max_mgmt_ie *)(buffer + sizeof(tlvbuf_custom_ie) + + tlv->length); + if (max_mgmt_ie_tlv) { + if (max_mgmt_ie_tlv->tag == MRVL_MAX_MGMT_IE_TLV_ID) { + for (i = 0; i < max_mgmt_ie_tlv->count; i++) { + printf("buf%d_size = %d\n", i, + max_mgmt_ie_tlv->info[i].buf_size); + printf("number of buffers = %d\n", + max_mgmt_ie_tlv->info[i].buf_count); + printf("\n"); + } + } + } + if (buffer) + free(buffer); + + return MLAN_STATUS_SUCCESS; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief Get one line from the File + * + * @param fp File handler + * @param str Storage location for data. + * @param size Maximum number of characters to read. + * @param lineno A pointer to return current line number + * @return returns string or NULL + */ +char * +mlan_config_get_line(FILE * fp, t_s8 *str, t_s32 size, int *lineno) +{ + char *start, *end; + int out, next_line; + + if (!fp || !str) + return NULL; + + do { +read_line: + if (!fgets(str, size, fp)) + break; + start = str; + start[size - 1] = '\0'; + end = start + strlen(str); + (*lineno)++; + + out = 1; + while (out && (start < end)) { + next_line = 0; + /* Remove empty lines and lines starting with # */ + switch (start[0]) { + case ' ': /* White space */ + case '\t': /* Tab */ + start++; + break; + case '#': + case '\n': + case '\0': + next_line = 1; + break; + case '\r': + if (start[1] == '\n') + next_line = 1; + else + start++; + break; + default: + out = 0; + break; + } + if (next_line) + goto read_line; + } + + /* Remove # comments unless they are within a double quoted + * string. Remove trailing white space. */ + if ((end = strstr(start, "\""))) { + if (!(end = strstr(end + 1, "\""))) + end = start; + } else + end = start; + + if ((end = strstr(end + 1, "#"))) + *end-- = '\0'; + else + end = start + strlen(start) - 1; + + out = 1; + while (out && (start < end)) { + switch (*end) { + case ' ': /* White space */ + case '\t': /* Tab */ + case '\n': + case '\r': + *end = '\0'; + end--; + break; + default: + out = 0; + break; + } + } + + if (start == '\0') + continue; + + return start; + } while (1); + + return NULL; +} + +/** + * @brief parse hex data + * @param fp File handler + * @param dst A pointer to receive hex data + * @return length of hex data + */ +int +fparse_for_hex(FILE * fp, t_u8 *dst) +{ + t_s8 *ptr; + t_u8 *dptr; + t_s8 buf[256]; + + dptr = dst; + while (fgets(buf, sizeof(buf), fp)) { + ptr = buf; + + while (*ptr) { + /* skip leading spaces */ + while (*ptr && (isspace(*ptr) || *ptr == '\t')) + ptr++; + + /* skip blank lines and lines beginning with '#' */ + if (*ptr == '\0' || *ptr == '#') + break; + + if (isxdigit(*ptr)) { + ptr = convert2hex(ptr, dptr++); + } else { + /* Invalid character on data line */ + ptr++; + } + } + } + + return (dptr - dst); +} + +#define STACK_NBYTES 100 /**< Number of bytes in stack */ +#define MAX_BYTESEQ 6 /**< Maximum byte sequence */ +#define TYPE_DNUM 1 /**< decimal number */ +#define TYPE_BYTESEQ 2 /**< byte sequence */ +#define MAX_OPERAND 0x40 /**< Maximum operands */ +#define TYPE_EQ (MAX_OPERAND+1) /**< byte comparison: == operator */ +#define TYPE_EQ_DNUM (MAX_OPERAND+2) /**< decimal comparison: =d operator */ +#define TYPE_EQ_BIT (MAX_OPERAND+3) /**< bit comparison: =b operator */ +#define TYPE_AND (MAX_OPERAND+4) /**< && operator */ +#define TYPE_OR (MAX_OPERAND+5) /**< || operator */ + +typedef struct { + t_u16 sp; /**< Stack pointer */ + t_u8 byte[STACK_NBYTES]; /**< Stack */ +} mstack_t; + +typedef struct { + t_u8 type; /**< Type */ + t_u8 reserve[3]; /**< so 4-byte align val array */ + /* byte sequence is the largest among all the operands and operators. */ + /* byte sequence format: 1 byte of num of bytes, then variable num bytes */ + t_u8 val[MAX_BYTESEQ + 1];/**< Value */ +} op_t; + +/** + * @brief push data to stack + * + * @param s a pointer to mstack_t structure + * + * @param nbytes number of byte to push to stack + * + * @param val a pointer to data buffer + * + * @return TRUE-- sucess , FALSE -- fail + * + */ +static int +push_n(mstack_t * s, t_u8 nbytes, t_u8 *val) +{ + if ((s->sp + nbytes) < STACK_NBYTES) { + memcpy((void *)(s->byte + s->sp), (const void *)val, + (size_t) nbytes); + s->sp += nbytes; + /* printf("push: n %d sp %d\n", nbytes, s->sp); */ + return TRUE; + } else /* stack full */ + return FALSE; +} + +/** + * @brief push data to stack + * + * @param s a pointer to mstack_t structure + * + * @param op a pointer to op_t structure + * + * @return TRUE-- sucess , FALSE -- fail + * + */ +static int +push(mstack_t * s, op_t * op) +{ + t_u8 nbytes; + switch (op->type) { + case TYPE_DNUM: + if (push_n(s, 4, op->val)) + return (push_n(s, 1, &op->type)); + return FALSE; + case TYPE_BYTESEQ: + nbytes = op->val[0]; + if (push_n(s, nbytes, op->val + 1) && + push_n(s, 1, op->val) && push_n(s, 1, &op->type)) + return TRUE; + return FALSE; + default: + return (push_n(s, 1, &op->type)); + } +} + +/** + * @brief parse RPN string + * + * @param s a pointer to Null-terminated string to scan. + * + * @param first_time a pointer to return first_time + * + * @return A pointer to the last token found in string. + * NULL is returned when there are no more tokens to be found. + * + */ +static char * +getop(char *s, int *first_time) +{ + const char delim[] = " \t\n"; + char *p; + if (*first_time) { + p = strtok(s, delim); + *first_time = FALSE; + } else { + p = strtok(NULL, delim); + } + return (p); +} + +/** + * @brief Verify hex digit. + * + * @param c input ascii char + * @param h a pointer to return integer value of the digit char. + * @return TURE -- c is hex digit, FALSE -- c is not hex digit. + */ +static int +ishexdigit(char c, t_u8 *h) +{ + if (c >= '0' && c <= '9') { + *h = c - '0'; + return (TRUE); + } else if (c >= 'a' && c <= 'f') { + *h = c - 'a' + 10; + return (TRUE); + } else if (c >= 'A' && c <= 'F') { + *h = c - 'A' + 10; + return (TRUE); + } + return (FALSE); +} + +/** + * @brief convert hex string to integer. + * + * @param s A pointer to hex string, string length up to 2 digits. + * @return integer value. + */ +static t_u8 +hex_atoi(char *s) +{ + int i; + t_u8 digit; /* digital value */ + t_u8 t = 0; /* total value */ + + for (i = 0, t = 0; ishexdigit(s[i], &digit) && i < 2; i++) + t = 16 * t + digit; + return (t); +} + +/** + * @brief Parse byte sequence in hex format string to a byte sequence. + * + * @param opstr A pointer to byte sequence in hex format string, with ':' as delimiter between two byte. + * @param val A pointer to return byte sequence string + * @return NA + */ +static void +parse_hex(char *opstr, t_u8 *val) +{ + char delim = ':'; + char *p; + char *q; + t_u8 i; + + /* +1 is for skipping over the preceding h character. */ + p = opstr + 1; + + /* First byte */ + val[1] = hex_atoi(p++); + + /* Parse subsequent bytes. */ + /* Each byte is preceded by the : character. */ + for (i = 1; *p; i++) { + q = strchr(p, delim); + if (!q) + break; + p = q + 1; + val[i + 1] = hex_atoi(p); + } + /* Set num of bytes */ + val[0] = i; +} + +/** + * @brief str2bin, convert RPN string to binary format + * + * @param str A pointer to rpn string + * @param stack A pointer to mstack_t structure + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +str2bin(char *str, mstack_t * stack) +{ + int first_time; + char *opstr; + op_t op; /* operator/operand */ + int dnum; + int ret = MLAN_STATUS_SUCCESS; + + memset(stack, 0, sizeof(mstack_t)); + first_time = TRUE; + while ((opstr = getop(str, &first_time)) != NULL) { + if (isdigit(*opstr)) { + op.type = TYPE_DNUM; + dnum = cpu_to_le32(atoi(opstr)); + memcpy((t_u8 *)op.val, &dnum, sizeof(dnum)); + if (!push(stack, &op)) { + printf("push decimal number failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } else if (*opstr == 'h') { + op.type = TYPE_BYTESEQ; + parse_hex(opstr, op.val); + if (!push(stack, &op)) { + printf("push byte sequence failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } else if (!strcmp(opstr, "==")) { + op.type = TYPE_EQ; + if (!push(stack, &op)) { + printf("push byte cmp operator failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } else if (!strcmp(opstr, "=d")) { + op.type = TYPE_EQ_DNUM; + if (!push(stack, &op)) { + printf("push decimal cmp operator failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } else if (!strcmp(opstr, "=b")) { + op.type = TYPE_EQ_BIT; + if (!push(stack, &op)) { + printf("push bit cmp operator failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } else if (!strcmp(opstr, "&&")) { + op.type = TYPE_AND; + if (!push(stack, &op)) { + printf("push AND operator failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } else if (!strcmp(opstr, "||")) { + op.type = TYPE_OR; + if (!push(stack, &op)) { + printf("push OR operator failed\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } else { + printf("Unknown operand\n"); + ret = MLAN_STATUS_FAILURE; + break; + } + } + return ret; +} + +/** + * @brief Converts colon separated MAC address to hex value + * + * @param mac A pointer to the colon separated MAC string + * @param raw A pointer to the hex data buffer + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + * MAC_BROADCAST - if breadcast mac + * MAC_MULTICAST - if multicast mac + */ +static int +mac2raw(char *mac, t_u8 *raw) +{ + unsigned int temp_raw[ETH_ALEN]; + int num_tokens = 0; + int i; + + if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) { + return MLAN_STATUS_FAILURE; + } + num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x", + temp_raw + 0, temp_raw + 1, temp_raw + 2, + temp_raw + 3, temp_raw + 4, temp_raw + 5); + if (num_tokens != ETH_ALEN) { + return MLAN_STATUS_FAILURE; + } + for (i = 0; i < num_tokens; i++) + raw[i] = (t_u8)temp_raw[i]; + + if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { + return MAC_BROADCAST; + } else if (raw[0] & 0x01) { + return MAC_MULTICAST; + } + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Parse function for a configuration line + * + * @param s Storage buffer for data + * @param size Maximum size of data + * @param stream File stream pointer + * @param line Pointer to current line within the file + * @param _pos Output string or NULL + * @return String or NULL + */ +static char * +config_get_line(char *s, int size, FILE * stream, int *line, char **_pos) +{ + *_pos = mlan_config_get_line(stream, s, size, line); + return *_pos; +} + +/** + * @brief Parses a command line + * + * @param line The line to parse + * @param args Pointer to the argument buffer to be filled in + * @return Number of arguments in the line or EOF + */ +static int +parse_line(char *line, char *args[]) +{ + int arg_num = 0; + int is_start = 0; + int is_quote = 0; + int length = 0; + int i = 0; + + arg_num = 0; + length = strlen(line); + /* Process line */ + + /* Find number of arguments */ + is_start = 0; + is_quote = 0; + for (i = 0; i < length; i++) { + /* Ignore leading spaces */ + if (is_start == 0) { + if (line[i] == ' ') { + continue; + } else if (line[i] == '\t') { + continue; + } else if (line[i] == '\n') { + break; + } else { + is_start = 1; + args[arg_num] = &line[i]; + arg_num++; + } + } + if (is_start == 1) { + /* Ignore comments */ + if (line[i] == '#') { + if (is_quote == 0) { + line[i] = '\0'; + arg_num--; + } + break; + } + /* Separate by '=' */ + if (line[i] == '=') { + line[i] = '\0'; + is_start = 0; + continue; + } + /* Separate by ',' */ + if (line[i] == ',') { + line[i] = '\0'; + is_start = 0; + continue; + } + /* Change ',' to ' ', but not inside quotes */ + if ((line[i] == ',') && (is_quote == 0)) { + line[i] = ' '; + continue; + } + } + /* Remove newlines */ + if (line[i] == '\n') { + line[i] = '\0'; + } + /* Check for quotes */ + if (line[i] == '"') { + is_quote = (is_quote == 1) ? 0 : 1; + continue; + } + if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) { + line[i] = '\0'; + is_start = 0; + continue; + } + } + return arg_num; +} + +#define FILTER_BYTESEQ TYPE_EQ /**< byte sequence */ +#define FILTER_DNUM TYPE_EQ_DNUM /**< decimal number */ +#define FILTER_BITSEQ TYPE_EQ_BIT /**< bit sequence */ +#define FILTER_TEST FILTER_BITSEQ+1 /**< test */ + +#define NAME_TYPE 1 /**< Field name 'type' */ +#define NAME_PATTERN 2 /**< Field name 'pattern' */ +#define NAME_OFFSET 3 /**< Field name 'offset' */ +#define NAME_NUMBYTE 4 /**< Field name 'numbyte' */ +#define NAME_REPEAT 5 /**< Field name 'repeat' */ +#define NAME_BYTE 6 /**< Field name 'byte' */ +#define NAME_MASK 7 /**< Field name 'mask' */ +#define NAME_DEST 8 /**< Field name 'dest' */ + +static struct mef_fields { + t_s8 *name; + /**< Name */ + t_s8 nameid; + /**< Name Id. */ +} mef_fields[] = { + { + "type", NAME_TYPE}, { + "pattern", NAME_PATTERN}, { + "offset", NAME_OFFSET}, { + "numbyte", NAME_NUMBYTE}, { + "repeat", NAME_REPEAT}, { + "byte", NAME_BYTE}, { + "mask", NAME_MASK}, { + "dest", NAME_DEST} +}; + +/** + * @brief get filter data + * + * @param fp A pointer to file stream + * @param ln A pointer to line number + * @param buf A pointer to hostcmd data + * @param size A pointer to the return size of hostcmd buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +mlan_get_filter_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size) +{ + t_s32 errors = 0, i; + t_s8 line[256], *pos, *pos1; + t_u16 type = 0; + t_u32 pattern = 0; + t_u16 repeat = 0; + t_u16 offset = 0; + t_s8 byte_seq[50]; + t_s8 mask_seq[50]; + t_u16 numbyte = 0; + t_s8 type_find = 0; + t_s8 pattern_find = 0; + t_s8 offset_find = 0; + t_s8 numbyte_find = 0; + t_s8 repeat_find = 0; + t_s8 byte_find = 0; + t_s8 mask_find = 0; + t_s8 dest_find = 0; + t_s8 dest_seq[50]; + + *size = 0; + while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) { + if (strcmp(pos, "}") == 0) { + break; + } + pos1 = strchr(pos, '='); + if (pos1 == NULL) { + printf("Line %d: Invalid mef_filter line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos1++ = '\0'; + for (i = 0; (t_u32)i < NELEMENTS(mef_fields); i++) { + if (strncmp + (pos, mef_fields[i].name, + strlen(mef_fields[i].name)) == 0) { + switch (mef_fields[i].nameid) { + case NAME_TYPE: + type = a2hex_or_atoi(pos1); + if ((type != FILTER_DNUM) && + (type != FILTER_BYTESEQ) + && (type != FILTER_BITSEQ) && + (type != FILTER_TEST)) { + printf("Invalid filter type:%d\n", type); + return MLAN_STATUS_FAILURE; + } + type_find = 1; + break; + case NAME_PATTERN: + pattern = a2hex_or_atoi(pos1); + pattern_find = 1; + break; + case NAME_OFFSET: + offset = a2hex_or_atoi(pos1); + offset_find = 1; + break; + case NAME_NUMBYTE: + numbyte = a2hex_or_atoi(pos1); + numbyte_find = 1; + break; + case NAME_REPEAT: + repeat = a2hex_or_atoi(pos1); + repeat_find = 1; + break; + case NAME_BYTE: + memset(byte_seq, 0, sizeof(byte_seq)); + strncpy(byte_seq, pos1, + (sizeof(byte_seq) - 1)); + byte_find = 1; + break; + case NAME_MASK: + memset(mask_seq, 0, sizeof(mask_seq)); + strncpy(mask_seq, pos1, + (sizeof(mask_seq) - 1)); + mask_find = 1; + break; + case NAME_DEST: + memset(dest_seq, 0, sizeof(dest_seq)); + strncpy(dest_seq, pos1, + (sizeof(dest_seq) - 1)); + dest_find = 1; + break; + } + break; + } + } + if (i == NELEMENTS(mef_fields)) { + printf("Line %d: unknown mef field '%s'.\n", + *line, pos); + errors++; + } + } + if (type_find == 0) { + printf("Can not find filter type\n"); + return MLAN_STATUS_FAILURE; + } + switch (type) { + case FILTER_DNUM: + if (!pattern_find || !offset_find || !numbyte_find) { + printf("Missing field for FILTER_DNUM: pattern=%d,offset=%d,numbyte=%d\n", pattern_find, offset_find, numbyte_find); + return MLAN_STATUS_FAILURE; + } + memset(line, 0, sizeof(line)); + snprintf(line, sizeof(line), "%d %d %d =d ", pattern, offset, + numbyte); + break; + case FILTER_BYTESEQ: + if (!byte_find || !offset_find || !repeat_find) { + printf("Missing field for FILTER_BYTESEQ: byte=%d,offset=%d,repeat=%d\n", byte_find, offset_find, repeat_find); + return MLAN_STATUS_FAILURE; + } + memset(line, 0, sizeof(line)); + snprintf(line, sizeof(line), "%d h%s %d == ", repeat, byte_seq, + offset); + break; + case FILTER_BITSEQ: + if (!byte_find || !offset_find || !mask_find) { + printf("Missing field for FILTER_BITSEQ: byte=%d,offset=%d,mask_find=%d\n", byte_find, offset_find, mask_find); + return MLAN_STATUS_FAILURE; + } + if (strlen(byte_seq) != strlen(mask_seq)) { + printf("byte string's length is different with mask's length!\n"); + return MLAN_STATUS_FAILURE; + } + memset(line, 0, sizeof(line)); + snprintf(line, sizeof(line), "h%s %d h%s =b ", byte_seq, offset, + mask_seq); + break; + case FILTER_TEST: + if (!byte_find || !offset_find || !repeat_find || !dest_find) { + printf("Missing field for FILTER_TEST: byte=%d,offset=%d,repeat=%d,dest=%d\n", byte_find, offset_find, repeat_find, dest_find); + return MLAN_STATUS_FAILURE; + } + memset(line, 0, sizeof(line)); + snprintf(line, sizeof(line), "h%s %d h%s %d ", dest_seq, repeat, + byte_seq, offset); + break; + } + memcpy(buf, line, strlen(line)); + *size = strlen(line); + return MLAN_STATUS_SUCCESS; +} + +#define NAME_MODE 1 /**< Field name 'mode' */ +#define NAME_ACTION 2 /**< Field name 'action' */ +#define NAME_FILTER_NUM 3 /**< Field name 'filter_num' */ +#define NAME_RPN 4 /**< Field name 'RPN' */ +static struct mef_entry_fields { + t_s8 *name; + /**< Name */ + t_s8 nameid; + /**< Name id */ +} mef_entry_fields[] = { + { + "mode", NAME_MODE}, { + "action", NAME_ACTION}, { + "filter_num", NAME_FILTER_NUM}, { +"RPN", NAME_RPN},}; + +typedef struct _MEF_ENTRY { + /** Mode */ + t_u8 Mode; + /** Size */ + t_u8 Action; + /** Size of expression */ + t_u16 ExprSize; +} MEF_ENTRY; + +/** + * @brief get mef_entry data + * + * @param fp A pointer to file stream + * @param ln A pointer to line number + * @param buf A pointer to hostcmd data + * @param size A pointer to the return size of hostcmd buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +mlan_get_mef_entry_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size) +{ + t_s8 line[256], *pos, *pos1; + t_u8 mode, action, filter_num = 0; + t_s8 rpn[256]; + t_s8 mode_find = 0; + t_s8 action_find = 0; + t_s8 filter_num_find = 0; + t_s8 rpn_find = 0; + t_s8 rpn_str[256]; + int rpn_len = 0; + t_s8 filter_name[50]; + t_s8 name_found = 0; + t_u16 len = 0; + int i; + int first_time = TRUE; + char *opstr; + t_s8 filter_action[10]; + t_s32 errors = 0; + MEF_ENTRY *pMefEntry = (MEF_ENTRY *) buf; + mstack_t stack; + while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) { + if (strcmp(pos, "}") == 0) { + break; + } + pos1 = strchr(pos, '='); + if (pos1 == NULL) { + printf("Line %d: Invalid mef_entry line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos1++ = '\0'; + if (!mode_find || !action_find || !filter_num_find || !rpn_find) { + for (i = 0; + (unsigned int)i < NELEMENTS(mef_entry_fields); + i++) { + if (strncmp + (pos, mef_entry_fields[i].name, + strlen(mef_entry_fields[i].name)) == 0) { + switch (mef_entry_fields[i].nameid) { + case NAME_MODE: + mode = a2hex_or_atoi(pos1); + if (mode & ~0x7) { + printf("invalid mode=%d\n", mode); + return MLAN_STATUS_FAILURE; + } + pMefEntry->Mode = mode; + mode_find = 1; + break; + case NAME_ACTION: + action = a2hex_or_atoi(pos1); + if (action & ~0xff) { + printf("invalid action=%d\n", action); + return MLAN_STATUS_FAILURE; + } + pMefEntry->Action = action; + action_find = 1; + break; + case NAME_FILTER_NUM: + filter_num = + a2hex_or_atoi(pos1); + filter_num_find = 1; + break; + case NAME_RPN: + memset(rpn, 0, sizeof(rpn)); + strncpy(rpn, pos1, + (sizeof(rpn) - 1)); + rpn_find = 1; + break; + } + break; + } + } + if (i == NELEMENTS(mef_fields)) { + printf("Line %d: unknown mef_entry field '%s'.\n", *line, pos); + return MLAN_STATUS_FAILURE; + } + } + if (mode_find && action_find && filter_num_find && rpn_find) { + for (i = 0; i < filter_num; i++) { + opstr = getop(rpn, &first_time); + if (opstr == NULL) + break; + snprintf(filter_name, sizeof(filter_name), + "%s={", opstr); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, + sizeof(line), + ln))) { + if (strncmp + (pos, filter_name, + strlen(filter_name)) == 0) { + name_found = 1; + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanconfig: %s not found in file\n", + filter_name); + return MLAN_STATUS_FAILURE; + } + if (MLAN_STATUS_FAILURE == + mlan_get_filter_data(fp, ln, + (t_u8 *)(rpn_str + + rpn_len), + &len)) + break; + rpn_len += len; + if (i > 0) { + memcpy(rpn_str + rpn_len, filter_action, + strlen(filter_action)); + rpn_len += strlen(filter_action); + } + opstr = getop(rpn, &first_time); + if (opstr == NULL) + break; + memset(filter_action, 0, sizeof(filter_action)); + snprintf(filter_action, sizeof(filter_action), + "%s ", opstr); + } + /* Remove the last space */ + if (rpn_len > 0) { + rpn_len--; + rpn_str[rpn_len] = 0; + } + if (MLAN_STATUS_FAILURE == str2bin(rpn_str, &stack)) { + printf("Fail on str2bin!\n"); + return MLAN_STATUS_FAILURE; + } + *size = sizeof(MEF_ENTRY); + pMefEntry->ExprSize = cpu_to_le16(stack.sp); + memmove(buf + sizeof(MEF_ENTRY), stack.byte, stack.sp); + *size += stack.sp; + break; + } else if (mode_find && action_find && filter_num_find && + (filter_num == 0)) { + pMefEntry->ExprSize = 0; + *size = sizeof(MEF_ENTRY); + break; + } + } + return MLAN_STATUS_SUCCESS; +} + +#define MEFCFG_CMDCODE 0x009a +/** + * @brief Process mef cfg + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_mef_cfg(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + t_s8 line[256], cmdname[256], *pos; + int cmdname_found = 0, name_found = 0; + int ln = 0; + int ret = MLAN_STATUS_SUCCESS; + int i; + t_u8 *buf; + t_u16 buf_len = 0; + t_u16 len = 0; + struct iwreq iwr; + HostCmd_DS_MEF_CFG *mefcmd; + HostCmd_DS_GEN *hostcmd; + FILE *fp = NULL; + + if (argc < 4) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./mlanconfig eth1 mefcfg \n"); + exit(1); + } + if (get_priv_ioctl("hostcmd", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + snprintf(cmdname, sizeof(cmdname), "%s={", argv[2]); + cmdname_found = 0; + if ((fp = fopen(argv[3], "r")) == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[4]); + exit(1); + } + + buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (buf == NULL) { + fclose(fp); + fprintf(stderr, "Cannot alloc memory\n"); + exit(1); + } + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + + hostcmd = (HostCmd_DS_GEN *)(buf); + hostcmd->command = cpu_to_le16(MEFCFG_CMDCODE); + mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN); + buf_len = sizeof(HostCmd_DS_MEF_CFG) + S_DS_GEN; + + while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { + if (strcmp(pos, cmdname) == 0) { + cmdname_found = 1; + snprintf(cmdname, sizeof(cmdname), "Criteria="); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, sizeof(line), + &ln))) { + if (strncmp(pos, cmdname, strlen(cmdname)) == 0) { + name_found = 1; + mefcmd->Criteria = + a2hex_or_atoi(pos + + strlen(cmdname)); + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanconfig: criteria not found in file '%s'\n", + argv[3]); + break; + } + snprintf(cmdname, sizeof(cmdname), "NumEntries="); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, sizeof(line), + &ln))) { + if (strncmp(pos, cmdname, strlen(cmdname)) == 0) { + name_found = 1; + mefcmd->NumEntries = + a2hex_or_atoi(pos + + strlen(cmdname)); + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanconfig: NumEntries not found in file '%s'\n", + argv[3]); + break; + } + for (i = 0; i < mefcmd->NumEntries; i++) { + snprintf(cmdname, sizeof(cmdname), + "mef_entry_%d={", i); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, + sizeof(line), + &ln))) { + if (strncmp + (pos, cmdname, + strlen(cmdname)) == 0) { + name_found = 1; + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanconfig: %s not found in file '%s'\n", + cmdname, argv[3]); + break; + } + if (MLAN_STATUS_FAILURE == + mlan_get_mef_entry_data(fp, &ln, + buf + buf_len, + &len)) { + ret = MLAN_STATUS_FAILURE; + break; + } + buf_len += len; + } + break; + } + } + fclose(fp); + /* hexdump("mef_cfg",buf,buf_len, ' '); */ + if (!cmdname_found) + fprintf(stderr, + "mlanconfig: cmdname '%s' not found in file '%s'\n", + argv[4], argv[3]); + + if (!cmdname_found || !name_found) { + ret = MLAN_STATUS_FAILURE; + goto mef_exit; + } + hostcmd->size = cpu_to_le16(buf_len); + mefcmd->Criteria = cpu_to_le32(mefcmd->Criteria); + mefcmd->NumEntries = cpu_to_le16(mefcmd->NumEntries); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = buf; + iwr.u.data.length = buf_len; + iwr.u.data.flags = 0; + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, "mlanconfig: MEFCFG is not supported by %s\n", + dev_name); + ret = MLAN_STATUS_FAILURE; + goto mef_exit; + } + ret = process_host_cmd_resp(buf); + +mef_exit: + if (buf) + free(buf); + return ret; + +} + +/** + * @brief Process transmission of mgmt frames + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_mgmt_frame_tx(int argc, char *argv[]) +{ + struct ifreq ifr; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, arg_num = 0, ret = 0, i = 0; + char *args[100] = { NULL }, *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 data_len = 0, subtype = 0; + wlan_mgmt_frame_tx *pmgmt_frame; + t_u8 *buffer = NULL; + pkt_header *hdr = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX mgmtframetx \n"); + exit(1); + } + + data_len = sizeof(wlan_mgmt_frame_tx); + + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + hdr = (pkt_header *)buffer; + pmgmt_frame = (wlan_mgmt_frame_tx *)(buffer + sizeof(pkt_header)); + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + arg_num = parse_line(line, args); + if (strcmp(args[0], "PktSubType") == 0) { + subtype = (t_u16)A2HEXDECIMAL(args[1]); + pmgmt_frame->frm_ctl |= subtype << 4; + } else if (strncmp(args[0], "Addr", 4) == 0) { + strncpy(mac_addr, args[1], 20); + if ((ret = + mac2raw(mac_addr, + peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + i = atoi(args[0] + 4); + switch (i) { + case 1: + memcpy(pmgmt_frame->addr1, peer_mac, ETH_ALEN); + break; + case 2: + memcpy(pmgmt_frame->addr2, peer_mac, ETH_ALEN); + break; + case 3: + memcpy(pmgmt_frame->addr3, peer_mac, ETH_ALEN); + break; + case 4: + memcpy(pmgmt_frame->addr4, peer_mac, ETH_ALEN); + break; + } + } else if (strcmp(args[0], "Data") == 0) { + for (i = 0; i < arg_num - 1; i++) + pmgmt_frame->payload[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + data_len += arg_num - 1; + } + } + pmgmt_frame->frm_len = data_len - sizeof(pmgmt_frame->frm_len); +#define MRVL_PKT_TYPE_MGMT_FRAME 0xE5 + hdr->pkt_len = data_len; + hdr->TxPktType = MRVL_PKT_TYPE_MGMT_FRAME; + hdr->TxControl = 0; + hexdump("Frame Tx", buffer, data_len + sizeof(pkt_header), ' '); + /* Send collective command */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)buffer; + + /* Perform ioctl */ + if (ioctl(sockfd, FRAME_TX_IOCTL, &ifr)) { + perror(""); + printf("ERR:Could not send management frame.\n"); + } else { + printf("Mgmt Frame sucessfully sent.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Performs the ioctl operation to send the command to + * the driver. + * + * @param cmd_buf Pointer to the command buffer + * @param buf_size Size of the allocated command buffer + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +static int +tdls_ioctl(t_u8 *cmd_buf, t_u16 buf_size) +{ + struct ifreq ifr; + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd_buf; + + /* Perform ioctl */ + if (ioctl(sockfd, TDLS_IOCTL, &ifr)) { + perror(""); + return MLAN_STATUS_FAILURE; + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief enable/disable tdls config + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_config(int argc, char *argv[]) +{ + + tdls_config *param_buf = NULL; + int ret = 0; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_config <0/1>\n"); + exit(1); + } + + cmd_len = sizeof(tdls_config); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_config *) buffer; + param_buf->action = ACTION_TDLS_CONFIG; + + param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]); + if ((param_buf->data != 0) && (param_buf->data != 1)) { + printf("ERR:Incorrect arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_config <0/1>\n"); + goto done; + } + hexdump("tdls_config ", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS %s successful.\n", + (param_buf->data) ? "enable" : "disable"); + } else { + printf("ERR:TDLS %s failed.\n", + (param_buf->data) ? "enable" : "disable"); + } + +done: + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_setinfo + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_setinfo(int argc, char *argv[]) +{ + tdls_setinfo *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, arg_num = 0, ret = 0, i = 0, cmd_found = 0, pairwise_index = + 0, akm_index = 0, pmkid_index = 0; + char *args[30] = { NULL }, *pos = NULL; + t_u16 cmd_len = 0, tlv_len = 0, tlv_len_rsn = 0, tlv_len_supp_chan = + 0, tlv_len_domain = 0; + t_u16 no_of_sub_band = 0, no_of_supp_chan_sub_band = + 0, pairwise_offset = 0, akm_offset = + 0, num_of_regulatory_class = 0, tlv_len_reg_class; + t_u16 akm_count = 0, pmk_count = 0, rsn_cap = 0; + t_u8 *buffer = NULL; + char country[COUNTRY_CODE_LEN]; + tlvbuf_DomainParamSet_t *domain = NULL; + tlvbuf_SupportedChannels_t *supp_chan = NULL; + tlvbuf_RegulatoryClass_t *reg_class = NULL; + tlvbuf_HTCap_t *tlv_ht_cap = NULL; + tlvbuf_RsnParamSet_t *rsn_ie = NULL; + tlvbuf_HTInfo_t *tlv_ht_info = NULL; + t_u8 pairwise_cipher_suite[PAIRWISE_CIPHER_SUITE_LEN]; + t_u8 akm_suite[AKM_SUITE_LEN]; + t_u8 pmkid[PMKID_LEN]; + tlvbuf_VHTCap_t *tlv_vht_cap = NULL; + tlvbuf_VHTOpra_t *tlv_vht_oper = NULL; + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_setinfo \n"); + exit(1); + } + + cmd_len = sizeof(tdls_setinfo); + + buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + param_buf = (tdls_setinfo *)buffer; + param_buf->action = ACTION_TDLS_SETINFO; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + arg_num = parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + if (strcmp(args[0], "CapInfo") == 0) { + param_buf->cap_info = (t_u16)A2HEXDECIMAL(args[1]); + param_buf->cap_info = cpu_to_le16(param_buf->cap_info); + } else if (strcmp(args[0], "Rate") == 0) { + tlvbuf_RatesParamSet_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_RatesParamSet_t) + arg_num - 1; + tlv = (tlvbuf_RatesParamSet_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_RATES; + tlv->length = arg_num - 1; + for (i = 0; i < tlv->length; i++) { + tlv->rates[i] = (t_u8)A2HEXDECIMAL(args[i + 1]); + } + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "QosInfo") == 0) { + tlvbuf_QosInfo_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_QosInfo_t); + tlv = (tlvbuf_QosInfo_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_QOSINFO; + tlv->length = sizeof(tlvbuf_QosInfo_t) - TLVHEADER_LEN; + tlv->u.qos_info_byte = (t_u8)A2HEXDECIMAL(args[1]); + if ((tlv->u.qos_info_byte != 0) && + (tlv->u.qos_info_byte != 0x0F)) { + printf("Invalid QosInfo. Should be 0x00 or 0x0F.\n"); + goto done; + } + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "ExtendCapabilities") == 0) { + tlvbuf_ExtCap_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_ExtCap_t) + arg_num - 1; + tlv = (tlvbuf_ExtCap_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_EXTCAP; + tlv->length = arg_num - 1; + for (i = 0; i < tlv->length; i++) { + tlv->ext_cap[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "HTCapability") == 0) { + /* Append a new TLV */ + tlv_ht_cap = (tlvbuf_HTCap_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_HTCap_t); + tlv_ht_cap->tag = TLV_TYPE_HT_CAP; + tlv_ht_cap->length = + sizeof(tlvbuf_HTCap_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_ht_cap); + } else if (strcmp(args[0], "HTCapabilityInfo") == 0) { + tlv_ht_cap->ht_cap.ht_cap_info = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_cap->ht_cap.ht_cap_info = + cpu_to_le16(tlv_ht_cap->ht_cap.ht_cap_info); + } else if (strcmp(args[0], "AMPDUParam") == 0) { + tlv_ht_cap->ht_cap.ampdu_param = + (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "SupportedMCSSet") == 0) { + for (i = 0; i < MCS_SET_LEN; i++) + tlv_ht_cap->ht_cap.supported_mcs_set[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "HTExtCapability") == 0) { + tlv_ht_cap->ht_cap.ht_ext_cap = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_cap->ht_cap.ht_ext_cap = + cpu_to_le16(tlv_ht_cap->ht_cap.ht_ext_cap); + } else if (strcmp(args[0], "TxBfCapability") == 0) { + tlv_ht_cap->ht_cap.tx_bf_cap = + (t_u32)A2HEXDECIMAL(args[1]); + tlv_ht_cap->ht_cap.tx_bf_cap = + cpu_to_le32(tlv_ht_cap->ht_cap.tx_bf_cap); + } else if (strcmp(args[0], "AntennaSel") == 0) { + tlv_ht_cap->ht_cap.asel = (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "HTInformation") == 0) { + /* Append a new TLV */ + tlv_ht_info = (tlvbuf_HTInfo_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_HTInfo_t); + tlv_ht_info->tag = TLV_TYPE_HT_INFO; + tlv_ht_info->length = + sizeof(tlvbuf_HTInfo_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_ht_info); + } else if (strcmp(args[0], "PrimaryChannel") == 0) { + tlv_ht_info->ht_info.pri_chan = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "Field2") == 0) { + tlv_ht_info->ht_info.field2 = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "Field3") == 0) { + tlv_ht_info->ht_info.field3 = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_info->ht_info.field3 = + cpu_to_le16(tlv_ht_info->ht_info.field3); + } else if (strcmp(args[0], "Field4") == 0) { + tlv_ht_info->ht_info.field4 = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_info->ht_info.field4 = + cpu_to_le16(tlv_ht_info->ht_info.field4); + } else if (strcmp(args[0], "BasicMCSSet") == 0) { + if ((arg_num - 1) != MCS_SET_LEN) { + printf("Incorrect number of arguments for BasicMCSSet.\n"); + goto done; + } + for (i = 0; i < MCS_SET_LEN; i++) + tlv_ht_info->ht_info.basic_mcs_set[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "2040BSSCoex") == 0) { + tlvbuf_2040BSSCo_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_2040BSSCo_t); + tlv = (tlvbuf_2040BSSCo_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_2040BSS_COEXISTENCE; + tlv->length = + sizeof(tlvbuf_2040BSSCo_t) - TLVHEADER_LEN; + tlv->bss_co_2040.bss_co_2040_value = + (t_u8)A2HEXDECIMAL(args[1]); + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "RSNInfo") == 0) { + /* Append a new TLV */ + rsn_ie = (tlvbuf_RsnParamSet_t *)(buffer + cmd_len); + tlv_len_rsn = sizeof(tlvbuf_RsnParamSet_t); + rsn_ie->tag = TLV_TYPE_RSN_IE; + rsn_ie->version = VERSION_RSN_IE; + rsn_ie->version = cpu_to_le16(rsn_ie->version); + cmd_len += tlv_len_rsn; + } else if (strcmp(args[0], "GroupCipherSuite") == 0) { + for (i = 0; i < GROUP_CIPHER_SUITE_LEN; i++) + rsn_ie->group_cipher_suite[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "PairwiseCipherCount") == 0) { + rsn_ie->pairwise_cipher_count = (t_u16)atoi(args[1]); + rsn_ie->pairwise_cipher_count = + cpu_to_le16(rsn_ie->pairwise_cipher_count); + } else if (strncmp(args[0], "PairwiseCipherSuite", 19) == 0) { + if (pairwise_index > MAX_PAIRWISE_CIPHER_SUITE_COUNT) { + printf("PairwiseCipherSuite exceeds max count\n"); + goto done; + } + tlv_len_rsn += PAIRWISE_CIPHER_SUITE_LEN; + cmd_len += PAIRWISE_CIPHER_SUITE_LEN; + for (i = 0; i < PAIRWISE_CIPHER_SUITE_LEN; i++) { + pairwise_cipher_suite[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } + memcpy((t_u8 *)(rsn_ie->pairwise_cipher_suite + + (pairwise_index * + PAIRWISE_CIPHER_SUITE_LEN)), + pairwise_cipher_suite, + PAIRWISE_CIPHER_SUITE_LEN); + pairwise_index++; + pairwise_offset = + pairwise_index * PAIRWISE_CIPHER_SUITE_LEN; + } else if (strcmp(args[0], "AKMSuiteCount") == 0) { + akm_count = (t_u16)atoi(args[1]); + akm_count = cpu_to_le16(akm_count); + memcpy((((t_u8 *)(&rsn_ie->akm_suite_count)) + + pairwise_offset), &akm_count, sizeof(t_u16)); + } else if (strncmp(args[0], "AKMSuite", 8) == 0) { + if (akm_index > MAX_AKM_SUITE_COUNT) { + printf("AKMSuite exceeds max count\n"); + goto done; + } + tlv_len_rsn += AKM_SUITE_LEN; + cmd_len += AKM_SUITE_LEN; + for (i = 0; i < AKM_SUITE_LEN; i++) { + akm_suite[i] = (t_u8)A2HEXDECIMAL(args[i + 1]); + } + memcpy((t_u8 *)(rsn_ie->akm_suite + + (akm_index * AKM_SUITE_LEN) + + pairwise_offset), akm_suite, + AKM_SUITE_LEN); + akm_index++; + akm_offset = akm_index * AKM_SUITE_LEN; + } else if (strcmp(args[0], "RSNCapability") == 0) { + rsn_cap = (t_u16)A2HEXDECIMAL(args[1]); + rsn_cap = cpu_to_le16(rsn_cap); + memcpy(((t_u8 *)(&(rsn_ie->rsn_capability))) + + pairwise_offset + akm_offset, &rsn_cap, + sizeof(t_u16)); + } else if (strcmp(args[0], "PMKIDCount") == 0) { + pmk_count = (t_u16)atoi(args[1]); + pmk_count = cpu_to_le16(pmk_count); + memcpy((((t_u8 *)(&rsn_ie->pmkid_count)) + + pairwise_offset + akm_offset), &pmk_count, + sizeof(t_u16)); + rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN; + endian_convert_tlv_header_out(rsn_ie); + } else if (strncmp(args[0], "PMKIDList", 9) == 0) { + if (pmkid_index > MAX_PMKID_COUNT) { + printf("PMKIDSuite exceeds max count\n"); + goto done; + } + for (i = 0; i < PMKID_LEN; i++) + pmkid[i] = (t_u8)A2HEXDECIMAL(args[i + 1]); + memcpy((t_u8 *)(rsn_ie->pmkid_list + + (pmkid_index * PMKID_LEN) + + pairwise_offset + akm_offset), pmkid, + PMKID_LEN); + pmkid_index++; + tlv_len_rsn += PMKID_LEN; + cmd_len += PMKID_LEN; + /* undo conversion done in PMKIDCount */ + endian_convert_tlv_header_in(rsn_ie); + rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN; + endian_convert_tlv_header_out(rsn_ie); + } else if (strcmp(args[0], "SupportedChannels") == 0) { + /* Append a new TLV */ + supp_chan = + (tlvbuf_SupportedChannels_t *)(buffer + + cmd_len); + supp_chan->tag = TLV_TYPE_SUPPORTED_CHANNELS; + supp_chan->length = sizeof(tlvbuf_SupportedChannels_t) + - TLVHEADER_LEN; + tlv_len_supp_chan = sizeof(tlvbuf_SupportedChannels_t); + cmd_len += tlv_len_supp_chan; + } else if (strncmp(args[0], "FirstChannelNo", 14) == 0) { + supp_chan->subband[no_of_supp_chan_sub_band]. + start_chan = atoi(args[1]); + } else if (strcmp(args[0], "NumberofSubBandChannels") == 0) { + supp_chan->subband[no_of_supp_chan_sub_band].num_chans = + atoi(args[1]); + no_of_supp_chan_sub_band++; + tlv_len_supp_chan += + sizeof(IEEEtypes_SupportChan_Subband_t); + supp_chan->length += + sizeof(IEEEtypes_SupportChan_Subband_t); + cmd_len += sizeof(IEEEtypes_SupportChan_Subband_t); + endian_convert_tlv_header_out(supp_chan); + } else if (strcmp(args[0], "SupportedRegulatoryClasses") == 0) { + /* Append a new TLV */ + reg_class = + (tlvbuf_RegulatoryClass_t *)(buffer + cmd_len); + tlv_len_reg_class = sizeof(tlvbuf_RegulatoryClass_t); + reg_class->tag = TLV_TYPE_REGULATORY_CLASSES; + cmd_len += tlv_len_reg_class; + } else if (strcmp(args[0], "CurrentRegulatoryClass") == 0) { + reg_class->regulatory_class.cur_regulatory_class = + atoi(args[1]); + reg_class->length = 1; + } else if (strcmp(args[0], "NumofRegulatoryClasses") == 0) { + num_of_regulatory_class = atoi(args[1]); + reg_class->length += num_of_regulatory_class; + cmd_len += num_of_regulatory_class; + endian_convert_tlv_header_out(reg_class); + } else if (strcmp(args[0], "ListOfRegulatoryClasses") == 0) { + for (i = 0; i < num_of_regulatory_class; i++) + reg_class->regulatory_class. + regulatory_classes_list[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "CountryInfo") == 0) { + /* Append a new TLV */ + domain = (tlvbuf_DomainParamSet_t *)(buffer + cmd_len); + domain->tag = TLV_TYPE_DOMAIN; + domain->length = sizeof(tlvbuf_DomainParamSet_t) + - TLVHEADER_LEN; + tlv_len_domain = sizeof(tlvbuf_DomainParamSet_t); + cmd_len += tlv_len_domain; + } else if (strcmp(args[0], "CountryString") == 0) { + strncpy(country, args[1] + 1, strlen(args[1]) - 2); + country[strlen(args[1]) - 2] = '\0'; + for (i = 1; (unsigned int)i < strlen(country) - 2; i++) { + if ((country[i] < 'A') || (country[i] > 'z')) { + printf("Invalid Country Code\n"); + goto done; + } + if (country[i] > 'Z') + country[i] = country[i] - 'a' + 'A'; + } + memset(domain->country_code, ' ', + sizeof(domain->country_code)); + memcpy(domain->country_code, country, strlen(country)); + } else if (strncmp(args[0], "FirstChannel", 12) == 0) { + domain->sub_band[no_of_sub_band].first_chan = + atoi(args[1]); + } else if (strncmp(args[0], "NumberofChannels", 16) == 0) { + domain->sub_band[no_of_sub_band].no_of_chan = + atoi(args[1]); + } else if (strncmp(args[0], "TxPower", 7) == 0) { + domain->sub_band[no_of_sub_band].max_tx_pwr = + atoi(args[1]); + no_of_sub_band++; + domain->length += sizeof(IEEEtypes_SubbandSet_t); + tlv_len_domain += sizeof(IEEEtypes_SubbandSet_t); + cmd_len += sizeof(IEEEtypes_SubbandSet_t); + endian_convert_tlv_header_out(domain); + } else if (strcmp(args[0], "VHTCapability") == 0) { + /* Append a new TLV */ + tlv_vht_cap = (tlvbuf_VHTCap_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_VHTCap_t); + tlv_vht_cap->tag = TLV_TYPE_VHT_CAP; + tlv_vht_cap->length = + sizeof(tlvbuf_VHTCap_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_vht_cap); + } else if (strcmp(args[0], "VHTCapabilityInfo") == 0) { + tlv_vht_cap->vht_cap.vht_cap_info = + (t_u32)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.vht_cap_info = + cpu_to_le16(tlv_vht_cap->vht_cap.vht_cap_info); + } else if (strcmp(args[0], "RxMCSMap") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + rx_mcs_map); + } else if (strcmp(args[0], "TxMCSMap") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + tx_mcs_map); + } else if (strcmp(args[0], "RxMaxRate") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + rx_max_rate); + } else if (strcmp(args[0], "TxMaxRate") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + tx_max_rate); + } else if (strcmp(args[0], "VHTOper") == 0) { + /* Append a new TLV */ + tlv_vht_oper = (tlvbuf_VHTOpra_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_VHTOpra_t); + tlv_vht_oper->tag = TLV_TYPE_VHT_OPER; + tlv_vht_oper->length = + sizeof(tlvbuf_VHTOpra_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_vht_oper); + } else if (strcmp(args[0], "ChanWidth") == 0) { + tlv_vht_oper->chan_width = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ChanCF1") == 0) { + tlv_vht_oper->chan_cf1 = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ChanCF2") == 0) { + tlv_vht_oper->chan_cf2 = (t_u16)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "BasicMCSMap") == 0) { + if ((arg_num - 1) != VHT_MCS_MAP_LEN) { + printf("Incorrect number of arguments for BasicMCSMap.\n"); + goto done; + } + for (i = 0; i < VHT_MCS_MAP_LEN; i++) + tlv_vht_oper->basic_mcs_map[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } + } + /* adjust for size of action and tlv_len, capInfo */ + param_buf->tlv_len = cmd_len - sizeof(tdls_setinfo); + + hexdump("tdls_setinfo", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS Info settings sucessfully set.\n"); + } else { + printf("ERR:Could not set TDLS info configuration.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_discovery + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_discovery(int argc, char *argv[]) +{ + tdls_discovery *param_buf = NULL; + tdls_discovery_resp *resp_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0, rssi = 0; + char *args[30] = { NULL }, *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0, buf_len = 0, resp_len = 0; + t_u8 *buffer = NULL, *raw = NULL; + IEEEtypes_Header_t *tlv = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_discovery \n"); + exit(1); + } + + cmd_len = sizeof(tdls_discovery); + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + buffer = (t_u8 *)malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, buf_len); + param_buf = (tdls_discovery *)buffer; + param_buf->action = ACTION_TDLS_DISCOVERY; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return MLAN_STATUS_FAILURE; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + if ((ret = + mac2raw(mac_addr, + peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_discovery", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + hexdump("tdls_response", buffer, 0x40, ' '); + printf("TDLS discovery done.\n"); + resp_buf = (tdls_discovery_resp *)buffer; + resp_len = resp_buf->payload_len; + printf("Response Length = %d\n", resp_len); + if (resp_len > 0) { + /* MAC */ + raw = resp_buf->peer_mac; + printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned int)raw[0], (unsigned int)raw[1], + (unsigned int)raw[2], (unsigned int)raw[3], + (unsigned int)raw[4], (unsigned int)raw[5]); + + /* RSSI, CapInfo */ + rssi = (int)(resp_buf->rssi); + if (rssi > 0x7f) + rssi = -(256 - rssi); + printf("\tRssi : %d dBm\n", rssi); + printf("\tCapInfo = 0x%02X\n", resp_buf->cap_info); + + resp_len -= ETH_ALEN + sizeof(resp_buf->rssi) + + sizeof(resp_buf->cap_info); + + /* TLVs */ + tlv = (IEEEtypes_Header_t *)&resp_buf->tlv_buffer; + while (resp_len > IEEE_HEADER_LEN) { + switch (tlv->element_id) { + case TLV_TYPE_RATES: + printf("\tRates : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_EXTENDED_SUPPORTED_RATES: + printf("\tExtended Rates : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_TYPE_QOSINFO: + printf("\tQosInfo "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_EXTCAP: + printf("\tExtended Cap "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_HT_CAP: + printf("\tHT Cap "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_HT_INFO: + printf("\tHT Info"); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_2040BSS_COEXISTENCE: + printf("\t2040 BSS Coex "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_RSN_IE: + printf("\tRSN IE "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_SUPPORTED_CHANNELS: + printf("\tSupported Channels "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_DOMAIN: + printf("\tDomain Info "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_LINK_IDENTIFIER: + printf("\tLink identifier : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_TIMEOUT_INTERVAL: + printf("\tTimeout interval : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_TYPE_REGULATORY_CLASSES: + printf("\t Regulatory classes : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + default: + printf("Unknown TLV\n"); + hexdump(NULL, ((t_u8 *)tlv), + IEEE_HEADER_LEN + tlv->len, + ' '); + break; + } + resp_len -= tlv->len + IEEE_HEADER_LEN; + tlv = (IEEEtypes_Header_t *)((t_u8 *)tlv + + tlv->len + + IEEE_HEADER_LEN); + } + } + + } else { + printf("ERR:Command response = Fail!\n"); + } +done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_setup + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_setup(int argc, char *argv[]) +{ + tdls_setup *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30] = { NULL }, *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_setup \n"); + exit(1); + } + + cmd_len = sizeof(tdls_setup); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_setup *) buffer; + param_buf->action = ACTION_TDLS_SETUP; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return MLAN_STATUS_FAILURE; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + if ((ret = + mac2raw(mac_addr, + peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "WaitTimems") == 0) { + param_buf->wait_time = (t_u32)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "KeyLifetime") == 0) { + param_buf->key_life_time = (t_u32)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_setup", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS setup request successful.\n"); + } else { + printf("ERR:TDLS setup request failed.\n"); + } + +done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_teardown + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_teardown(int argc, char *argv[]) +{ + tdls_teardown *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30] = { NULL }, *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_teardown \n"); + exit(1); + } + + cmd_len = sizeof(tdls_teardown); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_teardown *)buffer; + param_buf->action = ACTION_TDLS_TEARDOWN; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return MLAN_STATUS_FAILURE; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + if ((ret = + mac2raw(mac_addr, + peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "ReasonCode") == 0) { + param_buf->reason_code = (t_u16)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_teardown", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS teardown request successful.\n"); + } else { + printf("ERR:TDLS teardown request failed.\n"); + } + +done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_powermode + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_powermode(int argc, char *argv[]) +{ + tdls_powermode *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30] = { NULL }, *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_powermode \n"); + exit(1); + } + + cmd_len = sizeof(tdls_powermode); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_powermode *)buffer; + param_buf->action = ACTION_TDLS_POWER_MODE; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return MLAN_STATUS_FAILURE; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + if ((ret = + mac2raw(mac_addr, + peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "PowerMode") == 0) { + param_buf->power_mode = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->power_mode > 1) { + printf("ERR: Incorrect PowerMode value %s\n", + args[1]); + goto done; + } + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_powermode", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS powermode request successful.\n"); + } else { + printf("ERR:TDLS powermode request failed.\n"); + } + +done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_link_status + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_link_status(int argc, char *argv[]) +{ + int ret = 0; + tdls_link_status *param_buf = NULL; + tdls_link_status_resp *resp_buf = NULL; + t_u16 cmd_len = 0, buf_len = 0, resp_len = 0, curr_link_len = 0; + t_u8 no_of_links = 0, peer_mac[ETH_ALEN]; + t_u8 *buffer = NULL, *raw = NULL; + tdls_each_link_status *link_ptr = NULL; + + /* Check arguments */ + if (argc != 3 && argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_link_status [peer_mac_addr]\n"); + exit(1); + } + + cmd_len = sizeof(tdls_link_status); + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + buffer = (t_u8 *)malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, buf_len); + param_buf = (tdls_link_status *)buffer; + param_buf->action = ACTION_TDLS_LINK_STATUS; + + if (argc == 4) { + if ((ret = mac2raw(argv[3], peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret == + MAC_BROADCAST ? "Broadcast" : "Multicast"); + goto done; + } + if (memcmp(peer_mac, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)) { + memcpy(buffer + cmd_len, peer_mac, ETH_ALEN); + cmd_len += ETH_ALEN; + } + } + + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + hexdump("tdls_response", buffer, 0x60, ' '); + printf("TDLS Link Status - .\n"); + resp_buf = (tdls_link_status_resp *)buffer; + resp_len = resp_buf->payload_len; + printf("Response Length = %d\n", resp_len); + no_of_links = resp_buf->active_links; + printf("No of active links = %d\n", no_of_links); + resp_len--; + link_ptr = resp_buf->link_stats; + while (resp_len > 0 && no_of_links > 0) { + curr_link_len = 0; + /* MAC */ + raw = link_ptr->peer_mac; + printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned int)raw[0], (unsigned int)raw[1], + (unsigned int)raw[2], (unsigned int)raw[3], + (unsigned int)raw[4], (unsigned int)raw[5]); + + printf("\t %s initiated link.\n", + (link_ptr->link_flags & 0x01) ? "Self" : "Peer"); + printf("\t Security %s.\n", + (link_ptr-> + link_flags & 0x02) ? "Enabled" : "Disabled"); + printf("\t Self PS status = %s.\n", + (link_ptr-> + link_flags & 0x04) ? "Sleep" : "Active"); + printf("\t Peer PS status = %s.\n", + (link_ptr-> + link_flags & 0x08) ? "Sleep" : "Active"); + printf("\t Channel switch is %ssupported\n", + (link_ptr->link_flags & 0x10) ? "" : "NOT "); + printf("\t Current Channel %s\n", + (link_ptr->link_flags & 0x20) ? "off" : "base"); + + if (link_ptr->traffic_status) { + printf("\t Buffered traffic for"); + printf("%s", + (link_ptr-> + traffic_status & 0x01) ? "AC_BK, " : + ""); + printf("%s", + (link_ptr-> + traffic_status & 0x02) ? "AC_BE, " : + ""); + printf("%s", + (link_ptr-> + traffic_status & 0x04) ? "AC_VI, " : + ""); + printf("%s", + (link_ptr-> + traffic_status & 0x08) ? "AC_VO" : ""); + printf(".\n"); + } + printf("\t Successive Tx Failure count = %d\n", + link_ptr->tx_fail_count); + printf("\t Active channel number = %d\n", + link_ptr->active_channel); + printf("\t Last Data RSSI = %d dBm\n", + link_ptr->data_rssi_last); + printf("\t Last Data NF = %d dBm\n", + link_ptr->data_nf_last); + printf("\t Average Data RSSI = %d dBm\n", + link_ptr->data_rssi_avg); + printf("\t Average Data NF = %d dBm\n", + link_ptr->data_nf_avg); + printf("\t Tx data rate = %d Mbps\n", + link_ptr->u.final_data_rate); + + /* size of unsecure structure */ + curr_link_len = sizeof(tdls_each_link_status) - + (sizeof(t_u32) + sizeof(t_u8) + sizeof(t_u8)); + + if (link_ptr->link_flags & 0x02) { + /* security details */ + printf("\t Security Method = %s\n", + (link_ptr->security_method == + 1) ? "AES" : "None"); + printf("\t Key Lifetime = %d ms\n\t", + link_ptr->key_lifetime); + hexdump("Key", ((t_u8 *)link_ptr->key), + link_ptr->key_length, ' '); + curr_link_len += + sizeof(t_u32) + sizeof(t_u8) + + sizeof(t_u8) + + link_ptr->key_length; + } + resp_len -= curr_link_len; + link_ptr = + (tdls_each_link_status *)(((t_u8 *)link_ptr) + + curr_link_len); + printf(".\n"); + } + + } else { + printf("ERR:Command response = Fail!\n"); + } +done: + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_channel_swtich + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_channel_switch(int argc, char *argv[]) +{ + + tdls_channel_switch *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30] = { NULL }, *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_channel_switch \n"); + exit(1); + } + + cmd_len = sizeof(tdls_channel_switch); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_channel_switch *)buffer; + param_buf->action = ACTION_TDLS_INIT_CHAN_SWITCH; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return MLAN_STATUS_FAILURE; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + if ((ret = + mac2raw(mac_addr, + peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "Band") == 0) { + param_buf->band = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->band != BAND_BG + && param_buf->band != BAND_A) { + printf("ERR: Incorrect Band value %s\n", + args[1]); + goto done; + } + } else if (strcmp(args[0], "RegulatoryClass") == 0) { + param_buf->regulatory_class = + (t_u16)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "PrimaryChannel") == 0) { + param_buf->primary_channel = + (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->band == BAND_BG && + param_buf->primary_channel < MIN_BG_CHANNEL && + param_buf->primary_channel > MAX_BG_CHANNEL) { + printf("ERR: Incorrect Primary Channel value %s\n", args[1]); + goto done; + } else if (param_buf->band == BAND_A + && param_buf->primary_channel < MIN_A_CHANNEL + && param_buf->primary_channel > + MAX_A_CHANNEL) { + printf("ERR: Incorrect Primary Channel value %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "SecondaryChannelOffset") == 0) { + param_buf->secondary_channel_offset = + (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->secondary_channel_offset != 0 && + param_buf->secondary_channel_offset != + SECOND_CHANNEL_ABOVE && + param_buf->secondary_channel_offset != + SECOND_CHANNEL_BELOW) { + printf("ERR: Incorrect Secondary Channel Offset value %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "ChannelSwitchTime") == 0) { + param_buf->switch_time = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->switch_time == 0) { + printf("ERR: Incorrect Channel Switch time %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "ChannelSwitchTimeout") == 0) { + param_buf->switch_timeout = + (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->switch_timeout == 0) { + printf("ERR: Incorrect Channel Switch timeout %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "Periodicity") == 0) { + param_buf->periodicity = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->periodicity != NO_PERIODIC_SWITCH + && param_buf->periodicity != + ENABLE_PERIODIC_SWITCH) { + printf("ERR: Incorrect Periodicity value %s\n", + args[1]); + goto done; + } + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_channel_switch", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS channel switch request successful.\n"); + } else { + printf("ERR:TDLS channel switch request failed.\n"); + } + +done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief disable tdls_channel_swtich + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_disable_channel_switch(int argc, char *argv[]) +{ + + tdls_disable_cs *param_buf = NULL; + int ret = 0; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_disable_cs <0/1>\n"); + exit(1); + } + + cmd_len = sizeof(tdls_disable_cs); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_disable_cs *) buffer; + param_buf->action = ACTION_TDLS_CS_DISABLE; + + param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]); + if ((param_buf->data != 0) && (param_buf->data != 1)) { + printf("ERR:Incorrect arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_disable_cs <0/1>\n"); + goto done; + } + hexdump("tdls_disable_cs", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS disable channel switch successful.\n"); + } else { + printf("ERR:TDLS disable channel switch failed.\n"); + } + +done: + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_stop_channel_switch + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_stop_channel_switch(int argc, char *argv[]) +{ + tdls_stop_chan_switch *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30] = { NULL }, *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_stop_channel_switch \n"); + exit(1); + } + + cmd_len = sizeof(tdls_stop_chan_switch); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_stop_chan_switch *) buffer; + param_buf->action = ACTION_TDLS_STOP_CHAN_SWITCH; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return MLAN_STATUS_FAILURE; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + if ((ret = + mac2raw(mac_addr, + peer_mac)) != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_stop_channel_switch", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS stop channel switch successful.\n"); + } else { + printf("ERR:TDLS stop channel switch failed.\n"); + } + +done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_cs_params + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_cs_params(int argc, char *argv[]) +{ + tdls_cs_params *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30] = { NULL }, *pos = NULL; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_cs_params \n"); + exit(1); + } + + cmd_len = sizeof(tdls_cs_params); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_cs_params *) buffer; + param_buf->action = ACTION_TDLS_CS_PARAMS; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return MLAN_STATUS_FAILURE; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "UnitTime") == 0) { + param_buf->unit_time = (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ThresholdOtherLink") == 0) { + param_buf->threshold_otherlink = + (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ThresholdDirectLink") == 0) { + param_buf->threshold_directlink = + (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_cs_params", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS set channel switch parameters successful.\n"); + } else { + printf("ERR:TDLS set channel switch parameters failed.\n"); + } +done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_debug + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_debug(int argc, char *argv[]) +{ + int ret = 0; + tdls_debug *param_buf = NULL; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + t_u16 action = 0, value = 0; + + /* Check arguments */ + if (argc < 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug \n"); + exit(1); + } + + cmd_len = sizeof(tdls_debug); + + /* wrong_bss */ + if (!strcmp(argv[3], "wrong_bss")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_WRONG_BSS; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug wrong_bss <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* same link */ + else if (!strcmp(argv[3], "setup_existing_link")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_SETUP_SAME_LINK; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug setup_existing_link <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* fail_setup_confirm */ + else if (!strcmp(argv[3], "fail_setup_confirm")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_FAIL_SETUP_CONFIRM; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug fail_setup_confirm <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* setup prohibited */ + else if (!strcmp(argv[3], "setup_with_prohibited")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_SETUP_PROHIBITED; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug setup_with_prohibited <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* setup higher/lower mac */ + else if (!strcmp(argv[3], "higher_lower_mac")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_HIGHER_LOWER_MAC; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug higher_lower_mac <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* ignore key lifetime expiry */ + else if (!strcmp(argv[3], "ignore_key_expiry")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_IGNORE_KEY_EXPIRY; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug ignore_key_expiry <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* allow weak security */ + else if (!strcmp(argv[3], "allow_weak_security")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_ALLOW_WEAK_SECURITY; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug allow_weak_security <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* stop RX */ + else if (!strcmp(argv[3], "stop_rx")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_STOP_RX; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug stop_rx <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* Immediate return */ + else if (!strcmp(argv[3], "cs_im_return")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_CS_RET_IM; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanconfig mlanX tdls_debug cs_im_return <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } else { + printf("ERR:Incorrect command!\n"); + exit(1); + } + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + return -1; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_debug *)buffer; + param_buf->action = action; + memcpy(param_buf->data, &value, sizeof(value)); + + hexdump("tdls_debug", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS debug request successful.\n"); + } else { + printf("ERR:TDLS debug request failed.\n"); + } + + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Entry function for mlanconfig + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +main(int argc, char *argv[]) +{ + t_s32 cmd; + + if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { + fprintf(stdout, "Marvell mlanconfig version %s\n", + MLANCONFIG_VER); + exit(0); + } + if (argc < 3) { + fprintf(stderr, "Invalid number of parameters!\n"); + display_usage(); + exit(1); + } + + strncpy(dev_name, argv[1], IFNAMSIZ - 1); + + /* + * create a socket + */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "mlanconfig: Cannot open socket.\n"); + exit(1); + } + if (get_range() < 0) { + fprintf(stderr, "mlanconfig: Cannot get range.\n"); + close(sockfd); + exit(1); + } + switch ((cmd = findcommand(NELEMENTS(commands), commands, argv[2]))) { + case CMD_HOSTCMD: + process_host_cmd(argc, argv); + break; + case CMD_MEFCFG: + process_mef_cfg(argc, argv); + break; + case CMD_ARPFILTER: + process_arpfilter(argc, argv); + break; + case CMD_CFG_DATA: + process_cfg_data(argc, argv); + break; + case CMD_GET_SCAN_RSP: + process_getscantable(argc, argv); + break; + case CMD_SET_USER_SCAN: + process_setuserscan(argc, argv); + break; + case CMD_ADD_TS: + process_addts(argc, argv); + break; + case CMD_DEL_TS: + process_delts(argc, argv); + break; + case CMD_QCONFIG: + process_qconfig(argc, argv); + break; + case CMD_QSTATS: + process_qstats(argc, argv); + break; + case CMD_TS_STATUS: + process_wmm_ts_status(argc, argv); + break; + case CMD_WMM_QSTATUS: + process_wmm_qstatus(argc, argv); + break; + case CMD_REGRW: + process_regrdwr(argc, argv); + break; + case CMD_MEMRW: + process_memrdwr(argc, argv); + break; + case CMD_STA_CUSTOM_IE: + process_custom_ie(argc, argv); + break; + case CMD_STA_MGMT_FRAME_TX: + process_mgmt_frame_tx(argc, argv); + break; + case CMD_TDLS_CONF: + process_tdls_config(argc, argv); + break; + case CMD_TDLS_INFO: + process_tdls_setinfo(argc, argv); + break; + case CMD_TDLS_DISCOVERY: + process_tdls_discovery(argc, argv); + break; + case CMD_TDLS_SETUP: + process_tdls_setup(argc, argv); + break; + case CMD_TDLS_TEARDOWN: + process_tdls_teardown(argc, argv); + break; + case CMD_TDLS_POWERMODE: + process_tdls_powermode(argc, argv); + break; + case CMD_TDLS_LINK_STATUS: + process_tdls_link_status(argc, argv); + break; + case CMD_TDLS_CHANNEL_SWITCH: + process_tdls_channel_switch(argc, argv); + break; + case CMD_TDLS_STOP_CHAN_SWITCH: + process_tdls_stop_channel_switch(argc, argv); + break; + case CMD_TDLS_CS_PARAMS: + process_tdls_cs_params(argc, argv); + break; + case CMD_TDLS_CS_DISABLE: + process_tdls_disable_channel_switch(argc, argv); + break; + case CMD_TDLS_DEBUG: + process_tdls_debug(argc, argv); + break; + default: + fprintf(stderr, "Invalid command specified!\n"); + display_usage(); + close(sockfd); + exit(1); + } + + close(sockfd); + return MLAN_STATUS_SUCCESS; +} diff --git a/mwifiex_8997/mapp/mlanconfig/mlanconfig.h b/mwifiex_8997/mapp/mlanconfig/mlanconfig.h new file mode 100755 index 0000000..37bb1c2 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/mlanconfig.h @@ -0,0 +1,791 @@ +/** @file mlanconfig.h + * + * @brief This file contains definitions for application + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 11/26/2008: initial version +************************************************************************/ +#ifndef _MLANCONFIG_H_ +#define _MLANCONFIG_H_ + +/** Include header files */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#undef BIG_ENDIAN_SUPPORT +#endif + +/** Type definition: boolean */ +typedef enum { FALSE, TRUE } boolean; + +/** + * This macro specifies the attribute pack used for structure packing + */ +#ifndef __ATTRIB_PACK__ +#define __ATTRIB_PACK__ __attribute__((packed)) +#endif + +/** 16 bits byte swap */ +#define swap_byte_16(x) \ +((t_u16)((((t_u16)(x) & 0x00ffU) << 8) | \ + (((t_u16)(x) & 0xff00U) >> 8))) + +/** 32 bits byte swap */ +#define swap_byte_32(x) \ +((t_u32)((((t_u32)(x) & 0x000000ffUL) << 24) | \ + (((t_u32)(x) & 0x0000ff00UL) << 8) | \ + (((t_u32)(x) & 0x00ff0000UL) >> 8) | \ + (((t_u32)(x) & 0xff000000UL) >> 24))) + +/** Convert to correct endian format */ +#ifdef BIG_ENDIAN_SUPPORT +/** CPU to little-endian convert for 16-bit */ +#define cpu_to_le16(x) swap_byte_16(x) +/** CPU to little-endian convert for 32-bit */ +#define cpu_to_le32(x) swap_byte_32(x) +/** Little-endian to CPU convert for 16-bit */ +#define le16_to_cpu(x) swap_byte_16(x) +/** Little-endian to CPU convert for 32-bit */ +#define le32_to_cpu(x) swap_byte_32(x) +#else +/** Do nothing */ +#define cpu_to_le16(x) (x) +/** Do nothing */ +#define cpu_to_le32(x) (x) +/** Do nothing */ +#define le16_to_cpu(x) (x) +/** Do nothing */ +#define le32_to_cpu(x) (x) +#endif + +/** Character, 1 byte */ +typedef char t_s8; +/** Unsigned character, 1 byte */ +typedef unsigned char t_u8; + +/** Short integer */ +typedef signed short t_s16; +/** Unsigned short integer */ +typedef unsigned short t_u16; + +/** Integer */ +typedef signed int t_s32; +/** Unsigned integer */ +typedef unsigned int t_u32; + +/** Long long integer */ +typedef signed long long t_s64; +/** Unsigned long long integer */ +typedef unsigned long long t_u64; + +/** Void pointer (4-bytes) */ +typedef void t_void; + +/** Success */ +#define MLAN_STATUS_SUCCESS (0) +/** Failure */ +#define MLAN_STATUS_FAILURE (-1) + +t_s8 *mlan_config_get_line(FILE * fp, t_s8 *s, t_s32 size, int *line); +int get_priv_ioctl(char *ioctl_name, int *ioctl_val, int *subioctl_val); +int fparse_for_hex(FILE * fp, t_u8 *dst); + +/** + * Hex or Decimal to Integer + * @param num string to convert into decimal or hex + */ +#define A2HEXDECIMAL(num) \ + (strncasecmp("0x", (num), 2)?(unsigned int) strtoll((num),NULL,0):a2hex((num))) + +/** Convert character to integer */ +#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0')) + +/** Convert TLV header from little endian format to CPU format */ +#define endian_convert_tlv_header_in(x) \ + { \ + (x)->tag = le16_to_cpu((x)->tag); \ + (x)->length = le16_to_cpu((x)->length); \ + } + +/** Convert TLV header to little endian format from CPU format */ +#define endian_convert_tlv_header_out(x) \ + { \ + (x)->tag = cpu_to_le16((x)->tag); \ + (x)->length = cpu_to_le16((x)->length); \ + } +/** Private command ID to pass custom IE list */ +#define CUSTOM_IE_CFG (SIOCDEVPRIVATE + 13) +/* TLV Definitions */ +/** TLV header */ +#define TLVHEADER /** Tag */ \ + t_u16 tag; \ + /** Length */ \ + t_u16 length + +/** Maximum IE buffer length */ +#define MAX_IE_BUFFER_LEN 256 + +/** TLV: Management IE list */ +#define MRVL_MGMT_IE_LIST_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0x69) //0x0169 + +/** TLV: Max Management IE */ +#define MRVL_MAX_MGMT_IE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0xaa) //0x01aa + +/** custom IE info */ +typedef struct _custom_ie_info { + /** size of buffer */ + t_u16 buf_size; + /** no of buffers of buf_size */ + t_u16 buf_count; +} __ATTRIB_PACK__ custom_ie_info; + +/** TLV buffer : custom IE */ +typedef struct _tlvbuf_max_mgmt_ie { + /** Header */ + TLVHEADER; + /** No of tuples */ + t_u16 count; + /** custom IE info tuples */ + custom_ie_info info[0]; +} __ATTRIB_PACK__ tlvbuf_max_mgmt_ie; + +/** custom IE */ +typedef struct _custom_ie { + /** IE Index */ + t_u16 ie_index; + /** Mgmt Subtype Mask */ + t_u16 mgmt_subtype_mask; + /** IE Length */ + t_u16 ie_length; + /** IE buffer */ + t_u8 ie_buffer[0]; +} __ATTRIB_PACK__ custom_ie; + +/** TLV buffer : custom IE */ +typedef struct _tlvbuf_custom_ie { + /** Header */ + TLVHEADER; + /** custom IE data */ + custom_ie ie_data[0]; +} __ATTRIB_PACK__ tlvbuf_custom_ie; + +/** Maximum length of lines in configuration file */ +#define MAX_CONFIG_LINE 1024 +/** Ethernet address length */ +#define ETH_ALEN 6 +/** MAC BROADCAST */ +#define MAC_BROADCAST 0x1FF +/** MAC MULTICAST */ +#define MAC_MULTICAST 0x1FE + +/** pkt_header */ +typedef struct _pkt_header { + /** pkt_len */ + t_u32 pkt_len; + /** pkt_type */ + t_u32 TxPktType; + /** tx control */ + t_u32 TxControl; +} pkt_header; + +/** wlan_802_11_header packet from FW with length */ +typedef struct _wlan_mgmt_frame_tx { + /** Packet Length */ + t_u16 frm_len; + /** Frame Control */ + t_u16 frm_ctl; + /** Duration ID */ + t_u16 duration_id; + /** Address1 */ + t_u8 addr1[ETH_ALEN]; + /** Address2 */ + t_u8 addr2[ETH_ALEN]; + /** Address3 */ + t_u8 addr3[ETH_ALEN]; + /** Sequence Control */ + t_u16 seq_ctl; + /** Address4 */ + t_u8 addr4[ETH_ALEN]; + /** Frame payload */ + t_u8 payload[0]; +} __ATTRIB_PACK__ wlan_mgmt_frame_tx; + +/** frame tx ioctl number */ +#define FRAME_TX_IOCTL (SIOCDEVPRIVATE + 12) + +/** band BG */ +#define BAND_BG 0 +/** band A */ +#define BAND_A 1 +/** secondary channel is above */ +#define SECOND_CHANNEL_ABOVE 0x1 +/** secondary channel is below */ +#define SECOND_CHANNEL_BELOW 0x3 +/** NO PERIODIC SWITCH */ +#define NO_PERIODIC_SWITCH 0 +/** Enable periodic channel switch */ +#define ENABLE_PERIODIC_SWITCH 1 +/** Min channel value for BG band */ +#define MIN_BG_CHANNEL 1 +/** Max channel value for BG band */ +#define MAX_BG_CHANNEL 14 +/** Max channel value for A band */ +#define MIN_A_CHANNEL 36 +/** Max channel value for A band */ +#define MAX_A_CHANNEL 252 + +/** Host Command ioctl number */ +#define TDLS_IOCTL (SIOCDEVPRIVATE + 5) +/** TDLS action definitions */ +/** Action ID for TDLS config */ +#define ACTION_TDLS_CONFIG 0x0000 +/** Action ID for TDLS setinfo request */ +#define ACTION_TDLS_SETINFO 0x0001 +/** Action ID for TDLS Discovery request */ +#define ACTION_TDLS_DISCOVERY 0x0002 +/** Action ID for TDLS setup request */ +#define ACTION_TDLS_SETUP 0x0003 +/** Action ID for TDLS Teardown request */ +#define ACTION_TDLS_TEARDOWN 0x0004 +/** Action ID for TDLS power mode */ +#define ACTION_TDLS_POWER_MODE 0x0005 +/**Action ID for init TDLS Channel Switch*/ +#define ACTION_TDLS_INIT_CHAN_SWITCH 0x06 +/** Action ID for stop TDLS Channel Switch */ +#define ACTION_TDLS_STOP_CHAN_SWITCH 0x07 +/** Action ID for configure CS related parameters */ +#define ACTION_TDLS_CS_PARAMS 0x08 +/** Action ID for TDLS Disable Channel switch */ +#define ACTION_TDLS_CS_DISABLE 0x09 +/** Action ID for TDLS Link status */ +#define ACTION_TDLS_LINK_STATUS 0x000A +/** Action ID for TDLS CS immediate return */ +#define ACTION_TDLS_DEBUG_CS_RET_IM 0xFFF7 +/** Action ID for TDLS Stop RX */ +#define ACTION_TDLS_DEBUG_STOP_RX 0xFFF8 +/** Action ID for TDLS Allow weak security */ +#define ACTION_TDLS_DEBUG_ALLOW_WEAK_SECURITY 0xFFF9 +/** Action ID for TDLS Ignore key lifetime expiry */ +#define ACTION_TDLS_DEBUG_IGNORE_KEY_EXPIRY 0xFFFA +/** Action ID for TDLS Higher/Lower mac Test */ +#define ACTION_TDLS_DEBUG_HIGHER_LOWER_MAC 0xFFFB +/** Action ID for TDLS Prohibited Test */ +#define ACTION_TDLS_DEBUG_SETUP_PROHIBITED 0xFFFC +/** Action ID for TDLS Existing link Test */ +#define ACTION_TDLS_DEBUG_SETUP_SAME_LINK 0xFFFD +/** Action ID for TDLS Fail Setup Confirm */ +#define ACTION_TDLS_DEBUG_FAIL_SETUP_CONFIRM 0xFFFE +/** Action ID for TDLS WRONG BSS Test */ +#define ACTION_TDLS_DEBUG_WRONG_BSS 0xFFFF + +/** TLV type : Rates */ +#define TLV_TYPE_RATES 0x0001 +/** TLV type : Domain */ +#define TLV_TYPE_DOMAIN 0x0007 +/** TLV type : Supported channels */ +#define TLV_TYPE_SUPPORTED_CHANNELS 0x0024 +/** TLV type : HT Capabilities */ +#define TLV_TYPE_HT_CAP 0x002d +/** TLV type : Qos Info */ +#define TLV_TYPE_QOSINFO 0x002e +/** TLV type : RSN IE */ +#define TLV_TYPE_RSN_IE 0x0030 +/** TLV type : extended supported rates */ +#define TLV_EXTENDED_SUPPORTED_RATES 0x0032 +/** TLV type : timeout interval */ +#define TLV_TIMEOUT_INTERVAL 0x0038 +/** TLV type : Regulatory classes */ +#define TLV_TYPE_REGULATORY_CLASSES 0x003b +/** TLV type : HT Information */ +#define TLV_TYPE_HT_INFO 0x003d +/** TLV type : 20/40 BSS Coexistence */ +#define TLV_TYPE_2040BSS_COEXISTENCE 0x0048 +/** TLv Type : Link identifier */ +#define TLV_LINK_IDENTIFIER 0x0065 +/** TLV type : Extended capabilities */ +#define TLV_TYPE_EXTCAP 0x007f + +/** TLV type : VHT capabilities */ +#define TLV_TYPE_VHT_CAP 0x00BF +/** TLV type : VHT operations */ +#define TLV_TYPE_VHT_OPER 0x00C0 +/** Length of Basic MCS MAP */ +#define VHT_MCS_MAP_LEN 2 + +/** Country code length */ +#define COUNTRY_CODE_LEN 3 +/** Length of Group Cipher Suite */ +#define GROUP_CIPHER_SUITE_LEN 4 +/** Length of Pairwise Cipher Suite */ +#define PAIRWISE_CIPHER_SUITE_LEN 4 +/** Length of AKM Suite */ +#define AKM_SUITE_LEN 4 +/** PMKID length */ +#define PMKID_LEN 16 +/** Maximum number of pairwise_cipher_suite */ +#define MAX_PAIRWISE_CIPHER_SUITE_COUNT 2 +/** Maximum number of AKM suite */ +#define MAX_AKM_SUITE_COUNT 2 +/** Maximum number of PMKID list count */ +#define MAX_PMKID_COUNT 2 +/** Length of MCS set */ +#define MCS_SET_LEN 16 +/** Version in RSN IE */ +#define VERSION_RSN_IE 0x0001 + +/** tdls setinfo */ +typedef struct _tdls_setinfo { + /** Action */ + t_u16 action; + /** (TLV + capInfo) length */ + t_u16 tlv_len; + /** Capability Info */ + t_u16 cap_info; + /** tdls info */ + t_u8 tlv_buffer[0]; +} __ATTRIB_PACK__ tdls_setinfo; + +/** tdls discovery */ +typedef struct _tdls_discovery { + /** Action */ + t_u16 action; + /** Peer MAC address */ + t_u8 peer_mac[ETH_ALEN]; +} __ATTRIB_PACK__ tdls_discovery; + +/** tdls link status */ +typedef struct _tdls_links_status { + /** Action */ + t_u16 action; +} __ATTRIB_PACK__ tdls_link_status; + +/** tdls discovery response */ +typedef struct _tdls_discovery_resp { + /** Action */ + t_u16 action; + /** payload length */ + t_u16 payload_len; + /** peer mac Address */ + t_u8 peer_mac[ETH_ALEN]; + /** RSSI */ + signed char rssi; + /** Cap Info */ + t_u16 cap_info; + /** TLV buffer */ + t_u8 tlv_buffer[0]; +} __ATTRIB_PACK__ tdls_discovery_resp; + +/** tdls each link rate information */ +typedef struct _tdls_link_rate_info { + /** Tx Data Rate */ + t_u8 tx_data_rate; + /** Tx Rate HT info*/ + t_u8 tx_rate_htinfo; +} __ATTRIB_PACK__ tdls_link_rate_info; + +/** tdls each link status */ +typedef struct _tdls_each_link_status { + /** peer mac Address */ + t_u8 peer_mac[ETH_ALEN]; + /** Link Flags */ + t_u8 link_flags; + /** Traffic Status */ + t_u8 traffic_status; + /** Tx Failure Count */ + t_u8 tx_fail_count; + /** Channel Number */ + t_u32 active_channel; + /** Last Data RSSI in dBm */ + t_s16 data_rssi_last; + /** Last Data NF in dBm */ + t_s16 data_nf_last; + /** AVG DATA RSSI in dBm */ + t_s16 data_rssi_avg; + /** AVG DATA NF in dBm */ + t_s16 data_nf_avg; + union { + /** tdls rate info */ + tdls_link_rate_info rate_info; + /** final rate value*/ + t_u16 final_data_rate; + } u; + /** Security Method */ + t_u8 security_method; + /** Key Lifetime */ + t_u32 key_lifetime; + /** Key Length */ + t_u8 key_length; + /** actual key */ + t_u8 key[0]; +} __ATTRIB_PACK__ tdls_each_link_status; + +/** tdls link status response */ +typedef struct _tdls_link_status_resp { + /** Action */ + t_u16 action; + /** payload length */ + t_u16 payload_len; + /** number of links */ + t_u8 active_links; + /** structure for link status */ + tdls_each_link_status link_stats[1]; +} __ATTRIB_PACK__ tdls_link_status_resp; + +/** tdls setup */ +typedef struct _tdls_setup { + /** Action */ + t_u16 action; + /** Peer MAC address */ + t_u8 peer_mac[ETH_ALEN]; + /** Time to wait for response from peer*/ + t_u32 wait_time; + /** Key Life Time */ + t_u32 key_life_time; +} __ATTRIB_PACK__ tdls_setup; + +/** tdls tear down */ +typedef struct _tdls_tear_down { + /** Action */ + t_u16 action; + /** Peer MAC address */ + t_u8 peer_mac[ETH_ALEN]; + /** Reason code */ + t_u16 reason_code; +} __ATTRIB_PACK__ tdls_teardown; + +/** tdls power mode */ +typedef struct _tdls_power_mode { + /** Action */ + t_u16 action; + /** Peer MAC address */ + t_u8 peer_mac[ETH_ALEN]; + /** Power mode */ + t_u16 power_mode; +} __ATTRIB_PACK__ tdls_powermode; + +/** tdls channel switch info */ +typedef struct _tdls_channel_switch { + /** Action */ + t_u16 action; + /** peer mac Address */ + t_u8 peer_mac[ETH_ALEN]; + /** Channel Switch primary channel no */ + t_u8 primary_channel; + /** Channel Switch secondary channel offset */ + t_u8 secondary_channel_offset; + /** Channel Switch Band */ + t_u8 band; + /** Channel Switch time*/ + t_u16 switch_time; + /** Channel Switch timeout*/ + t_u16 switch_timeout; + /** Channel Regulatory class*/ + t_u8 regulatory_class; + /** Channel Switch periodicity*/ + t_u8 periodicity; +} __ATTRIB_PACK__ tdls_channel_switch; + +/** tdls stop channel switch */ +typedef struct _tdls_stop_chan_switch { + /** Action */ + t_u16 action; + /** Peer MAC address */ + t_u8 peer_mac[ETH_ALEN]; +} __ATTRIB_PACK__ tdls_stop_chan_switch; + +/** tdls disable channel switch */ +typedef struct _tdls_disable_cs { + /** Action */ + t_u16 action; + /** Data*/ + t_u16 data; +} __ATTRIB_PACK__ tdls_disable_cs, tdls_config; + +/** tdls channel switch parameters */ +typedef struct _tdls_cs_params { + /** Action */ + t_u16 action; + /** unit time, multiples of 10ms */ + t_u8 unit_time; + /** threshold for other link */ + t_u8 threshold_otherlink; + /** threshold for direct link */ + t_u8 threshold_directlink; +} __ATTRIB_PACK__ tdls_cs_params; + +/** tdls debug */ +typedef struct _tdls_debug { + /** Action */ + t_u16 action; + /** Data */ + t_u8 data[0]; +} __ATTRIB_PACK__ tdls_debug; + +/** TLV header */ +#define TLVHEADER /** Tag */ \ + t_u16 tag; \ + /** Length */ \ + t_u16 length + +/** Length of TLV header */ +#define TLVHEADER_LEN 4 + +/** Data structure for subband set */ +typedef struct _IEEEtypes_SubbandSet_t { + /** First channel */ + t_u8 first_chan; + /** Number of channels */ + t_u8 no_of_chan; + /** Maximum Tx power */ + t_u8 max_tx_pwr; +} __ATTRIB_PACK__ IEEEtypes_SubbandSet_t, *pIEEEtypes_SubbandSet_t; + +/** tlvbuf_DomainParamSet_t */ +typedef struct _tlvbuf_DomainParamSet { + /** Header */ + TLVHEADER; + /** Country code */ + t_u8 country_code[COUNTRY_CODE_LEN]; + /** Set of subbands */ + IEEEtypes_SubbandSet_t sub_band[0]; +} __ATTRIB_PACK__ tlvbuf_DomainParamSet_t; + +/** Data structure of WMM QoS information */ +typedef struct _IEEEtypes_WmmQosInfo_t { +#ifdef BIG_ENDIAN_SUPPORT + /** QoS UAPSD */ + t_u8 qos_uapsd:1; + /** Reserved */ + t_u8 reserved:3; + /** Parameter set count */ + t_u8 para_set_count:4; +#else + /** Parameter set count */ + t_u8 para_set_count:4; + /** Reserved */ + t_u8 reserved:3; + /** QoS UAPSD */ + t_u8 qos_uapsd:1; +#endif /* BIG_ENDIAN_SUPPORT */ +} __ATTRIB_PACK__ IEEEtypes_WmmQosInfo_t; + +/** Qos Info TLV */ +typedef struct _tlvbuf_QosInfo_t { + /** Header */ + TLVHEADER; + /** QosInfo */ + union { + /** QosInfo bitfield */ + IEEEtypes_WmmQosInfo_t qos_info; + /** QosInfo byte */ + t_u8 qos_info_byte; + } u; +} __ATTRIB_PACK__ tlvbuf_QosInfo_t; + +/** HT Capabilities Data */ +typedef struct _HTCap_t { + /** HT Capabilities Info field */ + t_u16 ht_cap_info; + /** A-MPDU Parameters field */ + t_u8 ampdu_param; + /** Supported MCS Set field */ + t_u8 supported_mcs_set[16]; + /** HT Extended Capabilities field */ + t_u16 ht_ext_cap; + /** Transmit Beamforming Capabilities field */ + t_u32 tx_bf_cap; + /** Antenna Selection Capability field */ + t_u8 asel; +} __ATTRIB_PACK__ HTCap_t, *pHTCap_t; + +/** HT Information Data */ +typedef struct _HTInfo_t { + /** Primary channel */ + t_u8 pri_chan; + /** Field 2 */ + t_u8 field2; + /** Field 3 */ + t_u16 field3; + /** Field 4 */ + t_u16 field4; + /** Bitmap indicating MCSs supported by all HT STAs in the BSS */ + t_u8 basic_mcs_set[16]; +} __ATTRIB_PACK__ HTInfo_t, *pHTInfo_t; + +/** 20/40 BSS Coexistence Data */ +typedef struct _BSSCo2040_t { + /** 20/40 BSS Coexistence value */ + t_u8 bss_co_2040_value; +} __ATTRIB_PACK__ BSSCo2040_t, *pBSSCo2040_t; + +/** HT Capabilities element */ +typedef struct _tlvbuf_HTCap_t { + /** Header */ + TLVHEADER; + /** HTCap struct */ + HTCap_t ht_cap; +} __ATTRIB_PACK__ tlvbuf_HTCap_t; + +/** HT Information element */ +typedef struct _tlvbuf_HTInfo_t { + /** Header */ + TLVHEADER; + + /** HTInfo struct */ + HTInfo_t ht_info; +} __ATTRIB_PACK__ tlvbuf_HTInfo_t; + +/** VHT MCS rate set field, refer to 802.11ac */ +typedef struct _VHT_MCS_set { + t_u16 rx_mcs_map; + t_u16 rx_max_rate; /* bit 29-31 reserved */ + t_u16 tx_mcs_map; + t_u16 tx_max_rate; /* bit 61-63 reserved */ +} __ATTRIB_PACK__ VHT_MCS_set_t, *pVHT_MCS_set_t; + +typedef struct _VHT_capa { + t_u32 vht_cap_info; + VHT_MCS_set_t mcs_sets; +} __ATTRIB_PACK__ VHT_capa_t, *pVHT_capa_t; + +/** VHT Capabilities IE */ +typedef struct _IEEEtypes_VHTCap_t { + /** Header */ + TLVHEADER; + /** VHTInfo struct */ + VHT_capa_t vht_cap; +} __ATTRIB_PACK__ tlvbuf_VHTCap_t, *ptlvbuf_VHTCap_t; + +/** VHT Operations IE */ +typedef struct _IEEEtypes_VHTOprat_t { + /** Header */ + TLVHEADER; + /** VHTOpra struct */ + t_u8 chan_width; + t_u8 chan_cf1; + t_u8 chan_cf2; + /** Basic MCS set map, each 2 bits stands for a Nss */ + t_u8 basic_mcs_map[VHT_MCS_MAP_LEN]; +} __ATTRIB_PACK__ tlvbuf_VHTOpra_t, *ptlvbuf_VHTOpra_t; + +/** 20/40 BSS Coexistence element */ +typedef struct _tlvbuf_2040BSSCo_t { + /** Header */ + TLVHEADER; + + /** BSSCo2040_t struct */ + BSSCo2040_t bss_co_2040; +} __ATTRIB_PACK__ tlvbuf_2040BSSCo_t; + +/** Extended Capabilities element */ +typedef struct _tlvbuf_ExtCap_t { + /** Header */ + TLVHEADER; + /** ExtCap_t struct */ + t_u8 ext_cap[0]; +} __ATTRIB_PACK__ tlvbuf_ExtCap_t; + +/** tlvbuf_RatesParamSet_t */ +typedef struct _tlvbuf_RatesParamSet_t { + /** Header */ + TLVHEADER; + /** Rates */ + t_u8 rates[0]; +} __ATTRIB_PACK__ tlvbuf_RatesParamSet_t; + +/* IEEE Supported Channel sub-band description (7.3.2.19) */ +/* Sub-band description used in the supported channels element. */ +typedef struct _IEEEtypes_SupportChan_Subband_t { + t_u8 start_chan;/**< Starting channel in the subband */ + t_u8 num_chans; /**< Number of channels in the subband */ + +} __ATTRIB_PACK__ IEEEtypes_SupportChan_Subband_t; + +/* IEEE Supported Channel element (7.3.2.19) */ +/** + * Sent in association requests. Details the sub-bands and number + * of channels supported in each subband + */ +typedef struct _tlvbuf_SupportedChannels_t { + /** Header */ + TLVHEADER; + /**< IEEE Element ID = 36 */ + /** Configured sub-bands information in the element */ + IEEEtypes_SupportChan_Subband_t subband[0]; +} __ATTRIB_PACK__ tlvbuf_SupportedChannels_t; + +/* IEEE Supported Regulatory Classes description (7.3.2.54) */ +typedef struct _IEEEtypes_RegulatoryClass_t { + /** current regulatory class */ + t_u8 cur_regulatory_class; + /** supported regulatory class list */ + t_u8 regulatory_classes_list[0]; + +} __ATTRIB_PACK__ IEEEtypes_RegulatoryClass_t; + +/* IEEE Supported Regulatory Classes TLV (7.3.2.54) */ +typedef struct _tlvbuf_RegulatoryClass_t { + /** Header */ + TLVHEADER; + /**< IEEE Element ID = 59 */ + /** supported regulatory class */ + IEEEtypes_RegulatoryClass_t regulatory_class; +} __ATTRIB_PACK__ tlvbuf_RegulatoryClass_t; + +/** tlvbuf_RsnParamSet_t */ +typedef struct _tlvbuf_RsnParamSet_t { + /** Header */ + TLVHEADER; + /** Version */ + t_u16 version; + /** Group Cipher Suite */ + t_u8 group_cipher_suite[4]; + /** Pairwise Cipher Suite count */ + t_u16 pairwise_cipher_count; + /** Pairwise Cipher Suite */ + t_u8 pairwise_cipher_suite[0]; + /** AKM Suite Sount */ + t_u16 akm_suite_count; + /** AKM Suite */ + t_u8 akm_suite[0]; + /** RSN Capability */ + t_u16 rsn_capability; + /** PMKID Count */ + t_u16 pmkid_count; + /** PMKID list */ + t_u8 pmkid_list[0]; +} __ATTRIB_PACK__ tlvbuf_RsnParamSet_t; + +extern t_s32 sockfd; /**< socket */ +extern t_s8 dev_name[IFNAMSIZ + 1]; /**< device name */ + +#endif /* _MLANCONFIG_H_ */ diff --git a/mwifiex_8997/mapp/mlanconfig/mlanhostcmd.c b/mwifiex_8997/mapp/mlanconfig/mlanhostcmd.c new file mode 100755 index 0000000..2e1fb11 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/mlanhostcmd.c @@ -0,0 +1,951 @@ +/** @file mlanhostcmd.c + * + * @brief This file contains mlanconfig helper functions + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 11/26/2008: initial version +************************************************************************/ + +#include "mlanconfig.h" +#include "mlanhostcmd.h" + +#ifndef MIN +/** Find minimum value */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ +/** + * @brief get hostcmd data + * + * @param ln A pointer to line number + * @param buf A pointer to hostcmd data + * @param size A pointer to the return size of hostcmd buffer + * @return MLAN_STATUS_SUCCESS + */ +static int +mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size) +{ + t_s32 errors = 0, i; + t_s8 line[512], *pos, *pos1, *pos2, *pos3; + t_u16 len; + + while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) { + (*ln)++; + if (strcmp(pos, "}") == 0) { + break; + } + + pos1 = strchr(pos, ':'); + if (pos1 == NULL) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos1++ = '\0'; + + pos2 = strchr(pos1, '='); + if (pos2 == NULL) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos2++ = '\0'; + + len = a2hex_or_atoi(pos1); + if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + + *size += len; + + if (*pos2 == '"') { + pos2++; + if ((pos3 = strchr(pos2, '"')) == NULL) { + printf("Line %d: invalid quotation '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos3 = '\0'; + memset(buf, 0, len); + memmove(buf, pos2, MIN(strlen(pos2), len)); + buf += len; + } else if (*pos2 == '\'') { + pos2++; + if ((pos3 = strchr(pos2, '\'')) == NULL) { + printf("Line %d: invalid quotation '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos3 = ','; + for (i = 0; i < len; i++) { + if ((pos3 = strchr(pos2, ',')) != NULL) { + *pos3 = '\0'; + *buf++ = (t_u8)a2hex_or_atoi(pos2); + pos2 = pos3 + 1; + } else + *buf++ = 0; + } + } else if (*pos2 == '{') { + t_u16 tlvlen = 0, tmp_tlvlen; + mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen); + tmp_tlvlen = tlvlen; + while (len--) { + *buf++ = (t_u8)(tmp_tlvlen & 0xff); + tmp_tlvlen >>= 8; + } + *size += tlvlen; + buf += tlvlen; + } else { + t_u32 value = a2hex_or_atoi(pos2); + while (len--) { + *buf++ = (t_u8)(value & 0xff); + value >>= 8; + } + } + } + return MLAN_STATUS_SUCCESS; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief convert char to hex integer + * + * @param chr char to convert + * @return hex integer or 0 + */ +int +hexval(t_s32 chr) +{ + if (chr >= '0' && chr <= '9') + return chr - '0'; + if (chr >= 'A' && chr <= 'F') + return chr - 'A' + 10; + if (chr >= 'a' && chr <= 'f') + return chr - 'a' + 10; + + return 0; +} + +/** + * @brief Hump hex data + * + * @param prompt A pointer prompt buffer + * @param p A pointer to data buffer + * @param len the len of data buffer + * @param delim delim char + * @return hex integer + */ +t_void +hexdump(t_s8 *prompt, t_void *p, t_s32 len, t_s8 delim) +{ + t_s32 i; + t_u8 *s = p; + + if (prompt) { + printf("%s: len=%d\n", prompt, (int)len); + } + for (i = 0; i < len; i++) { + if (i != len - 1) + printf("%02x%c", *s++, delim); + else + printf("%02x\n", *s); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); +} + +/** + * @brief convert char to hex integer + * + * @param chr char + * @return hex integer + */ +t_u8 +hexc2bin(t_s8 chr) +{ + if (chr >= '0' && chr <= '9') + chr -= '0'; + else if (chr >= 'A' && chr <= 'F') + chr -= ('A' - 10); + else if (chr >= 'a' && chr <= 'f') + chr -= ('a' - 10); + + return chr; +} + +/** + * @brief convert string to hex integer + * + * @param s A pointer string buffer + * @return hex integer + */ +t_u32 +a2hex(t_s8 *s) +{ + t_u32 val = 0; + + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + + while (*s && isxdigit(*s)) { + val = (val << 4) + hexc2bin(*s++); + } + + return val; +} + +/* + * @brief convert String to integer + * + * @param value A pointer to string + * @return integer + */ +t_u32 +a2hex_or_atoi(t_s8 *value) +{ + if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) { + return a2hex(value + 2); + } else if (isdigit(*value)) { + return atoi(value); + } else { + return *value; + } +} + +/** + * @brief convert string to hex + * + * @param ptr A pointer to data buffer + * @param chr A pointer to return integer + * @return A pointer to next data field + */ +t_s8 * +convert2hex(t_s8 *ptr, t_u8 *chr) +{ + t_u8 val; + + for (val = 0; *ptr && isxdigit(*ptr); ptr++) { + val = (val * 16) + hexval(*ptr); + } + + *chr = val; + + return ptr; +} + +/** + * @brief Check the Hex String + * @param s A pointer to the string + * @return MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString + */ +int +ishexstring(t_s8 *s) +{ + int ret = MLAN_STATUS_FAILURE; + t_s32 tmp; + + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + while (*s) { + tmp = toupper(*s); + if (((tmp >= 'A') && (tmp <= 'F')) || + ((tmp >= '0') && (tmp <= '9'))) { + ret = MLAN_STATUS_SUCCESS; + } else { + ret = MLAN_STATUS_FAILURE; + break; + } + s++; + } + + return ret; +} + +/** + * @brief Convert String to Integer + * @param buf A pointer to the string + * @return Integer + */ +int +atoval(t_s8 *buf) +{ + if (!strncasecmp(buf, "0x", 2)) + return a2hex(buf + 2); + else if (!ishexstring(buf)) + return a2hex(buf); + else + return atoi(buf); +} + +/** + * @brief Prepare host-command buffer + * @param fp File handler + * @param cmd_name Command name + * @param buf A pointer to comand buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf) +{ + t_s8 line[256], cmdname[256], *pos, cmdcode[10]; + HostCmd_DS_GEN *hostcmd; + int ln = 0; + int cmdname_found = 0, cmdcode_found = 0; + + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + hostcmd = (HostCmd_DS_GEN *)buf; + hostcmd->command = 0xffff; + + snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name); + cmdname_found = 0; + while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { + if (strcmp(pos, cmdname) == 0) { + cmdname_found = 1; + snprintf(cmdcode, sizeof(cmdcode), "CmdCode="); + cmdcode_found = 0; + while ((pos = + mlan_config_get_line(fp, line, sizeof(line), + &ln))) { + if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) { + cmdcode_found = 1; + hostcmd->command = + a2hex_or_atoi(pos + + strlen(cmdcode)); + hostcmd->size = S_DS_GEN; + mlan_get_hostcmd_data(fp, &ln, + buf + + hostcmd->size, + &hostcmd->size); + break; + } + } + if (!cmdcode_found) { + fprintf(stderr, + "mlanconfig: CmdCode not found in conf file\n"); + return MLAN_STATUS_FAILURE; + } + break; + } + } + + if (!cmdname_found) { + fprintf(stderr, + "mlanconfig: cmdname '%s' is not found in conf file\n", + cmd_name); + return MLAN_STATUS_FAILURE; + } + + hostcmd->seq_num = 0; + hostcmd->result = 0; + hostcmd->command = cpu_to_le16(hostcmd->command); + hostcmd->size = cpu_to_le16(hostcmd->size); + return MLAN_STATUS_SUCCESS; +} + +/** Config data header length */ +#define CFG_DATA_HEADER_LEN 6 + +/** + * @brief Prepare cfg-data buffer + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param fp File handler + * @param buf A pointer to comand buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf) +{ + int ln = 0, type; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_802_11_CFG_DATA *pcfg_data; + + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + hostcmd = (HostCmd_DS_GEN *)buf; + hostcmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); + pcfg_data = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN); + pcfg_data->action = + (argc == 4) ? HostCmd_ACT_GEN_GET : HostCmd_ACT_GEN_SET; + type = atoi(argv[3]); + if ((type < 1) || (type > 2)) { + fprintf(stderr, "mlanconfig: Invalid register type\n"); + return MLAN_STATUS_FAILURE; + } else { + pcfg_data->type = type; + } + if (argc == 5) { + ln = fparse_for_hex(fp, pcfg_data->data); + } + pcfg_data->data_len = ln; + hostcmd->size = + cpu_to_le16(pcfg_data->data_len + S_DS_GEN + + CFG_DATA_HEADER_LEN); + pcfg_data->data_len = cpu_to_le16(pcfg_data->data_len); + pcfg_data->type = cpu_to_le16(pcfg_data->type); + pcfg_data->action = cpu_to_le16(pcfg_data->action); + + hostcmd->seq_num = 0; + hostcmd->result = 0; + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process host_cmd response + * @param buf A pointer to the response buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_host_cmd_resp(t_u8 *buf) +{ + HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf; + int ret = MLAN_STATUS_SUCCESS; + + hostcmd->command = le16_to_cpu(hostcmd->command); + hostcmd->size = le16_to_cpu(hostcmd->size); + hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num); + hostcmd->result = le16_to_cpu(hostcmd->result); + + hostcmd->command &= ~HostCmd_RET_BIT; + if (!hostcmd->result) { + switch (hostcmd->command) { + case HostCmd_CMD_CFG_DATA: + { + HostCmd_DS_802_11_CFG_DATA *pstcfgData = + (HostCmd_DS_802_11_CFG_DATA *)(buf + + S_DS_GEN); + pstcfgData->data_len = + le16_to_cpu(pstcfgData->data_len); + pstcfgData->action = + le16_to_cpu(pstcfgData->action); + + if (pstcfgData->action == HostCmd_ACT_GEN_GET) { + hexdump("cfgdata", pstcfgData->data, + pstcfgData->data_len, ' '); + } + break; + } + case HostCmd_CMD_802_11_TPC_ADAPT_REQ: + { + mlan_ioctl_11h_tpc_resp *tpcIoctlResp = + (mlan_ioctl_11h_tpc_resp *)(buf + + S_DS_GEN); + if (tpcIoctlResp->status_code == 0) { + printf("tpcrequest: txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi); + } else { + printf("tpcrequest: failure, status = %d\n", tpcIoctlResp->status_code); + } + break; + } + case HostCmd_CMD_802_11_CRYPTO: + { + t_u16 alg = + le16_to_cpu((t_u16) + *(buf + S_DS_GEN + + sizeof(t_u16))); + if (alg == CIPHER_TEST_AES_CCM || + alg == CIPHER_TEST_GCMP) { + HostCmd_DS_802_11_CRYPTO_AES_CCM + *cmd_aes_ccm = + (HostCmd_DS_802_11_CRYPTO_AES_CCM + *)(buf + S_DS_GEN); + + cmd_aes_ccm->encdec + = + le16_to_cpu(cmd_aes_ccm-> + encdec); + cmd_aes_ccm->algorithm = + le16_to_cpu(cmd_aes_ccm-> + algorithm); + cmd_aes_ccm->key_length = + le16_to_cpu(cmd_aes_ccm-> + key_length); + cmd_aes_ccm->nonce_length = + le16_to_cpu(cmd_aes_ccm-> + nonce_length); + cmd_aes_ccm->AAD_length = + le16_to_cpu(cmd_aes_ccm-> + AAD_length); + cmd_aes_ccm->data.header.type = + le16_to_cpu(cmd_aes_ccm->data. + header.type); + cmd_aes_ccm->data.header.len = + le16_to_cpu(cmd_aes_ccm->data. + header.len); + + printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len); + + hexdump("Key", cmd_aes_ccm->key, + cmd_aes_ccm->key_length, ' '); + hexdump("Nonce", cmd_aes_ccm->nonce, + cmd_aes_ccm->nonce_length, ' '); + hexdump("AAD", cmd_aes_ccm->AAD, + cmd_aes_ccm->AAD_length, ' '); + hexdump("Data", cmd_aes_ccm->data.data, + cmd_aes_ccm->data.header.len, + ' '); + } else if (alg == CIPHER_TEST_WAPI) { + HostCmd_DS_802_11_CRYPTO_WAPI *cmd_wapi + = + (HostCmd_DS_802_11_CRYPTO_WAPI + *) (buf + S_DS_GEN); + + cmd_wapi->encdec + = le16_to_cpu(cmd_wapi->encdec); + cmd_wapi->algorithm + = + le16_to_cpu(cmd_wapi-> + algorithm); + cmd_wapi->key_length = + le16_to_cpu(cmd_wapi-> + key_length); + cmd_wapi->nonce_length = + le16_to_cpu(cmd_wapi-> + nonce_length); + cmd_wapi->AAD_length = + le16_to_cpu(cmd_wapi-> + AAD_length); + + printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_wapi->encdec, cmd_wapi->algorithm, cmd_wapi->key_length, cmd_wapi->nonce_length, cmd_wapi->AAD_length, cmd_wapi->data_length); + + hexdump("Key", cmd_wapi->key, + cmd_wapi->key_length, ' '); + hexdump("Nonce", cmd_wapi->nonce, + cmd_wapi->nonce_length, ' '); + hexdump("AAD", cmd_wapi->AAD, + cmd_wapi->AAD_length, ' '); + } else { + HostCmd_DS_802_11_CRYPTO *cmd = + (HostCmd_DS_802_11_CRYPTO *)(buf + + + S_DS_GEN); + cmd->encdec = le16_to_cpu(cmd->encdec); + cmd->algorithm = + le16_to_cpu(cmd->algorithm); + cmd->key_IV_length = + le16_to_cpu(cmd->key_IV_length); + cmd->key_length = + le16_to_cpu(cmd->key_length); + cmd->data.header.type = + le16_to_cpu(cmd->data.header. + type); + cmd->data.header.len = + le16_to_cpu(cmd->data.header. + len); + + printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len); + hexdump("KeyIV", cmd->keyIV, + cmd->key_IV_length, ' '); + hexdump("Key", cmd->key, + cmd->key_length, ' '); + hexdump("Data", cmd->data.data, + cmd->data.header.len, ' '); + } + break; + } + case HostCmd_CMD_802_11_AUTO_TX: + { + HostCmd_DS_802_11_AUTO_TX *at = + (HostCmd_DS_802_11_AUTO_TX *)(buf + + S_DS_GEN); + + if (le16_to_cpu(at->action) == + HostCmd_ACT_GEN_GET) { + if (S_DS_GEN + sizeof(at->action) == + hostcmd->size) { + printf("auto_tx not configured\n"); + + } else { + MrvlIEtypesHeader_t *header = + &at->auto_tx.header; + + header->type = + le16_to_cpu(header-> + type); + header->len = + le16_to_cpu(header-> + len); + + if ((S_DS_GEN + + sizeof(at->action) + + + sizeof(MrvlIEtypesHeader_t) + + header->len == + hostcmd->size) && + (header->type == + TLV_TYPE_AUTO_TX)) { + + AutoTx_MacFrame_t *atmf + = + &at->auto_tx. + auto_tx_mac_frame; + + printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval)); + printf("Priority: %#x\n", atmf->priority); + printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len)); + printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]); + printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]); + + hexdump("Frame Payload", + atmf->payload, + le16_to_cpu + (atmf-> + frame_len) + - + MLAN_MAC_ADDR_LENGTH + * 2, ' '); + } else { + printf("incorrect auto_tx command response\n"); + } + } + } + break; + } + case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: + { + HostCmd_DS_802_11_SUBSCRIBE_EVENT *se = + (HostCmd_DS_802_11_SUBSCRIBE_EVENT + *)(buf + S_DS_GEN); + if (le16_to_cpu(se->action) == + HostCmd_ACT_GEN_GET) { + int len = + S_DS_GEN + + sizeof + (HostCmd_DS_802_11_SUBSCRIBE_EVENT); + printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n"); + while (len < hostcmd->size) { + MrvlIEtypesHeader_t *header = + (MrvlIEtypesHeader_t + *)(buf + len); + switch (le16_to_cpu + (header->type)) { + case TLV_TYPE_RSSI_LOW: + { + MrvlIEtypes_RssiThreshold_t + *low_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_LOW: + { + MrvlIEtypes_SnrThreshold_t + *low_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no"); + break; + } + case TLV_TYPE_FAILCOUNT: + { + MrvlIEtypes_FailureCount_t + *failure_count + = + (MrvlIEtypes_FailureCount_t + *)(buf + + + len); + printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no"); + break; + } + case TLV_TYPE_BCNMISS: + { + MrvlIEtypes_BeaconsMissed_t + *bcn_missed + = + (MrvlIEtypes_BeaconsMissed_t + *)(buf + + + len); + printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_HIGH: + { + MrvlIEtypes_RssiThreshold_t + *high_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no"); + break; + } + + case TLV_TYPE_SNR_HIGH: + { + MrvlIEtypes_SnrThreshold_t + *high_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_LOW_DATA: + { + MrvlIEtypes_RssiThreshold_t + *low_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_LOW_DATA: + { + MrvlIEtypes_SnrThreshold_t + *low_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_HIGH_DATA: + { + MrvlIEtypes_RssiThreshold_t + *high_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_HIGH_DATA: + { + MrvlIEtypes_SnrThreshold_t + *high_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no"); + break; + } + case TLV_TYPE_LINK_QUALITY: + { + MrvlIEtypes_LinkQuality_t + *link_qual + = + (MrvlIEtypes_LinkQuality_t + *)(buf + + + len); + printf("Link Quality Parameters:\n"); + printf("------------------------\n"); + printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no"); + printf("Link SNR Threshold = %d\n", le16_to_cpu(link_qual->link_SNR_thrs)); + printf("Link SNR Frequency = %d\n", le16_to_cpu(link_qual->link_SNR_freq)); + printf("Min Rate Value = %d\n", le16_to_cpu(link_qual->min_rate_val)); + printf("Min Rate Frequency = %d\n", le16_to_cpu(link_qual->min_rate_freq)); + printf("Tx Latency Value = %d\n", le32_to_cpu(link_qual->tx_latency_val)); + printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs)); + + break; + } + case TLV_TYPE_PRE_BEACON_LOST: + { + MrvlIEtypes_PreBeaconLost_t + *pre_bcn_lost + = + (MrvlIEtypes_PreBeaconLost_t + *)(buf + + + len); + printf("------------------------\n"); + printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no"); + printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost); + break; + } + default: + printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len)); + break; + } + + len += (sizeof + (MrvlIEtypesHeader_t) + + + le16_to_cpu(header-> + len)); + } + } + break; + } + case HostCmd_CMD_MAC_REG_ACCESS: + case HostCmd_CMD_BBP_REG_ACCESS: + case HostCmd_CMD_RF_REG_ACCESS: + case HostCmd_CMD_CAU_REG_ACCESS: + { + HostCmd_DS_REG *preg = + (HostCmd_DS_REG *)(buf + S_DS_GEN); + preg->action = le16_to_cpu(preg->action); + if (preg->action == HostCmd_ACT_GEN_GET) { + preg->value = le32_to_cpu(preg->value); + printf("value = 0x%08x\n", preg->value); + } + break; + } + case HostCmd_CMD_MEM_ACCESS: + { + HostCmd_DS_MEM *pmem = + (HostCmd_DS_MEM *)(buf + S_DS_GEN); + pmem->action = le16_to_cpu(pmem->action); + if (pmem->action == HostCmd_ACT_GEN_GET) { + pmem->value = le32_to_cpu(pmem->value); + printf("value = 0x%08x\n", pmem->value); + } + break; + } + default: + printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x," + " SeqNum=%#04x, Result=%#04x\n", + hostcmd->command, hostcmd->size, + hostcmd->seq_num, hostcmd->result); + hexdump("payload", + (t_void *)(buf + S_DS_GEN), + hostcmd->size - S_DS_GEN, ' '); + break; + } + } else { + printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x," + " SeqNum=%#04x, Result=%#04x\n", + hostcmd->command, hostcmd->size, + hostcmd->seq_num, hostcmd->result); + } + return ret; +} + +/** + * @brief Prepare ARP filter buffer + * @param fp File handler + * @param buf A pointer to the buffer + * @param length A pointer to the length of buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_arp_filter_buffer(FILE * fp, t_u8 *buf, t_u16 *length) +{ + t_s8 line[256], *pos; + int ln = 0; + int ret = MLAN_STATUS_SUCCESS; + int arpfilter_found = 0; + + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { + if (strcmp(pos, "arpfilter={") == 0) { + arpfilter_found = 1; + mlan_get_hostcmd_data(fp, &ln, buf, length); + break; + } + } + if (!arpfilter_found) { + fprintf(stderr, + "mlanconfig: 'arpfilter' not found in conf file"); + ret = MLAN_STATUS_FAILURE; + } + return ret; +} + +/** + * @brief Prepare the hostcmd for register access + * @param type Register type + * @param offset Register offset + * @param value Pointer to value (NULL for read) + * @param buf Pointer to hostcmd buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf) +{ + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_REG *preg; + + hostcmd = (HostCmd_DS_GEN *)buf; + switch (type) { + case 1: + hostcmd->command = cpu_to_le16(HostCmd_CMD_MAC_REG_ACCESS); + break; + case 2: + hostcmd->command = cpu_to_le16(HostCmd_CMD_BBP_REG_ACCESS); + break; + case 3: + hostcmd->command = cpu_to_le16(HostCmd_CMD_RF_REG_ACCESS); + break; + case 5: + hostcmd->command = cpu_to_le16(HostCmd_CMD_CAU_REG_ACCESS); + break; + default: + printf("Invalid register set specified\n"); + return -EINVAL; + } + preg = (HostCmd_DS_REG *)(buf + S_DS_GEN); + preg->action = (value) ? HostCmd_ACT_GEN_SET : HostCmd_ACT_GEN_GET; + preg->action = cpu_to_le16(preg->action); + preg->offset = cpu_to_le16((t_u16)offset); + if (value) + preg->value = cpu_to_le32(*value); + else + preg->value = 0; + hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REG)); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + return MLAN_STATUS_SUCCESS; +} diff --git a/mwifiex_8997/mapp/mlanconfig/mlanhostcmd.h b/mwifiex_8997/mapp/mlanconfig/mlanhostcmd.h new file mode 100755 index 0000000..39794d5 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/mlanhostcmd.h @@ -0,0 +1,372 @@ +/** @file mlanhostcmd.h + * + * @brief This file contains command structures for mlanconfig application + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 11/26/2008: initial version +************************************************************************/ +#ifndef _MLANHOSTCMD_H_ +#define _MLANHOSTCMD_H_ + +/** Find number of elements */ +#define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) + +/** MLAN MAC Address Length */ +#define MLAN_MAC_ADDR_LENGTH (6) +/** Size of command buffer */ +#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) + +/** Command RET code, MSB is set to 1 */ +#define HostCmd_RET_BIT 0x8000 +/** General purpose action : Get */ +#define HostCmd_ACT_GEN_GET 0x0000 +/** General purpose action : Set */ +#define HostCmd_ACT_GEN_SET 0x0001 +/** General purpose action : Clear */ +#define HostCmd_ACT_GEN_CLEAR 0x0004 +/** General purpose action : Remove */ +#define HostCmd_ACT_GEN_REMOVE 0x0004 + +/** Host Command ID : Memory access */ +#define HostCmd_CMD_MEM_ACCESS 0x0086 + +/** Pre-Authenticate - 11r only */ +#define HostCmd_CMD_802_11_AUTHENTICATE 0x0011 + +/** Read/Write Mac register */ +#define HostCmd_CMD_MAC_REG_ACCESS 0x0019 +/** Read/Write BBP register */ +#define HostCmd_CMD_BBP_REG_ACCESS 0x001a +/** Read/Write RF register */ +#define HostCmd_CMD_RF_REG_ACCESS 0x001b +/** Get TX Power data */ +#define HostCmd_CMD_802_11_RF_TX_POWER 0x001e +/** Get the current TSF */ +#define HostCmd_CMD_GET_TSF 0x0080 +/** Host Command ID : CAU register access */ +#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed + +/** Host Command ID : 802.11 BG scan configuration */ +#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b +/** Host Command ID : Configuration data */ +#define HostCmd_CMD_CFG_DATA 0x008f +/** Host Command ID : 802.11 TPC adapt req */ +#define HostCmd_CMD_802_11_TPC_ADAPT_REQ 0x0060 +/** Host Command ID : 802.11 crypto */ +#define HostCmd_CMD_802_11_CRYPTO 0x0078 +/** Host Command ID : 802.11 auto Tx */ +#define HostCmd_CMD_802_11_AUTO_TX 0x0082 + +/** Host Command ID : 802.11 subscribe event */ +#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 + +/** Host Command ID : Channel TRPC config */ +#define HostCmd_CMD_CHAN_TRPC_CONFIG 0x00fb + +/** TLV type ID definition */ +#define PROPRIETARY_TLV_BASE_ID 0x0100 +/** TLV type : Beacon RSSI low */ +#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 0x04) //0x0104 +/** TLV type : Beacon SNR low */ +#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 0x05) //0x0105 +/** TLV type : Fail count */ +#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 0x06) //0x0106 +/** TLV type : BCN miss */ +#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 0x07) //0x0107 +/** TLV type : Beacon RSSI high */ +#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 0x16) //0x0116 +/** TLV type : Beacon SNR high */ +#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 0x17) //0x0117 +/** TLV type : Auto Tx */ +#define TLV_TYPE_AUTO_TX (PROPRIETARY_TLV_BASE_ID + 0x18) //0x0118 +/** TLV type :Link Quality */ +#define TLV_TYPE_LINK_QUALITY (PROPRIETARY_TLV_BASE_ID + 0x24) //0x0124 +/** TLV type : Data RSSI low */ +#define TLV_TYPE_RSSI_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x26) //0x0126 +/** TLV type : Data SNR low */ +#define TLV_TYPE_SNR_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x27) //0x0127 +/** TLV type : Data RSSI high */ +#define TLV_TYPE_RSSI_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x28) //0x0128 +/** TLV type : Data SNR high */ +#define TLV_TYPE_SNR_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x29) //0x0129 +/** TLV type: Pre-Beacon Lost */ +#define TLV_TYPE_PRE_BEACON_LOST (PROPRIETARY_TLV_BASE_ID + 0x49) //0x0149 + +/** TLV type : Channel TRPC */ +#define TLV_TYPE_CHAN_TRPC (PROPRIETARY_TLV_BASE_ID + 0x89) //0x0189 + +/* Define general hostcmd data structure */ +/** HostCmd_DS_GEN */ +typedef struct MAPP_HostCmd_DS_GEN { + /** Command */ + t_u16 command; + /** Size */ + t_u16 size; + /** Sequence number */ + t_u16 seq_num; + /** Result */ + t_u16 result; +} __ATTRIB_PACK__ HostCmd_DS_GEN; + +typedef struct _HostCmd_DS_MEF_CFG { + /** Criteria */ + t_u32 Criteria; + /** Number of entries */ + t_u16 NumEntries; +} __ATTRIB_PACK__ HostCmd_DS_MEF_CFG; + +typedef struct _MEF_CFG_DATA { + /** Size */ + t_u16 size; + /** Data */ + HostCmd_DS_MEF_CFG data; +} __ATTRIB_PACK__ MEF_CFG_DATA; + +/** Size of HostCmd_DS_GEN */ +#define S_DS_GEN sizeof(HostCmd_DS_GEN) + +/** HostCmd_DS_REG */ +typedef struct MAPP_HostCmd_DS_REG { + /** Read or write */ + t_u16 action; + /** Register offset */ + t_u16 offset; + /** Value */ + t_u32 value; +} __ATTRIB_PACK__ HostCmd_DS_REG; + +/** HostCmd_DS_MEM */ +typedef struct MAPP_HostCmd_DS_MEM { + /** Read or write */ + t_u16 action; + /** Reserved */ + t_u16 reserved; + /** Address */ + t_u32 addr; + /** Value */ + t_u32 value; +} __ATTRIB_PACK__ HostCmd_DS_MEM; + +/** HostCmd_DS_802_11_CFG_DATA */ +typedef struct MAPP_HostCmd_DS_802_11_CFG_DATA { + /** Action */ + t_u16 action; + /** Type */ + t_u16 type; + /** Data length */ + t_u16 data_len; + /** Data */ + t_u8 data[1]; +} __ATTRIB_PACK__ HostCmd_DS_802_11_CFG_DATA; + +/** mlan_ioctl_11h_tpc_resp */ +typedef struct { + int status_code; + /**< Firmware command result status code */ + int tx_power;/**< Reported TX Power from the TPC Report */ + int link_margin; + /**< Reported Link margin from the TPC Report */ + int rssi; /**< RSSI of the received TPC Report frame */ +} __ATTRIB_PACK__ mlan_ioctl_11h_tpc_resp; + +/** MrvlIEtypesHeader_t */ +typedef struct MrvlIEtypesHeader { + /** Header type */ + t_u16 type; + /** Header length */ + t_u16 len; +} __ATTRIB_PACK__ MrvlIEtypesHeader_t; + +/** MrvlIEtypes_Data_t */ +typedef struct MrvlIEtypes_Data_t { + /** Header */ + MrvlIEtypesHeader_t header; + /** Data */ + t_u8 data[1]; +} __ATTRIB_PACK__ MrvlIEtypes_Data_t; + +/** HostCmd_DS_802_11_CRYPTO */ +typedef struct MAPP_HostCmd_DS_802_11_CRYPTO { + t_u16 encdec; /**< Decrypt=0, Encrypt=1 */ + t_u16 algorithm; /**< RC4=1 AES=2 , AES_KEY_WRAP=3 */ + t_u16 key_IV_length;/**< Length of Key IV (bytes) */ + t_u8 keyIV[32]; /**< Key IV */ + t_u16 key_length; /**< Length of Key (bytes) */ + t_u8 key[32]; /**< Key */ + MrvlIEtypes_Data_t data; /**< Plain text if encdec=Encrypt, Ciphertext data if encdec=Decrypt*/ +} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO; + +/** HostCmd_DS_802_11_CRYPTO_AES_CCM */ +typedef struct MAPP_HostCmd_DS_802_11_CRYPTO_AES_CCM { + t_u16 encdec; /**< Decrypt=0, Encrypt=1 */ + t_u16 algorithm; /**< AES_CCM=4 */ + t_u16 key_length; /**< Length of Key (bytes) */ + t_u8 key[32]; /**< Key */ + t_u16 nonce_length;/**< Length of Nonce (bytes) */ + t_u8 nonce[14]; /**< Nonce */ + t_u16 AAD_length; /**< Length of AAD (bytes) */ + t_u8 AAD[32]; /**< AAD */ + MrvlIEtypes_Data_t data; /**< Plain text if encdec=Encrypt, Ciphertext data if encdec=Decrypt*/ +} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO_AES_CCM; + +/** HostCmd_DS_802_11_CRYPTO_WAPI */ +typedef struct MAPP_HostCmd_DS_802_11_CRYPTO_WAPI { + t_u16 encdec; /**< Decrypt=0, Encrypt=1 */ + t_u16 algorithm; /**< WAPI =5 */ + t_u16 key_length; /**< Length of Key (bytes) */ + t_u8 key[32]; /**< Key */ + t_u16 nonce_length;/**< Length of Nonce (bytes) */ + t_u8 nonce[16]; /**< Nonce */ + t_u16 AAD_length; /**< Length of AAD (bytes) */ + t_u8 AAD[48]; /**< AAD */ + t_u16 data_length; /**< Length of data (bytes) */ +} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO_WAPI; + +/** WAPI cipher test */ +#define CIPHER_TEST_WAPI (5) +/** AES CCM cipher test */ +#define CIPHER_TEST_AES_CCM (4) +/** GCMP cipher test */ +#define CIPHER_TEST_GCMP (6) +/** AutoTx_MacFrame_t */ +typedef struct AutoTx_MacFrame { + t_u16 interval; /**< in seconds */ + t_u8 priority; /**< User Priority: 0~7, ignored if non-WMM */ + t_u8 reserved; /**< set to 0 */ + t_u16 frame_len; /**< Length of MAC frame payload */ + t_u8 dest_mac_addr[MLAN_MAC_ADDR_LENGTH]; /**< Destination MAC address */ + t_u8 src_mac_addr[MLAN_MAC_ADDR_LENGTH]; /**< Source MAC address */ + t_u8 payload[]; /**< Payload */ +} __ATTRIB_PACK__ AutoTx_MacFrame_t; + +/** MrvlIEtypes_AutoTx_t */ +typedef struct MrvlIEtypes_AutoTx { + MrvlIEtypesHeader_t header; /**< Header */ + AutoTx_MacFrame_t auto_tx_mac_frame; /**< Auto Tx MAC frame */ +} __ATTRIB_PACK__ MrvlIEtypes_AutoTx_t; + +/** HostCmd_DS_802_11_AUTO_TX */ +typedef struct MAPP_HostCmd_DS_802_11_AUTO_TX { + /** Action */ + t_u16 action; /* 0 = ACT_GET; 1 = ACT_SET; */ + MrvlIEtypes_AutoTx_t auto_tx; /**< Auto Tx */ +} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTO_TX; + +/** HostCmd_DS_802_11_SUBSCRIBE_EVENT */ +typedef struct MAPP_HostCmd_DS_802_11_SUBSCRIBE_EVENT { + /** Action */ + t_u16 action; + /** Events */ + t_u16 events; +} __ATTRIB_PACK__ HostCmd_DS_802_11_SUBSCRIBE_EVENT; + +/** MrvlIEtypes_RssiParamSet_t */ +typedef struct MrvlIEtypes_RssiThreshold { + /** Header */ + MrvlIEtypesHeader_t header; + /** RSSI value */ + t_u8 RSSI_value; + /** RSSI frequency */ + t_u8 RSSI_freq; +} __ATTRIB_PACK__ MrvlIEtypes_RssiThreshold_t; + +/** MrvlIEtypes_SnrThreshold_t */ +typedef struct MrvlIEtypes_SnrThreshold { + /** Header */ + MrvlIEtypesHeader_t header; + /** SNR value */ + t_u8 SNR_value; + /** SNR frequency */ + t_u8 SNR_freq; +} __ATTRIB_PACK__ MrvlIEtypes_SnrThreshold_t; + +/** MrvlIEtypes_FailureCount_t */ +typedef struct MrvlIEtypes_FailureCount { + /** Header */ + MrvlIEtypesHeader_t header; + /** Failure value */ + t_u8 fail_value; + /** Failure frequency */ + t_u8 fail_freq; +} __ATTRIB_PACK__ MrvlIEtypes_FailureCount_t; + +/** MrvlIEtypes_BeaconsMissed_t */ +typedef struct MrvlIEtypes_BeaconsMissed { + /** Header */ + MrvlIEtypesHeader_t header; + /** Number of beacons missed */ + t_u8 beacon_missed; + /** Reserved */ + t_u8 reserved; +} __ATTRIB_PACK__ MrvlIEtypes_BeaconsMissed_t; + +/** MrvlIEtypes_LinkQuality_t */ +typedef struct MrvlIEtypes_LinkQuality { + /** Header */ + MrvlIEtypesHeader_t header; + /** Link SNR threshold */ + t_u16 link_SNR_thrs; + /** Link SNR frequency */ + t_u16 link_SNR_freq; + /** Minimum rate value */ + t_u16 min_rate_val; + /** Minimum rate frequency */ + t_u16 min_rate_freq; + /** Tx latency value */ + t_u32 tx_latency_val; + /** Tx latency threshold */ + t_u32 tx_latency_thrs; +} __ATTRIB_PACK__ MrvlIEtypes_LinkQuality_t; + +/** MrvlIEtypes_PreBeaconLost_t */ +typedef struct MrvlIEtypes_PreBeaconLost { + /** Header */ + MrvlIEtypesHeader_t header; + /** Pre-Beacon Lost */ + t_u8 pre_beacon_lost; + /** Reserved */ + t_u8 reserved; +} __ATTRIB_PACK__ MrvlIEtypes_PreBeaconLost_t; + +/* String helper functions */ +/** Convert char to hex integer */ +int hexval(t_s32 chr); +/** Convert char to hex integer */ +t_u8 hexc2bin(t_s8 chr); +/** Convert string to hex integer */ +t_u32 a2hex(t_s8 *s); +/** Check the Hex String */ +int ishexstring(t_s8 *s); +/** Convert String to integer */ +t_u32 a2hex_or_atoi(t_s8 *value); +/** Convert String to Integer */ +int atoval(t_s8 *buf); +/** Hump hex data */ +void hexdump(t_s8 *prompt, void *p, t_s32 len, t_s8 delim); +/** Convert String to Hex */ +t_s8 *convert2hex(t_s8 *ptr, t_u8 *chr); + +int process_host_cmd_resp(t_u8 *buf); +int prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf); +int prepare_arp_filter_buffer(FILE * fp, t_u8 *buf, t_u16 *length); +int prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf); +int prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf); + +#endif /* _MLANHOSTCMD_H_ */ diff --git a/mwifiex_8997/mapp/mlanconfig/mlanmisc.c b/mwifiex_8997/mapp/mlanconfig/mlanmisc.c new file mode 100755 index 0000000..19825cf --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/mlanmisc.c @@ -0,0 +1,1030 @@ +/** @file mlanmisc.c + * + * @brief Program to prepare command buffer + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ + +/************************************************************************ +Change log: + 03/10/2009: initial version +************************************************************************/ + +#include "mlanconfig.h" +#include "mlanhostcmd.h" +#include "mlanmisc.h" + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief Helper function for process_getscantable_idx + * + * @param pbuf A pointer to the buffer + * @param buf_len buffer length + * + * @return NA + * + */ +static void +dump_scan_elems(const t_u8 *pbuf, uint buf_len) +{ + uint idx; + uint marker = 2 + pbuf[1]; + + for (idx = 0; idx < buf_len; idx++) { + if (idx % 0x10 == 0) { + printf("\n%04x: ", idx); + } + + if (idx == marker) { + printf("|"); + marker = idx + pbuf[idx + 1] + 2; + } else { + printf(" "); + } + + printf("%02x ", pbuf[idx]); + } + + printf("\n"); +} + +/** + * @brief Helper function for process_getscantable_idx + * Find next element + * + * @param pp_ie_out pointer of a IEEEtypes_Generic_t structure pointer + * @param p_buf_left integer pointer, which contains the number of left p_buf + * + * @return MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE + */ +static int +scantable_elem_next(IEEEtypes_Generic_t **pp_ie_out, int *p_buf_left) +{ + IEEEtypes_Generic_t *pie_gen; + t_u8 *p_next; + + if (*p_buf_left < 2) { + return MLAN_STATUS_FAILURE; + } + + pie_gen = *pp_ie_out; + + p_next = (t_u8 *)pie_gen + (pie_gen->ieee_hdr.len + + sizeof(pie_gen->ieee_hdr)); + *p_buf_left -= (p_next - (t_u8 *)pie_gen); + + *pp_ie_out = (IEEEtypes_Generic_t *)p_next; + + if (*p_buf_left <= 0) { + return MLAN_STATUS_FAILURE; + } + + return MLAN_STATUS_SUCCESS; +} + + /** + * @brief Helper function for process_getscantable_idx + * scantable find element + * + * @param ie_buf pointer of the IE buffer + * @param ie_buf_len IE buffer length + * @param ie_type IE type + * @param ppie_out pointer to the IEEEtypes_Generic_t structure pointer + * @return MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE + */ +static int +scantable_find_elem(t_u8 *ie_buf, + unsigned int ie_buf_len, + IEEEtypes_ElementId_e ie_type, + IEEEtypes_Generic_t **ppie_out) +{ + int found; + unsigned int ie_buf_left; + + ie_buf_left = ie_buf_len; + + found = FALSE; + + *ppie_out = (IEEEtypes_Generic_t *)ie_buf; + + do { + found = ((*ppie_out)->ieee_hdr.element_id == ie_type); + + } while (!found && + (scantable_elem_next(ppie_out, (int *)&ie_buf_left) == 0)); + + if (!found) { + *ppie_out = NULL; + } + + return (found ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE); +} + + /** + * @brief Helper function for process_getscantable_idx + * It gets SSID from IE + * + * @param ie_buf IE buffer + * @param ie_buf_len IE buffer length + * @param pssid SSID + * @param ssid_buf_max size of SSID + * @return MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE + */ +static int +scantable_get_ssid_from_ie(t_u8 *ie_buf, + unsigned int ie_buf_len, + t_u8 *pssid, unsigned int ssid_buf_max) +{ + int retval; + IEEEtypes_Generic_t *pie_gen; + + retval = scantable_find_elem(ie_buf, ie_buf_len, SSID, &pie_gen); + if (retval == MLAN_STATUS_SUCCESS) + memcpy(pssid, pie_gen->data, + MIN(pie_gen->ieee_hdr.len, ssid_buf_max)); + + return retval; +} + +/** + * @brief Display detailed information for a specific scan table entry + * + * @param prsp_info_req Scan table entry request structure + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_getscantable_idx(wlan_ioctl_get_scan_table_info *prsp_info_req) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + t_u8 *pcurrent; + int ret = 0; + char ssid[33]; + t_u16 tmp_cap; + t_u8 tsf[8]; + t_u16 beacon_interval; + t_u8 *scan_rsp_buf = NULL; + t_u16 cap_info; + wlan_ioctl_get_scan_table_info *prsp_info; + + wlan_get_scan_table_fixed fixed_fields; + t_u32 fixed_field_length; + t_u32 bss_info_length; + + scan_rsp_buf = (t_u8 *)malloc(SCAN_RESP_BUF_SIZE); + if (scan_rsp_buf == NULL) { + printf("Error: allocate memory for scan_rsp_buf failed\n"); + return -ENOMEM; + } + memset(ssid, 0x00, sizeof(ssid)); + + prsp_info = (wlan_ioctl_get_scan_table_info *)scan_rsp_buf; + + memcpy(prsp_info, prsp_info_req, + sizeof(wlan_ioctl_get_scan_table_info)); + + if (get_priv_ioctl("getscantable", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + ret = -EOPNOTSUPP; + goto done; + } + + /* + * Set up and execute the ioctl call + */ + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = (caddr_t) prsp_info; + iwr.u.data.length = SCAN_RESP_BUF_SIZE; + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("mlanconfig: getscantable ioctl"); + ret = -EFAULT; + goto done; + } + + if (prsp_info->scan_number == 0) { + printf("mlanconfig: getscantable ioctl - index out of range\n"); + ret = -EINVAL; + goto done; + } + + pcurrent = prsp_info->scan_table_entry_buf; + + memcpy((t_u8 *)&fixed_field_length, + (t_u8 *)pcurrent, sizeof(fixed_field_length)); + pcurrent += sizeof(fixed_field_length); + + memcpy((t_u8 *)&bss_info_length, + (t_u8 *)pcurrent, sizeof(bss_info_length)); + pcurrent += sizeof(bss_info_length); + + memcpy((t_u8 *)&fixed_fields, (t_u8 *)pcurrent, sizeof(fixed_fields)); + pcurrent += fixed_field_length; + + /* time stamp is 8 byte long */ + memcpy(tsf, pcurrent, sizeof(tsf)); + pcurrent += sizeof(tsf); + bss_info_length -= sizeof(tsf); + + /* beacon interval is 2 byte long */ + memcpy(&beacon_interval, pcurrent, sizeof(beacon_interval)); + pcurrent += sizeof(beacon_interval); + bss_info_length -= sizeof(beacon_interval); + + /* capability information is 2 byte long */ + memcpy(&cap_info, pcurrent, sizeof(cap_info)); + pcurrent += sizeof(cap_info); + bss_info_length -= sizeof(cap_info); + + scantable_get_ssid_from_ie(pcurrent, + bss_info_length, (t_u8 *)ssid, sizeof(ssid)); + + printf("\n*** [%s], %02x:%02x:%02x:%02x:%02x:%2x\n", + ssid, + fixed_fields.bssid[0], + fixed_fields.bssid[1], + fixed_fields.bssid[2], + fixed_fields.bssid[3], + fixed_fields.bssid[4], fixed_fields.bssid[5]); + memcpy(&tmp_cap, &cap_info, sizeof(tmp_cap)); + printf("Channel = %d, SS = %d, CapInfo = 0x%04x, BcnIntvl = %d\n", + fixed_fields.channel, + 255 - fixed_fields.rssi, tmp_cap, beacon_interval); + + printf("TSF Values: AP(0x%02x%02x%02x%02x%02x%02x%02x%02x), ", + tsf[7], tsf[6], tsf[5], tsf[4], tsf[3], tsf[2], tsf[1], tsf[0]); + + printf("Network(0x%016llx)\n", fixed_fields.network_tsf); + printf("\n"); + printf("Element Data (%d bytes)\n", (int)bss_info_length); + printf("------------"); + dump_scan_elems(pcurrent, bss_info_length); + printf("\n"); + +done: + + if (scan_rsp_buf) + free(scan_rsp_buf); + + return ret; +} + +/******************************************************** + Global Functions +********************************************************/ + +/** + * @brief Retrieve and display the contents of the driver scan table. + * + * The ioctl to retrieve the scan table contents will be invoked, and portions + * of the scan data will be displayed on stdout. The entire beacon or + * probe response is also retrieved (if available in the driver). This + * data would be needed in case the application was explicitly controlling + * the association (inserting IEs, TLVs, etc). + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_getscantable(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + t_u8 *scan_rsp_buf = NULL; + + struct wlan_ioctl_get_scan_list *scan_list_head = NULL; + struct wlan_ioctl_get_scan_list *scan_list_node = NULL; + struct wlan_ioctl_get_scan_list *curr = NULL, *prev = NULL, *next = + NULL; + + t_u32 total_scan_res = 0; + + unsigned int scan_start; + int idx, ret = 0; + + t_u8 *pcurrent; + t_u8 *pnext; + IEEEtypes_ElementId_e *pelement_id; + t_u8 *pelement_len; + int ssid_idx; + t_u8 *pbyte; + t_u16 new_ss; + t_u16 curr_ss; + + IEEEtypes_VendorSpecific_t *pwpa_ie; + const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; + + IEEEtypes_WmmParameter_t *pwmm_ie; + const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; + IEEEtypes_VendorSpecific_t *pwps_ie; + const t_u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 }; + + int displayed_info; + + wlan_ioctl_get_scan_table_info rspInfoReq; + wlan_ioctl_get_scan_table_info *prsp_info; + + wlan_get_scan_table_fixed fixed_fields; + t_u32 fixed_field_length; + t_u32 bss_info_length; + wlan_ioctl_get_bss_info *bss_info; + + scan_rsp_buf = (t_u8 *)malloc(SCAN_RESP_BUF_SIZE); + if (scan_rsp_buf == NULL) { + printf("Error: allocate memory for scan_rsp_buf failed\n"); + return -ENOMEM; + } + prsp_info = (wlan_ioctl_get_scan_table_info *)scan_rsp_buf; + + if (get_priv_ioctl("getscantable", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + ret = -EOPNOTSUPP; + goto done; + } + + if (argc > 3 && (strcmp(argv[3], "tsf") != 0) + && (strcmp(argv[3], "help") != 0)) { + + idx = strtol(argv[3], NULL, 10); + + if (idx >= 0) { + if (scan_rsp_buf) { + free(scan_rsp_buf); + } + rspInfoReq.scan_number = idx; + return process_getscantable_idx(&rspInfoReq); + } + } + + displayed_info = FALSE; + scan_start = 1; + + do { + prsp_info->scan_number = scan_start; + + /* + * Set up and execute the ioctl call + */ + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = (caddr_t) prsp_info; + iwr.u.data.length = SCAN_RESP_BUF_SIZE; + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("mlanconfig: getscantable ioctl"); + ret = -EFAULT; + goto done; + } + total_scan_res += prsp_info->scan_number; + + pcurrent = 0; + pnext = prsp_info->scan_table_entry_buf; + + for (idx = 0; (unsigned int)idx < prsp_info->scan_number; idx++) { + + /* Alloc memory for new node for next BSS */ + scan_list_node = (struct wlan_ioctl_get_scan_list *) + malloc(sizeof(struct wlan_ioctl_get_scan_list)); + if (scan_list_node == NULL) { + printf("Error: allocate memory for scan_list_head failed\n"); + return -ENOMEM; + } + memset(scan_list_node, 0, + sizeof(struct wlan_ioctl_get_scan_list)); + + /* + * Set pcurrent to pnext in case pad bytes are at the end + * of the last IE we processed. + */ + pcurrent = pnext; + + /* Start extracting each BSS to prepare a linked list */ + memcpy((t_u8 *)&fixed_field_length, + (t_u8 *)pcurrent, sizeof(fixed_field_length)); + pcurrent += sizeof(fixed_field_length); + + memcpy((t_u8 *)&bss_info_length, + (t_u8 *)pcurrent, sizeof(bss_info_length)); + pcurrent += sizeof(bss_info_length); + + memcpy((t_u8 *)&fixed_fields, + (t_u8 *)pcurrent, sizeof(fixed_fields)); + pcurrent += fixed_field_length; + + scan_list_node->fixed_buf.fixed_field_length = + fixed_field_length; + scan_list_node->fixed_buf.bss_info_length = + bss_info_length; + scan_list_node->fixed_buf.fixed_fields = fixed_fields; + + bss_info = &scan_list_node->bss_info_buf; + + /* Set next to be the start of the next scan entry */ + pnext = pcurrent + bss_info_length; + + if (bss_info_length >= + (sizeof(bss_info->tsf) + + sizeof(bss_info->beacon_interval) + + sizeof(bss_info->cap_info))) { + + /* time stamp is 8 byte long */ + memcpy(bss_info->tsf, pcurrent, + sizeof(bss_info->tsf)); + pcurrent += sizeof(bss_info->tsf); + bss_info_length -= sizeof(bss_info->tsf); + + /* beacon interval is 2 byte long */ + memcpy(&bss_info->beacon_interval, pcurrent, + sizeof(bss_info->beacon_interval)); + pcurrent += sizeof(bss_info->beacon_interval); + bss_info_length -= + sizeof(bss_info->beacon_interval); + + /* capability information is 2 byte long */ + memcpy(&bss_info->cap_info, pcurrent, + sizeof(bss_info->cap_info)); + pcurrent += sizeof(bss_info->cap_info); + bss_info_length -= sizeof(bss_info->cap_info); + } + + bss_info->wmm_cap = ' '; /* M (WMM), C (WMM-Call Admission Control) */ + bss_info->wps_cap = ' '; /* "S" */ + bss_info->dot11k_cap = ' '; /* "K" */ + bss_info->dot11r_cap = ' '; /* "R" */ + bss_info->ht_cap = ' '; /* "N" */ + + /* "P" for Privacy (WEP) since "W" is WPA, and "2" is RSN/WPA2 */ + bss_info->priv_cap = + bss_info->cap_info.privacy ? 'P' : ' '; + + memset(bss_info->ssid, 0, MRVDRV_MAX_SSID_LENGTH + 1); + bss_info->ssid_len = 0; + + while (bss_info_length >= 2) { + pelement_id = (IEEEtypes_ElementId_e *)pcurrent; + pelement_len = pcurrent + 1; + pcurrent += 2; + + switch (*pelement_id) { + + case SSID: + if (*pelement_len && + *pelement_len <= + MRVDRV_MAX_SSID_LENGTH) { + memcpy(bss_info->ssid, pcurrent, + *pelement_len); + bss_info->ssid_len = + *pelement_len; + } + break; + + case WPA_IE: + pwpa_ie = + (IEEEtypes_VendorSpecific_t *) + pelement_id; + if ((memcmp + (pwpa_ie->vend_hdr.oui, wpa_oui, + sizeof(pwpa_ie->vend_hdr.oui)) == + 0) + && (pwpa_ie->vend_hdr.oui_type == + wpa_oui[3])) { + /* WPA IE found, 'W' for WPA */ + bss_info->priv_cap = 'W'; + } else { + pwmm_ie = + (IEEEtypes_WmmParameter_t + *)pelement_id; + if ((memcmp + (pwmm_ie->vend_hdr.oui, + wmm_oui, + sizeof(pwmm_ie->vend_hdr. + oui)) == 0) + && (pwmm_ie->vend_hdr. + oui_type == + wmm_oui[3])) { + /* Check the subtype: 1 == parameter, 0 == info */ + if ((pwmm_ie->vend_hdr. + oui_subtype == 1) + && pwmm_ie-> + ac_params + [WMM_AC_VO]. + aci_aifsn.acm) { + /* Call admission on VO; 'C' for CAC */ + bss_info-> + wmm_cap + = 'C'; + } else { + /* No CAC; 'M' for uh, WMM */ + bss_info-> + wmm_cap + = 'M'; + } + } else { + pwps_ie = + (IEEEtypes_VendorSpecific_t + *)pelement_id; + if ((memcmp + (pwps_ie->vend_hdr. + oui, wps_oui, + sizeof(pwps_ie-> + vend_hdr. + oui)) == 0) + && (pwps_ie-> + vend_hdr. + oui_type == + wps_oui[3])) { + bss_info-> + wps_cap + = 'S'; + } + } + } + break; + + case RSN_IE: + /* RSN IE found; '2' for WPA2 (RSN) */ + bss_info->priv_cap = '2'; + break; + case HT_CAPABILITY: + bss_info->ht_cap = 'N'; + break; + case VHT_CAPABILITY: + bss_info->vht_cap[0] = 'A'; + bss_info->vht_cap[1] = 'C'; + break; + default: + break; + } + + pcurrent += *pelement_len; + bss_info_length -= (2 + *pelement_len); + } + + /* Create a sorted list of BSS using Insertion Sort. + Sort as per Signal Strength (descending order) */ + new_ss = 255 - fixed_fields.rssi; + + if (scan_list_head == NULL) { + // Node is the first element in the list. + scan_list_head = scan_list_node; + scan_list_node->next = NULL; + } else { + + curr_ss = + 255 - + scan_list_head->fixed_buf.fixed_fields. + rssi; + + if (new_ss > curr_ss) { + // Insert the node to head of the list + scan_list_node->next = scan_list_head; + scan_list_head = scan_list_node; + } else { + + for (curr = scan_list_head; + curr != NULL; curr = curr->next) { + + curr_ss = + 255 - + curr->fixed_buf. + fixed_fields.rssi; + if (prev && new_ss > curr_ss) { + // Insert the node to current position in list + scan_list_node->next = + curr; + prev->next = + scan_list_node; + break; + } + prev = curr; + } + if (prev && (curr == NULL)) { + + // Insert the node to tail of the list + prev->next = scan_list_node; + scan_list_node->next = NULL; + } + } + } + } + + scan_start += prsp_info->scan_number; + } while (prsp_info->scan_number); + + // Display scan results + printf("---------------------------------------"); + printf("---------------------------------------\n"); + printf("# | ch | ss | bssid | cap | SSID \n"); + printf("---------------------------------------"); + printf("---------------------------------------\n"); + + for (curr = scan_list_head, idx = 0; + (curr != NULL) && ((unsigned int)idx < total_scan_res); + curr = curr->next, idx++) { + + fixed_fields = curr->fixed_buf.fixed_fields; + bss_info = &curr->bss_info_buf; + + printf("%02u| %03d | %03d | %02x:%02x:%02x:%02x:%02x:%02x |", + idx, + fixed_fields.channel, + 255 - fixed_fields.rssi, + fixed_fields.bssid[0], + fixed_fields.bssid[1], + fixed_fields.bssid[2], + fixed_fields.bssid[3], + fixed_fields.bssid[4], fixed_fields.bssid[5]); + + displayed_info = TRUE; + + /* "A" for Adhoc + * "I" for Infrastructure, + * "D" for DFS (Spectrum Mgmt) + */ + printf(" %c%c%c%c%c%c%c%c%c%c | ", bss_info->cap_info.ibss ? 'A' : 'I', bss_info->priv_cap, /* P (WEP), W (WPA), 2 (WPA2) */ + bss_info->cap_info.spectrum_mgmt ? 'D' : ' ', bss_info->wmm_cap, /* M (WMM), C (WMM-Call Admission Control) */ + bss_info->dot11k_cap, /* K */ + bss_info->dot11r_cap, /* R */ + bss_info->wps_cap, /* S */ + bss_info->ht_cap, /* N */ + bss_info->vht_cap[0], /* AC */ + bss_info->vht_cap[1]); + + /* Print out the ssid or the hex values if non-printable */ + for (ssid_idx = 0; ssid_idx < bss_info->ssid_len; ssid_idx++) { + if (isprint(bss_info->ssid[ssid_idx])) { + printf("%c", bss_info->ssid[ssid_idx]); + } else { + printf("\\%02x", bss_info->ssid[ssid_idx]); + } + } + + printf("\n"); + + if (argc > 3 && strcmp(argv[3], "tsf") == 0) { + /* TSF is a u64, some formatted printing libs have trouble + printing long longs, so cast and dump as bytes */ + pbyte = (t_u8 *)&fixed_fields.network_tsf; + printf(" TSF=%02x%02x%02x%02x%02x%02x%02x%02x\n", + pbyte[7], pbyte[6], pbyte[5], pbyte[4], + pbyte[3], pbyte[2], pbyte[1], pbyte[0]); + } + } + + if (displayed_info == TRUE) { + if (argc > 3 && strcmp(argv[3], "help") == 0) { + printf("\n\n" + "Capability Legend (Not all may be supported)\n" + "-----------------\n" + " I [ Infrastructure ]\n" + " A [ Ad-hoc ]\n" + " W [ WPA IE ]\n" + " 2 [ WPA2/RSN IE ]\n" + " M [ WMM IE ]\n" + " C [ Call Admission Control - WMM IE, VO ACM set ]\n" + " D [ Spectrum Management - DFS (11h) ]\n" + " K [ 11k ]\n" + " R [ 11r ]\n" + " S [ WPS ]\n" + " N [ HT (11n) ]\n" + " AC [VHT (11ac) ]\n" "\n\n"); + } + } else { + printf("< No Scan Results >\n"); + } + +done: + if (scan_rsp_buf) + free(scan_rsp_buf); + for (curr = scan_list_head; curr != NULL; curr = next) { + next = curr->next; + free(curr); + } + return ret; +} + +/** Maximum channel scratch */ +#define MAX_CHAN_SCRATCH 100 + +/** Maximum channel number for b/g band */ +#define MAX_CHAN_BG_BAND 14 + +/** Maximum number of probes to send on each channel */ +#define MAX_PROBES 4 + +/** Scan all the channels in specified band */ +#define BAND_SPECIFIED 0x80 +/** + * @brief Request a scan from the driver and display the scan table afterwards + * + * Command line interface for performing a specific immediate scan based + * on the following keyword parsing: + * + * chan=[chan#][band][mode] where band is [a,b,g,n] and mode is + * blank for active or 'p' for passive + * bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan + * ssid="[SSID]" specify a SSID filter for the scan + * keep=[0 or 1] keep the previous scan results (1), discard (0) + * dur=[scan time] time to scan for each channel in milliseconds + * probes=[#] number of probe requests to send on each chan + * type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any) + * + * Any combination of the above arguments can be supplied on the command line. + * If the chan token is absent, a full channel scan will be completed by + * the driver. If the dur or probes tokens are absent, the drivers default + * setting will be used. The bssid and ssid fields, if blank, + * will produce an unfiltered scan. The type field will default to 3 (Any) + * and the keep field will default to 0 (Discard). + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_setuserscan(int argc, char *argv[]) +{ + wlan_ioctl_user_scan_cfg scan_req; + int ioctl_val, subioctl_val; + struct iwreq iwr; + char *parg_tok; + char *pchan_tok; + char *parg_cookie; + char *pchan_cookie; + int arg_idx; + int chan_parse_idx; + int chan_cmd_idx; + char chan_scratch[MAX_CHAN_SCRATCH]; + char *pscratch; + int tmp_idx; + int scan_time; + int num_ssid; + int is_radio_set; + unsigned int mac[ETH_ALEN]; + + memset(&scan_req, 0x00, sizeof(scan_req)); + chan_cmd_idx = 0; + scan_time = 0; + num_ssid = 0; + + if (get_priv_ioctl("setuserscan", + &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + for (arg_idx = 0; arg_idx < argc; arg_idx++) { + + if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) { + /* + * "ssid" token string handler + */ + if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) { + strncpy(scan_req.ssid_list[num_ssid].ssid, + argv[arg_idx] + strlen("ssid="), + sizeof(scan_req.ssid_list[num_ssid]. + ssid)); + + scan_req.ssid_list[num_ssid].max_len = 0; + + num_ssid++; + } + } else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) == + 0) { + /* + * "bssid" token string handler + */ + sscanf(argv[arg_idx] + strlen("bssid="), + "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1, + mac + 2, mac + 3, mac + 4, mac + 5); + + for (tmp_idx = 0; + (unsigned int)tmp_idx < NELEMENTS(mac); + tmp_idx++) { + scan_req.specific_bssid[tmp_idx] = + (t_u8)mac[tmp_idx]; + } + } else if (strncmp(argv[arg_idx], "chan=", strlen("chan=")) == + 0) { + /* + * "chan" token string handler + */ + parg_tok = argv[arg_idx] + strlen("chan="); + + if (strlen(parg_tok) > MAX_CHAN_SCRATCH) { + printf("Error: Specified channels exceeds max limit\n"); + return MLAN_STATUS_FAILURE; + } + is_radio_set = FALSE; + + while ((parg_tok = + strtok_r(parg_tok, ",", + &parg_cookie)) != NULL) { + + memset(chan_scratch, 0x00, + sizeof(chan_scratch)); + pscratch = chan_scratch; + + for (chan_parse_idx = 0; + (unsigned int)chan_parse_idx < + strlen(parg_tok); chan_parse_idx++) { + if (isalpha + (*(parg_tok + chan_parse_idx))) { + *pscratch++ = ' '; + } + + *pscratch++ = + *(parg_tok + chan_parse_idx); + } + *pscratch = 0; + parg_tok = NULL; + + pchan_tok = chan_scratch; + + while ((pchan_tok = strtok_r(pchan_tok, " ", + &pchan_cookie)) != + NULL) { + if (isdigit(*pchan_tok)) { + scan_req. + chan_list[chan_cmd_idx]. + chan_number = + atoi(pchan_tok); + if (scan_req. + chan_list[chan_cmd_idx]. + chan_number > + MAX_CHAN_BG_BAND) + scan_req. + chan_list + [chan_cmd_idx]. + radio_type = 1; + } else { + switch (toupper(*pchan_tok)) { + case 'A': + scan_req. + chan_list + [chan_cmd_idx]. + radio_type = 1; + is_radio_set = TRUE; + break; + case 'B': + case 'G': + scan_req. + chan_list + [chan_cmd_idx]. + radio_type = 0; + is_radio_set = TRUE; + break; + case 'N': + break; + case 'P': + scan_req. + chan_list + [chan_cmd_idx]. + scan_type = + MLAN_SCAN_TYPE_PASSIVE; + break; + default: + printf("Error: Band type not supported!\n"); + return -EOPNOTSUPP; + } + if (!chan_cmd_idx && + !scan_req. + chan_list[chan_cmd_idx]. + chan_number && is_radio_set) + scan_req. + chan_list + [chan_cmd_idx]. + radio_type |= + BAND_SPECIFIED; + } + pchan_tok = NULL; + } + chan_cmd_idx++; + } + } else if (strncmp(argv[arg_idx], "keep=", strlen("keep=")) == + 0) { + /* + * "keep" token string handler + */ + scan_req.keep_previous_scan = + atoi(argv[arg_idx] + strlen("keep=")); + } else if (strncmp(argv[arg_idx], "dur=", strlen("dur=")) == 0) { + /* + * "dur" token string handler + */ + scan_time = atoi(argv[arg_idx] + strlen("dur=")); + scan_req.chan_list[0].scan_time = scan_time; + + } else if (strncmp(argv[arg_idx], "wc=", strlen("wc=")) == 0) { + + if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) { + /* + * "wc" token string handler + */ + pscratch = strrchr(argv[arg_idx], ','); + + if (pscratch) { + *pscratch = 0; + pscratch++; + + if (isdigit(*pscratch)) { + scan_req.ssid_list[num_ssid]. + max_len = + atoi(pscratch); + } else { + scan_req.ssid_list[num_ssid]. + max_len = *pscratch; + } + } else { + /* Standard wildcard matching */ + scan_req.ssid_list[num_ssid].max_len = + 0xFF; + } + + strncpy(scan_req.ssid_list[num_ssid].ssid, + argv[arg_idx] + strlen("wc="), + sizeof(scan_req.ssid_list[num_ssid]. + ssid)); + + num_ssid++; + } + } else if (strncmp(argv[arg_idx], "probes=", strlen("probes=")) + == 0) { + /* + * "probes" token string handler + */ + scan_req.num_probes = + atoi(argv[arg_idx] + strlen("probes=")); + if (scan_req.num_probes > MAX_PROBES) { + fprintf(stderr, "Invalid probes (> %d)\n", + MAX_PROBES); + return -EOPNOTSUPP; + } + } else if (strncmp(argv[arg_idx], "type=", strlen("type=")) == + 0) { + /* + * "type" token string handler + */ + scan_req.bss_mode = + atoi(argv[arg_idx] + strlen("type=")); + switch (scan_req.bss_mode) { + case MLAN_SCAN_MODE_BSS: + case MLAN_SCAN_MODE_IBSS: + break; + case MLAN_SCAN_MODE_ANY: + default: + /* Set any unknown types to ANY */ + scan_req.bss_mode = MLAN_SCAN_MODE_ANY; + break; + } + } + } + + /* + * Update all the channels to have the same scan time + */ + for (tmp_idx = 1; tmp_idx < chan_cmd_idx; tmp_idx++) { + scan_req.chan_list[tmp_idx].scan_time = scan_time; + } + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1); + iwr.u.data.pointer = (caddr_t) & scan_req; + iwr.u.data.length = sizeof(scan_req); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("mlanconfig: setuserscan ioctl"); + return -EFAULT; + } + + process_getscantable(0, 0); + + return MLAN_STATUS_SUCCESS; +} diff --git a/mwifiex_8997/mapp/mlanconfig/mlanmisc.h b/mwifiex_8997/mapp/mlanconfig/mlanmisc.h new file mode 100755 index 0000000..b646042 --- /dev/null +++ b/mwifiex_8997/mapp/mlanconfig/mlanmisc.h @@ -0,0 +1,681 @@ +/** @file mlanmisc.h + * + * @brief This file contains command definitions for application + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 03/10/2009: initial version +************************************************************************/ + +#ifndef _MLANMISC_H_ +#define _MLANMISC_H_ + +/** Maximum size of IEEE Information Elements */ +#define IEEE_MAX_IE_SIZE 256 + +/** Maximum scan response buffer size */ +#define SCAN_RESP_BUF_SIZE 2000 + +#ifdef FALSE +#undef FALSE +#endif + +#ifdef TRUE +#undef TRUE +#endif + +#ifndef MIN +/** Find minimum value */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +#ifndef MAX +/** Find maximum value */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif /* MAX */ + +/** Type enumeration of WMM AC_QUEUES */ +typedef enum _mlan_wmm_ac_e { + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VO +} __ATTRIB_PACK__ mlan_wmm_ac_e; + +/** Maximum length of SSID */ +#define MRVDRV_MAX_SSID_LENGTH 32 + +/** Enumeration for scan mode */ +enum { + MLAN_SCAN_MODE_UNCHANGED = 0, + MLAN_SCAN_MODE_BSS, + MLAN_SCAN_MODE_IBSS, + MLAN_SCAN_MODE_ANY +}; + +/** Enumeration for scan type */ +enum { + MLAN_SCAN_TYPE_UNCHANGED = 0, + MLAN_SCAN_TYPE_ACTIVE, + MLAN_SCAN_TYPE_PASSIVE +}; + +/** Length of ethernet address */ +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif +/** Maximum length of SSID list */ +#define MRVDRV_MAX_SSID_LIST_LENGTH 10 + +/** Maximum number of channels that can be sent in a setuserscan ioctl */ +#define WLAN_IOCTL_USER_SCAN_CHAN_MAX 50 + +/** IEEE Type definitions */ +typedef enum _IEEEtypes_ElementId_e { + SSID = 0, + SUPPORTED_RATES = 1, + FH_PARAM_SET = 2, + DS_PARAM_SET = 3, + CF_PARAM_SET = 4, + + IBSS_PARAM_SET = 6, + + COUNTRY_INFO = 7, + + POWER_CONSTRAINT = 32, + POWER_CAPABILITY = 33, + TPC_REQUEST = 34, + TPC_REPORT = 35, + SUPPORTED_CHANNELS = 36, + CHANNEL_SWITCH_ANN = 37, + QUIET = 40, + IBSS_DFS = 41, + HT_CAPABILITY = 45, + HT_OPERATION = 61, + BSSCO_2040 = 72, + OVERLAPBSSSCANPARAM = 74, + EXT_CAPABILITY = 127, + + VHT_CAPABILITY = 191, + VHT_OPERATION = 192, + EXT_BSS_LOAD = 193, + BW_CHANNEL_SWITCH = 194, + VHT_TX_POWER_ENV = 195, + EXT_POWER_CONSTR = 196, + AID_INFO = 197, + QUIET_CHAN = 198, + + ERP_INFO = 42, + EXTENDED_SUPPORTED_RATES = 50, + + VENDOR_SPECIFIC_221 = 221, + WMM_IE = VENDOR_SPECIFIC_221, + + WPS_IE = VENDOR_SPECIFIC_221, + + WPA_IE = VENDOR_SPECIFIC_221, + RSN_IE = 48, +} __ATTRIB_PACK__ IEEEtypes_ElementId_e; + +/** Capability Bit Map*/ +#ifdef BIG_ENDIAN_SUPPORT +typedef struct _IEEEtypes_CapInfo_t { + t_u8 rsrvd1:2; + t_u8 dsss_ofdm:1; + t_u8 rsvrd2:2; + t_u8 short_slot_time:1; + t_u8 rsrvd3:1; + t_u8 spectrum_mgmt:1; + t_u8 chan_agility:1; + t_u8 pbcc:1; + t_u8 short_preamble:1; + t_u8 privacy:1; + t_u8 cf_poll_rqst:1; + t_u8 cf_pollable:1; + t_u8 ibss:1; + t_u8 ess:1; +} __ATTRIB_PACK__ IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t; +#else +typedef struct _IEEEtypes_CapInfo_t { + /** Capability Bit Map : ESS */ + t_u8 ess:1; + /** Capability Bit Map : IBSS */ + t_u8 ibss:1; + /** Capability Bit Map : CF pollable */ + t_u8 cf_pollable:1; + /** Capability Bit Map : CF poll request */ + t_u8 cf_poll_rqst:1; + /** Capability Bit Map : privacy */ + t_u8 privacy:1; + /** Capability Bit Map : Short preamble */ + t_u8 short_preamble:1; + /** Capability Bit Map : PBCC */ + t_u8 pbcc:1; + /** Capability Bit Map : Channel agility */ + t_u8 chan_agility:1; + /** Capability Bit Map : Spectrum management */ + t_u8 spectrum_mgmt:1; + /** Capability Bit Map : Reserved */ + t_u8 rsrvd3:1; + /** Capability Bit Map : Short slot time */ + t_u8 short_slot_time:1; + /** Capability Bit Map : APSD */ + t_u8 apsd:1; + /** Capability Bit Map : Reserved */ + t_u8 rsvrd2:1; + /** Capability Bit Map : DSS OFDM */ + t_u8 dsss_ofdm:1; + /** Capability Bit Map : Reserved */ + t_u8 rsrvd1:2; +} __ATTRIB_PACK__ IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t; +#endif /* BIG_ENDIAN_SUPPORT */ + +/** IEEE IE header */ +typedef struct _IEEEtypes_Header_t { + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; +} __ATTRIB_PACK__ IEEEtypes_Header_t, *pIEEEtypes_Header_t; + +/** IEEE IE header */ +#define IEEE_HEADER_LEN sizeof(IEEEtypes_Header_t) + +/** Vendor specific IE header */ +typedef struct _IEEEtypes_VendorHeader_t { + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; + /** OUI */ + t_u8 oui[3]; + /** OUI type */ + t_u8 oui_type; + /** OUI subtype */ + t_u8 oui_subtype; + /** Version */ + t_u8 version; +} __ATTRIB_PACK__ IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t; + +/** Vendor specific IE */ +typedef struct _IEEEtypes_VendorSpecific_t { + /** Vendor specific IE header */ + IEEEtypes_VendorHeader_t vend_hdr; + /** IE Max - size of previous fields */ + t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)]; +} __ATTRIB_PACK__ IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t; + +/** IEEE IE */ +typedef struct _IEEEtypes_Generic_t { + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** IE Max - size of previous fields */ + t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)]; +} __ATTRIB_PACK__ IEEEtypes_Generic_t, *pIEEEtypes_Generic_t; + +/** Size of a TSPEC. Used to allocate necessary buffer space in commands */ +#define WMM_TSPEC_SIZE 63 + +/** Maximum number of AC QOS queues available in the driver/firmware */ +#define MAX_AC_QUEUES 4 + +/** Maximum number of User Priorities */ +#define MAX_USER_PRIORITIES 8 + +/** Extra IE bytes allocated in messages for appended IEs after a TSPEC */ +#define WMM_ADDTS_EXTRA_IE_BYTES 256 + +/** + * @brief Enumeration for the command result from an ADDTS or DELTS command + */ +typedef enum { + TSPEC_RESULT_SUCCESS = 0, + TSPEC_RESULT_EXEC_FAILURE = 1, + TSPEC_RESULT_TIMEOUT = 2, + TSPEC_RESULT_DATA_INVALID = 3, +} __ATTRIB_PACK__ mlan_wmm_tspec_result_e; + +/** + * @brief Enumeration for the action field in the Queue configure command + */ +typedef enum { + WMM_QUEUE_CONFIG_ACTION_GET = 0, + WMM_QUEUE_CONFIG_ACTION_SET = 1, + WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2, + + WMM_QUEUE_CONFIG_ACTION_MAX +} __ATTRIB_PACK__ mlan_wmm_queue_config_action_e; + +/** + * @brief Enumeration for the action field in the queue stats command + */ +typedef enum { + WMM_STATS_ACTION_START = 0, + WMM_STATS_ACTION_STOP = 1, + WMM_STATS_ACTION_GET_CLR = 2, + WMM_STATS_ACTION_SET_CFG = 3, /* Not currently used */ + WMM_STATS_ACTION_GET_CFG = 4, /* Not currently used */ + + WMM_STATS_ACTION_MAX +} __ATTRIB_PACK__ mlan_wmm_stats_action_e; + +/** Data structure of WMM Aci/Aifsn */ +typedef struct _IEEEtypes_WmmAciAifsn_t { +#ifdef BIG_ENDIAN_SUPPORT + /** Reserved */ + t_u8 reserved:1; + /** Aci */ + t_u8 aci:2; + /** Acm */ + t_u8 acm:1; + /** Aifsn */ + t_u8 aifsn:4; +#else + /** Aifsn */ + t_u8 aifsn:4; + /** Acm */ + t_u8 acm:1; + /** Aci */ + t_u8 aci:2; + /** Reserved */ + t_u8 reserved:1; +#endif +} __ATTRIB_PACK__ IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t; + +/** Data structure of WMM ECW */ +typedef struct _IEEEtypes_WmmEcw_t { +#ifdef BIG_ENDIAN_SUPPORT + /** Maximum Ecw */ + t_u8 ecw_max:4; + /** Minimum Ecw */ + t_u8 ecw_min:4; +#else + /** Minimum Ecw */ + t_u8 ecw_min:4; + /** Maximum Ecw */ + t_u8 ecw_max:4; +#endif +} __ATTRIB_PACK__ IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t; + +/** Data structure of WMM AC parameters */ +typedef struct _IEEEtypes_WmmAcParameters_t { + IEEEtypes_WmmAciAifsn_t aci_aifsn; /**< AciAifSn */ + IEEEtypes_WmmEcw_t ecw; /**< Ecw */ + t_u16 tx_op_limit; /**< Tx op limit */ +} __ATTRIB_PACK__ IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t; + +/** Data structure of WMM Info IE */ +typedef struct _IEEEtypes_WmmInfo_t { + + /** + * WMM Info IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [7] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [0] + * Version [1] + */ + IEEEtypes_VendorHeader_t vend_hdr; + + /** QoS information */ + IEEEtypes_WmmQosInfo_t qos_info; + +} __ATTRIB_PACK__ IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t; + +/** Data structure of WMM parameter IE */ +typedef struct _IEEEtypes_WmmParameter_t { + /** + * WMM Parameter IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [24] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [1] + * Version [1] + */ + IEEEtypes_VendorHeader_t vend_hdr; + + /** QoS information */ + IEEEtypes_WmmQosInfo_t qos_info; + /** Reserved */ + t_u8 reserved; + + /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */ + IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES]; + +} __ATTRIB_PACK__ IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t; + +/** + * @brief IOCTL structure to send an ADDTS request and retrieve the response. + * + * IOCTL structure from the application layer relayed to firmware to + * instigate an ADDTS management frame with an appropriate TSPEC IE as well + * as any additional IEs appended in the ADDTS Action frame. + * + * @sa wlan_wmm_addts_req_ioctl + */ +typedef struct { + mlan_wmm_tspec_result_e commandResult; + /**< Firmware execution result */ + + t_u32 timeout_ms; /**< Timeout value in milliseconds */ + t_u8 ieeeStatusCode; /**< IEEE status code */ + + t_u32 ieDataLen; + t_u8 ieData[WMM_TSPEC_SIZE + /**< TSPEC to send in the ADDTS */ + + WMM_ADDTS_EXTRA_IE_BYTES]; + /**< ADDTS extra IE buf */ +} wlan_ioctl_wmm_addts_req_t; + +/** + * @brief IOCTL structure to send a DELTS request. + * + * IOCTL structure from the application layer relayed to firmware to + * instigate an DELTS management frame with an appropriate TSPEC IE. + * + * @sa wlan_wmm_delts_req_ioctl + */ +typedef struct { + mlan_wmm_tspec_result_e commandResult; + /**< Firmware execution result */ + t_u8 ieeeReasonCode; /**< IEEE reason code sent, unused for WMM */ + + t_u32 ieDataLen; + t_u8 ieData[WMM_TSPEC_SIZE]; + /**< TSPEC to send in the DELTS */ +} wlan_ioctl_wmm_delts_req_t; + +/** + * @brief IOCTL structure to configure a specific AC Queue's parameters + * + * IOCTL structure from the application layer relayed to firmware to + * get, set, or default the WMM AC queue parameters. + * + * - msduLifetimeExpiry is ignored if set to 0 on a set command + * + * @sa wlan_wmm_queue_config_ioctl + */ +typedef struct { + mlan_wmm_queue_config_action_e action; + /**< Set, Get, or Default */ + mlan_wmm_ac_e accessCategory; /**< WMM_AC_BK(0) to WMM_AC_VO(3) */ + t_u16 msduLifetimeExpiry; /**< lifetime expiry in TUs */ + t_u8 supportedRates[10]; /**< Not supported yet */ +} wlan_ioctl_wmm_queue_config_t; + +/** Number of bins in the histogram for the HostCmd_DS_WMM_QUEUE_STATS */ +#define WMM_STATS_PKTS_HIST_BINS 7 + +/** + * @brief IOCTL structure to start, stop, and get statistics for a WMM AC + * + * IOCTL structure from the application layer relayed to firmware to + * start or stop statistical collection for a given AC. Also used to + * retrieve and clear the collected stats on a given AC. + * + * @sa wlan_wmm_queue_stats_ioctl + */ +typedef struct { + mlan_wmm_stats_action_e action; + /**< Start, Stop, or Get */ + t_u8 userPriority; + /**< User Priority (0 to 7) */ + t_u16 pktCount; /**< Number of successful packets transmitted */ + t_u16 pktLoss; /**< Packets lost; not included in pktCount */ + t_u32 avgQueueDelay; + /**< Average Queue delay in microseconds */ + t_u32 avgTxDelay;/**< Average Transmission delay in microseconds */ + t_u16 usedTime; /**< Calculated used time - units of 32 microsec */ + t_u16 policedTime; + /**< Calculated policed time - units of 32 microsec */ + + /** @brief Queue Delay Histogram; number of packets per queue delay range + * + * [0] - 0ms <= delay < 5ms + * [1] - 5ms <= delay < 10ms + * [2] - 10ms <= delay < 20ms + * [3] - 20ms <= delay < 30ms + * [4] - 30ms <= delay < 40ms + * [5] - 40ms <= delay < 50ms + * [6] - 50ms <= delay < msduLifetime (TUs) + */ + t_u16 delayHistogram[WMM_STATS_PKTS_HIST_BINS]; +} wlan_ioctl_wmm_queue_stats_t; + +/** + * @brief IOCTL and command sub structure for a Traffic stream status. + */ +typedef struct { + t_u8 tid; /**< TSID: Range: 0->7 */ + t_u8 valid; /**< TSID specified is valid */ + t_u8 accessCategory;/**< AC TSID is active on */ + t_u8 userPriority; /**< UP specified for the TSID */ + + t_u8 psb; /**< Power save mode for TSID: 0 (legacy), 1 (UAPSD) */ + t_u8 flowDir; /**< Upstream (0), Downlink(1), Bidirectional(3) */ + t_u16 mediumTime; /**< Medium time granted for the TSID */ +} __ATTRIB_PACK__ HostCmd_DS_WMM_TS_STATUS, + wlan_ioctl_wmm_ts_status_t, wlan_cmd_wmm_ts_status_t; + +/** + * @brief IOCTL sub structure for a specific WMM AC Status + */ +typedef struct { + /** WMM Acm */ + t_u8 wmmAcm; + /** Flow required flag */ + t_u8 flowRequired; + /** Flow created flag */ + t_u8 flowCreated; + /** Disabled flag */ + t_u8 disabled; + /** delivery enabled */ + t_u8 deliveryEnabled; + /** trigger enabled */ + t_u8 triggerEnabled; +} wlan_ioctl_wmm_queue_status_ac_t; + +/** + * @brief IOCTL structure to retrieve the WMM AC Queue status + * + * IOCTL structure from the application layer to retrieve: + * - ACM bit setting for the AC + * - Firmware status (flow required, flow created, flow disabled) + * + * @sa wlan_wmm_queue_status_ioctl + */ +typedef struct { + /** WMM AC queue status */ + wlan_ioctl_wmm_queue_status_ac_t acStatus[MAX_AC_QUEUES]; +} wlan_ioctl_wmm_queue_status_t; + +typedef struct _wlan_get_scan_table_fixed { + /** BSSID of this network */ + t_u8 bssid[MLAN_MAC_ADDR_LENGTH]; + /** Channel this beacon/probe response was detected */ + t_u8 channel; + /** RSSI for the received packet */ + t_u8 rssi; + /** TSF value from the firmware at packet reception */ + t_u64 network_tsf; +} wlan_get_scan_table_fixed; + +/** + * Structure passed in the wlan_ioctl_get_scan_table_info for each + * BSS returned in the WLAN_GET_SCAN_RESP IOCTL + */ +typedef struct _wlan_ioctl_get_scan_table_entry { + /** + * Fixed field length included in the response. + * + * Length value is included so future fixed fields can be added to the + * response without breaking backwards compatibility. Use the length + * to find the offset for the bssInfoLength field, not a sizeof() calc. + */ + t_u32 fixed_field_length; + + /** + * Length of the BSS Information (probe resp or beacon) that + * follows after the fixed_field_length + */ + t_u32 bss_info_length; + + /** + * Always present, fixed length data fields for the BSS + */ + wlan_get_scan_table_fixed fixed_fields; + + /* + * Probe response or beacon scanned for the BSS. + * + * Field layout: + * - TSF 8 octets + * - Beacon Interval 2 octets + * - Capability Info 2 octets + * + * - IEEE Infomation Elements; variable number & length per 802.11 spec + */ + /* t_u8 bss_info_buffer[1]; */ +} wlan_ioctl_get_scan_table_entry; + +/** + * Structure to store BSS info (probe resp or beacon) & IEEE IE info for each + * BSS returned in WLAN_GET_SCAN_RESP IOCTL + */ +typedef struct _wlan_ioctl_get_bss_info { + /** + * Length of the BSS Information (probe resp or beacon) that + * follows after the fixed_field + */ + t_u32 bss_info_length; + + /** + * Probe response or beacon scanned for the BSS. + * + * Field layout: + */ + /** TSF 8 octets */ + t_u8 tsf[8]; + /** Beacon Interval 2 octets */ + t_u16 beacon_interval; + /** Capability Info 2 octets */ + IEEEtypes_CapInfo_t cap_info; + + /** + * IEEE Infomation Elements; variable number & length per 802.11 spec + */ + /** SSID */ + char ssid[MRVDRV_MAX_SSID_LENGTH + 1]; + /** SSID Length */ + t_u32 ssid_len; + /** WMM Capability */ + char wmm_cap; + /** WPS Capability */ + char wps_cap; + /** Privacy Capability - WEP/WPA/RSN */ + char priv_cap; + /** HT (11N) Capability */ + char ht_cap; + /** VHT (11AC) Capability */ + char vht_cap[2]; + /* 802.11k Capability */ + char dot11k_cap; + /** 802.11r Capability */ + char dot11r_cap; +} wlan_ioctl_get_bss_info; + +/** + * Structure to save of scan table info for each BSS returned + * in WLAN_GET_SCAN_RESP IOCTL + */ +struct wlan_ioctl_get_scan_list { + /** fixed info */ + wlan_ioctl_get_scan_table_entry fixed_buf; + /** variable info - BSS info (probe resp or beacon) & IEEE IE info */ + wlan_ioctl_get_bss_info bss_info_buf; + /** pointer to next node in list */ + struct wlan_ioctl_get_scan_list *next; +}; + +/** + * Sructure to retrieve the scan table + */ +typedef struct { + /** + * - Zero based scan entry to start retrieval in command request + * - Number of scans entries returned in command response + */ + t_u32 scan_number; + /** + * Buffer marker for multiple wlan_ioctl_get_scan_table_entry structures. + * Each struct is padded to the nearest 32 bit boundary. + */ + t_u8 scan_table_entry_buf[1]; + +} wlan_ioctl_get_scan_table_info; + +typedef struct { + t_u8 chan_number; + /**< Channel Number to scan */ + t_u8 radio_type; + /**< Radio type: 'B/G' Band = 0, 'A' Band = 1 */ + t_u8 scan_type;/**< Scan type: Active = 1, Passive = 2 */ + t_u8 reserved;/**< Reserved */ + t_u32 scan_time; + /**< Scan duration in milliseconds; if 0 default used */ +} __ATTRIB_PACK__ wlan_ioctl_user_scan_chan; + +typedef struct { + char ssid[MRVDRV_MAX_SSID_LENGTH + 1]; + /**< SSID */ + t_u8 max_len; /**< Maximum length of SSID */ +} __ATTRIB_PACK__ wlan_ioctl_user_scan_ssid; + +typedef struct { + + /** Flag set to keep the previous scan table intact */ + t_u8 keep_previous_scan; /* Do not erase the existing scan results */ + + /** BSS mode to be sent in the firmware command */ + t_u8 bss_mode; + + /** Configure the number of probe requests for active chan scans */ + t_u8 num_probes; + + /** Reserved */ + t_u8 reserved; + + /** BSSID filter sent in the firmware command to limit the results */ + t_u8 specific_bssid[ETH_ALEN]; + + /** SSID filter list used in the to limit the scan results */ + wlan_ioctl_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH]; + + /** Variable number (fixed maximum) of channels to scan up */ + wlan_ioctl_user_scan_chan chan_list[WLAN_IOCTL_USER_SCAN_CHAN_MAX]; + +} __ATTRIB_PACK__ wlan_ioctl_user_scan_cfg; + +int process_setuserscan(int argc, char *argv[]); +int process_getscantable(int argc, char *argv[]); +int process_getscantable_idx(wlan_ioctl_get_scan_table_info *prsp_info_req); + +#endif /* _MLANMISC_H_ */ diff --git a/mwifiex_8997/mapp/mlanevent/Makefile b/mwifiex_8997/mapp/mlanevent/Makefile new file mode 100755 index 0000000..fe96718 --- /dev/null +++ b/mwifiex_8997/mapp/mlanevent/Makefile @@ -0,0 +1,51 @@ +# File : mlanevent/Makefile +# +# Copyright (C) 2008-2019, Marvell International Ltd. All Rights Reserved + +# Path to the top directory of the wlan distribution +PATH_TO_TOP = ../.. + +# Determine how we should copy things to the install directory +ABSPATH := $(filter /%, $(INSTALLDIR)) +RELPATH := $(filter-out /%, $(INSTALLDIR)) +INSTALLPATH := $(ABSPATH) +ifeq ($(strip $(INSTALLPATH)),) +INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH) +endif + +# Override CFLAGS for application sources, remove __ kernel namespace defines +CFLAGS := $(filter-out -D__%, $(ccflags-y)) +# remove KERNEL include dir +CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS)) + + +#CFLAGS += -DAP22 -fshort-enums +CFLAGS += -Wall +#ECHO = @ +LIBS = -lrt + +.PHONY: default tags all + +OBJECTS = mlanevent.o +HEADERS = mlanevent.h + +TARGET = mlanevent.exe + +build default: $(TARGET) + @cp -f $(TARGET) $(INSTALLPATH) + +all : tags default + +$(TARGET): $(OBJECTS) $(HEADERS) + $(ECHO)$(CC) $(LIBS) -o $@ $(OBJECTS) + +%.o: %.c $(HEADERS) + $(ECHO)$(CC) $(CFLAGS) -c -o $@ $< + +tags: + ctags -R -f tags.txt + +distclean clean: + $(ECHO)$(RM) $(OBJECTS) $(TARGET) + $(ECHO)$(RM) tags.txt + diff --git a/mwifiex_8997/mapp/mlanevent/mlanevent.c b/mwifiex_8997/mapp/mlanevent/mlanevent.c new file mode 100755 index 0000000..68801e1 --- /dev/null +++ b/mwifiex_8997/mapp/mlanevent/mlanevent.c @@ -0,0 +1,2775 @@ +/** @file mlanevent.c + * + * @brief Program to receive events from the driver/firmware of the uAP + * driver. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/**************************************************************************** +Change log: + 03/18/08: Initial creation +****************************************************************************/ + +/**************************************************************************** + Header files +****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "mlanevent.h" +#ifdef WIFI_DIRECT_SUPPORT +#include +#endif + +/**************************************************************************** + Definitions +****************************************************************************/ +/** Enable or disable debug outputs */ +#define DEBUG 1 + +int debug_level = MSG_NONE; +/**************************************************************************** + Global variables +****************************************************************************/ +/** Termination flag */ +int terminate_flag = 0; + +/**************************************************************************** + Local functions +****************************************************************************/ +#if DEBUG +/** + * @brief Conditional printf + * + * @param level Severity level of the message + * @param fmt Printf format string, followed by optional arguments + */ +void +mlanevent_printf(int level, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (level <= debug_level) { + vprintf(fmt, ap); + } + va_end(ap); +} + +static void +mlanevent_hexdump(int level, void *p, t_s32 len, char delim) +{ + t_s32 i; + t_u8 *s = p; + if (level <= debug_level) { + for (i = 0; i < len; i++) { + if (i != len - 1) + printf("%02x%c", *s++, delim); + else + printf("%02x\n", *s); + if ((i + 1) % 16 == 0) + printf("\n"); + } + } +} +#endif + +/** + * @brief Signal handler + * + * @param sig Received signal number + * @return N/A + */ +void +sig_handler(int sig) +{ + printf("Stopping application.\n"); +#if DEBUG + mlanevent_printf(MSG_DEBUG, "Process ID of process killed = %d\n", + getpid()); +#endif + terminate_flag = 1; +} + +/** + * @brief Dump hex data + * + * @param p A pointer to data buffer + * @param len The len of data buffer + * @param delim Deliminator character + * @return Hex integer + */ +static void +hexdump(void *p, t_s32 len, char delim) +{ + t_s32 i; + t_u8 *s = p; + for (i = 0; i < len; i++) { + if (i != len - 1) + printf("%02x%c", *s++, delim); + else + printf("%02x\n", *s); + if ((i + 1) % 16 == 0) + printf("\n"); + } +} + +/** + * @brief Hex to number + * + * @param c Hex value + * @return Integer value or -1 + */ +int +hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return -1; +} + +/** + * @brief Check hex string + * + * @param hex A pointer to hex string + * @return 0 or MLAN_EVENT_FAILURE + */ +int +ishexstring(void *hex) +{ + int i, a; + char *p = hex; + int len = strlen(p); + if (!strncasecmp("0x", p, 2)) { + p += 2; + len -= 2; + } + for (i = 0; i < len; i++) { + a = hex2num(*p); + if (a < 0) + return MLAN_EVENT_FAILURE; + p++; + } + return 0; +} + +/** + * @brief Convert char to hex integer + * + * @param chr Char + * @return Hex integer + */ +unsigned char +hexc2bin(char chr) +{ + if (chr >= '0' && chr <= '9') + chr -= '0'; + else if (chr >= 'A' && chr <= 'F') + chr -= ('A' - 10); + else if (chr >= 'a' && chr <= 'f') + chr -= ('a' - 10); + + return chr; +} + +/** + * @brief Convert string to hex integer + * + * @param s A pointer string buffer + * @return Hex integer + */ +unsigned int +a2hex(char *s) +{ + unsigned int val = 0; + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + while (*s && isxdigit(*s)) { + val = (val << 4) + hexc2bin(*s++); + } + return val; +} + +/** + * @brief Prints a MAC address in colon separated form from raw data + * + * @param raw A pointer to the hex data buffer + * @return N/A + */ +void +print_mac(t_u8 *raw) +{ + printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0], + (unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3], + (unsigned int)raw[4], (unsigned int)raw[5]); + return; +} + +/** + * @brief Print usage information + * + * @return N/A + */ +void +print_usage(void) +{ + printf("\n"); + printf("Usage : mlanevent.exe [-v] [-h]\n"); + printf(" -v : Print version information\n"); + printf(" -h : Print help information\n"); + printf(" -d : Set debug level: 0|1|2\n"); + printf(" -i : Specify device number from 0 to %d\n", + MAX_NO_OF_DEVICES - 1); + printf(" 0xff for all devices\n"); + printf("\n"); +} + +/** + * @brief Parse and print STA deauthentication event data + * + * @param buffer Pointer to received event buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_sta_deauth(t_u8 *buffer, t_u16 size) +{ + eventbuf_sta_deauth *event_body = NULL; + + if (size < sizeof(eventbuf_sta_deauth)) { + printf("ERR:Event buffer too small!\n"); + return; + } + event_body = (eventbuf_sta_deauth *)buffer; + event_body->reason_code = uap_le16_to_cpu(event_body->reason_code); + printf("EVENT: STA_DEAUTH\n"); + printf("Deauthenticated STA MAC: "); + print_mac(event_body->sta_mac_address); + printf("\nReason: "); + switch (event_body->reason_code) { + case 1: + printf("Client station leaving the network\n"); + break; + case 2: + printf("Client station aged out\n"); + break; + case 3: + printf("Client station deauthenticated by user's request\n"); + break; + case 4: + printf("Client station authentication failure\n"); + break; + case 5: + printf("Client station association failure\n"); + break; + case 6: + printf("Client mac address is blocked by ACL filter\n"); + break; + case 7: + printf("Client station table is full\n"); + break; + case 8: + printf("Client 4-way handshake timeout\n"); + break; + case 9: + printf("Client group key handshake timeout\n"); + break; + default: + printf("Unspecified\n"); + break; + } + return; +} + +/** + * @brief Parse and print WEP ICV error event data + * + * @param buffer Pointer to received event buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_wep_icv_error(t_u8 *buffer, t_u16 size) +{ + int i = 0; + eventbuf_wep_icv_error *event_body = NULL; + + if (size < sizeof(eventbuf_wep_icv_error)) { + printf("ERR:Event buffer too small!\n"); + return; + } + event_body = (eventbuf_wep_icv_error *)buffer; + event_body->reason_code = uap_le16_to_cpu(event_body->reason_code); + printf("EVENT: WEP_ICV_ERROR\n"); + printf("Deauthenticated STA MAC: "); + print_mac(event_body->sta_mac_address); + printf("WEP key index = %d\n", event_body->wep_key_index); + printf("WEP key length = %d\n", event_body->wep_key_length); + printf("WEP key : \n"); + for (i = 0; i < event_body->wep_key_length; i++) { + printf("%02x ", event_body->wep_key[i]); + } + printf("\n"); + return; +} + +/** + * @brief Prints mgmt frame + * + * @param mgmt_tlv A pointer to mgmt_tlv + * @param tlv_len Length of tlv payload + * @return N/A + */ +void +print_mgmt_frame(MrvlIETypes_MgmtFrameSet_t *mgmt_tlv, int tlv_len) +{ + IEEEtypes_AssocRqst_t *assoc_req = NULL; + IEEEtypes_ReAssocRqst_t *reassoc_req = NULL; + IEEEtypes_AssocRsp_t *assoc_resp = NULL; + t_u16 frm_ctl = 0; + printf("\nMgmt Frame:\n"); + memcpy(&frm_ctl, &mgmt_tlv->frame_control, sizeof(t_u16)); + printf("FrameControl: 0x%x\n", frm_ctl); + if (mgmt_tlv->frame_control.type != 0) { + printf("Frame type=%d subtype=%d:\n", + mgmt_tlv->frame_control.type, + mgmt_tlv->frame_control.sub_type); + hexdump(mgmt_tlv->frame_contents, tlv_len - sizeof(t_u16), ' '); + return; + } + switch (mgmt_tlv->frame_control.sub_type) { + case SUBTYPE_ASSOC_REQUEST: + printf("Assoc Request:\n"); + assoc_req = (IEEEtypes_AssocRqst_t *)mgmt_tlv->frame_contents; + printf("CapInfo: 0x%x ListenInterval: 0x%x \n", + uap_le16_to_cpu(assoc_req->cap_info), + uap_le16_to_cpu(assoc_req->listen_interval)); + printf("AssocReqIE:\n"); + hexdump(assoc_req->ie_buffer, + tlv_len - sizeof(IEEEtypes_AssocRqst_t) + - sizeof(IEEEtypes_FrameCtl_t), ' '); + break; + case SUBTYPE_REASSOC_REQUEST: + printf("ReAssoc Request:\n"); + reassoc_req = + (IEEEtypes_ReAssocRqst_t *)mgmt_tlv->frame_contents; + printf("CapInfo: 0x%x ListenInterval: 0x%x \n", + uap_le16_to_cpu(reassoc_req->cap_info), + uap_le16_to_cpu(reassoc_req->listen_interval)); + printf("Current AP address: "); + print_mac(reassoc_req->current_ap_addr); + printf("\nReAssocReqIE:\n"); + hexdump(reassoc_req->ie_buffer, + tlv_len - sizeof(IEEEtypes_ReAssocRqst_t) + - sizeof(IEEEtypes_FrameCtl_t), ' '); + break; + case SUBTYPE_ASSOC_RESPONSE: + case SUBTYPE_REASSOC_RESPONSE: + if (mgmt_tlv->frame_control.sub_type == SUBTYPE_ASSOC_RESPONSE) + printf("Assoc Response:\n"); + else + printf("ReAssoc Response:\n"); + assoc_resp = (IEEEtypes_AssocRsp_t *)mgmt_tlv->frame_contents; + printf("CapInfo: 0x%x StatusCode: %d AID: 0x%x \n", + uap_le16_to_cpu(assoc_resp->cap_info), + (int)(uap_le16_to_cpu(assoc_resp->status_code)), + uap_le16_to_cpu(assoc_resp->aid) & 0x3fff); + break; + default: + printf("Frame subtype = %d:\n", + mgmt_tlv->frame_control.sub_type); + hexdump(mgmt_tlv->frame_contents, tlv_len - sizeof(t_u16), ' '); + break; + } + return; +} + +/** + * @brief Parse and print RSN connect event data + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_rsn_connect(t_u8 *buffer, t_u16 size) +{ + int tlv_buf_left = size; + t_u16 tlv_type, tlv_len; + tlvbuf_header *tlv = NULL; + eventbuf_rsn_connect *event_body = NULL; + if (size < sizeof(eventbuf_rsn_connect)) { + printf("ERR:Event buffer too small!\n"); + return; + } + event_body = (eventbuf_rsn_connect *)buffer; + printf("EVENT: RSN_CONNECT\n"); + printf("Station MAC: "); + print_mac(event_body->sta_mac_address); + printf("\n"); + tlv_buf_left = size - sizeof(eventbuf_rsn_connect); + if (tlv_buf_left < (int)sizeof(tlvbuf_header)) + return; + tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_rsn_connect)); + + while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) { + tlv_type = uap_le16_to_cpu(tlv->type); + tlv_len = uap_le16_to_cpu(tlv->len); + if ((sizeof(tlvbuf_header) + tlv_len) > + (unsigned int)tlv_buf_left) { + printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, + tlv_buf_left); + break; + } + switch (tlv_type) { + case IEEE_WPA_IE: + printf("WPA IE:\n"); + hexdump((t_u8 *)tlv + sizeof(tlvbuf_header), tlv_len, + ' '); + break; + case IEEE_RSN_IE: + printf("RSN IE:\n"); + hexdump((t_u8 *)tlv + sizeof(tlvbuf_header), tlv_len, + ' '); + break; + default: + printf("unknown tlv: %d\n", tlv_type); + break; + } + tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len); + tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len + + sizeof(tlvbuf_header)); + } + return; +} + +/** + * @brief Parse and print STA associate event data + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_sta_assoc(t_u8 *buffer, t_u16 size) +{ + int tlv_buf_left = size; + t_u16 tlv_type, tlv_len; + tlvbuf_header *tlv = NULL; + MrvlIEtypes_WapiInfoSet_t *wapi_tlv = NULL; + MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = NULL; + eventbuf_sta_assoc *event_body = NULL; + if (size < sizeof(eventbuf_sta_assoc)) { + printf("ERR:Event buffer too small!\n"); + return; + } + event_body = (eventbuf_sta_assoc *)buffer; + printf("EVENT: STA_ASSOCIATE\n"); + printf("Associated STA MAC: "); + print_mac(event_body->sta_mac_address); + printf("\n"); + tlv_buf_left = size - sizeof(eventbuf_sta_assoc); + if (tlv_buf_left < (int)sizeof(tlvbuf_header)) + return; + tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_sta_assoc)); + + while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) { + tlv_type = uap_le16_to_cpu(tlv->type); + tlv_len = uap_le16_to_cpu(tlv->len); + if ((sizeof(tlvbuf_header) + tlv_len) > + (unsigned int)tlv_buf_left) { + printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, + tlv_buf_left); + break; + } + switch (tlv_type) { + case MRVL_WAPI_INFO_TLV_ID: + wapi_tlv = (MrvlIEtypes_WapiInfoSet_t *)tlv; + printf("WAPI Multicast PN:\n"); + hexdump(wapi_tlv->multicast_PN, tlv_len, ' '); + break; + case MRVL_MGMT_FRAME_TLV_ID: + mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv; + print_mgmt_frame(mgmt_tlv, tlv_len); + break; + default: + printf("unknown tlv: %d\n", tlv_type); + break; + } + tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len); + tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len + + sizeof(tlvbuf_header)); + } + return; +} + +/** + * @brief Parse and print BSS start event data + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_bss_start(t_u8 *buffer, t_u16 size) +{ + eventbuf_bss_start *event_body = NULL; + int tlv_buf_left = size; + t_u16 tlv_type, tlv_len; + tlvbuf_header *tlv = NULL; + tlvbuf_channel_config *channel_tlv = NULL; + + if (size < sizeof(eventbuf_bss_start)) { + printf("ERR:Event buffer too small!\n"); + return; + } + event_body = (eventbuf_bss_start *)buffer; + printf("EVENT: BSS_START "); + printf("BSS MAC: "); + print_mac(event_body->ap_mac_address); + printf("\n"); + tlv_buf_left = size - sizeof(eventbuf_bss_start); + if (tlv_buf_left < (int)sizeof(tlvbuf_header)) + return; + tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_bss_start)); + + while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) { + tlv_type = uap_le16_to_cpu(tlv->type); + tlv_len = uap_le16_to_cpu(tlv->len); + if ((sizeof(tlvbuf_header) + tlv_len) > + (unsigned int)tlv_buf_left) { + printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, + tlv_buf_left); + break; + } + switch (tlv_type) { + case MRVL_CHANNELCONFIG_TLV_ID: + channel_tlv = (tlvbuf_channel_config *)tlv; + printf("Channel = %d\n", channel_tlv->chan_number); + printf("Band = %s\n", + (channel_tlv->bandcfg.chanBand == + BAND_5GHZ) ? "5GHz" : "2.4GHz"); + printf("Channel Select Mode = %s\n", + (channel_tlv->bandcfg.scanMode == + SCAN_MODE_ACS) ? "ACS" : "Manual"); + if (channel_tlv->bandcfg.chan2Offset == SEC_CHAN_NONE) + printf("no secondary channel\n"); + else if (channel_tlv->bandcfg.chan2Offset == + SEC_CHAN_ABOVE) + printf("secondary channel is above primary channel\n"); + else if (channel_tlv->bandcfg.chan2Offset == + SEC_CHAN_BELOW) + printf("secondary channel is below primary channel\n"); + break; + default: +#if DEBUG + mlanevent_printf(MSG_DEBUG, "unknown tlv: %d\n", + tlv_type); +#endif + break; + } + tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len); + tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len + + sizeof(tlvbuf_header)); + } + + return; +} + +#ifdef WIFI_DIRECT_SUPPORT +/** + * @brief Print WIFI_WPS IE elements from event payload + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_wifi_wps_ie_elements(t_u8 *buffer, t_u16 size) +{ + t_u8 *ptr = buffer; + t_u8 *array_ptr; + int i; + t_u16 wps_len = 0, wps_type = 0; + t_u16 ie_len_wps = size; + + while (ie_len_wps > sizeof(tlvbuf_wps_ie)) { + memcpy(&wps_type, ptr, sizeof(t_u16)); + memcpy(&wps_len, ptr + 2, sizeof(t_u16)); + endian_convert_tlv_wps_header_in(wps_type, wps_len); + switch (wps_type) { + case SC_Version: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + printf("\t WPS Version = 0x%2x\n", + *(wps_tlv->data)); + } + break; + case SC_Simple_Config_State: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + printf("\t WPS setupstate = 0x%x\n", + *(wps_tlv->data)); + } + break; + case SC_Request_Type: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + printf("\t WPS RequestType = 0x%x\n", + *(wps_tlv->data)); + } + break; + case SC_Response_Type: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + printf("\t WPS ResponseType = 0x%x\n", + *(wps_tlv->data)); + } + break; + case SC_Config_Methods: + { + t_u16 wps_config_methods = 0; + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + memcpy(&wps_config_methods, wps_tlv->data, + sizeof(t_u16)); + wps_config_methods = ntohs(wps_config_methods); + printf("\t WPS SpecConfigMethods = 0x%x\n", + wps_config_methods); + } + break; + case SC_UUID_E: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS UUID = "); + for (i = 0; i < wps_len; i++) + printf("0x%02X ", *array_ptr++); + printf("\n"); + } + break; + case SC_Primary_Device_Type: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS Primary Device Type = "); + for (i = 0; i < wps_len; i++) + printf("0x%02X ", *array_ptr++); + printf("\n"); + } + break; + case SC_RF_Band: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + printf("\t WPS RF Band = 0x%x\n", + *(wps_tlv->data)); + } + break; + case SC_Association_State: + { + t_u16 wps_association_state = 0; + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + memcpy(&wps_association_state, wps_tlv->data, + sizeof(t_u16)); + wps_association_state = + ntohs(wps_association_state); + printf("\t WPS Association State = 0x%x\n", + wps_association_state); + } + break; + case SC_Configuration_Error: + { + t_u16 wps_configuration_error = 0; + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + memcpy(&wps_configuration_error, wps_tlv->data, + sizeof(t_u16)); + wps_configuration_error = + ntohs(wps_configuration_error); + printf("\t WPS Configuration Error = 0x%x\n", + wps_configuration_error); + } + break; + case SC_Device_Password_ID: + { + t_u16 wps_device_password_id = 0; + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + memcpy(&wps_device_password_id, wps_tlv->data, + sizeof(t_u16)); + wps_device_password_id = + ntohs(wps_device_password_id); + printf("\t WPS Device Password ID = 0x%x\n", + wps_device_password_id); + } + break; + case SC_Device_Name: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS Device Name = "); + for (i = 0; i < wps_len; i++) + printf("%c", *array_ptr++); + printf("\n"); + } + break; + case SC_Manufacturer: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS Manufacturer = "); + for (i = 0; i < wps_len; i++) + printf("%c", *array_ptr++); + printf("\n"); + } + break; + case SC_Model_Name: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS Model Name = "); + for (i = 0; i < wps_len; i++) + printf("%c", *array_ptr++); + printf("\n"); + } + break; + case SC_Model_Number: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS Model Number = "); + for (i = 0; i < wps_len; i++) + printf("%c", *array_ptr++); + printf("\n"); + } + break; + case SC_Serial_Number: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS Serial Number = "); + for (i = 0; i < wps_len; i++) + printf("%c", *array_ptr++); + printf("\n"); + } + break; + case SC_Vendor_Extension: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + array_ptr = wps_tlv->data; + printf("\t WPS 2.0 Vendor Extension = "); + for (i = 0; i < wps_len; i++) + printf("%x", *array_ptr++); + printf("\n"); + } + break; + case SC_Selected_Registrar: + { + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + printf("\t Selected Registrar = %d\n", + *(wps_tlv->data)); + } + break; + case SC_SelectedRegistrarConfigMethods: + { + t_u16 sr_config_methods = 0; + tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr; + memcpy(&sr_config_methods, wps_tlv->data, + sizeof(t_u16)); + sr_config_methods = ntohs(sr_config_methods); + printf("\t Selected Registrar Configuration Methods = 0x%x\n", sr_config_methods); + } + break; + default: + printf("unknown ie=0x%x, len=%d\n", wps_type, wps_len); + break; + } + ptr += wps_len + sizeof(tlvbuf_wps_ie); + /* Take care of error condition */ + if (wps_len + sizeof(tlvbuf_wps_ie) <= ie_len_wps) + ie_len_wps -= wps_len + sizeof(tlvbuf_wps_ie); + else + ie_len_wps = 0; + } +} + +/** + * @brief Print WIFIDIRECT IE elements from event payload + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_wifidirect_ie_elements(t_u8 *buffer, t_u16 size) +{ + t_u8 *ptr = buffer; + t_u8 *array_ptr, *orig_ptr = NULL; + int i; + static t_u16 len = 0; + static t_u16 saved_len = 0; + static t_u16 pending_len = 0; + static t_u8 type = 0; + static t_u8 next_byte = WIFIDIRECT_OVERLAP_TYPE; + static t_u8 saved_data[WIFI_IE_MAX_PAYLOAD] = { 0 }; + t_u16 temp; + t_u16 left_len = size; + + while (left_len > 0) { + if (next_byte == WIFIDIRECT_OVERLAP_TYPE) { + type = *ptr; + next_byte = WIFIDIRECT_OVERLAP_LEN; + left_len--; + ptr++; + } + if (left_len >= sizeof(len) && + next_byte == WIFIDIRECT_OVERLAP_LEN) { + memcpy(&len, ptr, sizeof(t_u16)); + len = uap_le16_to_cpu(len); + next_byte = WIFIDIRECT_OVERLAP_DATA; + left_len -= sizeof(t_u16); + ptr += sizeof(t_u16); + + /* case when Type, Len in one frame and data in next */ + if (left_len == 0) { + memcpy(saved_data, + ptr - WIFIDIRECT_IE_HEADER_LEN, + WIFIDIRECT_IE_HEADER_LEN); + saved_len = WIFIDIRECT_IE_HEADER_LEN; + pending_len = len; + } + } + if (left_len > 0 && next_byte == WIFIDIRECT_OVERLAP_DATA) { + /* copy next data */ + if (pending_len > 0 && + (left_len <= (WIFI_IE_MAX_PAYLOAD - saved_len))) { + memcpy(saved_data + saved_len, ptr, + pending_len); + orig_ptr = ptr; + ptr = saved_data; + } else { + ptr -= WIFIDIRECT_IE_HEADER_LEN; + } + + if (!pending_len && !orig_ptr && left_len < len) { + /* save along with type and len */ + memcpy(saved_data, + ptr - WIFIDIRECT_IE_HEADER_LEN, + left_len + WIFIDIRECT_IE_HEADER_LEN); + saved_len = left_len + WIFIDIRECT_IE_HEADER_LEN; + pending_len = len - left_len; + break; + } + switch (type) { + case TLV_TYPE_WIFIDIRECT_DEVICE_ID: + { + tlvbuf_wifidirect_device_id + *wifidirect_tlv = + (tlvbuf_wifidirect_device_id *) + ptr; + printf("\t Device ID - "); + print_mac(wifidirect_tlv-> + dev_mac_address); + printf("\n"); + } + break; + case TLV_TYPE_WIFIDIRECT_CAPABILITY: + { + tlvbuf_wifidirect_capability + *wifidirect_tlv = + (tlvbuf_wifidirect_capability *) + ptr; + printf("\t Device capability = %d\n", + (int)wifidirect_tlv-> + dev_capability); + printf("\t Group capability = %d\n", + (int)wifidirect_tlv-> + group_capability); + } + break; + case TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT: + { + tlvbuf_wifidirect_group_owner_intent + *wifidirect_tlv = + (tlvbuf_wifidirect_group_owner_intent + *)ptr; + printf("\t Group owner intent = %d\n", + (int)wifidirect_tlv->dev_intent); + } + break; + case TLV_TYPE_WIFIDIRECT_MANAGEABILITY: + { + tlvbuf_wifidirect_manageability + *wifidirect_tlv = + (tlvbuf_wifidirect_manageability + *)ptr; + printf("\t Manageability = %d\n", + (int)wifidirect_tlv-> + manageability); + } + break; + case TLV_TYPE_WIFIDIRECT_INVITATION_FLAG: + { + tlvbuf_wifidirect_invitation_flag + *wifidirect_tlv = + (tlvbuf_wifidirect_invitation_flag + *)ptr; + printf("\t Invitation Flag = %d\n", + (int)wifidirect_tlv-> + invitation_flag & + INVITATION_FLAG_MASK); + } + break; + case TLV_TYPE_WIFIDIRECT_CHANNEL_LIST: + { + tlvbuf_wifidirect_channel_list + *wifidirect_tlv = + (tlvbuf_wifidirect_channel_list + *)ptr; + chan_entry *temp_ptr; + printf("\t Country String %c%c", + wifidirect_tlv-> + country_string[0], + wifidirect_tlv-> + country_string[1]); + if (isalpha + (wifidirect_tlv->country_string[2])) + printf("%c", + wifidirect_tlv-> + country_string[2]); + printf("\n"); + temp_ptr = + (chan_entry *)wifidirect_tlv-> + wifidirect_chan_entry_list; + temp = uap_le16_to_cpu(wifidirect_tlv-> + length) - + (sizeof + (tlvbuf_wifidirect_channel_list) + - WIFIDIRECT_IE_HEADER_LEN); + while (temp) { + printf("\t Regulatory_class = %d\n", (int)(temp_ptr->regulatory_class)); + printf("\t No of channels = %d\n", (int)temp_ptr->num_of_channels); + printf("\t Channel list = "); + for (i = 0; + i < + temp_ptr->num_of_channels; + i++) { + printf("%d ", + *(temp_ptr-> + chan_list + + i)); + } + printf("\n"); + temp -= sizeof(chan_entry) + + temp_ptr-> + num_of_channels; + temp_ptr = + (chan_entry *)((t_u8 *) + temp_ptr + + + sizeof + (chan_entry) + + + temp_ptr-> + num_of_channels); + } + printf("\n"); + } + break; + case TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE: + { + tlvbuf_wifidirect_notice_of_absence + *wifidirect_tlv = + (tlvbuf_wifidirect_notice_of_absence + *)ptr; + noa_descriptor *temp_ptr; + printf("\t Instance of Notice of absence timing %d\n", (int)wifidirect_tlv->noa_index); + printf("\t CTWindow and Opportunistic power save parameters %d\n", (int)wifidirect_tlv->ctwindow_opp_ps); + temp_ptr = + (noa_descriptor *) + wifidirect_tlv-> + wifidirect_noa_descriptor_list; + temp = uap_le16_to_cpu(wifidirect_tlv-> + length) - + (sizeof + (tlvbuf_wifidirect_notice_of_absence) + - WIFIDIRECT_IE_HEADER_LEN); + while (temp) { + printf("\t Count or Type = %d\n", (int)temp_ptr->count_type); + printf("\t Duration = %dms\n", + uap_le32_to_cpu + (temp_ptr->duration)); + printf("\t Interval = %dms\n", + uap_le32_to_cpu + (temp_ptr->interval)); + printf("\t Start Time = %d\n", + uap_le32_to_cpu + (temp_ptr->start_time)); + printf("\n"); + temp_ptr += + sizeof(noa_descriptor); + temp -= sizeof(noa_descriptor); + } + } + break; + case TLV_TYPE_WIFIDIRECT_DEVICE_INFO: + { + tlvbuf_wifidirect_device_info + *wifidirect_tlv = + (tlvbuf_wifidirect_device_info + *)ptr; + printf("\t Device address - "); + print_mac(wifidirect_tlv->dev_address); + printf("\n"); + printf("\t Config methods - 0x%02X\n", + ntohs(wifidirect_tlv-> + config_methods)); + printf("\t Primay device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(wifidirect_tlv->primary_category), (int)wifidirect_tlv->primary_oui[0], (int)wifidirect_tlv->primary_oui[1], (int)wifidirect_tlv->primary_oui[2], (int)wifidirect_tlv->primary_oui[3], (int)ntohs(wifidirect_tlv->primary_subcategory)); + printf("\t Secondary Device Count = %d\n", (int)wifidirect_tlv->secondary_dev_count); + array_ptr = + wifidirect_tlv-> + secondary_dev_info; + for (i = 0; + i < + wifidirect_tlv-> + secondary_dev_count; i++) { + memcpy(&temp, array_ptr, + sizeof(t_u16)); + printf("\t Secondary device type = %02d-", ntohs(temp)); + array_ptr += sizeof(temp); + printf("%02X%02X%02X%02X", + array_ptr[0], + array_ptr[1], + array_ptr[2], + array_ptr[3]); + array_ptr += 4; + memcpy(&temp, array_ptr, + sizeof(t_u16)); + printf("-%02d\n", ntohs(temp)); + array_ptr += sizeof(temp); + } + /* display device name */ + array_ptr = + wifidirect_tlv->device_name + + wifidirect_tlv-> + secondary_dev_count * + WPS_DEVICE_TYPE_LEN; + if (*(t_u16 *) + (((t_u8 *)(&wifidirect_tlv-> + device_name_len)) + + wifidirect_tlv-> + secondary_dev_count * + WPS_DEVICE_TYPE_LEN)) + printf("\t Device Name = "); + memcpy(&temp, + (((t_u8 *)(&wifidirect_tlv-> + device_name_len)) + + wifidirect_tlv-> + secondary_dev_count * + WPS_DEVICE_TYPE_LEN), + sizeof(t_u16)); + temp = ntohs(temp); + for (i = 0; i < temp; i++) + printf("%c", *array_ptr++); + printf("\n"); + } + break; + case TLV_TYPE_WIFIDIRECT_GROUP_INFO: + { + tlvbuf_wifidirect_group_info + *wifidirect_tlv = + (tlvbuf_wifidirect_group_info *) + ptr; + t_u8 wifidirect_client_dev_length; + wifidirect_client_dev_info *temp_ptr; + temp_ptr = + (wifidirect_client_dev_info *) + wifidirect_tlv-> + wifidirect_client_dev_list; + if (temp_ptr == NULL) + break; + wifidirect_client_dev_length = + temp_ptr->dev_length; + temp = uap_le16_to_cpu(wifidirect_tlv-> + length) - + wifidirect_client_dev_length; + while (temp_ptr) { + + printf("\t Group WifiDirect Client Device address - "); + print_mac(temp_ptr-> + wifidirect_dev_address); + printf("\n"); + printf("\t Group WifiDirect Client Interface address - "); + print_mac(temp_ptr-> + wifidirect_intf_address); + printf("\n"); + printf("\t Group WifiDirect Client Device capability = %d\n", (int)temp_ptr->wifidirect_dev_capability); + printf("\t Group WifiDirect Client Config methods - 0x%02X\n", ntohs(temp_ptr->config_methods)); + printf("\t Group WifiDirect Client Primay device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(temp_ptr->primary_category), (int)temp_ptr->primary_oui[0], (int)temp_ptr->primary_oui[1], (int)temp_ptr->primary_oui[2], (int)temp_ptr->primary_oui[3], (int)ntohs(temp_ptr->primary_subcategory)); + printf("\t Group WifiDirect Client Secondary Device Count = %d\n", (int)temp_ptr->wifidirect_secondary_dev_count); + array_ptr = + temp_ptr-> + wifidirect_secondary_dev_info; + for (i = 0; + i < + temp_ptr-> + wifidirect_secondary_dev_count; + i++) { + memcpy(&temp, array_ptr, + sizeof(t_u16)); + printf("\t Group WifiDirect Client Secondary device type = %02d-", ntohs(temp)); + array_ptr += + sizeof(temp); + printf("%02X%02X%02X%02X", array_ptr[0], array_ptr[1], array_ptr[2], array_ptr[3]); + array_ptr += 4; + memcpy(&temp, array_ptr, + sizeof(t_u16)); + printf("-%02d\n", + ntohs(temp)); + array_ptr += + sizeof(temp); + } + /* display device name */ + array_ptr = + temp_ptr-> + wifidirect_device_name + + temp_ptr-> + wifidirect_secondary_dev_count + * WPS_DEVICE_TYPE_LEN; + printf("\t Group WifiDirect Device Name = "); + memcpy(&temp, + (((t_u8 *)(&temp_ptr-> + wifidirect_device_name_len)) + + + temp_ptr-> + wifidirect_secondary_dev_count + * WPS_DEVICE_TYPE_LEN), + sizeof(t_u16)); + temp = ntohs(temp); + for (i = 0; i < temp; i++) + printf("%c", + *array_ptr++); + printf("\n"); + temp_ptr += + wifidirect_client_dev_length; + temp -= wifidirect_client_dev_length; + if (temp_ptr) + wifidirect_client_dev_length + = + temp_ptr-> + dev_length; + } + printf("\n"); + } + break; + case TLV_TYPE_WIFIDIRECT_GROUP_ID: + { + tlvbuf_wifidirect_group_id + *wifidirect_tlv = + (tlvbuf_wifidirect_group_id *) + ptr; + printf("\t Group address - "); + print_mac(wifidirect_tlv-> + group_address); + printf("\n"); + printf("\t Group ssid = "); + for (i = 0; + (unsigned int)i < + uap_le16_to_cpu(wifidirect_tlv-> + length) + - + (sizeof(tlvbuf_wifidirect_group_id) + - WIFIDIRECT_IE_HEADER_LEN); i++) + printf("%c", + wifidirect_tlv-> + group_ssid[i]); + printf("\n"); + } + break; + case TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID: + { + tlvbuf_wifidirect_group_bss_id + *wifidirect_tlv = + (tlvbuf_wifidirect_group_bss_id + *)ptr; + printf("\t Group BSS Id - "); + print_mac(wifidirect_tlv->group_bssid); + printf("\n"); + } + break; + case TLV_TYPE_WIFIDIRECT_INTERFACE: + { + tlvbuf_wifidirect_interface + *wifidirect_tlv = + (tlvbuf_wifidirect_interface *) + ptr; + printf("\t Interface Id - "); + print_mac(wifidirect_tlv->interface_id); + printf("\t Interface count = %d", + (int)wifidirect_tlv-> + interface_count); + for (i = 0; + i < + wifidirect_tlv->interface_count; + i++) { + printf("\n\t Interface address [%d]", i + 1); + print_mac(&wifidirect_tlv-> + interface_idlist[i * + ETH_ALEN]); + } + printf("\n"); + } + break; + case TLV_TYPE_WIFIDIRECT_CHANNEL: + { + tlvbuf_wifidirect_channel + *wifidirect_tlv = + (tlvbuf_wifidirect_channel *) + ptr; + printf("\t Listen Channel Country String %c%c", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]); + if (isalpha + (wifidirect_tlv->country_string[2])) + printf("%c", + wifidirect_tlv-> + country_string[2]); + printf("\n"); + printf("\t Listen Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class); + printf("\t Listen Channel number = %d\n", (int)wifidirect_tlv->channel_number); + } + break; + + case TLV_TYPE_WIFIDIRECT_OPCHANNEL: + { + tlvbuf_wifidirect_channel + *wifidirect_tlv = + (tlvbuf_wifidirect_channel *) + ptr; + printf("\t Operating Channel Country String %c%c", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]); + if (isalpha + (wifidirect_tlv->country_string[2])) + printf("%c", + wifidirect_tlv-> + country_string[2]); + printf("\n"); + printf("\t Operating Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class); + printf("\t Operating Channel number = %d\n", (int)wifidirect_tlv->channel_number); + } + break; + + case TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT: + { + tlvbuf_wifidirect_config_timeout + *wifidirect_tlv = + (tlvbuf_wifidirect_config_timeout + *)ptr; + printf("\t GO configuration timeout = %d msec\n", (int)wifidirect_tlv->group_config_timeout * 10); + printf("\t Client configuration timeout = %d msec\n", (int)wifidirect_tlv->device_config_timeout * 10); + } + break; + case TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME: + { + tlvbuf_wifidirect_ext_listen_time + *wifidirect_tlv = + (tlvbuf_wifidirect_ext_listen_time + *)ptr; + printf("\t Availability Period = %d msec\n", (int)wifidirect_tlv->availability_period); + printf("\t Availability Interval = %d msec\n", (int)wifidirect_tlv->availability_interval); + } + break; + case TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS: + { + tlvbuf_wifidirect_intended_addr + *wifidirect_tlv = + (tlvbuf_wifidirect_intended_addr + *)ptr; + printf("\t Intended Interface Address - "); + print_mac(wifidirect_tlv-> + group_address); + printf("\n"); + } + break; + + case TLV_TYPE_WIFIDIRECT_STATUS: + { + tlvbuf_wifidirect_status *wifidirect_tlv + = + (tlvbuf_wifidirect_status *)ptr; + printf("\t Status = %d\n", + wifidirect_tlv->status_code); + } + break; + + default: + printf("unknown ie=0x%x, len=%d\n", type, len); + break; + } + next_byte = WIFIDIRECT_OVERLAP_TYPE; + if (orig_ptr) + ptr = orig_ptr + pending_len; + } + ptr += len + WIFIDIRECT_IE_HEADER_LEN; + left_len -= len; + } + printf("\n"); + return; +} + +/** + * @brief Parse and print WIFIDIRECT generic event data + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_wifidirect_generic(t_u8 *buffer, t_u16 size) +{ + const t_u8 wifi_oui[3] = { 0x50, 0x6F, 0x9A }; + const t_u8 wps_oui[3] = { 0x00, 0x50, 0xF2 }; + apeventbuf_wifidirect_generic *wifidirect_event; + wifidirect_ie_header *wifidirect_wps_header; + t_u16 wifidirect_wps_len = 0, type, sub_type; + printf("EVENT: WIFIDIRECT \n"); + wifidirect_event = (apeventbuf_wifidirect_generic *)(buffer); + printf("Event length = %d\n", + uap_le16_to_cpu(wifidirect_event->event_length)); + printf("Event Type = "); + type = uap_le16_to_cpu(wifidirect_event->event_type); + switch (type) { + case 0: + printf("Negotiation Request\n"); + break; + case 1: + printf("Negotiation Response\n"); + break; + case 2: + printf("Negotiation Result\n"); + break; + case 3: + printf("Invitation Request\n"); + break; + case 4: + printf("Invitation Response\n"); + break; + case 5: + printf("Discoverability Request\n"); + break; + case 6: + printf("Discoverability Response\n"); + break; + case 7: + printf("Provision Discovery Request\n"); + break; + case 8: + printf("Provision Discovery Response\n"); + break; + case 9: + printf("GO Negotiation response Tx Event\n"); + break; + case 10: + printf("GO Negotiation confirm Tx Event\n"); + break; + case 14: + printf("Peer Detected event\n"); + break; + case 15: + printf("Client associated event\n"); + break; + case 16: + printf("FW debug event: %s\n", + wifidirect_event->entire_ie_list); + return; + default: + printf("Unknown\n"); + break; + } + sub_type = uap_le16_to_cpu(wifidirect_event->event_sub_type); + if (type == 2) { + switch (sub_type) { + case 0: + printf("Event SubType = No Role\n"); + break; + case 1: + printf("Event SubType = Group Owner Role\n"); + break; + case 2: + printf("Event SubType = Client Role\n"); + break; + default: + printf("Event SubType = %d\n", sub_type); + break; + } + } else if (type == 3 || type == 4) { + switch (sub_type & 0x03) { /* lower 2 bits */ + case 0: + printf("Event SubType = No Role\n"); + break; + case 1: + printf("Event SubType = Group Owner Role\n"); + break; + case 2: + printf("Event SubType = Client Role\n"); + break; + } + switch ((sub_type & 0x1C) >> 2) { /* next 3 bits */ + case 0: + printf("Packet processing state = None\n"); + break; + case 1: + printf("Packet processing state = Processing\n"); + break; + case 2: + printf("Packet processing state = Insufficient information, Dropped\n"); + break; + case 3: + printf("Packet processing state = Success\n"); + break; + case 4: + printf("Packet processing state = Fail\n"); + break; + default: + printf("Event SubType = %d\n", sub_type); + break; + } + } else if (type == 7 || type == 8) { + switch (sub_type) { + case 0: + printf("Event SubType = No Config Method\n"); + break; + case 8: + printf("Event SubType = Config Method Display\n"); + break; + case 0x80: + printf("Event SubType = Config Method Push Button\n"); + break; + case 0x100: + printf("Event SubType = Config Method Keypad\n"); + break; + default: + printf("Event SubType = %d\n", sub_type); + break; + } + } + printf("Peer Mac Address - "); + print_mac(wifidirect_event->peer_mac_addr); + printf("\n"); + /* Print rest of IE elements */ + wifidirect_wps_header = + (wifidirect_ie_header *)(wifidirect_event->entire_ie_list); + wifidirect_wps_len = uap_le16_to_cpu(wifidirect_event->event_length) + - sizeof(apeventbuf_wifidirect_generic); + + while (wifidirect_wps_len >= sizeof(wifidirect_ie_header)) { + if (!memcmp + (wifidirect_wps_header->oui, wifi_oui, sizeof(wifi_oui)) || + !(memcmp + (wifidirect_wps_header->oui, wps_oui, sizeof(wps_oui)))) { + switch (wifidirect_wps_header->oui_type) { + case WIFIDIRECT_OUI_TYPE: + print_wifidirect_ie_elements + (wifidirect_wps_header->ie_list, + wifidirect_wps_header->ie_length - + sizeof(wifidirect_wps_header->oui) + - + sizeof(wifidirect_wps_header-> + oui_type)); + printf("\n"); + break; + case WIFI_WPS_OUI_TYPE: + print_wifi_wps_ie_elements + (wifidirect_wps_header->ie_list, + wifidirect_wps_header->ie_length - + sizeof(wifidirect_wps_header->oui) + - + sizeof(wifidirect_wps_header-> + oui_type)); + printf("\n"); + break; + } + } + wifidirect_wps_len -= + wifidirect_wps_header->ie_length + IE_HEADER_LEN; + wifidirect_wps_header = + (wifidirect_ie_header *)(((t_u8 *)wifidirect_wps_header) + + + wifidirect_wps_header-> + ie_length + IE_HEADER_LEN); + } +} + +/** + * @brief Parse and print WIFIDIRECT service discovery event data + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_wifidirect_service_discovery(t_u8 *buffer, t_u16 size) +{ + unsigned int i; + t_u16 event_len = 0; + t_u16 dns_len = 0, dns_type; + t_u8 action = 0; /* req = 0, resp = 1 */ + apeventbuf_wifidirect_discovery_request *wifidirect_disc_req; + apeventbuf_wifidirect_discovery_response *wifidirect_disc_resp; + printf("EVENT: WIFIDIRECT SERVICE DISCOVERY\n"); + memcpy(&event_len, buffer, sizeof(t_u16)); + event_len = uap_le16_to_cpu(event_len); + printf("Event length = %d\n", event_len); + printf("Service Discovery packet:\n"); + /* check request /response Byte at offset 2+6+2 */ + action = *(buffer + sizeof(t_u16) + ETH_ALEN + sizeof(t_u8)); + if (action == WIFIDIRECT_DISCOVERY_REQUEST_ACTION) { + wifidirect_disc_req = + (apeventbuf_wifidirect_discovery_request *)(buffer + + sizeof + (t_u16)); + printf("\t Peer Mac Address - "); + print_mac(wifidirect_disc_req->peer_mac_addr); + printf("\n\t Category = %d\n", wifidirect_disc_req->category); + printf("\t Action = %d\n", wifidirect_disc_req->action); + printf("\t Dialog taken = %d\n", + wifidirect_disc_req->dialog_taken); + printf("\t Advertize protocol IE - 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", wifidirect_disc_req->advertize_protocol_ie[0], wifidirect_disc_req->advertize_protocol_ie[1], wifidirect_disc_req->advertize_protocol_ie[2], wifidirect_disc_req->advertize_protocol_ie[3]); + printf("\t Request query length = %d\n", + uap_le16_to_cpu(wifidirect_disc_req->query_len)); + printf("\t Information Id - 0x%02x, 0x%02x\n", + wifidirect_disc_req->info_id[0], + wifidirect_disc_req->info_id[1]); + printf("\t Request length = %d\n", + uap_le16_to_cpu(wifidirect_disc_req->request_len)); + printf("\t OUI - 0x%02x, 0x%02x, 0x%02x\n", + wifidirect_disc_req->oui[0], wifidirect_disc_req->oui[1], + wifidirect_disc_req->oui[2]); + printf("\t OUI sub type = %d\n", + wifidirect_disc_req->oui_sub_type); + printf("\t Service update Indicator = %d\n", + uap_le16_to_cpu(wifidirect_disc_req-> + service_update_indicator)); + printf("\t Vendor length = %d\n", + uap_le16_to_cpu(wifidirect_disc_req->vendor_len)); + printf("\t Service protocol = %d\n", + wifidirect_disc_req->service_protocol); + printf("\t Service transaction Id = %d\n", + wifidirect_disc_req->service_transaction_id); + printf("\t Query Data = "); + if (wifidirect_disc_req->service_protocol == 1) { + printf(" * Bonjour * \n"); + printf("\t\t DNS = "); + dns_len = + uap_le16_to_cpu(wifidirect_disc_req-> + vendor_len) - + WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN; + for (i = 0; i < dns_len; i++) + printf("%02x ", + (int)*(wifidirect_disc_req->disc_query.u. + bonjour.dns + i)); + memcpy(&dns_type, + (&wifidirect_disc_req->disc_query.u.bonjour. + dns_type + dns_len), sizeof(dns_type)); + dns_type = uap_le16_to_cpu(dns_type); + printf("\n\t\t DNS Type = %d\n", dns_type); + printf("\t\t Version = %d\n", + *(&wifidirect_disc_req->disc_query.u.bonjour. + version + dns_len)); + } else if (wifidirect_disc_req->service_protocol == 2) { + printf(" * uPnP * \n"); + printf("\t\t Version = %d\n", + wifidirect_disc_req->disc_query.u.upnp.version); + dns_len = + uap_le16_to_cpu(wifidirect_disc_req-> + vendor_len) - + WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN; + printf("\t\t Value = "); + for (i = 0; i < dns_len; i++) + printf("%02x ", + (int)*(wifidirect_disc_req->disc_query.u. + upnp.value + i)); + } + printf("\n"); + } else if (action == WIFIDIRECT_DISCOVERY_RESPONSE_ACTION) { + wifidirect_disc_resp = + (apeventbuf_wifidirect_discovery_response *)(buffer + + sizeof + (t_u16)); + printf("\t Peer Mac Address - "); + print_mac(wifidirect_disc_resp->peer_mac_addr); + printf("\n\t Category = %d\n", wifidirect_disc_resp->category); + printf("\t Action = %d\n", wifidirect_disc_resp->action); + printf("\t Dialog taken = %d\n", + wifidirect_disc_resp->dialog_taken); + printf("\t Status code = %d\n", + wifidirect_disc_resp->status_code); + printf("\t GAS reply - 0x%02x\n", + uap_le16_to_cpu(wifidirect_disc_resp->gas_reply)); + printf("\t Advertize protocol IE - 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", wifidirect_disc_resp->advertize_protocol_ie[0], wifidirect_disc_resp->advertize_protocol_ie[1], wifidirect_disc_resp->advertize_protocol_ie[2], wifidirect_disc_resp->advertize_protocol_ie[3]); + printf("\t Response query length = %d\n", + uap_le16_to_cpu(wifidirect_disc_resp->query_len)); + printf("\t Information Id - 0x%02x, 0x%02x\n", + wifidirect_disc_resp->info_id[0], + wifidirect_disc_resp->info_id[1]); + printf("\t Response length = %d\n", + uap_le16_to_cpu(wifidirect_disc_resp->response_len)); + printf("\t OUI - 0x%02x, 0x%02x, 0x%02x\n", + wifidirect_disc_resp->oui[0], + wifidirect_disc_resp->oui[1], + wifidirect_disc_resp->oui[2]); + printf("\t OUI sub type = %d\n", + wifidirect_disc_resp->oui_sub_type); + printf("\t Service update Indicator = %d\n", + uap_le16_to_cpu(wifidirect_disc_resp-> + service_update_indicator)); + printf("\t Vendor length = %d\n", + uap_le16_to_cpu(wifidirect_disc_resp->vendor_len)); + printf("\t Service protocol = %d\n", + wifidirect_disc_resp->service_protocol); + printf("\t Service transaction Id = %d\n", + wifidirect_disc_resp->service_transaction_id); + printf("\t Status Code = %d\n", + wifidirect_disc_resp->disc_status_code); + printf("\t Response Data = "); + if (wifidirect_disc_resp->service_protocol == 1) { + printf(" * Bonjour * \n"); + /* + printf("\t\t DNS = "); + dns_len = uap_le16_to_cpu(wifidirect_disc_resp->vendor_len) - + (WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN + 1); + for( i=0; i < dns_len; i++) + printf("%c",*(wifidirect_disc_resp->disc_resp.u.bonjour.dns + i)); + memcpy(&dns_type, (&wifidirect_disc_req->disc_query.u.bonjour.dns_type + + dns_len), sizeof(dns_type)); + dns_type = uap_le16_to_cpu(dns_type); + printf("\n\t\t DNS Type = %d\n", dns_type); + printf("\t\t Version = %d\n", *(&wifidirect_disc_resp->disc_resp.u.bonjour.version + + dns_len)); + */ + } else if (wifidirect_disc_resp->service_protocol == 2) { + printf(" * uPnP * \n"); + printf("\t\t Version = %d\n", + wifidirect_disc_resp->disc_resp.u.upnp.version); + dns_len = + uap_le16_to_cpu(wifidirect_disc_resp-> + vendor_len) - + WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN; + printf("\t\t Value = "); + for (i = 0; i < dns_len; i++) + printf("%02x ", + (int)*(wifidirect_disc_resp->disc_resp.u. + upnp.value + i)); + } + printf("\n"); + } +} +#endif + +/** + * @brief Parse and print TDLS generic event data + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_tdls_generic(t_u8 *buffer, t_u16 size) +{ + eventbuf_tdls_generic *tdls_event; + eventbuf_tdls_debug *tdls_debug; + eventbuf_tdls_packet *tdls_pkt; + printf("EVENT: TDLS\n"); + tdls_event = (eventbuf_tdls_generic *)(buffer); + printf("Event Type = "); + switch (uap_le16_to_cpu(tdls_event->event_type)) { + case TDLS_EVENT_TYPE_SETUP_FAILURE: + printf("TDLS setup failure\n"); + break; + case TDLS_EVENT_TYPE_SETUP_REQ_RCVD: + printf("TDLS setup request received from peer\n"); + break; + case TDLS_EVENT_TYPE_LINK_TORN_DOWN: + printf("TDLS link torn down\n"); + break; + case TDLS_EVENT_TYPE_LINK_ESTABLISHED: + printf("TDLS link established\n"); + break; + case TDLS_EVENT_TYPE_DEBUG: + tdls_debug = (eventbuf_tdls_debug *)(buffer); + printf("TDLS debug event, "); + printf("TSF = %lld\n", uap_le64_to_cpu(tdls_debug->tsf)); + printf("String = "); + printf((char *)(tdls_debug->string), + uap_le32_to_cpu(tdls_debug->first_arg), + uap_le32_to_cpu(tdls_debug->second_arg), + uap_le32_to_cpu(tdls_debug->third_arg)); + printf("\n"); + return; + case TDLS_EVENT_TYPE_PACKET: + tdls_pkt = (eventbuf_tdls_packet *)(buffer); + printf("TDLS packet len=%d\n", tdls_pkt->length); + hexdump((t_u8 *)tdls_pkt->data, tdls_pkt->length, ' '); + return; + case TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT: + if (tdls_event->u.switch_result.status) { + printf("TDLS Channel Switch Failed! current channel=%d Reasoncode %d\n", tdls_event->u.switch_result.current_channel, tdls_event->u.switch_result.reason); + } else { + printf("TDLS Channel Switch Successful. current channel=%d\n", tdls_event->u.switch_result.current_channel); + } + break; + case TDLS_EVENT_TYPE_START_CHAN_SWITCH: + printf("TDLS Start channel switch...\n"); + break; + case TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED: + printf("TDLS Channel Switch stopped! reason=%d\n", + tdls_event->u.cs_stop_reason); + break; + default: + printf("Unknown\n"); + break; + } + printf("Peer Mac Address - "); + print_mac(tdls_event->peer_mac_addr); + printf("\n"); + if (uap_le16_to_cpu(tdls_event->event_type) == + TDLS_EVENT_TYPE_SETUP_FAILURE) { + switch (uap_le16_to_cpu(tdls_event->u.reason_code)) { + case 1: + printf("Reason Code = Internal error\n"); + break; + case 7: + printf("Reason Code = Timeout waiting for response\n"); + break; + case 8: + printf("Reason Code = Non-zero setup response status\n"); + break; + default: + printf("Reason Code = %d\n", + uap_le16_to_cpu(tdls_event->u.reason_code)); + break; + } + } else if (uap_le16_to_cpu(tdls_event->event_type) == + TDLS_EVENT_TYPE_LINK_TORN_DOWN) { + switch (uap_le16_to_cpu(tdls_event->u.reason_code)) { + case 3: + printf("Reason Code = Peer station is leaving BSS\n"); + break; + case 25: + printf("Reason Code = Peer station is unreachable on direct link\n"); + break; + case 26: + printf("Reason Code = Unspecified\n"); + break; + case 211: + printf("Reason Code = Setup received from TDLS peer\n"); + break; + case 212: + printf("Reason Code = Clearing TDLS connections due to deauth/disassoc\n"); + break; + default: + printf("Reason Code = %d\n", + uap_le16_to_cpu(tdls_event->u.reason_code)); + break; + } + } else if (uap_le16_to_cpu(tdls_event->event_type) == + TDLS_EVENT_TYPE_LINK_ESTABLISHED) { + int ie_len = uap_le16_to_cpu(tdls_event->u.ie_length); + if (ie_len) { + printf("Peer IE len=%d\n", ie_len); + hexdump((t_u8 *)tdls_event->ie_ptr, ie_len, ' '); + } + } +} + +/** + * @brief Prints station reject state + * + * @param state Fail state + * @return N/A + */ +void +print_reject_state(t_u8 state) +{ + switch (state) { + case REJECT_STATE_FAIL_EAPOL_2: + printf("Reject state: FAIL_EAPOL_2\n"); + break; + case REJECT_STATE_FAIL_EAPOL_4: + printf("Reject state: FAIL_EAPOL_4:\n"); + break; + case REJECT_STATE_FAIL_EAPOL_GROUP_2: + printf("Reject state: FAIL_EAPOL_GROUP_2\n"); + break; + default: + printf("ERR: unknown reject state %d\n", state); + break; + } + return; +} + +/** + * @brief Prints station reject reason + * + * @param reason Reason code + * @return N/A + */ +void +print_reject_reason(t_u16 reason) +{ + switch (reason) { + case IEEEtypes_REASON_INVALID_IE: + printf("Reject reason: Invalid IE\n"); + break; + case IEEEtypes_REASON_MIC_FAILURE: + printf("Reject reason: Mic Failure\n"); + break; + default: + printf("Reject reason: %d\n", reason); + break; + } + return; +} + +/** + * @brief Prints EAPOL state + * + * @param state Eapol state + * @return N/A + */ +void +print_eapol_state(t_u8 state) +{ + switch (state) { + case EAPOL_START: + printf("Eapol state: EAPOL_START\n"); + break; + case EAPOL_WAIT_PWK2: + printf("Eapol state: EAPOL_WAIT_PWK2\n"); + break; + case EAPOL_WAIT_PWK4: + printf("Eapol state: EAPOL_WAIT_PWK4\n"); + break; + case EAPOL_WAIT_GTK2: + printf("Eapol state: EAPOL_WAIT_GTK2\n"); + break; + case EAPOL_END: + printf("Eapol state: EAPOL_END\n"); + break; + default: + printf("ERR: unknow eapol state%d\n", state); + break; + } + return; +} + +/** + * @brief Parse and print debug event data + * + * @param buffer Pointer to received buffer + * @param size Length of the received event data + * @return N/A + */ +void +print_event_debug(t_u8 *buffer, t_u16 size) +{ + eventbuf_debug *event_body = NULL; + if (size < sizeof(eventbuf_debug)) { + printf("ERR:Event buffer too small!\n"); + return; + } + event_body = (eventbuf_debug *)buffer; + printf("Debug Event Type: %s\n", + (event_body->debug_type == 0) ? "EVENT" : "INFO"); + printf("%s log:\n", + (uap_le32_to_cpu(event_body->debug_id_major) == + DEBUG_ID_MAJ_AUTHENTICATOR) ? "Authenticator" : "Assoc_agent"); + if (uap_le32_to_cpu(event_body->debug_id_major) == + DEBUG_ID_MAJ_AUTHENTICATOR) { + switch (uap_le32_to_cpu(event_body->debug_id_minor)) { + case DEBUG_MAJ_AUTH_MIN_PWK1: + printf("EAPOL Key message 1 (PWK):\n"); + hexdump((t_u8 *)&event_body->info.eapol_pwkmsg, + sizeof(eapol_keymsg_debug_t), ' '); + break; + case DEBUG_MAJ_AUTH_MIN_PWK2: + printf("EAPOL Key message 2 (PWK):\n"); + hexdump((t_u8 *)&event_body->info.eapol_pwkmsg, + sizeof(eapol_keymsg_debug_t), ' '); + break; + case DEBUG_MAJ_AUTH_MIN_PWK3: + printf("EAPOL Key message 3 (PWK):\n"); + hexdump((t_u8 *)&event_body->info.eapol_pwkmsg, + sizeof(eapol_keymsg_debug_t), ' '); + break; + case DEBUG_MAJ_AUTH_MIN_PWK4: + printf("EAPOL Key message 4: (PWK)\n"); + hexdump((t_u8 *)&event_body->info.eapol_pwkmsg, + sizeof(eapol_keymsg_debug_t), ' '); + break; + case DEBUG_MAJ_AUTH_MIN_GWK1: + printf("EAPOL Key message 1: (GWK)\n"); + hexdump((t_u8 *)&event_body->info.eapol_pwkmsg, + sizeof(eapol_keymsg_debug_t), ' '); + break; + case DEBUG_MAJ_AUTH_MIN_GWK2: + printf("EAPOL Key message 2: (GWK)\n"); + hexdump((t_u8 *)&event_body->info.eapol_pwkmsg, + sizeof(eapol_keymsg_debug_t), ' '); + break; + case DEBUG_MAJ_AUTH_MIN_STA_REJ: + printf("Reject STA MAC: "); + print_mac(event_body->info.sta_reject.sta_mac_addr); + printf("\n"); + print_reject_state(event_body->info.sta_reject. + reject_state); + print_reject_reason(uap_le16_to_cpu + (event_body->info.sta_reject. + reject_reason)); + break; + case DEBUG_MAJ_AUTH_MIN_EAPOL_TR: + printf("STA MAC: "); + print_mac(event_body->info.eapol_state.sta_mac_addr); + printf("\n"); + print_eapol_state(event_body->info.eapol_state. + eapol_state); + break; + default: + printf("ERR: unknow debug_id_minor: %d\n", + (int)uap_le32_to_cpu(event_body-> + debug_id_minor)); + hexdump(buffer, size, ' '); + return; + } + } else if (uap_le32_to_cpu(event_body->debug_id_major) == + DEBUG_ID_MAJ_ASSOC_AGENT) { + switch (uap_le32_to_cpu(event_body->debug_id_minor)) { + case DEBUG_ID_MAJ_ASSOC_MIN_WPA_IE: + printf("STA MAC: "); + print_mac(event_body->info.wpaie.sta_mac_addr); + printf("\n"); + printf("wpa ie:\n"); + hexdump(event_body->info.wpaie.wpa_ie, MAX_WPA_IE_LEN, + ' '); + break; + case DEBUG_ID_MAJ_ASSOC_MIN_STA_REJ: + printf("Reject STA MAC: "); + print_mac(event_body->info.sta_reject.sta_mac_addr); + printf("\n"); + print_reject_state(event_body->info.sta_reject. + reject_state); + print_reject_reason(uap_le16_to_cpu + (event_body->info.sta_reject. + reject_reason)); + break; + default: + printf("ERR: unknow debug_id_minor: %d\n", + (int)uap_le32_to_cpu(event_body-> + debug_id_minor)); + hexdump(buffer, size, ' '); + return; + } + } + return; +} + +/** + * @brief Parse and print received nlist event information + * + * @param buffer Pointer to the data buffer + * @param size Length of the received event + * @return N/A + */ +void +print_event_11k_nlist_report(t_u8 *buffer, t_u16 size) +{ + int tlv_buf_left = 0; + tlvbuf_header *tlv; + nlist_entry_tlv *nlist; + int entry_num = 0; + t_u16 tlv_type, tlv_len; + + if (size < 2) { + printf("No neighbor AP list found: %d\n", size); + return; + } + tlv_buf_left = *(t_u16 *)buffer; + tlv_buf_left = uap_le16_to_cpu(tlv_buf_left); + if (tlv_buf_left < (int)sizeof(tlvbuf_header)) + return; + printf("neighbor AP list tlv len: %d\n", tlv_buf_left); + tlv = (tlvbuf_header *)(buffer + 2); + while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) { + tlv_type = uap_le16_to_cpu(tlv->type); + tlv_len = uap_le16_to_cpu(tlv->len); + if ((sizeof(tlvbuf_header) + tlv_len) > + (unsigned int)tlv_buf_left) { + printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, + tlv_buf_left); + break; + } + switch (tlv_type) { + case MRVL_NEIGHBOR_REPORT_TLV_ID: + nlist = (nlist_entry_tlv *) tlv; + printf("Neighbor entry %d:\n", entry_num); + printf("BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n", + nlist->bssid[0], nlist->bssid[1], + nlist->bssid[2], nlist->bssid[3], + nlist->bssid[4], nlist->bssid[5]); + printf("BSSID Info: %02x:%02x:%02x:%02x \n", + nlist->bssid_info[0], nlist->bssid_info[1], + nlist->bssid_info[2], nlist->bssid_info[3]); + printf("reg class: %d, chan: %d, phy: %d \n", + nlist->reg_class, nlist->chan, nlist->phy_type); + if (tlv_len > sizeof(nlist_entry_tlv)) { + printf("sub IE:\n"); + hexdump((t_u8 *)tlv + sizeof(nlist_entry_tlv), + tlv_len - sizeof(nlist_entry_tlv) + + sizeof(tlvbuf_header), ' '); + } + entry_num++; + break; + default: +#if DEBUG + mlanevent_printf(MSG_DEBUG, "unknown tlv: %d\n", + tlv_type); +#endif + break; + } + tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len); + tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len + + sizeof(tlvbuf_header)); + } + return; +} + +/** + * @brief Parse and print received event information + * + * @param event Pointer to received event + * @param size Length of the received event + * @return N/A + */ +void +print_event(event_header *event, t_u16 size) +{ + t_u32 event_id = event->event_id; + switch (event_id) { + case MICRO_AP_EV_ID_STA_DEAUTH: + print_event_sta_deauth(event->event_data, size - EVENT_ID_LEN); + break; + case MICRO_AP_EV_ID_STA_ASSOC: + print_event_sta_assoc(event->event_data, size - EVENT_ID_LEN); + break; + case MICRO_AP_EV_ID_BSS_START: + print_event_bss_start(event->event_data, size - EVENT_ID_LEN); + break; + case MICRO_AP_EV_ID_DEBUG: + print_event_debug(event->event_data, size - EVENT_ID_LEN); + break; + case MICRO_AP_EV_BSS_IDLE: + printf("EVENT: BSS_IDLE\n"); + break; + case MICRO_AP_EV_BSS_ACTIVE: + printf("EVENT: BSS_ACTIVE\n"); + break; + case MICRO_AP_EV_RSN_CONNECT: + print_event_rsn_connect(event->event_data, size - EVENT_ID_LEN); + break; +#ifdef WIFI_DIRECT_SUPPORT + case EVENT_WIFIDIRECT_GENERIC: + print_event_wifidirect_generic(event->event_data, + size - EVENT_ID_LEN); + break; + case EVENT_WIFIDIRECT_SERVICE_DISCOVERY: + print_event_wifidirect_service_discovery(event->event_data, + size - EVENT_ID_LEN); + break; +#endif + + case EVENT_TDLS_GENERIC: + print_event_tdls_generic(event->event_data, + size - EVENT_ID_LEN); + break; + case UAP_EVENT_ID_DRV_HS_ACTIVATED: + printf("EVENT: uAP HS_ACTIVATED\n"); + break; + case UAP_EVENT_ID_DRV_HS_DEACTIVATED: + printf("EVENT: uAP HS_DEACTIVATED\n"); + break; + case UAP_EVENT_ID_HS_WAKEUP: + printf("EVENT: uAP HS_WAKEUP\n"); + break; + case UAP_EVENT_HOST_SLEEP_AWAKE: + break; + case UAP_EVENT_ID_DRV_MGMT_FRAME: + printf("EVENT: Mgmt frame from FW\n"); + hexdump((void *)event, size, ' '); + break; + case MICRO_AP_EV_WMM_STATUS_CHANGE: + printf("EVENT: WMM_STATUS_CHANGE\n"); + break; + case EVENT_RADAR_DETECTED: + printf("EVENT: RADAR_DETECTED\n"); + break; + case EVENT_CHANNEL_REPORT_RDY: + printf("EVENT: CHANNEL_REPORT_READY\n"); + hexdump((void *)event, size, ' '); + break; + case EVENT_WEP_ICV_ERROR: + print_event_wep_icv_error(event->event_data, + size - EVENT_ID_LEN); + break; + case EVENT_ID_DRV_SCAN_REPORT: + printf("Scan request completed.\n"); + break; + case EVENT_NLIST_REPORT: + printf("EVENT: 11k neighbor AP list report\n"); + print_event_11k_nlist_report(event->event_data, + size - EVENT_ID_LEN); + break; + + default: + /* Handle string based events */ +#define CUS_EVT_PORT_RELEASE "EVENT=PORT_RELEASE" + if (!strncmp + ((char *)event, CUS_EVT_PORT_RELEASE, + strlen(CUS_EVT_PORT_RELEASE))) { + printf("EVENT: PORT_RELEASE.\n"); + break; + } +#define CUS_EVT_TDLS_CONNECTED "EVENT=TDLS_CONNECTED" + if (!strncmp + ((char *)event, CUS_EVT_TDLS_CONNECTED, + strlen(CUS_EVT_TDLS_CONNECTED))) { + printf("EVENT: TDLS_CONNECTED\n"); + print_mac((t_u8 *)event + + strlen(CUS_EVT_TDLS_CONNECTED)); + printf("\n"); + break; + } +#define CUS_EVT_TDLS_TEARDOWN "EVENT=TDLS_TEARDOWN" + if (!strncmp + ((char *)event, CUS_EVT_TDLS_TEARDOWN, + strlen(CUS_EVT_TDLS_TEARDOWN))) { + printf("EVENT: TDLS_TEARDOWN\n"); + print_mac((t_u8 *)event + + strlen(CUS_EVT_TDLS_TEARDOWN)); + printf("\n"); + break; + } +#define CUS_EVT_STA_CONNECTED "EVENT=STA_CONNECTED" + if (!strncmp + ((char *)event, CUS_EVT_STA_CONNECTED, + strlen(CUS_EVT_STA_CONNECTED))) { + printf("EVENT: STA_CONNECTED\n"); + print_mac((t_u8 *)event + + strlen(CUS_EVT_STA_CONNECTED) + 1); + printf("\n"); + break; + } +#define CUS_EVT_STA_DISCONNECTED "EVENT=STA_DISCONNECTED" + if (!strncmp + ((char *)event, CUS_EVT_STA_DISCONNECTED, + strlen(CUS_EVT_STA_DISCONNECTED))) { + printf("EVENT: STA_DISCONNECTED\n"); + break; + } +#define CUS_EVT_AP_CONNECTED "EVENT=AP_CONNECTED" + if (!strncmp + ((char *)event, CUS_EVT_AP_CONNECTED, + strlen(CUS_EVT_AP_CONNECTED))) { + printf("EVENT: AP_CONNECTED\n"); + print_mac((t_u8 *)event + strlen(CUS_EVT_AP_CONNECTED)); + printf("\n"); + break; + } +#define CUS_EVT_ADHOC_LINK_SENSED "EVENT=ADHOC_LINK_SENSED" + if (!strncmp + ((char *)event, CUS_EVT_ADHOC_LINK_SENSED, + strlen(CUS_EVT_ADHOC_LINK_SENSED))) { + printf("EVENT: ADHOC_LINK_SENSED\n"); + break; + } +#define CUS_EVT_ADHOC_LINK_LOST "EVENT=ADHOC_LINK_LOST" + if (!strncmp + ((char *)event, CUS_EVT_ADHOC_LINK_LOST, + strlen(CUS_EVT_ADHOC_LINK_LOST))) { + printf("EVENT: ADHOC_LINK_LOST\n"); + break; + } +#define CUS_EVT_OBSS_SCAN_PARAM "EVENT=OBSS_SCAN_PARAM" + if (!strncmp + ((char *)event, CUS_EVT_OBSS_SCAN_PARAM, + strlen(CUS_EVT_OBSS_SCAN_PARAM))) { + printf("EVENT: OBSS_SCAN_PARAM\n"); + break; + } +#define CUS_EVT_BW_CHANGED "EVENT=BW_CHANGED" + if (!strncmp + ((char *)event, CUS_EVT_BW_CHANGED, + strlen(CUS_EVT_BW_CHANGED))) { + printf("EVENT: BW_CHANGED\n"); + break; + } +#define CUS_EVT_MLME_MIC_ERR_UNI "MLME-MICHAELMICFAILURE.indication unicast" + if (!strncmp + ((char *)event, CUS_EVT_MLME_MIC_ERR_UNI, + strlen(CUS_EVT_MLME_MIC_ERR_UNI))) { + printf("EVENT: MLME-MICHAELMICFAILURE.indication unicast\n"); + break; + } +#define CUS_EVT_MLME_MIC_ERR_MUL "MLME-MICHAELMICFAILURE.indication multicast" + if (!strncmp + ((char *)event, CUS_EVT_MLME_MIC_ERR_MUL, + strlen(CUS_EVT_MLME_MIC_ERR_MUL))) { + printf("EVENT: MLME-MICHAELMICFAILURE.indication multicast\n"); + break; + } +#define CUS_EVT_BEACON_RSSI_LOW "EVENT=BEACON_RSSI_LOW" + if (!strncmp + ((char *)event, CUS_EVT_BEACON_RSSI_LOW, + strlen(CUS_EVT_BEACON_RSSI_LOW))) { + printf("EVENT: BEACON_RSSI_LOW\n"); + break; + } +#define CUS_EVT_BEACON_RSSI_HIGH "EVENT=BEACON_RSSI_HIGH" + if (!strncmp + ((char *)event, CUS_EVT_BEACON_RSSI_HIGH, + strlen(CUS_EVT_BEACON_RSSI_HIGH))) { + printf("EVENT: BEACON_RSSI_HIGH\n"); + break; + } +#define CUS_EVT_BEACON_SNR_LOW "EVENT=BEACON_SNR_LOW" + if (!strncmp + ((char *)event, CUS_EVT_BEACON_SNR_LOW, + strlen(CUS_EVT_BEACON_SNR_LOW))) { + printf("EVENT: BEACON_SNR_LOW\n"); + break; + } +#define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH" + if (!strncmp + ((char *)event, CUS_EVT_BEACON_SNR_HIGH, + strlen(CUS_EVT_BEACON_SNR_HIGH))) { + printf("EVENT: BEACON_SNR_HIGH\n"); + break; + } +#define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL" + if (!strncmp + ((char *)event, CUS_EVT_MAX_FAIL, + strlen(CUS_EVT_MAX_FAIL))) { + printf("EVENT: MAX_FAIL\n"); + break; + } +#define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW" + if (!strncmp + ((char *)event, CUS_EVT_DATA_RSSI_LOW, + strlen(CUS_EVT_DATA_RSSI_LOW))) { + printf("EVENT: DATA_RSSI_LOW\n"); + break; + } +#define CUS_EVT_DATA_SNR_LOW "EVENT=DATA_SNR_LOW" + if (!strncmp + ((char *)event, CUS_EVT_DATA_SNR_LOW, + strlen(CUS_EVT_DATA_SNR_LOW))) { + printf("EVENT: DATA_SNR_LOW\n"); + break; + } +#define CUS_EVT_DATA_RSSI_HIGH "EVENT=DATA_RSSI_HIGH" + if (!strncmp + ((char *)event, CUS_EVT_DATA_RSSI_HIGH, + strlen(CUS_EVT_DATA_RSSI_HIGH))) { + printf("EVENT: DATA_RSSI_HIGH\n"); + break; + } +#define CUS_EVT_DATA_SNR_HIGH "EVENT=DATA_SNR_HIGH" + if (!strncmp + ((char *)event, CUS_EVT_DATA_SNR_HIGH, + strlen(CUS_EVT_DATA_SNR_HIGH))) { + printf("EVENT: DATA_SNR_HIGH\n"); + break; + } +#define CUS_EVT_LINK_QUALITY "EVENT=LINK_QUALITY" + if (!strncmp + ((char *)event, CUS_EVT_LINK_QUALITY, + strlen(CUS_EVT_LINK_QUALITY))) { + printf("EVENT: LINK_QUALITY\n"); + break; + } +#define CUS_EVT_WEP_ICV_ERR "EVENT=WEP_ICV_ERR" + if (!strncmp + ((char *)event, CUS_EVT_WEP_ICV_ERR, + strlen(CUS_EVT_WEP_ICV_ERR))) { + printf("EVENT: WEP_ICV_ERR\n"); + break; + } +#define CUS_EVT_CHANNEL_SWITCH_ANN "EVENT=CHANNEL_SWITCH_ANN" + if (!strncmp + ((char *)event, CUS_EVT_CHANNEL_SWITCH_ANN, + strlen(CUS_EVT_CHANNEL_SWITCH_ANN))) { + printf("EVENT: CHANNEL_SWITCH_ANN\n"); + break; + } +#define CUS_EVT_HS_WAKEUP "HS_WAKEUP" + if (!strncmp + ((char *)event, CUS_EVT_HS_WAKEUP, + strlen(CUS_EVT_HS_WAKEUP))) { + printf("EVENT: HS_WAKEUP\n"); + break; + } +#define CUS_EVT_HS_ACTIVATED "HS_ACTIVATED" + if (!strncmp + ((char *)event, CUS_EVT_HS_ACTIVATED, + strlen(CUS_EVT_HS_ACTIVATED))) { + printf("EVENT: HS_ACTIVATED\n"); + break; + } +#define CUS_EVT_HS_DEACTIVATED "HS_DEACTIVATED" + if (!strncmp + ((char *)event, CUS_EVT_HS_DEACTIVATED, + strlen(CUS_EVT_HS_DEACTIVATED))) { + printf("EVENT: HS_DEACTIVATED\n"); + break; + } +/** Custom indication message sent to the application layer for WMM changes */ +#define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication" + if (!strncmp + ((char *)event, WMM_CONFIG_CHANGE_INDICATION, + strlen(WMM_CONFIG_CHANGE_INDICATION))) { + printf("EVENT: STA_DISCONNECTED\n"); + break; + } +#define CUS_EVT_DRIVER_HANG "EVENT=DRIVER_HANG" + if (!strncmp + ((char *)event, CUS_EVT_DRIVER_HANG, + strlen(CUS_EVT_DRIVER_HANG))) { + printf("EVENT: DRIVER_HANG\n"); + break; + } +#define FW_DEBUG_INFO "EVENT=FW_DEBUG_INFO" + if (!strncmp + ((char *)event, FW_DEBUG_INFO, strlen(FW_DEBUG_INFO))) { + printf("EVENT: FW_DEBUG_INFO\n"); + printf("%s\n", + (t_u8 *)event + strlen(CUS_EVT_STA_CONNECTED) + + 1); + printf("\n"); + break; + } + printf("ERR:Undefined event type (0x%X). Dumping event buffer:\n", (unsigned int)event_id); + hexdump((void *)event, size, ' '); + break; + } + return; +} + +/** + * @brief Read event data from netlink socket + * + * @param sk_fd Netlink socket handler + * @param buffer Pointer to the data buffer + * @param nlh Pointer to netlink message header + * @param msg Pointer to message header + * @return Number of bytes read or MLAN_EVENT_FAILURE + */ +int +read_event_netlink_socket(int sk_fd, unsigned char *buffer, + struct nlmsghdr *nlh, struct msghdr *msg) +{ + int count = -1; + count = recvmsg(sk_fd, msg, 0); +#if DEBUG + mlanevent_printf(MSG_DEBUG, "DBG:Waiting for message from NETLINK.\n"); +#endif + if (count < 0) { + printf("ERR:NETLINK read failed!\n"); + return MLAN_EVENT_FAILURE; + } +#if DEBUG + mlanevent_printf(MSG_DEBUG, "DBG:Received message payload (%d)\n", + count); +#endif + if (count > NLMSG_SPACE(NL_MAX_PAYLOAD)) { + printf("ERR:Buffer overflow!\n"); + return MLAN_EVENT_FAILURE; + } + memset(buffer, 0, NL_MAX_PAYLOAD); + memcpy(buffer, NLMSG_DATA(nlh), count - NLMSG_HDRLEN); +#if DEBUG + mlanevent_hexdump(MSG_DEBUG, buffer, count - NLMSG_HDRLEN, ' '); +#endif + return count - NLMSG_HDRLEN; +} + +/** + * @brief Configure and read event data from netlink socket + * + * @param sk_fd Array of netlink sockets + * @param no_of_sk Number of netlink sockets opened + * @param recv_buf Pointer to the array of evt_buf structures + * @param timeout Socket listen timeout value + * @param nlh Pointer to netlink message header + * @param msg Pointer to message header + * @return Number of bytes read or MLAN_EVENT_FAILURE + */ +int +read_event(int *sk_fd, int no_of_sk, evt_buf *recv_buf, int timeout, + struct nlmsghdr *nlh, struct msghdr *msg) +{ + struct timeval tv; + fd_set rfds; + int i = 0, max_sk_fd = sk_fd[0]; + int ret = MLAN_EVENT_FAILURE; + + /* Setup read fds */ + FD_ZERO(&rfds); + for (i = 0; i < no_of_sk; i++) { + if (sk_fd[i] > max_sk_fd) + max_sk_fd = sk_fd[i]; + + if (sk_fd[i] > 0) + FD_SET(sk_fd[i], &rfds); + } + + /* Initialize timeout value */ + if (timeout != 0) + tv.tv_sec = timeout; + else + tv.tv_sec = UAP_RECV_WAIT_DEFAULT; + tv.tv_usec = 0; + + /* Wait for reply */ + ret = select(max_sk_fd + 1, &rfds, NULL, NULL, &tv); + if (ret == -1) { + /* Error */ + terminate_flag++; + return MLAN_EVENT_FAILURE; + } else if (!ret) { + /* Timeout. Try again */ + return MLAN_EVENT_FAILURE; + } + for (i = 0; i < no_of_sk; i++) { + if (sk_fd[i] > 0) { + if (FD_ISSET(sk_fd[i], &rfds)) { + /* Success */ + recv_buf[i].flag = 1; + recv_buf[i].length = + read_event_netlink_socket(sk_fd[i], + recv_buf[i]. + buffer, nlh, + msg); + ret += recv_buf[i].length; + } + } + } + return ret; +} + +/* Command line options */ +static const struct option long_opts[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} +}; + +/** + * @brief Determine the netlink number + * + * @param i socket number + * + * @return Netlink number to use + */ +static int +get_netlink_num(int i) +{ + FILE *fp; + int netlink_num = NETLINK_MARVELL; + char str[64]; + char *srch = "netlink_num"; + char filename[64]; + + if (i == 0) { + strcpy(filename, "/proc/mwlan/config"); + } else if (i > 0) { + sprintf(filename, "/proc/mwlan/config%d", i); + } + /* Try to open /proc/mwlan/config$ */ + fp = fopen(filename, "r"); + if (fp) { + while (fgets(str, sizeof(str), fp)) { + if (strncmp(str, srch, strlen(srch)) == 0) { + netlink_num = atoi(str + strlen(srch) + 1); + break; + } + } + fclose(fp); + } else { + return -1; + } + printf("Netlink number = %d\n", netlink_num); + return netlink_num; +} + +/**************************************************************************** + Global functions +****************************************************************************/ +/** + * @brief The main function + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return 0 or 1 + */ +int +main(int argc, char *argv[]) +{ + int opt; + int nl_sk[MAX_NO_OF_DEVICES]; + struct nlmsghdr *nlh = NULL; + struct sockaddr_nl src_addr, dest_addr; + struct msghdr msg; + struct iovec iov; + evt_buf evt_recv_buf[MAX_NO_OF_DEVICES]; + struct timeval current_time; + struct tm *timeinfo; + int num_events = 0; + event_header *event = NULL; + int ret = MLAN_EVENT_FAILURE; + int netlink_num[MAX_NO_OF_DEVICES]; + char if_name[IFNAMSIZ + 1]; + t_u32 event_id = 0; + int i = 0, no_of_sk = 0, dev_index = -1; + + /* Check command line options */ + while ((opt = getopt_long(argc, argv, "hvti:d:", long_opts, NULL)) > 0) { + switch (opt) { + case 'h': + print_usage(); + return 0; + case 'v': + printf("mlanevent version : %s\n", MLAN_EVENT_VERSION); + return 0; + break; + case 'i': + if ((IS_HEX_OR_DIGIT(optarg) == MLAN_EVENT_FAILURE) || + (A2HEXDECIMAL(optarg) < 0) + || ((A2HEXDECIMAL(optarg) >= MAX_NO_OF_DEVICES) && + (A2HEXDECIMAL(optarg) != 0xff))) { + print_usage(); + return 1; + } else { + dev_index = A2HEXDECIMAL(optarg); + } + break; + case 'd': + debug_level = strtoul(optarg, NULL, 10); +#if DEBUG + mlanevent_printf(MSG_DEBUG, "debug_level=%x\n", + debug_level); +#endif + break; + default: + print_usage(); + return 1; + } + } + + if (optind < argc) { + fputs("Too many arguments.\n", stderr); + print_usage(); + return 1; + } + if ((dev_index >= 0) && (dev_index < MAX_NO_OF_DEVICES)) { + no_of_sk = 1; + } else { + /* Currently, we support maximum 4 devices */ + /* TODO: determine no_of_sk at run time */ + no_of_sk = MAX_NO_OF_DEVICES; + } + + for (i = 0; i < no_of_sk; i++) { + /* Initialise */ + nl_sk[i] = -1; + if (no_of_sk == 1) { + netlink_num[i] = get_netlink_num(dev_index); + if (netlink_num[i] < 0) { + printf("ERR:Could not get netlink socket. Invalid device number.\n"); + ret = MLAN_EVENT_FAILURE; + goto done; + } + } else { + netlink_num[i] = get_netlink_num(i); + } + if (netlink_num[i] >= 0) { + /* Open netlink socket */ + nl_sk[i] = socket(PF_NETLINK, SOCK_RAW, netlink_num[i]); + if (nl_sk[i] < 0) { + printf("ERR:Could not open netlink socket.\n"); + ret = MLAN_EVENT_FAILURE; + goto done; + } + + /* Set source address */ + memset(&src_addr, 0, sizeof(src_addr)); + src_addr.nl_family = AF_NETLINK; + src_addr.nl_pid = getpid(); /* Our PID */ + src_addr.nl_groups = NL_MULTICAST_GROUP; + + /* Bind socket with source address */ + if (bind + (nl_sk[i], (struct sockaddr *)&src_addr, + sizeof(src_addr)) < 0) { + printf("ERR:Could not bind socket!\n"); + ret = MLAN_EVENT_FAILURE; + goto done; + } + + /* Set destination address */ + memset(&dest_addr, 0, sizeof(dest_addr)); + dest_addr.nl_family = AF_NETLINK; + dest_addr.nl_pid = 0; /* Kernel */ + dest_addr.nl_groups = NL_MULTICAST_GROUP; + + /* Initialize netlink header */ + nlh = (struct nlmsghdr *) + malloc(NLMSG_SPACE(NL_MAX_PAYLOAD)); + if (!nlh) { + printf("ERR: Could not alloc buffer\n"); + ret = MLAN_EVENT_FAILURE; + goto done; + } + memset(nlh, 0, NLMSG_SPACE(NL_MAX_PAYLOAD)); + + /* Initialize I/O vector */ + iov.iov_base = (void *)nlh; + iov.iov_len = NLMSG_SPACE(NL_MAX_PAYLOAD); + + /* Initialize message header */ + memset(&msg, 0, sizeof(struct msghdr)); + msg.msg_name = (void *)&dest_addr; + msg.msg_namelen = sizeof(dest_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + memset(&evt_recv_buf[i], 0, sizeof(evt_buf)); + } + } + gettimeofday(¤t_time, NULL); + + printf("\n"); + printf("**********************************************\n"); + if ((timeinfo = localtime(&(current_time.tv_sec)))) + printf("mlanevent start time : %s", asctime(timeinfo)); + printf(" %u usecs\n", + (unsigned int)current_time.tv_usec); + printf("**********************************************\n"); + + signal(SIGTERM, sig_handler); + signal(SIGINT, sig_handler); + signal(SIGALRM, sig_handler); + while (1) { + if (terminate_flag) { + printf("Stopping!\n"); + break; + } + ret = read_event(nl_sk, no_of_sk, evt_recv_buf, 0, nlh, &msg); + + /* No result. Loop again */ + if (ret == MLAN_EVENT_FAILURE) { + continue; + } + if (ret == 0) { + /* Zero bytes received */ + printf("ERR:Received zero bytes!\n"); + continue; + } + for (i = 0; i < no_of_sk; i++) { + if (evt_recv_buf[i].flag == 1) { + num_events++; + gettimeofday(¤t_time, NULL); + printf("\n"); + printf("============================================\n"); + printf("Received event"); + if ((timeinfo = + localtime(&(current_time.tv_sec)))) + printf(": %s", asctime(timeinfo)); + printf(" %u usecs\n", + (unsigned int)current_time.tv_usec); + printf("============================================\n"); + + memcpy(&event_id, evt_recv_buf[i].buffer, + sizeof(event_id)); + if (((event_id & 0xFF000000) == 0x80000000) || + ((event_id & 0xFF000000) == 0)) { + event = (event_header + *)(evt_recv_buf[i].buffer); + } else { + memset(if_name, 0, IFNAMSIZ + 1); + memcpy(if_name, evt_recv_buf[i].buffer, + IFNAMSIZ); + printf("EVENT for interface %s\n", + if_name); + event = (event_header + *)((t_u8 *)(evt_recv_buf[i]. + buffer) + + IFNAMSIZ); + ret -= IFNAMSIZ; + evt_recv_buf[i].length -= IFNAMSIZ; + } +#if DEBUG + mlanevent_printf(MSG_DEBUG, + "DBG:Received buffer =\n"); + mlanevent_hexdump(MSG_DEBUG, + evt_recv_buf[i].buffer, + evt_recv_buf[i].length + + IFNAMSIZ, ' '); +#endif + print_event(event, evt_recv_buf[i].length); + /* Reset event flag after reading */ + evt_recv_buf[i].flag = 0; + } + } + fflush(stdout); + } + gettimeofday(¤t_time, NULL); + printf("\n"); + printf("*********************************************\n"); + if ((timeinfo = localtime(&(current_time.tv_sec)))) + printf("mlanevent end time : %s", asctime(timeinfo)); + printf(" %u usecs\n", + (unsigned int)current_time.tv_usec); + printf("Total events : %u\n", num_events); + printf("*********************************************\n"); +done: + for (i = 0; i < no_of_sk; i++) { + if (nl_sk[i] > 0) + close(nl_sk[i]); + } + if (nlh) + free(nlh); + return 0; +} diff --git a/mwifiex_8997/mapp/mlanevent/mlanevent.h b/mwifiex_8997/mapp/mlanevent/mlanevent.h new file mode 100755 index 0000000..d041c2e --- /dev/null +++ b/mwifiex_8997/mapp/mlanevent/mlanevent.h @@ -0,0 +1,1354 @@ +/** @file mlanevent.h + * + * @brief Header file for mlanevent application + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 03/18/08: Initial creation +************************************************************************/ + +#ifndef _MLAN_EVENT_H +#define _MLAN_EVENT_H + +/** Character, 1 byte */ +typedef signed char t_s8; +/** Unsigned character, 1 byte */ +typedef unsigned char t_u8; + +/** Short integer */ +typedef signed short t_s16; +/** Unsigned short integer */ +typedef unsigned short t_u16; + +/** Integer */ +typedef signed int t_s32; +/** Unsigned integer */ +typedef unsigned int t_u32; + +/** Long long integer */ +typedef long long t_s64; +/** Unsigned long long integer */ +typedef unsigned long long t_u64; + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#undef BIG_ENDIAN_SUPPORT +#endif + +/** 16 bits byte swap */ +#define swap_byte_16(x) \ + ((t_u16)((((t_u16)(x) & 0x00ffU) << 8) | \ + (((t_u16)(x) & 0xff00U) >> 8))) + +/** 32 bits byte swap */ +#define swap_byte_32(x) \ + ((t_u32)((((t_u32)(x) & 0x000000ffUL) << 24) | \ + (((t_u32)(x) & 0x0000ff00UL) << 8) | \ + (((t_u32)(x) & 0x00ff0000UL) >> 8) | \ + (((t_u32)(x) & 0xff000000UL) >> 24))) + +/** 64 bits byte swap */ +#define swap_byte_64(x) \ + ((t_u64)((t_u64)(((t_u64)(x) & 0x00000000000000ffULL) << 56) | \ + (t_u64)(((t_u64)(x) & 0x000000000000ff00ULL) << 40) | \ + (t_u64)(((t_u64)(x) & 0x0000000000ff0000ULL) << 24) | \ + (t_u64)(((t_u64)(x) & 0x00000000ff000000ULL) << 8) | \ + (t_u64)(((t_u64)(x) & 0x000000ff00000000ULL) >> 8) | \ + (t_u64)(((t_u64)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (t_u64)(((t_u64)(x) & 0x00ff000000000000ULL) >> 40) | \ + (t_u64)(((t_u64)(x) & 0xff00000000000000ULL) >> 56) )) + +#ifdef BIG_ENDIAN_SUPPORT +/** Convert from 16 bit little endian format to CPU format */ +#define uap_le16_to_cpu(x) swap_byte_16(x) +/** Convert from 32 bit little endian format to CPU format */ +#define uap_le32_to_cpu(x) swap_byte_32(x) +/** Convert from 64 bit little endian format to CPU format */ +#define uap_le64_to_cpu(x) swap_byte_64(x) +/** Convert to 16 bit little endian format from CPU format */ +#define uap_cpu_to_le16(x) swap_byte_16(x) +/** Convert to 32 bit little endian format from CPU format */ +#define uap_cpu_to_le32(x) swap_byte_32(x) +/** Convert to 64 bit little endian format from CPU format */ +#define uap_cpu_to_le64(x) swap_byte_64(x) +#else /* BIG_ENDIAN_SUPPORT */ +/** Do nothing */ +#define uap_le16_to_cpu(x) x +/** Do nothing */ +#define uap_le32_to_cpu(x) x +/** Do nothing */ +#define uap_le64_to_cpu(x) x +/** Do nothing */ +#define uap_cpu_to_le16(x) x +/** Do nothing */ +#define uap_cpu_to_le32(x) x +/** Do nothing */ +#define uap_cpu_to_le64(x) x +#endif /* BIG_ENDIAN_SUPPORT */ + +/** Convert WPS TLV header from network to host order */ +#define endian_convert_tlv_wps_header_in(t,l) \ + { \ + (t) = ntohs(t); \ + (l) = ntohs(l); \ + } + +/** + * Hex or Decimal to Integer + * @param num string to convert into decimal or hex + */ +#define A2HEXDECIMAL(num) \ + (strncasecmp("0x", (num), 2)?(unsigned int) strtoll((num),NULL,0):a2hex((num)))\ + +/** + * Check of decimal or hex string + * @param num string + */ +#define IS_HEX_OR_DIGIT(num) \ + (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num)))\ + +/** MLan Event application version string */ +#define MLAN_EVENT_VERSION "MlanEvent 2.0" + +/** Failure */ +#define MLAN_EVENT_FAILURE -1 + +#ifdef __GNUC__ +/** Structure packing begins */ +#define PACK_START +/** Structure packeing end */ +#define PACK_END __attribute__ ((packed)) +#else +/** Structure packing begins */ +#define PACK_START __packed +/** Structure packeing end */ +#define PACK_END +#endif + +#ifndef ETH_ALEN +/** MAC address length */ +#define ETH_ALEN 6 +#endif + +/** Netlink protocol number */ +#define NETLINK_MARVELL (MAX_LINKS - 1) +/** Netlink maximum payload size */ +#define NL_MAX_PAYLOAD 2048 //1024 +/** Netlink multicast group number */ +#define NL_MULTICAST_GROUP 1 +/** Default wait time in seconds for events */ +#define UAP_RECV_WAIT_DEFAULT 10 +/** Maximum number of devices */ +#define MAX_NO_OF_DEVICES 4 + +#ifndef NLMSG_HDRLEN +/** NL message header length */ +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#endif + +/** Event ID mask */ +#define EVENT_ID_MASK 0xffff + +/** BSS number mask */ +#define BSS_NUM_MASK 0xf + +/** Get BSS number from event cause (bit 23:16) */ +#define EVENT_GET_BSS_NUM(event_cause) \ + (((event_cause) >> 16) & BSS_NUM_MASK) + +/** Invitation Flag mask */ +#define INVITATION_FLAG_MASK 0x01 + +/* Event buffer */ +typedef PACK_START struct _evt_buf { + /** Flag to check if event data is present in the buffer or not */ + int flag; + /** Event length */ + int length; + /** Event data */ + t_u8 buffer[NL_MAX_PAYLOAD]; +} PACK_END evt_buf; + +/** Event header */ +typedef PACK_START struct _event_header { + /** Event ID */ + t_u32 event_id; + /** Event data */ + t_u8 event_data[0]; +} PACK_END event_header; + +/** Event ID length */ +#define EVENT_ID_LEN 4 + +/** Event ID : WMM status change */ +#define MICRO_AP_EV_WMM_STATUS_CHANGE 0x00000017 + +/** Event ID: STA deauth */ +#define MICRO_AP_EV_ID_STA_DEAUTH 0x0000002c + +/** Event ID: STA associated */ +#define MICRO_AP_EV_ID_STA_ASSOC 0x0000002d + +/** Event ID: BSS started */ +#define MICRO_AP_EV_ID_BSS_START 0x0000002e + +/** Event ID: Debug event */ +#define MICRO_AP_EV_ID_DEBUG 0x00000036 + +/** Event ID: BSS idle event */ +#define MICRO_AP_EV_BSS_IDLE 0x00000043 + +/** Event ID: BSS active event */ +#define MICRO_AP_EV_BSS_ACTIVE 0x00000044 + +/** Event ID: WEP ICV error */ +#define EVENT_WEP_ICV_ERROR 0x00000046 + +#ifdef WIFI_DIRECT_SUPPORT +/** Event ID: UAP,STA wifidirect generic event */ +#define EVENT_WIFIDIRECT_GENERIC 0x00000049 + +/** Event ID: UAP,STA wifidirect service discovery event */ +#define EVENT_WIFIDIRECT_SERVICE_DISCOVERY 0x0000004a +#endif + +/** Event ID: RSN Connect event */ +#define MICRO_AP_EV_RSN_CONNECT 0x00000051 + +/** Event ID: TDLS generic event */ +#define EVENT_TDLS_GENERIC 0x00000052 + +/** event type for tdls setup failure */ +#define TDLS_EVENT_TYPE_SETUP_FAILURE 1 +/** event type for tdls setup request received */ +#define TDLS_EVENT_TYPE_SETUP_REQ_RCVD 2 +/** event type for tdls link torn down */ +#define TDLS_EVENT_TYPE_LINK_TORN_DOWN 3 +/** event type for tdls link established */ +#define TDLS_EVENT_TYPE_LINK_ESTABLISHED 4 +/** event type for tdls debug */ +#define TDLS_EVENT_TYPE_DEBUG 5 +/** event type for tdls packet */ +#define TDLS_EVENT_TYPE_PACKET 6 +/** event type for channel switch result */ +#define TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT 7 +/** event type for start channel switch */ +#define TDLS_EVENT_TYPE_START_CHAN_SWITCH 8 +/** event type for stop channel switch */ +#define TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED 9 + +/** Event ID: Radar Detected */ +#define EVENT_RADAR_DETECTED 0x00000053 +/** Event ID: Channel Report Ready */ +#define EVENT_CHANNEL_REPORT_RDY 0x00000054 + +/** Event ID: NLIST REPORT */ +#define EVENT_NLIST_REPORT 0x00000079 +/** NLIST_REPORT TLV */ +#define MRVL_NEIGHBOR_REPORT_TLV_ID 0x1de + +/** HS WAKE UP event id */ +#define UAP_EVENT_ID_HS_WAKEUP 0x80000001 +/** HS_ACTIVATED event id */ +#define UAP_EVENT_ID_DRV_HS_ACTIVATED 0x80000002 +/** HS DEACTIVATED event id */ +#define UAP_EVENT_ID_DRV_HS_DEACTIVATED 0x80000003 +/** HOST SLEEP AWAKE event id in legacy PS*/ +#define UAP_EVENT_HOST_SLEEP_AWAKE 0x00000012 + +/** HS WAKE UP event id */ +#define UAP_EVENT_ID_DRV_MGMT_FRAME 0x80000005 + +/** SCAN REPORT Event id */ +#define EVENT_ID_DRV_SCAN_REPORT 0x80000009 + +/** WPA IE Tag */ +#define IEEE_WPA_IE 221 +/** RSN IE Tag */ +#define IEEE_RSN_IE 48 + +/** TLV ID : WAPI Information */ +#define MRVL_WAPI_INFO_TLV_ID 0x0167 + +/** TLV ID : Management Frame */ +#define MRVL_MGMT_FRAME_TLV_ID 0x0168 + +/** TLV Id : Channel Config */ +#define MRVL_CHANNELCONFIG_TLV_ID 0x012a + +/** Assoc Request */ +#define SUBTYPE_ASSOC_REQUEST 0 +/** Assoc Response */ +#define SUBTYPE_ASSOC_RESPONSE 1 +/** ReAssoc Request */ +#define SUBTYPE_REASSOC_REQUEST 2 +/** ReAssoc Response */ +#define SUBTYPE_REASSOC_RESPONSE 3 +/** WEP key user input length */ +#define WEP_KEY_USER_INPUT 13 + +/** TLV buffer header*/ +typedef PACK_START struct _tlvbuf_header { + /** Header type */ + t_u16 type; + /** Header length */ + t_u16 len; +} PACK_END tlvbuf_header; + +/** Event body : STA deauth */ +typedef PACK_START struct _eventbuf_sta_deauth { + /** Deauthentication reason */ + t_u16 reason_code; + /** MAC address of deauthenticated STA */ + t_u8 sta_mac_address[ETH_ALEN]; +} PACK_END eventbuf_sta_deauth; + +/** Event body : WEP ICV error */ +typedef PACK_START struct _eventbuf_wep_icv_error { + /** Deauthentication reason */ + t_u16 reason_code; + /** MAC address of deauthenticated STA */ + t_u8 sta_mac_address[ETH_ALEN]; + /** WEP key index */ + t_u8 wep_key_index; + /** WEP key length */ + t_u8 wep_key_length; + /** WEP key */ + t_u8 wep_key[WEP_KEY_USER_INPUT]; +} PACK_END eventbuf_wep_icv_error; + +/** Event body : STA associated */ +typedef PACK_START struct _eventbuf_sta_assoc { + /** Reserved */ + t_u8 reserved[2]; + /** MAC address of associated STA */ + t_u8 sta_mac_address[ETH_ALEN]; + /** Assoc request/response buffer */ + t_u8 assoc_payload[0]; +} PACK_END eventbuf_sta_assoc; + +/** Event body : RSN Connect */ +typedef PACK_START struct _eventbuf_rsn_connect { + /** Reserved */ + t_u8 reserved[2]; + /** MAC address of Station */ + t_u8 sta_mac_address[ETH_ALEN]; + /** WPA/WPA2 TLV IEs */ + t_u8 tlv_list[0]; +} PACK_END eventbuf_rsn_connect; + +/** Event body : BSS started */ +typedef PACK_START struct _eventbuf_bss_start { + /** Reserved */ + t_u8 reserved[2]; + /** MAC address of BSS */ + t_u8 ap_mac_address[ETH_ALEN]; +} PACK_END eventbuf_bss_start; + +/** + * IEEE 802.11 MAC Message Data Structures + * + * Each IEEE 802.11 MAC message includes a MAC header, a frame body (which + * can be empty), and a frame check sequence field. This section gives the + * structures that used for the MAC message headers and frame bodies that + * can exist in the three types of MAC messages - 1) Control messages, + * 2) Data messages, and 3) Management messages. + */ +typedef PACK_START struct _IEEEtypes_FrameCtl_t { + /** Protocol Version */ + t_u8 protocol_version:2; + /** Type */ + t_u8 type:2; + /** Sub Type */ + t_u8 sub_type:4; + /** To DS */ + t_u8 to_ds:1; + /** From DS */ + t_u8 from_ds:1; + /** More Frag */ + t_u8 more_frag:1; + /** Retry */ + t_u8 retry:1; + /** Power Mgmt */ + t_u8 pwr_mgmt:1; + /** More Data */ + t_u8 more_data:1; + /** Wep */ + t_u8 wep:1; + /** Order */ + t_u8 order:1; +} PACK_END IEEEtypes_FrameCtl_t; + +/** IEEEtypes_AssocRqst_t */ +typedef PACK_START struct _IEEEtypes_AssocRqst_t { + /** Capability Info */ + t_u16 cap_info; + /** Listen Interval */ + t_u16 listen_interval; + /** IE Buffer */ + t_u8 ie_buffer[0]; +} PACK_END IEEEtypes_AssocRqst_t; + +/** IEEEtypes_AssocRsp_t */ +typedef PACK_START struct _IEEEtypes_AssocRsp_t { + /** Capability Info */ + t_u16 cap_info; + /** Status Code */ + t_u16 status_code; + /** AID */ + t_u16 aid; +} PACK_END IEEEtypes_AssocRsp_t; + +/** IEEEtypes_ReAssocRqst_t */ +typedef PACK_START struct _IEEEtypes_ReAssocRqst_t { + /** Capability Info */ + t_u16 cap_info; + /** Listen Interval */ + t_u16 listen_interval; + /** Current AP Address */ + t_u8 current_ap_addr[ETH_ALEN]; + /** IE Buffer */ + t_u8 ie_buffer[0]; +} PACK_END IEEEtypes_ReAssocRqst_t; + +/** channel band */ +enum { + BAND_2GHZ = 0, + BAND_5GHZ = 1, + BAND_4GHZ = 2, +}; + +/** channel offset */ +enum { + SEC_CHAN_NONE = 0, + SEC_CHAN_ABOVE = 1, + SEC_CHAN_5MHZ = 2, + SEC_CHAN_BELOW = 3 +}; + +/** channel bandwidth */ +enum { + CHAN_BW_20MHZ = 0, + CHAN_BW_10MHZ, + CHAN_BW_40MHZ, + CHAN_BW_80MHZ, +}; + +/** scan mode */ +enum { + SCAN_MODE_MANUAL = 0, + SCAN_MODE_ACS, + SCAN_MODE_USER, +}; + +/** Band_Config_t */ +typedef PACK_START struct _Band_Config_t { +#ifdef BIG_ENDIAN_SUPPORT + /** Channel Selection Mode - (00)=manual, (01)=ACS, (02)=user*/ + t_u8 scanMode:2; + /** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */ + t_u8 chan2Offset:2; + /** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */ + t_u8 chanWidth:2; + /** Band Info - (00)=2.4GHz, (01)=5GHz */ + t_u8 chanBand:2; +#else + /** Band Info - (00)=2.4GHz, (01)=5GHz */ + t_u8 chanBand:2; + /** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */ + t_u8 chanWidth:2; + /** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */ + t_u8 chan2Offset:2; + /** Channel Selection Mode - (00)=manual, (01)=ACS, (02)=Adoption mode*/ + t_u8 scanMode:2; +#endif +} PACK_END Band_Config_t; + +/** TLV buffer : Channel Config */ +typedef PACK_START struct _tlvbuf_channel_config { + /** Type */ + t_u16 type; + /** Length */ + t_u16 len; + /** Band Configuration */ + Band_Config_t bandcfg; + /** Channel number */ + t_u8 chan_number; +} PACK_END tlvbuf_channel_config; + +/** MrvlIEtypes_WapiInfoSet_t */ +typedef PACK_START struct _MrvlIEtypes_WapiInfoSet_t { + /** Type */ + t_u16 type; + /** Length */ + t_u16 len; + /** Multicast PN */ + t_u8 multicast_PN[16]; +} PACK_END MrvlIEtypes_WapiInfoSet_t; + +/** MrvlIETypes_MgmtFrameSet_t */ +typedef PACK_START struct _MrvlIETypes_MgmtFrameSet_t { + /** Type */ + t_u16 type; + /** Length */ + t_u16 len; + /** Frame Control */ + IEEEtypes_FrameCtl_t frame_control; + /** Frame Contents */ + t_u8 frame_contents[0]; +} PACK_END MrvlIETypes_MgmtFrameSet_t; + +/** Debug Type : Event */ +#define DEBUG_TYPE_EVENT 0 +/** Debug Type : Info */ +#define DEBUG_TYPE_INFO 1 + +/** Major debug id: Authenticator */ +#define DEBUG_ID_MAJ_AUTHENTICATOR 1 +/** Minor debug id: PWK1 */ +#define DEBUG_MAJ_AUTH_MIN_PWK1 0 +/** Minor debug id: PWK2 */ +#define DEBUG_MAJ_AUTH_MIN_PWK2 1 +/** Minor debug id: PWK3 */ +#define DEBUG_MAJ_AUTH_MIN_PWK3 2 +/** Minor debug id: PWK4 */ +#define DEBUG_MAJ_AUTH_MIN_PWK4 3 +/** Minor debug id: GWK1 */ +#define DEBUG_MAJ_AUTH_MIN_GWK1 4 +/** Minor debug id: GWK2 */ +#define DEBUG_MAJ_AUTH_MIN_GWK2 5 +/** Minor debug id: station reject */ +#define DEBUG_MAJ_AUTH_MIN_STA_REJ 6 +/** Minor debug id: EAPOL_TR */ +#define DEBUG_MAJ_AUTH_MIN_EAPOL_TR 7 + +/** Major debug id: Assoicate agent */ +#define DEBUG_ID_MAJ_ASSOC_AGENT 2 +/** Minor debug id: WPA IE*/ +#define DEBUG_ID_MAJ_ASSOC_MIN_WPA_IE 0 +/** Minor debug id: station reject */ +#define DEBUG_ID_MAJ_ASSOC_MIN_STA_REJ 1 + +/** ether_hdr */ +typedef PACK_START struct { + /** Dest address */ + t_u8 da[ETH_ALEN]; + /** Src address */ + t_u8 sa[ETH_ALEN]; + /** Header type */ + t_u16 type; +} PACK_END ether_hdr_t; + +/** 8021x header */ +typedef PACK_START struct { + /** Protocol version*/ + t_u8 protocol_ver; + /** Packet type*/ + t_u8 pckt_type; + /** Packet len */ + t_u8 pckt_body_len; +} PACK_END hdr_8021x_t; + +/** Nonce size */ +#define NONCE_SIZE 32 +/** Max WPA IE len */ +#define MAX_WPA_IE_LEN 64 +/** EAPOL mic size */ +#define EAPOL_MIC_SIZE 16 + +/** EAPOL key message */ +typedef PACK_START struct { + /** Ether header */ + ether_hdr_t ether_hdr; + /** 8021x header */ + hdr_8021x_t hdr_8021x; + /** desc_type */ + t_u8 desc_type; + /** Key info */ + t_u16 k; + /** Key length */ + t_u16 key_length; + /** Replay count */ + t_u32 replay_cnt[2]; + /** Key nonce */ + t_u8 key_nonce[NONCE_SIZE]; + /** Key IV */ + t_u8 eapol_key_iv[16]; + /** Key RSC */ + t_u8 key_rsc[8]; + /** Key ID */ + t_u8 key_id[8]; + /** Key MIC */ + t_u8 key_mic[EAPOL_MIC_SIZE]; + /** Key len */ + t_u16 key_material_len; + /** Key data */ + t_u8 key_data[MAX_WPA_IE_LEN]; +} PACK_END eapol_keymsg_debug_t; + +/** Failure after receive EAPOL MSG2 PMK */ +#define REJECT_STATE_FAIL_EAPOL_2 1 +/** Failure after receive EAPOL MSG4 PMK*/ +#define REJECT_STATE_FAIL_EAPOL_4 2 +/** Failure after receive EAPOL Group MSG2 GWK */ +#define REJECT_STATE_FAIL_EAPOL_GROUP_2 3 + +/** Fail reason: Invalid ie */ +#define IEEEtypes_REASON_INVALID_IE 13 +/** Fail reason: Mic failure */ +#define IEEEtypes_REASON_MIC_FAILURE 14 + +/** Station reject */ +typedef PACK_START struct { + /** Reject state */ + t_u8 reject_state; + /** Reject reason */ + t_u16 reject_reason; + /** Station mac address */ + t_u8 sta_mac_addr[ETH_ALEN]; +} PACK_END sta_reject_t; + +/** wpa_ie */ +typedef PACK_START struct { + /** Station mac address */ + t_u8 sta_mac_addr[ETH_ALEN]; + /** WPA IE */ + t_u8 wpa_ie[MAX_WPA_IE_LEN]; +} PACK_END wpaie_t; + +/** Initial state of the state machine */ +#define EAPOL_START 1 +/** Sent eapol msg1, wait for msg2 from the client */ +#define EAPOL_WAIT_PWK2 2 +/** Sent eapol msg3, wait for msg4 from the client */ +#define EAPOL_WAIT_PWK4 3 +/** Sent eapol group key msg1, wait for group msg2 from the client */ +#define EAPOL_WAIT_GTK2 4 +/** Eapol handshake complete */ +#define EAPOL_END 5 + +#ifdef WIFI_DIRECT_SUPPORT +/** TLV : WifiDirect status */ +#define TLV_TYPE_WIFIDIRECT_STATUS 0x0000 +/** TLV : WifiDirect param capability */ +#define TLV_TYPE_WIFIDIRECT_CAPABILITY 0x0002 +/** TLV : WifiDirect param device Id */ +#define TLV_TYPE_WIFIDIRECT_DEVICE_ID 0x0003 +/** TLV : WifiDirect param group owner intent */ +#define TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT 0x0004 +/** TLV : WifiDirect param config timeout */ +#define TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT 0x0005 +/** TLV : WifiDirect param channel */ +#define TLV_TYPE_WIFIDIRECT_CHANNEL 0x0006 +/** TLV : WifiDirect param group bssId */ +#define TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID 0x0007 +/** TLV : WifiDirect param extended listen time */ +#define TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME 0x0008 +/** TLV : WifiDirect param intended address */ +#define TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS 0x0009 +/** TLV : WifiDirect param manageability */ +#define TLV_TYPE_WIFIDIRECT_MANAGEABILITY 0x000a +/** TLV : WifiDirect param channel list */ +#define TLV_TYPE_WIFIDIRECT_CHANNEL_LIST 0x000b +/** TLV : WifiDirect Notice of Absence */ +#define TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE 0x000c +/** TLV : WifiDirect param device Info */ +#define TLV_TYPE_WIFIDIRECT_DEVICE_INFO 0x000d +/** TLV : WifiDirect param Group Info */ +#define TLV_TYPE_WIFIDIRECT_GROUP_INFO 0x000e +/** TLV : WifiDirect param group Id */ +#define TLV_TYPE_WIFIDIRECT_GROUP_ID 0x000f +/** TLV : WifiDirect param interface */ +#define TLV_TYPE_WIFIDIRECT_INTERFACE 0x0010 +/** TLV : WifiDirect param operating channel */ +#define TLV_TYPE_WIFIDIRECT_OPCHANNEL 0x0011 +/** TLV : WifiDirect param invitation flag */ +#define TLV_TYPE_WIFIDIRECT_INVITATION_FLAG 0x0012 + +/** WPS Device Info OUI+Type+SubType Length */ +#define WPS_DEVICE_TYPE_LEN 8 + +/** IE header len */ +#define IE_HEADER_LEN 2 + +/** WIFIDIRECT IE header len */ +#define WIFIDIRECT_IE_HEADER_LEN 3 + +/** OUI Type WIFIDIRECT */ +#define WIFIDIRECT_OUI_TYPE 9 +/** OUI Type WPS */ +#define WIFI_WPS_OUI_TYPE 4 + +/* + * To handle overlapping WIFIDIRECT IEs + */ +/** IE next byte type */ +#define WIFIDIRECT_OVERLAP_TYPE 1 +/** IE next byte length */ +#define WIFIDIRECT_OVERLAP_LEN 2 +/** IE next byte data */ +#define WIFIDIRECT_OVERLAP_DATA 3 + +/** Max payload for IE buffer */ +#define WIFI_IE_MAX_PAYLOAD 256 + +/** Fixed length fields in bonjour payload query data */ +#define WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN 5 + +/** Fixed length fields in uPnP payload query data */ +#define WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN 3 + +/** Action field for discovery request */ +#define WIFIDIRECT_DISCOVERY_REQUEST_ACTION 10 + +/** Action field for discovery response */ +#define WIFIDIRECT_DISCOVERY_RESPONSE_ACTION 11 + +/** TLV buffer : WifiDirect Status */ +typedef PACK_START struct _tlvbuf_wifidirect_status { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT status code */ + t_u8 status_code; +} PACK_END tlvbuf_wifidirect_status; + +/** TLV buffer : wifidirect IE device Id */ +typedef PACK_START struct _tlvbuf_wifidirect_device_id { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT device MAC address */ + t_u8 dev_mac_address[ETH_ALEN]; +} PACK_END tlvbuf_wifidirect_device_id; + +/** TLV buffer : wifidirect IE capability */ +typedef PACK_START struct _tlvbuf_wifidirect_capability { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT device capability */ + t_u8 dev_capability; + /** WIFIDIRECT group capability */ + t_u8 group_capability; +} PACK_END tlvbuf_wifidirect_capability; + +/** TLV buffer : wifidirect IE Group owner intent */ +typedef PACK_START struct _tlvbuf_wifidirect_group_owner_intent { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT device group owner intent */ + t_u8 dev_intent; +} PACK_END tlvbuf_wifidirect_group_owner_intent; + +/** TLV buffer : WifiDirect IE Manageability */ +typedef PACK_START struct _tlvbuf_wifidirect_manageability { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT Manageability */ + t_u8 manageability; +} PACK_END tlvbuf_wifidirect_manageability; + +/** TLV buffer : WifiDirect IE Invitation Flag */ +typedef PACK_START struct _tlvbuf_wifidirect_invitation_flag { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT Manageability */ + t_u8 invitation_flag; +} PACK_END tlvbuf_wifidirect_invitation_flag; + +/** TLV buffer : wifidirect IE capability */ +typedef PACK_START struct _tlvbuf_wifidirect_channel { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT country string */ + t_u8 country_string[3]; + /** WIFIDIRECT regulatory class */ + t_u8 regulatory_class; + /** WIFIDIRECT channel number */ + t_u8 channel_number; +} PACK_END tlvbuf_wifidirect_channel; + +/** Channel Entry */ +typedef PACK_START struct _chan_entry { + /** WIFIDIRECT regulatory class */ + t_u8 regulatory_class; + /** WIFIDIRECT no of channels */ + t_u8 num_of_channels; + /** WIFIDIRECT channel number */ + t_u8 chan_list[0]; +} PACK_END chan_entry; + +/** TLV buffer : wifidirect IE channel list */ +typedef PACK_START struct _tlvbuf_wifidirect_channel_list { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT country string */ + t_u8 country_string[3]; + /** WIFIDIRECT channel entries */ + chan_entry wifidirect_chan_entry_list[0]; +} PACK_END tlvbuf_wifidirect_channel_list; + +/** NoA Descriptor */ +typedef PACK_START struct _noa_descriptor { + /** WIFIDIRECT count OR type */ + t_u8 count_type; + /** WIFIDIRECT duration */ + t_u32 duration; + /** WIFIDIRECT interval */ + t_u32 interval; + /** WIFIDIRECT start time */ + t_u32 start_time; +} PACK_END noa_descriptor; + +/** TLV buffer : WifiDirect IE Notice of Absence */ +typedef PACK_START struct _tlvbuf_wifidirect_notice_of_absence { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT NoA Index */ + t_u8 noa_index; + /** WIFIDIRECT CTWindow and OppPS parameters */ + t_u8 ctwindow_opp_ps; + /** WIFIDIRECT NoA Descriptor list */ + noa_descriptor wifidirect_noa_descriptor_list[0]; +} PACK_END tlvbuf_wifidirect_notice_of_absence; + +/** TLV buffer : wifidirect IE device Info */ +typedef PACK_START struct _tlvbuf_wifidirect_device_info { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT device address */ + t_u8 dev_address[ETH_ALEN]; + /** WPS config methods */ + t_u16 config_methods; + /** Primary device type : category */ + t_u16 primary_category; + /** Primary device type : OUI */ + t_u8 primary_oui[4]; + /** Primary device type : sub-category */ + t_u16 primary_subcategory; + /** Secondary Device Count */ + t_u8 secondary_dev_count; + /** Secondary Device Info */ + t_u8 secondary_dev_info[0]; + /** WPS Device Name Tag */ + t_u16 device_name_type; + /** WPS Device Name Length */ + t_u16 device_name_len; + /** Device name */ + t_u8 device_name[0]; +} PACK_END tlvbuf_wifidirect_device_info; + +typedef PACK_START struct _wifidirect_client_dev_info { + /** Length of each device */ + t_u8 dev_length; + /** WIFIDIRECT device address */ + t_u8 wifidirect_dev_address[ETH_ALEN]; + /** WIFIDIRECT Interface address */ + t_u8 wifidirect_intf_address[ETH_ALEN]; + /** WIFIDIRECT Device capability*/ + t_u8 wifidirect_dev_capability; + /** WPS config methods */ + t_u16 config_methods; + /** Primary device type : category */ + t_u16 primary_category; + /** Primary device type : OUI */ + t_u8 primary_oui[4]; + /** Primary device type : sub-category */ + t_u16 primary_subcategory; + /** Secondary Device Count */ + t_u8 wifidirect_secondary_dev_count; + /** Secondary Device Info */ + t_u8 wifidirect_secondary_dev_info[0]; + /** WPS WIFIDIRECT Device Name Tag */ + t_u16 wifidirect_device_name_type; + /** WPS WIFIDIRECT Device Name Length */ + t_u16 wifidirect_device_name_len; + /** WIFIDIRECT Device name */ + t_u8 wifidirect_device_name[0]; +} PACK_END wifidirect_client_dev_info; + +typedef PACK_START struct _tlvbuf_wifidirect_group_info { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** Secondary Device Info */ + t_u8 wifidirect_client_dev_list[0]; +} PACK_END tlvbuf_wifidirect_group_info; + +/** TLV buffer : wifidirect IE group Id */ +typedef PACK_START struct _tlvbuf_wifidirect_group_id { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT group MAC address */ + t_u8 group_address[ETH_ALEN]; + /** WIFIDIRECT group SSID */ + t_u8 group_ssid[0]; +} PACK_END tlvbuf_wifidirect_group_id; + +/** TLV buffer : wifidirect IE group BSS Id */ +typedef PACK_START struct _tlvbuf_wifidirect_group_bss_id { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT group Bss Id */ + t_u8 group_bssid[ETH_ALEN]; +} PACK_END tlvbuf_wifidirect_group_bss_id; + +/** TLV buffer : wifidirect IE Interface */ +typedef PACK_START struct _tlvbuf_wifidirect_interface { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT interface Id */ + t_u8 interface_id[ETH_ALEN]; + /** WIFIDIRECT interface count */ + t_u8 interface_count; + /** WIFIDIRECT interface addresslist */ + t_u8 interface_idlist[0]; +} PACK_END tlvbuf_wifidirect_interface; + +/** TLV buffer : WifiDirect configuration timeout */ +typedef PACK_START struct _tlvbuf_wifidirect_config_timeout { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** Group configuration timeout */ + t_u8 group_config_timeout; + /** Device configuration timeout */ + t_u8 device_config_timeout; +} PACK_END tlvbuf_wifidirect_config_timeout; + +/** TLV buffer : WifiDirect extended listen time */ +typedef PACK_START struct _tlvbuf_wifidirect_ext_listen_time { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** Availability period */ + t_u16 availability_period; + /** Availability interval */ + t_u16 availability_interval; +} PACK_END tlvbuf_wifidirect_ext_listen_time; + +/** TLV buffer : WifiDirect Intended Interface Address */ +typedef PACK_START struct _tlvbuf_wifidirect_intended_addr { + /** TLV Header tag */ + t_u8 tag; + /** TLV Header length */ + t_u16 length; + /** WIFIDIRECT Group interface address */ + t_u8 group_address[ETH_ALEN]; +} PACK_END tlvbuf_wifidirect_intended_addr; + +/** TLV buffer : Wifi WPS IE */ +typedef PACK_START struct _tlvbuf_wifi_wps_ie { + /** TLV Header tag */ + t_u16 tag; + /** TLV Header length */ + t_u16 length; + /** WIFI WPS IE data */ + t_u8 data[0]; +} PACK_END tlvbuf_wps_ie; + +/** WifiDirect IE Header */ +typedef PACK_START struct _wifidirect_ie_header { + /** Element ID */ + t_u8 element_id; + /** IE Length */ + t_u8 ie_length; + /** OUI */ + t_u8 oui[3]; + /** OUI type */ + t_u8 oui_type; + /** IE List of TLV */ + t_u8 ie_list[0]; +} PACK_END wifidirect_ie_header; + +/** Event : WifiDirect Generic event */ +typedef PACK_START struct _apeventbuf_wifidirect_generic { + /** Event Length */ + t_u16 event_length; + /** Event Type */ + t_u16 event_type; + /** Event SubType */ + t_u16 event_sub_type; + /** Peer mac address */ + t_u8 peer_mac_addr[ETH_ALEN]; + /** IE List of TLV */ + t_u8 entire_ie_list[0]; +} PACK_END apeventbuf_wifidirect_generic; + +/** Internal WIFIDIRECT structure for Query Data */ +typedef PACK_START struct wifidirect_query_data { + union { + PACK_START struct upnp_specific_query { + /** version field */ + t_u8 version; + /** value */ + t_u8 value[0]; + } PACK_END upnp; + + PACK_START struct bonjour_specific_query { + /** DNS name */ + t_u8 dns[0]; + /** DNS type */ + t_u8 dns_type; + /** version field */ + t_u8 version; + } PACK_END bonjour; + } u; +} PACK_END wifidirect_query_data; + +/** Internal WIFIDIRECT structure for Response Data */ +typedef PACK_START struct wifidirect_Response_data { + union { + PACK_START struct upnp_specific_response { + /** version field */ + t_u8 version; + /** value */ + t_u8 value[0]; + } PACK_END upnp; + + PACK_START struct bonjour_specific_response { + /** DNS name */ + t_u8 dns[0]; + /** DNS type */ + t_u8 dns_type; + /** version field */ + t_u8 version; + /** DNS name */ + t_u8 record[0]; + } PACK_END bonjour; + } u; +} PACK_END wifidirect_response_data; + +/** Event : Service Discovery request */ +typedef PACK_START struct _apeventbuf_wifidirect_discovery_request { + /** Peer mac address */ + t_u8 peer_mac_addr[ETH_ALEN]; + /** Category */ + t_u8 category; + /** Action */ + t_u8 action; + /** Dialog taken */ + t_u8 dialog_taken; + /** Advertize protocol IE */ + t_u8 advertize_protocol_ie[4]; + /** Query request Length */ + t_u16 query_len; + /** Information identifier */ + t_u8 info_id[2]; + /** Request Length */ + t_u16 request_len; + /** OUI */ + t_u8 oui[3]; + /** OUI sub type */ + t_u8 oui_sub_type; + /** Service update indicator */ + t_u16 service_update_indicator; + /** Vendor Length */ + t_u16 vendor_len; + /** Service protocol */ + t_u8 service_protocol; + /** Service transaction Id */ + t_u8 service_transaction_id; + /** Query Data */ + wifidirect_query_data disc_query; +} PACK_END apeventbuf_wifidirect_discovery_request; + +/** HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY response */ +typedef PACK_START struct _apeventbuf_wifidirect_discovery_response { + /** Peer mac address */ + t_u8 peer_mac_addr[ETH_ALEN]; + /** Category */ + t_u8 category; + /** Action */ + t_u8 action; + /** Dialog taken */ + t_u8 dialog_taken; + /** Status code */ + t_u8 status_code; + /** GAS comback reply */ + t_u16 gas_reply; + /** Advertize protocol IE */ + t_u8 advertize_protocol_ie[4]; + /** Query response Length */ + t_u16 query_len; + /** Information identifier */ + t_u8 info_id[2]; + /** Response Length */ + t_u16 response_len; + /** OUI */ + t_u8 oui[3]; + /** OUI sub type */ + t_u8 oui_sub_type; + /** Service update indicator */ + t_u16 service_update_indicator; + /** Vendor Length */ + t_u16 vendor_len; + /** Service protocol */ + t_u8 service_protocol; + /** Service transaction Id */ + t_u8 service_transaction_id; + /** Discovery status code */ + t_u8 disc_status_code; + /** Response Data */ + wifidirect_response_data disc_resp; +} PACK_END apeventbuf_wifidirect_discovery_response; + +/** enum : WPS attribute type */ +typedef enum { + SC_AP_Channel = 0x1001, + SC_Association_State = 0x1002, + SC_Authentication_Type = 0x1003, + SC_Authentication_Type_Flags = 0x1004, + SC_Authenticator = 0x1005, + SC_Config_Methods = 0x1008, + SC_Configuration_Error = 0x1009, + SC_Confirmation_URL4 = 0x100A, + SC_Confirmation_URL6 = 0x100B, + SC_Connection_Type = 0x100C, + SC_Connection_Type_Flags = 0x100D, + SC_Credential = 0x100E, + SC_Device_Name = 0x1011, + SC_Device_Password_ID = 0x1012, + SC_E_Hash1 = 0x1014, + SC_E_Hash2 = 0x1015, + SC_E_SNonce1 = 0x1016, + SC_E_SNonce2 = 0x1017, + SC_Encrypted_Settings = 0x1018, + SC_Encryption_Type = 0X100F, + SC_Encryption_Type_Flags = 0x1010, + SC_Enrollee_Nonce = 0x101A, + SC_Feature_ID = 0x101B, + SC_Identity = 0X101C, + SC_Identity_Proof = 0X101D, + SC_Key_Wrap_Authenticator = 0X101E, + SC_Key_Identifier = 0X101F, + SC_MAC_Address = 0x1020, + SC_Manufacturer = 0x1021, + SC_Message_Type = 0x1022, + SC_Model_Name = 0x1023, + SC_Model_Number = 0x1024, + SC_Network_Index = 0x1026, + SC_Network_Key = 0x1027, + SC_Network_Key_Index = 0x1028, + SC_New_Device_Name = 0x1029, + SC_New_Password = 0x102A, + SC_OOB_Device_Password = 0X102C, + SC_OS_Version = 0X102D, + SC_Power_Level = 0X102F, + SC_PSK_Current = 0x1030, + SC_PSK_Max = 0x1031, + SC_Public_Key = 0x1032, + SC_Radio_Enabled = 0x1033, + SC_Reboot = 0x1034, + SC_Registrar_Current = 0x1035, + SC_Registrar_Established = 0x1036, + SC_Registrar_List = 0x1037, + SC_Registrar_Max = 0x1038, + SC_Registrar_Nonce = 0x1039, + SC_Request_Type = 0x103A, + SC_Response_Type = 0x103B, + SC_RF_Band = 0X103C, + SC_R_Hash1 = 0X103D, + SC_R_Hash2 = 0X103E, + SC_R_SNonce1 = 0X103F, + SC_R_SNonce2 = 0x1040, + SC_Selected_Registrar = 0x1041, + SC_Serial_Number = 0x1042, + SC_Simple_Config_State = 0x1044, + SC_SSID = 0x1045, + SC_Total_Networks = 0x1046, + SC_UUID_E = 0x1047, + SC_UUID_R = 0x1048, + SC_Vendor_Extension = 0x1049, + SC_Version = 0x104A, + SC_X_509_Certificate_Request = 0x104B, + SC_X_509_Certificate = 0x104C, + SC_EAP_Identity = 0x104D, + SC_Message_Counter = 0x104E, + SC_Public_Key_Hash = 0x104F, + SC_Rekey_Key = 0x1050, + SC_Key_Lifetime = 0x1051, + SC_Permitted_Config_Methods = 0x1052, + SC_SelectedRegistrarConfigMethods = 0x1053, + SC_Primary_Device_Type = 0x1054, + SC_Secondary_Device_Type_List = 0x1055, + SC_Portable_Device = 0x1056, + SC_AP_Setup_Locked = 0x1057, + SC_Application_List = 0x1058, + SC_EAP_Type = 0x1059, + SC_Initialization_Vector = 0x1060, + SC_Key_Provided_Auto = 0x1061, + SC_8021x_Enabled = 0x1062, + SC_App_Session_key = 0x1063, + SC_WEP_Transmit_Key = 0x1064, +} wps_simple_config_attribute; +#endif + +/** structure for channel switch result from TDLS FW */ +typedef PACK_START struct _Channel_switch_result { + /** current channel, 0 - base channel, 1 - off channel*/ + t_u8 current_channel; + /** channel switch status*/ + t_u8 status; + /** channel switch fauilure reason code*/ + t_u8 reason; +} PACK_END Channel_switch_result; + +/** Event : TDLS Generic event */ +typedef PACK_START struct _eventbuf_tdls_generic { + /** Event Type */ + t_u16 event_type; + /** Peer mac address */ + t_u8 peer_mac_addr[ETH_ALEN]; + union { + /** channel switch result structure*/ + Channel_switch_result switch_result; + /** channel switch stop reason */ + t_u8 cs_stop_reason; + /** Reason code */ + t_u16 reason_code; + /** IE Length */ + t_u16 ie_length; + } u; + /** IE pointer */ + t_u8 ie_ptr[0]; +} PACK_END eventbuf_tdls_generic; + +/** Event : TDLS Debug event */ +typedef PACK_START struct _eventbuf_tdls_debug { + /** Event Type */ + t_u16 event_type; + /** TimeStamp value */ + t_u64 tsf; + /** First argument */ + t_u32 first_arg; + /** Second argument */ + t_u32 second_arg; + /** Third argument */ + t_u32 third_arg; + /** Third argument */ + t_u16 string_len; + /** Third argument */ + t_u8 string[0]; +} PACK_END eventbuf_tdls_debug; + +/** Event : TDLS packet event */ +typedef PACK_START struct _eventbuf_tdls_packet { + /** Event Type */ + t_u16 event_type; + /** Length */ + t_u16 length; + /** packet data */ + t_u8 data[0]; +} PACK_END eventbuf_tdls_packet; + +/** Eapol state */ +typedef PACK_START struct { + /** Eapol state*/ + t_u8 eapol_state; + /** Station address*/ + t_u8 sta_mac_addr[ETH_ALEN]; +} PACK_END eapol_state_t; + +/** Debug Info */ +typedef PACK_START union { + /** Eapol key message */ + eapol_keymsg_debug_t eapol_pwkmsg; + /** Station reject*/ + sta_reject_t sta_reject; + /** WPA IE */ + wpaie_t wpaie; + /** Eapol state */ + eapol_state_t eapol_state; +} PACK_END d_info; + +/** Event body : Debug */ +typedef PACK_START struct _eventbuf_debug { + /** Debug type */ + t_u8 debug_type; + /** Major debug id */ + t_u32 debug_id_major; + /** Minor debug id */ + t_u32 debug_id_minor; + /** Debug Info */ + d_info info; +} PACK_END eventbuf_debug; + +/** Event body : 11K NLIST */ +typedef PACK_START struct _nlist_entry_tlv { + tlvbuf_header hdr; + t_u8 bssid[6]; + t_u8 bssid_info[4]; + t_u8 reg_class; + t_u8 chan; + t_u8 phy_type; +} PACK_END nlist_entry_tlv; + +int ishexstring(void *hex); +unsigned int a2hex(char *s); +/** + * @brief isdigit for String. + * + * @param x Char string + * @return MLAN_EVENT_FAILURE for non-digit. + * 0 for digit + */ +static inline int +ISDIGIT(char *x) +{ + unsigned int i; + for (i = 0; i < strlen(x); i++) + if (isdigit(x[i]) == 0) + return MLAN_EVENT_FAILURE; + return 0; +} + +/** debug level */ +enum _debug_level { + MSG_NONE, + MSG_DEBUG, + MSG_ALL +}; +#endif /* _MLAN_EVENT_H */ diff --git a/mwifiex_8997/mapp/mlanutl/Makefile b/mwifiex_8997/mapp/mlanutl/Makefile new file mode 100755 index 0000000..a8062e2 --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/Makefile @@ -0,0 +1,54 @@ +# File : mlanutl/Makefile +# +# Copyright (C) 2011-2019, Marvell International Ltd. All Rights Reserved + +# Path to the top directory of the wlan distribution +PATH_TO_TOP = ../.. + +# Determine how we should copy things to the install directory +ABSPATH := $(filter /%, $(INSTALLDIR)) +RELPATH := $(filter-out /%, $(INSTALLDIR)) +INSTALLPATH := $(ABSPATH) +ifeq ($(strip $(INSTALLPATH)),) +INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH) +endif + +# Override CFLAGS for application sources, remove __ kernel namespace defines +CFLAGS := $(filter-out -D__%, $(ccflags-y)) +# remove KERNEL include dir +CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS)) + + +#CFLAGS += -DAP22 -fshort-enums +CFLAGS += -Wall +#ECHO = @ +LIBS = -lrt + +.PHONY: default tags all + +OBJECTS = mlanutl.o +HEADERS = mlanutl.h + + + +exectarget=mlanutl +TARGET := $(exectarget) + +build default: $(TARGET) + @cp -f $(TARGET) $(INSTALLPATH) + +all : tags default + +$(TARGET): $(OBJECTS) $(HEADERS) + $(ECHO)$(CC) $(LIBS) -o $@ $(OBJECTS) + +%.o: %.c $(HEADERS) + $(ECHO)$(CC) $(CFLAGS) -c -o $@ $< + +tags: + ctags -R -f tags.txt + +distclean clean: + $(ECHO)$(RM) $(OBJECTS) $(TARGET) + $(ECHO)$(RM) tags.txt + diff --git a/mwifiex_8997/mapp/mlanutl/mlanhostcmd.c b/mwifiex_8997/mapp/mlanutl/mlanhostcmd.c new file mode 100755 index 0000000..269f948 --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanhostcmd.c @@ -0,0 +1,922 @@ +/** @file mlanhostcmd.c + * + * @brief This file contains mlanutl helper functions + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 11/26/2008: initial version +************************************************************************/ + +#include "mlanhostcmd.h" + +#ifndef MIN +/** Find minimum value */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ +/** + * @brief get hostcmd data + * + * @param ln A pointer to line number + * @param buf A pointer to hostcmd data + * @param size A pointer to the return size of hostcmd buffer + * @return MLAN_STATUS_SUCCESS + */ +static int +mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size) +{ + t_s32 errors = 0, i; + t_s8 line[512], *pos, *pos1, *pos2, *pos3; + t_u16 len; + + while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) { + (*ln)++; + if (strcmp(pos, "}") == 0) { + break; + } + + pos1 = strchr(pos, ':'); + if (pos1 == NULL) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos1++ = '\0'; + + pos2 = strchr(pos1, '='); + if (pos2 == NULL) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos2++ = '\0'; + + len = a2hex_or_atoi(pos1); + if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + + *size += len; + + if (*pos2 == '"') { + pos2++; + pos3 = strchr(pos2, '"'); + if (pos3 == NULL) { + printf("Line %d: invalid quotation '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos3 = '\0'; + memset(buf, 0, len); + memmove(buf, pos2, MIN(strlen(pos2), len)); + buf += len; + } else if (*pos2 == '\'') { + pos2++; + pos3 = strchr(pos2, '\''); + if (pos3 == NULL) { + printf("Line %d: invalid quotation '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos3 = ','; + for (i = 0; i < len; i++) { + pos3 = strchr(pos2, ','); + if (pos3 != NULL) { + *pos3 = '\0'; + *buf++ = (t_u8)a2hex_or_atoi(pos2); + pos2 = pos3 + 1; + } else + *buf++ = 0; + } + } else if (*pos2 == '{') { + t_u16 tlvlen = 0, tmp_tlvlen; + mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen); + tmp_tlvlen = tlvlen; + while (len--) { + *buf++ = (t_u8)(tmp_tlvlen & 0xff); + tmp_tlvlen >>= 8; + } + *size += tlvlen; + buf += tlvlen; + } else { + t_u32 value = a2hex_or_atoi(pos2); + while (len--) { + *buf++ = (t_u8)(value & 0xff); + value >>= 8; + } + } + } + return MLAN_STATUS_SUCCESS; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief convert char to hex integer + * + * @param chr char to convert + * @return hex integer or 0 + */ +int +hexval(t_s32 chr) +{ + if (chr >= '0' && chr <= '9') + return chr - '0'; + if (chr >= 'A' && chr <= 'F') + return chr - 'A' + 10; + if (chr >= 'a' && chr <= 'f') + return chr - 'a' + 10; + + return 0; +} + +/** + * @brief Hump hex data + * + * @param prompt A pointer prompt buffer + * @param p A pointer to data buffer + * @param len the len of data buffer + * @param delim delim char + * @return hex integer + */ +t_void +hexdump(t_s8 *prompt, t_void *p, t_s32 len, t_s8 delim) +{ + t_s32 i; + t_u8 *s = p; + + if (prompt) { + printf("%s: len=%d\n", prompt, (int)len); + } + for (i = 0; i < len; i++) { + if (i != len - 1) + printf("%02x%c", *s++, delim); + else + printf("%02x\n", *s); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); +} + +/** + * @brief convert char to hex integer + * + * @param chr char + * @return hex integer + */ +t_u8 +hexc2bin(t_s8 chr) +{ + if (chr >= '0' && chr <= '9') + chr -= '0'; + else if (chr >= 'A' && chr <= 'F') + chr -= ('A' - 10); + else if (chr >= 'a' && chr <= 'f') + chr -= ('a' - 10); + + return chr; +} + +/** + * @brief convert string to hex integer + * + * @param s A pointer string buffer + * @return hex integer + */ +t_u32 +a2hex(t_s8 *s) +{ + t_u32 val = 0; + + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + + while (*s && isxdigit(*s)) { + val = (val << 4) + hexc2bin(*s++); + } + + return val; +} + +/* + * @brief convert String to integer + * + * @param value A pointer to string + * @return integer + */ +t_u32 +a2hex_or_atoi(t_s8 *value) +{ + if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) { + return a2hex(value + 2); + } else if (isdigit(*value)) { + return atoi(value); + } else { + return *value; + } +} + +/** + * @brief convert string to hex + * + * @param ptr A pointer to data buffer + * @param chr A pointer to return integer + * @return A pointer to next data field + */ +t_s8 * +convert2hex(t_s8 *ptr, t_u8 *chr) +{ + t_u8 val; + + for (val = 0; *ptr && isxdigit(*ptr); ptr++) { + val = (val * 16) + hexval(*ptr); + } + + *chr = val; + + return ptr; +} + +/** + * @brief Check the Hex String + * @param s A pointer to the string + * @return MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString + */ +int +ishexstring(t_s8 *s) +{ + int ret = MLAN_STATUS_FAILURE; + t_s32 tmp; + + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + while (*s) { + tmp = toupper(*s); + if (((tmp >= 'A') && (tmp <= 'F')) || + ((tmp >= '0') && (tmp <= '9'))) { + ret = MLAN_STATUS_SUCCESS; + } else { + ret = MLAN_STATUS_FAILURE; + break; + } + s++; + } + + return ret; +} + +/** + * @brief Convert String to Integer + * @param buf A pointer to the string + * @return Integer + */ +int +atoval(t_s8 *buf) +{ + if (!strncasecmp(buf, "0x", 2)) + return a2hex(buf + 2); + else if (!ishexstring(buf)) + return a2hex(buf); + else + return atoi(buf); +} + +/** + * @brief Prepare host-command buffer + * @param fp File handler + * @param cmd_name Command name + * @param buf A pointer to comand buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf) +{ + t_s8 line[256], cmdname[256], *pos, cmdcode[10]; + HostCmd_DS_GEN *hostcmd; + int ln = 0; + int cmdname_found = 0, cmdcode_found = 0; + + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + hostcmd = (HostCmd_DS_GEN *)buf; + hostcmd->command = 0xffff; + + snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name); + cmdname_found = 0; + while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { + if (strcmp(pos, cmdname) == 0) { + cmdname_found = 1; + snprintf(cmdcode, sizeof(cmdcode), "CmdCode="); + cmdcode_found = 0; + while ((pos = + mlan_config_get_line(fp, line, sizeof(line), + &ln))) { + if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) { + cmdcode_found = 1; + hostcmd->command = + a2hex_or_atoi(pos + + strlen(cmdcode)); + hostcmd->size = S_DS_GEN; + mlan_get_hostcmd_data(fp, &ln, + buf + + hostcmd->size, + &hostcmd->size); + break; + } + } + if (!cmdcode_found) { + fprintf(stderr, + "mlanutl: CmdCode not found in conf file\n"); + return MLAN_STATUS_FAILURE; + } + break; + } + } + + if (!cmdname_found) { + fprintf(stderr, + "mlanutl: cmdname '%s' is not found in conf file\n", + cmd_name); + return MLAN_STATUS_FAILURE; + } + + hostcmd->seq_num = 0; + hostcmd->result = 0; + hostcmd->command = cpu_to_le16(hostcmd->command); + hostcmd->size = cpu_to_le16(hostcmd->size); + return MLAN_STATUS_SUCCESS; +} + +/** Config data header length */ +#define CFG_DATA_HEADER_LEN 6 + +/** + * @brief Prepare cfg-data buffer + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param fp File handler + * @param buf A pointer to comand buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf) +{ + int ln = 0, type; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_802_11_CFG_DATA *pcfg_data; + + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + hostcmd = (HostCmd_DS_GEN *)buf; + hostcmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); + pcfg_data = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN); + pcfg_data->action = + (argc == 4) ? HostCmd_ACT_GEN_GET : HostCmd_ACT_GEN_SET; + type = atoi(argv[3]); + if ((type < 1) || (type > 2)) { + fprintf(stderr, "mlanutl: Invalid register type\n"); + return MLAN_STATUS_FAILURE; + } else { + pcfg_data->type = type; + } + if (argc == 5) { + ln = fparse_for_hex(fp, pcfg_data->data); + } + pcfg_data->data_len = ln; + hostcmd->size = + cpu_to_le16(pcfg_data->data_len + S_DS_GEN + + CFG_DATA_HEADER_LEN); + pcfg_data->data_len = cpu_to_le16(pcfg_data->data_len); + pcfg_data->type = cpu_to_le16(pcfg_data->type); + pcfg_data->action = cpu_to_le16(pcfg_data->action); + + hostcmd->seq_num = 0; + hostcmd->result = 0; + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process host_cmd response + * @param buf A pointer to the response buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_host_cmd_resp(t_u8 *buf) +{ + HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf; + int ret = MLAN_STATUS_SUCCESS; + + hostcmd->command = le16_to_cpu(hostcmd->command); + hostcmd->size = le16_to_cpu(hostcmd->size); + hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num); + hostcmd->result = le16_to_cpu(hostcmd->result); + + hostcmd->command &= ~HostCmd_RET_BIT; + if (!hostcmd->result) { + switch (hostcmd->command) { + case HostCmd_CMD_CFG_DATA: + { + HostCmd_DS_802_11_CFG_DATA *pstcfgData = + (HostCmd_DS_802_11_CFG_DATA *)(buf + + S_DS_GEN); + pstcfgData->data_len = + le16_to_cpu(pstcfgData->data_len); + pstcfgData->action = + le16_to_cpu(pstcfgData->action); + + if (pstcfgData->action == HostCmd_ACT_GEN_GET) { + hexdump("cfgdata", pstcfgData->data, + pstcfgData->data_len, ' '); + } + break; + } + case HostCmd_CMD_802_11_TPC_ADAPT_REQ: + { + mlan_ioctl_11h_tpc_resp *tpcIoctlResp = + (mlan_ioctl_11h_tpc_resp *)(buf + + S_DS_GEN); + if (tpcIoctlResp->status_code == 0) { + printf("tpcrequest: txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi); + } else { + printf("tpcrequest: failure, status = %d\n", tpcIoctlResp->status_code); + } + break; + } + case HostCmd_CMD_802_11_CRYPTO: + { + t_u16 alg = + le16_to_cpu((t_u16) + *(buf + S_DS_GEN + + sizeof(t_u16))); + if (alg != CIPHER_TEST_AES_CCM && + alg != CIPHER_TEST_GCMP) { + HostCmd_DS_802_11_CRYPTO *cmd = + (HostCmd_DS_802_11_CRYPTO *)(buf + + + S_DS_GEN); + cmd->encdec = le16_to_cpu(cmd->encdec); + cmd->algorithm = + le16_to_cpu(cmd->algorithm); + cmd->key_IV_length = + le16_to_cpu(cmd->key_IV_length); + cmd->key_length = + le16_to_cpu(cmd->key_length); + cmd->data.header.type = + le16_to_cpu(cmd->data.header. + type); + cmd->data.header.len = + le16_to_cpu(cmd->data.header. + len); + + printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len); + hexdump("KeyIV", cmd->keyIV, + cmd->key_IV_length, ' '); + hexdump("Key", cmd->key, + cmd->key_length, ' '); + hexdump("Data", cmd->data.data, + cmd->data.header.len, ' '); + } else { + HostCmd_DS_802_11_CRYPTO_AES_CCM + *cmd_aes_ccm = + (HostCmd_DS_802_11_CRYPTO_AES_CCM + *)(buf + S_DS_GEN); + + cmd_aes_ccm->encdec + = + le16_to_cpu(cmd_aes_ccm-> + encdec); + cmd_aes_ccm->algorithm = + le16_to_cpu(cmd_aes_ccm-> + algorithm); + cmd_aes_ccm->key_length = + le16_to_cpu(cmd_aes_ccm-> + key_length); + cmd_aes_ccm->nonce_length = + le16_to_cpu(cmd_aes_ccm-> + nonce_length); + cmd_aes_ccm->AAD_length = + le16_to_cpu(cmd_aes_ccm-> + AAD_length); + cmd_aes_ccm->data.header.type = + le16_to_cpu(cmd_aes_ccm->data. + header.type); + cmd_aes_ccm->data.header.len = + le16_to_cpu(cmd_aes_ccm->data. + header.len); + + printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len); + + hexdump("Key", cmd_aes_ccm->key, + cmd_aes_ccm->key_length, ' '); + hexdump("Nonce", cmd_aes_ccm->nonce, + cmd_aes_ccm->nonce_length, ' '); + hexdump("AAD", cmd_aes_ccm->AAD, + cmd_aes_ccm->AAD_length, ' '); + hexdump("Data", cmd_aes_ccm->data.data, + cmd_aes_ccm->data.header.len, + ' '); + } + break; + } + case HostCmd_CMD_802_11_AUTO_TX: + { + HostCmd_DS_802_11_AUTO_TX *at = + (HostCmd_DS_802_11_AUTO_TX *)(buf + + S_DS_GEN); + + if (le16_to_cpu(at->action) == + HostCmd_ACT_GEN_GET) { + if (S_DS_GEN + sizeof(at->action) == + hostcmd->size) { + printf("auto_tx not configured\n"); + + } else { + MrvlIEtypesHeader_t *header = + &at->auto_tx.header; + + header->type = + le16_to_cpu(header-> + type); + header->len = + le16_to_cpu(header-> + len); + + if ((S_DS_GEN + + sizeof(at->action) + + + sizeof(MrvlIEtypesHeader_t) + + header->len == + hostcmd->size) && + (header->type == + TLV_TYPE_AUTO_TX)) { + + AutoTx_MacFrame_t *atmf + = + &at->auto_tx. + auto_tx_mac_frame; + + printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval)); + printf("Priority: %#x\n", atmf->priority); + printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len)); + printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]); + printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]); + + hexdump("Frame Payload", + atmf->payload, + le16_to_cpu + (atmf-> + frame_len) + - + MLAN_MAC_ADDR_LENGTH + * 2, ' '); + } else { + printf("incorrect auto_tx command response\n"); + } + } + } + break; + } + case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: + { + HostCmd_DS_802_11_SUBSCRIBE_EVENT *se = + (HostCmd_DS_802_11_SUBSCRIBE_EVENT + *)(buf + S_DS_GEN); + if (le16_to_cpu(se->action) == + HostCmd_ACT_GEN_GET) { + int len = + S_DS_GEN + + sizeof + (HostCmd_DS_802_11_SUBSCRIBE_EVENT); + printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n"); + while (len < hostcmd->size) { + MrvlIEtypesHeader_t *header = + (MrvlIEtypesHeader_t + *)(buf + len); + switch (le16_to_cpu + (header->type)) { + case TLV_TYPE_RSSI_LOW: + { + MrvlIEtypes_RssiThreshold_t + *low_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_LOW: + { + MrvlIEtypes_SnrThreshold_t + *low_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no"); + break; + } + case TLV_TYPE_FAILCOUNT: + { + MrvlIEtypes_FailureCount_t + *failure_count + = + (MrvlIEtypes_FailureCount_t + *)(buf + + + len); + printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no"); + break; + } + case TLV_TYPE_BCNMISS: + { + MrvlIEtypes_BeaconsMissed_t + *bcn_missed + = + (MrvlIEtypes_BeaconsMissed_t + *)(buf + + + len); + printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_HIGH: + { + MrvlIEtypes_RssiThreshold_t + *high_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no"); + break; + } + + case TLV_TYPE_SNR_HIGH: + { + MrvlIEtypes_SnrThreshold_t + *high_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_LOW_DATA: + { + MrvlIEtypes_RssiThreshold_t + *low_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_LOW_DATA: + { + MrvlIEtypes_SnrThreshold_t + *low_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_HIGH_DATA: + { + MrvlIEtypes_RssiThreshold_t + *high_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_HIGH_DATA: + { + MrvlIEtypes_SnrThreshold_t + *high_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no"); + break; + } + case TLV_TYPE_LINK_QUALITY: + { + MrvlIEtypes_LinkQuality_t + *link_qual + = + (MrvlIEtypes_LinkQuality_t + *)(buf + + + len); + printf("Link Quality Parameters:\n"); + printf("------------------------\n"); + printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no"); + printf("Link SNR Threshold = %d\n", le16_to_cpu(link_qual->link_SNR_thrs)); + printf("Link SNR Frequency = %d\n", le16_to_cpu(link_qual->link_SNR_freq)); + printf("Min Rate Value = %d\n", le16_to_cpu(link_qual->min_rate_val)); + printf("Min Rate Frequency = %d\n", le16_to_cpu(link_qual->min_rate_freq)); + printf("Tx Latency Value = %d\n", le32_to_cpu(link_qual->tx_latency_val)); + printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs)); + + break; + } + case TLV_TYPE_PRE_BEACON_LOST: + { + MrvlIEtypes_PreBeaconLost_t + *pre_bcn_lost + = + (MrvlIEtypes_PreBeaconLost_t + *)(buf + + + len); + printf("------------------------\n"); + printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no"); + printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost); + break; + } + default: + printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len)); + break; + } + + len += (sizeof + (MrvlIEtypesHeader_t) + + + le16_to_cpu(header-> + len)); + } + } + break; + } + case HostCmd_CMD_MAC_REG_ACCESS: + case HostCmd_CMD_BBP_REG_ACCESS: + case HostCmd_CMD_RF_REG_ACCESS: + case HostCmd_CMD_CAU_REG_ACCESS: + { + HostCmd_DS_REG *preg = + (HostCmd_DS_REG *)(buf + S_DS_GEN); + preg->action = le16_to_cpu(preg->action); + if (preg->action == HostCmd_ACT_GEN_GET) { + preg->value = le32_to_cpu(preg->value); + printf("value = 0x%08x\n", preg->value); + } + break; + } + case HostCmd_CMD_MEM_ACCESS: + { + HostCmd_DS_MEM *pmem = + (HostCmd_DS_MEM *)(buf + S_DS_GEN); + pmem->action = le16_to_cpu(pmem->action); + if (pmem->action == HostCmd_ACT_GEN_GET) { + pmem->value = le32_to_cpu(pmem->value); + printf("value = 0x%08x\n", pmem->value); + } + break; + } + default: + printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x," + " SeqNum=%#04x, Result=%#04x\n", + hostcmd->command, hostcmd->size, + hostcmd->seq_num, hostcmd->result); + hexdump("payload", + (t_void *)(buf + S_DS_GEN), + hostcmd->size - S_DS_GEN, ' '); + break; + } + } else { + printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x," + " SeqNum=%#04x, Result=%#04x\n", + hostcmd->command, hostcmd->size, + hostcmd->seq_num, hostcmd->result); + } + return ret; +} + +/** + * @brief Prepare ARP filter buffer + * @param fp File handler + * @param buf A pointer to the buffer + * @param length A pointer to the length of buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_arp_filter_buffer(FILE * fp, t_u8 *buf, t_u16 *length) +{ + t_s8 line[256], *pos; + int ln = 0; + int ret = MLAN_STATUS_SUCCESS; + int arpfilter_found = 0; + + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { + if (strcmp(pos, "arpfilter={") == 0) { + arpfilter_found = 1; + mlan_get_hostcmd_data(fp, &ln, buf, length); + break; + } + } + if (!arpfilter_found) { + fprintf(stderr, "mlanutl: 'arpfilter' not found in conf file"); + ret = MLAN_STATUS_FAILURE; + } + return ret; +} + +/** + * @brief Prepare the hostcmd for register access + * @param type Register type + * @param offset Register offset + * @param value Pointer to value (NULL for read) + * @param buf Pointer to hostcmd buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf) +{ + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_REG *preg; + + hostcmd = (HostCmd_DS_GEN *)buf; + switch (type) { + case 1: + hostcmd->command = cpu_to_le16(HostCmd_CMD_MAC_REG_ACCESS); + break; + case 2: + hostcmd->command = cpu_to_le16(HostCmd_CMD_BBP_REG_ACCESS); + break; + case 3: + hostcmd->command = cpu_to_le16(HostCmd_CMD_RF_REG_ACCESS); + break; + case 5: + hostcmd->command = cpu_to_le16(HostCmd_CMD_CAU_REG_ACCESS); + break; + default: + printf("Invalid register set specified\n"); + return -EINVAL; + } + preg = (HostCmd_DS_REG *)(buf + S_DS_GEN); + preg->action = (value) ? HostCmd_ACT_GEN_SET : HostCmd_ACT_GEN_GET; + preg->action = cpu_to_le16(preg->action); + preg->offset = cpu_to_le16((t_u16)offset); + if (value) + preg->value = cpu_to_le32(*value); + else + preg->value = 0; + hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REG)); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + return MLAN_STATUS_SUCCESS; +} diff --git a/mwifiex_8997/mapp/mlanutl/mlanhostcmd.h b/mwifiex_8997/mapp/mlanutl/mlanhostcmd.h new file mode 100755 index 0000000..39521c9 --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanhostcmd.h @@ -0,0 +1,119 @@ +/** @file mlanhostcmd.h + * + * @brief This file contains command structures for mlanutl application + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 11/26/2008: initial version +************************************************************************/ +#ifndef _MLANHOSTCMD_H_ +#define _MLANHOSTCMD_H_ + +/** Find number of elements */ +#define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) + +/** Size of command buffer */ +#define MRVDRV_SIZE_OF_CMD_BUFFER (4 * 1024) + +/** Host Command ID : Memory access */ +#define HostCmd_CMD_MEM_ACCESS 0x0086 + +/** Pre-Authenticate - 11r only */ +#define HostCmd_CMD_802_11_AUTHENTICATE 0x0011 + +/** Read/Write Mac register */ +#define HostCmd_CMD_MAC_REG_ACCESS 0x0019 +/** Read/Write BBP register */ +#define HostCmd_CMD_BBP_REG_ACCESS 0x001a +/** Read/Write RF register */ +#define HostCmd_CMD_RF_REG_ACCESS 0x001b +/** Get TX Power data */ +#define HostCmd_CMD_802_11_RF_TX_POWER 0x001e +/** Host Command ID : CAU register access */ +#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed + +/** Host Command ID : 802.11 BG scan configuration */ +#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b +/** Host Command ID : Configuration data */ +#define HostCmd_CMD_CFG_DATA 0x008f +/** Host Command ID : 802.11 TPC adapt req */ +#define HostCmd_CMD_802_11_TPC_ADAPT_REQ 0x0060 +/** Host Command ID : 802.11 crypto */ +#define HostCmd_CMD_802_11_CRYPTO 0x0078 +/** Host Command ID : 802.11 auto Tx */ +#define HostCmd_CMD_802_11_AUTO_TX 0x0082 + +/** Host Command ID : 802.11 subscribe event */ +#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 + +/** Host Command ID : Channel TRPC config */ +#define HostCmd_CMD_CHAN_TRPC_CONFIG 0x00fb + +/** TLV type ID definition */ +#define PROPRIETARY_TLV_BASE_ID 0x0100 +/** TLV type : Beacon RSSI low */ +#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 0x04) /* 0x0104 */ +/** TLV type : Beacon SNR low */ +#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 0x05) /* 0x0105 */ +/** TLV type : Fail count */ +#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 0x06) /* 0x0106 */ +/** TLV type : BCN miss */ +#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 0x07) /* 0x0107 */ +/** TLV type : Beacon RSSI high */ +#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 0x16) /* 0x0116 */ +/** TLV type : Beacon SNR high */ +#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 0x17) /* 0x0117 */ +/** TLV type : Auto Tx */ +#define TLV_TYPE_AUTO_TX (PROPRIETARY_TLV_BASE_ID + 0x18) /* 0x0118 */ +/** TLV type :Link Quality */ +#define TLV_TYPE_LINK_QUALITY (PROPRIETARY_TLV_BASE_ID + 0x24) /* 0x0124 */ +/** TLV type : Data RSSI low */ +#define TLV_TYPE_RSSI_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x26) /* 0x0126 */ +/** TLV type : Data SNR low */ +#define TLV_TYPE_SNR_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x27) /* 0x0127 */ +/** TLV type : Data RSSI high */ +#define TLV_TYPE_RSSI_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x28) /* 0x0128 */ +/** TLV type : Data SNR high */ +#define TLV_TYPE_SNR_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x29) /* 0x0129 */ +/** TLV type: Pre-Beacon Lost */ +#define TLV_TYPE_PRE_BEACON_LOST (PROPRIETARY_TLV_BASE_ID + 0x49) /* 0x0149 */ + +/** TLV type : Channel TRPC */ +#define TLV_TYPE_CHAN_TRPC (PROPRIETARY_TLV_BASE_ID + 0x89) /* 0x0189 */ + +/** mlan_ioctl_11h_tpc_resp */ +typedef struct { + int status_code; + /**< Firmware command result status code */ + int tx_power;/**< Reported TX Power from the TPC Report */ + int link_margin; + /**< Reported Link margin from the TPC Report */ + int rssi; /**< RSSI of the received TPC Report frame */ +} __ATTRIB_PACK__ mlan_ioctl_11h_tpc_resp; + +/* Define general hostcmd data structure */ + +/** Convert String to integer */ +t_u32 a2hex_or_atoi(char *value); +char *mlan_config_get_line(FILE * fp, char *str, t_s32 size, int *lineno); + +int prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf); +int prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf); + +#endif /* _MLANHOSTCMD_H_ */ diff --git a/mwifiex_8997/mapp/mlanutl/mlanoffload.c b/mwifiex_8997/mapp/mlanutl/mlanoffload.c new file mode 100755 index 0000000..cfcc2b8 --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanoffload.c @@ -0,0 +1,2519 @@ +/** @file mlanoffload.c + * + * @brief This files contains mlanutl offload command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#include "mlanutl.h" +#include "mlanhostcmd.h" +#include "mlanoffload.h" + +/******************************************************** + Local Variables +********************************************************/ + +t_void hexdump(char *prompt, t_void *p, t_s32 len, t_s8 delim); + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief Remove unwanted spaces, tabs from a line + * + * @param data A pointer to the starting of the line + * @return NA + */ +static void +profile_param_polish(char *data) +{ + t_u8 i, j, len = 0; + char *ptr; + ptr = strrchr(data, '\r'); + if (ptr == NULL) { + ptr = strrchr(data, '\n'); + if (ptr == NULL) { + return; + } + } + len = ptr - data; + for (i = 0; i < len; i++) { + if ((*(data + i) == ' ') || (*(data + i) == '\t')) { + for (j = i; j < len; j++) { + data[j] = data[j + 1]; + } + i--; + len--; + } + } +} + +static int +ascii_value(char letter) +{ + if (letter >= '0' && letter <= '9') + return letter - '0'; + if (letter >= 'a' && letter <= 'f') + return letter - 'a' + 10; + if (letter >= 'A' && letter <= 'F') + return letter - 'A' + 10; + return -1; +} + +static int +twodigit_ascii(const char *nibble) +{ + int a, b; + a = ascii_value(*nibble++); + if (a < 0) + return -1; + b = ascii_value(*nibble++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +/** + * @brief Read a network block from the profile configuration file + * + * @param fp file pointer of the configuration file + * @param p_head profile head + * @return MLAN_STATUS_SUCCESS + */ +static int +profile_read_block(FILE * fp, profile_entry_t *p_head) +{ + char line[0x100]; + char *ptr, *eptr; + t_u8 key_cnt = 0; + t_u8 i, wep_len; + int byte; + int tmpIdx; + unsigned int mac[ETH_ALEN]; + + while (fgets(line, sizeof(line), fp)) { + /* call function to remove spaces, tabs */ + profile_param_polish(line); + + if (strstr(line, "}") != NULL) { + ptr = strstr(line, "}"); + /* end of network */ + break; + + } else if (line[0] == '#') { + /* comments go ahead */ + continue; + + } else if (strstr(line, "bssid=") != NULL) { + ptr = strstr(line, "bssid="); + ptr = ptr + strlen("bssid="); + sscanf(ptr, "%2x:%2x:%2x:%2x:%2x:%2x", + mac + 0, mac + 1, mac + 2, mac + 3, mac + 4, + mac + 5); + for (tmpIdx = 0; (unsigned int)tmpIdx < NELEMENTS(mac); + tmpIdx++) { + p_head->bssid[tmpIdx] = (t_u8)mac[tmpIdx]; + } + + } else if (strstr(line, "ssid=") != NULL) { + + ptr = strstr(line, "ssid="); + ptr = ptr + strlen("ssid="); + eptr = strrchr(ptr + 1, '"'); + + if ((*ptr != '"') || (strrchr(ptr + 1, '"') == NULL)) { + + fprintf(stderr, "ssid not within quotes\n"); + break; + } + + p_head->ssid_len = + MIN(IW_ESSID_MAX_SIZE, eptr - ptr - 1); + strncpy((char *)p_head->ssid, ptr + 1, + p_head->ssid_len); + p_head->ssid[p_head->ssid_len] = '\0'; + + } else if (strstr(line, "psk=") != NULL) { + ptr = strstr(line, "psk="); + ptr = ptr + strlen("psk="); + if (*ptr != '"') { + p_head->psk_config = 1; + strncpy((char *)p_head->psk, ptr, KEY_LEN); + } else { + eptr = strrchr(ptr + 1, '"'); + if (eptr == NULL) { + fprintf(stderr, + "passphrase not within quotes.\n"); + break; + } + p_head->passphrase_len = + MIN(PHRASE_LEN, eptr - ptr - 1); + strncpy((char *)p_head->passphrase, ptr + 1, + p_head->passphrase_len); + } + } else if (strstr(line, "wep_key") != NULL) { + ptr = strstr(line, "wep_key"); + ptr = ptr + strlen("wep_key"); + key_cnt = atoi(ptr); + ptr++; + if (*ptr != '=') { + fprintf(stderr, + "invalid wep_key, missing =.\n"); + break; + } + eptr = strrchr(ptr + 1, '\r'); + if (eptr == NULL) { + eptr = strrchr(ptr + 1, '\n'); + if (eptr == NULL) { + fprintf(stderr, + "missing EOL from the wep_key config\n"); + break; + } + } + ptr++; + if (*ptr == '"') { + eptr = strrchr(ptr + 1, '"'); + if (eptr == NULL) { + fprintf(stderr, + "wep key does not end with quote.\n"); + break; + } + *eptr = '\0'; + p_head->wep_key_len[key_cnt] = eptr - ptr - 1; + strncpy((char *)p_head->wep_key[key_cnt], + ptr + 1, p_head->wep_key_len[key_cnt]); + } else { + while (*eptr == '\r' || *eptr == '\n') + eptr--; + *(eptr + 1) = '\0'; + wep_len = strlen(ptr); + if (wep_len & 0x01) { + fprintf(stderr, + "incorrect wep key %s.\n", ptr); + break; + } + p_head->wep_key_len[key_cnt] = wep_len / 2; + for (i = 0; i < wep_len / 2; i++) { + byte = twodigit_ascii(ptr); + if (byte == -1) { + fprintf(stderr, + "incorrect wep key %s.\n", + ptr); + break; + } + *(p_head->wep_key[key_cnt] + i) = + (t_u8)byte; + ptr += 2; + } + } + } else if (strstr(line, "key_mgmt=") != NULL) { + ptr = strstr(line, "key_mgmt="); + ptr = ptr + strlen("key_mgmt="); + eptr = strstr(ptr, "WPA-EAP"); + if (eptr != NULL) { + p_head->key_mgmt |= + PROFILE_DB_KEY_MGMT_IEEE8021X; + } + eptr = strstr(ptr, "WPA-PSK"); + if (eptr != NULL) { + p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_PSK; + } + eptr = strstr(ptr, "FT-EAP"); + if (eptr != NULL) { + p_head->key_mgmt |= + PROFILE_DB_KEY_MGMT_FT_IEEE8021X; + } + eptr = strstr(ptr, "FT-PSK"); + if (eptr != NULL) { + p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_FT_PSK; + } + eptr = strstr(ptr, "WPA-EAP-SHA256"); + if (eptr != NULL) { + p_head->key_mgmt |= + PROFILE_DB_KEY_MGMT_SHA256_IEEE8021X; + } + eptr = strstr(ptr, "WPA-PSK-SHA256"); + if (eptr != NULL) { + p_head->key_mgmt |= + PROFILE_DB_KEY_MGMT_SHA256_PSK; + } + eptr = strstr(ptr, "CCKM"); + if (eptr != NULL) { + p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_CCKM; + } + eptr = strstr(ptr, "NONE"); + if (eptr != NULL) { + p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_NONE; + } + } else if (strstr(line, "proto=") != NULL) { + ptr = strstr(line, "proto="); + ptr = ptr + strlen("proto="); + eptr = strstr(ptr, "WPA"); + if (eptr != NULL) { + p_head->protocol |= PROFILE_DB_PROTO_WPA; + } + + eptr = strstr(ptr, "RSN"); + if (eptr != NULL) { + p_head->protocol |= PROFILE_DB_PROTO_WPA2; + + } + } else if (strstr(line, "pairwise=") != NULL) { + ptr = strstr(line, "pairwise="); + ptr = ptr + strlen("pairwise="); + eptr = strstr(ptr, "CCMP"); + if (eptr != NULL) { + p_head->pairwise_cipher |= + PROFILE_DB_CIPHER_CCMP; + } + eptr = strstr(ptr, "TKIP"); + if (eptr != NULL) { + p_head->pairwise_cipher |= + PROFILE_DB_CIPHER_TKIP; + } + } else if (strstr(line, "groupwise=") != NULL) { + ptr = strstr(line, "groupwise="); + ptr = ptr + strlen("groupwise="); + eptr = strstr(ptr, "CCMP"); + if (eptr != NULL) { + p_head->groupwise_cipher |= + PROFILE_DB_CIPHER_CCMP; + } + eptr = strstr(ptr, "TKIP"); + if (eptr != NULL) { + p_head->groupwise_cipher |= + PROFILE_DB_CIPHER_TKIP; + } + } else if (strstr(line, "wep_tx_keyidx=") != NULL) { + ptr = strstr(line, "wep_tx_keyidx="); + ptr = ptr + strlen("wep_tx_keyidx="); + p_head->wep_key_idx = atoi(ptr); + } else if (strstr(line, "roaming=") != NULL) { + ptr = strstr(line, "roaming="); + ptr = ptr + strlen("roaming="); + p_head->roaming = atoi(ptr); + } else if (strstr(line, "ccx=") != NULL) { + ptr = strstr(line, "ccx="); + ptr = ptr + strlen("ccx="); + p_head->ccx = atoi(ptr); + } else if (strstr(line, "mode=") != NULL) { + ptr = strstr(line, "mode="); + ptr = ptr + strlen("mode="); + p_head->mode = atoi(ptr); + } + } + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Issue profile command to add new profile to FW + * + * @param filename Name of profile file + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +profile_read_download(char *filename) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + int i = 0; + t_u16 temp, tempc; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + profile_entry_t *p_head = NULL; + FILE *fp; + char line[0x100]; + + fp = fopen(filename, "r"); + if (fp == NULL) { + perror("fopen"); + fprintf(stderr, "Cannot open file %s\n", filename); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + pos = (t_u8 *)hostcmd; + while (fgets(line, sizeof(line), fp)) { + /* call function to remove spaces, tabs */ + profile_param_polish(line); + if ((strstr(line, "network={") == NULL) || (line[0] == '#')) { + continue; + } + /* + * Memory allocation of every network block + */ + p_head = (profile_entry_t *)malloc(sizeof(profile_entry_t)); + if (p_head == NULL) { + fprintf(stderr, "Memory error.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + memset(p_head, 0x00, sizeof(profile_entry_t)); + + ret = profile_read_block(fp, p_head); + if (ret || p_head->ssid_len == 0) { + free(p_head); + continue; + } + + /* + * Put all the ssid parameters in the buffer + */ + memset(pos, 0, + (BUFFER_LENGTH - cmd_header_len - sizeof(t_u32))); + + /* Cmd Header : Command */ + hostcmd->command = cpu_to_le16(HostCmd_CMD_PROFILE_DB); + cmd_len = sizeof(HostCmd_DS_GEN); + + /* set action as set */ + tempc = cpu_to_le16(HostCmd_ACT_GEN_SET); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + + /* ssid */ + tempc = cpu_to_le16(TLV_TYPE_SSID); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = strlen((char *)p_head->ssid); + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + memcpy((void *)(pos + cmd_len), p_head->ssid, temp); + cmd_len += temp; + + if (memcmp(p_head->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)) { + /* bssid */ + tempc = cpu_to_le16(TLV_TYPE_BSSID); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = ETH_ALEN; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + memcpy((void *)(pos + cmd_len), p_head->bssid, temp); + cmd_len += temp; + } + + /* proto */ + if (p_head->protocol == 0) { + p_head->protocol = 0xFFFF; + } + + tempc = cpu_to_le16(TLV_TYPE_PROTO); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = 2; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + memcpy((pos + cmd_len), &(p_head->protocol), temp); + cmd_len += temp; + + /* key_mgmt */ + if (p_head->key_mgmt == 0) { + p_head->key_mgmt = 0xFFFF; + } + + tempc = cpu_to_le16(TLV_TYPE_AKMP); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = 2; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + memcpy((pos + cmd_len), &(p_head->key_mgmt), temp); + cmd_len += temp; + + /* pairwise */ + if (p_head->pairwise_cipher == 0) { + p_head->pairwise_cipher = 0xFF; + } + + /* groupwise */ + if (p_head->groupwise_cipher == 0) { + p_head->groupwise_cipher = 0xFF; + } + + tempc = cpu_to_le16(TLV_TYPE_CIPHER); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = 2; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + pos[cmd_len] = p_head->pairwise_cipher; + cmd_len += 1; + pos[cmd_len] = p_head->groupwise_cipher; + cmd_len += 1; + + if (p_head->passphrase_len) { + /* passphrase */ + tempc = cpu_to_le16(TLV_TYPE_PASSPHRASE); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = p_head->passphrase_len; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + memcpy((void *)(pos + cmd_len), p_head->passphrase, + temp); + cmd_len += temp; + } + + if (p_head->psk_config) { + /* psk method */ + tempc = cpu_to_le16(TLV_TYPE_PMK); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = 32; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + memcpy((void *)(pos + cmd_len), p_head->psk, temp); + cmd_len += temp; + } + + for (i = 0; i < WEP_KEY_CNT; i++) { + if (p_head->wep_key_len[i]) { + /* TAG_WEP_KEY */ + tempc = cpu_to_le16(TLV_TYPE_WEP_KEY); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + /* wep_key_len + sizeof(keyIndex) + sizeof(IsDefault) */ + tempc = cpu_to_le16(p_head->wep_key_len[i] + 1 + + 1); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + *(pos + cmd_len) = i; + cmd_len += 1; + *(pos + cmd_len) = (i == p_head->wep_key_idx); + cmd_len += 1; + temp = p_head->wep_key_len[i]; + memcpy((void *)(pos + cmd_len), + p_head->wep_key[i], temp); + cmd_len += temp; + } + } + + if (p_head->roaming | p_head->ccx) { + tempc = cpu_to_le16(TLV_TYPE_OFFLOAD_ENABLE); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = 2; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + tempc = 0; + if (p_head->roaming) + tempc |= PROFILE_DB_FEATURE_ROAMING; + if (p_head->ccx) + tempc |= PROFILE_DB_FEATURE_CCX; + tempc = cpu_to_le16(tempc); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += temp; + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + hostcmd->size = cpu_to_le16(cmd_len); + + fprintf(stdout, "Downloading profile: %s ... ", p_head->ssid); + fflush(stdout); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[profiledb ioctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } else { + hostcmd->result = le16_to_cpu(hostcmd->result); + if (hostcmd->result != 0) { + printf("hostcmd : profiledb ioctl failure, code %d\n", hostcmd->result); + ret = -EFAULT; + goto done; + } + } + + fprintf(stdout, "done.\n"); + + if (p_head) + free(p_head); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + if (fp) + fclose(fp); + return ret; +} + +/******************************************************** + Global Functions +********************************************************/ + +/** + * @brief Process sub command + * + * @param sub_cmd Sub command + * @param num_sub_cmds Number of subcommands + * @param argc Number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_sub_cmd(sub_cmd_exec_t *sub_cmd, int num_sub_cmds, + int argc, char *argv[]) +{ + int idx; + boolean invalid_cmd = TRUE; + int ret = MLAN_STATUS_FAILURE; + + if (argv[3]) { + for (idx = 0; idx < num_sub_cmds; idx++) { + if (strncmp(argv[3], + sub_cmd[idx].str, + sub_cmd[idx].match_len) == 0) { + invalid_cmd = FALSE; + ret = sub_cmd[idx].callback(argc - 4, argv + 4); + break; + } + } + } + + if (invalid_cmd) { + printf("\nUnknown %s command. Valid subcmds:\n", argv[2]); + for (idx = 0; idx < num_sub_cmds; idx++) { + if (sub_cmd[idx].display) { + printf(" - %s\n", sub_cmd[idx].str); + } + } + printf("\n"); + } + + return ret; +} + +/** + * @brief select the table's regclass + * + * @param table_str Reg channel table type + * @param pTable Pointer to the Reg channel table + * + * @return TRUE if success otherwise FALSE + */ +boolean +reg_class_table_select(char *table_str, reg_chan_table_e *pTable) +{ + boolean retval = TRUE; + + if (strcmp(table_str, "user") == 0) { + *pTable = REGTABLE_USER; + } else if ((strcmp(table_str, "md") == 0) || + (strncmp(table_str, "multidomain", 5) == 0)) { + *pTable = REGTABLE_MULTIDOMAIN; + } else if (strcmp(table_str, "ess") == 0) { + *pTable = REGTABLE_ESS; + } else if (strcmp(table_str, "default") == 0) { + *pTable = REGTABLE_DEFAULT; + } else { /* If no option/wrong option set to default */ + *pTable = REGTABLE_DEFAULT; + } + + return retval; +} + +/** + * @brief Issue a measurement timing command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_measurement(int argc, char *argv[]) +{ + int ret = 0; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + HostCmd_DS_MEASUREMENT_Timing *timing_cmd = NULL; + MrvlIETypes_MeasTiming_t *timing_tlv = NULL; + int idx, rsp_len; + t_u8 sel = 0; + t_u16 tlv_len = 0; + timing_sel_t sel_str[] = { {"disconnected", 1}, + {"adhoc", 1}, + {"fullpower", 1}, + {"ieeeps", 1}, + {"periodic", 1} + }; + + if ((argc < 4) || strncmp(argv[3], "timing", + MAX(strlen("timing"), strlen(argv[3])))) { + printf("\nUnknown %s command. Valid subcmd: timing \n", + argv[2]); + return MLAN_STATUS_FAILURE; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + cmd_len = S_DS_GEN + sizeof(t_u16); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + return -ENOMEM; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return -ENOMEM; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + hostcmd->command = cpu_to_le16(HostCmd_CMD_MEASUREMENT_TIMING_CONFIG); + hostcmd->size = cmd_len; + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + timing_cmd = (HostCmd_DS_MEASUREMENT_Timing *)pos; + timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + timing_tlv = (MrvlIETypes_MeasTiming_t *)timing_cmd->tlv_buffer; + + if (argc == 7) { + timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + timing_tlv->header.type = + cpu_to_le16(TLV_TYPE_MEASUREMENT_TIMING); + timing_tlv->header.len = + cpu_to_le16(sizeof(MrvlIETypes_MeasTiming_t) + - sizeof(timing_tlv->header)); + + for (idx = 1; (unsigned int)idx < NELEMENTS(sel_str); idx++) { + if (strncmp + (argv[4], sel_str[idx].str, + sel_str[idx].match_len) == 0) { + sel = idx + 1; + break; + } + } + + if (idx == NELEMENTS(sel_str)) { + printf("Wrong argument for mode selected \"%s\"\n", + argv[4]); + ret = -EINVAL; + goto done; + } + + timing_tlv->mode = cpu_to_le32(sel); + timing_tlv->max_off_channel = cpu_to_le32(atoi(argv[5])); + timing_tlv->max_on_channel = cpu_to_le32(atoi(argv[6])); + cmd_len += sizeof(MrvlIETypes_MeasTiming_t); + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + hostcmd->size = cpu_to_le16(cmd_len); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[measurement timing ioctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + printf("--------------------------------------------------\n"); + printf("%44s\n", "Measurement Timing Profiles (in ms)"); + printf("--------------------------------------------------\n"); + printf(" Profile | MaxOffChannel | MaxOnChannel\n"); + printf("--------------------------------------------------\n"); + + /* Changed to TLV parsing */ + rsp_len = le16_to_cpu(hostcmd->size); + rsp_len -= (S_DS_GEN + sizeof(t_u16)); + pos = (t_u8 *)hostcmd + S_DS_GEN + sizeof(t_u16); + while ((unsigned int)rsp_len > sizeof(MrvlIEtypesHeader_t)) { + switch (le16_to_cpu(*(t_u16 *)(pos))) { + case TLV_TYPE_MEASUREMENT_TIMING: + timing_tlv = (MrvlIETypes_MeasTiming_t *)pos; + tlv_len = le16_to_cpu(timing_tlv->header.len); + printf("%15s | %14d | %13d\n", + sel_str[le32_to_cpu(timing_tlv->mode) - 1].str, + (int)le32_to_cpu(timing_tlv->max_off_channel), + (int)le32_to_cpu(timing_tlv->max_on_channel)); + break; + } + pos += tlv_len + sizeof(MrvlIEtypesHeader_t); + rsp_len -= tlv_len + sizeof(MrvlIEtypesHeader_t); + rsp_len = (rsp_len > 0) ? rsp_len : 0; + } + printf("\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a profile command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_profile_entry(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + unsigned int mac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + int idx; + t_u16 temp, tempc; + char *ssid = NULL; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + if (argc < 4) { + fprintf(stderr, "Invalid number of argument!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (!strncmp(argv[3], "delete", sizeof("delete"))) { + if (argc > 4) { + if (strncmp(argv[4], "bssid=", strlen("bssid=")) == 0) { + /* "bssid" token string handler */ + sscanf(argv[4] + strlen("bssid="), + "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, + mac + 1, mac + 2, mac + 3, mac + 4, + mac + 5); + } else if (strncmp(argv[4], "ssid=", strlen("ssid=")) == + 0) { + /* "ssid" token string handler */ + ssid = argv[4] + strlen("ssid="); + } else { + printf("Error: missing required option for command (ssid, bssid)\n"); + ret = -ENOMEM; + goto done; + } + printf("Driver profile delete request\n"); + } else { + printf("Error: missing required option for command (ssid, bssid)\n"); + ret = -ENOMEM; + goto done; + } + } else if (!strncmp(argv[3], "flush", sizeof("flush"))) { + printf("Driver profile flush request\n"); + } else { + ret = profile_read_download(argv[3]); + goto done; + } + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = -ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = -ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + hostcmd->command = cpu_to_le16(HostCmd_CMD_PROFILE_DB); + hostcmd->size = 0; + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Point after host command header */ + pos = (t_u8 *)hostcmd; + cmd_len = S_DS_GEN; + + /* set action as del */ + tempc = cpu_to_le16(HostCmd_ACT_GEN_REMOVE); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + + /* ssid */ + if (ssid) { + printf("For ssid %s\n", ssid); + tempc = cpu_to_le16(TLV_TYPE_SSID); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = strlen((char *)ssid); + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + memcpy((void *)(pos + cmd_len), ssid, temp); + cmd_len += temp; + } else { + /* bssid */ + if (mac[0] != 0xFF) { + printf("For bssid %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + tempc = cpu_to_le16(TLV_TYPE_BSSID); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + temp = ETH_ALEN; + tempc = cpu_to_le16(temp); + memcpy((pos + cmd_len), &tempc, sizeof(t_u16)); + cmd_len += 2; + for (idx = 0; (unsigned int)idx < NELEMENTS(mac); idx++) { + pos[cmd_len + idx] = (t_u8)mac[idx]; + } + cmd_len += temp; + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + hostcmd->size = cpu_to_le16(cmd_len); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[profiledb ioctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } else { + hostcmd->result = le16_to_cpu(hostcmd->result); + if (hostcmd->result != 0) { + printf("hostcmd : profiledb ioctl failure, code %d\n", + hostcmd->result); + ret = -EFAULT; + goto done; + } + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a chan report command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_chanrpt(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int respLen; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + t_u8 *pByte; + t_u8 numBins; + t_u8 idx; + MrvlIEtypes_Data_t *pTlvHdr; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CHAN_RPT_RSP *pChanRptRsp; + HostCmd_DS_CHAN_RPT_REQ *pChanRptReq; + + MrvlIEtypes_ChanRptBcn_t *pBcnRpt; + MrvlIEtypes_ChanRptChanLoad_t *pLoadRpt; + MrvlIEtypes_ChanRptNoiseHist_t *pNoiseRpt; + MrvlIEtypes_ChanRpt11hBasic_t *pBasicRpt; + MrvlIEtypes_ChanRptFrame_t *pFrameRpt; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CHAN_RPT_REQ); + + hostcmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + pChanRptReq = (HostCmd_DS_CHAN_RPT_REQ *)pos; + pChanRptRsp = (HostCmd_DS_CHAN_RPT_RSP *)pos; + + memset((void *)pChanRptReq, 0x00, sizeof(HostCmd_DS_CHAN_RPT_REQ)); + + if ((argc != 5) && (argc != 6)) { + printf("\nchanrpt syntax: chanrpt [sFreq]\n\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + pChanRptReq->chanDesc.chanNum = atoi(argv[3]); + pChanRptReq->millisecDwellTime = cpu_to_le32(atoi(argv[4])); + + if (argc == 6) { + pChanRptReq->chanDesc.startFreq = cpu_to_le16(atoi(argv[5])); + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[chanrpt hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + /* TSF is a t_u64, some formatted printing libs have + * trouble printing long longs, so cast and dump as bytes + */ + pByte = (t_u8 *)&pChanRptRsp->startTsf; + + printf("\n"); + printf("[%03d] TSF: 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + atoi(argv[3]), + pByte[7], pByte[6], pByte[5], pByte[4], + pByte[3], pByte[2], pByte[1], pByte[0]); + printf("[%03d] Dwell: %u us\n", + atoi(argv[3]), (unsigned int)le32_to_cpu(pChanRptRsp->duration)); + + pByte = pChanRptRsp->tlvBuffer; + + respLen = le16_to_cpu(hostcmd->size) - sizeof(HostCmd_DS_GEN); + + respLen -= sizeof(pChanRptRsp->commandResult); + respLen -= sizeof(pChanRptRsp->startTsf); + respLen -= sizeof(pChanRptRsp->duration); + + pByte = pChanRptRsp->tlvBuffer; + + while ((unsigned int)respLen >= sizeof(pTlvHdr->header)) { + pTlvHdr = (MrvlIEtypes_Data_t *)pByte; + pTlvHdr->header.len = le16_to_cpu(pTlvHdr->header.len); + + switch (le16_to_cpu(pTlvHdr->header.type)) { + case TLV_TYPE_CHANRPT_BCN: + pBcnRpt = (MrvlIEtypes_ChanRptBcn_t *)pTlvHdr; + printf("[%03d] Beacon: scanReqId = %d\n", + atoi(argv[3]), pBcnRpt->scanReqId); + + break; + + case TLV_TYPE_CHANRPT_CHAN_LOAD: + pLoadRpt = (MrvlIEtypes_ChanRptChanLoad_t *)pTlvHdr; + printf("[%03d] ChanLoad: %d%%\n", + atoi(argv[3]), + (pLoadRpt->ccaBusyFraction * 100) / 255); + break; + + case TLV_TYPE_CHANRPT_NOISE_HIST: + pNoiseRpt = (MrvlIEtypes_ChanRptNoiseHist_t *)pTlvHdr; + numBins = + pNoiseRpt->header.len - sizeof(pNoiseRpt->anpi); + printf("[%03d] ANPI: %d dB\n", atoi(argv[3]), + le16_to_cpu(pNoiseRpt->anpi)); + printf("[%03d] NoiseHst:", atoi(argv[3])); + for (idx = 0; idx < numBins; idx++) { + printf(" %03d", pNoiseRpt->rpiDensities[idx]); + } + printf("\n"); + break; + + case TLV_TYPE_CHANRPT_11H_BASIC: + pBasicRpt = (MrvlIEtypes_ChanRpt11hBasic_t *)pTlvHdr; + printf("[%03d] 11hBasic: BSS(%d), OFDM(%d), UnId(%d), Radar(%d): " "[0x%02x]\n", atoi(argv[3]), pBasicRpt->map.BSS, pBasicRpt->map.OFDM_Preamble, pBasicRpt->map.Unidentified, pBasicRpt->map.Radar, *(t_u8 *)&pBasicRpt->map); + break; + + case TLV_TYPE_CHANRPT_FRAME: + pFrameRpt = (MrvlIEtypes_ChanRptFrame_t *)pTlvHdr; + printf("[%03d] Frame: %02x:%02x:%02x:%02x:%02x:%02x " "%02x:%02x:%02x:%02x:%02x:%02x %3d %02d\n", atoi(argv[3]), pFrameRpt->sourceAddr[0], pFrameRpt->sourceAddr[1], pFrameRpt->sourceAddr[2], pFrameRpt->sourceAddr[3], pFrameRpt->sourceAddr[4], pFrameRpt->sourceAddr[5], pFrameRpt->bssid[0], pFrameRpt->bssid[1], pFrameRpt->bssid[2], pFrameRpt->bssid[3], pFrameRpt->bssid[4], pFrameRpt->bssid[5], pFrameRpt->rssi, pFrameRpt->frameCnt); + break; + + default: + printf("[%03d] Other: Id=0x%x, Size = %d\n", + atoi(argv[3]), + pTlvHdr->header.type, pTlvHdr->header.len); + + break; + } + + pByte += (pTlvHdr->header.len + sizeof(pTlvHdr->header)); + respLen -= (pTlvHdr->header.len + sizeof(pTlvHdr->header)); + respLen = (respLen > 0) ? respLen : 0; + } + + printf("\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a assoc timing command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_assoc_timing(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_AssociationTiming_t *assoctiming; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_AssociationTiming_t); + + hostcmd->command = cpu_to_le16(HostCmd_CMD_ASSOCIATION_TIMING); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + assoctiming = (HostCmd_DS_AssociationTiming_t *)pos; + assoctiming->Action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (argc > 3) { + assoctiming->Action = cpu_to_le16(HostCmd_ACT_GEN_SET); + switch (argc) { + case 9: + assoctiming->ReassocDiscMax = + cpu_to_le16(atoi(argv[8])); + /* No break, do everything below as well */ + case 8: + assoctiming->PriorApDeauthDelay = + cpu_to_le16(atoi(argv[7])); + /* No break, do everything below as well */ + case 7: + assoctiming->FrameExchangeTimeout = + cpu_to_le16(atoi(argv[6])); + /* No break, do everything below as well */ + case 6: + assoctiming->HandShakeTimeout = + cpu_to_le16(atoi(argv[5])); + /* No break, do everything below as well */ + case 5: + assoctiming->ReassocTimeout = + cpu_to_le16(atoi(argv[4])); + /* No break, do everything below as well */ + case 4: + assoctiming->AssocTimeout = cpu_to_le16(atoi(argv[3])); + break; + } + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + puts(""); + printf("------------------------------------------------\n"); + printf(" Association Timing Parameters\n"); + printf("------------------------------------------------\n"); + + printf("Association Timeout %5u ms\n" + "Reassociation Timeout %5u ms\n" + "Handshake Timeout %5u ms\n" + "Frame Exchange Timeout %5u ms\n" + "Prior AP Deauth Delay %5u ms\n" + "Reassoc Disconnect Max %5u ms\n", + le16_to_cpu(assoctiming->AssocTimeout), + le16_to_cpu(assoctiming->ReassocTimeout), + le16_to_cpu(assoctiming->HandShakeTimeout), + le16_to_cpu(assoctiming->FrameExchangeTimeout), + le16_to_cpu(assoctiming->PriorApDeauthDelay), + le16_to_cpu(assoctiming->ReassocDiscMax)); + puts(""); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Retrieve the association response from the driver + * + * Retrieve the buffered (re)association management frame from the driver. + * The response is identical to the one received from the AP and conforms + * to the IEEE specification. + * + * @return MLAN_STATUS_SUCCESS or ioctl error code + */ +int +process_get_assocrsp(int argc, char *argv[]) +{ + int ret = 0; + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + IEEEtypes_AssocRsp_t *pAssocRsp = NULL; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + pAssocRsp = (IEEEtypes_AssocRsp_t *)buffer; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), argv[2], strlen(argv[2])); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: version fail\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (cmd->used_len) { + printf("getassocrsp: Status[%d], Cap[0x%04x]:\n", + pAssocRsp->StatusCode, + le16_to_cpu(*(t_u16 *)&pAssocRsp->Capability)); + hexdump(NULL, buffer, cmd->used_len, ' '); + } else { + printf("getassocrsp: \n"); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return ret; +} + +/* +** Process mlanutl fcontrol command: +** +** mlanutl mlanX fcontrol %d [0xAA 0xBB... ] +** +** Sets and/or retrieves the feature control settings for a specific +** control set (argv[3] decimal argument). +** +*/ +int +process_fcontrol(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + t_u8 idx; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_OFFLOAD_FEATURE_CONTROL *pFcontrol; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + pFcontrol = (HostCmd_DS_OFFLOAD_FEATURE_CONTROL *)pos; + + if (argc < 4) { + printf("Wrong number of arguments\n"); + ret = -EINVAL; + goto done; + } + + pFcontrol->controlSelect = atoi(argv[3]); + cmd_len = S_DS_GEN + sizeof(pFcontrol->controlSelect); + + for (idx = 4; idx < argc; idx++) { + pFcontrol->controlBitmap[idx - 4] = a2hex_or_atoi(argv[idx]); + cmd_len++; + } + + hostcmd->command = cpu_to_le16(HostCmd_CMD_OFFLOAD_FEATURE_CONTROL); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[fcontrol hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + cmd_len = (le16_to_cpu(hostcmd->size) - sizeof(HostCmd_DS_GEN)); + + printf("Control[%d]", pFcontrol->controlSelect); + cmd_len--; + + for (idx = 0; idx < cmd_len; idx++) { + printf("\t0x%02x", pFcontrol->controlBitmap[idx]); + } + + printf("\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/* +** Process mlanutl iapp command: +** +** mlanutl mlanX iapp 0xAA 0xBB [0x... 0x.. ] +** +** 0xAA = IAPP type +** 0xBB = IAPP subtype +** 0x.. = Remaning bytes are iapp data +** +*/ +int +process_iapp(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + t_u8 idx; + t_u8 fixlen; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_IAPP_PROXY *pIappProxy; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_IAPP_PROXY); + + pIappProxy = (HostCmd_DS_IAPP_PROXY *)pos; + + if (argc < 6) { + printf("Wrong number of arguments\n"); + ret = -EINVAL; + } + + memset(pIappProxy, 0x00, sizeof(HostCmd_DS_IAPP_PROXY)); + + pIappProxy->iappType = a2hex_or_atoi(argv[4]); + pIappProxy->iappSubType = a2hex_or_atoi(argv[5]); + + /* Fixed len portions of command */ + fixlen = (S_DS_GEN + sizeof(HostCmd_DS_IAPP_PROXY) + - sizeof(pIappProxy->iappData)); + + pIappProxy->timeout_ms = cpu_to_le32(a2hex_or_atoi(argv[3])); + + for (idx = 6; idx < argc; idx++) { + pIappProxy->iappData[idx - 6] = a2hex_or_atoi(argv[idx]); + pIappProxy->iappDataLen++; + } + + hostcmd->command = cpu_to_le16(HostCmd_CMD_IAPP_PROXY); + hostcmd->size = cpu_to_le16(fixlen + pIappProxy->iappDataLen); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + pIappProxy->iappDataLen = cpu_to_le32(pIappProxy->iappDataLen); + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[iapp hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + printf("\nResult: %d\n", le32_to_cpu(pIappProxy->commandResult)); + printf("Type: 0x%02x\n", pIappProxy->iappType); + printf("SubType: 0x%02x\n", pIappProxy->iappSubType); + + printf("IappData: "); + hexdump(NULL, pIappProxy->iappData, + le32_to_cpu(pIappProxy->iappDataLen), ' '); + printf("\n\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a rf tx power command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_rf_tx_power(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_802_11_RF_TX_POWER *pRfTxPower; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_802_11_RF_TX_POWER); + + pRfTxPower = (HostCmd_DS_802_11_RF_TX_POWER *)pos; + + memset(pRfTxPower, 0x00, sizeof(HostCmd_DS_802_11_RF_TX_POWER)); + + hostcmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + printf("\n"); + printf(" MinPower: %2d\n", pRfTxPower->min_power); + printf(" MaxPower: %2d\n", pRfTxPower->max_power); + printf(" Current: %2d\n", le16_to_cpu(pRfTxPower->current_level)); + printf("\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a authenticate command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_authenticate(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_802_11_AUTHENTICATE *pAuth; + unsigned int mac[ETH_ALEN]; + int tmpIdx; + + if (argc != 4) { + printf("Wrong number of arguments\n"); + ret = -EINVAL; + goto done; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_802_11_AUTHENTICATE); + + pAuth = (HostCmd_DS_802_11_AUTHENTICATE *)pos; + + memset(pAuth, 0x00, sizeof(HostCmd_DS_802_11_AUTHENTICATE)); + + sscanf(argv[3], + "%2x:%2x:%2x:%2x:%2x:%2x", + mac + 0, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5); + + for (tmpIdx = 0; (unsigned int)tmpIdx < NELEMENTS(mac); tmpIdx++) { + pAuth->MacAddr[tmpIdx] = (t_u8)mac[tmpIdx]; + } + + hostcmd->command = cpu_to_le16(HostCmd_CMD_802_11_AUTHENTICATE); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +static void +display_channel(void) +{ + FILE *tmpfile; + char result[200]; + char cmdStr[50]; + int ghz, mhz, chan; + + puts("\n"); + + sprintf(cmdStr, "iwlist %s chan", dev_name); + + tmpfile = popen(cmdStr, "r"); + + if (tmpfile == NULL) { + perror("mlanutl: iwlist failed to get current channel"); + } else { + while (fgets(result, sizeof(result), tmpfile)) { + if ((sscanf + (result, " Current Frequency=%d.%d ", &ghz, + &mhz) == 2) || + (sscanf + (result, " Current Frequency:%d.%d ", &ghz, + &mhz) == 2)) { + if (mhz < 10) { + mhz *= 100; + } else if (mhz < 100) { + mhz *= 10; + } + + chan = ghz * 1000 + mhz; + if (chan > 5000) { + chan -= 5000; + chan /= 5; + } else if (chan == 2484) { + chan = 14; + } else { + chan -= 2407; + chan /= 5; + } + printf(" Channel: %3d [%d.%d GHz]\n", chan, + ghz, mhz); + } + } + pclose(tmpfile); + } +} + +static char * +get_ratestr(int txRate) +{ + char *pStr; + + switch (txRate) { + case 0: + pStr = "1"; + break; + case 1: + pStr = "2"; + break; + case 2: + pStr = "5.5"; + break; + case 3: + pStr = "11"; + break; + case 4: + pStr = "6"; + break; + case 5: + pStr = "9"; + break; + case 6: + pStr = "12"; + break; + case 7: + pStr = "18"; + break; + case 8: + pStr = "24"; + break; + case 9: + pStr = "36"; + break; + case 10: + pStr = "48"; + break; + case 11: + pStr = "54"; + break; + case 12: + pStr = "MCS0"; + break; + case 13: + pStr = "MCS1"; + break; + case 14: + pStr = "MCS2"; + break; + case 15: + pStr = "MCS3"; + break; + case 16: + pStr = "MCS4"; + break; + case 17: + pStr = "MCS5"; + break; + case 18: + pStr = "MCS6"; + break; + case 19: + pStr = "MCS7"; + break; + + case 140: + pStr = "MCS0"; + break; + case 141: + pStr = "MCS1"; + break; + case 142: + pStr = "MCS2"; + break; + case 143: + pStr = "MCS3"; + break; + case 144: + pStr = "MCS4"; + break; + case 145: + pStr = "MCS5"; + break; + case 146: + pStr = "MCS6"; + break; + case 147: + pStr = "MCS7"; + break; + + default: + pStr = "Unkn"; + break; + } + + return pStr; +} + +typedef struct { + int rate; + int min; + int max; + +} RatePower_t; + +static int +get_txpwrcfg(RatePower_t ratePower[]) +{ + FILE *tmpfile; + char result[300]; + char cmdStr[50]; + int counter = 0; + char *pBuf; + int r1 = 0, r2 = 0, min = 0, max = 0, rate = 0; + int rateIdx = 0; + + sprintf(cmdStr, "iwpriv %s txpowercfg", dev_name); + + tmpfile = popen(cmdStr, "r"); + + if (tmpfile == NULL) { + perror("mlanutl: iwpriv failed to get txpowercfg"); + } else { + while (fgets(result, sizeof(result), tmpfile)) { + pBuf = strtok(result, ": "); + + while (pBuf != NULL) { + switch (counter % 5) { + case 0: + r1 = atoi(pBuf); + break; + + case 1: + r2 = atoi(pBuf); + break; + + case 2: + min = atoi(pBuf); + break; + + case 3: + max = atoi(pBuf); + break; + + case 4: + for (rate = r1; rate <= r2; rate++) { + ratePower[rateIdx].rate = rate; + ratePower[rateIdx].min = min; + ratePower[rateIdx].max = max; + rateIdx++; + } + break; + } + + if (isdigit(*pBuf)) { + counter++; + } + pBuf = strtok(NULL, ": "); + } + } + pclose(tmpfile); + } + + return rateIdx; +} + +static void +rateSort(RatePower_t rateList[], int numRates) +{ + int inc, i, j; + RatePower_t tmp; + + inc = 3; + + while (inc > 0) { + for (i = 0; i < numRates; i++) { + j = i; + memcpy(&tmp, &rateList[i], sizeof(RatePower_t)); + + while ((j >= inc) && + (rateList[j - inc].rate > tmp.rate)) { + memcpy(&rateList[j], &rateList[j - inc], + sizeof(RatePower_t)); + j -= inc; + } + + memcpy(&rateList[j], &tmp, sizeof(RatePower_t)); + } + + if (inc >> 1) { + inc >>= 1; + } else if (inc == 1) { + inc = 0; + } else { + inc = 1; + } + } +} + +typedef struct { + int rate; + int modGroup; + +} RateModPair_t; + +/* +** +** ModulationGroups +** 0: CCK (1,2,5.5,11 Mbps) +** 1: OFDM (6,9,12,18 Mbps) +** 2: OFDM (24,36 Mbps) +** 3: OFDM (48,54 Mbps) +** 4: HT20 (0,1,2) +** 5: HT20 (3,4) +** 6: HT20 (5,6,7) +** 7: HT40 (0,1,2) +** 8: HT40 (3,4) +** 9: HT40 (5,6,7) +*/ + +static RateModPair_t rateModPairs[] = { + {0, 0}, /* 1 */ + {1, 0}, /* 2 */ + {2, 0}, /* 5.5 */ + {3, 0}, /* 11 */ + {4, 1}, /* 6 */ + {5, 1}, /* 9 */ + {6, 1}, /* 12 */ + {7, 1}, /* 18 */ + {8, 2}, /* 24 */ + {9, 2}, /* 36 */ + {10, 3}, /* 48 */ + {11, 3}, /* 54 */ + {12, 4}, /* MCS0 */ + {13, 4}, /* MCS1 */ + {14, 4}, /* MCS2 */ + {15, 5}, /* MCS3 */ + {16, 5}, /* MCS4 */ + {17, 6}, /* MCS5 */ + {18, 6}, /* MCS6 */ + {19, 6}, /* MCS7 */ + + {140, 7}, /* MCS0 */ + {141, 7}, /* MCS1 */ + {142, 7}, /* MCS2 */ + {143, 8}, /* MCS3 */ + {144, 8}, /* MCS4 */ + {145, 9}, /* MCS5 */ + {146, 9}, /* MCS6 */ + {147, 9}, /* MCS7 */ +}; + +int +process_chantrpcdisp(int startRate, int endRate) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CHAN_TRPC_CONFIG *pChanTrpc; + MrvlIEtypes_ChanTrpcCfg_t *pChanTrpcTlv; + int totalTlvBytes = 0; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + pChanTrpc = (HostCmd_DS_CHAN_TRPC_CONFIG *)pos; + pChanTrpc->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + cmd_len = S_DS_GEN + sizeof(pChanTrpc->action); + hostcmd->command = cpu_to_le16(HostCmd_CMD_CHAN_TRPC_CONFIG); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[chantrpc hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + totalTlvBytes = (le16_to_cpu(hostcmd->size) + - sizeof(HostCmd_DS_GEN) + - sizeof(pChanTrpc->action) + - sizeof(pChanTrpc->reserved)); + + pChanTrpcTlv = (MrvlIEtypes_ChanTrpcCfg_t *)pChanTrpc->tlv_buffer; + + while (totalTlvBytes) { + int tlvSize, numModGroups, idx, modIdx, numOut; + + /* Switch to TLV parsing */ + printf("%4d.%-3d ", + le16_to_cpu(pChanTrpcTlv->chanDesc.startFreq), + pChanTrpcTlv->chanDesc.chanNum); + + numOut = 0; + + tlvSize = (le16_to_cpu(pChanTrpcTlv->header.len) + + sizeof(pChanTrpcTlv->header)); + + numModGroups = (le16_to_cpu(pChanTrpcTlv->header.len) + - sizeof(pChanTrpcTlv->chanDesc)); + numModGroups /= sizeof(pChanTrpcTlv->chanTrpcEntry[0]); + + for (idx = 0; idx < NELEMENTS(rateModPairs); idx++) { + if ((rateModPairs[idx].rate >= startRate) && + (rateModPairs[idx].rate <= endRate)) { + for (modIdx = 0; modIdx < numModGroups; + modIdx++) { + if (rateModPairs[idx].modGroup == + pChanTrpcTlv->chanTrpcEntry[modIdx]. + modGroup) { + printf("%*d", + (numOut == 0) ? 3 : 6, + pChanTrpcTlv-> + chanTrpcEntry[modIdx]. + txPower); + numOut++; + } + } + + if (numOut == 0) { + printf(" -- "); + } + } + } + + puts(""); + + pChanTrpcTlv = + (MrvlIEtypes_ChanTrpcCfg_t *)((t_u8 *)pChanTrpcTlv + + tlvSize); + totalTlvBytes -= tlvSize; + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a tx power display command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_txpowdisp(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int rateIdx, rates; + int connected; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_802_11_RF_TX_POWER *pRfTxPower; + RatePower_t ratePower[50]; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_802_11_RF_TX_POWER); + + pRfTxPower = (HostCmd_DS_802_11_RF_TX_POWER *)pos; + + memset(pRfTxPower, 0x00, sizeof(HostCmd_DS_802_11_RF_TX_POWER)); + + hostcmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[hostcmd]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + connected = le16_to_cpu(pRfTxPower->current_level) ? TRUE : FALSE; + + if (connected) { + display_channel(); + + printf("\n"); + printf(" MinPower: %2d\n", pRfTxPower->min_power); + printf(" MaxPower: %2d\n", pRfTxPower->max_power); + printf(" Current: %2d\n", + le16_to_cpu(pRfTxPower->current_level)); + printf("\n"); + } + + rates = get_txpwrcfg(ratePower); + + puts(""); + + rateSort(ratePower, rates); + + printf("20MHz:"); + + for (rateIdx = 0; rateIdx < 12; rateIdx++) { + printf("%6s", get_ratestr(ratePower[rateIdx].rate)); + } + + printf("\n---------------------------------------" + "----------------------------------------\n%s", + connected ? "Active" : "Max "); + + for (rateIdx = 0; rateIdx < 12; rateIdx++) { + printf("%6d", ratePower[rateIdx].max); + } + + if (!connected) { + printf("\n---------------------------------------" + "----------------------------------------\n"); + + process_chantrpcdisp(ratePower[0].rate, ratePower[12 - 1].rate); + } + + puts("\n"); + + /* + ** MCS0 -> MCS7 + */ + + printf("20MHz:"); + + for (rateIdx = 12; rateIdx < 20; rateIdx++) { + printf("%6s", get_ratestr(ratePower[rateIdx].rate)); + } + + printf("\n---------------------------------------" + "----------------------------------------\n%s", + connected ? "Active" : "Max "); + + for (rateIdx = 12; rateIdx < 20; rateIdx++) { + printf("%6d", ratePower[rateIdx].max); + } + + if (!connected) { + printf("\n---------------------------------------" + "----------------------------------------\n"); + + process_chantrpcdisp(ratePower[12].rate, + ratePower[20 - 1].rate); + } + + puts("\n"); + + /* + ** MCS0 -> MCS7 @ 40MHz + */ + + printf("40MHz:"); + + for (rateIdx = 20; rateIdx < rates; rateIdx++) { + printf("%6s", get_ratestr(ratePower[rateIdx].rate)); + } + + printf("\n---------------------------------------" + "----------------------------------------\n%s", + connected ? "Active" : "Max "); + + for (rateIdx = 20; rateIdx < rates; rateIdx++) { + printf("%6d", ratePower[rateIdx].max); + } + + if (!connected) { + printf("\n---------------------------------------" + "----------------------------------------\n"); + + process_chantrpcdisp(ratePower[20].rate, + ratePower[rates - 1].rate); + } + + puts("\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} diff --git a/mwifiex_8997/mapp/mlanutl/mlanoffload.h b/mwifiex_8997/mapp/mlanutl/mlanoffload.h new file mode 100755 index 0000000..c8e8340 --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanoffload.h @@ -0,0 +1,441 @@ +/** @file mlanoffload.h + * + * @brief This files contains mlanutl offload command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#ifndef _MLANOFFLOAD_H_ +#define _MLANOFFLOAD_H_ + +#ifndef MAX +/** Find maximum value */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif /* MAX */ + +/** Key length */ +#define KEY_LEN 32 +/** Phrase length */ +#define PHRASE_LEN 32 +/** WEP Key count */ +#define WEP_KEY_CNT 4 + +/* Bitmap for OFFLoad Enable - Feature*/ +#ifdef BIG_ENDIAN_SUPPORT +/** Roaming Feature */ +#define PROFILE_DB_FEATURE_ROAMING 0x8000 +/** CCX Feature */ +#define PROFILE_DB_FEATURE_CCX 0x4000 +/** UNUSED Feature */ +#define PROFILE_DB_FEATURE_UNUSED 0x2000 +/** adhoc/infra mode */ +#define PROFILE_DB_FEATURE_MODE 0x1000 +#else +/** Roaming Feature */ +#define PROFILE_DB_FEATURE_ROAMING 0x0001 +/** CCX Feature */ +#define PROFILE_DB_FEATURE_CCX 0x0002 +/** UNUSED Feature */ +#define PROFILE_DB_FEATURE_UNUSED 0x0004 +/** adhoc/infra mode */ +#define PROFILE_DB_FEATURE_MODE 0x0008 +#endif + +/* Bitmap for profile AKMP Support */ +#ifdef BIG_ENDIAN_SUPPORT +/** Key Management EAP */ +#define PROFILE_DB_KEY_MGMT_IEEE8021X 0x8000 +/** Key Management PSK */ +#define PROFILE_DB_KEY_MGMT_PSK 0x4000 +/** Key Management NONE */ +#define PROFILE_DB_KEY_MGMT_NONE 0x2000 +/** Key Management CCKM */ +#define PROFILE_DB_KEY_MGMT_CCKM 0x1000 +/** Key Management UNUSED */ +#define PROFILE_DB_KEY_MGMT_UNUSED 0x0800 +/** Key Management FT 802.1x */ +#define PROFILE_DB_KEY_MGMT_FT_IEEE8021X 0x0400 +/** Key Management FT PSK */ +#define PROFILE_DB_KEY_MGMT_FT_PSK 0x0200 +/** Key Management SHA256 802.1x */ +#define PROFILE_DB_KEY_MGMT_SHA256_IEEE8021X 0x0100 +/** Key Management SHA256 PSK*/ +#define PROFILE_DB_KEY_MGMT_SHA256_PSK 0x0080 +#else +/** Key Management EAP */ +#define PROFILE_DB_KEY_MGMT_IEEE8021X 0x0001 +/** Key Management PSK */ +#define PROFILE_DB_KEY_MGMT_PSK 0x0002 +/** Key Management NONE */ +#define PROFILE_DB_KEY_MGMT_NONE 0x0004 +/** Key Management CCKM */ +#define PROFILE_DB_KEY_MGMT_CCKM 0x0008 +/** Key Management UNUSED */ +#define PROFILE_DB_KEY_MGMT_UNUSED 0x0010 +/** Key Management FT 802.1x */ +#define PROFILE_DB_KEY_MGMT_FT_IEEE8021X 0x0020 +/** Key Management FT PSK */ +#define PROFILE_DB_KEY_MGMT_FT_PSK 0x0040 +/** Key Management SHA256 802.1x */ +#define PROFILE_DB_KEY_MGMT_SHA256_IEEE8021X 0x0080 +/** Key Management SHA256 PSK*/ +#define PROFILE_DB_KEY_MGMT_SHA256_PSK 0x0100 +#endif + +/* Bitmap for profile Encryption protocol support */ +#ifdef BIG_ENDIAN_SUPPORT +/** Encryption protocol noRsn */ +#define PROFILE_DB_PROTO_NO_RSN 0x8000 +/** Encryption protocol static wep */ +#define PROFILE_DB_PROTO_WEP_STATIC 0x4000 +/** Encryption protocol dynamic wep */ +#define PROFILE_DB_PROTO_WEP_DYNAMIC 0x2000 +/** Encryption protocol WPA */ +#define PROFILE_DB_PROTO_WPA 0x1000 +/** Encryption protocol WPA-none + * Ad-hoc Networks */ +#define PROFILE_DB_PROTO_WPA_NONE 0x0800 +/** Encryption protocol WPA2 */ +#define PROFILE_DB_PROTO_WPA2 0x0400 +/** Encryption protocol CCKM */ +#define PROFILE_DB_PROTO_CCKM 0x0200 +#else +/** Encryption protocol noRsn */ +#define PROFILE_DB_PROTO_NO_RSN 0x0001 +/** Encryption protocol static wep */ +#define PROFILE_DB_PROTO_WEP_STATIC 0x0002 +/** Encryption protocol dynamic wep */ +#define PROFILE_DB_PROTO_WEP_DYNAMIC 0x0004 +/** Encryption protocol WPA */ +#define PROFILE_DB_PROTO_WPA 0x0008 +/** Encryption protocol WPA-none + * Ad-hoc Networks */ +#define PROFILE_DB_PROTO_WPA_NONE 0x0010 +/** Encryption protocol WPA2 */ +#define PROFILE_DB_PROTO_WPA2 0x0020 +/** Encryption protocol CCKM */ +#define PROFILE_DB_PROTO_CCKM 0x0040 +#endif + +#ifdef BIG_ENDIAN_SUPPORT +/** Cipher wep40 */ +#define PROFILE_DB_CIPHER_WEP40 0x80 +/** Cipher wep104 */ +#define PROFILE_DB_CIPHER_WEP104 0x40 +/** Cipher tkip */ +#define PROFILE_DB_CIPHER_TKIP 0x20 +/** Cipher ccmp */ +#define PROFILE_DB_CIPHER_CCMP 0x10 +#else +/** Cipher wep40 */ +#define PROFILE_DB_CIPHER_WEP40 0x01 +/** Cipher wep104 */ +#define PROFILE_DB_CIPHER_WEP104 0x02 +/** Cipher tkip */ +#define PROFILE_DB_CIPHER_TKIP 0x04 +/** Cipher ccmp */ +#define PROFILE_DB_CIPHER_CCMP 0x08 +#endif + +typedef struct { + /** Header */ + MrvlIEtypesHeader_t header; + + t_u32 mode; /**< Mode */ + t_u32 max_off_channel; + /**< Maximum off-channel measurement duration (ms) */ + t_u32 max_on_channel; + /**< Maximum on-channel measurement duration (ms) */ + +} __ATTRIB_PACK__ MrvlIETypes_MeasTiming_t; + +typedef struct { + /** Action Set or get */ + t_u16 action; + + /** TLV buffer starts here */ + t_u8 tlv_buffer[1]; + + /* + * MrvlIETypes_MeasTiming_t + */ +} __ATTRIB_PACK__ HostCmd_DS_MEASUREMENT_Timing; + +/** helper structure for profile parsing */ +typedef struct { + /** SSID name string */ + t_u8 ssid[IW_ESSID_MAX_SIZE + 1]; + /** SSID len */ + t_u32 ssid_len; + /** BSSID network name */ + t_u8 bssid[ETH_ALEN]; + /** passphrase configured */ + t_s8 passphrase[PHRASE_LEN]; + /** passphrase length */ + t_u32 passphrase_len; + /** Pre-shared key config flag */ + int psk_config; + /** Pre-shared key */ + t_u8 psk[KEY_LEN]; + /** wep keys */ + t_u8 wep_key[WEP_KEY_CNT][KEY_LEN]; + /** wep keys lengths */ + t_u8 wep_key_len[WEP_KEY_CNT]; + /** wep key index */ + int wep_key_idx; + /** protocol fields */ + t_u16 protocol; + /** pairwise Cipher values */ + t_u8 pairwise_cipher; + /** Group Cipher values */ + t_u8 groupwise_cipher; + /** key management */ + t_u16 key_mgmt; + /** offload specific parameter(roaming) */ + t_u16 roaming; + /** offload specific parameter */ + t_u16 reserved; + /** offload specific parameter--ccx */ + t_u16 ccx; + /** offload specific parameter--mode */ + t_u16 mode; +} profile_entry_t; + +typedef struct { +#ifdef BIG_ENDIAN_SUPPORT + /** Reserved */ + t_u8 Reserved:3; + /** Channel not measured */ + t_u8 Unmeasured:1; + /** Radar detected */ + t_u8 Radar:1; + /** Unidentified signal received */ + t_u8 Unidentified:1; + /** OFDM Preamble received */ + t_u8 OFDM_Preamble:1; + /** BSS found */ + t_u8 BSS:1; +#else + /** BSS found */ + t_u8 BSS:1; + /** OFDM Preamble received */ + t_u8 OFDM_Preamble:1; + /** Unidentified signal received */ + t_u8 Unidentified:1; + /** Radar detected */ + t_u8 Radar:1; + /** Channel not measured */ + t_u8 Unmeasured:1; + /** Reserved */ + t_u8 Reserved:3; +#endif +} __ATTRIB_PACK__ IEEEtypes_DFS_Map_t; + +typedef struct { + MrvlIEtypesHeader_t Header; /**< Header */ + + t_u8 scanReqId; /**< Scan request id assigned in table */ +} __ATTRIB_PACK__ MrvlIEtypes_ChanRptBcn_t; + +typedef struct { + MrvlIEtypesHeader_t Header; /**< Header */ + + IEEEtypes_DFS_Map_t map; /**< IEEE 802.11h basic meas report */ +} __ATTRIB_PACK__ MrvlIEtypes_ChanRpt11hBasic_t; + +typedef struct { + MrvlIEtypesHeader_t Header; /**< Header */ + + t_u8 sourceAddr[ETH_ALEN]; /**< Source MAC */ + t_u8 bssid[ETH_ALEN]; /**< BSSID MAC */ + t_s16 rssi; /**< Avg RSSI of frames */ + t_u16 frameCnt; /**< # of frames */ +} __ATTRIB_PACK__ MrvlIEtypes_ChanRptFrame_t; + +typedef struct { + t_u8 modGroup; + t_u8 txPower; + +} __ATTRIB_PACK__ MrvlChanTrpcEntry_t; + +typedef struct { + MrvlIEtypesHeader_t header; + /**< Header */ + + MrvlChannelDesc_t chanDesc; + MrvlChanTrpcEntry_t chanTrpcEntry[1]; + +} __ATTRIB_PACK__ MrvlIEtypes_ChanTrpcCfg_t; + +typedef struct { + t_u16 action; + /**< CMD Action Get/Set*/ + t_u16 reserved; + + t_u8 tlv_buffer[1];/** MrvlIEtypes_ChanTrpcCfg_t TLVs */ + +} __ATTRIB_PACK__ HostCmd_DS_CHAN_TRPC_CONFIG; + +typedef struct { + t_u8 controlSelect; + + t_u8 controlBitmap[1]; /* Variable length # of byte bitmaps */ + +} __ATTRIB_PACK__ HostCmd_DS_OFFLOAD_FEATURE_CONTROL; + +#define IAPP_DATA_MAX 1000 + +/** + * @brief Enumeration for the command result from an IAPP Proxy command + */ +typedef enum { + IAPP_PROXY_RESULT_SUCCESS = 0, + IAPP_PROXY_RESULT_EXEC_FAILURE = 1, + IAPP_PROXY_RESULT_TIMEOUT = 2, + IAPP_PROXY_RESULT_DATA_INVALID = 3, +} __ATTRIB_PACK__ mlan_iapp_proxy_result_e; + +typedef struct { + mlan_iapp_proxy_result_e commandResult; + /**< Firmware execution result */ + + t_u32 timeout_ms; /**< Timeout value in milliseconds */ + + t_u8 iappType; + t_u8 iappSubType; + + t_u32 iappDataLen; + t_u8 iappData[IAPP_DATA_MAX]; + +} __ATTRIB_PACK__ HostCmd_DS_IAPP_PROXY; + +typedef struct { + /** Action: GET/SET */ + t_u16 Action; + /** Reserved */ + t_u16 Reserved; + /** Association timeout */ + t_u32 AssocTimeout; + /** Reassociation timeout */ + t_u32 ReassocTimeout; + /** Hand shake timeout */ + t_u32 HandShakeTimeout; + /** Frame exchange timeout */ + t_u32 FrameExchangeTimeout; + /** Deauth of old AP in millisec; 0 to disable */ + t_u32 PriorApDeauthDelay; + /** Maximum time after a disconnect where a reassoc frame will be sent */ + t_u32 ReassocDiscMax; +} __ATTRIB_PACK__ HostCmd_DS_AssociationTiming_t; + +/** 16 bit unsigned integer */ +typedef t_u16 IEEEtypes_AId_t; +/** 16 bit unsigned integer */ +typedef t_u16 IEEEtypes_StatusCode_t; + +typedef struct { + /** Capability information */ + IEEEtypes_CapInfo_t Capability; + /** Association response status code */ + IEEEtypes_StatusCode_t StatusCode; + /** Association ID */ + IEEEtypes_AId_t AId; + /** IE data buffer */ + t_u8 IEBuffer[1]; +} __ATTRIB_PACK__ IEEEtypes_AssocRsp_t; + +/** Maximum number of AC QOS queues available in the driver/firmware */ +#define MAX_AC_QUEUES 4 + +/** timing select structure */ +typedef struct { + char *str; /**< Timing mode string */ + int match_len; /**< match length */ + t_u8 sel; /**< flag */ + +} timing_sel_t; + +/** ENUM definition: reg_chan_table */ +typedef enum { + REGTABLE_DEFAULT = 0, + REGTABLE_ESS = 1, + REGTABLE_USER = 2, + REGTABLE_MULTIDOMAIN = 3, + + REGTABLE_MAX = 0xFFFF, +} reg_chan_table_e; + +/** Sub-command callback */ +typedef int (*sub_cmd_callback_t) (int argc, char *argv[]); + +/** Sub-command execution data */ +typedef struct { + char *str; + /**< Command string */ + int match_len; + /**< Length */ + int display; + /**< display as valid cmd */ + sub_cmd_callback_t callback; + /**< Sub-command callback */ + +} sub_cmd_exec_t; + +/** HostCmd_CMD_802_11_RF_TX_POWER */ +typedef struct { + t_u16 action; + t_s16 current_level; + t_s8 max_power; + t_s8 min_power; + +} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_TX_POWER; + +/** HostCmd_CMD_802_11_AUTHENTICATE */ +typedef struct { + /** MAC address */ + t_u8 MacAddr[ETH_ALEN]; + /** Authentication type */ + t_u8 AuthType; +} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTHENTICATE; + +boolean reg_class_table_select(char *tableStr, reg_chan_table_e *pTable); +int process_sub_cmd(sub_cmd_exec_t *sub_cmd, int num_sub_cmds, + int argc, char *argv[]); +int process_regclass(int argc, char *argv[]); +int process_scanagent(int argc, char *argv[]); +int process_measurement(int argc, char *argv[]); +int process_profile_entry(int argc, char *argv[]); +int process_get_ra_config(int argc, char *argv[]); +int process_set_ra_config(int argc, char *argv[]); +int process_chanrpt(int argc, char *argv[]); +int process_assoc_timing(int argc, char *argv[]); +int process_get_assocrsp(int argc, char *argv[]); +int process_link_stats(int argc, char *argv[]); + +int process_opchan(int argc, char *argv[]); +int process_changroup(int argc, char *argv[]); +int process_fcontrol(int argc, char *argv[]); +int process_iapp(int argc, char *argv[]); +int process_rf_tx_power(int argc, char *argv[]); +int process_authenticate(int argc, char *argv[]); +int process_txpowdisp(int argc, char *argv[]); + +#endif /* _MLANOFFLOAD_H_ */ diff --git a/mwifiex_8997/mapp/mlanutl/mlanregclass.c b/mwifiex_8997/mapp/mlanutl/mlanregclass.c new file mode 100755 index 0000000..505c6ef --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanregclass.c @@ -0,0 +1,539 @@ +/** @file mlanregclass.c + * + * @brief This files contains mlanutl regclass command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#include "mlanutl.h" +#include "mlanhostcmd.h" +#include "mlanoffload.h" +#include "mlanregclass.h" + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief Convert reg domain number to string + * + * @param reg_domain Reg Domain + * + * @return Reg Domain type + */ +static char * +reg_domain_to_str(reg_domain_e reg_domain) +{ + switch (reg_domain) { + case REGDOMAIN_FCC: + return "FCC"; + + case REGDOMAIN_ETSI: + return "ETSI"; + + case REGDOMAIN_MIC: + return "MIC"; + + case REGDOMAIN_OTHER: + return "MULTI"; + + default: + break; + } + + return "UNKN"; +} + +/** + * @brief Convert reg channel table number to string + * + * @param table_select Reg channel table + * + * @return Reg channel table type + */ +static char * +table_num_to_str(reg_chan_table_e table_select) +{ + switch (table_select) { + case REGTABLE_USER: + return "User"; + + case REGTABLE_MULTIDOMAIN: + return "MultiDomain"; + + case REGTABLE_ESS: + return "ESS"; + + case REGTABLE_DEFAULT: + return "Default"; + + default: + break; + } + + return "UNKN"; +} + +/** + * @brief Regclass dump channel table + * + * @param argc Number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +reg_class_dump_chan_table(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_REGCLASS_GET_CHAN_TABLE *get_table; + int idx; + t_u16 regLimits; + boolean invalid_cmd = FALSE; + + printf("ERR:Cannot allocate buffer for command!\n"); + if (argv[0] == NULL) { + invalid_cmd = TRUE; + } else { + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *) + malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, + strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = + (HostCmd_DS_GEN *)(buffer + cmd_header_len + + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_REGCLASS_GET_CHAN_TABLE); + hostcmd->command = cpu_to_le16(HostCmd_CMD_REGCLASS_CHAN_TABLE); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + get_table = (HostCmd_DS_REGCLASS_GET_CHAN_TABLE *)pos; + get_table->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + if (reg_class_table_select(argv[0], (reg_chan_table_e *) + &get_table->table_select) == FALSE) { + invalid_cmd = TRUE; + } + } + + if (invalid_cmd) { + printf("\nValid tables table; valid [user, md, ess, default]\n\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + get_table->table_select = cpu_to_le16((t_u16)(get_table->table_select)); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[regClassIoctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (!le16_to_cpu(hostcmd->result)) { + printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + + get_table->table_select = le16_to_cpu(get_table->table_select); + get_table->chan = le32_to_cpu(get_table->chan); + + printf("---------------------------------------"); + printf("---------------------------------------\n"); + printf("%35s: %s [%d]\n", "Channel Table", + table_num_to_str(get_table->table_select), (int)get_table->chan); + printf("---------------------------------------"); + printf("---------------------------------------\n"); + printf(" chn | freq | sfrq | sp | class | maxP | behavior limits\n"); + printf("---------------------------------------"); + printf("---------------------------------------\n"); + + for (idx = 0; (unsigned int)idx < get_table->chan; idx++) { + char regDisp[8]; + + sprintf(regDisp, "%4s-%02u", + reg_domain_to_str(get_table->chan_entry[idx]. + reg_domain), + get_table->chan_entry[idx].regulatory_class); + + printf(" %03u | %04u | %04u | %02u | %-8s | %02u |", + get_table->chan_entry[idx].chan_num, + (get_table->chan_entry[idx].start_freq + + (get_table->chan_entry[idx].chan_num * 5)), + le16_to_cpu(get_table->chan_entry[idx].start_freq), + le16_to_cpu(get_table->chan_entry[idx].chan_spacing), + regDisp, get_table->chan_entry[idx].max_tx_power); + + regLimits = le16_to_cpu(get_table->chan_entry[idx].reg_limits); + + if (regLimits & BLIMIT_NOMADIC) + printf(" nomadic"); + if (regLimits & BLIMIT_INDOOR_ONLY) + printf(" indoor"); + if (regLimits & BLIMIT_TPC) + printf(" tpc"); + if (regLimits & BLIMIT_DFS) + printf(" dfs"); + if (regLimits & BLIMIT_IBSS_PROHIBIT) + printf(" no_ibss"); + if (regLimits & BLIMIT_FOUR_MS_CS) + printf(" 4ms_cs"); + if (regLimits & BLIMIT_LIC_BASE_STA) + printf(" base_sta"); + if (regLimits & BLIMIT_MOBILE_STA) + printf(" mobile"); + if (regLimits & BLIMIT_PUBLIC_SAFETY) + printf(" safety"); + if (regLimits & BLIMIT_ISM_BANDS) + printf(" ism"); + + printf("\n"); + } + printf("---------------------------------------"); + printf("---------------------------------------\n"); + printf("\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Regclass configure user table + * + * @param argc Number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +reg_class_config_user_table(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_REGCLASS_CONFIG_USER_TABLE *cfg_user_table; + + if (argv[0] == NULL) { + printf("\nCountry string not specified\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_REGCLASS_CONFIG_USER_TABLE); + hostcmd->command = cpu_to_le16(HostCmd_CMD_REGCLASS_CONFIG_USER_TABLE); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + cfg_user_table = (HostCmd_DS_REGCLASS_CONFIG_USER_TABLE *)pos; + cfg_user_table->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + memcpy(cfg_user_table->regulatory_str, + argv[0], + MIN(strlen(argv[0]), sizeof(cfg_user_table->regulatory_str))); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[regClassIoctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (!le16_to_cpu(hostcmd->result)) { + printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue regclass multi-domain command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +reg_class_multidomain(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL *multidomain_ctrl; + boolean invalid_cmd = FALSE; + + if (argv[0] == NULL) { + invalid_cmd = TRUE; + } else { + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *) + malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, + strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = + (HostCmd_DS_GEN *)(buffer + cmd_header_len + + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = + S_DS_GEN + + sizeof(HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL); + hostcmd->command = + cpu_to_le16(HostCmd_CMD_REGCLASS_MULTIDOMAIN_CONTROL); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + multidomain_ctrl = + (HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL *)pos; + if (strcmp(argv[0], "on") == 0) { + multidomain_ctrl->multidomain_enable = 1; + } else if (strcmp(argv[0], "off") == 0) { + multidomain_ctrl->multidomain_enable = 0; + } else { + invalid_cmd = TRUE; + } + } + + if (invalid_cmd) { + printf("\nUnknown multiDomain command; valid [on, off]\n\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + multidomain_ctrl->multidomain_enable = + cpu_to_le32(multidomain_ctrl->multidomain_enable); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[regClass]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } else { + printf("\nMultiDomain: %s\n", + le32_to_cpu(multidomain_ctrl->multidomain_enable) ? + "Enabled" : "Disabled"); + } + + if (!le16_to_cpu(hostcmd->result)) { + printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a regclass command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_regclass(int argc, char *argv[]) +{ + sub_cmd_exec_t sub_cmd[] = { {"table", 1, 1, reg_class_dump_chan_table}, + {"multidomain", 1, 1, reg_class_multidomain}, + {"country", 1, 1, reg_class_config_user_table} + }; + + return process_sub_cmd(sub_cmd, NELEMENTS(sub_cmd), argc, argv); +} diff --git a/mwifiex_8997/mapp/mlanutl/mlanregclass.h b/mwifiex_8997/mapp/mlanutl/mlanregclass.h new file mode 100755 index 0000000..a6d979d --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanregclass.h @@ -0,0 +1,99 @@ +/** @file mlanregclass.h + * + * @brief This files contains mlanutl regclass command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#ifndef _MLANREGCLASS_H +#define _MLANREGCLASS_H + +/** Nomadic */ +#define BLIMIT_NOMADIC (1 << 0) +/** Indoor */ +#define BLIMIT_INDOOR_ONLY (1 << 1) +/** Tpc */ +#define BLIMIT_TPC (1 << 2) +/** Dfs */ +#define BLIMIT_DFS (1 << 3) +/** IBSS Prohibit */ +#define BLIMIT_IBSS_PROHIBIT (1 << 4) +/** Four MS CS */ +#define BLIMIT_FOUR_MS_CS (1 << 5) +/** LIC Base STA */ +#define BLIMIT_LIC_BASE_STA (1 << 6) +/** Mobile STA */ +#define BLIMIT_MOBILE_STA (1 << 7) +/** Public Safety */ +#define BLIMIT_PUBLIC_SAFETY (1 << 8) +/** ISM Bands */ +#define BLIMIT_ISM_BANDS (1 << 9) + +/** Enum Definitions: reg_domain */ +typedef enum { + REGDOMAIN_NULL = 0x00, + + REGDOMAIN_FCC = 0x01, + REGDOMAIN_ETSI = 0x02, + REGDOMAIN_MIC = 0x03, + + REGDOMAIN_OTHER = 0xFF, + +} reg_domain_e; + +typedef struct { + t_u8 reg_domain; /**< Domain */ + t_u8 regulatory_class; + /**< Regulatory class */ + t_u8 chan_num; /**< Channel Number */ + t_u8 reserved1; /**< Reserved */ + t_u16 start_freq; /**< Start frequency */ + t_u16 chan_spacing; /**< channel spacing */ + t_u8 max_tx_power; /**< Max. tx power */ + t_u8 coverage_class;/**< Coverage class */ + t_u16 reg_limits; /**< Limits */ +} __ATTRIB_PACK__ chan_entry_t; + +typedef struct { + /** Action: GET/SET */ + t_u16 action; + /** Reg channel table */ + t_u16 table_select; + /** Channel number */ + t_u32 chan; + /** Channel entry */ + chan_entry_t chan_entry[75]; +} __ATTRIB_PACK__ HostCmd_DS_REGCLASS_GET_CHAN_TABLE; + +typedef struct { + t_u16 action; + /**< Action: GET/SET */ + t_u16 reserved; + /**< Reserved */ + char regulatory_str[3];/**< Regulatory String */ +} __ATTRIB_PACK__ HostCmd_DS_REGCLASS_CONFIG_USER_TABLE; + +typedef struct { + t_u32 multidomain_enable; + /**< Multi domain enable */ +} __ATTRIB_PACK__ HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL; + +#endif /* _MLANREGCLASS_H */ diff --git a/mwifiex_8997/mapp/mlanutl/mlanroamagent.c b/mwifiex_8997/mapp/mlanutl/mlanroamagent.c new file mode 100755 index 0000000..e973e81 --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanroamagent.c @@ -0,0 +1,3669 @@ +/** @file mlanroamagent.c + * + * @brief This files contains mlanutl roamagent command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#include "mlanutl.h" +#include "mlanhostcmd.h" +#include "mlanoffload.h" +#include "mlanroamagent.h" + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief Issue getra failcnt command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetFailureCount(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int failCount, failTimeThresh, state, i; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold; + MrvlIEtypes_FailureCount_t *pFailureCount; + MrvlIEtypesHeader_t *pTlvHdr; + t_u8 *tlvptr; + const char *states[] = + { "Stable", "Degrading", "Unacceptable", "Hardroam" }; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos; + cmd_len = + (S_DS_GEN + + sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD) + - sizeof(statsthreshold->TlvBuffer)); + + /* Can be extended to all states later */ + for (state = STATE_HARDROAM - 1; state < STATE_HARDROAM; state++) { + statsthreshold->State = state + 1; + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roamstatistics]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + i = le16_to_cpu(hostcmd->size); + i -= cmd_len; + tlvptr = statsthreshold->TlvBuffer; + + while (i > 2) { + pTlvHdr = (MrvlIEtypesHeader_t *)tlvptr; + + switch (le16_to_cpu(pTlvHdr->type)) { + case TLV_TYPE_FAILCOUNT: + pFailureCount = + (MrvlIEtypes_FailureCount_t *)pTlvHdr; + failCount = pFailureCount->fail_value; + failTimeThresh = + le16_to_cpu(pFailureCount-> + fail_min_thresh_time_millisecs); + break; + } + + tlvptr += (le16_to_cpu(pTlvHdr->len) + + sizeof(MrvlIEtypesHeader_t)); + i -= (le16_to_cpu(pTlvHdr->len) + + sizeof(MrvlIEtypesHeader_t)); + } + + printf("State: %-8s. FailCount = %d, FailTimeThresh(ms) = %d\n", + states[state], failCount, failTimeThresh); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra bcnmiss command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetPreBeaconMiss(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int bcnmiss, state = STATE_HARDROAM, i; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold; + MrvlIEtypes_BeaconsMissed_t *pBeaconMissed; + MrvlIEtypesHeader_t *pTlvHdr; + t_u8 *tlvptr; + const char *states[] = + { "Stable", "Degrading", "Unacceptable", "Hardroam" }; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos; + cmd_len = + (S_DS_GEN + + sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD) + - sizeof(statsthreshold->TlvBuffer)); + + /* Can be extended to all states later */ + for (state = STATE_HARDROAM - 1; state < STATE_HARDROAM; state++) { + statsthreshold->State = state + 1; + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[beacon miss]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + i = le16_to_cpu(hostcmd->size); + i -= cmd_len; + tlvptr = statsthreshold->TlvBuffer; + + while (i > 2) { + pTlvHdr = (MrvlIEtypesHeader_t *)tlvptr; + + switch (le16_to_cpu(pTlvHdr->type)) { + + case TLV_TYPE_PRE_BEACON_LOST: + pBeaconMissed = + (MrvlIEtypes_BeaconsMissed_t *)pTlvHdr; + bcnmiss = pBeaconMissed->beacon_missed; + } + + tlvptr += (le16_to_cpu(pTlvHdr->len) + + sizeof(MrvlIEtypesHeader_t)); + i -= (le16_to_cpu(pTlvHdr->len) + + sizeof(MrvlIEtypesHeader_t)); + } + + printf("State: %-8s. Pre Beacon missed threshold %d\n", + states[state], bcnmiss); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra rssi/snr command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param type RSSI/SNR threshold type + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetStatsThreshold(int argc, char *argv[], int type) +{ + int ret = MLAN_STATUS_SUCCESS; + int state = 0, i = 0, profile = 1; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold; + MrvlIEtypes_BeaconHighRssiThreshold_t *pHighRssiThreshold; + MrvlIEtypes_BeaconLowRssiThreshold_t *pLowRssiThreshold; + MrvlIEtypes_BeaconHighSnrThreshold_t *pHighSnrThreshold; + MrvlIEtypes_BeaconLowSnrThreshold_t *pLowSnrThreshold; + t_s8 high, low; + t_u8 *tlvptr; + t_u16 tlv; + const char *states[] = { "Stable", "Degrading", "Unacceptable" }; + + if (argc) { + if (strncmp(argv[0], "configured", strlen("config")) == 0) { + profile = 0; + } else if (strncmp(argv[0], "active", strlen("active"))) { + printf("\nIncorrect parameter %s for getra command\n\n", + argv[0]); + ret = MLAN_STATUS_FAILURE; + goto done; + } + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos; + cmd_len = + (S_DS_GEN + + sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD) + - sizeof(statsthreshold->TlvBuffer)); + + printf("---------------------------------------------\n"); + if (type == RSSI_THRESHOLD) { + printf(" RSSI Thresholds\n"); + } else { + printf(" SNR Thresholds\n"); + } + printf("---------------------------------------------\n"); + + for (state = STATE_STABLE - 1; state < STATE_UNACCEPTABLE; state++) { + statsthreshold->State = state + 1; + statsthreshold->Profile = profile; + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roamstatistics]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", le16_to_cpu(hostcmd->command), le16_to_cpu(hostcmd->result)); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + i = le16_to_cpu(hostcmd->size); + i -= cmd_len; + tlvptr = statsthreshold->TlvBuffer; + while (i > 2) { + /* + * ENDIANNESS for Response + */ + tlv = le16_to_cpu(*((t_u16 *)(tlvptr))); + + switch (tlv) { + case TLV_TYPE_RSSI_HIGH: + high = *(t_s8 *)(tlvptr + sizeof(t_u16) + + sizeof(t_u16)); + pHighRssiThreshold = + (MrvlIEtypes_BeaconHighRssiThreshold_t + *)(tlvptr); + tlvptr += + (le16_to_cpu + (pHighRssiThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + i -= (le16_to_cpu + (pHighRssiThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + break; + + case TLV_TYPE_RSSI_LOW: + low = *(t_s8 *)(tlvptr + sizeof(t_u16) + + sizeof(t_u16)); + pLowRssiThreshold = + (MrvlIEtypes_BeaconLowRssiThreshold_t + *)(tlvptr); + tlvptr += + (le16_to_cpu + (pLowRssiThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + i -= (le16_to_cpu(pLowRssiThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + break; + + case TLV_TYPE_SNR_HIGH: + high = *(t_s8 *)(tlvptr + sizeof(t_u16) + + sizeof(t_u16)); + pHighSnrThreshold = + (MrvlIEtypes_BeaconHighSnrThreshold_t + *)(tlvptr); + tlvptr += + (le16_to_cpu + (pHighSnrThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + i -= (le16_to_cpu(pHighSnrThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + break; + + case TLV_TYPE_SNR_LOW: + low = *(t_s8 *)(tlvptr + sizeof(t_u16) + + sizeof(t_u16)); + pLowSnrThreshold = + (MrvlIEtypes_BeaconLowSnrThreshold_t + *)(tlvptr); + tlvptr += + (le16_to_cpu + (pLowSnrThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + i -= (le16_to_cpu(pLowSnrThreshold->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + break; + } + } + + printf("%-13s| High = %4d | Low = %4d |\n", + states[state], high, low); + } + puts(""); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra rssi/snr command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetRssiStatsThreshold(int argc, char *argv[]) +{ + return roamGetStatsThreshold(argc, argv, RSSI_THRESHOLD); +} + +/** + * @brief Coverts ms to exactTime + * + * @param ms number of milliseconds + * @param t converted into this structure + * + * @return none + */ +static void +ms2exactTime(t_u32 ms, ExactTime_t *t) +{ + memset(t, 0, sizeof(ExactTime_t)); + + t->msecs = ms % 1000; + if (ms >= 1000) { + ms = (ms - t->msecs) / 1000; + t->secs = ms % 60; + if (ms >= 60) { + ms = (ms - t->secs) / 60; + t->mins = ms % 60; + if (ms >= 60) { + ms = (ms - t->mins) / 60; + t->hrs = ms; + } + } + } + return; +} + +/** + * @brief Issue getra neighbor assessment command + * + * @pNborAssessment neighbour assessment struct + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +getNborAssessment(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT + *pNborAssessmentParam) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *pNborAssessment; + + /* + * NEIGHBOR_ASSESSMENT + */ + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + pNborAssessment = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *)pos; + cmd_len = S_DS_GEN + sizeof(pNborAssessment->action); + pNborAssessment->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[GetNeibhorAssesinfo]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + /* + * ENDIANNESS for Response + */ + pNborAssessment->QualifyingNumNeighbor = + le16_to_cpu(pNborAssessment->QualifyingNumNeighbor); + pNborAssessment->ShortBlacklistPeriod = + le32_to_cpu(pNborAssessment->ShortBlacklistPeriod); + pNborAssessment->LongBlacklistPeriod = + le32_to_cpu(pNborAssessment->LongBlacklistPeriod); + pNborAssessment->StaleCount = le16_to_cpu(pNborAssessment->StaleCount); + pNborAssessment->StalePeriod = + le32_to_cpu(pNborAssessment->StalePeriod); + + memcpy((void *)pNborAssessmentParam, (void *)pNborAssessment, + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT)); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Display exactTime structure elements + * + * @param t ExactTime_t struct + * + * @return None + */ +static void +printExactTime2stdout(ExactTime_t *t) +{ + int flag = 0; + if (t->hrs) { + printf("%dh ", t->hrs); + flag = 1; + } + if (t->mins) { + printf("%dm ", t->mins); + flag = 1; + } + if (t->secs) { + printf("%ds ", t->secs); + flag = 1; + } + if (t->msecs) { + printf("%dms", t->msecs); + flag = 1; + } + if (!flag) { + printf(" 0"); + } +} + +static int +printNeighborAssessmentConfig(void) +{ + HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT nborAssessment; + int idx; + int threshDisp = FALSE; + + if (getNborAssessment(&nborAssessment) != MLAN_STATUS_SUCCESS) { + return MLAN_STATUS_FAILURE; + } + + printf("----------------------------------------------------------\n"); + printf(" Neighbor Threshold Parameters\n"); + printf("----------------------------------------------------------\n"); + printf(" Neighbors needed for tracking mode = %d\n", + nborAssessment.QualifyingNumNeighbor); + printf(" Config RSSI qualification offset = %d dB\n", + nborAssessment.ConfQualSignalStrength); + printf(" Active RSSI qualification offset = %d dB\n", + nborAssessment.ActiveQualSignalStrength); + printf(" Short black list period = %d ms\n", + (int)nborAssessment.ShortBlacklistPeriod); + printf(" Long black list period = %d ms\n", + (int)nborAssessment.LongBlacklistPeriod); + printf(" Stale count = %d\n", + (int)nborAssessment.StaleCount); + printf(" Stale period = %d ms\n", + (int)nborAssessment.StalePeriod); + printf(" Proactive Roaming Thresholds ="); + for (idx = 0; idx < NELEMENTS(nborAssessment.RoamThresh); idx++) { + if (nborAssessment.RoamThresh[idx].RssiNborDiff) { + if (threshDisp) { + printf(" "); + } + + threshDisp = TRUE; + printf("%3d to %4d [%d]\n", + nborAssessment.RoamThresh[idx].RssiHighLevel, + nborAssessment.RoamThresh[idx].RssiLowLevel, + nborAssessment.RoamThresh[idx].RssiNborDiff); + } + } + + if (!threshDisp) { + puts(" < None >"); + } + puts(""); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Issue getra neighbors command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetNborList(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int cmdresplen, i; + struct ifreq ifr; + char neighflag[6]; + ExactTime_t t; + t_u16 tlv; + t_u8 *buffer = NULL, *pos = NULL, *tlvptr = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST *pNborList; + MrvlIEtypes_NeighborEntry_t *pNeighbor; + + /* + * NEIGHBOR_LIST + */ + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + pNborList = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST *)pos; + cmd_len = S_DS_GEN + sizeof(pNborList->action); + pNborList->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBORLIST); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roamneighborlist]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + cmdresplen = le16_to_cpu(hostcmd->size); + cmdresplen -= cmd_len + sizeof(pNborList->Reserved); + tlvptr = pNborList->TlvBuffer; + + printf("----------------------------------------------------" + "--------------\n"); + printf(" BSSID | RSSI | Age | Qualified |" + " Blacklist Duration\n"); + printf("----------------------------------------------------" + "--------------\n"); + + i = 0; + + while (cmdresplen > 2) { + i++; + /* + * ENDIANNESS for Response + */ + tlv = le16_to_cpu(*((t_u16 *)(tlvptr))); + switch (tlv) { + case TLV_TYPE_NEIGHBOR_ENTRY: + pNeighbor = (MrvlIEtypes_NeighborEntry_t *)(tlvptr); + pNeighbor->SignalStrength = + le16_to_cpu(pNeighbor->SignalStrength); + pNeighbor->Age = le16_to_cpu(pNeighbor->Age); + pNeighbor->QualifiedNeighborBitmap = + le32_to_cpu(pNeighbor->QualifiedNeighborBitmap); + + pNeighbor->BlackListDuration = + le32_to_cpu(pNeighbor->BlackListDuration); + ms2exactTime(pNeighbor->BlackListDuration, &t); + neighflag[0] = '\0'; + + if ((pNeighbor->QualifiedNeighborBitmap + & (BIT_NEIGHFLAG_RSSI + | BIT_NEIGHFLAG_AGE + | BIT_NEIGHFLAG_BLACKLIST + | BIT_NEIGHFLAG_ADMISSION_CAP + | BIT_NEIGHFLAG_UPLINK_RSSI)) + == (BIT_NEIGHFLAG_RSSI + | BIT_NEIGHFLAG_AGE + | BIT_NEIGHFLAG_BLACKLIST + | BIT_NEIGHFLAG_ADMISSION_CAP + | BIT_NEIGHFLAG_UPLINK_RSSI)) { + strcat(neighflag, "Yes"); + } else { + strcat(neighflag, "No: "); + if (! + (pNeighbor-> + QualifiedNeighborBitmap & + BIT_NEIGHFLAG_RSSI)) { + strcat(neighflag, "R"); + } + if (! + (pNeighbor-> + QualifiedNeighborBitmap & + BIT_NEIGHFLAG_AGE)) { + strcat(neighflag, "S"); + } + if (!(pNeighbor->QualifiedNeighborBitmap + & BIT_NEIGHFLAG_BLACKLIST)) { + strcat(neighflag, "B"); + } + if (!(pNeighbor->QualifiedNeighborBitmap + & BIT_NEIGHFLAG_ADMISSION_CAP)) { + strcat(neighflag, "A"); + } + if (!(pNeighbor->QualifiedNeighborBitmap + & BIT_NEIGHFLAG_UPLINK_RSSI)) { + strcat(neighflag, "U"); + } + } + printf(" %02x:%02x:%02x:%02x:%02x:%02x | %3d | %5d | %9s | ", pNeighbor->Bssid[0], pNeighbor->Bssid[1], pNeighbor->Bssid[2], pNeighbor->Bssid[3], pNeighbor->Bssid[4], pNeighbor->Bssid[5], pNeighbor->SignalStrength, pNeighbor->Age, neighflag); + + if (pNeighbor->BlackListDuration) { + printExactTime2stdout(&t); + } else { + printf("Not Blacklisted"); + } + printf("\n"); + + tlvptr += (le16_to_cpu(pNeighbor->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + cmdresplen -= (le16_to_cpu(pNeighbor->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + break; + + default: + printf("\nIncorrect response.\n\n"); + break; + } + } + + if (i == 0) { + printf("< Empty >\n"); + } + + printf("\n"); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra neighbor params command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetNborParams(int argc, char *argv[]) +{ + printNeighborAssessmentConfig(); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Issue getra metrics command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetMetrics(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int i; + t_u16 Metrics = 0; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *metricscmd; + + const char *metricslist[] = { "beacon", "data", "per", "fer" }; + + if (argc != 0) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + metricscmd = (HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *)pos; + cmd_len = S_DS_GEN + sizeof(metricscmd->action); + metricscmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roam set matrics]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + Metrics = le16_to_cpu(metricscmd->Metrics); + + if (le16_to_cpu(hostcmd->result) == MLAN_STATUS_SUCCESS) { + printf("\n Metrics Activated: "); + for (i = 0; (unsigned int)i < NELEMENTS(metricslist); i++) { + if (Metrics & BIT(i)) { + printf(" %s ", metricslist[i]); + } + } + printf("\n"); + + if (Metrics & BIT(3)) { + printf("FER Threshold : %u %% \n", + metricscmd->UcFerThresholdValue); + printf("FER Packet Threshold: %d \n", + le32_to_cpu(metricscmd->UiFerPktThreshold)); + printf("FER period. Stable : %d ms, Degrading : %d ms, " + "Unacceptable : %d ms\n", + le32_to_cpu(metricscmd->StableFERPeriod_ms), + le32_to_cpu(metricscmd->DegradingFERPeriod_ms), + le32_to_cpu(metricscmd-> + UnacceptableFERPeriod_ms)); + } + + if (Metrics & BIT(2)) { + printf("PER Threshold : %u %% \n", + metricscmd->UcPerThresholdValue); + printf("PER Packet Threshold: %d \n", + le32_to_cpu(metricscmd->UiPerPktThreshold)); + printf("PER period. Stable : %d ms, Degrading : %d ms, " + "Unacceptable : %d ms\n", + le32_to_cpu(metricscmd->StablePERPeriod_ms), + le32_to_cpu(metricscmd->DegradingPERPeriod_ms), + le32_to_cpu(metricscmd-> + UnacceptablePERPeriod_ms)); + } + + if (Metrics & BIT(1)) { + printf("Data Packet Threshold: %d \n", + le32_to_cpu(metricscmd->UiRxPktThreshold)); + } + + if ((Metrics & BIT(1)) || (Metrics & BIT(2)) || + (Metrics & BIT(3))) { + + printf("Inactivity Period: %d ms \n", + le32_to_cpu(metricscmd-> + InactivityPeriodThreshold_ms)); + } + } else { + printf("command response failure %d.\n", + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra scanperiod command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetScanPeriod(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int state = 0, scanmode = 0, cmdresplen; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL, *tlvptr = NULL; + t_u16 tlv; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP *scanPeriodInfo; + MrvlIEtypes_NeighborScanPeriod_t *pscanperiod; + const char *states[] = { "Stable", "Degrading", "Unacceptable" }; + const char *scanmodes[] = { "Discovery", "Tracking" }; + /* scanperiodValues[state][scanmode] */ + t_u32 values[3][2]; + + /* + * NEIGHBOR_SCANPERIOD + */ + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + scanPeriodInfo = + (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP *)pos; + cmd_len = S_DS_GEN + sizeof(scanPeriodInfo->action); + scanPeriodInfo->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_SCAN_PERIOD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roamscanperiod]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + cmdresplen = le16_to_cpu(hostcmd->size); + cmdresplen -= cmd_len + sizeof(scanPeriodInfo->Reserved); + tlvptr = scanPeriodInfo->TlvBuffer; + while (cmdresplen > 2) { + /* + * ENDIANNESS for Response + */ + tlv = le16_to_cpu(*((t_u16 *)(tlvptr))); + switch (tlv) { + case TLV_TYPE_NEIGHBOR_SCANPERIOD: + pscanperiod = + (MrvlIEtypes_NeighborScanPeriod_t *)(tlvptr); + pscanperiod->SearchMode = + le16_to_cpu(pscanperiod->SearchMode); + pscanperiod->State = le16_to_cpu(pscanperiod->State); + pscanperiod->ScanPeriod = + le32_to_cpu(pscanperiod->ScanPeriod); + state = pscanperiod->State; + scanmode = pscanperiod->SearchMode; + if ((state < STATE_STABLE) || + (state > STATE_UNACCEPTABLE)) { + puts("\nIncorrect state in response.\n"); + } + if ((scanmode < DISCOVERY_MODE) || + (scanmode > TRACKING_MODE)) { + puts("\nIncorrect scanmode in response.\n"); + } + values[state - 1][scanmode - 1] = + pscanperiod->ScanPeriod; + tlvptr += + (le16_to_cpu(pscanperiod->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + cmdresplen -= + (le16_to_cpu(pscanperiod->Header.len) + + sizeof(MrvlIEtypesHeader_t)); + break; + + default: + puts("\nIncorrect response.\n"); + break; + } + } + + for (state = STATE_STABLE - 1; state < STATE_UNACCEPTABLE; state++) { + printf("\nState: %-14s ", states[state]); + for (scanmode = DISCOVERY_MODE - 1; + scanmode < TRACKING_MODE; scanmode++) { + printf("%s = %6d ms\t", + scanmodes[scanmode], + (int)values[state][scanmode]); + } + } + printf("\n"); +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra command + * + * @param pcontrol control struct to return + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +getControl(HostCmd_DS_CMD_ROAMAGENT_CONTROL *pcontrol) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_CONTROL *roamcontrolcmd = NULL; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + cmd_len = S_DS_GEN + sizeof(roamcontrolcmd->action); + hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_CONTROL); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + roamcontrolcmd = (HostCmd_DS_CMD_ROAMAGENT_CONTROL *)pos; + + roamcontrolcmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roamcontrol]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + memcpy((void *)pcontrol, + (void *)roamcontrolcmd, + sizeof(HostCmd_DS_CMD_ROAMAGENT_CONTROL)); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param control roma control indicator value + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetEventBitmap(int argc, char *argv[]) +{ + t_u8 hostevent; + HostCmd_DS_CMD_ROAMAGENT_CONTROL roamcontrolcmd; + + if (getControl(&roamcontrolcmd) != MLAN_STATUS_SUCCESS) { + return MLAN_STATUS_FAILURE; + } + + hostevent = roamcontrolcmd.HostEvent; + if (!(hostevent | 0)) { + puts("\nHost events are disabled.\n"); + return MLAN_STATUS_SUCCESS; + } + printf("\nHost events enabled: "); + if (hostevent & HOST_EVENT_NBOR_ENABLE) + printf("neighbor "); + + if (hostevent & HOST_EVENT_ROAM_ENABLE) + printf("roam "); + + if (hostevent & HOST_EVENT_STATE_ENABLE) + printf("state"); + + printf("\n"); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Issue getra command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param control roma control indicator value + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetControl(int argc, char *argv[]) +{ + t_u8 control; + HostCmd_DS_CMD_ROAMAGENT_CONTROL roamcontrolcmd; + + if (getControl(&roamcontrolcmd) != MLAN_STATUS_SUCCESS) { + return MLAN_STATUS_FAILURE; + } + + control = roamcontrolcmd.Control; + printf("\nGlobal roaming agent state: "); + if (control & ROAM_CONTROL_ENABLE) { + printf("enabled, "); + if (control & ROAM_CONTROL_SUSPEND) + printf("suspend.\n"); + else + printf("resume.\n"); + } else + printf("disabled.\n"); + + printf("Crossband: "); + if (control & CROSSBAND_ENABLE) + printf("enabled.\n"); + else + printf("disabled.\n"); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Internal funtion to issue getra backoff + * + * @param roambackoffcmd Backoff command structure + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +getBackOff(HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmdParam) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmd; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + roambackoffcmd = (HostCmd_DS_CMD_ROAMAGENT_BACKOFF *)pos; + cmd_len = S_DS_GEN + sizeof(roambackoffcmd->action); + roambackoffcmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_BACKOFF); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roambackoff]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + /* + * ENDIANNESS for Response + */ + roambackoffcmd->Scans = le16_to_cpu(roambackoffcmd->Scans); + roambackoffcmd->Period = le32_to_cpu(roambackoffcmd->Period); + + memcpy((void *)roambackoffcmdParam, (void *)roambackoffcmd, + sizeof(HostCmd_DS_CMD_ROAMAGENT_BACKOFF)); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue getra backoff command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param control roma control indicator value + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamGetBackOff(int argc, char *argv[]) +{ + HostCmd_DS_CMD_ROAMAGENT_BACKOFF backoffcmd; + + if (getBackOff(&backoffcmd) != MLAN_STATUS_SUCCESS) { + return MLAN_STATUS_FAILURE; + } + + puts(""); + printf("----------------------------------------------------\n"); + printf(" Scanning Backoff Parameters \n"); + printf("----------------------------------------------------\n"); + printf(" Backoff period (max time in tracking) = %d ms\n", + backoffcmd.Period); + printf(" # of discovery scans before backoff = %d\n", + backoffcmd.Scans); + puts(""); + + if (backoffcmd.Scans) { + printf(" - Discovery backoff mode is enabled.\n" + " After %d discovery scans without a change in the number\n" + " of neighbors, the RA will only track the existing\n" + " neighbors until the backoff period expires.\n", + backoffcmd.Scans); + } else { + printf(" - Discovery backoff mode is disabled.\n" + " The RA will only move to tracking mode if a minimum\n" + " number of good neighbors have been found. See the\n" + " getra neighbor command for the current min setting.\n"); + } + puts(""); + + return MLAN_STATUS_SUCCESS; +} + +static int +printGetNeighborDeprecation(int argc, char *argv[]) +{ + printf("\nInfo: getra neighbor replaced with:\n" + " - getra nlist (display neighbor list)\n" + " - getra nparams (display neighbor assessment params)\n\n"); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Get the Roaming agent configuration parameters from FW. + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_get_ra_config(int argc, char *argv[]) +{ + if (argc == 3) { + return roamGetControl(argc, argv); + } + + sub_cmd_exec_t subCmds[] = { + {"rssi", 1, 1, roamGetRssiStatsThreshold}, + {"prebcnmiss", 1, 1, roamGetPreBeaconMiss}, + {"failcnt", 1, 1, roamGetFailureCount}, + {"backoff", 1, 1, roamGetBackOff}, + {"neighbor", 2, 0, printGetNeighborDeprecation}, + {"nlist", 2, 1, roamGetNborList}, + {"nparams", 2, 1, roamGetNborParams}, + {"scanperiod", 1, 1, roamGetScanPeriod}, + {"metrics", 1, 1, roamGetMetrics}, + {"event", 1, 1, roamGetEventBitmap} + }; + + return process_sub_cmd(subCmds, NELEMENTS(subCmds), argc, argv); +} + +/** + * @brief Issue setra bcnmiss command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetPreBeaconLoss(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int bcnmiss; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold; + MrvlIEtypes_BeaconsMissed_t *beaconmiss; + + if (argc != 1) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + bcnmiss = atoi(argv[0]); + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos; + cmd_len = sizeof(HostCmd_DS_GEN) + sizeof(statsthreshold->action) + + sizeof(statsthreshold->State) + + sizeof(statsthreshold->Profile) + + sizeof(MrvlIEtypes_BeaconsMissed_t); + + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos; + statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + statsthreshold->State = STATE_HARDROAM; + + beaconmiss = (MrvlIEtypes_BeaconsMissed_t *)&statsthreshold->TlvBuffer; + beaconmiss->beacon_missed = bcnmiss; + beaconmiss->header.type = cpu_to_le16(TLV_TYPE_PRE_BEACON_LOST); + beaconmiss->header.len = + cpu_to_le16(sizeof(MrvlIEtypes_BeaconsMissed_t) - + sizeof(MrvlIEtypesHeader_t)); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[setra]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + roamGetPreBeaconMiss(argc, argv); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue setra failurecnt command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetFailureCount(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int failCount, failTimeThresh; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold; + MrvlIEtypes_FailureCount_t *failcnt; + + if (argc != 2) { + puts("\n2 arguments required: FailCnt, FailTimeThresh(ms)\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + failCount = atoi(argv[0]); + failTimeThresh = atoi(argv[1]); + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos; + + cmd_len = (S_DS_GEN + + sizeof(statsthreshold->action) + + sizeof(statsthreshold->State) + + sizeof(statsthreshold->Profile) + + sizeof(MrvlIEtypes_FailureCount_t)); + + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + statsthreshold->State = STATE_HARDROAM; + + failcnt = (MrvlIEtypes_FailureCount_t *)&statsthreshold->TlvBuffer; + failcnt->fail_value = failCount; + failcnt->fail_min_thresh_time_millisecs = cpu_to_le16(failTimeThresh); + failcnt->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT); + failcnt->header.len = cpu_to_le16(sizeof(MrvlIEtypes_FailureCount_t) + - sizeof(MrvlIEtypesHeader_t)); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[setra]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + roamGetFailureCount(argc, argv); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue setra rssi/snr command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param type RSSI/SNR threshold type + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetStatsThreshold(int argc, char *argv[], int type) +{ + int ret = MLAN_STATUS_SUCCESS; + int i, state = 0, low = 0, high = 0, lowval, highval; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold; + MrvlIEtypes_BeaconHighRssiThreshold_t *bcnhighrssi; + MrvlIEtypes_BeaconLowRssiThreshold_t *bcnlowrssi; + MrvlIEtypes_BeaconHighSnrThreshold_t *bcnhighsnr; + MrvlIEtypes_BeaconLowSnrThreshold_t *bcnlowsnr; + + if (argv[0] == NULL) { + puts("\nInsufficient arguments.. \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (argv[0] && strncmp(argv[0], "stable", strlen("stable")) == 0) { + state = STATE_STABLE; + /* degrad[ing] */ + } else if (argv[0] && strncmp(argv[0], "degrad", strlen("degrad")) == 0) { + state = STATE_DEGRADING; + /* unaccep[table] */ + } else if (argv[0] + && strncmp(argv[0], "unaccep", strlen("unaccep")) == 0) { + state = STATE_UNACCEPTABLE; + } else { + puts("\nUnknown state. Use stable/degrading/unacceptable\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + if (argc != 3 && argc != 5) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + if (argv[1] && strncmp(argv[1], "low", strlen("low")) == 0) { + low = 1; + lowval = atoi(argv[2]); + /* TODO validation check on lowval */ + } + if (argv[1 + (2 * low)] + && strncmp(argv[1 + (2 * low)], "high", strlen("high")) == 0) { + high = 1; + highval = atoi(argv[2 + (2 * low)]); + /* TODO validation check on highval */ + } + /* check if low is specified after high */ + if ((low == 0) && (argc == 5)) { + if (argv[1 + (2 * high)] + && strncmp(argv[1 + (2 * high)], "low", strlen("low")) == 0) { + low = 1; + lowval = atoi(argv[2 + 2 * (high)]); + /* TODO validation check on lowval */ + } + } + + if (!low && !high) { + puts("\nIncorrect argument. Use low /high \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos; + cmd_len = + (S_DS_GEN + + sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD) + - sizeof(statsthreshold->TlvBuffer)); + if (type == RSSI_THRESHOLD) { + if (high) { + cmd_len += + sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t); + } + if (low) { + cmd_len += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t); + } + } else { + if (high) { + cmd_len += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t); + } + if (low) { + cmd_len += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t); + } + } + + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + statsthreshold->State = state; + + /* + * TLV buffer start pointer initialization + */ + i = 0; + if (type == RSSI_THRESHOLD) { + if (high) { + bcnhighrssi = (MrvlIEtypes_BeaconHighRssiThreshold_t *) + (((t_u8 *)&statsthreshold->TlvBuffer) + i); + bcnhighrssi->Header.type = TLV_TYPE_RSSI_HIGH; + bcnhighrssi->Header.len = + (sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t) + - sizeof(MrvlIEtypesHeader_t)); + bcnhighrssi->Value = highval; + i += sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t); + /* + * ENDIANNESS + */ + bcnhighrssi->Header.type = + cpu_to_le16(bcnhighrssi->Header.type); + bcnhighrssi->Header.len = + cpu_to_le16(bcnhighrssi->Header.len); + } + + if (low) { + bcnlowrssi = (MrvlIEtypes_BeaconLowRssiThreshold_t *) + (((t_u8 *)&statsthreshold->TlvBuffer) + i); + bcnlowrssi->Header.type = TLV_TYPE_RSSI_LOW; + bcnlowrssi->Header.len = + (sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t) + - sizeof(MrvlIEtypesHeader_t)); + bcnlowrssi->Value = lowval; + i += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t); + /* + * ENDIANNESS + */ + bcnlowrssi->Header.type = + cpu_to_le16(bcnlowrssi->Header.type); + bcnlowrssi->Header.len = + cpu_to_le16(bcnlowrssi->Header.len); + } + } else { + if (high) { + bcnhighsnr = (MrvlIEtypes_BeaconHighSnrThreshold_t *) + (((t_u8 *)&statsthreshold->TlvBuffer) + i); + bcnhighsnr->Header.type = TLV_TYPE_SNR_HIGH; + bcnhighsnr->Header.len = + (sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t) + - sizeof(MrvlIEtypesHeader_t)); + bcnhighsnr->Value = highval; + i += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t); + /* + * ENDIANNESS + */ + bcnhighsnr->Header.type = + cpu_to_le16(bcnhighsnr->Header.type); + bcnhighsnr->Header.len = + cpu_to_le16(bcnhighsnr->Header.len); + } + if (low) { + bcnlowsnr = (MrvlIEtypes_BeaconLowSnrThreshold_t *) + (((t_u8 *)&statsthreshold->TlvBuffer) + i); + bcnlowsnr->Header.type = TLV_TYPE_SNR_LOW; + bcnlowsnr->Header.len = + (sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t) + - sizeof(MrvlIEtypesHeader_t)); + bcnlowsnr->Value = lowval; + i += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t); + /* + * ENDIANNESS + */ + bcnlowsnr->Header.type = + cpu_to_le16(bcnlowsnr->Header.type); + bcnlowsnr->Header.len = + cpu_to_le16(bcnlowsnr->Header.len); + } + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[setra]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue setra rssi command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetRssiStatsThreshold(int argc, char *argv[]) +{ + if (roamSetStatsThreshold(argc, argv, RSSI_THRESHOLD) + == MLAN_STATUS_SUCCESS) { + roamGetStatsThreshold(0, argv, RSSI_THRESHOLD); + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Issue setra scanperiod command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetScanPeriod(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int scanmode = 0, period = 0, state = 0; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD *scanPeriodInfo; + + if (argv[0] == NULL) { + puts("\nInsufficient arguments.. \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* scanperiod */ + if (argc != 3) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (argv[0] && strncmp(argv[0], "stable", strlen("stable")) == 0) { + state = STATE_STABLE; + /* degrad[ing] */ + } else if (argv[0] && strncmp(argv[0], "degrad", strlen("degrad")) == 0) { + state = STATE_DEGRADING; + /* unaccep[table] */ + } else if (argv[0] + && strncmp(argv[0], "unaccep", strlen("unaccep")) == 0) { + state = STATE_UNACCEPTABLE; + } else { + puts("\nUnknown state. Use stable/degrading/unacceptable\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (argv[1] && strncmp(argv[1], "disc", strlen("disc")) == 0) { + scanmode = DISCOVERY_MODE; + /* track[ing] */ + } else if (argv[1] && strncmp(argv[1], "track", strlen("track")) == 0) { + scanmode = TRACKING_MODE; + } else { + puts("\nUnknown scamode. Use discovery/ tracking\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + period = atoi(argv[2]); + /* TODO validation check on period */ + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + scanPeriodInfo = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD *)pos; + cmd_len = + S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD); + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_SCAN_PERIOD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + scanPeriodInfo->action = HostCmd_ACT_GEN_SET; + scanPeriodInfo->scanPeriod.Header.type = TLV_TYPE_NEIGHBOR_SCANPERIOD; + scanPeriodInfo->scanPeriod.Header.len = + sizeof(MrvlIEtypes_NeighborScanPeriod_t) - + sizeof(MrvlIEtypesHeader_t); + scanPeriodInfo->scanPeriod.SearchMode = scanmode; + scanPeriodInfo->scanPeriod.State = state; + scanPeriodInfo->scanPeriod.ScanPeriod = period; + + /* + * ENDIANNESS + */ + scanPeriodInfo->action = cpu_to_le16(scanPeriodInfo->action); + scanPeriodInfo->scanPeriod.Header.type = cpu_to_le16 + (scanPeriodInfo->scanPeriod.Header.type); + scanPeriodInfo->scanPeriod.Header.len = cpu_to_le16 + (scanPeriodInfo->scanPeriod.Header.len); + scanPeriodInfo->scanPeriod.SearchMode = cpu_to_le16 + (scanPeriodInfo->scanPeriod.SearchMode); + scanPeriodInfo->scanPeriod.State = cpu_to_le16 + (scanPeriodInfo->scanPeriod.State); + scanPeriodInfo->scanPeriod.ScanPeriod = cpu_to_le32 + (scanPeriodInfo->scanPeriod.ScanPeriod); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[neighborlist maintain]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Check it string contains digits + * @param str string to check for digits + * @return same as isdigit(char) + */ +static inline int +isdigitstr(char *str) +{ + unsigned int i = 0; + for (i = 0; i < strlen(str); i++) { + if (!isdigit((str)[i])) + return 0; + } + return 1; +} + +/** + * @brief Process sub command + * + * @param valid_cmds valid commands array + * @param count number of valid commands + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param param argc parameter counter + * @param value values to update back + * + * @return command index--success, otherwise--fail + */ +static int +process_subcmd(char *valid_cmds[], int count, int argc, char *argv[], + int *param, int *value) +{ + int ret = 0; + int j = *param; + int k; + while (1) { + for (k = 0; k < count; k++) + if (argv[j] && + !strncmp(valid_cmds[k], argv[j], + strlen(valid_cmds[k]))) + break; + if (k >= count) { + break; + } else { + /* special case */ + if (!strncmp + (valid_cmds[k], "perperiod", strlen("perperiod")) || + !strncmp(valid_cmds[k], "ferperiod", + strlen("ferperiod"))) { + *param = j; + return ret | 1 << k; + } + if (!argv[j + 1] || !isdigitstr(argv[j + 1])) + return -1; + value[k] = atoi(argv[j + 1]); + j = j + 2; + ret |= (1 << k); + } + + if (j >= argc) { + break; + } + } + + if (*param == j) { + return -1; + } + + *param = j; + return ret; +} + +static int +printSetNeighborDeprecation(int argc, char *argv[]) +{ + printf("\nInfo: setra neighbor replaced with:\n" + " - setra nparams (config neighbor assessment params)\n\n"); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Issue setra neighbor command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetNborParams(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + int trackcount = 0, i = 0, j = 0; + int blist[2] = { 0, 0 }; /* blacklist short and long: 0-short 1-long */ + int qualoffset[1] = { 0 }; /* rssi */ + int stalecount = ~0; + int staleperiod = ~0; + signed char temp; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + char *valid_cmds[] = { "trackcount", "qualoffset", "blacklistdur", + "stalecount", "staleperiod", "roamthresh" + }; + + /** blacklistdur sub commands */ + char *valid_blcmds[] = { "short", "long" }; + + /** qualoffset sub commands */ + char *valid_bfcmds[] = { "rssi" }; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *pNborAssessment; + + if (argv[0] == NULL) { + puts("\nUnknown setra nparams subcmd. Valid subcmds:"); + for (i = 0; i < NELEMENTS(valid_cmds); i++) { + printf(" - %s\n", valid_cmds[i]); + } + printf("\n"); + + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (argc < 2 || argc > 18) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + pNborAssessment = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *)pos; + cmd_len = + S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT); + + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Get parameters unspecified on command line */ + if (getNborAssessment(pNborAssessment) != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + + while (argc - j) { + for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); i++) { + if (!strncmp + (valid_cmds[i], argv[j], strlen(valid_cmds[i]))) + break; + } + + if ((unsigned int)i >= NELEMENTS(valid_cmds)) { + printf("\nInvalid argument to \"%s\"\n\n", argv[0]); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + switch (i) { + + case 0: + /** trackcount */ + trackcount = atoi(argv[j + 1]); + pNborAssessment->QualifyingNumNeighbor = trackcount; + j = j + 2; + break; + + case 1: + /** qualoffset */ + j++; + ret = process_subcmd(valid_bfcmds, + NELEMENTS(valid_bfcmds), argc, + argv, &j, qualoffset); + if (ret == -1) { + printf("\nInvalid argument to \"%s\"\n\n", + argv[j - 1]); + ret = ret; + goto done; + } + pNborAssessment->ConfQualSignalStrength = qualoffset[0]; + break; + + case 2: + /** blacklistdur */ + j++; + ret = process_subcmd(valid_blcmds, + NELEMENTS(valid_blcmds), argc, + argv, &j, blist); + if (ret == -1) { + printf("\nInvalid argument to \"%s\"\n\n", + argv[j - 1]); + ret = ret; + goto done; + } else { + if (ret & 0x01) { + pNborAssessment->ShortBlacklistPeriod = + blist[0]; + } + if (ret & 0x02) { + pNborAssessment->LongBlacklistPeriod = + blist[1]; + } + } + break; + + case 3: + /** stalecount */ + stalecount = atoi(argv[j + 1]); + pNborAssessment->StaleCount = stalecount; + j = j + 2; + break; + + case 4: + /** staleperiod */ + staleperiod = atoi(argv[j + 1]); + pNborAssessment->StalePeriod = staleperiod; + j = j + 2; + break; + + case 5: + /** roamthresh */ + j++; + temp = 0; + for (i = 0; j + i < argc; i++) { + if (isdigit(*argv[j + i]) || + (*argv[j + i] == '-')) { + temp++; + } else { + break; + } + } + + if ((temp % 3 != 0) || (temp > 12)) { + puts(""); + printf("Error: %d numeric arguments detected for roamthresh.\n" " Roam threhold values must be specified in\n" " multiples of 3 (low, high, diff triplets) up\n" " to a maximum of 4 sets (12 numbers max).\n", temp); + puts(""); + + ret = MLAN_STATUS_FAILURE; + goto done; + } + + for (i = 0; (i < 12); i++) { + if ((j >= argc) || + (!isdigit(*argv[j]) && *argv[j] != '-')) { + temp = 0; + } else { + temp = atoi(argv[j]); + j++; + } + + switch (i % 3) { + case 0: + pNborAssessment->RoamThresh[i / + 3]. + RssiHighLevel = temp; + break; + + case 1: + pNborAssessment->RoamThresh[i / + 3]. + RssiLowLevel = temp; + break; + + case 2: + pNborAssessment->RoamThresh[i / + 3]. + RssiNborDiff = temp; + break; + } + } + break; + } + } + + pNborAssessment->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + + /* Both stalecount, staleperiod can not be zero */ + if ((pNborAssessment->StaleCount == 0) && + (pNborAssessment->StalePeriod == 0)) { + + puts("\nstalecount and staleperiod both can not be zero\n"); + ret = (MLAN_STATUS_FAILURE); + goto done; + } + + /* + * ENDIANNESS + */ + pNborAssessment->QualifyingNumNeighbor = + cpu_to_le16(pNborAssessment->QualifyingNumNeighbor); + pNborAssessment->ShortBlacklistPeriod = + cpu_to_le32(pNborAssessment->ShortBlacklistPeriod); + pNborAssessment->LongBlacklistPeriod = + cpu_to_le32(pNborAssessment->LongBlacklistPeriod); + pNborAssessment->StaleCount = cpu_to_le16(pNborAssessment->StaleCount); + pNborAssessment->StalePeriod = + cpu_to_le16(pNborAssessment->StalePeriod); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roam neighbor assessment]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printNeighborAssessmentConfig(); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue setra metrics command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetMetrics(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *metricscmd; + + int perlist[3] = { 0, 0, 0 }; /* 0=inactivity, + 1=perthreshold, + 2=packetthreshold */ + int ferlist[3] = { 0, 0, 0 }; /* 0=inactivity, + 1=ferthreshold, + 2=framethreshold */ + int perstate[3] = { 0, 0, 0 }; /* 0=stable, 1=degrading, 2=unacceptable */ + int ferstate[3] = { 0, 0, 0 }; /* 0=stable, 1=degrading, 2=unacceptable */ + int datalist[2] = { 0, 0 }; /* 0=inactivity, 1=datathreshold */ + char *valid_cmds[] = { "Beacon", "Data", "PER", "FER" }; + + /** PER sub commands */ + char *valid_percmds[] = { "inactivity", "perthreshold", + "packetthreshold", "perperiod" + }; + + char *valid_fercmds[] = { "inactivity", "ferthreshold", + "framethreshold", "ferperiod" + }; + + /** PER period states */ + char *per_states[] = { "stable", "degrading", "unacceptable" }; + + /** Data sub commands */ + char *valid_datacmds[] = { "inactivity", "datathreshold" }; + + int i = 0, j = 0; + + if (argv[0] == NULL) { + puts("\nInsufficient arguments.. \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (argc < 1 || argc > 38) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = + S_DS_GEN + + sizeof(HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD); + + hostcmd->command = + cpu_to_le16(HostCmd_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + metricscmd = (HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *)pos; + metricscmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + + /* clear [ Beacon/Data/PER ] */ + if (!strncmp("clear", argv[j], strlen("clear"))) { + if (argc == 1) { + puts("\nInvalid number of argument"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + while (1) { + j++; + for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); + i++) { + if (!strncmp + (valid_cmds[i], argv[j], + strlen(valid_cmds[i]))) + break; + } + if ((unsigned int)i >= NELEMENTS(valid_cmds)) { + printf("\nInvalid argument \"%s\"\n\n", + argv[j]); + ret = MLAN_STATUS_FAILURE; + goto done; + } else { + metricscmd->Metrics |= BIT(i); + } + + if (j >= (argc - 1)) { + break; + } + } + metricscmd->action = HostCmd_ACT_GEN_REMOVE; + } else { /* set [ Beacon/Data/PER ] */ + + while (argc - j) { + for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); + i++) { + if (!strncmp + (valid_cmds[i], argv[j], + strlen(valid_cmds[i]))) + break; + } + if ((unsigned int)i >= NELEMENTS(valid_cmds)) { + printf("\nInvalid argument to \"%s\"\n\n", + argv[j]); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + switch (i) { + case 0: + /** Beacon */ + j++; + metricscmd->Metrics |= 0x01; + break; + + case 1: + /** Data*/ + j++; + ret = process_subcmd(valid_datacmds, + NELEMENTS(valid_datacmds), + argc, argv, &j, datalist); + if (ret > 0) { + if (ret & 0x01) { + metricscmd-> + InactivityPeriodThreshold_ms + = datalist[0]; + } + if (ret & 0x02) { + metricscmd->UiRxPktThreshold = + datalist[1]; + } + } + metricscmd->Metrics |= 0x02; + break; + + case 2: + /** PER */ + j++; + ret = process_subcmd(valid_percmds, + NELEMENTS(valid_percmds), + argc, argv, &j, perlist); + if (ret > 0) { + if (ret & 0x01) { + metricscmd-> + InactivityPeriodThreshold_ms + = perlist[0]; + } + if (ret & 0x02) { + metricscmd-> + UcPerThresholdValue = + perlist[1]; + } + if (ret & 0x04) { + metricscmd->UiPerPktThreshold = + perlist[2]; + } + if (ret & 0x08) { + j++; + ret = process_subcmd(per_states, + NELEMENTS + (per_states), + argc, argv, + &j, + perstate); + if (ret & 0x01) { + metricscmd-> + StablePERPeriod_ms + = perstate[0]; + } + if (ret & 0x02) { + metricscmd-> + DegradingPERPeriod_ms + = perstate[1]; + } + if (ret & 0x04) { + metricscmd-> + UnacceptablePERPeriod_ms + = perstate[2]; + } + if (j < argc) { + ret = process_subcmd + (valid_percmds, + NELEMENTS + (valid_percmds), + argc, argv, &j, + perlist); + if (ret > 0) { + if (ret & 0x01) { + metricscmd-> + InactivityPeriodThreshold_ms + = + perlist + [0]; + } + if (ret & 0x02) { + metricscmd-> + UcPerThresholdValue + = + perlist + [1]; + } + if (ret & 0x04) { + metricscmd-> + UiPerPktThreshold + = + perlist + [2]; + } + } + } + } + } + metricscmd->Metrics |= 0x04; + break; + + case 3: + /** FER */ + j++; + ret = process_subcmd(valid_fercmds, + NELEMENTS(valid_fercmds), + argc, argv, &j, ferlist); + if (ret > 0) { + if (ret & 0x01) { + metricscmd-> + InactivityPeriodThreshold_ms + = ferlist[0]; + } + if (ret & 0x02) { + metricscmd-> + UcFerThresholdValue = + ferlist[1]; + } + if (ret & 0x04) { + metricscmd->UiFerPktThreshold = + ferlist[2]; + } + if (ret & 0x08) { + j++; + ret = process_subcmd(per_states, + NELEMENTS + (per_states), + argc, argv, + &j, + ferstate); + if (ret & 0x01) { + metricscmd-> + StableFERPeriod_ms + = ferstate[0]; + } + if (ret & 0x02) { + metricscmd-> + DegradingFERPeriod_ms + = ferstate[1]; + } + if (ret & 0x04) { + metricscmd-> + UnacceptableFERPeriod_ms + = ferstate[2]; + } + if (j < argc) { + ret = process_subcmd + (valid_fercmds, + NELEMENTS + (valid_fercmds), + argc, argv, &j, + ferlist); + if (ret > 0) { + if (ret & 0x01) { + metricscmd-> + InactivityPeriodThreshold_ms + = + ferlist + [0]; + } + if (ret & 0x02) { + metricscmd-> + UcFerThresholdValue + = + ferlist + [1]; + } + if (ret & 0x04) { + metricscmd-> + UiFerPktThreshold + = + ferlist + [2]; + } + } + } + } + } + metricscmd->Metrics |= 0x08; + break; + } + metricscmd->action = HostCmd_ACT_GEN_SET; + } + } + + /* + * ENDIANNESS + */ + metricscmd->action = cpu_to_le16(metricscmd->action); + metricscmd->Metrics = cpu_to_le16(metricscmd->Metrics); + metricscmd->UiPerPktThreshold = + cpu_to_le32(metricscmd->UiPerPktThreshold); + metricscmd->StablePERPeriod_ms = + cpu_to_le32(metricscmd->StablePERPeriod_ms); + metricscmd->DegradingPERPeriod_ms = + cpu_to_le32(metricscmd->DegradingPERPeriod_ms); + metricscmd->UnacceptablePERPeriod_ms = + cpu_to_le32(metricscmd->UnacceptablePERPeriod_ms); + metricscmd->InactivityPeriodThreshold_ms = + cpu_to_le32(metricscmd->InactivityPeriodThreshold_ms); + metricscmd->UiRxPktThreshold = + cpu_to_le32(metricscmd->UiRxPktThreshold); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[neighborlist maintain]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Process maintenance of Neighbor list + * + * @param argc # arguments + * @param argv A pointer to arguments array + * + */ +static int +roamSetNborMaintenance(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + char *valid_cmds[] = { "blacklist", "clear" }; + int i = 0, j = 0, k = 0; + unsigned int mac[ETH_ALEN]; + + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE *pNborMaintainance; + + if (argv[0] == NULL) { + puts("\nInsufficient arguments.. \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + if (argc != 2) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); i++) + if (!strncmp(valid_cmds[i], argv[j], strlen(valid_cmds[i]))) + break; + if ((unsigned int)i >= NELEMENTS(valid_cmds)) { + printf("\nInvalid argument \"%s\"\n\n", argv[0]); + ret = MLAN_STATUS_FAILURE; + goto done; + } + switch (i) { + case 0: + /** blacklist */ + j++; + sscanf(argv[j], "%2x:%2x:%2x:%2x:%2x:%2x", + mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5); + for (k = 0; k < ETH_ALEN; k++) { + if (*(mac + k) != 0xFF) { + break; + } + } + + if (k == ETH_ALEN) { + puts("\nBlacklisting a Broadcast address is not allowed"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + break; + + case 1: + /** clear */ + j++; + if (!strncmp("all", argv[j], strlen("all"))) { + for (k = 0; k < ETH_ALEN; k++) { + *(mac + k) = 0xFF; + } + } else { + sscanf(argv[j], "%2x:%2x:%2x:%2x:%2x:%2x", + mac, mac + 1, mac + 2, mac + 3, mac + 4, + mac + 5); + } + break; + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + pNborMaintainance + = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE *)pos; + + cmd_len = S_DS_GEN + + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE); + + hostcmd->command + = cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + pNborMaintainance->action = ((i == 0) ? HostCmd_ACT_ADD_TO_BLACKLIST : + HostCmd_ACT_REMOVE_FROM_BLACKLIST); + pNborMaintainance->action = cpu_to_le16(pNborMaintainance->action); + for (k = 0; k < ETH_ALEN; k++) { + pNborMaintainance->BSSID[k] = *(mac + k); + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[neighborlist maintain]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue setra backoff command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetBackOff(int argc, char *argv[]) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + int spflag[2] = { 0, 0 }; /*scan,priod */ + t_u16 minscan; + t_u32 bperiod; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmd; + int i; + + if (argv[0] == NULL) { + puts("\nInsufficient arguments.. \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + /* BackOff */ + if ((argc != 2) && (argc != 4)) { + puts("\nIncorrect number of arguments.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + for (i = 0; i < 4; i++) { + if (argv[i + 0] && + strncmp(argv[i + 0], "scans", strlen("scans")) == 0) { + minscan = atoi(argv[i + 1]); + i++; + spflag[0] = 1; + /* TODO validation check on minscan */ + } + if (argv[i + 0] && + strncmp(argv[i + 0], "period", strlen("period")) == 0) { + bperiod = atoi(argv[i + 1]); + i++; + spflag[1] = 1; + /* TODO validation check on bperiod */ + } + } + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + roambackoffcmd = (HostCmd_DS_CMD_ROAMAGENT_BACKOFF *)pos; + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_BACKOFF); + hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_BACKOFF); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + switch (spflag[0] + spflag[1]) { + case 0: + /* error */ + puts("\nIncorrect arguments for setra backoff command.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + + case 1: + /* get missing parameter */ + if (getBackOff(roambackoffcmd) != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + if (spflag[0] == 0) { + minscan = roambackoffcmd->Scans; + } else { + bperiod = roambackoffcmd->Period; + } + break; + + case 2: + default: + break; + } + + roambackoffcmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + roambackoffcmd->Scans = cpu_to_le16(minscan); + roambackoffcmd->Period = cpu_to_le16(bperiod); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roambackoff]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue setra enable/disable/resume/suspend command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param set/reset set/reset flag + * @param value roam control/ host event bitmap value + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetControl(int argc, char *argv[], int setreset, t_u8 value) +{ + int ret = MLAN_STATUS_SUCCESS; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd; + HostCmd_DS_CMD_ROAMAGENT_CONTROL *roamcontrolcmd; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + ret = ENOMEM; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = ENOMEM; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_CONTROL); + + hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_CONTROL); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + roamcontrolcmd = (HostCmd_DS_CMD_ROAMAGENT_CONTROL *)pos; + + /* get current value */ + if (getControl(roamcontrolcmd) != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + + roamcontrolcmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + switch (setreset) { + case 0: + roamcontrolcmd->Control &= value; + break; + case 1: + roamcontrolcmd->Control |= value; + break; + case 2: + roamcontrolcmd->HostEvent &= value; + break; + case 3: + roamcontrolcmd->HostEvent |= value; + break; + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[roamcontrol]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + if (le16_to_cpu(hostcmd->result)) { + printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } else { + printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n", + le16_to_cpu(hostcmd->command), + le16_to_cpu(hostcmd->result)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue setra enable command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetEnableControl(int argc, char *argv[]) +{ + return roamSetControl(argc, argv, 1, ROAM_CONTROL_ENABLE); +} + +/** + * @brief Issue setra disable command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetDisableControl(int argc, char *argv[]) +{ + return roamSetControl(argc, argv, 0, ROAM_CONTROL_DISABLE); +} + +/** + * @brief Issue setra suspend command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetSuspendControl(int argc, char *argv[]) +{ + return roamSetControl(argc, argv, 1, ROAM_CONTROL_SUSPEND); +} + +/** + * @brief Issue setra resume command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetResumeControl(int argc, char *argv[]) +{ + return roamSetControl(argc, argv, 0, ROAM_CONTROL_RESUME); +} + +/** + * @brief Issue setra crossband command + * + * @param argc number of arguments + * @param argv A pointer to argument array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetCrossband(int argc, char *argv[]) +{ + if (argc != 1) { + printf("Invalid Usage \n"); + return MLAN_STATUS_FAILURE; + } + if (strncmp(argv[0], "enable", strlen("enable")) == 0) { + return roamSetControl(argc, argv, 1, CROSSBAND_ENABLE); + } else if (strncmp(argv[0], "disable", strlen("disable")) == 0) { + return roamSetControl(argc, argv, 0, CROSSBAND_DISABLE); + } + + printf("Invalid Usage \n"); + return MLAN_STATUS_FAILURE; +} + +/** + * @brief Issue setra event command + * + * @param argc number of arguments + * @param argv A pointer to argument array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +roamSetEventBitmap(int argc, char *argv[]) +{ + int i, enableFlag, found = 0; + t_u8 value; + if (argc > 4 || argc < 2) { + printf("Invalid Usage \n"); + return MLAN_STATUS_FAILURE; + } + if (strncmp(argv[0], "enable", strlen("enable")) == 0) { + enableFlag = 3; + value = HOST_EVENT_NBOR_DISABLE & HOST_EVENT_ROAM_DISABLE + & HOST_EVENT_STATE_DISABLE; + } else if (strncmp(argv[0], "disable", strlen("disable")) == 0) { + enableFlag = 2; + value = HOST_EVENT_NBOR_ENABLE | HOST_EVENT_ROAM_ENABLE + | HOST_EVENT_STATE_ENABLE; + } else { + printf("Invalid parameter %s \n", argv[0]); + return MLAN_STATUS_FAILURE; + } + + for (i = 1; i < argc; i++) { + found = 0; + if (strncmp(argv[i], "neighbor", strlen("neighbor")) == 0) { + found = 1; + if (enableFlag == 3) { + value |= HOST_EVENT_NBOR_ENABLE; + } else { + value &= HOST_EVENT_NBOR_DISABLE; + } + } + if (strncmp(argv[i], "roam", strlen("roam")) == 0) { + found = 1; + if (enableFlag == 3) { + value |= HOST_EVENT_ROAM_ENABLE; + } else { + value &= HOST_EVENT_ROAM_DISABLE; + } + } + if (strncmp(argv[i], "state", strlen("state")) == 0) { + found = 1; + if (enableFlag == 3) { + value |= HOST_EVENT_STATE_ENABLE; + } else { + value &= HOST_EVENT_STATE_DISABLE; + } + } + if (found == 0) { + printf("Invalid parameter %s \n", argv[i]); + return MLAN_STATUS_FAILURE; + } + } + + return roamSetControl(argc, argv, enableFlag, value); +} + +/** + * @brief Set the Roaming agent configuration parameters to FW. + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_set_ra_config(int argc, char *argv[]) +{ + sub_cmd_exec_t subCmds[] = { + {"rssi", 2, 1, roamSetRssiStatsThreshold}, + {"prebcnmiss", 2, 1, roamSetPreBeaconLoss}, + {"failcnt", 2, 1, roamSetFailureCount}, + {"neighbor", 2, 0, printSetNeighborDeprecation}, + {"nparams", 2, 1, roamSetNborParams}, + {"maintain", 2, 1, roamSetNborMaintenance}, + {"scanperiod", 2, 1, roamSetScanPeriod}, + {"backoff", 2, 1, roamSetBackOff}, + {"enable", 2, 1, roamSetEnableControl}, + {"disable", 2, 1, roamSetDisableControl}, + {"suspend", 2, 1, roamSetSuspendControl}, + {"resume", 2, 1, roamSetResumeControl}, + {"metrics", 2, 1, roamSetMetrics}, + {"crossband", 2, 1, roamSetCrossband}, + {"event", 2, 1, roamSetEventBitmap} + }; + + return process_sub_cmd(subCmds, NELEMENTS(subCmds), argc, argv); +} diff --git a/mwifiex_8997/mapp/mlanutl/mlanroamagent.h b/mwifiex_8997/mapp/mlanutl/mlanroamagent.h new file mode 100755 index 0000000..c86f70f --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanroamagent.h @@ -0,0 +1,314 @@ +/** @file mlanroamagent.h + * + * @brief This files contains mlanutl roamagent command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#ifndef _MLANROAMAGENT_H_ +#define _MLANROAMAGENT_H_ + +/** Bit definitions */ +#ifndef BIT +#define BIT(x) (1UL << (x)) +#endif + +/* Define actionsd for HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE */ +/** Blacklist */ +#define HostCmd_ACT_ADD_TO_BLACKLIST 0x0001 +/** Flushing blacklisted entry */ +#define HostCmd_ACT_REMOVE_FROM_BLACKLIST 0x0002 + +/** Roaming scanmode: discovery */ +#define DISCOVERY_MODE 1 +/** Roaming scanmode: tracking */ +#define TRACKING_MODE 2 + +/** Threshold configuration: RSSI */ +#define RSSI_THRESHOLD 1 +/** Threshold configuration: SNR */ +#define SNR_THRESHOLD 2 + +#ifdef BIG_ENDIAN_SUPPORT +/** Bit values for Qualified Neighbor RSSI Entry */ +#define BIT_NEIGHFLAG_RSSI 0x80000000 +/** Bit values for Qualified Neighbor AGE Entry */ +#define BIT_NEIGHFLAG_AGE 0x40000000 +/** Bit values for Qualified Neighbor Blacklist Entry */ +#define BIT_NEIGHFLAG_BLACKLIST 0x20000000 +/** Bit values for Qualified Neighbor Admission Capacity */ +#define BIT_NEIGHFLAG_ADMISSION_CAP 0x10000000 +/** Bit values for Qualified Neighbor Uplink RSSI */ +#define BIT_NEIGHFLAG_UPLINK_RSSI 0x08000000 +#else +/** Bit values for Qualified Neighbor RSSI Entry */ +#define BIT_NEIGHFLAG_RSSI 0x01 +/** Bit values for Qualified Neighbor AGE Entry */ +#define BIT_NEIGHFLAG_AGE 0x02 +/** Bit values for Qualified Neighbor Blacklist Entry */ +#define BIT_NEIGHFLAG_BLACKLIST 0x04 +/** Bit values for Qualified Neighbor Admission Capacity */ +#define BIT_NEIGHFLAG_ADMISSION_CAP 0x08 +/** Bit values for Qualified Neighbor Uplink RSSI */ +#define BIT_NEIGHFLAG_UPLINK_RSSI 0x10 +#endif + +/** milliseconds time conversion data */ +typedef struct exactTime { + t_u16 hrs; /**< Number of hours */ + t_u16 mins; /**< Number of minutes */ + t_u16 secs; /**< Number of seconds */ + t_u16 msecs; /**< Number of milliseconds left */ +} ExactTime_t; + +/** ROAMAGENT HostEvent bitmasks */ +typedef enum { + HOST_EVENT_NBOR_DISABLE = 6, /* reset bit 0 */ + HOST_EVENT_NBOR_ENABLE = 1, /* set bit 0 */ + HOST_EVENT_ROAM_DISABLE = 5, /* reset bit 1 */ + HOST_EVENT_ROAM_ENABLE = 2, /* set bit 1 */ + HOST_EVENT_STATE_DISABLE = 3, /* reset bit 2 */ + HOST_EVENT_STATE_ENABLE = 4, /* reset bit 2 */ +} __ATTRIB_PACK__ HostEvent_e; + +/** ROAMAGENT_CONTROL command identifiers */ +typedef enum { + ROAM_CONTROL_DISABLE = 6, /* reset bit 0 */ + ROAM_CONTROL_ENABLE = 1, /* set bit 0 */ + ROAM_CONTROL_RESUME = 5, /* reset bit 1 */ + ROAM_CONTROL_SUSPEND = 2, /* set bit 1 */ + CROSSBAND_DISABLE = 3, /* reset bit 2 */ + CROSSBAND_ENABLE = 4 /* set bit 2 */ +} __ATTRIB_PACK__ RoamControl_e; + +/* + * Definitions of roaming state and other constants + */ +/** Enum Definitations: Roaming agent state */ +typedef enum { + STATE_DISCONNECTED, + STATE_STABLE, + STATE_DEGRADING, + STATE_UNACCEPTABLE, + STATE_HARDROAM, + STATE_LINKLOSS, + STATE_SOFTROAM, + STATE_SUSPEND, + STATE_CMD_SUSPEND, + STATE_ASYNCASSOC_SUSPEND +} RoamingAgentState; + +/** statistics threshold High RSSI */ +typedef struct { + /** Header */ + MrvlIEtypesHeader_t Header; + /** RSSI threshold (dBm) */ + t_u8 Value; + /** reporting frequency */ + t_u8 Frequency; +} __ATTRIB_PACK__ MrvlIEtypes_BeaconHighRssiThreshold_t, + MrvlIEtypes_BeaconLowRssiThreshold_t, + MrvlIEtypes_BeaconHighSnrThreshold_t, + MrvlIEtypes_BeaconLowSnrThreshold_t; + +/** HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD */ +typedef struct { + /** Action */ + t_u16 action; + /** roaming state */ + t_u8 State; + /** active/configured user */ + t_u8 Profile; + /** TLV buffer */ + t_u8 TlvBuffer[1]; + /* MrvlIEtypes_BeaconHighRssiThreshold_t BeaconHighRssiThreshold; + * MrvlIEtypes_BeaconLowRssiThreshold_t BeaconLowRssiThreshold; + * MrvlIEtypes_BeaconHighSnrThreshold_t BeaconHighSnrThreshold; + * MrvlIEtypes_BeaconLowSnrThreshold_t BeaconLowSnrThreshold; + * MrvlIEtypes_BeaconsMissed_t PreBeaconMissed; + * MrvlIEtypes_FailureCount_t FailureCnt; + */ +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD; + +typedef struct { + /** */ + signed char RssiHighLevel; + /** */ + signed char RssiLowLevel; + /** */ + signed char RssiNborDiff; + +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_ROAM_THRESHOLD; + +#define ROAM_THRESH_MAX 4 + +/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT */ +typedef struct { + /** Action */ + t_u16 action; + /** configured qualifying snr */ + signed char ConfQualSignalStrength; + /** active qualifying snr */ + signed char ActiveQualSignalStrength; + /** qualifying neighbor count */ + t_u16 QualifyingNumNeighbor; + /** inactivity in # scans */ + t_u16 StaleCount; + /** inactivity in time (ms) */ + t_u32 StalePeriod; + /** blacklist duration in ms due to minor failures */ + t_u32 ShortBlacklistPeriod; + /** blacklist duration in ms due to severe failures */ + t_u32 LongBlacklistPeriod; + + HostCmd_DS_CMD_ROAMAGENT_ROAM_THRESHOLD RoamThresh[ROAM_THRESH_MAX]; + +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT; + +/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST */ +typedef struct { + /** Action */ + t_u16 action; + /** Reserved */ + t_u16 Reserved; + /** TLV buffer */ + t_u8 TlvBuffer[1]; + /* MrvlIEtypes_NeighborEntry_t Neighbors[MRVL_ROAM_MAX_NEIGHBORS]; + * MRVL_ROAM_MAX_NEIGHBORS = 5 + */ +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST; + +/** neighbor entry details roaming agent */ +typedef struct { + /** Header */ + MrvlIEtypesHeader_t Header; + /** bssid of neighbor */ + t_u8 Bssid[ETH_ALEN]; + /** Reserved */ + t_u16 Reserved; + /** neighbor snr */ + t_s16 SignalStrength; + /** neighbor age */ + t_u16 Age; + /** bit map for qualified neighbor */ + t_u32 QualifiedNeighborBitmap; + /** blacklist duration in ms */ + t_u32 BlackListDuration; +} __ATTRIB_PACK__ MrvlIEtypes_NeighborEntry_t; + +/** HostCmd_DS_ROAMAGENT_ADV_METRIC_THRESHOLD */ +typedef struct { + /** Action */ + t_u16 action; + /** Beacon RSSI Metrics,Data RSSI Metrics or PER Metrics */ + t_u16 Metrics; + /** Percentage FER Threshold value to exceed for making a roam decision */ + t_u8 UcFerThresholdValue; + /** Percentage PER Threshold value to exceed for making a roam decision */ + t_u8 UcPerThresholdValue; + /** Reserved for later use */ + t_u8 Reserved[2]; + /** Time (ms) for which FER should prevail in stable state */ + t_u32 StableFERPeriod_ms; + /** Time (ms) for which FER should prevail in degrading state */ + t_u32 DegradingFERPeriod_ms; + /** Time (ms) for which FER should prevail in unacceptable state */ + t_u32 UnacceptableFERPeriod_ms; + /** Time (ms) for which FER should prevail in stable state */ + t_u32 StablePERPeriod_ms; + /** Time (ms) for which PER should prevail in degrading state */ + t_u32 DegradingPERPeriod_ms; + /** Time (ms) for which PER should prevail in unacceptable state */ + t_u32 UnacceptablePERPeriod_ms; + /** Number of TX packets to exceed in period_ms ms for the FER for Roam */ + t_u32 UiFerPktThreshold; + /** Number of TX packets to exceed in period_ms ms for the PER for Roam */ + t_u32 UiPerPktThreshold; + /** Time in ms for which inactivity should prevail for state transition */ + t_u32 InactivityPeriodThreshold_ms; + /** With Data RSSI Metrics, Roam only when RX packets in period_ms ms exceeds this */ + t_u32 UiRxPktThreshold; +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD; + +/** scan period for each search mode and state for roaming agent */ +typedef struct { + /** Header */ + MrvlIEtypesHeader_t Header; + /** search mode */ + t_u16 SearchMode; + /** roaming state */ + t_u16 State; + /** scan period value */ + t_u32 ScanPeriod; +} __ATTRIB_PACK__ MrvlIEtypes_NeighborScanPeriod_t; + +/** HostCmd_DS_CMD_ROAMAGENT_CONTROL */ +typedef struct { + /** Action */ + t_u16 action; + /** enable control */ + t_u8 Control; + /** host event control */ + t_u8 HostEvent; +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_CONTROL; + +/** HostCmd_DS_CMD_ROAMAGENT_BACKOFF */ +typedef struct { + /** Action */ + t_u16 action; + /** minimum scans */ + t_u16 Scans; + /** backoff period */ + t_u32 Period; +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_BACKOFF; + +/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD */ +typedef struct { + /** Action */ + t_u16 action; + /** Reserved */ + t_u16 Reserved; + /** scanPeriod TLV */ + MrvlIEtypes_NeighborScanPeriod_t scanPeriod; +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD; + +/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP */ +typedef struct { + /** Action */ + t_u16 action; + /** Reserved */ + t_u16 Reserved; + /** TLV buffer */ + t_u8 TlvBuffer[1]; + /* MrvlIEtypes_NeighborScanPeriod_t scanPeriod[MRVL_ROAM_SCAN_PERIODS]; + * MRVL_ROAM_SCAN_PERIODS = 6 + */ +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP; + +/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE */ +typedef struct { + /** Action */ + t_u16 action; + /** BSSID */ + t_u8 BSSID[ETH_ALEN]; +} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE; + +#endif /* _MLANROAMAGENT_H_ */ diff --git a/mwifiex_8997/mapp/mlanutl/mlanscanagent.c b/mwifiex_8997/mapp/mlanutl/mlanscanagent.c new file mode 100755 index 0000000..642380d --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanscanagent.c @@ -0,0 +1,840 @@ +/** @file mlanscanagent.c + * + * @brief This files contains mlanutl scanagent command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#include "mlanutl.h" +#include "mlanhostcmd.h" +#include "mlanoffload.h" +#include "mlanscanagent.h" + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief scanagent configure scan table + * + * @param age_limit age limit + * @param hold_limit hold limit + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_cfg_scan_table_limits(t_u32 age_limit, t_u32 hold_limit) +{ + int ret = 0; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS *scan_table_limits = NULL; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + return -ENOMEM; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return -ENOMEM; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_TABLE_LIMITS); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + scan_table_limits = (HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS *)pos; + scan_table_limits->table_age_limit = cpu_to_le16(age_limit); + scan_table_limits->table_hold_limit = cpu_to_le16(hold_limit); + + /* 0 set values are ignored by firmware */ + scan_table_limits->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[scanAgentIoctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + printf("\nAge limit = %7d seconds\n", + le16_to_cpu(scan_table_limits->table_age_limit)); + printf("Hold limit = %7d seconds\n\n", + le16_to_cpu(scan_table_limits->table_hold_limit)); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Set scanagent age limit + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_age_limit(int argc, char *argv[]) +{ + t_u32 age_limit = 0; + + if (argc) { + age_limit = atoi(argv[0]); + } + + return scanagent_cfg_scan_table_limits(age_limit, 0); +} + +/** + * @brief Set scanagent hold limit + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_hold_limit(int argc, char *argv[]) +{ + t_u32 hold_limit = 0; + + if (argc) { + hold_limit = atoi(argv[0]); + } + + return scanagent_cfg_scan_table_limits(0, hold_limit); +} + +/** + * @brief Set scanagent scan timing + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_timing(int argc, char *argv[]) +{ + int ret = 0; + struct ifreq ifr; + int idx; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len = 0, sel = 0; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + HostCmd_DS_SCANAGENT_CONFIG_TIMING *cfg_timing_cmd = NULL; + MrvlIEtypes_ConfigScanTiming_t *cfg_timing_tlv = NULL; + timing_sel_t sel_str[] = { {"disconnected", 1}, + {"adhoc", 1}, + {"fullpower", 1}, + {"ieeeps", 1}, + {"periodic", 1} + }; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + cmd_len = S_DS_GEN + sizeof(t_u16); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + return -ENOMEM; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return -ENOMEM; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_TIMING); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cfg_timing_cmd = (HostCmd_DS_SCANAGENT_CONFIG_TIMING *)pos; + cfg_timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + + cfg_timing_tlv + = (MrvlIEtypes_ConfigScanTiming_t *)cfg_timing_cmd->tlv_buffer; + + if (argc == 5) { + cfg_timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + cfg_timing_tlv->header.type = cpu_to_le16(TLV_TYPE_SCAN_TIMING); + cfg_timing_tlv->header.len = + cpu_to_le16(sizeof(MrvlIEtypes_ConfigScanTiming_t) + - sizeof(cfg_timing_tlv->header)); + + for (idx = 0; (unsigned int)idx < NELEMENTS(sel_str); idx++) { + if (strncmp(argv[0], + sel_str[idx].str, + sel_str[idx].match_len) == 0) { + sel = idx + 1; + break; + } + } + + if (idx == NELEMENTS(sel_str)) { + printf("Wrong argument for mode selected \"%s\"\n", + argv[0]); + ret = -EINVAL; + goto done; + } + + /* + * HostCmd_DS_ScanagentTimingMode_e; + * TIMING_MODE_INVALID = 0, + * TIMING_MODE_DISCONNECTED = 1, + * TIMING_MODE_ADHOC = 2, + * TIMING_MODE_FULL_POWER = 3, + * TIMING_MODE_IEEE_PS = 4, + * TIMING_MODE_PERIODIC_PS = 5, + */ + cfg_timing_tlv->mode = cpu_to_le32(sel); + cfg_timing_tlv->dwell = cpu_to_le32(atoi(argv[1])); + cfg_timing_tlv->max_off = cpu_to_le32(atoi(argv[2])); + cfg_timing_tlv->min_link = cpu_to_le32(atoi(argv[3])); + cfg_timing_tlv->rsp_timeout = cpu_to_le32(atoi(argv[4])); + + cmd_len += sizeof(MrvlIEtypes_ConfigScanTiming_t); + } + + hostcmd->size = cpu_to_le16(cmd_len); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[scanAgentIoctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + ret = process_host_cmd_resp(HOSTCMD, buffer); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Set scanagent profile scan period + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_profile_period(int argc, char *argv[]) +{ + int ret = 0; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len = 0; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN *cfg_profile_scan = NULL; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + cmd_len = S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + return -ENOMEM; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return -ENOMEM; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + hostcmd->command = + cpu_to_le16(HostCmd_CMD_SCANAGENT_CONFIG_PROFILE_SCAN); + hostcmd->size = cpu_to_le16(cmd_len); + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + cfg_profile_scan = (HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN *)pos; + if (argc == 1) { + cfg_profile_scan->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + cfg_profile_scan->scan_interval = cpu_to_le16(atoi(argv[0])); + } else { + cfg_profile_scan->action = cpu_to_le16(HostCmd_ACT_GEN_GET); + } + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[scanAgentIoctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + + cfg_profile_scan->scan_interval = + le16_to_cpu(cfg_profile_scan->scan_interval); + if ((int)cfg_profile_scan->scan_interval == 0) + printf("\nProfile Scan interval: \n\n"); + else + printf("\nProfile Scan interval: %d seconds\n\n", + (int)cfg_profile_scan->scan_interval); + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief scanagent parse entry selection + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param psel A pointer to scanagent entry selection + * + * @return None + */ +static void +scanAgentParseEntrySel(int argc, char *argv[], + HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *psel, + int *cmd_len) +{ + int arg_idx, tmp_idx; + t_u8 *tlv_pos; + MrvlIEtypes_SsIdParamSet_t *ssid; + MrvlIEtypes_Bssid_List_t *bssid; + unsigned int mac[ETH_ALEN]; + + tlv_pos = (t_u8 *)psel->tlv_buffer; + + for (arg_idx = 0; arg_idx < argc; arg_idx++) { + if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) { + ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv_pos; + ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); + ssid->header.len = + strlen(argv[arg_idx]) - strlen("ssid="); + strncpy((char *)ssid->ssid, + (argv[arg_idx] + strlen("ssid=")), + ssid->header.len); + tlv_pos += + ssid->header.len + sizeof(MrvlIEtypesHeader_t); + ssid->header.len = cpu_to_le16(ssid->header.len); + + } else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) == + 0) { + bssid = (MrvlIEtypes_Bssid_List_t *)tlv_pos; + bssid->header.type = cpu_to_le16(TLV_TYPE_BSSID); + bssid->header.len = ETH_ALEN; + /* + * "bssid" token string handler + */ + sscanf(argv[arg_idx] + strlen("bssid="), + "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1, + mac + 2, mac + 3, mac + 4, mac + 5); + for (tmp_idx = 0; + (unsigned int)tmp_idx < NELEMENTS(mac); + tmp_idx++) { + bssid->bssid[tmp_idx] = (t_u8)mac[tmp_idx]; + } + tlv_pos += + bssid->header.len + sizeof(MrvlIEtypesHeader_t); + bssid->header.len = cpu_to_le16(bssid->header.len); + + } else if (strncmp(argv[arg_idx], "age=", strlen("age=")) == 0) { + psel->age = + cpu_to_le32(atoi + (argv[arg_idx] + strlen("age="))); + + } else if (strncmp(argv[arg_idx], "id=", strlen("id=")) == 0) { + psel->scan_request_id = + cpu_to_le32(atoi + (argv[arg_idx] + strlen("id="))); + } + } + + *cmd_len += (tlv_pos - psel->tlv_buffer); +} + +/** + * @brief scanagent execute scan + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_exec_scan(int argc, char *argv[]) +{ + int ret = 0; + struct ifreq ifr; + int arg_idx, tmp_idx; + t_u32 cmd_len = 0, cmd_header_len = 0; + t_u8 *buffer = NULL, *pos = NULL, *tlv_pos = NULL; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + HostCmd_DS_SCANAGENT_SCAN_EXEC *scan_exec = NULL; + MrvlIEtypes_SsIdParamSet_t *ssid = NULL; + MrvlIEtypes_Bssid_List_t *bssid = NULL; + MrvlIEtypes_ConfigScanTiming_t *cfg_timing_tlv = NULL; + unsigned int mac[ETH_ALEN]; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + cmd_len = (S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_SCAN_EXEC) + - sizeof(scan_exec->tlv_buffer)); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + return -ENOMEM; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return -ENOMEM; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_EXEC); + hostcmd->size = 0; + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + scan_exec = (HostCmd_DS_SCANAGENT_SCAN_EXEC *)pos; + tlv_pos = scan_exec->tlv_buffer; + + for (arg_idx = 0; arg_idx < argc; arg_idx++) { + if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) { + /* + * "ssid" token string handler + */ + ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv_pos; + ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); + ssid->header.len = + strlen(argv[arg_idx]) - strlen("ssid="); + strncpy((char *)ssid->ssid, + argv[arg_idx] + strlen("ssid="), + ssid->header.len); + tlv_pos += + ssid->header.len + sizeof(MrvlIEtypesHeader_t); + ssid->header.len = cpu_to_le16(ssid->header.len); + } else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) == + 0) { + bssid = (MrvlIEtypes_Bssid_List_t *)tlv_pos; + bssid->header.type = cpu_to_le16(TLV_TYPE_BSSID); + bssid->header.len = ETH_ALEN; + /* + * "bssid" token string handler + */ + sscanf(argv[arg_idx] + strlen("bssid="), + "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1, + mac + 2, mac + 3, mac + 4, mac + 5); + for (tmp_idx = 0; + (unsigned int)tmp_idx < NELEMENTS(mac); + tmp_idx++) { + bssid->bssid[tmp_idx] = (t_u8)mac[tmp_idx]; + } + tlv_pos += + bssid->header.len + sizeof(MrvlIEtypesHeader_t); + bssid->header.len = cpu_to_le16(bssid->header.len); + } else if (strncmp(argv[arg_idx], "type=", strlen("type=")) == + 0) { + /* + if (strcmp(argv[arg_idx] + strlen("type="), "prof") == 0) { + scan_exec->scan_type = CONFIG_PROFILE; + } else { + scan_exec->scan_type = CONFIG_SITE_SURVEY; + } + */ + scan_exec->scan_type = CONFIG_SITE_SURVEY; + scan_exec->scan_type = + cpu_to_le16(scan_exec->scan_type); + } else if (strncmp(argv[arg_idx], "group=", strlen("group=")) == + 0) { + sscanf(argv[arg_idx] + strlen("group="), "0x%x", + &tmp_idx); + scan_exec->chan_group = cpu_to_le32(tmp_idx); + } else if (strncmp(argv[arg_idx], "delay=", strlen("delay=")) == + 0) { + /* + * "delay" token string handler + */ + sscanf(argv[arg_idx] + strlen("delay="), + "%d", (int *)&scan_exec->delay); + scan_exec->delay = cpu_to_le32(scan_exec->delay); + } else if (strncmp(argv[arg_idx], "timing=", strlen("timing=")) + == 0) { + cfg_timing_tlv = + (MrvlIEtypes_ConfigScanTiming_t *)tlv_pos; + cfg_timing_tlv->header.type = + cpu_to_le16(TLV_TYPE_SCAN_TIMING); + cfg_timing_tlv->header.len = ((sizeof(cfg_timing_tlv) + - + sizeof(cfg_timing_tlv-> + header))); + /* + * "timing" token string handler + */ + sscanf(argv[arg_idx] + strlen("timing="), "%d,%d,%d,%d", + (int *)&cfg_timing_tlv->dwell, + (int *)&cfg_timing_tlv->max_off, + (int *)&cfg_timing_tlv->min_link, + (int *)&cfg_timing_tlv->rsp_timeout); + + cfg_timing_tlv->mode = 0; + cfg_timing_tlv->dwell = + cpu_to_le32(cfg_timing_tlv->dwell); + cfg_timing_tlv->max_off = + cpu_to_le32(cfg_timing_tlv->max_off); + cfg_timing_tlv->min_link = + cpu_to_le32(cfg_timing_tlv->min_link); + cfg_timing_tlv->rsp_timeout = + cpu_to_le32(cfg_timing_tlv->rsp_timeout); + + tlv_pos += sizeof(MrvlIEtypesHeader_t); + tlv_pos += cfg_timing_tlv->header.len; + cfg_timing_tlv->header.len = + cpu_to_le16(cfg_timing_tlv->header.len); + } + } + + cmd_len += (tlv_pos - scan_exec->tlv_buffer); + hostcmd->size = cpu_to_le16(cmd_len); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[scanAgentIoctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } else { + printf("\nScan Scheduled, ID = %d\n\n", + (int)le32_to_cpu(scan_exec->scan_req_id_out)); + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a scanagent cmd_type subcommand + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * @param cmd_type command type + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_table_entry_sub_cmd(int argc, char *argv[], + HostCmd_DS_ScanagentTableMaintenance_e cmd_type) +{ + int ret = 0; + struct ifreq ifr; + t_u8 *buffer = NULL, *pos = NULL; + t_u32 cmd_len = 0, cmd_header_len = 0; + struct eth_priv_cmd *cmd = NULL; + HostCmd_DS_GEN *hostcmd = NULL; + HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *table_maintenance = NULL; + + cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD); + cmd_len = (S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE) + - sizeof(table_maintenance->tlv_buffer)); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (buffer == NULL) { + fprintf(stderr, "Cannot alloc memory\n"); + return -ENOMEM; + } + memset(buffer, 0, BUFFER_LENGTH); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return -ENOMEM; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* buffer = MRVL_CMD */ + strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL)); + strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD)); + + /* buffer = MRVL_CMD */ + hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32)); + hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_TABLE_MAINTENANCE); + hostcmd->size = 0; + hostcmd->seq_num = 0; + hostcmd->result = 0; + + /* Point after host command header */ + pos = (t_u8 *)hostcmd + S_DS_GEN; + + table_maintenance = (HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *)pos; + table_maintenance->action = cpu_to_le16((t_u16)cmd_type); + + scanAgentParseEntrySel(argc, argv, table_maintenance, (int *)&cmd_len); + + hostcmd->size = cpu_to_le16(cmd_len); + + /* Put buffer length */ + memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32)); + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + /* Perform ioctl */ + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("ioctl[scanAgentIoctl]"); + printf("ERR:Command sending failed!\n"); + ret = -EFAULT; + goto done; + } + +done: + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; +} + +/** + * @brief Issue a scanagent table lock subcommand + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_table_lock(int argc, char *argv[]) +{ + return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_LOCK); +} + +/** + * @brief Issue a scanagent table unlock subcommand + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_table_unlock(int argc, char *argv[]) +{ + return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_UNLOCK); +} + +/** + * @brief Issue a scanagent table purge subcommand + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS on success, otherwise error code + */ +static int +scanagent_table_purge(int argc, char *argv[]) +{ + return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_PURGE); +} + +/** + * @brief Issue a scanagent command + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_scanagent(int argc, char *argv[]) +{ + sub_cmd_exec_t sub_cmd[] = { + {"timing", 2, 1, scanagent_timing}, + {"scan", 2, 1, scanagent_exec_scan}, + {"lock", 2, 1, scanagent_table_lock}, + {"unlock", 2, 1, scanagent_table_unlock}, + {"purge", 2, 1, scanagent_table_purge}, + {"profile", 2, 1, scanagent_profile_period}, + {"holdlimit", 2, 1, scanagent_hold_limit}, + {"agelimit", 2, 1, scanagent_age_limit} + }; + + return process_sub_cmd(sub_cmd, NELEMENTS(sub_cmd), argc, argv); +} diff --git a/mwifiex_8997/mapp/mlanutl/mlanscanagent.h b/mwifiex_8997/mapp/mlanutl/mlanscanagent.h new file mode 100755 index 0000000..e30f1a3 --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanscanagent.h @@ -0,0 +1,149 @@ +/** @file mlanscanagent.h + * + * @brief This files contains mlanutl scanagent command handling. + * + * Copyright (C) 2008-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 08/11/2009: initial version +************************************************************************/ + +#ifndef _MLAN_SCANAGENT_H_ +#define _MLAN_SCANAGENT_H_ + +typedef struct { + /** Action GET or SET */ + t_u16 action; + /** scan interval */ + t_u16 scan_interval; +} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN; + +typedef struct { + t_u32 scan_req_id_out; + /**< Scan request id */ + t_u32 delay; /**< Delay */ + t_u32 chan_group; /**< Channel Group */ + t_u16 scan_type; /**< Scan type */ + t_u16 reserved; /**< Reserved */ + + t_u8 tlv_buffer[1]; /**< Rest is TLV buffer */ + + /* MrvlIEtypes_SsIdParamSet_t + * MrvlIEtypes_Bssid_List_t + * MrvlIEtypes_ConfigScanTiming_t + */ +} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_SCAN_EXEC; + +typedef struct { + /** Action Set or get */ + t_u16 action; + /** Reserved */ + t_u16 reserved; + /** Table age limit */ + t_u16 table_age_limit; + /** Table hold limit */ + t_u16 table_hold_limit; +} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS; + +typedef struct { + /** Action Set or get */ + t_u16 action; + /** TLV buffer starts here */ + t_u8 tlv_buffer[1]; + /* MrvlIEtypes_ConfigScanTiming_t */ +} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_CONFIG_TIMING; + +typedef struct { + /** HostCmd_DS_ScanagentTableMaintenance_e action */ + t_u16 action; + /** Reserved */ + t_u16 reserved; + /** Request Id, 0 to disable */ + t_u32 scan_request_id; + /** Age, 0 to disable */ + t_u32 age; + /** TLV Buffer follows */ + t_u8 tlv_buffer[1]; + + /* MrvlIEtypes_SsIdParamSet_t + * MrvlIEtypes_Bssid_List_t + */ +} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE; + +/** ENUM definition: Scanagent Table Maintenance */ +typedef enum { + SCAN_TABLE_OP_INVALID = 0, + + SCAN_TABLE_OP_LOCK = 1, + SCAN_TABLE_OP_UNLOCK = 2, + SCAN_TABLE_OP_PURGE = 3, + +} __ATTRIB_PACK__ HostCmd_DS_ScanagentTableMaintenance_e; + +/** MrvlIEtypes_SsIdParamSet_t */ +typedef struct _MrvlIEtypes_SsIdParamSet_t { + /** Header */ + MrvlIEtypesHeader_t header; + /** SSID */ + t_u8 ssid[1]; +} __ATTRIB_PACK__ MrvlIEtypes_SsIdParamSet_t; + +/** _MrvlIEtypes_Bssid_List_t */ +typedef struct _MrvlIEtypes_Bssid_List_t { + /** Header */ + MrvlIEtypesHeader_t header; + /** BSSID */ + t_u8 bssid[ETH_ALEN]; +} __ATTRIB_PACK__ MrvlIEtypes_Bssid_List_t; + +typedef struct { + /** Header */ + MrvlIEtypesHeader_t header; + + t_u32 mode; /**< Mode */ + t_u32 dwell; /**< Dwell */ + t_u32 max_off; /**< Max. off */ + t_u32 min_link;/**< Minimum Link */ + t_u32 rsp_timeout; + /**< Rsp Timeout */ + +} __ATTRIB_PACK__ MrvlIEtypes_ConfigScanTiming_t; + +/** ENUM definition: ScanAgentScanType */ +typedef enum { + CONFIG_SITE_SURVEY = 0, + CONFIG_NEIGHBOR = 1, + CONFIG_PROFILE = 2, + CONFIG_ARBITRARY_CHANNEL = 3, + +} __ATTRIB_PACK__ HostCmd_DS_ScanagentScanType_e; + +/** ENUM definition: ScanAgentScanTimingMode */ +typedef enum { + TIMING_MODE_INVALID = 0, + + TIMING_MODE_DISCONNECTED = 1, + TIMING_MODE_ADHOC = 2, + TIMING_MODE_FULL_POWER = 3, + TIMING_MODE_IEEE_PS = 4, + TIMING_MODE_PERIODIC_PS = 5, + +} __ATTRIB_PACK__HostCmd_DS_ScanagentTimingMode_e; + +int process_host_cmd_resp(char *cmd_name, t_u8 *buf); +#endif /* _MLAN_SCANAGENT_H_ */ diff --git a/mwifiex_8997/mapp/mlanutl/mlanutl.c b/mwifiex_8997/mapp/mlanutl/mlanutl.c new file mode 100755 index 0000000..111c37c --- /dev/null +++ b/mwifiex_8997/mapp/mlanutl/mlanutl.c @@ -0,0 +1,18720 @@ +/** @file mlanutl.c + * + * @brief Program to control parameters in the mlandriver + * + * Copyright (C) 2011-2019, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/************************************************************************ +Change log: + 11/04/2011: initial version +************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mlanutl.h" + +/** Supported stream modes */ +#define HT_STREAM_MODE_1X1 0x11 +#define HT_STREAM_MODE_2X2 0x22 + +/** mlanutl version number */ +#define MLANUTL_VER "M1.3" + +/** Initial number of total private ioctl calls */ +#define IW_INIT_PRIV_NUM 128 +/** Maximum number of total private ioctl calls supported */ +#define IW_MAX_PRIV_NUM 1024 + +/** Termination flag */ +int terminate_flag = 0; + +typedef struct { + t_u8 chanNum; /**< Channel Number */ + t_u8 chanLoad; /**< Channel Load fraction */ + t_s16 anpi; /**< Channel ANPI */ + +} ChanRptInfo_t; + +/******************************************************** + Local Variables +********************************************************/ +#define BAND_B (1U << 0) +#define BAND_G (1U << 1) +#define BAND_A (1U << 2) +#define BAND_GN (1U << 3) +#define BAND_AN (1U << 4) +#define BAND_GAC (1U << 5) +#define BAND_AAC (1U << 6) + +static char *band[] = { + "B", + "G", + "A", + "GN", + "AN", + "GAC", + "AAC", +}; + +/** Stringification of rateId enumeration */ +const char *rateIdStr[] = { "1", "2", "5.5", "11", "--", + "6", "9", "12", "18", "24", "36", "48", "54", "--", + "M0", "M1", "M2", "M3", "M4", "M5", "M6", "M7", + "H0", "H1", "H2", "H3", "H4", "H5", "H6", "H7" +}; + +#ifdef DEBUG_LEVEL1 +#define MMSG MBIT(0) +#define MFATAL MBIT(1) +#define MERROR MBIT(2) +#define MDATA MBIT(3) +#define MCMND MBIT(4) +#define MEVENT MBIT(5) +#define MINTR MBIT(6) +#define MIOCTL MBIT(7) + +#define MMPA_D MBIT(15) +#define MDAT_D MBIT(16) +#define MCMD_D MBIT(17) +#define MEVT_D MBIT(18) +#define MFW_D MBIT(19) +#define MIF_D MBIT(20) + +#define MENTRY MBIT(28) +#define MWARN MBIT(29) +#define MINFO MBIT(30) +#define MHEX_DUMP MBIT(31) +#endif +static int process_multi_chan_cfg(int argc, char *argv[]); +static int process_multi_chan_policy(int argc, char *argv[]); +static int process_drcs_time_slicing_cfg(int argc, char *argv[]); +static int process_dot11_txrx(int argc, char *argv[]); +#ifdef RX_PACKET_COALESCE +static int process_rx_pkt_coalesce_cfg(int argc, char *argv[]); +static void print_rx_packet_coalesc_help(void); +#endif +static int process_version(int argc, char *argv[]); +static int process_bandcfg(int argc, char *argv[]); +static int process_hostcmd(int argc, char *argv[]); +static int process_httxcfg(int argc, char *argv[]); +static int process_htcapinfo(int argc, char *argv[]); +static int process_addbapara(int argc, char *argv[]); +static int process_aggrpriotbl(int argc, char *argv[]); +static int process_addbareject(int argc, char *argv[]); +static int process_delba(int argc, char *argv[]); +static int process_rejectaddbareq(int argc, char *argv[]); +static int process_vhtcfg(int argc, char *argv[]); +static int process_opermodecfg(int argc, char *argv[]); +static int process_datarate(int argc, char *argv[]); +static int process_txratecfg(int argc, char *argv[]); +static int process_getlog(int argc, char *argv[]); +static int process_esuppmode(int argc, char *argv[]); +static int process_passphrase(int argc, char *argv[]); +static int process_deauth(int argc, char *argv[]); +#ifdef UAP_SUPPORT +static int process_getstalist(int argc, char *argv[]); +#endif +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) +static int process_bssrole(int argc, char *argv[]); +#endif +#endif +#ifdef STA_SUPPORT +static int process_setuserscan(int argc, char *argv[]); +static int wlan_process_getscantable(int argc, char *argv[], + wlan_ioctl_user_scan_cfg *scan_req); +static int process_getscantable(int argc, char *argv[]); +static int process_extcapcfg(int argc, char *argv[]); +static int process_cancelscan(int argc, char *argv[]); +#endif +static int process_deepsleep(int argc, char *argv[]); +static int process_ipaddr(int argc, char *argv[]); +static int process_otpuserdata(int argc, char *argv[]); +static int process_countrycode(int argc, char *argv[]); +static int process_tcpackenh(int argc, char *argv[]); +#ifdef REASSOCIATION +static int process_assocessid(int argc, char *argv[]); +#endif +#ifdef STA_SUPPORT +static int process_listeninterval(int argc, char *argv[]); +static int process_psmode(int argc, char *argv[]); +#endif +#ifdef DEBUG_LEVEL1 +static int process_drvdbg(int argc, char *argv[]); +#endif +static int process_hscfg(int argc, char *argv[]); +static int process_hssetpara(int argc, char *argv[]); +static int process_wakeupresaon(int argc, char *argv[]); +static int process_mgmtfilter(int argc, char *argv[]); +static int process_scancfg(int argc, char *argv[]); +static int process_warmreset(int argc, char *argv[]); +static int process_txpowercfg(int argc, char *argv[]); +static int process_pscfg(int argc, char *argv[]); +static int process_bcntimeoutcfg(int argc, char *argv[]); +static int process_sleeppd(int argc, char *argv[]); +static int process_txcontrol(int argc, char *argv[]); +static int process_host_tdls_config(int argc, char *argv[]); +static int process_tdls_config(int argc, char *argv[]); +static int process_tdls_setinfo(int argc, char *argv[]); +static int process_tdls_discovery(int argc, char *argv[]); +static int process_tdls_setup(int argc, char *argv[]); +static int process_tdls_teardown(int argc, char *argv[]); +static int process_tdls_powermode(int argc, char *argv[]); +static int process_tdls_link_status(int argc, char *argv[]); +static int process_tdls_debug(int argc, char *argv[]); +static int process_tdls_channel_switch(int argc, char *argv[]); +static int process_tdls_stop_channel_switch(int argc, char *argv[]); +static int process_tdls_cs_params(int argc, char *argv[]); +static int process_tdls_disable_channel_switch(int argc, char *argv[]); +static int process_tdls_idle_time(int argc, char *argv[]); +static int process_dfs_offload_enable(int argc, char *argv[]); +static int process_customie(int argc, char *argv[]); +static int process_regrdwr(int argc, char *argv[]); +static int process_rdeeprom(int argc, char *argv[]); +static int process_memrdwr(int argc, char *argv[]); +static int process_mefcfg(int argc, char *argv[]); +#ifdef STA_SUPPORT +static int process_arpfilter(int argc, char *argv[]); +#endif +static int process_cfgdata(int argc, char *argv[]); +static int process_mgmtframetx(int argc, char *argv[]); +static int process_mgmt_frame_passthrough(int argc, char *argv[]); +static int process_qconfig(int argc, char *argv[]); +static int process_addts(int argc, char *argv[]); +static int process_delts(int argc, char *argv[]); +static int process_wmm_qstatus(int argc, char *argv[]); +static int process_wmm_ts_status(int argc, char *argv[]); +static int process_qos_config(int argc, char *argv[]); +static int process_macctrl(int argc, char *argv[]); +static int process_fwmacaddr(int argc, char *argv[]); +static int process_regioncode(int argc, char *argv[]); +static int process_cfpinfo(int argc, char *argv[]); +static int process_offchannel(int argc, char *argv[]); +static int process_linkstats(int argc, char *argv[]); +#if defined(STA_SUPPORT) +static int process_pmfcfg(int argc, char *argv[]); +#endif +static int process_verext(int argc, char *argv[]); +#if defined(STA_SUPPORT) && defined(STA_WEXT) +static int process_radio_ctrl(int argc, char *argv[]); +#endif +static int process_wmm_cfg(int argc, char *argv[]); +static int process_wmm_param_config(int argc, char *argv[]); +#if defined(STA_SUPPORT) +static int process_11d_cfg(int argc, char *argv[]); +static int process_11d_clr_tbl(int argc, char *argv[]); +#endif +static int process_wws_cfg(int argc, char *argv[]); +#if defined(REASSOCIATION) +static int process_set_get_reassoc(int argc, char *argv[]); +#endif +static int process_txbuf_cfg(int argc, char *argv[]); +#ifdef STA_SUPPORT +static int process_set_get_auth_type(int argc, char *argv[]); +#endif +static int process_11h_local_pwr_constraint(int argc, char *argv[]); +static int process_ht_stream_cfg(int argc, char *argv[]); +static int process_mimo_switch(int argc, char *argv[]); +static int process_thermal(int argc, char *argv[]); +static int process_beacon_interval(int argc, char *argv[]); +static int process_cwmode(int argc, char *argv[]); +#ifdef STA_SUPPORT +static int process_get_signal(int argc, char *argv[]); +static int process_get_signal_ext(int argc, char *argv[]); +static int process_signalext_cfg(int argc, char *argv[]); +#endif +static int process_inactivity_timeout_ext(int argc, char *argv[]); +static int process_11n_amsdu_aggr_ctrl(int argc, char *argv[]); +static int process_tx_bf_cap_ioctl(int argc, char *argv[]); +static int process_sleep_params(int argc, char *argv[]); +static int process_net_monitor(int argc, char *argv[]); +#if defined(DFS_TESTING_SUPPORT) +static int process_dfs_testing(int argc, char *argv[]); +#endif +static int process_cfp_code(int argc, char *argv[]); +static int process_set_get_tx_rx_ant(int argc, char *argv[]); +static int process_sysclock(int argc, char *argv[]); +static int process_associate_ssid_bssid(int argc, char *argv[]); +static int process_tx_bf_cfg(int argc, char *argv[]); +static int process_wps_cfg(int argc, char *argv[]); +static int process_port_ctrl(int argc, char *argv[]); +static int process_bypassed_packet(int argc, char *argv[]); +/* #ifdef FW_WAKEUP_METHOD */ +static int process_fw_wakeup_method(int argc, char *argv[]); +/* #endif */ +#if defined(WIFI_DIRECT_SUPPORT) +static int process_cfg_noa_opp_ps(int argc, char *argv[]); +#endif +static int process_dscpmap(int argc, char *argv[]); +#ifdef WIFI_DIRECT_SUPPORT +static int process_miracastcfg(int argc, char *argv[]); +#endif +static int process_coex_rx_winsize(int argc, char *argv[]); +static int process_dfs_repeater(int argc, char *argv[]); +static int process_txaggrctrl(int argc, char *argv[]); +static int process_auto_tdls(int argc, char *argv[]); +static int process_pcie_reg_rw(int argc, char *argv[]); +static int process_pcie_bar0_reg_rw(int argc, char *argv[]); +static int process_get_sensor_temp(int argc, char *argv[]); +static int process_chan_graph(int argc, char *argv[]); +static int process_11k_cfg(int argc, char *argv[]); +static int process_11k_neighbor_report(int argc, char *argv[]); +static int process_extend_channel_switch(int argc, char *argv[]); +static int process_auto_arp(int argc, char *argv[]); +static int process_txrxhistogram(int argc, char *argv[]); +static int process_per_pkt_cfg(int argc, char *argv[]); +static int process_ind_rst_cfg(int argc, char *argv[]); +int process_tsf(int argc, char *argv[]); +static int process_dyn_bw(int argc, char *argv[]); +static int process_tx_ampdu_prot_mode(int argc, char *argv[]); +static int process_ctrldeauth(int argc, char *argv[]); +static int process_robustcoex(int argc, char *argv[]); +static int process_acs(int argc, char *argv[]); +static int process_bootsleep(int argc, char *argv[]); + +struct command_node command_list[] = { + {"version", process_version}, + {"bandcfg", process_bandcfg}, + {"hostcmd", process_hostcmd}, + {"httxcfg", process_httxcfg}, + {"htcapinfo", process_htcapinfo}, + {"addbapara", process_addbapara}, + {"aggrpriotbl", process_aggrpriotbl}, + {"addbareject", process_addbareject}, + {"delba", process_delba}, + {"rejectaddbareq", process_rejectaddbareq}, + {"vhtcfg", process_vhtcfg}, + {"opermodecfg", process_opermodecfg}, + {"getdatarate", process_datarate}, + {"txratecfg", process_txratecfg}, + {"getlog", process_getlog}, + {"esuppmode", process_esuppmode}, + {"passphrase", process_passphrase}, + {"deauth", process_deauth}, +#ifdef UAP_SUPPORT + {"getstalist", process_getstalist}, +#endif +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) + {"bssrole", process_bssrole}, +#endif +#endif +#ifdef STA_SUPPORT + {"setuserscan", process_setuserscan}, + {"getscantable", process_getscantable}, + {"extcapcfg", process_extcapcfg}, + {"cancelscan", process_cancelscan}, +#endif + {"deepsleep", process_deepsleep}, + {"ipaddr", process_ipaddr}, + {"otpuserdata", process_otpuserdata}, + {"countrycode", process_countrycode}, + {"tcpackenh", process_tcpackenh}, +#ifdef REASSOCIATION + {"assocessid", process_assocessid}, + {"assocessid_bssid", process_assocessid}, +#endif +#ifdef STA_SUPPORT + {"listeninterval", process_listeninterval}, + {"psmode", process_psmode}, +#endif +#ifdef DEBUG_LEVEL1 + {"drvdbg", process_drvdbg}, +#endif + {"hscfg", process_hscfg}, + {"hssetpara", process_hssetpara}, + {"wakeupreason", process_wakeupresaon}, + {"mgmtfilter", process_mgmtfilter}, + {"scancfg", process_scancfg}, + {"warmreset", process_warmreset}, + {"txpowercfg", process_txpowercfg}, + {"pscfg", process_pscfg}, + {"bcntimeoutcfg", process_bcntimeoutcfg}, + {"sleeppd", process_sleeppd}, + {"txcontrol", process_txcontrol}, + {"host_tdls_config", process_host_tdls_config}, + {"tdls_config", process_tdls_config}, + {"tdls_setinfo", process_tdls_setinfo}, + {"tdls_discovery", process_tdls_discovery}, + {"tdls_setup", process_tdls_setup}, + {"tdls_teardown", process_tdls_teardown}, + {"tdls_powermode", process_tdls_powermode}, + {"tdls_link_status", process_tdls_link_status}, + {"tdls_debug", process_tdls_debug}, + {"tdls_channel_switch", process_tdls_channel_switch}, + {"tdls_stop_channel_switch", process_tdls_stop_channel_switch}, + {"tdls_cs_params", process_tdls_cs_params}, + {"tdls_disable_cs", process_tdls_disable_channel_switch}, + {"tdls_idle_time", process_tdls_idle_time}, + {"dfs_offload", process_dfs_offload_enable}, + {"customie", process_customie}, + {"regrdwr", process_regrdwr}, + {"rdeeprom", process_rdeeprom}, + {"memrdwr", process_memrdwr}, + {"mefcfg", process_mefcfg}, +#ifdef STA_SUPPORT + {"arpfilter", process_arpfilter}, +#endif + {"cfgdata", process_cfgdata}, + {"mgmtframetx", process_mgmtframetx}, + {"mgmtframectrl", process_mgmt_frame_passthrough}, + {"qconfig", process_qconfig}, + {"addts", process_addts}, + {"delts", process_delts}, + {"ts_status", process_wmm_ts_status}, + {"qstatus", process_wmm_qstatus}, + {"qoscfg", process_qos_config}, + {"macctrl", process_macctrl}, + {"fwmacaddr", process_fwmacaddr}, + {"regioncode", process_regioncode}, + {"cfpinfo", process_cfpinfo}, + {"offchannel", process_offchannel}, + {"linkstats", process_linkstats}, +#if defined(STA_SUPPORT) + {"pmfcfg", process_pmfcfg}, +#endif + {"verext", process_verext}, +#if defined(STA_SUPPORT) && defined(STA_WEXT) + {"radioctrl", process_radio_ctrl}, +#endif + {"wmmcfg", process_wmm_cfg}, + {"wmmparamcfg", process_wmm_param_config}, +#if defined(STA_SUPPORT) + {"11dcfg", process_11d_cfg}, + {"11dclrtbl", process_11d_clr_tbl}, +#endif + {"wwscfg", process_wws_cfg}, +#if defined(REASSOCIATION) + {"reassoctrl", process_set_get_reassoc}, +#endif + {"txbufcfg", process_txbuf_cfg}, +#ifdef STA_SUPPORT + {"authtype", process_set_get_auth_type}, +#endif + {"powercons", process_11h_local_pwr_constraint}, + {"htstreamcfg", process_ht_stream_cfg}, + {"mimoswitch", process_mimo_switch}, + {"thermal", process_thermal}, + {"bcninterval", process_beacon_interval}, + {"cwmode", process_cwmode}, +#ifdef STA_SUPPORT + {"getsignal", process_get_signal}, + {"getsignalext", process_get_signal_ext}, + {"getsignalextv2", process_get_signal_ext}, + {"signalextcfg", process_signalext_cfg}, +#endif + {"inactivityto", process_inactivity_timeout_ext}, + {"amsduaggrctrl", process_11n_amsdu_aggr_ctrl}, + {"httxbfcap", process_tx_bf_cap_ioctl}, + {"sleepparams", process_sleep_params}, + {"netmon", process_net_monitor}, +#if defined(DFS_TESTING_SUPPORT) + {"dfstesting", process_dfs_testing}, +#endif + {"cfpcode", process_cfp_code}, + {"antcfg", process_set_get_tx_rx_ant}, + {"dscpmap", process_dscpmap}, + {"changraph", process_chan_graph}, + {"associate", process_associate_ssid_bssid}, + {"httxbfcfg", process_tx_bf_cfg}, + {"wpssession", process_wps_cfg}, + {"port_ctrl", process_port_ctrl}, + {"pb_bypass", process_bypassed_packet}, +/* #ifdef FW_WAKEUP_METHOD */ + {"fwwakeupmethod", process_fw_wakeup_method}, +/* #endif */ + {"sysclock", process_sysclock}, + {"mc_cfg", process_multi_chan_cfg}, + {"mc_policy", process_multi_chan_policy}, + {"mc_cfg_ext", process_drcs_time_slicing_cfg}, +#ifdef RX_PACKET_COALESCE + {"rxpktcoal_cfg", process_rx_pkt_coalesce_cfg}, +#endif +#if defined(WIFI_DIRECT_SUPPORT) + {"cfg_noa", process_cfg_noa_opp_ps}, + {"cfg_opp_ps", process_cfg_noa_opp_ps}, +#endif +#ifdef WIFI_DIRECT_SUPPORT + {"miracastcfg", process_miracastcfg}, +#endif + {"coex_rx_winsize", process_coex_rx_winsize}, + {"dfs_repeater", process_dfs_repeater}, + {"txaggrctrl", process_txaggrctrl}, + {"autotdls", process_auto_tdls}, + {"pcieregrw", process_pcie_reg_rw}, + {"pciebar0regrw", process_pcie_bar0_reg_rw}, + {"get_sensor_temp", process_get_sensor_temp}, + {"11k_enable", process_11k_cfg}, + {"neighbor_report", process_11k_neighbor_report}, + {"channel_switch", process_extend_channel_switch}, + {"auto_arp", process_auto_arp}, + {"txrxhistogram", process_txrxhistogram}, + {"indrstcfg", process_ind_rst_cfg}, + {"tsf", process_tsf}, + {"dot11_txrx", process_dot11_txrx}, + {"per_pkt_cfg", process_per_pkt_cfg}, + {"dyn_bw", process_dyn_bw}, + {"tx_ampdu_prot_mode", process_tx_ampdu_prot_mode}, + {"ctrldeauth", process_ctrldeauth}, + {"robustcoex", process_robustcoex}, + {"acs", process_acs}, + {"bootsleep", process_bootsleep}, +}; + +static char *usage[] = { + "Usage: ", + " mlanutl -v (version)", + " mlanutl [...]", + " where", + " ifname : wireless network interface name, such as mlanX or uapX", + " cmd :", + " 11dcfg", + " 11dclrtbl", + " addbapara", + " addbareject", + " addts", + " aggrpriotbl", + " amsduaggrctrl", + " antcfg", +#ifdef STA_SUPPORT + " arpfilter", +#endif +#ifdef REASSOCIATION + " assocessid", + " assocessid_bssid", +#endif + " associate", + " authtype", + " autotdls", + " bandcfg", + " bcninterval", +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) + " bssrole", +#endif +#endif + " cfgdata", + " cfpcode", + " changraph", + " coex_rx_winsize", + " countrycode", + " customie", + " deauth", + " deepsleep", + " delba", + " delts", +#if defined(DFS_TESTING_SUPPORT) + " dfstesting", +#endif + " dfs_repeater", +#ifdef DEBUG_LEVEL1 + " drvdbg", +#endif + " dscpmap", + " esuppmode", +#ifdef STA_SUPPORT + " extcapcfg", + " cancelscan", +#endif + " fwmacaddr", +/* #ifdef FW_WAKEUP_METHOD */ + " fwwakeupmethod", +/* #endif */ + " getdatarate", + " getlog", +#ifdef STA_SUPPORT + " getscantable", +#endif + " getsignal", +#ifdef UAP_SUPPORT + " getstalist", +#endif + " hostcmd", + " hscfg", + " hssetpara", + " mgmtfilter", + " htcapinfo", + " htstreamcfg", + " mimoswitch", +#ifdef STA_SUPPORT + " signalextcfg", + " getsignalext", + " getsignalextv2", +#endif + " httxbfcap", + " httxbfcfg", + " httxcfg", + " inactivityto", + " ipaddr", + " linkstats", +#ifdef STA_SUPPORT + " listeninterval", +#endif + " macctrl", + " mefcfg", + " memrdwr", +#ifdef WIFI_DIRECT_SUPPORT + " miracastcfg", +#endif + " mgmtframectrl", + " mgmtframetx", + " netmon", +#if defined(WIFI_DIRECT_SUPPORT) +#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + " cfg_noa", + " cfg_opp_ps", +#endif +#endif + " offchannel", + " otpuserdata", + " passphrase", + " pb_bypass", + " pcieregrw", +#if defined(STA_SUPPORT) + " pmfcfg", +#endif + " port_ctrl", + " powercons", + " pscfg", +#ifdef STA_SUPPORT + " psmode", +#endif + " qconfig", + " qoscfg", + " qstatus", +#ifdef STA_WEXT + " radioctrl", +#endif + " rdeeprom", +#if defined(REASSOCIATION) + " reassoctrl", +#endif + " regioncode", + " cfpinfo", + " regrdwr", + " rejectaddbareq", + " scancfg", +#ifdef STA_SUPPORT + " setuserscan", +#endif + " sleepparams", + " sleeppd", + " sysclock", + " tcpackenh", + " tdls_idle_time", + " tdls_channel_switch", + " tdls_config", + " tdls_cs_params", + " tdls_debug", + " tdls_disable_cs", + " tdls_discovery", + " tdls_link_status", + " tdls_powermode", + " tdls_setinfo", + " tdls_setup", + " tdls_stop_channel_switch", + " tdls_teardown", + " thermal", + " ts_status", + " tsf", + " txaggrctrl", + " txbufcfg", + " txcontrol", + " txpowercfg", + " txratecfg", + " verext", + " version", + " vhtcfg", + " opermodecfg", + " wakeupreason", + " warmreset", + " wmmcfg", + " wmmparamcfg", + " wpssession", + " wwscfg", + " mc_cfg", + " mc_policy", + " mc_cfg_ext", +#ifdef RX_PACKET_COALESCE + " rxpktcoal_cfg", +#endif + " get_sensor_temp", + " 11k_enable", + " neighbor_report", + " channel_switch", + " indrstcfg", + " dfs_offload", + + " tx_ampdu_prot_mode", + " cwmode", + " dyn_bw", + " txrxhistogram", + " per_pkt_cfg", + " dot11_txrx", + " ctrldeauth", + " robustcoex", +}; + +/** Socket */ +t_s32 sockfd; +/** Device name */ +char dev_name[IFNAMSIZ + 1]; +#define HOSTCMD "hostcmd" + +#define BSSID_FILTER 1 +#define SSID_FILTER 2 +/******************************************************** + Global Variables +********************************************************/ + +int setuserscan_filter = 0; +int num_ssid_filter = 0; +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief isdigit for String. + * + * @param x Char string + * @return MLAN_STATUS_FAILURE for non-digit. + * MLAN_STATUS_SUCCESS for digit + */ +static int +ISDIGIT(char *x) +{ + unsigned int i; + for (i = 0; i < strlen(x); i++) + if (isdigit(x[i]) == 0) + return MLAN_STATUS_FAILURE; + return MLAN_STATUS_SUCCESS; +} + +/** + * Check of decimal or hex string + * @param num string + */ +#define IS_HEX_OR_DIGIT(num) \ + (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num))) + +/** + * @brief Convert char to hex integer + * + * @param chr Char to convert + * @return Hex integer or 0 + */ +int +hexval(t_s32 chr) +{ + if (chr >= '0' && chr <= '9') + return chr - '0'; + if (chr >= 'A' && chr <= 'F') + return chr - 'A' + 10; + if (chr >= 'a' && chr <= 'f') + return chr - 'a' + 10; + + return 0; +} + +/** + * @brief Hump hex data + * + * @param prompt A pointer prompt buffer + * @param p A pointer to data buffer + * @param len The len of data buffer + * @param delim Delim char + * @return Hex integer + */ +t_void +hexdump(char *prompt, t_void *p, t_s32 len, char delim) +{ + t_s32 i; + t_u8 *s = p; + + if (prompt) { + printf("%s: len=%d\n", prompt, (int)len); + } + for (i = 0; i < len; i++) { + if (i != len - 1) + printf("%02x%c", *s++, delim); + else + printf("%02x\n", *s); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); +} + +/** + * @brief Convert char to hex integer + * + * @param chr Char + * @return Hex integer + */ +t_u8 +hexc2bin(char chr) +{ + if (chr >= '0' && chr <= '9') + chr -= '0'; + else if (chr >= 'A' && chr <= 'F') + chr -= ('A' - 10); + else if (chr >= 'a' && chr <= 'f') + chr -= ('a' - 10); + + return chr; +} + +/** + * @brief Convert string to hex integer + * + * @param s A pointer string buffer + * @return Hex integer + */ +t_u32 +a2hex(char *s) +{ + t_u32 val = 0; + + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + + while (*s && isxdigit(*s)) { + val = (val << 4) + hexc2bin(*s++); + } + + return val; +} + +/* + * @brief Convert String to integer + * + * @param value A pointer to string + * @return Integer + */ +t_u32 +a2hex_or_atoi(char *value) +{ + if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) { + return a2hex(value + 2); + } else { + return (t_u32)atoi(value); + } +} + +/** + * @brief Convert string to hex + * + * @param ptr A pointer to data buffer + * @param chr A pointer to return integer + * @return A pointer to next data field + */ +char * +convert2hex(char *ptr, t_u8 *chr) +{ + t_u8 val; + + for (val = 0; *ptr && isxdigit(*ptr); ptr++) { + val = (val * 16) + hexval(*ptr); + } + + *chr = val; + + return ptr; +} + +/** + * @brief Check the Hex String + * @param s A pointer to the string + * @return MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString + */ +int +ishexstring(char *s) +{ + int ret = MLAN_STATUS_FAILURE; + t_s32 tmp; + + if (!strncasecmp("0x", s, 2)) { + s += 2; + } + while (*s) { + tmp = toupper(*s); + if (((tmp >= 'A') && (tmp <= 'F')) || + ((tmp >= '0') && (tmp <= '9'))) { + ret = MLAN_STATUS_SUCCESS; + } else { + ret = MLAN_STATUS_FAILURE; + break; + } + s++; + } + + return ret; +} + +/** + * @brief Convert String to Integer + * @param buf A pointer to the string + * @return Integer + */ +int +atoval(char *buf) +{ + if (!strncasecmp(buf, "0x", 2)) + return a2hex(buf + 2); + else if (!ishexstring(buf)) + return a2hex(buf); + else + return atoi(buf); +} + +/** + * @brief Display usage + * + * @return NA + */ +static t_void +display_usage(t_void) +{ + t_u32 i; + for (i = 0; i < NELEMENTS(usage); i++) + fprintf(stderr, "%s\n", usage[i]); +} + +/** + * @brief Find and execute command + * + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS for success, otherwise failure + */ +static int +process_command(int argc, char *argv[]) +{ + int i = 0, ret = MLAN_STATUS_NOTFOUND; + struct command_node *node = NULL; + + for (i = 0; i < (int)NELEMENTS(command_list); i++) { + node = &command_list[i]; + if (!strcasecmp(node->name, argv[2])) { + ret = node->handler(argc, argv); + break; + } + } + + return ret; +} + +/** + * @brief Converts a string to hex value + * + * @param str A pointer to the string + * @param raw A pointer to the raw data buffer + * @return Number of bytes read + **/ +int +string2raw(char *str, unsigned char *raw) +{ + int len = (strlen(str) + 1) / 2; + + do { + if (!isxdigit(*str)) { + return -1; + } + *str = toupper(*str); + *raw = CHAR2INT(*str) << 4; + ++str; + *str = toupper(*str); + if (*str == '\0') + break; + *raw |= CHAR2INT(*str); + ++raw; + } while (*++str != '\0'); + return len; +} + +/** + * @brief Prepare command buffer + * @param buffer Command buffer to be filled + * @param cmd Command id + * @param num Number of arguments + * @param args Arguments list + * @return MLAN_STATUS_SUCCESS + */ +static int +prepare_buffer(t_u8 *buffer, char *cmd, t_u32 num, char *args[]) +{ + t_u8 *pos = NULL; + unsigned int i = 0; + + memset(buffer, 0, BUFFER_LENGTH); + + /* Flag it for our use */ + pos = buffer; + strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL)); + pos += (strlen(CMD_MARVELL)); + + /* Insert command */ + strncpy((char *)pos, (char *)cmd, strlen(cmd)); + pos += (strlen(cmd)); + + /* Insert arguments */ + for (i = 0; i < num; i++) { + strncpy((char *)pos, args[i], strlen(args[i])); + pos += strlen(args[i]); + if (i < (num - 1)) { + strncpy((char *)pos, " ", strlen(" ")); + pos += 1; + } + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Determine the netlink number + * + * @param i socket number + * + * @return Netlink number to use + */ +static int +get_netlink_num(int i) +{ + FILE *fp; + int netlink_num = NETLINK_MARVELL; + char str[64]; + char *srch = "netlink_num"; + char filename[64]; + + if (i == 0) { + strcpy(filename, "/proc/mwlan/config"); + } else if (i > 0) { + sprintf(filename, "/proc/mwlan/config%d", i); + } + /* Try to open /proc/mwlan/config$ */ + fp = fopen(filename, "r"); + if (fp) { + while (!feof(fp)) { + fgets(str, sizeof(str), fp); + if (strncmp(str, srch, strlen(srch)) == 0) { + netlink_num = atoi(str + strlen(srch) + 1); + break; + } + } + fclose(fp); + } else { + return -1; + } + return netlink_num; +} + +/** + * @brief Read event data from netlink socket + * + * @param sk_fd Netlink socket handler + * @param buffer Pointer to the data buffer + * @param nlh Pointer to netlink message header + * @param msg Pointer to message header + * + * @return Number of bytes read or MLAN_EVENT_FAILURE + */ +int +read_event_netlink_socket(int sk_fd, unsigned char *buffer, + struct nlmsghdr *nlh, struct msghdr *msg) +{ + int count = -1; + count = recvmsg(sk_fd, msg, 0); +#if DEBUG + printf("DBG:Waiting for message from NETLINK.\n"); +#endif + if (count < 0) { + printf("ERR:NETLINK read failed!\n"); + terminate_flag++; + return MLAN_EVENT_FAILURE; + } +#if DEBUG + printf("DBG:Received message payload (%d)\n", count); +#endif + if (count > NLMSG_SPACE(NL_MAX_PAYLOAD)) { + printf("ERR:Buffer overflow!\n"); + return MLAN_EVENT_FAILURE; + } + memset(buffer, 0, NL_MAX_PAYLOAD); + memcpy(buffer, NLMSG_DATA(nlh), count - NLMSG_HDRLEN); +#if DEBUG + hexdump(buffer, count - NLMSG_HDRLEN, ' '); +#endif + return count - NLMSG_HDRLEN; +} + +/** + * @brief Configure and read event data from netlink socket + * + * @param sk_fd Array of netlink sockets + * @param no_of_sk Number of netlink sockets opened + * @param recv_buf Pointer to the array of evt_buf structures + * @param timeout Socket listen timeout value + * @param nlh Pointer to netlink message header + * @param msg Pointer to message header + * + * @return Number of bytes read or MLAN_EVENT_FAILURE + */ +int +read_event(int *sk_fd, int no_of_sk, evt_buf *recv_buf, int timeout, + struct nlmsghdr *nlh, struct msghdr *msg) +{ + struct timeval tv; + fd_set rfds; + int i = 0, max_sk_fd = sk_fd[0]; + int ret = MLAN_EVENT_FAILURE; + + /* Setup read fds */ + FD_ZERO(&rfds); + for (i = 0; i < no_of_sk; i++) { + if (sk_fd[i] > max_sk_fd) + max_sk_fd = sk_fd[i]; + + if (sk_fd[i] > 0) + FD_SET(sk_fd[i], &rfds); + } + + /* Initialize timeout value */ + if (timeout != 0) + tv.tv_sec = timeout; + else + tv.tv_sec = UAP_RECV_WAIT_DEFAULT; + tv.tv_usec = 0; + + /* Wait for reply */ + ret = select(max_sk_fd + 1, &rfds, NULL, NULL, &tv); + if (ret == -1) { + /* Error */ + terminate_flag++; + return MLAN_EVENT_FAILURE; + } else if (!ret) { + /* Timeout. Try again */ + return MLAN_EVENT_FAILURE; + } + for (i = 0; i < no_of_sk; i++) { + if (sk_fd[i] > 0) { + if (FD_ISSET(sk_fd[i], &rfds)) { + /* Success */ + recv_buf[i].flag = 1; + recv_buf[i].length = + read_event_netlink_socket(sk_fd[i], + recv_buf[i]. + buffer, nlh, + msg); + ret += recv_buf[i].length; + } + } + } + return ret; +} + +/** + * @brief Signal handler + * + * @param sig Received signal number + * + * @return N/A + */ +void +sig_handler(int sig) +{ + printf("Stopping application.\n"); + terminate_flag = 1; +} + +/** + * @brief Wait event specified by event ID, and return back the pointer. + * + * @param eventID Event ID + * @param pEvent Pointer to the Event buffer + * @param pEventLen Pointer to the Event Length + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE + */ +static int +wait_event(t_u32 eventID, t_u8 **pEvent, int *pEventLen) +{ + int nl_sk[MAX_NO_OF_DEVICES]; + struct nlmsghdr *nlh = NULL; + struct sockaddr_nl src_addr, dest_addr; + struct msghdr msg; + struct iovec iov; + evt_buf evt_recv_buf[MAX_NO_OF_DEVICES]; + int num_events = 0; + event_header *event = NULL; + int ret = MLAN_EVENT_FAILURE; + int netlink_num[MAX_NO_OF_DEVICES]; + char if_name[IFNAMSIZ + 1]; + t_u32 event_id = 0; + int i = 0, no_of_sk = 0; + + /* Currently, we support maximum 4 devices */ + /* TODO: determine no_of_sk at run time */ + no_of_sk = MAX_NO_OF_DEVICES; + + for (i = 0; i < no_of_sk; i++) { + /* Initialise */ + nl_sk[i] = -1; + netlink_num[i] = get_netlink_num(i); + if (netlink_num[i] >= 0) { + /* Open netlink socket */ + nl_sk[i] = socket(PF_NETLINK, SOCK_RAW, netlink_num[i]); + if (nl_sk[i] < 0) { + printf("ERR:Could not open netlink socket.\n"); + ret = MLAN_EVENT_FAILURE; + goto done; + } + + /* Set source address */ + memset(&src_addr, 0, sizeof(src_addr)); + src_addr.nl_family = AF_NETLINK; + src_addr.nl_pid = getpid(); /* Our PID */ + src_addr.nl_groups = NL_MULTICAST_GROUP; + + /* Bind socket with source address */ + if (bind + (nl_sk[i], (struct sockaddr *)&src_addr, + sizeof(src_addr)) < 0) { + printf("ERR:Could not bind socket!\n"); + ret = MLAN_EVENT_FAILURE; + goto done; + } + + /* Set destination address */ + memset(&dest_addr, 0, sizeof(dest_addr)); + dest_addr.nl_family = AF_NETLINK; + dest_addr.nl_pid = 0; /* Kernel */ + dest_addr.nl_groups = NL_MULTICAST_GROUP; + + /* Initialize netlink header */ + nlh = (struct nlmsghdr *) + malloc(NLMSG_SPACE(NL_MAX_PAYLOAD)); + if (!nlh) { + printf("ERR: Could not alloc buffer\n"); + ret = MLAN_EVENT_FAILURE; + goto done; + } + memset(nlh, 0, NLMSG_SPACE(NL_MAX_PAYLOAD)); + + /* Initialize I/O vector */ + iov.iov_base = (void *)nlh; + iov.iov_len = NLMSG_SPACE(NL_MAX_PAYLOAD); + + /* Initialize message header */ + memset(&msg, 0, sizeof(struct msghdr)); + msg.msg_name = (void *)&dest_addr; + msg.msg_namelen = sizeof(dest_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + memset(&evt_recv_buf[i], 0, sizeof(evt_buf)); + } + } + + signal(SIGTERM, sig_handler); + signal(SIGINT, sig_handler); + signal(SIGALRM, sig_handler); + while (1) { + if (terminate_flag) { + printf("Stopping!\n"); + break; + } + ret = read_event(nl_sk, no_of_sk, evt_recv_buf, 0, nlh, &msg); + + /* No result. Loop again */ + if (ret == MLAN_EVENT_FAILURE) { + continue; + } + if (ret == 0) { + /* Zero bytes received */ + printf("ERR:Received zero bytes!\n"); + continue; + } + for (i = 0; i < no_of_sk; i++) { + if (evt_recv_buf[i].flag == 1) { + num_events++; + + memcpy(&event_id, evt_recv_buf[i].buffer, + sizeof(event_id)); + if (((event_id & 0xFF000000) == 0x80000000) || + ((event_id & 0xFF000000) == 0)) { + event = (event_header + *)(evt_recv_buf[i].buffer); + } else { + memset(if_name, 0, IFNAMSIZ + 1); + memcpy(if_name, evt_recv_buf[i].buffer, + IFNAMSIZ); + event = (event_header + *)((t_u8 *)(evt_recv_buf[i]. + buffer) + + IFNAMSIZ); + ret -= IFNAMSIZ; + evt_recv_buf[i].length -= IFNAMSIZ; + } + if (event->event_id == eventID) { + *pEvent = (t_u8 *)event; + *pEventLen = evt_recv_buf[i].length; + goto done; + } + /* Reset event flag after reading */ + evt_recv_buf[i].flag = 0; + } + } + fflush(stdout); + } + +done: + for (i = 0; i < no_of_sk; i++) { + if (nl_sk[i] > 0) + close(nl_sk[i]); + } + if (nlh) + free(nlh); + return 0; + +} + +/** + * @brief Set Robustcoex gpiocfg + * + * @param argc Number of arguments + * @param argv Pointer to the arguments array + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE + */ + +static int +process_robustcoex(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd; + struct ifreq ifr; + + if (argc <= 4) { + printf("Err: Invalid number of arguments\n"); + printf("Usage: ./mlanutl robustcoex [gpiocfg] [value]\n"); + return MLAN_STATUS_FAILURE; + } + if (strcmp(argv[3], "gpiocfg") == 0) { + if (argc != 7 && argc != 5) { + printf("ERR: Invalid number of arguments\n"); + printf("Usage: ./mlanutl robustcoex gpiocfg [Enable][Gpionum][Gpiopolarity]\n"); + printf("Usage: ./mlanutl robustcoex gpiocfg [Disable]\n"); + return MLAN_STATUS_FAILURE; + } + } else { + printf("ERR: Invalid arguments\n"); + printf("Usage: ./mlanutl robustcoex [gpiocfg][value]\n"); + return MLAN_STATUS_FAILURE; + } + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: robustcoex fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Do acs scan + * + * @param argc Number of arguments + * @param argv Pointer to the arguments array + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE + */ + +static int +process_acs(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd; + struct ifreq ifr; + acs_result *pacs_result = NULL; + int i = 0; + + if (argc < 3) { + printf("Err: Invalid number of arguments\n"); + printf("Usage: ./mlanutl acs [channels]\n"); + return MLAN_STATUS_FAILURE; + } + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: acs fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + if (cmd->used_len) { + pacs_result = (acs_result *) buffer; + printf("Best Channel: %d\n", pacs_result->best_ch); + if (pacs_result->ch_stats_num) { + printf("Channel Statistics:\n"); + for (i = 0; i < pacs_result->ch_stats_num; i++) + printf("\t[CH %d]\t\ttotal_networks=%d\tcca_busy_duration=%d\n", pacs_result->ch_stats[i].chan_num, pacs_result->ch_stats[i].total_networks, pacs_result->ch_stats[i].cca_busy_duration); + } + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Get one line from the File + * + * @param fp File handler + * @param str Storage location for data. + * @param size Maximum number of characters to read. + * @param lineno A pointer to return current line number + * @return returns string or NULL + */ +char * +mlan_config_get_line(FILE * fp, char *str, t_s32 size, int *lineno) +{ + char *start, *end; + int out, next_line; + + if (!fp || !str) + return NULL; + + do { +read_line: + if (!fgets(str, size, fp)) + break; + start = str; + start[size - 1] = '\0'; + end = start + strlen(str); + (*lineno)++; + + out = 1; + while (out && (start < end)) { + next_line = 0; + /* Remove empty lines and lines starting with # */ + switch (start[0]) { + case ' ': /* White space */ + case '\t': /* Tab */ + start++; + break; + case '#': + case '\n': + case '\0': + next_line = 1; + break; + case '\r': + if (start[1] == '\n') + next_line = 1; + else + start++; + break; + default: + out = 0; + break; + } + if (next_line) + goto read_line; + } + + /* Remove # comments unless they are within a double quoted + * string. Remove trailing white space. */ + end = strstr(start, "\""); + if (end) { + end = strstr(end + 1, "\""); + if (!end) + end = start; + } else + end = start; + + end = strstr(end + 1, "#"); + if (end) + *end-- = '\0'; + else + end = start + strlen(start) - 1; + + out = 1; + while (out && (start < end)) { + switch (*end) { + case ' ': /* White space */ + case '\t': /* Tab */ + case '\n': + case '\r': + *end = '\0'; + end--; + break; + default: + out = 0; + break; + } + } + + if (start == '\0') + continue; + + return start; + } while (1); + + return NULL; +} + +/** + * @brief Parse function for a configuration line + * + * @param s Storage buffer for data + * @param size Maximum size of data + * @param stream File stream pointer + * @param line Pointer to current line within the file + * @param _pos Output string or NULL + * @return String or NULL + */ +static char * +config_get_line(char *s, int size, FILE * stream, int *line, char **_pos) +{ + *_pos = mlan_config_get_line(stream, s, size, line); + return *_pos; +} + +/** + * @brief Converts colon separated MAC address to hex value + * + * @param mac A pointer to the colon separated MAC string + * @param raw A pointer to the hex data buffer + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + * MAC_BROADCAST - if broadcast mac + * MAC_MULTICAST - if multicast mac + */ +static int +mac2raw(char *mac, t_u8 *raw) +{ + unsigned int temp_raw[ETH_ALEN]; + int num_tokens = 0; + int i; + + if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) { + return MLAN_STATUS_FAILURE; + } + num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x", + temp_raw + 0, temp_raw + 1, temp_raw + 2, + temp_raw + 3, temp_raw + 4, temp_raw + 5); + if (num_tokens != ETH_ALEN) { + return MLAN_STATUS_FAILURE; + } + for (i = 0; i < num_tokens; i++) + raw[i] = (t_u8)temp_raw[i]; + + if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { + return MAC_BROADCAST; + } else if (raw[0] & 0x01) { + return MAC_MULTICAST; + } + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Parses a command line + * + * @param line The line to parse + * @param args Pointer to the argument buffer to be filled in + * @return Number of arguments in the line or EOF + */ +static int +parse_line(char *line, char *args[]) +{ + int arg_num = 0; + int is_start = 0; + int is_quote = 0; + int length = 0; + int i = 0; + + arg_num = 0; + length = strlen(line); + /* Process line */ + + /* Find number of arguments */ + is_start = 0; + is_quote = 0; + for (i = 0; i < length; i++) { + /* Ignore leading spaces */ + if (is_start == 0) { + if (line[i] == ' ') { + continue; + } else if (line[i] == '\t') { + continue; + } else if (line[i] == '\n') { + break; + } else { + is_start = 1; + args[arg_num] = &line[i]; + arg_num++; + } + } + if (is_start == 1) { + /* Ignore comments */ + if (line[i] == '#') { + if (is_quote == 0) { + line[i] = '\0'; + arg_num--; + } + break; + } + /* Separate by '=' */ + if (line[i] == '=') { + line[i] = '\0'; + is_start = 0; + continue; + } + /* Separate by ',' */ + if (line[i] == ',') { + line[i] = '\0'; + is_start = 0; + continue; + } + /* Change ',' to ' ', but not inside quotes */ + if ((line[i] == ',') && (is_quote == 0)) { + line[i] = ' '; + continue; + } + } + /* Remove newlines */ + if (line[i] == '\n') { + line[i] = '\0'; + } + /* Check for quotes */ + if (line[i] == '"') { + is_quote = (is_quote == 1) ? 0 : 1; + continue; + } + if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) { + line[i] = '\0'; + is_start = 0; + continue; + } + } + return arg_num; +} + +/** + * @brief Process version + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_version(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: version fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("Version string received: %s\n", buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process band configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_bandcfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + int i; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_bandcfg *bandcfg = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: bandcfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + bandcfg = (struct eth_priv_bandcfg *)buffer; + if (argc == 3) { + /* GET operation */ + printf("Band Configuration:\n"); + printf(" Infra Band: %d (", (int)bandcfg->config_bands); + for (i = 0; i < 7; i++) { + if ((bandcfg->config_bands >> i) & 0x1) + printf(" %s", band[i]); + } + printf(" )\n"); + printf(" Adhoc Start Band: %d (", + (int)bandcfg->adhoc_start_band); + for (i = 0; i < 7; i++) { + if ((bandcfg->adhoc_start_band >> i) & 0x1) + printf(" %s", band[i]); + } + printf(" )\n"); + printf(" Adhoc Start Channel: %d\n", + (int)bandcfg->adhoc_channel); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief get hostcmd data + * + * @param ln A pointer to line number + * @param buf A pointer to hostcmd data + * @param size A pointer to the return size of hostcmd buffer + * @return MLAN_STATUS_SUCCESS + */ +static int +mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size) +{ + t_s32 errors = 0, i; + char line[512], *pos, *pos1, *pos2, *pos3; + t_u16 len; + + while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) { + (*ln)++; + if (strcmp(pos, "}") == 0) { + break; + } + + pos1 = strchr(pos, ':'); + if (pos1 == NULL) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos1++ = '\0'; + + pos2 = strchr(pos1, '='); + if (pos2 == NULL) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos2++ = '\0'; + + len = a2hex_or_atoi(pos1); + if (len < 1 || len > BUFFER_LENGTH) { + printf("Line %d: Invalid hostcmd line '%s'\n", *ln, + pos); + errors++; + continue; + } + + *size += len; + + if (*pos2 == '"') { + pos2++; + pos3 = strchr(pos2, '"'); + if (pos3 == NULL) { + printf("Line %d: invalid quotation '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos3 = '\0'; + memset(buf, 0, len); + memmove(buf, pos2, MIN(strlen(pos2), len)); + buf += len; + } else if (*pos2 == '\'') { + pos2++; + pos3 = strchr(pos2, '\''); + if (pos3 == NULL) { + printf("Line %d: invalid quotation '%s'\n", *ln, + pos); + errors++; + continue; + } + *pos3 = ','; + for (i = 0; i < len; i++) { + pos3 = strchr(pos2, ','); + if (pos3 != NULL) { + *pos3 = '\0'; + *buf++ = (t_u8)a2hex_or_atoi(pos2); + pos2 = pos3 + 1; + } else + *buf++ = 0; + } + } else if (*pos2 == '{') { + t_u16 tlvlen = 0, tmp_tlvlen; + mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen); + tmp_tlvlen = tlvlen; + while (len--) { + *buf++ = (t_u8)(tmp_tlvlen & 0xff); + tmp_tlvlen >>= 8; + } + *size += tlvlen; + buf += tlvlen; + } else { + t_u32 value = a2hex_or_atoi(pos2); + while (len--) { + *buf++ = (t_u8)(value & 0xff); + value >>= 8; + } + } + } + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Prepare host-command buffer + * @param fp File handler + * @param cmd_name Command name + * @param buf A pointer to comand buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf) +{ + char line[256], cmdname[256], *pos, cmdcode[10]; + HostCmd_DS_GEN *hostcmd; + t_u32 hostcmd_size = 0; + int ln = 0; + int cmdname_found = 0, cmdcode_found = 0; + + hostcmd = (HostCmd_DS_GEN *)(buf + sizeof(t_u32)); + hostcmd->command = 0xffff; + + snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name); + cmdname_found = 0; + while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { + if (strcmp(pos, cmdname) == 0) { + cmdname_found = 1; + snprintf(cmdcode, sizeof(cmdcode), "CmdCode="); + cmdcode_found = 0; + while ((pos = + mlan_config_get_line(fp, line, sizeof(line), + &ln))) { + if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) { + cmdcode_found = 1; + hostcmd->command = + a2hex_or_atoi(pos + + strlen(cmdcode)); + hostcmd->size = S_DS_GEN; + mlan_get_hostcmd_data(fp, &ln, + buf + + sizeof(t_u32) + + hostcmd->size, + &hostcmd->size); + break; + } + } + if (!cmdcode_found) { + fprintf(stderr, + "mlanutl: CmdCode not found in conf file\n"); + return MLAN_STATUS_FAILURE; + } + break; + } + } + + if (!cmdname_found) { + fprintf(stderr, + "mlanutl: cmdname '%s' is not found in conf file\n", + cmd_name); + return MLAN_STATUS_FAILURE; + } + + hostcmd->seq_num = 0; + hostcmd->result = 0; + hostcmd->command = cpu_to_le16(hostcmd->command); + hostcmd->size = cpu_to_le16(hostcmd->size); + + hostcmd_size = (t_u32)(hostcmd->size); + memcpy(buf, (t_u8 *)&hostcmd_size, sizeof(t_u32)); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Prints a MAC address in colon separated form from raw data + * + * @param raw A pointer to the hex data buffer + * @return N/A + */ +void +print_mac(t_u8 *raw) +{ + printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0], + (unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3], + (unsigned int)raw[4], (unsigned int)raw[5]); + return; +} + +/** + * @brief Process host_cmd response + * @param cmd_name Command name + * @param buf A pointer to the response buffer + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_host_cmd_resp(char *cmd_name, t_u8 *buf) +{ + t_u32 hostcmd_size = 0; + HostCmd_DS_GEN *hostcmd = NULL; + int ret = MLAN_STATUS_SUCCESS; + + buf += strlen(CMD_MARVELL) + strlen(cmd_name); + memcpy((t_u8 *)&hostcmd_size, buf, sizeof(t_u32)); + buf += sizeof(t_u32); + + hostcmd = (HostCmd_DS_GEN *)buf; + hostcmd->command = le16_to_cpu(hostcmd->command); + hostcmd->size = le16_to_cpu(hostcmd->size); + hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num); + hostcmd->result = le16_to_cpu(hostcmd->result); + + hostcmd->command &= ~HostCmd_RET_BIT; + if (!hostcmd->result) { + switch (hostcmd->command) { + case HostCmd_CMD_CFG_DATA: + { + HostCmd_DS_802_11_CFG_DATA *pstcfgData = + (HostCmd_DS_802_11_CFG_DATA *)(buf + + S_DS_GEN); + pstcfgData->data_len = + le16_to_cpu(pstcfgData->data_len); + pstcfgData->action = + le16_to_cpu(pstcfgData->action); + + if (pstcfgData->action == HostCmd_ACT_GEN_GET) { + hexdump("cfgdata", pstcfgData->data, + pstcfgData->data_len, ' '); + } + break; + } + case HostCmd_CMD_802_11_TPC_ADAPT_REQ: + { + mlan_ioctl_11h_tpc_resp *tpcIoctlResp = + (mlan_ioctl_11h_tpc_resp *)(buf + + S_DS_GEN); + if (tpcIoctlResp->status_code == 0) { + printf("tpcrequest: txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi); + } else { + printf("tpcrequest: failure, status = %d\n", tpcIoctlResp->status_code); + } + break; + } + case HostCmd_CMD_802_11_CRYPTO: + { + t_u16 alg = + le16_to_cpu((t_u16) + *(buf + S_DS_GEN + + sizeof(t_u16))); + if (alg == CIPHER_TEST_AES_CCM || + alg == CIPHER_TEST_GCMP) { + HostCmd_DS_802_11_CRYPTO_AES_CCM + *cmd_aes_ccm = + (HostCmd_DS_802_11_CRYPTO_AES_CCM + *)(buf + S_DS_GEN); + + cmd_aes_ccm->encdec + = + le16_to_cpu(cmd_aes_ccm-> + encdec); + cmd_aes_ccm->algorithm = + le16_to_cpu(cmd_aes_ccm-> + algorithm); + cmd_aes_ccm->key_length = + le16_to_cpu(cmd_aes_ccm-> + key_length); + cmd_aes_ccm->nonce_length = + le16_to_cpu(cmd_aes_ccm-> + nonce_length); + cmd_aes_ccm->AAD_length = + le16_to_cpu(cmd_aes_ccm-> + AAD_length); + cmd_aes_ccm->data.header.type = + le16_to_cpu(cmd_aes_ccm->data. + header.type); + cmd_aes_ccm->data.header.len = + le16_to_cpu(cmd_aes_ccm->data. + header.len); + + printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len); + + hexdump("Key", cmd_aes_ccm->key, + cmd_aes_ccm->key_length, ' '); + hexdump("Nonce", cmd_aes_ccm->nonce, + cmd_aes_ccm->nonce_length, ' '); + hexdump("AAD", cmd_aes_ccm->AAD, + cmd_aes_ccm->AAD_length, ' '); + hexdump("Data", cmd_aes_ccm->data.data, + cmd_aes_ccm->data.header.len, + ' '); + } else if (alg == CIPHER_TEST_WAPI) { + HostCmd_DS_802_11_CRYPTO_WAPI *cmd_wapi + = + (HostCmd_DS_802_11_CRYPTO_WAPI + *) (buf + S_DS_GEN); + + cmd_wapi->encdec + = le16_to_cpu(cmd_wapi->encdec); + cmd_wapi->algorithm + = + le16_to_cpu(cmd_wapi-> + algorithm); + cmd_wapi->key_length = + le16_to_cpu(cmd_wapi-> + key_length); + cmd_wapi->nonce_length = + le16_to_cpu(cmd_wapi-> + nonce_length); + cmd_wapi->AAD_length = + le16_to_cpu(cmd_wapi-> + AAD_length); + + printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_wapi->encdec, cmd_wapi->algorithm, cmd_wapi->key_length, cmd_wapi->nonce_length, cmd_wapi->AAD_length, cmd_wapi->data_length); + + hexdump("Key", cmd_wapi->key, + cmd_wapi->key_length, ' '); + hexdump("Nonce", cmd_wapi->nonce, + cmd_wapi->nonce_length, ' '); + hexdump("AAD", cmd_wapi->AAD, + cmd_wapi->AAD_length, ' '); + } else { + HostCmd_DS_802_11_CRYPTO *cmd = + (HostCmd_DS_802_11_CRYPTO *)(buf + + + S_DS_GEN); + cmd->encdec = le16_to_cpu(cmd->encdec); + cmd->algorithm = + le16_to_cpu(cmd->algorithm); + cmd->key_IV_length = + le16_to_cpu(cmd->key_IV_length); + cmd->key_length = + le16_to_cpu(cmd->key_length); + cmd->data.header.type = + le16_to_cpu(cmd->data.header. + type); + cmd->data.header.len = + le16_to_cpu(cmd->data.header. + len); + + printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len); + hexdump("KeyIV", cmd->keyIV, + cmd->key_IV_length, ' '); + hexdump("Key", cmd->key, + cmd->key_length, ' '); + hexdump("Data", cmd->data.data, + cmd->data.header.len, ' '); + } + break; + } + case HostCmd_CMD_802_11_AUTO_TX: + { + HostCmd_DS_802_11_AUTO_TX *at = + (HostCmd_DS_802_11_AUTO_TX *)(buf + + S_DS_GEN); + + if (le16_to_cpu(at->action) == + HostCmd_ACT_GEN_GET) { + if (S_DS_GEN + sizeof(at->action) == + hostcmd->size) { + printf("auto_tx not configured\n"); + + } else { + MrvlIEtypesHeader_t *header = + &at->auto_tx.header; + + header->type = + le16_to_cpu(header-> + type); + header->len = + le16_to_cpu(header-> + len); + + if ((S_DS_GEN + + sizeof(at->action) + + + sizeof(MrvlIEtypesHeader_t) + + header->len == + hostcmd->size) && + (header->type == + TLV_TYPE_AUTO_TX)) { + + AutoTx_MacFrame_t *atmf + = + &at->auto_tx. + auto_tx_mac_frame; + + printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval)); + printf("Priority: %#x\n", atmf->priority); + printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len)); + printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]); + printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]); + + hexdump("Frame Payload", + atmf->payload, + le16_to_cpu + (atmf-> + frame_len) + - + MLAN_MAC_ADDR_LENGTH + * 2, ' '); + } else { + printf("incorrect auto_tx command response\n"); + } + } + } + break; + } + case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: + { + HostCmd_DS_802_11_SUBSCRIBE_EVENT *se = + (HostCmd_DS_802_11_SUBSCRIBE_EVENT + *)(buf + S_DS_GEN); + if (le16_to_cpu(se->action) == + HostCmd_ACT_GEN_GET) { + int len = + S_DS_GEN + + sizeof + (HostCmd_DS_802_11_SUBSCRIBE_EVENT); + printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n"); + while (len < hostcmd->size) { + MrvlIEtypesHeader_t *header = + (MrvlIEtypesHeader_t + *)(buf + len); + switch (le16_to_cpu + (header->type)) { + case TLV_TYPE_RSSI_LOW: + { + MrvlIEtypes_RssiThreshold_t + *low_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_LOW: + { + MrvlIEtypes_SnrThreshold_t + *low_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no"); + break; + } + case TLV_TYPE_FAILCOUNT: + { + MrvlIEtypes_FailureCount_t + *failure_count + = + (MrvlIEtypes_FailureCount_t + *)(buf + + + len); + printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no"); + break; + } + case TLV_TYPE_BCNMISS: + { + MrvlIEtypes_BeaconsMissed_t + *bcn_missed + = + (MrvlIEtypes_BeaconsMissed_t + *)(buf + + + len); + printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_HIGH: + { + MrvlIEtypes_RssiThreshold_t + *high_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no"); + break; + } + + case TLV_TYPE_SNR_HIGH: + { + MrvlIEtypes_SnrThreshold_t + *high_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_LOW_DATA: + { + MrvlIEtypes_RssiThreshold_t + *low_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_LOW_DATA: + { + MrvlIEtypes_SnrThreshold_t + *low_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no"); + break; + } + case TLV_TYPE_RSSI_HIGH_DATA: + { + MrvlIEtypes_RssiThreshold_t + *high_rssi + = + (MrvlIEtypes_RssiThreshold_t + *)(buf + + + len); + printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no"); + break; + } + case TLV_TYPE_SNR_HIGH_DATA: + { + MrvlIEtypes_SnrThreshold_t + *high_snr + = + (MrvlIEtypes_SnrThreshold_t + *)(buf + + + len); + printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no"); + break; + } + case TLV_TYPE_LINK_QUALITY: + { + MrvlIEtypes_LinkQuality_t + *link_qual + = + (MrvlIEtypes_LinkQuality_t + *)(buf + + + len); + printf("Link Quality Parameters:\n"); + printf("------------------------\n"); + printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no"); + printf("Link SNR Threshold = %d\n", le16_to_cpu(link_qual->link_SNR_thrs)); + printf("Link SNR Frequency = %d\n", le16_to_cpu(link_qual->link_SNR_freq)); + printf("Min Rate Value = %d\n", le16_to_cpu(link_qual->min_rate_val)); + printf("Min Rate Frequency = %d\n", le16_to_cpu(link_qual->min_rate_freq)); + printf("Tx Latency Value = %d\n", le32_to_cpu(link_qual->tx_latency_val)); + printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs)); + + break; + } + case TLV_TYPE_PRE_BEACON_LOST: + { + MrvlIEtypes_PreBeaconLost_t + *pre_bcn_lost + = + (MrvlIEtypes_PreBeaconLost_t + *)(buf + + + len); + printf("------------------------\n"); + printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no"); + printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost); + break; + } + default: + printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len)); + break; + } + + len += (sizeof + (MrvlIEtypesHeader_t) + + + le16_to_cpu(header-> + len)); + } + } + break; + } + case HostCmd_CMD_MAC_REG_ACCESS: + case HostCmd_CMD_BBP_REG_ACCESS: + case HostCmd_CMD_RF_REG_ACCESS: + case HostCmd_CMD_CAU_REG_ACCESS: + { + HostCmd_DS_REG *preg = + (HostCmd_DS_REG *)(buf + S_DS_GEN); + preg->action = le16_to_cpu(preg->action); + if (preg->action == HostCmd_ACT_GEN_GET) { + preg->value = le32_to_cpu(preg->value); + printf("value = 0x%08x\n", preg->value); + } + break; + } + case HostCmd_CMD_MEM_ACCESS: + { + HostCmd_DS_MEM *pmem = + (HostCmd_DS_MEM *)(buf + S_DS_GEN); + pmem->action = le16_to_cpu(pmem->action); + if (pmem->action == HostCmd_ACT_GEN_GET) { + pmem->value = le32_to_cpu(pmem->value); + printf("value = 0x%08x\n", pmem->value); + } + break; + } + case HostCmd_CMD_LINK_STATS_SUMMARY: + { + HostCmd_DS_LINK_STATS_SUMMARY *linkstats = + (HostCmd_DS_LINK_STATS_SUMMARY *)(buf + + S_DS_GEN); + /* GET operation */ + printf("Link Statistics: \n"); + /* format */ + printf("Duration: %u\n", + (int)le32_to_cpu(linkstats-> + timeSinceLastQuery_ms)); + + printf("Beacon count: %u\n", + le16_to_cpu(linkstats->bcnCnt)); + printf("Beacon missing: %u\n", + le16_to_cpu(linkstats->bcnMiss)); + printf("Beacon RSSI avg: %d\n", + le16_to_cpu(linkstats->bcnRssiAvg)); + printf("Beacon SNR avg: %d\n", + le16_to_cpu(linkstats->bcnSnrAvg)); + + printf("Rx packets: %u\n", + (int)le32_to_cpu(linkstats->rxPkts)); + printf("Rx RSSI avg: %d\n", + le16_to_cpu(linkstats->rxRssiAvg)); + printf("Rx SNR avg: %d\n", + le16_to_cpu(linkstats->rxSnrAvg)); + + printf("Tx packets: %u\n", + (int)le32_to_cpu(linkstats->txPkts)); + printf("Tx Attempts: %u\n", + (int)le32_to_cpu(linkstats->txAttempts)); + printf("Tx Failures: %u\n", + (int)le32_to_cpu(linkstats->txFailures)); + printf("Tx Initial Rate: %s\n", + rateIdStr[linkstats->txInitRate]); + + printf("Tx AC VO: %u [ %u ]\n", + le16_to_cpu(linkstats-> + txQueuePktCnt[WMM_AC_VO]), + (int)le32_to_cpu(linkstats-> + txQueueDelay[WMM_AC_VO]) + / 1000); + printf("Tx AC VI: %u [ %u ]\n", + le16_to_cpu(linkstats-> + txQueuePktCnt[WMM_AC_VI]), + (int)le32_to_cpu(linkstats-> + txQueueDelay[WMM_AC_VI]) + / 1000); + printf("Tx AC BE: %u [ %u ]\n", + le16_to_cpu(linkstats-> + txQueuePktCnt[WMM_AC_BE]), + (int)le32_to_cpu(linkstats-> + txQueueDelay[WMM_AC_BE]) + / 1000); + printf("Tx AC BK: %u [ %u ]\n", + le16_to_cpu(linkstats-> + txQueuePktCnt[WMM_AC_BK]), + (int)le32_to_cpu(linkstats-> + txQueueDelay[WMM_AC_BK]) + / 1000); + break; + } + case HostCmd_CMD_WMM_PARAM_CONFIG: + { + HostCmd_DS_WMM_PARAM_CONFIG *wmm_param = + (HostCmd_DS_WMM_PARAM_CONFIG *) (buf + + S_DS_GEN); + printf("WMM Params: \n"); + printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_BE].aci_aifsn.aifsn, wmm_param->ac_params[AC_BE].ecw.ecw_max, wmm_param->ac_params[AC_BE].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_BE].tx_op_limit)); + printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_BK].aci_aifsn.aifsn, wmm_param->ac_params[AC_BK].ecw.ecw_max, wmm_param->ac_params[AC_BK].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_BK].tx_op_limit)); + printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_VI].aci_aifsn.aifsn, wmm_param->ac_params[AC_VI].ecw.ecw_max, wmm_param->ac_params[AC_VI].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_VI].tx_op_limit)); + printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_VO].aci_aifsn.aifsn, wmm_param->ac_params[AC_VO].ecw.ecw_max, wmm_param->ac_params[AC_VO].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_VO].tx_op_limit)); + break; + } + default: + printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x," + " SeqNum=%#04x, Result=%#04x\n", + hostcmd->command, hostcmd->size, + hostcmd->seq_num, hostcmd->result); + hexdump("payload", + (t_void *)(buf + S_DS_GEN), + hostcmd->size - S_DS_GEN, ' '); + break; + } + } else { + printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x," + " SeqNum=%#04x, Result=%#04x\n", + hostcmd->command, hostcmd->size, + hostcmd->seq_num, hostcmd->result); + } + return ret; +} + +/** + * @brief Trims leading and traling spaces only + * @param str A pointer to argument string + * @return pointer to trimmed string + */ +char * +trim_spaces(char *str) +{ + char *str_end = NULL; + + if (!str) + return NULL; + + /* Trim leading spaces */ + while (!*str && isspace(*str)) + str++; + + if (*str == 0) /* All spaces? */ + return str; + + /* Trim trailing spaces */ + str_end = str + strlen(str) - 1; + while (str_end > str && isspace(*str_end)) + str_end--; + + /* null terminate the string */ + *(str_end + 1) = '\0'; + + return str; +} + +/** + * @brief Process hostcmd command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_hostcmd(int argc, char *argv[]) +{ + t_u8 *buffer = NULL, *raw_buf = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + FILE *fp = NULL; + FILE *fp_raw = NULL; + FILE *fp_dtsi = NULL; + char cmdname[256]; + boolean call_ioctl = TRUE; + t_u32 buf_len = 0, i, j, k; + char *line = NULL, *pos = NULL; + int li = 0, blk_count = 0, ob = 0; + int ret = MLAN_STATUS_SUCCESS; + + struct cmd_node { + char cmd_string[256]; + struct cmd_node *next; + }; + struct cmd_node *command = NULL, *header = NULL, *new_node = NULL; + + if (argc < 5) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./mlanutl mlanX hostcmd \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + snprintf(cmdname, sizeof(cmdname), "%s", argv[4]); + + if (!strcmp(cmdname, "generate_raw")) { + call_ioctl = FALSE; + } + + if (!call_ioctl && argc != 6) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./mlanutl mlanX hostcmd %s \n", cmdname); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + fp = fopen(argv[3], "r"); + if (fp == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[3]); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + if (call_ioctl) { + /* Prepare the hostcmd buffer */ + prepare_buffer(buffer, argv[2], 0, NULL); + if (MLAN_STATUS_FAILURE == + prepare_host_cmd_buffer(fp, cmdname, + buffer + strlen(CMD_MARVELL) + + strlen(argv[2]))) { + fclose(fp); + ret = MLAN_STATUS_FAILURE; + goto done; + } + fclose(fp); + } else { + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + fclose(fp); + ret = MLAN_STATUS_FAILURE; + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + while (config_get_line(line, MAX_CONFIG_LINE, fp, &li, &pos)) { + line = trim_spaces(line); + if (line[strlen(line) - 1] == '{') { + if (ob == 0) { + new_node = + (struct cmd_node *) + malloc(sizeof(struct cmd_node)); + if (!new_node) { + printf("ERR:Cannot allocate memory for cmd_node\n"); + fclose(fp); + ret = MLAN_STATUS_FAILURE; + goto done; + } + memset(new_node, 0, + sizeof(struct cmd_node)); + new_node->next = NULL; + if (blk_count == 0) { + header = new_node; + command = new_node; + } else { + command->next = new_node; + command = new_node; + } + strncpy(command->cmd_string, line, + (strchr(line, '=') - line)); + memmove(command->cmd_string, + trim_spaces(command-> + cmd_string), + strlen(trim_spaces + (command->cmd_string)) + + 1); + } + ob++; + continue; /* goto while() */ + } + if (line[strlen(line) - 1] == '}') { + ob--; + if (ob == 0) + blk_count++; + continue; /* goto while() */ + } + } + + rewind(fp); /* Set the source file pointer to the beginning again */ + command = header; /* Set 'command' at the beginning of the command list */ + + fp_raw = fopen(argv[5], "w"); + if (fp_raw == NULL) { + fprintf(stderr, + "Cannot open the destination raw_data file %s\n", + argv[5]); + fclose(fp); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* prepare .dtsi output */ + snprintf(cmdname, sizeof(cmdname), "%s.dtsi", argv[5]); + fp_dtsi = fopen(cmdname, "w"); + if (fp_dtsi == NULL) { + fprintf(stderr, "Cannot open the destination file %s\n", + cmdname); + fclose(fp); + fclose(fp_raw); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + for (k = 0; k < blk_count && command != NULL; k++) { + if (MLAN_STATUS_FAILURE == + prepare_host_cmd_buffer(fp, command->cmd_string, + buffer)) + memset(buffer, 0, BUFFER_LENGTH); + + memcpy(&buf_len, buffer, sizeof(t_u32)); + if (buf_len) { + raw_buf = buffer + sizeof(t_u32); /* raw_buf points to start of actual */ + printf("buf_len = %d\n", (int)buf_len); + if (k > 0) + fprintf(fp_raw, "\n\n"); + fprintf(fp_raw, "%s={\n", command->cmd_string); + fprintf(fp_dtsi, + "/ {\n\tmarvell_cfgdata {\n\t\tmarvell,%s = /bits/ 8 <\n", + command->cmd_string); + i = j = 0; + while (i < buf_len) { + for (j = 0; j < 16; j++) { + fprintf(fp_raw, "%02x ", + *(raw_buf + i)); + if (i >= 8) { + fprintf(fp_dtsi, + "0x%02x", + *(raw_buf + i)); + if ((j < 16 - 1) && + (i < buf_len - 1)) + fprintf(fp_dtsi, + " "); + } + if (++i >= buf_len) + break; + } + fputc('\n', fp_raw); + fputc('\n', fp_dtsi); + } + fprintf(fp_raw, "}"); + fprintf(fp_dtsi, "\t\t>;\n\t};\n};\n"); + } + command = command->next; + rewind(fp); + } + + fclose(fp_dtsi); + fclose(fp_raw); + fclose(fp); + } + + if (call_ioctl) { + cmd = (struct eth_priv_cmd *) + malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: hostcmd fail\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Process result */ + process_host_cmd_resp(argv[2], buffer); + } + +done: + while (header) { + command = header; + header = header->next; + free(command); + } + if (line) + free(line); + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return ret; +} + +/** + * @brief Process HT Tx configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_httxcfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + t_u32 *data = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: httxcfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (argc == 3) { + /* Get result */ + data = (t_u32 *)buffer; + printf("HT Tx cfg: \n"); + printf(" BG band: 0x%08x\n", data[0]); + printf(" A band: 0x%08x\n", data[1]); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process HT capability configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_htcapinfo(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_htcapinfo *ht_cap = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: htcapinfo fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + if (argc == 3) { + ht_cap = (struct eth_priv_htcapinfo *)buffer; + printf("HT cap info: \n"); + printf(" BG band: 0x%08x\n", ht_cap->ht_cap_info_bg); + printf(" A band: 0x%08x\n", ht_cap->ht_cap_info_a); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process HT Add BA parameters + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_addbapara(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + struct eth_priv_addba *addba = NULL; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: addbapara fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (argc == 3) { + /* Get */ + addba = (struct eth_priv_addba *)buffer; + printf("Add BA configuration: \n"); + printf(" Time out : %d\n", addba->time_out); + printf(" TX window: %d\n", addba->tx_win_size); + printf(" RX window: %d\n", addba->rx_win_size); + printf(" TX AMSDU : %d\n", addba->tx_amsdu); + printf(" RX AMSDU : %d\n", addba->rx_amsdu); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process Aggregation priority table parameters + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_aggrpriotbl(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int i; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: aggrpriotbl fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (argc == 3) { + /* Get */ + printf("Aggregation priority table cfg: \n"); + printf(" TID AMPDU AMSDU \n"); + for (i = 0; i < MAX_NUM_TID; i++) { + printf(" %d %3d %3d \n", + i, buffer[2 * i], buffer[2 * i + 1]); + } + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process HT Add BA reject configurations + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_addbareject(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int i; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: addbareject fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (argc == 3) { + /* Get */ + printf("Add BA reject configuration: \n"); + printf(" TID Reject \n"); + for (i = 0; i < MAX_NUM_TID; i++) { + printf(" %d %d\n", i, buffer[i]); + } + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process HT Del BA command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_delba(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: delba fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process reject addba req command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_rejectaddbareq(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: rejectaddbareq fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("Reject addba req command response: %s\n", buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process VHT configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_vhtcfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_vhtcfg vhtcfg; + struct ifreq ifr; + t_u8 i, num = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* Sanity tests */ + if (argc < 5) { + printf("Insufficient parameters\n"); + printf("For STA interface: mlanutl mlanX vhtcfg [bwcfg] [vhtcap]\n"); + printf("For uAP interface: mlanutl uapX vhtcfg [bwcfg] [vhtcap] [vht_tx_mcs] [vht_rx_mcs]\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: vhtcfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + /* the first attribute is the number of vhtcfg entries */ + num = *buffer; + if (argc == 5) { + /* GET operation */ + printf("11AC VHT Configuration: \n"); + for (i = 0; i < num; i++) { + memcpy(&vhtcfg, buffer + 1 + i * sizeof(vhtcfg), + sizeof(vhtcfg)); + /* Band */ + if (vhtcfg.band == 1) + printf("Band: 2.4G\n"); + else + printf("Band: 5G\n"); + /* BW confi9 */ + + if (vhtcfg.bwcfg == 0) + printf(" BW config: Follow BW in the 11N config\n"); + else + printf(" BW config: Follow BW in VHT Capabilities\n"); + + /* Tx/Rx */ + if (vhtcfg.txrx & 0x1) + printf(" VHT operation for Tx: 0x%08x\n", + vhtcfg.vht_cap_info); + if (vhtcfg.txrx & 0x2) + /* VHT capabilities */ + printf(" VHT Capabilities Info: 0x%08x\n", + vhtcfg.vht_cap_info); + /* MCS */ + if (vhtcfg.txrx & 0x2) { + printf(" Tx MCS set: 0x%04x\n", + vhtcfg.vht_tx_mcs); + printf(" Rx MCS set: 0x%04x\n", + vhtcfg.vht_rx_mcs); + } + } + } else { + /* SET operation */ + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process Operating Mode Notification configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_opermodecfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_opermodecfg *cfg = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: opermodecfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + cfg = (struct eth_priv_opermodecfg *)(buffer); + printf("11AC Operating Mode Notification Configuration: \n"); + printf(" bw: %d\n", cfg->bw); + printf(" nss: %d\n", cfg->nss); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +static char *rate_format[3] = { "LG", "HT", "VHT" }; + +static char *lg_rate[] = { "1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps", + "6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps", + "24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps" +}; + +/** + * @brief Process Get data rate + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_datarate(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_data_rate *datarate = NULL; + struct ifreq ifr; + char *bw[] = { "20 MHz", "40 MHz", "80 MHz", "160 MHz" }; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: getdatarate fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + datarate = (struct eth_priv_data_rate *)buffer; + printf("Data Rate:\n"); + printf(" TX: \n"); + if (datarate->tx_rate_format <= 2) { + printf(" Type: %s\n", rate_format[datarate->tx_rate_format]); + if ((datarate->tx_rate_format == 0) && + datarate->tx_data_rate <= 11) + /* LG */ + printf(" Rate: %s\n", + lg_rate[datarate->tx_data_rate]); + else { + /* HT and VHT */ + if (datarate->tx_bw <= 3) + printf(" BW: %s\n", bw[datarate->tx_bw]); + if (datarate->tx_gi == 0) + printf(" GI: Long\n"); + else + printf(" GI: Short\n"); + if (datarate->tx_rate_format == 3) + printf(" NSS: %d\n", datarate->tx_nss); + if (datarate->tx_mcs_index != 0xFF) + printf(" MCS: MCS %d\n", + (int)datarate->tx_mcs_index); + else + printf(" MCS: Auto\n"); + printf(" Rate: %f Mbps\n", + (float)datarate->tx_data_rate / 2); + } + } + + printf(" RX: \n"); + if (datarate->rx_rate_format <= 2) { + printf(" Type: %s\n", rate_format[datarate->rx_rate_format]); + if ((datarate->rx_rate_format == 0) && + datarate->rx_data_rate <= 11) + /* LG */ + printf(" Rate: %s\n", + lg_rate[datarate->rx_data_rate]); + else { + /* HT and VHT */ + if (datarate->rx_bw <= 3) + printf(" BW: %s\n", bw[datarate->rx_bw]); + if (datarate->rx_gi == 0) + printf(" GI: Long\n"); + else + printf(" GI: Short\n"); + if (datarate->rx_rate_format == 3) + printf(" NSS: %d\n", datarate->rx_nss); + if (datarate->rx_mcs_index != 0xFF) + printf(" MCS: MCS %d\n", + (int)datarate->rx_mcs_index); + else + printf(" MCS: Auto\n"); + printf(" Rate: %f Mbps\n", + (float)datarate->rx_data_rate / 2); + } + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tx rate configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_txratecfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_tx_rate_cfg *txratecfg = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: txratecfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + txratecfg = (struct eth_priv_tx_rate_cfg *)buffer; + if (argc == 3) { + /* GET operation */ + printf("Tx Rate Configuration: \n"); + /* format */ + if (txratecfg->rate_format == 0xFF) { + printf(" Type: 0xFF (Auto)\n"); + } else if (txratecfg->rate_format <= 2) { + printf(" Type: %d (%s)\n", + txratecfg->rate_format, + rate_format[txratecfg->rate_format]); + if (txratecfg->rate_format == 0) + printf(" Rate Index: %d (%s)\n", + txratecfg->rate_index, + lg_rate[txratecfg->rate_index]); + else if (txratecfg->rate_format >= 1) + printf(" MCS Index: %d\n", + (int)txratecfg->rate_index); + if (txratecfg->rate_format == 2) + printf(" NSS: %d\n", + (int)txratecfg->nss); + } else { + printf(" Unknown rate format.\n"); + } + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process get wireless stats + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_getlog(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_get_log *stats = NULL; + struct ifreq ifr; + struct timeval tv; + int i = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: getlog fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + gettimeofday(&tv, NULL); + + /* Process results */ + stats = (struct eth_priv_get_log *)buffer; + printf("Get log: timestamp %d.%06d sec\n", (int)tv.tv_sec, + (int)tv.tv_usec); + printf("dot11GroupTransmittedFrameCount %u\n" + "dot11FailedCount %u\n" + "dot11RetryCount %u\n" + "dot11MultipleRetryCount %u\n" + "dot11FrameDuplicateCount %u\n" + "dot11RTSSuccessCount %u\n" + "dot11RTSFailureCount %u\n" + "dot11ACKFailureCount %u\n" + "dot11ReceivedFragmentCount %u\n" + "dot11GroupReceivedFrameCount %u\n" + "dot11FCSErrorCount %u\n" + "dot11TransmittedFrameCount %u\n" + "wepicverrcnt-1 %u\n" + "wepicverrcnt-2 %u\n" + "wepicverrcnt-3 %u\n" + "wepicverrcnt-4 %u\n" + "beaconReceivedCount %u\n" + "beaconMissedCount %u\n", stats->mcast_tx_frame, + stats->failed, stats->retry, stats->multi_retry, + stats->frame_dup, stats->rts_success, stats->rts_failure, + stats->ack_failure, stats->rx_frag, stats->mcast_rx_frame, + stats->fcs_error, stats->tx_frame, stats->wep_icv_error[0], + stats->wep_icv_error[1], stats->wep_icv_error[2], + stats->wep_icv_error[3], stats->bcn_rcv_cnt, + stats->bcn_miss_cnt); + if (cmd->used_len == sizeof(struct eth_priv_get_log)) { + printf("dot11TransmittedFragmentCount %u\n", + stats->tx_frag_cnt); + printf("dot11QosTransmittedFragmentCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_tx_frag_cnt[i]); + } + printf("\ndot11QosFailedCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_failed_cnt[i]); + } + printf("\ndot11QosRetryCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_retry_cnt[i]); + } + printf("\ndot11QosMultipleRetryCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_multi_retry_cnt[i]); + } + printf("\ndot11QosFrameDuplicateCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_frm_dup_cnt[i]); + } + printf("\ndot11QosRTSSuccessCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_rts_suc_cnt[i]); + } + printf("\ndot11QosRTSFailureCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_rts_failure_cnt[i]); + } + printf("\ndot11QosACKFailureCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_ack_failure_cnt[i]); + } + printf("\ndot11QosReceivedFragmentCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_rx_frag_cnt[i]); + } + printf("\ndot11QosTransmittedFrameCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_tx_frm_cnt[i]); + } + printf("\ndot11QosDiscardedFrameCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_discarded_frm_cnt[i]); + } + printf("\ndot11QosMPDUsReceivedCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_mpdus_rx_cnt[i]); + } + printf("\ndot11QosRetriesReceivedCount "); + for (i = 0; i < 8; i++) { + printf("%u ", stats->qos_retries_rx_cnt[i]); + } + printf("\ndot11RSNAStatsCMACICVErrors %u\n" + "dot11RSNAStatsCMACReplays %u\n" + "dot11RSNAStatsRobustMgmtCCMPReplays %u\n" + "dot11RSNAStatsTKIPICVErrors %u\n" + "dot11RSNAStatsTKIPReplays %u\n" + "dot11RSNAStatsCCMPDecryptErrors %u\n" + "dot11RSNAstatsCCMPReplays %u\n" + "dot11TransmittedAMSDUCount %u\n" + "dot11FailedAMSDUCount %u\n" + "dot11RetryAMSDUCount %u\n" + "dot11MultipleRetryAMSDUCount %u\n" + "dot11TransmittedOctetsInAMSDUCount %llu\n" + "dot11AMSDUAckFailureCount %u\n" + "dot11ReceivedAMSDUCount %u\n" + "dot11ReceivedOctetsInAMSDUCount %llu\n" + "dot11TransmittedAMPDUCount %u\n" + "dot11TransmittedMPDUsInAMPDUCount %u\n" + "dot11TransmittedOctetsInAMPDUCount %llu\n" + "dot11AMPDUReceivedCount %u\n" + "dot11MPDUInReceivedAMPDUCount %u\n" + "dot11ReceivedOctetsInAMPDUCount %llu\n" + "dot11AMPDUDelimiterCRCErrorCount %u\n", + stats->cmacicv_errors, + stats->cmac_replays, + stats->mgmt_ccmp_replays, + stats->tkipicv_errors, + stats->tkip_replays, + stats->ccmp_decrypt_errors, + stats->ccmp_replays, + stats->tx_amsdu_cnt, + stats->failed_amsdu_cnt, + stats->retry_amsdu_cnt, + stats->multi_retry_amsdu_cnt, + stats->tx_octets_in_amsdu_cnt, + stats->amsdu_ack_failure_cnt, + stats->rx_amsdu_cnt, + stats->rx_octets_in_amsdu_cnt, + stats->tx_ampdu_cnt, + stats->tx_mpdus_in_ampdu_cnt, + stats->tx_octets_in_ampdu_cnt, + stats->ampdu_rx_cnt, + stats->mpdu_in_rx_ampdu_cnt, + stats->rx_octets_in_ampdu_cnt, + stats->ampdu_delimiter_crc_error_cnt); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process esuppmode command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_esuppmode(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_esuppmode_cfg *esuppmodecfg = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: esuppmode fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + esuppmodecfg = (struct eth_priv_esuppmode_cfg *)buffer; + if (argc == 3) { + /* GET operation */ + printf("Esupplicant Mode Configuration: \n"); + /* RSN mode */ + printf(" RSN mode: 0x%x ( ", esuppmodecfg->rsn_mode); + if (esuppmodecfg->rsn_mode & MBIT(0)) + printf("No-RSN "); + if (esuppmodecfg->rsn_mode & MBIT(3)) + printf("WPA "); + if (esuppmodecfg->rsn_mode & MBIT(4)) + printf("WPA-None "); + if (esuppmodecfg->rsn_mode & MBIT(5)) + printf("WPA2 "); + printf(")\n"); + /* Pairwise cipher */ + printf(" Pairwise cipher: 0x%x ( ", + esuppmodecfg->pairwise_cipher); + if (esuppmodecfg->pairwise_cipher & MBIT(2)) + printf("TKIP "); + if (esuppmodecfg->pairwise_cipher & MBIT(3)) + printf("AES "); + printf(")\n"); + /* Group cipher */ + printf(" Group cipher: 0x%x ( ", + esuppmodecfg->group_cipher); + if (esuppmodecfg->group_cipher & MBIT(2)) + printf("TKIP "); + if (esuppmodecfg->group_cipher & MBIT(3)) + printf("AES "); + printf(")\n"); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process passphrase command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_passphrase(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* The argument being a string, this requires special handling */ + prepare_buffer(buffer, argv[2], 0, NULL); + if (argc >= 4) { + strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])), + argv[3]); + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: passphrase fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("Passphrase Configuration: %s\n", (char *)buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process deauth command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_deauth(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* The argument being a string, this requires special handling */ + prepare_buffer(buffer, argv[2], 0, NULL); + if (argc >= 4) { + strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])), + argv[3]); + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: deauth fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +#ifdef UAP_SUPPORT +/** + * @brief Process getstalist command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_getstalist(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + struct eth_priv_getstalist *list = NULL; + int i = 0, rssi = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* The argument being a string, this requires special handling */ + prepare_buffer(buffer, argv[2], 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: getstalist fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + list = (struct eth_priv_getstalist *)(buffer + strlen(CMD_MARVELL) + + strlen(argv[2])); + + printf("Number of STA = %d\n\n", list->sta_count); + + for (i = 0; i < list->sta_count; i++) { + printf("STA %d information:\n", i + 1); + printf("=====================\n"); + printf("MAC Address: "); + print_mac(list->client_info[i].mac_address); + printf("\nPower mfg status: %s\n", + (list->client_info[i].power_mfg_status == + 0) ? "active" : "power save"); + + /** On some platform, s8 is same as unsigned char*/ + rssi = (int)list->client_info[i].rssi; + if (rssi > 0x7f) + rssi = -(256 - rssi); + printf("Rssi : %d dBm\n\n", rssi); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} +#endif + +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) +/** + * @brief Process BSS role command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_bssrole(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: bssrole fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + if (argc == 3) { + /* GET operation */ + printf("BSS role: %d\n", buffer[0]); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} +#endif +#endif + +#ifdef STA_SUPPORT +/** + * @brief Helper function for process_getscantable_idx + * + * @param pbuf A pointer to the buffer + * @param buf_len Buffer length + * + * @return NA + * + */ +static void +dump_scan_elems(const t_u8 *pbuf, uint buf_len) +{ + uint idx; + uint marker = 2 + pbuf[1]; + + for (idx = 0; idx < buf_len; idx++) { + if (idx % 0x10 == 0) { + printf("\n%04x: ", idx); + } + + if (idx == marker) { + printf("|"); + marker = idx + pbuf[idx + 1] + 2; + } else { + printf(" "); + } + + printf("%02x ", pbuf[idx]); + } + + printf("\n"); +} + +/** + * @brief Helper function for process_getscantable_idx + * Find next element + * + * @param pp_ie_out Pointer of a IEEEtypes_Generic_t structure pointer + * @param p_buf_left Integer pointer, which contains the number of left p_buf + * + * @return MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE + */ +static int +scantable_elem_next(IEEEtypes_Generic_t **pp_ie_out, int *p_buf_left) +{ + IEEEtypes_Generic_t *pie_gen; + t_u8 *p_next; + + if (*p_buf_left < 2) { + return MLAN_STATUS_FAILURE; + } + + pie_gen = *pp_ie_out; + + p_next = (t_u8 *)pie_gen + (pie_gen->ieee_hdr.len + + sizeof(pie_gen->ieee_hdr)); + *p_buf_left -= (p_next - (t_u8 *)pie_gen); + + *pp_ie_out = (IEEEtypes_Generic_t *)p_next; + + if (*p_buf_left <= 0) { + return MLAN_STATUS_FAILURE; + } + + return MLAN_STATUS_SUCCESS; +} + + /** + * @brief Helper function for process_getscantable_idx + * scantable find element + * + * @param ie_buf Pointer of the IE buffer + * @param ie_buf_len IE buffer length + * @param ie_type IE type + * @param ppie_out Pointer to the IEEEtypes_Generic_t structure pointer + * @return MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE + */ +static int +scantable_find_elem(t_u8 *ie_buf, + unsigned int ie_buf_len, + IEEEtypes_ElementId_e ie_type, + IEEEtypes_Generic_t **ppie_out) +{ + int found; + unsigned int ie_buf_left; + + ie_buf_left = ie_buf_len; + + found = FALSE; + + *ppie_out = (IEEEtypes_Generic_t *)ie_buf; + + do { + found = ((*ppie_out)->ieee_hdr.element_id == ie_type); + + } while (!found && + (scantable_elem_next(ppie_out, (int *)&ie_buf_left) == 0)); + + if (!found) { + *ppie_out = NULL; + } + + return found ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE; +} + + /** + * @brief Helper function for process_getscantable_idx + * It gets SSID from IE + * + * @param ie_buf IE buffer + * @param ie_buf_len IE buffer length + * @param pssid SSID + * @param ssid_buf_max Size of SSID + * @return MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE + */ +static int +scantable_get_ssid_from_ie(t_u8 *ie_buf, + unsigned int ie_buf_len, + t_u8 *pssid, unsigned int ssid_buf_max) +{ + int retval; + IEEEtypes_Generic_t *pie_gen; + + retval = scantable_find_elem(ie_buf, ie_buf_len, SSID, &pie_gen); + if (retval == MLAN_STATUS_SUCCESS) + memcpy(pssid, pie_gen->data, + MIN(pie_gen->ieee_hdr.len, ssid_buf_max)); + else + return MLAN_STATUS_FAILURE; + + return retval; +} + +/** + * @brief Display detailed information for a specific scan table entry + * + * @param cmd_name Command name + * @param prsp_info_req Scan table entry request structure + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_getscantable_idx(char *cmd_name, + wlan_ioctl_get_scan_table_info *prsp_info_req) +{ + int ret = 0; + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + t_u8 *pcurrent; + char ssid[33]; + t_u16 tmp_cap; + t_u8 tsf[8]; + t_u16 beacon_interval; + t_u16 cap_info; + wlan_ioctl_get_scan_table_info *prsp_info; + + wlan_get_scan_table_fixed fixed_fields; + t_u32 fixed_field_length; + t_u32 bss_info_length; + + memset(ssid, 0x00, sizeof(ssid)); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, cmd_name, 0, NULL); + + prsp_info = + (wlan_ioctl_get_scan_table_info *)(buffer + + strlen(CMD_MARVELL) + + strlen(cmd_name)); + + memcpy(prsp_info, prsp_info_req, + sizeof(wlan_ioctl_get_scan_table_info)); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* + * Set up and execute the ioctl call + */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + if (errno == EAGAIN) { + ret = -EAGAIN; + } else { + perror("mlanutl"); + fprintf(stderr, "mlanutl: getscantable fail\n"); + ret = MLAN_STATUS_FAILURE; + } + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return ret; + } + + prsp_info = (wlan_ioctl_get_scan_table_info *)buffer; + if (prsp_info->scan_number == 0) { + printf("mlanutl: getscantable ioctl - index out of range\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return -EINVAL; + } + + pcurrent = prsp_info->scan_table_entry_buf; + + memcpy((t_u8 *)&fixed_field_length, + (t_u8 *)pcurrent, sizeof(fixed_field_length)); + pcurrent += sizeof(fixed_field_length); + + memcpy((t_u8 *)&bss_info_length, + (t_u8 *)pcurrent, sizeof(bss_info_length)); + pcurrent += sizeof(bss_info_length); + + memcpy((t_u8 *)&fixed_fields, (t_u8 *)pcurrent, sizeof(fixed_fields)); + pcurrent += fixed_field_length; + + /* Time stamp is 8 byte long */ + memcpy(tsf, pcurrent, sizeof(tsf)); + pcurrent += sizeof(tsf); + bss_info_length -= sizeof(tsf); + + /* Beacon interval is 2 byte long */ + memcpy(&beacon_interval, pcurrent, sizeof(beacon_interval)); + pcurrent += sizeof(beacon_interval); + bss_info_length -= sizeof(beacon_interval); + + /* Capability information is 2 byte long */ + memcpy(&cap_info, pcurrent, sizeof(cap_info)); + pcurrent += sizeof(cap_info); + bss_info_length -= sizeof(cap_info); + + scantable_get_ssid_from_ie(pcurrent, + bss_info_length, (t_u8 *)ssid, sizeof(ssid)); + + printf("\n*** [%s], %02x:%02x:%02x:%02x:%02x:%2x\n", + ssid, + fixed_fields.bssid[0], + fixed_fields.bssid[1], + fixed_fields.bssid[2], + fixed_fields.bssid[3], + fixed_fields.bssid[4], fixed_fields.bssid[5]); + memcpy(&tmp_cap, &cap_info, sizeof(tmp_cap)); + printf("Channel = %d, SS = %d, CapInfo = 0x%04x, BcnIntvl = %d\n", + fixed_fields.channel, + 255 - fixed_fields.rssi, tmp_cap, beacon_interval); + + printf("TSF Values: AP(0x%02x%02x%02x%02x%02x%02x%02x%02x), ", + tsf[7], tsf[6], tsf[5], tsf[4], tsf[3], tsf[2], tsf[1], tsf[0]); + + printf("Network(0x%016llx)\n", fixed_fields.network_tsf); + printf("\n"); + printf("Element Data (%d bytes)\n", (int)bss_info_length); + printf("------------"); + dump_scan_elems(pcurrent, bss_info_length); + printf("\n"); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief channel validation. + * @param scan_req A pointer to wlan_ioctl_user_scan_cfg structure + * @param chan_num channel number + * + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +wlan_is_channel_valid(wlan_ioctl_user_scan_cfg *scan_req, t_u8 chan_number) +{ + int ret = -1; + int i; + if (scan_req && scan_req->chan_list[0].chan_number) { + for (i = 0; + i < WLAN_IOCTL_USER_SCAN_CHAN_MAX && + scan_req->chan_list[i].chan_number; i++) { + if (scan_req->chan_list[i].chan_number == chan_number) { + ret = 0; + break; + } + } + } else { + ret = 0; + } + return ret; +} + +/** + * @brief filter_ssid_result + * @param scan_req A pointer to wlan_ioctl_user_scan_cfg structure + * @param num_ssid_rqst Number of SSIDs which are filterted + * @param bss_info A pointer to current bss information structure + * @return 0--success, otherwise--fail + */ + +int +filter_ssid_result(wlan_ioctl_user_scan_cfg *scan_req, int num_ssid_rqst, + wlan_ioctl_get_bss_info *bss_info) +{ + int i, ret = 1; + + for (i = 0; i < num_ssid_rqst; i++) { + if ((memcmp(scan_req->ssid_list[i].ssid, bss_info->ssid, + (int)bss_info->ssid_len)) == 0) { + return 0; + } + } + return ret; +} + +/** + * @brief Process getscantable command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @param scan_req A pointer to wlan_ioctl_user_scan_cfg structure + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +wlan_process_getscantable(int argc, char *argv[], + wlan_ioctl_user_scan_cfg *scan_req) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + struct wlan_ioctl_get_scan_list *scan_list_head = NULL; + struct wlan_ioctl_get_scan_list *scan_list_node = NULL; + struct wlan_ioctl_get_scan_list *curr = NULL, *next = NULL; + + t_u32 total_scan_res = 0; + + unsigned int scan_start; + int idx, ret = 0; + + t_u8 *pcurrent; + t_u8 *pnext; + IEEEtypes_ElementId_e *pelement_id; + t_u8 *pelement_len; + int ssid_idx; + int insert = 0; + int sort_by_channel = 0; + t_u8 *pbyte; + t_u16 new_ss = 0; + t_u16 curr_ss = 0; + t_u8 new_ch = 0; + t_u8 curr_ch = 0; + + IEEEtypes_VendorSpecific_t *pwpa_ie; + const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; + + IEEEtypes_WmmParameter_t *pwmm_ie; + const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; + IEEEtypes_VendorSpecific_t *pwps_ie; + const t_u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 }; + + int displayed_info; + + wlan_ioctl_get_scan_table_info rsp_info_req; + wlan_ioctl_get_scan_table_info *prsp_info; + + wlan_get_scan_table_fixed fixed_fields; + t_u32 fixed_field_length; + t_u32 bss_info_length; + wlan_ioctl_get_bss_info *bss_info; + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + if (argc > 3 && (strcmp(argv[3], "tsf") != 0) + && (strcmp(argv[3], "help") != 0) + && (strcmp(argv[3], "ch") != 0)) { + + idx = strtol(argv[3], NULL, 10); + + if (idx >= 0) { + rsp_info_req.scan_number = idx; + ret = process_getscantable_idx(argv[2], &rsp_info_req); + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return ret; + } + } + + displayed_info = FALSE; + scan_start = 1; + + do { + prepare_buffer(buffer, argv[2], 0, NULL); + prsp_info = + (wlan_ioctl_get_scan_table_info *)(buffer + + strlen(CMD_MARVELL) + + strlen(argv[2])); + + prsp_info->scan_number = scan_start; + + /* + * Set up and execute the ioctl call + */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + if (errno == EAGAIN) { + ret = -EAGAIN; + } else { + perror("mlanutl"); + fprintf(stderr, "mlanutl: getscantable fail\n"); + ret = MLAN_STATUS_FAILURE; + } + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return ret; + } + + prsp_info = (wlan_ioctl_get_scan_table_info *)buffer; + pcurrent = 0; + pnext = prsp_info->scan_table_entry_buf; + total_scan_res += prsp_info->scan_number; + + for (idx = 0; (unsigned int)idx < prsp_info->scan_number; idx++) { + /* Alloc memory for new node for next BSS */ + scan_list_node = (struct wlan_ioctl_get_scan_list *) + malloc(sizeof(struct wlan_ioctl_get_scan_list)); + if (scan_list_node == NULL) { + printf("Error: allocate memory for scan_list_head failed\n"); + return -ENOMEM; + } + memset(scan_list_node, 0, + sizeof(struct wlan_ioctl_get_scan_list)); + + /* + * Set pcurrent to pnext in case pad bytes are at the end + * of the last IE we processed. + */ + pcurrent = pnext; + + /* Start extracting each BSS to prepare a linked list */ + memcpy((t_u8 *)&fixed_field_length, + (t_u8 *)pcurrent, sizeof(fixed_field_length)); + pcurrent += sizeof(fixed_field_length); + + memcpy((t_u8 *)&bss_info_length, + (t_u8 *)pcurrent, sizeof(bss_info_length)); + pcurrent += sizeof(bss_info_length); + + memcpy((t_u8 *)&fixed_fields, + (t_u8 *)pcurrent, sizeof(fixed_fields)); + pcurrent += fixed_field_length; + + scan_list_node->fixed_buf.fixed_field_length = + fixed_field_length; + scan_list_node->fixed_buf.bss_info_length = + bss_info_length; + scan_list_node->fixed_buf.fixed_fields = fixed_fields; + + bss_info = &scan_list_node->bss_info_buf; + + /* Set next to be the start of the next scan entry */ + pnext = pcurrent + bss_info_length; + + if (bss_info_length >= + (sizeof(bss_info->tsf) + + sizeof(bss_info->beacon_interval) + + sizeof(bss_info->cap_info))) { + + /* time stamp is 8 byte long */ + memcpy(bss_info->tsf, pcurrent, + sizeof(bss_info->tsf)); + pcurrent += sizeof(bss_info->tsf); + bss_info_length -= sizeof(bss_info->tsf); + + /* beacon interval is 2 byte long */ + memcpy(&bss_info->beacon_interval, pcurrent, + sizeof(bss_info->beacon_interval)); + pcurrent += sizeof(bss_info->beacon_interval); + bss_info_length -= + sizeof(bss_info->beacon_interval); + /* capability information is 2 byte long */ + memcpy(&bss_info->cap_info, pcurrent, + sizeof(bss_info->cap_info)); + pcurrent += sizeof(bss_info->cap_info); + bss_info_length -= sizeof(bss_info->cap_info); + } + + bss_info->wmm_cap = ' '; /* M (WMM), C (WMM-Call Admission Control) */ + bss_info->wps_cap = ' '; /* "S" */ + bss_info->dot11k_cap = ' '; /* "K" */ + bss_info->dot11r_cap = ' '; /* "R" */ + bss_info->ht_cap = ' '; /* "N" */ + bss_info->vht_cap[0] = 'A'; + bss_info->vht_cap[1] = 'C'; + /* "P" for Privacy (WEP) since "W" is WPA, and "2" is RSN/WPA2 */ + bss_info->priv_cap = + bss_info->cap_info.privacy ? 'P' : ' '; + + memset(bss_info->ssid, 0, MRVDRV_MAX_SSID_LENGTH + 1); + bss_info->ssid_len = 0; + + while (bss_info_length >= 2) { + pelement_id = (IEEEtypes_ElementId_e *)pcurrent; + pelement_len = pcurrent + 1; + pcurrent += 2; + + if ((bss_info_length - 2) < *pelement_len) { + printf("Error when processing bss info, bss_info_length < element length\n"); + bss_info_length = 0; + continue; + } + + switch (*pelement_id) { + case SSID: + if (*pelement_len && + *pelement_len <= + MRVDRV_MAX_SSID_LENGTH) { + memcpy(bss_info->ssid, pcurrent, + *pelement_len); + bss_info->ssid_len = + *pelement_len; + } + break; + + case WPA_IE: + pwpa_ie = + (IEEEtypes_VendorSpecific_t *) + pelement_id; + if ((memcmp + (pwpa_ie->vend_hdr.oui, wpa_oui, + sizeof(pwpa_ie->vend_hdr.oui)) == + 0) + && (pwpa_ie->vend_hdr.oui_type == + wpa_oui[3])) { + /* WPA IE found, 'W' for WPA */ + bss_info->priv_cap = 'W'; + } else { + pwmm_ie = + (IEEEtypes_WmmParameter_t + *)pelement_id; + if ((memcmp + (pwmm_ie->vend_hdr.oui, + wmm_oui, + sizeof(pwmm_ie->vend_hdr. + oui)) == 0) + && (pwmm_ie->vend_hdr. + oui_type == + wmm_oui[3])) { + /* Check the subtype: 1 == parameter, 0 == info */ + if ((pwmm_ie->vend_hdr. + oui_subtype == 1) + && pwmm_ie-> + ac_params + [WMM_AC_VO]. + aci_aifsn.acm) { + /* Call admission on VO; 'C' for CAC */ + bss_info-> + wmm_cap + = 'C'; + } else { + /* No CAC; 'M' for uh, WMM */ + bss_info-> + wmm_cap + = 'M'; + } + } else { + pwps_ie = + (IEEEtypes_VendorSpecific_t + *)pelement_id; + if ((memcmp + (pwps_ie->vend_hdr. + oui, wps_oui, + sizeof(pwps_ie-> + vend_hdr. + oui)) == 0) + && (pwps_ie-> + vend_hdr. + oui_type == + wps_oui[3])) { + bss_info-> + wps_cap + = 'S'; + } + } + } + break; + + case RSN_IE: + /* RSN IE found; '2' for WPA2 (RSN) */ + bss_info->priv_cap = '2'; + break; + case HT_CAPABILITY: + bss_info->ht_cap = 'N'; + break; + case VHT_CAPABILITY: + bss_info->vht_cap[0] = 'A'; + bss_info->vht_cap[1] = 'C'; + break; + default: + break; + } + + pcurrent += *pelement_len; + bss_info_length -= (2 + *pelement_len); + } + + /* Create a sorted list of BSS using Insertion Sort. */ + if ((argc > 3) && !strcmp(argv[3], "ch")) { + /* Sort by channel number (ascending order) */ + new_ch = fixed_fields.channel; + sort_by_channel = 1; + } else { + /* Sort as per Signal Strength (descending order) (Default case) */ + new_ss = 255 - fixed_fields.rssi; + } + if (scan_list_head == NULL) { + /* Node is the first element in the list. */ + scan_list_head = scan_list_node; + scan_list_node->next = NULL; + scan_list_node->prev = NULL; + } else { + curr = scan_list_head; + insert = 0; + do { + if (sort_by_channel) { + curr_ch = + curr->fixed_buf. + fixed_fields.channel; + if (new_ch < curr_ch) + insert = 1; + } else { + curr_ss = + 255 - + curr->fixed_buf. + fixed_fields.rssi; + if (new_ss > curr_ss) { + insert = 1; + } + } + if (insert) { + if (curr == scan_list_head) { + /* Insert the node to head of the list */ + scan_list_node->next = + scan_list_head; + scan_list_head->prev = + scan_list_node; + scan_list_head = + scan_list_node; + } else { + /* Insert the node to current position in list */ + scan_list_node->prev = + curr->prev; + scan_list_node->next = + curr; + (curr->prev)->next = + scan_list_node; + curr->prev = + scan_list_node; + } + break; + } + if (curr->next == NULL) { + /* Insert the node to tail of the list */ + curr->next = scan_list_node; + scan_list_node->prev = curr; + scan_list_node->next = NULL; + break; + } + curr = curr->next; + } while (curr != NULL); + } + } + scan_start += prsp_info->scan_number; + } while (prsp_info->scan_number); + + /* Display scan results */ + printf("---------------------------------------"); + printf("---------------------------------------\n"); + printf("# | ch | ss | bssid | cap | SSID \n"); + printf("---------------------------------------"); + printf("---------------------------------------\n"); + + for (curr = scan_list_head, idx = 0; + (curr != NULL) && ((unsigned int)idx < total_scan_res); + curr = curr->next, idx++) { + fixed_fields = curr->fixed_buf.fixed_fields; + bss_info = &curr->bss_info_buf; + if (wlan_is_channel_valid(scan_req, fixed_fields.channel)) + continue; + + if (setuserscan_filter == BSSID_FILTER) { + if (memcmp + (scan_req->specific_bssid, fixed_fields.bssid, + ETH_ALEN)) + continue; + } + if (setuserscan_filter == SSID_FILTER) { + if (filter_ssid_result + (scan_req, num_ssid_filter, bss_info)) + continue; + } + printf("%02u| %03d | %03d | %02x:%02x:%02x:%02x:%02x:%02x |", + idx, + fixed_fields.channel, + -fixed_fields.rssi, + fixed_fields.bssid[0], + fixed_fields.bssid[1], + fixed_fields.bssid[2], + fixed_fields.bssid[3], + fixed_fields.bssid[4], fixed_fields.bssid[5]); + + displayed_info = TRUE; + + /* "A" for Adhoc + * "I" for Infrastructure, + * "D" for DFS (Spectrum Mgmt) + */ + printf(" %c%c%c%c%c%c%c%c%c%c | ", bss_info->cap_info.ibss ? 'A' : 'I', bss_info->priv_cap, /* P (WEP), W (WPA), 2 (WPA2) */ + bss_info->cap_info.spectrum_mgmt ? 'D' : ' ', bss_info->wmm_cap, /* M (WMM), C (WMM-Call Admission Control) */ + bss_info->dot11k_cap, /* K */ + bss_info->dot11r_cap, /* R */ + bss_info->wps_cap, /* S */ + bss_info->ht_cap, /* N */ + bss_info->vht_cap[0], /* AC */ + bss_info->vht_cap[1]); + + /* Print out the ssid or the hex values if non-printable */ + for (ssid_idx = 0; ssid_idx < (int)bss_info->ssid_len; + ssid_idx++) { + if (isprint(bss_info->ssid[ssid_idx])) { + printf("%c", bss_info->ssid[ssid_idx]); + } else { + printf("\\%02x", bss_info->ssid[ssid_idx]); + } + } + + printf("\n"); + + if (argc > 3 && strcmp(argv[3], "tsf") == 0) { + /* TSF is a u64, some formatted printing libs have trouble + printing long longs, so cast and dump as bytes */ + pbyte = (t_u8 *)&fixed_fields.network_tsf; + printf(" TSF=%02x%02x%02x%02x%02x%02x%02x%02x\n", + pbyte[7], pbyte[6], pbyte[5], pbyte[4], + pbyte[3], pbyte[2], pbyte[1], pbyte[0]); + } + } + + if (displayed_info == TRUE) { + if (argc > 3 && strcmp(argv[3], "help") == 0) { + printf("\n\n" + "Capability Legend (Not all may be supported)\n" + "-----------------\n" + " I [ Infrastructure ]\n" + " A [ Ad-hoc ]\n" + " W [ WPA IE ]\n" + " 2 [ WPA2/RSN IE ]\n" + " M [ WMM IE ]\n" + " C [ Call Admission Control - WMM IE, VO ACM set ]\n" + " D [ Spectrum Management - DFS (11h) ]\n" + " K [ 11k ]\n" + " R [ 11r ]\n" + " S [ WPS ]\n" + " N [ HT (11n) ]\n" + " AC [VHT (11ac) ]\n" "\n\n"); + } + } else { + printf("< No Scan Results >\n"); + } + + for (curr = scan_list_head; curr != NULL; curr = next) { + next = curr->next; + free(curr); + } + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process getscantable command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @param scan_req A pointer to wlan_ioctl_user_scan_cfg structure + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_getscantable(int argc, char *argv[]) +{ + return wlan_process_getscantable(argc, argv, NULL); +} + +/** + * @brief Prepare setuserscan command buffer + * @param scan_req pointer to wlan_ioctl_user_scan_cfg structure + * @param num Number of arguments + * @param args Arguments list + * @return MLAN_STATUS_SUCCESS + */ +static int +prepare_setuserscan_buffer(wlan_ioctl_user_scan_cfg *scan_req, t_u32 num, + char *args[]) +{ + int arg_idx = 0; + int num_ssid = 0; + char *parg_tok = NULL; + char *pchan_tok = NULL; + char *parg_cookie = NULL; + char *pchan_cookie = NULL; + int chan_parse_idx = 0; + int chan_cmd_idx = 0; + char chan_scratch[MAX_CHAN_SCRATCH]; + char *pscratch = NULL; + int tmp_idx = 0; + int scan_time = 0; + int is_radio_set = 0; + unsigned int mac[ETH_ALEN]; + + for (arg_idx = 0; arg_idx < (int)num; arg_idx++) { + if (strncmp(args[arg_idx], "ssid=", strlen("ssid=")) == 0) { + /* "ssid" token string handler */ + if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) { + strncpy(scan_req->ssid_list[num_ssid].ssid, + args[arg_idx] + strlen("ssid="), + sizeof(scan_req->ssid_list[num_ssid]. + ssid)); + + scan_req->ssid_list[num_ssid].max_len = 0; + setuserscan_filter = SSID_FILTER; + num_ssid++; + num_ssid_filter++; + } + } else if (strncmp(args[arg_idx], "bssid=", strlen("bssid=")) == + 0) { + /* "bssid" token string handler */ + sscanf(args[arg_idx] + strlen("bssid="), + "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1, + mac + 2, mac + 3, mac + 4, mac + 5); + setuserscan_filter = BSSID_FILTER; + for (tmp_idx = 0; + (unsigned int)tmp_idx < NELEMENTS(mac); + tmp_idx++) { + scan_req->specific_bssid[tmp_idx] = + (t_u8)mac[tmp_idx]; + } + } else if (strncmp(args[arg_idx], "chan=", strlen("chan=")) == + 0) { + /* "chan" token string handler */ + parg_tok = args[arg_idx] + strlen("chan="); + + if (strlen(parg_tok) > MAX_CHAN_SCRATCH) { + printf("Error: Specified channels exceeds max limit\n"); + return MLAN_STATUS_FAILURE; + } + is_radio_set = FALSE; + + while ((parg_tok = + strtok_r(parg_tok, ",", + &parg_cookie)) != NULL) { + + memset(chan_scratch, 0x00, + sizeof(chan_scratch)); + pscratch = chan_scratch; + + for (chan_parse_idx = 0; + (unsigned int)chan_parse_idx < + strlen(parg_tok); chan_parse_idx++) { + if (isalpha + (*(parg_tok + chan_parse_idx))) { + *pscratch++ = ' '; + } + + *pscratch++ = + *(parg_tok + chan_parse_idx); + } + *pscratch = 0; + parg_tok = NULL; + + pchan_tok = chan_scratch; + + while ((pchan_tok = strtok_r(pchan_tok, " ", + &pchan_cookie)) != + NULL) { + if (isdigit(*pchan_tok)) { + scan_req-> + chan_list[chan_cmd_idx]. + chan_number = + atoi(pchan_tok); + if (scan_req-> + chan_list[chan_cmd_idx]. + chan_number > + MAX_CHAN_BG_BAND) + scan_req-> + chan_list + [chan_cmd_idx]. + radio_type = 1; + } else { + switch (toupper(*pchan_tok)) { + case 'A': + scan_req-> + chan_list + [chan_cmd_idx]. + radio_type = 1; + is_radio_set = TRUE; + break; + case 'B': + case 'G': + scan_req-> + chan_list + [chan_cmd_idx]. + radio_type = 0; + is_radio_set = TRUE; + break; + case 'N': + break; + case 'C': + scan_req-> + chan_list + [chan_cmd_idx]. + scan_type = + MLAN_SCAN_TYPE_ACTIVE; + break; + case 'P': + scan_req-> + chan_list + [chan_cmd_idx]. + scan_type = + MLAN_SCAN_TYPE_PASSIVE; + break; + default: + printf("Error: Band type not supported!\n"); + return -EOPNOTSUPP; + } + if (!chan_cmd_idx && + !scan_req-> + chan_list[chan_cmd_idx]. + chan_number && is_radio_set) + scan_req-> + chan_list + [chan_cmd_idx]. + radio_type |= + BAND_SPECIFIED; + } + pchan_tok = NULL; + } + if (((scan_req->chan_list[chan_cmd_idx]. + chan_number > MAX_CHAN_BG_BAND) + && !scan_req->chan_list[chan_cmd_idx]. + radio_type) || + ((scan_req->chan_list[chan_cmd_idx]. + chan_number < MAX_CHAN_BG_BAND) + && (scan_req->chan_list[chan_cmd_idx]. + radio_type == 1))) { + printf("Error: Invalid Radio type: chan=%d radio_type=%d\n", scan_req->chan_list[chan_cmd_idx].chan_number, scan_req->chan_list[chan_cmd_idx].radio_type); + return MLAN_STATUS_FAILURE; + } + chan_cmd_idx++; + } + } else if (strncmp(args[arg_idx], "gap=", strlen("gap=")) == 0) { + scan_req->scan_chan_gap = + atoi(args[arg_idx] + strlen("gap=")); + } else if (strncmp(args[arg_idx], "keep=", strlen("keep=")) == + 0) { + /* "keep" token string handler */ + scan_req->keep_previous_scan = + atoi(args[arg_idx] + strlen("keep=")); + } else if (strncmp(args[arg_idx], "dur=", strlen("dur=")) == 0) { + /* "dur" token string handler */ + scan_time = atoi(args[arg_idx] + strlen("dur=")); + scan_req->chan_list[0].scan_time = scan_time; + + } else if (strncmp(args[arg_idx], "wc=", strlen("wc=")) == 0) { + + if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) { + /* "wc" token string handler */ + pscratch = strrchr(args[arg_idx], ','); + + if (pscratch) { + *pscratch = 0; + pscratch++; + + if (isdigit(*pscratch)) { + scan_req->ssid_list[num_ssid]. + max_len = + atoi(pscratch); + } else { + scan_req->ssid_list[num_ssid]. + max_len = *pscratch; + } + } else { + /* Standard wildcard matching */ + scan_req->ssid_list[num_ssid].max_len = + 0xFF; + } + + strncpy(scan_req->ssid_list[num_ssid].ssid, + args[arg_idx] + strlen("wc="), + sizeof(scan_req->ssid_list[num_ssid]. + ssid)); + + num_ssid++; + } + } else if (strncmp(args[arg_idx], "probes=", strlen("probes=")) + == 0) { + /* "probes" token string handler */ + scan_req->num_probes = + atoi(args[arg_idx] + strlen("probes=")); + if (scan_req->num_probes > MAX_PROBES) { + fprintf(stderr, "Invalid probes (> %d)\n", + MAX_PROBES); + return -EOPNOTSUPP; + } + } else if (strncmp + (args[arg_idx], "bss_type=", + strlen("bss_type=")) == 0) { + /* "bss_type" token string handler */ + scan_req->bss_mode = + atoi(args[arg_idx] + strlen("bss_type=")); + switch (scan_req->bss_mode) { + case MLAN_SCAN_MODE_BSS: + case MLAN_SCAN_MODE_IBSS: + break; + case MLAN_SCAN_MODE_ANY: + default: + /* Set any unknown types to ANY */ + scan_req->bss_mode = MLAN_SCAN_MODE_ANY; + break; + } + } else if (strncmp + (args[arg_idx], "scan_type=", + strlen("scan_type=")) == 0) { + /* "scan_type" token string handler */ + scan_req->ext_scan_type = + atoi(args[arg_idx] + strlen("scan_type=")); + } + } + + /* Update all the channels to have the same scan time */ + for (tmp_idx = 1; tmp_idx < chan_cmd_idx; tmp_idx++) { + scan_req->chan_list[tmp_idx].scan_time = scan_time; + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process setuserscan command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_setuserscan(int argc, char *argv[]) +{ + wlan_ioctl_user_scan_cfg *scan_req = NULL; + t_u8 *pos = NULL; + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int status = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + memset(buffer, 0, BUFFER_LENGTH); + + /* Flag it for our use */ + pos = buffer; + strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL)); + pos += (strlen(CMD_MARVELL)); + + /* Insert command */ + strncpy((char *)pos, (char *)argv[2], strlen(argv[2])); + pos += (strlen(argv[2])); + + /* Insert arguments */ + scan_req = (wlan_ioctl_user_scan_cfg *)pos; + + if (prepare_setuserscan_buffer(scan_req, (argc - 3), &argv[3])) { + printf("ERR:Invalid parameter\n"); + return MLAN_STATUS_FAILURE; + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: setuserscan fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + if (argc > 3) { + if (!strcmp(argv[3], "sort_by_ch")) { + argv[3] = "ch"; + } else { + argc = 0; + } + } + do { + argv[2] = "getscantable"; + status = wlan_process_getscantable(argc, argv, scan_req); + } while (status == -EAGAIN); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process extended capabilities configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_extcapcfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL, ext_cap[9]; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + IEEEtypes_Header_t ie; + + if (argc > 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX extcapcfg \n"); + return MLAN_STATUS_FAILURE; + } + + if (argc == 4 && MLAN_STATUS_FAILURE == ishexstring(argv[3])) { + printf("ERR:Only hex digits are allowed.\n"); + printf("Syntax: ./mlanutl mlanX extcapcfg \n"); + return MLAN_STATUS_FAILURE; + } + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* Only insert command */ + prepare_buffer(buffer, argv[2], 0, NULL); + + if (argc == 4) { + if (!strncasecmp("0x", argv[3], 2)) + argv[3] += 2; + + if (strlen(argv[3]) > 2 * sizeof(ext_cap)) { + printf("ERR:Incorrect length of arguments.\n"); + printf("Syntax: ./mlanutl mlanX extcapcfg \n"); + return MLAN_STATUS_FAILURE; + } + + memset(ext_cap, 0, sizeof(ext_cap)); + ie.element_id = TLV_TYPE_EXTCAP; + ie.len = sizeof(ext_cap); + + string2raw(argv[3], ext_cap); + memcpy(buffer + strlen(CMD_MARVELL) + strlen(argv[2]), &ie, + sizeof(ie)); + memcpy(buffer + strlen(CMD_MARVELL) + strlen(argv[2]) + + sizeof(ie), ext_cap, sizeof(ext_cap)); + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, + "mlanutl: extended capabilities configure fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + hexdump("Extended capabilities", buffer + sizeof(IEEEtypes_Header_t), + ((IEEEtypes_Header_t *)buffer)->len, ' '); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Cancel ongoing scan + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_cancelscan(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + if (argc != 3) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX cancelscan\n"); + return MLAN_STATUS_FAILURE; + } + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* Only insert command */ + prepare_buffer(buffer, argv[2], 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: cancel scan fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} +#endif /* STA_SUPPORT */ + +/** + * @brief Process deep sleep configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_deepsleep(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: deepsleep fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("Deepsleep command response: %s\n", buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process ipaddr command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_ipaddr(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* The argument being a string, this requires special handling */ + prepare_buffer(buffer, argv[2], 0, NULL); + if (argc >= 4) { + strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])), + argv[3]); + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: ipaddr fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("IP address Configuration: %s\n", (char *)buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process otpuserdata command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_otpuserdata(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + if (argc < 4) { + printf("ERR:No argument\n"); + return MLAN_STATUS_FAILURE; + } + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: otpuserdata fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + hexdump("OTP user data: ", buffer, + MIN(cmd->used_len, a2hex_or_atoi(argv[3])), ' '); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process countrycode setting + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_countrycode(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct eth_priv_countrycode *countrycode = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* The argument being a string, this requires special handling */ + prepare_buffer(buffer, argv[2], 0, NULL); + if (argc >= 4) { + strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])), + argv[3]); + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: countrycode fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + countrycode = (struct eth_priv_countrycode *)buffer; + if (argc == 3) { + /* GET operation */ + printf("Country code: %s\n", countrycode->country_code); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process TCP ACK enhancement configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tcpackenh(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: tcpackenh fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("TCP Ack enhancement: "); + if (buffer[0]) + printf("enabled.\n"); + else + printf("disabled.\n"); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +#ifdef REASSOCIATION +/** + * @brief Process asynced essid setting + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_assocessid(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* The argument being a string, this requires special handling */ + prepare_buffer(buffer, argv[2], 0, NULL); + if (argc >= 4) { + strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])), + argv[3]); + } + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: assocessid fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("Set Asynced ESSID: %s\n", (char *)buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; + +} +#endif + +#ifdef STA_SUPPORT +/** + * @brief Process listen interval configuration + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_listeninterval(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: listen interval fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + if (argc == 3) + printf("Listen interval command response: %s\n", buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process power save mode setting + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_psmode(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int psmode = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: psmode fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + psmode = *(int *)buffer; + printf("PS mode: %d\n", psmode); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} +#endif + +#ifdef DEBUG_LEVEL1 +/** + * @brief Process driver debug configuration + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_drvdbg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + t_u32 drvdbg; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: drvdbg config fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + if (argc == 3) { + memcpy(&drvdbg, buffer, sizeof(drvdbg)); + printf("drvdbg: 0x%08x\n", drvdbg); +#ifdef DEBUG_LEVEL2 + printf("MINFO (%08x) %s\n", MINFO, + (drvdbg & MINFO) ? "X" : ""); + printf("MWARN (%08x) %s\n", MWARN, + (drvdbg & MWARN) ? "X" : ""); + printf("MENTRY (%08x) %s\n", MENTRY, + (drvdbg & MENTRY) ? "X" : ""); +#endif + printf("MMPA_D (%08x) %s\n", MMPA_D, + (drvdbg & MMPA_D) ? "X" : ""); + printf("MIF_D (%08x) %s\n", MIF_D, + (drvdbg & MIF_D) ? "X" : ""); + printf("MFW_D (%08x) %s\n", MFW_D, + (drvdbg & MFW_D) ? "X" : ""); + printf("MEVT_D (%08x) %s\n", MEVT_D, + (drvdbg & MEVT_D) ? "X" : ""); + printf("MCMD_D (%08x) %s\n", MCMD_D, + (drvdbg & MCMD_D) ? "X" : ""); + printf("MDAT_D (%08x) %s\n", MDAT_D, + (drvdbg & MDAT_D) ? "X" : ""); + printf("MIOCTL (%08x) %s\n", MIOCTL, + (drvdbg & MIOCTL) ? "X" : ""); + printf("MINTR (%08x) %s\n", MINTR, + (drvdbg & MINTR) ? "X" : ""); + printf("MEVENT (%08x) %s\n", MEVENT, + (drvdbg & MEVENT) ? "X" : ""); + printf("MCMND (%08x) %s\n", MCMND, + (drvdbg & MCMND) ? "X" : ""); + printf("MDATA (%08x) %s\n", MDATA, + (drvdbg & MDATA) ? "X" : ""); + printf("MERROR (%08x) %s\n", MERROR, + (drvdbg & MERROR) ? "X" : ""); + printf("MFATAL (%08x) %s\n", MFATAL, + (drvdbg & MFATAL) ? "X" : ""); + printf("MMSG (%08x) %s\n", MMSG, (drvdbg & MMSG) ? "X" : ""); + + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} +#endif + +/** + * @brief Process hscfg configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_hscfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + struct eth_priv_hs_cfg *hscfg; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: hscfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + hscfg = (struct eth_priv_hs_cfg *)buffer; + if (argc == 3) { + /* GET operation */ + printf("HS Configuration:\n"); + printf(" Conditions: %d\n", (int)hscfg->conditions); + printf(" GPIO: %d\n", (int)hscfg->gpio); + printf(" GAP: %d\n", (int)hscfg->gap); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process hssetpara configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_hssetpara(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: hssetpara fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process wakeup reason + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_wakeupresaon(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: get wakeup reason fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + printf("Get wakeup reason response: %s\n", buffer); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process hscfg management frame config + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_mgmtfilter(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + FILE *fp = NULL; + int ret = MLAN_STATUS_SUCCESS; + char line[256], cmdname[256], *pos = NULL, *filter = NULL; + int cmdname_found = 0, name_found = 0; + int ln = 0, i = 0, numEntries = 0, len = 0; + eth_priv_mgmt_frame_wakeup hs_mgmt_filter[2]; + + if (argc < 4) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./mlanutl mlanX mgmtfilter \n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + + pos = (char *)buffer; + strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL)); + pos += (strlen(CMD_MARVELL)); + len += (strlen(CMD_MARVELL)); + + /* Insert command */ + strncpy((char *)pos, argv[2], strlen(argv[2])); + pos += (strlen(argv[2])); + len += (strlen(argv[2])); + + filter = pos; + + cmdname_found = 0; + snprintf(cmdname, sizeof(cmdname), "%s={", argv[2]); + + fp = fopen(argv[3], "r"); + if (fp == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[3]); + ret = MLAN_STATUS_FAILURE; + if (buffer) + free(buffer); + goto done; + } + + while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) { + if (strcmp(pos, cmdname) == 0) { + cmdname_found = 1; + snprintf(cmdname, sizeof(cmdname), "entry_num="); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, sizeof(line), + &ln))) { + if (strncmp(pos, cmdname, strlen(cmdname)) == 0) { + name_found = 1; + numEntries = + a2hex_or_atoi(pos + + strlen(cmdname)); + if (numEntries > 2) { + printf("mlanutl: NumEntries exceed max number.\ + We support two entries in currently\n"); + return MLAN_STATUS_FAILURE; + } + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanutl: NumEntries not found in file '%s'\n", + argv[3]); + break; + } + for (i = 0; i < numEntries; i++) { + snprintf(cmdname, sizeof(cmdname), "entry_%d={", + i); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, + sizeof(line), + &ln))) { + if (strncmp + (pos, cmdname, + strlen(cmdname)) == 0) { + name_found = 1; + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanutl: %s not found in file '%s'\n", + cmdname, argv[3]); + break; + } + snprintf(cmdname, sizeof(cmdname), "action="); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, + sizeof(line), + &ln))) { + if (strncmp + (pos, cmdname, + strlen(cmdname)) == 0) { + name_found = 1; + hs_mgmt_filter[i].action = + a2hex_or_atoi(pos + + strlen + (cmdname)); + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanutl: %s not found in file '%s'\n", + cmdname, argv[3]); + break; + } + snprintf(cmdname, sizeof(cmdname), "type="); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, + sizeof(line), + &ln))) { + if (strncmp + (pos, cmdname, + strlen(cmdname)) == 0) { + name_found = 1; + hs_mgmt_filter[i].type = + a2hex_or_atoi(pos + + strlen + (cmdname)); + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanutl: %s not found in file '%s'\n", + cmdname, argv[3]); + break; + } + snprintf(cmdname, sizeof(cmdname), + "frame_mask="); + name_found = 0; + while ((pos = + mlan_config_get_line(fp, line, + sizeof(line), + &ln))) { + if (strncmp + (pos, cmdname, + strlen(cmdname)) == 0) { + name_found = 1; + hs_mgmt_filter[i].frame_mask = + a2hex_or_atoi(pos + + strlen + (cmdname)); + break; + } + } + if (!name_found) { + fprintf(stderr, + "mlanutl: %s not found in file '%s'\n", + cmdname, argv[3]); + break; + } + } + break; + } + } + fclose(fp); + if (!cmdname_found) { + fprintf(stderr, "mlanutl: ipPkt data not found in file '%s'\n", + argv[3]); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + memcpy(filter, (t_u8 *)hs_mgmt_filter, + sizeof(eth_priv_mgmt_frame_wakeup) * numEntries); + len += sizeof(eth_priv_mgmt_frame_wakeup) * numEntries; + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = len; + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: cloud keep alive fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + +done: + return ret; +} + +/** + * @brief Process scancfg configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_scancfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + struct eth_priv_scan_cfg *scancfg; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: scancfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + scancfg = (struct eth_priv_scan_cfg *)buffer; + /* Show scan configure */ + printf("Scan Configuration:\n"); + printf(" Scan Type: %d (%s)\n", scancfg->scan_type, + (scancfg->scan_type == 1) ? "Active" : (scancfg->scan_type == + 2) ? "Passive" : ""); + printf(" Scan Mode: %d (%s)\n", scancfg->scan_mode, + (scancfg->scan_mode == 1) ? "BSS" : (scancfg->scan_mode == + 2) ? "IBSS" : (scancfg-> + scan_mode == + 3) ? "Any" : + ""); + printf(" Scan Probes: %d (%s)\n", scancfg->scan_probe, + "per channel"); + printf(" Specific Scan Time: %d ms\n", + scancfg->scan_time.specific_scan_time); + printf(" Active Scan Time: %d ms\n", + scancfg->scan_time.active_scan_time); + printf(" Passive Scan Time: %d ms\n", + scancfg->scan_time.passive_scan_time); + printf(" Passive to Active Scan: %d (%s)\n", + scancfg->passive_to_active_scan, + (scancfg->passive_to_active_scan == + MLAN_PASS_TO_ACT_SCAN_EN) ? "Enable" : (scancfg-> + passive_to_active_scan + == + MLAN_PASS_TO_ACT_SCAN_DIS) + ? "Disable" : ""); + printf(" Extended Scan Support: %d (%s)\n", scancfg->ext_scan, + (scancfg->ext_scan == 1) ? "No" : (scancfg->ext_scan == + 2) ? "Yes" : (scancfg-> + ext_scan == + 3) ? "Enhanced" + : ""); + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process warmreset command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_warmreset(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + /* The argument being a string, this requires special handling */ + prepare_buffer(buffer, argv[2], 0, NULL); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: warmreset fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +static char *bandwidth[4] = { "20 MHz", "40 MHz", "80 MHz", "160 MHz" }; + +/** + * @brief Process txpowercfg command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_txpowercfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + struct eth_priv_power_cfg_ext *power_ext = NULL; + struct eth_priv_power_group *power_group = NULL; + int i = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(2 * BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = 2 * BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: txpowercfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + power_ext = (struct eth_priv_power_cfg_ext *)buffer; + if (argc == 3) { + /* GET operation */ + printf("Tx Power Configurations:\n"); + for (i = 0; i < power_ext->num_pwr_grp; i++) { + power_group = &power_ext->power_group[i]; + if (power_group->rate_format == MLAN_RATE_FORMAT_HT) { + if (power_group->bandwidth == MLAN_HT_BW20) { + power_group->first_rate_ind += 12; + power_group->last_rate_ind += 12; + } else if (power_group->bandwidth == + MLAN_HT_BW40) { + power_group->first_rate_ind += 140; + power_group->last_rate_ind += 140; + } + } + printf(" Power Group %d: \n", i); + printf(" Bandwidth: %3s %s\n", + rate_format[power_group->rate_format], + bandwidth[power_group->bandwidth]); + if (power_group->rate_format == 2) + /** NSS */ + printf(" NSS: %3d\n", + power_group->nss); + printf(" first rate index: %3d\n", + power_group->first_rate_ind); + printf(" last rate index: %3d\n", + power_group->last_rate_ind); + printf(" minimum power: %3d dBm\n", + power_group->power_min); + printf(" maximum power: %3d dBm\n", + power_group->power_max); + printf(" power step: %3d\n", + power_group->power_step); + printf("\n"); + power_group++; + } + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process pscfg command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_pscfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + struct eth_priv_ds_ps_cfg *ps_cfg = NULL; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: pscfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + ps_cfg = (struct eth_priv_ds_ps_cfg *)buffer; + if (argc == 3) { + /* GET operation */ + printf("PS Configurations:\n"); + printf("%d", (int)ps_cfg->ps_null_interval); + printf(" %d", (int)ps_cfg->multiple_dtim_interval); + printf(" %d", (int)ps_cfg->listen_interval); + printf(" %d", (int)ps_cfg->bcn_miss_timeout); + printf(" %d", (int)ps_cfg->delay_to_ps); + printf(" %d", (int)ps_cfg->ps_mode); + printf("\n"); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process bcntimeoutcfg command + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_bcntimeoutcfg(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + + if (argc != 7) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]\n"); + return -EINVAL; + } + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return -ENOMEM; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return -ENOMEM; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: bcntimeoutcfg fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return -EFAULT; + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return 0; +} + +/** + * @brief Process sleeppd configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_sleeppd(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int sleeppd = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: sleeppd fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + sleeppd = *(int *)buffer; + if (argc == 3) { + /* GET operation */ + printf("Sleep Period: %d ms\n", sleeppd); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tx control configuration + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_txcontrol(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + t_u32 txcontrol = 0; + + /* Initialize buffer */ + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return MLAN_STATUS_FAILURE; + } + + prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]); + + cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd)); + if (!cmd) { + printf("ERR:Cannot allocate buffer for command!\n"); + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Fill up buffer */ +#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT + memset(cmd, 0, sizeof(struct eth_priv_cmd)); + memcpy(&cmd->buf, &buffer, sizeof(buffer)); +#else + cmd->buf = buffer; +#endif + cmd->used_len = 0; + cmd->total_len = BUFFER_LENGTH; + + /* Perform IOCTL */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd; + + if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) { + perror("mlanutl"); + fprintf(stderr, "mlanutl: txcontrol fail\n"); + if (cmd) + free(cmd); + if (buffer) + free(buffer); + return MLAN_STATUS_FAILURE; + } + + /* Process result */ + txcontrol = *(t_u32 *)buffer; + if (argc == 3) { + /* GET operation */ + printf("Tx control: 0x%x\n", txcontrol); + } + + if (buffer) + free(buffer); + if (cmd) + free(cmd); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Performs the ioctl operation to send the command to driver. + * @param cmd_buf Pointer to the command buffer + * @param buf_size Size of the allocated command buffer + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +static int +tdls_ioctl(t_u8 *cmd_buf, t_u16 buf_size) +{ + struct ifreq ifr; + + /* Initialize the ifr structure */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name)); + ifr.ifr_ifru.ifru_data = (void *)cmd_buf; + + /* Perform ioctl */ + if (ioctl(sockfd, TDLS_IOCTL, &ifr)) { + perror(""); + return MLAN_STATUS_FAILURE; + } + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief host tdls config + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_host_tdls_config(int argc, char *argv[]) +{ + host_tdls_cfg *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, i = 0, cmd_found = 0; + char *args[30], *pos = NULL; + t_u16 cmd_len = 0, tlv_len_supp_chan = 0; + t_u16 no_of_supp_chan_sub_band = 0, num_of_regulatory_class = + 0, tlv_len_reg_class; + t_u8 *buffer = NULL; + tlvbuf_SupportedChannels_t *supp_chan = NULL; + tlvbuf_RegulatoryClass_t *reg_class = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX host_tdls_config \n"); + printf("Syntax: ./mlanutl mlanX host_tdls_config <0/1> \n "); + exit(1); + } + + cmd_len = sizeof(host_tdls_cfg); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + param_buf = (host_tdls_cfg *) buffer; + param_buf->action = ACTION_HOST_TDLS_CONFIG; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("ERR:Incorrect arguments.\n"); + printf("Syntax: ./mlanutl mlanX host_tdls_config \n"); + exit(1); + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + if (strcmp(args[0], "uapsd_support") == 0) { + param_buf->uapsd_support = (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "cs_support") == 0) { + param_buf->cs_support = (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "SupportedChannels") == 0) { + /* Append a new TLV */ + supp_chan = + (tlvbuf_SupportedChannels_t *)(buffer + + cmd_len); + supp_chan->tag = TLV_TYPE_SUPPORTED_CHANNELS; + supp_chan->length = sizeof(tlvbuf_SupportedChannels_t) + - TLVHEADER_LEN; + tlv_len_supp_chan = sizeof(tlvbuf_SupportedChannels_t); + cmd_len += tlv_len_supp_chan; + } else if (strncmp(args[0], "FirstChannelNo", 14) == 0) { + supp_chan->subband[no_of_supp_chan_sub_band]. + start_chan = atoi(args[1]); + } else if (strcmp(args[0], "NumberofSubBandChannels") == 0) { + supp_chan->subband[no_of_supp_chan_sub_band].num_chans = + atoi(args[1]); + no_of_supp_chan_sub_band++; + tlv_len_supp_chan += + sizeof(IEEEtypes_SupportChan_Subband_t); + supp_chan->length += + sizeof(IEEEtypes_SupportChan_Subband_t); + cmd_len += sizeof(IEEEtypes_SupportChan_Subband_t); + endian_convert_tlv_header_out(supp_chan); + } else if (strcmp(args[0], "SupportedRegulatoryClasses") == 0) { + /* Append a new TLV */ + reg_class = + (tlvbuf_RegulatoryClass_t *)(buffer + cmd_len); + tlv_len_reg_class = sizeof(tlvbuf_RegulatoryClass_t); + reg_class->tag = TLV_TYPE_REGULATORY_CLASSES; + cmd_len += tlv_len_reg_class; + } else if (strcmp(args[0], "CurrentRegulatoryClass") == 0) { + reg_class->regulatory_class.cur_regulatory_class = + atoi(args[1]); + reg_class->length = 1; + } else if (strcmp(args[0], "NumofRegulatoryClasses") == 0) { + num_of_regulatory_class = atoi(args[1]); + reg_class->length += num_of_regulatory_class; + cmd_len += num_of_regulatory_class; + endian_convert_tlv_header_out(reg_class); + } else if (strcmp(args[0], "ListOfRegulatoryClasses") == 0) { + for (i = 0; i < num_of_regulatory_class; i++) + reg_class->regulatory_class. + regulatory_classes_list[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } + } + /* adjust for size of action and tlv_len, capInfo */ + param_buf->tlv_len = cmd_len - sizeof(host_tdls_cfg); + + hexdump("host_tdls_config", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS Info settings sucessfully set.\n"); + } else { + printf("ERR:Could not set TDLS info configuration.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief enable/disable tdls config + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_config(int argc, char *argv[]) +{ + + tdls_config *param_buf = NULL; + int ret = 0; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_config <0/1>\n"); + exit(1); + } + + cmd_len = sizeof(tdls_config); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_config *) buffer; + param_buf->action = ACTION_TDLS_CONFIG; + + param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]); + if ((param_buf->data != 0) && (param_buf->data != 1)) { + printf("ERR:Incorrect arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_config <0/1>\n"); + goto done; + } + hexdump("tdls_config ", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS %s successful.\n", + (param_buf->data) ? "enable" : "disable"); + } else { + printf("ERR:TDLS %s failed.\n", + (param_buf->data) ? "enable" : "disable"); + } + +done: + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_setinfo + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_setinfo(int argc, char *argv[]) +{ + tdls_setinfo *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, arg_num = 0, ret = 0, i = 0, cmd_found = 0, pairwise_index = + 0, akm_index = 0, pmkid_index = 0; + char *args[30], *pos = NULL; + t_u16 cmd_len = 0, tlv_len = 0, tlv_len_rsn = 0, tlv_len_supp_chan = + 0, tlv_len_domain = 0; + t_u16 no_of_sub_band = 0, no_of_supp_chan_sub_band = + 0, pairwise_offset = 0, akm_offset = + 0, num_of_regulatory_class = 0, tlv_len_reg_class; + t_u16 akm_count = 0, pmk_count = 0, rsn_cap = 0; + t_u8 *buffer = NULL; + char country[COUNTRY_CODE_LEN]; + tlvbuf_DomainParamSet_t *domain = NULL; + tlvbuf_SupportedChannels_t *supp_chan = NULL; + tlvbuf_RegulatoryClass_t *reg_class = NULL; + tlvbuf_HTCap_t *tlv_ht_cap = NULL; + tlvbuf_RsnParamSet_t *rsn_ie = NULL; + tlvbuf_HTInfo_t *tlv_ht_info = NULL; + t_u8 pairwise_cipher_suite[PAIRWISE_CIPHER_SUITE_LEN]; + t_u8 akm_suite[AKM_SUITE_LEN]; + t_u8 pmkid[PMKID_LEN]; + tlvbuf_VHTCap_t *tlv_vht_cap = NULL; + tlvbuf_VHTOpra_t *tlv_vht_oper = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_setinfo \n"); + exit(1); + } + + cmd_len = sizeof(tdls_setinfo); + + buffer = (t_u8 *)malloc(BUFFER_LENGTH); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, BUFFER_LENGTH); + param_buf = (tdls_setinfo *)buffer; + param_buf->action = ACTION_TDLS_SETINFO; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + arg_num = parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + if (strcmp(args[0], "CapInfo") == 0) { + param_buf->cap_info = (t_u16)A2HEXDECIMAL(args[1]); + param_buf->cap_info = cpu_to_le16(param_buf->cap_info); + } else if (strcmp(args[0], "Rate") == 0) { + tlvbuf_RatesParamSet_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_RatesParamSet_t) + arg_num - 1; + tlv = (tlvbuf_RatesParamSet_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_RATES; + tlv->length = arg_num - 1; + for (i = 0; i < tlv->length; i++) { + tlv->rates[i] = (t_u8)A2HEXDECIMAL(args[i + 1]); + } + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "QosInfo") == 0) { + tlvbuf_QosInfo_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_QosInfo_t); + tlv = (tlvbuf_QosInfo_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_QOSINFO; + tlv->length = sizeof(tlvbuf_QosInfo_t) - TLVHEADER_LEN; + tlv->u.qos_info_byte = (t_u8)A2HEXDECIMAL(args[1]); + if ((tlv->u.qos_info_byte != 0) && + (tlv->u.qos_info_byte != 0x0F)) { + printf("Invalid QosInfo. Should be 0x00 or 0x0F.\n"); + goto done; + } + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "ExtendCapabilities") == 0) { + tlvbuf_ExtCap_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_ExtCap_t) + arg_num - 1; + tlv = (tlvbuf_ExtCap_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_EXTCAP; + tlv->length = arg_num - 1; + for (i = 0; i < tlv->length; i++) { + tlv->ext_cap[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "HTCapability") == 0) { + /* Append a new TLV */ + tlv_ht_cap = (tlvbuf_HTCap_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_HTCap_t); + tlv_ht_cap->tag = TLV_TYPE_HT_CAP; + tlv_ht_cap->length = + sizeof(tlvbuf_HTCap_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_ht_cap); + } else if (strcmp(args[0], "HTCapabilityInfo") == 0) { + tlv_ht_cap->ht_cap.ht_cap_info = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_cap->ht_cap.ht_cap_info = + cpu_to_le16(tlv_ht_cap->ht_cap.ht_cap_info); + } else if (strcmp(args[0], "AMPDUParam") == 0) { + tlv_ht_cap->ht_cap.ampdu_param = + (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "SupportedMCSSet") == 0) { + for (i = 0; i < MCS_SET_LEN; i++) + tlv_ht_cap->ht_cap.supported_mcs_set[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "HTExtCapability") == 0) { + tlv_ht_cap->ht_cap.ht_ext_cap = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_cap->ht_cap.ht_ext_cap = + cpu_to_le16(tlv_ht_cap->ht_cap.ht_ext_cap); + } else if (strcmp(args[0], "TxBfCapability") == 0) { + tlv_ht_cap->ht_cap.tx_bf_cap = + (t_u32)A2HEXDECIMAL(args[1]); + tlv_ht_cap->ht_cap.tx_bf_cap = + cpu_to_le32(tlv_ht_cap->ht_cap.tx_bf_cap); + } else if (strcmp(args[0], "AntennaSel") == 0) { + tlv_ht_cap->ht_cap.asel = (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "HTInformation") == 0) { + /* Append a new TLV */ + tlv_ht_info = (tlvbuf_HTInfo_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_HTInfo_t); + tlv_ht_info->tag = TLV_TYPE_HT_INFO; + tlv_ht_info->length = + sizeof(tlvbuf_HTInfo_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_ht_info); + } else if (strcmp(args[0], "PrimaryChannel") == 0) { + tlv_ht_info->ht_info.pri_chan = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "Field2") == 0) { + tlv_ht_info->ht_info.field2 = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "Field3") == 0) { + tlv_ht_info->ht_info.field3 = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_info->ht_info.field3 = + cpu_to_le16(tlv_ht_info->ht_info.field3); + } else if (strcmp(args[0], "Field4") == 0) { + tlv_ht_info->ht_info.field4 = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_ht_info->ht_info.field4 = + cpu_to_le16(tlv_ht_info->ht_info.field4); + } else if (strcmp(args[0], "BasicMCSSet") == 0) { + if ((arg_num - 1) != MCS_SET_LEN) { + printf("Incorrect number of arguments for BasicMCSSet.\n"); + goto done; + } + for (i = 0; i < MCS_SET_LEN; i++) + tlv_ht_info->ht_info.basic_mcs_set[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "2040BSSCoex") == 0) { + tlvbuf_2040BSSCo_t *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_2040BSSCo_t); + tlv = (tlvbuf_2040BSSCo_t *)(buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->tag = TLV_TYPE_2040BSS_COEXISTENCE; + tlv->length = + sizeof(tlvbuf_2040BSSCo_t) - TLVHEADER_LEN; + tlv->bss_co_2040.bss_co_2040_value = + (t_u8)A2HEXDECIMAL(args[1]); + endian_convert_tlv_header_out(tlv); + } else if (strcmp(args[0], "RSNInfo") == 0) { + /* Append a new TLV */ + rsn_ie = (tlvbuf_RsnParamSet_t *)(buffer + cmd_len); + tlv_len_rsn = sizeof(tlvbuf_RsnParamSet_t); + rsn_ie->tag = TLV_TYPE_RSN_IE; + rsn_ie->version = VERSION_RSN_IE; + rsn_ie->version = cpu_to_le16(rsn_ie->version); + cmd_len += tlv_len_rsn; + } else if (strcmp(args[0], "GroupCipherSuite") == 0) { + for (i = 0; i < GROUP_CIPHER_SUITE_LEN; i++) + rsn_ie->group_cipher_suite[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "PairwiseCipherCount") == 0) { + rsn_ie->pairwise_cipher_count = (t_u16)atoi(args[1]); + rsn_ie->pairwise_cipher_count = + cpu_to_le16(rsn_ie->pairwise_cipher_count); + } else if (strncmp(args[0], "PairwiseCipherSuite", 19) == 0) { + if (pairwise_index > MAX_PAIRWISE_CIPHER_SUITE_COUNT) { + printf("PairwiseCipherSuite exceeds max count\n"); + goto done; + } + tlv_len_rsn += PAIRWISE_CIPHER_SUITE_LEN; + cmd_len += PAIRWISE_CIPHER_SUITE_LEN; + for (i = 0; i < PAIRWISE_CIPHER_SUITE_LEN; i++) { + pairwise_cipher_suite[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } + memcpy((t_u8 *)(rsn_ie->pairwise_cipher_suite + + (pairwise_index * + PAIRWISE_CIPHER_SUITE_LEN)), + pairwise_cipher_suite, + PAIRWISE_CIPHER_SUITE_LEN); + pairwise_index++; + pairwise_offset = + pairwise_index * PAIRWISE_CIPHER_SUITE_LEN; + } else if (strcmp(args[0], "AKMSuiteCount") == 0) { + akm_count = (t_u16)atoi(args[1]); + akm_count = cpu_to_le16(akm_count); + memcpy((((t_u8 *)(&rsn_ie->akm_suite_count)) + + pairwise_offset), &akm_count, sizeof(t_u16)); + } else if (strncmp(args[0], "AKMSuite", 8) == 0) { + if (akm_index > MAX_AKM_SUITE_COUNT) { + printf("AKMSuite exceeds max count\n"); + goto done; + } + tlv_len_rsn += AKM_SUITE_LEN; + cmd_len += AKM_SUITE_LEN; + for (i = 0; i < AKM_SUITE_LEN; i++) { + akm_suite[i] = (t_u8)A2HEXDECIMAL(args[i + 1]); + } + memcpy((t_u8 *)(rsn_ie->akm_suite + + (akm_index * AKM_SUITE_LEN) + + pairwise_offset), akm_suite, + AKM_SUITE_LEN); + akm_index++; + akm_offset = akm_index * AKM_SUITE_LEN; + } else if (strcmp(args[0], "RSNCapability") == 0) { + rsn_cap = (t_u16)A2HEXDECIMAL(args[1]); + rsn_cap = cpu_to_le16(rsn_cap); + memcpy(((t_u8 *)(&(rsn_ie->rsn_capability))) + + pairwise_offset + akm_offset, &rsn_cap, + sizeof(t_u16)); + } else if (strcmp(args[0], "PMKIDCount") == 0) { + pmk_count = (t_u16)atoi(args[1]); + pmk_count = cpu_to_le16(pmk_count); + memcpy((((t_u8 *)(&rsn_ie->pmkid_count)) + + pairwise_offset + akm_offset), &pmk_count, + sizeof(t_u16)); + rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN; + endian_convert_tlv_header_out(rsn_ie); + } else if (strncmp(args[0], "PMKIDList", 9) == 0) { + if (pmkid_index > MAX_PMKID_COUNT) { + printf("PMKIDSuite exceeds max count\n"); + goto done; + } + for (i = 0; i < PMKID_LEN; i++) + pmkid[i] = (t_u8)A2HEXDECIMAL(args[i + 1]); + memcpy((t_u8 *)(rsn_ie->pmkid_list + + (pmkid_index * PMKID_LEN) + + pairwise_offset + akm_offset), pmkid, + PMKID_LEN); + pmkid_index++; + tlv_len_rsn += PMKID_LEN; + cmd_len += PMKID_LEN; + /* undo conversion done in PMKIDCount */ + endian_convert_tlv_header_in(rsn_ie); + rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN; + endian_convert_tlv_header_out(rsn_ie); + } else if (strcmp(args[0], "SupportedChannels") == 0) { + /* Append a new TLV */ + supp_chan = + (tlvbuf_SupportedChannels_t *)(buffer + + cmd_len); + supp_chan->tag = TLV_TYPE_SUPPORTED_CHANNELS; + supp_chan->length = sizeof(tlvbuf_SupportedChannels_t) + - TLVHEADER_LEN; + tlv_len_supp_chan = sizeof(tlvbuf_SupportedChannels_t); + cmd_len += tlv_len_supp_chan; + } else if (strncmp(args[0], "FirstChannelNo", 14) == 0) { + supp_chan->subband[no_of_supp_chan_sub_band]. + start_chan = atoi(args[1]); + } else if (strcmp(args[0], "NumberofSubBandChannels") == 0) { + supp_chan->subband[no_of_supp_chan_sub_band].num_chans = + atoi(args[1]); + no_of_supp_chan_sub_band++; + tlv_len_supp_chan += + sizeof(IEEEtypes_SupportChan_Subband_t); + supp_chan->length += + sizeof(IEEEtypes_SupportChan_Subband_t); + cmd_len += sizeof(IEEEtypes_SupportChan_Subband_t); + endian_convert_tlv_header_out(supp_chan); + } else if (strcmp(args[0], "SupportedRegulatoryClasses") == 0) { + /* Append a new TLV */ + reg_class = + (tlvbuf_RegulatoryClass_t *)(buffer + cmd_len); + tlv_len_reg_class = sizeof(tlvbuf_RegulatoryClass_t); + reg_class->tag = TLV_TYPE_REGULATORY_CLASSES; + cmd_len += tlv_len_reg_class; + } else if (strcmp(args[0], "CurrentRegulatoryClass") == 0) { + reg_class->regulatory_class.cur_regulatory_class = + atoi(args[1]); + reg_class->length = 1; + } else if (strcmp(args[0], "NumofRegulatoryClasses") == 0) { + num_of_regulatory_class = atoi(args[1]); + reg_class->length += num_of_regulatory_class; + cmd_len += num_of_regulatory_class; + endian_convert_tlv_header_out(reg_class); + } else if (strcmp(args[0], "ListOfRegulatoryClasses") == 0) { + for (i = 0; i < num_of_regulatory_class; i++) + reg_class->regulatory_class. + regulatory_classes_list[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } else if (strcmp(args[0], "CountryInfo") == 0) { + /* Append a new TLV */ + domain = (tlvbuf_DomainParamSet_t *)(buffer + cmd_len); + domain->tag = TLV_TYPE_DOMAIN; + domain->length = sizeof(tlvbuf_DomainParamSet_t) + - TLVHEADER_LEN; + tlv_len_domain = sizeof(tlvbuf_DomainParamSet_t); + cmd_len += tlv_len_domain; + } else if (strcmp(args[0], "CountryString") == 0) { + strncpy(country, args[1] + 1, strlen(args[1]) - 2); + country[strlen(args[1]) - 2] = '\0'; + for (i = 1; (unsigned int)i < strlen(country) - 2; i++) { + if ((country[i] < 'A') || (country[i] > 'z')) { + printf("Invalid Country Code\n"); + goto done; + } + if (country[i] > 'Z') + country[i] = country[i] - 'a' + 'A'; + } + memset(domain->country_code, ' ', + sizeof(domain->country_code)); + memcpy(domain->country_code, country, strlen(country)); + } else if (strncmp(args[0], "FirstChannel", 12) == 0) { + domain->sub_band[no_of_sub_band].first_chan = + atoi(args[1]); + } else if (strncmp(args[0], "NumberofChannels", 16) == 0) { + domain->sub_band[no_of_sub_band].no_of_chan = + atoi(args[1]); + } else if (strncmp(args[0], "TxPower", 7) == 0) { + domain->sub_band[no_of_sub_band].max_tx_pwr = + atoi(args[1]); + no_of_sub_band++; + domain->length += sizeof(IEEEtypes_SubbandSet_t); + tlv_len_domain += sizeof(IEEEtypes_SubbandSet_t); + cmd_len += sizeof(IEEEtypes_SubbandSet_t); + endian_convert_tlv_header_out(domain); + } else if (strcmp(args[0], "VHTCapability") == 0) { + /* Append a new TLV */ + tlv_vht_cap = (tlvbuf_VHTCap_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_VHTCap_t); + tlv_vht_cap->tag = VHT_CAPABILITY; + tlv_vht_cap->length = + sizeof(tlvbuf_VHTCap_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_vht_cap); + } else if (strcmp(args[0], "VHTCapabilityInfo") == 0) { + tlv_vht_cap->vht_cap.vht_cap_info = + (t_u32)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.vht_cap_info = + cpu_to_le16(tlv_vht_cap->vht_cap.vht_cap_info); + } else if (strcmp(args[0], "RxMCSMap") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + rx_mcs_map); + } else if (strcmp(args[0], "TxMCSMap") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + tx_mcs_map); + } else if (strcmp(args[0], "RxMaxRate") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + rx_max_rate); + } else if (strcmp(args[0], "TxMaxRate") == 0) { + tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate = + (t_u16)A2HEXDECIMAL(args[1]); + tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate = + cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets. + tx_max_rate); + } else if (strcmp(args[0], "VHTOper") == 0) { + /* Append a new TLV */ + tlv_vht_oper = (tlvbuf_VHTOpra_t *)(buffer + cmd_len); + tlv_len = sizeof(tlvbuf_VHTOpra_t); + tlv_vht_oper->tag = VHT_OPERATION; + tlv_vht_oper->length = + sizeof(tlvbuf_VHTOpra_t) - TLVHEADER_LEN; + cmd_len += tlv_len; + endian_convert_tlv_header_out(tlv_vht_oper); + } else if (strcmp(args[0], "ChanWidth") == 0) { + tlv_vht_oper->chan_width = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ChanCF1") == 0) { + tlv_vht_oper->chan_cf1 = A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ChanCF2") == 0) { + tlv_vht_oper->chan_cf2 = (t_u16)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "BasicMCSMap") == 0) { + if ((arg_num - 1) != VHT_MCS_MAP_LEN) { + printf("Incorrect number of arguments for BasicMCSMap.\n"); + goto done; + } + for (i = 0; i < VHT_MCS_MAP_LEN; i++) + tlv_vht_oper->basic_mcs_map[i] = + (t_u8)A2HEXDECIMAL(args[i + 1]); + } + } + /* adjust for size of action and tlv_len, capInfo */ + param_buf->tlv_len = cmd_len - sizeof(tdls_setinfo); + + hexdump("tdls_setinfo", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS Info settings sucessfully set.\n"); + } else { + printf("ERR:Could not set TDLS info configuration.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_discovery + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_discovery(int argc, char *argv[]) +{ + tdls_discovery *param_buf = NULL; + tdls_discovery_resp *resp_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0, rssi = 0; + char *args[30], *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0, buf_len = 0, resp_len = 0; + t_u8 *buffer = NULL, *raw = NULL; + IEEEtypes_Header_t *tlv = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_discovery \n"); + exit(1); + } + + cmd_len = sizeof(tdls_discovery); + buf_len = BUFFER_LENGTH; + + buffer = (t_u8 *)malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, buf_len); + param_buf = (tdls_discovery *)buffer; + param_buf->action = ACTION_TDLS_DISCOVERY; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + ret = mac2raw(mac_addr, peer_mac); + if (ret != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_discovery", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + hexdump("tdls_response", buffer, 0x40, ' '); + printf("TDLS discovery done.\n"); + resp_buf = (tdls_discovery_resp *)buffer; + resp_len = resp_buf->payload_len; + printf("Response Length = %d\n", resp_len); + if (resp_len > 0) { + /* MAC */ + raw = resp_buf->peer_mac; + printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned int)raw[0], (unsigned int)raw[1], + (unsigned int)raw[2], (unsigned int)raw[3], + (unsigned int)raw[4], (unsigned int)raw[5]); + + /* RSSI, CapInfo */ + rssi = (int)(resp_buf->rssi); + if (rssi > 0x7f) + rssi = -(256 - rssi); + printf("\tRssi : %d dBm\n", rssi); + printf("\tCapInfo = 0x%02X\n", resp_buf->cap_info); + + resp_len -= ETH_ALEN + sizeof(resp_buf->rssi) + + sizeof(resp_buf->cap_info); + + /* TLVs */ + tlv = (IEEEtypes_Header_t *)&resp_buf->tlv_buffer; + while (resp_len > IEEE_HEADER_LEN) { + switch (tlv->element_id) { + case TLV_TYPE_RATES: + printf("\tRates : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_EXTENDED_SUPPORTED_RATES: + printf("\tExtended Rates : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_TYPE_QOSINFO: + printf("\tQosInfo "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_EXTCAP: + printf("\tExtended Cap "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_HT_CAP: + printf("\tHT Cap "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_HT_INFO: + printf("\tHT Info"); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_2040BSS_COEXISTENCE: + printf("\t2040 BSS Coex "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_RSN_IE: + printf("\tRSN IE "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_SUPPORTED_CHANNELS: + printf("\tSupported Channels "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + + case TLV_TYPE_DOMAIN: + printf("\tDomain Info "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_LINK_IDENTIFIER: + printf("\tLink identifier : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_TIMEOUT_INTERVAL: + printf("\tTimeout interval : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + case TLV_TYPE_REGULATORY_CLASSES: + printf("\t Regulatory classes : "); + hexdump(NULL, + ((t_u8 *)tlv) + IEEE_HEADER_LEN, + tlv->len, ' '); + break; + default: + printf("Unknown TLV\n"); + hexdump(NULL, ((t_u8 *)tlv), + IEEE_HEADER_LEN + tlv->len, + ' '); + break; + } + resp_len -= tlv->len + IEEE_HEADER_LEN; + tlv = (IEEEtypes_Header_t *)((t_u8 *)tlv + + tlv->len + + IEEE_HEADER_LEN); + } + } + + } else { + printf("ERR:Command response = Fail!\n"); + } +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_setup + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_setup(int argc, char *argv[]) +{ + tdls_setup *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30], *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_setup \n"); + exit(1); + } + + cmd_len = sizeof(tdls_setup); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_setup *) buffer; + param_buf->action = ACTION_TDLS_SETUP; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + ret = mac2raw(mac_addr, peer_mac); + if (ret != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "WaitTimems") == 0) { + param_buf->wait_time = (t_u32)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "KeyLifetime") == 0) { + param_buf->key_life_time = (t_u32)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_setup", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS setup request successful.\n"); + } else { + printf("ERR:TDLS setup request failed.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_teardown + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_teardown(int argc, char *argv[]) +{ + tdls_teardown *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30], *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_teardown \n"); + exit(1); + } + + cmd_len = sizeof(tdls_teardown); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_teardown *)buffer; + param_buf->action = ACTION_TDLS_TEARDOWN; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + ret = mac2raw(mac_addr, peer_mac); + if (ret != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "ReasonCode") == 0) { + param_buf->reason_code = (t_u16)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_teardown", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS teardown request successful.\n"); + } else { + printf("ERR:TDLS teardown request failed.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_powermode + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_powermode(int argc, char *argv[]) +{ + tdls_powermode *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30], *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_powermode \n"); + exit(1); + } + + cmd_len = sizeof(tdls_powermode); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_powermode *)buffer; + param_buf->action = ACTION_TDLS_POWER_MODE; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + ret = mac2raw(mac_addr, peer_mac); + if (ret != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "PowerMode") == 0) { + param_buf->power_mode = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->power_mode > 1) { + printf("ERR: Incorrect PowerMode value %s\n", + args[1]); + goto done; + } + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_powermode", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS powermode request successful.\n"); + } else { + printf("ERR:TDLS powermode request failed.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_link_status + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_link_status(int argc, char *argv[]) +{ + int ret = 0; + tdls_link_status *param_buf = NULL; + tdls_link_status_resp *resp_buf = NULL; + t_u16 cmd_len = 0, buf_len = 0, resp_len = 0, curr_link_len = 0; + t_u8 no_of_links = 0, peer_mac[ETH_ALEN]; + t_u8 *buffer = NULL, *raw = NULL; + tdls_each_link_status *link_ptr = NULL; + + /* Check arguments */ + if (argc != 3 && argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_link_status [peer_mac_addr]\n"); + exit(1); + } + + cmd_len = sizeof(tdls_link_status); + buf_len = BUFFER_LENGTH; + + buffer = (t_u8 *)malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, buf_len); + param_buf = (tdls_link_status *)buffer; + param_buf->action = ACTION_TDLS_LINK_STATUS; + + if (argc == 4) { + ret = mac2raw(argv[3], peer_mac); + if (ret != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret == + MAC_BROADCAST ? "Broadcast" : "Multicast"); + goto done; + } + if (memcmp(peer_mac, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)) { + memcpy(buffer + cmd_len, peer_mac, ETH_ALEN); + cmd_len += ETH_ALEN; + } + } + + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + hexdump("tdls_response", buffer, 0x60, ' '); + printf("TDLS Link Status - .\n"); + resp_buf = (tdls_link_status_resp *)buffer; + resp_len = resp_buf->payload_len; + printf("Response Length = %d\n", resp_len); + no_of_links = resp_buf->active_links; + printf("No of active links = %d\n", no_of_links); + resp_len--; + link_ptr = resp_buf->link_stats; + while (resp_len > 0 && no_of_links > 0) { + curr_link_len = 0; + /* MAC */ + raw = link_ptr->peer_mac; + printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned int)raw[0], (unsigned int)raw[1], + (unsigned int)raw[2], (unsigned int)raw[3], + (unsigned int)raw[4], (unsigned int)raw[5]); + + printf("\t %s initiated link.\n", + (link_ptr->link_flags & 0x01) ? "Self" : "Peer"); + printf("\t Security %s.\n", + (link_ptr-> + link_flags & 0x02) ? "Enabled" : "Disabled"); + printf("\t Self PS status = %s.\n", + (link_ptr-> + link_flags & 0x04) ? "Sleep" : "Active"); + printf("\t Peer PS status = %s.\n", + (link_ptr-> + link_flags & 0x08) ? "Sleep" : "Active"); + printf("\t Channel switch is %ssupported\n", + (link_ptr->link_flags & 0x10) ? "" : "NOT "); + printf("\t Current Channel %s\n", + (link_ptr->link_flags & 0x20) ? "off" : "base"); + + if (link_ptr->traffic_status) { + printf("\t Buffered traffic for"); + printf("%s", + (link_ptr-> + traffic_status & 0x01) ? "AC_BK, " : + ""); + printf("%s", + (link_ptr-> + traffic_status & 0x02) ? "AC_BE, " : + ""); + printf("%s", + (link_ptr-> + traffic_status & 0x04) ? "AC_VI, " : + ""); + printf("%s", + (link_ptr-> + traffic_status & 0x08) ? "AC_VO" : ""); + printf(".\n"); + } + printf("\t Successive Tx Failure count = %d\n", + link_ptr->tx_fail_count); + printf("\t Active channel number = %d\n", + link_ptr->active_channel); + printf("\t Last Data RSSI = %d dBm\n", + link_ptr->data_rssi_last); + printf("\t Last Data NF = %d dBm\n", + link_ptr->data_nf_last); + printf("\t Average Data RSSI = %d dBm\n", + link_ptr->data_rssi_avg); + printf("\t Average Data NF = %d dBm\n", + link_ptr->data_nf_avg); + printf("\t Tx data rate = %d Mbps\n", + link_ptr->u.final_data_rate); + + /* size of unsecure structure */ + curr_link_len = sizeof(tdls_each_link_status) - + (sizeof(t_u32) + sizeof(t_u8) + sizeof(t_u8)); + + if (link_ptr->link_flags & 0x02) { + /* security details */ + printf("\t Security Method = %s\n", + (link_ptr->security_method == + 1) ? "AES" : "None"); + printf("\t Key Lifetime = %d ms\n\t", + link_ptr->key_lifetime); + hexdump("Key", ((t_u8 *)link_ptr->key), + link_ptr->key_length, ' '); + curr_link_len += + sizeof(t_u32) + sizeof(t_u8) + + sizeof(t_u8) + + link_ptr->key_length; + } + resp_len -= curr_link_len; + link_ptr = + (tdls_each_link_status *)(((t_u8 *)link_ptr) + + curr_link_len); + printf(".\n"); + } + + } else { + printf("ERR:Command response = Fail!\n"); + } +done: + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_channel_swtich + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_channel_switch(int argc, char *argv[]) +{ + + tdls_channel_switch *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30], *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_channel_switch \n"); + exit(1); + } + + cmd_len = sizeof(tdls_channel_switch); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_channel_switch *)buffer; + param_buf->action = ACTION_TDLS_INIT_CHAN_SWITCH; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + ret = mac2raw(mac_addr, peer_mac); + if (ret != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "Band") == 0) { + param_buf->band = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->band != BAND_BG_TDLS && + param_buf->band != BAND_A_TDLS) { + printf("ERR: Incorrect Band value %s\n", + args[1]); + goto done; + } + } else if (strcmp(args[0], "RegulatoryClass") == 0) { + param_buf->regulatory_class = + (t_u16)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "PrimaryChannel") == 0) { + param_buf->primary_channel = + (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->band == BAND_BG_TDLS && + param_buf->primary_channel < MIN_BG_CHANNEL && + param_buf->primary_channel > MAX_BG_CHANNEL) { + printf("ERR: Incorrect Primary Channel value %s\n", args[1]); + goto done; + } else if (param_buf->band == BAND_A_TDLS + && param_buf->primary_channel < MIN_A_CHANNEL + && param_buf->primary_channel > + MAX_A_CHANNEL) { + printf("ERR: Incorrect Primary Channel value %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "SecondaryChannelOffset") == 0) { + param_buf->secondary_channel_offset = + (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->secondary_channel_offset != SEC_CHAN_NONE + && param_buf->secondary_channel_offset != + SEC_CHAN_ABOVE && + param_buf->secondary_channel_offset != + SEC_CHAN_BELOW) { + printf("ERR: Incorrect Secondary Channel Offset value %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "ChannelSwitchTime") == 0) { + param_buf->switch_time = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->switch_time == 0) { + printf("ERR: Incorrect Channel Switch time %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "ChannelSwitchTimeout") == 0) { + param_buf->switch_timeout = + (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->switch_timeout == 0) { + printf("ERR: Incorrect Channel Switch timeout %s\n", args[1]); + goto done; + } + } else if (strcmp(args[0], "Periodicity") == 0) { + param_buf->periodicity = (t_u16)A2HEXDECIMAL(args[1]); + if (param_buf->periodicity != NO_PERIODIC_SWITCH + && param_buf->periodicity != + ENABLE_PERIODIC_SWITCH) { + printf("ERR: Incorrect Periodicity value %s\n", + args[1]); + goto done; + } + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_channel_switch", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS channel switch request successful.\n"); + } else { + printf("ERR:TDLS channel switch request failed.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief disable tdls_channel_swtich + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_disable_channel_switch(int argc, char *argv[]) +{ + + tdls_disable_cs *param_buf = NULL; + int ret = 0; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_disable_cs <0/1>\n"); + exit(1); + } + + cmd_len = sizeof(tdls_disable_cs); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_disable_cs *) buffer; + param_buf->action = ACTION_TDLS_CS_DISABLE; + + param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]); + if ((param_buf->data != 0) && (param_buf->data != 1)) { + printf("ERR:Incorrect arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_disable_cs <0/1>\n"); + goto done; + } + hexdump("tdls_disable_cs", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS disable channel switch successful.\n"); + } else { + printf("ERR:TDLS disable channel switch failed.\n"); + } + +done: + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_stop_channel_switch + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_stop_channel_switch(int argc, char *argv[]) +{ + tdls_stop_chan_switch *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30], *pos = NULL, mac_addr[20]; + t_u8 peer_mac[ETH_ALEN]; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_stop_channel_switch \n"); + exit(1); + } + + cmd_len = sizeof(tdls_stop_chan_switch); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_stop_chan_switch *) buffer; + param_buf->action = ACTION_TDLS_STOP_CHAN_SWITCH; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "PeerMAC") == 0) { + strncpy(mac_addr, args[1], 20); + ret = mac2raw(mac_addr, peer_mac); + if (ret != MLAN_STATUS_SUCCESS) { + printf("ERR: %s Address \n", + ret == + MLAN_STATUS_FAILURE ? "Invalid MAC" : ret + == + MAC_BROADCAST ? "Broadcast" : + "Multicast"); + goto done; + } + memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_stop_channel_switch", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS stop channel switch successful.\n"); + } else { + printf("ERR:TDLS stop channel switch failed.\n"); + } + +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_cs_params + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_cs_params(int argc, char *argv[]) +{ + tdls_cs_params *param_buf = NULL; + char *line = NULL; + FILE *config_file = NULL; + int li = 0, ret = 0, cmd_found = 0; + char *args[30], *pos = NULL; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + + /* Check arguments */ + if (argc != 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_cs_params \n"); + exit(1); + } + + cmd_len = sizeof(tdls_cs_params); + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_cs_params *) buffer; + param_buf->action = ACTION_TDLS_CS_PARAMS; + + /* Check if file exists */ + config_file = fopen(argv[3], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + line = (char *)malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + memset(line, 0, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { + parse_line(line, args); + if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0]))) + continue; + + cmd_found = 1; + + if (strcmp(args[0], "UnitTime") == 0) { + param_buf->unit_time = (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ThresholdOtherLink") == 0) { + param_buf->threshold_otherlink = + (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "ThresholdDirectLink") == 0) { + param_buf->threshold_directlink = + (t_u8)A2HEXDECIMAL(args[1]); + } else if (strcmp(args[0], "}") == 0 && cmd_found) { + break; + } + } + hexdump("tdls_cs_params", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS set channel switch parameters successful.\n"); + } else { + printf("ERR:TDLS set channel switch parameters failed.\n"); + } +done: + if (config_file) + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls_debug + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_debug(int argc, char *argv[]) +{ + int ret = 0; + tdls_debug *param_buf = NULL; + t_u16 cmd_len = 0; + t_u8 *buffer = NULL; + t_u16 action = 0, value = 0; + + /* Check arguments */ + if (argc < 4) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug \n"); + exit(1); + } + + cmd_len = sizeof(tdls_debug); + + /* wrong_bss */ + if (!strcmp(argv[3], "wrong_bss")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_WRONG_BSS; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug wrong_bss <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* same link */ + else if (!strcmp(argv[3], "setup_existing_link")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_SETUP_SAME_LINK; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug setup_existing_link <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* fail_setup_confirm */ + else if (!strcmp(argv[3], "fail_setup_confirm")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_FAIL_SETUP_CONFIRM; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug fail_setup_confirm <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* setup prohibited */ + else if (!strcmp(argv[3], "setup_with_prohibited")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_SETUP_PROHIBITED; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug setup_with_prohibited <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* setup higher/lower mac */ + else if (!strcmp(argv[3], "higher_lower_mac")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_HIGHER_LOWER_MAC; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug higher_lower_mac <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* ignore key lifetime expiry */ + else if (!strcmp(argv[3], "ignore_key_expiry")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_IGNORE_KEY_EXPIRY; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug ignore_key_expiry <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* allow weak security */ + else if (!strcmp(argv[3], "allow_weak_security")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_ALLOW_WEAK_SECURITY; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug allow_weak_security <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* stop RX */ + else if (!strcmp(argv[3], "stop_rx")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_STOP_RX; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug stop_rx <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } + /* Immediate return */ + else if (!strcmp(argv[3], "cs_im_return")) { + cmd_len += sizeof(t_u16); + action = ACTION_TDLS_DEBUG_CS_RET_IM; + if (argc < 5) { + printf("ERR:Incorrect number of arguments.\n"); + printf("Syntax: ./mlanutl mlanX tdls_debug cs_im_return <0/1>\n"); + exit(1); + } + value = (t_u16)A2HEXDECIMAL(argv[4]); + } else { + printf("ERR:Incorrect command!\n"); + exit(1); + } + + buffer = (t_u8 *)malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + return -1; + } + memset(buffer, 0, cmd_len); + param_buf = (tdls_debug *)buffer; + param_buf->action = action; + memcpy(param_buf->data, &value, sizeof(value)); + + hexdump("tdls_debug", buffer, cmd_len, ' '); + /* Send collective command */ + ret = tdls_ioctl((t_u8 *)buffer, cmd_len); + + /* Process response */ + if (ret == MLAN_STATUS_SUCCESS) { + printf("TDLS debug request successful.\n"); + } else { + printf("ERR:TDLS debug request failed.\n"); + } + + if (buffer) + free(buffer); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Process tdls idle time set/get + * @param argc Number of arguments + * @param argv A pointer to arguments array + * @return MLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_tdls_idle_time(int argc, char *argv[]) +{ + t_u8 *buffer = NULL; + struct eth_priv_cmd *cmd = NULL; + struct ifreq ifr; + int tdls_idle_time = 0; + + /* Check arguments */ + if (argc < 3 || argc > 4) { + printf("ERR:Incorrect number of arguments!\n"); + printf("Syntax: ./mlanutl mlanX tdls_idle_time