/** @file uapcmd.c * * @brief This file contains the handling of command. * * * Copyright 2014-2020 NXP * * This software file (the File) is distributed by NXP * under the terms of the GNU General Public License Version 2, June 1991 * (the License). You may use, redistribute and/or modify the File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE * ARE EXPRESSLY DISCLAIMED. The License provides additional details about * this warranty disclaimer. * */ /**************************************************************************** Change log: 03/01/08: Initial creation ****************************************************************************/ /**************************************************************************** Header files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #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 bss_status * command * * $return N/A */ void print_sys_cfg_bss_status_usage(void) { printf("\nUsage : sys_cfg_bss_status\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("\n MODE: band config mode "); printf("\n Bit 0: ACS mode enable/disable"); printf("\n Bit 1: secondary channel is above primary channel"); printf("\n Bit 2: secondary channel is below primary channel"); printf("\n"); return; } /** * @brief Show usage information for the sys_cfg_channel * command * * $return N/A */ void print_sys_cfg_channel_ext_usage(void) { printf("\nUsage : sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]\n"); printf("\nIf CHANNEL is provided, a 'set' is performed, else a 'get' is performed."); printf("\n BAND:"); printf("\n 0 : 2.4GHz operation"); printf("\n 1 : 5GHz operation"); printf("\n MODE: band config mode "); printf("\n Bit 0: ACS mode enable/disable"); printf("\n Bit 1: secondary channel is above primary channel"); printf("\n Bit 2: secondary channel is below primary channel"); printf("\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 [CHANNEL[.BAND]]\n"); printf("\nIf CHANNELS and BANDS are provided, a 'set' is performed, else a 'get' is performed.\n"); printf("\n BAND : band of operation"); printf("\n 0 : 2.4GHZ"); printf("\n 1 : 5GHZ\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]\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."); 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,send empty SSID (length=0) in beacon"); printf("\n 1 - Enable SSID broadcast"); printf("\n 2 - Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length"); 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"); printf("\nOptions: 0 - Auto/Default"); printf("\n 1 - Short Preamble"); printf("\n 2 - Long Preamble\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 [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_tx_beacon_rate * command * * $return N/A */ void print_sys_cfg_tx_beacon_rates_usage(void) { printf("\nUsage : sys_cfg_tx_beacon_rate [TX_DATA_RATE]\n"); printf("\nOptions: 0 - Auto rate"); printf("\n >0 - Set specified beacon rate"); printf("\n empty - Get current beacon 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 255 - Auto (Open and 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 [PKT_FWD_CTRL]\n"); printf("\nPKT_FWD_CTRL: bit 0 -- Packet forwarding handled by Host (0) or Firmware (1)"); printf("\n bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1)"); printf("\n bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1)"); printf("\n bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1)"); 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 be between 100 and 864000.\n"); return; } /** * @brief Show usage information for the sys_cfg_ps_sta_ageout_timer * command * * $return N/A */ void print_sys_cfg_ps_sta_ageout_timer_usage(void) { printf("\nUsage : sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]\n"); printf("\nIf PS_STA_AGEOUT_TIMER is provided, a 'set' is performed, else a 'get' is performed."); printf("\nPS_STA_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 be between 100 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] [AKM_SUITE]\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 256 - WPA3 SAE"); printf("\n empty - Get current protocol"); printf("\n AKM_SUITE: bit 0 - KEY_MGMT_EAP"); printf("\n bit 1 - KEY_MGMT_PSK"); printf("\n bit 2 - KEY_MGMT_NONE"); printf("\n bit 8 - KEY_MGMT_PSK_SHA256"); printf("\n bit 10 - KEY_MGMT_WPA3_SAE"); printf("\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_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_pwk_cipher * command * * $return N/A */ void print_sys_cfg_pwk_cipher_usage(void) { printf("\nUsage : sys_cfg_pwk_cipher [] [PAIRWISE_CIPHER]\n"); printf("\nOptions: PROTOCOL :"); printf("\n 8 - WPA"); printf("\n 32 - WPA2"); printf("\n PAIRWISE_CIPHER : "); printf("\n 4 - TKIP"); printf("\n 8 - AES CCMP"); printf("\n 12 - AES CCMP + TKIP"); printf("\n WPA/TKIP cannot be used when uAP operates in 802.11n mode.\n"); printf("\n If only PROTOCOL is given, pairwise cipher for that protocol is displayed\n"); printf("\n empty - Get current protocol and pairwise cipher settings\n"); return; } /** * @brief Show usage information for the sys_cfg_gwk_cipher * command * * $return N/A */ void print_sys_cfg_gwk_cipher_usage(void) { printf("\nUsage : sys_cfg_gwk_cipher [GROUP_CIPHER]\n"); printf("\n GROUP_CIPHER :"); printf("\n 4 - TKIP"); printf("\n 8 - AES CCMP"); printf("\n empty - Get current group 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 sys_cfg_wpa3_sae_password * command * * $return N/A */ void print_sys_cfg_wpa3_sae_password_usage(void) { printf("\nUsage : sys_cfg_wpa3_sae_password [PASSWORD]\n"); printf("\nIf PASSWORD 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 \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.\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 be greater than or equal to zero and less than or equal to 14\n"); return; } /** * @brief Show usage information for the sys_cfg_sticky_tim_config command * * $return N/A */ void print_sys_cfg_sticky_tim_config_usage(void) { printf("\nUsage : sys_cfg_sticky_tim_config [ENABLE] [ ]\n"); printf("\nOptions: ENABLE 0 - disable"); printf("\n 1 - enable"); printf("\n 2 - enable with previous values of DURATION and STICKY_BITMASK"); printf("\n DURATION: duration for sticky TIM"); printf("\n STICKY_BITMASK: Bitmask for sticky TIM configuartion"); printf("\n empty - Get current sticky TIM configuration\n"); return; } /** * @brief Show usage information for the sys_cfg_sticky_tim_mac_addr command * * $return N/A */ void print_sys_cfg_sticky_tim_sta_mac_addr_usage(void) { printf("\nUsage : sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]\n"); printf("\nOptions: CONTROL: sticky TIM config for given station"); printf("\n STA_MAC_ADDRESS: station MAC address"); printf("\n if only STA_MAC_ADDRESS is given - Get sticky TIM configuration for that station\n"); printf("\n empty - Get current sticky TIM configuration for all associated stations\n"); return; } /** * @brief Show usage information for the sys_cfg_2040_coex command * * $return N/A */ void print_sys_cfg_2040_coex_usage(void) { printf("\nUsage : sys_cfg_2040_coex [ENABLE]\n"); printf("\nOptions: ENABLE 0 - disable"); printf("\n 1 - enable"); printf("\n empty - Get current 20/40 BSS coexistence configuration\n"); return; } /** * @brief Show usage information for the sys_cfg_eapol_pwk_hsk command * * $return N/A */ void print_sys_cfg_eapol_pwk_hsk_usage(void) { printf("\nUsage : sys_cfg_eapol_pwk_hsk [ ]\n"); printf("\nIf TIMEOUT and number of RETRIES are both provided, a 'set' is performed."); printf("\nIf no parameter is provided,a 'get' is performed."); printf("\nTIMEOUT and number of RETRIES should be greater than or equal to zero\n"); return; } /** * @brief Show usage information for the sys_cfg_eapol_gwk_hsk command * * $return N/A */ void print_sys_cfg_eapol_gwk_hsk_usage(void) { printf("\nUsage : sys_cfg_eapol_gwk_hsk [ ]\n"); printf("\nIf TIMEOUT and number of RETRIES are both provided, a 'set' is performed."); printf("\nIf no parameter is provided,a 'get' is performed."); printf("\nTIMEOUT and number of RETRIES should be greater than or equal to zero\n"); return; } /** * @brief Show usage information for the cfg_data command * * $return N/A */ void print_cfg_data_usage(void) { printf("\nUsage : cfg_data [*.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(t_u8 *rates) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_rates *tlv = NULL; t_u8 *buffer = NULL; t_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 = (t_u8 *)malloc(cmd_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return -1; } memset(buffer, 0, cmd_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_rates *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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((t_u8 *)cmd_buf, &cmd_len, cmd_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_RATES_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return -1; } /* Copy response */ if (cmd_buf->result == CMD_SUCCESS) { for (i = 0; i < tlv->length; i++) { if (tlv->operational_rates[i] != 0) { rates[rate_cnt++] = tlv->operational_rates[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(t_u8 rate) { int rate_cnt = 0; int i; t_u8 rates[MAX_DATA_RATES]; rate_cnt = get_sys_cfg_rates((t_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(t_u8 rate) { int rate_cnt = 0; int i; t_u8 rates[MAX_DATA_RATES]; rate_cnt = get_sys_cfg_rates((t_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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_ap_mac_address(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_ap_mac_address *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_ap_mac_address_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc > 1) { printf("ERR:Too many arguments.\n"); print_sys_cfg_ap_mac_address_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_ap_mac_address); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->ap_mac_addr)) != UAP_SUCCESS) { printf("ERR: %s Address \n", ret == UAP_FAILURE ? "Invalid MAC" : ret == UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast"); free(buffer); return UAP_FAILURE; } } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_AP_MAC_ADDRESS_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("AP MAC address = "); print_mac(tlv->ap_mac_addr); 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_ssid(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_ssid *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; t_u8 ssid[33]; argc--; argv++; /* Check arguments */ if (argc > 1) { printf("ERR:Too many arguments.\n"); print_sys_cfg_ssid_usage(); return UAP_FAILURE; } 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 UAP_FAILURE; } /* 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 UAP_FAILURE; } cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_ssid) + strlen(argv[0]); } /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_ssid *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_SSID_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { memset(ssid, 0, sizeof(ssid)); strncpy((char *)ssid, (char *)tlv->ssid, sizeof(ssid) - 1); 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_beacon_period(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_beacon_period *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_beacon_period_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(BEACONPERIOD, argc, argv) != UAP_SUCCESS) { print_sys_cfg_beacon_period_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_beacon_period); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_beacon_period *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->beacon_period_ms = (t_u16)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->beacon_period_ms = uap_cpu_to_le16(tlv->beacon_period_ms); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->beacon_period_ms = uap_le16_to_cpu(tlv->beacon_period_ms); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_BEACON_PERIOD_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("Beacon period = %d\n", tlv->beacon_period_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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_dtim_period(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_dtim_period *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_dtim_period_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(DTIMPERIOD, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_dtim_period_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_dtim_period); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_dtim_period *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->dtim_period = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_DTIM_PERIOD_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("DTIM period = %d\n", tlv->dtim_period); } 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for bss_status * and sends to the driver * * Usage: "sys_cfg_bss_status" * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_bss_status(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_bss_status *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_bss_status_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc != 0) { printf("ERR:Too many arguments.\n"); print_sys_cfg_bss_status_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_bss_status); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_bss_status *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_BSS_STATUS_TLV_ID; tlv->length = 2; cmd_buf->action = ACTION_GET; endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->bss_status = uap_le16_to_cpu(tlv->bss_status); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_BSS_STATUS_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { printf("BSS status = %s\n", (tlv->bss_status == 0) ? "stopped" : "started"); } else { printf("ERR:Could not get BSS status!\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** DFS Radar starting channel FCC */ #define DFS_FCC_RADAR_CHANNEL_START 52 /** DFS Radar ending channel FCC */ #define DFS_FCC_RADAR_CHANNEL_END 144 /** DFS Radar starting channel ETSI */ #define DFS_ETSI_RADAR_CHANNEL_START 52 /** DFS Radar ending channel ETSI */ #define DFS_ETSI_RADAR_CHANNEL_END 140 /** DFS Radar starting channel JAPAN */ #define DFS_JAPAN_RADAR_CHANNEL_START 52 /** DFS Radar ending channel JAPAN */ #define DFS_JAPAN_RADAR_CHANNEL_END 140 /** list of RegDomain values */ typedef enum { RegDomain_Null = 0x00, RegDomain_FCC = 0x01, RegDomain_ETSI = 0x02, RegDomain_MIC = 0x03, RegDomain_Other = 0xFF, } regdomain_e; /** mapping of region and domain code */ typedef struct { /** region */ t_u8 region[COUNTRY_CODE_LEN]; /** domain code */ regdomain_e code; } region_code_mapping_t; static region_code_mapping_t region_code_mapping[] = { {"US ", RegDomain_FCC}, /* US FCC 0x10 */ {"SG ", RegDomain_FCC}, /* Singapore 0x10 */ {"EU ", RegDomain_ETSI}, /* ETSI 0x30 */ {"AU ", RegDomain_ETSI}, /* Australia 0x30 */ {"KR ", RegDomain_ETSI}, /* Republic Of Korea 0x30 */ {"JP ", RegDomain_MIC}, /* Japan 0x40 */ {"J1 ", RegDomain_MIC}, /* Japan1 0x41 */ }; /** * @brief This function converts region string to region code * * @param region_string Region string * * @return Region code */ regdomain_e region_string_2_region_code(char *region_string) { t_u8 i; t_u8 size = sizeof(region_code_mapping) / sizeof(region_code_mapping_t); for (i = 0; i < COUNTRY_CODE_LEN && region_string[i]; i++) { region_string[i] = toupper(region_string[i]); } for (i = 0; i < size; i++) { if (!memcmp(region_string, region_code_mapping[i].region, COUNTRY_CODE_LEN)) { return (region_code_mapping[i].code); } } /* default is US */ return (region_code_mapping[0].code); } /** * @brief Checks if channel is dfs channel and allow only if 11h is enabled. * * @param channel Channel * @param country Country * @return UAP_FAILURE/UAP_SUCCESS */ int is_dfs_channel(int channel, char *country) { regdomain_e region; t_u8 DFS_RadarDetectChannelStart = DFS_FCC_RADAR_CHANNEL_START; t_u8 DFS_RadarDetectChannelEnd = DFS_FCC_RADAR_CHANNEL_END; region = region_string_2_region_code(country); /* set radar start channel and end channel */ switch (region) { default: /* use FCC as default setting */ case RegDomain_FCC: DFS_RadarDetectChannelStart = DFS_FCC_RADAR_CHANNEL_START; DFS_RadarDetectChannelEnd = DFS_FCC_RADAR_CHANNEL_END; break; case RegDomain_ETSI: DFS_RadarDetectChannelStart = DFS_ETSI_RADAR_CHANNEL_START; DFS_RadarDetectChannelEnd = DFS_ETSI_RADAR_CHANNEL_END; break; case RegDomain_MIC: DFS_RadarDetectChannelStart = DFS_JAPAN_RADAR_CHANNEL_START; DFS_RadarDetectChannelEnd = DFS_JAPAN_RADAR_CHANNEL_END; break; } if (channel < DFS_RadarDetectChannelStart || channel > DFS_RadarDetectChannelEnd) { return UAP_FAILURE; } return UAP_SUCCESS; } /** * @brief Checks if channel is valid for given 11d domain. * * @param channel Channel * @param band Band * @param set_domain Flag to indicate update domain info with this channel * @return UAP_FAILURE/UAP_SUCCESS */ int check_channel_validity_11d(int channel, int band, int set_domain) { apcmdbuf_cfg_80211d *cmd_buf = NULL; ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS]; t_u8 *buf = NULL; t_u16 cmd_len; t_u16 buf_len = 0; int ret = UAP_FAILURE; int i, j, found = 0; t_u8 no_of_sub_band = 0; char country[4] = { ' ', ' ', 0, 0 }; buf_len = sizeof(apcmdbuf_cfg_80211d); buf_len += MAX_SUB_BANDS * sizeof(ieeetypes_subband_set_t); buf = (t_u8 *)malloc(buf_len); if (!buf) { printf("ERR:Cannot allocate buffer from command!\n"); return UAP_FAILURE; } memset(buf, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_cfg_80211d *)buf; cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t)); cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->result = 0; cmd_buf->seq_num = 0; cmd_buf->action = ACTION_GET; cmd_buf->action = uap_cpu_to_le16(cmd_buf->action); cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO; ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); if (ret == UAP_SUCCESS) { if (cmd_buf->result == CMD_SUCCESS) { /* Check channel against US if country code is not set */ if (! (cmd_buf->domain.country_code[0] || cmd_buf->domain.country_code[1] || cmd_buf->domain.country_code[2])) { country[0] = 'U'; country[1] = 'S'; country[2] = '\0'; /* Do not send this country code to FW though */ set_domain = 0; } else { country[0] = cmd_buf->domain.country_code[0]; country[1] = cmd_buf->domain.country_code[1]; } if (cmd_buf->domain.country_code[2] == 'I') { if ((channel != 36) && (channel != 40) && (channel != 44) && (channel != 48)) { printf("ERR: Channel not valid for indoor operation!\n"); ret = UAP_FAILURE; goto done; } } if (is_dfs_channel(channel, country) == UAP_SUCCESS) { printf("DFS channel selected.\n"); } no_of_sub_band = parse_domain_file(country, band, sub_bands, NULL); /* copy third character of country code here as domain file cannot handle it */ country[2] = cmd_buf->domain.country_code[2]; if (no_of_sub_band == UAP_FAILURE) { printf("Parsing of domain configuration file failed\n"); ret = UAP_FAILURE; goto done; } for (i = 0; i < no_of_sub_band; i++) { for (j = 0; j < sub_bands[i].no_of_chan; j++) { if (channel == (sub_bands[i].first_chan + j)) { found = 1; break; } } if (found) break; } if (!found) { printf("ERR:Invalid channel %d for given domain!\n", channel); ret = UAP_FAILURE; goto done; } } else { printf("ERR:Command Response incorrect!\n"); ret = UAP_FAILURE; goto done; } } else { printf("ERR:Command sending failed!\n"); goto done; } if (found && set_domain) { /* If channel is valid then set domain_info with new band */ memset(buf, 0, buf_len); buf_len = sizeof(apcmdbuf_cfg_80211d) + no_of_sub_band * sizeof(ieeetypes_subband_set_t); cmd_buf = (apcmdbuf_cfg_80211d *)buf; cmd_len = buf_len; cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->result = 0; cmd_buf->seq_num = 0; cmd_buf->action = ACTION_SET; cmd_buf->action = uap_cpu_to_le16(cmd_buf->action); cmd_buf->cmd_code = 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_subband_set_t))); memset(cmd_buf->domain.country_code, ' ', sizeof(cmd_buf->domain.country_code)); memcpy(cmd_buf->domain.country_code, country, strlen(country)); memcpy(cmd_buf->domain.subband, sub_bands, no_of_sub_band * sizeof(ieeetypes_subband_set_t)); ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); if (ret == UAP_SUCCESS) { if (cmd_buf->result == CMD_SUCCESS) { ret = UAP_SUCCESS; } else { printf("ERR:Command Response incorrect!\n"); ret = UAP_FAILURE; goto done; } } else { printf("ERR:Command sending failed!\n"); ret = UAP_FAILURE; goto done; } } done: if (buf) free(buf); return ret; } /** * @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 * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_channel(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_channel_config *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; int mode = 0; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_channel_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(CHANNEL, argc, argv) != UAP_SUCCESS) { print_sys_cfg_channel_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_channel_config *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_CHANNELCONFIG_TLV_ID; tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; if (argc == 1) { tlv->chan_number = (t_u8)atoi(argv[0]); memset(&(tlv->bandcfg), 0, sizeof(tlv->bandcfg)); } else { mode = atoi(argv[1]); memset(&(tlv->bandcfg), 0, sizeof(tlv->bandcfg)); if (mode & BITMAP_ACS_MODE) { int mode; if (uap_ioctl_dfs_repeater_mode(&mode) == UAP_SUCCESS) { if (mode) { printf("ERR: ACS in DFS Repeater mode" " is not allowed\n"); ret = UAP_FAILURE; goto done; } } tlv->bandcfg.scanMode = SCAN_MODE_ACS; } if (mode & BITMAP_CHANNEL_ABOVE) tlv->bandcfg.chan2Offset = SEC_CHAN_ABOVE; if (mode & BITMAP_CHANNEL_BELOW) tlv->bandcfg.chan2Offset = SEC_CHAN_BELOW; tlv->chan_number = (t_u8)atoi(argv[0]); } if (atoi(argv[0]) > MAX_CHANNELS_BG) { tlv->bandcfg.chanBand = BAND_5GHZ; } } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("Mode = %s\n", (tlv->bandcfg.scanMode == SCAN_MODE_ACS) ? "ACS" : "Manual"); printf("Channel = %d\n", tlv->chan_number); if (tlv->bandcfg.chan2Offset == SEC_CHAN_NONE) printf("no secondary channel\n"); else if (tlv->bandcfg.chan2Offset == SEC_CHAN_ABOVE) printf("secondary channel is above primary channel\n"); else if (tlv->bandcfg.chan2Offset == SEC_CHAN_BELOW) printf("secondary channel is below primary channel\n"); } 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } done: if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for channel * and sends to the driver * * Usage: "sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]" * if CHANNEL is provided, a 'set' is performed * else a 'get' is performed * if BAND is provided, a 'set' is performed with band info(2.4GHz/5GHz) * if MODE is provided, a 'set' is performed with mode (ACS/secondary channel) * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_channel_ext(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_channel_config *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; int mode = 0; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_channel_ext_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(CHANNEL_EXT, argc, argv) != UAP_SUCCESS) { print_sys_cfg_channel_ext_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_channel_config *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_CHANNELCONFIG_TLV_ID; tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; tlv->chan_number = (t_u8)atoi(argv[0]); if (argc == 1) { if (atoi(argv[0]) > MAX_CHANNELS_BG) tlv->bandcfg.chanBand = BAND_5GHZ; } else { if (atoi(argv[1]) == 0) { tlv->bandcfg.chanBand = BAND_2GHZ; } else { tlv->bandcfg.chanBand = BAND_5GHZ; } if (argc == 3) { mode = atoi(argv[2]); if (mode & BITMAP_ACS_MODE) { int mode; if (uap_ioctl_dfs_repeater_mode(&mode) == UAP_SUCCESS) { if (mode) { printf("ERR: ACS in DFS Repeater mode" " is not allowed\n"); ret = UAP_FAILURE; goto done; } } tlv->bandcfg.scanMode = SCAN_MODE_ACS; } if (mode & BITMAP_CHANNEL_ABOVE) tlv->bandcfg.chan2Offset = SEC_CHAN_ABOVE; if (mode & BITMAP_CHANNEL_BELOW) tlv->bandcfg.chan2Offset = SEC_CHAN_BELOW; } } } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("Mode = %s\n", (tlv->bandcfg.scanMode == SCAN_MODE_ACS) ? "ACS" : "Manual"); printf("Channel = %d\n", tlv->chan_number); printf("Band = %s\n", (tlv->bandcfg.chanBand == BAND_5GHZ) ? "5GHz" : "2.4GHz"); if (tlv->bandcfg.chan2Offset == SEC_CHAN_NONE) printf("no secondary channel\n"); else if (tlv->bandcfg.chan2Offset == SEC_CHAN_ABOVE) printf("secondary channel is above primary channel\n"); else if (tlv->bandcfg.chan2Offset == SEC_CHAN_BELOW) printf("secondary channel is below primary channel\n"); } 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } done: if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for channel list * and sends to the driver * * Usage: "sys_cfg_scan_channels [CHANNEL[.BAND]]" * if CHANNEL and BAND are provided, a 'set' is performed * else a 'get' is performed * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_scan_channels(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_channel_list *tlv = NULL; channel_list *pchan_list = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_FAILURE; int opt; int i; int scan_channels_band; int chan_number = 0; int band_flag = -1; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_scan_channels_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(SCANCHANNELS, argc, argv) != UAP_SUCCESS) { print_sys_cfg_scan_channels_usage(); return UAP_FAILURE; } /* 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 = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* LOCATE HEADERS */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_channel_list *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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; pchan_list = tlv->chan_list; for (i = 0; i < argc; i++) { band_flag = -1; sscanf(argv[i], "%d.%d", &chan_number, &band_flag); pchan_list->chan_number = chan_number; pchan_list->bandcfg.chanBand = BAND_2GHZ; if (((band_flag != -1) && (band_flag)) || (chan_number > MAX_CHANNELS_BG)) { pchan_list->bandcfg.chanBand = BAND_5GHZ; } scan_channels_band = BAND_B | BAND_G; if ((scan_channels_band != BAND_A) && (pchan_list->bandcfg.chanBand == BAND_5GHZ)) { scan_channels_band = BAND_A; } if (check_channel_validity_11d (pchan_list->chan_number, scan_channels_band, 0) == UAP_FAILURE) { free(buffer); return UAP_FAILURE; } pchan_list++; } } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_CHANNELLIST_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* 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 UAP_FAILURE; } pchan_list = tlv->chan_list; for (i = 0; (unsigned int)i < (tlv->length / sizeof(channel_list)); i++) { printf("\n%d\t%sGHz", pchan_list->chan_number, (pchan_list->bandcfg.chanBand == BAND_5GHZ) ? "5" : "2.4"); pchan_list++; } printf("\n"); } else { printf("Scan Channel List setting successful\n"); } } else { printf("ERR:Could not %s scan channel list!\n", argc ? "SET" : "GET"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_rates_ext(int argc, char *argv[]) { int i, j = 0, found = 0; int opt; int rflag = 0, mflag = 0; char *argv_rate[14]; int argc_rate = 0; char *argv_mrate[1]; int mrate_found = UAP_FAILURE; t_u8 *tlv_buf = NULL; tlvbuf_mcbc_data_rate *tlv_mrate = NULL; tlvbuf_rates *tlv_rate = NULL; t_u8 *buffer = NULL; apcmdbuf_sys_configure *cmd_buf = NULL; int ret = UAP_SUCCESS; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int output[3][2]; char *keywords[3] = { "rates", "mbrate" }; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_rates_ext_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; if (argc) { /* * SET */ parse_input(argc, argv, output); for (i = 0; i < 3; i++) { if (output[i][0] == -1) { for (j = 0; j < 3; j++) { if (output[j][0] == 0) found = 1; } if (!found) { printf("%s keyword not specified!\n", keywords[i]); ret = UAP_FAILURE; goto done; } } } /* * 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)); memset(argv_rate[i], 0, sizeof(char) * (strlen(argv[j]) + 1)); strncpy(argv_rate[i], argv[j], strlen(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(); ret = UAP_FAILURE; goto done; } mflag = 1; argv_mrate[0] = (char *)malloc(sizeof(char) * (strlen(argv[j]) + 1)); memset(argv_mrate[0], 0, sizeof(char) * (strlen(argv[j]) + 1)); strncpy(argv_mrate[0], argv[output[1][0] + 1], strlen(argv[j])); } if (!rflag && !mflag) { printf("ERR: Invalid input\n"); print_sys_cfg_rates_ext_usage(); ret = UAP_FAILURE; 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(); ret = UAP_FAILURE; 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(); ret = UAP_FAILURE; goto done; } if (!rflag && mflag) { /* * Check mrate 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(); ret = UAP_FAILURE; goto done; } } else if (rflag && mflag) { /* * Check mrate 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 (mflag && A2HEXDECIMAL(argv_mrate[0]) && !(mrate_found == UAP_SUCCESS)) { printf("ERR: mrate not valid\n"); ret = UAP_FAILURE; goto done; } } /* Post-parsing */ cmd_len = sizeof(apcmdbuf_sys_configure); if (rflag) cmd_len += sizeof(tlvbuf_rates) + argc_rate; if (mflag) cmd_len += sizeof(tlvbuf_mcbc_data_rate); } else { /* GET */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rates) + MAX_RATES + sizeof(tlvbuf_mcbc_data_rate); } buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Fill the command buffer */ cmd_buf = (apcmdbuf_sys_configure *)buffer; cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->operational_rates[i] = (t_u8)A2HEXDECIMAL(argv_rate[i]); } tlv_buf += tlv_rate->length + sizeof(tlvbuf_rates); endian_convert_tlv_header_out(tlv_rate); } if (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->mcbc_datarate = 0; if (mflag) { tlv_mrate->mcbc_datarate = (t_u16)A2HEXDECIMAL(argv_mrate[0]) & ~BASIC_RATE_SET_BIT; tlv_mrate->mcbc_datarate = uap_cpu_to_le16(tlv_mrate->mcbc_datarate); } tlv_buf += sizeof(tlvbuf_mcbc_data_rate); endian_convert_tlv_header_out(tlv_mrate); } /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); tlv_buf = buffer + sizeof(apcmdbuf_sys_configure); if (ret == UAP_SUCCESS) { /* Verify response */ if (cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { printf("ERR:Corrupted response! cmd_code=%x\n", cmd_buf->cmd_code); ret = UAP_FAILURE; goto done; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc) { printf("Rates setting successful\n"); } else { print_tlv((t_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"); ret = UAP_FAILURE; } } 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 (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_rates(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_rates *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int i = 0; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_rates_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(RATE, argc, argv) != UAP_SUCCESS) { print_sys_cfg_rates_usage(); return UAP_FAILURE; } 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 = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_rates *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->operational_rates[i] = (t_u8)A2HEXDECIMAL(argv[i]); } } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (uap_le16_to_cpu(tlv->tag) != MRVL_RATES_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, uap_le16_to_cpu(tlv->tag)); free(buffer); return UAP_FAILURE; } /* 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Checks if tx power is valid for given 11d domain. * * @param tx_pwr tx power * @return UAP_FAILURE/UAP_SUCCESS */ int check_tx_pwr_validity_11d(t_u8 tx_pwr) { apcmdbuf_sys_configure *cmd_buf1 = NULL; apcmdbuf_cfg_80211d *cmd_buf2 = NULL; tlvbuf_channel_config *tlv = NULL; ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS]; t_u8 *buf = NULL; t_u16 cmd_len; t_u16 buf_len = 0; int ret = UAP_FAILURE; int i, found = 0, band = BAND_B | BAND_G; t_u8 no_of_sub_band = 0, channel = 0; char country[4] = { ' ', ' ', 0, 0 }; /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config); /* Initialize the command buffer */ buf = (t_u8 *)malloc(cmd_len); if (!buf) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buf, 0, cmd_len); /* Locate headers */ cmd_buf1 = (apcmdbuf_sys_configure *)buf; tlv = (tlvbuf_channel_config *)(buf + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf1->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf1->size = cmd_len; cmd_buf1->seq_num = 0; cmd_buf1->result = 0; tlv->tag = MRVL_CHANNELCONFIG_TLV_ID; tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN; cmd_buf1->action = ACTION_GET; endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf1, &cmd_len, cmd_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf1->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf1->cmd_code, tlv->tag); free(buf); return UAP_FAILURE; } /* Print response */ if (cmd_buf1->result == CMD_SUCCESS) { channel = tlv->chan_number; printf("channel=%d\n", channel); } else { printf("ERR:Could not get channel!\n"); free(buf); return UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); free(buf); return UAP_FAILURE; } /* free current buffer */ free(buf); if (channel > MAX_CHANNELS_BG) band = BAND_A; /* initialize second command length and buffer */ buf_len = sizeof(apcmdbuf_cfg_80211d); buf_len += MAX_SUB_BANDS * sizeof(ieeetypes_subband_set_t); buf = (t_u8 *)malloc(buf_len); if (!buf) { printf("ERR:Cannot allocate buffer from command!\n"); return UAP_FAILURE; } memset(buf, 0, buf_len); /* Locate headers */ cmd_buf2 = (apcmdbuf_cfg_80211d *)buf; cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t)); cmd_buf2->size = cmd_len - BUF_HEADER_SIZE; cmd_buf2->result = 0; cmd_buf2->seq_num = 0; cmd_buf2->action = ACTION_GET; cmd_buf2->action = uap_cpu_to_le16(cmd_buf2->action); cmd_buf2->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO; ret = uap_ioctl((t_u8 *)cmd_buf2, &cmd_len, buf_len); if (ret == UAP_SUCCESS) { if (cmd_buf2->result == CMD_SUCCESS) { if (cmd_buf2->domain.country_code[0] || cmd_buf2->domain.country_code[1] || cmd_buf2->domain.country_code[2]) { country[0] = cmd_buf2->domain.country_code[0]; country[1] = cmd_buf2->domain.country_code[1]; if (cmd_buf2->domain.country_code[2] == 'I') { if (tx_pwr > MAX_TX_PWR_INDOOR) { printf("Transmit power invalid for indoor operation!\n"); ret = UAP_FAILURE; goto done; } } no_of_sub_band = parse_domain_file(country, band, sub_bands, NULL); if (no_of_sub_band == UAP_FAILURE) { printf("Parsing of domain configuration file failed\n"); ret = UAP_FAILURE; goto done; } for (i = 0; i < no_of_sub_band; i++) { if (tx_pwr <= (sub_bands[i].max_tx_pwr)) { found = 1; break; } } if (!found) { printf("ERR:Invalid transmit power for given domain!\n"); ret = UAP_FAILURE; goto done; } } } else { printf("ERR:Command Response incorrect!\n"); ret = UAP_FAILURE; goto done; } } else { printf("ERR:Command sending failed!\n"); } done: if (buf) free(buf); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_tx_power(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_tx_power *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; t_u8 state = 0; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_tx_power_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(TXPOWER, argc, argv) != UAP_SUCCESS) { print_sys_cfg_tx_power_usage(); return UAP_FAILURE; } /* Check if tx power is valid for given domain. */ if (argc) { ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state), &state); if (state) { ret = check_tx_pwr_validity_11d(atoi(argv[0])); if (ret == UAP_FAILURE) { print_sys_cfg_tx_power_usage(); return UAP_FAILURE; } } } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tx_power); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_tx_power *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->tx_power_dbm = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_TX_POWER_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("Tx power = %d dBm\n", tlv->tx_power_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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_bcast_ssid_ctl(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_bcast_ssid_ctl *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_bcast_ssid_ctl_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(BROADCASTSSID, argc, argv) != UAP_SUCCESS) { print_sys_cfg_bcast_ssid_ctl_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_bcast_ssid_ctl); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->bcast_ssid_ctl = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_BCAST_SSID_CTL_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("SSID broadcast is %s\n", (tlv->bcast_ssid_ctl == 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_preamble_ctl(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_preamble_ctl *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_preamble_ctl_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(PREAMBLETYPE, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_preamble_ctl_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_preamble_ctl); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_preamble_ctl *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_PREAMBLE_CTL_TLV_ID; tlv->length = 1; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; tlv->preamble_type = (t_u16)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_PREAMBLE_CTL_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("Preamble type is %s\n", (tlv->preamble_type == 0) ? "auto" : ((tlv->preamble_type == 1) ? "short" : "long")); } else { printf("Preamble type setting successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get preamble type!\n"); } else { printf("ERR:Could not set preamble type!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_rts_threshold(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_rts_threshold *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_rts_threshold_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(RTSTHRESH, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_rts_threshold_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rts_threshold); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_rts_threshold *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->rts_threshold = (t_u16)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->rts_threshold = uap_cpu_to_le16(tlv->rts_threshold); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->rts_threshold = uap_le16_to_cpu(tlv->rts_threshold); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_RTS_THRESHOLD_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("RTS threshold = %d\n", tlv->rts_threshold); } 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_frag_threshold(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_frag_threshold *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_frag_threshold_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(FRAGTHRESH, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_frag_threshold_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_frag_threshold); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_frag_threshold *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->frag_threshold = (t_u16)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->frag_threshold = uap_cpu_to_le16(tlv->frag_threshold); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->frag_threshold = uap_le16_to_cpu(tlv->frag_threshold); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_FRAG_THRESHOLD_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("Fragmentation threshold = %d\n", tlv->frag_threshold); } else { printf("Fragmentation threshold setting successful\n"); } } else { if (argc == 1) { printf("ERR:Could not set Fragmentation threshold!\n"); } else { printf("ERR:Could not get Fragmentation threshold!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_rsn_replay_prot(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_rsn_replay_prot *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_rsn_replay_prot_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(RSNREPLAYPROT, argc, argv) != UAP_SUCCESS) { print_sys_cfg_rsn_replay_prot_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rsn_replay_prot); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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 = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_RSN_REPLAY_PROT_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->Tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_mcbc_data_rate(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_mcbc_data_rate *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_mcbc_data_rates_usage(); return UAP_SUCCESS; } } 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 UAP_FAILURE; } 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 UAP_FAILURE; } } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_mcbc_data_rate); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->mcbc_datarate = (t_u16)A2HEXDECIMAL(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->mcbc_datarate = uap_cpu_to_le16(tlv->mcbc_datarate); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->mcbc_datarate = uap_le16_to_cpu(tlv->mcbc_datarate); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_MCBC_DATA_RATE_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { if (tlv->mcbc_datarate == 0) { printf("MCBC data rate is auto\n"); } else { printf("MCBC data rate = 0x%x\n", tlv->mcbc_datarate); } } 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for Tx beacon rates * and sends to the driver * * Usage: "sys_cfg_tx_beacon_rate [TX_BEACON_RATE]" * * Options: 0 - Auto rate * >0 - Set specified data rate * empty - Get current data rate * * TX_BEACON_RATE is represented in units of 500 kbps * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_tx_beacon_rate(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_tx_data_rate *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_tx_beacon_rates_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc) { if (is_input_valid(TXBEACONRATE, argc, argv) != UAP_SUCCESS) { printf("ERR: Invalid input\n"); return UAP_FAILURE; } else if ((A2HEXDECIMAL(argv[0]) != 0) && (is_tx_rate_valid(A2HEXDECIMAL(argv[0])) != UAP_SUCCESS)) { printf("ERR: invalid tx beacon rate."); return UAP_FAILURE; } } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tx_data_rate); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_TX_BEACON_RATE_TLV_ID; tlv->length = 2; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; tlv->tx_data_rate = (t_u16)A2HEXDECIMAL(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->tx_data_rate = uap_cpu_to_le16(tlv->tx_data_rate); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->tx_data_rate = uap_le16_to_cpu(tlv->tx_data_rate); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_TX_BEACON_RATE_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { if (tlv->tx_data_rate == 0) { printf("Tx beacon rate is auto\n"); } else { printf("Tx beacon rate = 0x%x\n", tlv->tx_data_rate); } } else { printf("Tx beacon rate setting successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get tx beacon rate!\n"); } else { printf("ERR:Could not set tx beacon rate!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for packet forwarding * and sends to the driver * * Usage: "sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]" * * PKT_FWD_CTRL: bit 0 -- Packet forwarding handled by Host (0) or Firmware (1) * bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1) * bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1) * bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1) * empty - Get current packet forwarding setting * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_pkt_fwd_ctl(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_pkt_fwd_ctl *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_pkt_fwd_ctl_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(PKTFWD, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_pkt_fwd_ctl_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_pkt_fwd_ctl); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->pkt_fwd_ctl = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_PKT_FWD_CTL_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("%s handles packet forwarding -\n", ((tlv->pkt_fwd_ctl & PKT_FWD_FW_BIT) == 0) ? "Host" : "Firmware"); printf("\tIntra-BSS broadcast packets are %s\n", ((tlv-> pkt_fwd_ctl & PKT_FWD_INTRA_BCAST) == 0) ? "allowed" : "denied"); printf("\tIntra-BSS unicast packets are %s\n", ((tlv-> pkt_fwd_ctl & PKT_FWD_INTRA_UCAST) == 0) ? "allowed" : "denied"); printf("\tInter-BSS unicast packets are %s\n", ((tlv-> pkt_fwd_ctl & PKT_FWD_INTER_UCAST) == 0) ? "allowed" : "denied"); } 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 100 and 864000 * * STA_AGEOUT_TIMER is represented in units of 100 ms * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_sta_ageout_timer(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_sta_ageout_timer *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_sta_ageout_timer_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(STAAGEOUTTIMER, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_sta_ageout_timer_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_sta_ageout_timer); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->sta_ageout_timer_ms = (t_u32)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->sta_ageout_timer_ms = uap_cpu_to_le32(tlv->sta_ageout_timer_ms); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->sta_ageout_timer_ms = uap_le32_to_cpu(tlv->sta_ageout_timer_ms); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_STA_AGEOUT_TIMER_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("STA ageout timer value = %d\n", (int)tlv->sta_ageout_timer_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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for PS STA ageout timer * and sends to the driver * * Usage: "sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]" * if PS_STA_AGEOUT_TIMER is provided, a 'set' is performed * else a 'get' is performed. * The value should between 100 and 864000 * * PS_STA_AGEOUT_TIMER is represented in units of 100 ms * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_ps_sta_ageout_timer(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_ps_sta_ageout_timer *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_ps_sta_ageout_timer_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(PSSTAAGEOUTTIMER, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_ps_sta_ageout_timer_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_ps_sta_ageout_timer); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_ps_sta_ageout_timer *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_PS_STA_AGEOUT_TIMER_TLV_ID; tlv->length = 4; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; tlv->ps_sta_ageout_timer_ms = (t_u32)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->ps_sta_ageout_timer_ms = uap_cpu_to_le32(tlv->ps_sta_ageout_timer_ms); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->ps_sta_ageout_timer_ms = uap_le32_to_cpu(tlv->ps_sta_ageout_timer_ms); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_PS_STA_AGEOUT_TIMER_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("PS STA ageout timer value = %d\n", (int)tlv->ps_sta_ageout_timer_ms); } else { printf("PS STA ageout timer setting successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get PS STA ageout timer!\n"); } else { printf("ERR:Could not set PS STA ageout timer!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_auth(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_auth_mode *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_auth_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(AUTHMODE, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_auth_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_auth_mode); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_auth_mode *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->auth_mode = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_AUTH_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_protocol(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_protocol *tlv = NULL; tlvbuf_akmp *akmp_tlv = NULL; t_u8 *buffer = NULL; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; t_u16 cmd_len = 0; int ret = UAP_SUCCESS; int opt; int get_akm_val = 0; int resend = 0; t_u16 tlv_val_16 = 0; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_protocol_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(PROTOCOL, argc, argv) != UAP_SUCCESS || is_input_valid(AKM_SUITE, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_protocol_usage(); return UAP_FAILURE; } if ((argc == 1) && ((atoi(argv[0]) == PROTOCOL_WPA) || (atoi(argv[0]) == PROTOCOL_WPA2) || (atoi(argv[0]) == PROTOCOL_WPA2_MIXED) || (atoi(argv[0]) == PROTOCOL_WPA3_SAE) )) { get_akm_val = 1; } /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } /* case such as ./uaputl.exe sys_cfg_protocol 8/32/40 */ /* Don't assume PSK in such cases, query FW and then set */ do { memset(buffer, 0, buf_len); /* 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); } /* 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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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 = 4; /* sizeof(tlvbuf_akmp) - TLVHEADER_LEN */ } else { cmd_buf->action = ACTION_SET; tlv->protocol = (t_u16)atoi(argv[0]); printf("protocol: 0x%x\n", tlv->protocol); if (tlv->protocol & (PROTOCOL_WPA | PROTOCOL_WPA2 | PROTOCOL_WPA3_SAE)) { akmp_tlv->tag = MRVL_AKMP_TLV_ID; akmp_tlv->length = 4; /* sizeof(tlvbuf_akmp) - TLVHEADER_LEN */ if (argc == 2) { akmp_tlv->key_mgmt = (t_u16)A2HEXDECIMAL(argv[1]); } else { akmp_tlv->key_mgmt = tlv_val_16; // AKM SUITE from FW in 2nd iteration if (get_akm_val) { /* Get AKM SUITE val from FW */ cmd_buf->action = ACTION_GET; resend = 1; } else resend = 0; } printf("KeyMgmt: 0x%x\n", akmp_tlv->key_mgmt); akmp_tlv->key_mgmt = uap_cpu_to_le16(akmp_tlv->key_mgmt); } } 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((t_u8 *)cmd_buf, &cmd_len, buf_len); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if (cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, uap_le16_to_cpu(tlv->tag)); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { print_tlv((t_u8 *)tlv, cmd_buf->size - sizeof(apcmdbuf_sys_configure) + BUF_HEADER_SIZE); } else { if (get_akm_val) { get_akm_val = 0; /* AKM Suite value from FW */ tlv_val_16 = *(t_u8 *)&akmp_tlv-> key_mgmt; tlv_val_16 |= (* ((t_u8 *)&akmp_tlv-> key_mgmt + 1) << 8); } 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } } while (resend && (ret == UAP_SUCCESS)); if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_wep_key(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_wep_key *tlv = NULL; t_u8 *buffer = NULL; t_u8 *tmp_buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; 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 UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc > 12) { printf("ERR:Too many arguments.\n"); print_sys_cfg_wep_key_usage(); return UAP_FAILURE; } else if ((argc > 1) && ((argc % 3) != 0)) { printf("ERR:Illegal number of parameters.\n"); print_sys_cfg_wep_key_usage(); return UAP_FAILURE; } 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 UAP_FAILURE; } 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 UAP_FAILURE; } 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)]), (t_u32)strlen(argv[(3 * i) + 2])); print_sys_cfg_wep_key_usage(); return UAP_FAILURE; } 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 UAP_FAILURE; } } } } 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 UAP_FAILURE; } } /* 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; } else { cmd_len = sizeof(apcmdbuf_sys_configure); } /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->seq_num = 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->key_index = 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 */ tmp_buffer = realloc(buffer, (cmd_len + sizeof(tlvbuf_wep_key) + key_len)); if (!tmp_buffer) { printf("ERR:Cannot append WEP key configurations TLV!\n"); free(buffer); return UAP_FAILURE; } else { buffer = tmp_buffer; tmp_buffer = NULL; } /* 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->key_index = (t_u8)keyindex; tlv->is_default = (t_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((t_u8 *)cmd_buf, &cmd_len, buf_len); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if (cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { printf("ERR:Corrupted response!\n"); free(buffer); return UAP_FAILURE; } /* 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((t_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"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for cipher configurations * and sends to the driver * * Usage: "sys_cfg_cipher [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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_cipher(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_cipher *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_cipher_usage(); return UAP_FAILURE; } } argc -= optind; argv += optind; /* Check arguments */ if ((argc != 0) && (argc != 2)) { printf("ERR:wrong arguments.\n"); print_sys_cfg_cipher_usage(); return UAP_FAILURE; } if (argc == 2) { if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)) { print_sys_cfg_cipher_usage(); return UAP_FAILURE; } if (atoi(argv[0]) & ~CIPHER_BITMAP) { printf("ERR:Illegal PAIRWISE_CIPHER parameter %s.\n", argv[0]); print_sys_cfg_cipher_usage(); return UAP_FAILURE; } if (atoi(argv[1]) & ~CIPHER_BITMAP) { printf("ERR:Illegal GROUP_CIPHER parameter %s.\n", argv[1]); print_sys_cfg_cipher_usage(); return UAP_FAILURE; } if (is_cipher_valid(atoi(argv[0]), atoi(argv[1])) != UAP_SUCCESS) { printf("ERR:Wrong group and pairwise cipher combination!\n"); print_sys_cfg_cipher_usage(); return UAP_FAILURE; } } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_cipher); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_cipher *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->pairwise_cipher = (t_u8)atoi(argv[0]); tlv->group_cipher = (t_u8)atoi(argv[1]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_CIPHER_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for pairwise cipher configurations * and sends to the driver * * Usage: "sys_cfg_pwk_cipher [] [PAIRWISE_CIPHER]" * * Options: PROTOCOL : Bit 3 - WPA * Bit 5 - WPA2 * PAIRWISE_CIPHER : Bit 2 - TKIP * Bit 3 - AES CCMP * empty - Get current pairwise cipher settings * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_pwk_cipher(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_pwk_cipher *tlv = NULL; HTCap_t htcap; t_u16 proto = 0; t_u8 *buffer = NULL; t_u16 tlv_get_len = 0, protocol = 0, cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_pwk_cipher_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc) { if (is_input_valid(PWK_CIPHER, argc, argv) != UAP_SUCCESS) { print_sys_cfg_pwk_cipher_usage(); return UAP_FAILURE; } if ((argc == 2) && (atoi(argv[1]) == CIPHER_TKIP)) { if (UAP_SUCCESS == get_sys_cfg_protocol(&proto)) { /* Ok to have TKIP in mixed mode */ if (proto != PROTOCOL_WPA2_MIXED) { memset(&htcap, 0, sizeof(htcap)); if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) { if (htcap.supported_mcs_set[0]) { printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n"); print_sys_cfg_pwk_cipher_usage (); return UAP_FAILURE; } } } } } } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_pwk_cipher); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_pwk_cipher *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_CIPHER_PWK_TLV_ID; if (argc < 2) { cmd_buf->action = ACTION_GET; tlv->length = 0; /* Adjust cmd_len for 0 payload */ cmd_len = cmd_len - (sizeof(tlvbuf_pwk_cipher) - TLVHEADER_LEN); if (argc == 1) protocol = atoi(argv[0]); } else { cmd_buf->action = ACTION_SET; tlv->length = sizeof(tlvbuf_pwk_cipher) - TLVHEADER_LEN; tlv->protocol = (t_u16)atoi(argv[0]); tlv->pairwise_cipher = (t_u8)atoi(argv[1]); } endian_convert_tlv_header_out(tlv); tlv->protocol = uap_cpu_to_le16(tlv->protocol); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_CIPHER_PWK_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc < 2) { tlv_get_len = cmd_buf->size - sizeof(apcmdbuf_sys_configure) + BUF_HEADER_SIZE; if ((!tlv_get_len) || (tlv_get_len % sizeof(tlvbuf_pwk_cipher)) || (tlv_get_len > (3 * sizeof(tlvbuf_pwk_cipher)))) { printf("ERR:Corrupted response!\n"); free(buffer); return UAP_FAILURE; } if (!proto) get_sys_cfg_protocol(&proto); if (proto & PROTOCOL_WPA || proto & PROTOCOL_WPA2) printf("Active Protocol = %s\n", (proto == PROTOCOL_WPA) ? "WPA" : (proto == PROTOCOL_WPA2) ? "WPA2" : "WPA | WPA2"); while (tlv_get_len > 0) { endian_convert_tlv_header_in(tlv); tlv->protocol = uap_le16_to_cpu(tlv->protocol); if ((argc == 1) && (protocol != tlv->protocol)) { tlv_get_len -= sizeof (tlvbuf_pwk_cipher); tlv++; continue; } print_pwk_cipher(tlv); tlv_get_len -= sizeof(tlvbuf_pwk_cipher); tlv++; } } else { printf("protocol and pairwise cipher setting successful\n"); } } else { if (argc < 2) { printf("ERR:Could not get pairwise cipher parameters!\n"); } else { printf("ERR:Could not set pairwise cipher parameters!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for group cipher configurations * and sends to the driver * * Usage: "sys_cfg_gwk_cipher [GROUP_CIPHER]" * * Options: GROUP_CIPHER : Bit 2 - TKIP * Bit 3 - AES CCMP * empty - Get current group cipher settings * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_gwk_cipher(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_gwk_cipher *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_gwk_cipher_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc) { if (is_input_valid(GWK_CIPHER, argc, argv) != UAP_SUCCESS) { print_sys_cfg_gwk_cipher_usage(); return UAP_FAILURE; } } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_gwk_cipher); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_gwk_cipher *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_CIPHER_GWK_TLV_ID; tlv->length = 2; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; tlv->group_cipher = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_CIPHER_GWK_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { print_gwk_cipher(tlv); } else { printf("group cipher setting successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get group cipher parameters!\n"); } else { printf("ERR:Could not set group cipher parameters!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_group_rekey_timer(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_group_rekey_timer *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_group_rekey_timer_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(GROUPREKEYTIMER, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_group_rekey_timer_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_group_rekey_timer); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->group_rekey_time_sec = (t_u32)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->group_rekey_time_sec = uap_cpu_to_le32(tlv->group_rekey_time_sec); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->group_rekey_time_sec = uap_le32_to_cpu(tlv->group_rekey_time_sec); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_GRP_REKEY_TIME_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { if (tlv->group_rekey_time_sec > 0) printf("Group rekey time is %d s\n", tlv->group_rekey_time_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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_wpa_passphrase(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_wpa_passphrase *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; argc--; argv++; /* Check arguments */ if (argc > 1) { printf("ERR:Too many arguments.\n"); print_sys_cfg_wpa_passphrase_usage(); return UAP_FAILURE; } if ((argc == 1) && (strlen(argv[0]) > MAX_WPA_PASSPHRASE_LENGTH)) { printf("ERR:PASSPHRASE too long.\n"); return UAP_FAILURE; } if ((argc == 1) && (strlen(argv[0]) < MIN_WPA_PASSPHRASE_LENGTH)) { printf("ERR:PASSPHRASE too short.\n"); return UAP_FAILURE; } 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 UAP_FAILURE; } } /* 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 = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_wpa_passphrase *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_WPA_PASSPHRASE_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for WPA3 SAE password * and sends to the driver * * Usage: "sys_cfg_wpa3_sae_password [PASSWORD]" * if PASSWORD is provided, a 'set' is performed * else a 'get' is performed * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_wpa3_sae_password(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_wpa3_sae_password *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; argc--; argv++; /* Check arguments */ if (argc > 1) { printf("ERR:Too many arguments.\n"); print_sys_cfg_wpa3_sae_password_usage(); return UAP_FAILURE; } if ((argc == 1) && (strlen(argv[0]) > MAX_WPA3_SAE_PASSWORD_LENGTH)) { printf("ERR:PASSWORD too long.\n"); return UAP_FAILURE; } if ((argc == 1) && (strlen(argv[0]) < MIN_WPA3_SAE_PASSWORD_LENGTH)) { printf("ERR:PASSWORD too short.\n"); return UAP_FAILURE; } /* Initialize the command length */ if (argc == 0) cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wpa3_sae_password) + MAX_WPA3_SAE_PASSWORD_LENGTH; else cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wpa3_sae_password) + strlen(argv[0]); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_wpa3_sae_password *) (buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_WPA3_SAE_PASSWORD_TLV_ID; if (argc == 0) { cmd_buf->action = ACTION_GET; tlv->length = MAX_WPA3_SAE_PASSWORD_LENGTH; } else { cmd_buf->action = ACTION_SET; tlv->length = strlen(argv[0]); memcpy(tlv->password, argv[0], tlv->length); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_WPA3_SAE_PASSWORD_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { if (tlv->length > 0) printf("WPA3 SAE password = %s\n", tlv->password); else printf("WPA3 SAE password: None\n"); } else { printf("WPA3 SAE password setting successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get WPA3 SAE password!\n"); } else { printf("ERR:Could not set WPA3 SAE password!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a STA filter request and sends to the driver * * Usage: "sta_filter_table " * * 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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sta_filter_table(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_sta_mac_addr_filter *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int i = 0; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sta_filter_table_usage(); return UAP_SUCCESS; } } 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 UAP_FAILURE; } 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 UAP_FAILURE; } } /* 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 { if (argc == 1) { 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 = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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->filter_mode = atoi(argv[0]); tlv->count = argc - 1; if (tlv->count) { for (i = 0; i < tlv->count; i++) { if ((ret = mac2raw(argv[i + 1], &tlv->mac_address[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 UAP_FAILURE; } } } else { memset(tlv->mac_address, 0, MAX_MAC_ONESHOT_FILTER * ETH_ALEN); } } if (tlv->count) { tlv->length = tlv->count * ETH_ALEN + 2; } else { tlv->length = MAX_MAC_ONESHOT_FILTER * ETH_ALEN + 2; } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_STA_MAC_ADDR_FILTER_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_max_sta_num(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_max_sta_num *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; t_u16 max_sta_num_supported = 0; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_max_sta_num_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(MAXSTANUM, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_max_sta_num_usage(); return UAP_FAILURE; } if (argc) { if (get_max_sta_num_supported(&max_sta_num_supported) == UAP_FAILURE) { return UAP_FAILURE; } if (atoi(argv[0]) > max_sta_num_supported) { printf("ERR: MAX_STA_NUM must be less than %d\n", max_sta_num_supported); print_sys_cfg_max_sta_num_usage(); return UAP_FAILURE; } } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_sta_num); if (argc) { cmd_len -= sizeof(tlv->max_sta_num_supported); } /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_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->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_MAX_STA_CNT_TLV_ID; if (argc == 0) { tlv->length = 4; cmd_buf->action = ACTION_GET; } else { tlv->length = 2; cmd_buf->action = ACTION_SET; tlv->max_sta_num_configured = (t_u16)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); tlv->max_sta_num_configured = uap_cpu_to_le16(tlv->max_sta_num_configured); tlv->max_sta_num_supported = uap_cpu_to_le16(tlv->max_sta_num_supported); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->max_sta_num_configured = uap_le16_to_cpu(tlv->max_sta_num_configured); tlv->max_sta_num_supported = uap_le16_to_cpu(tlv->max_sta_num_supported); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_MAX_STA_CNT_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("configured max station count = %d\n", tlv->max_sta_num_configured); if (tlv->length == 4) { printf("max number of stations supported = %d\n", tlv->max_sta_num_supported); } } else { printf("max station number setting successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get configured max station count and supported max station count!\n"); } else { printf("ERR:Could not set max station number!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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 UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_retry_limit(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_retry_limit *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_retry_limit_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(RETRYLIMIT, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_retry_limit_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_retry_limit); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_retry_limit *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 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 = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_RETRY_LIMIT_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* 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"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for sticky TIM configuration * and sends to the driver * * Usage: "sys_cfg_sticky_tim_config [ENABLE] [ ]" * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_sticky_tim_config(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_sticky_tim_config *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_sticky_tim_config_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(STICKYTIMCONFIG, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_sticky_tim_config_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_sticky_tim_config); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_sticky_tim_config *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_STICKY_TIM_CONFIG_TLV_ID; tlv->length = sizeof(tlvbuf_sticky_tim_config) - TLVHEADER_LEN; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; tlv->enable = (t_u16)atoi(argv[0]); if (argc > 1) { tlv->duration = (t_u16)atoi(argv[1]); tlv->sticky_bitmask = (t_u16)atoi(argv[2]); } } endian_convert_tlv_header_out(tlv); tlv->enable = uap_cpu_to_le16(tlv->enable); if (argc > 1) { tlv->duration = uap_cpu_to_le16(tlv->duration); tlv->sticky_bitmask = uap_cpu_to_le16(tlv->sticky_bitmask); } /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->enable = uap_le16_to_cpu(tlv->enable); if (argc > 1) { tlv->duration = uap_le16_to_cpu(tlv->duration); tlv->sticky_bitmask = uap_le16_to_cpu(tlv->sticky_bitmask); } /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_STICKY_TIM_CONFIG_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("Sticky TIM is %s\n", (tlv->enable == 0) ? "disabled" : "enabled"); printf("Duration = %d beacons\n", tlv->duration); printf("Sticky Bitmask = %x\n", tlv->sticky_bitmask); } else { printf("sticky TIM configuration successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get sticky TIM configuration!\n"); } else { printf("ERR:Could not set sticky TIM configuration!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for sticky TIM station MAC address * and sends to the driver * * Usage: "sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]" * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_sticky_tim_sta_mac_addr(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_sticky_tim_sta_mac_addr *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int tlv_get_len = 0; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_sticky_tim_sta_mac_addr_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(STICKYTIMSTAMACADDR, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_sticky_tim_sta_mac_addr_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_sticky_tim_sta_mac_addr); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_sticky_tim_sta_mac_addr *)(buffer + sizeof (apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_STICKY_TIM_STA_MAC_ADDR_TLV_ID; tlv->length = sizeof(tlvbuf_sticky_tim_sta_mac_addr) - TLVHEADER_LEN; if (argc < 2) { cmd_buf->action = ACTION_GET; if (argc == 0) { tlv->length = 0; cmd_len -= sizeof(tlvbuf_sticky_tim_sta_mac_addr) - TLVHEADER_LEN; } if ((argc == 1) && mac2raw(argv[0], tlv->sta_mac_address) != UAP_SUCCESS) { printf("ERR: Invalid MAC address %s \n", argv[0]); free(buffer); return UAP_FAILURE; } } else { cmd_buf->action = ACTION_SET; tlv->control = (t_u16)atoi(argv[0]); if (mac2raw(argv[1], tlv->sta_mac_address) != UAP_SUCCESS) { printf("ERR: Invalid MAC address %s \n", argv[1]); free(buffer); return UAP_FAILURE; } } endian_convert_tlv_header_out(tlv); tlv->control = uap_cpu_to_le16(tlv->control); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); tlv->control = uap_le16_to_cpu(tlv->control); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_STICKY_TIM_STA_MAC_ADDR_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc < 2) { tlv_get_len = cmd_buf->size - sizeof(apcmdbuf_sys_configure) + BUF_HEADER_SIZE; while (tlv_get_len > 0) { printf("station MAC address = "); print_mac(tlv->sta_mac_address); printf("\ncontrol = %x\n", tlv->control); tlv++; tlv_get_len -= sizeof (tlvbuf_sticky_tim_sta_mac_addr); } } else { printf("sticky TIM configuration for given station is successful\n"); } } else { if (argc < 2) { printf("ERR:Could not get sticky TIM configuration for station(s)!\n"); } else { printf("ERR:Could not set sticky TIM configuration for given station!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for 20/40 coex configuration * and sends to the driver * * Usage: "sys_cfg_2040_coex [ENABLE]" * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_2040_coex(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_2040_coex *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_2040_coex_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && (is_input_valid(COEX2040CONFIG, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_2040_coex_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_2040_coex); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_2040_coex *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_2040_BSS_COEX_CONTROL_TLV_ID; tlv->length = sizeof(tlvbuf_2040_coex) - TLVHEADER_LEN; if (argc == 0) { cmd_buf->action = ACTION_GET; } else { cmd_buf->action = ACTION_SET; tlv->enable = (t_u8)atoi(argv[0]); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_2040_BSS_COEX_CONTROL_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { printf("20/40 BSS Co-existence is %s\n", (tlv->enable == 0) ? "disabled" : "enabled"); } else { printf("20/40 coex configuration successful\n"); } } else { printf("ERR:Could not %s 2040 coex configuration!\n", argc ? "set" : "get"); if (argc) printf("20/40 coex configuration is allowed to set only before bss start.\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for setting pairwise key handshake timeout * and number of retries and sends to the driver * * Usage: "sys_cfg_eapol_pwk_hsk [ ]" * If both TIMEOUT value and number of RETRIES are provided, * a 'set' is performed else a 'get' is performed. * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_eapol_pwk_hsk(int argc, char *argv[]) { int opt; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; t_u8 *tlv_buf = NULL; t_u8 *buffer = NULL; apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_eapol_pwk_hsk_timeout *timeout_tlv = NULL; tlvbuf_eapol_pwk_hsk_retries *retries_tlv = NULL; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_eapol_pwk_hsk_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check Arguments */ if (argc && (is_input_valid(EAPOL_PWK_HSK, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_eapol_pwk_hsk_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_eapol_pwk_hsk_timeout) + sizeof(tlvbuf_eapol_pwk_hsk_retries); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Fill the command buffer */ cmd_buf = (apcmdbuf_sys_configure *)buffer; cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; cmd_buf->action = argc ? ACTION_SET : ACTION_GET; tlv_buf = buffer + sizeof(apcmdbuf_sys_configure); /* Fill Timeout tlv */ timeout_tlv = (tlvbuf_eapol_pwk_hsk_timeout *)(buffer + sizeof (apcmdbuf_sys_configure)); timeout_tlv->tag = MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID; timeout_tlv->length = 4; if (argv[0]) timeout_tlv->pairwise_update_timeout = (t_u32)atoi(argv[0]); tlv_buf += sizeof(tlvbuf_eapol_pwk_hsk_timeout); endian_convert_tlv_header_out(timeout_tlv); timeout_tlv->pairwise_update_timeout = uap_cpu_to_le32(timeout_tlv->pairwise_update_timeout); /* Fill retries tlv */ retries_tlv = (tlvbuf_eapol_pwk_hsk_retries *)(tlv_buf); retries_tlv->tag = MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID; retries_tlv->length = 4; if (argv[1]) retries_tlv->pwk_retries = (t_u32)atoi(argv[1]); endian_convert_tlv_header_out(retries_tlv); retries_tlv->pwk_retries = uap_cpu_to_le32(retries_tlv->pwk_retries); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); tlv_buf = buffer + sizeof(apcmdbuf_sys_configure); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if (cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { printf("ERR:Corrupted response! cmd_code=%x\n", cmd_buf->cmd_code); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc) { printf("PWK update timeout and retries setting successful\n"); } else { print_tlv((t_u8 *)tlv_buf, cmd_buf->size - sizeof(apcmdbuf_sys_configure) + BUF_HEADER_SIZE); } } else { printf("ERR:Could not %s pwk timeout and retries value!\n", argc ? "set" : "get"); if (argc) printf("PWK timeout and retries are allowed to set only before bss start.\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for setting groupwise key handshake timeout * and number of retries and sends to the driver * * Usage: "sys_cfg_eapol_gwk_hsk [ ]" * If both TIMEOUT value and number of RETRIES are provided, * a 'set' is performed else a 'get' is performed. * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_eapol_gwk_hsk(int argc, char *argv[]) { int opt; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; t_u8 *tlv_buf = NULL; t_u8 *buffer = NULL; apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_eapol_gwk_hsk_timeout *timeout_tlv = NULL; tlvbuf_eapol_gwk_hsk_retries *retries_tlv = NULL; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_eapol_gwk_hsk_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check Arguments */ if (argc && (is_input_valid(EAPOL_GWK_HSK, argc, argv) != UAP_SUCCESS)) { print_sys_cfg_eapol_gwk_hsk_usage(); return UAP_FAILURE; } /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_eapol_gwk_hsk_timeout) + sizeof(tlvbuf_eapol_gwk_hsk_retries); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Fill the command buffer */ cmd_buf = (apcmdbuf_sys_configure *)buffer; cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; cmd_buf->action = argc ? ACTION_SET : ACTION_GET; tlv_buf = buffer + sizeof(apcmdbuf_sys_configure); /* Fill Timeout tlv */ timeout_tlv = (tlvbuf_eapol_gwk_hsk_timeout *)(buffer + sizeof (apcmdbuf_sys_configure)); timeout_tlv->tag = MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID; timeout_tlv->length = 4; if (argv[0]) timeout_tlv->groupwise_update_timeout = (t_u32)atoi(argv[0]); tlv_buf += sizeof(tlvbuf_eapol_gwk_hsk_timeout); endian_convert_tlv_header_out(timeout_tlv); timeout_tlv->groupwise_update_timeout = uap_cpu_to_le32(timeout_tlv->groupwise_update_timeout); /* Fill retries tlv */ retries_tlv = (tlvbuf_eapol_gwk_hsk_retries *)(tlv_buf); retries_tlv->tag = MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID; retries_tlv->length = 4; if (argv[1]) retries_tlv->gwk_retries = (t_u32)atoi(argv[1]); endian_convert_tlv_header_out(retries_tlv); retries_tlv->gwk_retries = uap_cpu_to_le32(retries_tlv->gwk_retries); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); tlv_buf = buffer + sizeof(apcmdbuf_sys_configure); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if (cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { printf("ERR:Corrupted response! cmd_code=%x\n", cmd_buf->cmd_code); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc) { printf("GWK update timeout and retries setting successful\n"); } else { print_tlv((t_u8 *)tlv_buf, cmd_buf->size - sizeof(apcmdbuf_sys_configure) + BUF_HEADER_SIZE); } } else { printf("ERR:Could not %s gwk timeout and retries value!\n", argc ? "set" : "get"); if (argc) printf("GWK timeout and retries are allowed to set only before bss start.\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @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, t_u8 *chr) { t_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, t_u8 *dst) { char *ptr; t_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 " * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_cfg_data(int argc, char *argv[]) { apcmdbuf_cfg_data *cmd_buf = NULL; t_u8 *buf = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; FILE *fp = NULL; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_cfg_data_usage(); return UAP_FAILURE; } } argc -= optind; argv += optind; /* Check arguments */ if ((argc == 0) || (argc > 2)) { printf("ERR:wrong arguments.\n"); print_cfg_data_usage(); return UAP_FAILURE; } 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 UAP_FAILURE; } } buf = (t_u8 *)malloc(buf_len); if (buf == NULL) { printf("Error: allocate memory for hostcmd failed\n"); return UAP_FAILURE; } memset(buf, 0, buf_len); cmd_buf = (apcmdbuf_cfg_data *)buf; 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 UAP_FAILURE; } 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 UAP_FAILURE; } } 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 = uap_le16_to_cpu(cmd_buf->data_len) + sizeof(apcmdbuf_cfg_data); cmd_buf->cmd_code = HostCmd_CMD_CFG_DATA; cmd_buf->size = cmd_len; cmd_buf->seq_num = 0; cmd_buf->result = 0; /* Send the command */ ret = uap_ioctl((t_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 ret; } /** * @brief Show usage information for the sys_cfg_11n * command * * $return N/A */ void print_sys_cfg_11n_usage(void) { printf("\nUsage : sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_MAP]\n"); printf("\nOptions: ENABLE 0 - disable"); printf("\n 1 - enable"); printf("\n HTCAP: HT Capabilities info"); printf("\n AMPDU: A-MPDU Parameter"); printf("\n TXBFCAP: TX Beamforming capabilities info"); printf("\n HT_MCS_MAP: Bitmap for supported MCS rates\n"); printf("\n empty - Get current 802.11n parameters\n"); return; } /** * @brief Get Ht capability Info from firmware * * @param pHtCap A pointer to HTCap_t structure * @return UAP_SUCCESS/UAP_FAILURE */ int get_sys_cfg_11n(HTCap_t *pHtCap) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_htcap_t *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len; int ret = UAP_FAILURE; /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_htcap_t); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(cmd_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return -1; } memset(buffer, 0, cmd_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_htcap_t *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = HT_CAPABILITY_TLV_ID; cmd_buf->action = ACTION_GET; tlv->length = sizeof(HTCap_t); endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != HT_CAPABILITY_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Copy response */ if (cmd_buf->result == CMD_SUCCESS) { memcpy(pHtCap, &tlv->ht_cap, sizeof(HTCap_t)); pHtCap->ht_cap_info = uap_le16_to_cpu(pHtCap->ht_cap_info); pHtCap->tx_bf_cap = uap_le32_to_cpu(pHtCap->tx_bf_cap); ret = UAP_SUCCESS; } else { ret = UAP_FAILURE; printf("ERR:Could not get HT capability!\n"); } } else { printf("ERR:Command sending failed!\n"); ret = UAP_FAILURE; } if (buffer) free(buffer); return ret; } #ifdef RX_PACKET_COALESCE void print_rx_packet_coalesc_help() { printf("\nUSAGE: rxpktcoal_cfg [PKT-THRESHOLD] [TIMEOUT]\n\n"); printf("OPTIONS:"); printf("PKT-THRESHOLD: count after which packets would be sent to host. Valid values 1-7\n"); printf("\tTIMEOUT: Time after which packets would be sent to host Valid values 1-4\n"); printf("\tCoalescing is disabled if both or either of PKT-THRESHOLD or TIMEOUT is zero\n\n"); printf("\tEmpty - Get current packet coalescing settings\n"); } int apcmd_rx_pkt_coalesce(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_rx_pkt_coal_t *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_rx_packet_coalesc_help(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc) { if (argc != 2) { printf("ERR: Invalid no. of arguments.\n"); print_rx_packet_coalesc_help(); return UAP_FAILURE; } if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)) { printf("ERR: Invalid arguments %s/%s. Both params must be digits.\n", argv[0], argv[1]); print_rx_packet_coalesc_help(); return UAP_FAILURE; } } /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_rx_pkt_coal_t *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Initialize the command length */ if (argc) { cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rx_pkt_coal_t); cmd_buf->action = ACTION_SET; } else { cmd_len = sizeof(apcmdbuf_sys_configure) + TLVHEADER_LEN; cmd_buf->action = ACTION_GET; } /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->seq_num = 0; cmd_buf->result = 0; if (!argc) { tlv->tag = MRVL_RX_PKT_COAL_TLV_ID; tlv->length = 0; //endian_convert_tlv_header_out(tlv); } else { tlv->length = sizeof(tlvbuf_rx_pkt_coal_t) - TLVHEADER_LEN; tlv->tag = MRVL_RX_PKT_COAL_TLV_ID; tlv->rx_pkt_count = uap_cpu_to_le32(atoi(argv[0])); tlv->delay = uap_cpu_to_le16(atoi(argv[1])); } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if (cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { printf("ERR:Corrupted response! cmd_code=%x\n", cmd_buf->cmd_code); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc) { printf("Configure RX packet coalesce parameters successful\n"); } else { print_tlv((t_u8 *)tlv, cmd_buf->size - sizeof(apcmdbuf_sys_configure) + BUF_HEADER_SIZE); } } else { if (argc) printf("ERR:Could not set RX packet coalesce parameters!\n"); else printf("ERR: Could not get RX packet coalesce parameters!\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } #endif /** * @brief Creates a sys_cfg request for 11n parameters * and sends to the driver * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_11n(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_htcap_t *tlv = NULL; tlvbuf_htinfo_t *ht_info_tlv = NULL; HTCap_t htcap; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; t_u32 supported_mcs_set = 0; fw_info fw; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_11n_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc) { if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) || (atoi(argv[0]) > 1)) { printf("ERR: Illegal ENABLE parameter %s. Must be either '0' or '1'.\n", argv[0]); print_sys_cfg_11n_usage(); return UAP_FAILURE; } if (argc > 5) { printf("ERR:wrong arguments.\n"); print_sys_cfg_11n_usage(); return UAP_FAILURE; } if (argc > 1) { if (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) { printf("ERR: Only Number values are allowed\n"); print_sys_cfg_11n_usage(); return UAP_FAILURE; } if ((((t_u16)A2HEXDECIMAL(argv[1])) & (~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK) { printf("ERR: Invalid HTCAP value!\n"); print_sys_cfg_11n_usage(); return UAP_FAILURE; } } if (argc > 2) { if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) { printf("ERR: Only Number values are allowed\n"); print_sys_cfg_11n_usage(); return UAP_FAILURE; } if ((A2HEXDECIMAL(argv[2])) > AMPDU_CONFIG_MASK) { printf("ERR: Invalid AMPDU value!\n"); print_sys_cfg_11n_usage(); return UAP_FAILURE; } } if (argc > 3) { if (IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE) { printf("ERR: Only Number values are allowed\n"); print_sys_cfg_11n_usage(); return UAP_FAILURE; } } if (argc > 4) { if (IS_HEX_OR_DIGIT(argv[4]) == UAP_FAILURE) { printf("ERR: Only Number values are allowed\n"); print_sys_cfg_11n_usage(); return UAP_FAILURE; } if (0 == get_fw_info(&fw)) { /* Check upper nibble of MCS support value * and block MCS_SET_1 when 2X2 is not supported * by the underlying hardware */ if (((fw.hw_dev_mcs_support & 0xf0) < STREAM_2X2_MASK) && (A2HEXDECIMAL(argv[4]) & MCS_SET_1_MASK)) { printf("ERR: Invalid HT_MCS_MAP\n"); return UAP_FAILURE; } } } memset(&htcap, 0, sizeof(htcap)); if (UAP_FAILURE == get_sys_cfg_11n(&htcap)) { printf("Fail to get 11n parameters from firmware\n"); return UAP_FAILURE; } } /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_htcap_t *)(buffer + sizeof(apcmdbuf_sys_configure)); tlv->tag = HT_CAPABILITY_TLV_ID; /* Initialize the command length */ if (argc) { cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_htcap_t); cmd_buf->action = ACTION_SET; } else { cmd_len = sizeof(apcmdbuf_sys_configure) + 2 * TLVHEADER_LEN; cmd_buf->action = ACTION_GET; } /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->seq_num = 0; cmd_buf->result = 0; if (!argc) { tlv->length = 0; /* Append HT_INFO TLV only for GET */ ht_info_tlv = (tlvbuf_htinfo_t *)(buffer + sizeof(apcmdbuf_sys_configure) + TLVHEADER_LEN); ht_info_tlv->tag = HT_INFO_TLV_ID; ht_info_tlv->length = 0; endian_convert_tlv_header_out(ht_info_tlv); } else { tlv->length = sizeof(HTCap_t); /* disable 802.11n */ if (atoi(argv[0]) == 0) { if (argc > 1) { printf("ERR:wrong arguments.\n"); print_sys_cfg_11n_usage(); free(buffer); return UAP_FAILURE; } memcpy(&tlv->ht_cap, &htcap, sizeof(HTCap_t)); /* disable mcs rate */ tlv->ht_cap.supported_mcs_set[0] = 0; tlv->ht_cap.supported_mcs_set[4] = 0; tlv->ht_cap.supported_mcs_set[1] = 0; } else { t_u8 is_40MHz_supported = 0; /* enable 802.11n */ memcpy(&tlv->ht_cap, &htcap, sizeof(HTCap_t)); if (0 == get_fw_info(&fw)) { if ((fw.hw_dev_mcs_support & 0x0f) >= 2) tlv->ht_cap.supported_mcs_set[1] = DEFAULT_MCS_SET_1; } if (argc >= 2) { tlv->ht_cap.ht_cap_info = DEFAULT_HT_CAP_VALUE & ~HT_CAP_CONFIG_MASK; tlv->ht_cap.ht_cap_info |= (t_u16)A2HEXDECIMAL(argv[1]) & HT_CAP_CONFIG_MASK; tlv->ht_cap.ht_cap_info = uap_cpu_to_le16(tlv->ht_cap. ht_cap_info); is_40MHz_supported = tlv->ht_cap.ht_cap_info & MBIT(1); } /* enable mcs rate */ tlv->ht_cap.supported_mcs_set[0] = DEFAULT_MCS_SET_0; /* enable MCS32 only in case of both 20/40 MHz support */ if (is_40MHz_supported) tlv->ht_cap.supported_mcs_set[4] = DEFAULT_MCS_SET_4; else tlv->ht_cap.supported_mcs_set[4] = 0; if (argc >= 3) tlv->ht_cap.ampdu_param = (t_u8)A2HEXDECIMAL(argv[2]) & AMPDU_CONFIG_MASK; if (argc >= 4) { tlv->ht_cap.tx_bf_cap = (t_u32)A2HEXDECIMAL(argv[3]); tlv->ht_cap.tx_bf_cap = uap_cpu_to_le32(tlv->ht_cap.tx_bf_cap); } if (argc == 5) { supported_mcs_set = (t_u32)A2HEXDECIMAL(argv[4]); supported_mcs_set = uap_cpu_to_le32(supported_mcs_set); memcpy(tlv->ht_cap.supported_mcs_set, &supported_mcs_set, sizeof(t_u32)); } } } endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if (cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) { printf("ERR:Corrupted response! cmd_code=%x\n", cmd_buf->cmd_code); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc) { printf("Configure 802.11n parameters successful\n"); } else { print_tlv((t_u8 *)tlv, cmd_buf->size - sizeof(apcmdbuf_sys_configure) + BUF_HEADER_SIZE); } } else { if (argc) printf("ERR:Could not set 802.11n parameters!\n"); else printf("ERR: Could not get 802.11n parameters!\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Show usage information for the sys_cfg_wmm * command * * $return N/A */ void print_sys_cfg_wmm_usage(void) { printf("\nUsage : sys_cfg_wmm [qosinfo=] [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\n [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\n [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\n [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\nOptions: qosinfo - 0x80 or 0x00"); printf("\n AC_BE - 0, AC_BK - 1"); printf("\n AC_VI - 2, AC_VO - 3"); printf("\n AIFSN - AIFSN value"); printf("\n ECW_MAX: ECW max"); printf("\n ECW_MIN: ECW min"); printf("\n TX_OP: TXOP Limit"); printf("\n empty - Get current wmm parameters\n"); return; } /** @brief Show usage information for the sys_cfg_ap_wmm * command * * $return N/A */ void print_sys_cfg_ap_wmm_usage(void) { printf("\nUsage : sys_cfg_wmm [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\n [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\n [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\n [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]\n"); printf("\nOptions: AC_BE - 0, AC_BK - 1"); printf("\n AC_VI - 2, AC_VO - 3"); printf("\n AIFSN - AIFSN value"); printf("\n ECW_MAX: ECW max"); printf("\n ECW_MIN: ECW min"); printf("\n TX_OP: TXOP Limit"); printf("\n empty - Get current wmm parameters\n"); return; } /** * @brief Get WMM parameters from firmware * * @param pWmm A pointer to WmmParameter_t structure * @param tlv_tag TLV ID * @return UAP_SUCCESS/UAP_FAILURE */ int get_wmm_parameters(WmmParameter_t *pWmm, t_u16 tlv_tag) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_wmm_para_t *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len; t_u8 oui_type[4] = { 0x00, 0x50, 0xF2, 0x02 }; int ret = UAP_FAILURE; /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wmm_para_t); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(cmd_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return -1; } memset(buffer, 0, cmd_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_wmm_para_t *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = tlv_tag; cmd_buf->action = ACTION_GET; tlv->length = sizeof(WmmParameter_t); memcpy(tlv->wmm_para.ouitype, oui_type, sizeof(oui_type)); tlv->wmm_para.ouisubtype = 1; tlv->wmm_para.version = 1; endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != tlv_tag) || (tlv->length != sizeof(WmmParameter_t))) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Copy response */ if (cmd_buf->result == CMD_SUCCESS) { memcpy(pWmm, &tlv->wmm_para, sizeof(WmmParameter_t)); ret = UAP_SUCCESS; } else { ret = UAP_FAILURE; printf("ERR:Could not get wmm parameters!\n"); } } else { printf("ERR:Command sending failed!\n"); ret = UAP_FAILURE; } if (buffer) free(buffer); return ret; } /** * @brief Creates a sys_cfg request for wmm parameters * and sends to the driver * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_wmm(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_wmm_para_t *tlv = NULL; WmmParameter_t wmm_para; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int i; int ret = UAP_SUCCESS; int opt; t_u8 ac = 0; t_u8 wmm_disable = 1; t_u8 qos_info = 0; t_u8 flag = 0; char str[13]; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_wmm_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; memset(&wmm_para, 0, sizeof(wmm_para)); memset(str, 0, sizeof(str)); if (UAP_FAILURE == get_wmm_parameters(&wmm_para, VENDOR_SPECIFIC_IE_TLV_ID)) { printf("Fail to get wmm parameters from firmware\n"); return UAP_FAILURE; } if (!argc) { printf("wmm parameters:\n"); printf("\tqos_info = 0x%x\n", wmm_para.qos_info); printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_BE].aci_aifsn.aifsn, wmm_para.ac_params[AC_BE].ecw.ecw_max, wmm_para.ac_params[AC_BE].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_BE].tx_op_limit)); printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_BK].aci_aifsn.aifsn, wmm_para.ac_params[AC_BK].ecw.ecw_max, wmm_para.ac_params[AC_BK].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_BK].tx_op_limit)); printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_VI].aci_aifsn.aifsn, wmm_para.ac_params[AC_VI].ecw.ecw_max, wmm_para.ac_params[AC_VI].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_VI].tx_op_limit)); printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_VO].aci_aifsn.aifsn, wmm_para.ac_params[AC_VO].ecw.ecw_max, wmm_para.ac_params[AC_VO].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_VO].tx_op_limit)); return UAP_SUCCESS; } if (strlen(argv[0]) > 8) { if (strncmp(argv[0], "qosinfo=", 8) == 0) { strncpy(str, argv[0], sizeof(str) - 1); strncpy(str, strchr(str, '=') + 1, 4); qos_info = A2HEXDECIMAL(str); if ((qos_info != ENABLE_WMM_PS) && (qos_info != DISABLE_WMM_PS)) { printf("ERR:qos_info must be either 0x80 or 0x00\n"); print_sys_cfg_wmm_usage(); return UAP_FAILURE; } argc -= 1; argv += 1; flag = 1; } else { printf("ERR:Invalid argument!\n"); print_sys_cfg_wmm_usage(); return UAP_FAILURE; } } /* Check arguments */ if ((argc != 1) && ((argc > 20) || ((argc > 0) && ((argc % 5) != 0)))) { printf("ERR:Illegal number of parameters.\n"); print_sys_cfg_wmm_usage(); return UAP_FAILURE; } for (i = 0; i < argc; i++) { if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) { printf("ERR: Only Number values are allowed\n"); print_sys_cfg_wmm_usage(); return UAP_FAILURE; } if (A2HEXDECIMAL(argv[i])) wmm_disable = 0; } if ((argc == 1) && A2HEXDECIMAL(argv[0])) { printf("ERR: Only 0 is allowed to disable WMM using single parameter.\n"); print_sys_cfg_wmm_usage(); return UAP_FAILURE; } if (argc != 20 && argc != 1) wmm_disable = 0; /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wmm_para_t); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_wmm_para_t *)(buffer + sizeof(apcmdbuf_sys_configure)); tlv->tag = VENDOR_SPECIFIC_IE_TLV_ID; tlv->length = sizeof(WmmParameter_t); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->seq_num = 0; cmd_buf->result = 0; cmd_buf->action = ACTION_SET; endian_convert_tlv_header_out(tlv); memcpy(&tlv->wmm_para, &wmm_para, sizeof(WmmParameter_t)); if (wmm_disable) { /* clear AC parameters to disalbe wmm */ memset((t_u8 *)tlv->wmm_para.ac_params, 0, sizeof(IEEEtypes_WmmAcParameters_t) * MAX_AC_QUEUES); } else { if (flag) { if (qos_info) tlv->wmm_para.qos_info = wmm_para.qos_info | qos_info; else tlv->wmm_para.qos_info = wmm_para.qos_info & WMM_PS_MASK; } for (i = 0; i < (argc / 5); i++) { ac = (t_u8)A2HEXDECIMAL(argv[i * 5]); if (ac > AC_VO) { printf("ERR: Invalid AC queue index, Only support AC_BE, AC_BK, AC_VI, AC_VO\n"); print_sys_cfg_wmm_usage(); free(buffer); return UAP_FAILURE; } tlv->wmm_para.ac_params[ac].aci_aifsn.aifsn = (t_u8)A2HEXDECIMAL(argv[i * 5 + 1]); tlv->wmm_para.ac_params[ac].aci_aifsn.aci = (t_u8)ac; tlv->wmm_para.ac_params[ac].ecw.ecw_max = (t_u8)A2HEXDECIMAL(argv[i * 5 + 2]); tlv->wmm_para.ac_params[ac].ecw.ecw_min = (t_u8)A2HEXDECIMAL(argv[i * 5 + 3]); tlv->wmm_para.ac_params[ac].tx_op_limit = uap_cpu_to_le16((t_u16) A2HEXDECIMAL(argv[i * 5 + 4])); } } /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != VENDOR_SPECIFIC_IE_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { printf("Configure wmm parameters successful\n"); } else { printf("ERR:Could not set wmm parameters!\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_ap_wmm(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_wmm_para_t *tlv = NULL; WmmParameter_t wmm_para; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int i; int opt; t_u8 ac = 0; t_u8 wmm_reset = 1; int ret = UAP_SUCCESS; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_ap_wmm_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; memset(&wmm_para, 0, sizeof(wmm_para)); if (UAP_FAILURE == get_wmm_parameters(&wmm_para, MRVL_AP_WMM_PARAM_TLV_ID)) { printf("Fail to get ap wmm parameters from firmware\n"); return UAP_FAILURE; } if (!argc) { printf("ap wmm parameters:\n"); printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_BE].aci_aifsn.aifsn, wmm_para.ac_params[AC_BE].ecw.ecw_max, wmm_para.ac_params[AC_BE].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_BE].tx_op_limit)); printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_BK].aci_aifsn.aifsn, wmm_para.ac_params[AC_BK].ecw.ecw_max, wmm_para.ac_params[AC_BK].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_BK].tx_op_limit)); printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_VI].aci_aifsn.aifsn, wmm_para.ac_params[AC_VI].ecw.ecw_max, wmm_para.ac_params[AC_VI].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_VI].tx_op_limit)); printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_para.ac_params[AC_VO].aci_aifsn.aifsn, wmm_para.ac_params[AC_VO].ecw.ecw_max, wmm_para.ac_params[AC_VO].ecw.ecw_min, uap_le16_to_cpu(wmm_para.ac_params[AC_VO].tx_op_limit)); return UAP_SUCCESS; } /* Check arguments */ if ((argc != 1) && ((argc > 20) || ((argc > 0) && ((argc % 5) != 0)))) { printf("ERR:Illegal number of parameters.\n"); print_sys_cfg_ap_wmm_usage(); return UAP_FAILURE; } for (i = 0; i < argc; i++) { if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) { printf("ERR: Only Number values are allowed\n"); print_sys_cfg_ap_wmm_usage(); return UAP_FAILURE; } if (A2HEXDECIMAL(argv[i])) wmm_reset = 0; } if ((argc == 1) && A2HEXDECIMAL(argv[0])) { printf("ERR: Only 0 is allowed to reset AP WMM using single parameter.\n"); print_sys_cfg_ap_wmm_usage(); return UAP_FAILURE; } if (argc != 20 && argc != 1) wmm_reset = 0; /* Initialize the command length */ cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wmm_para_t); /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_wmm_para_t *)(buffer + sizeof(apcmdbuf_sys_configure)); tlv->tag = MRVL_AP_WMM_PARAM_TLV_ID; /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->size = cmd_len - BUF_HEADER_SIZE; cmd_buf->seq_num = 0; cmd_buf->result = 0; cmd_buf->action = ACTION_SET; endian_convert_tlv_header_out(tlv); memcpy(&tlv->wmm_para, &wmm_para, sizeof(WmmParameter_t)); if (wmm_reset) { /* clear AC parameters to reset ap wmm */ memset((t_u8 *)tlv->wmm_para.ac_params, 0, sizeof(IEEEtypes_WmmAcParameters_t) * MAX_AC_QUEUES); } else { for (i = 0; i < (argc / 5); i++) { ac = (t_u8)A2HEXDECIMAL(argv[i * 5]); if (ac > AC_VO) { printf("ERR: Invalid AC queue index, Only support AC_BE, AC_BK, AC_VI, AC_VO\n"); print_sys_cfg_ap_wmm_usage(); free(buffer); return UAP_FAILURE; } tlv->wmm_para.ac_params[ac].aci_aifsn.aifsn = (t_u8)A2HEXDECIMAL(argv[i * 5 + 1]); tlv->wmm_para.ac_params[ac].aci_aifsn.aci = (t_u8)ac; tlv->wmm_para.ac_params[ac].ecw.ecw_max = (t_u8)A2HEXDECIMAL(argv[i * 5 + 2]); tlv->wmm_para.ac_params[ac].ecw.ecw_min = (t_u8)A2HEXDECIMAL(argv[i * 5 + 3]); tlv->wmm_para.ac_params[ac].tx_op_limit = uap_cpu_to_le16((t_u16) A2HEXDECIMAL(argv[i * 5 + 4])); } } /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_AP_WMM_PARAM_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { printf("Configure ap wmm parameters successful\n"); } else { printf("ERR:Could not set ap wmm parameters!\n"); ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; } /** * @brief Show usage information for the sys_cfg_restrict_client_mode * command * * $return N/A */ void print_sys_cfg_restrict_client_mode_usage(void) { printf("\nUsage : sys_cfg_restrict_client_mode [ [MODE_CONFIG]]\n"); printf("\nOptions:"); printf("\n Bit 0: 1 enable restricted client mode"); printf("\n 0 disable restricted client mode"); printf("\n Bits [1-7] : set to 0"); printf("\n Bits [8:12]:"); printf("\n Bit 8: B only Mode"); printf("\n Bit 9: A only Mode"); printf("\n Bit 10: G only Mode"); printf("\n Bit 11: N only Mode"); printf("\n Bit 12: AC only Mode"); printf("\n Bits [13:15]: set to 0"); printf("\n"); printf("\n Empty - Get current restricted client mode setting.\n"); return; } /** * @brief Creates a sys_cfg request to Set/Get restricted client mode * and sends to the driver * * Usage: "sys_cfg_restrict_client_mode [ [MODE_CONFIG]]" * If arguments are provided, a 'set' is performed * else a 'get' is performed. * * @param argc Number of arguments * @param argv Pointer to the arguments * @return UAP_SUCCESS/UAP_FAILURE */ int apcmd_sys_cfg_restrict_client_mode(int argc, char *argv[]) { apcmdbuf_sys_configure *cmd_buf = NULL; tlvbuf_restrict_client_mode *tlv = NULL; t_u8 *buffer = NULL; t_u16 cmd_len = 0; t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER; int ret = UAP_SUCCESS; int opt; while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) { switch (opt) { default: print_sys_cfg_restrict_client_mode_usage(); return UAP_SUCCESS; } } argc -= optind; argv += optind; /* Check arguments */ if (argc && is_input_valid(RESTRICT_CLIENT_MODE, argc, argv) != UAP_SUCCESS) { print_sys_cfg_restrict_client_mode_usage(); return UAP_FAILURE; } /* Initialize the command buffer */ buffer = (t_u8 *)malloc(buf_len); if (!buffer) { printf("ERR:Cannot allocate buffer for command!\n"); return UAP_FAILURE; } memset(buffer, 0, buf_len); /* Locate headers */ cmd_buf = (apcmdbuf_sys_configure *)buffer; tlv = (tlvbuf_restrict_client_mode *)(buffer + sizeof(apcmdbuf_sys_configure)); /* Fill the command buffer */ cmd_buf->cmd_code = APCMD_SYS_CONFIGURE; cmd_buf->seq_num = 0; cmd_buf->result = 0; tlv->tag = MRVL_RESTRICT_CLIENT_MODE_TLV_ID; if (argc == 0) { cmd_buf->action = ACTION_GET; tlv->length = 0; } else { cmd_buf->action = ACTION_SET; tlv->length = sizeof(t_u16); tlv->mode_config = (t_u16)((tlv-> mode_config | RESTRICT_CLIENT_MODE_ENABLE_MASK) & atoi(argv[0])); if (argc == 2) { tlv->mode_config |= (t_u16)(A2HEXDECIMAL(argv[1]) << 8); } tlv->mode_config = uap_cpu_to_le16(tlv->mode_config); } cmd_buf->size = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_restrict_client_mode); cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_restrict_client_mode); endian_convert_tlv_header_out(tlv); /* Send the command */ ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len); endian_convert_tlv_header_in(tlv); /* Process response */ if (ret == UAP_SUCCESS) { /* Verify response */ if ((cmd_buf->cmd_code != (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) || (tlv->tag != MRVL_RESTRICT_CLIENT_MODE_TLV_ID)) { printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag); free(buffer); return UAP_FAILURE; } /* Print response */ if (cmd_buf->result == CMD_SUCCESS) { if (argc == 0) { tlv->mode_config = uap_le16_to_cpu(tlv->mode_config); printf("Restricted Client Mode: %s\n", (tlv-> mode_config & RESTRICT_CLIENT_MODE_ENABLE_MASK) ? "Enabled" : "Disabled"); if (tlv-> mode_config & RESTRICT_CLIENT_MODE_ENABLE_MASK) { printf("Current client mode : "); if (tlv->mode_config & B_ONLY_MASK) printf("B Only\n"); else if (tlv->mode_config & A_ONLY_MASK) printf("A Only\n"); else if (tlv->mode_config & G_ONLY_MASK) printf("G Only\n"); else if (tlv->mode_config & N_ONLY_MASK) printf("N Only\n"); else if (tlv-> mode_config & AC_ONLY_MASK) printf("AC Only\n"); } } else { printf("Restricted client mode setting successful\n"); } } else { if (argc == 0) { printf("ERR:Could not get restrict client mode setting!\n"); } else { printf("ERR:Could not set restrict client mode setting!\n"); } ret = UAP_FAILURE; } } else { printf("ERR:Command sending failed!\n"); } if (buffer) free(buffer); return ret; }