diff options
Diffstat (limited to 'packages')
-rwxr-xr-x | packages/dreamplug-uaputl/Makefile | 52 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/config/80211d_domain.conf | 28 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/config/pack.conf | 1 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/config/sample_cal_data_bg_8688.conf | 42 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/config/uapcoex.conf | 21 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/config/uaputl.conf | 95 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/uapcmd.c | 4704 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/uapcmd.h | 63 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/uaputl.c | 5565 | ||||
-rw-r--r-- | packages/dreamplug-uaputl/uaputl.h | 1289 |
10 files changed, 11860 insertions, 0 deletions
diff --git a/packages/dreamplug-uaputl/Makefile b/packages/dreamplug-uaputl/Makefile new file mode 100755 index 0000000..1847183 --- /dev/null +++ b/packages/dreamplug-uaputl/Makefile @@ -0,0 +1,52 @@ +# File : uaputl/Makefile +# +# Copyright (C) 2008, 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__%, $(EXTRA_CFLAGS)) + + +#CFLAGS += -DAP22 -fshort-enums +CFLAGS += -Wall +#ECHO = @ +LIBS = -lrt + +.PHONY: default tags all + +OBJECTS = uaputl.o uapcmd.o +HEADERS = uaputl.h uapcmd.h + +TARGET = uaputl + +build default: $(TARGET) + @cp -f $(TARGET) $(INSTALLPATH) + @cp -rf config/* $(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 + +clean: + $(ECHO)$(RM) $(OBJECTS) $(TARGET) + $(ECHO)$(RM) tags.txt + diff --git a/packages/dreamplug-uaputl/config/80211d_domain.conf b/packages/dreamplug-uaputl/config/80211d_domain.conf new file mode 100644 index 0000000..08061c4 --- /dev/null +++ b/packages/dreamplug-uaputl/config/80211d_domain.conf @@ -0,0 +1,28 @@ +/* Domain and country mapping are in this section */ +/* Domain name followed by supported countries */ + +COUNTRY: DOMAIN_CODE_FCC AE AL AM AN AR AT AU AZ BA BE BG BH BL BN BR BY CH CL CN CR CS CY CZ DE DK DZ EC EE EG ES FI FR GE GB GR HN HK HR HU ID IE IL IN IS IR IT JM JO KP KR KW KZ LB LI LK LT LU LV MC MA MO MK MT MY NL NO NP OM PE PG PH PK PL PT QA RO RU SA SE SG SI SK SV SY TH TT TN TR UA UY YE ZA ZW VN +COUNTRY: DOMAIN_CODE_FCC1 US UZ CA CO DO GT MX PA PR TW NZ BO BZ VE +COUNTRY: DOMAIN_CODE_MKK JP + + +/* Domain specific sub-band information */ +/* Domain name followed by set of triplets separated by comma */ +/* 1st number in triplet is First channel, */ +/* 2nd number in triplet is Number of channels followed from the First channel */ +/* 3rd number in triplet is Max-TX-power in dbm */ + +DOMAIN: DOMAIN_CODE_FCC 1 11 20 +DOMAIN: DOMAIN_CODE_FCC1 1 11 30 +DOMAIN: DOMAIN_CODE_IC 1 11 30 +DOMAIN: DOMAIN_CODE_ETSI 1 13 20 +DOMAIN: DOMAIN_CODE_FRANCE 10 4 20 +DOMAIN: DOMAIN_CODE_MKK 1 14 23 +DOMAIN: DOMAIN_CODE_DGT 1 11 30 +DOMAIN: DOMAIN_CODE_AUS 1 13 20 +DOMAIN: DOMAIN_CODE_AUS1 1 13 30 +DOMAIN: DOMAIN_CODE_MKK2 1 14 23 +DOMAIN: DOMAIN_CODE_ALL 1 14 30 +DOMAIN: DOMAIN_CODE_TEST 1 1 20, 2 1 16, 3 6 30, 11 1 10 +DOMAIN: DOMAIN_CODE_TEST1 1 11 30, 36 1 17, 40 1 17, 44 1 17, 48 1 17, 52 1 24, 56 1 24, 60 1 24, 64 1 24, 149 1 23, 153 1 23, 157 1 23, 161 1 23, 165 1 23, +DOMAIN: DOMAIN_CODE_END diff --git a/packages/dreamplug-uaputl/config/pack.conf b/packages/dreamplug-uaputl/config/pack.conf new file mode 100644 index 0000000..256fbbc --- /dev/null +++ b/packages/dreamplug-uaputl/config/pack.conf @@ -0,0 +1 @@ +C0 00 3A 01 00 12 F0 C2 41 7F 00 50 43 20 BA EA 00 50 43 20 BA EA 00 00 00 00 diff --git a/packages/dreamplug-uaputl/config/sample_cal_data_bg_8688.conf b/packages/dreamplug-uaputl/config/sample_cal_data_bg_8688.conf new file mode 100644 index 0000000..7139ce5 --- /dev/null +++ b/packages/dreamplug-uaputl/config/sample_cal_data_bg_8688.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/packages/dreamplug-uaputl/config/uapcoex.conf b/packages/dreamplug-uaputl/config/uapcoex.conf new file mode 100644 index 0000000..5727eae --- /dev/null +++ b/packages/dreamplug-uaputl/config/uapcoex.conf @@ -0,0 +1,21 @@ +# File : uapcoex.conf + +coex_config={ + common_config={ + bitmap=0x0 # bit 0: override CTS2RTS protection + } + sco_config={ + protectionFromQTime0=1000 + protectionFromQTime1=600 + protectionFromQTime2=0 + protectionFromQTime3=0 + scoProtectionFromRate=9 + aclFrequency=20 + } + acl_config={ + enabled=1 + btTime=40 + wlanTime=60 + aclProtectionFromRate=1 + } +} diff --git a/packages/dreamplug-uaputl/config/uaputl.conf b/packages/dreamplug-uaputl/config/uaputl.conf new file mode 100644 index 0000000..0899b51 --- /dev/null +++ b/packages/dreamplug-uaputl/config/uaputl.conf @@ -0,0 +1,95 @@ +# File : uap.conf + + +ap_config={ + SSID="Marvell Micro AP" # SSID of Micro AP + BeaconPeriod=100 # Beacon period in TU + Channel=6 # Radio Channel 6 +# Channel=0,1 # auto channel select (MCS mode) + ChanList=1,6,11 # Scan channel list +# AP_MAC=00:34:22:77:46:41 # MAC address of AP + RxAntenna=0 # 0 for Antenna A + # 1 for Antenna B + TxAntenna=0 # 0 for Antenna A + # 1 for Antenna B + Rate=0x82,0x84,0x8b,0x96,0x0C,0x12,0x18,0x24,0x30,0x48,0x60,0x6c + # Set of data rate that a station + # in the BSS may use + # (in unit of 500 kilobit/s) + TxPowerLevel=13 # Transmit power level in dBm + BroadcastSSID=1 # Broadcast SSID feature + # 1: Enable 0:Disable + RTSThreshold=2347 # RTS threshold value + FragThreshold=2346 # Fragmentation threshold value + DTIMPeriod=1 # DTIM period in beacon periods + RadioControl=1 # 0: radio on 1: radio off + MCBCdataRate=0 # MCBC rate to use for packet transmission + # 0:auto + # >0 fix rate (in unit of 500 kilobit/s) + TxDataRate=0 # Data rate to use for packet transmission + # 0:auto + # >0 fix rate (in unit of 500 kilobit/s) + PktFwdCtl=1 # Packet forwarding control + # 0: forward all packets to the host + # 1: firmware handles intr-BSS packets + StaAgeoutTimer=1800 # Inactive client station age out timer value + # in units of 100ms + MaxStaNum=8 # Max number of stations allowed to connect + Retrylimit=7 # Retry limit to use for packet transmissions + AuthMode=0 # 0:Open authentication + # 1:shared key authentication + # 2: Static WEP + Protocol=1 # protocol to use + # 1: No security 2: Static WEP + # 8: WPA 32: WPA2 40:WPA2 Mixed Mode + RSNReplayProtection=0 # RSN replay protection 0: disabled, 1: enabled + +# **** WEP security setting****** +# KeyIndex=0 # Index of WEP key to use (0 to 3) +# Sample Key configurations are +# Key_0="55555" +# Key_1=1234567890 +# Key_2="1234567890123" +# Key_3=12345678901234567890123456 + + +# **** WPA/WPA2 PSK setting****** + +# PairwiseCipher=4 # Pairwise cipher type + # 0: None + # 4: TKIP 8: AES CCMP + # 12: AES CCMP + TKIP +# GroupCipher=4 # group cipher type + # 0: None + # 4: TKIP 8: AES CCMP +# PSK="1234567890" # WPA/WPA2 passphrase + GroupRekeyTime= 86400 # Group key re-key interval, in second. + # 0 mean never re-key + #802.11D specific configuration + 11d_enable=0 # 0-disable 1-enable +# country=US # country information +} + + + +ap_mac_filter={ + FilterMode=0 # Mode of filter table + # 0: filter table is disabled + # 1: allow MAC address in the filter table to associate + # 2: block MAC address in the filter table + Count=0 # Number of entries in filter table,up to 16 +#Sample mac settings are +# mac_1=00:50:23:45:76:22 # mac address +# mac_2=00:34:22:77:46:34 # mac address +} + +#custom_ie_config={ +# MgmtSubtypeMask_0=0x1 +# IEBuffer_0=0x6403736976 +# MgmtSubtypeMask_1=0x2 +# IEBuffer_1=0x650473697661 +# MgmtSubtypeMask_2=0x4 +# IEBuffer_2=0x6606736976617273 +# MgmtSubtypeMask_3=0x8 +# IEBuffer_3=0x6606736976617573 +#} diff --git a/packages/dreamplug-uaputl/uapcmd.c b/packages/dreamplug-uaputl/uapcmd.c new file mode 100644 index 0000000..628280b --- /dev/null +++ b/packages/dreamplug-uaputl/uapcmd.c @@ -0,0 +1,4704 @@ +/** @file uapcmd.c + * + * @brief This file contains the handling of command. + * + * Copyright (C) 2008-2009, 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/01/08: Initial creation +****************************************************************************/ + +/**************************************************************************** + Header files +****************************************************************************/ +#include <sys/types.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <stdio.h> +#include <getopt.h> +#include <netinet/in.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <sys/ioctl.h> +#include <errno.h> +#include "uaputl.h" +#include "uapcmd.h" + +extern struct option cmd_options[]; + +/**************************************************************************** + Local functions +****************************************************************************/ +/** + * @brief Show usage information for the sys_cfg_ap_mac_address + * command + * + * $return N/A + */ +void +print_sys_cfg_ap_mac_address_usage(void) +{ + printf("\nUsage : sys_cfg_ap_mac_address [AP_MAC_ADDRESS]\n"); + printf + ("\nIf AP_MAC_ADDRESS is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_ssid command + * + * $return N/A + */ +void +print_sys_cfg_ssid_usage(void) +{ + printf("\nUsage : sys_cfg_ssid [SSID]\n"); + printf + ("\nIf SSID is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_beacon_period + * command + * + * $return N/A + */ +void +print_sys_cfg_beacon_period_usage(void) +{ + printf("\nUsage : sys_cfg_beacon_period [BEACON_PERIOD]\n"); + printf + ("\nIf BEACON_PERIOD is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_dtim_period + * command + * + * $return N/A + */ +void +print_sys_cfg_dtim_period_usage(void) +{ + printf("\nUsage : sys_cfg_dtim_period [DTIM_PERIOD]\n"); + printf + ("\nIf DTIM_PERIOD is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_channel + * command + * + * $return N/A + */ +void +print_sys_cfg_channel_usage(void) +{ + printf("\nUsage : sys_cfg_channel [CHANNEL] [MODE]\n"); + printf + ("\nIf CHANNEL is provided, a 'set' is performed, else a 'get' is performed."); + printf("\nIf MODE is provided, 0 for manual channel selection,"); + printf("\nelse ACS (automatic channel selection) is performed\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_scan_channels + * command + * + * $return N/A + */ +void +print_sys_cfg_scan_channels_usage(void) +{ + printf("\nUsage : sys_cfg_scan_channels [CHANNELS]\n"); + printf + ("\nIf CHANNELS are provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_rates_ext command + * + * $return N/A + */ +void +print_sys_cfg_rates_ext_usage(void) +{ + printf + ("\nUsage : sys_cfg_rates_ext [rates RATES] [mbrate RATE] [urate RATE]\n"); + printf + ("\nIf 'Rate' provided, a 'set' is performed else a 'get' is performed"); + printf + ("\nRATES is provided as a set of data rates, in unit of 500 kilobits"); + printf("\nA rate with MSB bit is basic rate, i.e 0x82 is basic rate.\n"); + printf("\nFollowing is the list of supported rates in units of 500 Kbps:"); + printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)"); + printf + ("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)"); + printf + ("\nBasic rates: (0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc)\n"); + printf + ("\nRates 2, 4, 11 and 22 (in units of 500 Kbps) must be present in either of basic or"); + printf + ("\nnon-basic rates. If OFDM rates are enabled then 12, 24 and 48 (in units of 500 Kbps)"); + printf("\nmust be present in either basic or non-basic rates"); + printf("\nEach rate must be separated by a space."); + printf("\nrates followed by RATES for setting operational rates."); + printf + ("\nmbrate followed by RATE for setting multicast and broadcast rate."); + printf("\nurate followed by RATE for setting unicast rate.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_rates command + * + * $return N/A + */ +void +print_sys_cfg_rates_usage(void) +{ + printf("\nUsage : sys_cfg_rates [RATES]\n"); + printf + ("\n[RATES] is set of data rates in unit of 500 kbps and each rate can be"); + printf + ("\nentered in hexadecimal or decimal format. Rates must be separated by"); + printf("\nspace. Duplicate Rate fields are not allowed"); + printf("\nA rate with MSB bit is basic rate, i.e 0x82 is basic rate."); + printf("\nFollowing is the list of supported rates in units of 500 Kbps:"); + printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)"); + printf + ("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)"); + printf + ("\nBasic rates: (0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc)\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_tx_power + * command + * + * $return N/A + */ +void +print_sys_cfg_tx_power_usage(void) +{ + printf("\nUsage : sys_cfg_tx_power [TX_POWER]\n"); + printf + ("\nIf TX_POWER is provided, a 'set' is performed, else a 'get' is performed."); + printf("\nTX_POWER is represented in dBm.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_bcast_ssid_ctl + * command + * + * $return N/A + */ +void +print_sys_cfg_bcast_ssid_ctl_usage(void) +{ + printf("\nUsage : sys_cfg_bcast_ssid_ctl [0|1]\n"); + printf("\nOptions: 0 - Disable SSID broadcast"); + printf("\n 1 - Enable SSID broadcast"); + printf("\n empty - Get current SSID broadcast setting\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_rsn_replay_prot + * command + * + * $return N/A + */ +void +print_sys_cfg_rsn_replay_prot_usage(void) +{ + printf("\nUsage : sys_cfg_rsn_replay_prot [0|1]\n"); + printf("\nOptions: 0 - Disable RSN replay protection"); + printf("\n 1 - Enable RSN replay protection"); + printf("\n empty - Get current RSN replay protection setting\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_preamble_ctl + * command + * + * $return N/A + */ +void +print_sys_cfg_preamble_ctl_usage(void) +{ + printf("\nUsage : sys_cfg_preamble_ctl\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_antenna_ctl + * command + * + * $return N/A + */ +void +print_sys_cfg_antenna_ctl_usage(void) +{ + printf("\nUsage : sys_cfg_antenna_ctl <ANTENNA> [MODE]\n"); + printf("\nOptions: ANTENNA : 0 - Rx antenna"); + printf("\n 1 - Tx antenna"); + printf("\n MODE : 0 - Antenna A"); + printf("\n 1 - Antenna B"); + printf("\n empty - Get current antenna settings\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_rts_threshold + * command + * + * $return N/A + */ +void +print_sys_cfg_rts_threshold_usage(void) +{ + printf("\nUsage : sys_cfg_rts_threshold [RTS_THRESHOLD]\n"); + printf + ("\nIf RTS_THRESHOLD is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_frag_threshold + * command + * + * $return N/A + */ +void +print_sys_cfg_frag_threshold_usage(void) +{ + printf("\nUsage : sys_cfg_frag_threshold [FRAG_THRESHOLD]\n"); + printf + ("\nIf FRAG_THRESHOLD is provided, a 'set' is performed, else a 'get' is performed."); + printf("\nFragment threshold should between 256 and 2346.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_radio_ctl + * command + * + * $return N/A + */ +void +print_sys_cfg_radio_ctl_usage(void) +{ + printf("\nUsage : sys_cfg_radio_ctl [0|1]\n"); + printf("\nOptions: 0 - Turn radio on"); + printf("\n 1 - Turn radio off"); + printf("\n empty - Get current radio setting\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_tx_data_rate + * command + * + * $return N/A + */ +void +print_sys_cfg_tx_data_rates_usage(void) +{ + printf("\nUsage : sys_cfg_tx_data_rate [TX_DATA_RATE]\n"); + printf("\nOptions: 0 - Auto rate"); + printf("\n >0 - Set specified data rate"); + printf("\n empty - Get current data rate"); + printf("\nFollowing is the list of supported rates in units of 500 Kbps"); + printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)"); + printf + ("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)"); + printf("\nOnly zero or rates currently configured are allowed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_mcbc_data_rate + * command + * + * $return N/A + */ +void +print_sys_cfg_mcbc_data_rates_usage(void) +{ + printf("\nUsage : sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]\n"); + printf("\nOptions: 0 - Auto rate"); + printf("\n >0 - Set specified MCBC data rate"); + printf("\n empty - Get current MCBC data rate"); + printf("\nFollowing is the list of supported rates in units of 500 Kbps"); + printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)"); + printf + ("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)"); + printf + ("\nOnly zero or one of the basic rates currently configured are allowed.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_auth command + * + * $return N/A + */ +void +print_sys_cfg_auth_usage(void) +{ + printf("\nUsage : sys_cfg_auth [AUTHMODE]\n"); + printf("\nOptions: AUTHMODE : 0 - Open authentication"); + printf("\n 1 - Shared key authentication"); + printf("\n empty - Get current authenticaton mode\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_pkt_fwd_ctl command + * + * $return N/A + */ +void +print_sys_cfg_pkt_fwd_ctl_usage(void) +{ + printf("\nUsage : sys_cfg_pkt_fwd_ctl [0|1]\n"); + printf("\nOptions: 0 - Forward all packets to the host"); + printf("\n 1 - Firmware handles intra-BSS packets"); + printf("\n empty - Get current packet forwarding setting\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_sta_ageout_timer + * command + * + * $return N/A + */ +void +print_sys_cfg_sta_ageout_timer_usage(void) +{ + printf("\nUsage : sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]\n"); + printf + ("\nIf STA_AGEOUT_TIMER is provided, a 'set' is performed, else a 'get' is performed."); + printf("\nSTA_AGEOUT_TIMER is represented in units of 100 ms."); + printf("\nValue of 0 will mean that stations will never be aged out."); + printf("\nThe value should between 300 and 864000.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_protocol command + * + * $return N/A + */ +void +print_sys_cfg_protocol_usage(void) +{ + printf("\nUsage : sys_cfg_protocol [PROTOCOL]\n"); + printf("\nOptions: PROTOCOL: 1 - No RSN"); + printf("\n 2 - WEP Static"); + printf("\n 8 - WPA"); + printf("\n 32 - WPA2"); + printf("\n 40 - WPA2 Mixed"); + printf("\n empty - Get current protocol\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_wep_key + * command + * + * $return N/A + */ +void +print_sys_cfg_wep_key_usage(void) +{ + printf("\nUsage : sys_cfg_wep_key "); + printf + ("[INDEX_0 IS_DEFAULT KEY_0] [INDEX_1 IS_DEFAULT KEY_1] [INDEX_2 IS_DEFAULT KEY_2] [INDEX_3 IS_DEFAULT KEY_3]\n"); + printf("[Index_0] [Index_1] [Index_2] [Index_3]\n"); + printf("\nOptions: INDEX_* : 0 - KeyIndex is 0"); + printf("\n 1 - KeyIndex is 1"); + printf("\n 2 - KeyIndex is 2"); + printf("\n 3 - KeyIndex is 3"); + printf("\n IS_DEFAULT : 0 - KeyIndex is not the default"); + printf + ("\n 1 - KeyIndex is the default transmit key"); + printf("\n KEY_* : Key value"); + printf("\n Index_*: 0 - Get key 0 setting"); + printf("\n 1 - Get key 1 setting"); + printf("\n 2 - Get key 2 setting"); + printf("\n 3 - Get key 3 setting"); + printf("\n empty - Get current WEP key settings\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_custom_ie + * command + * + * $return N/A + */ +void +print_sys_cfg_custom_ie_usage(void) +{ + printf("\nUsage : sys_cfg_custom_ie [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 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 Show usage information for the sys_cfg_cipher * command * * $return + N/A */ +void +print_sys_cfg_cipher_usage(void) +{ + printf("\nUsage : sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]\n"); + printf("\nOptions: PAIRWISE_CIPHER: 0 - NONE"); + printf("\n 4 - TKIP"); + printf("\n 8 - AES CCMP"); + printf("\n 12 - AES CCMP + TKIP"); + printf("\n GROUP_CIPHER : 0 - NONE"); + printf("\n 4 - TKIP"); + printf("\n 8 - AES CCMP"); + printf("\n empty - Get current cipher settings\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_group_rekey_timer command + * + * $return N/A + */ +void +print_sys_cfg_group_rekey_timer_usage(void) +{ + printf("\nUsage : sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]\n"); + printf("\nOptions: GROUP_REKEY_TIME is represented in seconds"); + printf("\n empty - Get current group re-key time\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_wpa_passphrase + * command + * + * $return N/A + */ +void +print_sys_cfg_wpa_passphrase_usage(void) +{ + printf("\nUsage : sys_cfg_wpa_passphrase [PASSPHRASE]\n"); + printf + ("\nIf PASSPHRASE is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Show usage information for the sta_filter_table command + * + * $return N/A + */ +void +print_sta_filter_table_usage(void) +{ + printf("\nUsage : sta_filter_table <FILTERMODE> <MACADDRESS_LIST>\n"); + printf("\nOptions: FILTERMODE : 0 - Disable filter table"); + printf + ("\n 1 - allow MAC addresses specified in the allowed list"); + printf + ("\n 2 - block MAC addresses specified in the banned list"); + printf + ("\n MACADDRESS_LIST is the list of MAC addresses to be acted upon. Each"); + printf + ("\n MAC address must be separated with a space. Maximum of"); + printf("\n 16 MAC addresses are supported."); + printf("\n empty - Get current mac filter settings\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_max_sta_num command + * + * $return N/A + */ +void +print_sys_cfg_max_sta_num_usage(void) +{ + printf("\nUsage : sys_cfg_max_sta_num [STA_NUM]\n"); + printf + ("\nIf STA_NUM is provided, a 'set' is performed, else a 'get' is performed."); + printf("\nSTA_NUM should not bigger than 8.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_retry_limit command + * + * $return N/A + */ +void +print_sys_cfg_retry_limit_usage(void) +{ + printf("\nUsage : sys_cfg_retry_limit [RETRY_LIMIT]\n"); + printf + ("\nIf RETRY_LIMIT is provided, a 'set' is performed, else a 'get' is performed."); + printf("\nRETRY_LIMIT should not bigger than 14.\n"); + return; +} + +/** + * @brief Show usage information for the sys_cfg_retry_limit command + * + * $return N/A + */ +void +print_cfg_data_usage(void) +{ + printf("\nUsage : cfg_data <type> [*.conf]\n"); + printf("\n type : 2 -- cal data"); + printf("\n *.conf : file contain configuration data"); + printf("\n empty - get current configuration data\n"); + return; +} + +/** + * @brief get configured operational rates. + * + * @param rates Operational rates allowed are + * stored at this pointer + * @return number of basic rates allowed. + * -1 if a failure + */ +int +get_sys_cfg_rates(u8 * rates) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_RATES *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int i = 0; + int rate_cnt = 0; + /* Initialize the command length */ + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_RATES) + MAX_DATA_RATES; + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return -1; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RATES *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_RATES_TLV_ID; + cmd_buf->Action = ACTION_GET; + tlv->Length = MAX_DATA_RATES; + + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_RATES_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return -1; + } + + /* copy response */ + if (cmd_buf->Result == CMD_SUCCESS) { + for (i = 0; i < tlv->Length; i++) { + if (tlv->OperationalRates[i] != 0) { + rates[rate_cnt++] = tlv->OperationalRates[i]; + } + } + } else { + printf("ERR:Could not get operational rates!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return rate_cnt; +} + +/** + * @brief check rate is valid or not. + * + * @param rate rate for check + * + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_tx_rate_valid(u8 rate) +{ + int rate_cnt = 0; + int i; + u8 rates[MAX_DATA_RATES]; + + rate_cnt = get_sys_cfg_rates((u8 *) & rates); + if (rate_cnt > 0) { + for (i = 0; i < rate_cnt; i++) { + if (rate == (rates[i] & ~BASIC_RATE_SET_BIT)) { + return UAP_SUCCESS; + } + } + } + return UAP_FAILURE; +} + +/** + * @brief check mcbc rate is valid or not. + * + * @param rate rate for check + * + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_mcbc_rate_valid(u8 rate) +{ + int rate_cnt = 0; + int i; + u8 rates[MAX_DATA_RATES]; + + rate_cnt = get_sys_cfg_rates((u8 *) & rates); + if (rate_cnt > 0) { + for (i = 0; i < rate_cnt; i++) { + if (rates[i] & BASIC_RATE_SET_BIT) { + if (rate == (rates[i] & ~BASIC_RATE_SET_BIT)) { + return UAP_SUCCESS; + } + } + } + } + return UAP_FAILURE; +} + +/**************************************************************************** + Global functions +****************************************************************************/ +/** + * @brief Creates a sys_cfg request for AP MAC address + * and sends to the driver + * + * Usage: "sys_cfg_ap_mac_address [AP_MAC_ADDRESS]" + * if AP_MAC_ADDRESS is provided, a 'set' is performed, + * else a 'get' is performed. + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_ap_mac_address(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_AP_MAC_ADDRESS *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_ap_mac_address_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 1) { + printf("ERR:Too many arguments.\n"); + print_sys_cfg_ap_mac_address_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_AP_MAC_ADDRESS); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AP_MAC_ADDRESS *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_AP_MAC_ADDRESS_TLV_ID; + tlv->Length = ETH_ALEN; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + if ((ret = mac2raw(argv[0], tlv->ApMacAddr)) != UAP_SUCCESS) { + printf("ERR: %s Address \n", ret == UAP_FAILURE ? "Invalid MAC" : + ret == UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); + free(buffer); + return; + } + } + endian_convert_tlv_header_out(tlv); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_AP_MAC_ADDRESS_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("AP MAC address = "); + print_mac(tlv->ApMacAddr); + printf("\n"); + } else { + printf("AP MAC address setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get AP MAC address!\n"); + } else { + printf("ERR:Could not set AP MAC address!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for SSID + * and sends to the driver + * + * Usage: "sys_cfg_ssid [SSID]" + * if SSID is provided, a 'set' is performed + * else a 'get' is performed + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_ssid(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_SSID *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + u8 ssid[33]; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_ssid_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 1) { + printf("ERR:Too many arguments.\n"); + print_sys_cfg_ssid_usage(); + return; + } + + if (argc == 0) { + /* Initialize the command length */ + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_SSID) + + MAX_SSID_LENGTH; + } else { + if (strlen(argv[0]) > MAX_SSID_LENGTH) { + printf("ERR:SSID too long.\n"); + return; + } + /* Initialize the command length */ + if (argv[0][1] == '"') { + argv[0]++; + } + if (argv[0][strlen(argv[0])] == '"') { + argv[0][strlen(argv[0])] = '\0'; + } + if (!strlen(argv[0])) { + printf("ERR:NULL SSID not allowed.\n"); + return; + } + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_SSID) + + strlen(argv[0]); + } + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_SSID *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_SSID_TLV_ID; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + tlv->Length = MAX_SSID_LENGTH; + } else { + cmd_buf->Action = ACTION_SET; + tlv->Length = strlen(argv[0]); + memcpy(tlv->Ssid, argv[0], tlv->Length); + } + + endian_convert_tlv_header_out(tlv); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + endian_convert_tlv_header_in(tlv); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_SSID_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + memset(ssid, 0, sizeof(ssid)); + memcpy(ssid, tlv->Ssid, tlv->Length); + printf("SSID = %s\n", ssid); + } else { + printf("SSID setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get SSID!\n"); + } else { + printf("ERR:Could not set SSID!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for beacon period + * and sends to the driver + * + * Usage: "sys_cfg_beacon_period [BEACON_PERIOD]" + * if BEACON_PERIOD is provided, a 'set' is performed + * else a 'get' is performed. + * + * BEACON_PERIOD is represented in ms + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_beacon_period(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_BEACON_PERIOD *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_beacon_period_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc && is_input_valid(BEACONPERIOD, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_beacon_period_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_BEACON_PERIOD); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_BEACON_PERIOD *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_BEACON_PERIOD_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->BeaconPeriod_ms = (u16) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->BeaconPeriod_ms = uap_cpu_to_le16(tlv->BeaconPeriod_ms); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->BeaconPeriod_ms = uap_le16_to_cpu(tlv->BeaconPeriod_ms); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_BEACON_PERIOD_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("Beacon period = %d\n", tlv->BeaconPeriod_ms); + } else { + printf("Beacon period setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get beacon period!\n"); + } else { + printf("ERR:Could not set beacon period!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for DTIM period + * and sends to the driver + * + * Usage: "sys_cfg_dtim_period [DTIM_PERIOD]" + * if DTIM_PERIOD is provided, a 'set' is performed + * else a 'get' is performed + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_dtim_period(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_DTIM_PERIOD *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_dtim_period_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(DTIMPERIOD, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_dtim_period_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_DTIM_PERIOD); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_DTIM_PERIOD *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_DTIM_PERIOD_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->DtimPeriod = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_DTIM_PERIOD_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("DTIM period = %d\n", tlv->DtimPeriod); + } else { + printf("DTIM period setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get DTIM period!\n"); + } else { + printf("ERR:Could not set DTIM period!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for channel + * and sends to the driver + * + * Usage: "sys_cfg_channel [CHANNEL] [MODE]" + * if CHANNEL is provided, a 'set' is performed + * else a 'get' is performed + * if MODE is provided, a 'set' is performed with + * 0 as manual channel selection + * 1 as automatic channel selection. + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_channel(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_CHANNEL_CONFIG *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_channel_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc && is_input_valid(CHANNEL, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_channel_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_CHANNEL_CONFIG); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CHANNEL_CONFIG *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_CHANNELCONFIG_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + if (argc == 1) { + tlv->ChanNumber = (u8) atoi(argv[0]); + tlv->BandConfigType = 0; + } else { + tlv->BandConfigType = atoi(argv[1]) ? BAND_CONFIG_ACS_MODE : 0; + tlv->ChanNumber = (u8) atoi(argv[0]); + } + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_CHANNELCONFIG_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("Mode = %s\n", + (tlv->BandConfigType == 0) ? "Manual" : "ACS"); + printf("Channel = %d\n", tlv->ChanNumber); + } else { + printf("Channel setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get channel!\n"); + } else { + printf("ERR:Could not set channel!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for channel list + * and sends to the driver + * + * Usage: "sys_cfg_scan_channels [CHANNELS]" + * if CHANNELS are provided, a 'set' is performed + * else a 'get' is performed + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_scan_channels(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_CHANNEL_LIST *tlv = NULL; + CHANNEL_LIST *pChanList = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + int i; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_scan_channels_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc && is_input_valid(SCANCHANNELS, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_scan_channels_usage(); + return; + } + + /* Initialize the command length */ + if (argc == 0) + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_CHANNEL_LIST) + + sizeof(CHANNEL_LIST) * MAX_CHANNELS; + else + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_CHANNEL_LIST) + + sizeof(CHANNEL_LIST) * argc; + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Can not allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* LOCATE HEADERS */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CHANNEL_LIST *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_CHANNELLIST_TLV_ID; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + tlv->Length = sizeof(CHANNEL_LIST) * MAX_CHANNELS; + } else { + cmd_buf->Action = ACTION_SET; + tlv->Length = sizeof(CHANNEL_LIST) * argc; + pChanList = tlv->ChanList; + for (i = 0; i < argc; i++) { + pChanList->ChanNumber = (u8) atoi(argv[i]); + pChanList->BandConfigType = 0; + pChanList++; + } + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_CHANNELLIST_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("Channels List = "); + if (tlv->Length % sizeof(CHANNEL_LIST)) { + printf("Error: Length mismatch\n"); + free(buffer); + return; + } + pChanList = tlv->ChanList; + for (i = 0; i < (tlv->Length / sizeof(CHANNEL_LIST)); i++) { + printf("%d ", pChanList->ChanNumber); + pChanList++; + } + printf("\n"); + } else { + printf("Scan Channel List setting successful\n"); + } + } else { + printf("ERR:Could not %s scan channel list!\n", + argc ? "SET" : "GET"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief parser for sys_cfg_rates_ext input + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @param output stores indexes for "rates, mbrate and urate" + * arguments + * + * e.g., + * + * "rates 0x82 4 16 22 0x30 mbrate 2 urate 16" + * + * will have output array as + * + * start_index end_index + * rates 0 5 + * mbrate 6 7 + * urate 8 9 + * + * @return NA + * + */ +void +parse_input(int argc, char **argv, int output[3][2]) +{ + int i, j, k = 0; + char *keywords[3] = { "rates", "mbrate", "urate" }; + + for (i = 0; i < 3; i++) + output[i][0] = -1; + + for (i = 0; i < argc; i++) { + for (j = 0; j < 3; j++) { + if (strcmp(argv[i], keywords[j]) == 0) { + output[j][1] = output[j][0] = i; + k = j; + break; + } + } + output[k][1] += 1; + } +} + +/** + * @brief Creates a sys_cfg request for setting data_rates, MCBC and + * TX data rates. + * + * Usage: "sys_cfg_rates_ext [RATES]" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_rates_ext(int argc, char *argv[]) +{ + int i, j = 0; + int opt; + int rflag = 0, mflag = 0, uflag = 0; + char *argv_rate[14]; + int argc_rate = 0; + char *argv_mrate[1]; + char *argv_urate[1]; + int mrate_found = UAP_FAILURE; + int urate_found = UAP_FAILURE; + u8 *tlv_buf = NULL; + TLVBUF_TX_DATA_RATE *tlv_urate = NULL; + TLVBUF_MCBC_DATA_RATE *tlv_mrate = NULL; + TLVBUF_RATES *tlv_rate = NULL; + u8 *buffer = NULL; + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + int ret = UAP_FAILURE; + u16 cmd_len; + int output[3][2]; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_rates_ext_usage(); + return; + } + } + argc -= optind; + argv += optind; + + if (argc) { + /* + * SET + */ + parse_input(argc, argv, output); + + /* + * Rate + */ + if ((output[0][0] != -1) && (output[0][1] > output[0][0])) { + rflag = 1; + i = 0; + for (j = (output[0][0] + 1); j < output[0][1]; j++) { + argv_rate[i] = + (char *) malloc(sizeof(char) * (strlen(argv[j]) + 1)); + strcpy(argv_rate[i], argv[j]); + argc_rate = ++i; + } + } + + /* + * mrate + */ + + if ((output[1][0] != -1) && (output[1][1] > output[1][0])) { + if ((output[1][1] - output[1][0]) != 2) { + printf("\nERR: Invalid mrate input"); + print_sys_cfg_rates_ext_usage(); + goto done; + } + mflag = 1; + argv_mrate[0] = + (char *) malloc(sizeof(char) * (strlen(argv[j]) + 1)); + strcpy(argv_mrate[0], argv[output[1][0] + 1]); + } + + /* + * urate + */ + if ((output[2][0] != -1) && (output[2][1] > output[2][0])) { + if ((output[2][1] - output[2][0]) != 2) { + printf("\nERR: Invalid urate input"); + print_sys_cfg_rates_ext_usage(); + goto done; + } + uflag = 1; + argv_urate[0] = + (char *) malloc(sizeof(char) * (strlen(argv[j]) + 1)); + strcpy(argv_urate[0], argv[output[2][0] + 1]); + } + + if (!rflag && !mflag & !uflag) { + printf("ERR: Invalid input\n"); + print_sys_cfg_rates_ext_usage(); + goto done; + } + + if (rflag && is_input_valid(RATE, argc_rate, argv_rate) != UAP_SUCCESS) { + printf("ERR: Invalid RATE\n"); + print_sys_cfg_rates_ext_usage(); + goto done; + } + + if (mflag && is_input_valid(MCBCDATARATE, 1, argv_mrate) != UAP_SUCCESS) { + printf("ERR: Invalid MCBC RATE\n"); + print_sys_cfg_rates_ext_usage(); + goto done; + } + + if (uflag && is_input_valid(TXDATARATE, 1, argv_urate) != UAP_SUCCESS) { + printf("ERR: Invalid TX RATE\n"); + print_sys_cfg_rates_ext_usage(); + goto done; + } + + if (!rflag && (mflag || uflag)) { + /* + * Check mrate and urate wrt old Rates + */ + if (mflag && A2HEXDECIMAL(argv_mrate[0]) && + is_mcbc_rate_valid(A2HEXDECIMAL(argv_mrate[0])) != + UAP_SUCCESS) { + printf("ERR: invalid MCBC data rate."); + print_sys_cfg_rates_ext_usage(); + goto done; + } + if (uflag && A2HEXDECIMAL(argv_urate[0]) && + is_tx_rate_valid(A2HEXDECIMAL(argv_urate[0])) != UAP_SUCCESS) { + printf("ERR: invalid tx data rate."); + print_sys_cfg_rates_ext_usage(); + goto done; + } + } else if (rflag && (mflag || uflag)) { + /* + * Check mrate and urate wrt new Rates + */ + for (i = 0; i < argc_rate; i++) { + /* + * MCBC rate must be from Basic rates + */ + if (mflag && !mrate_found && + A2HEXDECIMAL(argv_rate[i]) & BASIC_RATE_SET_BIT) { + if (A2HEXDECIMAL(argv_mrate[0]) == + (A2HEXDECIMAL(argv_rate[i]) & ~BASIC_RATE_SET_BIT)) { + mrate_found = UAP_SUCCESS; + } + } + if (uflag && !urate_found && (A2HEXDECIMAL(argv_urate[0]) == + ((A2HEXDECIMAL(argv_rate[i]) & + ~BASIC_RATE_SET_BIT)))) { + urate_found = UAP_SUCCESS; + } + } + + if (mflag && A2HEXDECIMAL(argv_mrate[0]) && + !(mrate_found == UAP_SUCCESS)) { + printf("ERR: mrate not valid\n"); + goto done; + } + + if (uflag && A2HEXDECIMAL(argv_urate[0]) && + !(urate_found == UAP_SUCCESS)) { + printf("ERR: urate not valid\n"); + goto done; + } + } + /* post-parsing */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE); + if (rflag) { + cmd_len += sizeof(TLVBUF_RATES) + argc_rate; + cmd_len += sizeof(TLVBUF_MCBC_DATA_RATE); + cmd_len += sizeof(TLVBUF_TX_DATA_RATE); + } else { + if (mflag) + cmd_len += sizeof(TLVBUF_MCBC_DATA_RATE); + if (uflag) + cmd_len += sizeof(TLVBUF_TX_DATA_RATE); + } + } else { + /* GET */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(TLVBUF_RATES) + MAX_RATES + sizeof(TLVBUF_MCBC_DATA_RATE) + + sizeof(TLVBUF_TX_DATA_RATE); + } + + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + goto done; + } + bzero((char *) buffer, cmd_len); + + /* Fill the command buffer */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Action = argc ? ACTION_SET : ACTION_GET; + tlv_buf = buffer + sizeof(APCMDBUF_SYS_CONFIGURE); + /* Locate headers */ + if (rflag || (!argc)) { + tlv_rate = (TLVBUF_RATES *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + tlv_rate->Tag = MRVL_RATES_TLV_ID; + tlv_rate->Length = argc ? argc_rate : MAX_RATES; + for (i = 0; i < argc_rate; i++) { + tlv_rate->OperationalRates[i] = (u8) A2HEXDECIMAL(argv_rate[i]); + } + tlv_buf += tlv_rate->Length + sizeof(TLVBUF_RATES); + endian_convert_tlv_header_out(tlv_rate); + } + if (rflag || mflag || (!argc)) { + tlv_mrate = (TLVBUF_MCBC_DATA_RATE *) tlv_buf; + tlv_mrate->Tag = MRVL_MCBC_DATA_RATE_TLV_ID; + tlv_mrate->Length = 2; + tlv_mrate->MCBCdatarate = 0; + if (mflag) { + tlv_mrate->MCBCdatarate = (u16) A2HEXDECIMAL(argv_mrate[0]) + & ~BASIC_RATE_SET_BIT; + tlv_mrate->MCBCdatarate = uap_cpu_to_le16(tlv_mrate->MCBCdatarate); + } + tlv_buf += sizeof(TLVBUF_MCBC_DATA_RATE); + endian_convert_tlv_header_out(tlv_mrate); + } + if (rflag || uflag || (!argc)) { + tlv_urate = (TLVBUF_TX_DATA_RATE *) tlv_buf; + tlv_urate->Tag = MRVL_TX_DATA_RATE_TLV_ID; + tlv_urate->Length = 2; + tlv_urate->TxDataRate = 0; + if (uflag) { + tlv_urate->TxDataRate = (u16) A2HEXDECIMAL(argv_urate[0]) + & ~BASIC_RATE_SET_BIT; + tlv_urate->TxDataRate = uap_cpu_to_le16(tlv_urate->TxDataRate); + } + endian_convert_tlv_header_out(tlv_urate); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + tlv_buf = buffer + sizeof(APCMDBUF_SYS_CONFIGURE); + + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response! CmdCode=%x\n", cmd_buf->CmdCode); + goto done; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc) { + printf("Rates setting successful\n"); + } else { + print_tlv((u8 *) tlv_buf, + cmd_buf->Size - sizeof(APCMDBUF_SYS_CONFIGURE) + + BUF_HEADER_SIZE); + } + } else { + printf("ERR:Could not %s operational rates!\n", + argc ? "set" : "get"); + if (argc) + printf + ("operational rates only allow to set before bss start.\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + done: + if (rflag) { + for (i = 0; i < argc_rate; i++) { + free(argv_rate[i]); + } + } + if (mflag) + free(argv_mrate[0]); + if (uflag) + free(argv_urate[0]); + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for data rates + * and sends to the driver + * + * Usage: "sys_cfg_rates [RATES]" + * + * RATES is provided as a set of data rates, in + * unit of 500 kilobits/s. + * Maximum 12 rates can be provided. + * + * if no RATE is provided, then it gets configured rates + * + * Each rate must be separated by a space + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_rates(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_RATES *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int i = 0; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_rates_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc && is_input_valid(RATE, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_rates_usage(); + return; + } + if (argc == 0) { + /* Initialize the command length */ + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_RATES) + MAX_RATES; + } else { + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_RATES) + argc; + } + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RATES *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_RATES_TLV_ID; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + tlv->Length = MAX_RATES; + } else { + cmd_buf->Action = ACTION_SET; + tlv->Length = argc; + for (i = 0; i < tlv->Length; i++) { + tlv->OperationalRates[i] = (u8) A2HEXDECIMAL(argv[i]); + } + } + + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_RATES_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + print_rate(tlv); + } else { + printf("Rates setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get operational rates!\n"); + } else { + printf("ERR:Could not set operational rates!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for Tx power + * and sends to the driver + * + * Usage: "sys_cfg_tx_power [TX_POWER]" + * if TX_POWER is provided, a 'set' is performed + * else a 'get' is performed. + * + * TX_POWER is represented in dBm + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_tx_power(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_TX_POWER *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_tx_power_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && is_input_valid(TXPOWER, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_tx_power_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_TX_POWER); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_TX_POWER *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_TX_POWER_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + printf("Please check power calibration for board to see if this power\n" + "setting is within calibrated range. Firmware may over-ride\n " + "this setting if it is not within calibrated range, which can\n" + "vary from board to board.\n"); + cmd_buf->Action = ACTION_SET; + tlv->TxPower_dBm = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_TX_POWER_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("Tx power = %d dBm\n", tlv->TxPower_dBm); + } else { + printf("Tx power setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get tx power!\n"); + } else { + printf("ERR:Could not set tx power!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for SSID broadcast + * and sends to the driver + * + * Usage: "sys_cfg_bcast_ssid_ctl [0|1]" + * + * Options: 0 - Disable SSID broadcast + * 1 - Enable SSID broadcast + * empty - Get current SSID broadcast setting + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_bcast_ssid_ctl(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_BCAST_SSID_CTL *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_bcast_ssid_ctl_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && is_input_valid(BROADCASTSSID, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_bcast_ssid_ctl_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_BCAST_SSID_CTL); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_BCAST_SSID_CTL *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_BCAST_SSID_CTL_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->BcastSsidCtl = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_BCAST_SSID_CTL_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("SSID broadcast is %s\n", + (tlv->BcastSsidCtl == 1) ? "enabled" : "disabled"); + } else { + printf("SSID broadcast setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get SSID broadcast!\n"); + } else { + printf("ERR:Could not set SSID broadcast!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for preamble settings + * and sends to the driver + * + * Usage: "sys_cfg_preamble_ctl" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_preamble_ctl(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_PREAMBLE_CTL *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_preamble_ctl_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_sys_cfg_preamble_ctl_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_PREAMBLE_CTL); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_PREAMBLE_CTL *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_PREAMBLE_CTL_TLV_ID; + tlv->Length = 1; + cmd_buf->Action = ACTION_GET; + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_PREAMBLE_CTL_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) + printf("Preamble type is %s\n", (tlv->PreambleType == 0) ? + "auto" : ((tlv->PreambleType == 1) ? "short" : "long")); + else + printf("ERR:Could not get preamble type!\n"); + + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for antenna configuration + * and sends to the driver + * + * Usage: "sys_cfg_antenna_ctl <ANTENNA> [MODE]" + * + * Options: ANTENNA : 0 - Rx antenna + * 1 - Tx antenna + * MODE : 0 - Antenna A + * 1 - Antenna B + * empty - Get current antenna settings + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_antenna_ctl(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_ANTENNA_CTL *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_antenna_ctl_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if ((argc == 0) || (argc > 2)) { + printf("ERR:wrong arguments.\n"); + print_sys_cfg_antenna_ctl_usage(); + return; + } else if (argc == 1) { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf + ("ERR:Illegal ANTENNA parameter %s. Must be either '0' or '1'.\n", + argv[0]); + print_sys_cfg_antenna_ctl_usage(); + return; + } + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf + ("ERR:Illegal ANTENNA parameter %s. Must be either '0' or '1'.\n", + argv[0]); + print_sys_cfg_antenna_ctl_usage(); + return; + } + if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) || + (atoi(argv[1]) > 1)) { + printf + ("ERR:Illegal MODE parameter %s. Must be either '0' or '1'.\n", + argv[1]); + print_sys_cfg_antenna_ctl_usage(); + return; + } + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_ANTENNA_CTL); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_ANTENNA_CTL *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_ANTENNA_CTL_TLV_ID; + tlv->Length = 2; + tlv->WhichAntenna = (u8) atoi(argv[0]); + if (argc == 1) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->AntennaMode = (u8) atoi(argv[1]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_ANTENNA_CTL_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 1) { + printf("%s antenna: %s\n", (tlv->WhichAntenna == 0) ? + "Rx" : "Tx", (tlv->AntennaMode == 0) ? "A" : "B"); + } else { + printf("Antenna setting successful\n"); + } + } else { + if (argc == 1) { + printf("ERR:Could not get antenna!\n"); + } else { + printf("ERR:Could not set antenna!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for RTS threshold + * and sends to the driver + * + * Usage: "sys_cfg_rts_threshold [RTS_THRESHOLD]" + * if RTS_THRESHOLD is provided, a 'set' is performed + * else a 'get' is performed + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_rts_threshold(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_RTS_THRESHOLD *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_rts_threshold_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(RTSTHRESH, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_rts_threshold_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_RTS_THRESHOLD); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RTS_THRESHOLD *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_RTS_THRESHOLD_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->RtsThreshold = (u16) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->RtsThreshold = uap_cpu_to_le16(tlv->RtsThreshold); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->RtsThreshold = uap_le16_to_cpu(tlv->RtsThreshold); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_RTS_THRESHOLD_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("RTS threshold = %d\n", tlv->RtsThreshold); + } else { + printf("RTS threshold setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get RTS threshold!\n"); + } else { + printf("ERR:Could not set RTS threshold!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for Fragmentation threshold + * and sends to the driver + * + * Usage: "sys_cfg_frag_threshold [FRAG_THRESHOLD]" + * if FRAG_THRESHOLD is provided, a 'set' is performed + * else a 'get' is performed + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_frag_threshold(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_FRAG_THRESHOLD *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_frag_threshold_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(FRAGTHRESH, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_frag_threshold_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_FRAG_THRESHOLD); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_FRAG_THRESHOLD *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_FRAG_THRESHOLD_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->FragThreshold = (u16) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->FragThreshold = uap_cpu_to_le16(tlv->FragThreshold); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->FragThreshold = uap_le16_to_cpu(tlv->FragThreshold); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_FRAG_THRESHOLD_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("Fragmentation threshold = %d\n", tlv->FragThreshold); + } else { + printf("Fragmentation threshold setting successful\n"); + } + } else { + if (argc == 1) { + printf("ERR:Could not get Fragmentation threshold!\n"); + } else { + printf("ERR:Could not set Fragmentation threshold!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for radio settings + * and sends to the driver + * + * Usage: "sys_cfg_radio_ctl [0|1]" + * + * Options: 0 - Turn radio on + * 1 - Turn radio off + * empty - Get current radio setting + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_radio_ctl(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_RADIO_CTL *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_radio_ctl_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(RADIOCONTROL, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_radio_ctl_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_RADIO_CTL); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RADIO_CTL *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_RADIO_CTL_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->RadioCtl = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_RADIO_CTL_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("Radio is %s\n", (tlv->RadioCtl == 0) ? "on" : "off"); + } else { + printf("Radio setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get radio status!\n"); + } else { + printf("ERR:Could not set radio status!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for RSN replay protection + * and sends to the driver + * + * Usage: "sys_cfg_rsn_replay_prot [0|1]" + * + * Options: 0 - Disable RSN replay protection + * 1 - Enable RSN replay protection + * empty - Get current RSN replay protection setting + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_rsn_replay_prot(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + tlvbuf_rsn_replay_prot *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_rsn_replay_prot_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && is_input_valid(RSNREPLAYPROT, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_rsn_replay_prot_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(tlvbuf_rsn_replay_prot); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (tlvbuf_rsn_replay_prot *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_RSN_REPLAY_PROT_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->rsn_replay_prot = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_RSN_REPLAY_PROT_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("RSN replay protection is %s\n", + (tlv->rsn_replay_prot == 1) ? "enabled" : "disabled"); + } else { + printf("RSN replay protection setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get RSN replay protection !\n"); + } else { + printf("ERR:Could not set RSN replay protection !\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for MCBC data rates + * and sends to the driver + * + * Usage: "sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]" + * + * Options: 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 + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_mcbc_data_rate(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_MCBC_DATA_RATE *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_mcbc_data_rates_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc) { + if (is_input_valid(MCBCDATARATE, argc, argv) != UAP_SUCCESS) { + printf("ERR: Invalid input\n"); + print_sys_cfg_mcbc_data_rates_usage(); + return; + } + if ((A2HEXDECIMAL(argv[0]) != 0) && + (is_mcbc_rate_valid(A2HEXDECIMAL(argv[0])) != UAP_SUCCESS)) { + printf("ERR: invalid MCBC data rate."); + print_sys_cfg_mcbc_data_rates_usage(); + return; + } + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_MCBC_DATA_RATE); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_MCBC_DATA_RATE *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_MCBC_DATA_RATE_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->MCBCdatarate = (u16) A2HEXDECIMAL(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->MCBCdatarate = uap_cpu_to_le16(tlv->MCBCdatarate); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->MCBCdatarate = uap_le16_to_cpu(tlv->MCBCdatarate); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_MCBC_DATA_RATE_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + if (tlv->MCBCdatarate == 0) { + printf("MCBC data rate is auto\n"); + } else { + printf("MCBC data rate = 0x%x\n", tlv->MCBCdatarate); + } + } else { + printf("MCBC data rate setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get MCBC data rate!\n"); + } else { + printf("ERR:Could not set MCBC data rate!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for Tx data rates + * and sends to the driver + * + * Usage: "sys_cfg_tx_data_rate [TX_DATA_RATE]" + * + * Options: 0 - Auto rate + * >0 - Set specified data rate + * empty - Get current data rate + * + * TX_DATA_RATE is represented in units of 500 kbps + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_tx_data_rate(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_TX_DATA_RATE *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_tx_data_rates_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc) { + if (is_input_valid(TXDATARATE, argc, argv) != UAP_SUCCESS) { + printf("ERR: Invalid input\n"); + print_sys_cfg_tx_data_rates_usage(); + return; + } else if ((A2HEXDECIMAL(argv[0]) != 0) && + (is_tx_rate_valid(A2HEXDECIMAL(argv[0])) != UAP_SUCCESS)) { + printf("ERR: invalid tx data rate."); + print_sys_cfg_tx_data_rates_usage(); + return; + } + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_TX_DATA_RATE); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_TX_DATA_RATE *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_TX_DATA_RATE_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->TxDataRate = (u16) A2HEXDECIMAL(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->TxDataRate = uap_cpu_to_le16(tlv->TxDataRate); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->TxDataRate = uap_le16_to_cpu(tlv->TxDataRate); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_TX_DATA_RATE_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + if (tlv->TxDataRate == 0) { + printf("Tx data rate is auto\n"); + } else { + printf("Tx data rate = 0x%x\n", tlv->TxDataRate); + } + } else { + printf("Tx data rate setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get tx data rate!\n"); + } else { + printf("ERR:Could not set tx data rate!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for packet forwarding + * and sends to the driver + * + * Usage: "sys_cfg_pkt_fwd_ctl [0|1]" + * + * Options: 0 - Forward all packets to the host + * 1 - Firmware handles intra-BSS packets + * empty - Get current packet forwarding setting + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_pkt_fwd_ctl(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_PKT_FWD_CTL *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_pkt_fwd_ctl_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(PKTFWD, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_pkt_fwd_ctl_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_PKT_FWD_CTL); + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_PKT_FWD_CTL *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_PKT_FWD_CTL_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->PktFwdCtl = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_PKT_FWD_CTL_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("Firmware %s\n", (tlv->PktFwdCtl == 0) ? + "forwards all packets to the host" : + "handles intra-BSS packets"); + } else { + printf("Packet control logic setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get packet control logic!\n"); + } else { + printf("ERR:Could not set packet control logic!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for STA ageout timer + * and sends to the driver + * + * Usage: "sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]" + * if STA_AGEOUT_TIMER is provided, a 'set' is performed + * else a 'get' is performed. + * The value should between 300 and 864000 + * + * STA_AGEOUT_TIMER is represented in units of 100 ms + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_sta_ageout_timer(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_STA_AGEOUT_TIMER *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_sta_ageout_timer_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(STAAGEOUTTIMER, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_sta_ageout_timer_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_STA_AGEOUT_TIMER); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_STA_AGEOUT_TIMER *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_STA_AGEOUT_TIMER_TLV_ID; + tlv->Length = 4; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->StaAgeoutTimer_ms = (u32) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->StaAgeoutTimer_ms = uap_cpu_to_le32(tlv->StaAgeoutTimer_ms); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->StaAgeoutTimer_ms = uap_le32_to_cpu(tlv->StaAgeoutTimer_ms); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_STA_AGEOUT_TIMER_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("STA ageout timer value = %d\n", + (int) tlv->StaAgeoutTimer_ms); + } else { + printf("STA ageout timer setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get STA ageout timer!\n"); + } else { + printf("ERR:Could not set STA ageout timer!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for authentication mode + * and sends to the driver + * + * Usage: "Usage : sys_cfg_auth [AUTHMODE]" + * + * Options: AUTHMODE : 0 - Open authentication + * 1 - Shared key authentication + * empty - Get current authentication mode + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_auth(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_AUTH_MODE *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_auth_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(AUTHMODE, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_auth_usage(); + return; + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_AUTH_MODE); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AUTH_MODE *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_AUTH_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->AuthMode = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_AUTH_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + print_auth(tlv); + } else { + printf("authentication mode setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get authentication mode!\n"); + } else { + printf("ERR:Could not set authentication mode!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for encryption protocol + * and sends to the driver + * + * Usage: "Usage : sys_cfg_protocol [PROTOCOL]" + * + * Options: PROTOCOL Bit 0 - No RSN + * Bit 1 - WEP Static + * Bit 3 - WPA + * Bit 3 - WPA2 + * empty - Get current protocol + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_protocol(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_PROTOCOL *tlv = NULL; + TLVBUF_AKMP *akmp_tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_protocol_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && is_input_valid(PROTOCOL, argc, argv) != UAP_SUCCESS) { + print_sys_cfg_protocol_usage(); + return; + } + /* Initialize the command length */ + if ((argc == 1) && + ((atoi(argv[0]) == PROTOCOL_NO_SECURITY) || + (atoi(argv[0]) == PROTOCOL_STATIC_WEP))) { + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_PROTOCOL); + } else + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_PROTOCOL) + + sizeof(TLVBUF_AKMP); + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_PROTOCOL *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + akmp_tlv = + (TLVBUF_AKMP *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(TLVBUF_PROTOCOL)); + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_PROTOCOL_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + akmp_tlv->Tag = MRVL_AKMP_TLV_ID; + akmp_tlv->Length = 2; + } else { + cmd_buf->Action = ACTION_SET; + tlv->Protocol = (u16) atoi(argv[0]); + if (tlv->Protocol & (PROTOCOL_WPA | PROTOCOL_WPA2)) { + akmp_tlv->Tag = MRVL_AKMP_TLV_ID; + akmp_tlv->Length = 2; + akmp_tlv->KeyMgmt = KEY_MGMT_PSK; + akmp_tlv->KeyMgmt = uap_cpu_to_le16(akmp_tlv->KeyMgmt); + } + } + endian_convert_tlv_header_out(tlv); + if (cmd_len == + (sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_PROTOCOL) + + sizeof(TLVBUF_AKMP))) + endian_convert_tlv_header_out(akmp_tlv); + tlv->Protocol = uap_cpu_to_le16(tlv->Protocol); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + if (cmd_len == + (sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_PROTOCOL) + + sizeof(TLVBUF_AKMP))) + endian_convert_tlv_header_in(akmp_tlv); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + print_tlv((u8 *) tlv, + cmd_buf->Size - sizeof(APCMDBUF_SYS_CONFIGURE) + + BUF_HEADER_SIZE); + } else { + printf("protocol setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get protocol!\n"); + } else { + printf("ERR:Could not set protocol!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for WEP keys settings + * and sends to the driver + * + * Usage: "sys_cfg_wep_key [INDEX_0 IS_DEFAULT KEY_0] [INDEX_1 IS_DEFAULT KEY_1] [INDEX_2 IS_DEFAULT KEY_2] [INDEX_3 IS_DEFAULT KEY_3]" + * + * Options: INDEX_* : 0 - KeyIndex is 0 + * 1 - KeyIndex is 1 + * 2 - KeyIndex is 2 + * 3 - KeyIndex is 3 + * IS_DEFAUL : 0 - KeyIndex is not the default + * 1 - KeyIndex is the default transmit key + * KEY_* : Key value + * empty - Get current WEP key settings + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_wep_key(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_WEP_KEY *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + int key_len = -1; + int length = 0; + int number_of_keys = 0; + int i = 0; + int keyindex = -1; + int is_default = -1; + char *key = NULL; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_wep_key_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 12) { + printf("ERR:Too many arguments.\n"); + print_sys_cfg_wep_key_usage(); + return; + } else if ((argc > 1) && ((argc % 3) != 0)) { + printf("ERR:Illegal number of parameters.\n"); + print_sys_cfg_wep_key_usage(); + return; + } else if (argc > 1) { + /* Find number of keys provided */ + number_of_keys = argc / 3; + for (i = 0; i < number_of_keys; i++) { + if ((ISDIGIT(argv[(3 * i)]) == 0) || (atoi(argv[(3 * i)]) < 0) || + (atoi(argv[(3 * i)]) > 3)) { + printf + ("ERR:Illegal INDEX %s. Must be either '0', '1', '2', or '3'.\n", + argv[(3 * i)]); + print_sys_cfg_wep_key_usage(); + return; + } + if ((ISDIGIT(argv[(3 * i) + 1]) == 0) || + (atoi(argv[(3 * i) + 1]) < 0) || + (atoi(argv[(3 * i) + 1]) > 1)) { + printf + ("ERR:Illegal IS_DEFAULT %s. Must be either '0', or '1'.\n", + argv[(3 * i) + 1]); + print_sys_cfg_wep_key_usage(); + return; + } + if ((strlen(argv[(3 * i) + 2]) != 5) && + (strlen(argv[(3 * i) + 2]) != 10) + && (strlen(argv[(3 * i) + 2]) != 13) && + (strlen(argv[(3 * i) + 2]) != 26)) { + printf("ERR:Incorrect KEY_%d length %d\n", atoi(argv[(3 * i)]), + strlen(argv[(3 * i) + 2])); + print_sys_cfg_wep_key_usage(); + return; + } + if ((strlen(argv[(3 * i) + 2]) == 10) || + (strlen(argv[(3 * i) + 2]) == 26)) { + if (UAP_FAILURE == ishexstring(argv[(3 * i) + 2])) { + printf + ("ERR:Only hex digits are allowed when key length is 10 or 26\n"); + print_sys_cfg_wep_key_usage(); + return; + } + } + } + } else if (argc == 1) { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 3)) { + printf + ("ERR:Illegal INDEX %s. Must be either '0', '1', '2', or '3'.\n", + argv[0]); + print_sys_cfg_wep_key_usage(); + return; + } + } + + /* Initialize the command length */ + if (argc == 0 || argc == 1) { + if (argc == 0) + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_HEADER); + else + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_WEP_KEY) - 1; + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + } else { + buf_len = cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE); + } + /* Initialize the command buffer */ + buffer = (u8 *) malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, buf_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + if (argc == 0 || argc == 1) { + cmd_buf->Action = ACTION_GET; + tlv = (TLVBUF_WEP_KEY *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + tlv->Tag = MRVL_WEP_KEY_TLV_ID; + if (argc == 0) + tlv->Length = 0; + else { + tlv->Length = 1; + tlv->KeyIndex = atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + } else { + cmd_buf->Action = ACTION_SET; + } + /* Add key TLVs */ + for (i = 0; i < number_of_keys; i++) { + keyindex = atoi(argv[(3 * i)]); + is_default = atoi(argv[(3 * i) + 1]); + key = argv[(3 * i) + 2]; + length = strlen(key); + switch (length) { + case 5: + case 10: + key_len = 5; + break; + case 13: + case 26: + key_len = 13; + break; + default: + key_len = 0; + break; + } + /* Adjust command buffer */ + buffer = realloc(buffer, (cmd_len + sizeof(TLVBUF_WEP_KEY) + key_len)); + if (!buffer) { + printf("ERR:Cannot append WEP key configurations TLV!\n"); + return; + } + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_WEP_KEY *) (buffer + cmd_len); + /* Adjust command length */ + cmd_len += (sizeof(TLVBUF_WEP_KEY) + key_len); + /* Set TLV fields */ + tlv->Tag = MRVL_WEP_KEY_TLV_ID; + tlv->Length = 2 + key_len; + tlv->KeyIndex = (u8) keyindex; + tlv->IsDefault = (u8) is_default; + /* Check if string or raw */ + switch (length) { + case 5: + case 13: + memcpy(tlv->Key, key, length); + break; + case 10: + case 26: + string2raw(key, tlv->Key); + break; + default: + break; + } + endian_convert_tlv_header_out(tlv); + } + + /* Update command length */ + cmd_buf->Size = cmd_len; + if ((argc != 0) && (argc != 1)) + buf_len = cmd_len; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if ((argc != 0) && (argc != 1)) { + printf("WEP key setting successful\n"); + } else { + printf("query WEP key setting successful\n"); + tlv = + (TLVBUF_WEP_KEY *) (buffer + + sizeof(APCMDBUF_SYS_CONFIGURE)); + print_tlv((u8 *) tlv, + cmd_buf->Size - sizeof(APCMDBUF_SYS_CONFIGURE) + + BUF_HEADER_SIZE); + } + } else { + if ((argc != 0) && (argc != 1)) + printf("ERR:Could not set WEP keys!\n"); + else + printf("ERR:Could not get WEP keys!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for custom IE settings + * and sends to the driver + * + * Usage: "sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]" + * + * Options: INDEX : 0 - Get/Set IE index 0 setting + * 1 - Get/Set IE index 1 setting + * 2 - Get/Set IE index 2 setting + * 3 - Get/Set IE index 3 setting + * 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 + */ +void +apcmd_sys_cfg_custom_ie(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + tlvbuf_custom_ie *tlv = NULL; + custom_ie *ie_ptr = NULL; + u8 *buffer = NULL; + u16 cmd_len; + u16 buf_len; + u16 mgmt_subtype_mask = 0; + int ret = UAP_FAILURE; + int ie_buf_len = 0, ie_len = 0; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_custom_ie_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 3) { + printf("ERR:Too many arguments.\n"); + print_sys_cfg_custom_ie_usage(); + return; + } + + /* Error checks and initialize the command length */ + if (argc >= 1) { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 3)) { + printf + ("ERR:Illegal index %s. Must be either '0', '1', '2', or '3'.\n", + argv[0]); + print_sys_cfg_custom_ie_usage(); + return; + } + } + switch (argc) { + case 0: + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(tlvbuf_custom_ie); + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + break; + case 1: + /* TLV header + ie_index */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(tlvbuf_custom_ie) + + sizeof(u16); + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + break; + case 2: + if (UAP_FAILURE == ishexstring(argv[1]) || A2HEXDECIMAL(argv[1]) != 0) { + printf("ERR: Mask value should be 0 to clear IEBuffers.\n"); + print_sys_cfg_custom_ie_usage(); + return; + } + buf_len = cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(tlvbuf_custom_ie) + sizeof(custom_ie); + break; + case 3: + if (UAP_FAILURE == ishexstring(argv[1]) || A2HEXDECIMAL(argv[1]) == 0) { + printf("ERR: Mask value should not be 0 to set IEBuffers.\n"); + print_sys_cfg_custom_ie_usage(); + return; + } + if (UAP_FAILURE == ishexstring(argv[2])) { + printf("ERR:Only hex digits are allowed\n"); + print_sys_cfg_custom_ie_usage(); + return; + } + ie_buf_len = strlen(argv[2]); + if (!strncasecmp("0x", argv[2], 2)) { + ie_len = (ie_buf_len - 2 + 1) / 2; + argv[2] += 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_sys_cfg_custom_ie_usage(); + return; + } + mgmt_subtype_mask = (u16) A2HEXDECIMAL(argv[1]); + buf_len = cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(tlvbuf_custom_ie) + sizeof(custom_ie) + ie_len; + break; + } + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + memset(buffer, 0, buf_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Size = cmd_len; + + if (argc == 0 || argc == 1) { + cmd_buf->Action = ACTION_GET; + tlv = (tlvbuf_custom_ie *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + tlv->Tag = MRVL_MGMT_IE_LIST_TLV_ID; + if (argc == 0) + tlv->Length = 0; + else { + tlv->Length = sizeof(u16); + ie_ptr = (custom_ie *) (tlv->ie_data); + ie_ptr->ie_index = (u16) uap_cpu_to_le16(atoi(argv[0])); + } + endian_convert_tlv_header_out(tlv); + } else { + cmd_buf->Action = ACTION_SET; + /* Locate headers */ + tlv = (tlvbuf_custom_ie *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + ie_ptr = (custom_ie *) (tlv->ie_data); + /* Set TLV fields */ + tlv->Tag = MRVL_MGMT_IE_LIST_TLV_ID; + tlv->Length = sizeof(custom_ie) + ie_len; + ie_ptr->ie_index = uap_cpu_to_le16(atoi(argv[0])); + ie_ptr->mgmt_subtype_mask = uap_cpu_to_le16(mgmt_subtype_mask); + ie_ptr->ie_length = uap_cpu_to_le16(ie_len); + if (argc == 3) + string2raw(argv[2], ie_ptr->ie_buffer); + endian_convert_tlv_header_out(tlv); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if ((argc != 0) && (argc != 1)) { + printf("custom IE setting successful\n"); + } else { + printf("Querying custom IE successful\n"); + tlv = + (tlvbuf_custom_ie *) (buffer + + sizeof(APCMDBUF_SYS_CONFIGURE)); + print_tlv((u8 *) tlv, + cmd_buf->Size - sizeof(APCMDBUF_SYS_CONFIGURE) + + BUF_HEADER_SIZE); + } + } else { + if ((argc != 0) && (argc != 1)) + printf("ERR:Could not set custom IE elements!\n"); + else + printf("ERR:Could not get custom IE elements!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for cipher configurations + * and sends to the driver + * + * Usage: "sys_cfg_security_cfg [PAIRWISE_CIPHER GROUP_CIPHER]" + * + * Options: PAIRWISE_CIPHER : Bit 2 - TKIP + * Bit 3 - AES CCMP + * GROUP_CIPHER : Bit 2 - TKIP + * Bit 3 - AES CCMP + * empty - Get current cipher settings + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_cipher(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_CIPHER *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_cipher_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if ((argc != 0) && (argc != 2)) { + printf("ERR:wrong arguments.\n"); + print_sys_cfg_cipher_usage(); + return; + } + if (argc == 2) { + if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)) { + print_sys_cfg_cipher_usage(); + return; + } + if (atoi(argv[0]) & ~CIPHER_BITMAP) { + printf("ERR:Illegal PAIRWISE_CIPHER parameter %s.\n", argv[0]); + print_sys_cfg_cipher_usage(); + return; + } + if (atoi(argv[1]) & ~CIPHER_BITMAP) { + printf("ERR:Illegal GROUP_CIPHER parameter %s.\n", argv[1]); + print_sys_cfg_cipher_usage(); + return; + } + if (is_cipher_valid(atoi(argv[0]), atoi(argv[1])) != UAP_SUCCESS) { + printf("ERR:Wrong group and pair cipher combination!\n"); + print_sys_cfg_cipher_usage(); + return; + } + } + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_CIPHER); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CIPHER *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_CIPHER_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->PairwiseCipher = (u8) atoi(argv[0]); + tlv->GroupCipher = (u8) atoi(argv[1]); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_CIPHER_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + print_cipher(tlv); + } else { + printf("cipher setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get cipher parameters!\n"); + } else { + printf("ERR:Could not set cipher parameters!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for group re-key timer + * and sends to the driver + * + * Usage: "Usage : sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]" + * + * Options: GROUP_REKEY_TIME is represented in seconds + * Get current group re-key timer + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_group_rekey_timer(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_GROUP_REKEY_TIMER *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_group_rekey_timer_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc && (is_input_valid(GROUPREKEYTIMER, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_group_rekey_timer_usage(); + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_GROUP_REKEY_TIMER); + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = + (TLVBUF_GROUP_REKEY_TIMER *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_GRP_REKEY_TIME_TLV_ID; + tlv->Length = 4; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->GroupRekeyTime_sec = (u32) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->GroupRekeyTime_sec = uap_cpu_to_le32(tlv->GroupRekeyTime_sec); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->GroupRekeyTime_sec = uap_le32_to_cpu(tlv->GroupRekeyTime_sec); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_GRP_REKEY_TIME_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + if (tlv->GroupRekeyTime_sec > 0) + printf("Group rekey time is %ld s\n", + tlv->GroupRekeyTime_sec); + else + printf("Group rekey time is disabled\n"); + } else { + printf("group re-key time setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get group re-key time!\n"); + } else { + printf("ERR:Could not set group re-key time!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for WPA passphrase + * and sends to the driver + * + * Usage: "sys_cfg_wpa_passphrase [PASSPHRASE]" + * if PASSPHRASE is provided, a 'set' is performed + * else a 'get' is performed + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_wpa_passphrase(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_WPA_PASSPHRASE *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_wpa_passphrase_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc > 1) { + printf("ERR:Too many arguments.\n"); + print_sys_cfg_wpa_passphrase_usage(); + return; + } + if ((argc == 1) && (strlen(argv[0]) > MAX_WPA_PASSPHRASE_LENGTH)) { + printf("ERR:PASSPHRASE too long.\n"); + return; + } + if ((argc == 1) && (strlen(argv[0]) < MIN_WPA_PASSPHRASE_LENGTH)) { + printf("ERR:PASSPHRASE too short.\n"); + return; + } + if ((argc == 1) && (strlen(argv[0]) == MAX_WPA_PASSPHRASE_LENGTH)) { + if (UAP_FAILURE == ishexstring(argv[0])) { + printf + ("ERR:Only hex digits are allowed when passphrase's length is 64\n"); + return; + } + } + /* Initialize the command length */ + if (argc == 0) + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_WPA_PASSPHRASE) + + MAX_WPA_PASSPHRASE_LENGTH; + else + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_WPA_PASSPHRASE) + + strlen(argv[0]); + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_WPA_PASSPHRASE *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_WPA_PASSPHRASE_TLV_ID; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + tlv->Length = MAX_WPA_PASSPHRASE_LENGTH; + } else { + cmd_buf->Action = ACTION_SET; + tlv->Length = strlen(argv[0]); + memcpy(tlv->Passphrase, argv[0], tlv->Length); + } + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_WPA_PASSPHRASE_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + if (tlv->Length > 0) + printf("WPA passphrase = %s\n", tlv->Passphrase); + else + printf("WPA passphrase: None\n"); + } else { + printf("WPA passphrase setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get WPA passphrase!\n"); + } else { + printf("ERR:Could not set WPA passphrase!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a STA filter request and sends to the driver + * + * Usage: "sta_filter_table <FILTERMODE> <MACADDRESS_LIST>" + * + * Options: FILTERMODE : 0 - Disable filter table + * 1 - Allow mac address specified in the allwed 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. + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sta_filter_table(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_STA_MAC_ADDR_FILTER *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int i = 0; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sta_filter_table_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if (argc > (MAX_MAC_ONESHOT_FILTER + 1)) { + printf("ERR:Too many arguments.\n"); + print_sta_filter_table_usage(); + return; + } + if (argc > 0) { + if ((ISDIGIT(argv[0]) == 0) || + ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 2))) { + printf + ("ERR:Illegal FILTERMODE parameter %s. Must be either '0', '1', or '2'.\n", + argv[1]); + print_sta_filter_table_usage(); + return; + } + if ((atoi(argv[0]) != 0) && (argc == 1)) { + printf("ERR:At least one mac is required.\n"); + print_sta_filter_table_usage(); + return; + } + } + /* Initialize the command length */ + if (argc == 0) { + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(TLVBUF_STA_MAC_ADDR_FILTER) + + (MAX_MAC_ONESHOT_FILTER * ETH_ALEN); + } else { + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(TLVBUF_STA_MAC_ADDR_FILTER) + (argc - 1) * ETH_ALEN; + } + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = + (TLVBUF_STA_MAC_ADDR_FILTER *) (buffer + + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_STA_MAC_ADDR_FILTER_TLV_ID; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + tlv->Count = MAX_MAC_ONESHOT_FILTER; + } else { + cmd_buf->Action = ACTION_SET; + tlv->FilterMode = atoi(argv[0]); + tlv->Count = argc - 1; + for (i = 0; i < tlv->Count; i++) { + if ((ret = + mac2raw(argv[i + 1], + &tlv->MacAddress[i * ETH_ALEN])) != UAP_SUCCESS) { + printf("ERR: %s Address\n", + ret == UAP_FAILURE ? "Invalid MAC" : ret == + UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); + print_sta_filter_table_usage(); + free(buffer); + return; + } + } + } + tlv->Length = tlv->Count * ETH_ALEN + 2; + endian_convert_tlv_header_out(tlv); + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_STA_MAC_ADDR_FILTER_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + print_mac_filter(tlv); + } else { + printf("MAC address filter table setting successful!\n"); + } + } else { + if (argc == 0) { + printf + ("ERR:Could not get MAC address filter table settings!\n"); + } else { + printf + ("ERR:Could not set MAC address filter table settings!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for max station number + * and sends to the driver + * + * Usage: "sys_cfg_max_sta_num [STA_NUM]" + * if STA_NUM is provided, a 'set' is performed + * else a 'get' is performed. + * + * STA_NUM should not bigger than 8 + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_max_sta_num(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_MAX_STA_NUM *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_max_sta_num_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc && (is_input_valid(MAXSTANUM, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_max_sta_num_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_MAX_STA_NUM); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_MAX_STA_NUM *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_MAX_STA_CNT_TLV_ID; + tlv->Length = 2; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->Max_sta_num = (u16) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + tlv->Max_sta_num = uap_cpu_to_le16(tlv->Max_sta_num); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + tlv->Max_sta_num = uap_le16_to_cpu(tlv->Max_sta_num); + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_MAX_STA_CNT_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("max station number = %d\n", tlv->Max_sta_num); + } else { + printf("max station number setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get max station number!\n"); + } else { + printf("ERR:Could not set max station number!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Creates a sys_cfg request for retry limit + * and sends to the driver + * + * Usage: "sys_cfg_retry_limit [RETRY_LIMIT]" + * if RETRY_LIMIT is provided, a 'set' is performed + * else a 'get' is performed. + * + * RETRY_LIMIT should not bigger than 14 + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_cfg_retry_limit(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + TLVBUF_RETRY_LIMIT *tlv = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_cfg_max_sta_num_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc && (is_input_valid(RETRYLIMIT, argc, argv) != UAP_SUCCESS)) { + print_sys_cfg_retry_limit_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(TLVBUF_RETRY_LIMIT); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RETRY_LIMIT *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + tlv->Tag = MRVL_RETRY_LIMIT_TLV_ID; + tlv->Length = 1; + if (argc == 0) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + tlv->retry_limit = (u8) atoi(argv[0]); + } + endian_convert_tlv_header_out(tlv); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + endian_convert_tlv_header_in(tlv); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if ((cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || + (tlv->Tag != MRVL_RETRY_LIMIT_TLV_ID)) { + printf("ERR:Corrupted response! CmdCode=%x, Tlv->Tag=%x\n", + cmd_buf->CmdCode, tlv->Tag); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc == 0) { + printf("retry limit = %d\n", tlv->retry_limit); + } else { + printf("retry limit setting successful\n"); + } + } else { + if (argc == 0) { + printf("ERR:Could not get retry limit!\n"); + } else { + printf("ERR:Could not set retry limit!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief convert string to integer + * + * @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, u8 * chr) +{ + u8 val; + + for (val = 0; *ptr && isxdigit(*ptr); ptr++) { + val = (val * 16) + hexc2bin(*ptr); + } + + *chr = val; + + return ptr; +} + +/** + * @brief parse hex data + * @param fp A pointer to FILE stream + * @param dst A pointer to receive hex data + * @return length of hex data + */ +int +fparse_for_hex(FILE * fp, u8 * dst) +{ + char *ptr; + u8 *dptr; + char 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); +} + +/** + * @brief Creates a cfg_data request + * and sends to the driver + * + * Usage: "cfg_data <cfg_data.conf>" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_cfg_data(int argc, char *argv[]) +{ + APCMDBUF_CFG_DATA *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + int opt; + FILE *fp = NULL; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_cfg_data_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if ((argc == 0) || (argc > 2)) { + printf("ERR:wrong arguments.\n"); + print_cfg_data_usage(); + return; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) != 2)) { + printf("ERR:Illegal type parameter %s. Must be '2'.\n", argv[0]); + print_cfg_data_usage(); + return; + } + } + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + buf = (u8 *) malloc(buf_len); + memset(buf, 0, buf_len); + cmd_buf = (APCMDBUF_CFG_DATA *) buf; + if (buf == NULL) { + printf("Error: allocate memory for hostcmd failed\n"); + return; + } + if (argc == 2) { + /* Check if file exists */ + fp = fopen(argv[1], "r"); + if (fp == NULL) { + printf("\nERR:Config file can not open %s.\n", argv[1]); + free(buf); + return; + } + cmd_buf->action = ACTION_SET; + cmd_buf->data_len = fparse_for_hex(fp, cmd_buf->data); + fclose(fp); + if (cmd_buf->data_len > MAX_CFG_DATA_SIZE) { + printf("ERR: Config file is too big %d\n", cmd_buf->data_len); + free(buf); + return; + } + } else { + cmd_buf->action = ACTION_GET; + cmd_buf->data_len = 0; + } + + cmd_buf->action = uap_cpu_to_le16(cmd_buf->action); + cmd_buf->type = atoi(argv[0]); + cmd_buf->type = uap_cpu_to_le16(cmd_buf->type); + cmd_buf->data_len = uap_cpu_to_le16(cmd_buf->data_len); + + /* Fill the command buffer */ + cmd_len = cmd_buf->data_len + sizeof(APCMDBUF_CFG_DATA); + cmd_buf->CmdCode = HostCmd_CMD_CFG_DATA; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + /* Process response */ + if (ret == UAP_SUCCESS) { + cmd_buf->action = uap_le16_to_cpu(cmd_buf->action); + cmd_buf->data_len = uap_le16_to_cpu(cmd_buf->data_len); + if (cmd_buf->action == ACTION_GET) { + hexdump_data("cfg_data", cmd_buf->data, cmd_buf->data_len, ' '); + } else + printf("download cfg data successful\n"); + } + if (buf) + free(buf); + return; +} diff --git a/packages/dreamplug-uaputl/uapcmd.h b/packages/dreamplug-uaputl/uapcmd.h new file mode 100644 index 0000000..b4dbc25 --- /dev/null +++ b/packages/dreamplug-uaputl/uapcmd.h @@ -0,0 +1,63 @@ +/** @file uapcmd.h + * + * @brief This file contains declaration referring to + * functions defined in uapcmd.c + * + * Copyright (C) 2008-2009, 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/01/08: Initial creation +************************************************************************/ + +#ifndef _UAPCMD_H +#define _UAPCMD_H + +/** Function Prototype Declaration */ +void apcmd_sys_cfg_ap_mac_address(int argc, char *argv[]); +void apcmd_sys_cfg_ssid(int argc, char *argv[]); +void apcmd_sys_cfg_beacon_period(int argc, char *argv[]); +void apcmd_sys_cfg_dtim_period(int argc, char *argv[]); +void apcmd_sys_cfg_channel(int argc, char *argv[]); +void apcmd_sys_cfg_scan_channels(int argc, char *argv[]); +void apcmd_sys_cfg_rates(int argc, char *argv[]); +void apcmd_sys_cfg_rates_ext(int argc, char *argv[]); +void apcmd_sys_cfg_tx_power(int argc, char *argv[]); +void apcmd_sys_cfg_bcast_ssid_ctl(int argc, char *argv[]); +void apcmd_sys_cfg_preamble_ctl(int argc, char *argv[]); +void apcmd_sys_cfg_antenna_ctl(int argc, char *argv[]); +void apcmd_sys_cfg_rts_threshold(int argc, char *argv[]); +void apcmd_sys_cfg_frag_threshold(int argc, char *argv[]); +void apcmd_sys_cfg_radio_ctl(int argc, char *argv[]); +void apcmd_sys_cfg_rsn_replay_prot(int argc, char *argv[]); +void apcmd_sys_cfg_tx_data_rate(int argc, char *argv[]); +void apcmd_sys_cfg_mcbc_data_rate(int argc, char *argv[]); +void apcmd_sys_cfg_pkt_fwd_ctl(int argc, char *argv[]); +void apcmd_sys_cfg_sta_ageout_timer(int argc, char *argv[]); +void apcmd_sys_cfg_auth(int argc, char *argv[]); +void apcmd_sys_cfg_protocol(int argc, char *argv[]); +void apcmd_sys_cfg_wep_key(int argc, char *argv[]); +void apcmd_sys_cfg_custom_ie(int argc, char *argv[]); +void apcmd_sys_cfg_cipher(int argc, char *argv[]); +void apcmd_sys_cfg_wpa_passphrase(int argc, char *argv[]); +void apcmd_sys_cfg_group_rekey_timer(int argc, char *argv[]); +void apcmd_coex_config_profile(int argc, char *argv[]); +void apcmd_sta_filter_table(int argc, char *argv[]); +void apcmd_sys_cfg_max_sta_num(int argc, char *argv[]); +void apcmd_sys_cfg_retry_limit(int argc, char *argv[]); +void apcmd_cfg_data(int argc, char *argv[]); +#endif /* _UAP_H */ diff --git a/packages/dreamplug-uaputl/uaputl.c b/packages/dreamplug-uaputl/uaputl.c new file mode 100644 index 0000000..8337f2b --- /dev/null +++ b/packages/dreamplug-uaputl/uaputl.c @@ -0,0 +1,5565 @@ +/** @file uaputl.c + * + * @brief Program to send AP commands to the driver/firmware of the uAP + * driver. + * + * Copyright (C) 2008-2009, 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/01/08: Initial creation +****************************************************************************/ + +/**************************************************************************** + Header files +****************************************************************************/ +#include <stdarg.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <stdio.h> +#include <getopt.h> +#include <netinet/in.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <linux/if.h> +#include <sys/ioctl.h> +#include <errno.h> +#include "uaputl.h" +#include "uapcmd.h" + +/**************************************************************************** + Definitions +****************************************************************************/ +/** Default debug level */ +int debug_level = MSG_NONE; + +/** Enable or disable debug outputs */ +#define DEBUG 1 + +/** Convert character to integer */ +#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0')) + +/**************************************************************************** + Global variables +****************************************************************************/ +/** Device name */ +static char dev_name[IFNAMSIZ + 1]; +/** option for cmd */ +struct option cmd_options[] = { + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} +}; + +/**************************************************************************** + Local functions +****************************************************************************/ +/** + * @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 check protocol is valid or not + * + * @param protocol protocol + * + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_protocol_valid(int protocol) +{ + int ret = UAP_FAILURE; + switch (protocol) { + case PROTOCOL_NO_SECURITY: + case PROTOCOL_STATIC_WEP: + case PROTOCOL_WPA: + case PROTOCOL_WPA2: + case PROTOCOL_WPA2_MIXED: + ret = UAP_SUCCESS; + break; + default: + printf("ERR: Invalid Protocol: %d\n", protocol); + break; + } + return ret; +} + +/** + * @brief Function to check valid rate + * + * + * @param rate rate to verify + * + * return UAP_SUCCESS or UAP_FAILURE + **/ +int +is_rate_valid(int rate) +{ + int ret = UAP_SUCCESS; + switch (rate) { + case 2: + case 4: + case 11: + case 22: + case 12: + case 18: + case 24: + case 48: + case 72: + case 96: + case 108: + case 36: + break; + default: + ret = UAP_FAILURE; + break; + } + return ret; +} + +/** + * @brief detects duplicates rate in array of strings + * Note that 0x82 and 0x2 are same for rate + * + * @param argc number of elements + * @param argv array of strings + * @return UAP_FAILURE or UAP_SUCCESS + */ +inline int +has_dup_rate(int argc, char *argv[]) +{ + int i, j; + /* Check for duplicate */ + for (i = 0; i < (argc - 1); i++) { + for (j = i + 1; j < argc; j++) { + if ((A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT) == + (A2HEXDECIMAL(argv[j]) & ~BASIC_RATE_SET_BIT)) { + return UAP_FAILURE; + } + } + } + return UAP_SUCCESS; +} + +/** + * @brief Check for mandatory rates + * + * + * 2, 4, 11, 22 must be present + * + * 6 12 and 24 must be present for ofdm + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_FAILURE or UAP_SUCCESS + * + */ +int +check_mandatory_rates(int argc, char **argv) +{ + int i; + int tmp; + u32 rate_bitmap = 0; + int ofdm_enable = 0; +#define BITMAP_RATE_1M 0x01 +#define BITMAP_RATE_2M 0x02 +#define BITMAP_RATE_5_5M 0x04 +#define BITMAP_RATE_11M 0x8 +#define B_RATE_MANDATORY 0x0f +#define BITMAP_RATE_6M 0x10 +#define BITMAP_RATE_12M 0x20 +#define BITMAP_RATE_24M 0x40 +#define G_RATE_MANDATORY 0x70 + for (i = 0; i < argc; i++) { + tmp = (A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT); + switch (tmp) { + case 2: + rate_bitmap |= BITMAP_RATE_1M; + break; + case 4: + rate_bitmap |= BITMAP_RATE_2M; + break; + case 11: + rate_bitmap |= BITMAP_RATE_5_5M; + break; + case 22: + rate_bitmap |= BITMAP_RATE_11M; + break; + case 12: + ofdm_enable = 1; + rate_bitmap |= BITMAP_RATE_6M; + break; + case 24: + ofdm_enable = 1; + rate_bitmap |= BITMAP_RATE_12M; + break; + case 48: + ofdm_enable = 1; + rate_bitmap |= BITMAP_RATE_24M; + break; + case 18: + case 36: + case 72: + case 96: + case 108: + ofdm_enable = 1; + break; + } + } + if ((rate_bitmap & B_RATE_MANDATORY) != B_RATE_MANDATORY) { + printf("Basic Rates 2, 4, 11 and 22 (500K units) \n" + "must be present in basic or non-basic rates\n"); + return UAP_FAILURE; + } + if (ofdm_enable && ((rate_bitmap & G_RATE_MANDATORY) != G_RATE_MANDATORY)) { + printf("OFDM Rates 12, 24 and 48 ( 500Kb units)\n" + "must be present in basic or non-basic rates\n"); + return UAP_FAILURE; + } + return UAP_SUCCESS; +} + +/** + * @brief detects duplicates channel in array of strings + * + * @param argc number of elements + * @param argv array of strings + * @return UAP_FAILURE or UAP_SUCCESS + */ +inline int +has_dup_channel(int argc, char *argv[]) +{ + int i, j; + /* Check for duplicate */ + for (i = 0; i < (argc - 1); i++) { + for (j = i + 1; j < argc; j++) { + if (atoi(argv[i]) == atoi(argv[j])) { + return UAP_FAILURE; + } + } + } + return UAP_SUCCESS; +} + +/** + * @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 Dump 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 None + */ +void +hexdump_data(char *prompt, void *p, int len, char delim) +{ + int i; + unsigned char *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"); +} + +#if DEBUG +/** + * @brief conditional printf + * + * @param level severity level of the message + * @param fmt printf format string, followed by optional arguments + */ +void +uap_printf(int level, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (level <= debug_level) { + vprintf(fmt, ap); + } + va_end(ap); +} + +/** + * @brief Dump 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 None + */ +void +hexdump(char *prompt, void *p, int len, char delim) +{ + if (debug_level < MSG_ALL) + return; + hexdump_data(prompt, p, len, delim); +} +#endif + +/** + * @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 Show usage information for the sys_info command + * + * $return N/A + */ +void +print_sys_info_usage(void) +{ + printf("\nUsage : sys_info\n"); + return; +} + +/** + * @brief Parse domain file for country information + * + * @param country Country name + * @param sub_bands band information + * @return number of band/ UAP_FAILURE + */ +u8 +parse_domain_file(char *country, IEEEtypes_SubbandSet_t * sub_bands) +{ + FILE *fp; + char str[64]; + char domain_name[40]; + int cflag = 0; + int dflag = 0; + int found = 0; + int j = -1, reset_j = 0; + u8 no_of_sub_band = 0; + char third; + char country2[3]; + + fp = fopen("80211d_domain.conf", "r"); + if (fp == NULL) { + printf("File opening Error\n"); + return UAP_FAILURE; + } + + strncpy((char *) country2, country, 2); + country2[2] = '\0'; + third = country[2]; + + /** + * Search specific domain name + */ + while (!feof(fp)) { + fscanf(fp, "%s", str); + if (cflag) { + strcpy(domain_name, str); + cflag = 0; + } + if (!strcmp(str, "COUNTRY:")) { + /** store next string to domain_name */ + cflag = 1; + } + + if (!strcmp(str, country2)) { + /** Country is matched ;)*/ + if (third && !((third == 'I') || (third == 'O') || (third == ' '))) + found = 0; + else + found = 1; + break; + } + } + + if (!found) { + printf("No match found for Country = %s in the 80211d_domain.conf \n", + country); + fclose(fp); + found = 0; + return UAP_FAILURE; + } + + /** + * Search domain specific information + */ + while (!feof(fp)) { + fscanf(fp, "%s", str); + + if (feof(fp) || (dflag && !strcmp(str, "DOMAIN:"))) { + break; + } + + if (dflag) { + j++; + if (strchr(str, ',')) + reset_j = 1; + + strcpy(str, strtok(str, ", ")); + + if (str == NULL) { + if (reset_j) { + j = -1; + reset_j = 0; + } + continue; + } + + if (IS_HEX_OR_DIGIT(str) == UAP_FAILURE) { + printf("ERR: Only Number values are allowed\n"); + fclose(fp); + return UAP_FAILURE; + } + + switch (j) { + case 0: + sub_bands[no_of_sub_band].FirstChan = (u8) A2HEXDECIMAL(str); + break; + case 1: + sub_bands[no_of_sub_band].NoOfChan = (u8) A2HEXDECIMAL(str); + break; + case 2: + sub_bands[no_of_sub_band++].MaxTxPwr = (u8) A2HEXDECIMAL(str); + break; + default: + printf("ERR: Incorrect 80211d_domain.conf file\n"); + fclose(fp); + return UAP_FAILURE; + } + + if (reset_j) { + j = -1; + reset_j = 0; + } + } + + if (cflag && !strcmp(str, domain_name)) { + /* Followed will be the band details */ + cflag = 0; + dflag = 1; + } + if (!dflag && !strcmp(str, "DOMAIN:")) { + cflag = 1; + } + } + fclose(fp); + return (no_of_sub_band); + +} + +/** + * + * @brief Set/Get SNMP MIB + * + * @param action 0-GET 1-SET + * @param oid oid + * @param size size of oid value + * @param oid_buf oid value + * @return UAP_FAILURE or UAP_SUCCESS + * + */ +int +sg_snmp_mib(u16 action, u16 oid, u16 size, u8 * oid_buf) +{ + APCMDBUF_SNMP_MIB *cmd_buf = NULL; + TLVBUF_HEADER *tlv = NULL; + int ret = UAP_FAILURE; + u8 *buf = NULL; + u16 buf_len; + u16 cmd_len; + int i; + + buf_len = sizeof(APCMDBUF_SNMP_MIB) + sizeof(TLVBUF_HEADER) + size; + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return ret; + } + bzero((char *) buf, buf_len); + + /* Locate Headers */ + cmd_buf = (APCMDBUF_SNMP_MIB *) buf; + tlv = (TLVBUF_HEADER *) (buf + sizeof(APCMDBUF_SNMP_MIB)); + cmd_buf->Size = buf_len - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->CmdCode = HostCmd_SNMP_MIB; + + tlv->Type = uap_cpu_to_le16(oid); + tlv->Len = uap_cpu_to_le16(size); + for (i = 0; action && (i < size); i++) { + tlv->Data[i] = oid_buf[i]; + } + + cmd_buf->Action = uap_cpu_to_le16(action); + cmd_len = buf_len; + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + if (!action) { + /** Reloacte the headers */ + tlv = + (TLVBUF_HEADER *) ((u8 *) cmd_buf + + sizeof(APCMDBUF_SNMP_MIB)); + for (i = 0; i < MIN(uap_le16_to_cpu(tlv->Len), size); i++) { + oid_buf[i] = tlv->Data[i]; + } + } + ret = UAP_SUCCESS; + } else { + printf("ERR:Command Response incorrect!\n"); + ret = UAP_FAILURE; + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return ret; +} + +/** + * @brief Creates a sys_info request and sends to the driver + * + * Usage: "sys_info" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_info(int argc, char *argv[]) +{ + APCMDBUF_SYS_INFO_REQUEST *cmd_buf = NULL; + APCMDBUF_SYS_INFO_RESPONSE *response_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_info_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_sys_info_usage(); + return; + } + + buf_len = + (sizeof(APCMDBUF_SYS_INFO_REQUEST) >= + sizeof(APCMDBUF_SYS_INFO_RESPONSE)) ? sizeof(APCMDBUF_SYS_INFO_REQUEST) + : sizeof(APCMDBUF_SYS_INFO_RESPONSE); + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_SYS_INFO_REQUEST); + cmd_buf = (APCMDBUF_SYS_INFO_REQUEST *) buf; + response_buf = (APCMDBUF_SYS_INFO_RESPONSE *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_INFO; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (response_buf->CmdCode != (APCMD_SYS_INFO | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + /* Print response */ + if (response_buf->Result == CMD_SUCCESS) { + printf("System information = %s\n", response_buf->SysInfo); + } else { + printf("ERR:Could not retrieve system information!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + + free(buf); + return; +} + +/** + * @brief Show usage information for the powermode command + * + * $return N/A + */ +void +print_power_mode_usage(void) +{ + printf + ("\nUsage : powermode [MODE] [SLEEP_PARAM=1 CTRL MIN_SLEEP MAX_SLEEP]"); + printf("\n [INACT_PARAM=2 INACTTO MIN_AWAKE MAX_AWAKE]"); + printf("\nOptions: MODE : 0 - disable power mode"); + printf("\n 1 - periodic DTIM power save mode"); + printf("\n 2 - inactivity based power save mode"); + printf("\n SLEEP_PARAM:"); + printf + ("\n CTRL: 0 - disable CTS2Self protection frame Tx before PS"); + printf + ("\n 1 - enable CTS2Self protection frame Tx before PS"); + printf("\n MIN_SLEEP: Minimum sleep duration in microseconds"); + printf("\n MAX_SLEEP: Maximum sleep duration in miroseconds"); + printf("\n INACT_PARAM: (only for inactivity based power save mode)"); + printf("\n INACTTO: Inactivity timeout in miroseconds"); + printf("\n MIN_AWAKE: Minimum awake duration in microseconds"); + printf("\n MAX_AWAKE: Maximum awake duration in microseconds"); + printf("\n empty - get current power mode\n"); + return; +} + +/** + * @brief Set/get power mode + * + * @param pm A pointer to ps_mgmt structure + * @return N/A + */ +void +send_power_mode_ioctl(ps_mgmt * pm) +{ + struct ifreq ifr; + s32 sockfd; + + /* Open socket */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("ERR:Cannot open socket\n"); + return; + } + /* 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 *) pm; + /* Perform ioctl */ + errno = 0; + if (ioctl(sockfd, UAP_POWER_MODE, &ifr)) { + perror(""); + printf("ERR:UAP_POWER_MODE is not supported by %s\n", dev_name); + return; + } + switch (pm->ps_mode) { + case 0: + printf("power mode = Disabled\n"); + break; + case 1: + printf("power mode = Periodic DTIM PS\n"); + break; + case 2: + printf("power mode = Inactivity based PS \n"); + break; + } + if (pm->flags & PS_FLAG_SLEEP_PARAM) { + printf("Sleep param:\n"); + printf("\tctrl_bitmap=%d\n", (int) pm->sleep_param.ctrl_bitmap); + printf("\tmin_sleep=%d us\n", (int) pm->sleep_param.min_sleep); + printf("\tmax_sleep=%d us\n", (int) pm->sleep_param.max_sleep); + } + if (pm->flags & PS_FLAG_INACT_SLEEP_PARAM) { + printf("Inactivity sleep param:\n"); + printf("\tinactivity_to=%d us\n", (int) pm->inact_param.inactivity_to); + printf("\tmin_awake=%d us\n", (int) pm->inact_param.min_awake); + printf("\tmax_awake=%d us\n", (int) pm->inact_param.max_awake); + } + /* Close socket */ + close(sockfd); + return; +} + +/** + * @brief Creates power mode request and send to driver + * and sends to the driver + * + * Usage: "Usage : powermode [MODE]" + * + * Options: MODE : 0 - disable power mode + * 1 - enable power mode + * 2 - get current power mode + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_power_mode(int argc, char *argv[]) +{ + int opt; + ps_mgmt pm; + int type = 0; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_power_mode_usage(); + return; + } + } + argc -= optind; + argv += optind; + + memset(&pm, 0, sizeof(ps_mgmt)); + /* Check arguments */ + if ((argc > 9) || + ((argc != 0) && (argc != 1) && (argc != 5) && (argc != 9))) { + printf("ERR:wrong arguments.\n"); + print_power_mode_usage(); + return; + } + + if (argc) { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 2)) { + printf + ("ERR:Illegal power mode %s. Must be either '0' '1' or '2'.\n", + argv[0]); + print_power_mode_usage(); + return; + } + pm.flags = PS_FLAG_PS_MODE; + pm.ps_mode = atoi(argv[0]); + if ((pm.ps_mode == PS_MODE_DISABLE) && (argc > 1)) { + printf("ERR: Illegal parameter for disable power mode\n"); + print_power_mode_usage(); + return; + } + if ((pm.ps_mode != PS_MODE_INACTIVITY) && (argc > 5)) { + printf("ERR: Illegal parameter\n"); + print_power_mode_usage(); + return; + } + if (argc >= 5) { + if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 1) || + (atoi(argv[1]) > 2)) { + printf + ("ERR:Illegal parameter type %s. Must be either '1' or '2'.\n", + argv[1]); + print_power_mode_usage(); + return; + } + type = atoi(argv[1]); + if ((type == INACTIVITY_SLEEP_PARAMETER) && + (pm.ps_mode != PS_MODE_INACTIVITY)) { + printf + ("ERR: inactivity sleep parameter only valid for inactivity power save mode\n"); + print_power_mode_usage(); + return; + } + if (type == SLEEP_PARAMETER) { + if ((ISDIGIT(argv[2]) == 0) || (atoi(argv[2]) < 0) || + (atoi(argv[2]) > 1)) { + printf + ("ERR:Illegal ctrl bitmap = %s. Must be either '0' or '1'.\n", + argv[2]); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_SLEEP_PARAM; + pm.sleep_param.ctrl_bitmap = atoi(argv[2]); + if ((ISDIGIT(argv[3]) == 0) || (ISDIGIT(argv[4]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.sleep_param.min_sleep = atoi(argv[3]); + pm.sleep_param.max_sleep = atoi(argv[4]); + if (pm.sleep_param.min_sleep > pm.sleep_param.max_sleep) { + printf + ("ERR: MIN_SLEEP value should be less than or equal to MAX_SLEEP\n"); + return; + } + if (pm.sleep_param.min_sleep < PS_SLEEP_PARAM_MIN || + ((pm.sleep_param.max_sleep > PS_SLEEP_PARAM_MAX) && + pm.sleep_param.ctrl_bitmap)) { + printf + ("ERR: Incorrect value of sleep period. Please check README\n"); + return; + } + } else { + if ((ISDIGIT(argv[2]) == 0) || (ISDIGIT(argv[3]) == 0) || + (ISDIGIT(argv[4]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_INACT_SLEEP_PARAM; + pm.inact_param.inactivity_to = atoi(argv[2]); + pm.inact_param.min_awake = atoi(argv[3]); + pm.inact_param.max_awake = atoi(argv[4]); + if (pm.inact_param.min_awake > pm.inact_param.max_awake) { + printf + ("ERR: MIN_AWAKE value should be less than or equal to MAX_AWAKE\n"); + return; + } + if (pm.inact_param.min_awake < PS_AWAKE_PERIOD_MIN) { + printf("ERR: Incorrect value of MIN_AWAKE period.\n"); + return; + } + } + } + if (argc == 9) { + if ((ISDIGIT(argv[5]) == 0) || (atoi(argv[5]) < 1) || + (atoi(argv[5]) > 2)) { + printf + ("ERR:Illegal parameter type %s. Must be either '1' or '2'.\n", + argv[5]); + print_power_mode_usage(); + return; + } + if (type == atoi(argv[5])) { + printf("ERR: Duplicate parameter type %s.\n", argv[5]); + print_power_mode_usage(); + return; + } + type = atoi(argv[5]); + if (type == SLEEP_PARAMETER) { + if ((ISDIGIT(argv[6]) == 0) || (atoi(argv[6]) < 0) || + (atoi(argv[6]) > 1)) { + printf + ("ERR:Illegal ctrl bitmap = %s. Must be either '0' or '1'.\n", + argv[6]); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_SLEEP_PARAM; + pm.sleep_param.ctrl_bitmap = atoi(argv[6]); + if ((ISDIGIT(argv[7]) == 0) || (ISDIGIT(argv[8]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.sleep_param.min_sleep = atoi(argv[7]); + pm.sleep_param.max_sleep = atoi(argv[8]); + if (pm.sleep_param.min_sleep > pm.sleep_param.max_sleep) { + printf + ("ERR: MIN_SLEEP value should be less than or equal to MAX_SLEEP\n"); + return; + } + if (pm.sleep_param.min_sleep < PS_SLEEP_PARAM_MIN || + ((pm.sleep_param.max_sleep > PS_SLEEP_PARAM_MAX) && + pm.sleep_param.ctrl_bitmap)) { + printf + ("ERR: Incorrect value of sleep period. Please check README\n"); + return; + } + } else { + if ((ISDIGIT(argv[6]) == 0) || (ISDIGIT(argv[7]) == 0) || + (ISDIGIT(argv[8]) == 0)) { + printf("ERR:Illegal parameter\n"); + print_power_mode_usage(); + return; + } + pm.flags |= PS_FLAG_INACT_SLEEP_PARAM; + pm.inact_param.inactivity_to = atoi(argv[6]); + pm.inact_param.min_awake = atoi(argv[7]); + pm.inact_param.max_awake = atoi(argv[8]); + if (pm.inact_param.min_awake > pm.inact_param.max_awake) { + printf + ("ERR: MIN_AWAKE value should be less than or equal to MAX_AWAKE\n"); + return; + } + if (pm.inact_param.min_awake < PS_AWAKE_PERIOD_MIN) { + printf("ERR: Incorrect value of MIN_AWAKE period.\n"); + return; + } + } + } + } + send_power_mode_ioctl(&pm); + return; +} + +/** + * @brief Show usage information for the sys_reset command + * + * $return N/A + */ +void +print_sys_reset_usage(void) +{ + printf("\nUsage : sys_reset\n"); + return; +} + +/** + * @brief Creates a sys_reset request and sends to the driver + * + * Usage: "sys_reset" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_reset(int argc, char *argv[]) +{ + APCMDBUF_SYS_RESET *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + ps_mgmt pm; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_reset_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_sys_reset_usage(); + return; + } + + memset(&pm, 0, sizeof(ps_mgmt)); + pm.flags = PS_FLAG_PS_MODE; + pm.ps_mode = PS_MODE_DISABLE; + send_power_mode_ioctl(&pm); + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_SYS_RESET); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_RESET *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_RESET; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_RESET | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("System reset successful!\n"); + } else { + printf("ERR:Could not reset system!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the bss_start command + * + * $return N/A + */ +void +print_bss_start_usage(void) +{ + printf("\nUsage : bss_start\n"); + return; +} + +/** + * @brief Creates a BSS start request and sends to the driver + * + * Usage: "bss_start" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_bss_start(int argc, char *argv[]) +{ + APCMDBUF_BSS_START *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_bss_start_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_bss_start_usage(); + return; + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_BSS_START); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_BSS_START *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_BSS_START; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_BSS_START | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BSS started!\n"); + } else if (cmd_buf->Result == BSS_FAILURE_START_INVAL) { + printf("ERR:Could not start BSS! Invalid BSS parameters.\n"); + } else if (cmd_buf->Result == BSS_FAILURE_START_REDUNDANT) { + printf("ERR:Could not start BSS! BSS already started.\n"); + } else { + printf("ERR:Could not start BSS!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the bss_stop command + * + * $return N/A + */ +void +print_bss_stop_usage(void) +{ + printf("\nUsage : bss_stop\n"); + return; +} + +/** + * @brief Creates a BSS stop request and sends to the driver + * + * Usage: "bss_stop" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_bss_stop(int argc, char *argv[]) +{ + APCMDBUF_BSS_STOP *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_bss_stop_usage(); + return; + } + } + argc -= optind; + argv += optind; /* Check arguments */ + + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_bss_stop_usage(); + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_BSS_STOP); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_BSS_STOP *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_BSS_STOP; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_BSS_STOP | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BSS stopped!\n"); + } else if (cmd_buf->Result == BSS_FAILURE_STOP_REDUNDANT) { + printf("ERR:Could not stop BSS! BSS already stopped.\n"); + } else if (cmd_buf->Result == BSS_FAILURE_STOP_INVAL) { + printf("ERR:Could not stop BSS! No active BSS.\n"); + } else { + printf("ERR:Could not stop BSS!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the sta_list command + * + * $return N/A + */ +void +print_sta_list_usage(void) +{ + printf("\nUsage : sta_list\n"); + return; +} + +/** + * @brief Creates a STA list request and sends to the driver + * + * Usage: "sta_list" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sta_list(int argc, char *argv[]) +{ + APCMDBUF_STA_LIST_REQUEST *cmd_buf = NULL; + APCMDBUF_STA_LIST_RESPONSE *response_buf = NULL; + u8 *buf = NULL; + u16 buf_len; + TLVBUF_STA_INFO *tlv = NULL; + u16 cmd_len; + u16 response_len; + int ret = UAP_FAILURE; + int i = 0; + int opt; + int rssi = 0; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sta_list_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 0) { + printf("ERR:Too many arguments.\n"); + print_sta_list_usage(); + return; + } + response_len = + sizeof(APCMDBUF_STA_LIST_RESPONSE) + + (MAX_NUM_CLIENTS * sizeof(TLVBUF_STA_INFO)); + if (response_len > sizeof(APCMDBUF_STA_LIST_REQUEST)) + buf_len = response_len; + else + buf_len = sizeof(APCMDBUF_STA_LIST_REQUEST); + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_STA_LIST_REQUEST); + + /* Initialize the command buffer */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_STA_LIST_REQUEST *) buf; + response_buf = (APCMDBUF_STA_LIST_RESPONSE *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_STA_LIST; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + response_buf->StaCount = uap_le16_to_cpu(response_buf->StaCount); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (response_buf->CmdCode != (APCMD_STA_LIST | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + + /* Print response */ + if (response_buf->Result == CMD_SUCCESS) { + printf("Number of STA = %d\n\n", response_buf->StaCount); + for (i = 0; i < response_buf->StaCount; i++) { + tlv = (TLVBUF_STA_INFO *) (&response_buf->StaList[i]); + endian_convert_tlv_header_in(tlv); + if (tlv) { + if (tlv->Tag != MRVL_STA_INFO_TLV_ID) { + printf("STA %d information corrupted.\n", i + 1); + continue; + } + printf("STA %d information:\n", i + 1); + printf("=====================\n"); + printf("MAC Address: "); + print_mac(tlv->MacAddress); + printf("\nPower mfg status: %s\n", + (tlv->PowerMfgStatus == + 0) ? "active" : "power save"); + /** On some platform, s8 is same as unsigned char*/ + rssi = (int) tlv->Rssi; + if (rssi > 0x7f) + rssi = -(256 - rssi); + printf("Rssi : %d dBm\n\n", rssi); + } else { + printf("ERR:Unable to find information for STA %d\n\n", + i + 1); + } + } + } else { + printf("ERR:Could not get STA list!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return; +} + +/** + * @brief Show usage information for the sta_deauth command + * + * $return N/A + */ +void +print_sta_deauth_usage(void) +{ + printf("\nUsage : sta_deauth <STA_MAC_ADDRESS> [REASON_CODE]\n"); + return; +} + +/** + * @brief Creates a STA deauth request and sends to the driver + * + * Usage: "sta_deauth <STA_MAC_ADDRESS>" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sta_deauth(int argc, char *argv[]) +{ + APCMDBUF_STA_DEAUTH *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sta_deauth_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc != 1 && argc != 2) { + printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS.\n"); + printf("\t\t with optional REASON_CODE.\n"); + print_sta_deauth_usage(); + return; + } + + /* Check Reason Code */ + if (argc == 2) { + if (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) { + printf("ERR: Invalid input for reason code\n"); + print_sta_deauth_usage(); + return; + } + } + + /* Initialize the command length */ + cmd_len = sizeof(APCMDBUF_STA_DEAUTH); + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, cmd_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_STA_DEAUTH *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_STA_DEAUTH; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + if ((ret = mac2raw(argv[0], cmd_buf->StaMacAddress)) != UAP_SUCCESS) { + printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" : + ret == UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); + free(buffer); + return; + } + if (argc == 2) { + cmd_buf->ReasonCode = uap_cpu_to_le16((u16) A2HEXDECIMAL(argv[1])); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_STA_DEAUTH | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buffer); + return; + } + + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Deauthentication successful!\n"); + } else { + printf("ERR:Deauthentication unsuccessful!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** + * @brief Show usage information for the coex_config command + * + * $return N/A + */ +void +print_coex_config_usage(void) +{ + printf("\nUsage : coex_config [CONFIG_FILE]\n"); + printf + ("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n"); + return; +} + +/** + * @brief Creates a coex_config request and sends to the driver + * + * Usage: "Usage : coex_config [CONFIG_FILE]" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_coex_config(int argc, char *argv[]) +{ + apcmdbuf_coex_config *cmd_buf = NULL; + tlvbuf_coex_common_cfg *coex_common_tlv; + tlvbuf_coex_sco_cfg *coex_sco_tlv; + tlvbuf_coex_acl_cfg *coex_acl_tlv; + tlvbuf_coex_stats *coex_stats_tlv; + u8 *buf = NULL; + u16 cmd_len; + int ret = UAP_FAILURE; + int opt; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_coex_config_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 1) { + printf("ERR:Too many arguments.\n"); + print_coex_config_usage(); + return; + } + if (argc == 1) { + /* Read profile and send command to firmware */ + apcmd_coex_config_profile(argc, argv); + return; + } + + /* fixed command length */ + cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg) + + sizeof(tlvbuf_coex_stats); + /* alloc buf for command */ + buf = (u8 *) malloc(cmd_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, cmd_len); + + cmd_buf = (apcmdbuf_coex_config *) buf; + + coex_common_tlv = (tlvbuf_coex_common_cfg *) cmd_buf->tlv_buffer; + coex_common_tlv->Tag = MRVL_BT_COEX_COMMON_CFG_TLV_ID; + coex_common_tlv->Length = + sizeof(tlvbuf_coex_common_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_common_tlv); + + coex_sco_tlv = (tlvbuf_coex_sco_cfg *) (cmd_buf->tlv_buffer + + sizeof(tlvbuf_coex_common_cfg)); + coex_sco_tlv->Tag = MRVL_BT_COEX_SCO_CFG_TLV_ID; + coex_sco_tlv->Length = sizeof(tlvbuf_coex_sco_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_sco_tlv); + + coex_acl_tlv = (tlvbuf_coex_acl_cfg *) (cmd_buf->tlv_buffer + + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg)); + coex_acl_tlv->Tag = MRVL_BT_COEX_ACL_CFG_TLV_ID; + coex_acl_tlv->Length = sizeof(tlvbuf_coex_acl_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_acl_tlv); + + coex_stats_tlv = (tlvbuf_coex_stats *) (cmd_buf->tlv_buffer + + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg) + + sizeof(tlvbuf_coex_acl_cfg)); + coex_stats_tlv->Tag = MRVL_BT_COEX_STATS_TLV_ID; + coex_stats_tlv->Length = sizeof(tlvbuf_coex_stats) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_stats_tlv); + + /* Fill the command buffer */ + cmd_buf->CmdCode = HostCmd_ROBUST_COEX; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->action = uap_cpu_to_le16(ACTION_GET); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BT Coex settings:\n"); + print_tlv(buf + sizeof(apcmdbuf_coex_config), + cmd_buf->Size - sizeof(apcmdbuf_coex_config) + + BUF_HEADER_SIZE); + } else { + printf("ERR:Could not retrieve coex configuration.\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return; +} + +/** + * @brief Show usage information for the sys_config command + * + * $return N/A + */ +void +print_sys_config_usage(void) +{ + printf("\nUsage : sys_config [CONFIG_FILE]\n"); + printf + ("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n"); + printf("CONFIG_FILE is file contain all the Micro AP settings.\n"); + return; +} + +/** + * @brief Show usage information for the rdeeprom command + * + * $return N/A + */ +void +print_apcmd_read_eeprom_usage(void) +{ + printf("\nUsage: rdeeprom <offset> <bytecount>\n"); + printf(" offset : 0,4,8,..., multiple of 4\n"); + printf(" bytecount : 4-20, multiple of 4\n"); + return; +} + +/** + * @brief Show protocol tlv + * + * @param tlv Poniter to protocol tlv + * + * $return N/A + */ +void +print_protocol(TLVBUF_PROTOCOL * tlv) +{ + switch (tlv->Protocol) { + case 0: + case PROTOCOL_NO_SECURITY: + printf("PROTOCOL = No security\n"); + break; + case PROTOCOL_STATIC_WEP: + printf("PROTOCOL = Static WEP\n"); + break; + case PROTOCOL_WPA: + printf("PROTOCOL = WPA \n"); + break; + case PROTOCOL_WPA2: + printf("PROTOCOL = WPA2 \n"); + break; + case PROTOCOL_WPA | PROTOCOL_WPA2: + printf("PROTOCOL = WPA/WPA2 \n"); + break; + default: + printf("Unknown PROTOCOL: 0x%x \n", tlv->Protocol); + break; + } +} + +/** + * @brief Show wep tlv + * + * @param tlv Poniter to wep tlv + * + * $return N/A + */ +void +print_wep_key(TLVBUF_WEP_KEY * tlv) +{ + int i; + if (tlv->Length <= 2) { + printf("wrong wep_key tlv: length=%d\n", tlv->Length); + return; + } + printf("WEP KEY_%d = ", tlv->KeyIndex); + for (i = 0; i < tlv->Length - 2; i++) + printf("%02x ", tlv->Key[i]); + if (tlv->IsDefault) + printf("\nDefault WEP Key = %d\n", tlv->KeyIndex); + else + printf("\n"); +} + +/** + * @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] == '#') { + 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 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) +{ + char *pos, *end, *sstart; + while (fgets(s, size, stream)) { + (*line)++; + s[size - 1] = '\0'; + pos = s; + /* Skip white space from the beginning of line. */ + while (*pos == ' ' || *pos == '\t' || *pos == '\r') + pos++; + /* Skip comment lines and empty lines */ + if (*pos == '#' || *pos == '\n' || *pos == '\0') + continue; + /* + * Remove # comments unless they are within a double quoted + * string. + */ + sstart = strchr(pos, '"'); + if (sstart) + sstart = strrchr(sstart + 1, '"'); + if (!sstart) + sstart = pos; + end = strchr(sstart, '#'); + if (end) + *end-- = '\0'; + else + end = pos + strlen(pos) - 1; + /* Remove trailing white space. */ + while (end > pos && + (*end == '\n' || *end == ' ' || *end == '\t' || *end == '\r')) + *end-- = '\0'; + if (*pos == '\0') + continue; + if (_pos) + *_pos = pos; + return pos; + } + + if (_pos) + *_pos = NULL; + return NULL; +} + +/** + * @brief Read the profile and sends to the driver + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_coex_config_profile(int argc, char *argv[]) +{ + FILE *config_file = NULL; + char *line = NULL; + int i, ret, index, li = 0; + char *pos = NULL; + int arg_num = 0; + char *args[30]; + int is_coex_config = 0; + int is_coex_common_config = 0; + int is_coex_sco_config = 0; + int is_coex_acl_config = 0; + u8 *buf = NULL; + apcmdbuf_coex_config *cmd_buf = NULL; + tlvbuf_coex_common_cfg *coex_common_tlv; + tlvbuf_coex_sco_cfg *coex_sco_tlv; + tlvbuf_coex_acl_cfg *coex_acl_tlv; + u16 acl_enabled = 0; + u32 conf_bitmap = 0; + u16 cmd_len = 0, tlv_len = 0; + u16 sco_prot_qtime[4] = { 0, 0, 0, 0 }, sco_prot_rate = 0, sco_acl_freq = 0; + u16 acl_bt_time = 0, acl_wlan_time = 0, acl_prot_rate = 0; + + /* Check if file exists */ + config_file = fopen(argv[0], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return; + } + line = (char *) malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + bzero(line, MAX_CONFIG_LINE); + + /* fixed command length */ + cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg) + + sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg); + /* alloc buf for command */ + buf = (u8 *) malloc(cmd_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + goto done; + } + bzero((char *) buf, cmd_len); + + cmd_buf = (apcmdbuf_coex_config *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = HostCmd_ROBUST_COEX; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->action = uap_cpu_to_le16(ACTION_SET); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n", li, line); +#endif + arg_num = parse_line(line, args); +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n", arg_num); + for (i = 0; i < arg_num; i++) { + uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1, args[i]); + } +#endif + /* Check for end of Coex configurations */ + if (is_coex_acl_config == 1) { + if (strcmp(args[0], "}") == 0) { + coex_acl_tlv = + (tlvbuf_coex_acl_cfg *) (cmd_buf->tlv_buffer + tlv_len); + coex_acl_tlv->Tag = MRVL_BT_COEX_ACL_CFG_TLV_ID; + coex_acl_tlv->Length = + sizeof(tlvbuf_coex_acl_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_acl_tlv); + coex_acl_tlv->enabled = uap_cpu_to_le16(acl_enabled); + coex_acl_tlv->bt_time = uap_cpu_to_le16(acl_bt_time); + coex_acl_tlv->wlan_time = uap_cpu_to_le16(acl_wlan_time); + coex_acl_tlv->protection_rate = uap_cpu_to_le16(acl_prot_rate); + tlv_len += sizeof(tlvbuf_coex_acl_cfg); + is_coex_acl_config = 0; + } + } else if (is_coex_sco_config == 1) { + if (strcmp(args[0], "}") == 0) { + coex_sco_tlv = + (tlvbuf_coex_sco_cfg *) (cmd_buf->tlv_buffer + tlv_len); + coex_sco_tlv->Tag = MRVL_BT_COEX_SCO_CFG_TLV_ID; + coex_sco_tlv->Length = + sizeof(tlvbuf_coex_sco_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_sco_tlv); + for (i = 0; i < 4; i++) + coex_sco_tlv->protection_qtime[i] = + uap_cpu_to_le16(sco_prot_qtime[i]); + coex_sco_tlv->protection_rate = uap_cpu_to_le16(sco_prot_rate); + coex_sco_tlv->acl_frequency = uap_cpu_to_le16(sco_acl_freq); + tlv_len += sizeof(tlvbuf_coex_sco_cfg); + is_coex_sco_config = 0; + } + } else if (is_coex_common_config == 1) { + if (strcmp(args[0], "}") == 0) { + coex_common_tlv = + (tlvbuf_coex_common_cfg *) (cmd_buf->tlv_buffer + tlv_len); + coex_common_tlv->Tag = MRVL_BT_COEX_COMMON_CFG_TLV_ID; + coex_common_tlv->Length = + sizeof(tlvbuf_coex_common_cfg) - sizeof(TLVBUF_HEADER); + endian_convert_tlv_header_out(coex_common_tlv); + coex_common_tlv->config_bitmap = uap_cpu_to_le32(conf_bitmap); + tlv_len += sizeof(tlvbuf_coex_common_cfg); + is_coex_common_config = 0; + } + } else if (is_coex_config == 1) { + if (strcmp(args[0], "}") == 0) + is_coex_config = 0; + } + if (strcmp(args[0], "coex_config") == 0) { + is_coex_config = 1; + } else if (strcmp(args[0], "common_config") == 0) { + is_coex_common_config = 1; + } else if (strcmp(args[0], "sco_config") == 0) { + is_coex_sco_config = 1; + } else if (strcmp(args[0], "acl_config") == 0) { + is_coex_acl_config = 1; + } + if ((strcmp(args[0], "bitmap") == 0) && is_coex_common_config) { + if (is_input_valid(COEX_COMM_BITMAP, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + conf_bitmap = (u32) A2HEXDECIMAL(args[1]); + } else if ((strncmp(args[0], "protectionFromQTime", 19) == 0) && + is_coex_sco_config) { + index = atoi(args[0] + strlen("protectionFromQTime")); + if (index < 0 || index > 3) { + printf("ERR:Incorrect index %d.\n", index); + goto done; + } + if (is_input_valid(COEX_PROTECTION, arg_num, args) != UAP_SUCCESS) { + goto done; + } + sco_prot_qtime[index] = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "scoProtectionFromRate") == 0) && + is_coex_sco_config) { + if (is_input_valid(COEX_PROTECTION, arg_num, args) != UAP_SUCCESS) { + goto done; + } + sco_prot_rate = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "aclFrequency") == 0) && is_coex_sco_config) { + if (is_input_valid(COEX_SCO_ACL_FREQ, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + sco_acl_freq = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "enabled") == 0) && is_coex_acl_config) { + if (is_input_valid(COEX_ACL_ENABLED, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + acl_enabled = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "btTime") == 0) && is_coex_acl_config) { + if (is_input_valid(COEX_ACL_BT_TIME, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + acl_bt_time = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "wlanTime") == 0) && is_coex_acl_config) { + if (is_input_valid(COEX_ACL_WLAN_TIME, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + acl_wlan_time = (u16) atoi(args[1]); + } else if ((strcmp(args[0], "aclProtectionFromRate") == 0) && + is_coex_acl_config) { + if (is_input_valid(COEX_PROTECTION, arg_num, args) != UAP_SUCCESS) { + goto done; + } + acl_prot_rate = (u16) atoi(args[1]); + } + } + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + goto done; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("BT Coex settings sucessfully set.\n"); + } else { + printf("ERR:Could not set coex configuration.\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + done: + fclose(config_file); + if (buf) + free(buf); + if (line) + free(line); +} + +/** + * @brief Read the profile and sends to the driver + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_sys_config_profile(int argc, char *argv[]) +{ + FILE *config_file = NULL; + char *line = NULL; + int li = 0; + char *pos = NULL; + int arg_num = 0; + char *args[30]; + int i; + int is_ap_config = 0; + int is_custom_ie_config = 0; + int is_ap_mac_filter = 0; + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len = 0; + u16 tlv_len = 0; + u16 ie_len = 0; + u16 ie_buf_len = 0; + u16 mask_ie_index = 0; + int keyindex = -1; + int pairwisecipher = -1; + int groupcipher = -1; + TLVBUF_STA_MAC_ADDR_FILTER *filter_tlv = NULL; + tlvbuf_custom_ie *custom_ie_tlv_head = NULL; + tlvbuf_custom_ie *custom_ie_tlv = NULL; + custom_ie *custom_ie_ptr = NULL; + int custom_ie_tlv_len = 0; + int custom_mask_count = 0; + int custom_buf_count = 0; + int filter_mac_count = -1; + int tx_data_rate = -1; + int mcbc_data_rate = -1; + u8 rate[MAX_RATES]; + int found = 0; + char country_80211d[4]; + u8 state_80211d; + int flag_80211d = 0; + + memset(rate, 0, MAX_RATES); + /* Check if file exists */ + config_file = fopen(argv[0], "r"); + if (config_file == NULL) { + printf("\nERR:Config file can not open.\n"); + return; + } + line = (char *) malloc(MAX_CONFIG_LINE); + if (!line) { + printf("ERR:Cannot allocate memory for line\n"); + goto done; + } + bzero(line, MAX_CONFIG_LINE); + + /* Parse file and process */ + while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) { +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n", li, line); +#endif + arg_num = parse_line(line, args); +#if DEBUG + uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n", arg_num); + for (i = 0; i < arg_num; i++) { + uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1, args[i]); + } +#endif + /* Check for end of AP configurations */ + if (is_ap_config == 1) { + if (strcmp(args[0], "}") == 0) { + is_ap_config = 0; + if (tx_data_rate != -1) { + if ((!rate[0]) && (tx_data_rate) && + (is_tx_rate_valid((u8) tx_data_rate) != UAP_SUCCESS)) { + printf("ERR: Invalid Tx Data Rate \n"); + goto done; + } + if (rate[0] && tx_data_rate) { + for (i = 0; rate[i] != 0; i++) { + if ((rate[i] & ~BASIC_RATE_SET_BIT) == tx_data_rate) { + found = 1; + break; + } + } + if (!found) { + printf("ERR: Invalid Tx Data Rate \n"); + goto done; + } + } + + /* Append a new TLV */ + TLVBUF_TX_DATA_RATE *tlv = NULL; + tlv_len = sizeof(TLVBUF_TX_DATA_RATE); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append tx data rate TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_TX_DATA_RATE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_TX_DATA_RATE_TLV_ID; + tlv->Length = 2; + tlv->TxDataRate = tx_data_rate; + endian_convert_tlv_header_out(tlv); + tlv->TxDataRate = uap_cpu_to_le16(tlv->TxDataRate); + } + if (mcbc_data_rate != -1) { + if ((!rate[0]) && (mcbc_data_rate) && + (is_mcbc_rate_valid((u8) mcbc_data_rate) != + UAP_SUCCESS)) { + printf("ERR: Invalid Tx Data Rate \n"); + goto done; + } + if (rate[0] && mcbc_data_rate) { + for (i = 0; rate[i] != 0; i++) { + if (rate[i] & BASIC_RATE_SET_BIT) { + if ((rate[i] & ~BASIC_RATE_SET_BIT) == + mcbc_data_rate) { + found = 1; + break; + } + } + } + if (!found) { + printf("ERR: Invalid MCBC Data Rate \n"); + goto done; + } + } + + /* Append a new TLV */ + TLVBUF_MCBC_DATA_RATE *tlv = NULL; + tlv_len = sizeof(TLVBUF_MCBC_DATA_RATE); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append tx data rate TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_MCBC_DATA_RATE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_MCBC_DATA_RATE_TLV_ID; + tlv->Length = 2; + tlv->MCBCdatarate = mcbc_data_rate; + endian_convert_tlv_header_out(tlv); + tlv->MCBCdatarate = uap_cpu_to_le16(tlv->MCBCdatarate); + } + + if ((pairwisecipher >= 0) && (groupcipher >= 0)) { + if (is_cipher_valid(pairwisecipher, groupcipher) != + UAP_SUCCESS) { + printf + ("ERR:Wrong group and pair cipher combination!\n"); + goto done; + } + TLVBUF_CIPHER *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_CIPHER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append cipher TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CIPHER *) (buffer + cmd_len); + bzero((char *) tlv, tlv_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_CIPHER_TLV_ID; + tlv->Length = 2; + tlv->PairwiseCipher = pairwisecipher; + tlv->GroupCipher = groupcipher; + endian_convert_tlv_header_out(tlv); + } + cmd_buf->Size = cmd_len; + /* Send collective command */ + uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + cmd_len = 0; + if (buffer) { + free(buffer); + buffer = NULL; + } + continue; + } + } + + /* Check for beginning of AP configurations */ + if (strcmp(args[0], "ap_config") == 0) { + is_ap_config = 1; + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE); + if (buffer) { + free(buffer); + buffer = NULL; + } + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Action = ACTION_SET; + continue; + } + + /* Check for end of AP MAC address filter configurations */ + if (is_ap_mac_filter == 1) { + if (strcmp(args[0], "}") == 0) { + is_ap_mac_filter = 0; + if (filter_tlv->Count != filter_mac_count) { + printf + ("ERR:Number of MAC address provided does not match 'Count'\n"); + goto done; + } + if (filter_tlv->FilterMode && (filter_tlv->Count == 0)) { + printf + ("ERR:Filter list can not be empty for %s Filter mode\n", + (filter_tlv->FilterMode == 1) ? "'Allow'" : "'Block'"); + goto done; + } + filter_tlv->Length = (filter_tlv->Count * ETH_ALEN) + 2; + cmd_len -= + (MAX_MAC_ONESHOT_FILTER - filter_mac_count) * ETH_ALEN; + cmd_buf->Size = cmd_len; + endian_convert_tlv_header_out(filter_tlv); + uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + cmd_len = 0; + if (buffer) { + free(buffer); + buffer = NULL; + } + continue; + } + } + + /* Check for end of custom IE configurations */ + if (is_custom_ie_config == 1) { + if (strcmp(args[0], "}") == 0) { + if (custom_mask_count != custom_buf_count) { + printf + ("ERR:custom IE mask count and buffer count does not match\n"); + goto done; + } + is_custom_ie_config = 0; + custom_ie_tlv_head->Length = custom_ie_tlv_len; + cmd_len -= + (MAX_IE_BUFFER_LEN * MAX_CUSTOM_IE_COUNT) - + custom_ie_tlv_len; + cmd_len -= sizeof(custom_ie) * MAX_CUSTOM_IE_COUNT; + cmd_buf->Size = cmd_len; + endian_convert_tlv_header_out(custom_ie_tlv_head); + uap_ioctl((u8 *) cmd_buf, &cmd_len, cmd_len); + cmd_len = 0; + if (buffer) { + free(buffer); + buffer = NULL; + } + continue; + } + } + + if (flag_80211d && (strcmp(args[0], "11d_enable") == 0)) { + if (IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) { + printf("ERR: valid input for state are 0 or 1\n"); + goto done; + } + state_80211d = (u8) A2HEXDECIMAL(args[1]); + + if ((state_80211d != 0) && (state_80211d != 1)) { + printf("ERR: valid input for state are 0 or 1 \n"); + goto done; + } + if (sg_snmp_mib + (ACTION_SET, OID_80211D_ENABLE, sizeof(state_80211d), + &state_80211d) + == UAP_FAILURE) { + goto done; + } + } + + if (strcmp(args[0], "country") == 0) { + APCMDBUF_CFG_80211D *cmd_buf = NULL; + IEEEtypes_SubbandSet_t sub_bands[MAX_SUB_BANDS]; + u8 no_of_sub_band = 0; + u16 buf_len; + u16 cmdlen; + u8 *buf = NULL; + + if ((strlen(args[1]) > 3) || (strlen(args[1]) < 0)) { + printf("In-correct country input\n"); + goto done; + } + strcpy(country_80211d, args[1]); + for (i = 0; i < strlen(country_80211d); i++) { + if ((country_80211d[i] < 'A') || (country_80211d[i] > 'z')) { + printf("Invalid Country Code\n"); + goto done; + } + if (country_80211d[i] > 'Z') + country_80211d[i] = country_80211d[i] - 'a' + 'A'; + } + no_of_sub_band = parse_domain_file(country_80211d, sub_bands); + if (no_of_sub_band == UAP_FAILURE) { + printf("Parsing Failed\n"); + goto done; + } + buf_len = sizeof(APCMDBUF_CFG_80211D); + buf_len += no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t); + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + goto done; + } + bzero((char *) buf, buf_len); + cmd_buf = (APCMDBUF_CFG_80211D *) buf; + cmdlen = buf_len; + cmd_buf->Size = cmdlen - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->Action = uap_cpu_to_le16(ACTION_SET); + cmd_buf->CmdCode = HostCmd_CMD_802_11D_DOMAIN_INFO; + cmd_buf->Domain.Tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN); + cmd_buf->Domain.Length = uap_cpu_to_le16(sizeof(domain_param_t) + - BUF_HEADER_SIZE + + + (no_of_sub_band * + sizeof + (IEEEtypes_SubbandSet_t))); + + memset(cmd_buf->Domain.CountryCode, ' ', + sizeof(cmd_buf->Domain.CountryCode)); + memcpy(cmd_buf->Domain.CountryCode, country_80211d, + strlen(country_80211d)); + memcpy(cmd_buf->Domain.Subband, sub_bands, + no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t)); + + /* Send the command */ + uap_ioctl((u8 *) cmd_buf, &cmdlen, buf_len); + if (buf) + free(buf); + } + + /* Check for beginning of AP MAC address filter configurations */ + if (strcmp(args[0], "ap_mac_filter") == 0) { + is_ap_mac_filter = 1; + cmd_len = + sizeof(APCMDBUF_SYS_CONFIGURE) + + sizeof(TLVBUF_STA_MAC_ADDR_FILTER) + + (MAX_MAC_ONESHOT_FILTER * ETH_ALEN); + if (buffer) { + free(buffer); + buffer = NULL; + } + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Action = ACTION_SET; + filter_tlv = + (TLVBUF_STA_MAC_ADDR_FILTER *) (buffer + + sizeof(APCMDBUF_SYS_CONFIGURE)); + filter_tlv->Tag = MRVL_STA_MAC_ADDR_FILTER_TLV_ID; + filter_tlv->Length = 2; + filter_tlv->Count = 0; + filter_mac_count = 0; + continue; + } + + /* Check for beginning of custom IE configurations */ + if (strcmp(args[0], "custom_ie_config") == 0) { + is_custom_ie_config = 1; + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE) + sizeof(tlvbuf_custom_ie) + + + ((MAX_IE_BUFFER_LEN + sizeof(custom_ie)) * MAX_CUSTOM_IE_COUNT); + if (buffer) { + free(buffer); + buffer = NULL; + } + buffer = (u8 *) malloc(cmd_len); + if (!buffer) { + printf("ERR:Cannot allocate memory!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->Action = ACTION_SET; + custom_ie_tlv = + (tlvbuf_custom_ie *) (buffer + sizeof(APCMDBUF_SYS_CONFIGURE)); + custom_ie_ptr = (custom_ie *) (custom_ie_tlv->ie_data); + custom_ie_tlv_head = custom_ie_tlv; + custom_ie_tlv_head->Tag = MRVL_MGMT_IE_LIST_TLV_ID; + continue; + } + + if ((strcmp(args[0], "FilterMode") == 0) && is_ap_mac_filter) { + if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) || + (atoi(args[1]) > 2)) { + printf + ("ERR:Illegal FilterMode paramter %d. Must be either '0', '1', or '2'.\n", + atoi(args[1])); + goto done; + } + filter_tlv->FilterMode = atoi(args[1]); + continue; + } + if ((strcmp(args[0], "Count") == 0) && is_ap_mac_filter) { + filter_tlv->Count = atoi(args[1]); + if ((ISDIGIT(args[1]) == 0) || + (filter_tlv->Count > MAX_MAC_ONESHOT_FILTER)) { + printf("ERR: Illegal Count parameter.\n"); + goto done; + } + } + if ((strncmp(args[0], "mac_", 4) == 0) && is_ap_mac_filter) { + if (filter_mac_count < MAX_MAC_ONESHOT_FILTER) { + if (mac2raw + (args[1], + &filter_tlv->MacAddress[filter_mac_count * ETH_ALEN]) != + UAP_SUCCESS) { + printf("ERR: Invalid MAC address %s \n", args[1]); + goto done; + } + filter_mac_count++; + } else { + printf + ("ERR: Filter table can not have more than %d MAC addresses\n", + MAX_MAC_ONESHOT_FILTER); + goto done; + } + } + + /* custom ie configuration parameters */ + if ((strncmp(args[0], "MgmtSubtypeMask_", 16) == 0) && + is_custom_ie_config) { + if (UAP_FAILURE == ishexstring(args[1])) { + printf("ERR:Illegal MgmtSubtypeMask %s.\n", args[1]); + goto done; + } + mask_ie_index = (u16) atoi(args[0] + strlen("MgmtSubtypeMask_")); + if (mask_ie_index > 3) { + printf("ERR:Incorrect index %d.\n", mask_ie_index); + goto done; + } + custom_ie_ptr->ie_index = uap_cpu_to_le16(mask_ie_index); + custom_ie_ptr->mgmt_subtype_mask = (u16) A2HEXDECIMAL(args[1]); + custom_ie_ptr->mgmt_subtype_mask = uap_cpu_to_le16 + (custom_ie_ptr->mgmt_subtype_mask); + custom_mask_count++; + continue; + } + if ((strncmp(args[0], "IEBuffer_", 9) == 0) && is_custom_ie_config) { + if (UAP_FAILURE == ishexstring(args[1])) { + printf("ERR:Only hex digits are allowed\n"); + goto done; + } + ie_buf_len = strlen(args[1]); + if (!strncasecmp("0x", args[1], 2)) { + ie_len = (ie_buf_len - 2 + 1) / 2; + args[1] += 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); + goto done; + } + + custom_ie_ptr->ie_index = (u16) atoi(args[0] + strlen("IEBuffer_")); + if (custom_ie_ptr->ie_index != mask_ie_index) { + printf("ERR:IE buffer%d should follow MgmtSubtypeMask%d\n", + mask_ie_index, mask_ie_index); + goto done; + } + custom_ie_ptr->ie_index = uap_cpu_to_le16(custom_ie_ptr->ie_index); + string2raw(args[1], custom_ie_ptr->ie_buffer); + custom_ie_ptr->ie_length = uap_cpu_to_le16(ie_len); + custom_ie_tlv_len += sizeof(custom_ie) + ie_len; + custom_ie_tlv = (tlvbuf_custom_ie *) ((u8 *) custom_ie_tlv + + sizeof(custom_ie) + ie_len); + custom_ie_ptr = (custom_ie *) (custom_ie_tlv->ie_data); + custom_buf_count++; + continue; + } + if (strcmp(args[0], "SSID") == 0) { + if (arg_num == 1) { + printf("ERR:SSID field is blank!\n"); + goto done; + } else { + TLVBUF_SSID *tlv = NULL; + if (args[1][0] == '"') { + args[1]++; + } + if (args[1][strlen(args[1]) - 1] == '"') { + args[1][strlen(args[1]) - 1] = '\0'; + } + if ((strlen(args[1]) > MAX_SSID_LENGTH) || + (strlen(args[1]) == 0)) { + printf("ERR:SSID length out of range (%d to %d).\n", + MIN_SSID_LENGTH, MAX_SSID_LENGTH); + goto done; + } + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_SSID) + strlen(args[1]); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc SSID TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_SSID *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_SSID_TLV_ID; + tlv->Length = strlen(args[1]); + memcpy(tlv->Ssid, args[1], tlv->Length); + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "BeaconPeriod") == 0) { + if (is_input_valid(BEACONPERIOD, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_BEACON_PERIOD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_BEACON_PERIOD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc beacon period TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_BEACON_PERIOD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_BEACON_PERIOD_TLV_ID; + tlv->Length = 2; + tlv->BeaconPeriod_ms = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->BeaconPeriod_ms = uap_cpu_to_le16(tlv->BeaconPeriod_ms); + } + if (strcmp(args[0], "ChanList") == 0) { + if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + + TLVBUF_CHANNEL_LIST *tlv = NULL; + CHANNEL_LIST *pChanList = NULL; + /* Append a new TLV */ + tlv_len = + sizeof(TLVBUF_CHANNEL_LIST) + + ((arg_num - 1) * sizeof(CHANNEL_LIST)); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel list TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CHANNEL_LIST *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_CHANNELLIST_TLV_ID; + tlv->Length = sizeof(CHANNEL_LIST) * (arg_num - 1); + pChanList = (CHANNEL_LIST *) tlv->ChanList; + for (i = 0; i < (arg_num - 1); i++) { + pChanList->ChanNumber = (u8) atoi(args[i + 1]); + pChanList->BandConfigType = 0; + pChanList++; + } + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "Channel") == 0) { + if (is_input_valid(CHANNEL, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_CHANNEL_CONFIG *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_CHANNEL_CONFIG); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_CHANNEL_CONFIG *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_CHANNELCONFIG_TLV_ID; + tlv->Length = 2; + tlv->ChanNumber = (u8) atoi(args[1]); + if ((arg_num - 1) == 2) + tlv->BandConfigType = atoi(args[2]) ? BAND_CONFIG_ACS_MODE : 0; + else + tlv->BandConfigType = 0; + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "AP_MAC") == 0) { + int ret; + TLVBUF_AP_MAC_ADDRESS *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_AP_MAC_ADDRESS); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AP_MAC_ADDRESS *) (buffer + cmd_len); + cmd_len += tlv_len; + cmd_buf->Action = ACTION_SET; + tlv->Tag = MRVL_AP_MAC_ADDRESS_TLV_ID; + tlv->Length = ETH_ALEN; + if ((ret = mac2raw(args[1], tlv->ApMacAddr)) != UAP_SUCCESS) { + printf("ERR: %s Address \n", + ret == UAP_FAILURE ? "Invalid MAC" : ret == + UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); + goto done; + } + endian_convert_tlv_header_out(tlv); + } + + if (strcmp(args[0], "RxAntenna") == 0) { + if ((ISDIGIT(args[1]) != UAP_SUCCESS) || (atoi(args[1]) < 0) || + (atoi(args[1]) > 1)) { + printf("ERR: Invalid Antenna value\n"); + goto done; + } + TLVBUF_ANTENNA_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_ANTENNA_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_ANTENNA_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + cmd_buf->Action = ACTION_SET; + tlv->Tag = MRVL_ANTENNA_CTL_TLV_ID; + tlv->Length = 2; + tlv->WhichAntenna = 0; + tlv->AntennaMode = atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + + if (strcmp(args[0], "TxAntenna") == 0) { + if ((ISDIGIT(args[1]) != UAP_SUCCESS) || (atoi(args[1]) < 0) || + (atoi(args[1]) > 1)) { + printf("ERR: Invalid Antenna value\n"); + goto done; + } + TLVBUF_ANTENNA_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_ANTENNA_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append channel TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_ANTENNA_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + cmd_buf->Action = ACTION_SET; + tlv->Tag = MRVL_ANTENNA_CTL_TLV_ID; + tlv->Length = 2; + tlv->WhichAntenna = 1; + tlv->AntennaMode = atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "Rate") == 0) { + if (is_input_valid(RATE, arg_num - 1, args + 1) != UAP_SUCCESS) { + printf("ERR: Invalid Rate input\n"); + goto done; + } + TLVBUF_RATES *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RATES) + arg_num - 1; + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append rates TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RATES *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RATES_TLV_ID; + tlv->Length = arg_num - 1; + for (i = 0; i < tlv->Length; i++) { + rate[i] = tlv->OperationalRates[i] = + (u8) A2HEXDECIMAL(args[i + 1]); + } + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "TxPowerLevel") == 0) { + if (is_input_valid(TXPOWER, arg_num - 1, args + 1) != UAP_SUCCESS) { + printf("ERR:Invalid TxPowerLevel \n"); + goto done; + } else { + TLVBUF_TX_POWER *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_TX_POWER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append tx power level TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_TX_POWER *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_TX_POWER_TLV_ID; + tlv->Length = 1; + tlv->TxPower_dBm = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "BroadcastSSID") == 0) { + if (is_input_valid(BROADCASTSSID, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_BCAST_SSID_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_BCAST_SSID_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append SSID broadcast control TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_BCAST_SSID_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_BCAST_SSID_CTL_TLV_ID; + tlv->Length = 1; + tlv->BcastSsidCtl = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "RTSThreshold") == 0) { + if (is_input_valid(RTSTHRESH, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_RTS_THRESHOLD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RTS_THRESHOLD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append RTS threshold TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RTS_THRESHOLD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RTS_THRESHOLD_TLV_ID; + tlv->Length = 2; + tlv->RtsThreshold = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->RtsThreshold = uap_cpu_to_le16(tlv->RtsThreshold); + } + if (strcmp(args[0], "FragThreshold") == 0) { + if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_FRAG_THRESHOLD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_FRAG_THRESHOLD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append Fragmentation threshold TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_FRAG_THRESHOLD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_FRAG_THRESHOLD_TLV_ID; + tlv->Length = 2; + tlv->FragThreshold = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->FragThreshold = uap_cpu_to_le16(tlv->FragThreshold); + } + if (strcmp(args[0], "DTIMPeriod") == 0) { + if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_DTIM_PERIOD *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_DTIM_PERIOD); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append DTIM period TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_DTIM_PERIOD *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_DTIM_PERIOD_TLV_ID; + tlv->Length = 1; + tlv->DtimPeriod = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "RadioControl") == 0) { + if (is_input_valid(RADIOCONTROL, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_RADIO_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RADIO_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append radio control TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RADIO_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RADIO_CTL_TLV_ID; + tlv->Length = 1; + tlv->RadioCtl = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "RSNReplayProtection") == 0) { + if (is_input_valid(RSNREPLAYPROT, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + tlvbuf_rsn_replay_prot *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(tlvbuf_rsn_replay_prot); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append RSN replay protection TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (tlvbuf_rsn_replay_prot *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RSN_REPLAY_PROT_TLV_ID; + tlv->Length = 1; + tlv->rsn_replay_prot = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "TxDataRate") == 0) { + if (is_input_valid(TXDATARATE, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + tx_data_rate = (u16) A2HEXDECIMAL(args[1]); + } + if (strcmp(args[0], "MCBCdataRate") == 0) { + if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + mcbc_data_rate = (u16) A2HEXDECIMAL(args[1]); + } + if (strcmp(args[0], "PktFwdCtl") == 0) { + if (is_input_valid(PKTFWD, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_PKT_FWD_CTL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_PKT_FWD_CTL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append packet forwarding control TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_PKT_FWD_CTL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_PKT_FWD_CTL_TLV_ID; + tlv->Length = 1; + tlv->PktFwdCtl = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "StaAgeoutTimer") == 0) { + if (is_input_valid(STAAGEOUTTIMER, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_STA_AGEOUT_TIMER *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_STA_AGEOUT_TIMER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append STA ageout timer TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_STA_AGEOUT_TIMER *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_STA_AGEOUT_TIMER_TLV_ID; + tlv->Length = 4; + tlv->StaAgeoutTimer_ms = (u32) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->StaAgeoutTimer_ms = uap_cpu_to_le32(tlv->StaAgeoutTimer_ms); + } + if (strcmp(args[0], "AuthMode") == 0) { + if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_AUTH_MODE *tlv = NULL; + if ((atoi(args[1]) < 0) || (atoi(args[1]) > 1)) { + printf + ("ERR:Illegal AuthMode parameter. Must be either '0' or '1'.\n"); + goto done; + } + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_AUTH_MODE); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append auth mode TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AUTH_MODE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_AUTH_TLV_ID; + tlv->Length = 1; + tlv->AuthMode = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } + if (strcmp(args[0], "KeyIndex") == 0) { + if (arg_num == 1) { + printf("KeyIndex is blank!\n"); + goto done; + } else { + if (ISDIGIT(args[1]) == 0) { + printf + ("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n"); + goto done; + } + keyindex = atoi(args[1]); + if ((keyindex < 0) || (keyindex > 3)) { + printf + ("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n"); + goto done; + } + } + } + if (strncmp(args[0], "Key_", 4) == 0) { + if (arg_num == 1) { + printf("ERR:%s is blank!\n", args[0]); + goto done; + } else { + TLVBUF_WEP_KEY *tlv = NULL; + int key_len = 0; + if (args[1][0] == '"') { + if ((strlen(args[1]) != 2) && (strlen(args[1]) != 7) && + (strlen(args[1]) != 15)) { + printf("ERR:Wrong key length!\n"); + goto done; + } + key_len = strlen(args[1]) - 2; + } else { + if ((strlen(args[1]) != 0) && (strlen(args[1]) != 10) && + (strlen(args[1]) != 26)) { + printf("ERR:Wrong key length!\n"); + goto done; + } + if (UAP_FAILURE == ishexstring(args[1])) { + printf + ("ERR:Only hex digits are allowed when key length is 10 or 26\n"); + goto done; + } + key_len = strlen(args[1]) / 2; + } + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_WEP_KEY) + key_len; + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append WEP key configurations TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_WEP_KEY *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_WEP_KEY_TLV_ID; + tlv->Length = key_len + 2; + if (strcmp(args[0], "Key_0") == 0) { + tlv->KeyIndex = 0; + } else if (strcmp(args[0], "Key_1") == 0) { + tlv->KeyIndex = 1; + } else if (strcmp(args[0], "Key_2") == 0) { + tlv->KeyIndex = 2; + } else if (strcmp(args[0], "Key_3") == 0) { + tlv->KeyIndex = 3; + } + if (keyindex == tlv->KeyIndex) { + tlv->IsDefault = 1; + } else { + tlv->IsDefault = 0; + } + if (args[1][0] == '"') { + memcpy(tlv->Key, &args[1][1], strlen(args[1]) - 2); + } else { + string2raw(args[1], tlv->Key); + } + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "PSK") == 0) { + if (arg_num == 1) { + printf("ERR:PSK is blank!\n"); + goto done; + } else { + TLVBUF_WPA_PASSPHRASE *tlv = NULL; + if (args[1][0] == '"') { + args[1]++; + } + if (args[1][strlen(args[1]) - 1] == '"') { + args[1][strlen(args[1]) - 1] = '\0'; + } + tlv_len = sizeof(TLVBUF_WPA_PASSPHRASE) + strlen(args[1]); + if (strlen(args[1]) > MAX_WPA_PASSPHRASE_LENGTH) { + printf("ERR:PSK too long.\n"); + goto done; + } + if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) { + printf("ERR:PSK too short.\n"); + goto done; + } + if (strlen(args[1]) == MAX_WPA_PASSPHRASE_LENGTH) { + if (UAP_FAILURE == ishexstring(args[1])) { + printf + ("ERR:Only hex digits are allowed when passphrase's length is 64\n"); + goto done; + } + } + /* Append a new TLV */ + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append WPA passphrase TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_WPA_PASSPHRASE *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_WPA_PASSPHRASE_TLV_ID; + tlv->Length = strlen(args[1]); + memcpy(tlv->Passphrase, args[1], tlv->Length); + endian_convert_tlv_header_out(tlv); + } + } + if (strcmp(args[0], "Protocol") == 0) { + if (is_input_valid(PROTOCOL, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_PROTOCOL *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_PROTOCOL); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append protocol TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_PROTOCOL *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_PROTOCOL_TLV_ID; + tlv->Length = 2; + tlv->Protocol = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->Protocol = uap_cpu_to_le16(tlv->Protocol); + if (atoi(args[1]) & (PROTOCOL_WPA | PROTOCOL_WPA2)) { + TLVBUF_AKMP *tlv = NULL; + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_AKMP); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append AKMP TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_AKMP *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_AKMP_TLV_ID; + tlv->Length = 2; + tlv->KeyMgmt = KEY_MGMT_PSK; + endian_convert_tlv_header_out(tlv); + tlv->KeyMgmt = uap_cpu_to_le16(tlv->KeyMgmt); + } + } + if (strcmp(args[0], "PairwiseCipher") == 0) { + if (arg_num == 1) { + printf("ERR:PairwiseCipher is blank!\n"); + goto done; + } else { + if (ISDIGIT(args[1]) == 0) { + printf + ("ERR:Illegal PairwiseCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + pairwisecipher = atoi(args[1]); + if (pairwisecipher & ~CIPHER_BITMAP) { + printf + ("ERR:Illegal PairwiseCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + } + } + if (strcmp(args[0], "GroupCipher") == 0) { + if (arg_num == 1) { + printf("ERR:GroupCipher is blank!\n"); + goto done; + } else { + if (ISDIGIT(args[1]) == 0) { + printf + ("ERR:Illegal GroupCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + groupcipher = atoi(args[1]); + if (groupcipher & ~CIPHER_BITMAP) { + printf + ("ERR:Illegal GroupCipher parameter. Must be either bit '2' or '3'.\n"); + goto done; + } + } + } + if (strcmp(args[0], "GroupRekeyTime") == 0) { + if (is_input_valid(GROUPREKEYTIMER, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_GROUP_REKEY_TIMER *tlv = NULL; + + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_GROUP_REKEY_TIMER); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot append protocol TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_GROUP_REKEY_TIMER *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_GRP_REKEY_TIME_TLV_ID; + tlv->Length = 4; + tlv->GroupRekeyTime_sec = (u32) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->GroupRekeyTime_sec = uap_cpu_to_le32(tlv->GroupRekeyTime_sec); + } + if (strcmp(args[0], "MaxStaNum") == 0) { + if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) != UAP_SUCCESS) { + goto done; + } + TLVBUF_MAX_STA_NUM *tlv = NULL; + + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_MAX_STA_NUM); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc max station number TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_MAX_STA_NUM *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_MAX_STA_CNT_TLV_ID; + tlv->Length = 2; + tlv->Max_sta_num = (u16) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + tlv->Max_sta_num = uap_cpu_to_le16(tlv->Max_sta_num); + } + if (strcmp(args[0], "Retrylimit") == 0) { + if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) != + UAP_SUCCESS) { + goto done; + } + TLVBUF_RETRY_LIMIT *tlv = NULL; + + /* Append a new TLV */ + tlv_len = sizeof(TLVBUF_RETRY_LIMIT); + buffer = realloc(buffer, cmd_len + tlv_len); + if (!buffer) { + printf("ERR:Cannot realloc retry limit TLV!\n"); + goto done; + } + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buffer; + tlv = (TLVBUF_RETRY_LIMIT *) (buffer + cmd_len); + cmd_len += tlv_len; + /* Set TLV fields */ + tlv->Tag = MRVL_RETRY_LIMIT_TLV_ID; + tlv->Length = 1; + tlv->retry_limit = (u8) atoi(args[1]); + endian_convert_tlv_header_out(tlv); + } +#if DEBUG + if (cmd_len != 0) { + hexdump("Command Buffer", (void *) cmd_buf, cmd_len, ' '); + } +#endif + } + done: + fclose(config_file); + if (buffer) + free(buffer); + if (line) + free(line); +} + +/** + * @brief Show usage information for the cfg_80211d command + * + * $return N/A + */ +void +print_apcmd_cfg_80211d_usage(void) +{ + printf("\nUsage: cfg_80211d <state 0/1> <country Country_code> \n"); + return; +} + +/** + * @brief Show usage information for the uap_stats command + * + * $return N/A + */ +void +print_apcmd_uap_stats(void) +{ + printf("Usage: uap_stats \n"); + return; +} + +/** + * SNMP MIB OIDs Table + */ +static oids_table snmp_oids[] = { + {0x0b, 4, "dot11LocalTKIPMICFailures"}, + {0x0c, 4, "dot11CCMPDecryptErrors"}, + {0x0d, 4, "dot11WEPUndecryptableCount"}, + {0x0e, 4, "dot11WEPICVErrorCount"}, + {0x0f, 4, "dot11DecryptFailureCount"}, + {0x12, 4, "dot11FailedCount"}, + {0x13, 4, "dot11RetryCount"}, + {0x14, 4, "dot11MultipleRetryCount"}, + {0x15, 4, "dot11FrameDuplicateCount"}, + {0x16, 4, "dot11RTSSuccessCount"}, + {0x17, 4, "dot11RTSFailureCount"}, + {0x18, 4, "dot11ACKFailureCount"}, + {0x19, 4, "dot11ReceivedFragmentCount"}, + {0x1a, 4, "dot11MulticastReceivedFrameCount"}, + {0x1b, 4, "dot11FCSErrorCount"}, + {0x1c, 4, "dot11TransmittedFrameCount"}, + {0x1d, 4, "dot11RSNATKIPCounterMeasuresInvoked"}, + {0x1e, 4, "dot11RSNA4WayHandshakeFailures"}, + {0x1f, 4, "dot11MulticastTransmittedFrameCount"} +}; + +/** + * @brief Get uAP stats + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * + * @return NA + */ +void +apcmd_uap_stats(int argc, char *argv[]) +{ + u8 no_of_oids = sizeof(snmp_oids) / sizeof(snmp_oids[0]); + u16 i, j; + int size; + APCMDBUF_SNMP_MIB *cmd_buf = NULL; + u8 *buf = NULL; + TLVBUF_HEADER *tlv = NULL; + u16 cmd_len = 0; + u16 buf_len = 0; + u8 ret; + int opt; + u16 oid_size; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_apcmd_uap_stats(); + return; + } + } + + argc -= optind; + argv += optind; + if (argc) { + printf("Error: Invalid Input\n"); + print_apcmd_uap_stats(); + return; + } + + /** Command Header */ + buf_len += sizeof(APCMDBUF_SNMP_MIB); + + for (i = 0; i < no_of_oids; i++) { + /** + * size of Oid + Oid_value + Oid_size + */ + buf_len += snmp_oids[i].len + sizeof(TLVBUF_HEADER); + } + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate Headers */ + cmd_buf = (APCMDBUF_SNMP_MIB *) buf; + cmd_buf->Size = buf_len - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->CmdCode = HostCmd_SNMP_MIB; + cmd_buf->Action = uap_cpu_to_le16(ACTION_GET); + + tlv = (TLVBUF_HEADER *) ((u8 *) cmd_buf + sizeof(APCMDBUF_SNMP_MIB)); + /* Add oid, oid_size and oid_value for each OID */ + for (i = 0; i < no_of_oids; i++) { + /** Copy Index as Oid */ + tlv->Type = uap_cpu_to_le16(snmp_oids[i].type); + /** Copy its size */ + tlv->Len = uap_cpu_to_le16(snmp_oids[i].len); + /** Next TLV */ + tlv = (TLVBUF_HEADER *) & (tlv->Data[snmp_oids[i].len]); + } + cmd_len = buf_len; + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + tlv = + (TLVBUF_HEADER *) ((u8 *) cmd_buf + sizeof(APCMDBUF_SNMP_MIB)); + + size = + cmd_buf->Size - (sizeof(APCMDBUF_SNMP_MIB) - BUF_HEADER_SIZE); + + while (size >= sizeof(TLVBUF_HEADER)) { + tlv->Type = uap_le16_to_cpu(tlv->Type); + for (i = 0; i < no_of_oids; i++) { + if (snmp_oids[i].type == tlv->Type) { + printf("%s: ", snmp_oids[i].name); + break; + } + } + oid_size = uap_le16_to_cpu(tlv->Len); + switch (oid_size) { + case 1: + printf("%d", (unsigned int) tlv->Data[0]); + break; + case 2: + printf("%d", + (unsigned int) uap_le16_to_cpu(*(u16 *) tlv->Data)); + break; + case 4: + printf("%ld", + (unsigned long) uap_le32_to_cpu(*(u32 *) tlv->Data)); + break; + default: + for (j = 0; j < oid_size; j++) { + printf("%d ", (u8) tlv->Data[i]); + } + break; + } + /** Next TLV */ + tlv = (TLVBUF_HEADER *) & (tlv->Data[oid_size]); + size -= (sizeof(TLVBUF_HEADER) + oid_size); + size = (size > 0) ? size : 0; + printf("\n"); + } + + } else { + printf("ERR:Command Response incorrect!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); +} + +/** + * @brief parser for sys_cfg_80211d input + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @param output stores indexes for "state, country" + * arguments + * + * @return NA + * + */ +void +parse_input_80211d(int argc, char **argv, int output[2][2]) +{ + int i, j, k = 0; + char *keywords[2] = { "state", "country" }; + + for (i = 0; i < 2; i++) + output[i][0] = -1; + + for (i = 0; i < argc; i++) { + for (j = 0; j < 2; j++) { + if (strcmp(argv[i], keywords[j]) == 0) { + output[j][1] = output[j][0] = i; + k = j; + break; + } + } + output[k][1] += 1; + } +} + +/** + * @brief Set/Get 802.11D country information + * + * Usage: cfg_80211d state country_code + * + * State 0 or 1 + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_cfg_80211d(int argc, char *argv[]) +{ + APCMDBUF_CFG_80211D *cmd_buf = NULL; + IEEEtypes_SubbandSet_t *subband = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int output[2][2]; + int ret = UAP_FAILURE; + int opt; + int i, j; + u8 state = 0; + char country[4] = { ' ', ' ', 0, 0 }; + u8 sflag = 0, cflag = 0; + IEEEtypes_SubbandSet_t sub_bands[MAX_SUB_BANDS]; + u8 no_of_sub_band = 0; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_apcmd_cfg_80211d_usage(); + return; + } + } + argc -= optind; + argv += optind; + + if (argc) { + /** SET */ + parse_input_80211d(argc, argv, output); + + /** state */ + if ((output[0][0] != -1) && (output[0][1] > output[0][0])) { + if ((output[0][1] - output[0][0]) != 2) { + printf("ERR: Invalid state inputs\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + + if (IS_HEX_OR_DIGIT(argv[output[0][0] + 1]) == UAP_FAILURE) { + printf("ERR: valid input for state are 0 or 1\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + state = (u8) A2HEXDECIMAL(argv[output[0][0] + 1]); + + if ((state != 0) && (state != 1)) { + printf("ERR: valid input for state are 0 or 1 \n"); + print_apcmd_cfg_80211d_usage(); + return; + } + sflag = 1; + } + + /** country */ + if ((output[1][0] != -1) && (output[1][1] > output[1][0])) { + if ((output[1][1] - output[1][0]) > 2) { + printf("ERR: Invalid country inputs\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + if ((strlen(argv[output[1][0] + 1]) > 3) || + (strlen(argv[output[1][0] + 1]) < 0)) { + print_apcmd_cfg_80211d_usage(); + return; + } + + strcpy(country, argv[output[1][0] + 1]); + + for (i = 0; i < strlen(country); i++) { + if ((country[i] < 'A') || (country[i] > 'z')) { + printf("Invalid Country Code\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + if (country[i] > 'Z') + country[i] = country[i] - 'a' + 'A'; + } + + cflag = 1; + + /** Get domain information from the file */ + no_of_sub_band = parse_domain_file(country, sub_bands); + if (no_of_sub_band == UAP_FAILURE) { + printf("Parsing Failed\n"); + return; + } + } + } + + if (argc && !cflag && !sflag) { + printf("ERR: Invalid input\n"); + print_apcmd_cfg_80211d_usage(); + return; + } + + if (sflag && !cflag) { + /** + * Update MIB only and return + */ + if (sg_snmp_mib(ACTION_SET, OID_80211D_ENABLE, sizeof(state), &state) == + UAP_SUCCESS) { + printf("802.11d %sd \n", state ? "enable" : "disable"); + } + return; + } + + buf_len = sizeof(APCMDBUF_CFG_80211D); + + if (cflag) { + buf_len += no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t); + } else { /** Get */ + buf_len += MAX_SUB_BANDS * sizeof(IEEEtypes_SubbandSet_t); + } + + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + /* Locate headers */ + cmd_buf = (APCMDBUF_CFG_80211D *) buf; + cmd_len = argc ? buf_len : + /** set */ + (sizeof(APCMDBUF_CFG_80211D) - sizeof(domain_param_t)); /** Get */ + + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->Action = argc ? ACTION_SET : ACTION_GET; + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->CmdCode = HostCmd_CMD_802_11D_DOMAIN_INFO; + + if (cflag) { + cmd_buf->Domain.Tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN); + cmd_buf->Domain.Length = uap_cpu_to_le16(sizeof(domain_param_t) + - BUF_HEADER_SIZE + + + (no_of_sub_band * + sizeof + (IEEEtypes_SubbandSet_t))); + + memset(cmd_buf->Domain.CountryCode, ' ', + sizeof(cmd_buf->Domain.CountryCode)); + memcpy(cmd_buf->Domain.CountryCode, country, strlen(country)); + memcpy(cmd_buf->Domain.Subband, sub_bands, + no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t)); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + if (argc) { + printf("Set executed successfully\n"); + if (sflag) { + if (sg_snmp_mib + (ACTION_SET, OID_80211D_ENABLE, sizeof(state), + &state) == UAP_SUCCESS) { + printf("802.11d %sd \n", state ? "enable" : "disable"); + } + } + } else { + j = uap_le16_to_cpu(cmd_buf->Domain.Length); + if (sg_snmp_mib + (ACTION_GET, OID_80211D_ENABLE, sizeof(state), &state) + == UAP_SUCCESS) { + printf("State = %sd\n", state ? "enable" : "disable"); + } + + if (!(cmd_buf->Domain.CountryCode[0] | + cmd_buf->Domain.CountryCode[1] | + cmd_buf->Domain.CountryCode[2])) { + printf("Dot11d = country code is not set.\n"); + } else { + printf("Country string = %c%c%c", + cmd_buf->Domain.CountryCode[0], + cmd_buf->Domain.CountryCode[1], + cmd_buf->Domain.CountryCode[2]); + j -= sizeof(cmd_buf->Domain.CountryCode); + subband = + (IEEEtypes_SubbandSet_t *) cmd_buf->Domain.Subband; + printf("\nSub-band info="); + // printf("\n\t\t(First Channel, Number of Channels, + // Maximum TX Power) \n"); + printf("\t(1st, #chan, MAX-power) \n"); + for (i = 0; i < (j / 3); i++) { + printf("\t\t(%d, \t%d, \t%d dbm)\n", subband->FirstChan, + subband->NoOfChan, subband->MaxTxPwr); + subband++; + } + } + } + } else { + printf("ERR:Command Response incorrect!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + return; +} + +/** + * @brief Creates a sys_config request and sends to the driver + * + * Usage: "Usage : sys_config [CONFIG_FILE]" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +void +apcmd_sys_config(int argc, char *argv[]) +{ + APCMDBUF_SYS_CONFIGURE *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + int opt; + char **argv_dummy; + ps_mgmt pm; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_config_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (argc > 1) { + printf("ERR:Too many arguments.\n"); + print_sys_config_usage(); + return; + } + if (argc == 1) { + /* Read profile and send command to firmware */ + apcmd_sys_config_profile(argc, argv); + return; + } + + /** Query AP's setting */ + buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_SYS_CONFIGURE); + cmd_buf = (APCMDBUF_SYS_CONFIGURE *) buf; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_CONFIGURE; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response!\n"); + free(buf); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + printf("AP settings:\n"); + print_tlv(buf + sizeof(APCMDBUF_SYS_CONFIGURE), + cmd_buf->Size - sizeof(APCMDBUF_SYS_CONFIGURE) + + BUF_HEADER_SIZE); + printf("\n802.11D setting:\n"); + apcmd_cfg_80211d(1, argv_dummy); + } else { + printf("ERR:Could not retrieve system configure\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + free(buf); + memset(&pm, 0, sizeof(ps_mgmt)); + send_power_mode_ioctl(&pm); + return; +} + +/** + * @brief Send read/write command along with register details to the driver + * @param reg reg type + * @param offset pointer to register offset string + * @param strvalue pointer to value string + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +apcmd_regrdwr_process(int reg, s8 * offset, s8 * strvalue) +{ + APCMDBUF_REG_RDWR *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + s8 *whichreg; + + buf_len = sizeof(APCMDBUF_REG_RDWR); + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return UAP_FAILURE; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_REG_RDWR); + cmd_buf = (APCMDBUF_REG_RDWR *) buf; + + /* Fill the command buffer */ + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + + switch (reg) { + case CMD_MAC: + whichreg = "MAC"; + cmd_buf->CmdCode = HostCmd_CMD_MAC_REG_ACCESS; + break; + case CMD_BBP: + whichreg = "BBP"; + cmd_buf->CmdCode = HostCmd_CMD_BBP_REG_ACCESS; + break; + case CMD_RF: + cmd_buf->CmdCode = HostCmd_CMD_RF_REG_ACCESS; + whichreg = "RF"; + break; + default: + printf("Invalid register set specified.\n"); + free(buf); + return UAP_FAILURE; + } + if (strvalue) { + cmd_buf->Action = 1; // WRITE + } else { + cmd_buf->Action = 0; // READ + } + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->Offset = A2HEXDECIMAL(offset); + cmd_buf->Offset = uap_cpu_to_le16(cmd_buf->Offset); + if (strvalue) { + cmd_buf->Value = A2HEXDECIMAL(strvalue); + cmd_buf->Value = uap_cpu_to_le32(cmd_buf->Value); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Successfully executed the command\n"); + printf("%s[0x%04hx] = 0x%08lx\n", + whichreg, uap_le16_to_cpu(cmd_buf->Offset), + uap_le32_to_cpu(cmd_buf->Value)); + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return UAP_FAILURE; + } + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return UAP_FAILURE; + } + + free(buf); + return UAP_SUCCESS; +} + +/** + * @brief Send read command for EEPROM + * + * Usage: "Usage : rdeeprom <offset> <byteCount>" + * + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_read_eeprom(int argc, char *argv[]) +{ + APCMDBUF_EEPROM_ACCESS *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + u16 byteCount, offset; + int ret = UAP_FAILURE; + int opt; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_apcmd_read_eeprom_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if (!argc || (argc && is_input_valid(RDEEPROM, argc, argv) != UAP_SUCCESS)) { + print_apcmd_read_eeprom_usage(); + return; + } + offset = A2HEXDECIMAL(argv[0]); + byteCount = A2HEXDECIMAL(argv[1]); + + buf_len = sizeof(APCMDBUF_EEPROM_ACCESS) + MAX_EEPROM_LEN; + buf = (u8 *) malloc(buf_len); + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_EEPROM_ACCESS *) buf; + cmd_len = sizeof(APCMDBUF_EEPROM_ACCESS); + + cmd_buf->Size = sizeof(APCMDBUF_EEPROM_ACCESS) - BUF_HEADER_SIZE; + cmd_buf->Result = 0; + cmd_buf->SeqNum = 0; + cmd_buf->Action = 0; + + cmd_buf->CmdCode = HostCmd_EEPROM_ACCESS; + cmd_buf->Offset = uap_cpu_to_le16(offset); + cmd_buf->ByteCount = uap_cpu_to_le16(byteCount); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Successfully executed the command\n"); + byteCount = uap_le16_to_cpu(cmd_buf->ByteCount); + offset = uap_le16_to_cpu(cmd_buf->Offset); + hexdump_data("EEPROM", (void *) cmd_buf->Value, byteCount, ' '); + } else { + printf("ERR:Command Response incorrect!\n"); + } + } else { + printf("ERR:Command sending failed!\n"); + } + + free(buf); + return; +} + +/** + * @brief Show usage information for the regrdwr command + * command + * + * $return N/A + */ +void +print_regrdwr_usage(void) +{ + printf("\nUsage : uaputl.exe regrdwr <TYPE> <OFFSET> [value]\n"); + printf("\nTYPE Options: 0 - read/write MAC register"); + printf("\n 1 - read/write BBP register"); + printf("\n 2 - read/write RF register"); + printf("\n"); + return; + +} + +/** + * @brief Provides interface to perform read/write operations on regsiters + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_regrdwr(int argc, char *argv[]) +{ + int opt; + s32 reg; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_regrdwr_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if ((argc < 2) || (argc > 3)) { + printf("ERR:wrong arguments.\n"); + print_regrdwr_usage(); + return; + } + if ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1) && (atoi(argv[0]) != 2)) { + printf("ERR:Illegal register type %s. Must be either '0','1' or '2'.\n", + argv[0]); + print_regrdwr_usage(); + return; + } + reg = atoi(argv[0]); + apcmd_regrdwr_process(reg, argv[1], argc > 2 ? argv[2] : NULL); + return; +} + +/** + * @brief Show usage information for the memaccess command + * command + * + * $return N/A + */ +void +print_memaccess_usage(void) +{ + printf("\nUsage : uaputl.exe memaccess <ADDRESS> [value]\n"); + printf("\nRead/Write memory location"); + printf("\nADDRESS: Address of the memory location to be read/written"); + printf("\nValue : Value to be written at that address\n"); + return; +} + +/** + * @brief Provides interface to perform read/write memory location + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_memaccess(int argc, char *argv[]) +{ + int opt; + APCMDBUF_MEM_ACCESS *cmd_buf = NULL; + u8 *buf = NULL; + u16 cmd_len; + u16 buf_len; + int ret = UAP_FAILURE; + s8 *address = NULL; + s8 *value = NULL; + + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_memaccess_usage(); + return; + } + } + argc -= optind; + argv += optind; + + /* Check arguments */ + if ((argc < 1) || (argc > 2)) { + printf("ERR:wrong arguments.\n"); + print_memaccess_usage(); + return; + } + + address = argv[0]; + if (argc == 2) + value = argv[1]; + + buf_len = sizeof(APCMDBUF_MEM_ACCESS); + + /* alloc buf for command */ + buf = (u8 *) malloc(buf_len); + + if (!buf) { + printf("ERR:Cannot allocate buffer from command!\n"); + return; + } + bzero((char *) buf, buf_len); + /* Locate headers */ + cmd_len = sizeof(APCMDBUF_MEM_ACCESS); + cmd_buf = (APCMDBUF_MEM_ACCESS *) buf; + + /* Fill the command buffer */ + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->CmdCode = HostCmd_CMD_MEM_ACCESS; + + if (value) + cmd_buf->Action = 1; // WRITE + else + cmd_buf->Action = 0; // READ + + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->Address = A2HEXDECIMAL(address); + cmd_buf->Address = uap_cpu_to_le32(cmd_buf->Address); + + if (value) { + cmd_buf->Value = A2HEXDECIMAL(value); + cmd_buf->Value = uap_cpu_to_le32(cmd_buf->Value); + } + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + if (cmd_buf->Result == CMD_SUCCESS) { + printf("Successfully executed the command\n"); + printf("[0x%04lx] = 0x%08lx\n", + uap_le32_to_cpu(cmd_buf->Address), + uap_le32_to_cpu(cmd_buf->Value)); + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return; + } + } else { + printf("ERR:Command sending failed!\n"); + free(buf); + return; + } + free(buf); + return; +} + +/** + * @brief Show usage information for sys_debug command + * command + * + * $return N/A + */ +void +print_sys_debug_usage(void) +{ + printf("\nUsage : uaputl.exe sys_debug <subcmd> [parameter]\n"); + printf("\nSet/Get debug parameter"); + printf("\nsubcmd: used to set/get debug parameters or set user scan"); + printf("\nparameter : parameters for specific subcmd"); + printf("\n If no [parameter] are given, it return"); + printf("\n debug parameters for selected subcmd"); + printf("\n\n"); + return; +} + +/** + * @brief Creates a sys_debug request and sends to the driver + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return N/A + */ +void +apcmd_sys_debug(int argc, char *argv[]) +{ + APCMDBUF_SYS_DEBUG *cmd_buf = NULL; + u8 *buffer = NULL; + u16 cmd_len; + u16 buf_len; + u32 subcmd = 0; + int ret = UAP_FAILURE; + int opt; + s8 *value = NULL; + u32 parameter = 0; + while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { + switch (opt) { + default: + print_sys_debug_usage(); + return; + } + } + argc -= optind; + argv += optind; + /* Check arguments */ + if ((argc == 0) || (argc > 2)) { + printf("ERR:wrong arguments.\n"); + print_sys_debug_usage(); + return; + } else { + if (argc == 2) { + value = argv[1]; + parameter = A2HEXDECIMAL(value); + } + } + subcmd = atoi(argv[0]); + /* Initialize the command length */ + if (subcmd == DEBUG_SUBCOMMAND_CHANNEL_SCAN) { + buf_len = + sizeof(APCMDBUF_SYS_DEBUG) + + MAX_CHANNELS * sizeof(CHANNEL_SCAN_ENTRY_T); + cmd_len = sizeof(APCMDBUF_SYS_DEBUG) - sizeof(debugConfig_t); + } else { + cmd_len = sizeof(APCMDBUF_SYS_DEBUG); + buf_len = cmd_len; + } + + /* Initialize the command buffer */ + buffer = (u8 *) malloc(buf_len); + if (!buffer) { + printf("ERR:Cannot allocate buffer for command!\n"); + return; + } + bzero((char *) buffer, buf_len); + + /* Locate headers */ + cmd_buf = (APCMDBUF_SYS_DEBUG *) buffer; + + /* Fill the command buffer */ + cmd_buf->CmdCode = APCMD_SYS_DEBUG; + cmd_buf->Size = cmd_len - BUF_HEADER_SIZE; + cmd_buf->SeqNum = 0; + cmd_buf->Result = 0; + cmd_buf->subcmd = subcmd; + if (subcmd == DEBUG_SUBCOMMAND_CHANNEL_SCAN) { + cmd_buf->Action = ACTION_SET; + } else { + if (argc == 1) { + cmd_buf->Action = ACTION_GET; + } else { + cmd_buf->Action = ACTION_SET; + if (subcmd == DEBUG_SUBCOMMAND_GMODE) + cmd_buf->debugConfig.globalDebugMode = (u8) parameter; + else if (subcmd == DEBUG_SUBCOMMAND_MAJOREVTMASK) { + cmd_buf->debugConfig.debugMajorIdMask = parameter; + cmd_buf->debugConfig.debugMajorIdMask = + uap_cpu_to_le32(cmd_buf->debugConfig.debugMajorIdMask); + } else { + cmd_buf->debugConfig.value = uap_cpu_to_le32(parameter); + } + } + } + cmd_buf->Action = uap_cpu_to_le16(cmd_buf->Action); + cmd_buf->subcmd = uap_cpu_to_le32(cmd_buf->subcmd); + + /* Send the command */ + ret = uap_ioctl((u8 *) cmd_buf, &cmd_len, buf_len); + + /* Process response */ + if (ret == UAP_SUCCESS) { + /* Verify response */ + if (cmd_buf->CmdCode != (APCMD_SYS_DEBUG | APCMD_RESP_CHECK)) { + printf("ERR:Corrupted response! CmdCode=%x\n", cmd_buf->CmdCode); + free(buffer); + return; + } + /* Print response */ + if (cmd_buf->Result == CMD_SUCCESS) { + if (subcmd == DEBUG_SUBCOMMAND_CHANNEL_SCAN) { + int i = 0; + CHANNEL_SCAN_ENTRY_T *cst = NULL; + if (cmd_buf->Size < + (sizeof(APCMDBUF_SYS_DEBUG) - BUF_HEADER_SIZE)) { + printf + ("ERR: Invalid command response size, cmd_buf->Size = %x\n", + cmd_buf->Size); + free(buffer); + return; + } + for (i = 0; i < cmd_buf->debugConfig.cs_entry.numChannels; i++) { + if (i == 0) { + printf + ("\n------------------------------------------------------"); + printf("\nChan\tNumAPs\tCCA_Count\tDuration\tWeight"); + printf + ("\n------------------------------------------------------"); + cst = cmd_buf->debugConfig.cs_entry.cst; + } + printf("\n%d\t%d\t%ld\t\t%ld\t\t%ld", cst->chan_num, + cst->num_of_aps, + cst->CCA_count, cst->duration, cst->channel_weight); + cst++; + } + printf + ("\n------------------------------------------------------\n"); + } else { + if (argc == 1) { + if (subcmd == DEBUG_SUBCOMMAND_GMODE) { + printf("globalDebugmode=%d\n", + cmd_buf->debugConfig.globalDebugMode); + } else if (subcmd == DEBUG_SUBCOMMAND_MAJOREVTMASK) { + printf("MajorId mask=0x%08lx\n", + uap_le32_to_cpu(cmd_buf->debugConfig. + debugMajorIdMask)); + } else { + printf("Value = %ld\n", + uap_le32_to_cpu(cmd_buf->debugConfig.value)); + } + } else { + printf("set debug parameter successful\n"); + } + } + } else { + if (argc == 1) { + printf("ERR:Could not get debug parameter!\n"); + } else { + printf("ERR:Could not set debug parameter!\n"); + } + } + } else { + printf("ERR:Command sending failed!\n"); + } + if (buffer) + free(buffer); + return; +} + +/** structure of command table*/ +typedef struct +{ + /** command name */ + char *cmd; + /** command function pointer */ + void (*func) (int argc, char *argv[]); + /**command usuage */ + char *help; +} command_table; + +/** ap command table */ +static command_table ap_command[] = { + {"sys_config", apcmd_sys_config, "\tSet/get uAP's profile"}, + {"sys_info", apcmd_sys_info, "\tDisplay system info"}, + {"sys_reset", apcmd_sys_reset, "\tReset uAP"}, + {"bss_start", apcmd_bss_start, "\tStart the BSS"}, + {"bss_stop", apcmd_bss_stop, "\tStop the BSS"}, + {"sta_deauth", apcmd_sta_deauth, "\tDeauth client"}, + {"sta_list", apcmd_sta_list, "\tDisplay list of clients"}, + {"sys_cfg_ap_mac_address", apcmd_sys_cfg_ap_mac_address, + "Set/get uAP mac address"}, + {"sys_cfg_ssid", apcmd_sys_cfg_ssid, "\tSet/get uAP ssid"}, + {"sys_cfg_beacon_period", apcmd_sys_cfg_beacon_period, + "Set/get uAP beacon period"}, + {"sys_cfg_dtim_period", apcmd_sys_cfg_dtim_period, + "Set/get uAP dtim period"}, + {"sys_cfg_channel", apcmd_sys_cfg_channel, "\tSet/get uAP radio channel"}, + {"sys_cfg_scan_channels", apcmd_sys_cfg_scan_channels, + "Set/get uAP radio channel list"}, + {"sys_cfg_rates", apcmd_sys_cfg_rates, "\tSet/get uAP rates"}, + {"sys_cfg_rates_ext", apcmd_sys_cfg_rates_ext, + "Set/get uAP rates (extended)"}, + {"sys_cfg_tx_power", apcmd_sys_cfg_tx_power, "Set/get uAP tx power"}, + {"sys_cfg_bcast_ssid_ctl", apcmd_sys_cfg_bcast_ssid_ctl, + "Set/get uAP broadcast ssid"}, + {"sys_cfg_preamble_ctl", apcmd_sys_cfg_preamble_ctl, "Get uAP preamble"}, + {"sys_cfg_antenna_ctl", apcmd_sys_cfg_antenna_ctl, + "Set/get uAP tx/rx antenna"}, + {"sys_cfg_rts_threshold", apcmd_sys_cfg_rts_threshold, + "Set/get uAP rts threshold"}, + {"sys_cfg_frag_threshold", apcmd_sys_cfg_frag_threshold, + "Set/get uAP frag threshold"}, + {"sys_cfg_radio_ctl", apcmd_sys_cfg_radio_ctl, "Set/get uAP radio on/off"}, + {"sys_cfg_tx_data_rate", apcmd_sys_cfg_tx_data_rate, "Set/get uAP tx rate"}, + {"sys_cfg_mcbc_data_rate", apcmd_sys_cfg_mcbc_data_rate, + "Set/get uAP MCBC rate"}, + {"sys_cfg_rsn_replay_prot", apcmd_sys_cfg_rsn_replay_prot, + "Set/get RSN replay protection"}, + {"sys_cfg_pkt_fwd_ctl", apcmd_sys_cfg_pkt_fwd_ctl, + "Set/get uAP packet forwarding"}, + {"sys_cfg_sta_ageout_timer", apcmd_sys_cfg_sta_ageout_timer, + "Set/get station ageout timer"}, + {"sys_cfg_auth", apcmd_sys_cfg_auth, "\tSet/get uAP authentication mode"}, + {"sys_cfg_protocol", apcmd_sys_cfg_protocol, + "Set/get uAP security protocol"}, + {"sys_cfg_wep_key", apcmd_sys_cfg_wep_key, "\tSet/get uAP wep key"}, + {"sys_cfg_cipher", apcmd_sys_cfg_cipher, "\tSet/get uAP WPA/WPA cipher"}, + {"sys_cfg_wpa_passphrase", apcmd_sys_cfg_wpa_passphrase, + "Set/get uAP WPA or WPA2 passphrase"}, + {"sys_cfg_group_rekey_timer", apcmd_sys_cfg_group_rekey_timer, + "Set/get uAP group re-key time"}, + {"sys_cfg_max_sta_num", apcmd_sys_cfg_max_sta_num, + "Set/get uAP max station number"}, + {"sys_cfg_retry_limit", apcmd_sys_cfg_retry_limit, + "Set/get uAP retry limit number"}, + {"sys_cfg_custom_ie", apcmd_sys_cfg_custom_ie, + "\tSet/get custom IE configuration"}, + {"sta_filter_table", apcmd_sta_filter_table, "Set/get uAP mac filter"}, + {"regrdwr", apcmd_regrdwr, "\t\tRead/Write register command"}, + {"memaccess", apcmd_memaccess, "\tRead/Write to a memory address command"}, + {"rdeeprom", apcmd_read_eeprom, "\tRead EEPROM "}, + {"cfg_data", apcmd_cfg_data, + "\tGet/Set configuration file from/to firmware"}, + {"sys_debug", apcmd_sys_debug, "\tSet/Get debug parameter"}, + {"sys_cfg_80211d", apcmd_cfg_80211d, "\tSet/Get 802.11D info"}, + {"uap_stats", apcmd_uap_stats, "\tGet uAP stats"}, + {"powermode", apcmd_power_mode, "\tSet/get uAP power mode"}, + {"coex_config", apcmd_coex_config, "\tSet/get uAP BT coex configuration"}, + {NULL, NULL, 0} +}; + +/** + * @brief Prints usage information of uaputl + * + * @return N/A + */ +static void +print_tool_usage(void) +{ + int i; + printf("uaputl.exe - uAP utility ver %s\n", UAP_VERSION); + printf("Usage:\n" + "\tuaputl.exe [options] <command> [command parameters]\n"); + printf("Options:\n" + "\t--help\tDisplay help\n" + "\t-v\tDisplay version\n" + "\t-i <interface>\n" "\t-d <debug_level=0|1|2>\n"); + printf("Commands:\n"); + for (i = 0; ap_command[i].cmd; i++) + printf("\t%-4s\t\t%s\n", ap_command[i].cmd, ap_command[i].help); + printf("\n" + "For more information on the usage of each command use:\n" + "\tuaputl.exe <command> --help\n"); +} + +/**************************************************************************** + Global functions +****************************************************************************/ +/** option parameter*/ +static struct option ap_options[] = { + {"help", 0, NULL, 'h'}, + {"interface", 1, NULL, 'i'}, + {"debug", 1, NULL, 'd'}, + {"version", 0, NULL, 'v'}, + {NULL, 0, NULL, '\0'} +}; + +/** + * @brief isdigit for String. + * + * @param x char string + * @return UAP_FAILURE for non-digit. + * UAP_SUCCESS for digit + */ +inline int +ISDIGIT(char *x) +{ + int i; + for (i = 0; i < strlen(x); i++) + if (isdigit(x[i]) == 0) + return UAP_FAILURE; + return UAP_SUCCESS; +} + +/** + * @brief Checkes a particular input for validatation. + * + * @param cmd Type of input + * @param argc Number of arguments + * @param argv Pointer to the arguments + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_input_valid(valid_inputs cmd, int argc, char *argv[]) +{ + int i; + int ret = UAP_SUCCESS; + if (argc == 0) + return UAP_FAILURE; + switch (cmd) { + case RDEEPROM: + if (argc != 2) { + printf(" ERR: Argument count mismatch\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0) || + (A2HEXDECIMAL(argv[0]) & 0x03) || + (A2HEXDECIMAL(argv[0]) < 0) || + (A2HEXDECIMAL(argv[1]) & 0x03) || + (A2HEXDECIMAL(argv[1]) < 4) || (A2HEXDECIMAL(argv[1]) > 20)) { + printf(" ERR: Invalid inputs for Read EEPROM\n"); + ret = UAP_FAILURE; + } + } + break; + case SCANCHANNELS: + if (argc > MAX_CHANNELS) { + printf("ERR: Invalid List of Channels\n"); + ret = UAP_FAILURE; + } else { + for (i = 0; i < argc; i++) { + if ((ISDIGIT(argv[i]) == 0) || (atoi(argv[i]) < 1) || + (atoi(argv[i]) > MAX_CHANNELS)) { + printf("ERR: Channel must be in the range of 1 to %d\n", + MAX_CHANNELS); + ret = UAP_FAILURE; + break; + } + } + if ((ret != UAP_FAILURE) && + (has_dup_channel(argc, argv) != UAP_SUCCESS)) { + printf("ERR: Duplicate channel values entered\n"); + ret = UAP_FAILURE; + } + } + break; + case TXPOWER: + if ((argc > 1) || (ISDIGIT(argv[0]) == 0)) { + printf("ERR:Invalid Transmit power\n"); + ret = UAP_FAILURE; + } else { + if ((atoi(argv[0]) < MIN_TX_POWER) || + (atoi(argv[0]) > MAX_TX_POWER)) { + printf("ERR: TX Powar must be in the rage of %d to %d. \n", + MIN_TX_POWER, MAX_TX_POWER); + ret = UAP_FAILURE; + } + } + break; + case PROTOCOL: + if ((argc > 1) || (ISDIGIT(argv[0]) == 0)) { + printf("ERR:Invalid Protocol\n"); + ret = UAP_FAILURE; + } else + ret = is_protocol_valid(atoi(argv[0])); + break; + case CHANNEL: + if ((argc != 1) && (argc != 2)) { + printf("ERR: Incorrect arguments for channel.\n"); + ret = UAP_FAILURE; + } else { + if (argc == 2) { + if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) || + (atoi(argv[1]) > 1)) { + printf("ERR: MODE must be either 0 or 1\n"); + ret = UAP_FAILURE; + } + if ((atoi(argv[1]) == 1) && (atoi(argv[0]) != 0)) { + printf("ERR: Channel must be 0 for ACS; MODE = 1.\n"); + ret = UAP_FAILURE; + } + } + if ((argc == 1) || (atoi(argv[1]) == 0)) { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) || + (atoi(argv[0]) > MAX_CHANNELS)) { + printf("ERR: Channel must be in the range of 1 to %d\n", + MAX_CHANNELS); + ret = UAP_FAILURE; + } + } + } + break; + case RATE: + if (argc > MAX_RATES) { + printf("ERR: Incorrect number of RATES arguments.\n"); + ret = UAP_FAILURE; + } else { + for (i = 0; i < argc; i++) { + if ((IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) || + (is_rate_valid(A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT) + != UAP_SUCCESS)) { + printf("ERR:Unsupported rate.\n"); + ret = UAP_FAILURE; + break; + } + } + if ((ret != UAP_FAILURE) && + (has_dup_rate(argc, argv) != UAP_SUCCESS)) { + printf("ERR: Duplicate rate values entered\n"); + ret = UAP_FAILURE; + } + if (check_mandatory_rates(argc, argv) != UAP_SUCCESS) { + ret = UAP_FAILURE; + } + } + break; + case BROADCASTSSID: + if (argc != 1) { + printf("ERR:wrong BROADCASTSSID arguments.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || + ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1))) { + printf + ("ERR:Illegal parameter %s for BROADCASTSSID. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case RTSTHRESH: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for RTSTHRESHOLD\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > MAX_RTS_THRESHOLD)) { + printf + ("ERR:Illegal RTSTHRESHOLD %s. The value must between 0 and %d\n", + argv[0], MAX_RTS_THRESHOLD); + ret = UAP_FAILURE; + } + break; + case FRAGTHRESH: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for FRAGTHRESH\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || + (atoi(argv[0]) < MIN_FRAG_THRESHOLD) || + (atoi(argv[0]) > MAX_FRAG_THRESHOLD)) { + printf + ("ERR:Illegal FRAGTHRESH %s. The value must between %d and %d\n", + argv[0], MIN_FRAG_THRESHOLD, MAX_FRAG_THRESHOLD); + ret = UAP_FAILURE; + } + break; + case DTIMPERIOD: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for DTIMPERIOD\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) || + (atoi(argv[0]) > MAX_DTIM_PERIOD)) { + printf("ERR: DTIMPERIOD Value must be in range of 1 to %d\n", + MAX_DTIM_PERIOD); + ret = UAP_FAILURE; + } + break; + case RADIOCONTROL: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for RADIOCONTROL\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf + ("ERR:Illegal RADIOCONTROL parameter %s. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case RSNREPLAYPROT: + if (argc != 1) { + printf("ERR:wrong RSNREPLAYPROT arguments.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || + ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1))) { + printf + ("ERR:Illegal parameter %s for RSNREPLAYPROT. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case MCBCDATARATE: + case TXDATARATE: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for DATARATE\n"); + ret = UAP_FAILURE; + } else { + if (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) { + printf("ERR: invalid data rate\n"); + ret = UAP_FAILURE; + } else if ((A2HEXDECIMAL(argv[0]) != 0) && + (is_rate_valid + (A2HEXDECIMAL(argv[0]) & ~BASIC_RATE_SET_BIT) != + UAP_SUCCESS)) { + printf("ERR: invalid data rate\n"); + ret = UAP_FAILURE; + } + } + break; + case PKTFWD: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for PKTFWD.\n"); + ret = UAP_FAILURE; + } else if ((ISDIGIT(argv[0]) == 0) || + ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1))) { + printf + ("ERR:Illegal PKTFWD parameter %s. Must be either '0' or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + break; + case STAAGEOUTTIMER: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for STAAGEOUTTIMER.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) && + ((atoi(argv[0]) < + MIN_STAGE_OUT_TIME) || + (atoi(argv[0]) > + MAX_STAGE_OUT_TIME)))) { + printf + ("ERR:Illegal STAAGEOUTTIMER %s. Must be between %d and %d.\n", + argv[0], MIN_STAGE_OUT_TIME, MAX_STAGE_OUT_TIME); + ret = UAP_FAILURE; + } + } + break; + case AUTHMODE: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for AUTHMODE\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf + ("ERR:Illegal AUTHMODE parameter %s. Must be either '0', or '1'.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case GROUPREKEYTIMER: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for GROUPREKEYTIMER.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > MAX_GRP_TIMER)) { + printf("ERR: GROUPREKEYTIMER range is [0:%d] (0 for disable)\n", + MAX_GRP_TIMER); + ret = UAP_FAILURE; + } + } + break; + case MAXSTANUM: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for MAXSTANUM\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) > 8) || + (atoi(argv[0]) < 0)) { + printf("ERR:STA_NUM must be in the range of [0:8] %s.\n", + argv[0]); + ret = UAP_FAILURE; + } + } + break; + case BEACONPERIOD: + if (argc != 1) { + printf("ERR:Incorrect number of argument for BEACONPERIOD.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < MIN_BEACON_PERIOD) + || (atoi(argv[0]) > MAX_BEACON_PERIOD)) { + printf("ERR: BEACONPERIOD must be in range of %d to %d.\n", + MIN_BEACON_PERIOD, MAX_BEACON_PERIOD); + ret = UAP_FAILURE; + } + } + break; + case RETRYLIMIT: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for RETRY LIMIT\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) > MAX_RETRY_LIMIT) || + (atoi(argv[0]) < 0)) { + printf + ("ERR:RETRY_LIMIT must be in the range of [0:%d]. The input was %s.\n", + MAX_RETRY_LIMIT, argv[0]); + ret = UAP_FAILURE; + } + } + break; + case COEX_COMM_BITMAP: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for Bitmap.\n"); + ret = UAP_FAILURE; + } else { + /* Only bit 0 is supported now, hence check for 1 or 0 */ + if ((IS_HEX_OR_DIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf("ERR: Bitmap must have value of 1 or 0.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_SCO_ACL_FREQ: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for aclFrequency.\n"); + ret = UAP_FAILURE; + } else { + if (ISDIGIT(argv[0]) == 0) { + printf("ERR: Incorrect value for aclFrequency.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_ACL_ENABLED: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for (acl) enabled.\n"); + ret = UAP_FAILURE; + } else { + if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || + (atoi(argv[0]) > 1)) { + printf("ERR: (acl) enabled must have value of 1 or 0.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_ACL_BT_TIME: + case COEX_ACL_WLAN_TIME: + if (argc != 1) { + printf("ERR:Incorrect number of arguments for bt/wlan time.\n"); + ret = UAP_FAILURE; + } else { + if (ISDIGIT(argv[0]) == 0) { + printf("ERR: Incorrect value for bt/wlan time.\n"); + ret = UAP_FAILURE; + } + } + break; + case COEX_PROTECTION: + if (argc != 2) { + printf("ERR:Incorrect number of arguments for %s.\n", argv[0]); + ret = UAP_FAILURE; + } else { + if (ISDIGIT(argv[1]) == 0) { + printf("ERR: Incorrect value for %s.\n", argv[0]); + ret = UAP_FAILURE; + } + } + break; + default: + ret = UAP_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 UAP_SUCCESS or UAP_FAILURE + * UAP_RET_MAC_BROADCAST - if broadcast mac + * UAP_RET_MAC_MULTICAST - if multicast mac + */ +int +mac2raw(char *mac, u8 * raw) +{ + unsigned int temp_raw[ETH_ALEN]; + int num_tokens = 0; + int i; + if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) { + return UAP_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 UAP_FAILURE; + } + for (i = 0; i < num_tokens; i++) + raw[i] = (u8) temp_raw[i]; + + if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { + return UAP_RET_MAC_BROADCAST; + } else if (raw[0] & 0x01) { + return UAP_RET_MAC_MULTICAST; + } + return UAP_SUCCESS; +} + +/** + * @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 Prints a MAC address in colon separated form from hex data + * + * @param raw A pointer to the hex data buffer + * @return N/A + */ +void +print_mac(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 check hex string + * + * @param hex A pointer to hex string + * @return UAP_SUCCESS or UAP_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 UAP_FAILURE; + p++; + } + return UAP_SUCCESS; +} + +/** + * @brief Show auth tlv + * + * @param tlv Poniter to auth tlv + * + * $return N/A + */ +void +print_auth(TLVBUF_AUTH_MODE * tlv) +{ + switch (tlv->AuthMode) { + case 0: + printf("AUTHMODE = Open authentication\n"); + break; + case 1: + printf("AUTHMODE = Shared key authentication\n"); + break; + case 2: + printf("AUTHMODE = Auto (open and shared key)\n"); + break; + default: + printf("ERR: Invalid authmode=%d\n", tlv->AuthMode); + break; + } +} + +/** + * + * @brief Show cipher tlv + * + * @param tlv Poniter to cipher tlv + * + * $return N/A + */ +void +print_cipher(TLVBUF_CIPHER * tlv) +{ + switch (tlv->PairwiseCipher) { + case CIPHER_TKIP: + printf("PairwiseCipher = TKIP\n"); + break; + case CIPHER_AES_CCMP: + printf("PairwiseCipher = AES CCMP\n"); + break; + case CIPHER_TKIP | CIPHER_AES_CCMP: + printf("PairwiseCipher = TKIP + AES CCMP\n"); + break; + case CIPHER_NONE: + printf("PairwiseCipher = None\n"); + break; + default: + printf("Unknown Pairwise cipher 0x%x\n", tlv->PairwiseCipher); + break; + } + switch (tlv->GroupCipher) { + case CIPHER_TKIP: + printf("GroupCipher = TKIP\n"); + break; + case CIPHER_AES_CCMP: + printf("GroupCipher = AES CCMP\n"); + break; + case CIPHER_NONE: + printf("GroupCipher = None\n"); + break; + default: + printf("Unknown Group cipher 0x%x\n", tlv->GroupCipher); + break; + } +} + +/** + * @brief Show mac filter tlv + * + * @param tlv Poniter to filter tlv + * + * $return N/A + */ +void +print_mac_filter(TLVBUF_STA_MAC_ADDR_FILTER * tlv) +{ + int i; + switch (tlv->FilterMode) { + case 0: + printf("Filter Mode = Filter table is disabled\n"); + return; + case 1: + printf + ("Filter Mode = Allow mac address specified in the allwed list\n"); + break; + case 2: + printf + ("Filter Mode = Block MAC addresses specified in the banned list\n"); + break; + } + for (i = 0; i < tlv->Count; i++) { + printf("MAC_%d = ", i); + print_mac(&tlv->MacAddress[i * ETH_ALEN]); + printf("\n"); + } +} + +/** + * @brief Show rate tlv + * + * @param tlv Poniter to rate tlv + * + * $return N/A + */ +void +print_rate(TLVBUF_RATES * tlv) +{ + int flag = 0; + int i; + printf("Basic Rates ="); + for (i = 0; i < tlv->Length; i++) { + if (tlv->OperationalRates[i] > (BASIC_RATE_SET_BIT - 1)) { + flag = flag ? : 1; + printf(" 0x%x", tlv->OperationalRates[i]); + } + } + printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) "); + for (flag = 0, i = 0; i < tlv->Length; i++) { + if (tlv->OperationalRates[i] < BASIC_RATE_SET_BIT) { + flag = flag ? : 1; + printf(" 0x%x", tlv->OperationalRates[i]); + } + } + printf("%s\n", flag ? "" : " ( none ) "); +} + +/** + * @brief Show all the tlv in the buf + * + * @param buf Poniter to tlv buffer + * @param len tlv buffer len + * + * $return N/A + */ +void +print_tlv(u8 * buf, u16 len) +{ + TLVBUF_HEADER *pCurrentTlv = (TLVBUF_HEADER *) buf; + int tlvBufLeft = len; + u16 tlvType; + u16 tlvLen; + u16 custom_ie_len; + u8 ssid[33]; + int i = 0; + TLVBUF_AP_MAC_ADDRESS *mac_tlv; + TLVBUF_SSID *ssid_tlv; + TLVBUF_BEACON_PERIOD *beacon_tlv; + TLVBUF_DTIM_PERIOD *dtim_tlv; + TLVBUF_RATES *rates_tlv; + TLVBUF_TX_POWER *txpower_tlv; + TLVBUF_BCAST_SSID_CTL *bcast_tlv; + TLVBUF_PREAMBLE_CTL *preamble_tlv; + TLVBUF_ANTENNA_CTL *antenna_tlv; + TLVBUF_RTS_THRESHOLD *rts_tlv; + TLVBUF_RADIO_CTL *radio_tlv; + TLVBUF_TX_DATA_RATE *txrate_tlv; + TLVBUF_MCBC_DATA_RATE *mcbcrate_tlv; + TLVBUF_PKT_FWD_CTL *pkt_fwd_tlv; + TLVBUF_STA_AGEOUT_TIMER *ageout_tlv; + TLVBUF_AUTH_MODE *auth_tlv; + TLVBUF_PROTOCOL *proto_tlv; + TLVBUF_AKMP *akmp_tlv; + TLVBUF_CIPHER *cipher_tlv; + TLVBUF_GROUP_REKEY_TIMER *rekey_tlv; + TLVBUF_WPA_PASSPHRASE *psk_tlv; + TLVBUF_WEP_KEY *wep_tlv; + TLVBUF_FRAG_THRESHOLD *frag_tlv; + TLVBUF_STA_MAC_ADDR_FILTER *filter_tlv; + TLVBUF_MAX_STA_NUM *max_sta_tlv; + TLVBUF_RETRY_LIMIT *retry_limit_tlv; + TLVBUF_CHANNEL_CONFIG *channel_tlv; + TLVBUF_CHANNEL_LIST *chnlist_tlv; + tlvbuf_custom_ie *custom_ie_tlv; + custom_ie *custom_ie_ptr; + tlvbuf_coex_common_cfg *coex_common_tlv; + tlvbuf_coex_sco_cfg *coex_sco_tlv; + tlvbuf_coex_acl_cfg *coex_acl_tlv; + tlvbuf_coex_stats *coex_stats_tlv; + CHANNEL_LIST *pChanList; +#ifdef DEBUG + uap_printf(MSG_DEBUG, "tlv total len=%d\n", len); +#endif + while (tlvBufLeft >= (int) sizeof(TLVBUF_HEADER)) { + tlvType = uap_le16_to_cpu(pCurrentTlv->Type); + tlvLen = uap_le16_to_cpu(pCurrentTlv->Len); + if ((sizeof(TLVBUF_HEADER) + tlvLen) > tlvBufLeft) { + printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlvLen, tlvBufLeft); + break; + } + switch (tlvType) { + case MRVL_AP_MAC_ADDRESS_TLV_ID: + mac_tlv = (TLVBUF_AP_MAC_ADDRESS *) pCurrentTlv; + printf("AP MAC address = "); + print_mac(mac_tlv->ApMacAddr); + printf("\n"); + break; + case MRVL_SSID_TLV_ID: + memset(ssid, 0, sizeof(ssid)); + ssid_tlv = (TLVBUF_SSID *) pCurrentTlv; + memcpy(ssid, ssid_tlv->Ssid, ssid_tlv->Length); + printf("SSID = %s\n", ssid); + break; + case MRVL_BEACON_PERIOD_TLV_ID: + beacon_tlv = (TLVBUF_BEACON_PERIOD *) pCurrentTlv; + beacon_tlv->BeaconPeriod_ms = + uap_le16_to_cpu(beacon_tlv->BeaconPeriod_ms); + printf("Beacon period = %d\n", beacon_tlv->BeaconPeriod_ms); + break; + case MRVL_DTIM_PERIOD_TLV_ID: + dtim_tlv = (TLVBUF_DTIM_PERIOD *) pCurrentTlv; + printf("DTIM period = %d\n", dtim_tlv->DtimPeriod); + break; + case MRVL_CHANNELCONFIG_TLV_ID: + channel_tlv = (TLVBUF_CHANNEL_CONFIG *) pCurrentTlv; + printf("Channel = %d\n", channel_tlv->ChanNumber); + printf("Channel Select Mode = %s\n", + (channel_tlv->BandConfigType == 0) ? "Manual" : "ACS"); + break; + case MRVL_CHANNELLIST_TLV_ID: + chnlist_tlv = (TLVBUF_CHANNEL_LIST *) pCurrentTlv; + printf("Channels List = "); + pChanList = (CHANNEL_LIST *) & (chnlist_tlv->ChanList); + if (chnlist_tlv->Length % sizeof(CHANNEL_LIST)) { + break; + } + for (i = 0; i < (chnlist_tlv->Length / sizeof(CHANNEL_LIST)); i++) { + printf("%d ", pChanList->ChanNumber); + pChanList++; + } + printf("\n"); + break; + case MRVL_RATES_TLV_ID: + rates_tlv = (TLVBUF_RATES *) pCurrentTlv; + print_rate(rates_tlv); + break; + case MRVL_TX_POWER_TLV_ID: + txpower_tlv = (TLVBUF_TX_POWER *) pCurrentTlv; + printf("Tx power = %d dBm\n", txpower_tlv->TxPower_dBm); + break; + case MRVL_BCAST_SSID_CTL_TLV_ID: + bcast_tlv = (TLVBUF_BCAST_SSID_CTL *) pCurrentTlv; + printf("SSID broadcast = %s\n", + (bcast_tlv->BcastSsidCtl == 1) ? "enabled" : "disabled"); + break; + case MRVL_PREAMBLE_CTL_TLV_ID: + preamble_tlv = (TLVBUF_PREAMBLE_CTL *) pCurrentTlv; + printf("Preamble type = %s\n", (preamble_tlv->PreambleType == 0) ? + "auto" : ((preamble_tlv->PreambleType == 1) ? "short" : + "long")); + break; + case MRVL_ANTENNA_CTL_TLV_ID: + antenna_tlv = (TLVBUF_ANTENNA_CTL *) pCurrentTlv; + printf("%s antenna = %s\n", (antenna_tlv->WhichAntenna == 0) ? + "Rx" : "Tx", (antenna_tlv->AntennaMode == 0) ? "A" : "B"); + break; + case MRVL_RTS_THRESHOLD_TLV_ID: + rts_tlv = (TLVBUF_RTS_THRESHOLD *) pCurrentTlv; + rts_tlv->RtsThreshold = uap_le16_to_cpu(rts_tlv->RtsThreshold); + printf("RTS threshold = %d\n", rts_tlv->RtsThreshold); + break; + case MRVL_FRAG_THRESHOLD_TLV_ID: + frag_tlv = (TLVBUF_FRAG_THRESHOLD *) pCurrentTlv; + frag_tlv->FragThreshold = uap_le16_to_cpu(frag_tlv->FragThreshold); + printf("Fragmentation threshold = %d\n", frag_tlv->FragThreshold); + break; + case MRVL_RADIO_CTL_TLV_ID: + radio_tlv = (TLVBUF_RADIO_CTL *) pCurrentTlv; + printf("Radio = %s\n", (radio_tlv->RadioCtl == 0) ? "on" : "off"); + break; + case MRVL_TX_DATA_RATE_TLV_ID: + txrate_tlv = (TLVBUF_TX_DATA_RATE *) pCurrentTlv; + txrate_tlv->TxDataRate = uap_le16_to_cpu(txrate_tlv->TxDataRate); + if (txrate_tlv->TxDataRate == 0) + printf("Tx data rate = auto\n"); + else + printf("Tx data rate = 0x%x\n", txrate_tlv->TxDataRate); + break; + case MRVL_MCBC_DATA_RATE_TLV_ID: + mcbcrate_tlv = (TLVBUF_MCBC_DATA_RATE *) pCurrentTlv; + mcbcrate_tlv->MCBCdatarate = + uap_le16_to_cpu(mcbcrate_tlv->MCBCdatarate); + if (mcbcrate_tlv->MCBCdatarate == 0) + printf("MCBC data rate = auto\n"); + else + printf("MCBC data rate = 0x%x\n", mcbcrate_tlv->MCBCdatarate); + break; + case MRVL_PKT_FWD_CTL_TLV_ID: + pkt_fwd_tlv = (TLVBUF_PKT_FWD_CTL *) pCurrentTlv; + printf("Firmware = %s\n", (pkt_fwd_tlv->PktFwdCtl == 0) ? + "forwards all packets to the host" : + "handles intra-BSS packets"); + break; + case MRVL_STA_AGEOUT_TIMER_TLV_ID: + ageout_tlv = (TLVBUF_STA_AGEOUT_TIMER *) pCurrentTlv; + ageout_tlv->StaAgeoutTimer_ms = + uap_le32_to_cpu(ageout_tlv->StaAgeoutTimer_ms); + printf("STA ageout timer = %d\n", + (int) ageout_tlv->StaAgeoutTimer_ms); + break; + case MRVL_AUTH_TLV_ID: + auth_tlv = (TLVBUF_AUTH_MODE *) pCurrentTlv; + print_auth(auth_tlv); + break; + case MRVL_PROTOCOL_TLV_ID: + proto_tlv = (TLVBUF_PROTOCOL *) pCurrentTlv; + proto_tlv->Protocol = uap_le16_to_cpu(proto_tlv->Protocol); + print_protocol(proto_tlv); + break; + case MRVL_AKMP_TLV_ID: + akmp_tlv = (TLVBUF_AKMP *) pCurrentTlv; + if (uap_le16_to_cpu(akmp_tlv->KeyMgmt) == KEY_MGMT_PSK) + printf("KeyMgmt = PSK\n"); + else + printf("KeyMgmt = NONE\n"); + break; + case MRVL_CIPHER_TLV_ID: + cipher_tlv = (TLVBUF_CIPHER *) pCurrentTlv; + print_cipher(cipher_tlv); + break; + case MRVL_GRP_REKEY_TIME_TLV_ID: + rekey_tlv = (TLVBUF_GROUP_REKEY_TIMER *) pCurrentTlv; + if (rekey_tlv->GroupRekeyTime_sec == 0) + printf("Group re-key time = disabled\n"); + else + printf("Group re-key time = %ld second\n", + uap_le32_to_cpu(rekey_tlv->GroupRekeyTime_sec)); + break; + case MRVL_WPA_PASSPHRASE_TLV_ID: + psk_tlv = (TLVBUF_WPA_PASSPHRASE *) pCurrentTlv; + if (psk_tlv->Length > 0) { + printf("WPA passphrase = "); + for (i = 0; i < psk_tlv->Length; i++) + printf("%c", psk_tlv->Passphrase[i]); + printf("\n"); + } else + printf("WPA passphrase = None\n"); + break; + case MRVL_WEP_KEY_TLV_ID: + wep_tlv = (TLVBUF_WEP_KEY *) pCurrentTlv; + print_wep_key(wep_tlv); + break; + case MRVL_STA_MAC_ADDR_FILTER_TLV_ID: + filter_tlv = (TLVBUF_STA_MAC_ADDR_FILTER *) pCurrentTlv; + print_mac_filter(filter_tlv); + break; + case MRVL_MAX_STA_CNT_TLV_ID: + max_sta_tlv = (TLVBUF_MAX_STA_NUM *) pCurrentTlv; + printf("Max Station Number = %d\n", max_sta_tlv->Max_sta_num); + break; + case MRVL_RETRY_LIMIT_TLV_ID: + retry_limit_tlv = (TLVBUF_RETRY_LIMIT *) pCurrentTlv; + printf("Retry Limit = %d\n", retry_limit_tlv->retry_limit); + break; + case MRVL_MGMT_IE_LIST_TLV_ID: + custom_ie_tlv = (tlvbuf_custom_ie *) pCurrentTlv; + custom_ie_len = tlvLen; + custom_ie_ptr = (custom_ie *) (custom_ie_tlv->ie_data); + while (custom_ie_len >= sizeof(custom_ie)) { + printf("Index [%d]\n", + uap_le16_to_cpu(custom_ie_ptr->ie_index)); + printf("Management Subtype Mask = 0x%02x\n", + uap_le16_to_cpu(custom_ie_ptr->mgmt_subtype_mask)); + hexdump_data("IE Buffer", (void *) custom_ie_ptr->ie_buffer, + uap_le16_to_cpu(custom_ie_ptr->ie_length), ' '); + custom_ie_len -= + sizeof(custom_ie) + + uap_le16_to_cpu(custom_ie_ptr->ie_length); + custom_ie_ptr = + (custom_ie *) ((u8 *) custom_ie_ptr + sizeof(custom_ie) + + uap_le16_to_cpu(custom_ie_ptr->ie_length)); + } + break; + case MRVL_BT_COEX_COMMON_CFG_TLV_ID: + printf("Coex common configuration:\n"); + coex_common_tlv = (tlvbuf_coex_common_cfg *) pCurrentTlv; + printf("\tConfig Bitmap = 0x%02lx\n", + uap_le32_to_cpu(coex_common_tlv->config_bitmap)); + break; + + case MRVL_BT_COEX_SCO_CFG_TLV_ID: + printf("Coex sco configuration:\n"); + coex_sco_tlv = (tlvbuf_coex_sco_cfg *) pCurrentTlv; + for (i = 0; i < 4; i++) + printf("\tQtime protection [%d] = %d usecs\n", i, + uap_le16_to_cpu(coex_sco_tlv->protection_qtime[i])); + printf("\tProtection frame rate = %d\n", + uap_le16_to_cpu(coex_sco_tlv->protection_rate)); + printf("\tACL frequency = %d\n", + uap_le16_to_cpu(coex_sco_tlv->acl_frequency)); + break; + + case MRVL_BT_COEX_ACL_CFG_TLV_ID: + printf("Coex acl configuration: "); + coex_acl_tlv = (tlvbuf_coex_acl_cfg *) pCurrentTlv; + coex_acl_tlv->enabled = uap_le16_to_cpu(coex_acl_tlv->enabled); + printf("%s\n", (coex_acl_tlv->enabled) ? "enabled" : "disabled"); + if (coex_acl_tlv->enabled) { + printf("\tBT time = %d usecs\n", + uap_le16_to_cpu(coex_acl_tlv->bt_time)); + printf("\tWLan time = %d usecs\n", + uap_le16_to_cpu(coex_acl_tlv->wlan_time)); + printf("\tProtection frame rate = %d\n", + uap_le16_to_cpu(coex_acl_tlv->protection_rate)); + } + break; + + case MRVL_BT_COEX_STATS_TLV_ID: + printf("Coex statistics: \n"); + coex_stats_tlv = (tlvbuf_coex_stats *) pCurrentTlv; + printf("\tNull not sent = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_not_sent)); + printf("\tNull queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_queued)); + printf("\tNull not queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_not_queued)); + printf("\tCF End queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->cf_end_queued)); + printf("\tCF End not queued = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->cf_end_not_queued)); + printf("\tNull allocation failures = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->null_alloc_fail)); + printf("\tCF End allocation failures = %ld\n", + uap_le32_to_cpu(coex_stats_tlv->cf_end_alloc_fail)); + break; + default: + break; + } + tlvBufLeft -= (sizeof(TLVBUF_HEADER) + tlvLen); + pCurrentTlv = (TLVBUF_HEADER *) (pCurrentTlv->Data + tlvLen); + } + return; +} + +/** + * @brief Performs the ioctl operation to send the command to + * the driver. + * + * @param cmd Pointer to the command buffer + * @param size Pointer to the command size. This value is + * overwritten by the function with the size of the + * received response. + * @param buf_size Size of the allocated command buffer + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +uap_ioctl(u8 * cmd, u16 * size, u16 buf_size) +{ + struct ifreq ifr; + APCMDBUF *header = NULL; + s32 sockfd; + + if (buf_size < *size) { + printf("buf_size should not less than cmd buffer size\n"); + return UAP_FAILURE; + } + + /* Open socket */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("ERR:Cannot open socket\n"); + return UAP_FAILURE; + } + *(u32 *) cmd = buf_size - BUF_HEADER_SIZE; + + /* 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; + header = (APCMDBUF *) cmd; + header->Size = *size - BUF_HEADER_SIZE; + if (header->CmdCode == APCMD_SYS_CONFIGURE) { + APCMDBUF_SYS_CONFIGURE *sys_cfg; + sys_cfg = (APCMDBUF_SYS_CONFIGURE *) cmd; + sys_cfg->Action = uap_cpu_to_le16(sys_cfg->Action); + } + endian_convert_request_header(header); +#if DEBUG + /* Dump request buffer */ + hexdump("Request buffer", (void *) cmd, *size, ' '); +#endif + /* Perform ioctl */ + errno = 0; + if (ioctl(sockfd, UAPHOSTCMD, &ifr)) { + perror(""); + printf("ERR:UAPHOSTCMD is not supported by %s\n", dev_name); + close(sockfd); + return UAP_FAILURE; + } + endian_convert_response_header(header); + header->CmdCode &= HostCmd_CMD_ID_MASK; + header->CmdCode |= APCMD_RESP_CHECK; + *size = header->Size; + + /* Validate response size */ + if (*size > (buf_size - BUF_HEADER_SIZE)) { + printf + ("ERR:Response size (%d) greater than buffer size (%d)! Aborting!\n", + *size, buf_size); + close(sockfd); + return UAP_FAILURE; + } +#if DEBUG + /* Dump respond buffer */ + hexdump("Respond buffer", (void *) header, header->Size + BUF_HEADER_SIZE, + ' '); +#endif + + /* Close socket */ + close(sockfd); + return UAP_SUCCESS; +} + +/** + * @brief check cipher is valid or not + * + * @param pairwisecipher pairwise cipher + * @param groupcipher group cipher + * @return UAP_SUCCESS or UAP_FAILURE + */ +int +is_cipher_valid(int pairwisecipher, int groupcipher) +{ + if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE)) + return UAP_SUCCESS; + if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP)) + return UAP_SUCCESS; + if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_AES_CCMP)) + return UAP_SUCCESS; + if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP)) + return UAP_SUCCESS; + return UAP_FAILURE; +} + +/** + * @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, i; + memset(dev_name, 0, sizeof(dev_name)); + strcpy(dev_name, DEFAULT_DEV_NAME); + + /* parse arguments */ + while ((opt = getopt_long(argc, argv, "+hi:d:v", ap_options, NULL)) != -1) { + switch (opt) { + case 'i': + if (strlen(optarg) < IFNAMSIZ) { + memset(dev_name, 0, sizeof(dev_name)); + strncpy(dev_name, optarg, strlen(optarg)); + } + printf("dev_name:%s\n", dev_name); + break; + case 'v': + printf("uaputl.exe - uAP utility ver %s\n", UAP_VERSION); + exit(0); + case 'd': + debug_level = strtoul(optarg, NULL, 10); + uap_printf(MSG_DEBUG, "debug_level=%x\n", debug_level); + break; + case 'h': + default: + print_tool_usage(); + exit(0); + } + } + + argc -= optind; + argv += optind; + optind = 0; + + if (argc < 1) { + print_tool_usage(); + exit(1); + } + + /* process command */ + for (i = 0; ap_command[i].cmd; i++) { + if (strncmp(ap_command[i].cmd, argv[0], strlen(ap_command[i].cmd))) + continue; + if (strlen(ap_command[i].cmd) != strlen(argv[0])) + continue; + ap_command[i].func(argc, argv); + break; + } + if (!ap_command[i].cmd) { + printf("ERR: %s is not supported\n", argv[0]); + exit(1); + } + return 0; +} diff --git a/packages/dreamplug-uaputl/uaputl.h b/packages/dreamplug-uaputl/uaputl.h new file mode 100644 index 0000000..1cd0fba --- /dev/null +++ b/packages/dreamplug-uaputl/uaputl.h @@ -0,0 +1,1289 @@ +/** @file uaputl.h + * + * @brief Header file for uaputl application + * + * Copyright (C) 2008-2009, 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/01/08: Initial creation +************************************************************************/ + +#ifndef _UAP_H +#define _UAP_H + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#undef BIG_ENDIAN +#endif + +/** 16 bits byte swap */ +#define swap_byte_16(x) \ + ((u16)((((u16)(x) & 0x00ffU) << 8) | \ + (((u16)(x) & 0xff00U) >> 8))) + +/** 32 bits byte swap */ +#define swap_byte_32(x) \ + ((u32)((((u32)(x) & 0x000000ffUL) << 24) | \ + (((u32)(x) & 0x0000ff00UL) << 8) | \ + (((u32)(x) & 0x00ff0000UL) >> 8) | \ + (((u32)(x) & 0xff000000UL) >> 24))) + +/** 64 bits byte swap */ +#define swap_byte_64(x) \ + ((u64)((u64)(((u64)(x) & 0x00000000000000ffULL) << 56) | \ + (u64)(((u64)(x) & 0x000000000000ff00ULL) << 40) | \ + (u64)(((u64)(x) & 0x0000000000ff0000ULL) << 24) | \ + (u64)(((u64)(x) & 0x00000000ff000000ULL) << 8) | \ + (u64)(((u64)(x) & 0x000000ff00000000ULL) >> 8) | \ + (u64)(((u64)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (u64)(((u64)(x) & 0x00ff000000000000ULL) >> 40) | \ + (u64)(((u64)(x) & 0xff00000000000000ULL) >> 56) )) + +#ifdef BIG_ENDIAN +/** 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) + +/** Convert APCMD header to little endian format from CPU format */ +#define endian_convert_request_header(x); \ + { \ + (x)->CmdCode = uap_cpu_to_le16((x)->CmdCode); \ + (x)->Size = uap_cpu_to_le16((x)->Size); \ + (x)->SeqNum = uap_cpu_to_le16((x)->SeqNum); \ + (x)->Result = uap_cpu_to_le16((x)->Result); \ + } + +/** Convert APCMD header from little endian format to CPU format */ +#define endian_convert_response_header(x); \ + { \ + (x)->CmdCode = uap_le16_to_cpu((x)->CmdCode); \ + (x)->Size = uap_le16_to_cpu((x)->Size); \ + (x)->SeqNum = uap_le16_to_cpu((x)->SeqNum); \ + (x)->Result = uap_le16_to_cpu((x)->Result); \ + } + +/** Convert TLV header to little endian format from CPU format */ +#define endian_convert_tlv_header_out(x); \ + { \ + (x)->Tag = uap_cpu_to_le16((x)->Tag); \ + (x)->Length = uap_cpu_to_le16((x)->Length); \ + } + +/** Convert TLV header from little endian format to CPU format */ +#define endian_convert_tlv_header_in(x); \ + { \ + (x)->Tag = uap_le16_to_cpu((x)->Tag); \ + (x)->Length = uap_le16_to_cpu((x)->Length); \ + } + +#else /* BIG_ENDIAN */ +/** 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 + +/** Do nothing */ +#define endian_convert_request_header(x) +/** Do nothing */ +#define endian_convert_response_header(x) +/** Do nothing */ +#define endian_convert_tlv_header_out(x) +/** Do nothing */ +#define endian_convert_tlv_header_in(x) +#endif /* BIG_ENDIAN */ + +/** uAP application version string */ +#define UAP_VERSION "1.12" +/** Host Command ioctl number */ +#define UAPHOSTCMD (SIOCDEVPRIVATE + 1) +/** Private command ID to Power Mode */ +#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3) + +/** Default device name */ +#define DEFAULT_DEV_NAME "uap0" + +/** Success */ +#define UAP_SUCCESS 1 +/** Failure */ +#define UAP_FAILURE 0 +/** MAC BROADCAST */ +#define UAP_RET_MAC_BROADCAST 0x1FF +/** MAC MULTICAST */ +#define UAP_RET_MAC_MULTICAST 0x1FE + +/** Command is successful */ +#define CMD_SUCCESS 0 +/** Command fails */ +#define CMD_FAILURE -1 + +/** BSS start error : Invalid parameters */ +#define BSS_FAILURE_START_INVAL -2 +/** BSS start error : BSS already started */ +#define BSS_FAILURE_START_REDUNDANT -3 + +/** BSS stop error : BSS already stopped */ +#define BSS_FAILURE_STOP_REDUNDANT -2 +/** BSS stop error : No active BSS */ +#define BSS_FAILURE_STOP_INVAL -3 + +/** Maximum line length for config file */ +#define MAX_LINE_LENGTH 240 +/** Maximum command length */ +#define MAX_CMD_LENGTH 100 +/** Size of command buffer */ +#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) +/** Maximum number of clients supported by AP */ +#define MAX_NUM_CLIENTS 16 +/** Maximum number of MAC addresses for one-shot filter modifications */ +#define MAX_MAC_ONESHOT_FILTER 16 +/** Maximum SSID length */ +#define MAX_SSID_LENGTH 32 +/** Maximum SSID length */ +#define MIN_SSID_LENGTH 1 +/** Maximum WPA passphrase length */ +#define MAX_WPA_PASSPHRASE_LENGTH 64 +/** Minimum WPA passphrase length */ +#define MIN_WPA_PASSPHRASE_LENGTH 8 +/** Maximum data rates */ +#define MAX_DATA_RATES 14 +/** Maximum length of lines in configuration file */ +#define MAX_CONFIG_LINE 240 +/** MSB bit is set if its a basic rate */ +#define BASIC_RATE_SET_BIT 0x80 +/** Maximum group key timer */ +#define MAX_GRP_TIMER 86400 +/** Maximum Retry Limit */ +#define MAX_RETRY_LIMIT 14 + +/** Maximum TX Power Limit */ +#define MAX_TX_POWER 20 +/** Minimum TX Power Limit */ +#define MIN_TX_POWER 0 + +/** Maximum channels */ +#define MAX_CHANNELS 14 +/** Maximum RTS threshold */ +#define MAX_RTS_THRESHOLD 2347 + +/** Maximum fragmentation threshold */ +#define MAX_FRAG_THRESHOLD 2346 +/** Minimum fragmentation threshold */ +#define MIN_FRAG_THRESHOLD 256 + +/** Maximum stage out time */ +#define MAX_STAGE_OUT_TIME 864000 +/** Minimum stage out time */ +#define MIN_STAGE_OUT_TIME 300 + +/** Maximum DTIM period */ +#define MAX_DTIM_PERIOD 100 + +/** Maximum BEACON period */ +#define MAX_BEACON_PERIOD 4000 + +/** Minimum BEACON period */ +#define MIN_BEACON_PERIOD 50 + +/** Maximum IE buffer length */ +#define MAX_IE_BUFFER_LEN 256 + +/** Maximum custom IE count */ +#define MAX_CUSTOM_IE_COUNT 4 + +/** Maximum number of rates allowed at a time */ +#define MAX_RATES 12 + +/** Default wait period in seconds */ +#define DEFAULT_WAIT_TIME 3 + +#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 + +/** Action field value : get */ +#define ACTION_GET 0 +/** Action field value : set */ +#define ACTION_SET 1 +/** + * 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)))\ + +/** Find minimum value */ +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +/** Character, 1 byte */ +typedef char s8; +/** Unsigned character, 1 byte */ +typedef unsigned char u8; + +/** Short integer */ +typedef signed short s16; +/** Unsigned short integer */ +typedef unsigned short u16; + +/** Long integer */ +typedef signed long s32; +/** Unsigned long integer */ +typedef unsigned long u32; + +/** Valid Input Commands */ +typedef enum +{ + RDEEPROM, + SCANCHANNELS, + TXPOWER, + PROTOCOL, + CHANNEL, + RATE, + BROADCASTSSID, + RTSTHRESH, + FRAGTHRESH, + DTIMPERIOD, + RADIOCONTROL, + TXDATARATE, + MCBCDATARATE, + PKTFWD, + STAAGEOUTTIMER, + AUTHMODE, + GROUPREKEYTIMER, + MAXSTANUM, + BEACONPERIOD, + RETRYLIMIT, + RSNREPLAYPROT, + COEX_COMM_BITMAP, + COEX_PROTECTION, + COEX_SCO_ACL_FREQ, + COEX_ACL_ENABLED, + COEX_ACL_BT_TIME, + COEX_ACL_WLAN_TIME, +} valid_inputs; + +/** Message verbosity level */ +enum +{ MSG_NONE, MSG_DEBUG, MSG_ALL }; + +/** oids_table */ +typedef struct +{ + /** oid type */ + u16 type; + /** oid len */ + u16 len; + /** oid name */ + char *name; +} oids_table; + +/** 4 byte header to store buf len*/ +#define BUF_HEADER_SIZE 4 + +/** AP CMD header */ +#define APCMDHEADER /** Buf Size */ \ + u32 BufSize; \ + /** CmdCode */ \ + u16 CmdCode; \ + /** Size */ \ + u16 Size; \ + /** SeqNum */ \ + u16 SeqNum; \ + /** Result */ \ + s16 Result + +/** TLV header */ +#define TLVHEADER /** Tag */ \ + u16 Tag; \ + /** Length */ \ + u16 Length + +/* TLV Definitions */ + +/** TLV buffer header*/ +typedef PACK_START struct _TLVBUF_HEADER +{ + /** Header type */ + u16 Type; + /** Header length */ + u16 Len; + /** Data */ + u8 Data[0]; +} PACK_END TLVBUF_HEADER; + +/** Band config ACS mode */ +#define BAND_CONFIG_ACS_MODE 0x40 + +/** TLV buffer : Channel Config */ +typedef PACK_START struct _TLVBUF_CHANNEL_CONFIG +{ + /** Header */ + TLVHEADER; + /** Band Configuration + * + * [7-6] Channel Selection Mode; 00 manual, 01 ACS + * [3-2] Channel Width; 00 20 MHz + * [1-0] Band Info; 00 2.4 GHz + */ + u8 BandConfigType; + /** Channel number */ + u8 ChanNumber; +} PACK_END TLVBUF_CHANNEL_CONFIG; + +/** Channel List Entry */ +typedef PACK_START struct _CHANNEL_LIST +{ + /** Band Config */ + u8 BandConfigType; + /** Channel Number */ + u8 ChanNumber; + /** Reserved */ + u8 Reserved1; + /** Reserved */ + u16 Reserved2; + /** Reserved */ + u16 Reserved3; +} PACK_END CHANNEL_LIST; + +/** TLV buffer : Channel List */ +typedef PACK_START struct _TLVBUF_CHANNEL_LIST +{ + /** Header */ + TLVHEADER; + /** Channel List */ + CHANNEL_LIST ChanList[0]; +} PACK_END TLVBUF_CHANNEL_LIST; + +/** TLV buffer : AP MAC address */ +typedef PACK_START struct _TLVBUF_AP_MAC_ADDRESS +{ + /** Header */ + TLVHEADER; + /** AP MAC address */ + u8 ApMacAddr[ETH_ALEN]; +} PACK_END TLVBUF_AP_MAC_ADDRESS; + +/** TLV buffer : SSID */ +typedef PACK_START struct _TLVBUF_SSID +{ + /** Header */ + TLVHEADER; + /** SSID */ + u8 Ssid[0]; +} PACK_END TLVBUF_SSID; + +/** TLV buffer : Beacon period */ +typedef PACK_START struct _TLVBUF_BEACON_PERIOD +{ + /** Header */ + TLVHEADER; + /** Beacon period */ + u16 BeaconPeriod_ms; +} PACK_END TLVBUF_BEACON_PERIOD; + +/** TLV buffer : DTIM period */ +typedef PACK_START struct _TLVBUF_DTIM_PERIOD +{ + /** Header */ + TLVHEADER; + /** DTIM period */ + u8 DtimPeriod; +} PACK_END TLVBUF_DTIM_PERIOD; + +/** TLV buffer : Channel */ +typedef PACK_START struct _TLVBUF_PHYPARAMDSSET +{ + /** Header */ + TLVHEADER; + /** Channel */ + u8 Channel; +} PACK_END TLVBUF_PHYPARAMDSSET; + +/** TLV buffer : Operational rates */ +typedef PACK_START struct _TLVBUF_RATES +{ + /** Header */ + TLVHEADER; + /** Operational rates */ + u8 OperationalRates[0]; +} PACK_END TLVBUF_RATES; + +/** TLV buffer : Tx power */ +typedef PACK_START struct _TLVBUF_TX_POWER +{ + /** Header */ + TLVHEADER; + /** Tx power in dBm */ + u8 TxPower_dBm; +} PACK_END TLVBUF_TX_POWER; + +/** TLV buffer : SSID broadcast control */ +typedef PACK_START struct _TLVBUF_BCAST_SSID_CTL +{ + /** Header */ + TLVHEADER; + /** SSID broadcast control flag */ + u8 BcastSsidCtl; +} PACK_END TLVBUF_BCAST_SSID_CTL; + +/** TLV buffer : RSN replay protection */ +typedef PACK_START struct _tlvbuf_rsn_replay_prot +{ + /** Header */ + TLVHEADER; + /** RSN replay protection control flag */ + u8 rsn_replay_prot; +} PACK_END tlvbuf_rsn_replay_prot; + +/** TLV buffer : Preamble control */ +typedef PACK_START struct _TLVBUF_PREAMBLE_CTL +{ + /** Header */ + TLVHEADER; + /** Preamble type */ + u8 PreambleType; +} PACK_END TLVBUF_PREAMBLE_CTL; + +/** TLV buffer : Antenna control */ +typedef PACK_START struct _TLVBUF_ANTENNA_CTL +{ + /** Header */ + TLVHEADER; + /** Antenna type */ + u8 WhichAntenna; + /** Antenna mode */ + u8 AntennaMode; +} PACK_END TLVBUF_ANTENNA_CTL; + +/** TLV buffer : RTS threshold */ +typedef PACK_START struct _TLVBUF_RTS_THRESHOLD +{ + /** Header */ + TLVHEADER; + /** RTS threshold */ + u16 RtsThreshold; +} PACK_END TLVBUF_RTS_THRESHOLD; + +/** TLV buffer : Radio control */ +typedef PACK_START struct _TLVBUF_RADIO_CTL +{ + /** Header */ + TLVHEADER; + /** Radio control flag */ + u8 RadioCtl; +} PACK_END TLVBUF_RADIO_CTL; + +/** TLV buffer : Tx data rate */ +typedef PACK_START struct _TLVBUF_TX_DATA_RATE +{ + /** Header */ + TLVHEADER; + /** Tx data rate */ + u16 TxDataRate; +} PACK_END TLVBUF_TX_DATA_RATE; + +/** TLV buffer : MCBC Data Rate */ +typedef PACK_START struct _TLVBUF_MCBC_DATA_RATE +{ + /** Header */ + TLVHEADER; + /** MCBC data rate */ + u16 MCBCdatarate; +} PACK_END TLVBUF_MCBC_DATA_RATE; + +/** TLV buffer : Packet forward control */ +typedef PACK_START struct _TLVBUF_PKT_FWD_CTL +{ + /** Header */ + TLVHEADER; + /** Packet forwarding control flag */ + u8 PktFwdCtl; +} PACK_END TLVBUF_PKT_FWD_CTL; + +/** TLV buffer : STA information */ +typedef PACK_START struct _TLVBUF_STA_INFO +{ + /** Header */ + TLVHEADER; + /** STA MAC address */ + u8 MacAddress[ETH_ALEN]; + /** Power mfg status */ + u8 PowerMfgStatus; + /** RSSI */ + s8 Rssi; +} PACK_END TLVBUF_STA_INFO; + +/** TLV buffer : STA MAC address filtering control */ +typedef PACK_START struct _TLVBUF_STA_MAC_ADDR_FILTER +{ + /** Header */ + TLVHEADER; + /** Filter mode */ + u8 FilterMode; + /** Number of STA MACs */ + u8 Count; + /** STA MAC addresses buffer */ + u8 MacAddress[0]; +} PACK_END TLVBUF_STA_MAC_ADDR_FILTER; + +/** TLV buffer : STA ageout timer */ +typedef PACK_START struct _TLVBUF_STA_AGEOUT_TIMER +{ + /** Header */ + TLVHEADER; + /** STA ageout timer in ms */ + u32 StaAgeoutTimer_ms; +} PACK_END TLVBUF_STA_AGEOUT_TIMER; + +/** TLV buffer : max station number */ +typedef PACK_START struct _TLVBUF_MAX_STA_NUM +{ + /** Header */ + TLVHEADER; + /** max station number */ + u16 Max_sta_num; +} PACK_END TLVBUF_MAX_STA_NUM; + +/** TLV buffer : retry limit */ +typedef PACK_START struct _TLVBUF_RETRY_LIMIT +{ + /** Header */ + TLVHEADER; + /** retry limit */ + u8 retry_limit; +} PACK_END TLVBUF_RETRY_LIMIT; + +/* Bitmap for protocol to use */ +/** No security */ +#define PROTOCOL_NO_SECURITY 1 +/** Static WEP */ +#define PROTOCOL_STATIC_WEP 2 +/** WPA */ +#define PROTOCOL_WPA 8 +/** WPA2 */ +#define PROTOCOL_WPA2 32 +/** WP2 Mixed */ +#define PROTOCOL_WPA2_MIXED 40 + +/* Bitmap for unicast/bcast cipher type */ +/** None */ +#define CIPHER_NONE 0 +/** WEP 40 */ +#define CIPHER_WEP_40 1 +/** WEP 104 */ +#define CIPHER_WEP_104 2 +/** TKIP */ +#define CIPHER_TKIP 4 +/** AES CCMP */ +#define CIPHER_AES_CCMP 8 +/** valid cipher bitmap */ +#define CIPHER_BITMAP 0x0c + +/** TLV buffer : Authentication Mode */ +typedef PACK_START struct _TLVBUF_AUTH_MODE +{ + /** Header */ + TLVHEADER; + /** Authentication Mode */ + u8 AuthMode; +} PACK_END TLVBUF_AUTH_MODE; + +/** TLV buffer : Security Protocol */ +typedef PACK_START struct _TLVBUF_PROTOCOL +{ + /** Header */ + TLVHEADER; + /** Security protocol */ + u16 Protocol; +} PACK_END TLVBUF_PROTOCOL; + +/** TLV buffer : cipher */ +typedef PACK_START struct _TLVBUF_CIPHER +{ + /** Header */ + TLVHEADER; + /** Pairwise cipher */ + u8 PairwiseCipher; + /** Group cipher */ + u8 GroupCipher; +} PACK_END TLVBUF_CIPHER; + +/** TLV buffer : Group re-key time */ +typedef PACK_START struct _TLVBUF_GROUP_REKEY_TIMER +{ + /** Header */ + TLVHEADER; + /** Group rekey time in seconds */ + u32 GroupRekeyTime_sec; +} PACK_END TLVBUF_GROUP_REKEY_TIMER; + +/** Key_mgmt_psk */ +#define KEY_MGMT_NONE 0x04 +/** Key_mgmt_none */ +#define KEY_MGMT_PSK 0x02 + +/** TLV buffer : KeyMgmt */ +typedef PACK_START struct _TLVBUF_AKMP +{ + /** Header */ + TLVHEADER; + /** KeyMgmt */ + u16 KeyMgmt; +} PACK_END TLVBUF_AKMP; + +/** TLV buffer : Single WEP key */ +typedef PACK_START struct _TLVBUF_WEP_KEY +{ + /** Header */ + TLVHEADER; + /** Key index */ + u8 KeyIndex; + /** Default key flag */ + u8 IsDefault; + /** Key */ + u8 Key[0]; +} PACK_END TLVBUF_WEP_KEY; + +/** custom IE */ +typedef PACK_START struct _custom_ie +{ + /** IE Index */ + u16 ie_index; + /** Mgmt Subtype Mask */ + u16 mgmt_subtype_mask; + /** IE Length */ + u16 ie_length; + /** IE buffer */ + u8 ie_buffer[0]; +} PACK_END custom_ie; + +/** TLV buffer : custom IE */ +typedef PACK_START struct _tlvbuf_custom_ie +{ + /** Header */ + TLVHEADER; + /** custom IE data */ + custom_ie ie_data[0]; +} PACK_END tlvbuf_custom_ie; + +/** TLV buffer : WPA passphrase */ +typedef PACK_START struct _TLVBUF_WPA_PASSPHRASE +{ + /** Header */ + TLVHEADER; + /** WPA passphrase */ + u8 Passphrase[0]; +} PACK_END TLVBUF_WPA_PASSPHRASE; + +/** TLV buffer : Fragmentation threshold */ +typedef PACK_START struct _TLVBUF_FRAG_THRESHOLD +{ + /** Header */ + TLVHEADER; + /** Fragmentation threshold */ + u16 FragThreshold; +} PACK_END TLVBUF_FRAG_THRESHOLD; + +/* APCMD definitions */ +/** APCMD buffer */ +typedef PACK_START struct _APCMDBUF +{ + /** Header */ + APCMDHEADER; +} +PACK_END APCMDBUF; + +/** APCMD header length */ +#define APCMDHEADERLEN (sizeof(APCMDBUF)) + +/** APCMD buffer : sys_info request */ +typedef PACK_START struct _APCMDBUF_SYS_INFO_REQUEST +{ + /** Header */ + APCMDHEADER; +} PACK_END APCMDBUF_SYS_INFO_REQUEST; + +/** APCMD buffer : sys_info response */ +typedef PACK_START struct _APCMDBUF_SYS_INFO_RESPONSE +{ + /** Header */ + APCMDHEADER; + /** System information buffer */ + u8 SysInfo[64]; +} PACK_END APCMDBUF_SYS_INFO_RESPONSE; + +/** APCMD buffer : sys_reset */ +typedef PACK_START struct _APCMDBUF_SYS_RESET +{ + /** Header */ + APCMDHEADER; +} PACK_END APCMDBUF_SYS_RESET; + +/** APCMD buffer : sys_configure */ +typedef PACK_START struct _APCMDBUF_SYS_CONFIGURE +{ + /** Header */ + APCMDHEADER; + /** Action : GET or SET */ + u16 Action; +} PACK_END APCMDBUF_SYS_CONFIGURE; + +/** APCMD buffer : SNMP MIB */ +typedef PACK_START struct _APCMDBUF_SNMP_MIB +{ + /** Header */ + APCMDHEADER; + /** Action : GET or SET */ + u16 Action; +} PACK_END APCMDBUF_SNMP_MIB; +/** APCMD buffer : bss_start */ +typedef PACK_START struct _APCMDBUF_BSS_START +{ + /** Header */ + APCMDHEADER; +} PACK_END APCMDBUF_BSS_START; + +/** APCMD buffer : bss_stop */ +typedef PACK_START struct _APCMDBUF_BSS_STOP +{ + /** Header */ + APCMDHEADER; +} PACK_END APCMDBUF_BSS_STOP; + +/** APCMD buffer : sta_list request */ +typedef PACK_START struct _APCMDBUF_STA_LIST_REQUEST +{ + /** Header */ + APCMDHEADER; +} PACK_END APCMDBUF_STA_LIST_REQUEST; + +/** APCMD buffer : sta_list response */ +typedef PACK_START struct _APCMDBUF_STA_LIST_RESPONSE +{ + /** Header */ + APCMDHEADER; + /** Number of STAs */ + u16 StaCount; + /** STA information TLVs */ + TLVBUF_STA_INFO StaList[0]; +} PACK_END APCMDBUF_STA_LIST_RESPONSE; + +/** APCMD buffer : sta_deauth */ +typedef PACK_START struct _APCMDBUF_STA_DEAUTH +{ + /** Header */ + APCMDHEADER; + /** STA MAC address to deauthenticate */ + u8 StaMacAddress[ETH_ALEN]; + /** Reason Code */ + u16 ReasonCode; +} PACK_END APCMDBUF_STA_DEAUTH; + +/** TLV : BT Coex common configuration */ +typedef PACK_START struct _tlvbuf_coex_common_cfg +{ + /** Header */ + TLVHEADER; + /** Configuration bitmap */ + u32 config_bitmap; + /** Reserved */ + u32 reserved[4]; +} PACK_END tlvbuf_coex_common_cfg; + +/** TLV : BT Coex SCO configuration */ +typedef PACK_START struct _tlvbuf_coex_sco_cfg +{ + /** Header */ + TLVHEADER; + /** Qtime protection */ + u16 protection_qtime[4]; + /** Rate protection */ + u16 protection_rate; + /** ACL frequency */ + u16 acl_frequency; + /** Reserved */ + u32 reserved[4]; +} PACK_END tlvbuf_coex_sco_cfg; + +/** TLV : BT Coex ACL configuration */ +typedef PACK_START struct _tlvbuf_coex_acl_cfg +{ + /** Header */ + TLVHEADER; + /** Enabled or not */ + u16 enabled; + /** BT time */ + u16 bt_time; + /** Wlan time */ + u16 wlan_time; + /** Rate protection */ + u16 protection_rate; + /** Reserved */ + u32 reserved[4]; +} PACK_END tlvbuf_coex_acl_cfg; + +/** TLV : BT Coex statistics */ +typedef PACK_START struct _tlvbuf_coex_stats +{ + /** Header */ + TLVHEADER; + /** Null not sent */ + u32 null_not_sent; + /** Null queued */ + u32 null_queued; + /** Null not queued */ + u32 null_not_queued; + /** CF end queued */ + u32 cf_end_queued; + /** CF end not queued */ + u32 cf_end_not_queued; + /** Null allocation failures */ + u32 null_alloc_fail; + /** CF end allocation failures */ + u32 cf_end_alloc_fail; + /** Reserved */ + u32 reserved[8]; +} PACK_END tlvbuf_coex_stats; + +/** APCMD buffer : BT Coex API extension */ +typedef PACK_START struct _apcmdbuf_coex_config +{ + /** Header */ + APCMDHEADER; + /** Action : GET or SET */ + u16 action; + /** Reserved for alignment */ + u16 coex_reserved; + /** TLV buffer */ + u8 tlv_buffer[0]; +} PACK_END apcmdbuf_coex_config; + +/** Reg TYPE*/ +enum reg_commands +{ + CMD_MAC = 0, + CMD_BBP, + CMD_RF +}; + +/** APCMD buffer: Regrdwr */ +typedef PACK_START struct _APCMDBUF_REG_RDWR +{ + /** Header */ + APCMDHEADER; + /** Read or Write */ + u16 Action; + /** Register offset */ + u16 Offset; + /** Value */ + u32 Value; +} PACK_END APCMDBUF_REG_RDWR; + +/** sub-band type */ +typedef PACK_START struct _IEEEtypes_SubbandSet +{ + u8 FirstChan; /**< First channel */ + u8 NoOfChan; /**< Number of channels */ + u8 MaxTxPwr; /**< Maximum Tx power */ +} PACK_END IEEEtypes_SubbandSet_t; + +/** country code length used for 802.11D */ +#define COUNTRY_CODE_LEN 3 + +/** MAX domain SUB-BAND*/ +#define MAX_SUB_BANDS 40 + +/** Max Multi Domain Entries for G */ +#define MaxMultiDomainCapabilityEntryG 1 + +/** Max Multi Domain Entries for A */ +#define MaxMultiDomainCapabilityEntryA 31 + +/** Country code and Sub-band */ +typedef PACK_START struct domain_param +{ + TLVHEADER; + u8 CountryCode[COUNTRY_CODE_LEN]; /**< Country code */ + IEEEtypes_SubbandSet_t Subband[0]; /**< Set of subbands */ +} PACK_END domain_param_t; + +/** HostCmd_CFG_80211D */ +typedef PACK_START struct _APCMDBUF_CFG_80211D +{ + /** Header */ + APCMDHEADER; + /** Action */ + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + /** Domain parameters */ + domain_param_t Domain; +} PACK_END APCMDBUF_CFG_80211D; + +/** HostCmd_MEM_ACCESS */ +typedef PACK_START struct _APCMDBUF_MEM_ACCESS +{ + /** Header */ + APCMDHEADER; + /** Action */ + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + /** Reserved field */ + u16 Reserved; + /** Address */ + u32 Address; + /** Value */ + u32 Value; +} PACK_END APCMDBUF_MEM_ACCESS; + +/** HostCmd_EEPROM_ACCESS */ +typedef PACK_START struct _APCMDBUF_EEPROM_ACCESS +{ + /** Header */ + APCMDHEADER; + /** Action */ + u16 Action; /* 0 = ACT_GET; */ + /** Reserved field */ + u16 Offset; /* Multiples of 4 */ + /** Address */ + u16 ByteCount; /* Multiples of 4 */ + /** Value */ + u8 Value[1]; +} PACK_END APCMDBUF_EEPROM_ACCESS; + +/** Max EEPROM length */ +#define MAX_EEPROM_LEN 20 + +/**subcmd id for glbal flag */ +#define DEBUG_SUBCOMMAND_GMODE 1 +/**subcmd id for Majorid mask */ +#define DEBUG_SUBCOMMAND_MAJOREVTMASK 2 +/**subcmd id to trigger a scan */ +#define DEBUG_SUBCOMMAND_CHANNEL_SCAN 3 + +/** Channel scan entry for each channel */ +typedef PACK_START struct _CHANNEL_SCAN_ENTRY_T +{ + /** Channel Number */ + u8 chan_num; + /** Number of APs */ + u8 num_of_aps; + /** CCA count */ + u32 CCA_count; + /** Duration */ + u32 duration; + /** Channel weight */ + u32 channel_weight; +} PACK_END CHANNEL_SCAN_ENTRY_T; + +/** Channel scan entry */ +typedef PACK_START struct _CHANNEL_SCAN_ENTRY +{ + /** Number of channels */ + u8 numChannels; + /** Channel scan entry */ + CHANNEL_SCAN_ENTRY_T cst[0]; +} PACK_END CHANNEL_SCAN_ENTRY; + +/** debugConfig_t */ +typedef PACK_START union +{ + /** used in all new debug commands */ + u32 value; + /** used in DEBUG_SUBCOMMAND_GMODE */ + u8 globalDebugMode; + /** used in DEBUG_SUBCOMMAND_MAJOREVTMASK */ + u32 debugMajorIdMask; + /** used in DEBUG_SUBCOMMAND_CHANNEL_SCAN */ + CHANNEL_SCAN_ENTRY cs_entry; +} PACK_END debugConfig_t; + +/** HostCmd_SYS_DEBUG */ +typedef PACK_START struct _APCMDBUF_SYS_DEBUG +{ + /** Header */ + APCMDHEADER; + /** Action */ + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + /** Sub command */ + u32 subcmd; + /** debug parameter */ + debugConfig_t debugConfig; +} PACK_END APCMDBUF_SYS_DEBUG; + +/** HostCmd_CFG_DATA */ +typedef PACK_START struct _APCMDBUF_CFG_DATA +{ + /** Header */ + APCMDHEADER; + /** Action */ + u16 action; + /** Type */ + u16 type; + /** Data length */ + u16 data_len; + /** Data */ + u8 data[0]; +} PACK_END APCMDBUF_CFG_DATA; + +/** Maximum size of set/get configurations */ +#define MAX_CFG_DATA_SIZE 2000 /* less than + MRVDRV_SIZE_OF_CMD_BUFFER */ + +/** Host Command ID bit mask (bit 11:0) */ +#define HostCmd_CMD_ID_MASK 0x0fff +/** APCMD response check */ +#define APCMD_RESP_CHECK 0x8000 + +/* AP CMD IDs */ +/** APCMD : sys_info */ +#define APCMD_SYS_INFO 0x00ae +/** APCMD : sys_reset */ +#define APCMD_SYS_RESET 0x00af +/** APCMD : sys_configure */ +#define APCMD_SYS_CONFIGURE 0x00b0 +/** APCMD : bss_start */ +#define APCMD_BSS_START 0x00b1 +/** APCMD : bss_stop */ +#define APCMD_BSS_STOP 0x00b2 +/** APCMD : sta_list */ +#define APCMD_STA_LIST 0x00b3 +/** APCMD : sta_deauth */ +#define APCMD_STA_DEAUTH 0x00b5 +/** SNMP MIB SET/GET */ +#define HostCmd_SNMP_MIB 0x0016 +/** 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 +/** Host Command ID : EEPROM access */ +#define HostCmd_EEPROM_ACCESS 0x0059 +/** Host Command ID : Memory access */ +#define HostCmd_CMD_MEM_ACCESS 0x0086 +/** Host Command ID : 802.11D configuration */ +#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b +/** Host Command ID : Configuration data */ +#define HostCmd_CMD_CFG_DATA 0x008f +/** Host Command ID: SYS_DEBUG */ +#define APCMD_SYS_DEBUG 0x00db + +/** Host Command ID: ROBUST_COEX */ +#define HostCmd_ROBUST_COEX 0x00e0 + +/** Oid for 802.11D enable/disable */ +#define OID_80211D_ENABLE 0x0009 + +/* TLV IDs */ +/** TLV : Base */ +#define PROPRIETARY_TLV_BASE_ID 0x0100 + +/**TLV: Domain type */ +#define TLV_TYPE_DOMAIN 0x0007 + +/** TLV : SSID */ +#define MRVL_SSID_TLV_ID 0x0000 +/** TLV : Operational rates */ +#define MRVL_RATES_TLV_ID 0x0001 +/** TLV : Channel */ +#define MRVL_PHYPARAMDSSET_TLV_ID 0x0003 +/** TLV type : Scan Channels list */ +#define MRVL_CHANNELLIST_TLV_ID (PROPRIETARY_TLV_BASE_ID + 1) +/** TLV type : Authentication type */ +#define MRVL_AUTH_TLV_ID (PROPRIETARY_TLV_BASE_ID + 31) +/** TLV Id : Channel Config */ +#define MRVL_CHANNELCONFIG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 42) +/** TLV : AP MAC address */ +#define MRVL_AP_MAC_ADDRESS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 43) +/** TLV : Beacon period */ +#define MRVL_BEACON_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 44) +/** TLV : DTIM period */ +#define MRVL_DTIM_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 45) +/** TLV : Tx power */ +#define MRVL_TX_POWER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 47) +/** TLV : SSID broadcast control */ +#define MRVL_BCAST_SSID_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 48) +/** TLV : Preamble control */ +#define MRVL_PREAMBLE_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 49) +/** TLV : Antenna control */ +#define MRVL_ANTENNA_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 50) +/** TLV : RTS threshold */ +#define MRVL_RTS_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 51) +/** TLV : Radio control */ +#define MRVL_RADIO_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 52) +/** TLV : Tx data rate */ +#define MRVL_TX_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 53) +/** TLV : Packet forwarding control */ +#define MRVL_PKT_FWD_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 54) +/** TLV : STA information */ +#define MRVL_STA_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 55) +/** TLV : STA MAC address filter */ +#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56) +/** TLV : STA ageout timer */ +#define MRVL_STA_AGEOUT_TIMER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 57) +/** TLV : WEP keys */ +#define MRVL_WEP_KEY_TLV_ID (PROPRIETARY_TLV_BASE_ID + 59) +/** TLV : WPA passphrase */ +#define MRVL_WPA_PASSPHRASE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 60) +/** TLV type : protocol TLV */ +#define MRVL_PROTOCOL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 64) +/** TLV type : AKMP TLV */ +#define MRVL_AKMP_TLV_ID (PROPRIETARY_TLV_BASE_ID + 65) +/** TLV type : Cipher TLV */ +#define MRVL_CIPHER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 66) +/** TLV : Fragment threshold */ +#define MRVL_FRAG_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 70) +/** TLV : Group rekey timer */ +#define MRVL_GRP_REKEY_TIME_TLV_ID (PROPRIETARY_TLV_BASE_ID + 71) +/**TLV: Max Station number */ +#define MRVL_MAX_STA_CNT_TLV_ID (PROPRIETARY_TLV_BASE_ID + 85) +/**TLV: Retry limit */ +#define MRVL_RETRY_LIMIT_TLV_ID (PROPRIETARY_TLV_BASE_ID + 93) +/**TLV: MCBC data rate */ +#define MRVL_MCBC_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 98) +/**TLV: RSN replay protection */ +#define MRVL_RSN_REPLAY_PROT_TLV_ID (PROPRIETARY_TLV_BASE_ID + 100) +/** TLV: Management IE list */ +#define MRVL_MGMT_IE_LIST_TLV_ID (PROPRIETARY_TLV_BASE_ID + 105) +/** TLV : Coex common configuration */ +#define MRVL_BT_COEX_COMMON_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 108) +/** TLV : Coex SCO configuration */ +#define MRVL_BT_COEX_SCO_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 109) +/** TLV : Coex ACL configuration */ +#define MRVL_BT_COEX_ACL_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 110) +/** TLV : Coex stats configuration */ +#define MRVL_BT_COEX_STATS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 111) + +/** sleep_param */ +typedef struct _ps_sleep_param +{ + /** control bitmap */ + u32 ctrl_bitmap; + /** minimum sleep period (micro second) */ + u32 min_sleep; + /** maximum sleep period (micro second) */ + u32 max_sleep; +} ps_sleep_param; + +/** inactivity sleep_param */ +typedef struct _inact_sleep_param +{ + /** inactivity timeout (micro second) */ + u32 inactivity_to; + /** miniumu awake period (micro second) */ + u32 min_awake; + /** maximum awake period (micro second) */ + u32 max_awake; +} inact_sleep_param; + +/** flag for ps mode */ +#define PS_FLAG_PS_MODE 1 +/** flag for sleep param */ +#define PS_FLAG_SLEEP_PARAM 2 +/** flag for inactivity sleep param */ +#define PS_FLAG_INACT_SLEEP_PARAM 4 + +/** Disable power mode */ +#define PS_MODE_DISABLE 0 +/** Enable periodic dtim ps */ +#define PS_MODE_PERIODIC_DTIM 1 +/** Enable inactivity ps */ +#define PS_MODE_INACTIVITY 2 + +/** sleep parameter */ +#define SLEEP_PARAMETER 1 +/** inactivity sleep parameter */ +#define INACTIVITY_SLEEP_PARAMETER 2 + +/** sleep parameter : lower limit in micro-sec */ +#define PS_SLEEP_PARAM_MIN 5000 +/** sleep parameter : upper limit in micro-sec */ +#define PS_SLEEP_PARAM_MAX 32000 +/** power save awake period minimum value in micro-sec */ +#define PS_AWAKE_PERIOD_MIN 10 + +/** ps_mgmt */ +typedef struct _ps_mgmt +{ + /** flags for valid field */ + u16 flags; + /** power mode */ + u16 ps_mode; + /** sleep param */ + ps_sleep_param sleep_param; + /** inactivity sleep param */ + inact_sleep_param inact_param; +} ps_mgmt; + +/** Function Prototype Declaration */ +int mac2raw(char *mac, u8 * raw); +void print_mac(u8 * raw); +int uap_ioctl(u8 * cmd, u16 * size, u16 buf_size); +void print_auth(TLVBUF_AUTH_MODE * tlv); +void print_tlv(u8 * buf, u16 len); +void print_cipher(TLVBUF_CIPHER * tlv); +void print_rate(TLVBUF_RATES * tlv); +int string2raw(char *str, unsigned char *raw); +void print_mac_filter(TLVBUF_STA_MAC_ADDR_FILTER * tlv); +int ishexstring(void *hex); +inline int ISDIGIT(char *x); +unsigned int a2hex(char *s); +int fparse_for_hex(FILE * fp, u8 * dst); +int is_input_valid(valid_inputs cmd, int argc, char *argv[]); +int is_cipher_valid(int pairwisecipher, int groupcipher); +int get_sys_cfg_rates(u8 * rates); +int is_tx_rate_valid(u8 rate); +int is_mcbc_rate_valid(u8 rate); +void hexdump_data(char *prompt, void *p, int len, char delim); +unsigned char hexc2bin(char chr); +#endif /* _UAP_H */ |